本次提交对全项目的国际化调用进行了规范化重构:
1. 为中文/英文语言包新增了avatar和gender的别名映射,兼容旧有headImg/sex写法
2. 修正了lang.js中的注释路径错误
3. 将所有页面和组件内的$lang调用从短路径改为带业务模块前缀的完整命名空间路径,例如将$lang('title')改为$lang('article.list.title')
4. 优化了i18n-lazy.js的注释说明,补充了正确的key命名格式示例
5. 统一了分销、订单、会员等模块的国际化key层级,确保所有语言调用路径一致
380 lines
9.3 KiB
Vue
380 lines
9.3 KiB
Vue
<template>
|
||
<view :style="themeColor">
|
||
<template v-if="memberInfo">
|
||
<!-- 一键授权绑定区域(小程序环境) -->
|
||
<!-- #ifdef MP -->
|
||
<view v-if="!showManualForm" class="bind-wrap">
|
||
<view class="bind-tip">
|
||
<view class="tip-title">{{ $lang('member.bind_mobile.tipTitle') }}</view>
|
||
<view class="tip-desc">{{ $lang('member.bind_mobile.bindBenefitTip') }}</view>
|
||
</view>
|
||
<view class="save-item bind-mobile">
|
||
<button type="primary" open-type="getPhoneNumber" @getphonenumber="mobileAuth">{{ $lang('member.bind_mobile.oneClickAuthBind') }}</button>
|
||
</view>
|
||
<view class="save-item bind-mobile">
|
||
<button type="primary" @click="showManualForm = true">{{ $lang('member.bind_mobile.manualBind') }}</button>
|
||
</view>
|
||
</view>
|
||
<!-- #endif -->
|
||
|
||
<!-- 手动绑定表单 -->
|
||
<view class="edit-info">
|
||
<!-- #ifdef MP -->
|
||
<view v-if="showManualForm" class="form-switch-back" @click="showManualForm = false">
|
||
<text>{{ $lang('member.bind_mobile.oneClickAuthBind') }}</text>
|
||
</view>
|
||
<!-- #endif -->
|
||
<view class="edit-info-box">
|
||
<text class="info-name">{{ $lang('member.bind_mobile.phoneNumber') }}</text>
|
||
<input class="uni-input info-content" type="number" maxlength="11" :placeholder="$lang('member.bind_mobile.pleInputMobile')" v-model="formData.mobile" />
|
||
</view>
|
||
<view class="edit-info-box">
|
||
<text class="info-name">{{ $lang('member.bind_mobile.confirmCode') }}</text>
|
||
<input class="uni-input info-content" type="number" maxlength="4" :placeholder="$lang('member.bind_mobile.confirmCodeInput')" v-model="formData.mobileVercode" />
|
||
<image :src="captcha.img" class="captcha" @click="getCaptcha" show-menu-by-longpress></image>
|
||
</view>
|
||
<view class="edit-info-box">
|
||
<text class="info-name">{{ $lang('member.bind_mobile.smsCode') }}</text>
|
||
<input class="uni-input info-content" type="number" maxlength="6" :placeholder="$lang('member.bind_mobile.animateCodeInput')" v-model="formData.mobileDynacode" />
|
||
<button type="primary" class="dynacode" @click="bindMoblieCode()">{{ formData.mobileCodeText }}</button>
|
||
</view>
|
||
<view class="save-item" @click="bindMobile">
|
||
<button type="primary">{{ $lang('member.bind_mobile.save') }}</button>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
<ns-login ref="login"></ns-login>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import validate from '@/common/js/validate.js';
|
||
import auth from '@/common/js/auth.js';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
showManualForm: false,
|
||
formData: {
|
||
mobile: '',
|
||
mobileVercode: '',
|
||
mobileDynacode: '',
|
||
mobileCodeText: '',
|
||
},
|
||
seconds: 120,
|
||
timer: null,
|
||
isSend: false,
|
||
captcha: {
|
||
id: '',
|
||
img: ''
|
||
},
|
||
};
|
||
},
|
||
mixins: [auth],
|
||
onLoad() {
|
||
this.formData.mobileCodeText = this.$lang('member.bind_mobile.findanimateCode');
|
||
this.getCaptcha();
|
||
// #ifdef MP-WEIXIN
|
||
this.getCode();
|
||
// #endif
|
||
},
|
||
onShow() {
|
||
if (!this.storeToken) {
|
||
this.redirectTologinOnShowLifecycle('/pages_tool/member/bind_mobile');
|
||
return;
|
||
}
|
||
},
|
||
onHide() {
|
||
this.seconds = 120;
|
||
this.formData.mobileCodeText = this.$lang('member.bind_mobile.findanimateCode');
|
||
this.isSend = false;
|
||
clearInterval(this.timer);
|
||
},
|
||
watch: {
|
||
seconds(value) {
|
||
if (value == 0) {
|
||
this.seconds = 120;
|
||
this.formData.mobileCodeText = this.$lang('member.bind_mobile.findanimateCode');
|
||
this.isSend = false;
|
||
clearInterval(this.timer);
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
themeColor() {
|
||
return this.$store.state.themeStyle ? `--main_color:${this.$store.state.themeStyle.main_color}` : '';
|
||
},
|
||
themeStyle() {
|
||
return this.$store.state.themeStyle || {};
|
||
},
|
||
memberInfo() {
|
||
return this.$store.state.memberInfo || {};
|
||
},
|
||
storeToken() {
|
||
return this.$store.state.token;
|
||
},
|
||
},
|
||
methods: {
|
||
// 获取图形验证码
|
||
getCaptcha() {
|
||
this.$api.sendRequest({
|
||
url: '/api/captcha/captcha',
|
||
data: {
|
||
captcha_id: this.captcha.id
|
||
},
|
||
success: res => {
|
||
if (res.code >= 0) {
|
||
this.captcha = res.data;
|
||
this.captcha.img = this.captcha.img.replace(/\r\n/g, '');
|
||
}
|
||
}
|
||
});
|
||
},
|
||
// 验证手机号
|
||
vertifyMobile() {
|
||
var rule = [{
|
||
name: 'mobile',
|
||
checkType: 'required',
|
||
errorMsg: this.$lang('member.bind_mobile.pleInputMobile')
|
||
}, {
|
||
name: 'mobile',
|
||
checkType: 'phoneno',
|
||
errorMsg: this.$lang('member.bind_mobile.surePhoneNumber')
|
||
}];
|
||
var checkRes = validate.check(this.formData, rule);
|
||
if (!checkRes) {
|
||
this.$util.showToast({
|
||
title: validate.error
|
||
});
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
// 发送短信动态码
|
||
async bindMoblieCode() {
|
||
if (this.seconds != 120) return;
|
||
var rule = [{
|
||
name: 'mobile',
|
||
checkType: 'phoneno',
|
||
errorMsg: this.$lang('member.bind_mobile.surePhoneNumber')
|
||
},
|
||
{
|
||
name: 'mobileVercode',
|
||
checkType: 'required',
|
||
errorMsg: this.$lang('member.bind_mobile.confirmCodeInput')
|
||
},
|
||
];
|
||
|
||
var checkRes = validate.check(this.formData, rule);
|
||
|
||
if (checkRes && !this.isSend) {
|
||
this.isSend = true;
|
||
this.$api.sendRequest({
|
||
url: '/api/member/bindmobliecode',
|
||
data: {
|
||
mobile: this.formData.mobile,
|
||
captcha_id: this.captcha.id,
|
||
captcha_code: this.formData.mobileVercode
|
||
},
|
||
success: res => {
|
||
let data = res.data;
|
||
if (data.key) {
|
||
if (this.seconds == 120 && this.timer == null) {
|
||
this.timer = setInterval(() => {
|
||
this.seconds--;
|
||
this.formData.mobileCodeText = this.$lang('member.bind_mobile.codeSent', { seconds: this.seconds });
|
||
}, 1000);
|
||
}
|
||
uni.setStorageSync('mobile_key', data.key);
|
||
} else {
|
||
this.$util.showToast({
|
||
title: res.message
|
||
});
|
||
this.isSend = false;
|
||
}
|
||
},
|
||
fail: res => {
|
||
this.isSend = false;
|
||
this.getCaptcha();
|
||
}
|
||
});
|
||
} else {
|
||
this.$util.showToast({
|
||
title: validate.error ? validate.error : this.$lang('member.bind_mobile.doNotRepeatedlyClick')
|
||
});
|
||
}
|
||
},
|
||
// 绑定手机号
|
||
bindMobile() {
|
||
if (!this.vertifyMobile()) return;
|
||
|
||
var mobileRule = [{
|
||
name: 'mobileVercode',
|
||
checkType: 'required',
|
||
errorMsg: this.$lang('member.bind_mobile.confirmCodeInput')
|
||
},
|
||
{
|
||
name: 'mobileDynacode',
|
||
checkType: 'required',
|
||
errorMsg: this.$lang('member.bind_mobile.animateCodeInput')
|
||
},
|
||
];
|
||
var checkRes = validate.check(this.formData, mobileRule);
|
||
|
||
if (checkRes) {
|
||
if (this.memberInfo.mobile && this.formData.mobile == this.memberInfo.mobile) {
|
||
this.$util.showToast({
|
||
title: this.$lang('member.bind_mobile.alikePhone')
|
||
});
|
||
return;
|
||
}
|
||
this.$api.sendRequest({
|
||
url: '/api/member/modifymobile',
|
||
data: {
|
||
mobile: this.formData.mobile,
|
||
captcha_id: this.captcha.id,
|
||
captcha_code: this.formData.mobileVercode,
|
||
code: this.formData.mobileDynacode,
|
||
key: uni.getStorageSync("mobile_key"),
|
||
},
|
||
success: res => {
|
||
if (res.code == 0) {
|
||
this.memberInfo.mobile = this.formData.mobile;
|
||
this.$store.commit('setMemberInfo', this.memberInfo);
|
||
this.$util.showToast({
|
||
title: this.$lang('member.bind_mobile.bindSuccess')
|
||
});
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
} else {
|
||
this.$util.showToast({
|
||
title: res.message
|
||
});
|
||
this.getCaptcha();
|
||
}
|
||
},
|
||
fail: res => {
|
||
this.isSend = false;
|
||
this.getCaptcha();
|
||
}
|
||
});
|
||
} else {
|
||
this.$util.showToast({
|
||
title: validate.error
|
||
});
|
||
}
|
||
},
|
||
// 一键授权绑定(小程序)
|
||
mobileAuth(e) {
|
||
if (e.detail.errMsg == 'getPhoneNumber:ok') {
|
||
let data = e.detail
|
||
// #ifdef MP-WEIXIN
|
||
Object.assign(data, this.authInfo)
|
||
// #endif
|
||
this.$api.sendRequest({
|
||
url: '/api/member/mobileauth',
|
||
data,
|
||
success: res => {
|
||
if (res.code == 0) {
|
||
this.$util.showToast({
|
||
title: this.$lang('member.bind_mobile.bindSuccess')
|
||
});
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
} else {
|
||
this.$util.showToast({
|
||
title: res.message
|
||
});
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.bind-wrap {
|
||
padding: 60rpx 40rpx;
|
||
}
|
||
|
||
.bind-tip {
|
||
text-align: center;
|
||
margin-bottom: 60rpx;
|
||
|
||
.tip-title {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.tip-desc {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
.edit-info-box {
|
||
margin-top: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 20rpx 40rpx;
|
||
min-height: 50rpx;
|
||
background-color: #fff;
|
||
|
||
.info-name {
|
||
width: 150rpx;
|
||
font-size: 28rpx;
|
||
text-align: left;
|
||
}
|
||
|
||
.info-content {
|
||
flex: 1;
|
||
width: 0;
|
||
font-size: 28rpx;
|
||
padding: 0;
|
||
}
|
||
|
||
.dynacode {
|
||
margin: 0;
|
||
padding: 0 10rpx;
|
||
width: 250rpx;
|
||
height: 60rpx;
|
||
font-size: 24rpx;
|
||
line-height: 60rpx;
|
||
word-break: break-all;
|
||
}
|
||
}
|
||
|
||
.captcha {
|
||
width: 170rpx;
|
||
height: 50rpx;
|
||
}
|
||
|
||
.save-item {
|
||
margin-top: 50rpx;
|
||
|
||
button {
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
|
||
.bind-mobile {
|
||
button {
|
||
border-radius: 60rpx;
|
||
}
|
||
}
|
||
|
||
.form-switch-back {
|
||
text-align: center;
|
||
padding: 20rpx;
|
||
font-size: 26rpx;
|
||
color: var(--main_color);
|
||
}
|
||
</style>
|