feat(购物页面): 已完成购物页面的调整条数米数功能并计算预估金额

This commit is contained in:
xuan 2022-10-25 15:27:07 +08:00
parent da5d41cfaa
commit a2697b14af
10 changed files with 263 additions and 101 deletions

1
global.d.ts vendored
View File

@ -20,4 +20,5 @@ declare namespace NodeJS {
declare const CURRENT_VERSION: string declare const CURRENT_VERSION: string
declare const CURRENT_GITHASH: string declare const CURRENT_GITHASH: string
declare const CURRENT_ENV: string declare const CURRENT_ENV: string
declare const CURRENT_BASE_URL: string

View File

@ -1,4 +1,4 @@
import { useRequest } from "@/use/useHttp" import { useRequest } from '@/use/useHttp'
/** /**
* *
* @returns * @returns
@ -13,19 +13,29 @@ export const ShoppingCartUpdateApi = () => {
* *
* @returns * @returns
*/ */
export const ShoppingCartDeleteApi = () => { export const ShoppingCartDeleteApi = () => {
return useRequest({ return useRequest({
url: `/v2/mp/shoppingCart/productColor`, url: `/v2/mp/shoppingCart/productColor`,
method: "delete", method: 'delete',
}) })
} }
/** /**
* *
* @returns * @returns
*/ */
export const ShoppingCartListApi = () => { export const ShoppingCartListApi = () => {
return useRequest({ return useRequest({
url: `/v2/mp/shoppingCart/productColor`, url: `/v2/mp/shoppingCart/productColor`,
method: "get", method: 'get',
}) })
}
/**
*
* @returns
*/
export const AdjestShoppingCartApi = () => {
return useRequest({
url: `/v2/mp/shoppingCart/productColor/list`,
method: 'post',
})
} }

View File

@ -0,0 +1,16 @@
购物页面的 组件结构
> Shopping
>
> > ShoppingProvider
> >
> > > ShoppingCartContainer
> > >
> > > > ShoppingCartItem
> > > >
> > > > > GoodsList
> > > > >
> > > > > > ColorKindItem
还用到发布订阅者模式 通知祖先组件请求接口更新数据

View File

@ -8,18 +8,23 @@ import { debounce } from '@/common/util'
import { formatImgUrl, formatPriceDiv } from '@/common/format' import { formatImgUrl, formatPriceDiv } from '@/common/format'
import { EnumSaleMode } from '@/common/Enumerate' import { EnumSaleMode } from '@/common/Enumerate'
import { selectList } from '../../config' import { selectList } from '../../config'
import { AdjestShoppingCartApi } from '@/api/shopping/index'
import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context' import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
import { ShoppingStore } from '../../context/shoppingStore'
type PropsType = { type PropsType = {
state?: Goods state?: {
multipleSelection: Goods[]
Observer: ShoppingStore
}
purchaserId: number purchaserId: number
itemData: Record<string, any> & object itemData: Record<string, any> & object
orderType: EnumSaleMode orderType: EnumSaleMode
} }
let ColorKindItem: FC<PropsType> = props => { let ColorKindItem: FC<PropsType> = props => {
console.log('Rerender component: ColorKindItem') const { state, purchaserId, itemData, orderType = EnumSaleMode.Bulk } = props
const { state: multipleSelection, purchaserId, itemData, orderType = EnumSaleMode.Bulk } = props console.log('Rerender component: ColorKindItem', itemData.id)
const dispatch = useShoppingDispatch() const dispatch = useShoppingDispatch()
// console.log('checked==>', checked) // console.log('checked==>', checked)
@ -43,12 +48,12 @@ let ColorKindItem: FC<PropsType> = props => {
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: { data: {
purchaserId: purchaserId, purchaserId: purchaserId,
multipleSelection: { ...multipleSelection, [itemData.id]: itemData }, multipleSelection: { ...state?.multipleSelection, [itemData.id]: itemData },
}, },
}) })
} }
const handleClose = () => { const handleClose = () => {
const temp = multipleSelection const temp = state?.multipleSelection
delete temp?.[itemData.id] delete temp?.[itemData.id]
dispatch({ dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
@ -58,26 +63,39 @@ let ColorKindItem: FC<PropsType> = props => {
}, },
}) })
} }
const { fetchData } = AdjestShoppingCartApi()
// 调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
// TODO需要新增调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
const getInputValue = debounce(async (num, itemData) => { const getInputValue = debounce(async (num, itemData) => {
const targetColor: Record<string, any> = {
product_color_id: itemData.product_color_id,
roll: 0,
length: 0,
}
if (itemData.sale_mode === EnumSaleMode.Bulk) { if (itemData.sale_mode === EnumSaleMode.Bulk) {
itemData.roll = num itemData.roll = num
targetColor.roll = num
} else { } else {
itemData.length = num itemData.length = num
targetColor.length = num
} }
const res = await fetchData({
}, 260) color_list: [targetColor],
purchaser_id: purchaserId,
sale_mode: itemData.sale_mode,
sale_offset: itemData.sale_offset,
})
if (res.success) {
state?.Observer?.notify(purchaserId)
}
}, 400)
return ( return (
<MCheckbox <MCheckbox
status={multipleSelection?.hasOwnProperty(itemData.id) || false} status={state?.multipleSelection?.hasOwnProperty(itemData.id) || false}
onSelect={handleSelect} onSelect={handleSelect}
onClose={handleClose} onClose={handleClose}
customClassName={classnames(styles.checkbox, multipleSelection?.hasOwnProperty(itemData.id) ? styles.selected : '')} customClassName={classnames(styles.checkbox, state?.multipleSelection?.hasOwnProperty(itemData.id) ? styles.selected : '')}
customTextClass={styles.colorKindItem}> customTextClass={styles.colorKindItem}>
<View className={styles['colorKindItem__left']}> <View className={styles['colorKindItem__left']}>
<Image className={styles['colorKindItem__left--image']} mode='aspectFill' src={formatImgUrl(itemData.product_color_texture_url)}></Image> <Image className={styles['colorKindItem__left--image']} mode='aspectFill' src={formatImgUrl(itemData.product_color_texture_url)}></Image>
@ -101,8 +119,8 @@ let ColorKindItem: FC<PropsType> = props => {
digits={selectList[orderType].digits} digits={selectList[orderType].digits}
onClickBtn={e => getInputValue(e, itemData)} onClickBtn={e => getInputValue(e, itemData)}
unit={formatUnit(itemData)} unit={formatUnit(itemData)}
minNum={selectList[orderType].minNum} minNum={itemData.min_num}
maxNum={selectList[orderType].maxNum} maxNum={itemData.max_num}
/> />
</View> </View>
</View> </View>
@ -120,11 +138,11 @@ const withStateSlice = (comp, slice) => {
return memo(forwardRef(Wrapper)) return memo(forwardRef(Wrapper))
} }
ColorKindItem = withStateSlice( ColorKindItem = withStateSlice(ColorKindItem, (state: ShoppingStateContextValue, props: PropsType) => {
ColorKindItem, return {
(state: ShoppingStateContextValue, props: PropsType) => { multipleSelection: state.colorStore[props.purchaserId]['multipleSelection'],
return state.colorStore[props.purchaserId]['multipleSelection'] Observer: state.Observer,
}, }
) })
export default ColorKindItem export default ColorKindItem

View File

@ -1,4 +1,4 @@
import { FC, ReactNode, useEffect, useReducer, useRef } from 'react' import { FC, ReactNode, useEffect, useMemo, useReducer, useRef } from 'react'
import { import {
ShoppingAction, ShoppingAction,
ShoppingDispatchContext, ShoppingDispatchContext,
@ -8,6 +8,7 @@ import {
ShoppingStateContext, ShoppingStateContext,
} from '../../context' } from '../../context'
import { ColorStore, ShoppingStateContextValue } from '../../context' import { ColorStore, ShoppingStateContextValue } from '../../context'
import { ShoppingStore } from '../../context/shoppingStore'
export type TriggerCheckboxOptions = { export type TriggerCheckboxOptions = {
colorStore: ColorStore colorStore: ColorStore
@ -15,15 +16,6 @@ export type TriggerCheckboxOptions = {
setSelectedAmount: ShoppingDispatchContextValue['UPDATE_SELECTED_AMOUNT'] setSelectedAmount: ShoppingDispatchContextValue['UPDATE_SELECTED_AMOUNT']
} }
type InitialState = {
colorStore: ColorStore
currentCheckedPurchaserId: number
currentCheckedSaleMode: number
isManageStatus: boolean
isMultipleSelection: boolean
selectedAmount: number
}
export interface ShoppingCartPropsType { export interface ShoppingCartPropsType {
initialValues?: ColorStore initialValues?: ColorStore
onTriggerCheckbox?: (options: TriggerCheckboxOptions) => void onTriggerCheckbox?: (options: TriggerCheckboxOptions) => void
@ -35,18 +27,22 @@ export const ShoppingProvider: FC<ShoppingCartPropsType> = props => {
const onTriggerCheckboxRef = useRef(onTriggerCheckbox) const onTriggerCheckboxRef = useRef(onTriggerCheckbox)
onTriggerCheckboxRef.current = onTriggerCheckbox onTriggerCheckboxRef.current = onTriggerCheckbox
// 发布订阅
const Observer = useMemo(() => new ShoppingStore(), [])
const [state, dispatch] = useReducer<(state: ShoppingStateContextValue, action: ShoppingAction) => InitialState>(shoppingReducer, { const [state, dispatch] = useReducer<(state: ShoppingStateContextValue, action: ShoppingAction) => ShoppingStateContextValue>(shoppingReducer, {
colorStore: initialValues || {}, colorStore: initialValues || {},
currentCheckedPurchaserId: -1, currentCheckedPurchaserId: -1,
currentCheckedSaleMode: 0, currentCheckedSaleMode: 0,
isManageStatus: false, isManageStatus: false,
isMultipleSelection: false, isMultipleSelection: false,
selectedAmount: 0, selectedAmount: 0,
Observer,
}) })
// 这里要在 useEffect 也就是刷新 state 后再调用,否则如果在 onFieldsChangeRef 修改值会覆盖掉上次修改 // 这里要在 useEffect 也就是刷新 state 后再调用,否则如果在 onFieldsChangeRef 修改值会覆盖掉上次修改
useEffect(() => { useEffect(() => {
console.log('onTriggerCheckboxRef start run')
onTriggerCheckboxRef.current?.({ onTriggerCheckboxRef.current?.({
colorStore: state.colorStore, colorStore: state.colorStore,
currentCheckedPurchaserId: state.currentCheckedPurchaserId, currentCheckedPurchaserId: state.currentCheckedPurchaserId,
@ -54,6 +50,19 @@ export const ShoppingProvider: FC<ShoppingCartPropsType> = props => {
}) })
}, [state.colorStore, state.currentCheckedPurchaserId]) }, [state.colorStore, state.currentCheckedPurchaserId])
// 加入一个监听,为 onFieldsChange 回调服务
// useEffect(() => {
// const unsubscribe = Observer.subscribe(() => {
// console.log('onTriggerCheckboxRef start run')
// onTriggerCheckboxRef.current?.({
// colorStore: state.colorStore,
// currentCheckedPurchaserId: state.currentCheckedPurchaserId,
// setSelectedAmount: amount => dispatch({ type: ShoppingDispatchType.UPDATE_SELECTED_AMOUNT, data: amount }),
// })
// })
// return unsubscribe
// }, [Observer])
return ( return (
<ShoppingStateContext.Provider value={state}> <ShoppingStateContext.Provider value={state}>
<ShoppingDispatchContext.Provider value={dispatch}>{children}</ShoppingDispatchContext.Provider> <ShoppingDispatchContext.Provider value={dispatch}>{children}</ShoppingDispatchContext.Provider>

View File

@ -1,5 +1,5 @@
import { Text, View } from '@tarojs/components' import { Text, View } from '@tarojs/components'
import { FC, forwardRef, memo, useEffect, useMemo, useState, useTransition } from 'react' import { FC, forwardRef, memo, useEffect, useMemo, useRef, useState, useTransition } from 'react'
import styles from './index.module.scss' import styles from './index.module.scss'
import classnames from 'classnames' import classnames from 'classnames'
import { formatMeterDiv } from '@/common/format' import { formatMeterDiv } from '@/common/format'
@ -14,6 +14,8 @@ import IconFont from '@/components/iconfont/iconfont'
import { isEmptyObject } from '@/common/common' import { isEmptyObject } from '@/common/common'
import classNames from 'classnames' import classNames from 'classnames'
import LoadingCard from '@/components/loadingCard' import LoadingCard from '@/components/loadingCard'
import { ShoppingCartListApi } from '@/api'
import { ShoppingStore } from '../../context/shoppingStore'
interface ButtonPropsType { interface ButtonPropsType {
isActive: boolean isActive: boolean
@ -53,11 +55,13 @@ type PropsType = {
state?: { state?: {
multipleSelection?: GoodsMeta['multipleSelection'] multipleSelection?: GoodsMeta['multipleSelection']
currentCheckedPurchaserId?: number currentCheckedPurchaserId?: number
Observer?: ShoppingStore
} }
} }
let ShoppingCartItem: FC<PropsType> = props => { let ShoppingCartItem: FC<PropsType> = props => {
const { itemData, state } = props const { state } = props
const [itemData, setItemData] = useState(props.itemData)
const { multipleSelection, currentCheckedPurchaserId } = state! const { multipleSelection, currentCheckedPurchaserId } = state!
const dispatch = useShoppingDispatch() const dispatch = useShoppingDispatch()
@ -87,7 +91,10 @@ let ShoppingCartItem: FC<PropsType> = props => {
} }
dispatch({ type: ShoppingDispatchType.UPDATE_SELECTED_AMOUNT, data: 0 }) dispatch({ type: ShoppingDispatchType.UPDATE_SELECTED_AMOUNT, data: 0 })
dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_SALEMODE, data: selected }) dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_SALEMODE, data: selected })
dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_PURCHASERID, data: itemData?.purchaser_id as number }) dispatch({
type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_PURCHASERID,
data: itemData?.purchaser_id as number,
})
dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION, data: false }) dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION, data: false })
} }
@ -131,6 +138,58 @@ let ShoppingCartItem: FC<PropsType> = props => {
}, [multipleSelection, currentCheckedPurchaserId, selected, itemData]) }, [multipleSelection, currentCheckedPurchaserId, selected, itemData])
const [isPending, startTransition] = useTransition() const [isPending, startTransition] = useTransition()
const { fetchData } = ShoppingCartListApi()
// 发布订阅
useEffect(() => {
const unsubscribe = state?.Observer?.subscribe(async id => {
if (itemData?.purchaser_id !== id) return
console.log('request new data start run')
const res = await fetchData({
purchaser_id: id,
})
console.log('res===>', res)
if (res.success) {
const newGoodsKind = Object.fromEntries(
res.data[0]?.[BackEndSaleModeListFieldMap[selected]].map(item => [
item?.id,
{
id: item?.id,
estimate_amount: item.estimate_amount,
product_code: item.product_code,
product_color_code: item.product_color_code,
sale_mode: item.sale_mode,
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
},
]),
)
dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: {
purchaserId: id,
goodsKind: newGoodsKind,
multipleSelection: Object.fromEntries(
Object.keys(multipleSelection!).map(id => [
id,
{
id,
estimate_amount: newGoodsKind[id].estimate_amount,
product_code: newGoodsKind[id].product_code,
product_color_code: newGoodsKind[id].product_color_code,
sale_mode: newGoodsKind[id].sale_mode,
count: selected === EnumSaleMode.Bulk ? newGoodsKind[id].roll : Number(formatMeterDiv(newGoodsKind[id].length)),
},
]),
),
},
})
setItemData(res.data[0])
}
})
// 取消订阅
return unsubscribe
}, [multipleSelection])
return ( return (
<LayoutBlock <LayoutBlock
@ -194,7 +253,13 @@ let ShoppingCartItem: FC<PropsType> = props => {
</View> </View>
</View> </View>
<View className={styles.orderContainer}> <View className={styles.orderContainer}>
<GoodsList itemData={itemData} selected={selected} isPending={isPending} startTransition={startTransition} /> <GoodsList
multipleSelection={multipleSelection}
itemData={itemData}
selected={selected}
isPending={isPending}
startTransition={startTransition}
/>
</View> </View>
</View> </View>
</> </>
@ -205,52 +270,78 @@ let ShoppingCartItem: FC<PropsType> = props => {
interface GoodsListPropType { interface GoodsListPropType {
itemData?: ShoppingCartData itemData?: ShoppingCartData
multipleSelection?: GoodsMeta['multipleSelection']
selected: EnumSaleMode selected: EnumSaleMode
isPending: boolean isPending: boolean
startTransition: React.TransitionStartFunction startTransition: React.TransitionStartFunction
} }
const GoodsList = memo<GoodsListPropType>(props => { const GoodsList = memo<GoodsListPropType>(props => {
console.log('Rerender component: GoodsList') console.log('Rerender component: GoodsList', props.multipleSelection)
const { itemData, selected, isPending, startTransition } = props const { itemData, selected, isPending, startTransition, multipleSelection } = props
const currentSelected = useRef<EnumSaleMode | null>(null)
const dispatch = useShoppingDispatch() const dispatch = useShoppingDispatch()
const [component, setComponent] = useState<JSX.Element | null>(null) const [component, setComponent] = useState<JSX.Element | null>(null)
// 更新 GoodsList 组件
const updateComponent = () => {
setComponent(
itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => {
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem>
})
) : (
<View className={styles.noList}></View>
),
)
}
useEffect(() => { useEffect(() => {
startTransition(() => { const newGoodsKind = Object.fromEntries(
setComponent( itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => [
itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? ( item?.id,
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => { {
dispatch({ id: item?.id,
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, estimate_amount: item.estimate_amount,
data: { product_code: item.product_code,
purchaserId: itemData?.purchaser_id!, product_color_code: item.product_color_code,
goodsKind: { sale_mode: item.sale_mode,
[item?.id]: { count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
id: item?.id, },
estimate_amount: item.estimate_amount, ]),
product_code: item.product_code, )
product_color_code: item.product_color_code, // 这里做一层比较是为了 重新渲染的时候如果没有切换订单类型的话就不让面料的选中状态初始化
sale_mode: item.sale_mode, if (currentSelected.current === selected) {
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)), dispatch({
}, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
}, data: {
multipleSelection: {}, purchaserId: itemData?.purchaser_id!,
}, goodsKind: newGoodsKind,
}) multipleSelection: multipleSelection,
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem> },
}) })
) : ( updateComponent()
<View className={styles.noList}></View> } else {
), // 重新把当前的选中状态赋值给ref 作为下一次比较的旧状态
) currentSelected.current = selected
}) dispatch({
}, [itemData, selected]) type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: {
purchaserId: itemData?.purchaser_id!,
goodsKind: newGoodsKind,
multipleSelection: {},
},
})
startTransition(updateComponent)
}
}, [itemData, selected, multipleSelection])
return ( return (
<> <>
{isPending ? ( {isPending ? (
<View className='flex-row items-center justify-center' style={{ width: '100%', height: '200px' }}> <View className={styles.noList} style={{margin: '60rpx 0'}}>
<LoadingCard /> <LoadingCard />
</View> </View>
) : ( ) : (
@ -262,12 +353,12 @@ const GoodsList = memo<GoodsListPropType>(props => {
// State 分割组件 思路就是把 context 直接通过 props 的形式传给组件,这样的话就解决了 context 强制刷新 memo 的问题了 // State 分割组件 思路就是把 context 直接通过 props 的形式传给组件,这样的话就解决了 context 强制刷新 memo 的问题了
// 那么当 context 内的 value 被更新的时候react 只会强制渲染 Wrapper // 那么当 context 内的 value 被更新的时候react 只会强制渲染 Wrapper
const withStateSlice = (comp, slice) => { const withStateSlice = (comp, slice) => {
const MemoComp = memo(comp, (prevProps, nextProps)=>{ const MemoComp = memo(comp, (prevProps, nextProps) => {
let needMemo = true let needMemo = true
if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) { if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) {
needMemo = false needMemo = false
} }
if(JSON.stringify(prevProps.state) !== JSON.stringify(nextProps.state)){ if (JSON.stringify(prevProps.state) !== JSON.stringify(nextProps.state)) {
needMemo = false needMemo = false
} }
return needMemo return needMemo
@ -283,6 +374,7 @@ const withStateSlice = (comp, slice) => {
ShoppingCartItem = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({ ShoppingCartItem = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({
multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.['multipleSelection'], multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.['multipleSelection'],
currentCheckedPurchaserId: state.currentCheckedPurchaserId, currentCheckedPurchaserId: state.currentCheckedPurchaserId,
Observer: state.Observer,
})) }))
export default ShoppingCartItem export default ShoppingCartItem

View File

@ -1,6 +1,7 @@
import { EnumSaleMode } from '@/common/Enumerate' import { EnumSaleMode } from '@/common/Enumerate'
import React, { Dispatch } from 'react' import React, { Dispatch } from 'react'
import { useContext } from 'react' import { useContext } from 'react'
import { ShoppingStore } from './shoppingStore'
/** /**
* 456: { * 456: {
@ -8,7 +9,13 @@ import { useContext } from 'react'
* colorKind: { * colorKind: {
* 4562: { * 4562: {
* id: 4562, * id: 4562,
* checked: false * ...
* }
* },
* multipleSelection: {
* 4562: {
* id: 4562,
* ...
* } * }
* } * }
* }, * },
@ -17,7 +24,7 @@ import { useContext } from 'react'
* colorKind: { * colorKind: {
* 4562: { * 4562: {
* id: 4562, * id: 4562,
* checked: false * ...
* } * }
* } * }
* } * }
@ -40,9 +47,7 @@ export interface GoodsMeta {
goodsKind?: { goodsKind?: {
[id: Goods['id']]: Goods [id: Goods['id']]: Goods
} }
multipleSelection: { multipleSelection?: GoodsMeta['goodsKind']
[id: Goods['id']]: Goods
}
} }
export interface ShoppingStateContextValue { export interface ShoppingStateContextValue {
@ -52,6 +57,7 @@ export interface ShoppingStateContextValue {
currentCheckedSaleMode: EnumSaleMode currentCheckedSaleMode: EnumSaleMode
colorStore: ColorStore colorStore: ColorStore
selectedAmount: number selectedAmount: number
Observer: ShoppingStore
} }
export enum ShoppingDispatchType { export enum ShoppingDispatchType {
@ -63,7 +69,7 @@ export enum ShoppingDispatchType {
UPDATE_SELECTED_AMOUNT = 'UPDATE_SELECTED_AMOUNT', UPDATE_SELECTED_AMOUNT = 'UPDATE_SELECTED_AMOUNT',
UPDATE_CHANGED_CHECKBOX = 'UPDATE_CHANGED_CHECKBOX', UPDATE_CHANGED_CHECKBOX = 'UPDATE_CHANGED_CHECKBOX',
} }
// UPDATE_MultipleSelection
export interface ShoppingDispatchContextValue { export interface ShoppingDispatchContextValue {
[ShoppingDispatchType.UPDATE_MANAGE_STATUS]: (isManageStatus: ShoppingStateContextValue['isManageStatus']) => void [ShoppingDispatchType.UPDATE_MANAGE_STATUS]: (isManageStatus: ShoppingStateContextValue['isManageStatus']) => void
[ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION]: (isMultipleSelection: ShoppingStateContextValue['isMultipleSelection']) => void [ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION]: (isMultipleSelection: ShoppingStateContextValue['isMultipleSelection']) => void
@ -109,7 +115,7 @@ export function shoppingReducer(state: ShoppingStateContextValue, action: Shoppi
[data.purchaserId as number]: { [data.purchaserId as number]: {
purchaserId: data.purchaserId, purchaserId: data.purchaserId,
goodsKind: { ...state.colorStore[data.purchaserId]?.goodsKind, ...data.goodsKind }, goodsKind: { ...state.colorStore[data.purchaserId]?.goodsKind, ...data.goodsKind },
multipleSelection: { ...data.multipleSelection }, multipleSelection: data?.multipleSelection ? data.multipleSelection : state.colorStore[data.purchaserId]?.multipleSelection,
}, },
}, },
} }

View File

@ -1,7 +1,9 @@
import { GoodsMeta, ColorStore } from '.'
// 用于优化数据流 结合发布订阅 更新组件内部状态可以组件自己处理 // 用于优化数据流 结合发布订阅 更新组件内部状态可以组件自己处理
export type SubscribeCallback = (changedGoods: GoodsMeta) => void import { ColorStore } from "."
export type SubscribeCallback = (changedGoods: any) => void
export class ShoppingStore { export class ShoppingStore {
// 全局缓存 // 全局缓存
@ -9,7 +11,7 @@ export class ShoppingStore {
// 监听器数组 // 监听器数组
private observers: SubscribeCallback[] = [] private observers: SubscribeCallback[] = []
constructor(initialValue: ColorStore) { constructor(initialValue?: any) {
initialValue && this.updateStore(initialValue) initialValue && this.updateStore(initialValue)
} }
// 更新全局缓存 // 更新全局缓存
@ -27,9 +29,9 @@ export class ShoppingStore {
} }
} }
// 通知 // 通知
notify(changedGoods: GoodsMeta) { notify(changedGoods: any) {
// 循环调用 // 循环调用
this.observers.forEach((callback) => { this.observers.forEach(callback => {
callback(changedGoods) callback(changedGoods)
}) })
} }

View File

@ -21,7 +21,7 @@ export const Shopping: FC = memo(() => {
// 计算总的预估金额 // 计算总的预估金额
const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => { const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => {
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.multipleSelection const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.multipleSelection
console.log('handleTriggerCheckbox==>', colorStore) console.log('handleTriggerCheckbox==>', multipleSelection)
if (multipleSelection) { if (multipleSelection) {
const result = Object.values(multipleSelection).reduce((prev: number, value: Goods) => { const result = Object.values(multipleSelection).reduce((prev: number, value: Goods) => {
@ -84,11 +84,18 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
setSearchOptions(prev => ({ ...prev, short_name_or_phone: e })) setSearchOptions(prev => ({ ...prev, short_name_or_phone: e }))
}, []) }, [])
const [shoppingCartData, setShoppingCartData] = useState<{ list: ShoppingCartData[]; total: number }>({ list: [], total: 0 }) const [shoppingCartData, setShoppingCartData] = useState<{
list: ShoppingCartData[]
total: number
}>({ list: [], total: 0 })
//数据加载状态 //数据加载状态
const statusMore = useMemo(() => { const statusMore = useMemo(() => {
const status = dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading }) const status = dataLoadingStatus({
list: shoppingCartData.list,
total: shoppingCartData.total,
status: state.loading,
})
console.log('status==>', status) console.log('status==>', status)
return status return status
}, [shoppingCartData, state]) }, [shoppingCartData, state])
@ -144,7 +151,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
// 批量某个客户的删除商品 // 批量某个客户的删除商品
const handleDelete = async () => { const handleDelete = async () => {
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection'] const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection']
let checked: Goods[] = Object.values(multipleSelection) let checked: Goods[] = Object.values(multipleSelection!)
if (checked.length === 0) { if (checked.length === 0) {
return Taro.showToast({ title: '请选择商品', icon: 'error' }) return Taro.showToast({ title: '请选择商品', icon: 'error' })
} }
@ -203,6 +210,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
} }
return ( return (
<View className={classnames('flex-col', styles.shopping)} id='shoppingContainer'> <View className={classnames('flex-col', styles.shopping)} id='shoppingContainer'>
<View className={styles['shopping--topBar']} id='topBar'> <View className={styles['shopping--topBar']} id='topBar'>