2023-03-18 14:15:44 +08:00

430 lines
14 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 { Image, ScrollView, Text, View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import classnames from 'classnames'
import { Ref, useCallback, useEffect, useMemo, useRef, useState, useTransition } from 'react'
import Counter from '../counter'
import type { SalesManDialogRef } from '../bindSalesManDialog'
import BindSalesManDialog from '../bindSalesManDialog'
import LabAndImgShow from '../LabAndImgShow'
import LabAndImg from '../LabAndImg'
import OrganizationNameModal from '../organizationNameModal'
import styles from './index.module.scss'
import ProductItem from './components/productItem'
import Popup from '@/components/popup'
import MCheckbox from '@/components/checkbox'
import LoadingCard from '@/components/loadingCard'
import InfiniteScroll from '@/components/infiniteScroll'
import { alert, goLink, retrieval } from '@/common/common'
import { DelShoppingCartApi, GetShoppingCartApi, UpdateShoppingCartApi } from '@/api/shopCart'
import { formatHashTag, formatImgUrl, formatPriceDiv } from '@/common/format'
import { setParam } from '@/common/system'
import { debounce, throttle } from '@/common/util'
import { ApplyOrderAccessApi, GetAdminUserInfoApi, SubscriptionMessageApi } from '@/api/user'
import useCommonData from '@/use/useCommonData'
import type { saleModeType } from '@/common/enum'
import { useSelector } from '@/reducers/hooks'
import { companyDetailApi, companyUpdateApi } from '@/api/company'
import useLogin from '@/use/useLogin'
interface param {
show?: true | false
onClose?: () => void
intoStatus?: 'again' | 'shop'
default_sale_mode?: saleModeType // 面料类型0大货 1剪版2散剪
}
interface modelClassType {
value: saleModeType
title: string
unit: string
step: number
digits: number
minNum: number
maxNum: number
defaultNum: number
eunit: string
}
const ShopCart = ({ show = false, onClose, intoStatus = 'shop', default_sale_mode }: param) => {
const selectList: modelClassType[] = [
{ value: 0, title: '大货', unit: '条', eunit: 'kg', step: 1, digits: 0, minNum: 1, maxNum: 100000, defaultNum: 1 },
{ value: 1, title: '剪板', unit: '米', eunit: 'm', step: 1, digits: 2, minNum: 0.3, maxNum: 100000, defaultNum: 0.3 },
{ value: 2, title: '散剪', unit: '米', eunit: 'kg', step: 1, digits: 2, minNum: 3, maxNum: 100000, defaultNum: 3 },
]
const userInfo = useSelector(state => state.userInfo)
const bindSalesManDialogRef = useRef<SalesManDialogRef | null>(null)
const [isPending, startTransition] = useTransition()
// 切换面料类型
const [selectIndex, setSelectIndex] = useState<saleModeType>(default_sale_mode || 0)
const selectProduct = (index: 0 | 1 | 2) => {
setSelectIndex(index)
}
useEffect(() => {
if (!isPending) {
setSelectIndex(() => default_sale_mode!)
}
}, [default_sale_mode])
// 获取购物车数据数量
const { getShopCount } = useCommonData()
// 获取所有数据数据
const [list, setList] = useState<Record<number, any>>({})
const [loading, setLoading] = useState(false)
const { fetchData: getShoppingFetchData } = GetShoppingCartApi()
// 更新单条数据
const getShoppingCartInfo = async(item) => {
const res = await getShoppingFetchData({ id: item.id })
if (res.success) {
const info = res.data.color_list[0]
const newInfo = {
...item,
estimate_amount: info.estimate_amount,
estimate_weight: info.estimate_weight,
lab: info.lab,
roll: info.roll,
length: info.length,
sale_offset: info.sale_offset,
sale_price: info.sale_price,
standard_price: info.standard_price,
}
setList(e => ({ ...e, [item.id]: newInfo }))
}
}
const listData = useMemo(() => {
return Object.values(list)
}, [list])
// 初始化全部数据默认勾选
const initList = (color_list) => {
const obj = {}
color_list?.forEach((item) => {
item.selected = selectIndex == item.sale_mode
const { unit, eunit, step, digits, minNum, maxNum } = selectList[item.sale_mode]
item = { ...item, unit, eunit, step, digits, minNum, maxNum }
obj[item.id] = item
})
setList(() => ({ ...obj }))
}
const getShoppingCart = async() => {
const { data } = await getShoppingFetchData()
const color_list = data.color_list || []
initList(color_list)
setLoading(false)
}
// 重置勾选数据
const resetList = () => {
Object.values(list)?.forEach((item) => {
if (selectIndex == item.sale_mode) {
item.selected = true
}
else {
item.selected = false
}
list[item.id] = { ...item }
})
setList(() => ({ ...list }))
}
// 显示时展示数据
useEffect(() => {
if (!show) {
setList({})
setSelectIndex(default_sale_mode || 0)
}
else {
setLoading(true)
getShoppingCart()
// setShowBindSalesman(() => false)
bindSalesManDialogRef.current?.handleChange(false)
}
}, [show])
const [showPopup, setShowPopup] = useState(false)
useEffect(() => {
setShowPopup(show)
}, [show])
// 全选反选
const [selectStatus, setSelectStatus] = useState(false)
const selectAll = () => {
Object.values(list)?.forEach((item) => {
if (selectIndex == item.sale_mode) {
item.selected = !selectStatus
list[item.id] = { ...item }
}
})
setList(() => ({ ...list }))
setSelectStatus(!selectStatus)
}
// checkbox选中判断是否全部选中全部选中后是全选否则反选
useEffect(() => {
let list_count = 0
let select_count = 0
Object.values(list)?.forEach((item) => {
if (selectIndex == item.sale_mode) {
list_count++
if (item.selected) { select_count++ }
}
})
setSelectStatus(select_count == list_count)
}, [list])
// 计数组件-当后端修改完成才修改前端显示
const { fetchData: fetchDataUpdateShoppingCart } = UpdateShoppingCartApi()
const getInputValue = debounce(async(item) => {
const res = await fetchDataUpdateShoppingCart({ id: item.id, roll: item.roll, length: item.length })
if (res.success) {
console.log('item修改', item)
getShoppingCartInfo(item)
}
else {
setList(e => ({ ...e }))
}
}, 300)
// 修改数量
const onChangeCount = useCallback((item) => {
getInputValue(item)
}, [])
// 修改选择
const onChangeSelect = useCallback((item) => {
setList(e => ({ ...e, [item.id]: { ...item } }))
}, [])
// popup关闭
const closePopup = () => {
onClose?.()
setShowPopup(false)
}
// 获取面料选中的id
const selectIds = useRef<number[]>([])
const getSelectId = () => {
selectIds.current = []
Object.values(list)?.forEach((item) => {
if (selectIndex == item.sale_mode) {
item.selected && selectIds.current.push(item.id)
}
})
}
// 删除购物车内容
const { fetchData: delShopFetchData } = DelShoppingCartApi()
const delSelect = () => {
getSelectId()
if (selectIds.current.length <= 0) { return alert.none('请选择要删除的面料!') }
Taro.showModal({
content: '删除所选商品?',
async success(res) {
if (res.confirm) {
const res = await delShopFetchData({ id: selectIds.current })
if (res.success) {
getShoppingCart()
getShopCount()
Taro.showToast({
title: '成功',
icon: 'success',
})
}
else {
Taro.showToast({
title: res.msg,
icon: 'none',
})
}
}
else if (res.cancel) {
console.log('用户点击取消')
}
},
})
}
// 预估金额和总条数
const estimatePrice = useMemo(() => {
let estimate_amount = 0
const product_list = new Set() // 面料
let color_count = 0 // 颜色数量
let all_count = 0 // 总数量
Object.values(list)?.forEach((item) => {
if (item.selected) {
estimate_amount += item.estimate_amount
product_list.add(item.product_id)
color_count++
all_count += item.sale_mode == 0 ? parseFloat(item.roll) : parseFloat(item.length)
}
})
const all_count_text = selectIndex == 0 ? `${all_count}` : `${all_count / 100}`
console.log('text::', list)
return {
price: Number(formatPriceDiv(estimate_amount)).toFixed(2),
countText: `已选 ${product_list.size} 种面料,${color_count} 个颜色,共 ${all_count_text}`,
color_count,
}
}, [list])
const [showModal, setShowModal] = useState(false)
const handleClose = () => {
setShowModal(false)
}
const handleShowChange = (val: boolean) => {
setShowModal(val)
}
// 去结算
const { fetchData: FetchData } = GetAdminUserInfoApi()
const { fetchData: applyOrderAccessFetchData } = ApplyOrderAccessApi()
const orderDetail = throttle(async() => {
const res = await FetchData()
if (res.data.order_access_status !== 3) {
if (res.data.order_access_status == 1) { applyOrderAccessFetchData() }
bindSalesManDialogRef.current?.handleChange(true)
onClose?.()
return
}
// 检测是否修改过组织昵称
if (userInfo.adminUserInfo.first_change_name) {
setShowModal(true)
return
}
getSelectId()
if (selectIds.current.length == 0) {
alert.error('请选择面料')
}
else {
const ids = selectIds.current.join('-')
setParam({ ids, sale_mode: selectIndex }) // 临时存储
closePopup()
if (intoStatus == 'again') {
goLink('/pages/order/comfirm', null, 'redirectTo')
}
else {
goLink('/pages/order/comfirm')
}
}
}, 500)
// 显示图片弹窗
const [showLabImage, setShowLabImage] = useState(false)
const [labImageValue, setLabImageValue] = useState()
const getLabAndImg = useCallback((val) => {
setShowLabImage(() => true)
setLabImageValue(val)
}, [])
const closeLabImgShow = useCallback(() => {
setShowLabImage(() => false)
}, [])
const goShop = useCallback(() => {
onClose?.()
goLink('/pages/index/index', null, 'switchTab')
}, [])
useEffect(() => {
startTransition(() => {
resetList()
setSelectStatus(true)
})
}, [selectIndex])
// 弹出修改组织昵称弹窗
const handleBindSalesManSuccess = () => {
// 检测是否修改过组织昵称
if (userInfo.adminUserInfo.first_change_name) {
setShowModal(true)
}
}
const { getAdminUserInfo } = useLogin()
const { fetchData: saveFetch } = companyUpdateApi()
const { fetchData: getCompanyFetch } = companyDetailApi()
const handleOrganizationNameModalConfirm = async(text: string) => {
const params = await getCompanyFetch()
const result = await saveFetch({
...params.data,
company_name: text,
})
if (result.success) {
getAdminUserInfo()
handleClose()
alert.success('保存成功')
}
else {
alert.none(result.msg)
}
}
return (
<View className={styles.shop_cart_main}>
<Popup showTitle={false} show={showPopup} onClose={() => closePopup()}>
<View className={styles.popup_con}>
<View className={styles.header}>
<View onClick={selectAll}>{!selectStatus ? '全选' : '反选'}</View>
<View onClick={delSelect}>
<text className={classnames('iconfont', 'icon-shanchu', styles.miconfont)}></text>
</View>
</View>
<View className={styles.count_all}>{estimatePrice.countText}</View>
<View className={styles.search}>
{selectList.map((item) => {
return (
<View
key={item.value}
onClick={() => selectProduct(item.value)}
className={classnames(styles.search_item, selectIndex == item.value && styles.search_item_select)}
>
{item.title}
</View>
)
})}
</View>
<View className={styles.con}>
{(loading || isPending) && <LoadingCard />}
{!loading && !isPending && listData?.length > 0 && (
<InfiniteScroll moreStatus={false}>
<View className={styles.product_list}>
{listData?.map((item) => {
return <ProductItem key={item.id} sale_model={selectIndex} onChangeCount={onChangeCount} onChangeSelect={onChangeSelect} item={item} />
})}
</View>
</InfiniteScroll>
)}
{!loading && listData?.length == 0 && (
<View className={styles.empty}>
<View className={styles.title}></View>
<View className={styles.btn} onClick={goShop}>
</View>
</View>
)}
</View>
<View className={styles.buy_btn}>
<View className={styles.buy_con}>
<View className={styles.icon}>
<View className={classnames('iconfont', 'icon-gouwuche', styles.miconfont)}></View>
</View>
<View className={styles.price_con}>
<View className={styles.price_real}>
<Text></Text>
{estimatePrice.price}
</View>
<View className={styles.price_forecast}></View>
</View>
<View className={styles.goPay} onClick={() => orderDetail()}>
({estimatePrice.color_count})
</View>
</View>
</View>
</View>
</Popup>
<View>
<BindSalesManDialog ref={bindSalesManDialogRef} onSuccess={handleBindSalesManSuccess} />
</View>
<View>
<LabAndImgShow value={labImageValue} show={showLabImage} onClose={closeLabImgShow} />
</View>
<OrganizationNameModal showModal={showModal} onClose={handleClose} onShowModalChange={handleShowChange} onConfirm={handleOrganizationNameModalConfirm} />
</View>
)
}
export default ShopCart