219 lines
8.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Search from '@/components/search'
import { View } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro'
import React, { FC, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } 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 BottomBtns from '@/components/BottomBtns'
import { formatPriceDiv } from '@/common/format'
import BottomSettleBar from './components/bottomSettleBar'
import BottomEditBar from './components/bottomEditBar'
import { ShoppingCartDeleteApi, ShoppingCartListApi } from '@/api/index'
import { dataLoadingStatus, debounce } from '@/common/util'
import { ShoppingCart, TriggerCheckboxOptions } from './components/shoppingCart/index'
import { GoodsMeta, Goods, useShoppingCart, useShoppingContext } from './context'
import { alert, goLink } from '@/common/common'
export const Shopping: FC = memo(() => {
// 计算总的预估金额
const handleTriggerCheckbox = useCallback(({ colorStore, changedCheckbox, currentCheckedPurchaserId, setSelectedAmount }) => {
console.log('handleTriggerCheckbox==>', colorStore, changedCheckbox)
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
if (targetGoodsKind) {
const result = Object.values(targetGoodsKind).reduce((prev: number, value: Goods) => {
console.log('value==>', value)
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 (
<ShoppingCart onTriggerCheckbox={handleTriggerCheckbox}>
<ShoppingCartContainer />
</ShoppingCart>
)
})
interface InternalContainer {}
const ShoppingCartContainer: FC<InternalContainer> = () => {
const { isManageStatus, setManageStatus, selectedAmount, currentCheckedPurchaserId, currentCheckedSaleMode, colorStore, setColorStore } = useShoppingContext()
// 管理
const onStartToManage = () => {
setManageStatus(!isManageStatus)
}
const [listHeight, setListHeight] = useState('auto')
const { fetchData, state } = ShoppingCartListApi()
const [searchOptions, setSearchOptions] = useState({
short_name_or_phone: '',
})
useEffect(() => {
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(() => {
return dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading })
}, [shoppingCartData, state])
// useLayoutEffect 执行在DOM更新之后浏览器绘制之前 如果放在 useEffect 里面会产生多一次不必要的回流和重绘,可能会引起视图闪现
useLayoutEffect(() => {
;(async () => {
await fetchData()
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
setListHeight(listHeight + 'px')
})
})()
}, [])
useEffect(() => {
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()
// TODO: 批量删除商品
const handleDelete = async () => {
const targetGoodsKind = colorStore?.[currentCheckedPurchaserId]?.['goodsKind']
if (targetGoodsKind && Object.values(targetGoodsKind).every((item: Goods) => !item.checked)) {
return Taro.showToast({ title: '请选择商品', icon: 'error' })
}
Taro.showModal({
title: '要取消这些商品吗?',
success: async function(res) {
if (res.confirm) {
const res = await deleteApi()
if (res.success) {
alert.success('取消成功')
fetchData()
} else {
alert.none(res.msg)
}
}
},
})
}
// 全选
const handleSelectAllCheckbox = (isSelectAll: boolean) => {
console.log('handleSelectAllCheckbox', isSelectAll)
const tempObject = {}
Object.entries(colorStore).forEach(([key, value]) => {
tempObject[key] = {
...value,
checked: isSelectAll,
}
})
console.log(tempObject)
setColorStore(() => 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: listHeight }}>
<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 onDelete={handleDelete} onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}></BottomEditBar>
) : (
<BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar>
)}
</View>
</View>
)
}
export default Shopping