diff --git a/.gitignore b/.gitignore index 47026650e..f7f9e38ba 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ openspec/ scripts/ .agent/ .codex/ -.cursor/commit-summary +.cursor/ diff --git a/src/api/dianwu.js b/src/api/dianwu.js index 0e3b2558e..d796ff87e 100644 --- a/src/api/dianwu.js +++ b/src/api/dianwu.js @@ -23,6 +23,11 @@ export function cartFastBuyAdd(params) { return req.post('/operator/cartfastbuyadd', params) } +// 移动收银选择会员后同步会话(POST body;company_id 由 req 拦截器注入,与 cartdataadd 一致) +export function memberReady(params) { + return req.post('/operator/member/ready', params) +} + // 扫码加入收银台 export function scanAddToCart(params) { return req.post('/operator/scancodeAddcart', params) diff --git a/src/pages/home/wgts/film/index.jsx b/src/pages/home/wgts/film/index.jsx index d28c7b527..b4c9db915 100644 --- a/src/pages/home/wgts/film/index.jsx +++ b/src/pages/home/wgts/film/index.jsx @@ -47,14 +47,6 @@ function WgtFilm(props) { })} style={styleNames(outerStyle)} > - {base.title && ( - - - {base.title} - {base.subtitle && {base.subtitle}} - - - )} ) diff --git a/src/pages/home/wgts/imghot-zone/index.scss b/src/pages/home/wgts/imghot-zone/index.scss index b8e4e75b9..7e92e8226 100644 --- a/src/pages/home/wgts/imghot-zone/index.scss +++ b/src/pages/home/wgts/imghot-zone/index.scss @@ -22,22 +22,29 @@ .wgt-imghot-zone__body-img-wrapper__vertical { width: 100%; height: 100%; - overflow-x: scroll; - scroll-snap-type: x mandatory; box-sizing: border-box; + white-space: nowrap; + + .wgt-imghot-zone__scroll-inner { + position: relative; + display: inline-block; + height: 100%; + vertical-align: top; + } .wgt-imghot-zone__body-img { height: 100% !important; - width: min-content; + width: max-content; + display: block; } } + .wgt-imghot-zone__body_zone { + position: absolute; + z-index: 1; + } + .wgt-imghot-zone__body { position: relative; - - &_zone { - position: absolute; - z-index: 99; - } } } \ No newline at end of file diff --git a/src/pages/purchase/auth.js b/src/pages/purchase/auth.js index 3eb021422..aa43ffbd2 100644 --- a/src/pages/purchase/auth.js +++ b/src/pages/purchase/auth.js @@ -230,14 +230,15 @@ function PurchaseAuth() { // 企业二维码扫码登录 const getQrcodeEid = async () => { try { - const { id, enterprise_id, code } = await entryLaunch.getRouteParams() + const { id, activity_id, enterprise_id, code } = await entryLaunch.getRouteParams() //亲友扫码 + let _id = id || activity_id || '' setState((draft) => { draft.invite_code = code || '' - draft.activity_id = id || '' + draft.activity_id = _id || '' draft.enterprise_id = enterprise_id || '' }) - return { id, enterprise_id, code } + return { id:_id, enterprise_id, code } } catch (error) { return {} } diff --git a/src/pages/recommend/detail.js b/src/pages/recommend/detail.js index ff9734025..117c2e14a 100644 --- a/src/pages/recommend/detail.js +++ b/src/pages/recommend/detail.js @@ -22,6 +22,7 @@ import './detail.scss' const initialState = { itemId: '', title: '', + summary: '', articleFocusNum: 0, content: [], updated: '', @@ -33,7 +34,7 @@ function GuideRecommendDetail(props) { const { i18n } = useTranslation() const $instance = getCurrentInstance() || {} const [state, setState] = useImmer(initialState) - const { img, shareImageUrl, itemId, title, content, articleFocusNum, updated } = state + const { img, shareImageUrl, itemId, title, summary, content, articleFocusNum, updated } = state const { userInfo } = useSelector((state) => state.guide) const router = useRouter() @@ -88,7 +89,7 @@ function GuideRecommendDetail(props) { }) } } - const { itemId, title, articleFocusNum, content, updated, isPraise, articlePraiseNum } = pickBy( + const { itemId, title, summary, articleFocusNum, content, updated, isPraise, articlePraiseNum } = pickBy( res, doc.article.ARTICLE_ITEM ) @@ -96,6 +97,7 @@ function GuideRecommendDetail(props) { setState((draft) => { draft.itemId = itemId draft.title = title + draft.summary = summary draft.articleFocusNum = articleFocusNum draft.content = content draft.updated = updated @@ -162,7 +164,10 @@ function GuideRecommendDetail(props) { > - {title} + + {title} + {summary ? {summary} : null} + {updated} diff --git a/src/pages/recommend/detail.scss b/src/pages/recommend/detail.scss index 8e38c957d..977a7fb19 100644 --- a/src/pages/recommend/detail.scss +++ b/src/pages/recommend/detail.scss @@ -13,10 +13,19 @@ .article-bd { background: #fff; } + .article-title-row { + display: flex; + flex-direction: column; + gap: 8px; + } .article-title { font-size: 40px; color: #222; } + .article-summary { + font-size: 28px; + color: #666; + } .article-info { margin-top: 16px; } diff --git a/src/subpages/dianwu/cashier.js b/src/subpages/dianwu/cashier.js index 1d26b223e..15a5c411f 100644 --- a/src/subpages/dianwu/cashier.js +++ b/src/subpages/dianwu/cashier.js @@ -24,7 +24,7 @@ import { SpInput as AtInput } from '@/components' import { useDianWuLogin, useDebounce } from '@/hooks' -import { styleNames, pickBy, showToast, classNames, validate } from '@/utils' +import { styleNames, pickBy, showToast, classNames } from '@/utils' import { useTranslation, $t, i18n, ti } from '@/i18n' import { selectMember } from '@/store/slices/dianwu' import CompGoods from './comps/comp-goods' @@ -33,6 +33,7 @@ import CompGoodsPrice from './comps/comp-goods-price' import CompTabbar from './comps/comp-tabbar' import CompDianwuSelectMember from './comps/comp-dianwu-select-member' import CompDianwuPlatformOrder from './comps/comp-dianwu-platform-order' +import { isDianwuGoodsDisabled, resolveDianwuGoodsActions } from './utils/dianwu-goods-action' import './cashier.scss' const initialState = { @@ -43,7 +44,8 @@ const initialState = { searchResultLayout: false, addUserCurtain: false, isCameraOpend: false, - platformOrderItem: null + platformOrderItem: null, + isPlatformStoreBuy: false } function DianWuCashier() { @@ -57,7 +59,8 @@ function DianWuCashier() { searchGoodsList, isCameraOpend, distributor_id, - platformOrderItem + platformOrderItem, + isPlatformStoreBuy } = state const pageRef = useRef() const getCashierListRef = useRef(null) @@ -113,7 +116,7 @@ function DianWuCashier() { const handleSearchByKeyword = async (keywords) => { Taro.showLoading({ title: '' }) - const { list: goodsList } = await dianwuApi.goodsItems({ + const { list: goodsList, is_platform_store_buy } = await dianwuApi.goodsItems({ page: 1, pageSize: 100, keywords, @@ -123,6 +126,9 @@ function DianWuCashier() { setState((draft) => { draft.searchGoodsList = pickBy(goodsList, doc.dianwu.GOODS_ITEM) + if (is_platform_store_buy != null) { + draft.isPlatformStoreBuy = !!is_platform_store_buy + } // draft.searchMemberList = pickBy(memberList, doc.dianwu.MEMBER_ITEM) draft.searchResultLayout = true }) @@ -268,43 +274,6 @@ function DianWuCashier() { } } - const handleCreateMember = async () => { - const res = await dianwuApi.createMember({ mobile }) - const newUser = pickBy(res, doc.dianwu.CREATE_MEMBER_ITEM) - const userInfo = await dianwuApi.getMemberByUserId({ user_id: newUser.userId }) - const { couponNum, point, vipDiscount } = pickBy(userInfo, doc.dianwu.MEMBER_INFO) - dispatch( - selectMember({ - ...newUser, - couponNum, - point, - vipDiscount - }) - ) - setState((draft) => { - draft.addUserCurtain = false - }) - } - - const onChangeMobile = (e) => { - setState((draft) => { - draft.mobile = e - }) - } - - const handleConfirm = async () => { - if (validate.isMobileNum(mobile)) { - const { list } = await dianwuApi.getMembers({ - mobile - }) - setState((draft) => { - draft.searchMemberResult = pickBy(list, doc.dianwu.MEMBER_ITEM) - }) - } else { - showToast($t('7187dbd0.a32ab5')) - } - } - const onChangePlus = async (item, idx, index) => { const _num = parseInt(item.num) + 1 if (_num > item.store) { @@ -657,35 +626,43 @@ function DianWuCashier() { }} > - {searchGoodsList.map((item, index) => ( - - - {item.store > 0 && item.isTotalStore === true && ( - - {$t('7187dbd0.cd2240')} - - )} + {searchGoodsList.map((item, index) => { + const actions = resolveDianwuGoodsActions(item, isPlatformStoreBuy) + return ( + + + {actions.addToCashier && ( + + {$t('7187dbd0.cd2240')} + + )} - {item.store == 0 && item.platformStore > 0 && ( - { - setState((draft) => { - draft.platformOrderItem = item - }) - }} - > - 立即下单 - - )} - - - ))} + {actions.buyNow && ( + { + setState((draft) => { + draft.platformOrderItem = item + }) + }} + > + {$t('8cac8565.887eb6')} + + )} + + + ) + })} diff --git a/src/subpages/dianwu/cashier.scss b/src/subpages/dianwu/cashier.scss index ff93e670f..d9c31758b 100644 --- a/src/subpages/dianwu/cashier.scss +++ b/src/subpages/dianwu/cashier.scss @@ -542,6 +542,9 @@ &:not(:last-child) { margin-bottom: 30px; } + &.item-disabled { + opacity: 0.6; + } .at-button { display: inline-block; min-width: 120px; diff --git a/src/subpages/dianwu/comps/comp-dianwu-select-member.js b/src/subpages/dianwu/comps/comp-dianwu-select-member.js index b52876e6c..15fe7da9e 100644 --- a/src/subpages/dianwu/comps/comp-dianwu-select-member.js +++ b/src/subpages/dianwu/comps/comp-dianwu-select-member.js @@ -54,6 +54,17 @@ function CompDianwuSelectMember({ open, onClose, onAfterSelect, distributor_id } const handleSelectMember = async () => { const [item] = searchMemberResult const userInfo = await dianwuApi.getMemberByUserId({ user_id: item.userId }) + try { + await dianwuApi.memberReady({ + user_id: item.userId, + distributor_id, + showError: false + }) + } catch (e) { + const msg = + e?.message || e?.res?.data?.data?.message || $t('09e29d60.g3q6mc') + showToast(msg) + } const { couponNum, point, vipDiscount } = pickBy(userInfo, doc.dianwu.MEMBER_INFO) dispatch( selectMember({ diff --git a/src/subpages/dianwu/comps/comp-goods.js b/src/subpages/dianwu/comps/comp-goods.js index 47a0335be..ff65c1e94 100644 --- a/src/subpages/dianwu/comps/comp-goods.js +++ b/src/subpages/dianwu/comps/comp-goods.js @@ -6,19 +6,19 @@ import React from 'react' import { View, Text } from '@tarojs/components' import { SpImage } from '@/components' import { useTranslation, $t, ti } from '@/i18n' +import { resolveDianwuGoodsDisplay } from '../utils/dianwu-goods-action' import CompGoodsPrice from './comp-goods-price' import './comp-goods.scss' function CompGoods(props) { useTranslation() - const { children, info } = props + const { children, info, isPlatformStoreBuy = false } = props if (!info) { return null } - const showStore = info.isTotalStore === true - const showPlatformStore = info.platformStore != null - const showInventory = showStore || showPlatformStore + const display = resolveDianwuGoodsDisplay(info, isPlatformStoreBuy) + const showInventory = display.showStore || display.showCloud return ( @@ -34,26 +34,15 @@ function CompGoods(props) { {info.name} {info.itemSpecDesc && {info.itemSpecDesc}} - {/* - - - - - - - - - - */} {showInventory && ( {$t('982aa174.b008bd')} - {showStore && {ti('982aa174.285600', [info.store])}} - {showStore && showPlatformStore && | } - {showPlatformStore && {ti('982aa174.f36d41', [info.platformStore])}} + {display.showStore && {ti('982aa174.285600', [display.storeValue])}} + {display.showStore && display.showCloud && | } + {display.showCloud && {ti('982aa174.f36d41', [display.cloudValue])}} )} {info.barcode && ( @@ -64,12 +53,6 @@ function CompGoods(props) { )} {children} - {/* - - */} - {/* - 缺货 - */} diff --git a/src/subpages/dianwu/list.js b/src/subpages/dianwu/list.js index 6058abdf1..faac9c999 100644 --- a/src/subpages/dianwu/list.js +++ b/src/subpages/dianwu/list.js @@ -16,28 +16,21 @@ import { useNavigation } from '@/hooks' import CompGoods from './comps/comp-goods' import CompTabbar from './comps/comp-tabbar' import CompDianwuPlatformOrder from './comps/comp-dianwu-platform-order' +import { isDianwuGoodsDisabled, resolveDianwuGoodsActions } from './utils/dianwu-goods-action' import './list.scss' -/** 无库存不可加购:门店与云仓均为 0 才禁用;未返回 platform_store 时仅按门店库存判断(与历史行为一致) */ -function isDianwuListGoodsDisabled(item) { - if (item.store != 0) return false - const ps = item.platformStore - if (ps == null || ps === '') return true - return ps == 0 -} - const initialState = { keywords: '', list: [], - current: 0, cartList: [], - platformOrderItem: null + platformOrderItem: null, + isPlatformStoreBuy: false } function DianWuList() { useTranslation() const [state, setState] = useImmer(initialState) - const { keywords, typeList, current, list, cartList, platformOrderItem } = state + const { keywords, list, cartList, platformOrderItem, isPlatformStoreBuy } = state const goodsRef = useRef() const $instance = getCurrentInstance() || {} const { distributor_id } = $instance?.router?.params @@ -72,13 +65,16 @@ function DianWuList() { } Taro.showLoading({ title: '' }) try { - const { list: _list, total_count } = await dianwuApi.goodsItems(params) + const { list: _list, total_count, is_platform_store_buy } = await dianwuApi.goodsItems(params) setState((draft) => { // 首屏请求需清空分页缓存,否则搜索无结果时仍保留上一关键词的多页数据 if (pageIndex === 1) { draft.list = [] } + if (pageIndex === 1 && is_platform_store_buy != null) { + draft.isPlatformStoreBuy = !!is_platform_store_buy + } draft.list[pageIndex - 1] = pickBy(_list, doc.dianwu.GOODS_ITEM) }) @@ -153,40 +149,43 @@ function DianWuList() { {list.map((items, idx) => { - return items.map((item, sidx) => ( - - - {item.store > 0 && item.isTotalStore === true && ( - - {$t('8cac8565.cd2240')} - - )} + return items.map((item, sidx) => { + const actions = resolveDianwuGoodsActions(item, isPlatformStoreBuy) + return ( + + + {actions.addToCashier && ( + + {$t('8cac8565.cd2240')} + + )} - {item.store == 0 && item.platformStore > 0 && ( - { - setState((draft) => { - draft.platformOrderItem = item - }) - }} - > - {$t('8cac8565.887eb6')} - - )} - - - )) + {actions.buyNow && ( + { + setState((draft) => { + draft.platformOrderItem = item + }) + }} + > + {$t('8cac8565.887eb6')} + + )} + + + ) + }) })} diff --git a/src/subpages/dianwu/utils/dianwu-goods-action.js b/src/subpages/dianwu/utils/dianwu-goods-action.js new file mode 100644 index 000000000..4a562d475 --- /dev/null +++ b/src/subpages/dianwu/utils/dianwu-goods-action.js @@ -0,0 +1,107 @@ +/** + * Copyright © ShopeX (http://www.shopex.cn). All rights reserved. + * See LICENSE file for license details. + */ + +/** 商品开启店铺库存(店铺发货) */ +export function isDianwuStoreInventoryEnabled(item) { + const v = item?.isTotalStore + return v === false || v === 0 || v === '0' || v === 'false' +} + +function toStockNum(val) { + const n = Number(val) + return Number.isFinite(n) ? n : 0 +} + +function resolvePlatformStockNum(item) { + if (item?.platformStore == null || item.platformStore === '') { + return null + } + return toStockNum(item.platformStore) +} + +/** + * @param {object} item pickBy(GOODS_ITEM) + * @param {boolean} isPlatformStoreBuy 门店 is_platform_store_buy + */ +export function resolveDianwuGoodsDisplay(item, isPlatformStoreBuy) { + const storeStock = toStockNum(item?.store) + const platformStock = resolvePlatformStockNum(item) + const storeInventoryEnabled = isDianwuStoreInventoryEnabled(item) + + if (isPlatformStoreBuy) { + if (storeInventoryEnabled) { + return { + showStore: true, + showCloud: platformStock != null, + storeValue: storeStock, + cloudValue: platformStock != null ? platformStock : 0 + } + } + return { + showStore: false, + showCloud: true, + storeValue: 0, + cloudValue: platformStock != null ? platformStock : storeStock + } + } + + if (storeInventoryEnabled) { + return { + showStore: true, + showCloud: false, + storeValue: storeStock, + cloudValue: 0 + } + } + + return { + showStore: false, + showCloud: true, + storeValue: 0, + cloudValue: storeStock + } +} + +/** + * @param {object} item + * @param {boolean} isPlatformStoreBuy + */ +export function resolveDianwuGoodsActions(item, isPlatformStoreBuy) { + const storeStock = toStockNum(item?.store) + const platformStock = resolvePlatformStockNum(item) + const storeInventoryEnabled = isDianwuStoreInventoryEnabled(item) + + let addToCashier = false + let buyNow = false + + if (isPlatformStoreBuy) { + if (storeInventoryEnabled) { + if (storeStock > 0) { + addToCashier = true + } else if (platformStock != null && platformStock > 0) { + buyNow = true + } + } else if (platformStock != null && platformStock > 0) { + buyNow = true + } + } else if (storeInventoryEnabled) { + if (storeStock > 0) { + addToCashier = true + } + } else if (storeStock > 0) { + buyNow = true + } + + return { addToCashier, buyNow } +} + +/** + * @param {object} item + * @param {boolean} isPlatformStoreBuy + */ +export function isDianwuGoodsDisabled(item, isPlatformStoreBuy) { + const { addToCashier, buyNow } = resolveDianwuGoodsActions(item, isPlatformStoreBuy) + return !addToCashier && !buyNow +} diff --git a/src/subpages/guide/components/wgts/film.js b/src/subpages/guide/components/wgts/film.js index 5137f68c7..126f76389 100644 --- a/src/subpages/guide/components/wgts/film.js +++ b/src/subpages/guide/components/wgts/film.js @@ -77,7 +77,7 @@ export default class WgtFilm extends Component { const { width, height, objectFit } = this.resolveSize(config, screenWidth, base) return ( - + {base.title && ( {base.title} diff --git a/src/subpages/guide/components/wgts/film.scss b/src/subpages/guide/components/wgts/film.scss index 1bef0167c..916e214ed 100644 --- a/src/subpages/guide/components/wgts/film.scss +++ b/src/subpages/guide/components/wgts/film.scss @@ -2,34 +2,13 @@ * Copyright © ShopeX (http://www.shopex.cn). All rights reserved. * See LICENSE file for license details. */ -.wgt-film { - .wgts { - &__header { - // padding: 45px 30px 30px; - padding: 15px 30px 30px; - } - &__title { - line-height: 18px; - letter-spacing: 1px; - color: #000000; - font-size: 32px; - } - &__subtitle { - font-size: 22px; - line-height: 18px; - margin-top: 22px; - color: #8a8a8a; - } - &__wrap { - position: relative; - } - } -} +.wgt-guide-film { + .flim-video { + width: 100%; + display: block; -.flim-video { - width: 100%; - display: block; - &.is-fullscreen { - position: absolute; + &.is-fullscreen { + position: absolute; + } } -} +} \ No newline at end of file diff --git a/src/subpages/i18n/locales/ar.json b/src/subpages/i18n/locales/ar.json index 99c6a6462..58cce32aa 100644 --- a/src/subpages/i18n/locales/ar.json +++ b/src/subpages/i18n/locales/ar.json @@ -2932,6 +2932,7 @@ "09e29d60.625fb2": "إلغاء", "09e29d60.3a6fa4": "اختيار عضو", "09e29d60.9fd000": "إنشاء الآن", + "09e29d60.g3q6mc": "فشل مزامنة جلسة العضو", "eac57497.887eb6": "اطلب الآن", "eac57497.0bf60b": "الكمية", "eac57497.5591b7": "${0} متاح في المستودع السحابي", diff --git a/src/subpages/i18n/locales/en.json b/src/subpages/i18n/locales/en.json index 025e59f86..560865ab3 100644 --- a/src/subpages/i18n/locales/en.json +++ b/src/subpages/i18n/locales/en.json @@ -2932,6 +2932,7 @@ "09e29d60.625fb2": "Cancel", "09e29d60.3a6fa4": "Select member", "09e29d60.9fd000": "Create now", + "09e29d60.g3q6mc": "Failed to sync member session", "eac57497.887eb6": "Order now", "eac57497.0bf60b": "Quantity", "eac57497.5591b7": "${0} available in cloud warehouse", diff --git a/src/subpages/i18n/locales/zhcn.json b/src/subpages/i18n/locales/zhcn.json index 987de0b40..21a4ac4be 100644 --- a/src/subpages/i18n/locales/zhcn.json +++ b/src/subpages/i18n/locales/zhcn.json @@ -2936,6 +2936,7 @@ "09e29d60.625fb2": "取消", "09e29d60.3a6fa4": "选择会员", "09e29d60.9fd000": "立即创建", + "09e29d60.g3q6mc": "会员就绪同步失败", "eac57497.887eb6": "立即下单", "eac57497.0bf60b": "数量", "eac57497.5591b7": "云仓可售 ${0} 件", diff --git a/src/subpages/member/point-detail.scss b/src/subpages/member/point-detail.scss index 7f716e19c..3ef95e628 100644 --- a/src/subpages/member/point-detail.scss +++ b/src/subpages/member/point-detail.scss @@ -5,25 +5,24 @@ .page-point-detail { overflow-x: hidden; .point-detail-hd { - width: 850px; + box-sizing: border-box; + width: 100%; height: 300px; background: var(--color-primary); - border-radius: 0 0 150px 150px; + border-radius: 0 0 80px 80px; position: relative; - left: 50%; - transform: translateX(-50%); } .point-info { - width: 710px; + box-sizing: border-box; + left: 20px; + right: 20px; + width: auto; height: 190px; background: #ffffff; border-radius: 16px; position: absolute; - left: 50%; - transform: translateX(-50%); bottom: -80px; padding: 30px 40px; - box-sizing: border-box; &-hd { display: flex; justify-content: space-between; diff --git a/src/subpages/pointshop/comps/comp-deliver.scss b/src/subpages/pointshop/comps/comp-deliver.scss index ce1dbef9c..764b5e0bc 100644 --- a/src/subpages/pointshop/comps/comp-deliver.scss +++ b/src/subpages/pointshop/comps/comp-deliver.scss @@ -11,21 +11,34 @@ display: flex; justify-content: flex-end; align-items: center; + box-sizing: border-box; + width: 100%; + padding: 14px 16px 0; } .switch-tab { display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 8px; + max-width: 100%; background: #f5f5f5; border-radius: 50px; - margin: 14px 16px 10px 20px; + margin: 0 0 16px; + padding: 4px; font-size: 24px; + box-sizing: border-box; .switch-item { - // padding: 0px 30px; - width: 160px; + width: auto; + min-width: 100px; + max-width: 100%; + padding: 0 24px; text-align: center; height: 65px; line-height: 65px; color: #666; border-radius: 50px; + white-space: nowrap; + box-sizing: border-box; &.active { font-weight: bold; color: #fff; @@ -34,6 +47,11 @@ } } } + .address-picker { + .address { + padding-top: 0; + } + } .address-module { background: #fff; padding: 12px 30px; diff --git a/src/subpages/pointshop/espier-checkout.js b/src/subpages/pointshop/espier-checkout.js index 734493f6f..1cfb3fe35 100644 --- a/src/subpages/pointshop/espier-checkout.js +++ b/src/subpages/pointshop/espier-checkout.js @@ -25,7 +25,6 @@ import { pickBy, authSetting, showToast, - isWeb, isAPP, isWxWeb, log, @@ -48,7 +47,7 @@ function PointShopEspierCheckout() { const { i18n } = useTranslation() const $instance = getCurrentInstance() || {} const { updateAddress } = useLocation() - const { isLogin, isNewUser, getUserInfoAuth } = useLogin({ + const { isLogin } = useLogin({ autoLogin: true, loginSuccess: () => { updateAddress() @@ -125,12 +124,13 @@ function PointShopEspierCheckout() { }, [isLogin]) useEffect(() => { - if (isNewUser) { + const token = S?.getAuthToken() + if (!token) { Taro.redirectTo({ url: `/subpages/member/index` }) } - }, [isNewUser]) + }, []) useEffect(() => { console.log( @@ -638,7 +638,12 @@ function PointShopEspierCheckout() { } return ( - + d.label)] + } + return [unlimitedLabel] +} + function displayPickerLabel(value) { if (value === PLACEHOLDER_PROVINCE) return $t('9e660622.19a4c5') if (value === PLACEHOLDER_CITY) return $t('9e660622.0c1085') @@ -32,12 +39,114 @@ function displayPickerLabel(value) { return value } +/** 独立子组件:避免列表刷新导致 Picker value 被重置、滚动回弹 */ +const LocationRegionPicker = memo(function LocationRegionPicker({ + provinceLabel, + cityLabel, + districtLabel, + onConfirm +}) { + useTranslation() + const [areaData, setAreaData] = useState([]) + const [areaList, setAreaList] = useState([[], [], []]) + const [multiIndex, setMultiIndex] = useState([0, 0, 0]) + + const loadArea = useCallback(async () => { + try { + const res = await api.member.areaList() + if (!res?.length) return + + const unlimitedLabel = $t('9e660622.8441b3') + const provinces = res.map((item) => item.label) + const firstCity = res[0]?.children?.[0] + const cities = res[0]?.children?.map((c) => c.label) || [''] + const districts = getDistrictLabels(firstCity, unlimitedLabel) + + setAreaData(res) + setAreaList([provinces, cities.length ? cities : [''], districts]) + setMultiIndex([0, 0, 0]) + } catch (e) { + console.error('loadArea error', e) + } + }, []) + + useEffect(() => { + loadArea() + }, [loadArea]) + + useEffect(() => { + const onLanguageChanged = () => { + loadArea() + } + i18n.on('languageChanged', onLanguageChanged) + return () => i18n.off('languageChanged', onLanguageChanged) + }, [loadArea]) + + const onColumnChange = (e) => { + const { column, value } = e.detail + const unlimitedLabel = $t('9e660622.8441b3') + + if (column === 0) { + const province = areaData[value] + const cities = province?.children?.map((c) => c.label) || [''] + const districts = getDistrictLabels(province?.children?.[0], unlimitedLabel) + setMultiIndex([value, 0, 0]) + setAreaList([areaList[0], cities.length ? cities : [''], districts]) + } else if (column === 1) { + const city = areaData[multiIndex[0]]?.children?.[value] + const districts = getDistrictLabels(city, unlimitedLabel) + setMultiIndex([multiIndex[0], value, 0]) + setAreaList([areaList[0], areaList[1], districts]) + } else { + setMultiIndex([multiIndex[0], multiIndex[1], value]) + } + } + + const onChange = (e) => { + const [provinceIndex, cityIndex, districtIndex] = e.detail.value || [0, 0, 0] + const province = areaData[provinceIndex] + const city = province?.children?.[cityIndex] + const district = districtIndex === 0 ? null : city?.children?.[districtIndex - 1] + + setMultiIndex([provinceIndex, cityIndex, districtIndex]) + onConfirm({ + province: province?.label || PLACEHOLDER_PROVINCE, + city: city?.label || PLACEHOLDER_CITY, + district: + districtIndex === 0 ? DISTRICT_UNLIMITED : district?.label || PLACEHOLDER_DISTRICT + }) + } + + return ( + + + + {displayPickerLabel(provinceLabel)} + + + + {displayPickerLabel(cityLabel)} + + + + {displayPickerLabel(districtLabel)} + + + + + ) +}) + const initialState = { shopList: [], keyword: '', - locationList: [], - locationRange: [[], [], []], - locationValue: [0, 0, 0], selectedProvince: PLACEHOLDER_PROVINCE, selectedCity: PLACEHOLDER_CITY, selectedDistrict: PLACEHOLDER_DISTRICT, @@ -62,8 +171,6 @@ function NearbyList() { const { shopList, keyword, - locationRange, - locationValue, selectedProvince, selectedCity, selectedDistrict, @@ -125,7 +232,6 @@ function NearbyList() { useEffect(() => { const onLanguageChanged = () => { setNavigationBarTitle($t('678873b3.9f3102')) - initLocationPicker() } onLanguageChanged() i18n.on('languageChanged', onLanguageChanged) @@ -133,7 +239,6 @@ function NearbyList() { }, [setNavigationBarTitle]) useEffect(() => { - initLocationPicker() getLocationInfo() fetchCategoryList() }, []) @@ -158,28 +263,6 @@ function NearbyList() { } }, [refresh]) - const initLocationPicker = async () => { - try { - const res = await api.member.areaList() - if (!res || !Array.isArray(res)) return - - const provinces = res.map((item) => item.label) - const cities = res[0]?.children ? res[0].children.map((c) => c.label) : [] - const unlimitedLabel = $t('9e660622.8441b3') - const districts = res[0]?.children?.[0]?.children - ? [unlimitedLabel, ...res[0].children[0].children.map((d) => d.label)] - : [unlimitedLabel] - - setState((draft) => { - draft.locationList = res - draft.locationRange = [provinces, cities, districts] - draft.locationValue = [0, 0, 0] - }) - } catch (e) { - console.error('initLocationPicker error', e) - } - } - const getLocationInfo = async () => { await entryLaunch.isOpenPosition(async (res) => { bumpListFetchGen() @@ -361,49 +444,16 @@ function NearbyList() { return category?.category_name || $t('9e660622.a48948') } - const onColumnChange = (e) => { - const { column, value } = e.detail + const handleLocationConfirm = useCallback((selection) => { + bumpListFetchGen() setState((draft) => { - if (column === 0) { - draft.locationValue = [value, 0, 0] - const currentProvince = draft.locationList[value] - const cities = currentProvince?.children ? currentProvince.children.map((c) => c.label) : [] - const unlimitedLabel = $t('9e660622.8441b3') - const districts = currentProvince?.children?.[0]?.children - ? [unlimitedLabel, ...currentProvince.children[0].children.map((d) => d.label)] - : [unlimitedLabel] - draft.locationRange = [draft.locationRange[0], cities, districts] - } else if (column === 1) { - draft.locationValue[1] = value - draft.locationValue[2] = 0 - const currentProvince = draft.locationList[draft.locationValue[0]] - const currentCity = currentProvince?.children?.[value] - const unlimitedLabel = $t('9e660622.8441b3') - const districts = currentCity?.children - ? [unlimitedLabel, ...currentCity.children.map((d) => d.label)] - : [unlimitedLabel] - draft.locationRange[2] = districts - } else if (column === 2) { - draft.locationValue[2] = value - } + draft.selectedProvince = selection.province + draft.selectedCity = selection.city + draft.selectedDistrict = selection.district + draft.shopList = [] + draft.refresh = true }) - } - - const onLocationChange = (e) => { - const [provinceIndex, cityIndex, districtIndex] = e.detail.value || [0, 0, 0] - setState((draft) => { - const province = draft.locationList[provinceIndex] - const city = province?.children?.[cityIndex] - // 区列表第一项是"不限",所以索引需要减1 - const district = districtIndex === 0 ? null : city?.children?.[districtIndex - 1] - draft.selectedProvince = province?.label || PLACEHOLDER_PROVINCE - draft.selectedCity = city?.label || PLACEHOLDER_CITY - draft.selectedDistrict = - districtIndex === 0 ? DISTRICT_UNLIMITED : district?.label || PLACEHOLDER_DISTRICT - draft.locationValue = [provinceIndex, cityIndex, districtIndex] - }) - refreshList() - } + }, []) const handleNavigation = (e, info) => { e.stopPropagation() @@ -479,7 +529,7 @@ function NearbyList() { /> {/* 搜索筛选区域 */} - + {/* 搜索框和门店类型 */} @@ -550,28 +600,12 @@ function NearbyList() { {/* 省市区选择 */} - - - - {displayPickerLabel(selectedProvince)} - - - - {displayPickerLabel(selectedCity)} - - - - {displayPickerLabel(selectedDistrict)} - - - - + diff --git a/src/subpages/store/nearby-list.scss b/src/subpages/store/nearby-list.scss index fe79af287..4ca55efc1 100644 --- a/src/subpages/store/nearby-list.scss +++ b/src/subpages/store/nearby-list.scss @@ -26,6 +26,7 @@ .filter-section { background-color: #f3f3f3; padding: 40px 36px 24px; + flex-shrink: 0; border-radius: 16px 16px 0 0; display: flex; @@ -34,6 +35,7 @@ .search-row-wrapper { position: relative; + z-index: 200; } .search-row { @@ -97,6 +99,9 @@ } .location-row { + position: relative; + flex-shrink: 0; + .location-picker { display: flex; justify-content: space-between; @@ -104,19 +109,36 @@ padding: 0 16px; .picker-item { + flex: 1; + min-width: 0; display: flex; align-items: center; + justify-content: center; gap: 8px; font-size: 24px; color: #000; + .picker-item-label { + flex: 1; + min-width: 0; + @include multi-ellipsis(1); + } + .arrow-icon { + flex-shrink: 0; font-size: 10px; color: #444; } } } } + + &.is-store-type-open { + .location-row { + visibility: hidden; + pointer-events: none; + } + } } // 门店列表滚动区域 @@ -288,7 +310,7 @@ right: -36px; width: calc(100% + 72px); background-color: #fff; - z-index: 100; + z-index: 201; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); .dropdown-content {