mirror of
https://gitee.com/ShopeX/ECShopX_mobile-frontend
synced 2026-08-09 13:35:58 +08:00
fix: product detail scroll nav mantle, price/SKU header tweaks, and delivery UI cleanup
This commit is contained in:
@@ -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' && (
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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} />}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'>
|
||||
|
||||
Reference in New Issue
Block a user