fix: product detail scroll nav mantle, price/SKU header tweaks, and delivery UI cleanup

This commit is contained in:
moyayu
2026-05-20 11:03:34 +08:00
parent 08825b508c
commit 1bbce1833e
7 changed files with 41 additions and 308 deletions

View File

@@ -2,14 +2,15 @@
* Copyright © ShopeX http://www.shopex.cn. All rights reserved.
* See LICENSE file for license details.
*/
import React, { useEffect, useRef, useImperativeHandle, useMemo } from 'react'
import React, { useEffect, useRef, useImperativeHandle } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import Taro, { getCurrentInstance } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import { View, ScrollView, Text } from '@tarojs/components'
import { useImmer } from 'use-immer'
import {
AddressChoose,
SpCell,
SpFloatLayout,
SpForm,
SpFormItem,
SpTimePicker,
@@ -22,22 +23,6 @@ import api from '@/api'
import { $t, ti, useTranslation } from '@/i18n'
import './index.scss'
/** 企业购结算页分段条:与设计稿图标对应 */
const PURCHASE_DELIVERY_ICONS = {
logistics: 'icon-office-box',
dada: 'icon-delivery',
merchant: 'icon-delivery',
ziti: 'icon-zitidian'
}
/** 企业购 Figma 58:460 文案(与 DELIVERY_LIST 中「同城配」区分),键与 locales 既有配送文案对齐 */
const PURCHASE_TAB_LABEL_KEYS = {
logistics: '97e6d964.249bfe',
dada: '97e6d964.bdcbc9',
merchant: '97e6d964.bdcbc9',
ziti: '9c730348.93ab28'
}
const initialState = {
distributorInfo: null,
receiptType: '',
@@ -90,6 +75,7 @@ function SpDeliver(props, ref) {
receiptType,
showTimePicker,
form,
rules,
weekdays,
timeSlots,
pickerIndex,
@@ -430,11 +416,7 @@ function SpDeliver(props, ref) {
return (
<View
key={item.type}
className={classNames(
'switch-item',
receiptType === item.type && 'active',
isPurchase && 'switch-item--purchase'
)}
className={`switch-item ${receiptType === item.type ? 'active' : ''}`}
onClick={handleSwitchExpress.bind(this, item.type)}
>
{receiptType === item.type && item.type === 'logistics' && (

View File

@@ -11,10 +11,6 @@
background: #f5f5f5;
border-radius: 12px;
font-size: 24px;
height: 110px;
width: 100%;
box-sizing: border-box;
background-color: #F5F5F5;
.switch-item {
// padding: 0px 30px;
display: flex;
@@ -294,198 +290,3 @@
}
}
}
.ziti-info {
margin-top: 24px;
padding: 30px 30px 30px 50px;
border-radius: 20px;
background: #fff;
box-shadow: inset 0 0 0 1px #f2f2f2;
.sp-order-item__idx {
margin-left: -20px;
}
.applychief-form {
.sp-form-item {
margin-bottom: 0;
padding: 0;
background: transparent;
&.sp-form-item-line {
padding: 10px 0;
align-items: center;
border-bottom: 1px solid #ececec;
}
&:last-child.sp-form-item-line {
border-bottom: 0;
}
.form-item-label {
.label {
font-size: 28px;
font-weight: 500;
color: #333;
}
}
.required {
top: 2px;
color: #df2f2f;
}
.form-item-control {
min-width: 0;
}
.at-input,
.picker-time {
margin: 0;
padding: 8px 0 10px;
border: 0;
border-radius: 0;
background: transparent;
min-height: 68px;
box-sizing: border-box;
&:after {
border: 0;
}
}
.picker-time {
.sp-cell__bd {
justify-content: flex-start;
padding: 0;
.placeholder {
color: #ccc;
}
}
.sp-cell__ft {
padding-right: 0;
}
}
.at-input {
margin-left: 0;
}
.at-input__input,
.picker-time text {
width: 100%;
font-size: 30px;
color: #222;
}
.placeholder,
.at-input .input-placeholder {
color: #c7c7c7;
}
.form-item-message {
left: 96px;
bottom: -30px;
font-size: 22px;
}
}
}
}
.ziti-info {
margin-top: 24px;
padding: 30px 30px 30px 50px;
border-radius: 20px;
background: #fff;
box-shadow: inset 0 0 0 1px #f2f2f2;
.sp-order-item__idx {
margin-left: -20px;
}
.applychief-form {
.sp-form-item {
margin-bottom: 0;
padding: 0;
background: transparent;
&.sp-form-item-line {
padding: 10px 0;
align-items: center;
border-bottom: 1px solid #ececec;
}
&:last-child.sp-form-item-line {
border-bottom: 0;
}
.form-item-label {
.label {
font-size: 28px;
font-weight: 500;
color: #333;
}
}
.required {
top: 2px;
color: #df2f2f;
}
.form-item-control {
min-width: 0;
}
.at-input,
.picker-time {
margin: 0;
padding: 8px 0 10px;
border: 0;
border-radius: 0;
background: transparent;
min-height: 68px;
box-sizing: border-box;
&:after {
border: 0;
}
}
.picker-time {
.sp-cell__bd {
justify-content: flex-start;
padding: 0;
.placeholder {
color: #ccc;
}
}
.sp-cell__ft {
padding-right: 0;
}
}
.at-input {
margin-left: 0;
}
.at-input__input,
.picker-time text {
width: 100%;
font-size: 30px;
color: #222;
}
.placeholder,
.at-input .input-placeholder {
color: #c7c7c7;
}
.form-item-message {
left: 96px;
bottom: -30px;
font-size: 22px;
}
}
}
}

View File

@@ -41,7 +41,7 @@ function SpGoodsPrice(props) {
<View className='activity-wrap'>
<SpPrice className='activity-price' value={activityPrice} symbol='¥' />
{/* <Text className='activity-label'>¥{activityPrice.toFixed(2)}</Text> */}
<SpPrice size={24} lineThrough noSymbol={!isPurchase} value={price} />
<SpPrice size={24} lineThrough noSymbol value={price} />
{/* <SpPrice size={36} className='activity-price' value={activityPrice} /> */}
</View>
@@ -53,20 +53,6 @@ function SpGoodsPrice(props) {
{isNaN(activityPrice) && (
<View>
<View className='goods-price'>
{isPoint && price == 0 && <SpPoint className='sale-point' value={point} />}
{isPoint && price > 0 && (
<View className='point-plus-price-wrap'>
<SpPoint className='sale-point' value={point} />
<Text className='point-plus-price'>+</Text>
<SpPrice size={42} className='sale-price' value={price} />
</View>
)}
{!isPoint && <SpPrice size={42} className='sale-price' value={price} />}
{marketPrice > 0 && enMarketPrice && (
<SpPrice className='mkt-price' lineThrough value={marketPrice} />
)}
</View>
<View>
{info.memberPrice < info.price && enMemberPrice && isLogin && (
<View className='vip-price'>
<SpVipLabel content={$t('d59e9e9d.8fdd6f')} type='member' />
@@ -80,8 +66,8 @@ function SpGoodsPrice(props) {
(!info.svipPrice || info.vipPrice > info.svipPrice) &&
enSvipPrice && (
<View className='vip-price'>
<SpPrice value={info.vipPrice} />
<SpVipLabel content='VIP' type='vip' />
<SpPrice size={42} className='sale-price' value={info.vipPrice} />
</View>
)}
@@ -91,8 +77,8 @@ function SpGoodsPrice(props) {
info.svipPrice < info.memberPrice &&
enSvipPrice && (
<View className='svip-price'>
<SpPrice value={info.svipPrice} />
<SpVipLabel content='SVIP' type='svip' />
<SpPrice size={42} className='sale-price' value={info.svipPrice} />
</View>
)}
{isPoint && price == 0 && <SpPoint className='sale-point' value={point} />}

View File

@@ -46,9 +46,12 @@ const CustomNavigationHeader = memo((props) => {
'background-position': 'center',
'padding-top': `${gStatusBarHeight}px`
}
// 吸顶挂件 > 沉浸式滚动 50px 后显示的导航背景 > 默认导航背景
// 吸顶挂件 > 页面显式控制的导航背景 > 沉浸式滚动 50px 后显示的导航背景 > 默认导航背景
const headerBg =
statusBarBgColor ?? immersiveScrollRevealBgColor ?? pageConfig?.navigateBackgroundColor
statusBarBgColor ??
(navigateMantle ? navigateBackgroundColor : null) ??
immersiveScrollRevealBgColor ??
pageConfig?.navigateBackgroundColor
if (headerBg) {
style['background-color'] = headerBg
}

View File

@@ -572,6 +572,7 @@ function SpSkuSelect(props) {
<SpPrice value={curItem ? curItem.price : info.price}></SpPrice>
<SpPrice value={curItem ? curItem.marketPrice : info.marketPrice} lineThrough></SpPrice>
</View> */}
<View className='title'>{info.itemName}</View>
<SpGoodsPrice info={curItem || info} />
<View className='goods-sku-txt'>
{curItem ? ti('47ac6066.aa995b', [skuText]) : skuText}

View File

@@ -126,12 +126,6 @@ export default class Login extends Component {
}
}
componentWillUnmount() {
if (this._onLanguageChanged) {
i18n.off('languageChanged', this._onLanguageChanged)
}
}
componentDidShow() {
Taro.setNavigationBarTitle({ title: $t('3ca883d0.402d19') })
const { redirect } = this.$instance?.router?.params

View File

@@ -120,6 +120,7 @@ function EspierDetail(props) {
useTranslation()
const $instance = getCurrentInstance() || {}
const pageRef = useRef()
const scrollTopRef = useRef(0)
const { userInfo } = useSelector((state) => state.user)
const { colorPrimary, openRecommend } = useSelector((state) => state.sys)
@@ -468,6 +469,26 @@ function EspierDetail(props) {
})
}
const syncNavigateMantle = (scrollTop = 0) => {
const bannerHeight = imgHeightList[curImgIdx] || defaultImageHeight
const nextNavigateMantle = scrollTop > bannerHeight
setState((draft) => {
draft.navigateMantle = nextNavigateMantle
})
}
const handleGoodsScroll = (e) => {
const detail = e?.detail || {}
console.log('[espier-detail] handleGoodsScroll', detail)
scrollTopRef.current = detail.scrollTop || 0
pageRef.current?.handlePageScroll(detail)
syncNavigateMantle(detail.scrollTop || 0)
}
useEffect(() => {
syncNavigateMantle(scrollTopRef.current)
}, [curImgIdx, imgHeightList])
const setSwiperCss = (item) => {
return {
height: '100%',
@@ -542,7 +563,12 @@ function EspierDetail(props) {
}
>
<View className='page-item-espierdetail__header-bg'></View>
<ScrollView scrollY className='page-item-espierdetail-goods-contents' style='height: 100%;'>
<ScrollView
scrollY
className='page-item-espierdetail-goods-contents'
style='height: 100vh;'
onScroll={handleGoodsScroll}
>
{info && (
<View className='goods-contents'>
<View className='goods-pic-container'>
@@ -687,28 +713,6 @@ function EspierDetail(props) {
<View className='title'>{info.itemName}</View>
<View className='brief'>{info.brief}</View>
</View>
{(isWeixin || isAPP()) && (
// {(
<View className='btn-share-wrap'>
<View
onClick={async () => {
if (isAPP()) {
Taro.SAPPShare.open()
} else {
// await getUserInfoAuth()
setState((draft) => {
draft.sharePanelOpen = true
})
}
}}
>
<View className='btn-share'>
<Text className='iconfont icon-fenxiang-01'></Text>
<Text className='share-txt'>{$t('934ffec2.c31f48')}</Text>
</View>
</View>
</View>
)}
</View>
{info.isMedicine == 1 && info?.medicineData?.is_prescription == 1 && (
<View className='item-pre'>
@@ -756,44 +760,6 @@ function EspierDetail(props) {
</View>
)}
<View className='sku-block'>
{promotionPackage.length > 0 && (
<SpCell
title={$t('6c0659eb.f4fb0d')}
isLink
onClick={() => {
Taro.navigateTo({
url: `/subpages/marketing/package-list?id=${info.itemId}&distributor_id=${info.distributorId}`
})
// setState((draft) => {
// draft.packageOpen = true
// })
}}
>
<Text className='cell-value'>
{ti('6578cf7b.0fe3d0', [promotionPackage.length])}
</Text>
</SpCell>
)}
{promotionActivity.length > 0 && (
<SpCell
title={$t('dc155244.cd5666')}
isLink
onClick={() => {
setState((draft) => {
draft.promotionOpen = true
})
}}
>
{promotionActivity.map((item, index) => (
<View className='promotion-tag' key={`promotion-tag__${index}`}>
{item.promotionTag}
</View>
))}
</SpCell>
)}
</View>
{/* {info.itemParams.length > 0 && <View className='goods-params'>
<View className='params-hd'>商品参数</View>
<View className='params-bd'>