🐞 fix(购物页面): 修复选中条数不正确的偶现问题

This commit is contained in:
xuan 2023-01-03 19:30:16 +08:00
parent b37006724b
commit 9cd2f5579d
4 changed files with 99 additions and 75 deletions

View File

@ -15,7 +15,7 @@ export const BASE_URL = CURRENT_BASE_URL
// export const BASE_URL = 'http://192.168.1.7:50002/lymarket' // 添 // export const BASE_URL = 'http://192.168.1.7:50002/lymarket' // 添
// export const BASE_URL = 'http://192.168.1.42:50002/lymarket' // 杰 // export const BASE_URL = 'http://192.168.1.42:50002/lymarket' // 杰
// export const BASE_URL = `http://192.168.1.95:40001/lymarket` // 华 // export const BASE_URL = `http://192.168.1.95:40001/lymarket` // 华
// export const BASE_URL = 'http://192.168.1.28:50002/lymarket' // 婷 // export const BASE_URL = 'http://192.168.1.28:50001/lymarket' // 婷
// CDN // CDN
// 生成密钥 // 生成密钥

View File

@ -1,6 +1,6 @@
import { Image, Text, View } from '@tarojs/components' import { Image, Text, View } from '@tarojs/components'
import type { FC } from 'react' import type { FC } from 'react'
import { forwardRef, memo, useCallback, useEffect, useState } from 'react' import { forwardRef, memo, useCallback, useEffect, useRef, useState } from 'react'
import classnames from 'classnames' import classnames from 'classnames'
import { selectList } from '../../config' import { selectList } from '../../config'
import type { ShoppingStateContextValue } from '../../context' import type { ShoppingStateContextValue } from '../../context'
@ -37,7 +37,10 @@ const ColorKindItem: FC<PropsType> = (props) => {
props.onChange?.(value, itemData.id) props.onChange?.(value, itemData.id)
}, },
}) })
const currentCount = useRef({
roll: itemData.roll,
length: itemData.length,
})
// 格式化数量 // 格式化数量
const formatCount = (itemData) => { const formatCount = (itemData) => {
return itemData.sale_mode == EnumSaleMode.Bulk ? itemData.roll : formatMeterDiv(itemData.length) return itemData.sale_mode == EnumSaleMode.Bulk ? itemData.roll : formatMeterDiv(itemData.length)
@ -60,13 +63,14 @@ const ColorKindItem: FC<PropsType> = (props) => {
} }
// 选中 // 选中
const handleSelect = () => { const handleSelect = () => {
console.log('currentCount==>', currentCount.current, itemData)
const payload = { const payload = {
id: itemData?.id, id: itemData?.id,
estimate_amount: itemData.estimate_amount, estimate_amount: itemData.estimate_amount,
product_code: itemData.product_code, product_code: itemData.product_code,
product_color_code: itemData.product_color_code, product_color_code: itemData.product_color_code,
sale_mode: itemData.sale_mode, sale_mode: itemData.sale_mode,
count: itemData.sale_mode === EnumSaleMode.Bulk ? itemData.roll : Number(formatMeterDiv(itemData.length)), count: itemData.sale_mode === EnumSaleMode.Bulk ? currentCount.current.roll : Number(formatMeterDiv(currentCount.current.length)),
} }
events.trigger('updatePurchaserMultipleSelection', purchaserId, payload, 'add', itemData?.id) events.trigger('updatePurchaserMultipleSelection', purchaserId, payload, 'add', itemData?.id)
setCheck(true) setCheck(true)
@ -81,16 +85,16 @@ const ColorKindItem: FC<PropsType> = (props) => {
// 调整条数/米数的接口 并在调整完成后重新请求整个购物车页面 // 调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
const getInputValue = useCallback(debounce(async(num) => { const getInputValue = useCallback(debounce(async(num) => {
console.log('num===>', num) console.log('num===>', num)
const targetColor: Record<string, any> = { const targetColor = {
roll: 0, roll: 0,
length: 0, length: 0,
} }
if (itemData.sale_mode === EnumSaleMode.Bulk) { if (itemData.sale_mode === EnumSaleMode.Bulk) {
itemData.roll = num // itemData.roll = num
targetColor.roll = num targetColor.roll = num
} }
else { else {
itemData.length = formatMeterMul(num) // itemData.length = formatMeterMul(num)
targetColor.length = formatMeterMul(num) targetColor.length = formatMeterMul(num)
} }
const res = await fetchData({ const res = await fetchData({
@ -99,17 +103,24 @@ const ColorKindItem: FC<PropsType> = (props) => {
length: targetColor.length, length: targetColor.length,
}) })
if (res.success) { if (res.success) {
currentCount.current = targetColor
state?.Observer?.notify(purchaserId) state?.Observer?.notify(purchaserId)
} }
else {
// 请求失败,赋值回初始数量
setCount(formatCount(itemData))
}
}, 460), [itemData]) }, 460), [itemData])
const labAndImgObj = useCallback((item) => { const labAndImgObj = useCallback((item) => {
return { lab: item.lab, rgb: item.rgb, texture_url: item.product_color_texture_url } return { lab: item.lab, rgb: item.rgb, texture_url: item.product_color_texture_url }
}, []) }, [])
useEffect(() => { useEffect(() => {
console.log('itemData==>', itemData) console.log('itemData==>', itemData)
setCount(formatCount(itemData)) setCount(formatCount(itemData))
}, [itemData.roll, itemData.length]) }, [itemData.roll, itemData.length])
return ( return (
<MCheckbox <MCheckbox
status={isChecked} status={isChecked}

View File

@ -7,7 +7,7 @@ import classNames from 'classnames'
import produce, { setAutoFreeze } from 'immer' import produce, { setAutoFreeze } from 'immer'
import ColorKindItem from '../colorKindItem' import ColorKindItem from '../colorKindItem'
import { selectList } from '../../config' import { selectList } from '../../config'
import type { Goods, GoodsMeta, ShoppingStateContextValue } from '../../context' import type { ColorStore, Goods, GoodsMeta, ShoppingStateContextValue } from '../../context'
import { ShoppingDispatchType, useShoppingDispatch, useShoppingState } from '../../context' import { ShoppingDispatchType, useShoppingDispatch, useShoppingState } from '../../context'
import type { ShoppingStore } from '../../context/shoppingStore' import type { ShoppingStore } from '../../context/shoppingStore'
import { events } from '../../context/shoppingStore' import { events } from '../../context/shoppingStore'
@ -66,47 +66,48 @@ interface GoodsListPropType {
} }
const GoodsList = (props: GoodsListPropType) => { const GoodsList = (props: GoodsListPropType) => {
const { itemData, selected, isPending, startTransition, multipleSelection } = props const { itemData, selected, isPending, startTransition, multipleSelection } = props
const prevMultipleSelection = useRef(multipleSelection) console.log('rerender component GoodsList', props)
// const prevMultipleSelection = useRef(multipleSelection)
const currentSelected = useRef<EnumSaleMode | null>(null) 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)
// 使用 produce 更新特定的 ColorKindItem // 使用 produce 更新特定的 ColorKindItem
const updateSpecifiedComponent = () => { // const updateSpecifiedComponent = () => {
let newId // let newId
if (multipleSelection && prevMultipleSelection.current !== multipleSelection) { // if (multipleSelection && prevMultipleSelection.current !== multipleSelection) {
for (const key in multipleSelection) { // for (const key in multipleSelection) {
if (!prevMultipleSelection.current?.hasOwnProperty(key)) { // if (!prevMultipleSelection.current?.hasOwnProperty(key)) {
newId = key // newId = key
break // break
} // }
} // }
} // }
console.log('multipleSelection==+>', multipleSelection) // console.log('multipleSelection==+>', multipleSelection)
console.log('currentSelected', currentSelected.current, selected) // console.log('currentSelected', currentSelected.current, selected)
console.log('component', component) // console.log('component', component)
if (component) { // if (component) {
if (itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0) { // if (itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0) {
setComponent(produce(component, (draft) => { // setComponent(produce(component, (draft) => {
console.log('prev', component) // console.log('prev', component)
const index = (draft as unknown as any[]).findIndex(item => item.key === newId) // const index = (draft as unknown as any[]).findIndex(item => item.key === newId)
console.log('index', index) // console.log('index', index)
if (index !== -1) { // if (index !== -1) {
const item = itemData?.[BackEndSaleModeListFieldMap[selected]].find((item) => { // const item = itemData?.[BackEndSaleModeListFieldMap[selected]].find((item) => {
return item.id === Number(newId) // return item.id === Number(newId)
}) // })
console.log('item', item, newId) // console.log('item', item, newId)
draft![index] = <ColorKindItem checked={multipleSelection?.hasOwnProperty(newId)} purchaserId={itemData?.purchaser_id} key={newId} itemData={item}></ColorKindItem> // draft![index] = <ColorKindItem checked={multipleSelection?.hasOwnProperty(newId)} purchaserId={itemData?.purchaser_id} key={newId} itemData={item}></ColorKindItem>
} // }
})) // }))
} // }
else { // else {
setComponent(<View className={styles.noList}></View>) // setComponent(<View className={styles.noList}>暂无数据</View>)
} // }
} // }
prevMultipleSelection.current = multipleSelection // prevMultipleSelection.current = multipleSelection
} // }
// 更新 GoodsList 组件 // 更新 GoodsList 组件
const updateComponent = () => { const updateComponent = () => {
setComponent( setComponent(
@ -121,7 +122,7 @@ const GoodsList = (props: GoodsListPropType) => {
<View className={styles.noList}></View> <View className={styles.noList}></View>
), ),
) )
prevMultipleSelection.current = multipleSelection // prevMultipleSelection.current = multipleSelection
} }
useEffect(() => { useEffect(() => {
@ -184,6 +185,7 @@ const GoodsListWithMemo = memo<GoodsListPropType>(GoodsList)
interface PropsType { interface PropsType {
itemData?: ShoppingCartData itemData?: ShoppingCartData
state?: { state?: {
colorStore?: ColorStore
multipleSelection?: GoodsMeta['multipleSelection'] multipleSelection?: GoodsMeta['multipleSelection']
currentCheckedPurchaserId?: number currentCheckedPurchaserId?: number
Observer?: ShoppingStore Observer?: ShoppingStore
@ -194,11 +196,13 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
const { state } = props const { state } = props
console.log('rerender component ShoppingCartItem', props) console.log('rerender component ShoppingCartItem', props)
const currentItemData = useRef<ShoppingCartData | undefined>(props.itemData)
const [itemData, setItemData] = usePropsValue({ const [itemData, setItemData] = usePropsValue({
value: props.itemData, value: currentItemData.current,
defaultValue: props.itemData, defaultValue: props.itemData,
}) })
const { multipleSelection, currentCheckedPurchaserId } = state! const { multipleSelection, currentCheckedPurchaserId, colorStore } = state!
const dispatch = useShoppingDispatch() const dispatch = useShoppingDispatch()
const [openDetail, setOpenDetail] = useState(false) const [openDetail, setOpenDetail] = useState(false)
@ -216,14 +220,16 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
} }
const handleClickLayout = () => { const handleClickLayout = () => {
if (currentCheckedPurchaserId === itemData?.purchaser_id) { if (currentCheckedPurchaserId === props.itemData?.purchaser_id) {
return return
} }
currentItemData.current = props.itemData
setItemData(props.itemData)
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({ dispatch({
type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_PURCHASERID, type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_PURCHASERID,
data: itemData?.purchaser_id as number, data: props.itemData?.purchaser_id as number,
}) })
dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION_STATUS, data: false }) dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION_STATUS, data: false })
} }
@ -233,6 +239,7 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
} }
// 统计已选面料 // 统计已选面料
const materialChecked = useMemo(() => { const materialChecked = useMemo(() => {
const multipleSelection = colorStore?.[itemData!.purchaser_id]?.multipleSelection
if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 } if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 }
return new Set( return new Set(
Object.values(multipleSelection)?.reduce((prev, item: Goods) => { Object.values(multipleSelection)?.reduce((prev, item: Goods) => {
@ -242,10 +249,11 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
return prev return prev
}, []), }, []),
).size ).size
}, [multipleSelection, currentCheckedPurchaserId, selected, itemData]) }, [colorStore, currentCheckedPurchaserId, selected, itemData])
// 统计已选颜色 // 统计已选颜色
const colorChecked = useMemo(() => { const colorChecked = useMemo(() => {
const multipleSelection = colorStore?.[itemData!.purchaser_id]?.multipleSelection
console.log('colorChecked item', multipleSelection) console.log('colorChecked item', multipleSelection)
if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 } if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 }
return new Set( return new Set(
@ -256,20 +264,26 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
return prev return prev
}, []), }, []),
).size ).size
}, [multipleSelection, currentCheckedPurchaserId, selected, itemData]) }, [colorStore, currentCheckedPurchaserId, selected, itemData])
// 统计已选条数 / 米数 // 统计已选条数 / 米数
const lengthOrRollChecked = useMemo(() => { const lengthOrRollChecked = useMemo(() => {
console.log('lengthOrRollChecked item', multipleSelection) const multipleSelection = colorStore?.[itemData!.purchaser_id]?.multipleSelection
console.log('lengthOrRollChecked item', multipleSelection, currentCheckedPurchaserId, itemData)
if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 } if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 }
return ( return (
Object.values(multipleSelection).reduce((prev, item: Goods) => { Object.values(multipleSelection).reduce((prev, item: Goods) => {
return prev + item.count return prev + item.count
}, 0) || 0 }, 0) || 0
) )
}, [multipleSelection, currentCheckedPurchaserId, selected, itemData]) }, [colorStore, currentCheckedPurchaserId, selected, itemData])
const { fetchData } = ShoppingCartListApi() const { fetchData } = ShoppingCartListApi()
useEffect(() => {
if (itemData?.purchaser_id === 1708 || itemData?.purchaser_id === 642) {
console.log('useEffect multipleSelection', multipleSelection, colorStore)
}
}, [itemData, multipleSelection, colorStore])
// 更新当前客户的多选项 // 更新当前客户的多选项
const updatePurchaserMultipleSelection = (purchaserId, payload, operationType: OperationType, goodsId: number) => { const updatePurchaserMultipleSelection = (purchaserId, payload, operationType: OperationType, goodsId: number) => {
if (operationType === 'add') { if (operationType === 'add') {
@ -277,21 +291,15 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: { data: {
purchaserId, purchaserId,
multipleSelection: produce(multipleSelection, (multipleSelectionDraft) => { multipleSelection: {
if (!multipleSelectionDraft) { ...colorStore?.[purchaserId].multipleSelection,
return { [goodsId]: payload,
[goodsId]: payload, },
}
}
else {
multipleSelectionDraft[goodsId] = payload
}
}),
}, },
}) })
} }
else if (operationType === 'delete') { else if (operationType === 'delete') {
const temp = { ...multipleSelection } const temp = { ...colorStore?.[purchaserId].multipleSelection }
delete temp?.[goodsId] delete temp?.[goodsId]
dispatch({ dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
@ -326,6 +334,7 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
// ... // ...
// } // }
if (!res.data.list.length) { return alert.error('修改数量失败') } if (!res.data.list.length) { return alert.error('修改数量失败') }
const newGoodsKind = Object.fromEntries( const newGoodsKind = Object.fromEntries(
res.data.list[0]?.[BackEndSaleModeListFieldMap[selected]].map(item => [ res.data.list[0]?.[BackEndSaleModeListFieldMap[selected]].map(item => [
item?.id, item?.id,
@ -360,6 +369,7 @@ const ShoppingCartItem: FC<PropsType> = (props) => {
), ),
}, },
}) })
currentItemData.current = res.data.list[0]
setItemData(() => res.data.list[0]) setItemData(() => res.data.list[0])
} }
else { else {
@ -459,17 +469,17 @@ const withStateSlice = (comp, slice) => {
if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) { if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) {
needMemo = false needMemo = false
} }
if (prevProps.itemData.purchaser_name === 'JENNIE') { // if (prevProps.itemData.purchaser_name === 'JENNIE') {
console.log('------withStateSlice props-------') // console.log('------withStateSlice props-------')
console.log('withStateSlice props prevProps', prevProps) // console.log('withStateSlice props prevProps', prevProps)
console.log('withStateSlice props prevProps comparison itemData', prevProps.itemData === nextProps.itemData) // console.log('withStateSlice props prevProps comparison itemData', prevProps.itemData === nextProps.itemData)
console.log('withStateSlice props nextProps', nextProps) // console.log('withStateSlice props nextProps', nextProps)
console.log('withStateSlice props prevProps comparison multipleSelection', prevProps.state.multipleSelection === nextProps.state.multipleSelection) // console.log('withStateSlice props prevProps comparison multipleSelection', prevProps.state.multipleSelection === nextProps.state.multipleSelection)
console.log('withStateSlice props prevProps comparison currentCheckedPurchaserId', prevProps.state.currentCheckedPurchaserId === nextProps.state.currentCheckedPurchaserId) // console.log('withStateSlice props prevProps comparison currentCheckedPurchaserId', prevProps.state.currentCheckedPurchaserId === nextProps.state.currentCheckedPurchaserId)
console.log('withStateSlice props prevProps comparison Observer', prevProps.state.Observer === nextProps.state.Observer) // console.log('withStateSlice props prevProps comparison Observer', prevProps.state.Observer === nextProps.state.Observer)
console.log('withStateSlice props prevProps comparison state', prevProps.state === nextProps.state) // console.log('withStateSlice props prevProps comparison state', prevProps.state === nextProps.state)
console.log('------withStateSlice props-------') // console.log('------withStateSlice props-------')
} // }
if (prevProps.state.Observer !== nextProps.state.Observer) { if (prevProps.state.Observer !== nextProps.state.Observer) {
console.log('Observer 有变化') console.log('Observer 有变化')
needMemo = false needMemo = false
@ -486,13 +496,15 @@ const withStateSlice = (comp, slice) => {
}) })
const Wrapper = (props, ref) => { const Wrapper = (props, ref) => {
const state = useShoppingState() const state = useShoppingState()
// console.log('Wrapper colorStore', state.colorStore)
return <MemoComp ref={ref} state={slice(state, props)} {...props} /> return <MemoComp ref={ref} state={slice(state, props)} {...props} />
} }
return memo(forwardRef(Wrapper)) return memo(forwardRef(Wrapper))
} }
const ShoppingCartItemWithStateSlice = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({ const ShoppingCartItemWithStateSlice = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({
multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.multipleSelection, colorStore: state.colorStore,
multipleSelection: state.colorStore?.[props.itemData.purchaser_id]?.multipleSelection,
currentCheckedPurchaserId: state.currentCheckedPurchaserId, currentCheckedPurchaserId: state.currentCheckedPurchaserId,
Observer: state.Observer, Observer: state.Observer,
})) }))

View File

@ -5,6 +5,7 @@ import type { ShoppingStore } from './shoppingStore'
import type { EnumSaleMode } from '@/common/Enumerate' import type { EnumSaleMode } from '@/common/Enumerate'
/** /**
* 使weakmap来作为第一层的数据结构
* 456: { * 456: {
* purchaserId: 456, * purchaserId: 456,
* colorKind: { * colorKind: {