✨ feat(购物页面): 新增批量删除商品功能
This commit is contained in:
parent
d5190ba439
commit
4b75ef1493
@ -15,7 +15,7 @@ export const ShoppingCartUpdateApi = () => {
|
||||
*/
|
||||
export const ShoppingCartDeleteApi = () => {
|
||||
return useRequest({
|
||||
url: `/v1/mp/shoppingCart/productColor`,
|
||||
url: `/v2/mp/shoppingCart/productColor`,
|
||||
method: "delete",
|
||||
})
|
||||
}
|
||||
|
@ -5,30 +5,26 @@
|
||||
justify-content: space-between;
|
||||
background-color: white;
|
||||
padding: 16px 24px;
|
||||
|
||||
.bottomLeft{
|
||||
margin-left: 12px;
|
||||
.moneyText{
|
||||
|
||||
.bottomLeft {
|
||||
margin-left: 12px;
|
||||
.moneyText {
|
||||
font-size: 24px;
|
||||
font-family: $font_family;
|
||||
font-weight: 400;
|
||||
color: rgba($color: #000000, $alpha: 0.6);
|
||||
}
|
||||
.moneyNumber{
|
||||
|
||||
.moneyNumber {
|
||||
font-size: 28px;
|
||||
font-family: $font_family;
|
||||
font-weight: 500;
|
||||
color: $color_money;
|
||||
}
|
||||
}
|
||||
.bottomRight{
|
||||
|
||||
.bottomRight {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.bottomButton {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,23 +8,23 @@ import MCheckbox from '@/components/checkbox'
|
||||
type PropsType = {
|
||||
onDelete?: Function
|
||||
onSelectCheckbox?: (bool: boolean) => void
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export default memo<PropsType>((props) => {
|
||||
const { onDelete, onSelectCheckbox } = props
|
||||
export default memo<PropsType>(props => {
|
||||
const { onDelete, onSelectCheckbox, disabled = false } = props
|
||||
|
||||
const handleSettle = () => {
|
||||
const handleDelete = () => {
|
||||
onDelete && onDelete()
|
||||
}
|
||||
|
||||
const selectCallBack = () => {
|
||||
setSelectAll(true)
|
||||
onSelectCheckbox && onSelectCheckbox(true)
|
||||
setSelectAll(true)
|
||||
}
|
||||
const closeCallBack = () => {
|
||||
setSelectAll(false)
|
||||
onSelectCheckbox && onSelectCheckbox(false)
|
||||
|
||||
}
|
||||
|
||||
const [isSelectAll, setSelectAll] = useState(false)
|
||||
@ -34,6 +34,7 @@ export default memo<PropsType>((props) => {
|
||||
<View className={styles.bottomLeft}>
|
||||
<MCheckbox
|
||||
status={isSelectAll}
|
||||
disabled={disabled}
|
||||
round
|
||||
size='small'
|
||||
onSelect={selectCallBack}
|
||||
@ -43,7 +44,7 @@ export default memo<PropsType>((props) => {
|
||||
</MCheckbox>
|
||||
</View>
|
||||
<View className={styles.bottomRight}>
|
||||
<NormalButton round type='danger' size='normal' onClick={handleSettle} customStyles={{ backgroundColor: '#F44761' }}>
|
||||
<NormalButton round type='danger' size='normal' onClick={handleDelete} customStyles={{ backgroundColor: '#F44761', padding: '0 80rpx' }}>
|
||||
<Text style={{ fontSize: '32rpx' }}>删除</Text>
|
||||
</NormalButton>
|
||||
</View>
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { formatPriceDiv } from '@/common/format'
|
||||
import NormalButton from '@/components/normalButton'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { memo } from 'react'
|
||||
@ -9,7 +8,7 @@ type PropsType = {
|
||||
onSettleAccount?: Function
|
||||
}
|
||||
|
||||
export default memo<PropsType>((props) => {
|
||||
export default memo<PropsType>(props => {
|
||||
const { onSettleAccount, amount = 0 } = props
|
||||
|
||||
const handleSettle = () => {
|
||||
@ -26,8 +25,8 @@ export default memo<PropsType>((props) => {
|
||||
</Text>
|
||||
</View>
|
||||
<View className={styles.bottomRight}>
|
||||
<NormalButton type='primary' round size='normal' onClick={handleSettle}>
|
||||
<Text style={{fontSize: '32rpx'}}>结算</Text>
|
||||
<NormalButton type='primary' round size='normal' onClick={handleSettle} customStyles={{ padding: '0 80rpx' }}>
|
||||
<Text style={{ fontSize: '32rpx' }}>结算</Text>
|
||||
</NormalButton>
|
||||
</View>
|
||||
</View>
|
||||
|
@ -45,14 +45,12 @@ const ColorKindItem: FC<PropsType> = memo(
|
||||
setChangedCheckbox({
|
||||
purchaserId: purchaserId,
|
||||
goodsKind: { [itemData.id]: { ...colorStore[purchaserId].goodsKind?.[itemData.id]!, checked: true } },
|
||||
checked: colorStore[purchaserId].checked,
|
||||
})
|
||||
}
|
||||
const handleClose = () => {
|
||||
setChangedCheckbox({
|
||||
purchaserId: purchaserId,
|
||||
goodsKind: { [itemData.id]: { ...colorStore[purchaserId].goodsKind?.[itemData.id]!, checked: false } },
|
||||
checked: colorStore[purchaserId].checked,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ export const ShoppingCart: FC<ShoppingCartPropsType> = (props) => {
|
||||
onTriggerCheckboxRef.current = onTriggerCheckbox
|
||||
|
||||
const [colorStore, setColorStore] = useState<ColorStore>(() => initialValues || {})
|
||||
// 客户的选中状态
|
||||
const [changedCheckbox, setChangedCheckbox] = useState<GoodsMeta>({} as GoodsMeta)
|
||||
// 当前高亮的客户
|
||||
const [currentCheckedPurchaserId, setCurrentCheckedPurchaserId] = useState<number>(-1)
|
||||
@ -55,7 +56,6 @@ export const ShoppingCart: FC<ShoppingCartPropsType> = (props) => {
|
||||
[changedGoods.purchaserId as number]: {
|
||||
purchaserId: changedGoods.purchaserId,
|
||||
goodsKind: currentGoodsKind,
|
||||
checked: changedGoods.checked,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
@ -1,7 +1,7 @@
|
||||
.layout {
|
||||
margin: 24px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
// padding-left: 0;
|
||||
// padding-right: 0;
|
||||
border: 1px solid transparent;
|
||||
.checkbox {
|
||||
padding: 0 24px;
|
||||
|
@ -66,18 +66,9 @@ export default memo<PropsType>(props => {
|
||||
weight_cut_color_list: itemData?.weight_cut_color_list,
|
||||
}
|
||||
|
||||
const { setChangedCheckbox, currentCheckedPurchaserId, setCurrentCheckedPurchaserId, isManageStatus, setSelectedAmount, colorStore, currentCheckedSaleMode } = useShoppingContext()
|
||||
const { setChangedCheckbox, currentCheckedPurchaserId, setCurrentCheckedPurchaserId, setSelectedAmount, colorStore } = useShoppingContext()
|
||||
|
||||
const memoList = useMemo(() => {
|
||||
const selectedList = itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? itemData?.[BackEndSaleModeListFieldMap[selected]] : [{}]
|
||||
// 给每一个客户都初始化一个 checked 状态
|
||||
selectedList.forEach(() => {
|
||||
// 初始化选中状态
|
||||
setChangedCheckbox({
|
||||
purchaserId: itemData?.purchaser_id!,
|
||||
checked: false,
|
||||
})
|
||||
})
|
||||
// 向 context 中初始化数据
|
||||
return itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
|
||||
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => {
|
||||
@ -94,7 +85,6 @@ export default memo<PropsType>(props => {
|
||||
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
|
||||
},
|
||||
},
|
||||
checked: false,
|
||||
})
|
||||
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem>
|
||||
})
|
||||
@ -112,20 +102,6 @@ export default memo<PropsType>(props => {
|
||||
setCurrentCheckedPurchaserId(itemData?.purchaser_id as number)
|
||||
}
|
||||
|
||||
const handleChecked = () => {
|
||||
// 初始化选中状态
|
||||
setChangedCheckbox({
|
||||
purchaserId: itemData?.purchaser_id!,
|
||||
checked: true,
|
||||
})
|
||||
}
|
||||
const handleUnchecked = () => {
|
||||
// 初始化选中状态
|
||||
setChangedCheckbox({
|
||||
purchaserId: itemData?.purchaser_id!,
|
||||
checked: false,
|
||||
})
|
||||
}
|
||||
// 统计已选面料
|
||||
const materialChecked = useMemo(() => {
|
||||
const targetGoodsKind = colorStore?.[itemData?.purchaser_id!]?.['goodsKind']
|
||||
@ -173,70 +149,63 @@ export default memo<PropsType>(props => {
|
||||
circle
|
||||
customClassName={classnames(styles.layout, itemData?.purchaser_id === currentCheckedPurchaserId ? styles.selected : '')}
|
||||
onClick={handleClickLayout}>
|
||||
<MCheckbox
|
||||
hiddenCheckboxIcon={!isManageStatus}
|
||||
onSelect={handleChecked}
|
||||
onClose={handleUnchecked}
|
||||
status={colorStore[itemData?.purchaser_id!]?.checked}
|
||||
customClassName={styles['checkbox']}
|
||||
customTextClass={styles['checkbox--text']}
|
||||
triggerLabel={false}>
|
||||
<View className='flex-row justify-between' onClick={handleOpenDetail}>
|
||||
<View className={styles.topItem}>
|
||||
<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>
|
||||
{itemData?.sale_user_name}
|
||||
</Tag>
|
||||
</View>
|
||||
<View className={styles.summary}>
|
||||
<Text>
|
||||
已选 {materialChecked} 种面料,{colorChecked} 个颜色,共{' '}
|
||||
{selected === EnumSaleMode.Bulk ? `${lengthOrRollChecked} 条` : `${lengthOrRollChecked} 米`}
|
||||
</Text>
|
||||
</View>
|
||||
<View className='flex-row justify-between' onClick={handleOpenDetail}>
|
||||
<View className={styles.topItem}>
|
||||
<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>
|
||||
{itemData?.sale_user_name}
|
||||
</Tag>
|
||||
</View>
|
||||
<View className={styles.summary}>
|
||||
<Text>
|
||||
已选 {materialChecked} 种面料,{colorChecked} 个颜色,共{' '}
|
||||
{selected === EnumSaleMode.Bulk ? `${lengthOrRollChecked} 条` : `${lengthOrRollChecked} 米`}
|
||||
</Text>
|
||||
</View>
|
||||
<DrawerButton isOpen={openDetail} />
|
||||
</View>
|
||||
</MCheckbox>
|
||||
<DrawerButton isOpen={openDetail} />
|
||||
</View>
|
||||
{/* 减少节点渲染 */}
|
||||
{openDetail && (
|
||||
<View className={classnames(styles.detailBox, openDetail ? styles.drawerOpen : styles.drawerClose)}>
|
||||
<View className={styles.orderType}>
|
||||
<Divider customClassName={styles.line}></Divider>
|
||||
<View className={styles.orderTitle}>订单类型</View>
|
||||
<View className={styles.orderTypeDetail}>
|
||||
<SaleModeButton
|
||||
customStyle={{ padding: '0 50rpx' }}
|
||||
isActive={selected === EnumSaleMode.Bulk}
|
||||
onClick={() => onSelectOrderType(EnumSaleMode.Bulk)}>
|
||||
大货
|
||||
</SaleModeButton>
|
||||
<SaleModeButton
|
||||
customStyle={{ padding: '0 50rpx' }}
|
||||
isActive={selected === EnumSaleMode.Plate}
|
||||
onClick={() => onSelectOrderType(EnumSaleMode.Plate)}>
|
||||
剪板
|
||||
</SaleModeButton>
|
||||
<SaleModeButton
|
||||
customStyle={{ padding: '0 50rpx' }}
|
||||
isActive={selected === EnumSaleMode.BulkCut}
|
||||
onClick={() => onSelectOrderType(EnumSaleMode.BulkCut)}>
|
||||
散剪
|
||||
</SaleModeButton>
|
||||
<>
|
||||
<Divider customClassName={styles.line}></Divider>
|
||||
<View className={classnames(styles.detailBox, openDetail ? styles.drawerOpen : styles.drawerClose)}>
|
||||
<View className={styles.orderType}>
|
||||
<View className={styles.orderTitle}>订单类型</View>
|
||||
<View className={styles.orderTypeDetail}>
|
||||
<SaleModeButton
|
||||
customStyle={{ padding: '0 50rpx' }}
|
||||
isActive={selected === EnumSaleMode.Bulk}
|
||||
onClick={() => onSelectOrderType(EnumSaleMode.Bulk)}>
|
||||
大货
|
||||
</SaleModeButton>
|
||||
<SaleModeButton
|
||||
customStyle={{ padding: '0 50rpx' }}
|
||||
isActive={selected === EnumSaleMode.Plate}
|
||||
onClick={() => onSelectOrderType(EnumSaleMode.Plate)}>
|
||||
剪板
|
||||
</SaleModeButton>
|
||||
<SaleModeButton
|
||||
customStyle={{ padding: '0 50rpx' }}
|
||||
isActive={selected === EnumSaleMode.BulkCut}
|
||||
onClick={() => onSelectOrderType(EnumSaleMode.BulkCut)}>
|
||||
散剪
|
||||
</SaleModeButton>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.orderColor}>
|
||||
<Divider customClassName={styles.line}></Divider>
|
||||
<View className={classnames(styles.orderTitle, 'justify-between')}>
|
||||
<Text>布料颜色</Text>
|
||||
<Tag type='danger' size='normal' circle plain>
|
||||
{selectList[selected].title}单位:{selectList[selected].unit}
|
||||
</Tag>
|
||||
<View className={styles.orderColor}>
|
||||
<Divider customClassName={styles.line}></Divider>
|
||||
<View className={classnames(styles.orderTitle, 'justify-between')}>
|
||||
<Text>布料颜色</Text>
|
||||
<Tag type='danger' size='normal' circle plain>
|
||||
{selectList[selected].title}单位:{selectList[selected].unit}
|
||||
</Tag>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.orderContainer}>{memoList}</View>
|
||||
</View>
|
||||
<View className={styles.orderContainer}>{memoList}</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</LayoutBlock>
|
||||
)
|
||||
|
@ -43,7 +43,6 @@ export interface GoodsMeta {
|
||||
goodsKind?: {
|
||||
[id: number]: Goods
|
||||
}
|
||||
checked: boolean
|
||||
}
|
||||
|
||||
export interface ShoppingContextValue {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Search from '@/components/search'
|
||||
import { View } from '@tarojs/components'
|
||||
import Taro, { useDidHide, useDidShow, useRouter } from '@tarojs/taro'
|
||||
import React, { FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||
import Taro, { useDidHide, useDidShow } from '@tarojs/taro'
|
||||
import { FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||
import styles from './index.module.scss'
|
||||
import classnames from 'classnames'
|
||||
import IconText from '@/components/iconText'
|
||||
@ -24,7 +24,6 @@ export const Shopping: FC = memo(() => {
|
||||
|
||||
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))
|
||||
}
|
||||
@ -47,10 +46,17 @@ export const Shopping: FC = memo(() => {
|
||||
interface InternalContainer {}
|
||||
|
||||
const ShoppingCartContainer: FC<InternalContainer> = () => {
|
||||
|
||||
let isFirst = useRef(true)
|
||||
|
||||
const { isManageStatus, setManageStatus, selectedAmount, currentCheckedPurchaserId, currentCheckedSaleMode, colorStore, setColorStore } = useShoppingContext()
|
||||
const {
|
||||
setChangedCheckbox,
|
||||
isManageStatus,
|
||||
setManageStatus,
|
||||
selectedAmount,
|
||||
currentCheckedPurchaserId,
|
||||
currentCheckedSaleMode,
|
||||
colorStore,
|
||||
} = useShoppingContext()
|
||||
|
||||
// 管理
|
||||
const onStartToManage = () => {
|
||||
@ -64,23 +70,18 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
||||
const [searchOptions, setSearchOptions] = useState({
|
||||
short_name_or_phone: '',
|
||||
})
|
||||
useDidShow(()=>{
|
||||
console.log('onShow');
|
||||
if (!isFirst.current){
|
||||
|
||||
useDidShow(() => {
|
||||
if (!isFirst.current) {
|
||||
fetchData(searchOptions)
|
||||
}
|
||||
}
|
||||
})
|
||||
useDidHide(() => {
|
||||
console.log('onHide');
|
||||
})
|
||||
console.log('rerender');
|
||||
console.log('rerender')
|
||||
|
||||
useEffect(() => {
|
||||
console.log('useEffect fetchData')
|
||||
if (!isEmptyObject(getFilterData(searchOptions))){
|
||||
if (!isEmptyObject(getFilterData(searchOptions))) {
|
||||
fetchData(searchOptions)
|
||||
}
|
||||
}
|
||||
}, [searchOptions])
|
||||
|
||||
// 输入了搜索关键字
|
||||
@ -142,20 +143,27 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
||||
|
||||
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' })
|
||||
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: '要取消这些商品吗?',
|
||||
title: '要删除这些商品吗?',
|
||||
success: async function(res) {
|
||||
if (res.confirm) {
|
||||
const res = await deleteApi()
|
||||
const res = await deleteApi({
|
||||
ids: checked.map(item => item.id).join(','),
|
||||
})
|
||||
if (res.success) {
|
||||
alert.success('取消成功')
|
||||
fetchData()
|
||||
alert.success('删除成功')
|
||||
fetchData(searchOptions)
|
||||
} else {
|
||||
alert.none(res.msg)
|
||||
}
|
||||
@ -166,15 +174,22 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
||||
// 全选
|
||||
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(colorStore).forEach(([key, value]) => {
|
||||
Object.entries(targetGoodsKind).forEach(([key, value]) => {
|
||||
tempObject[key] = {
|
||||
...value,
|
||||
checked: isSelectAll,
|
||||
}
|
||||
})
|
||||
console.log(tempObject)
|
||||
setColorStore(() => tempObject)
|
||||
console.log('tempObject==>', tempObject)
|
||||
setChangedCheckbox({
|
||||
purchaserId: currentCheckedPurchaserId,
|
||||
goodsKind: tempObject,
|
||||
})
|
||||
}
|
||||
|
||||
// 加载刷新数据
|
||||
@ -220,7 +235,10 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
||||
</View>
|
||||
<View id='bottomBar'>
|
||||
{isManageStatus ? (
|
||||
<BottomEditBar onDelete={handleDelete} onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}></BottomEditBar>
|
||||
<BottomEditBar
|
||||
disabled={currentCheckedPurchaserId < 0}
|
||||
onDelete={handleDelete}
|
||||
onSelectCheckbox={isAll => handleSelectAllCheckbox(isAll)}></BottomEditBar>
|
||||
) : (
|
||||
<BottomSettleBar onSettleAccount={handleSettleAccount} amount={selectedAmount}></BottomSettleBar>
|
||||
)}
|
||||
|
Loading…
x
Reference in New Issue
Block a user