426 lines
14 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { 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)