feat: 修改首页分类
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
export const apiName = {
|
||||
/**
|
||||
* 查询分类
|
||||
*/
|
||||
queryPrimaryCategory: '/category/queryPrimaryCategory',
|
||||
/**
|
||||
* 获取二级和三级标签
|
||||
*/
|
||||
@@ -15,3 +19,66 @@ export const apiName = {
|
||||
// 查询分类及标签
|
||||
queryCategoryAndLabel: '/category/queryCategoryAndLabel'
|
||||
}
|
||||
|
||||
/**
|
||||
* 大分类中的背景图颜色
|
||||
*/
|
||||
export const categoryBackColor = {
|
||||
0: '#23b2ff',
|
||||
1: '#ea7d4d',
|
||||
2: '#e93532',
|
||||
3: '#343d71',
|
||||
4: '#dc4ad6',
|
||||
5: '#72b633',
|
||||
6: '#9047de',
|
||||
7: '#dc4077',
|
||||
8: '#dc4077'
|
||||
}
|
||||
|
||||
export const mockCategoryList = [
|
||||
{
|
||||
title: '后端',
|
||||
total: 50,
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
title: '前端1',
|
||||
total: 50,
|
||||
id: 2
|
||||
},
|
||||
{
|
||||
title: '前端2',
|
||||
total: 50,
|
||||
id: 3
|
||||
},
|
||||
{
|
||||
title: '前端3',
|
||||
total: 50,
|
||||
id: 4
|
||||
},
|
||||
{
|
||||
title: '前端4',
|
||||
total: 50,
|
||||
id: 5
|
||||
},
|
||||
{
|
||||
title: '前端5',
|
||||
total: 50,
|
||||
id: 6
|
||||
},
|
||||
{
|
||||
title: '前端6',
|
||||
total: 50,
|
||||
id: 7
|
||||
},
|
||||
{
|
||||
title: '前端7',
|
||||
total: 50,
|
||||
id: 8
|
||||
},
|
||||
{
|
||||
title: '前端8',
|
||||
total: 50,
|
||||
id: 9
|
||||
}
|
||||
]
|
||||
|
@@ -0,0 +1,38 @@
|
||||
import { useState } from 'react'
|
||||
import LabelList from './label-list'
|
||||
import PrimaryList from './primary-list'
|
||||
|
||||
const CategoryList = props => {
|
||||
const [selectValue, setSelectValue] = useState({
|
||||
primaryId: '', // 大类ID
|
||||
categoryId: '', // 二级分类ID,
|
||||
labelId: '' // 标签ID
|
||||
})
|
||||
|
||||
const changePrimaryId = primaryId => {
|
||||
setSelectValue({
|
||||
...selectValue,
|
||||
primaryId
|
||||
})
|
||||
}
|
||||
|
||||
const changeLabel = ids => {
|
||||
const [categoryId, labelId] = ids.split('_')
|
||||
const values = {
|
||||
...selectValue,
|
||||
categoryId,
|
||||
labelId
|
||||
}
|
||||
setSelectValue({ ...values })
|
||||
props.onChangeLabel({ ...values })
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='category-list-container'>
|
||||
<PrimaryList changePrimaryId={changePrimaryId} />
|
||||
<LabelList primaryId={selectValue.primaryId} changeLabel={changeLabel} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CategoryList
|
||||
|
32
src/components/category-list/index-new.less
Normal file
32
src/components/category-list/index-new.less
Normal file
@@ -0,0 +1,32 @@
|
||||
.category-card {
|
||||
transition: all 0.5s;
|
||||
color: white;
|
||||
&-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
&-count {
|
||||
font-size: 12px;
|
||||
}
|
||||
&:hover {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
&.active {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
}
|
||||
|
||||
/** label-list style **/
|
||||
.label-list-box {
|
||||
padding-top: 15px;
|
||||
.label-list-item {
|
||||
line-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.label-title {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
112
src/components/category-list/label-list.jsx
Normal file
112
src/components/category-list/label-list.jsx
Normal file
@@ -0,0 +1,112 @@
|
||||
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'
|
||||
import req from '@utils/request'
|
||||
import { Divider, Spin, Tag } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { apiName } from './constant'
|
||||
|
||||
const { CheckableTag } = Tag
|
||||
const maxCount = 4
|
||||
|
||||
const LabelList = props => {
|
||||
const { primaryId, changeLabel } = props
|
||||
const [spinning, setSpinning] = useState(false)
|
||||
const [categoryAndLabelList, setCategoryAndLabelList] = useState([])
|
||||
const [isPutAway, setIsPutAway] = useState(true)
|
||||
const [checkedLabelId, setCheckedLabelId] = useState()
|
||||
|
||||
const getCategoryAndLabel = () => {
|
||||
// setSpinning(true)
|
||||
req({
|
||||
method: 'post',
|
||||
url: apiName.queryCategoryAndLabel,
|
||||
data: { id: primaryId }
|
||||
})
|
||||
.then(res => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
const ids = `${res.data[0].id}_${res.data[0].labelDTOList[0].id}`
|
||||
setCategoryAndLabelList(res.data)
|
||||
setCheckedLabelId(ids)
|
||||
changeLabel(ids)
|
||||
} else {
|
||||
setCategoryAndLabelList([])
|
||||
setCheckedLabelId('')
|
||||
changeLabel('')
|
||||
}
|
||||
// setSpinning(false)
|
||||
})
|
||||
.catch(err => {
|
||||
// setSpinning(false)
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
const onChangePutAway = () => {
|
||||
setIsPutAway(!isPutAway)
|
||||
}
|
||||
|
||||
const changeChecked = (categoryId, labelId) => {
|
||||
const ids = `${categoryId}_${labelId}`
|
||||
if (ids === checkedLabelId) return
|
||||
setCheckedLabelId(ids)
|
||||
changeLabel(ids)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (primaryId) {
|
||||
getCategoryAndLabel()
|
||||
}
|
||||
}, [primaryId])
|
||||
|
||||
return (
|
||||
<Spin spinning={spinning}>
|
||||
<div className='label-list-box'>
|
||||
{categoryAndLabelList.map((categoryItem, index) => {
|
||||
return (
|
||||
<div
|
||||
className='label-list-item'
|
||||
key={categoryItem.id}
|
||||
style={{
|
||||
display: index >= maxCount && isPutAway ? 'none' : 'flex'
|
||||
}}
|
||||
>
|
||||
<div className='label-title'>{categoryItem.categoryName}:</div>
|
||||
{categoryItem.labelDTOList.map(labelItem => {
|
||||
return (
|
||||
<CheckableTag
|
||||
key={labelItem.id}
|
||||
checked={checkedLabelId === `${categoryItem.id}_${labelItem.id}`}
|
||||
className='label-tag'
|
||||
onChange={() => changeChecked(categoryItem.id, labelItem.id)}
|
||||
>
|
||||
{labelItem.labelName}
|
||||
</CheckableTag>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{categoryAndLabelList.length > maxCount ? (
|
||||
<Divider
|
||||
onClick={onChangePutAway}
|
||||
dashed
|
||||
style={{
|
||||
marginTop: 10,
|
||||
marginBottom: 10,
|
||||
fontSize: 13,
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
{isPutAway ? '展开' : '收起'}
|
||||
{isPutAway ? (
|
||||
<CaretDownOutlined style={{ marginLeft: 4 }} />
|
||||
) : (
|
||||
<CaretUpOutlined style={{ marginLeft: 4 }} />
|
||||
)}
|
||||
</Divider>
|
||||
) : null}
|
||||
</Spin>
|
||||
)
|
||||
}
|
||||
|
||||
export default LabelList
|
89
src/components/category-list/primary-list.jsx
Normal file
89
src/components/category-list/primary-list.jsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import req from '@utils/request'
|
||||
import { Card, Space, Spin } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Navigation } from 'swiper/modules'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
import { apiName, categoryBackColor, mockCategoryList } from './constant'
|
||||
|
||||
import 'swiper/css'
|
||||
import 'swiper/css/navigation'
|
||||
import 'swiper/css/pagination'
|
||||
import 'swiper/css/scrollbar'
|
||||
import './index-new.less'
|
||||
|
||||
const PrimaryList = props => {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [primaryCategoryId, setPrimaryCategoryId] = useState()
|
||||
const [categoryList, setCategoryList] = useState([])
|
||||
|
||||
/**
|
||||
* 获取大类分类
|
||||
*/
|
||||
const getPrimaryCategoryInfo = () => {
|
||||
setLoading(true)
|
||||
req({
|
||||
method: 'post',
|
||||
url: apiName.queryPrimaryCategory,
|
||||
data: { categoryType: 1 }
|
||||
})
|
||||
.then(res => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
setPrimaryCategoryId(res.data[0].id)
|
||||
setCategoryList([...res.data])
|
||||
props.changePrimaryId(res.data[0].id)
|
||||
} else {
|
||||
setPrimaryCategoryId(mockCategoryList[0].id)
|
||||
setCategoryList(mockCategoryList)
|
||||
}
|
||||
setLoading(false)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getPrimaryCategoryInfo()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<div className='category-box'>
|
||||
<Swiper
|
||||
spaceBetween={14}
|
||||
slidesPerView={6.5}
|
||||
style={{ paddingTop: '10px' }}
|
||||
modules={[Navigation]}
|
||||
navigation
|
||||
>
|
||||
{categoryList.map((item, index) => {
|
||||
return (
|
||||
<SwiperSlide
|
||||
key={index}
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setPrimaryCategoryId(item.id)
|
||||
props.changePrimaryId(item.id)
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
style={{ backgroundColor: `${categoryBackColor[index]}` }}
|
||||
bodyStyle={{ padding: '10px 14px' }}
|
||||
className={`category-card ${item.id === primaryCategoryId ? 'active' : ''}`}
|
||||
>
|
||||
<Space direction='vertical' size='middle'>
|
||||
<div className='category-card-title'>{item.categoryName}</div>
|
||||
<div className='category-card-count'>{item.count}道题</div>
|
||||
</Space>
|
||||
</Card>
|
||||
</SwiperSlide>
|
||||
)
|
||||
})}
|
||||
</Swiper>
|
||||
</div>
|
||||
</Spin>
|
||||
)
|
||||
}
|
||||
|
||||
export default PrimaryList
|
Reference in New Issue
Block a user