268 lines
9.5 KiB
TypeScript
268 lines
9.5 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'
|
||
|
||
export const Shopping: FC = memo(() => {
|
||
// 计算总的预估金额
|
||
const handleTriggerCheckbox = ({ multipleSelection, setSelectedAmount }) => {
|
||
console.log('handleTriggerCheckbox==>', multipleSelection)
|
||
|
||
if (multipleSelection) {
|
||
const result = Object.values(multipleSelection).reduce((prev: number , value: Goods) => {
|
||
return prev + Number(formatPriceDiv(value.estimate_amount))
|
||
}, 0) as number
|
||
// 同步修改上下文的 预估金额
|
||
setSelectedAmount(result)
|
||
} else {
|
||
setSelectedAmount(0)
|
||
}
|
||
}
|
||
return (
|
||
<ShoppingProvider onTriggerCheckbox={handleTriggerCheckbox}>
|
||
<ShoppingCartContainer />
|
||
</ShoppingProvider>
|
||
)
|
||
})
|
||
|
||
interface SearchOptions {
|
||
short_name_or_phone?: string
|
||
}
|
||
|
||
const ShoppingCartContainer: FC = () => {
|
||
let isFirst = useRef(true)
|
||
|
||
const { isMultipleSelection, isManageStatus, selectedAmount, currentCheckedPurchaserId, currentCheckedSaleMode, colorStore } = useShoppingState()
|
||
|
||
const dispatch = useShoppingDispatch()
|
||
|
||
// 管理
|
||
const onStartToManage = () => {
|
||
// if (isManageStatus) {
|
||
// handleSelectAllCheckbox(false) // 取消全选
|
||
// }
|
||
dispatch({ type: ShoppingDispatchType.UPDATE_MANAGE_STATUS, data: !isManageStatus })
|
||
}
|
||
|
||
const listHeightRef = useRef('auto')
|
||
// 强制刷新
|
||
const [, setForceUpdate] = useState({})
|
||
|
||
const { fetchData, state } = ShoppingCartListApi()
|
||
|
||
const [searchOptions, setSearchOptions] = useState<SearchOptions>({})
|
||
|
||
useDidShow(() => {
|
||
// 第二次进入该页面时触发
|
||
if (!isFirst.current) {
|
||
// 重新刷新
|
||
// setShoppingCartData({ list: [], total: 0 })
|
||
fetchData(getFilterData(searchOptions))
|
||
}
|
||
})
|
||
|
||
useEffect(() => {
|
||
console.log('useEffect fetchData', getFilterData(searchOptions))
|
||
if (!isFirst.current) {
|
||
fetchData(getFilterData(searchOptions))
|
||
}
|
||
}, [searchOptions])
|
||
|
||
// 输入了搜索关键字
|
||
const getSearchData = useCallback(e => {
|
||
console.log('getSearchData===>',e);
|
||
setSearchOptions({ short_name_or_phone: e })
|
||
}, [])
|
||
|
||
const [shoppingCartData, setShoppingCartData] = useState<{
|
||
list: ShoppingCartData[]
|
||
total: number
|
||
}>({ list: [], total: 0 })
|
||
|
||
|
||
//数据加载状态
|
||
const statusMore = useMemo(() => {
|
||
console.log('shoppingCartData==>', shoppingCartData, state)
|
||
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(getFilterData(searchOptions))
|
||
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'
|
||
// 强制刷新
|
||
setForceUpdate({})
|
||
})
|
||
})()
|
||
}, [])
|
||
|
||
useEffect(() => {
|
||
if (state.success) {
|
||
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 checkedGoodsKind = Object.values(multipleSelection).reduce((prev, item: Goods) => {
|
||
return [...prev, item.id]
|
||
}, [])
|
||
if (checkedGoodsKind.length === 0) return alert.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 multipleSelection = colorStore?.[currentCheckedPurchaserId].multipleSelection
|
||
let checked: Goods[] = Object.values(multipleSelection!)
|
||
if (checked.length === 0) {
|
||
return alert.error('请选择商品')
|
||
}
|
||
console.log('checked==>', checked)
|
||
Taro.showModal({
|
||
title: '要删除这些商品吗?',
|
||
success: async function(res) {
|
||
if (res.confirm) {
|
||
alert.showLoading('删除中')
|
||
const res = await deleteApi({
|
||
ids: checked.map(item => item.id).join(','),
|
||
})
|
||
if (res.success) {
|
||
alert.hideLoading()
|
||
alert.success('删除成功')
|
||
// 清空多选
|
||
dispatch({
|
||
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||
data: {
|
||
purchaserId: currentCheckedPurchaserId,
|
||
goodsKind: colorStore?.[currentCheckedPurchaserId].goodsKind,
|
||
multipleSelection: {},
|
||
},
|
||
})
|
||
fetchData(searchOptions)
|
||
// Observer.notify(currentCheckedPurchaserId)
|
||
} else {
|
||
alert.hideLoading()
|
||
alert.none(res.msg)
|
||
}
|
||
}
|
||
},
|
||
})
|
||
}
|
||
// 全选
|
||
const handleSelectAllCheckbox = (isSelectAll: boolean) => {
|
||
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId].goodsKind
|
||
if (!targetGoodsKind) return alert.error('请先选择客户')
|
||
|
||
const tempObject = { ...targetGoodsKind }
|
||
dispatch({
|
||
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||
data: {
|
||
purchaserId: currentCheckedPurchaserId,
|
||
multipleSelection: isSelectAll ? tempObject : {},
|
||
},
|
||
})
|
||
}
|
||
|
||
// 加载刷新数据
|
||
const [refreshStatus, setRefreshStatus] = useState(false)
|
||
|
||
// 下拉刷新
|
||
const handleRefresh = async () => {
|
||
setRefreshStatus(true)
|
||
const res = await fetchData(getFilterData(searchOptions))
|
||
if (res.success) {
|
||
setRefreshStatus(false)
|
||
alert.success('刷新成功')
|
||
} else {
|
||
alert.error('刷新失败')
|
||
setRefreshStatus(false)
|
||
}
|
||
}
|
||
// 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} 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 id='shoppingListContainer' className={classnames(styles.shopping__list__container, 'flex-item')} style={{ height: listHeightRef.current }}>
|
||
<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>
|
||
<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>
|
||
)
|
||
}
|
||
|
||
export default Shopping
|