From b6d968ae960d3e587142bdffa7e80b96d77f7536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8?= Date: Tue, 26 May 2026 16:20:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=BF=98=E8=AE=B0?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E9=A1=B5=E9=9D=A2=20-=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=AD=A5=E9=AA=A4=E6=9D=A1=EF=BC=8C=E5=90=88=E5=B9=B6=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=EF=BC=8C=E9=AA=8C=E8=AF=81=E7=A0=81=E5=90=8E=E6=89=8D?= =?UTF-8?q?=E8=83=BD=E8=BE=93=E5=85=A5=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/capital/transfer/index.vue | 4 +- src/views/order/history/index.vue | 29 ++- src/views/order/history/options.ts | 25 +-- src/views/user/ForgotPassword.vue | 302 +++++++++------------------ 4 files changed, 131 insertions(+), 229 deletions(-) diff --git a/src/views/capital/transfer/index.vue b/src/views/capital/transfer/index.vue index 4d3cd10..7c994cc 100644 --- a/src/views/capital/transfer/index.vue +++ b/src/views/capital/transfer/index.vue @@ -153,7 +153,7 @@ const transferType = ref('internal') * @description 创建默认转账表单数据 */ const createDefaultTransferForm = ():any => ({ - transferOutAccount: -1, + transferOutAccount: '', transferInAccount: '', transferAmount: '', remark: '', @@ -357,6 +357,8 @@ const getTransferWalletOptions = async () => { const data: any = await getTransferWalletOptionsApi() transferFormOptionsMap.value.transferOutAccount = data transferFormOptionsMap.value.transferInAccount = data.filter((item: any) => item.value !== -1) + + transferForm.value.transferOutAccount = -1 } /** * @description 页面加载完成需要渲染的数据 diff --git a/src/views/order/history/index.vue b/src/views/order/history/index.vue index 1c53e50..e6fe7e5 100644 --- a/src/views/order/history/index.vue +++ b/src/views/order/history/index.vue @@ -41,23 +41,18 @@ import { getStorage } from '@/utils/storage' import dayjs from 'dayjs' // 公用方法 +import { getRecentSevenDays } from '@/utils/handleTime.ts' /** * @description: 定义搜索数据 */ // 获取近一周的时间范围 -const dateRange = { - start: dayjs().subtract(7, 'day').format('YYYY-MM-DD'), - end: dayjs().format('YYYY-MM-DD'), -} -const searchForm = ref({ +const initTime = getRecentSevenDays() +const searchForm = ref({ accountName: '', orderId: '2', tradeType: '', - start_time: dateRange.start, - end_time: dateRange.end, - startTime: dateRange.start, - endTime: dateRange.end, + dateRange: [initTime.start, initTime.end], subAccountName: '', }) const searchOptions = ref(search) @@ -85,6 +80,13 @@ const total = ref(0) const getCustomerTradeOrderList = async () => { try { startLoading() + // 从 dateRange 中提取开始和结束时间 + let startTime = initTime.start + let endTime = initTime.end + if (searchForm.value.dateRange && searchForm.value.dateRange.length === 2) { + startTime = dayjs(searchForm.value.dateRange[0]).format('YYYY-MM-DD HH:mm:ss') + endTime = dayjs(searchForm.value.dateRange[1]).format('YYYY-MM-DD HH:mm:ss') + } const params = { page: currentPage.value, page_size: pageSize.value, @@ -92,8 +94,8 @@ const getCustomerTradeOrderList = async () => { account_id: searchForm.value.subAccountName, order_no: '', type: searchForm.value.tradeType, - start_time: dateRange.start, - end_time: dateRange.end, + start_time: startTime, + end_time: endTime, } console.log(params) const data: any = await getCustomTradeOrderListApi(params) @@ -165,10 +167,7 @@ const handleReset = () => { accountName: '', orderId: '', tradeType: '', - startTime: dateRange.start, - endTime: dateRange.end, - start_time: dateRange.start, - end_time: dateRange.end, + dateRange: [initTime.start, initTime.end], subAccountName: '', } getCustomerTradeOrderList() diff --git a/src/views/order/history/options.ts b/src/views/order/history/options.ts index a2fc802..fd91fd5 100644 --- a/src/views/order/history/options.ts +++ b/src/views/order/history/options.ts @@ -57,18 +57,19 @@ export const search = [ ], width: '140px' }, - // // 开始时间 - // { - // prop: "startTime", label: '注册开始时间', type: 'date' as const, dateType: 'date' as const, // 时间范围选择器 - // valueFormat: 'YYYY-MM-DD', - // width: '140px' - // }, - // // 结束时间 - // { - // prop: "endTime", label: '注册结束时间', type: 'date' as const, dateType: 'date' as const, // 时间范围选择器 - // valueFormat: 'YYYY-MM-DD', - // width: '140px' - // }, + // 时间范围 + { + label: '时间', + prop: 'dateRange', + type: 'date' as const, + dateType: 'datetimerange' as const, + placeholder: '请选择时间范围', + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'YYYY-MM-DD HH:mm:ss', + startPlaceholder: '开始时间', + endPlaceholder: '结束时间', + width: '340' + }, ] /** diff --git a/src/views/user/ForgotPassword.vue b/src/views/user/ForgotPassword.vue index f4f7d6e..07ca958 100644 --- a/src/views/user/ForgotPassword.vue +++ b/src/views/user/ForgotPassword.vue @@ -2,46 +2,44 @@
- + - - - - + + + + + + + + + +
+ {{ item.name }} + {{ item.code }} +
+
+
+ +
+ + + + + + + + + + + - - - -
- {{ item.name }} - {{ item.code }} -
-
-
- -
- -
- - - - - - -
-
-
-
-
-
-
- {{ activeTab === 'password' ? '去登录' : '继续' + {{ codeSent ? '重置密码' : '发送验证码' }}
@@ -78,22 +76,24 @@ const router = useRouter() //userText 实例 const userText = ref({ backText: '返回', - title: '恢复密码', + title: '忘记密码', text: '请输入您注册时使用的邮箱或手机号', account: '', - }) -//tabs实例 +// tabs实例 - 用于切换邮箱和手机 const tabList = ref([ { label: '邮箱', name: 'email' }, { label: '手机', name: 'phone' }, ]) const activeTab = ref('email') -const hideTab = ref(false) + +// 验证码是否已发送标记 +const codeSent = ref(false) // 表单实例 const forgotPasswordFormRef = ref() +const captchaRef = ref() const forgotPasswordForm = ref({ email: '', countryCode: '+86', @@ -110,13 +110,31 @@ const forgotPasswordRules = ref({ code: codeRules().code }) +// 监听 activeTab 变化,重置状态并清空所有输入字段 +watch(activeTab, (newTab, oldTab) => { + codeSent.value = false + forgotPasswordForm.value.password = '' + forgotPasswordForm.value.confirmPassword = '' + // 清空验证码输入框 + captchaRef.value?.clear() + // 切换到手机时清空邮箱,切换到邮箱时清空手机号 + if (newTab === 'phone') { + forgotPasswordForm.value.email = '' + forgotPasswordFormRef.value?.clearValidate(['email']) + } else if (newTab === 'email') { + forgotPasswordForm.value.phone = '' + forgotPasswordFormRef.value?.clearValidate(['phone']) + } + forgotPasswordFormRef.value?.clearValidate(['code', 'password', 'confirmPassword']) +}) + // 验证码实例 const showSendButton = ref(true) const sendState = ref({ isCounting: false, countdown: 0, }) -//初始化验证码倒计时状态(添加页面前缀隔离不同页面的倒计时状态) +//初始化验证码倒计时状态 const emailCaptchaState = initCaptchaState('email', 60, 'forgot_email'); // 邮箱专属 const phoneCaptchaState = initCaptchaState('phone', 60, 'forgot_phone'); // 手机专属 // 邮箱验证码状态 @@ -126,7 +144,6 @@ const { isCounting: phoneIsCounting, countdown: phoneCountdown } = phoneCaptchaS //方法 - // 统一更新sendState的方法 const updateSendState = (type: string) => { if (type === 'email') { @@ -142,167 +159,88 @@ const updateSendState = (type: string) => { } } -// 监听activeTab变化,同步sendState -watch(activeTab, (newTab) => { - if (newTab === 'email' || newTab === 'phone') { - // 切换回邮箱/手机页时,重置sendState - sendState.value = { isCounting: false, countdown: 0 } - } else if (newTab === 'code') { - // 切换到验证码页时,根据当前存储的类型更新状态 - const currentType: string = getStorage('forgotType', 'session') || 'email' - updateSendState(currentType) - } -}) - // 定义发送验证码接口 const sendCodeApi = async () => { // 发送验证码参数 const sendParams = { email: forgotPasswordForm.value.email, mobile: forgotPasswordForm.value.phone, - type:'transfer_code' + type: 'transfer_code' } return userStore.sendCode(sendParams) } //发送验证码 const handleSendCode = async () => { - // 第二步:确定类型、接收方、对应的倒计时状态和发送函数 - const type: string = getStorage('forgotType', 'session') || 'email' + // 根据当前 tab 确定类型 + const type = activeTab.value const receiver = type === 'phone' ? forgotPasswordForm.value.phone : forgotPasswordForm.value.email; const currentCaptchaState = type === 'phone' ? phoneCaptchaState : emailCaptchaState; - // 第三步:调用封装的发送函数(传正确的函数,而非字符串) + // 调用封装的发送函数 await sendCaptcha( type, receiver, - currentCaptchaState, // 只更新当前类型的倒计时状态 - () => sendCodeApi() // 传入返回Promise的函数 + currentCaptchaState, + () => sendCodeApi() ); //把状态同步给子组件 updateSendState(type) + // 标记验证码已发送 + codeSent.value = true } // 返回上一页 const handleBack = () => { - // 从密码页返回 → 验证码页 - if (activeTab.value === 'password') { - activeTab.value = 'code' - userText.value = { - ...userText.value, - title: '双重验证', - text: '请输入发送的验证码', - account: getStorage('forgot', 'session') || '' - } - // 清空密码字段 - forgotPasswordForm.value.password = '' - forgotPasswordForm.value.confirmPassword = '' - forgotPasswordFormRef.value?.clearValidate(['password', 'confirmPassword']) - } - - // 从验证码页返回 → 邮箱/手机页 - else if (activeTab.value === 'code') { - const getForgotType: string = getStorage('forgotType', 'session') || 'email' - activeTab.value = getForgotType - hideTab.value = false - userText.value = { - ...userText.value, - title: '恢复密码', - text: '请输入您注册时使用的邮箱或手机号', - account: '' - } - // 清空验证码字段 - forgotPasswordForm.value.code = '' - forgotPasswordFormRef.value?.clearValidate(['code']) - } - - // 从邮箱/手机页返回 → 重置为初始状态 - else { - activeTab.value = 'email' - forgotPasswordForm.value.email = '' - forgotPasswordForm.value.phone = '' - forgotPasswordFormRef.value?.clearValidate(['email', 'phone']) - router.push('/user/login') - } + router.push('/user/login') } -//重置密码 +//提交表单 const handleForgotPassword = async () => { if (!forgotPasswordFormRef.value) return try { - const currentTab = activeTab.value; - const getForgotType: string = getStorage('forgotType', 'session') || 'email' - // 步骤1:校验邮箱/手机号 → 切换到验证码页 - if (currentTab === 'email' || currentTab === 'phone') { - // 校验当前字段 - await forgotPasswordFormRef.value.validateField(currentTab) - // 存储账号类型和值 - setStorage('forgotType', currentTab, 'session') - setStorage('forgot', currentTab === 'email' ? forgotPasswordForm.value.email : forgotPasswordForm.value.phone, 'session') - // 更新状态 - hideTab.value = true - activeTab.value = 'code' - userText.value = { - ...userText.value, - title: '双重验证', - text: '请输入发送的验证码', - account: currentTab === 'email' ? forgotPasswordForm.value.email : forgotPasswordForm.value.phone - } - updateSendState(getForgotType) + // 根据当前 tab 校验对应的邮箱或手机号 + await forgotPasswordFormRef.value.validateField(activeTab.value) + + // 校验验证码 + await forgotPasswordFormRef.value.validateField('code') + + // 校验密码 + await forgotPasswordFormRef.value.validateField(['password', 'confirmPassword']) + + // 重置密码参数 + const forgotParams = { + mobile: activeTab.value === 'phone' ? forgotPasswordForm.value.phone : undefined, + email: activeTab.value === 'email' ? forgotPasswordForm.value.email : undefined, + code: forgotPasswordForm.value.code, + login_password1: forgotPasswordForm.value.password, + login_password2: forgotPasswordForm.value.confirmPassword, } - // 步骤2:校验验证码 → 切换到密码页 - else if (currentTab === 'code') { - // 校验验证码 - await forgotPasswordFormRef.value.validateField(currentTab) - // 更新状态 - activeTab.value = 'password' - userText.value = { - ...userText.value, - title: '设置新密码', - text: '请设置您的新登录密码', - account: getStorage('forgot', 'session') || '' - } + // 调用重置密码接口 + await userStore.forgotPassword(forgotParams) + + // 清空存储和表单 + forgotPasswordForm.value = { + email: '', + countryCode: '+86', + phone: '', + password: '', + confirmPassword: '', + code: '' } + codeSent.value = false - // 步骤3:校验密码 → 重置密码 - else if (currentTab === 'password') { - // 校验密码+确认密码 - await forgotPasswordFormRef.value.validateField(['password', 'confirmPassword']) - - // 重置密码参数 - const forgotParams = { - mobile: forgotPasswordForm.value.phone, - email: forgotPasswordForm.value.email, - code: forgotPasswordForm.value.code, - // login_password1: md5Encrypt(forgotPasswordForm.value.password), - // login_password2: md5Encrypt(forgotPasswordForm.value.confirmPassword), - login_password1: forgotPasswordForm.value.password, - login_password2: forgotPasswordForm.value.confirmPassword, - } - - // 调用重置密码接口 - await userStore.forgotPassword(forgotParams) - - // 清空存储和表单 - removeStorage('forgotType', 'session') - removeStorage('forgot', 'session') - forgotPasswordForm.value = { - email: '', - countryCode: '+86', - phone: '', - password: '', - confirmPassword: '', - code: '' - } - } + // 跳转到登录页 + ElMessage.success('密码重置成功,请登录') + router.push('/user/login') } catch (error) { console.error('表单提交失败:', error) } } -// 4. 组件卸载时清除定时器(关键:防止内存泄漏) +// 组件卸载时清除定时器 onUnmounted(() => { clearCaptchaTimer(emailCaptchaState); clearCaptchaTimer(phoneCaptchaState); @@ -316,43 +254,5 @@ onUnmounted(() => { flex-wrap: nowrap; } } - - .forgot-next { - display: flex; - justify-content: center; - width: 100%; - margin-bottom: 20px; - margin-top: 60px; - - div { - position: relative; - height: 4px; - width: 40px; - background: rgb(209 213 219 / var(--tw-bg-opacity, 1)); - border-radius: 999px; - - &::before { - content: ''; - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 0; - background-color: var(--el-color-primary); - transition: all 0.3s ease-out; - border-radius: 999px; - } - - &:nth-child(2) { - margin: 0 10px; - } - } - - .active { - &::before { - width: 100%; - } - } - } }