🎈 perf(购物页面): 多选面料的性能优化

This commit is contained in:
xuan 2022-10-19 19:07:25 +08:00
parent bd08ba8df2
commit cd676c4e8b
7 changed files with 14065 additions and 86 deletions

View File

@ -66,22 +66,26 @@ export default ({minNum = 0, maxNum = 10000, step=1, digits = 0, defaultNum = 0,
if(res === '') { if(res === '') {
setValue({...value, count:minNum}) setValue({...value, count:minNum})
onChange?.(minNum) onChange?.(minNum)
return minNum
} }
else if(!isNaN(Number(res))) { else if(!isNaN(Number(res))) {
let count = formatDigits(res) let count = formatDigits(res)
count = checkData(count) count = checkData(count)
setValue({...value, count}) setValue({...value, count})
onChange?.(parseFloat(count as string)) onChange?.(parseFloat(count as string))
return count
} else { } else {
let num = parseFloat(res) let num = parseFloat(res)
if(!isNaN(num)) { if (!isNaN(num)) {
let count = formatDigits(num) let count = formatDigits(num)
count = checkData(count) count = checkData(count)
setValue({...value, count}) setValue({ ...value, count })
onChange?.(count as number) onChange?.(count as number)
return count
} else { } else {
setValue({...value, count:defaultNum}) setValue({ ...value, count: defaultNum })
onChange?.(defaultNum) onChange?.(defaultNum)
return defaultNum
} }
} }
@ -89,14 +93,16 @@ export default ({minNum = 0, maxNum = 10000, step=1, digits = 0, defaultNum = 0,
const onBluerEven = () => { const onBluerEven = () => {
let num = parseFloat(value.count) let num = parseFloat(value.count)
if(!isNaN(num)) { if (!isNaN(num)) {
let count = formatDigits(num) let count = formatDigits(num)
count = checkData(count) count = checkData(count)
setValue({...value, count}) setValue({ ...value, count })
onBlue?.(count as number) onBlue?.(count as number)
return count
} else { } else {
setValue({...value, count:defaultNum}) setValue({ ...value, count: defaultNum })
onBlue?.(defaultNum) onBlue?.(defaultNum)
return defaultNum
} }
} }
const noop = (e) => { const noop = (e) => {

View File

@ -62,7 +62,6 @@ const Login: FC = () => {
account, account,
password, password,
}) })
console.log('state===>', res)
if (res.success) { if (res.success) {
alert.success('登陆成功') alert.success('登陆成功')
setToken(res.data.token) setToken(res.data.token)

View File

@ -1,7 +1,7 @@
import { View, Text, Image } from '@tarojs/components' import { View, Text, Image } from '@tarojs/components'
import MCheckbox from '@/components/checkbox' import MCheckbox from '@/components/checkbox'
import Counter from '@/components/counter' import Counter from '@/components/counter'
import { FC, forwardRef, memo, ReactNode, useCallback, useEffect, useState } from 'react' import { FC, forwardRef, memo } from 'react'
import classnames from 'classnames' import classnames from 'classnames'
import styles from './index.module.scss' import styles from './index.module.scss'
import { debounce } from '@/common/util' import { debounce } from '@/common/util'
@ -9,6 +9,7 @@ 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 { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context' import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
type PropsType = { type PropsType = {
state?: Goods state?: Goods
purchaserId: number purchaserId: number
@ -20,11 +21,9 @@ type PropsType = {
let ColorKindItem: FC<PropsType> = props => { let ColorKindItem: FC<PropsType> = props => {
console.log('Rerender component: ColorKindItem') console.log('Rerender component: ColorKindItem')
const { state: goods, purchaserId, itemData, orderType = EnumSaleMode.Bulk } = props const { state: multipleSelection, purchaserId, itemData, orderType = EnumSaleMode.Bulk } = props
// const { colorStore } = useShoppingState()
const dispatch = useShoppingDispatch() const dispatch = useShoppingDispatch()
// console.log('checked==>', checked) // console.log('checked==>', checked)
// const { checked } = colorStore[purchaserId]['goodsKind']![itemData.id] || { checked: false }
//格式化金额 //格式化金额
const formatPrice = (price: number) => { const formatPrice = (price: number) => {
@ -42,39 +41,45 @@ let ColorKindItem: FC<PropsType> = props => {
} }
const handleSelect = () => { const handleSelect = () => {
// console.log('handleSelect')
dispatch({ dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: { data: {
purchaserId: purchaserId, purchaserId: purchaserId,
goodsKind: { [itemData.id]: { ...goods!, checked: true } }, multipleSelection: { ...multipleSelection, [itemData.id]: itemData },
}, },
}) })
} }
const handleClose = () => { const handleClose = () => {
const temp = multipleSelection
delete temp?.[itemData.id]
dispatch({ dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: { data: {
purchaserId: purchaserId, purchaserId: purchaserId,
goodsKind: { [itemData.id]: { ...goods!, checked: false } }, multipleSelection: temp,
}, },
}) })
} }
// TODO需要新增调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
const getInputValue = debounce(async (num, itemData) => { const getInputValue = debounce(async (num, itemData) => {
if (itemData.sale_mode === EnumSaleMode.Bulk) { if (itemData.sale_mode === EnumSaleMode.Bulk) {
itemData.roll = num itemData.roll = num
} else { } else {
itemData.length = num itemData.length = num
} }
}, 300)
}, 260)
return ( return (
<MCheckbox <MCheckbox
status={goods?.checked} status={multipleSelection?.hasOwnProperty(itemData.id) || false}
onSelect={handleSelect} onSelect={handleSelect}
onClose={handleClose} onClose={handleClose}
customClassName={classnames(styles.checkbox, goods?.checked ? styles.selected : '')} customClassName={classnames(styles.checkbox, 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>
@ -119,7 +124,7 @@ const withStateSlice = (comp, slice) => {
ColorKindItem = withStateSlice( ColorKindItem = withStateSlice(
ColorKindItem, ColorKindItem,
(state: ShoppingStateContextValue, props: PropsType) => { (state: ShoppingStateContextValue, props: PropsType) => {
return state.colorStore[props.purchaserId]['goodsKind']![props.itemData.id] return state.colorStore[props.purchaserId]['multipleSelection']
}, },
) )

View File

@ -9,7 +9,7 @@ import Divider from '@/components/divider'
import ColorKindItem from '../colorKindItem' import ColorKindItem from '../colorKindItem'
import { EnumSaleMode } from '@/common/Enumerate' import { EnumSaleMode } from '@/common/Enumerate'
import { selectList } from '../../config' import { selectList } from '../../config'
import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context' import { Goods, GoodsMeta, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
import IconFont from '@/components/iconfont/iconfont' import IconFont from '@/components/iconfont/iconfont'
import { isEmptyObject } from '@/common/common' import { isEmptyObject } from '@/common/common'
import classNames from 'classnames' import classNames from 'classnames'
@ -51,14 +51,14 @@ enum BackEndSaleModeListFieldMap {
type PropsType = { type PropsType = {
itemData?: ShoppingCartData itemData?: ShoppingCartData
state?: { state?: {
goodsKind?: Goods multipleSelection?: GoodsMeta['multipleSelection']
currentCheckedPurchaserId?: number currentCheckedPurchaserId?: number
} }
} }
let ShoppingCartItem: FC<PropsType> = props => { let ShoppingCartItem: FC<PropsType> = props => {
const { itemData, state } = props const { itemData, state } = props
const { goodsKind, currentCheckedPurchaserId } = state! const { multipleSelection, currentCheckedPurchaserId } = state!
const dispatch = useShoppingDispatch() const dispatch = useShoppingDispatch()
const [openDetail, setOpenDetail] = useState(false) const [openDetail, setOpenDetail] = useState(false)
@ -93,49 +93,42 @@ let ShoppingCartItem: FC<PropsType> = props => {
// 统计已选面料 // 统计已选面料
const materialChecked = useMemo(() => { const materialChecked = useMemo(() => {
const targetGoodsKind = goodsKind if (!multipleSelection || isEmptyObject(multipleSelection)) return 0
if (!targetGoodsKind || isEmptyObject(targetGoodsKind)) return 0
return new Set( return new Set(
// @ts-ignore Object.values(multipleSelection)?.reduce((prev, item: Goods) => {
Object.values(targetGoodsKind)?.reduce((prev, item: Goods) => { if (item.sale_mode === selected) {
if (item.checked && item.sale_mode === selected) {
return [...prev, item.product_code] return [...prev, item.product_code]
} }
return prev return prev
}, []), }, []),
).size ).size
}, [goodsKind, currentCheckedPurchaserId, selected, itemData]) }, [multipleSelection, currentCheckedPurchaserId, selected, itemData])
// 统计已选颜色 // 统计已选颜色
const colorChecked = useMemo(() => { const colorChecked = useMemo(() => {
const targetGoodsKind = goodsKind if (!multipleSelection || isEmptyObject(multipleSelection)) return 0
if (!targetGoodsKind || isEmptyObject(targetGoodsKind)) return 0
return new Set( return new Set(
// @ts-ignore Object.values(multipleSelection).reduce((prev, item: Goods) => {
Object.values(targetGoodsKind).reduce((prev, item: Goods) => { if (item.sale_mode === selected) {
if (item.checked && item.sale_mode === selected) {
return [...prev, item.product_color_code] return [...prev, item.product_color_code]
} }
return prev return prev
}, []), }, []),
).size ).size
}, [goodsKind, currentCheckedPurchaserId, selected, itemData]) }, [multipleSelection, currentCheckedPurchaserId, selected, itemData])
// 统计已选条数 / 米数 // 统计已选条数 / 米数
const lengthOrRollChecked = useMemo(() => { const lengthOrRollChecked = useMemo(() => {
const targetGoodsKind = goodsKind if (!multipleSelection || isEmptyObject(multipleSelection)) return 0
if (!targetGoodsKind || isEmptyObject(targetGoodsKind)) return 0
return ( return (
// @ts-ignore Object.values(multipleSelection).reduce((prev, item: Goods) => {
Object.values(targetGoodsKind).reduce((prev, item: Goods) => { if (item.sale_mode === selected) {
if (item.checked && item.sale_mode === selected) {
// @ts-ignore
return prev + item.count return prev + item.count
} }
return prev return prev
}, 0) || 0 }, 0) || 0
) )
}, [goodsKind, currentCheckedPurchaserId, selected, itemData]) }, [multipleSelection, currentCheckedPurchaserId, selected, itemData])
const [isPending, startTransition] = useTransition() const [isPending, startTransition] = useTransition()
@ -236,13 +229,13 @@ const GoodsList = memo<GoodsListPropType>(props => {
[item?.id]: { [item?.id]: {
id: item?.id, id: item?.id,
estimate_amount: item.estimate_amount, estimate_amount: item.estimate_amount,
checked: false,
product_code: item.product_code, product_code: item.product_code,
product_color_code: item.product_color_code, product_color_code: item.product_color_code,
sale_mode: item.sale_mode, sale_mode: item.sale_mode,
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)), count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
}, },
}, },
multipleSelection: {},
}, },
}) })
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem> return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem>
@ -287,7 +280,7 @@ const withStateSlice = (comp, slice) => {
} }
ShoppingCartItem = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({ ShoppingCartItem = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({
goodsKind: state.colorStore?.[props.itemData?.purchaser_id]?.['goodsKind']!, multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.['multipleSelection'],
currentCheckedPurchaserId: state.currentCheckedPurchaserId, currentCheckedPurchaserId: state.currentCheckedPurchaserId,
})) }))

