✨ feat(ID1000738):需求拆分:内部商城新增二级面料分类、排序
This commit is contained in:
parent
81f6c48794
commit
e2c4c99ff1
@ -8,6 +8,8 @@
|
||||
"no-prototype-builtins": "off",
|
||||
"import/first": "off",
|
||||
"react/no-children-prop": "off",
|
||||
"import/no-commonjs": "off"
|
||||
"import/no-commonjs": "off",
|
||||
"no-use-before-define": "off",
|
||||
"@typescript-eslint/no-use-before-define": ["error"]
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,3 +74,13 @@ export const ProductListApi = () => {
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取面料种类子分类
|
||||
*/
|
||||
export const GetClassList = () => {
|
||||
return useRequest({
|
||||
url: '/v2/mp/product/kind/sub/list',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
@ -70,10 +70,34 @@
|
||||
.sideBar_con {
|
||||
flex: 1;
|
||||
|
||||
min-width: 0;
|
||||
position: relative;
|
||||
padding-top: 90px;
|
||||
.product_class {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
.sideBar_con_scroll {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.nosideBar_con{
|
||||
flex: 1;
|
||||
|
||||
min-width: 0;
|
||||
position: relative;
|
||||
.product_class {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
.sideBar_con_scroll {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,8 @@ import type { StatusParam } from '../infiniteScroll'
|
||||
import InfiniteScroll from '../infiniteScroll'
|
||||
import LoadingCard from '../loadingCard'
|
||||
import styles from './index.module.scss'
|
||||
import ProductClass from '@/pages/index/components/productClass'
|
||||
import { GetClassList } from '@/api/index'
|
||||
|
||||
interface Params {
|
||||
list?: any[]
|
||||
@ -20,6 +22,7 @@ interface Params {
|
||||
selfOnScrolltolower?: () => void
|
||||
hasMore?: true | false
|
||||
statusMore?: StatusParam
|
||||
selectClass?: (val: number) => void
|
||||
}
|
||||
const SideBar = ({
|
||||
list = [],
|
||||
@ -33,6 +36,7 @@ const SideBar = ({
|
||||
selfOnScrolltolower,
|
||||
hasMore = true,
|
||||
statusMore = 0,
|
||||
selectClass,
|
||||
}: Params) => {
|
||||
const num_half = useRef(0)
|
||||
|
||||
@ -76,21 +80,37 @@ const SideBar = ({
|
||||
})
|
||||
}, [])
|
||||
|
||||
// 二级面料系列分类
|
||||
const [openClass, setOpenClass] = useState(false)
|
||||
const [classList, setClassList] = useState([])
|
||||
const [classId, setClassId] = useState(-1)
|
||||
const { fetchData } = GetClassList()
|
||||
const getClassData = async(id) => {
|
||||
const res = await fetchData({ id })
|
||||
if (res.success) {
|
||||
if (res.data?.list.length > 0) {
|
||||
res.data.list = [{ id: -1, name: '全部' }, ...res.data.list]
|
||||
}
|
||||
setClassList(() => res.data?.list)
|
||||
console.log('res.data?.list=>', res.data?.list)
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
if (selected) { getClassData(selected) }
|
||||
}, [selected])
|
||||
|
||||
const getSelectClass = (id) => {
|
||||
selectClass?.(id)
|
||||
setClassId(() => id)
|
||||
}
|
||||
|
||||
const clickEvent = ({ item, index }: { item; index: number }) => {
|
||||
setSelected(item.id)
|
||||
sideBarOnClick?.(item)
|
||||
computeSelectTab(index)
|
||||
setClassId(-1)
|
||||
selectClass?.(-1)
|
||||
}
|
||||
|
||||
const [currentIndex, setcurrentIndex] = useState(0)
|
||||
useMemo(() => {
|
||||
Taro.nextTick(() => {
|
||||
let index = 0
|
||||
index = list.findIndex((item) => { return item.id == selected })
|
||||
setcurrentIndex(currentIndex)
|
||||
})
|
||||
}, [selected])
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className={classnames(styles.sideBar_main, 'side_bar_select')}>
|
||||
@ -116,7 +136,12 @@ const SideBar = ({
|
||||
})
|
||||
}
|
||||
</ScrollView>
|
||||
<View className={styles.sideBar_con}>
|
||||
<View className={classnames(classList.length > 0 ? styles.sideBar_con : styles.nosideBar_con)}>
|
||||
{classList.length > 0 && (
|
||||
<View className={styles.product_class} style={{ height: openClass ? '100%' : '' }}>
|
||||
<ProductClass list={classList} open={openClass} onOpenClick={val => setOpenClass(val)} onSelect={getSelectClass} defaultSelectId={classId} />
|
||||
</View>
|
||||
)}
|
||||
<InfiniteScroll statusMore={statusMore} selfonScrollToLower={() => selfOnScrolltolower?.()} refresherTriggered={refresherTriggered} refresherEnabled selfOnRefresherRefresh={() => selfOnRefresherRefresh?.()}>
|
||||
{children}
|
||||
</InfiniteScroll>
|
||||
|
||||
143
src/pages/index/components/productClass/index.module.scss
Normal file
143
src/pages/index/components/productClass/index.module.scss
Normal file
@ -0,0 +1,143 @@
|
||||
.class_main {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
.product_class_main_line {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
margin-bottom: 20px;
|
||||
background-color: #fff;
|
||||
.product_class_scroll {
|
||||
box-sizing: border-box;
|
||||
padding: 6px 90px 0 20px;
|
||||
.product_class_list {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
.product_class_item {
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
padding: 0 15px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 29px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
box-sizing: border-box;
|
||||
max-width: 260px;
|
||||
// @include common_ellipsis;
|
||||
margin: 0 8px 16px 8px;
|
||||
}
|
||||
.product_class_item_selected {
|
||||
border: 1px solid #3c78f4;
|
||||
color: #3c78f4;
|
||||
background: #ecf2ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
.product_class_more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 88px;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
box-shadow: -7px 0px 7px -5px rgba(0, 0, 0, 0.16);
|
||||
line-height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.zhankai{
|
||||
margin-left: 15px;
|
||||
}
|
||||
.product_class_more_icon {
|
||||
margin-left: 20px;
|
||||
display: inline-block;
|
||||
transform: rotate(90deg);
|
||||
font-size: 30px;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product_class_main_block {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
.product_class_block_con {
|
||||
max-height: 500px;
|
||||
background-color: #fff;
|
||||
z-index: 999;
|
||||
position: relative;
|
||||
}
|
||||
.product_class_scroll {
|
||||
box-sizing: border-box;
|
||||
max-height: 500px;
|
||||
padding: 0 20px;
|
||||
padding: 6px 20px 0 20px;
|
||||
.product_class_list {
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
.product_class_item {
|
||||
width: 169px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
padding: 0 15px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 29px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
margin: 0 8px 16px 8px;
|
||||
box-sizing: border-box;
|
||||
max-width: 260px;
|
||||
@include common_ellipsis(1);
|
||||
}
|
||||
.product_class_item_selected {
|
||||
border: 1px solid #3c78f4;
|
||||
color: #3c78f4;
|
||||
background: #ecf2ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
.product_class_close {
|
||||
font-size: 24px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
// text-align: center;
|
||||
padding-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
// .product_class_close_icon {
|
||||
// display: inline-block;
|
||||
// transform: rotate(-90deg);
|
||||
// font-size: 27px;
|
||||
// color: rgba(0, 0, 0, 0.5);
|
||||
// padding: 0 10px;
|
||||
// }
|
||||
}
|
||||
.product_class_block_mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
126
src/pages/index/components/productClass/index.tsx
Normal file
126
src/pages/index/components/productClass/index.tsx
Normal file
@ -0,0 +1,126 @@
|
||||
import { ScrollView, View } from '@tarojs/components'
|
||||
import classnames from 'classnames'
|
||||
import { memo, useCallback, useEffect, useState } from 'react'
|
||||
import styles from './index.module.scss'
|
||||
import IconFont from '@/components/iconfont/iconfont'
|
||||
|
||||
interface Param {
|
||||
open: boolean
|
||||
onOpenClick?: (val: boolean) => void
|
||||
onSelect?: (id: number) => void
|
||||
list?: { name: string; id: number }[]
|
||||
defaultSelectId: number
|
||||
}
|
||||
|
||||
type ParamProduct = Omit<Param, 'open'>
|
||||
|
||||
const ProductClassLine = memo((option: ParamProduct) => {
|
||||
const { onOpenClick, defaultSelectId = 0, onSelect, list = [] } = option
|
||||
const [selectInfo, setSelectInfo] = useState({
|
||||
selected: 0, // 当前选中的id
|
||||
tabId: 0, // 需要滚动到的id
|
||||
})
|
||||
|
||||
console.log('刷新了')
|
||||
|
||||
useEffect(() => {
|
||||
let data: { item: any; index: number } = { item: null, index: 0 }
|
||||
list?.filter((item, index) => {
|
||||
if (item.id == defaultSelectId) {
|
||||
data = { item, index }
|
||||
}
|
||||
})
|
||||
if (data.item) {
|
||||
const num = data.index > 0 ? data.index - 1 : 0
|
||||
console.log('获取数据::', list[num].id)
|
||||
setSelectInfo(e => ({ ...e, tabId: list[num].id, selected: data.item.id }))
|
||||
}
|
||||
}, [defaultSelectId, list])
|
||||
|
||||
const clickEvent = ({ item, index }: { item: any; index: number }) => {
|
||||
const num = index > 0 ? index - 1 : 0
|
||||
setSelectInfo(e => ({ ...e, tabId: list[num].id, selected: item.id }))
|
||||
onSelect?.(item.id)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.product_class_main_line}>
|
||||
<ScrollView scrollX scrollWithAnimation className={styles.product_class_scroll} scrollIntoView={`tabs_${selectInfo.tabId}`}>
|
||||
<View className={styles.product_class_list}>
|
||||
{list?.map((item, index) => (
|
||||
<View
|
||||
id={`tabs_${item.id}`}
|
||||
className={classnames(styles.product_class_item, item.id == selectInfo.selected ? styles.product_class_item_selected : '')}
|
||||
onClick={() => clickEvent({ item, index })}
|
||||
key={item.id}
|
||||
>
|
||||
{item.name}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
<View className={styles.product_class_more} onClick={() => onOpenClick?.(true)}>
|
||||
<IconFont name="icon-zhankai" color="#000000" size={40} customClassName={styles.zhankai}></IconFont>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
})
|
||||
|
||||
ProductClassLine.displayName = 'ProductClassLine'
|
||||
|
||||
const ProductClassBlock = (option: ParamProduct & { open: boolean }) => {
|
||||
const { onOpenClick, defaultSelectId = 0, onSelect, list = [], open } = option
|
||||
const [selectInfo, setSelectInfo] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
setSelectInfo(defaultSelectId)
|
||||
}, [defaultSelectId])
|
||||
|
||||
const clickEvent = (item) => {
|
||||
setSelectInfo(item.id)
|
||||
onSelect?.(item.id)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<View className={styles.product_class_main_block} style={{ display: open ? 'block' : 'none' }}>
|
||||
<View className={styles.product_class_block_con}>
|
||||
<ScrollView scrollY className={styles.product_class_scroll}>
|
||||
<View className={styles.product_class_list}>
|
||||
{list?.map(item => (
|
||||
<View
|
||||
className={classnames(styles.product_class_item, item.id == selectInfo ? styles.product_class_item_selected : '')}
|
||||
onClick={() => clickEvent(item)}
|
||||
key={item.id}
|
||||
>
|
||||
{item.name}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
<View className={styles.product_class_close} onClick={() => onOpenClick?.(false)}>
|
||||
点击收起<IconFont name="icon-shouqi" color="#000000" size={40} customClassName={styles.shouqi}></IconFont>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.product_class_block_mask} onClick={() => onOpenClick?.(false)}></View>
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const PrcductSub = (option: Param) => {
|
||||
const { open = false, onOpenClick, onSelect, list, defaultSelectId } = option
|
||||
const getSelect = useCallback((id) => {
|
||||
onSelect?.(id)
|
||||
}, [])
|
||||
const openClick = useCallback((val) => {
|
||||
onOpenClick?.(val)
|
||||
}, [])
|
||||
return (
|
||||
<>
|
||||
<View className={styles.class_main}>
|
||||
<ProductClassLine list={list} defaultSelectId={defaultSelectId} onSelect={getSelect} onOpenClick={openClick}></ProductClassLine>
|
||||
<ProductClassBlock open={open} list={list} defaultSelectId={defaultSelectId} onSelect={getSelect} onOpenClick={openClick}></ProductClassBlock>
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -13,6 +13,7 @@ import { ClientListApi, MpProductColorList, MpShoppingCartProductColorList } fro
|
||||
import { dataLoadingStatus, getFilterData } from '@/common/util'
|
||||
|
||||
const Index = () => {
|
||||
const product_kind_id_ref = useRef(0)
|
||||
// 获取客户
|
||||
const [clienList, setclienList] = useState<any[]>([])
|
||||
const { fetchData: listFetchData } = ClientListApi()
|
||||
@ -43,6 +44,7 @@ const Index = () => {
|
||||
if (res.data?.list) {
|
||||
setKindData({ ...kindData, list: res.data.list, defaultId: res.data.list[0].id })
|
||||
setFiltrate({ ...filtrate, product_kind_id: res.data.list[0].id })
|
||||
product_kind_id_ref.current = res.data.list[0].id
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +69,7 @@ const Index = () => {
|
||||
pageNum.current.page = 1
|
||||
setProductData({ list: [], total: 0 })
|
||||
setFiltrate(list => ({ ...list, size: 5, product_kind_id: e.id }))
|
||||
product_kind_id_ref.current = e.id
|
||||
}, [])
|
||||
|
||||
// 上拉加载数据
|
||||
@ -326,6 +329,16 @@ const Index = () => {
|
||||
}
|
||||
})
|
||||
|
||||
// 获取二级分类
|
||||
const product_kind_id_next_ref = useRef(0)
|
||||
const getSelectClassId = useCallback((id) => {
|
||||
pageNum.current.page = 1
|
||||
setProductData({ list: [], total: 0 })
|
||||
const kind_id = id == -1 ? product_kind_id_ref.current : id
|
||||
product_kind_id_next_ref.current = id
|
||||
setFiltrate(list => ({ ...list, size: 5, product_kind_id: kind_id }))
|
||||
}, [])
|
||||
|
||||
return (
|
||||
// <MoveBtn onClick={() => setShowShopCart(showShopCart)}>
|
||||
<View className={styles.main}>
|
||||
@ -347,6 +360,7 @@ const Index = () => {
|
||||
selfOnScrolltolower={getScrolltolower}
|
||||
sideBarOnClick={getProductKindId}
|
||||
heightItem={150}
|
||||
selectClass={getSelectClassId}
|
||||
refresherTriggered={refresherTriggeredStatus}
|
||||
selfOnRefresherRefresh={() => getRefresherRefresh()}
|
||||
>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user