🌈 style(eslint): add eslint rules

This commit is contained in:
xuan
2022-11-26 14:35:05 +08:00
parent f3aa20f049
commit 99a920975f
245 changed files with 14909 additions and 14349 deletions
@@ -1,11 +1,11 @@
import NormalButton from '@/components/normalButton'
import { View, Text } from '@tarojs/components'
import { Text, View } from '@tarojs/components'
import { ShoppingDispatchType, useShoppingDispatch } from '../../context'
import styles from './index.module.scss'
import NormalButton from '@/components/normalButton'
import MCheckbox from '@/components/checkbox'
import { usePropsValue } from '@/use/useCommon'
import { ShoppingDispatchType, useShoppingDispatch } from '../../context'
type PropsType = {
interface PropsType {
onDelete?: Function
onSelectCheckbox?: (bool: boolean) => void
disabled?: boolean
@@ -41,15 +41,16 @@ export default (props: PropsType) => {
status={isSelectAll}
disabled={disabled}
round
size='small'
size="small"
onSelect={selectCallBack}
onClose={closeCallBack}
customStyles={{ color: '$color: #000000, $alpha: 0.6' }}>
customStyles={{ color: '$color: #000000, $alpha: 0.6' }}
>
全选
</MCheckbox>
</View>
<View className={styles.bottomRight}>
<NormalButton round type='danger' size='normal' onClick={handleDelete} customStyles={{ backgroundColor: '#F44761', padding: '0 80rpx' }}>
<NormalButton round type="danger" size="normal" onClick={handleDelete} customStyles={{ backgroundColor: '#F44761', padding: '0 80rpx' }}>
<Text style={{ fontSize: '32rpx' }}>删除</Text>
</NormalButton>
</View>
@@ -1,10 +1,10 @@
import { formatMillionYuan, toDecimal2 } from '@/common/format'
import NormalButton from '@/components/normalButton'
import { View, Text } from '@tarojs/components'
import { Text, View } from '@tarojs/components'
import { memo } from 'react'
import styles from './index.module.scss'
import NormalButton from '@/components/normalButton'
import { formatMillionYuan, toDecimal2 } from '@/common/format'
type PropsType = {
interface PropsType {
amount?: number
onSettleAccount?: Function
}
@@ -25,11 +25,11 @@ export default (props: PropsType) => {
<Text className={styles.money}>{Number(Number(amount)
.toFixed(2))
.toLocaleString()}</Text>
</Text>
</View>
<View className={styles.bottomRight}>
<NormalButton type='primary' round size='normal' onClick={handleSettle} customStyles={{ padding: '0 80rpx' }}>
<NormalButton type="primary" round size="normal" onClick={handleSettle} customStyles={{ padding: '0 80rpx' }}>
<Text style={{ fontSize: '32rpx' }}>结算</Text>
</NormalButton>
</View>
@@ -1,20 +1,23 @@
import { View, Text, Image } from '@tarojs/components'
import { Image, Text, View } from '@tarojs/components'
import type { FC } from 'react'
import { forwardRef, memo, useCallback, useEffect, useState } from 'react'
import classnames from 'classnames'
import { selectList } from '../../config'
import type { ShoppingStateContextValue } from '../../context'
import { Goods, ShoppingDispatchType, useShoppingDispatch, useShoppingState } from '../../context'
import type { ShoppingStore } from '../../context/shoppingStore'
import { events } from '../../context/shoppingStore'
import styles from './index.module.scss'
import MCheckbox from '@/components/checkbox'
import Counter from '@/components/counter'
import { FC, forwardRef, memo, useCallback, useEffect, useState } from 'react'
import classnames from 'classnames'
import styles from './index.module.scss'
import { debounce } from '@/common/util'
import { formatImgUrl, formatMeterDiv, formatMeterMul, formatPriceDiv } from '@/common/format'
import { EnumSaleMode } from '@/common/Enumerate'
import { selectList } from '../../config'
import { AdjestShoppingCartApi } from '@/api/shopping/index'
import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
import { events, ShoppingStore } from '../../context/shoppingStore'
import LabAndImg from '@/components/LabAndImg'
import { usePropsValue } from '@/use/useCommon'
type PropsType = {
interface PropsType {
state?: {
Observer: ShoppingStore
}
@@ -24,31 +27,30 @@ type PropsType = {
onChange?: (isChecked: boolean, goodsId: number) => void
}
const ColorKindItem: FC<PropsType> = props => {
console.log('rerender component ColorKindItem', props);
const ColorKindItem: FC<PropsType> = (props) => {
console.log('rerender component ColorKindItem', props)
const { state, purchaserId, itemData, checked = false } = props
const [isChecked, setCheck] = usePropsValue({
value: checked,
defaultValue: checked,
onChange: (value) => {
props.onChange?.(value, itemData.id)
}
},
})
//格式化数量
const formatCount = itemData => {
// 格式化数量
const formatCount = (itemData) => {
return itemData.sale_mode == EnumSaleMode.Bulk ? itemData.roll : formatMeterDiv(itemData.length)
}
useEffect(() => {
console.log('itemData==>',itemData);
console.log('itemData==>', itemData)
setCount(formatCount(itemData))
}, [itemData.roll, itemData.length])
const [count, setCount] = useState(formatCount(itemData))
//格式化金额
// 格式化金额
const formatPrice = (price: number) => {
return Number(formatPriceDiv(price))
}
@@ -56,10 +58,9 @@ const ColorKindItem: FC<PropsType> = props => {
const handleCountChange = (nextValue: number) => {
setCount(nextValue)
}
//格式化单位
const formatUnit = itemData => {
// 格式化单位
const formatUnit = (itemData) => {
return itemData.sale_mode == EnumSaleMode.Bulk ? '条' : '米'
}
// 选中
@@ -83,7 +84,7 @@ const ColorKindItem: FC<PropsType> = props => {
const { fetchData } = AdjestShoppingCartApi()
// 调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
const getInputValue = useCallback(debounce(async (num) => {
const getInputValue = useCallback(debounce(async(num) => {
console.log('num===>', num)
const targetColor: Record<string, any> = {
roll: 0,
@@ -92,7 +93,8 @@ const ColorKindItem: FC<PropsType> = props => {
if (itemData.sale_mode === EnumSaleMode.Bulk) {
itemData.roll = num
targetColor.roll = num
} else {
}
else {
itemData.length = formatMeterMul(num)
targetColor.length = formatMeterMul(num)
}
@@ -106,7 +108,7 @@ const ColorKindItem: FC<PropsType> = props => {
}
}, 460), [itemData])
const labAndImgObj = useCallback(item => {
const labAndImgObj = useCallback((item) => {
return { lab: item.lab, rgb: item.rgb, texture_url: item.product_color_texture_url }
}, [])
@@ -116,11 +118,12 @@ const ColorKindItem: FC<PropsType> = props => {
onSelect={handleSelect}
onClose={handleClose}
customClassName={classnames(styles.checkbox, isChecked ? styles.selected : '')}
customTextClass={styles.colorKindItem}>
<View className={styles['colorKindItem__left']}>
customTextClass={styles.colorKindItem}
>
<View className={styles.colorKindItem__left}>
<LabAndImg value={labAndImgObj(itemData)} />
</View>
<View className={styles['colorKindItem__center']}>
<View className={styles.colorKindItem__center}>
<Text className={styles['colorKindItem__center--title']}>
{itemData.product_code}# {itemData.product_name}
</Text>
@@ -129,7 +132,7 @@ const ColorKindItem: FC<PropsType> = props => {
<Text className={styles['colorKindItem__center--description']}>{itemData.product_color_name}</Text>
</View>
</View>
<View className={styles['colorKindItem__right']}>
<View className={styles.colorKindItem__right}>
<View className={styles['colorKindItem__right--price']}>¥ {formatPrice(itemData.sale_price)}/{itemData.sale_mode == EnumSaleMode.Plate ? '米' : 'kg'}</View>
<View className={styles['colorKindItem__right--counter']}>
<Counter
@@ -152,21 +155,21 @@ const ColorKindItem: FC<PropsType> = props => {
// 那么当 context 内的 value 被更新的时候,react 只会强制渲染 Wrapper
const withStateSlice = (comp, slice) => {
const MemoComp = memo(comp, (prevProps, nextProps) => {
let needMemo = true
let needMemo = true
if (prevProps.itemData !== nextProps.itemData) {
console.log('itemData 有变化');
console.log('itemData 有变化')
needMemo = false
}
if (prevProps.state.Observer !== nextProps.state.Observer) {
console.log('Observer 有变化');
console.log('Observer 有变化')
needMemo = false
}
if (prevProps.checked !== nextProps.checked) {
console.log('checked 有变化', prevProps.checked, nextProps.checked);
console.log('checked 有变化', prevProps.checked, nextProps.checked)
needMemo = false
}
if (prevProps.purchaserId !== nextProps.purchaserId) {
console.log('purchaserId 有变化');
console.log('purchaserId 有变化')
needMemo = false
}
return needMemo
@@ -1,19 +1,23 @@
import produce from 'immer'
import { FC, ReactNode, useEffect, useMemo, useReducer, useRef } from 'react'
import {
import type { FC, ReactNode } from 'react'
import { useEffect, useMemo, useReducer, useRef } from 'react'
import type {
ColorStore,
GoodsMeta,
ShoppingAction,
ShoppingDispatchContext,
ShoppingDispatchContextValue,
ShoppingStateContextValue,
} from '../../context'
import {
ShoppingDispatchContext,
ShoppingDispatchType,
shoppingReducer,
ShoppingStateContext,
throwError,
shoppingReducer, throwError,
} from '../../context'
import { ColorStore, ShoppingStateContextValue } from '../../context'
import { ShoppingStore } from '../../context/shoppingStore'
export type TriggerCheckboxOptions = {
export interface TriggerCheckboxOptions {
multipleSelection: GoodsMeta['multipleSelection']
setSelectedAmount: ShoppingDispatchContextValue['UPDATE_SELECTED_AMOUNT']
}
@@ -24,7 +28,7 @@ export interface ShoppingCartPropsType {
children?: ReactNode
}
// 购物车上下文组件
export const ShoppingProvider: FC<ShoppingCartPropsType> = props => {
export const ShoppingProvider: FC<ShoppingCartPropsType> = (props) => {
const { children, onTriggerCheckbox, initialValues } = props
const onTriggerCheckboxRef = useRef(onTriggerCheckbox)
@@ -1,24 +1,27 @@
import { Text, View } from '@tarojs/components'
import { FC, forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState, useTransition } from 'react'
import styles from './index.module.scss'
import { nextTick } from '@tarojs/taro'
import type { FC } from 'react'
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState, useTransition } from 'react'
import classnames from 'classnames'
import classNames from 'classnames'
import produce, { setAutoFreeze } from 'immer'
import ColorKindItem from '../colorKindItem'
import { selectList } from '../../config'
import type { Goods, GoodsMeta, ShoppingStateContextValue } from '../../context'
import { ShoppingDispatchType, useShoppingDispatch, useShoppingState } from '../../context'
import type { ShoppingStore } from '../../context/shoppingStore'
import { events } from '../../context/shoppingStore'
import styles from './index.module.scss'
import { formatMeterDiv } from '@/common/format'
import LayoutBlock from '@/components/layoutBlock'
import Tag from '@/components/tag'
import Divider from '@/components/divider'
import ColorKindItem from '../colorKindItem'
import { EnumSaleMode } from '@/common/Enumerate'
import { selectList } from '../../config'
import { Goods, GoodsMeta, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
import IconFont from '@/components/iconfont/iconfont'
import { alert, isEmptyObject } from '@/common/common'
import classNames from 'classnames'
import LoadingCard from '@/components/loadingCard'
import { ShoppingCartListApi } from '@/api'
import { events, ShoppingStore } from '../../context/shoppingStore'
import { usePropsValue } from '@/use/useCommon'
import produce, { setAutoFreeze } from 'immer'
import { nextTick } from '@tarojs/taro'
interface ButtonPropsType {
isActive: boolean
@@ -28,7 +31,7 @@ interface ButtonPropsType {
}
type OperationType = 'add' | 'delete'
// 订单类型
const SaleModeButton: FC<ButtonPropsType> = props => {
const SaleModeButton: FC<ButtonPropsType> = (props) => {
const { onClick, children, isActive = false, customStyle } = props
const handleClick = () => {
onClick?.()
@@ -43,7 +46,7 @@ const SaleModeButton: FC<ButtonPropsType> = props => {
const DrawerButton = memo<{ isOpen: boolean }>(({ isOpen }) => {
return (
<View className={styles.drawerButton}>
{isOpen ? <IconFont name='icon-shouqi' size={52}></IconFont> : <IconFont name='icon-zhankai' size={52}></IconFont>}
{isOpen ? <IconFont name="icon-shouqi" size={52}></IconFont> : <IconFont name="icon-zhankai" size={52}></IconFont>}
</View>
)
})
@@ -54,7 +57,7 @@ enum BackEndSaleModeListFieldMap {
weight_cut_color_list = 2,
}
type PropsType = {
interface PropsType {
itemData?: ShoppingCartData
state?: {
multipleSelection?: GoodsMeta['multipleSelection']
@@ -63,7 +66,7 @@ type PropsType = {
}
}
const ShoppingCartItem: FC<PropsType> = props => {
const ShoppingCartItem: FC<PropsType> = (props) => {
const { state } = props
console.log('rerender component ShoppingCartItem', props)
@@ -84,7 +87,7 @@ const ShoppingCartItem: FC<PropsType> = props => {
const [selected, setSelect] = useState<EnumSaleMode>(0)
const onSelectOrderType = (type: EnumSaleMode) => {
if (isPending) return
if (isPending) { return }
setSelect(type)
dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_SALEMODE, data: type })
// 重置预估金额
@@ -92,7 +95,6 @@ const ShoppingCartItem: FC<PropsType> = props => {
dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION_STATUS, data: false })
}
const handleClickLayout = () => {
if (currentCheckedPurchaserId === itemData?.purchaser_id) {
return
@@ -108,7 +110,7 @@ const ShoppingCartItem: FC<PropsType> = props => {
// 统计已选面料
const materialChecked = useMemo(() => {
if (!multipleSelection || isEmptyObject(multipleSelection)) return 0
if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 }
return new Set(
Object.values(multipleSelection)?.reduce((prev, item: Goods) => {
if (item.sale_mode === selected) {
@@ -121,8 +123,8 @@ const ShoppingCartItem: FC<PropsType> = props => {
// 统计已选颜色
const colorChecked = useMemo(() => {
console.log('colorChecked item',multipleSelection);
if (!multipleSelection || isEmptyObject(multipleSelection)) return 0
console.log('colorChecked item', multipleSelection)
if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 }
return new Set(
Object.values(multipleSelection).reduce((prev, item: Goods) => {
if (item.sale_mode === selected) {
@@ -135,8 +137,8 @@ const ShoppingCartItem: FC<PropsType> = props => {
// 统计已选条数 / 米数
const lengthOrRollChecked = useMemo(() => {
console.log('lengthOrRollChecked item',multipleSelection);
if (!multipleSelection || isEmptyObject(multipleSelection)) return 0
console.log('lengthOrRollChecked item', multipleSelection)
if (!multipleSelection || isEmptyObject(multipleSelection)) { return 0 }
return (
Object.values(multipleSelection).reduce((prev, item: Goods) => {
return prev + item.count
@@ -148,37 +150,38 @@ const ShoppingCartItem: FC<PropsType> = props => {
const { fetchData } = ShoppingCartListApi()
// 更新当前客户的多选项
const updatePurchaserMultipleSelection = (purchaserId, payload, operationType: OperationType, goodsId: number) => {
if(operationType === 'add'){
if (operationType === 'add') {
dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: {
purchaserId: purchaserId,
multipleSelection: produce(multipleSelection, (multipleSelectionDraft) =>{
if(!multipleSelectionDraft){
purchaserId,
multipleSelection: produce(multipleSelection, (multipleSelectionDraft) => {
if (!multipleSelectionDraft) {
return {
[goodsId]: payload
[goodsId]: payload,
}
}else{
}
else {
multipleSelectionDraft[goodsId] = payload
}
}),
},
})
}else if(operationType === 'delete'){
const temp = {...multipleSelection}
}
else if (operationType === 'delete') {
const temp = { ...multipleSelection }
delete temp?.[goodsId]
dispatch({
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
data: {
purchaserId: purchaserId,
purchaserId,
multipleSelection: temp,
},
})
}
}
// 发布订阅
useEffect(()=>{
useEffect(() => {
events.on('updatePurchaserMultipleSelection', updatePurchaserMultipleSelection)
return () => {
events.off('updatePurchaserMultipleSelection', updatePurchaserMultipleSelection)
@@ -186,9 +189,9 @@ const ShoppingCartItem: FC<PropsType> = props => {
}, [updatePurchaserMultipleSelection])
// 发布订阅
useEffect(() => {
console.log('update multipleSelection',multipleSelection);
const unsubscribe = state?.Observer?.subscribe(async id => {
if (itemData?.purchaser_id !== id) return
console.log('update multipleSelection', multipleSelection)
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,
@@ -235,7 +238,8 @@ const ShoppingCartItem: FC<PropsType> = props => {
},
})
setItemData(() => res.data[0])
}else{
}
else {
alert.error('请求失败')
}
})
@@ -247,12 +251,13 @@ const ShoppingCartItem: FC<PropsType> = props => {
<LayoutBlock
circle
customClassName={classnames(styles.layout, itemData?.purchaser_id === currentCheckedPurchaserId ? styles.selected : '')}
onClick={handleClickLayout}>
onClick={handleClickLayout}
>
<View className={classNames(styles.checkbox, 'flex-row', 'justify-between')} onClick={handleOpenDetail}>
<View className={styles.topItem}>
<View className='flex-row items-center'>
<View className="flex-row items-center">
<View className={styles.topTitle}>{itemData?.purchaser_name}</View>
<Tag type='info' size='normal' circle customStyle={{ backgroundColor: '#f0f0f0', borderColor: 'transparent' }} plain>
<Tag type="info" size="normal" circle customStyle={{ backgroundColor: '#f0f0f0', borderColor: 'transparent' }} plain>
{itemData?.sale_user_name}
</Tag>
</View>
@@ -278,19 +283,22 @@ const ShoppingCartItem: FC<PropsType> = props => {
<SaleModeButton
customStyle={{ padding: '0 50rpx' }}
isActive={selected === EnumSaleMode.Bulk}
onClick={() => onSelectOrderType(EnumSaleMode.Bulk)}>
onClick={() => onSelectOrderType(EnumSaleMode.Bulk)}
>
大货
</SaleModeButton>
<SaleModeButton
customStyle={{ padding: '0 50rpx' }}
isActive={selected === EnumSaleMode.Plate}
onClick={() => onSelectOrderType(EnumSaleMode.Plate)}>
onClick={() => onSelectOrderType(EnumSaleMode.Plate)}
>
剪板
</SaleModeButton>
<SaleModeButton
customStyle={{ padding: '0 50rpx' }}
isActive={selected === EnumSaleMode.BulkCut}
onClick={() => onSelectOrderType(EnumSaleMode.BulkCut)}>
onClick={() => onSelectOrderType(EnumSaleMode.BulkCut)}
>
散剪
</SaleModeButton>
</View>
@@ -299,7 +307,7 @@ const ShoppingCartItem: FC<PropsType> = props => {
<Divider customClassName={styles.line}></Divider>
<View className={classnames(styles.orderTitle, 'justify-between')}>
<Text>布料颜色</Text>
<Tag type='danger' size='normal' circle plain>
<Tag type="danger" size="normal" circle plain>
{selectList[selected].title}单位:{selectList[selected].unit}
</Tag>
</View>
@@ -327,7 +335,7 @@ interface GoodsListPropType {
isPending: boolean
startTransition: React.TransitionStartFunction
}
const GoodsList = memo<GoodsListPropType>(props => {
const GoodsList = memo<GoodsListPropType>((props) => {
const { itemData, selected, isPending, startTransition, multipleSelection } = props
const prevMultipleSelection = useRef(multipleSelection)
const currentSelected = useRef<EnumSaleMode | null>(null)
@@ -338,49 +346,51 @@ const GoodsList = memo<GoodsListPropType>(props => {
// 使用 produce 更新特定的 ColorKindItem
const updateSpecifiedComponent = () => {
let newId
if(multipleSelection && prevMultipleSelection.current !== multipleSelection){
for(let key in multipleSelection){
if(!prevMultipleSelection.current?.hasOwnProperty(key)){
if (multipleSelection && prevMultipleSelection.current !== multipleSelection) {
for (const key in multipleSelection) {
if (!prevMultipleSelection.current?.hasOwnProperty(key)) {
newId = key
break
}
}
}
}
console.log('multipleSelection==+>',multipleSelection);
console.log('currentSelected', currentSelected.current, selected);
console.log('component',component);
if(component){
if(itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0){
console.log('multipleSelection==+>', multipleSelection)
console.log('currentSelected', currentSelected.current, selected)
console.log('component', component)
if (component) {
if (itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0) {
setComponent(produce(component, (draft) => {
console.log('prev',component);
const index = (draft as unknown as any[]).findIndex((item)=> item.key === newId)
console.log('index',index)
if(index !== -1) {
const item = itemData?.[BackEndSaleModeListFieldMap[selected]].find(item => {
console.log('prev', component)
const index = (draft as unknown as any[]).findIndex(item => item.key === newId)
console.log('index', index)
if (index !== -1) {
const item = itemData?.[BackEndSaleModeListFieldMap[selected]].find((item) => {
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>
}
}))
}else{
}
else {
setComponent(<View className={styles.noList}>暂无数据</View>)
}
}
prevMultipleSelection.current = multipleSelection
}
// 更新 GoodsList 组件
const updateComponent = () => {
setComponent(
() => itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => {
console.log('item===>', item, multipleSelection?.hasOwnProperty(item.id))
return <ColorKindItem checked={multipleSelection?.hasOwnProperty(item.id)} purchaserId={itemData.purchaser_id} key={item.id} itemData={item}></ColorKindItem>
})
) : (
<View className={styles.noList}>暂无数据</View>
)
() => itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0
? (
itemData?.[BackEndSaleModeListFieldMap[selected]].map((item) => {
console.log('item===>', item, multipleSelection?.hasOwnProperty(item.id))
return <ColorKindItem checked={multipleSelection?.hasOwnProperty(item.id)} purchaserId={itemData.purchaser_id} key={item.id} itemData={item}></ColorKindItem>
})
)
: (
<View className={styles.noList}>暂无数据</View>
),
)
prevMultipleSelection.current = multipleSelection
}
@@ -406,11 +416,12 @@ const GoodsList = memo<GoodsListPropType>(props => {
data: {
purchaserId: itemData?.purchaser_id!,
goodsKind: newGoodsKind,
multipleSelection: multipleSelection,
multipleSelection,
},
})
updateComponent()
} else {
}
else {
currentSelected.current = selected
// 重新把当前的选中状态赋值给ref 作为下一次比较的旧状态
dispatch({
@@ -427,13 +438,15 @@ const GoodsList = memo<GoodsListPropType>(props => {
return (
<>
{isPending ? (
<View className={styles.noList} style={{margin: '60rpx 0'}}>
<LoadingCard />
</View>
) : (
component
)}
{isPending
? (
<View className={styles.noList} style={{ margin: '60rpx 0' }}>
<LoadingCard />
</View>
)
: (
component
)}
</>
)
})
@@ -445,27 +458,27 @@ const withStateSlice = (comp, slice) => {
if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) {
needMemo = false
}
if(prevProps.itemData.purchaser_name === 'JENNIE'){
console.log('------withStateSlice props-------');
console.log('withStateSlice props prevProps', prevProps);
console.log('withStateSlice props prevProps comparison itemData', prevProps.itemData === nextProps.itemData);
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 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 state', prevProps.state === nextProps.state);
console.log('------withStateSlice props-------');
if (prevProps.itemData.purchaser_name === 'JENNIE') {
console.log('------withStateSlice props-------')
console.log('withStateSlice props prevProps', prevProps)
console.log('withStateSlice props prevProps comparison itemData', prevProps.itemData === nextProps.itemData)
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 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 state', prevProps.state === nextProps.state)
console.log('------withStateSlice props-------')
}
if (prevProps.state.Observer !== nextProps.state.Observer) {
console.log('Observer 有变化');
console.log('Observer 有变化')
needMemo = false
}
if (prevProps.state.multipleSelection !== nextProps.state.multipleSelection) {
console.log('multipleSelection 有变化');
console.log('multipleSelection 有变化')
needMemo = false
}
if (prevProps.state.currentCheckedPurchaserId !== nextProps.state.currentCheckedPurchaserId) {
console.log('currentCheckedPurchaserId 有变化');
console.log('currentCheckedPurchaserId 有变化')
needMemo = false
}
return needMemo
@@ -478,7 +491,7 @@ const withStateSlice = (comp, slice) => {
}
const ShoppingCartItemWithStateSlice = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({
multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.['multipleSelection'],
multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.multipleSelection,
currentCheckedPurchaserId: state.currentCheckedPurchaserId,
Observer: state.Observer,
}))
+15 -20
View File
@@ -1,8 +1,8 @@
import { EnumSaleMode } from '@/common/Enumerate'
import produce from 'immer'
import React, { Dispatch } from 'react'
import { useContext } from 'react'
import { ShoppingStore } from './shoppingStore'
import type { Dispatch } from 'react'
import React, { useContext } from 'react'
import type { ShoppingStore } from './shoppingStore'
import type { EnumSaleMode } from '@/common/Enumerate'
/**
* 456: {
@@ -30,11 +30,9 @@ import { ShoppingStore } from './shoppingStore'
* }
* }
*/
export type ColorStore = {
[purchaserId: GoodsMeta['purchaserId']]: GoodsMeta
}
export type ColorStore = Record<GoodsMeta['purchaserId'], GoodsMeta>
export type Goods = {
export interface Goods {
id: number
product_code: number // 面料编号
product_color_code: number // 颜色编号
@@ -47,9 +45,7 @@ export type Goods = {
// 分组
export interface GoodsMeta {
purchaserId: number
goodsKind?: {
[id: Goods['id']]: Goods
}
goodsKind?: Record<Goods['id'], Goods>
multipleSelection?: GoodsMeta['goodsKind']
}
@@ -83,13 +79,12 @@ export interface ShoppingDispatchContextValue {
[ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX]: (amount: React.SetStateAction<ShoppingStateContextValue['selectedAmount']>) => void
}
export type ShoppingAction = {
export interface ShoppingAction {
type: ShoppingDispatchType
data?: any
}
export const shoppingReducer = produce((draft: ShoppingStateContextValue, action: ShoppingAction)=>{
export const shoppingReducer = produce((draft: ShoppingStateContextValue, action: ShoppingAction) => {
const { type, data } = action
switch (type) {
case ShoppingDispatchType.UPDATE_MANAGE_STATUS: {
@@ -117,14 +112,15 @@ export const shoppingReducer = produce((draft: ShoppingStateContextValue, action
break
}
case ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX: {
if(!draft.colorStore[data.purchaserId]){
if (!draft.colorStore[data.purchaserId]) {
draft.colorStore[data.purchaserId] = {
purchaserId: data.purchaserId,
goodsKind: data.goodsKind,
multipleSelection: data.multipleSelection
multipleSelection: data.multipleSelection,
}
}else{
draft.colorStore[data.purchaserId] = produce(draft.colorStore[data.purchaserId], purchaserDraft => {
}
else {
draft.colorStore[data.purchaserId] = produce(draft.colorStore[data.purchaserId], (purchaserDraft) => {
purchaserDraft.purchaserId = data.purchaserId
purchaserDraft.goodsKind = { ...purchaserDraft.goodsKind, ...data.goodsKind }
purchaserDraft.multipleSelection = data.multipleSelection ? data.multipleSelection : purchaserDraft?.multipleSelection
@@ -136,7 +132,6 @@ export const shoppingReducer = produce((draft: ShoppingStateContextValue, action
throwError()
}
})
export const ShoppingStateContext = React.createContext<ShoppingStateContextValue | null>(null)
@@ -160,7 +155,7 @@ export function useShoppingDispatch() {
export function useWatch(purchaserId: GoodsMeta['purchaserId'], id: number) {
const { colorStore } = useShoppingState()
return id ? colorStore[purchaserId]['goodsKind']![id] : colorStore[purchaserId]['goodsKind']
return id ? colorStore[purchaserId].goodsKind![id] : colorStore[purchaserId].goodsKind
}
export interface ShoppingCartAction {
+7 -3
View File
@@ -1,8 +1,9 @@
// 用于优化数据流 结合发布订阅 更新组件内部状态可以组件自己处理
import { Events } from "@tarojs/taro"
import { ColorStore } from "."
import { Events } from '@tarojs/taro'
import type { ColorStore } from '.'
export const events = new Events()
export type SubscribeCallback = (changedGoods: any) => void
@@ -16,10 +17,12 @@ export class ShoppingStore {
constructor(initialValue?: any) {
initialValue && this.updateStore(initialValue)
}
// 更新全局缓存
private updateStore(nextStore: ColorStore) {
this.store = nextStore
}
// 订阅
subscribe(callback: SubscribeCallback) {
this.observers.push(callback)
@@ -30,10 +33,11 @@ export class ShoppingStore {
})
}
}
// 通知
notify(changedGoods: any) {
// 循环调用
this.observers.forEach(callback => {
this.observers.forEach((callback) => {
callback(changedGoods)
})
}
+2 -2
View File
@@ -1,4 +1,4 @@
export default {
navigationBarTitleText: '购物页面',
navigationBarTitleText: '购物页面',
}
+62 -53
View File
@@ -1,19 +1,21 @@
import Search from '@/components/search'
import { View } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro'
import { FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useTransition } from 'react'
import styles from './index.module.scss'
import type { FC } from 'react'
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useTransition } from 'react'
import classnames from 'classnames'
import IconText from '@/components/iconText'
import InfiniteScroll from '@/components/infiniteScroll'
import styles from './index.module.scss'
import ItemList from './components/shoppingCartItem/index'
import { formatPriceDiv } from '@/common/format'
import BottomSettleBar from './components/bottomSettleBar'
import BottomEditBar from './components/bottomEditBar'
import { ShoppingCartDeleteApi, ShoppingCartListApi } from '@/api/index'
import { dataLoadingStatus, debounce, getFilterData } from '@/common/util'
import { ShoppingProvider } from './components/shoppingCart/index'
import { Goods, ShoppingDispatchType, useShoppingDispatch, useShoppingState } from './context'
import type { Goods } from './context'
import { ShoppingDispatchType, useShoppingDispatch, useShoppingState } from './context'
import { dataLoadingStatus, debounce, getFilterData } from '@/common/util'
import { ShoppingCartDeleteApi, ShoppingCartListApi } from '@/api/index'
import { formatPriceDiv } from '@/common/format'
import InfiniteScroll from '@/components/infiniteScroll'
import IconText from '@/components/iconText'
import Search from '@/components/search'
import { alert, goLink, isEmptyObject } from '@/common/common'
export const Shopping: FC = memo(() => {
@@ -22,12 +24,13 @@ export const Shopping: FC = memo(() => {
console.log('handleTriggerCheckbox==>', multipleSelection)
if (multipleSelection) {
const result = Object.values(multipleSelection).reduce((prev: number , value: Goods) => {
const result = Object.values(multipleSelection).reduce((prev: number, value: Goods) => {
return prev + Number(formatPriceDiv(value.estimate_amount))
}, 0) as number
// 同步修改上下文的 预估金额
setSelectedAmount(result)
} else {
}
else {
setSelectedAmount(0)
}
}
@@ -43,7 +46,7 @@ interface SearchOptions {
}
const ShoppingCartContainer: FC = () => {
let isFirst = useRef(true)
const isFirst = useRef(true)
const { isMultipleSelection, isManageStatus, selectedAmount, currentCheckedPurchaserId, currentCheckedSaleMode, colorStore } = useShoppingState()
@@ -82,8 +85,8 @@ const ShoppingCartContainer: FC = () => {
}, [searchOptions])
// 输入了搜索关键字
const getSearchData = useCallback(e => {
console.log('getSearchData===>',e);
const getSearchData = useCallback((e) => {
console.log('getSearchData===>', e)
setSearchOptions({ short_name_or_phone: e })
}, [])
@@ -92,8 +95,7 @@ const ShoppingCartContainer: FC = () => {
total: number
}>({ list: [], total: 0 })
//数据加载状态
// 数据加载状态
const statusMore = useMemo(() => {
console.log('shoppingCartData==>', shoppingCartData, state)
const status = dataLoadingStatus({
@@ -107,22 +109,22 @@ const ShoppingCartContainer: FC = () => {
// useLayoutEffect 执行在DOM更新之后,浏览器绘制之前 如果放在 useEffect 里面会产生多一次不必要的回流和重绘,可能会引起视图闪现
useLayoutEffect(() => {
;(async () => {
(async() => {
console.log('useLayoutEffect')
await fetchData(getFilterData(searchOptions))
isFirst.current = false
let query = Taro.createSelectorQuery()
const query = Taro.createSelectorQuery()
console.log('query', query)
query.select('#shoppingContainer').boundingClientRect()
query.select('#topBar').boundingClientRect()
query.select('#bottomBar').boundingClientRect()
query.exec(res => {
query.exec((res) => {
console.log('res==>', res)
const containerHeight = res[0].height
const topBarHeight = res[1].height
const bottomBarHeight = res[2].height
const listHeight = containerHeight - topBarHeight - bottomBarHeight
listHeightRef.current = listHeight + 'px'
listHeightRef.current = `${listHeight}px`
// 强制刷新
setForceUpdate({})
})
@@ -131,19 +133,19 @@ const ShoppingCartContainer: FC = () => {
useEffect(() => {
if (state.success) {
console.log('fetch success', state);
console.log('fetch success', state)
setShoppingCartData({ list: state.data.list, total: state.data.total })
}
}, [state])
// 结算
const handleSettleAccount = debounce(() => {
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection']
if (!multipleSelection) return alert.error('请先选择客户')
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.multipleSelection
if (!multipleSelection) { return alert.error('请先选择客户') }
const checkedGoodsKind = Object.values(multipleSelection).reduce((prev, item: Goods) => {
return [...prev, item.id]
}, [])
if (checkedGoodsKind.length === 0) return alert.error('请先选择商品')
if (checkedGoodsKind.length === 0) { return alert.error('请先选择商品') }
goLink('/pages/submitOrder/index', {
purchaser_id: currentCheckedPurchaserId,
sale_mode: currentCheckedSaleMode,
@@ -155,16 +157,16 @@ const ShoppingCartContainer: FC = () => {
const { fetchData: deleteApi } = ShoppingCartDeleteApi()
// 批量某个客户的删除商品
const handleDelete = async () => {
const handleDelete = async() => {
const multipleSelection = colorStore?.[currentCheckedPurchaserId].multipleSelection
let checked: Goods[] = Object.values(multipleSelection!)
const checked: Goods[] = Object.values(multipleSelection!)
if (checked.length === 0) {
return alert.error('请选择商品')
}
console.log('checked==>', checked)
Taro.showModal({
title: '要删除这些商品吗?',
success: async function(res) {
async success(res) {
if (res.confirm) {
alert.showLoading('删除中')
const res = await deleteApi({
@@ -184,7 +186,8 @@ const ShoppingCartContainer: FC = () => {
})
fetchData(searchOptions)
// Observer.notify(currentCheckedPurchaserId)
} else {
}
else {
alert.hideLoading()
alert.none(res.msg)
}
@@ -195,7 +198,7 @@ const ShoppingCartContainer: FC = () => {
// 全选
const handleSelectAllCheckbox = (isSelectAll: boolean) => {
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId].goodsKind
if (!targetGoodsKind) return alert.error('请先选择客户')
if (!targetGoodsKind) { return alert.error('请先选择客户') }
const tempObject = { ...targetGoodsKind }
dispatch({
@@ -211,13 +214,14 @@ const ShoppingCartContainer: FC = () => {
const [refreshStatus, setRefreshStatus] = useState(false)
// 下拉刷新
const handleRefresh = async () => {
const handleRefresh = async() => {
setRefreshStatus(true)
const res = await fetchData(getFilterData(searchOptions))
if (res.success) {
setRefreshStatus(false)
alert.success('刷新成功')
} else {
}
else {
alert.error('刷新失败')
setRefreshStatus(false)
}
@@ -225,40 +229,45 @@ const ShoppingCartContainer: FC = () => {
// const [isPending, startTransition] = useTransition()
return (
<View className={classnames('flex-col', styles.shopping)} id='shoppingContainer'>
<View className={styles['shopping--topBar']} id='topBar'>
<Search placeholder='请输入客户名称' showBtn={false} changeOnSearch={getSearchData}>
<View className={classnames('flex-col', styles.shopping)} id="shoppingContainer">
<View className={styles['shopping--topBar']} id="topBar">
<Search placeholder="请输入客户名称" showBtn={false} changeOnSearch={getSearchData}>
<View className={styles.flexBox} onClick={onStartToManage}>
{isManageStatus ? (
<IconText svg iconName='icon-guanlidingdan' text='取消' color='#4581ff' customClass={styles['icon--manage--cancel']} />
) : (
<IconText svg iconName='icon-guanlidingdan' text='管理' />
)}
{isManageStatus
? (
<IconText svg iconName="icon-guanlidingdan" text="取消" color="#4581ff" customClass={styles['icon--manage--cancel']} />
)
: (
<IconText svg iconName="icon-guanlidingdan" text="管理" />
)}
</View>
</Search>
</View>
<View className={classnames('flex-item', 'flex-col', styles['shopping--context'])}>
<View id='shoppingListContainer' className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: listHeightRef.current }}>
<InfiniteScroll statusMore={statusMore} refresherEnabled={true} selfOnRefresherRefresh={handleRefresh} refresherTriggered={refreshStatus}>
<View id="shoppingListContainer" className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: listHeightRef.current }}>
<InfiniteScroll statusMore={statusMore} refresherEnabled selfOnRefresherRefresh={handleRefresh} refresherTriggered={refreshStatus}>
{
!!shoppingCartData?.list?.length &&
shoppingCartData?.list?.map((item, index) => {
!!shoppingCartData?.list?.length
&& shoppingCartData?.list?.map((item, index) => {
return <ItemList itemData={item} key={index}></ItemList>
})
}
</InfiniteScroll>
</View>
</View>
<View id='bottomBar'>
{isManageStatus ? (
<BottomEditBar
disabled={currentCheckedPurchaserId < 0}
isSelectAll={isMultipleSelection}
onDelete={handleDelete}
onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}></BottomEditBar>
) : (
<BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar>
)}
<View id="bottomBar">
{isManageStatus
? (
<BottomEditBar
disabled={currentCheckedPurchaserId < 0}
isSelectAll={isMultipleSelection}
onDelete={handleDelete}
onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}
></BottomEditBar>
)
: (
<BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar>
)}
</View>
</View>
)
+2 -2
View File
@@ -7,8 +7,8 @@ interface ShoppingCartData {
sale_user_id: number
sale_user_name: string
bulk_color_list: ColorList
length_cut_color_list: ColorList // 剪板
weight_cut_color_list: ColorList // 散剪
length_cut_color_list: ColorList // 剪板
weight_cut_color_list: ColorList // 散剪
[Property: string]: any
}
interface ColorList {