使用il8n

This commit is contained in:
2026-05-09 15:30:10 +08:00
parent 9207ca69bb
commit 07a1214127
7 changed files with 330 additions and 81 deletions

18
src/i18n/index.ts Normal file
View File

@ -0,0 +1,18 @@
import { createI18n } from 'vue-i18n'
import zhCN from './locales/zh-CN/index'
import enUS from './locales/en-US/index'
export type { LanguageType } from '@/stores/modules/language'
// 创建 i18n 实例
const i18n = createI18n({
legacy: false, // 使用 Composition API 模式
locale: localStorage.getItem('lang') || 'zh-CN', // 默认语言
fallbackLocale: 'zh-CN', // 回退语言
messages: {
'zh-CN': zhCN,
'en-US': enUS
}
})
export default i18n

View File

@ -0,0 +1,101 @@
// English translation file
export default {
// Common
common: {
loading: 'Loading...',
submit: 'Submit',
cancel: 'Cancel',
confirm: 'Confirm',
edit: 'Edit',
delete: 'Delete',
save: 'Save',
close: 'Close',
search: 'Search',
reset: 'Reset',
pleaseInput: 'Please enter',
pleaseSelect: 'Please select',
operation: 'Operation',
status: 'Status',
createTime: 'Create Time',
updateTime: 'Update Time',
remark: 'Remark',
success: 'Operation successful',
error: 'Operation failed',
warning: 'Warning',
info: 'Info'
},
// Personal Center
personalCenter: {
pageTitle: 'Account Information',
username: 'Username',
email: 'Email',
mobile: 'Mobile',
password: 'Password',
language: 'Language',
languageDesc: 'Select your preferred communication language',
lastLogin: 'Last Login',
notSet: 'Not set',
notBound: 'Not bound',
bound: 'Bound',
goToBind: 'Go to bind',
bind: 'Bind',
modify: 'Modify',
bindEmail: 'Bind Email',
bindMobile: 'Bind Mobile',
rebindMobile: 'Rebind Mobile',
modifyUsername: 'Modify Username',
modifyPassword: 'Modify Password',
verifyMethod: 'Verification Method',
verifyAccount: 'Verification Account',
mobileVerify: 'Mobile Verification',
emailVerify: 'Email Verification',
newPassword: 'New Password',
confirmPassword: 'Confirm Password',
passwordPlaceholder: '6-12 characters, including uppercase, lowercase and special characters',
confirmPasswordPlaceholder: 'Please enter new password again',
// Validation messages
pleaseInputEmail: 'Please enter email',
emailFormatError: 'Email format is incorrect',
pleaseInputMobile: 'Please enter mobile number',
mobileFormatError: 'Mobile number format is incorrect',
pleaseInputUsername: 'Please enter username',
usernameLengthError: 'Username length must be 2-20 characters',
pleaseSelectVerifyMethod: 'Please select verification method',
pleaseInputNewPassword: 'Please enter new password',
passwordLengthError: 'Length must be 6-12 characters',
passwordComplexityError: 'Must include uppercase, lowercase and special characters',
pleaseConfirmNewPassword: 'Please confirm new password',
passwordMismatchError: 'Passwords do not match',
// Message prompts
pleaseBindMobileOrEmail: 'Please bind mobile or email first',
pleaseInputVerifyAccount: 'Please bind verification account first',
pleaseInputReceiverAccount: 'Please enter the account to receive verification code',
getUserInfoFailed: 'Failed to get user information',
languageChangeFailed: 'Failed to change language'
},
// Agent User Detail
agentUser: {
phone: 'Phone',
accountBalance: 'Account Balance',
depositAmount: 'Deposit Amount',
email: 'Email',
registerTime: 'Register Time',
historyTradeAmount: 'History Trade Amount',
tradeAccount: 'Trade Account',
accountName: 'Account Name',
balance: 'Balance',
tradeLeverage: 'Trade Leverage',
historyTradeVolume: 'History Trade Volume',
addTime: 'Add Time',
loadDetailFailed: 'Failed to load detail',
operateAccount: 'Operate Account',
role: {
1: 'Platform',
2: 'Contractor',
3: 'Special Market Maker',
4: 'Ordinary Market Maker',
5: 'Agent',
6: 'User'
}
}
}

