334 lines
11 KiB
TypeScript
334 lines
11 KiB
TypeScript
import { View, Text } from '@tarojs/components'
|
||
import Popup from '@/components/popup'
|
||
import LoadingCard from '@/components/loadingCard'
|
||
import Search from '@/components/search'
|
||
import Counter from '../counter'
|
||
import Big from 'big.js'
|
||
import classnames from 'classnames'
|
||
import styles from './index.module.scss'
|
||
import { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||
import { useSelector } from '@/reducers/hooks'
|
||
import { GetColorList } from '@/api/materialColor'
|
||
import { AddShoppingCartApi } from '@/api/shopCart'
|
||
import Taro, { useRouter } from '@tarojs/taro'
|
||
import UseLogin from '@/use/useLogin'
|
||
import { formatHashTag, formatPriceDiv } from '@/common/fotmat'
|
||
import { getFilterData } from '@/common/util'
|
||
import LabAndImg from '@/components/LabAndImg'
|
||
import VirtualList from '@tarojs/components/virtual-list'
|
||
import useCommonData from '@/use/useCommonData'
|
||
import LabAndImgShow from '@/components/LabAndImgShow'
|
||
|
||
type param = {
|
||
show?: true | false
|
||
onClose?: () => void
|
||
title?: string
|
||
productId?: number
|
||
}
|
||
export default memo(({ show = false, onClose, title = '', productId = 0 }: param) => {
|
||
const { adminUserInfo } = useSelector((state) => state.userInfo)
|
||
|
||
const [selectList, _] = useState([
|
||
{ id: 0, step: 1, digits: 0, maxNum: 100000, defaultNum: 1, title: '大货', unit: '条', eunit: 'kg', priceField: 'bulk_price' },
|
||
{ id: 1, step: 1, digits: 2, maxNum: 9.99, defaultNum: 1, title: '剪板', unit: '米', eunit: 'm', priceField: 'length_cut_price' },
|
||
{ id: 2, step: 1, digits: 2, minNum: 10, maxNum: 100000, defaultNum: 10, title: '散剪', unit: '米', eunit: 'kg', priceField: 'weight_cut_price' },
|
||
])
|
||
const [selectIndex, setSelectIndex] = useState(0)
|
||
const selectProduct = (index: number) => {
|
||
setSelectIndex(() => index)
|
||
}
|
||
|
||
//重置数据
|
||
useEffect(() => {
|
||
const newList = initList(list)
|
||
setList([...newList])
|
||
condition.current.code_or_name = null
|
||
setSearchShow(false)
|
||
}, [selectIndex])
|
||
|
||
//获取面料颜色列表
|
||
const { fetchData: colorFetchData, state: colorState } = GetColorList()
|
||
const [list, setList] = useState<any[]>([])
|
||
const condition = useRef({ physical_warehouse: adminUserInfo?.physical_warehouse, sale_mode: selectIndex, product_id: 0, code_or_name: null })
|
||
const getColorList = async () => {
|
||
let { data } = await colorFetchData(getFilterData(condition.current))
|
||
let lists = initList(data.list)
|
||
setList(() => [...lists])
|
||
}
|
||
const [showPopup, setShowPopup] = useState(false)
|
||
|
||
//显示获取
|
||
useEffect(() => {
|
||
if (show) {
|
||
setSelectIndex(0)
|
||
condition.current.code_or_name = null
|
||
setSearchShow(false)
|
||
condition.current.product_id = productId
|
||
getColorList()
|
||
}
|
||
setShowPopup(show)
|
||
}, [show])
|
||
|
||
//初始化列表数据
|
||
const initList = useCallback((list) => {
|
||
const newList = list.map((item) => {
|
||
item.count = 0
|
||
item.show = false
|
||
return item
|
||
})
|
||
return newList
|
||
}, [])
|
||
|
||
//卸载数据
|
||
useEffect(() => {
|
||
return () => {
|
||
setList([])
|
||
}
|
||
}, [])
|
||
|
||
//popup关闭
|
||
const closePopup = () => {
|
||
onClose?.()
|
||
setShowPopup(false)
|
||
setList([])
|
||
}
|
||
|
||
//计算总数量和总米/件数
|
||
const [selectCount, setSelectCount] = useState<{ sumCount: number; kindCount: number; color_list: any[] }>({
|
||
sumCount: 0,
|
||
kindCount: 0,
|
||
color_list: [],
|
||
})
|
||
useEffect(() => {
|
||
let sumCount = 0,
|
||
kindCount = 0,
|
||
color_list: any[] = []
|
||
let color_list_info = {}
|
||
list.map((item) => {
|
||
if (item.count > 0) {
|
||
sumCount = Big(sumCount).add(item.count).toNumber()
|
||
kindCount++
|
||
color_list_info = selectIndex == 0 ? { product_color_id: item.id, roll: item.count } : { product_color_id: item.id, length: item.count * 100 }
|
||
color_list.push(color_list_info)
|
||
}
|
||
})
|
||
setSelectCount({ ...selectCount, sumCount, kindCount, color_list })
|
||
}, [list])
|
||
|
||
//计数组件
|
||
const getInputValue = useCallback(
|
||
(num, item) => {
|
||
item.count = parseFloat(num)
|
||
if (num == 0) item.show = false
|
||
setList(() => [...list])
|
||
},
|
||
[list],
|
||
)
|
||
|
||
const onAdd = (item) => {
|
||
item.show = true
|
||
item.count = selectList[selectIndex].defaultNum
|
||
setList((list) => [...list])
|
||
}
|
||
|
||
//搜索显示与隐藏
|
||
const [searchShow, setSearchShow] = useState(false)
|
||
const changeSearchShow = () => {
|
||
setSearchShow(true)
|
||
}
|
||
|
||
//添加购物车
|
||
const { getShopCount } = useCommonData()
|
||
const { getSelfUserInfo } = UseLogin()
|
||
const { fetchData: addFetchData } = AddShoppingCartApi()
|
||
const addShopCart = async () => {
|
||
try {
|
||
await getSelfUserInfo()
|
||
} catch (msg) {
|
||
Taro.showToast({
|
||
icon: 'none',
|
||
title: '授权失败,请求完善授权',
|
||
})
|
||
return false
|
||
}
|
||
if (selectCount.sumCount == 0) {
|
||
Taro.showToast({
|
||
icon: 'none',
|
||
title: '请选择面料颜色!',
|
||
})
|
||
return false
|
||
}
|
||
|
||
const state = await addFetchData({
|
||
sale_mode: selectIndex,
|
||
color_list: selectCount.color_list,
|
||
})
|
||
if (state.success) {
|
||
Taro.showToast({
|
||
title: '添加成功',
|
||
})
|
||
getShopCount()
|
||
onClose?.()
|
||
} else {
|
||
Taro.showToast({
|
||
icon: 'none',
|
||
title: state.msg,
|
||
})
|
||
}
|
||
}
|
||
|
||
//筛选数据
|
||
const searchInput = useCallback((e) => {
|
||
condition.current.code_or_name = e
|
||
getColorList()
|
||
}, [])
|
||
|
||
//清空搜索内容
|
||
const searchRef = useRef<any>(null)
|
||
const clearSearch = () => {
|
||
searchRef.current.clearInput()
|
||
setSearchShow(false)
|
||
}
|
||
|
||
//格式化金额
|
||
const formatPrice = useCallback(
|
||
(item) => {
|
||
const price = Number(formatPriceDiv(item[selectList[selectIndex].priceField]))
|
||
return (
|
||
<View className={styles.priceText}>
|
||
<Text>¥</Text>
|
||
{price}
|
||
<Text> /{selectList[selectIndex].eunit}</Text>
|
||
</View>
|
||
)
|
||
},
|
||
[selectIndex],
|
||
)
|
||
|
||
//显示图片弹窗
|
||
const [showLabImage, setShowLabImage] = useState(false)
|
||
const [labImageValue, setLabImageValue] = useState()
|
||
const getLabAndImg = useCallback((val) => {
|
||
setShowLabImage(() => true)
|
||
setLabImageValue(val)
|
||
}, [])
|
||
const closeLabImgShow = useCallback(() => {
|
||
setShowLabImage(() => false)
|
||
}, [])
|
||
|
||
//虚拟滚动
|
||
const Rows = memo(({ id, index, style, data }: any) => {
|
||
let item = data[index]
|
||
return (
|
||
<>
|
||
{(item && (
|
||
<View className={styles.item} key={item.id}>
|
||
<View className={styles.item_color}>
|
||
<LabAndImg value={{ lab: item.lab, rgb: item.rgb, texture_url: item.texture_url, title: item.code }} showStatus={false} onClick={getLabAndImg} />
|
||
</View>
|
||
<View className={styles.item_con}>
|
||
<View className={styles.title}>{formatHashTag(item.code, item.name)}</View>
|
||
<View className={styles.num}>{formatPrice(item)}</View>
|
||
</View>
|
||
<View className={styles.btn_con}>
|
||
{(!item.show && (
|
||
<View className={styles.btn} onClick={() => onAdd(item)}>
|
||
添加
|
||
</View>
|
||
)) || (
|
||
<View className={styles.btn_count}>
|
||
<Counter
|
||
otherData={item}
|
||
onBlue={getInputValue}
|
||
defaultNum={item.count}
|
||
step={selectList[selectIndex].step}
|
||
digits={selectList[selectIndex].digits}
|
||
onClickBtn={getInputValue}
|
||
unit={selectList[selectIndex].unit}
|
||
minNum={selectList[selectIndex].minNum}
|
||
maxNum={selectList[selectIndex].maxNum}
|
||
/>
|
||
</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
)) || <View className={styles.item}></View>}
|
||
</>
|
||
)
|
||
})
|
||
|
||
return (
|
||
<View className={styles.shop_cart_main}>
|
||
<Popup showTitle={false} show={showPopup} onClose={() => closePopup()}>
|
||
<View className={styles.popup_con}>
|
||
<View className={styles.header}>{title}</View>
|
||
<View className={styles.search}>
|
||
<View className={styles.search_title}>下单类型:</View>
|
||
<View className={styles.search_list}>
|
||
{selectList.map((item, index) => {
|
||
return (
|
||
<View
|
||
key={index}
|
||
onClick={() => selectProduct(index)}
|
||
className={classnames(styles.search_item, selectIndex == index && styles.search_item_select)}>
|
||
{item.title}
|
||
</View>
|
||
)
|
||
})}
|
||
</View>
|
||
</View>
|
||
{searchShow && (
|
||
<View className={styles.colorFind}>
|
||
<View className={styles.search}>
|
||
<Search placeIcon='out' ref={searchRef} changeOnSearch={searchInput} debounceTime={400} />
|
||
</View>
|
||
<View className={styles.text} onClick={() => clearSearch()}>
|
||
取消
|
||
</View>
|
||
</View>
|
||
)}
|
||
<View className={styles.colorNum}>
|
||
<View className={styles.title}>颜色分类 ({list.length})</View>
|
||
{!searchShow && <View className={classnames('iconfont icon-sousuo', styles.miconfont)} onClick={() => changeSearchShow()}></View>}
|
||
</View>
|
||
|
||
<View className={styles.product_color_con}>
|
||
{list.length <= 0 && colorState.loading && <LoadingCard />}
|
||
{list.length > 0 && !colorState.loading && (
|
||
<View className={styles.color_con}>
|
||
<VirtualList
|
||
className={styles.virtual_list}
|
||
height={400} /* 列表的高度 */
|
||
width='100%' /* 列表的宽度 */
|
||
itemData={list} /* 渲染列表的数据 */
|
||
itemCount={list.length + 1} /* 渲染列表的长度 */
|
||
itemSize={100} /* 列表单项的高度 */
|
||
overscanCount={1}>
|
||
{Rows}
|
||
</VirtualList>
|
||
<View className='common_safe_area_y'></View>
|
||
</View>
|
||
)}
|
||
{list.length <= 0 && !colorState.loading && <View className={styles.noData}>暂无此商品</View>}
|
||
</View>
|
||
<View className={styles.buy_btn}>
|
||
<View className={styles.buy_btn_con}>
|
||
<View className={styles.count}>
|
||
当前已选{selectCount.kindCount}种,共{selectCount.sumCount}
|
||
{selectList[selectIndex].unit}
|
||
</View>
|
||
<View className={classnames(styles.add_cart, selectCount.kindCount && styles.select_add_cart)} onClick={() => addShopCart()}>
|
||
加入购物车
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
<View className='common_safe_area_y'></View>
|
||
</Popup>
|
||
<View>
|
||
<LabAndImgShow value={labImageValue} show={showLabImage} onClose={closeLabImgShow} />
|
||
</View>
|
||
</View>
|
||
)
|
||
})
|