feat: 客户注册对齐登录壳,并拆分网页/微信注册入口
All checks were successful
Build and Deploy Front / deploy (push) Successful in 7m11s

登录仅保留账号与微信;注册先选渠道,代理码仅 URL 携带时自动绑定。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-10-30 17:07:23 +08:00
parent 17c4380c1b
commit 351b465d5b
11 changed files with 1229 additions and 225 deletions

View File

@ -1,4 +1,5 @@
import localeLogin from '@/views/login/locale/en-US'; import localeLogin from '@/views/login/locale/en-US';
import localeRegister from '@/views/register/locale/en-US';
import localeWechat from '@/views/wechat/locale/en-US'; import localeWechat from '@/views/wechat/locale/en-US';
import localeH5Center from '@/views/h5/customer-center/locale/en-US'; import localeH5Center from '@/views/h5/customer-center/locale/en-US';
import localeH5AdminCenter from '@/views/h5/admin-center/locale/en-US'; import localeH5AdminCenter from '@/views/h5/admin-center/locale/en-US';
@ -13,6 +14,7 @@ export default {
'app.language': 'Language', 'app.language': 'Language',
'navbar.action.locale': 'Switch to English', 'navbar.action.locale': 'Switch to English',
...localeLogin, ...localeLogin,
...localeRegister,
...localeWechat, ...localeWechat,
...localeH5Track, ...localeH5Track,
...localeH5Center, ...localeH5Center,

View File

@ -1,4 +1,5 @@
import localeLogin from '@/views/login/locale/zh-CN'; import localeLogin from '@/views/login/locale/zh-CN';
import localeRegister from '@/views/register/locale/zh-CN';
import localeWechat from '@/views/wechat/locale/zh-CN'; import localeWechat from '@/views/wechat/locale/zh-CN';
import localeH5Center from '@/views/h5/customer-center/locale/zh-CN'; import localeH5Center from '@/views/h5/customer-center/locale/zh-CN';
import localeH5AdminCenter from '@/views/h5/admin-center/locale/zh-CN'; import localeH5AdminCenter from '@/views/h5/admin-center/locale/zh-CN';
@ -13,6 +14,7 @@ export default {
'app.language': '语言', 'app.language': '语言',
'navbar.action.locale': '切换为中文', 'navbar.action.locale': '切换为中文',
...localeLogin, ...localeLogin,
...localeRegister,
...localeWechat, ...localeWechat,
...localeH5Track, ...localeH5Track,
...localeH5Center, ...localeH5Center,

View File

@ -463,25 +463,41 @@ export default {
'marketing.register.title': 'Register', 'marketing.register.title': 'Register',
'marketing.register.subtitle': 'Member pricing and welcome benefits', 'marketing.register.subtitle': 'Member pricing and welcome benefits',
'marketing.register.brandHint': 'Welcome to IDE customer portal',
'marketing.register.brandHint.web': 'Register with email & phone',
'marketing.register.brandHint.wechat': 'Register with WeChat',
'marketing.register.choose.web': 'Web register',
'marketing.register.choose.webDesc': 'Fill in details and open your portal',
'marketing.register.choose.wechat': 'WeChat register',
'marketing.register.choose.wechatDesc': 'Scan to authorize and finish quickly',
'marketing.register.backToChoose': '← Back to options',
'marketing.register.referrerHint': 'Invited by {name} ({code})', 'marketing.register.referrerHint': 'Invited by {name} ({code})',
'marketing.register.invalidRef': 'Invalid invite code — you can still register', 'marketing.register.invalidRef': 'Invalid invite code — you can still register',
'marketing.register.referrerLoading': 'Validating invite code…', 'marketing.register.referrerLoading': 'Validating invite code…',
'marketing.register.referrerTimeout': 'marketing.register.referrerTimeout':
'Invite validation timed out. Check your network and refresh; you can still register.', 'Invite validation timed out. Check your network and refresh; you can still register.',
'marketing.register.agentHint': 'Channel partner · {name} ({code})', 'marketing.register.referrerBadge': 'Friend invite',
'marketing.register.agentHint': '{name} · {code}',
'marketing.register.agentBadge': 'Channel partner',
'marketing.register.agentFallbackName': 'Partner',
'marketing.register.agentField': 'Agent code (optional)', 'marketing.register.agentField': 'Agent code (optional)',
'marketing.register.agentPlaceholder': 'Enter agent code if you were referred by a partner', 'marketing.register.agentPlaceholder': 'Enter agent code if you were referred by a partner',
'marketing.register.agentLockedHint': 'marketing.register.agentLockedHint': 'You will be linked to the partner above after register',
'Locked by invite link; you will be bound to this agent after register',
'marketing.register.agentInvalid': 'Agent code is invalid or disabled', 'marketing.register.agentInvalid': 'Agent code is invalid or disabled',
'marketing.register.agentValidating': 'Validating agent code…', 'marketing.register.agentValidating': 'Validating agent code…',
'marketing.register.agentPriorityHint': 'marketing.register.agentPriorityHint':
'Agent code filled — channel agent binding takes priority over friend invite', 'Agent code filled — channel agent binding takes priority over friend invite',
'marketing.register.customerName': 'Name', 'marketing.register.customerName': 'Name',
'marketing.register.customerNamePlaceholder': 'Your name',
'marketing.register.phone': 'Phone', 'marketing.register.phone': 'Phone',
'marketing.register.phonePlaceholder': 'Mobile number',
'marketing.register.email': 'Email', 'marketing.register.email': 'Email',
'marketing.register.emailPlaceholder': 'Email address',
'marketing.register.password': 'Password', 'marketing.register.password': 'Password',
'marketing.register.passwordPlaceholder': '6+ letters and digits',
'marketing.register.confirmPassword': 'Confirm password', 'marketing.register.confirmPassword': 'Confirm password',
'marketing.register.confirmPasswordPlaceholder': 'Re-enter password',
'marketing.register.submit': 'Register', 'marketing.register.submit': 'Register',
'marketing.register.submitting': 'Registering…', 'marketing.register.submitting': 'Registering…',
'marketing.register.success': 'Registered — please sign in', 'marketing.register.success': 'Registered — please sign in',

View File

@ -460,22 +460,39 @@ export default {
'marketing.register.title': '客户注册', 'marketing.register.title': '客户注册',
'marketing.register.subtitle': '注册即享会员价与新人福利', 'marketing.register.subtitle': '注册即享会员价与新人福利',
'marketing.register.brandHint': '欢迎注册 IDE 客户门户',
'marketing.register.brandHint.web': '网页注册 IDE 客户账号',
'marketing.register.brandHint.wechat': '微信扫码注册 IDE 客户账号',
'marketing.register.choose.web': '网页注册',
'marketing.register.choose.webDesc': '填写资料,立即开通客户门户',
'marketing.register.choose.wechat': '微信注册',
'marketing.register.choose.wechatDesc': '扫码授权,快捷完成注册',
'marketing.register.backToChoose': '← 返回选择注册方式',
'marketing.register.referrerHint': '您正通过 {name}({code})的邀请注册', 'marketing.register.referrerHint': '您正通过 {name}({code})的邀请注册',
'marketing.register.invalidRef': '邀请码无效或已失效,您仍可正常注册', 'marketing.register.invalidRef': '邀请码无效或已失效,您仍可正常注册',
'marketing.register.referrerLoading': '正在校验邀请码…', 'marketing.register.referrerLoading': '正在校验邀请码…',
'marketing.register.referrerTimeout': '邀请码校验超时,请检查网络后刷新;您仍可继续注册', 'marketing.register.referrerTimeout': '邀请码校验超时,请检查网络后刷新;您仍可继续注册',
'marketing.register.agentHint': '渠道推荐 · {name}({code})', 'marketing.register.referrerBadge': '好友邀请',
'marketing.register.agentHint': '{name} · {code}',
'marketing.register.agentBadge': '渠道推荐',
'marketing.register.agentFallbackName': '渠道代理',
'marketing.register.agentField': '代理编号(选填)', 'marketing.register.agentField': '代理编号(选填)',
'marketing.register.agentPlaceholder': '有渠道推荐人可填写其代理编号', 'marketing.register.agentPlaceholder': '有渠道推荐人可填写其代理编号',
'marketing.register.agentLockedHint': '已由专属链接锁定,注册后自动绑定该代理', 'marketing.register.agentLockedHint': '注册完成后将关联上方推荐渠道',
'marketing.register.agentInvalid': '代理编号无效或已停用', 'marketing.register.agentInvalid': '代理编号无效或已停用',
'marketing.register.agentValidating': '正在校验代理编号…', 'marketing.register.agentValidating': '正在校验代理编号…',
'marketing.register.agentPriorityHint': '已填写代理编号,将优先绑定渠道代理(不走好友邀请)', 'marketing.register.agentPriorityHint': '已填写代理编号,将优先绑定渠道代理(不走好友邀请)',
'marketing.register.customerName': '客户名称', 'marketing.register.customerName': '客户名称',
'marketing.register.customerNamePlaceholder': '请输入客户名称',
'marketing.register.phone': '手机号', 'marketing.register.phone': '手机号',
'marketing.register.phonePlaceholder': '请输入手机号',
'marketing.register.email': '邮箱', 'marketing.register.email': '邮箱',
'marketing.register.emailPlaceholder': '请输入邮箱',
'marketing.register.password': '密码', 'marketing.register.password': '密码',
'marketing.register.passwordPlaceholder': '6 位以上字母数字组合',
'marketing.register.confirmPassword': '确认密码', 'marketing.register.confirmPassword': '确认密码',
'marketing.register.confirmPasswordPlaceholder': '请再次输入密码',
'marketing.register.submit': '注册', 'marketing.register.submit': '注册',
'marketing.register.submitting': '注册中…', 'marketing.register.submitting': '注册中…',
'marketing.register.success': '注册成功,请登录', 'marketing.register.success': '注册成功,请登录',

View File

@ -64,7 +64,10 @@
</div> </div>
</form> </form>
<div v-if="props.loginType === OmsLoginType.Customer" class="wechat-login-entry"> <div v-if="props.loginType === OmsLoginType.Customer" class="login-alt-entry">
<div class="login-alt-entry__divider">
<span>{{ t('login.altEntry.or') }}</span>
</div>
<a-tooltip :content="t('login.switchToWechat')"> <a-tooltip :content="t('login.switchToWechat')">
<button <button
type="button" type="button"
@ -77,6 +80,10 @@
<icon-wechat :size="28" /> <icon-wechat :size="28" />
</button> </button>
</a-tooltip> </a-tooltip>
<p class="login-alt-entry__hint">
{{ t('login.noAccount') }}
<a-link @click="goRegister">{{ t('login.goRegister') }}</a-link>
</p>
</div> </div>
<a-modal <a-modal
@ -93,7 +100,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, nextTick, inject, type ShallowRef } from 'vue'; import { ref, reactive, computed, nextTick, inject, type ShallowRef } from 'vue';
import { useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { IconWechat } from '@arco-design/web-vue/es/icon'; import { IconWechat } from '@arco-design/web-vue/es/icon';
@ -123,9 +130,20 @@ const emit = defineEmits<{
prefetchWechat: []; prefetchWechat: [];
}>(); }>();
const route = useRoute();
const router = useRouter(); const router = useRouter();
const rbacUserStore = useRbacUserStore(); const rbacUserStore = useRbacUserStore();
function goRegister() {
const query: Record<string, string> = {};
for (const key of ['agent', 'agentCode', 'ref', 'invite', 'advisor', 'redirect'] as const) {
const raw = route.query[key];
const value = typeof raw === 'string' ? raw.trim() : '';
if (value) query[key] = value;
}
void router.push({ path: '/register', query });
}
const passwordInputRef = ref<{ focus?: () => void } | null>(null); const passwordInputRef = ref<{ focus?: () => void } | null>(null);
const loading = ref(false); const loading = ref(false);
const showPassword = ref(false); const showPassword = ref(false);
@ -601,12 +619,31 @@ async function handleSubmit() {
} }
} }
.wechat-login-entry { .login-alt-entry {
display: flex; display: flex;
justify-content: center; flex-direction: column;
align-items: center;
gap: 14px;
margin-top: 18px; margin-top: 18px;
} }
.login-alt-entry__divider {
display: flex;
align-items: center;
gap: 12px;
width: 100%;
font-size: 12px;
color: rgba(100, 116, 139, 0.75);
&::before,
&::after {
content: '';
flex: 1;
height: 1px;
background: rgba(148, 163, 184, 0.35);
}
}
.wechat-entry-btn { .wechat-entry-btn {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@ -638,6 +675,17 @@ async function handleSubmit() {
} }
} }
.login-alt-entry__hint {
margin: 0;
font-size: 13px;
color: #86909c;
:deep(.arco-link) {
color: var(--app-primary-color);
font-weight: 600;
}
}
.agreement-content { .agreement-content {
max-height: 55vh; max-height: 55vh;
overflow-y: auto; overflow-y: auto;

View File

@ -51,7 +51,7 @@
</div> </div>
</div> </div>
<div v-if="!scanned" class="tips" :class="{ 'tips--warn': expired }"> <div v-if="!scanned" class="tips" :class="{ 'tips--warn': expired }">
{{ expired ? t('login.wechat.expiredTip') : t('login.wechat.tips') }} {{ expired ? t('login.wechat.expiredTip') : tipsText }}
</div> </div>
<a-button <a-button
v-if="!scanned" v-if="!scanned"
@ -64,11 +64,11 @@
{{ expired ? t('login.wechat.refreshExpired') : t('login.wechat.refresh') }} {{ expired ? t('login.wechat.refreshExpired') : t('login.wechat.refresh') }}
</a-button> </a-button>
<div class="account-login-entry"> <div class="account-login-entry">
<a-tooltip :content="t('login.switchToAccount')"> <a-tooltip :content="backTooltip">
<button <button
type="button" type="button"
class="account-entry-btn" class="account-entry-btn"
:aria-label="t('login.switchToAccount')" :aria-label="backTooltip"
@click="emit('switchPwd')" @click="emit('switchPwd')"
> >
<icon-user :size="24" /> <icon-user :size="24" />
@ -98,6 +98,16 @@ const QR_EXPIRE_MS = 600_000;
/** 首轮更快感知扫码,后续略放宽 */ /** 首轮更快感知扫码,后续略放宽 */
const POLL_INTERVAL_MS = 1800; const POLL_INTERVAL_MS = 1800;
const props = withDefaults(
defineProps<{
/** login:登录页扫码;register:注册页扫码 */
intent?: 'login' | 'register';
}>(),
{
intent: 'login',
},
);
const { t } = useI18n(); const { t } = useI18n();
const router = useRouter(); const router = useRouter();
const rbacUserStore = useRbacUserStore(); const rbacUserStore = useRbacUserStore();
@ -107,6 +117,14 @@ const emit = defineEmits<{
switchPwd: []; switchPwd: [];
}>(); }>();
const isRegisterIntent = computed(() => props.intent === 'register');
const tipsText = computed(() =>
isRegisterIntent.value ? t('login.wechat.tipsRegister') : t('login.wechat.tips'),
);
const backTooltip = computed(() =>
isRegisterIntent.value ? t('login.switchToRegisterChoose') : t('login.switchToAccount'),
);
const qrCodeUrl = ref(''); const qrCodeUrl = ref('');
const loginUuid = ref(''); const loginUuid = ref('');
const loadingQr = ref(false); const loadingQr = ref(false);

View File

@ -20,10 +20,17 @@
'login.form.brandHint.admin': 'Welcome to IDE Operations Console', 'login.form.brandHint.admin': 'Welcome to IDE Operations Console',
'login.form.brandHint.agent': 'Welcome to IDE Channel Agent Portal', 'login.form.brandHint.agent': 'Welcome to IDE Channel Agent Portal',
'login.brand.suffix.agent': 'Channel Agent', 'login.brand.suffix.agent': 'Channel Agent',
'login.switchToWechat': 'Sign in / register with WeChat', 'login.switchToWechat': 'Sign in with WeChat',
'login.switchToAccount': 'Account and password', 'login.switchToAccount': 'Account and password',
'login.wechat.tips': 'Scan with WeChat to sign in / register. QR code valid for 10 minutes.', 'login.altEntry.or': 'More options',
'login.noAccount': "Don't have an account?",
'login.goRegister': 'Register',
'login.switchToRegisterChoose': 'Back to registration options',
'login.wechat.tips': 'Scan with WeChat to sign in. QR code valid for 10 minutes.',
'login.wechat.tipsRegister': 'Scan with WeChat to register. QR code valid for 10 minutes.',
'login.wechat.scanned': 'Scanned. Signing you in…', 'login.wechat.scanned': 'Scanned. Signing you in…',
'login.wechat.qrValid': 'QR code valid for 10 minutes', 'login.wechat.qrValid': 'QR code valid for 10 minutes',
'login.wechat.scanPending': 'Waiting for scan…', 'login.wechat.scanPending': 'Waiting for scan…',
'login.wechat.loading': 'Loading QR code…', 'login.wechat.loading': 'Loading QR code…',

View File

@ -20,10 +20,17 @@
'login.form.brandHint.admin': '欢迎登录 IDE 运营管理后台', 'login.form.brandHint.admin': '欢迎登录 IDE 运营管理后台',
'login.form.brandHint.agent': '欢迎登录 IDE 渠道代理门户', 'login.form.brandHint.agent': '欢迎登录 IDE 渠道代理门户',
'login.brand.suffix.agent': '渠道代理', 'login.brand.suffix.agent': '渠道代理',
'login.switchToWechat': '微信扫码登录/注册', 'login.switchToWechat': '微信扫码登录',
'login.switchToAccount': '账号密码登录', 'login.switchToAccount': '账号密码登录',
'login.wechat.tips': '请使用微信扫一扫登录/注册,二维码 10 分钟内有效', 'login.altEntry.or': '其他方式',
'login.noAccount': '没有账号?',
'login.goRegister': '去注册',
'login.switchToRegisterChoose': '返回选择注册方式',
'login.wechat.tips': '请使用微信扫一扫登录,二维码 10 分钟内有效',
'login.wechat.tipsRegister': '请使用微信扫一扫完成注册,二维码 10 分钟内有效',
'login.wechat.scanned': '扫码成功,正在登录…', 'login.wechat.scanned': '扫码成功,正在登录…',
'login.wechat.qrValid': '二维码十分钟有效', 'login.wechat.qrValid': '二维码十分钟有效',
'login.wechat.scanPending': '等待扫码中…', 'login.wechat.scanPending': '等待扫码中…',
'login.wechat.longPress': '微信内请长按二维码识别', 'login.wechat.longPress': '微信内请长按二维码识别',

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
export default {
'marketing.register.title': 'Register',
'marketing.register.subtitle': 'Member pricing and welcome benefits',
'marketing.register.brandHint': 'Welcome to IDE customer portal',
'marketing.register.brandHint.web': 'Register with email & phone',
'marketing.register.brandHint.wechat': 'Register with WeChat',
'marketing.register.choose.web': 'Web register',
'marketing.register.choose.webDesc': 'Fill in details and open your portal',
'marketing.register.choose.wechat': 'WeChat register',
'marketing.register.choose.wechatDesc': 'Scan to authorize and finish quickly',
'marketing.register.backToChoose': '← Back to options',
'marketing.register.referrerHint': 'Invited by {name} ({code})',
'marketing.register.invalidRef': 'Invalid invite code — you can still register',
'marketing.register.referrerLoading': 'Validating invite code…',
'marketing.register.referrerTimeout':
'Invite validation timed out. Check your network and refresh; you can still register.',
'marketing.register.referrerBadge': 'Friend invite',
'marketing.register.agentHint': '{name} · {code}',
'marketing.register.agentBadge': 'Channel partner',
'marketing.register.agentFallbackName': 'Partner',
'marketing.register.agentField': 'Agent code (optional)',
'marketing.register.agentPlaceholder': 'Enter agent code if you were referred by a partner',
'marketing.register.agentLockedHint': 'You will be linked to the partner above after register',
'marketing.register.agentInvalid': 'Agent code is invalid or disabled',
'marketing.register.agentValidating': 'Validating agent code…',
'marketing.register.agentPriorityHint':
'Agent code filled — channel agent binding takes priority over friend invite',
'marketing.register.customerName': 'Name',
'marketing.register.customerNamePlaceholder': 'Your name',
'marketing.register.phone': 'Phone',
'marketing.register.phonePlaceholder': 'Mobile number',
'marketing.register.email': 'Email',
'marketing.register.emailPlaceholder': 'Email address',
'marketing.register.password': 'Password',
'marketing.register.passwordPlaceholder': '6+ letters and digits',
'marketing.register.confirmPassword': 'Confirm password',
'marketing.register.confirmPasswordPlaceholder': 'Re-enter password',
'marketing.register.submit': 'Register',
'marketing.register.submitting': 'Registering…',
'marketing.register.success': 'Registered — please sign in',
'marketing.register.failed': 'Registration failed',
'marketing.register.hasAccount': 'Already have an account?',
'marketing.register.goLogin': 'Sign in',
'marketing.register.customerNameRequired': 'Name is required',
'marketing.register.phoneRequired': 'Phone is required',
'marketing.register.emailRequired': 'Email is required',
'marketing.register.emailInvalid': 'Invalid email',
'marketing.register.passwordRequired': 'Password is required',
'marketing.register.passwordInvalid': 'Password must be 6+ letters and digits',
'marketing.register.confirmPasswordRequired': 'Confirm password',
'profile.passwordMismatch': 'Passwords do not match',
};

View File

@ -0,0 +1,51 @@
export default {
'marketing.register.title': '客户注册',
'marketing.register.subtitle': '注册即享会员价与新人福利',
'marketing.register.brandHint': '欢迎注册 IDE 客户门户',
'marketing.register.brandHint.web': '网页注册 IDE 客户账号',
'marketing.register.brandHint.wechat': '微信扫码注册 IDE 客户账号',
'marketing.register.choose.web': '网页注册',
'marketing.register.choose.webDesc': '填写资料,立即开通客户门户',
'marketing.register.choose.wechat': '微信注册',
'marketing.register.choose.wechatDesc': '扫码授权,快捷完成注册',
'marketing.register.backToChoose': '← 返回选择注册方式',
'marketing.register.referrerHint': '您正通过 {name}({code})的邀请注册',
'marketing.register.invalidRef': '邀请码无效或已失效,您仍可正常注册',
'marketing.register.referrerLoading': '正在校验邀请码…',
'marketing.register.referrerTimeout': '邀请码校验超时,请检查网络后刷新;您仍可继续注册',
'marketing.register.referrerBadge': '好友邀请',
'marketing.register.agentHint': '{name} · {code}',
'marketing.register.agentBadge': '渠道推荐',
'marketing.register.agentFallbackName': '渠道代理',
'marketing.register.agentField': '代理编号(选填)',
'marketing.register.agentPlaceholder': '有渠道推荐人可填写其代理编号',
'marketing.register.agentLockedHint': '注册完成后将关联上方推荐渠道',
'marketing.register.agentInvalid': '代理编号无效或已停用',
'marketing.register.agentValidating': '正在校验代理编号…',
'marketing.register.agentPriorityHint': '已填写代理编号,将优先绑定渠道代理(不走好友邀请)',
'marketing.register.customerName': '客户名称',
'marketing.register.customerNamePlaceholder': '请输入客户名称',
'marketing.register.phone': '手机号',
'marketing.register.phonePlaceholder': '请输入手机号',
'marketing.register.email': '邮箱',
'marketing.register.emailPlaceholder': '请输入邮箱',
'marketing.register.password': '密码',
'marketing.register.passwordPlaceholder': '6 位以上字母数字组合',
'marketing.register.confirmPassword': '确认密码',
'marketing.register.confirmPasswordPlaceholder': '请再次输入密码',
'marketing.register.submit': '注册',
'marketing.register.submitting': '注册中…',
'marketing.register.success': '注册成功,请登录',
'marketing.register.failed': '注册失败',
'marketing.register.hasAccount': '已有账号?',
'marketing.register.goLogin': '去登录',
'marketing.register.customerNameRequired': '请输入客户名称',
'marketing.register.phoneRequired': '请输入手机号',
'marketing.register.emailRequired': '请输入邮箱',
'marketing.register.emailInvalid': '邮箱格式不正确',
'marketing.register.passwordRequired': '请输入密码',
'marketing.register.passwordInvalid': '密码须为 6 位以上字母数字组合',
'marketing.register.confirmPasswordRequired': '请确认密码',
'profile.passwordMismatch': '两次密码不一致',
};