商品列表状态保存

This commit is contained in:
liu
2026-09-13 01:23:35 +08:00
parent 8f9b54ce76
commit 44e422febb
+62 -6
View File
@@ -5,6 +5,8 @@ import { Empty, Search } from '@antmjs/vantui'
import useCartStore from '@/stores/cart/useCartStore'
import { getCategoriesApi, getProductListApi } from '@/services/product'
import type { ProductListParams } from '@/services/product'
import { getCartApi } from '@/services/cart'
import { getToken } from '@/utils/request'
import { getProductCover } from '@/types/product'
import type { Category, Product, ProductCartPatch } from '@/types/product'
import CartBall from '@/components/CartBall'
@@ -42,6 +44,10 @@ export default function ProductPage() {
const reqSeqRef = useRef(0)
/** 是否有请求进行中(仅用于避免"加载更多"并发) */
const loadingRef = useRef(false)
/** 是否已完成首次加载(区分首次进入与从详情页返回) */
const hasLoadedRef = useRef(false)
/** 上次加载时的登录态(登录/登出后需整列刷新价格与购物车字段) */
const tokenRef = useRef<string | null>(null)
/** 当前选中二级分类所属的一级分类ID(用于父级高亮) */
const activeParentId = useMemo(() => {
@@ -131,8 +137,38 @@ export default function ProductPage() {
}
}, [])
/**
* 仅同步已加载商品的订货量(详情页加购返回时调用):
* 拉一次购物车,按 product_id 回写列表项的 cart_id/cart_quantity,
* 不重拉列表,保留滚动位置与已加载分页
*/
const syncCartFields = useCallback(async () => {
// 未登录无购物车(接口固定 401,会触发清登录态跳登录页),直接跳过
if (!getToken()) return
try {
const res = await getCartApi()
const itemMap = new Map(res.data.items.map(it => [it.product_id, it]))
setProducts(prev => {
let changed = false
const next = prev.map(p => {
const item = itemMap.get(p.id)
const cartId = item?.id ?? 0
const cartQty = item?.quantity ?? '0.00'
if ((p.cart_id ?? 0) === cartId && Number(p.cart_quantity ?? 0) === Number(cartQty)) {
return p
}
changed = true
return { ...p, cart_id: cartId, cart_quantity: cartQty }
})
return changed ? next : prev
})
} catch {
// 错误已由 request 层 toast
}
}, [])
useDidShow(() => {
// 处理首页搜索跳转带入的关键词
// 处理首页搜索跳转带入的关键词(switchTab 无法带参,经本地存储传递)
let pendingKeyword: string | null = null
try {
pendingKeyword = Taro.getStorageSync(PENDING_KEYWORD_KEY) || null
@@ -140,12 +176,32 @@ export default function ProductPage() {
} catch {
// noop
}
if (pendingKeyword) {
setInputKey(pendingKeyword)
setSearchKey(pendingKeyword)
// 首页分类跳转带入的分类(只读取,由 loadCategories 消费移除)
let pendingCategory: number | null = null
try {
pendingCategory = Taro.getStorageSync(PENDING_CATEGORY_KEY) || null
} catch {
// noop
}
const token = getToken()
/** 登录态变化(登录/登出/换账号):价格与购物车字段都变了,需整列刷新 */
const authChanged = hasLoadedRef.current && token !== tokenRef.current
if (!hasLoadedRef.current || pendingKeyword || pendingCategory || authChanged) {
// 首次进入 / 首页带参跳转 / 登录态变化:整列刷新
hasLoadedRef.current = true
tokenRef.current = token
if (pendingKeyword) {
setInputKey(pendingKeyword)
setSearchKey(pendingKeyword)
}
loadCategories()
fetchList(1, true, pendingKeyword ?? undefined)
} else {
// 从详情页等返回:保留列表与滚动位置,仅同步订货量
syncCartFields()
}
loadCategories()
fetchList(1, true, pendingKeyword ?? undefined)
})
/** 右侧列表触底加载(页面为固定布局不滚动,由 ScrollView 触发) */