zayac-admin/continew-admin-ui/src/views/system/user/center/components/security-settings/update-phone.vue

271 lines
7.2 KiB
Vue

<template>
<a-list-item-meta>
<template #avatar>
<a-typography-paragraph>
{{ $t('userCenter.securitySettings.phone.label') }}
</a-typography-paragraph>
</template>
<template #description>
<div class="tip">
{{ $t('userCenter.securitySettings.phone.tip') }}
</div>
<div class="content">
<a-typography-paragraph v-if="userStore.phone">
{{ userStore.phone }}
</a-typography-paragraph>
<a-typography-paragraph v-else class="tip">
{{ $t('userCenter.securitySettings.phone.content') }}
</a-typography-paragraph>
</div>
<div class="operation">
<a-link
:title="$t('userCenter.securitySettings.button.update')"
@click="toUpdate"
>
{{ $t('userCenter.securitySettings.button.update') }}
</a-link>
</div>
</template>
</a-list-item-meta>
<a-modal
:title="$t('userCenter.securitySettings.updatePhone.modal.title')"
:visible="visible"
:mask-closable="false"
:esc-to-close="false"
@ok="handleUpdate"
@cancel="handleCancel"
>
<a-form ref="formRef" :model="form" :rules="rules" size="large">
<a-form-item
:label="
$t('userCenter.securitySettings.updatePhone.form.label.newPhone')
"
field="newPhone"
>
<a-input
v-model="form.newPhone"
:placeholder="
$t(
'userCenter.securitySettings.updatePhone.form.placeholder.newPhone',
)
"
allow-clear
/>
</a-form-item>
<a-form-item
:label="
$t('userCenter.securitySettings.updatePhone.form.label.captcha')
"
field="captcha"
>
<a-input
v-model="form.captcha"
:placeholder="
$t('userCenter.securitySettings.form.placeholder.captcha')
"
:max-length="4"
allow-clear
style="width: 80%"
/>
<a-button
:loading="captchaLoading"
type="primary"
:disabled="captchaDisable"
class="captcha-btn"
@click="handleOpenBehaviorCaptcha"
>
{{ captchaBtnName }}
</a-button>
</a-form-item>
<a-form-item
:label="
$t(
'userCenter.securitySettings.updatePhone.form.label.currentPassword',
)
"
field="currentPassword"
>
<a-input-password
v-model="form.currentPassword"
:placeholder="
$t(
'userCenter.securitySettings.updatePhone.form.placeholder.currentPassword',
)
"
:max-length="32"
allow-clear
/>
</a-form-item>
</a-form>
<Verify
ref="verifyRef"
:mode="captchaMode"
:captcha-type="captchaType"
:img-size="{ width: '330px', height: '155px' }"
@success="handleSendCaptcha"
></Verify>
</a-modal>
</template>
<script lang="ts" setup>
import { getCurrentInstance, ref, reactive, computed } from 'vue';
import { FieldRule } from '@arco-design/web-vue';
import { BehaviorCaptchaReq, getSmsCaptcha } from '@/api/common/captcha';
import { UserPhoneUpdateReq, updatePhone } from '@/api/system/user-center';
import { useI18n } from 'vue-i18n';
import { useUserStore } from '@/store';
import { encryptByRsa } from '@/utils/encrypt';
const { proxy } = getCurrentInstance() as any;
const { t } = useI18n();
const userStore = useUserStore();
const captchaTime = ref(60);
const captchaTimer = ref();
const captchaLoading = ref(false);
const captchaDisable = ref(true);
const captchaType = ref('blockPuzzle');
const captchaMode = ref('pop');
const visible = ref(false);
const captchaBtnNameKey = ref('userCenter.securitySettings.captcha.get');
const captchaBtnName = computed(() => t(captchaBtnNameKey.value));
// 表单数据
const form = reactive<UserPhoneUpdateReq>({
newPhone: '',
captcha: '',
currentPassword: '',
});
// 表单验证规则
const rules = computed((): Record<string, FieldRule[]> => {
return {
newPhone: [
{
required: true,
message: t(
'userCenter.securitySettings.updatePhone.form.error.required.newPhone',
),
},
{
match: /^1[3-9]\d{9}$/,
message: t(
'userCenter.securitySettings.updatePhone.form.error.match.newPhone',
),
},
],
captcha: [
{
required: true,
message: t('userCenter.securitySettings.form.error.required.captcha'),
},
],
currentPassword: [
{
required: true,
message: t(
'userCenter.securitySettings.updatePhone.form.error.required.currentPassword',
),
},
],
};
});
/**
* 重置验证码
*/
const resetCaptcha = () => {
window.clearInterval(captchaTimer.value);
captchaTime.value = 60;
captchaBtnNameKey.value = 'userCenter.securitySettings.captcha.get';
captchaDisable.value = false;
};
/**
* 弹出行为验证码
*/
const handleOpenBehaviorCaptcha = () => {
if (captchaLoading.value) return;
proxy.$refs.formRef.validateField('newPhone', (valid: any) => {
if (!valid) {
proxy.$refs.verifyRef.show();
}
});
};
/**
* 发送验证码
*/
const handleSendCaptcha = (captchaParam: BehaviorCaptchaReq) => {
if (captchaLoading.value) return;
proxy.$refs.formRef.validateField('newPhone', (valid: any) => {
if (!valid) {
captchaLoading.value = true;
captchaBtnNameKey.value = 'userCenter.securitySettings.captcha.ing';
getSmsCaptcha(form.newPhone, captchaParam)
.then((res) => {
captchaLoading.value = false;
captchaDisable.value = true;
captchaBtnNameKey.value = `${t(
'userCenter.securitySettings.captcha.get',
)}(${(captchaTime.value -= 1)}s)`;
captchaTimer.value = window.setInterval(() => {
captchaTime.value -= 1;
captchaBtnNameKey.value = `${t(
'userCenter.securitySettings.captcha.get',
)}(${captchaTime.value}s)`;
if (captchaTime.value <= 0) {
resetCaptcha();
}
}, 1000);
proxy.$message.success(res.msg);
})
.catch(() => {
resetCaptcha();
captchaLoading.value = false;
});
}
});
};
/**
* 取消
*/
const handleCancel = () => {
visible.value = false;
proxy.$refs.formRef.resetFields();
resetCaptcha();
};
/**
* 修改
*/
const handleUpdate = () => {
proxy.$refs.formRef.validate((valid: any) => {
if (!valid) {
updatePhone({
newPhone: form.newPhone,
captcha: form.captcha,
currentPassword: encryptByRsa(form.currentPassword) || '',
}).then((res) => {
handleCancel();
userStore.getInfo();
proxy.$message.success(res.msg);
});
}
});
};
/**
* 打开修改对话框
*/
const toUpdate = () => {
visible.value = true;
};
</script>
<style scoped lang="less">
.captcha-btn {
margin-left: 5px;
}
</style>