2023-03-03 15:18:28 +08:00

277 lines
10 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 { Text, View } from '@tarojs/components'
import Taro, { usePullDownRefresh, useReady, useRouter } from '@tarojs/taro'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import SelectData from './components/selectData'
import styles from './searchList.module.scss'
import Search from '@/components/search'
import Filter from '@/components/filter'
import InfiniteScroll from '@/components/infiniteScroll'
import type { SortBtnRef, SortParam } from '@/components/sortBtn'
import SortBtn from '@/components/sortBtn'
import { goLink } from '@/common/common'
import { formatHashTag, formatPriceDiv } from '@/common/fotmat'
import { dataLoadingStatus, getFilterData } from '@/common/util'
import useLogin from '@/use/useLogin'
import LabAndImg from '@/components/LabAndImg'
import IconFont from '@/components/iconfont/iconfont'
import Tag from '@/components/tag'
import { EnumAllLabelApi, GetLabelProductsApi, HomePageJumpApi } from '@/api/search'
enum FilterOptions {
RECOMMEND = 1,
SALES = 2,
PRICE = 3,
}
export default () => {
const isFirst = useRef(true)
useLogin()
const router = useRouter()
const { fetchData } = HomePageJumpApi()
// 获取指定的标签组的标签列表
const getLabelsWithHomeJump = async() => {
await getAllLabel()
if (router.params.pageJump) {
const res = await fetchData({ page_jump: router.params.pageJump || 1 })
const labelIds = res.data.list.map(item => item.product_label_id)
setLabelIds(labelIds)
setSearchField(prev => ({ ...prev, label_ids: labelIds.join(',') }))
}
else {
setLabelIds([])
setSearchField(prev => ({ ...prev, label_ids: '' }))
}
isFirst.current = false
}
// 获取所有标签列表
const { fetchData: getAllLabelApi } = EnumAllLabelApi()
const getAllLabel = async() => {
const res = await getAllLabelApi()
const labelList = res.data.list.map(item => ({ id: item.id, name: item.name }))
setLabelList(labelList)
}
// 搜索参数
const [searchField, setSearchField] = useState({
code_or_name: router.params.key,
page: 1,
size: 10,
filter_type: 1, // 综合推荐
width: '',
weight_density: '',
label_ids: router.params?.label_ids || '',
component: '', // 成分
abstract_sort_key: '',
})
// 获取面料列表
const [materialList, setMaterialList] = useState<{ list: any[]; total: number }>({ list: [], total: 0 })
const { fetchData: materialFetchData, state: materialState } = GetLabelProductsApi()
const getProductList = async() => {
const { data } = await materialFetchData(getFilterData(searchField))
setMaterialList({ list: data.list, total: data.total })
setRefresherTriggeredStatus(false)
}
useEffect(() => {
getLabelsWithHomeJump()
}, [])
// 监听筛选条件变化
useEffect(() => {
// 首次进入页面不执行
if (!isFirst.current) {
getProductList()
}
}, [searchField, isFirst.current])
// 上拉加载数据
const pageNum = useRef({ size: searchField.size, page: searchField.page })
const getScrolltolower = () => {
if (materialList.list.length < materialList.total) {
pageNum.current.page++
const size = pageNum.current.size * pageNum.current.page
setSearchField(prev => ({ ...prev, size }))
}
}
// 数据加载状态
const statusMore = useMemo(() => {
return dataLoadingStatus({ list: materialList.list, total: materialList.total, status: materialState.loading })
}, [materialList, materialState])
// 输入了搜索关键字
const getSearchData = useCallback((e) => {
console.log('e', e)
pageNum.current.page = 1
setSearchField(val => ({ ...val, code_or_name: e, size: 10 }))
pageNum.current = { size: 10, page: 1 }
}, [])
const handleInput = (e) => {
if (e === '') {
getSearchData(e)
}
}
const goLinkPage = (item) => {
goLink('/pages/details/index', { id: item.id })
}
const [labelIds, setLabelIds] = useState<number[]>([])
// 获取筛选条件
const getFilter = (e) => {
console.log('e', e)
pageNum.current.page = 1
setSearchField(prev => ({
...prev,
width: e?.width,
weight_density: e?.weight_density,
size: 10,
component: e?.component,
label_ids: e?.label_ids.join(','),
}))
setLabelIds([...e?.label_ids])
}
// 排序
const sortCollectionRef = useRef<SortBtnRef>(null)
const [sortStatus, setSortStatus] = useState<SortParam>('none')
const changeSort = () => {
setCurrentOption(FilterOptions.PRICE)
if (sortCollectionRef.current) {
const { status, value } = sortCollectionRef.current.changeSort()
setSortStatus(status)
// 如果状态为none就是综合推荐
if (status === 'none') {
setSearchField(e => ({ ...e, filter_type: FilterOptions.RECOMMEND, size: 10, page: 1 }))
setCurrentOption(FilterOptions.RECOMMEND)
}
else {
setSearchField(e => ({ ...e, filter_type: value as number, size: 10, page: 1 }))
}
}
pageNum.current = { size: 10, page: 1 }
}
const labAndImgObj = useCallback(
(item) => {
const img = item ? item.texture_url.split(',')[0] : ''
return { lab: item.lab, rgb: item.rgb, texture_url: img }
},
[materialList],
)
const [currentOption, setCurrentOption] = useState(FilterOptions.RECOMMEND)
const handleSelectFilterOptions = (key: FilterOptions) => {
if (key === currentOption) { return }
setSearchField(e => ({ ...e, filter_type: key, size: 10, page: 1 }))
setSortStatus('none')
setCurrentOption(key)
}
const [labelList, setLabelList] = useState<any[]>([])
const [selected, setSelected] = useState<number[]>([])
const handleClickTag = (ids: number[]) => {
console.log('ids', ids)
setSelected([...ids])
setSearchField(prev => ({
...prev,
label_ids: ids.join(','),
}))
}
// 列表下拉刷新
const [refresherTriggeredStatus, setRefresherTriggeredStatus] = useState(false)
const getRefresherRefresh = async() => {
pageNum.current.page = 1
pageNum.current.size = 10
setRefresherTriggeredStatus(true)
setSearchField(val => ({ ...val, size: 10 }))
}
return (
<View className={styles.main}>
<View className={styles.search}>
<Search placeholder="请输入搜索面料" showBtn btnTitle="搜索" clickOnSearch={getSearchData} defaultValue={router.params.key} changeOnSearch={handleInput} debounceTime={300} />
</View>
<View className={styles.filter}>
<View className={styles.filter_all}>
<View className={styles.text_zh} onClick={() => handleSelectFilterOptions(FilterOptions.RECOMMEND)}>
<Text className={currentOption === FilterOptions.RECOMMEND ? styles.filter_active : ''}></Text>
</View>
<View className={styles.text_sc} onClick={() => handleSelectFilterOptions(FilterOptions.SALES)}>
<Text className={currentOption === FilterOptions.SALES ? styles.filter_active : ''}></Text>
</View>
<View className={styles.text_sc} onClick={changeSort}>
<Text className={currentOption === FilterOptions.PRICE ? styles.filter_active : ''} style={{ marginRight: '8rpx' }}></Text>
<SortBtn status={sortStatus} ref={sortCollectionRef} sortValue={{ desc: 3, asc: 4 }} />
</View>
<View className={styles.text_sc}>
<Filter defaultValue={selected} onFilter={e => getFilter(e)} />
</View>
</View>
{
!!labelList.length && <View className={styles.filter_btn_con}>
<View className={styles.filter_scroll}>
<SelectData defaultValue={labelIds} list={labelList} onClickTag={handleClickTag} />
</View>
</View>
}
</View>
<View className={styles.list}>
<View className={styles.scroll}>
<InfiniteScroll refresherEnabled selfOnRefresherRefresh={getRefresherRefresh} refresherTriggered={refresherTriggeredStatus} safeAreaInsetBottom={false} selfonScrollToLower={getScrolltolower} statusMore={statusMore}>
<View className={styles.product_list}>
{materialList.list?.map((item) => {
return (
<View key={item.id} className={styles.product_item} onClick={() => goLinkPage(item)}>
<View className={styles.product_img}>
<LabAndImg value={labAndImgObj(item)} />
<View className={styles.color_num}>{item.product_color_count}</View>
</View>
<View className={styles.product_info}>
<View className={styles.title}>
<Text className={styles.title_text}>
{formatHashTag(item.code, item.name)}
</Text>
<View className={styles.favorite}>
{item.is_favorite && <IconFont customClassName={styles.collection_icon} name="icon-shoucang1" size={40} />}
</View>
</View>
<View className={styles.tag_list}>
<Tag customClassName={styles.tag} type="primary" size="small" circle>{item.width}</Tag>
<Tag customClassName={styles.tag} type="primary" size="small" circle>{item.weight_density}</Tag>
{
!!item.product_screw_id
&& <Tag customClassName={styles.tag_g} circle type="primary" size="small"></Tag>
}
</View>
<View className={styles.bottom}>
<View className={styles.introduce}>{item.component}</View>
<View className={styles.price}>
<View className={styles.price_unit}>¥</View>
<View className={styles.price_num}>{formatPriceDiv(item.lowest_price).toLocaleString()}</View>
</View>
</View>
</View>
</View>
)
})}
</View>
</InfiniteScroll>
</View>
</View>
</View>
)
}