refactor(i18n): move react-i18next bundle under subpage and trim main usage

Move src/i18n (index, instance, app-config-t, locales) to src/subpage/i18n so the implementation lives with the subpage package instead of a root-level i18n folder.

Replace react-i18next usage with inline Chinese strings on touched auth flows, member index, cart, and validate helpers to avoid pulling i18next JSON into those bundles.

Keep legacy lang switching: Taro.$changeLang still bootstraps subpages/i18n JSON; sync to i18next uses dynamic import of @/subpage/i18n/instance from lang/index.js.

Also updates SpPage, store, marketing/coupon/package/buy-toolbar, hot-zone widget, app.config comment, and extra keys in subpages/i18n/lang/index.json where needed.

Made-with: Cursor
This commit is contained in:
moyayu
2026-04-22 13:34:29 +08:00
parent eb1b210b20
commit ee8dd2df44
25 changed files with 267 additions and 273 deletions

View File

@@ -2,7 +2,7 @@
* Copyright © ShopeX http://www.shopex.cn. All rights reserved.
* See LICENSE file for license details.
*/
import { appConfigT } from '@/i18n/app-config-t'
// import { appConfigT } from '@/subpage/i18n/app-config-t'
const config = {
pages: [
@@ -479,7 +479,7 @@ const config = {
],
permission: {
'scope.userLocation': {
desc: appConfigT('95285d68.93f311')
desc: '您的位置信息将用于定位附近门店'
}
},
// usingComponents: {
@@ -488,7 +488,7 @@ const config = {
window: {
'backgroundTextStyle': 'light',
'navigationBarBackgroundColor': '#fff',
'navigationBarTitleText': appConfigT('95285d68.0ed510'),
'navigationBarTitleText': '小程序',
'navigationBarTextStyle': 'black'
},
plugins: {

View File

@@ -155,12 +155,13 @@ const SpPage = memo(
let _navigationRSpace = 0 // 导航栏右间距
const { screenHeight, windowWidth, windowHeight } = Taro.getWindowInfo()
const [absolutePath] = router?.path.split('?')
const forceShowBack = String(router?.params?.showBack || '') === '1'
// 小程序/支付宝:按页面 config 是否 customH5有 pageConfig 或 immersive 时也使用自定义顶栏以支持相同顶部样式
const custom_navigation =
isWeixin || isAlipay
? navigationStyle === 'custom'
: isWeb && !!(props.pageConfig || props.immersive)
const _btnReturn = pages.length > 1 && !TAB_PAGES.includes(absolutePath)
const _btnReturn = pages.length > 1 && (!TAB_PAGES.includes(absolutePath) || forceShowBack)
const _btnHome = pages.length == 1 && !TAB_PAGES.includes(absolutePath)
if (isWeixin || isAlipay) {
const menuButton = Taro.getMenuButtonBoundingClientRect()

View File

@@ -3,7 +3,6 @@
* See LICENSE file for license details.
*/
import Taro from '@tarojs/taro'
import { syncI18nLanguage } from '@/i18n/instance'
class Lang {
constructor() {
@@ -11,7 +10,6 @@ class Lang {
}
init() {
const self = this
// 定义翻译函数
let $t = function (key, val, nameSpace) {
// 获取指定命名空间下的语言包
@@ -67,43 +65,6 @@ class Lang {
// 返回语言对象
return langObj
}
/**
* 必须在首屏即可用:`setLanguagePackage` 在 useLaunch 里异步执行,
* 用户在语言包就绪前进「设置 → 切换语言」会导致 Taro.$changeLang 未定义。
*/
Taro.$changeLang = (lang) => {
const apply = () => {
globalThis._localStorage.setItem('lang', lang)
globalThis.$t.locale(globalThis.langMap[lang], 'lang')
if (Taro.eventCenter) {
Taro.eventCenter.trigger('languageChanged', { lang, langMap: globalThis.langMap[lang] })
}
Promise.resolve(syncI18nLanguage(lang)).catch(() => {})
}
if (
globalThis.langMap &&
typeof globalThis.langMap === 'object' &&
Object.keys(globalThis.langMap).length > 0
) {
apply()
return
}
import('@/subpages/i18n/index')
.then(() => {
const langJSON = Taro['langJSON']
if (!langJSON) {
console.error('[Lang] Taro.langJSON missing, cannot switch language')
return
}
self.setLanguagePackage(langJSON)
apply()
})
.catch((e) => {
console.error('[Lang] Failed to load language bundle', e)
})
}
}
setLanguagePackage(langJSON) {
@@ -185,7 +146,15 @@ class Lang {
}
// 根据当前语言设置翻译函数的语言包
globalThis.$t.locale(globalThis.langMap[lang], 'lang')
Promise.resolve(syncI18nLanguage(lang)).catch(() => {})
Taro.$changeLang = (lang) => {
globalThis._localStorage.setItem('lang', lang)
globalThis.$t.locale(globalThis.langMap[lang], 'lang')
// 触发语言变化事件,让其他地方能够监听到
if (Taro.eventCenter) {
Taro.eventCenter.trigger('languageChanged', { lang, langMap: globalThis.langMap[lang] })
}
}
}
}

View File

@@ -86,46 +86,50 @@ function CompActivityItem(props) {
<Text className='activity-item__content-reject-reason'>{reason}</Text>
</View>
)}
<View className='activity-item__content-btns'>
{isActivity && <View className='activity-item__content-btn activity-btn'>会员免费</View>}
<View className='activity-item__content-btn-wrapper'>
{isActivity && recordId ? (
<View
className='activity-item__view-records'
onClick={(e) => {
e.stopPropagation()
onViewRecords(info)
}}
>
查看报名记录
</View>
) : null}
{actionEdit && !isActivity && (
<View
className='activity-item__content-btn'
onClick={(e) => handleBtnClick(e, 'reFill')}
>
重新填写
</View>
)}
{!isActivity && actionApply && (
<View className='activity-item__content-btn' onClick={(e) => handleBtnClick(e, 'sign')}>
立即报名
</View>
)}
{isActivity && recordId ? (
<View
className='activity-item__view-records'
onClick={(e) => {
e.stopPropagation()
onViewRecords(info)
}}
>
查看报名记录
</View>
) : null}
{actionEdit && !isActivity && (
<View
className='activity-item__content-btn'
onClick={(e) => handleBtnClick(e, 'reFill')}
>
重新填写
</View>
)}
{!isActivity && actionApply && (
<View
className='activity-item__content-btn'
onClick={(e) => handleBtnClick(e, 'sign')}
>
立即报名
</View>
)}
{isActivity && (
<View
className={classNames('activity-item__content-btn', {
' disabled-btn': signDisabled
})}
onClick={(e) => handleBtnClick(e, 'sign')}
>
立即报名
</View>
)}
</View></View>
{isActivity && (
<View
className={classNames('activity-item__content-btn', {
' disabled-btn': signDisabled
})}
onClick={(e) => handleBtnClick(e, 'sign')}
>
立即报名
</View>
)}
</View>
</View>
</View>
</View>
)

View File

@@ -3,7 +3,7 @@
* See LICENSE file for license details.
*/
import Taro, { getCurrentInstance, useDidShow } from '@tarojs/taro'
import React, { useEffect, useState, useMemo } from 'react'
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { View, Text, ScrollView } from '@tarojs/components'
import { AtButton } from 'taro-ui'
@@ -12,7 +12,6 @@ import qs from 'qs'
import api from '@/api'
import doc from '@/doc'
import { navigateTo, pickBy, classNames, throttle } from '@/utils'
import { useTranslation, $t, ti } from '@/i18n'
import { useLogin, useLocation, useDebounce } from '@/hooks'
import { fetchCartList, deleteCartItem, updateCartItemNum, updateCount } from '@/store/slices/cart'
import { updatePurchaseShareInfo, updateInviteCode } from '@/store/slices/purchase'
@@ -45,7 +44,6 @@ const initialState = {
}
function CartIndex() {
useTranslation()
const { updateAddress } = useLocation()
const { shopInfo = {} } = useSelector((state) => state.shop)
@@ -224,11 +222,11 @@ function CartIndex() {
const onDeleteCartGoodsItem = async ({ cart_id }) => {
const res = await Taro.showModal({
title: $t('61e2d21a.02d981'),
content: $t('61e2d21a.a4936e'),
title: '提示',
content: '将当前商品移出购物车?',
showCancel: true,
cancelText: $t('61e2d21a.625fb2'),
confirmText: $t('61e2d21a.e83a25'),
cancelText: '取消',
confirmText: '确认',
confirmColor: colorPrimary
})
if (!res.confirm) return
@@ -303,9 +301,9 @@ function CartIndex() {
)}
{!isLogin && (
<View className='login-header'>
<View className='login-txt'>{$t('f9ef9536.29b36a')}</View>
<View className='login-txt'>授权登录后同步购物车的商品</View>
<SpLogin onChange={() => {}}>
<View className='btn-login'>{$t('f9ef9536.d72d86')}</View>
<View className='btn-login'>授权登录</View>
</SpLogin>
</View>
)}
@@ -319,7 +317,7 @@ function CartIndex() {
<View className='shop-cart-item' key={`shop-cart-item__${all_index}`}>
<View className='shop-cart-item-hd'>
<Text className='iconfont icon-shop' />
{all_item.shop_name || $t('f9ef9536.491c0c')}
{all_item.shop_name || '自营'}
</View>
<View className='shop-cart-item-shadow'>
{/** 店铺商品开始 */}
@@ -344,9 +342,7 @@ function CartIndex() {
})
}
>
<Text className='shop-cart-activity-label'>
{$t('f9ef9536.1687b1')}
</Text>
<Text className='shop-cart-activity-label'>换购</Text>
<Text>{discount_desc.info}</Text>
</View>
<View
@@ -357,7 +353,7 @@ function CartIndex() {
})
}
>
{$t('f9ef9536.5ba3e7')}
去选择
<Text className='at-icon at-icon-chevron-right'></Text>
</View>
</View>
@@ -426,7 +422,7 @@ function CartIndex() {
<View className='lf'>
<SpCheckboxNew
checked={allChecked}
label={$t('f9ef9536.66eeac')}
label='全选'
onChange={onChangeGoodsIsCheck.bind(this, all_item, 'all')}
/>
</View>
@@ -435,12 +431,12 @@ function CartIndex() {
<View className='rg'>
<View className='rg-lt'>
<View className='total-price-wrap'>
{$t('f9ef9536.7b2864')}
合计
<SpPrice className='total-pirce' value={all_item.total_fee / 100} />
</View>
{all_item.discount_fee > 0 && (
<View className='discount-price-wrap'>
{$t('f9ef9536.1784cf')}
共优惠
<SpPrice
className='total-pirce'
value={all_item.discount_fee / 100}
@@ -455,7 +451,7 @@ function CartIndex() {
disabled={all_item.cart_total_num <= 0}
onClick={() => handleCheckout(all_item)}
>
{ti('f9ef9536.605bad', [all_item.cart_total_num])}
{`结算(${all_item.cart_total_num})`}
</AtButton>
</View>
</View>
@@ -468,7 +464,7 @@ function CartIndex() {
{invalidCart.length > 0 && (
<View className='invalid-cart-block'>
<View className='shop-cart-item'>
<View className='shop-cart-item-hd-disabeld'>{$t('f9ef9536.31a812')}</View>
<View className='shop-cart-item-hd-disabeld'>已失效商品</View>
<View className='shop-cart-item-bd'>
<View className='shop-activity'></View>
{invalidCart.map((sitem, sindex) => (
@@ -492,9 +488,9 @@ function CartIndex() {
)}
{validCart.length == 0 && invalidCart.length == 0 && (
<SpDefault type='cart' message={$t('61e2d21a.8bdc0a')}>
<SpDefault type='cart' message='购物车内暂无商品~'>
<AtButton type='primary' circle onClick={navigateTo.bind(this, '/pages/index', true)}>
{$t('61e2d21a.aed876')}
去选购
</AtButton>
</SpDefault>
)}

View File

@@ -92,16 +92,16 @@ function WgtImgHotZone(props) {
distributor_id
})
if (item.id === 'customerService') {
return (
<Button
openType='contact'
key={item.id || Math.random()}
className='wgt-imghot-zone__body_zone opacity-0'
style={getZoneStyle(item)}
/>
)
}
if (item.id === 'customerService') {
return (
<Button
openType='contact'
key={item.id || Math.random()}
className='wgt-imghot-zone__body_zone opacity-0'
style={getZoneStyle(item)}
/>
)
}
if (needLogin(item)) {
return (

View File

@@ -7,7 +7,6 @@ import { View, Text } from '@tarojs/components'
import { classNames } from '@/utils'
import { useImmer } from 'use-immer'
import { SpInput as AtInput } from '@/components'
import { useTranslation, $t } from '@/i18n'
import './comp-password-input.scss'
const initialValue = {
@@ -16,7 +15,6 @@ const initialValue = {
}
const CompPasswordInput = (props) => {
useTranslation()
const {
onChange = () => {},
disabled,
@@ -26,7 +24,7 @@ const CompPasswordInput = (props) => {
placeholder
} = props
const placeholderText = placeholder ?? $t('24f4b47f.c4d0c8')
const placeholderText = placeholder ?? '密码需由6-16位数字或字母组成'
const [state, setState] = useImmer(initialValue)

View File

@@ -9,11 +9,9 @@ import { SpPage, SpInput as AtInput } from '@/components'
import { classNames, validate, showToast } from '@/utils'
import { AtForm, AtButton } from 'taro-ui'
import api from '@/api'
import { useTranslation, $t } from '@/i18n'
import './forgotpwd.scss'
const PageForgotPwdEmail = () => {
useTranslation()
const $instance = getCurrentInstance() || {}
const { email: emailParam, redi_url: rediUrlParam } = $instance?.router?.params || {}
@@ -29,7 +27,7 @@ const PageForgotPwdEmail = () => {
const handleSend = async () => {
const trimmed = email.trim()
if (!validate.isEmail(trimmed)) {
showToast($t('4e9d53b5.c902bb'))
showToast('请输入正确的电子邮箱')
return
}
if (submitting) return
@@ -45,7 +43,7 @@ const PageForgotPwdEmail = () => {
email: trimmed,
...(reset_base_url ? { reset_base_url } : {})
})
showToast($t('0dbd2dc3.e3b0c2'))
showToast('若该邮箱已注册,您将收到重置密码邮件')
} catch (e) {
console.log(e)
} finally {
@@ -62,8 +60,8 @@ const PageForgotPwdEmail = () => {
})}
>
<View className='auth-hd'>
<View className='title'>{$t('0dbd2dc3.e1b0a0')}</View>
<View className='desc'>{$t('0dbd2dc3.e2b0b1')}</View>
<View className='title'>邮箱找回密码</View>
<View className='desc'>将向您的邮箱发送重置密码链接</View>
</View>
<View className='auth-bd'>
<AtForm className='form'>
@@ -73,7 +71,7 @@ const PageForgotPwdEmail = () => {
name='email'
type='text'
value={email}
placeholder={$t('3ca883d0.c90811')}
placeholder='请输入电子邮箱'
onChange={(val) => setEmail(val)}
/>
</View>
@@ -87,7 +85,7 @@ const PageForgotPwdEmail = () => {
className='login-button'
onClick={handleSend}
>
{$t('0dbd2dc3.e4b0d3')}
发送重置密码邮件
</AtButton>
</View>
@@ -102,7 +100,7 @@ const PageForgotPwdEmail = () => {
})
}
>
{$t('0dbd2dc3.e5b0e4')}
返回登录
</Text>
</View>
) : null}

View File

@@ -12,7 +12,6 @@ import { AtForm, AtButton } from 'taro-ui'
import api from '@/api'
import { useImmer } from 'use-immer'
import { useSelector } from 'react-redux'
import { useTranslation, $t } from '@/i18n'
import { CompPasswordInput } from './comps'
import './forgotpwd.scss'
@@ -30,7 +29,6 @@ const initialValue = {
}
const PageBindPhone = () => {
useTranslation()
const $instance = getCurrentInstance() || {}
const {
params: { phone, redi_url }
@@ -70,10 +68,10 @@ const PageBindPhone = () => {
})
if (is_new === 1) {
const res = await Taro.showModal({
title: $t('0dbd2dc3.02d981'),
content: $t('0dbd2dc3.aa160c'),
cancelText: $t('0dbd2dc3.7173f8'),
confirmText: $t('0dbd2dc3.e61f2c'),
title: '提示',
content: '此手机号码未注册、是否同意前往注册',
cancelText: '拒绝',
confirmText: '同意',
confirmColor: colorPrimary
})
if (res.confirm) {
@@ -88,11 +86,11 @@ const PageBindPhone = () => {
const handleTimerStart = async (resolve) => {
if (!validate.isMobileNum(username)) {
showToast($t('0dbd2dc3.a32ab5'))
showToast('请输入正确的手机号')
return
}
if (!validate.isRequired(yzm)) {
showToast($t('0dbd2dc3.e70066'))
showToast('请输入图形验证码')
return
}
@@ -107,7 +105,7 @@ const PageBindPhone = () => {
yzm: yzm,
token: imgInfo.imageToken
})
showToast($t('0dbd2dc3.4d7fb5'))
showToast('验证码已发送')
resolve()
} catch (e) {
getImageVcode()
@@ -116,7 +114,7 @@ const PageBindPhone = () => {
const handleSubmit = async () => {
if (!validate.isPassword(password)) {
return showToast($t('0dbd2dc3.eac67a'))
return showToast('密码格式不正确')
}
try {
await api.user.forgotPwd({
@@ -124,7 +122,7 @@ const PageBindPhone = () => {
password,
vcode
})
showToast($t('0dbd2dc3.00f316'), () => {
showToast('设置密码成功', () => {
Taro.navigateBack()
})
} catch (e) {
@@ -154,7 +152,7 @@ const PageBindPhone = () => {
})}
>
<View className='auth-hd'>
<View className='title'>{$t('0dbd2dc3.0974fb')}</View>
<View className='title'>忘记密码</View>
</View>
<View className='auth-bd'>
<AtForm className='form'>
@@ -165,7 +163,7 @@ const PageBindPhone = () => {
maxLength={11}
type='tel'
value={username}
placeholder={$t('0dbd2dc3.787a47')}
placeholder='请输入您的手机号码'
onChange={handleInputChange('username')}
/>
</View>
@@ -177,7 +175,7 @@ const PageBindPhone = () => {
clear
name='yzm'
value={yzm}
placeholder={$t('0dbd2dc3.e70066')}
placeholder='请输入图形验证码'
onChange={handleInputChange('yzm')}
/>
</View>
@@ -198,14 +196,14 @@ const PageBindPhone = () => {
clear
name='vcode'
value={vcode}
placeholder={$t('0dbd2dc3.d0c06a')}
placeholder='请输入验证码'
onChange={handleInputChange('vcode')}
/>
</View>
<View className='btn-field'>
<SpTimer
defaultMsg={$t('0eb8dfea.c5c358')}
msg={$t('0eb8dfea.89b213')}
defaultMsg='发送验证码'
msg='重新发送'
onStart={handleTimerStart}
/>
</View>
@@ -224,7 +222,7 @@ const PageBindPhone = () => {
className='login-button'
onClick={handleSubmit}
>
{$t('0dbd2dc3.769d88')}
完成
</AtButton>
</View>
</AtForm>

View File

@@ -13,7 +13,6 @@ import { connect } from 'react-redux'
import S from '@/spx'
import api from '@/api'
import { classNames, navigateTo, validate, showToast, tokenParseH5 } from '@/utils'
import { $t, i18n } from '@/i18n'
import { CompOtherLogin, CompPasswordInput, CompInputPhone } from './comps'
import { navigationToReg, setToken, setTokenAndRedirect, addListener } from './util'
import './login.scss'
@@ -103,22 +102,14 @@ export default class Login extends Component {
}
componentDidMount() {
this._onLanguageChanged = () => this.forceUpdate()
i18n.on('languageChanged', this._onLanguageChanged)
this.prefillLoginFromRouter()
if (!this._loginRouterPrefilled) {
this.getImageVcode()
}
}
componentWillUnmount() {
if (this._onLanguageChanged) {
i18n.off('languageChanged', this._onLanguageChanged)
}
}
componentDidShow() {
Taro.setNavigationBarTitle({ title: $t('aa1b799d.402d19') })
Taro.setNavigationBarTitle({ title: '登录' })
const { redirect } = this.$instance?.router?.params
if (S.getAuthToken()) {
const url = redirect ? decodeURIComponent(redirect) : '/subpages/member/index'
@@ -134,13 +125,13 @@ export default class Login extends Component {
const { imgInfo } = this.state
const { mobile, yzm } = this.state.info
if (!validate.isMobileNum(mobile)) {
return showToast($t('3ca883d0.a32ab5'))
return showToast('请输入正确的手机号')
}
if (!validate.isRequired(yzm)) {
return showToast($t('3ca883d0.e70066'))
return showToast('请输入图形验证码')
}
if (!imgInfo?.imageToken) {
showToast($t('3ca883d0.8eb88e'))
showToast('图形验证码未就绪,请刷新重试')
this.getImageVcode()
return
}
@@ -151,7 +142,7 @@ export default class Login extends Component {
yzm: yzm,
token: imgInfo.imageToken
})
showToast($t('3ca883d0.4d7fb5'))
showToast('验证码已发送')
resolve()
} catch (e) {
this.getImageVcode()
@@ -164,13 +155,13 @@ export default class Login extends Component {
const { email, yzm } = this.state.info
const emailTrim = (email || '').trim()
if (!validate.isEmail(emailTrim)) {
return showToast($t('3ca883d0.04154b'))
return showToast('请输入正确的电子邮箱')
}
if (!validate.isRequired(yzm)) {
return showToast($t('3ca883d0.e70066'))
return showToast('请输入图形验证码')
}
if (!imgInfo?.imageToken) {
showToast($t('3ca883d0.8eb88e'))
showToast('图形验证码未就绪,请刷新重试')
this.getImageVcode()
return
}
@@ -181,7 +172,7 @@ export default class Login extends Component {
token: imgInfo.imageToken,
yzm
})
showToast($t('3ca883d0.4d7fb5'))
showToast('验证码已发送')
this.setState((prev) => ({
info: { ...prev.info, yzm: '' }
}))
@@ -263,7 +254,7 @@ export default class Login extends Component {
resendActivateYzm: ''
})
} catch (e) {
showToast(e.message || $t('3ca883d0.8eb88e'))
showToast(e.message || '图形验证码未就绪,请刷新重试')
}
}
@@ -283,13 +274,13 @@ export default class Login extends Component {
const { imgInfoActivate, resendActivateYzm } = this.state
const emailTrim = (this.state.info.email || '').trim()
if (!validate.isEmail(emailTrim)) {
return showToast($t('3ca883d0.04154b'))
return showToast('请输入正确的电子邮箱')
}
if (!validate.isRequired(resendActivateYzm)) {
return showToast($t('3ca883d0.e70066'))
return showToast('请输入图形验证码')
}
if (!imgInfoActivate?.imageToken) {
showToast($t('3ca883d0.8eb88e'))
showToast('图形验证码未就绪,请刷新重试')
this.getResendActivateImageVcode()
return
}
@@ -309,15 +300,15 @@ export default class Login extends Component {
}
try {
await api.user.memberEmailCode(resendPayload)
showToast($t('3ca883d0.actResentOk'))
showToast('激活邮件已发送,请查收邮箱')
this.handleCloseResendActivateModal()
} catch (e) {
showToast(e.message || $t('3ca883d0.actResentFail'))
showToast(e.message || '发送失败,请稍后重试')
try {
const img = await api.user.regImg({ type: 'sign' })
this.setState({ imgInfoActivate: img, resendActivateYzm: '' })
} catch (err) {
showToast(err.message || $t('3ca883d0.8eb88e'))
showToast(err.message || '图形验证码未就绪,请刷新重试')
}
}
}
@@ -385,16 +376,16 @@ export default class Login extends Component {
if (accountMode === 'email') {
const emailTrim = (email || '').trim()
if (!validate.isEmail(emailTrim)) {
showToast($t('3ca883d0.04154b'))
showToast('请输入正确的电子邮箱')
return
}
if (loginType == 1) {
if (!validate.isRequired(password)) {
showToast($t('3ca883d0.e39ffe'))
showToast('请输入密码')
return
}
if (!validate.isEmailChannelPassword(password)) {
return showToast($t('3ca883d0.96246d'))
return showToast('请输入密码8-20位须含字母与数字')
}
params = {
username: emailTrim,
@@ -406,7 +397,7 @@ export default class Login extends Component {
}
} else {
if (!validate.isRequired(vcode)) {
showToast($t('3ca883d0.d0c06a'))
showToast('请输入验证码')
return
}
params = {
@@ -422,17 +413,17 @@ export default class Login extends Component {
username: mobile
}
if (!validate.isMobileNum(mobile)) {
showToast($t('3ca883d0.a32ab5'))
showToast('请输入正确的手机号')
return
}
if (loginType == 1) {
if (!validate.isRequired(password)) {
showToast($t('3ca883d0.e39ffe'))
showToast('请输入密码')
return
}
if (!validate.isPassword(password)) {
return showToast($t('3ca883d0.eac67a'))
return showToast('密码格式不正确')
}
params['password'] = password
params['check_type'] = 'password'
@@ -440,7 +431,7 @@ export default class Login extends Component {
params['auto_register'] = 0
} else {
if (!validate.isRequired(vcode)) {
showToast($t('3ca883d0.d0c06a'))
showToast('请输入验证码')
return
}
params['vcode'] = vcode
@@ -475,7 +466,7 @@ export default class Login extends Component {
if (accountMode === 'email') {
this.setState({ showEmailNotActivatedHint: false })
if (loginType === 1) {
return showToast($t('3ca883d0.54414f'))
return showToast('该邮箱尚未注册,请先注册或使用验证码登录')
}
setToken(token)
const emailTrim = (this.state.info.email || '').trim()
@@ -487,7 +478,7 @@ export default class Login extends Component {
return
}
if (loginType === 1) {
return showToast($t('3ca883d0.3bfe03'))
return showToast('当前手机号未注册,请先注册!')
}
setToken(token)
Taro.navigateTo({
@@ -693,7 +684,7 @@ export default class Login extends Component {
>
<View style={{ padding: '0 32px' }}>
<View className='auth-hd'>
<View className='title'>{$t('3ca883d0.04b015')}</View>
<View className='title'>{'欢迎登录'}</View>
{/* <View className='desc'>使用已注册的手机号登录</View> */}
</View>
<View className='auth-bd'>
@@ -704,7 +695,7 @@ export default class Login extends Component {
})}
onClick={() => this.handleAccountModeChange('mobile')}
>
{$t('3ca883d0.c906ff')}
{'手机号登录'}
</View>
<View
className={classNames('login-type-tab', {
@@ -712,7 +703,7 @@ export default class Login extends Component {
})}
onClick={() => this.handleAccountModeChange('email')}
>
{$t('3ca883d0.c90700')}
{'邮箱登录'}
</View>
</View>
<AtForm className='form'>
@@ -745,7 +736,7 @@ export default class Login extends Component {
clear
name='yzm'
value={info.yzm}
placeholder={$t('3ca883d0.e70066')}
placeholder={'请输入图形验证码'}
onChange={this.handleInputChange.bind(this, 'yzm')}
placeholderClass='input-placeholder'
{...inputProp}
@@ -769,7 +760,7 @@ export default class Login extends Component {
clear
name='vcode'
value={info.vcode}
placeholder={$t('3ca883d0.d0c06a')}
placeholder={'请输入验证码'}
onChange={this.handleInputChange.bind(this, 'vcode')}
placeholderClass='input-placeholder'
{...inputProp}
@@ -785,11 +776,11 @@ export default class Login extends Component {
)}
<View className='btn-text-group'>
<Text className='btn-text' onClick={this.handleToggleLogin.bind(this)}>
{passwordLogin ? $t('3ca883d0.4bc8be') : $t('3ca883d0.0d9631')}
{passwordLogin ? '验证码登录' : '密码登录'}
</Text>
{passwordLogin && (
<Text className='btn-text forgot-password' onClick={this.handleForgotPsd}>
{$t('3ca883d0.804890')}
{'忘记密码?'}
</Text>
)}
</View>
@@ -802,7 +793,7 @@ export default class Login extends Component {
name='email'
type='text'
value={info.email}
placeholder={$t('3ca883d0.b457cd')}
placeholder={'请输入登录邮箱'}
onChange={this.handleInputChange.bind(this, 'email')}
placeholderClass='input-placeholder'
{...inputProp}
@@ -812,7 +803,7 @@ export default class Login extends Component {
<View className='form-field'>
<View className='input-field'>
<CompPasswordInput
placeholder={$t('3ca883d0.96246d')}
placeholder={'请输入密码8-20位须含字母与数字'}
onChange={this.handleInputChange.bind(this, 'password')}
{...inputProp}
value={info.password}
@@ -827,7 +818,7 @@ export default class Login extends Component {
clear
name='email-yzm'
value={info.yzm}
placeholder={$t('3ca883d0.e70066')}
placeholder={'请输入图形验证码'}
onChange={this.handleInputChange.bind(this, 'yzm')}
placeholderClass='input-placeholder'
{...inputProp}
@@ -851,7 +842,7 @@ export default class Login extends Component {
clear
name='email-vcode'
value={info.vcode}
placeholder={$t('3ca883d0.a5ae49')}
placeholder={'请输入邮箱验证码'}
onChange={this.handleInputChange.bind(this, 'vcode')}
placeholderClass='input-placeholder'
{...inputProp}
@@ -868,7 +859,7 @@ export default class Login extends Component {
)}
<View className='btn-text-group'>
<Text className='btn-text' onClick={this.handleToggleLogin.bind(this)}>
{passwordLogin ? $t('3ca883d0.4bc8be') : $t('3ca883d0.0d9631')}
{passwordLogin ? '验证码登录' : '密码登录'}
</Text>
{(passwordLogin || showEmailNotActivatedHint) && (
<Text
@@ -879,7 +870,7 @@ export default class Login extends Component {
: this.handleForgotPsd
}
>
{showEmailNotActivatedHint ? $t('3ca883d0.actHint') : $t('3ca883d0.804890')}
{showEmailNotActivatedHint ? '未收到激活邮件?' : '忘记密码?'}
</Text>
)}
</View>
@@ -893,7 +884,7 @@ export default class Login extends Component {
className='login-button'
onClick={this.handleSubmit.bind(this)}
>
{$t('3ca883d0.e43613')}
{'登 录'}
</AtButton>
<AtButton
circle
@@ -901,7 +892,7 @@ export default class Login extends Component {
className='reg-button'
onClick={this.handleNavigateReg}
>
{$t('3ca883d0.495d84')}
{'注 册'}
</AtButton>
</View>
</AtForm>
@@ -913,29 +904,29 @@ export default class Login extends Component {
<SpFloatLayout
className='login-resend-activate-modal'
title={$t('3ca883d0.actModalTitle')}
title={'重发激活邮件'}
open={showResendActivateModal}
onClose={this.handleCloseResendActivateModal}
renderFooter={
<View className='resend-activate-footer'>
<AtButton circle onClick={this.handleCloseResendActivateModal}>
{$t('3ca883d0.actCancel')}
{'取消'}
</AtButton>
<AtButton circle type='primary' onClick={this.handleConfirmResendActivate}>
{$t('3ca883d0.actConfirm')}
{'确认'}
</AtButton>
</View>
}
>
<View className='resend-activate-body'>
<Text className='resend-activate-body__text'>{$t('3ca883d0.actModalBody')}</Text>
<Text className='resend-activate-body__text'>{'是否向该邮箱重新发送激活邮件?'}</Text>
<View className='form-field resend-activate-captcha'>
<View className='input-field'>
<AtInput
clear
name='resend-activate-yzm'
value={resendActivateYzm}
placeholder={$t('3ca883d0.e70066')}
placeholder={'请输入图形验证码'}
onChange={this.handleResendActivateYzmChange}
placeholderClass='input-placeholder'
/>

View File

@@ -12,7 +12,6 @@ import { useSelector } from 'react-redux'
import { AtForm, AtButton } from 'taro-ui'
import api from '@/api'
import { useImmer } from 'use-immer'
import { useTranslation, $t, ti, i18n } from '@/i18n'
import { CompPasswordInput } from './comps'
import './reg.scss'
@@ -78,7 +77,6 @@ function pickDefaultMemberGradeIdFromCard(data) {
const Reg = () => {
const regModeEffectSkip = useRef(true)
useTranslation()
const [state, setState] = useImmer(initialValue)
const {
@@ -138,15 +136,15 @@ const Reg = () => {
const handleSmsTimerStart = async (done) => {
if (!validate.isMobileNum(mobile)) {
showToast($t('4e9d53b5.a32ab5'))
showToast('请输入正确的手机号')
return
}
if (!validate.isRequired(yzm)) {
showToast($t('4e9d53b5.e70066'))
showToast('请输入图形验证码')
return
}
if (!imgInfo?.imageToken) {
showToast($t('4e9d53b5.c901aa'))
showToast('请稍候再试')
getImageVcode()
return
}
@@ -157,7 +155,7 @@ const Reg = () => {
yzm: yzm,
token: imgInfo.imageToken
})
showToast($t('4e9d53b5.4d7fb5'))
showToast('验证码已发送')
done()
} catch (e) {
getImageVcode()
@@ -167,11 +165,11 @@ const Reg = () => {
const handleSubmit = async () => {
if (!checked) {
const res = await Taro.showModal({
title: $t('4e9d53b5.02d981'),
content: ti('4e9d53b5.0ce185', [member_register, privacy]),
title: '提示',
content: `请先阅读并同意${member_register}${privacy}?`,
showCancel: true,
cancelText: $t('4e9d53b5.7173f8'),
confirmText: $t('4e9d53b5.e61f2c'),
cancelText: '拒绝',
confirmText: '同意',
confirmColor: colorPrimary
})
if (!res.confirm) return
@@ -179,19 +177,19 @@ const Reg = () => {
if (regMode === 'mobile') {
if (!validate.isMobileNum(mobile)) {
showToast($t('4e9d53b5.a32ab5'))
showToast('请输入正确的手机号')
return
}
if (!validate.isRequired(vcode)) {
showToast($t('4e9d53b5.d0c06a'))
showToast('请输入验证码')
return
}
if (!validate.isRequired(password)) {
showToast($t('4e9d53b5.e39ffe'))
showToast('请输入密码')
return
}
if (!validate.isPassword(password)) {
return showToast($t('4e9d53b5.eac67a'))
return showToast('密码格式不正确')
}
try {
const regRes = await api.user.reg({
@@ -204,7 +202,7 @@ const Reg = () => {
user_type: 'local'
})
const routerParams = getCurrentInstance()?.router?.params || {}
showToast(pickRegisterSuccessToast(regRes, $t('4e9d53b5.6506a9')), () => {
showToast(pickRegisterSuccessToast(regRes, '注册成功'), () => {
Taro.redirectTo({
url: buildPostRegisterLoginUrl('mobile', { mobile }, routerParams)
})
@@ -216,20 +214,20 @@ const Reg = () => {
}
if (!validate.isEmail(email.trim())) {
showToast($t('4e9d53b5.c902bb'))
showToast('请输入正确的电子邮箱')
return
}
if (!validate.isRequired(yzm)) {
showToast($t('4e9d53b5.e70066'))
showToast('请输入图形验证码')
return
}
if (!imgInfo?.imageToken) {
showToast($t('4e9d53b5.c901aa'))
showToast('请稍候再试')
getImageVcode()
return
}
if (!validate.isEmailChannelPassword(password)) {
return showToast($t('4e9d53b5.c903cc'))
return showToast('密码需8-20位且同时包含字母与数字')
}
const passMsg = validate.validatePass2(password, passwordConfirm)
if (passMsg) {
@@ -251,7 +249,7 @@ const Reg = () => {
const emailRegRes = await api.user.memberEmailRegister(emailPayload)
const routerParams = getCurrentInstance()?.router?.params || {}
const emailTrim = email.trim()
showToast(pickRegisterSuccessToast(emailRegRes, $t('4e9d53b5.6506a9')), () => {
showToast(pickRegisterSuccessToast(emailRegRes, '注册成功'), () => {
Taro.redirectTo({
url: buildPostRegisterLoginUrl('email', { email: emailTrim }, routerParams)
})
@@ -314,10 +312,7 @@ const Reg = () => {
}
useEffect(() => {
Taro.setNavigationBarTitle({ title: $t('461de497.fe0e8b') })
const onLang = () => Taro.setNavigationBarTitle({ title: $t('461de497.fe0e8b') })
i18n.on('languageChanged', onLang)
return () => i18n.off('languageChanged', onLang)
Taro.setNavigationBarTitle({ title: '注册' })
}, [])
useEffect(() => {
@@ -352,7 +347,7 @@ const Reg = () => {
})}
>
<View className='auth-hd'>
<View className='title'>{$t('4e9d53b5.8c4312')}</View>
<View className='title'>欢迎注册</View>
</View>
<View className='auth-bd'>
<View className='reg-type-tabs'>
@@ -360,13 +355,13 @@ const Reg = () => {
className={classNames('reg-type-tab', { 'reg-type-tab--active': regMode === 'mobile' })}
onClick={() => setRegMode('mobile')}
>
{$t('4e9d53b5.c904dd')}
手机号注册
</View>
<View
className={classNames('reg-type-tab', { 'reg-type-tab--active': regMode === 'email' })}
onClick={() => setRegMode('email')}
>
{$t('4e9d53b5.c905ee')}
邮箱注册
</View>
</View>
<AtForm className='form'>
@@ -379,7 +374,7 @@ const Reg = () => {
maxLength={11}
type='tel'
value={state.mobile}
placeholder={$t('4e9d53b5.787a47')}
placeholder='请输入您的手机号码'
onChange={handleInputChange('mobile')}
/>
</View>
@@ -390,7 +385,7 @@ const Reg = () => {
clear
name='yzm'
value={state.yzm}
placeholder={$t('4e9d53b5.e70066')}
placeholder={'请输入图形验证码'}
onChange={handleInputChange('yzm')}
/>
</View>
@@ -411,15 +406,15 @@ const Reg = () => {
clear
name='vcode'
value={state.vcode}
placeholder={$t('4e9d53b5.d0c06a')}
placeholder={'请输入验证码'}
onChange={handleInputChange('vcode')}
/>
</View>
<View className='btn-field'>
<SpTimer
key='reg-mobile-timer'
defaultMsg={$t('0eb8dfea.c5c358')}
msg={$t('0eb8dfea.89b213')}
defaultMsg='发送验证码'
msg='重新发送'
onStart={handleSmsTimerStart}
/>
</View>
@@ -428,7 +423,7 @@ const Reg = () => {
<View className='form-field'>
<View className='input-field'>
<CompPasswordInput
placeholder={$t('4e9d53b5.e39ffe')}
placeholder={'请输入密码'}
onChange={handleInputChange('password')}
value={state.password}
/>
@@ -443,7 +438,7 @@ const Reg = () => {
name='email'
type='text'
value={state.email}
placeholder={$t('3ca883d0.c90811')}
placeholder='请输入电子邮箱'
onChange={handleInputChange('email')}
/>
</View>
@@ -454,7 +449,7 @@ const Reg = () => {
clear
name='email-yzm'
value={state.yzm}
placeholder={$t('4e9d53b5.e70066')}
placeholder={'请输入图形验证码'}
onChange={handleInputChange('yzm')}
/>
</View>
@@ -472,7 +467,7 @@ const Reg = () => {
<View className='form-field'>
<View className='input-field'>
<CompPasswordInput
placeholder={$t('4e9d53b5.c903cc')}
placeholder={'密码需8-20位且同时包含字母与数字'}
onChange={handleInputChange('password')}
value={state.password}
/>
@@ -482,7 +477,7 @@ const Reg = () => {
<View className='form-field'>
<View className='input-field'>
<CompPasswordInput
placeholder={$t('4e9d53b5.c90700')}
placeholder='请再次确认登录密码'
onChange={handleInputChange('passwordConfirm')}
value={state.passwordConfirm}
/>
@@ -494,7 +489,7 @@ const Reg = () => {
{regMode === 'email' && (
<View className='btn-text-group btn-text-group--end'>
<Text className='btn-text' onClick={handleNavigateForgotEmail}>
{$t('3ca883d0.804890')}
忘记密码
</Text>
</View>
)}
@@ -507,14 +502,14 @@ const Reg = () => {
className='login-button'
onClick={handleSubmit}
>
{$t('4e9d53b5.3179ba')}
同意协议并注册
</AtButton>
</View>
<View className='form-text'>
<SpCheckbox checked={checked} onChange={handleSelect} />
<View>
{$t('4e9d53b5.b840cb')}
已阅读并同意
<Text
className='primary-color'
onClick={() =>

View File

@@ -16468,5 +16468,59 @@
"en": "",
"zh-tw": "",
"ar": ""
},
"c717q1e": {
"zh-cn": "图形验证码未就绪,请刷新重试",
"en": "",
"zh-tw": "",
"ar": ""
},
"j09fb6d": {
"zh-cn": "激活邮件已发送,请查收邮箱",
"en": "",
"zh-tw": "",
"ar": ""
},
"6785lka": {
"zh-cn": "发送失败,请稍后重试",
"en": "",
"zh-tw": "",
"ar": ""
},
"j4d180k": {
"zh-cn": "请输入密码8-20位须含字母与数字",
"en": "",
"zh-tw": "",
"ar": ""
},
"otk5kck": {
"zh-cn": "该邮箱尚未注册,请先注册或使用验证码登录",
"en": "",
"zh-tw": "",
"ar": ""
},
"i6fyqi7": {
"zh-cn": "请输入登录邮箱",
"en": "",
"zh-tw": "",
"ar": ""
},
"glf74o8": {
"zh-cn": "未收到激活邮件?",
"en": "",
"zh-tw": "",
"ar": ""
},
"r5t1uh6": {
"zh-cn": "重发激活邮件",
"en": "",
"zh-tw": "",
"ar": ""
},
"6c74mzf": {
"zh-cn": "是否向该邮箱重新发送激活邮件?",
"en": "",
"zh-tw": "",
"ar": ""
}
}

View File

@@ -164,7 +164,7 @@ function CompGoodsBuyToolbar(props) {
</SpLogin>
<View
className='toolbar-item'
onClick={navigateTo.bind(this, '/pages/cart/espier-index?tabbar=0')}
onClick={navigateTo.bind(this, '/pages/cart/espier-index?showBack=1')}
>
<Text className='iconfont icon-gouwuche'></Text>
<Text className='toolbar-item-txt'>购物车</Text>

View File

@@ -102,6 +102,7 @@ function CompPackageItem(props) {
const onChangeSkuSelect = (specText, curItem) => {
console.log(specText, curItem)
if (!curItem || !curItem.itemId) return
if (curGoodsType == 0) {
setState((draft) => {
draft.mainGoods.specText = specText
@@ -114,7 +115,6 @@ function CompPackageItem(props) {
})
} else {
setState((draft) => {
console.log(package_price[curItem.itemId].price)
draft.makeUpGoods[curMakeUpGoodsIndex].specText = specText
draft.makeUpGoods[curMakeUpGoodsIndex]['curItem'] = {
...curItem,
@@ -140,7 +140,9 @@ function CompPackageItem(props) {
if (mainGoods.curItem) {
itemId = mainGoods.curItem.itemId
// packageTotalPrice += mainGoods.curItem.packagePrice
packageTotalPrice += main_package_price[itemId].price / 100
packageTotalPrice += main_package_price?.[itemId]?.price
? main_package_price[itemId].price / 100
: mainGoods.curItem?.price || 0
}
}
makeUpGoods.forEach((goods) => {
@@ -153,7 +155,9 @@ function CompPackageItem(props) {
if (goods.curItem) {
sitemIds.push(goods.curItem.itemId)
// packageTotalPrice += goods.curItem.packagePrice
packageTotalPrice += package_price[goods.curItem.itemId].price / 100
packageTotalPrice += package_price?.[goods.curItem.itemId]?.price
? package_price[goods.curItem.itemId].price / 100
: goods.curItem?.price || 0
} else {
sitemIds.push(null)
}

View File

@@ -125,16 +125,14 @@ function CouponCenter(props) {
0: '已领完',
1: '立即领取',
2: '已领取'
})[status]
}[status])
const renderCouponBtn = (item, index) => {
const label = couponBtnLabel(item.couponStatus)
const text = <Text>{label}</Text>
// 未登录领取:用 SpLogin 在本页弹窗登录,避免请求 401 被全局重定向到个人中心
if (item.couponStatus === 1 && !isLogin) {
return (
<SpLogin onChange={() => handleClickCouponItem(item, index)}>{text}</SpLogin>
)
return <SpLogin onChange={() => handleClickCouponItem(item, index)}>{text}</SpLogin>
}
return text
}

View File

@@ -42,7 +42,6 @@ import {
} from '@/store/slices/purchase'
import { useLogin, useLocation } from '@/hooks'
import { updateDeliveryPersonnel } from '@/store/slices/cart'
import { useTranslation, $t } from '@/i18n'
import CompMenu from './comps/comp-menu'
import './index.scss'
@@ -116,7 +115,6 @@ const initialState = {
}
function MemberIndex(props) {
useTranslation()
// console.log('===>getCurrentPages==>', getCurrentPages(), getCurrentInstance())
const pageRef = useRef(null)
const $instance = getCurrentInstance() || {}
@@ -359,21 +357,21 @@ function MemberIndex(props) {
Taro.navigateTo({ url: link })
} else {
const { confirm } = await Taro.showModal({
title: $t('3009e832.75716c'),
content: $t('3009e832.7785f6'),
title: '邀请推广',
content: '确定申请成为推广员?',
showCancel: true,
cancelText: $t('3009e832.625fb2'),
confirmText: $t('3009e832.e83a25'),
cancelText: '取消',
confirmText: '确认',
confirmColor: '#0b4137'
})
if (!confirm) return
const { status } = await api.distribution.become()
if (status) {
Taro.showModal({
title: $t('3009e832.a1651e'),
content: $t('3009e832.44fafb'),
title: '恭喜',
content: '已成为推广员',
showCancel: false,
confirmText: $t('3009e832.ac2c8f')
confirmText: '好'
})
}
}
@@ -433,7 +431,7 @@ function MemberIndex(props) {
<Text>
{
{
true: vipInfo.grade_name || $t('3009e832.4d9dd5'),
true: vipInfo.grade_name || '会员',
false: userInfo?.gradeInfo?.grade_name || ''
}[vipInfo.isVip]
}
@@ -460,7 +458,7 @@ function MemberIndex(props) {
showpoweredBy={false}
pageConfig={state.pageData?.base || {}}
renderFooter={<SpTabbar />}
title={$t('75e226b0.12688a')}
title='会员中心'
onReady={({ gNavbarH, footerHeight }) => {
setState((draft) => {
draft.bodyHeight = `calc(100vh - ${
@@ -486,13 +484,14 @@ function MemberIndex(props) {
<View
className='user-avatar'
onClick={() => onLoginChange('/subpages/member/user-info')}
style={{ width: '72px', height: '72px' }}
>
<SpImage
className='avatar-img'
src={(userInfo && userInfo.avatar) || 'user_icon.png'}
width={144}
height={144}
mode='aspectFit'
radius={72}
/>
</View>
@@ -516,7 +515,7 @@ function MemberIndex(props) {
</View>
</>
) : (
<Text className='login-text font-medium text-34'>{$t('3009e832.a1f629')}</Text>
<Text className='login-text font-medium text-34'>点击登录</Text>
)}
</View>
@@ -557,7 +556,7 @@ function MemberIndex(props) {
onClick={() => onLoginChange('/subpages/marketing/coupon')}
>
<Text className='stat-value'>{isLogin ? state.couponCount || 0 : '···'}</Text>
<Text className='stat-label'>{$t('3009e832.2f3635')}</Text>
<Text className='stat-label'>优惠券</Text>
</View>
<View

View File

@@ -54,11 +54,12 @@
width: 144px;
height: 144px;
border-radius: 50%;
border: 2px solid #ebebeb;
border: 1PX solid #ebebeb;
overflow: hidden;
position: absolute;
left: 36px;
top: -36px;
box-sizing: border-box;
.avatar-img {
width: 100%;

View File

@@ -59,7 +59,6 @@ const initState = {
info: null,
skuPanelOpen: false,
selectType: 'picker',
statusBarHeight: '',
open: false,
hideClose: true,
/** 页面滚动超过 20px 时搜索条白底 */
@@ -85,7 +84,6 @@ function StoreIndex() {
info,
skuPanelOpen,
selectType,
statusBarHeight,
open,
searchSolidBg
} = state
@@ -96,7 +94,6 @@ function StoreIndex() {
useDidShow(() => {
fetchWgts()
init()
salesmanShare()
})
@@ -154,14 +151,6 @@ function StoreIndex() {
// }
}
const init = async () => {
const { statusBarHeight } = await Taro.getSystemInfoSync()
setState((draft) => {
draft.statusBarHeight = statusBarHeight
})
console.log('MenuButton:', statusBarHeight)
}
const fetchWgts = async () => {
const { id, dtid, uid } = await parameter()

View File

@@ -2,7 +2,6 @@
* Copyright © ShopeX http://www.shopex.cn. All rights reserved.
* See LICENSE file for license details.
*/
import { $t } from '@/i18n'
const phone_rule = /^1[3456789]\d{9}$/
const password_rule = /^[(a-z|A-Z|0-9)]{6,16}$/
@@ -32,14 +31,14 @@ const validate = {
validatePass2: function (val, val1) {
let message = null
if (val != val1) {
message = $t('6f8a23e8.076573')
message = '输入的密码不一致'
}
return message
},
validateEmail: function (val) {
let message = null
if (!email_rule.test(val)) {
message = $t('6f8a23e8.75262e')
message = '邮箱格式不正确'
}
return message
},