This commit is contained in:
liu
2026-08-06 16:37:04 +08:00
parent c613b520a9
commit 39b789154c
47 changed files with 3377 additions and 265 deletions
+145
View File
@@ -0,0 +1,145 @@
import { create } from 'zustand'
import Taro from '@tarojs/taro'
import {
addCartApi,
clearCartApi,
deleteCartItemApi,
getCartApi,
updateCartItemApi,
} from '@/services/cart'
import type { CartItem } from '@/types/cart'
/** 存储 key */
const STORAGE_KEY = 'cart_data'
/** 持久化的购物车快照(服务端为准,此处仅作展示缓存) */
interface StoredCart {
items: CartItem[]
totalCount: number
totalQuantity: string
totalAmount: string
}
/** 从本地存储恢复购物车快照 */
function loadFromStorage(): StoredCart | null {
try {
const stored = Taro.getStorageSync(STORAGE_KEY)
if (stored && Array.isArray(stored.items)) {
return stored as StoredCart
}
} catch {
// noop
}
return null
}
interface CartState {
items: CartItem[]
/** 总项数 */
totalCount: number
/** 可购项总数量(服务端字符串金额/数量) */
totalQuantity: string
/** 可购项总金额(服务端重算) */
totalAmount: string
/** 是否已从服务端同步过(避免每次展示都闪烁 loading) */
loaded: boolean
loading: boolean
/** 拉取购物车(以服务端为准,金额一律服务端重算) */
fetchCart: () => Promise<void>
/** 加购 */
addItem: (productId: number, quantity: number) => Promise<void>
/** 修改数量 */
updateQuantity: (id: number, quantity: number) => Promise<void>
/** 删除单项 */
removeItem: (id: number) => Promise<void>
/** 清空购物车 */
clearCart: () => Promise<void>
/** 下单成功后本地清空(不请求接口) */
clearLocal: () => void
}
/** 空的购物车快照 */
const EMPTY_SNAPSHOT = {
items: [] as CartItem[],
totalCount: 0,
totalQuantity: '0.00',
totalAmount: '0.00',
}
const useCartStore = create<CartState>((set, get) => {
const cached = loadFromStorage()
/** 持久化购物车快照 */
const persist = (
snapshot: Pick<CartState, 'items' | 'totalCount' | 'totalQuantity' | 'totalAmount'>,
) => {
try {
Taro.setStorageSync(STORAGE_KEY, snapshot)
} catch {
// storage 写入失败不阻塞
}
}
return {
...EMPTY_SNAPSHOT,
items: cached?.items ?? [],
totalCount: cached?.totalCount ?? 0,
totalQuantity: cached?.totalQuantity ?? '0.00',
totalAmount: cached?.totalAmount ?? '0.00',
loaded: false,
loading: false,
/** 拉取购物车(服务端为准) */
fetchCart: async () => {
if (get().loading) return
set({ loading: true })
try {
const res = await getCartApi()
const { items, total_count, total_quantity, total_amount } = res.data
const next = {
items,
totalCount: total_count,
totalQuantity: total_quantity,
totalAmount: total_amount,
}
set({ ...next, loaded: true })
persist(next)
} finally {
set({ loading: false })
}
},
/** 加购:服务端校验上架与等级价,成功后重新同步 */
addItem: async (productId, quantity) => {
await addCartApi({ product_id: productId, quantity })
await get().fetchCart()
},
/** 修改数量 */
updateQuantity: async (id, quantity) => {
await updateCartItemApi(id, quantity)
await get().fetchCart()
},
/** 删除单项 */
removeItem: async (id) => {
await deleteCartItemApi(id)
await get().fetchCart()
},
/** 清空购物车 */
clearCart: async () => {
await clearCartApi()
set({ ...EMPTY_SNAPSHOT, loaded: true })
persist(EMPTY_SNAPSHOT)
},
/** 下单成功后本地清空 */
clearLocal: () => {
set(EMPTY_SNAPSHOT)
persist(EMPTY_SNAPSHOT)
},
}
})
export default useCartStore