init
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user