perf: 发送验证码交互优化

This commit is contained in:
rd
2025-09-12 14:06:36 +08:00
parent 958d7a6424
commit 2c28ff7b06
8 changed files with 38 additions and 31 deletions

View File

@ -64,6 +64,9 @@ export class Request {
const { data, status } = res; const { data, status } = res;
switch (status) { switch (status) {
case HttpStatusCode.Success: case HttpStatusCode.Success:
if (data.code !== HttpStatusCode.Success) {
message.error(data.message);
}
return data; return data;
default: default:
return Promise.reject(data); return Promise.reject(data);

View File

@ -79,7 +79,6 @@ export const useUserStore = defineStore('user', {
const { primary_enterprise } = data; const { primary_enterprise } = data;
if (!enterpriseStore.enterpriseInfo && !isEmpty(primary_enterprise)) { if (!enterpriseStore.enterpriseInfo && !isEmpty(primary_enterprise)) {
console.log('setEnterpriseInfo');
enterpriseStore.setEnterpriseInfo(primary_enterprise); enterpriseStore.setEnterpriseInfo(primary_enterprise);
} }
} }

View File

@ -16,7 +16,7 @@
:wrapperCol="{ span: 19 }" :wrapperCol="{ span: 19 }"
> >
<FormItem label="手机号" name="mobile"> <FormItem label="手机号" name="mobile">
<Input v-model:value="form.mobile" placeholder="请输入新的手机号" size="large" /> <Input v-model:value="form.mobile" placeholder="请输入新的手机号" size="large" ref="inputRef" />
</FormItem> </FormItem>
<FormItem label="获取验证码" name="captcha"> <FormItem label="获取验证码" name="captcha">
@ -54,6 +54,7 @@ import { useUserStore } from '@/stores';
const store = useUserStore(); const store = useUserStore();
const formRef = ref(); const formRef = ref();
const inputRef = ref();
const visible = ref(false); const visible = ref(false);
const timer = ref(); const timer = ref();
const isLegalMobile = ref(false); const isLegalMobile = ref(false);
@ -112,6 +113,9 @@ const canGetCaptcha = computed(() => {
// 打开弹窗 // 打开弹窗
const open = () => { const open = () => {
visible.value = true; visible.value = true;
nextTick(() => {
inputRef.value?.focus();
});
}; };
// 发送验证码 // 发送验证码

View File

@ -10,7 +10,7 @@
> >
<Form :model="form" ref="formRef"> <Form :model="form" ref="formRef">
<FormItem label="昵称" name="name"> <FormItem label="昵称" name="name">
<Input v-model:value="form.name" placeholder="请输入新昵称" size="large" /> <Input v-model:value="form.name" placeholder="请输入新昵称" size="large" ref="inputRef" />
</FormItem> </FormItem>
</Form> </Form>
<div class="flex justify-end mt-20px"> <div class="flex justify-end mt-20px">
@ -29,6 +29,7 @@ import { useUserStore } from '@/stores';
const store = useUserStore(); const store = useUserStore();
const formRef = ref(); const formRef = ref();
const inputRef = ref();
const visible = ref(false); const visible = ref(false);
const submitLoading = ref(false); const submitLoading = ref(false);
const form = ref({ const form = ref({
@ -39,6 +40,10 @@ const form = ref({
const open = (userName) => { const open = (userName) => {
form.value.name = userName; form.value.name = userName;
visible.value = true; visible.value = true;
nextTick(() => {
inputRef.value?.focus();
});
}; };
// 确定按钮点击 // 确定按钮点击

View File

@ -57,6 +57,12 @@
<Button type="text" class="pl-0" v-if="hasGetCode && countdown === 0" @click="getCaptcha">重新发送</Button> <Button type="text" class="pl-0" v-if="hasGetCode && countdown === 0" @click="getCaptcha">重新发送</Button>
</template> </template>
</div> </div>
<PuzzleVerification
:show="isVerificationVisible"
@submit="handleVerificationSubmit"
@cancel="isVerificationVisible = false"
/>
</Modal> </Modal>
</template> </template>
@ -64,8 +70,10 @@
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { Button, Form, FormItem, Input, message, Modal } from 'ant-design-vue'; import { Button, Form, FormItem, Input, message, Modal } from 'ant-design-vue';
import VerificationCode from '../verification-code/index.vue'; import VerificationCode from '../verification-code/index.vue';
import PuzzleVerification from '@/views/login/components/PuzzleVerification.vue';
import { postUpdatePasswordCaptcha, postUpdatePassword } from '@/api/all/login'; import { postUpdatePasswordCaptcha, postUpdatePassword } from '@/api/all/login';
import { postClearRateLimiter } from '@/api/all/common';
import icon1 from '@/assets/img/login/icon-close.png'; import icon1 from '@/assets/img/login/icon-close.png';
import icon2 from '@/assets/img/login/icon-open.png'; import icon2 from '@/assets/img/login/icon-open.png';
@ -75,7 +83,7 @@ const visible = ref(false);
const phone = ref(''); const phone = ref('');
const isCheckPass = ref(false); const isCheckPass = ref(false);
const formRef = ref(null); const formRef = ref(null);
const isVerificationVisible = ref(false);
// 验证码输入相关 // 验证码输入相关
const countdown = ref(0); const countdown = ref(0);
const timer = ref<number | null>(null); const timer = ref<number | null>(null);
@ -146,9 +154,20 @@ const getCaptcha = async () => {
// 重置倒计时 // 重置倒计时
countdown.value = 0; countdown.value = 0;
clearInterval(timer.value); clearInterval(timer.value);
if (error.status === 429) {
isVerificationVisible.value = true;
}
} }
}; };
const handleVerificationSubmit = async () => {
isVerificationVisible.value = false;
verificationCodeRef.value?.init();
await postClearRateLimiter();
getCaptcha();
};
// 开始倒计时 // 开始倒计时
const startCountdown = () => { const startCountdown = () => {
countdown.value = 60; countdown.value = 60;

View File

@ -45,6 +45,8 @@
.ant-input-affix-wrapper { .ant-input-affix-wrapper {
border-radius: 8px !important; border-radius: 8px !important;
} }
} }
} }

View File

@ -127,6 +127,8 @@ defineExpose({ init });
border: 1px solid #d7d7d9; border: 1px solid #d7d7d9;
outline: none; outline: none;
caret-color: #6d4cfe;
&:hover { &:hover {
border-color: #6d4cfe !important; border-color: #6d4cfe !important;
} }

View File

@ -137,21 +137,6 @@ const changePasswordModalRef = ref(null);
const changeNameModalRef = ref(null); const changeNameModalRef = ref(null);
const changeMobileModalRef = ref(null); const changeMobileModalRef = ref(null);
// const userInfo = computed(() => {
// return store.userInfo ?? {};
// });
const columns = [
{
title: '用户信息',
slotName: 'info',
},
{
title: '手机号',
slotName: 'mobile',
},
];
const infoVisible = ref(false); const infoVisible = ref(false);
const imageVisible = ref(false); const imageVisible = ref(false);
const mobileVisible = ref(false); const mobileVisible = ref(false);
@ -290,18 +275,6 @@ async function handleVerificationSubmit() {
beginCountdown(); beginCountdown();
} }
async function handleUpdateMobile() {
if (!isSendCaptcha.value) {
message.error('请先获取验证码!');
return false;
}
const res = await formRef.value.validate();
if (res === true || res === undefined) {
await updateMobile(form);
message.success('修改成功!');
}
}
function getFileExtension(filename: string): string { function getFileExtension(filename: string): string {
const match = filename.match(/\.([^.]+)$/); const match = filename.match(/\.([^.]+)$/);
return match ? match[1].toLowerCase() : ''; return match ? match[1].toLowerCase() : '';