From 139e82d40e1b7796878b75c5a522da3644935fd7 Mon Sep 17 00:00:00 2001 From: moyayu <1623253835@qq.com> Date: Fri, 24 Apr 2026 17:25:38 +0800 Subject: [PATCH] This merge consolidates recent fixes and refactors across auth, member, goods widgets, and recommendation pages, with a focus on runtime stability, i18n consistency, and UI warning cleanup. --- src/components/sp-goods-item/index.js | 6 +-- src/components/sp-render-goods/hero-card.jsx | 8 ++- src/pages/home/wgts/goodscard.js | 5 +- src/pages/home/wgts/goodscard.scss | 8 +-- src/pages/home/wgts/helper.js | 22 ++++----- src/pages/recommend/detail.js | 1 + src/subpages/auth/forgotpwd-email.js | 5 +- src/subpages/auth/forgotpwd.js | 9 +++- src/subpages/auth/login.js | 52 +++++++++++--------- src/subpages/auth/reg.js | 23 +++++---- src/subpages/auth/util.js | 27 ++++++++-- src/subpages/guide/recommend/detail.js | 5 +- src/subpages/member/index.js | 5 +- src/subpages/member/index.scss | 2 +- 14 files changed, 111 insertions(+), 67 deletions(-) diff --git a/src/components/sp-goods-item/index.js b/src/components/sp-goods-item/index.js index 1498ecefa..0ccd541c2 100644 --- a/src/components/sp-goods-item/index.js +++ b/src/components/sp-goods-item/index.js @@ -185,7 +185,7 @@ function SpGoodsItem(props) { {!info.point && showPrice && ( - + {isPurchase && ( <> {info.activityPrice && enPurActivityPrice ? ( @@ -201,14 +201,14 @@ function SpGoodsItem(props) { {!isPurchase && ( )} - {/* {info.marketPrice > 0 && enMarketPrice && ( + {info.marketPrice > 0 && enMarketPrice && ( - )} */} + )} {!info.activityPrice && isLogin && !isPurchase && ( diff --git a/src/components/sp-render-goods/hero-card.jsx b/src/components/sp-render-goods/hero-card.jsx index 13c0644c5..312b08a17 100644 --- a/src/components/sp-render-goods/hero-card.jsx +++ b/src/components/sp-render-goods/hero-card.jsx @@ -78,13 +78,17 @@ function SpGoodsHeroCard(props) { {info.promotion?.map((tag, index) => ( ))} {info.couponList?.map((tag, index) => ( - + ))} )} diff --git a/src/pages/home/wgts/goodscard.js b/src/pages/home/wgts/goodscard.js index 8bc0364f1..983ab7167 100644 --- a/src/pages/home/wgts/goodscard.js +++ b/src/pages/home/wgts/goodscard.js @@ -190,10 +190,7 @@ export default class WgtGoodsCard extends Component { const isFav = Boolean(item.favStatus ?? favs?.[item.item_id]) return ( - + {item.item_name} diff --git a/src/pages/home/wgts/goodscard.scss b/src/pages/home/wgts/goodscard.scss index b9ada30a6..b17bdb2be 100644 --- a/src/pages/home/wgts/goodscard.scss +++ b/src/pages/home/wgts/goodscard.scss @@ -3,6 +3,8 @@ * See LICENSE file for license details. */ .wgt-goods-card { + + .wgt-bd { .goods-card { &:not(:last-child) { @@ -55,8 +57,8 @@ height: 64px; font-size: 28px; color: $color-brand-primary; - background: #ffffff; - border: 1px solid #dcdfe6; + background: #FFFFFF; + border: 1PX solid #DCDFE6; border-radius: 12px; } @@ -72,4 +74,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/pages/home/wgts/helper.js b/src/pages/home/wgts/helper.js index 6c4024233..68e4176bd 100644 --- a/src/pages/home/wgts/helper.js +++ b/src/pages/home/wgts/helper.js @@ -122,35 +122,35 @@ export function getGlobalBaseStyle(baseStyle) { // 处理边距 if (baseStyle.paddedt !== undefined && baseStyle.paddedt !== null) { - style['padding-top'] = Taro.pxTransform(baseStyle.paddedt) + style.paddingTop = Taro.pxTransform(baseStyle.paddedt) } if (baseStyle.paddedb !== undefined && baseStyle.paddedb !== null) { - style['padding-bottom'] = Taro.pxTransform(baseStyle.paddedb) + style.paddingBottom = Taro.pxTransform(baseStyle.paddedb) } if (baseStyle.paddedl !== undefined && baseStyle.paddedl !== null) { - style['padding-left'] = Taro.pxTransform(baseStyle.paddedl) + style.paddingLeft = Taro.pxTransform(baseStyle.paddedl) } if (baseStyle.paddedr !== undefined && baseStyle.paddedr !== null) { - style['padding-right'] = Taro.pxTransform(baseStyle.paddedr) + style.paddingRight = Taro.pxTransform(baseStyle.paddedr) } // 处理背景 const bgType = baseStyle.bgType if (bgType === 'color' && baseStyle.bgColor) { - style['background-color'] = baseStyle.bgColor + style.backgroundColor = baseStyle.bgColor } else if (bgType === 'pic' && baseStyle.bgPic) { - style['background-image'] = `url(${baseStyle.bgPic})` - style['background-size'] = 'cover' - style['background-position'] = 'center' - style['background-repeat'] = 'no-repeat' + style.backgroundImage = `url(${baseStyle.bgPic})` + style.backgroundSize = 'cover' + style.backgroundPosition = 'center' + style.backgroundRepeat = 'no-repeat' } else if (bgType === 'gradient' && baseStyle.startColor) { // 如果 endColor 为空,使用 startColor 作为结束颜色(单色渐变) const endColor = baseStyle.endColor || baseStyle.startColor - style['background-image'] = `linear-gradient(${baseStyle.startColor}, ${endColor})` - style['background-size'] = 'cover' + style.backgroundImage = `linear-gradient(${baseStyle.startColor}, ${endColor})` + style.backgroundSize = 'cover' } return style diff --git a/src/pages/recommend/detail.js b/src/pages/recommend/detail.js index 96b31e207..5abc9e76d 100644 --- a/src/pages/recommend/detail.js +++ b/src/pages/recommend/detail.js @@ -124,6 +124,7 @@ function GuideRecommendDetail(props) { } } + return ( { @@ -96,7 +97,9 @@ const PageForgotPwdEmail = () => { className='btn-text' onClick={() => Taro.navigateTo({ - url: `/subpages/auth/login?redirect=${encodeURIComponent(rediUrlParam)}` + url: `/subpages/auth/login?redirect=${encodeURIComponent( + normalizeAuthRedirectParam(rediUrlParam) + )}` }) } > diff --git a/src/subpages/auth/forgotpwd.js b/src/subpages/auth/forgotpwd.js index c004f7192..b501b6287 100644 --- a/src/subpages/auth/forgotpwd.js +++ b/src/subpages/auth/forgotpwd.js @@ -13,6 +13,7 @@ import api from '@/api' import { useImmer } from 'use-immer' import { useSelector } from 'react-redux' import { CompPasswordInput } from './comps' +import { normalizeAuthRedirectParam } from './util' import './forgotpwd.scss' const SYMBOL = 'forgot_password' @@ -60,7 +61,7 @@ const PageBindPhone = () => { const showModalReg = async () => { let url = `/subpages/auth/reg` if (redi_url) { - url += `?redi_url=${encodeURIComponent(redi_url)}` + url += `?redi_url=${encodeURIComponent(normalizeAuthRedirectParam(redi_url))}` } const { is_new } = await api.wx.getIsNew({ mobile: username }) setState((_state) => { @@ -201,7 +202,11 @@ const PageBindPhone = () => { /> - + diff --git a/src/subpages/auth/login.js b/src/subpages/auth/login.js index 43c945ab1..5789b5bd2 100644 --- a/src/subpages/auth/login.js +++ b/src/subpages/auth/login.js @@ -14,7 +14,13 @@ import S from '@/spx' import api from '@/api' import { classNames, navigateTo, validate, showToast, tokenParseH5 } from '@/utils' import { CompOtherLogin, CompPasswordInput, CompInputPhone } from './comps' -import { navigationToReg, setToken, setTokenAndRedirect, addListener } from './util' +import { + navigationToReg, + setToken, + setTokenAndRedirect, + addListener, + normalizeAuthRedirectParam +} from './util' import './login.scss' /** 注册页 redirect 带来的 email query(可能与 reg 侧 `encodeEmailForLoginQuery` 成对使用) */ @@ -112,7 +118,7 @@ export default class Login extends Component { Taro.setNavigationBarTitle({ title: '登录' }) const { redirect } = this.$instance?.router?.params if (S.getAuthToken()) { - const url = redirect ? decodeURIComponent(redirect) : '/subpages/member/index' + const url = redirect ? normalizeAuthRedirectParam(redirect) : '/subpages/member/index' window.location.href = url } // 部分环境下 query 仅在 didShow 就绪,用于补一次「注册成功带回邮箱」的预填 @@ -473,7 +479,7 @@ export default class Login extends Component { Taro.navigateTo({ url: `/subpages/auth/edit-password?phone=${encodeURIComponent( emailTrim - )}&redi_url=${encodeURIComponent(redirect || '')}` + )}&redi_url=${encodeURIComponent(normalizeAuthRedirectParam(redirect || ''))}` }) return } @@ -483,7 +489,7 @@ export default class Login extends Component { setToken(token) Taro.navigateTo({ url: `/subpages/auth/edit-password?phone=${mobile}&redi_url=${encodeURIComponent( - redirect || '' + normalizeAuthRedirectParam(redirect || '') )}` }) return @@ -547,7 +553,7 @@ export default class Login extends Component { if (accountMode === 'email') { const parts = [] if (redirect) { - parts.push(`redi_url=${encodeURIComponent(redirect)}`) + parts.push(`redi_url=${encodeURIComponent(normalizeAuthRedirectParam(redirect))}`) } if (email) { parts.push(`email=${encodeURIComponent(email.trim())}`) @@ -562,7 +568,7 @@ export default class Login extends Component { const parts = [] if (redirect) { - parts.push(`redi_url=${encodeURIComponent(redirect)}`) + parts.push(`redi_url=${encodeURIComponent(normalizeAuthRedirectParam(redirect))}`) } if (mobile) { parts.push(`phone=${mobile}`) @@ -684,7 +690,7 @@ export default class Login extends Component { > - 欢迎登录 + {'欢迎登录'} {/* 使用已注册的手机号登录 */} @@ -695,7 +701,7 @@ export default class Login extends Component { })} onClick={() => this.handleAccountModeChange('mobile')} > - 手机号登录 + {'手机号登录'} this.handleAccountModeChange('email')} > - 邮箱登录 + {'邮箱登录'} @@ -736,7 +742,7 @@ export default class Login extends Component { clear name='yzm' value={info.yzm} - placeholder='请输入图形验证码' + placeholder={'请输入图形验证码'} onChange={this.handleInputChange.bind(this, 'yzm')} placeholderClass='input-placeholder' {...inputProp} @@ -760,7 +766,7 @@ export default class Login extends Component { clear name='vcode' value={info.vcode} - placeholder='请输入验证码' + placeholder={'请输入验证码'} onChange={this.handleInputChange.bind(this, 'vcode')} placeholderClass='input-placeholder' {...inputProp} @@ -780,7 +786,7 @@ export default class Login extends Component { {passwordLogin && ( - 忘记密码? + {'忘记密码?'} )} @@ -793,7 +799,7 @@ export default class Login extends Component { name='email' type='text' value={info.email} - placeholder='请输入登录邮箱' + placeholder={'请输入登录邮箱'} onChange={this.handleInputChange.bind(this, 'email')} placeholderClass='input-placeholder' {...inputProp} @@ -803,7 +809,7 @@ export default class Login extends Component { - 登 录 + {'登 录'} - 注 册 + {'注 册'} @@ -904,29 +910,29 @@ export default class Login extends Component { - 取消 + {'取消'} - 确认 + {'确认'} } > - 是否向该邮箱重新发送激活邮件? + {'是否向该邮箱重新发送激活邮件?'} diff --git a/src/subpages/auth/reg.js b/src/subpages/auth/reg.js index 11954fe7b..5f9162b77 100644 --- a/src/subpages/auth/reg.js +++ b/src/subpages/auth/reg.js @@ -13,6 +13,7 @@ import { AtForm, AtButton } from 'taro-ui' import api from '@/api' import { useImmer } from 'use-immer' import { CompPasswordInput } from './comps' +import { normalizeAuthRedirectParam } from './util' import './reg.scss' /** query 里邮箱保留 `@`,避免链接或路由层把 `%40` 当字面量带进输入框;其余字符仍按 URI 编码 */ @@ -38,11 +39,13 @@ function buildPostRegisterLoginUrl(accountMode, fields, routerParams) { qs.push(`email=${encodeEmailForLoginQuery(fields.email)}`) } const { redi_url, redirect } = routerParams || {} - if (redi_url) { - qs.push(`redi_url=${encodeURIComponent(redi_url)}`) + const rediPlain = redi_url ? normalizeAuthRedirectParam(redi_url) : '' + const redirectPlain = redirect ? normalizeAuthRedirectParam(redirect) : '' + if (rediPlain) { + qs.push(`redi_url=${encodeURIComponent(rediPlain)}`) } - if (redirect) { - qs.push(`redirect=${encodeURIComponent(redirect)}`) + if (redirectPlain) { + qs.push(`redirect=${encodeURIComponent(redirectPlain)}`) } return `/subpages/auth/login?${qs.join('&')}` } @@ -114,7 +117,7 @@ const Reg = () => { const redi_url = getCurrentInstance()?.router?.params?.redi_url const parts = [] if (redi_url) { - parts.push(`redi_url=${encodeURIComponent(redi_url)}`) + parts.push(`redi_url=${encodeURIComponent(normalizeAuthRedirectParam(redi_url))}`) } const e = email.trim() if (e) { @@ -385,7 +388,7 @@ const Reg = () => { clear name='yzm' value={state.yzm} - placeholder='请输入图形验证码' + placeholder={'请输入图形验证码'} onChange={handleInputChange('yzm')} /> @@ -406,7 +409,7 @@ const Reg = () => { clear name='vcode' value={state.vcode} - placeholder='请输入验证码' + placeholder={'请输入验证码'} onChange={handleInputChange('vcode')} /> @@ -423,7 +426,7 @@ const Reg = () => { @@ -449,7 +452,7 @@ const Reg = () => { clear name='email-yzm' value={state.yzm} - placeholder='请输入图形验证码' + placeholder={'请输入图形验证码'} onChange={handleInputChange('yzm')} /> @@ -467,7 +470,7 @@ const Reg = () => { diff --git a/src/subpages/auth/util.js b/src/subpages/auth/util.js index c2e78613e..386e01eb5 100644 --- a/src/subpages/auth/util.js +++ b/src/subpages/auth/util.js @@ -7,10 +7,31 @@ import { showToast } from '@/utils' import Taro, { getCurrentInstance } from '@tarojs/taro' import { SG_CHECK_STORE_RULE } from '@/consts' +/** + * 将 redirect / redi_url 规范成「未 URI 编码的站内路径」, + * 避免 登录→注册→登录 等链路里对已编码字符串再次 encode 出现 %252F、%25252F 乱码。 + */ +export function normalizeAuthRedirectParam(raw) { + if (raw == null) return '' + let s = String(raw).trim() + if (!s) return '' + for (let i = 0; i < 8; i += 1) { + try { + const next = decodeURIComponent(s) + if (next === s) break + s = next + } catch { + break + } + } + return s +} + //跳转到注册页 function navigationToReg(redirect) { + const plain = normalizeAuthRedirectParam(redirect) Taro.navigateTo({ - url: `/subpages/auth/reg?redi_url=${encodeURIComponent(redirect)}` + url: `/subpages/auth/reg?redi_url=${encodeURIComponent(plain)}` }) } @@ -44,9 +65,9 @@ async function setTokenAndRedirect(token = '', tokenSetSuccessCallback, options) const url = forceMemberCenter ? '/subpages/member/index' : redi_url - ? decodeURIComponent(redi_url) + ? normalizeAuthRedirectParam(redi_url) : redirect - ? decodeURIComponent(redirect) + ? normalizeAuthRedirectParam(redirect) : '/subpages/member/index' // 清空店铺进店规则检查 Taro.setStorageSync(SG_CHECK_STORE_RULE, 0) diff --git a/src/subpages/guide/recommend/detail.js b/src/subpages/guide/recommend/detail.js index 3612349f3..ab0dc4a7c 100644 --- a/src/subpages/guide/recommend/detail.js +++ b/src/subpages/guide/recommend/detail.js @@ -79,6 +79,7 @@ function GuideRecommendDetail(props) { }) } + return ( } {item.name === 'writing' && } {item.name === 'heading' && } - {item.name === 'goodsCard' && } + {item.name === 'goodsCard' && ( + + )} ))} diff --git a/src/subpages/member/index.js b/src/subpages/member/index.js index 5ed69fd5c..58655b8f9 100644 --- a/src/subpages/member/index.js +++ b/src/subpages/member/index.js @@ -8,7 +8,7 @@ import { updateUserInfo, updateCheckChief } from '@/store/slices/user' import { WgtsContext } from '@/pages/home/wgts/wgts-context' import { platformTemplateName } from '@/utils/platform' import { View, Text, ScrollView } from '@tarojs/components' -import { SG_APP_CONFIG } from '@/consts' +import { SG_APP_CONFIG, DEFAULT_POINT_NAME } from '@/consts' import { useSelector, useDispatch } from 'react-redux' import HomeWgts from '@/pages/home/comps/home-wgts' import { useImmer } from 'use-immer' @@ -110,7 +110,6 @@ const initialState = { shareInfo: {}, footerHeight: 0, pageData: null, - shareInfo: {}, bodyHeight: 0 } @@ -136,7 +135,7 @@ function MemberIndex(props) { const [policyModal, setPolicyModal] = useState(false) const { userInfo = {}, vipInfo = {} } = useSelector((state) => state.user) - const { pointName } = useSelector((state) => state.sys) + const pointName = useSelector((state) => state.sys?.pointName ?? DEFAULT_POINT_NAME()) log.debug(`store userInfo: ${JSON.stringify(userInfo)}`) const dispatch = useDispatch() diff --git a/src/subpages/member/index.scss b/src/subpages/member/index.scss index 2a65ef634..c686801cd 100644 --- a/src/subpages/member/index.scss +++ b/src/subpages/member/index.scss @@ -54,7 +54,7 @@ width: 144px; height: 144px; border-radius: 50%; - border: 1px solid #ebebeb; + border: 1PX solid #ebebeb; overflow: hidden; position: absolute; left: 36px;