diff --git a/src/App.tsx b/src/App.tsx index fd28198..e65b63d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { Component, useEffect } from 'react'; +import { useEffect, memo } from 'react'; import './App.less'; import { useLocation, useNavigate, Outlet } from 'react-router-dom'; import PubSub from 'pubsub-js'; @@ -8,67 +8,47 @@ import Head from '@views/imgs/head.jpg' import TopMenu from '@components/top-menu' const { Search } = Input; -class NavTop extends Component { - constructor(props) { - super(props); - this.state = { - userName: '', - intervieweEamil: '', - headImg: '', - isShowTimer: false, - }; - } - timerRef = React.createRef(); +const NavTop = () => { + const { pathname } = window.location; - componentDidMount() { - - PubSub.subscribe('handleToRender', () => { - this.setState({}); - }); - } - - render() { - let { headImg, isShowTimer } = this.state; - const { pathname } = window.location; - return ( -
-
-
-
- (window.location.href = '/question-bank') - }> - -
- + return ( +
+
+
+
+ (window.location.href = '/question-bank') + }> +
-
-
- {'/question-bank' == pathname && ( -
- console.log(value)} - style={{ width: 300, borderRadius: '10px' }} - /> -
- )} -
- {/* */} -
-
- +
+
+
+ {'/question-bank' == pathname && ( +
+ console.log(value)} + style={{ width: 300, borderRadius: '10px' }} />
+ )} +
+ {/* */} +
+
+
- ); - } +
+ ) } const App = () => { @@ -87,4 +67,4 @@ const App = () => { ) } -export default App +export default memo(App) diff --git a/src/components/category-list/constant.js b/src/components/category-list/constant.js index 6cb36b2..342b4dc 100644 --- a/src/components/category-list/constant.js +++ b/src/components/category-list/constant.js @@ -8,23 +8,23 @@ export const filterDifficulty = [ }, { id: 1, - title: 'T4', + title: '初级', }, { id: 2, - title: 'T5', + title: '中级', }, { id: 3, - title: 'T6', + title: '高级', }, { id: 4, - title: 'T7', + title: '资深', }, { id: 5, - title: 'T8', + title: '专家', }, ]; @@ -33,6 +33,14 @@ export const apiName = { * 获取二级和三级标签 */ getCategoryLabelInfo: '/admin/question/category/getCategoryLabelInfo', + + /** + * 查询大类下分类 + */ + queryCategoryByPrimary: '/category/queryCategoryByPrimary', + + // 根据分类查标签 + queryLabelByCategoryId: '/label/queryLabelByCategoryId' }; export const imgObject = { diff --git a/src/components/category-list/index.jsx b/src/components/category-list/index.jsx index 23930c2..e110a5f 100644 --- a/src/components/category-list/index.jsx +++ b/src/components/category-list/index.jsx @@ -1,4 +1,4 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component, Fragment, useState, useEffect } from 'react'; import { RightOutlined, @@ -8,7 +8,7 @@ import { CaretUpOutlined, } from '@ant-design/icons'; import req from '@utils/request'; -import { Divider } from 'antd'; +import { Divider, Spin } from 'antd'; import _ from 'lodash'; import './index.less'; import { apiName, imgObject } from './constant'; @@ -30,12 +30,263 @@ export const categoryBackImg = { const categoryShowCount = 4; -export default class CategoryList extends Component { +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 ( +
+ {categoryList.slice(0, 7).map((categoryModuleItem, categoryModuleIndex) => { + return ( +
+
+ {categoryModuleItem.categoryName} +
+
+ {categoryModuleItem.count || 50}道题 +
+
+ ); + })} + {categoryList.length > 7 && ( +
+ 更多 + +
+ )} +
+ ); + }; + + /** + * 选择标签-支持单选(多选) + * @param {*} categoryId 一级分类id + * @param {*} secondCategoryIndex 二级分类对象index + * @param {*} thirdCategoryIndex 三级标签index + * @param {*} active 三级标签当前的选中状态 + * @returns + */ + const onChangeLabel = (secondCategoryIndex, thirdCategoryIndex, active) => () => { + const list = _.cloneDeep(secondCategoryList) + _.set(list, [secondCategoryIndex, 'children', thirdCategoryIndex, 'active'], !active) + setSecondCategoryList(list) + }; + + /** + * 展开/收起 + * @param {*} secondCategoryIndex + * @returns + */ + const onChangeOpenStatus = (secondCategoryIndex, isOpen) => () => { + return + let { secondCategoryList } = this.state; + _.set(secondCategoryList, [secondCategoryIndex, 'isOpen'], !isOpen); + this.setState({ + secondCategoryList, + }); + }; + + /** + * 展开/收起 + */ + const onChangePutAway = () => { + return + let { isPutAway } = this.state; + this.setState({ + isPutAway: !isPutAway, + }); + }; + + /** + * 二级分类模块 + * @returns + */ + const renderSecondContainer = () => { + return ( + +
+ {secondCategoryList.map((secondCategoryItem, secondCategoryIndex) => { + return ( +
= categoryShowCount && isPutAway + ? 'none' + : 'flex', + }} + className="second-category-item" + key={`second_category_${secondCategoryItem.id}`}> +
+ {secondCategoryItem.categoryName}: +
+ {secondCategoryItem?.children?.length > 0 && ( +
+
+ {secondCategoryItem.children.map( + (thirdCategoryItem, thirdCategoryIndex) => { + return ( +
+ {thirdCategoryItem.labelName}· + {thirdCategoryItem.subjectCount || 0} +
+ ); + } + )} +
+
+
+ {secondCategoryItem.isOpen ? '收起' : '展开'} +
+
+ {secondCategoryItem.isOpen ? ( + + ) : ( + + )} +
+
+
+ )} +
+ ); + })} + {secondCategoryList?.length >= categoryShowCount && ( + + {isPutAway ? '展开' : '收起'} + {isPutAway ? ( + + ) : ( + + )} + + )} +
+
+ + ); + }; + + return ( +
+ {categoryList?.length && renderFirstContainer()} + + {secondCategoryList?.length > 0 && renderSecondContainer()} + + {/* {!this.props.isHideSec && ( + + {secondCategoryList?.length > 0 && this.renderSecondContainer()} + + )} */} +
+ ) +} + +export default CategoryList + + +class CategoryList1 extends Component { constructor(props) { super(props); this.state = { secondCategoryList: [], - currentActive: '', + currentActive: null, isPutAway: true, // 是否收起 默认收起状态 }; } @@ -49,7 +300,7 @@ export default class CategoryList extends Component { */ initCategoryList() { const { categoryList, primaryCategoryId } = this.props; - let currentActive = primaryCategoryId ?? categoryList[0].primaryCategoryId; + let currentActive = primaryCategoryId ?? categoryList[0]; this.props.onChangeCategory(currentActive); this.getSecondCategoryList(currentActive); } @@ -61,8 +312,8 @@ export default class CategoryList extends Component { const { categoryListMap } = this.props; // 调用接口返回二级三级数据 let params = { - primaryCategoryId: currentActive, - subjectTypeList: [4], + parentId: currentActive.id, + categoryType: 2, }; req({ method: 'post', @@ -210,28 +461,13 @@ export default class CategoryList extends Component { }); }; - render() { - const { categoryList } = this.props; - const { secondCategoryList } = this.state; - return ( -
- {categoryList?.length > 0 && this.renderFirstContainer()} - {!this.props.isHideSec && ( - - {secondCategoryList?.length > 0 && this.renderSecondContainer()} - - )} -
- ); - } + /** * 一级分类模块 * @returns */ renderFirstContainer = () => { - const { categoryList } = this.props; - const { currentActive } = this.state; return (
{categoryList.slice(0, 7).map((categoryModuleItem, categoryModuleIndex) => { @@ -240,7 +476,7 @@ export default class CategoryList extends Component { className={`first-category-item ${categoryModuleItem.primaryCategoryId === currentActive && 'first-category-item-active' }`} - key={`first_category_${categoryModuleItem.primaryCategoryId}`} + key={`first_category_${categoryModuleItem.id}`} style={{ backgroundImage: `url(${categoryBackImg[categoryModuleIndex]})`, }} @@ -358,5 +594,19 @@ export default class CategoryList extends Component {
); }; + render() { + const { categoryList } = this.props; + const { secondCategoryList } = this.state; + return ( +
+ {categoryList?.length > 0 && this.renderFirstContainer()} + {!this.props.isHideSec && ( + + {secondCategoryList?.length > 0 && this.renderSecondContainer()} + + )} +
+ ); + } } diff --git a/src/components/category-list/index.less b/src/components/category-list/index.less index e99a1a8..a393f5e 100644 --- a/src/components/category-list/index.less +++ b/src/components/category-list/index.less @@ -91,16 +91,30 @@ font-size: 14px; border: 1px solid rgba(0, 0, 0, 0.04); border-radius: 4px; + // @mixin box-backgroundColor($alpha: 1) { + // background-color: rgba(60, 110, 238, $alpha) !important; + // } + + // @mixin box-border($width: 1px, $style: solid, $alpha: 1) { + // border: $width $style rgba(60, 110, 238, $alpha) !important; + // } + + // @mixin font-color($alpha: 1) { + // color: rgba(60, 110, 238, $alpha) !important; + // } &:hover { - @include box-backgroundColor(0.1); - @include box-border(); - @include font-color(); + background-color: rgba(60, 110, 238, 0.1); + border: 1px solid rgba(60, 110, 238, 1); + color: rgba(60, 110, 238, 1) } } .third-category-item-active { - @include box-backgroundColor(0.1); - @include box-border(); - @include font-color(); + // @include box-backgroundColor(0.1); + // @include box-border(); + // @include font-color(); + background-color: rgba(60, 110, 238, 0.1); + border: 1px solid rgba(60, 110, 238, 1); + color: rgba(60, 110, 238, 1) } } .second-category-item-status { diff --git a/src/components/top-menu/index.jsx b/src/components/top-menu/index.jsx index 3acb3bc..1149732 100644 --- a/src/components/top-menu/index.jsx +++ b/src/components/top-menu/index.jsx @@ -1,6 +1,6 @@ import { message } from 'antd'; -import React, { Component } from 'react' -import { useLocation } from 'react-router-dom'; +import React, { Component, useState, memo } from 'react' +import { useLocation, useNavigate } from 'react-router-dom'; import './index.less' // 顶部tab const MENULIST = [ @@ -12,7 +12,7 @@ const MENULIST = [ { key: 'prictiseQuestion', title: '练题', - route: '/question-bank', + route: '/brush-question', }, { key: 'practiceQuestions', @@ -31,66 +31,43 @@ const MENULIST = [ const mapMenu = { '/question-bank': 'questionBank', } -class TopMenu extends Component { - constructor(props) { - super(props) - this.state = { - currentKey: 'questionBank', - } - } - componentDidMount() { - // this.setState({ - // currentKey: mapMenu[this.props.currentRoute] || '', - // }) - } +const TopMenu = () => { + + const [currentKey, setCurrentKey] = useState('questionBank') + const location = useLocation() + const navigate = useNavigate() /** * 切换item * @param {*} item * @returns */ - changeMenu = (item) => () => { + const changeMenu = (item) => () => { if (item.key === "questionBank") { - return + if (location.pathname === '/question-bank') return + navigate('/question-bank') } else { return message.info("敬请期待") } - - // 打开新窗口 - if (item.isOpenNewWindow) { - window.open(item.route) - return - } - this.setState( - { - currentKey: item.key, - }, - () => { - this.props.history.push(item.route) - } - ) } - render() { - const { currentKey } = this.state - return ( -
- {MENULIST.map((item, index) => { - return ( -
-
{item.title}
-
-
- ) - })} -
- ) - } + return ( +
+ {MENULIST.map((item, index) => { + return ( +
+
{item.title}
+
+
+ ) + })} +
+ ) } -export default TopMenu +export default memo(TopMenu) diff --git a/src/main.tsx b/src/main.tsx index ce4ab26..b65e600 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,5 +1,4 @@ import './main.less' - import React from 'react' import ReactDOM from 'react-dom/client' import router from '@/router' diff --git a/src/views/question-bank/index.tsx b/src/views/question-bank/index.tsx index e3e7909..dd703de 100644 --- a/src/views/question-bank/index.tsx +++ b/src/views/question-bank/index.tsx @@ -1,5 +1,5 @@ // import { Component } from 'react'; -import { useState, useEffect } from 'react' +import { useState, useEffect, memo } from 'react' import QuestionList from '@components/question-list'; import CategoryList from '@components/category-list'; import ContributionList from './components/contribution-list'; @@ -12,9 +12,8 @@ import './index.less'; const QuestionBank = () => { - const [firstCategoryList, setFirstCategoryList] = useState([]) - const [questionList, setQuestionList] = useState(mockDataList) + const [questionList, setQuestionList] = useState([]) const [isShowSpin, setIsShowSpin] = useState(false) const [labelList, setLabelList] = useState([]); // 选中的标签列表 const [difficulty, setDiffculty] = useState(0); //困难度(全部) @@ -46,30 +45,13 @@ const QuestionBank = () => { }) } - // 获取大类下分类 - const getCategoryByPrimary = () => { - req({ - method: 'post', - url: apiName.queryCategoryByPrimary, - data: { categoryType: 1, parentId: 1 } - }).then(res => { - console.log(res) - }) - } - - useEffect(() => { - if (primaryCategoryId) { - getCategoryByPrimary() - } - }, [primaryCategoryId]) - /** * 切换一级分类 * @param {*} e */ - const onChangeCategory = (e: string) => { + const onChangeCategory = (item: Record) => { setLabelList([]) - setPromaryCategoryId(e) + setPromaryCategoryId(item.id) setPageIndex(1) }; @@ -82,11 +64,12 @@ const QuestionBank = () => { setLabelList(assembleIds) setPromaryCategoryId(primaryCategoryId) setPageIndex(1) - // this.getInterviewSubjectList(); }; useEffect(() => { - getPrimaryCategoryInfo() + if (!primaryCategoryId) { + getPrimaryCategoryInfo() + } }, []) return ( @@ -99,6 +82,7 @@ const QuestionBank = () => { onChangeCategory={onChangeCategory} categoryList={firstCategoryList} onChangeLabel={onChangeLabel} + primaryCategoryId={primaryCategoryId} /> )}
@@ -123,131 +107,4 @@ const QuestionBank = () => {
); } -export default QuestionBank -// class QuestionBank extends Component { -// constructor(props) { -// super(props); -// this.state = { -// firstCategoryList: [], -// questionList: [], -// isShowSpin: false, -// }; -// } -// labelList = []; // 选中的标签列表 -// difficulty = 0; //困难度(全部) -// total = 0; // 总条数 -// pageIndex = 1; -// primaryCategoryId = ''; //第一个大类id - -// componentDidMount() { -// // this.getPrimaryCategoryInfo(); -// // console.log(this.props.route); -// } - - - -// /** -// * 获取题目列表 -// */ -// getInterviewSubjectList() { -// let params = { -// pageInfo: { -// pageIndex: this.pageIndex, -// pageSize: 10, -// }, -// difficulty: this.difficulty, -// primaryCategoryId: this.primaryCategoryId, -// assembleIds: this.labelList, -// }; -// req({ -// method: 'post', -// data: params, -// url: apiName.getInterviewSubjectList, -// }) -// .then((res) => { -// if (res.data && res.data?.pageList?.length > 0) { -// this.total = res.data.pageInfo.total; -// this.setState({ -// questionList: res.data.pageList, -// isShowSpin: false, -// }); -// } else { -// this.total = 0; -// this.setState({ -// questionList: [], -// isShowSpin: false, -// }); -// } -// }) -// .catch((err) => console.log(err)); -// } - - - -// /** -// * 切换一级分类 -// * @param {*} e -// */ -// onChangeCategory = (e) => { -// this.labelList = []; -// this.primaryCategoryId = e; -// this.pageIndex = 1; -// this.getInterviewSubjectList(); -// }; - -// /** -// * 筛选列表数据 -// * @param {*} id -// */ -// handleChangeSelect = (id) => { -// this.difficulty = id; -// this.pageIndex = 1; -// this.getInterviewSubjectList(); -// }; - -// /** -// * 分页功能 -// * @param {*} pageIndex 当前页码 -// */ -// onChangePagination = (pageIndex) => { -// this.pageIndex = pageIndex; -// this.getInterviewSubjectList(); -// }; - -// render() { -// const { firstCategoryList, questionList, isShowSpin } = this.state; -// return ( -//
-// -//
-//
-// {firstCategoryList?.length > 0 && ( -// -// )} -//
-//
-// -//
-//
-//
-//
-// -// -//
-//
-// ); -// } -// } +export default memo(QuestionBank) diff --git a/src/views/upload-questions/components/kind-editor/index.jsx b/src/views/upload-questions/components/kind-editor/index.jsx index f6ba25f..594f9fe 100644 --- a/src/views/upload-questions/components/kind-editor/index.jsx +++ b/src/views/upload-questions/components/kind-editor/index.jsx @@ -1,11 +1,19 @@ -import React, { Component } from 'react'; +import React, { Component, useRef } from 'react'; import './index.less'; import Editor from 'wangeditor'; +const defaultValueHead = `
`; +const defaultValueFoot = '
'; + +// const KindEditor = () => { +// const menuRef = useRef() +// const bodyRef = useRef() +// const editor = new Editor() + +// } + export default class KindEditor extends Component { - defaultValueHead = `
`; - defaultValueFoot = '
'; editor = Editor; constructor(props) { diff --git a/src/views/upload-questions/constant.js b/src/views/upload-questions/constant.js index 8c73523..9f22418 100644 --- a/src/views/upload-questions/constant.js +++ b/src/views/upload-questions/constant.js @@ -3,9 +3,9 @@ */ export const apiName = { /** - * 获取一级/二级分类 + * 获取一级 */ - getInterviewCategory: '/admin/question/category/getCategory', + queryPrimaryCategory: '/subject/category/queryPrimaryCategory', /** * 获取三级分类标签