View File

@ -0,0 +1,101 @@
// 中文翻译文件
export default {
// 通用
common: {
loading: '加载中...',
submit: '提交',
cancel: '取消',
confirm: '确认',
edit: '修改',
delete: '删除',
save: '保存',
close: '关闭',
search: '搜索',
reset: '重置',
pleaseInput: '请输入',
pleaseSelect: '请选择',
operation: '操作',
status: '状态',
createTime: '创建时间',
updateTime: '更新时间',
remark: '备注',
success: '操作成功',
error: '操作失败',
warning: '警告',
info: '提示'
},
// 个人中心
personalCenter: {
pageTitle: '账户信息',
username: '用户名',
email: '邮箱',
mobile: '手机号',
password: '密码',
language: '语言',
languageDesc: '选择您偏好的通讯语言',
lastLogin: '最后登录',
notSet: '未设置',
notBound: '未绑定',
bound: '已绑定',
goToBind: '去绑定',
bind: '绑定',
modify: '修改',
bindEmail: '绑定邮箱',
bindMobile: '绑定手机号',
rebindMobile: '重新绑定手机号',
modifyUsername: '修改用户名',
modifyPassword: '修改密码',
verifyMethod: '验证方式',
verifyAccount: '验证账号',
mobileVerify: '手机验证',
emailVerify: '邮箱验证',
newPassword: '新密码',
confirmPassword: '确认密码',
passwordPlaceholder: '6-12位含大小写+特殊字符',
confirmPasswordPlaceholder: '请再次输入新密码',
// 验证规则提示
pleaseInputEmail: '请输入邮箱',
emailFormatError: '邮箱格式不正确',
pleaseInputMobile: '请输入手机号',
mobileFormatError: '手机号格式不正确',
pleaseInputUsername: '请输入用户名',
usernameLengthError: '用户名长度 2-20 位',
pleaseSelectVerifyMethod: '请选择验证方式',
pleaseInputNewPassword: '请输入新密码',
passwordLengthError: '长度 6-12 位',
passwordComplexityError: '必须包含大小写+特殊字符',
pleaseConfirmNewPassword: '请确认新密码',
passwordMismatchError: '两次密码不一致',
// 消息提示
pleaseBindMobileOrEmail: '请先绑定手机或邮箱',
pleaseInputVerifyAccount: '请先绑定验证账号',
pleaseInputReceiverAccount: '请输入接收验证码的账号',
getUserInfoFailed: '获取用户信息失败',
languageChangeFailed: '语言切换失败'
},
// 代理用户详情
agentUser: {
phone: '手机号',
accountBalance: '账户余额',
depositAmount: '存款金额',
email: '邮箱',
registerTime: '注册时间',
historyTradeAmount: '历史交易金额',
tradeAccount: '交易账号',
accountName: '账户名称',
balance: '余额',
tradeLeverage: '交易杠杆',
historyTradeVolume: '历史交易量',
addTime: '添加时间',
loadDetailFailed: '加载详情失败',
operateAccount: '操作账户',
role: {
1: '平台',
2: '承包商',
3: '特殊做市商',
4: '普通做市商',
5: '代理',
6: '用户'
}
}
}

View File

@ -5,12 +5,14 @@ import 'element-plus/dist/index.css'
//语言配置
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import en from 'element-plus/dist/locale/en.mjs'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import i18n from './i18n'
import {setupAuthDirective} from './directives/auth'
import { setStorage } from '@/utils/storage'
import '@imengyu/vue3-context-menu/lib/vue3-context-menu.css'
@ -22,9 +24,13 @@ const app = createApp(App)
setupAuthDirective(app)
app.use(createPinia())
app.use(router)
app.use(i18n)
app.use(ContextMenu)
app.use(ElementPlus, {
locale: zhCn,
})
app.mount('#app')
// 导出 app 实例以便在其他地方使用
export default app

