🎈 perf(多选): 完成购物车多选逻辑

This commit is contained in:
xuan 2022-09-27 12:03:22 +08:00
parent eb22811dfa
commit 3b3adcb203
10 changed files with 53 additions and 47 deletions

View File

@ -80,7 +80,7 @@
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
"react-refresh": "0.11.0", "react-refresh": "0.11.0",
"stylelint": "9.3.0", "stylelint": "9.3.0",
"taro-iconfont-svg": "^1.0.7", "taro-iconfont-svg": "^1.0.8",
"terser-webpack-plugin": "^5.3.6", "terser-webpack-plugin": "^5.3.6",
"typescript": "^4.1.0", "typescript": "^4.1.0",
"webpack": "^5.74.0" "webpack": "^5.74.0"

View File

@ -11,6 +11,7 @@ type ParamLink = 'navigateTo' | 'switchTab' | 'reLaunch' | 'redirectTo'
export const goLink = (path = '', params = {}, way: ParamLink = 'navigateTo') => { export const goLink = (path = '', params = {}, way: ParamLink = 'navigateTo') => {
if (path) { if (path) {
let params_str = Qs.stringify(params) let params_str = Qs.stringify(params)
console.log('params_str==>', params_str)
path = params_str ? path + '?' + params_str : path path = params_str ? path + '?' + params_str : path
Taro[way]({ url: path }) Taro[way]({ url: path })
} }

View File

@ -4,7 +4,7 @@
// export const BASE_URL = `http://10.0.0.5:50001/lymarket` // export const BASE_URL = `http://10.0.0.5:50001/lymarket`
// export const BASE_URL = `http://192.168.0.89:40001/lymarket` // export const BASE_URL = `http://192.168.0.89:40001/lymarket`
// export const BASE_URL = `http://192.168.1.165:40001/lymarket` // 王霞 // export const BASE_URL = `http://192.168.1.165:40001/lymarket` // 王霞
// export const BASE_URL = `https://test.zzfzyc.com/lymarket` // 测试环境 export const BASE_URL = `https://test.zzfzyc.com/lymarket` // 测试环境
// export const BASE_URL = `https://pre.zzfzyc.com/lymarket` // 预发布 // export const BASE_URL = `https://pre.zzfzyc.com/lymarket` // 预发布
// export const BASE_URL = `http://192.168.1.9:40001/lymarket` // 发 // export const BASE_URL = `http://192.168.1.9:40001/lymarket` // 发
// export const BASE_URL = `http://192.168.1.9:50005/lymarket` // 发 // export const BASE_URL = `http://192.168.1.9:50005/lymarket` // 发
@ -14,7 +14,7 @@
// export const BASE_URL = `http://192.168.1.5:40001/lymarket` // 王霞 // export const BASE_URL = `http://192.168.1.5:40001/lymarket` // 王霞
// 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:50001/lymarket` // 杰 // export const BASE_URL = `http://192.168.1.42:50001/lymarket` // 杰
export const BASE_URL = `http://192.168.1.95:40001/lymarket` // 华 // export const BASE_URL = `http://192.168.1.95:40001/lymarket` // 华
// CDN // CDN
// 生成密钥 // 生成密钥

View File

@ -8,6 +8,7 @@ type PropsType = {
iconName: IconNames iconName: IconNames
iconSize?: number iconSize?: number
svg?: boolean svg?: boolean
color?: string,
text?: string text?: string
children?: React.ReactNode children?: React.ReactNode
customClass?: string customClass?: string
@ -16,10 +17,10 @@ type PropsType = {
} }
const IconText: FC<PropsType> = (props) => { const IconText: FC<PropsType> = (props) => {
const { children, svg = false, iconName, iconSize = 40, text = '' } = props const { children, svg = false, iconName, iconSize = 40, text = '', color } = props
return ( return (
<View className={classnames(styles.iconText, props.customStyle, props.customClass)}> <View className={classnames(styles.iconText, props.customStyle, props.customClass)}>
{svg ? <IconFont name={iconName} size={iconSize}></IconFont> : <Text className={classnames('iconfont', iconName, styles.iconfont)}></Text>} {svg ? <IconFont name={iconName} size={iconSize} color={color}></IconFont> : <Text className={classnames('iconfont', iconName, styles.iconfont)}></Text>}
{children ? children : <Text className={classnames(props.textClassName)}>{text}</Text>} {children ? children : <Text className={classnames(props.textClassName)}>{text}</Text>}
</View> </View>
) )

View File

@ -4,7 +4,7 @@ import "./iconfont.scss";
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import classnames from "classnames"; import classnames from "classnames";
const initSvgSize = (36 / 750) * Taro.getSystemInfoSync().windowWidth const SystemWidth = Taro.getSystemInfoSync().windowWidth
const quot = '"' const quot = '"'
function hex2rgb(hex) { function hex2rgb(hex) {
@ -43,7 +43,7 @@ const IconFont:FC<PropsType> = ({
}) => { }) => {
const [colors, setColors] = useState<PropsType['color']>() const [colors, setColors] = useState<PropsType['color']>()
const [isStr, setIsStr] = useState(true) const [isStr, setIsStr] = useState(true)
const [svgSize, setSvgSize] = useState(initSvgSize) const [svgSize, setSvgSize] = useState(() => (size / 750) * SystemWidth)
useEffect(() => { useEffect(() => {
setIsStr(typeof color === 'string') setIsStr(typeof color === 'string')
@ -60,7 +60,7 @@ const IconFont:FC<PropsType> = ({
}, [color]) }, [color])
useEffect(() => { useEffect(() => {
setSvgSize((size / 750) * Taro.getSystemInfoSync().windowWidth) setSvgSize((size / 750) * SystemWidth)
}, [size]) }, [size])
// 也可以使用 if (name === 'xxx') { return <view> } 来渲染但是测试发现在ios下会有问题报错 Maximum call stack啥的。下面这个写法没问题 // 也可以使用 if (name === 'xxx') { return <view> } 来渲染但是测试发现在ios下会有问题报错 Maximum call stack啥的。下面这个写法没问题

View File

@ -76,9 +76,6 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
Text {
font-size: 52px;
}
} }
.drawerOpen { .drawerOpen {

View File

@ -14,15 +14,14 @@ import { EnumSaleMode } from '@/common/Enumerate'
import { useNeedMemoCallback } from '@/use/useCommon' import { useNeedMemoCallback } from '@/use/useCommon'
import { selectList } from '../../config' import { selectList } from '../../config'
import { useShoppingContext } from '../../context' import { useShoppingContext } from '../../context'
import IconFont from '@/components/iconfont/iconfont'
type PropsType = { type PropsType = {
itemData?: ShoppingCartData itemData?: ShoppingCartData
} }
const DrawerButton = memo<{ isOpen: boolean }>(({ isOpen }) => { const DrawerButton = memo<{ isOpen: boolean }>(({ isOpen }) => {
return ( return <View className={styles.drawerButton}>{isOpen ? <IconFont name='icon-shouqi' size={52}></IconFont> : <IconFont name='icon-zhankai' size={52}></IconFont>}</View>
<View className={styles.drawerButton}>{isOpen ? <Text className='iconfont icon-shouqi'></Text> : <Text className='iconfont icon-zhankai'></Text>}</View>
)
}) })
enum BackEndSaleModeListFieldMap { enum BackEndSaleModeListFieldMap {
@ -68,16 +67,21 @@ export default memo<PropsType>((props) => {
const { setChangedCheckbox, currentCheckedPurchaserId, setCurrentCheckedPurchaserId, isManageStatus, setSelectedAmount, colorStore } = useShoppingContext() const { setChangedCheckbox, currentCheckedPurchaserId, setCurrentCheckedPurchaserId, isManageStatus, setSelectedAmount, colorStore } = useShoppingContext()
const memoList = useMemo(() => { const memoList = useMemo(() => {
return itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
itemData?.[BackEndSaleModeListFieldMap[selected]].map((item) => { const selectedList = itemData?.[BackEndSaleModeListFieldMap[selected]].length !==0 ? itemData?.[BackEndSaleModeListFieldMap[selected]] : [{}]
selectedList.forEach((item) => {
console.log('memoList itemData', item) console.log('memoList itemData', item)
// 初始化选中状态 // 初始化选中状态
setChangedCheckbox({ setChangedCheckbox({
purchaserId: itemData.purchaser_id, purchaserId: itemData?.purchaser_id!,
goodsKind: { [item.id]: { id: item.id, estimate_amount: item.estimate_amount, checked: false } }, goodsKind: { [item?.id]: { id: item?.id, estimate_amount: item.estimate_amount, checked: false } },
checked: false, checked: false,
}) })
})
return itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
itemData?.[BackEndSaleModeListFieldMap[selected]].map((item) => {
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} item={item} orderType={selected}></ColorKindItem> return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} item={item} orderType={selected}></ColorKindItem>
}) })
) : ( ) : (

View File

@ -1,4 +1,3 @@
import { EnumSaleMode } from '@/common/Enumerate'
import React, { useRef } from 'react' import React, { useRef } from 'react'
import { useContext } from 'react' import { useContext } from 'react'

View File

@ -1,7 +1,7 @@
import Search from '@/components/search' import Search from '@/components/search'
import { View } from '@tarojs/components' import { View } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro' import Taro, { useDidShow } from '@tarojs/taro'
import React, { FC, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react' import React, { FC, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import styles from './index.module.scss' import styles from './index.module.scss'
import classnames from 'classnames' import classnames from 'classnames'
import IconText from '@/components/iconText' import IconText from '@/components/iconText'
@ -12,7 +12,7 @@ import { formatPriceDiv } from '@/common/format'
import BottomSettleBar from './components/bottomSettleBar' import BottomSettleBar from './components/bottomSettleBar'
import BottomEditBar from './components/bottomEditBar' import BottomEditBar from './components/bottomEditBar'
import { ShoppingCartDeleteApi, ShoppingCartListApi } from '@/api/index' import { ShoppingCartDeleteApi, ShoppingCartListApi } from '@/api/index'
import { dataLoadingStatus } from '@/common/util' import { dataLoadingStatus, debounce } from '@/common/util'
import { ShoppingCart, TriggerCheckboxOptions } from './components/shoppingCart/index' import { ShoppingCart, TriggerCheckboxOptions } from './components/shoppingCart/index'
import { GoodsMeta, Goods, useShoppingCart, useShoppingContext } from './context' import { GoodsMeta, Goods, useShoppingCart, useShoppingContext } from './context'
import { alert, goLink } from '@/common/common' import { alert, goLink } from '@/common/common'
@ -60,7 +60,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
const { fetchData, state } = ShoppingCartListApi() const { fetchData, state } = ShoppingCartListApi()
// 输入了搜索关键字 // 输入了搜索关键字
const getSearchData = useCallback((e) => { const getSearchData = useCallback(e => {
fetchData({ short_name_or_phone: e }) fetchData({ short_name_or_phone: e })
// pageNum.current.page = 1 // pageNum.current.page = 1
// setOrderData(() => ({ list: [], total: 0 })) // setOrderData(() => ({ list: [], total: 0 }))
@ -74,7 +74,8 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
return dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading }) return dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading })
}, [shoppingCartData, state]) }, [shoppingCartData, state])
useDidShow(() => { // useLayoutEffect 执行在DOM更新之后浏览器绘制之前 如果放在 useEffect 里面会产生多一次不必要的回流和重绘,可能会引起视图闪现
useLayoutEffect(() => {
;(async () => { ;(async () => {
await fetchData() await fetchData()
let query = Taro.createSelectorQuery() let query = Taro.createSelectorQuery()
@ -82,7 +83,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
query.select('#shoppingContainer').boundingClientRect() query.select('#shoppingContainer').boundingClientRect()
query.select('#topBar').boundingClientRect() query.select('#topBar').boundingClientRect()
query.select('#bottomBar').boundingClientRect() query.select('#bottomBar').boundingClientRect()
query.exec((res) => { query.exec(res => {
console.log('res==>', res) console.log('res==>', res)
const containerHeight = res[0].height const containerHeight = res[0].height
const topBarHeight = res[1].height const topBarHeight = res[1].height
@ -91,26 +92,29 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
setListHeight(listHeight + 'px') setListHeight(listHeight + 'px')
}) })
})() })()
}) }, [])
useEffect(() => { useEffect(() => {
setShoppingCartData({ list: state.data, total: state.data.length }) setShoppingCartData({ list: state.data, total: state.data.length })
}, [state]) }, [state])
// 结算 // 结算
const handleSettleAccount = () => { const handleSettleAccount = debounce(() => {
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind'] const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
if (!targetGoodsKind) return if (!targetGoodsKind) return Taro.showToast({ title: '请先选择客户', icon: 'error' })
const checkedGoodsKind = Object.values(targetGoodsKind).reduce((prev, item: Goods) => {
if (item.checked) {
return [...prev,item.id]
}
return prev
}, [])
if (checkedGoodsKind.length === 0) return Taro.showToast({ title: '请先选择商品', icon: 'error' })
goLink('/pages/submitOrder/index', { goLink('/pages/submitOrder/index', {
purchaser_id: currentCheckedPurchaserId, purchaser_id: currentCheckedPurchaserId,
sale_mode: currentCheckedSaleMode, sale_mode: currentCheckedSaleMode,
shopping_cart_product_color_list: Object.values(targetGoodsKind).map((item: Goods) => { shopping_cart_product_color_list: JSON.stringify(checkedGoodsKind),
if (item.checked) {
return item.id
}
}),
}) })
} }, 400)
const { fetchData: deleteApi } = ShoppingCartDeleteApi() const { fetchData: deleteApi } = ShoppingCartDeleteApi()
@ -138,7 +142,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
// 全选 // 全选
const handleSelectAllCheckbox = (isSelectAll: boolean) => { const handleSelectAllCheckbox = (isSelectAll: boolean) => {
console.log('handleSelectAllCheckbox', isSelectAll) console.log('handleSelectAllCheckbox', isSelectAll)
const tempObject = colorStore const tempObject = {}
Object.entries(colorStore).forEach(([key, value]) => { Object.entries(colorStore).forEach(([key, value]) => {
tempObject[key] = { tempObject[key] = {
...value, ...value,
@ -155,9 +159,9 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
<Search placeholder='请输入客户名称' showBtn={false} changeOnSearch={getSearchData} debounceTime={300}> <Search placeholder='请输入客户名称' showBtn={false} changeOnSearch={getSearchData} debounceTime={300}>
<View className={styles.flexBox} onClick={onStartToManage}> <View className={styles.flexBox} onClick={onStartToManage}>
{isManageStatus ? ( {isManageStatus ? (
<IconText iconName='icon-guanlidingdan' text='取消' customClass={styles['icon--manage--cancel']} /> <IconText svg iconName='icon-guanlidingdan' text='取消' color='#4581ff' customClass={styles['icon--manage--cancel']} />
) : ( ) : (
<IconText iconName='icon-guanlidingdan' text='管理' /> <IconText svg iconName='icon-guanlidingdan' text='管理' />
)} )}
</View> </View>
</Search> </Search>
@ -174,7 +178,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
</View> </View>
<View id='bottomBar'> <View id='bottomBar'>
{isManageStatus ? ( {isManageStatus ? (
<BottomEditBar onDelete={handleDelete} onSelectCheckbox={(isAll) => handleSelectAllCheckbox(isAll)}></BottomEditBar> <BottomEditBar onDelete={handleDelete} onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}></BottomEditBar>
) : ( ) : (
<BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar> <BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar>
)} )}

View File

@ -12704,10 +12704,10 @@ taro-css-to-react-native@3.3.10:
css-mediaquery "^0.1.2" css-mediaquery "^0.1.2"
postcss-value-parser "^3.3.0" postcss-value-parser "^3.3.0"
taro-iconfont-svg@^1.0.7: taro-iconfont-svg@^1.0.8:
version "1.0.7" version "1.0.8"
resolved "https://registry.yarnpkg.com/taro-iconfont-svg/-/taro-iconfont-svg-1.0.7.tgz#953c842b3cd8865be9ee434b7fb9a86e4f7827d7" resolved "https://registry.yarnpkg.com/taro-iconfont-svg/-/taro-iconfont-svg-1.0.8.tgz#7b9c20a45a8ce53bb737816eaba2d1aebe196c2b"
integrity sha512-sPXvxRQW5EfWLHKdLRgpV2xIId0m7GHhYlSOgGMKqj9a6ibNcATXaklL2KYWfX9ogshi/bdOBTCuPdAqPIgXPg== integrity sha512-nxKx7yGAd+HUVo7FK0PW1AbAuoZgGyUN3tL4kDKeCaGEAxtyEfET2giYt1uTK/eC4WOAZcQnCqyrFM6j8E/wpg==
dependencies: dependencies:
"@tarojs/taro" "^3.5.5" "@tarojs/taro" "^3.5.5"
classnames "^2.3.2" classnames "^2.3.2"