View File

@ -32,13 +32,15 @@ export type Goods = {
estimate_amount: number // 预估金额 estimate_amount: number // 预估金额
count: number // 已选的条数或米数 count: number // 已选的条数或米数
sale_mode: number sale_mode: number
checked: boolean
} }
// 分组 // 分组
export interface GoodsMeta { export interface GoodsMeta {
purchaserId: number purchaserId: number
goodsKind?: { goodsKind?: {
[id: number]: Goods [id: Goods['id']]: Goods
}
multipleSelection: {
[id: Goods['id']]: Goods
} }
} }
@ -100,6 +102,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 },
}, },
}, },
} }

View File

@ -20,15 +20,12 @@ import LoadingCard from '@/components/loadingCard'
export const Shopping: FC = memo(() => { export const Shopping: FC = memo(() => {
// 计算总的预估金额 // 计算总的预估金额
const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => { const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => {
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind'] const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.multipleSelection
console.log('handleTriggerCheckbox==>', colorStore) console.log('handleTriggerCheckbox==>', colorStore)
if (targetGoodsKind) { if (multipleSelection) {
const result = Object.values(targetGoodsKind).reduce((prev: number, value: Goods) => { const result = Object.values(multipleSelection).reduce((prev: number, value: Goods) => {
if (value.checked) {
return prev + Number(formatPriceDiv(value.estimate_amount)) return prev + Number(formatPriceDiv(value.estimate_amount))
}
return prev
}, 0) as number }, 0) as number
console.log('result==>', result) console.log('result==>', result)
// 同步修改上下文的 预估金额 // 同步修改上下文的 预估金额
@ -125,13 +122,10 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
// 结算 // 结算
const handleSettleAccount = debounce(() => { const handleSettleAccount = debounce(() => {
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind'] const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection']
if (!targetGoodsKind) return Taro.showToast({ title: '请先选择客户', icon: 'error' }) if (!multipleSelection) return Taro.showToast({ title: '请先选择客户', icon: 'error' })
const checkedGoodsKind = Object.values(targetGoodsKind).reduce((prev, item: Goods) => { const checkedGoodsKind = Object.values(multipleSelection).reduce((prev, item: Goods) => {
if (item.checked) {
return [...prev, item.id] return [...prev, item.id]
}
return prev
}, []) }, [])
if (checkedGoodsKind.length === 0) return Taro.showToast({ title: '请先选择商品', icon: 'error' }) if (checkedGoodsKind.length === 0) return Taro.showToast({ title: '请先选择商品', icon: 'error' })
goLink('/pages/submitOrder/index', { goLink('/pages/submitOrder/index', {
@ -146,14 +140,11 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
// 批量某个客户的删除商品 // 批量某个客户的删除商品
const handleDelete = async () => { const handleDelete = async () => {
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind'] const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection']
let checked: Goods[] = [] let checked: Goods[] = Object.values(multipleSelection)
if (targetGoodsKind) {
checked = Object.values(targetGoodsKind).filter((item: Goods) => item.checked)
if (checked.length === 0) { if (checked.length === 0) {
return Taro.showToast({ title: '请选择商品', icon: 'error' }) return Taro.showToast({ title: '请选择商品', icon: 'error' })
} }
}
console.log('checked==>', checked) console.log('checked==>', checked)
Taro.showModal({ Taro.showModal({
title: '要删除这些商品吗?', title: '要删除这些商品吗?',
@ -179,26 +170,15 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
if (!targetGoodsKind) return Taro.showToast({ title: '请先选择客户', icon: 'error' }) if (!targetGoodsKind) return Taro.showToast({ title: '请先选择客户', icon: 'error' })
console.log('targetGoodsKind==>', targetGoodsKind) console.log('targetGoodsKind==>', targetGoodsKind)
const tempObject = {} const tempObject = { ...targetGoodsKind }
Object.entries(targetGoodsKind).forEach(([key, value]) => {
tempObject[key] = {
...value,
checked: isSelectAll,
}
})
console.log('tempObject==>', tempObject) console.log('tempObject==>', tempObject)
dispatch({ dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX, type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: { data: {
purchaserId: currentCheckedPurchaserId, purchaserId: currentCheckedPurchaserId,
goodsKind: tempObject, multipleSelection: isSelectAll ? tempObject : {},
}, },
}) })
// setChangedCheckbox({
// purchaserId: currentCheckedPurchaserId,
// goodsKind: tempObject,
// })
} }
// 加载刷新数据 // 加载刷新数据

13993
yarn-error.log Normal file

File diff suppressed because it is too large Load Diff