View File

@ -14,16 +14,11 @@ export const useLanguageStore = defineStore('language', () => {
if (!getStorage('lang')) {
setStorage('lang', initLang)
}
// const setHtmlLang = (currentLang: LanguageType) => {
// document.documentElement.lang = langMap[currentLang]
// }
// setHtmlLang(lang.value)
const changeLang = (newLang: LanguageType) => {
lang.value = newLang
setStorage('lang', newLang)
// setHtmlLang(newLang)
// i18n 的 locale 会通过 watch 自动同步
}
return { lang, changeLang }

View File

@ -23,7 +23,7 @@
<el-icon>
<Phone />
</el-icon>
<span>手机号</span>
<span>{{ t('agentUser.phone') }}</span>
</div>
<div class="item-value">{{ userInfo.phone || '-' }}</div>
</div>
@ -32,7 +32,7 @@
<el-icon>
<CreditCard />
</el-icon>
<span>账户余额</span>
<span>{{ t('agentUser.accountBalance') }}</span>
</div>
<div class="item-value text-highlight">
<AnimatedNumber :value="Number(userInfo.balance) || 0" />
@ -43,7 +43,7 @@
<el-icon>
<Money />
</el-icon>
<span>存款金额</span>
<span>{{ t('agentUser.depositAmount') }}</span>
</div>
<div class="item-value text-highlight">
<AnimatedNumber :value="Number(userInfo.deposit) || 0" />
@ -54,7 +54,7 @@
<el-icon>
<Message />
</el-icon>
<span>邮箱</span>
<span>{{ t('agentUser.email') }}</span>
</div>
<div class="item-value">{{ userInfo.email || '-' }}</div>
</div>
@ -63,7 +63,7 @@
<el-icon>
<Clock />
</el-icon>
<span>注册时间</span>
<span>{{ t('agentUser.registerTime') }}</span>
</div>
<div class="item-value">{{ userInfo.registerTime || '-' }}</div>
</div>
@ -72,7 +72,7 @@
<el-icon>
<Wallet />
</el-icon>
<span>历史交易金额</span>
<span>{{ t('agentUser.historyTradeAmount') }}</span>
</div>
<div class="item-value">
<AnimatedNumber :value="Number(userInfo.hisMeny) || 0" />
@ -98,9 +98,11 @@ defineOptions({
})
import { ref, watch, computed } from 'vue'
import { ElAvatar, ElIcon, ElDrawer, ElButton, ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
import { UserFilled, Phone, Message, Money, Wallet, Clock, CreditCard } from '@element-plus/icons-vue'
import CustomerListTable from '@/components/common/Table.vue'
import { getCustomerDetailApi } from '@/api/modules/agent/customerDetail'
import { useLanguageStore } from '@/stores/modules/language'
import dayjs from 'dayjs'
import AnimatedNumber from './AnimatedNumber.vue'
@ -115,14 +117,18 @@ import type {
TableColumn
} from '@/api/types/agent'
const roleMap: Record<RoleType, string> = {
1: '平台',
2: '承包商',
3: '特殊做市商',
4: '普通做市商',
5: '代理',
6: '用户',
}
const { t, locale } = useI18n()
const languageStore = useLanguageStore()
// 使 computed
const roleMap = computed<Record<RoleType, string>>(() => ({
1: t('agentUser.role.1'),
2: t('agentUser.role.2'),
3: t('agentUser.role.3'),
4: t('agentUser.role.4'),
5: t('agentUser.role.5'),
6: t('agentUser.role.6'),
}))
//
const props = defineProps<{
@ -165,13 +171,15 @@ const userInfo = ref<UserDisplayInfo>({
//
const tableData = ref<TableDataRow[]>([])
const tableColumnsOptions = ref<TableColumn[]>([
{ label: '交易账号', prop: 'tradeAccount' },
{ label: '账户名称', prop: 'accountName' },
{ label: '余额', prop: 'balance', sortable: true },
{ label: '交易杠杆', prop: 'leverage' },
{ label: '历史交易量', prop: 'tradeVolume' },
{ label: '添加时间', prop: 'addTime', width: 180 }
//
const tableColumnsOptions = computed<TableColumn[]>(() => [
{ label: t('agentUser.tradeAccount'), prop: 'tradeAccount' },
{ label: t('agentUser.accountName'), prop: 'accountName' },
{ label: t('agentUser.balance'), prop: 'balance', sortable: true },
{ label: t('agentUser.tradeLeverage'), prop: 'leverage' },
{ label: t('agentUser.historyTradeVolume'), prop: 'tradeVolume' },
{ label: t('agentUser.addTime'), prop: 'addTime', width: 180 }
])
@ -187,7 +195,7 @@ const loadDetailData = async (id: string | number) => {
userInfo.value = {
name: user.email || user.mobile || '-',
id: user.id,
role: roleMap[user.role_id] || '-',
role: roleMap.value[user.role_id] || '-',
phone: user.mobile || '-',
email: user.email || '-',
balance: Number(user.capital_amount) || 0,
@ -207,7 +215,7 @@ const loadDetailData = async (id: string | number) => {
}))
} catch (err) {
console.error('加载详情失败:', err);
ElMessage.error('加载详情失败')
ElMessage.error(t('agentUser.loadDetailFailed'))
} finally {
loading.value = false
tableLoading.value = false
@ -224,9 +232,18 @@ watch(
{ immediate: true }
)
// i18n locale
watch(
() => languageStore.lang,
(newLang) => {
locale.value = newLang
},
{ immediate: true }
)
//
const handleAccount = (row: TableDataRow) => {
ElMessage.success('操作账户:' + row.tradeAccount)
ElMessage.success(t('agentUser.operateAccount') + '' + row.tradeAccount)
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<div class="personal-center">
<div class="page-header">
<h2>账户信息</h2>
<h2>{{ t('personalCenter.pageTitle') }}</h2>
</div>
<div class="content-wrapper">
@ -17,9 +17,9 @@
<div class="info-text">
<div class="username-row">
<span class="username-text">{{ userInfo.username }}</span>
<el-button link type="primary" size="small" @click="showEditDialog('username')">修改</el-button>
<el-button link type="primary" size="small" @click="showEditDialog('username')">{{ t('personalCenter.modify') }}</el-button>
</div>
<div class="login-time">最后登录{{ userInfo.last_login }}</div>
<div class="login-time">{{ t('personalCenter.lastLogin') }}{{ userInfo.last_login }}</div>
</div>
</div>
</el-card>
@ -27,35 +27,35 @@
<el-card class="card info-card">
<div class="info-list">
<div class="info-item">
<span class="label">邮箱</span>
<span class="value">{{ userInfo.email || '未设置' }}</span>
<span class="label">{{ t('personalCenter.email') }}</span>
<span class="value">{{ userInfo.email || t('personalCenter.notSet') }}</span>
<template v-if="!userInfo.email">
<el-button link type="primary" @click="showEditDialog('email')">去绑定</el-button>
<el-button link type="primary" @click="showEditDialog('email')">{{ t('personalCenter.goToBind') }}</el-button>
</template>
<template v-else>
<el-tag type="success" size="small">已绑定</el-tag>
<el-tag type="success" size="small">{{ t('personalCenter.bound') }}</el-tag>
</template>
</div>
<div class="info-item">
<span class="label">手机号</span>
<span class="value">{{ userInfo.mobile || '未绑定' }}</span>
<span class="label">{{ t('personalCenter.mobile') }}</span>
<span class="value">{{ userInfo.mobile || t('personalCenter.notBound') }}</span>
<el-button v-if="!userInfo.mobile" link type="primary" @click="showEditDialog('mobile')">
绑定
{{ t('personalCenter.bind') }}
</el-button>
<template v-else>
<el-tag type="success" size="small">已绑定</el-tag>
<el-tag type="success" size="small">{{ t('personalCenter.bound') }}</el-tag>
</template>
</div>
<div class="info-item">
<span class="label">密码</span>
<el-button link type="primary" @click="showPasswordDialog">修改</el-button>
<span class="label">{{ t('personalCenter.password') }}</span>
<el-button link type="primary" @click="showPasswordDialog">{{ t('personalCenter.modify') }}</el-button>
</div>
<div class="info-item">
<span class="label">语言</span>
<span class="value">选择您偏好的通讯语言</span>
<span class="label">{{ t('personalCenter.language') }}</span>
<span class="value">{{ t('personalCenter.languageDesc') }}</span>
<el-select v-model="userInfo.lang_type" @change="handleLanguageChange" style="width: 130px" size="small">
<el-option label="简体中文" :value="1" />
<el-option label="English" :value="2" />
@ -70,7 +70,7 @@
@cancel="handleEditDialogReset" @close="handleEditDialogReset">
<el-form ref="editFormRef" :model="editForm" :rules="getEditRules()" label-width="80px" label-position="top">
<el-form-item :label="editForm.label" prop="value">
<el-input v-if="editField !== 'language'" v-model="editForm.value" :placeholder="`请输入${editForm.label}`"
<el-input v-if="editField !== 'language'" v-model="editForm.value" :placeholder="`${t('common.pleaseInput')}${editForm.label}`"
size="large" />
</el-form-item>
@ -80,20 +80,20 @@
</Dialog>
<!-- 密码修改弹窗 验证码模式 -->
<Dialog :visible="passwordDialogVisible" title="修改密码" width="500px" @confirm="handlePasswordConfirm"
<Dialog :visible="passwordDialogVisible" :title="t('personalCenter.modifyPassword')" width="500px" @confirm="handlePasswordConfirm"
@cancel="handlePasswordDialogReset" @close="handlePasswordDialogReset">
<el-form ref="passwordFormRef" :model="passwordForm" :rules="passwordFormRules" label-width="100px"
label-position="top">
<!-- 选择验证方式 -->
<el-form-item label="验证方式" prop="verifyType">
<el-form-item :label="t('personalCenter.verifyMethod')" prop="verifyType">
<el-radio-group v-model="passwordForm.verifyType" @change="onVerifyTypeChange">
<el-radio label="mobile" :disabled="!userInfo.mobile">手机验证</el-radio>
<el-radio label="email" :disabled="!userInfo.email">邮箱验证</el-radio>
<el-radio label="mobile" :disabled="!userInfo.mobile">{{ t('personalCenter.mobileVerify') }}</el-radio>
<el-radio label="email" :disabled="!userInfo.email">{{ t('personalCenter.emailVerify') }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 验证账号 -->
<el-form-item label="验证账号">
<el-form-item :label="t('personalCenter.verifyAccount')">
<span style="font-weight:500;color:#333">
{{ passwordForm.verifyType === 'mobile' ? userInfo.mobile : userInfo.email }}
</span>
@ -104,14 +104,14 @@
:show-send-button="showPwdSendButton" :send-state="pwdSendState" />
<!-- 新密码1 -->
<el-form-item label="新密码" prop="login_password1">
<el-input v-model="passwordForm.login_password1" type="password" show-password placeholder="6-12位含大小写+特殊字符"
<el-form-item :label="t('personalCenter.newPassword')" prop="login_password1">
<el-input v-model="passwordForm.login_password1" type="password" show-password :placeholder="t('personalCenter.passwordPlaceholder')"
size="large" />
</el-form-item>
<!-- 新密码2 -->
<el-form-item label="确认密码" prop="login_password2">
<el-input v-model="passwordForm.login_password2" type="password" show-password placeholder="请再次输入新密码"
<el-form-item :label="t('personalCenter.confirmPassword')" prop="login_password2">
<el-input v-model="passwordForm.login_password2" type="password" show-password :placeholder="t('personalCenter.confirmPasswordPlaceholder')"
size="large" />
</el-form-item>
</el-form>
@ -124,9 +124,10 @@
defineOptions({
name: 'PersonalCenter'
})
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue';
import { ref, reactive, onMounted, onUnmounted, nextTick, watch } from 'vue';
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
import { UserFilled } from '@element-plus/icons-vue';
import { useI18n } from 'vue-i18n';
import Dialog from '@/components/common/Dialog.vue';
import UserCaptcha from '@/views/user/components/Captcha.vue';
import { useUserStore } from '@/stores/modules/user';
@ -134,6 +135,7 @@ import { useLanguageStore } from '@/stores/modules/language';
import { sendCaptcha, initCaptchaState, clearCaptchaTimer } from '@/utils/sendCaptcha';
import { codeRules } from '@/views/user/config/rules';
const { t, locale } = useI18n()
//
import type {
UserInfo,
@ -206,20 +208,20 @@ const getEditRules = (): FormRules => {
switch (editField.value) {
case 'email':
rules.value = [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
{ required: true, message: t('personalCenter.pleaseInputEmail'), trigger: 'blur' },
{ type: 'email', message: t('personalCenter.emailFormatError'), trigger: 'blur' }
];
return rules;
case 'mobile':
rules.value = [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^\+?\d{5,20}$/, message: '手机号格式不正确', trigger: 'blur' }
{ required: true, message: t('personalCenter.pleaseInputMobile'), trigger: 'blur' },
{ pattern: /^\+?\d{5,20}$/, message: t('personalCenter.mobileFormatError'), trigger: 'blur' }
];
return rules;
case 'username':
rules.value = [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 20, message: '用户名长度 2-20 位', trigger: 'blur' }
{ required: true, message: t('personalCenter.pleaseInputUsername'), trigger: 'blur' },
{ min: 2, max: 20, message: t('personalCenter.usernameLengthError'), trigger: 'blur' }
];
return rules;
default:
@ -229,22 +231,22 @@ const getEditRules = (): FormRules => {
//
const passwordFormRules = ref<FormRules>({
verifyType: [{ required: true, message: '请选择验证方式', trigger: 'change' }],
verifyType: [{ required: true, message: t('personalCenter.pleaseSelectVerifyMethod'), trigger: 'change' }],
code: codeRules().code,
login_password1: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{ min: 6, max: 12, message: '长度 6-12 位', trigger: 'blur' },
{ required: true, message: t('personalCenter.pleaseInputNewPassword'), trigger: 'blur' },
{ min: 6, max: 12, message: t('personalCenter.passwordLengthError'), trigger: 'blur' },
{
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{6,12}$/,
message: '必须包含大小写+特殊字符', trigger: 'blur'
message: t('personalCenter.passwordComplexityError'), trigger: 'blur'
}
],
login_password2: [
{ required: true, message: '请确认新密码', trigger: 'blur' },
{ required: true, message: t('personalCenter.pleaseConfirmNewPassword'), trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (value !== passwordForm.login_password1) {
callback(new Error('两次密码不一致'));
callback(new Error(t('personalCenter.passwordMismatchError')));
} else {
callback();
}
@ -261,7 +263,7 @@ const fetchUserProfile = async () => {
Object.assign(userInfo, res);
languageStore.changeLang(res.lang_type === 1 ? 'zh-CN' : 'en-US');
} catch (error) {
ElMessage.error('获取用户信息失败');
ElMessage.error(t('personalCenter.getUserInfoFailed'));
console.error('获取用户信息失败:', error);
}
};
@ -272,19 +274,19 @@ const showEditDialog = (field: 'email' | 'mobile' | 'username') => {
editForm.code = '';
switch (field) {
case 'email':
editForm.label = '邮箱';
editForm.label = t('personalCenter.email');
editForm.value = userInfo.email;
dialogTitle.value = '绑定邮箱';
dialogTitle.value = t('personalCenter.bindEmail');
break;
case 'mobile':
editForm.label = '手机号';
editForm.label = t('personalCenter.mobile');
editForm.value = userInfo.mobile;
dialogTitle.value = userInfo.mobile ? '重新绑定手机号' : '绑定手机号';
dialogTitle.value = userInfo.mobile ? t('personalCenter.rebindMobile') : t('personalCenter.bindMobile');
break;
case 'username':
editForm.label = '用户名';
editForm.label = t('personalCenter.username');
editForm.value = userInfo.username;
dialogTitle.value = '修改用户名';
dialogTitle.value = t('personalCenter.modifyUsername');
break;
}
dialogVisible.value = true;
@ -296,13 +298,13 @@ const handleSendCaptcha = async () => {
const type = editField.value === 'email' ? 'email' : 'phone';
const receiver = editForm.value?.trim();
if (!receiver) {
ElMessage.warning('请输入接收验证码的账号');
ElMessage.warning(t('personalCenter.pleaseInputReceiverAccount'));
return;
}
const currentState = type === 'email' ? emailCaptchaState : phoneCaptchaState;
await sendCaptcha(type, receiver, currentState, () => {
return userStore.sendCode({
reg_type: type === 'email' ? 1 : 2,
reg_type: userStore.userInfo!.reg_type,
[type === 'email' ? 'email' : 'mobile']: receiver,
type: type === 'email' ? 'transfer_code' : 'bindMobile_code'
});
@ -358,7 +360,7 @@ const handleEditConfirm = async () => {
// ==================== ====================
const showPasswordDialog = () => {
if (!userInfo.mobile && !userInfo.email) {
ElMessage.warning('请先绑定手机或邮箱');
ElMessage.warning(t('personalCenter.pleaseBindMobileOrEmail'));
return;
}
passwordForm.verifyType = userInfo.mobile ? 'mobile' : 'email';
@ -389,14 +391,14 @@ const handleSendPwdCaptcha = async () => {
const type = passwordForm.verifyType === 'email' ? 'email' : 'phone';
const receiver = passwordForm.verifyType === 'email' ? userInfo.email : userInfo.mobile;
if (!receiver) {
ElMessage.warning('请先绑定验证账号');
ElMessage.warning(t('personalCenter.pleaseInputVerifyAccount'));
return;
}
const currentState = passwordForm.verifyType === 'email' ? pwdEmailCaptchaState : pwdMobileCaptchaState;
await sendCaptcha(type, receiver, currentState, () => {
return userStore.sendCode({
reg_type: passwordForm.verifyType === 'email' ? 1 : 2,
reg_type: userStore.userInfo!.reg_type,
[passwordForm.verifyType]: receiver,
type: 'resetPass_code'
});
@ -416,7 +418,7 @@ const handlePasswordConfirm = async () => {
await passwordFormRef.value.validate();
const params: UpdatePwdByCaptchaParams = {
reg_type: passwordForm.verifyType === 'email' ? 1 : 2,
reg_type: userStore.userInfo!.reg_type,
email: passwordForm.verifyType === 'email' ? userInfo.email : undefined,
mobile: passwordForm.verifyType === 'mobile' ? userInfo.mobile : undefined,
code: passwordForm.code,
@ -443,6 +445,15 @@ const handlePasswordDialogReset = () => {
passwordFormRef.value?.resetFields();
};
// i18n locale
watch(
() => languageStore.lang,
(newLang) => {
locale.value = newLang
},
{ immediate: true }
)
onMounted(() => {
fetchUserProfile();
});