Files
qing-yu-club-front/src/components/category-list/index.jsx

295 lines
12 KiB
JavaScript
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 React, { Component, Fragment, useState, useEffect } from 'react';
import {
RightOutlined,
UpOutlined,
DownOutlined,
CaretDownOutlined,
CaretUpOutlined,
} from '@ant-design/icons';
import req from '@utils/request';
import { Divider, Spin } from 'antd';
import _ from 'lodash';
import './index.less';
import { apiName, imgObject } from './constant';
/**
* 大分类中的背景图
*/
export const categoryBackImg = {
0: imgObject.backAllImg,
1: imgObject.dataImg,
2: imgObject.javaImg,
3: imgObject.npmImg,
4: imgObject.parallelComputingImg,
5: imgObject.springbootImg,
6: imgObject.sqlImg,
7: imgObject.systemDesignImg,
8: imgObject.algorithmImg,
};
const categoryShowCount = 4;
const cacheMap = {}
const CategoryList = ({ primaryCategoryId, categoryList, ...props }) => {
const [secondCategoryList, setSecondCategoryList] = useState([])
const [currentActive, setCurrentActive] = useState(categoryList[0])
const [isPutAway, setIsPutAway] = useState(true)
const [loading, setLoading] = useState(false)
const getLabels = (id) => {
return new Promise(resolve => {
req({
method: 'post',
url: apiName.queryLabelByCategoryId,
data: { categoryId: id }
}).then(res => {
if (cacheMap[id]) {
resolve(cacheMap[id])
} else {
cacheMap[id] = res.data
resolve(res.data)
}
})
})
}
// 获取大类下分类
const getCategoryByPrimary = () => {
req({
method: 'post',
url: apiName.queryCategoryByPrimary,
data: { categoryType: 2, parentId: currentActive.id }
}).then(async res => {
let list = res.data
for (let i = 0; i < list.length; i++) {
list[i].children = await getLabels(list[i].id)
}
setSecondCategoryList(_.cloneDeep(list))
})
}
useEffect(() => {
if (primaryCategoryId) {
getCategoryByPrimary()
}
}, [primaryCategoryId])
/**
* 切换一级分类
* @param {*} item
* @returns
*/
const onChangeCategory = (item) => () => {
if (currentActive.id === item.id) {
return;
}
setCurrentActive(item)
props.onChangeCategory(item);
};
/**
* 一级分类模块
* @returns
*/
const renderFirstContainer = () => {
return (
<div className="first-category-list">
{categoryList.slice(0, 7).map((categoryModuleItem, categoryModuleIndex) => {
return (
<div
className={`first-category-item ${categoryModuleItem.id === currentActive.id &&
'first-category-item-active'
}`}
key={`first_category_${categoryModuleItem.id}`}
style={{
backgroundImage: `url(${categoryBackImg[categoryModuleIndex]})`,
}}
onClick={onChangeCategory(categoryModuleItem)}>
<div className="first-category-item-title">
{categoryModuleItem.categoryName}
</div>
<div className="first-category-item-count">
{categoryModuleItem.count || 50}道题
</div>
</div>
);
})}
{categoryList.length > 7 && (
<div className="first-category-more">
更多
<RightOutlined />
</div>
)}
</div>
);
};
const [currentLabelIndex, setCurrentLabelIndex] = useState([])
/**
* 选择标签-支持单选(多选)
* @param {*} categoryId 一级分类id
* @param {*} secondCategoryIndex 二级分类对象index
* @param {*} thirdCategoryIndex 三级标签index
* @param {*} active 三级标签当前的选中状态
* @returns
*/
const onChangeLabel = (secondCategoryIndex, thirdCategoryIndex, active) => () => {
const { isMultipleChoice } = props;
const list = _.cloneDeep(secondCategoryList)
if (isMultipleChoice) {
// 三级标签支持多选
_.set(list, [secondCategoryIndex, 'children', thirdCategoryIndex, 'active'], !active)
setSecondCategoryList(list)
} else {
// 三级标签支持单选
if (currentLabelIndex.length) {
_.set(list, [currentLabelIndex[0], 'children', currentLabelIndex[1], 'active'], false)
}
_.set(list, [secondCategoryIndex, 'children', thirdCategoryIndex, 'active'], !active)
setCurrentLabelIndex([secondCategoryIndex, thirdCategoryIndex])
setSecondCategoryList(list)
}
props.onChangeLabel(_.get(list, [secondCategoryIndex, 'id']), _.get(list, [secondCategoryIndex, 'children', thirdCategoryIndex, 'id']))
};
/**
* 展开/收起
* @param {*} secondCategoryIndex
* @returns
*/
const onChangeOpenStatus = (secondCategoryIndex, isOpen) => () => {
const _list = _.cloneDeep(secondCategoryList)
_.set(_list, [secondCategoryIndex, 'isOpen'], !isOpen);
setSecondCategoryList(_list)
};
/**
* 展开/收起
*/
const onChangePutAway = () => {
setIsPutAway(!isPutAway)
};
/**
* 二级分类模块
* @returns
*/
const renderSecondContainer = () => {
return (
<Spin spinning={loading}>
<div className="second-category-list">
{secondCategoryList.map((secondCategoryItem, secondCategoryIndex) => {
return (
<div
style={{
display:
secondCategoryIndex >= categoryShowCount && isPutAway
? 'none'
: 'flex',
}}
className="second-category-item"
key={`second_category_${secondCategoryItem.id}`}>
<div className="second-category-item-title">
{secondCategoryItem.categoryName}
</div>
{secondCategoryItem?.children?.length > 0 && (
<div className="second-category-item-box">
<div
style={{
height: secondCategoryItem.isOpen ? 'auto' : 43,
}}
className="second-category-item-list"
id={`id_${secondCategoryIndex}`}>
{secondCategoryItem.children.map(
(thirdCategoryItem, thirdCategoryIndex) => {
return (
<div
className={`third-category-item ${thirdCategoryItem.active
? 'third-category-item-active'
: ''
}`}
key={`third_category_${thirdCategoryItem.id}`}
onClick={onChangeLabel(
secondCategoryIndex,
thirdCategoryIndex,
(thirdCategoryItem.active || false)
)}>
{thirdCategoryItem.labelName}
</div>
);
}
)}
</div>
{
secondCategoryItem.children.length > 5 ? <div
id={`second_id_${secondCategoryIndex}`}
className="second-category-item-status"
onClick={onChangeOpenStatus(
secondCategoryIndex,
(secondCategoryItem.isOpen || false)
)}>
<div className="second-category-item-type" style={{ fontSize: 12 }}>
{secondCategoryItem.isOpen ? '收起' : '展开'}
</div>
<div className="second-category-item-icon" style={{ fontSize: 12 }}>
{secondCategoryItem.isOpen ? (
<UpOutlined />
) : (
<DownOutlined />
)}
</div>
</div> : null
}
</div>
)}
</div>
);
})}
{secondCategoryList?.length >= categoryShowCount && (
<Divider
onClick={onChangePutAway}
dashed
style={{
marginTop: 10,
fontSize: 13,
cursor: 'pointer'
}}>
{isPutAway ? '展开' : '收起'}
{isPutAway ? (
<CaretDownOutlined style={{ marginLeft: 4 }} />
) : (
<CaretUpOutlined style={{ marginLeft: 4 }} />
)}
</Divider>
)}
</div>
</Spin>
);
};
return (
<div className="category-box">
<Fragment>{categoryList?.length && renderFirstContainer()}</Fragment>
<Fragment>
{secondCategoryList?.length > 0 && renderSecondContainer()}
</Fragment>
{/* {!this.props.isHideSec && (
<Fragment>
{secondCategoryList?.length > 0 && this.renderSecondContainer()}
</Fragment>
)} */}
</div>
)
}
export default CategoryList