289 lines
11 KiB
TypeScript
289 lines
11 KiB
TypeScript
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 classnames from 'classnames'
|
||
import IconText from '@/components/iconText'
|
||
import InfiniteScroll from '@/components/infiniteScroll'
|
||
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 { alert, goLink, isEmptyObject } from '@/common/common'
|
||
import LoadingCard from '@/components/loadingCard'
|
||
|
||
export const Shopping: FC = memo(() => {
|
||
// 计算总的预估金额
|
||
const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => {
|
||
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
|
||
console.log('handleTriggerCheckbox==>', colorStore)
|
||
|
||
if (targetGoodsKind) {
|
||
const result = Object.values(targetGoodsKind).reduce((prev: number, value: Goods) => {
|
||
if (value.checked) {
|
||
return prev + Number(formatPriceDiv(value.estimate_amount))
|
||
}
|
||
return prev
|
||
}, 0) as number
|
||
console.log('result==>', result)
|
||
// 同步修改上下文的 预估金额
|
||
setSelectedAmount(result)
|
||
} else {
|
||
setSelectedAmount(0)
|
||
}
|
||
}
|
||
return (
|
||
<ShoppingProvider onTriggerCheckbox={handleTriggerCheckbox}>
|
||
<ShoppingCartContainer />
|
||
</ShoppingProvider>
|
||
)
|
||
})
|
||
|
||
interface InternalContainer {}
|
||
|
||
const ShoppingCartContainer: FC<InternalContainer> = () => {
|
||
let isFirst = useRef(true)
|
||
|
||
const { isManageStatus, selectedAmount, currentCheckedPurchaserId, currentCheckedSaleMode, colorStore } = useShoppingState()
|
||
|
||
const dispatch = useShoppingDispatch()
|
||
|
||
// 管理
|
||
const onStartToManage = () => {
|
||
dispatch({ type: ShoppingDispatchType.UPDATE_MANAGE_STATUS, data: !isManageStatus })
|
||
}
|
||
|
||
const listHeightRef = useRef('auto')
|
||
|
||
const { fetchData, state } = ShoppingCartListApi()
|
||
|
||
const [searchOptions, setSearchOptions] = useState({
|
||
short_name_or_phone: '',
|
||
})
|
||
useDidShow(() => {
|
||
if (!isFirst.current) {
|
||
fetchData(searchOptions)
|
||
}
|
||
})
|
||
console.log('Rerender component: ShoppingCartContainer')
|
||
|
||
useEffect(() => {
|
||
console.log('useEffect fetchData')
|
||
if (!isEmptyObject(getFilterData(searchOptions))) {
|
||
fetchData(searchOptions)
|
||
}
|
||
}, [searchOptions])
|
||
|
||
// 输入了搜索关键字
|
||
const getSearchData = useCallback(e => {
|
||
setSearchOptions(prev => ({ ...prev, short_name_or_phone: e }))
|
||
}, [])
|
||
|
||
const [shoppingCartData, setShoppingCartData] = useState<{ list: ShoppingCartData[]; total: number }>({ list: [], total: 0 })
|
||
|
||
//数据加载状态
|
||
const statusMore = useMemo(() => {
|
||
const status = dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading })
|
||
console.log('status==>', status)
|
||
return status
|
||
}, [shoppingCartData, state])
|
||
|
||
// useLayoutEffect 执行在DOM更新之后,浏览器绘制之前 如果放在 useEffect 里面会产生多一次不必要的回流和重绘,可能会引起视图闪现
|
||
useLayoutEffect(() => {
|
||
;(async () => {
|
||
console.log('useLayoutEffect')
|
||
await fetchData()
|
||
isFirst.current = false
|
||
let query = Taro.createSelectorQuery()
|
||
console.log('query', query)
|
||
query.select('#shoppingContainer').boundingClientRect()
|
||
query.select('#topBar').boundingClientRect()
|
||
query.select('#bottomBar').boundingClientRect()
|
||
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'
|
||
})
|
||
})()
|
||
}, [])
|
||
|
||
const [isPending, startTransition] = useTransition()
|
||
|
||
useEffect(() => {
|
||
startTransition(() => {
|
||
setShoppingCartData({ list: state.data, total: state.data.length })
|
||
})
|
||
}, [state])
|
||
|
||
// 结算
|
||
const handleSettleAccount = debounce(() => {
|
||
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
|
||
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', {
|
||
purchaser_id: currentCheckedPurchaserId,
|
||
sale_mode: currentCheckedSaleMode,
|
||
shopping_cart_product_color_list: JSON.stringify(checkedGoodsKind),
|
||
purchaser_name: shoppingCartData?.list.find(item => item.purchaser_id === currentCheckedPurchaserId)?.purchaser_name,
|
||
})
|
||
}, 400)
|
||
|
||
const { fetchData: deleteApi } = ShoppingCartDeleteApi()
|
||
|
||
// 批量某个客户的删除商品
|
||
const handleDelete = async () => {
|
||
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
|
||
let checked: Goods[] = []
|
||
if (targetGoodsKind) {
|
||
checked = Object.values(targetGoodsKind).filter((item: Goods) => item.checked)
|
||
if (checked.length === 0) {
|
||
return Taro.showToast({ title: '请选择商品', icon: 'error' })
|
||
}
|
||
}
|
||
console.log('checked==>', checked)
|
||
Taro.showModal({
|
||
title: '要删除这些商品吗?',
|
||
success: async function(res) {
|
||
if (res.confirm) {
|
||
const res = await deleteApi({
|
||
ids: checked.map(item => item.id).join(','),
|
||
})
|
||
if (res.success) {
|
||
alert.success('删除成功')
|
||
fetchData(searchOptions)
|
||
} else {
|
||
alert.none(res.msg)
|
||
}
|
||
}
|
||
},
|
||
})
|
||
}
|
||
// 全选
|
||
const handleSelectAllCheckbox = (isSelectAll: boolean) => {
|
||
console.log('handleSelectAllCheckbox', isSelectAll)
|
||
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
|
||
if (!targetGoodsKind) return Taro.showToast({ title: '请先选择客户', icon: 'error' })
|
||
console.log('targetGoodsKind==>', targetGoodsKind)
|
||
|
||
const tempObject = {}
|
||
Object.entries(targetGoodsKind).forEach(([key, value]) => {
|
||
tempObject[key] = {
|
||
...value,
|
||
checked: isSelectAll,
|
||
}
|
||
})
|
||
console.log('tempObject==>', tempObject)
|
||
dispatch({
|
||
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||
data: {
|
||
purchaserId: currentCheckedPurchaserId,
|
||
goodsKind: tempObject,
|
||
},
|
||
})
|
||
|
||
// setChangedCheckbox({
|
||
// purchaserId: currentCheckedPurchaserId,
|
||
// goodsKind: tempObject,
|
||
// })
|
||
}
|
||
|
||
// 加载刷新数据
|
||
const [refreshStatus, setRefreshStatus] = useState(false)
|
||
|
||
// 下拉刷新
|
||
const handleRefresh = async () => {
|
||
setRefreshStatus(true)
|
||
const res = await fetchData(searchOptions)
|
||
if (res.success) {
|
||
console.log('请求 成功')
|
||
setRefreshStatus(false)
|
||
Taro.showToast({ title: '刷新成功', icon: 'success' })
|
||
} else {
|
||
console.log('请求 失败')
|
||
Taro.showToast({ title: '刷新失败', icon: 'error' })
|
||
setRefreshStatus(false)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<View className={classnames('flex-col', styles.shopping)} id='shoppingContainer'>
|
||
<View className={styles['shopping--topBar']} id='topBar'>
|
||
<Search placeholder='请输入客户名称' showBtn={false} changeOnSearch={getSearchData} debounceTime={300}>
|
||
<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='管理' />
|
||
)}
|
||
</View>
|
||
</Search>
|
||
</View>
|
||
<View className={classnames('flex-item', 'flex-col', styles['shopping--context'])}>
|
||
<View className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: listHeightRef.current }}>
|
||
<InfiniteScroll statusMore={statusMore} refresherEnabled={true} selfOnRefresherRefresh={handleRefresh} refresherTriggered={refreshStatus}>
|
||
{isPending ? (
|
||
<LoadingCard />
|
||
) : (
|
||
!!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}
|
||
onDelete={handleDelete}
|
||
onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}></BottomEditBar>
|
||
) : (
|
||
<BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar>
|
||
)}
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|
||
// interface ScrollListPropType {
|
||
// height: string
|
||
// }
|
||
// const ScrollList = memo<ScrollListPropType>((props) => {
|
||
// const { height } = props
|
||
// const [shoppingCartData, setShoppingCartData] = useState<{ list: ShoppingCartData[]; total: number }>({ list: [], total: 0 })
|
||
|
||
// //数据加载状态
|
||
// const statusMore = useMemo(() => {
|
||
// return dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading })
|
||
// }, [shoppingCartData, state])
|
||
|
||
// return (
|
||
// <View className={classnames('flex-item', 'flex-col', styles['shopping--context'])}>
|
||
// <View className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: height }}>
|
||
// <InfiniteScroll statusMore={statusMore} refresherEnabled={true} selfOnRefresherRefresh={handleRefresh} refresherTriggered={refreshStatus}>
|
||
// {!!shoppingCartData?.list?.length &&
|
||
// shoppingCartData?.list?.map((item, index) => {
|
||
// return <ItemList itemData={item} key={index}></ItemList>
|
||
// })}
|
||
// </InfiniteScroll>
|
||
// </View>
|
||
// </View>
|
||
// )
|
||
// })
|
||
|
||
export default Shopping
|