426 lines
14 KiB
TypeScript
426 lines
14 KiB
TypeScript
import { Text, View } from '@tarojs/components'
|
||
import Taro, { useRouter } from '@tarojs/taro'
|
||
import Big from 'big.js'
|
||
import classnames from 'classnames'
|
||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||
import VirtualList from '@tarojs/components/virtual-list'
|
||
import GuidePopup from '../guidePopup/index'
|
||
import styles from './index.module.scss'
|
||
import Popup from '@/components/popup'
|
||
import LoadingCard from '@/components/loadingCard'
|
||
import Search from '@/components/search'
|
||
import Counter from '@/components/counter'
|
||
import { useSelector } from '@/reducers/hooks'
|
||
import { GetColorList } from '@/api/materialColor'
|
||
import { AddShoppingCartApi } from '@/api/shopCart'
|
||
import UseLogin from '@/use/useLogin'
|
||
import { formatHashTag, formatPriceDiv, formatWeightDiv } from '@/common/fotmat'
|
||
import { getFilterData } from '@/common/util'
|
||
import LabAndImg from '@/components/LabAndImg'
|
||
import useCommonData from '@/use/useCommonData'
|
||
import LabAndImgShow from '@/components/LabAndImgShow'
|
||
import IconFont from '@/components/iconfont/iconfont'
|
||
import { goLink } from '@/common/common'
|
||
|
||
interface param {
|
||
show?: true | false
|
||
onClose?: () => void
|
||
title?: string
|
||
productId?: number
|
||
is_first_login?: boolean // 是否首次进来需要展示引导
|
||
recommendStatus?: boolean
|
||
recom_title?: string
|
||
}
|
||
const OrderCount = ({ show = false, onClose, title = '', productId = 0, is_first_login = true, recommendStatus = false, recom_title = '' }: 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', originalPrice: 'last_bulk_price' },
|
||
{ id: 1, step: 1, digits: 2, maxNum: 9.99, defaultNum: 1, title: '剪板', unit: '米', eunit: 'm', priceField: 'length_cut_price', originalPrice: 'last_length_cut_price' },
|
||
{
|
||
id: 2,
|
||
step: 1,
|
||
digits: 2,
|
||
minNum: 3,
|
||
maxNum: 100000,
|
||
defaultNum: 3,
|
||
returnZero: true,
|
||
title: '散剪',
|
||
unit: '米',
|
||
eunit: 'kg',
|
||
priceField: 'weight_cut_price',
|
||
originalPrice: 'last_weight_cut_price',
|
||
},
|
||
])
|
||
const [selectIndex, setSelectIndex] = useState(0)
|
||
|
||
// 获取面料颜色列表
|
||
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 initList = useCallback((list) => {
|
||
const newList = list.map((item) => {
|
||
item.count = 0
|
||
item.show = false
|
||
return item
|
||
})
|
||
return newList
|
||
}, [])
|
||
const getColorList = async() => {
|
||
const { data } = await colorFetchData(getFilterData(condition.current))
|
||
const lists = initList(data.list)
|
||
setList(() => [...lists])
|
||
}
|
||
const [showPopup, setShowPopup] = useState(false)
|
||
|
||
const selectProduct = (index: number) => {
|
||
condition.current.code_or_name = null
|
||
getColorList()
|
||
setSelectIndex(() => index)
|
||
}
|
||
|
||
// 卸载数据
|
||
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
|
||
let kindCount = 0
|
||
const color_list: any[] = []
|
||
let color_list_info = {}
|
||
list.forEach((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)
|
||
}
|
||
// 显示获取
|
||
useEffect(() => {
|
||
if (show && productId) {
|
||
setSelectIndex(0)
|
||
condition.current.code_or_name = null
|
||
setSearchShow(false)
|
||
condition.current.product_id = productId
|
||
getColorList()
|
||
}
|
||
setShowPopup(show)
|
||
}, [show, productId])
|
||
// 重置数据
|
||
useEffect(() => {
|
||
setSearchShow(false)
|
||
}, [selectIndex])
|
||
// 添加购物车
|
||
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,
|
||
is_screw_recommend: recommendStatus,
|
||
})
|
||
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 formatOriginalPrice = useCallback(
|
||
(item) => {
|
||
if (selectIndex === 1 || selectIndex === 2) { return }
|
||
const price = Number(formatPriceDiv(item[selectList[selectIndex].originalPrice]))
|
||
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 = ({ id, index, style, data }: any) => {
|
||
const item = data[index]
|
||
console.log(item, 6666)
|
||
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>
|
||
{/* {selectIndex == 0 && <View className={styles.weight_error}>空差:{formatWeightDiv(item.weight_error)}kg</View>} */}
|
||
<View className={styles.flexBox}>
|
||
{(selectIndex === 0 && item.bulk_price !== item.last_bulk_price) && <View className={styles.numone}>{formatOriginalPrice(item)}</View>}
|
||
<View className={styles.num}>{formatPrice(item)}</View>
|
||
</View>
|
||
|
||
</View>
|
||
<View className={styles.btn_con}>
|
||
{(!item.show && (
|
||
<View className={styles.btn} onClick={() => onAdd(item)}>
|
||
添加
|
||
</View>
|
||
)) || (
|
||
<View className={styles.btn_count}>
|
||
<Counter
|
||
onBlue={num => getInputValue(num, item)}
|
||
defaultNum={item.count}
|
||
step={selectList[selectIndex].step}
|
||
digits={selectList[selectIndex].digits}
|
||
onClickBtn={num => getInputValue(num, item)}
|
||
unit={selectList[selectIndex].unit}
|
||
minNum={selectList[selectIndex].minNum}
|
||
maxNum={selectList[selectIndex].maxNum}
|
||
returnZero={selectList[selectIndex].returnZero}
|
||
/>
|
||
</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
)) || <View className={styles.item}></View>}
|
||
</>
|
||
)
|
||
}
|
||
// 虚拟滚动
|
||
const RowsWithMemo = memo(Rows)
|
||
|
||
const [virtualHeight, setVirtualheight] = useState(400)
|
||
const getHeight = () => {
|
||
const query = Taro.createSelectorQuery()
|
||
query
|
||
.select('#product_color_con')
|
||
.boundingClientRect((rect) => {
|
||
console.log('rect::', rect)
|
||
const clientHeight = rect.height
|
||
setVirtualheight(() => clientHeight)
|
||
})
|
||
.exec()
|
||
}
|
||
useEffect(() => {
|
||
if (!show) { return }
|
||
setTimeout(() => {
|
||
Taro.nextTick(() => {
|
||
getHeight()
|
||
})
|
||
}, 100)
|
||
}, [show])
|
||
|
||
const [showGuidePopup, setshowGuidePopup] = useState(true)
|
||
|
||
useEffect(() => {
|
||
if (show) {
|
||
if (!is_first_login) {
|
||
console.log(is_first_login, 'showGuidePopupshowGuidePopup')
|
||
console.log(2222)
|
||
setshowGuidePopup(false)
|
||
}
|
||
}
|
||
}, [show])
|
||
|
||
const onNavigator = () => {
|
||
if (recommendStatus) { goLink('/pages/details/index', { id: productId }) }
|
||
}
|
||
|
||
return (
|
||
<View className={styles.shop_cart_main}>
|
||
<Popup showTitle={false} show={showPopup} onClose={() => closePopup()}>
|
||
<View className={styles.popup_con}>
|
||
<View className={styles.header}>
|
||
<View className={styles.header_title} onClick={onNavigator}>
|
||
<Text>{recommendStatus ? recom_title : title}</Text>
|
||
<IconFont name="icon-rukou" color="#000000FF" />
|
||
</View>
|
||
{recommendStatus && <View className={styles.header_label}>
|
||
<Text>推荐</Text>
|
||
<Text>配套螺纹</Text>
|
||
</View>}
|
||
</View>
|
||
<View className={styles.search}>
|
||
<View className={styles.search_title}>下单类型 <View onClick={() => setshowGuidePopup(true)}><IconFont name="icon-tishi" size={30}></IconFont></View>:</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} id="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={virtualHeight} /* 列表的高度 */
|
||
width="100%" /* 列表的宽度 */
|
||
itemData={list} /* 渲染列表的数据 */
|
||
itemCount={searchShow ? list.length + 1 : list.length} /* 渲染列表的长度 */
|
||
itemSize={100} /* 列表单项的高度 */
|
||
overscanCount={1}
|
||
>
|
||
{RowsWithMemo}
|
||
</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>
|
||
{
|
||
showGuidePopup && showPopup && <GuidePopup closePopup={() => setshowGuidePopup(false)}></GuidePopup>
|
||
}
|
||
<View>
|
||
<LabAndImgShow value={labImageValue} show={showLabImage} onClose={closeLabImgShow} />
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|
||
export default memo(OrderCount)
|