From 5a17d2da74ed4c0d2e313fa182114123661045c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E6=B0=B4=E6=B5=AE=E5=B0=98?= <18510549872@163.comm> Date: Sun, 12 Nov 2023 16:54:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 4 +- src/App.less | 213 +++--- src/components/category-list/index.jsx | 670 +++++++++--------- src/constants/index.ts | 126 ++-- src/imgs/ranking1Img.png | Bin 0 -> 3750 bytes src/imgs/ranking2Img.png | Bin 0 -> 4360 bytes src/imgs/ranking3Img.png | Bin 0 -> 4566 bytes src/imgs/rankingImg.png | Bin 0 -> 603 bytes src/utils/request.ts | 119 ++-- src/views/login/index.less | 70 +- src/views/login/index.tsx | 89 ++- .../components/ranking-box/index.jsx | 69 +- src/views/user-info/index.tsx | 67 +- vite.config.ts | 16 +- 14 files changed, 744 insertions(+), 699 deletions(-) create mode 100644 src/imgs/ranking1Img.png create mode 100644 src/imgs/ranking2Img.png create mode 100644 src/imgs/ranking3Img.png create mode 100644 src/imgs/rankingImg.png diff --git a/.env.development b/.env.development index 204eaff..6a06899 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,2 @@ -VITE_API_HOST=http://117.72.10.84:3010 -VITE_IMG_HOST=http://117.72.14.166:9000 \ No newline at end of file +VITE_API_HOST=http://117.72.10.84:5000 +VITE_IMG_HOST=http://117.72.14.166:9000 diff --git a/src/App.less b/src/App.less index cb96a0e..8b051e6 100644 --- a/src/App.less +++ b/src/App.less @@ -1,159 +1,160 @@ @import '@assets/base.less'; .app-main { - display: flex; - flex-direction: row; - border-radius: 4px; + display: flex; + flex-direction: row; + border-radius: 4px; + margin: 0 auto; + position: absolute; + min-width: 1439px; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #f3f4f6; + padding: 66px 16px 32px; + overflow: hidden; + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; /* Non-prefixed version, currently not supported by any browser */ + .content-box { + width: 1439px; margin: 0 auto; - position: absolute; - min-width: 1439px; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: #f3f4f6; - padding: 66px 16px 32px; - overflow: hidden; - -webkit-touch-callout: none; /* iOS Safari */ - -webkit-user-select: none; /* Chrome/Safari/Opera */ - -khtml-user-select: none; /* Konqueror */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* Internet Explorer/Edge */ - user-select: none; /* Non-prefixed version, currently not supported by any browser */ - .content-box{ - width: 1439px; - margin: 0 auto; - } + overflow: auto; + } } .header-navigator { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 50px; - min-width: 1439px; - background-color: #fff; - border-radius: 4px; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 50px; + min-width: 1439px; + background-color: #fff; + border-radius: 4px; } .nav-title { - display: flex; - justify-content: space-between; - cursor: pointer; - width: 1407px; - margin: 0 auto; - line-height: 50px; - color: #1890ff; - font-size: 24px; - // font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", 微软雅黑, - // Arial, sans-serif; + display: flex; + justify-content: space-between; + cursor: pointer; + width: 1407px; + margin: 0 auto; + line-height: 50px; + color: #1890ff; + font-size: 24px; + // font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", 微软雅黑, + // Arial, sans-serif; } .header-navigator .user { - width: 36px; - height: 36px; - float: right; - /* background: #1890ff; */ - border-radius: 50%; - color: #fff; - margin-top: 7px; - line-height: 36px; - text-align: center; - font-size: 16px; - overflow: hidden; - box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.08); + width: 36px; + height: 36px; + float: right; + /* background: #1890ff; */ + border-radius: 50%; + color: #fff; + margin-top: 7px; + line-height: 36px; + text-align: center; + font-size: 16px; + overflow: hidden; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.08); } .jump-box { - font-size: 14px; - margin-right: 20px; + font-size: 14px; + margin-right: 20px; } .info-time-box { - display: flex; + display: flex; } .time-box { - margin-top: 8px; - margin-right: 120px; + margin-top: 8px; + margin-right: 120px; } .head-navigator-box { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 50px; - background-color: #fff; - border-radius: 4px; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 50px; + background-color: #fff; + border-radius: 4px; } .head-navigator { - display: flex; - align-items: center; - justify-content: space-between; - margin: 0 auto; - width: 1435px; + display: flex; + align-items: center; + justify-content: space-between; + margin: 0 auto; + width: 1435px; } .head-navigator-left { - display: flex; - align-items: center; + display: flex; + align-items: center; } .head-navigator-logo { - margin-right: 20px; - // line-height: 50px; - cursor: pointer; - color: #1890ff; - font-size: 24px; - // font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, 微软雅黑, - // Arial, sans-serif; + margin-right: 20px; + // line-height: 50px; + cursor: pointer; + color: #1890ff; + font-size: 24px; + // font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, 微软雅黑, + // Arial, sans-serif; } .head-navigator-select-box { - display: flex; - justify-content: space-between; - align-items: center; - width: 500px; + display: flex; + justify-content: space-between; + align-items: center; + width: 500px; } .head-navigator-menu-box { - display: flex; + display: flex; } .head-navigator-menu-box .ant-menu-horizontal { - border-bottom: 0; + border-bottom: 0; } .ant-menu-horizontal > .ant-menu-item, .ant-menu-horizontal > .ant-menu-submenu { - padding: 0px; - margin: 0 12px; + padding: 0px; + margin: 0 12px; } .head-navigator-input-box { - margin-right: 24px; + margin-right: 24px; } .head-navigator-input-box .ant-input { - border-radius: 16px; + border-radius: 16px; } .head-navigator-user-box { - display: flex; - justify-content: center; - align-items: center; + display: flex; + justify-content: center; + align-items: center; } .head-navigator-bell { - display: flex; - justify-content: center; - align-items: center; - margin-right: 24px; - width: 28px; - height: 28px; - border-radius: 50%; - cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + margin-right: 24px; + width: 28px; + height: 28px; + border-radius: 50%; + cursor: pointer; } .head-navigator-bell:hover { - background-color: rgba(0, 10, 32, 0.03); + background-color: rgba(0, 10, 32, 0.03); } .head-navigator-user-img { - width: 36px; - height: 36px; - color: #fff; - cursor: pointer; - border-radius: 50%; - box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.08); + width: 36px; + height: 36px; + color: #fff; + cursor: pointer; + border-radius: 50%; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.08); } diff --git a/src/components/category-list/index.jsx b/src/components/category-list/index.jsx index 02a68ac..efec0c5 100644 --- a/src/components/category-list/index.jsx +++ b/src/components/category-list/index.jsx @@ -1,373 +1,353 @@ -import React, { Fragment, useState, useEffect } from 'react'; +import React, { Fragment, useEffect, useState } from 'react' import { - RightOutlined, - UpOutlined, - DownOutlined, - CaretDownOutlined, - CaretUpOutlined, -} from '@ant-design/icons'; -import req from '@utils/request'; -import { Divider, Spin, Modal } from 'antd'; -import _ from 'lodash'; -import './index.less'; -import { apiName } from './constant'; -import { imgObject } from '@constants' + CaretDownOutlined, + CaretUpOutlined, + DownOutlined, + RightOutlined, + UpOutlined +} from '@ant-design/icons' +import req from '@utils/request' +import { Divider, Modal, Spin } from 'antd' +import _ from 'lodash' +import { apiName } from './constant' +import './index.less' /** - * 大分类中的背景图 + * 大分类中的背景图颜色 */ -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 categoryBackColor = { + 0: '#23b2ff', + 1: '#ea7d4d', + 2: '#e93532', + 3: '#343d71', + 4: '#dc4ad6', + 5: '#72b633', + 6: '#9047de', + 7: '#dc4077' +} -const categoryShowCount = 4; +const categoryShowCount = 4 const cacheMap = {} /** - * 上万后展示 W+ - * @param {*} total - * @returns - */ -const formatTotal = (total) => { - if (total >= 10000) { - return Math.floor(total / 10000) + 'W+'; - } - return total; + * 上万后展示 W+ + * @param {*} total + * @returns + */ +const formatTotal = total => { + if (total >= 10000) { + return Math.floor(total / 10000) + 'W+' + } + return total } 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 [currentLabelIndex, setCurrentLabelIndex] = useState([]) - const [openMoreFlag, setOpenMoreFlag] = useState(false) + const [secondCategoryList, setSecondCategoryList] = useState([]) + const [currentActive, setCurrentActive] = useState(categoryList[0]) + const [isPutAway, setIsPutAway] = useState(true) + const [loading, setLoading] = useState(false) + const [currentLabelIndex, setCurrentLabelIndex] = useState([]) + const [openMoreFlag, setOpenMoreFlag] = 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) - if (i === 0 && list[i].children.length) { - list[i].children[0].active = true - } - } - setSecondCategoryList(_.cloneDeep(list)) - setCurrentLabelIndex([0, 0]) - props.onChangeLabel(_.get(list, [0, 'id']), _.get(list, [0, 'children', 0, 'id'])) - }) - } - - 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 && ( -
setOpenMoreFlag(true)}> - 更多 - -
- )} -
- ); - }; - - - /** - * 点击更多的分类项 - * @param {*} id - * @returns - */ - const onChangeCategoryMore = (cur) => () => { - setOpenMoreFlag(false) - setCurrentActive(cur) - let list = [...categoryList].reduce((pre, item) => { - if (item.id !== cur.id) { - pre.push(item); - } else { - pre.unshift(item); - } - return pre; - }, []); - props.onChangeCategoryMore && props.onChangeCategoryMore(cur.id, list); - }; - - /** - * 更多分类 - * @returns - */ - const renderMoreBox = () => { - return ( -
- {categoryList.slice(7).map((categoryModuleItem, categoryModuleIndex) => { - return ( -
-
- {categoryModuleItem.categoryName} -
-
- {formatTotal(categoryModuleItem.subjectCount)}道题 -
-
- ); - })} -
- ); - }; - - /** - * 选择标签-支持单选(多选) - * @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) + 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 { - // 三级标签支持单选 - if (currentLabelIndex.length) { - _.set(list, [currentLabelIndex[0], 'children', currentLabelIndex[1], 'active'], false) - } - _.set(list, [secondCategoryIndex, 'children', thirdCategoryIndex, 'active'], !active) - setCurrentLabelIndex([secondCategoryIndex, thirdCategoryIndex]) - setSecondCategoryList(list) + cacheMap[id] = res.data + resolve(res.data) } - 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 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) + if (i === 0 && list[i].children.length) { + list[i].children[0].active = true + } + } + setSecondCategoryList(_.cloneDeep(list)) + setCurrentLabelIndex([0, 0]) + props.onChangeLabel(_.get(list, [0, 'id']), _.get(list, [0, 'children', 0, 'id'])) + }) + } - /** - * 展开/收起 - */ - const onChangePutAway = () => { - setIsPutAway(!isPutAway) - }; + useEffect(() => { + if (primaryCategoryId) { + getCategoryByPrimary() + } + }, [primaryCategoryId]) - /** - * 二级分类模块 - * @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} -
- ); - } - )} -
- { - secondCategoryItem.children.length > 5 ?
-
- {secondCategoryItem.isOpen ? '收起' : '展开'} -
-
- {secondCategoryItem.isOpen ? ( - - ) : ( - - )} -
-
: null - } - -
- )} -
- ); - })} - {secondCategoryList?.length >= categoryShowCount && ( - - {isPutAway ? '展开' : '收起'} - {isPutAway ? ( - - ) : ( - - )} - - )} -
-
- - ); - }; + /** + * 切换一级分类 + * @param {*} item + * @returns + */ + const onChangeCategory = item => () => { + if (currentActive.id === item.id) { + return + } + setCurrentActive(item) + props.onChangeCategory(item) + } + /** + * 一级分类模块 + * @returns + */ + const renderFirstContainer = () => { return ( -
- {categoryList?.length && renderFirstContainer()} - - {secondCategoryList?.length > 0 && renderSecondContainer()} - - {/* {!this.props.isHideSec && ( +
+ {categoryList.slice(0, 7).map((categoryModuleItem, categoryModuleIndex) => { + return ( +
+
{categoryModuleItem.categoryName}
+
{categoryModuleItem.count || 50}道题
+
+ ) + })} + {categoryList.length > 7 && ( +
setOpenMoreFlag(true)}> + 更多 + +
+ )} +
+ ) + } + + /** + * 点击更多的分类项 + * @param {*} id + * @returns + */ + const onChangeCategoryMore = cur => () => { + setOpenMoreFlag(false) + setCurrentActive(cur) + let list = [...categoryList].reduce((pre, item) => { + if (item.id !== cur.id) { + pre.push(item) + } else { + pre.unshift(item) + } + return pre + }, []) + props.onChangeCategoryMore && props.onChangeCategoryMore(cur.id, list) + } + + /** + * 更多分类 + * @returns + */ + const renderMoreBox = () => { + return ( +
+ {categoryList.slice(7).map((categoryModuleItem, categoryModuleIndex) => { + return ( +
+
{categoryModuleItem.categoryName}
+
+ {formatTotal(categoryModuleItem.subjectCount)}道题 +
+
+ ) + })} +
+ ) + } + + /** + * 选择标签-支持单选(多选) + * @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 ( + +
+ {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} +
+ ) + })} +
+ {secondCategoryItem.children.length > 5 ? ( +
+
+ {secondCategoryItem.isOpen ? '收起' : '展开'} +
+
+ {secondCategoryItem.isOpen ? : } +
+
+ ) : null} +
+ )} +
+ ) + })} + {secondCategoryList?.length >= categoryShowCount && ( + + {isPutAway ? '展开' : '收起'} + {isPutAway ? ( + + ) : ( + + )} + + )} +
+
+ ) + } + + return ( +
+ {categoryList?.length && renderFirstContainer()} + {secondCategoryList?.length > 0 && renderSecondContainer()} + {/* {!this.props.isHideSec && ( {secondCategoryList?.length > 0 && this.renderSecondContainer()} )} */} - setOpenMoreFlag(false)}> - {renderMoreBox()} - -
- ) + setOpenMoreFlag(false)} + > + {renderMoreBox()} + +
+ ) } export default CategoryList - - diff --git a/src/constants/index.ts b/src/constants/index.ts index 8371d10..2f1b4de 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -3,86 +3,60 @@ const host = import.meta.env.VITE_IMG_HOST * 难度筛选 */ export const filterDifficulty = [ - { - id: 0, - title: '全部', - }, - { - id: 1, - title: '初级', - }, - { - id: 2, - title: '中级', - }, - { - id: 3, - title: '高级', - }, - { - id: 4, - title: '资深', - }, - { - id: 5, - title: '专家', - }, -]; + { + id: 0, + title: '全部' + }, + { + id: 1, + title: '初级' + }, + { + id: 2, + title: '中级' + }, + { + id: 3, + title: '高级' + }, + { + id: 4, + title: '资深' + }, + { + id: 5, + title: '专家' + } +] /** * 难度等级 */ export const gradeObject = { - 1: { - color: 'rgba(60, 110, 238, 0.5)', - title: '初级', - }, - 2: { - color: 'rgba(60, 110, 238, 0.6)', - title: '中级', - }, - 3: { - color: 'rgba(60, 110, 238, 0.7)', - title: '高级', - }, - 4: { - color: 'rgba(60, 110, 238, 0.8)', - title: '资深', - }, - 5: { - color: 'rgba(60, 110, 238, 0.9)', - title: '专家', - }, -}; + 1: { + color: 'rgba(60, 110, 238, 0.5)', + title: '初级' + }, + 2: { + color: 'rgba(60, 110, 238, 0.6)', + title: '中级' + }, + 3: { + color: 'rgba(60, 110, 238, 0.7)', + title: '高级' + }, + 4: { + color: 'rgba(60, 110, 238, 0.8)', + title: '资深' + }, + 5: { + color: 'rgba(60, 110, 238, 0.9)', + title: '专家' + } +} export const imgObject = { - clickImg: - host + '/jichi/icon/%E7%83%AD%E9%97%A8.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20231102%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231102T153146Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=e6b8cdb3231b1c3d7114212cb9278ecc17cf6d4ec0f759ea0200e04156d4c8b7', - ranking1Img: - 'https://img12.360buyimg.com/imagetools/jfs/t1/110906/3/22471/3750/6214a3bfE392596cf/122c9e4b30948682.png', - ranking2Img: - 'https://img13.360buyimg.com/imagetools/jfs/t1/211695/8/12987/4360/6214a3bfEd4679fde/4f3c55783bb9119c.png', - ranking3Img: - 'https://img10.360buyimg.com/imagetools/jfs/t1/175261/19/28428/4566/6214a3bfE476e1b0f/ea59084c55001c06.png', - rankingImg: - 'https://img11.360buyimg.com/imagetools/jfs/t1/167264/35/27633/603/6214a3bfEf8feff1d/8d833235e6bc468d.png', - timeline: - 'https://img13.360buyimg.com/imagetools/jfs/t1/210387/35/7564/555/617f4fbbE0cb305c1/728913d21e650794.png', - backAllImg: - 'https://img11.360buyimg.com/imagetools/jfs/t1/206213/24/13307/2603/617f4fc4E676d448d/622d5287fbf5a919.png', - dataImg: - 'https://img12.360buyimg.com/imagetools/jfs/t1/207558/34/7606/3672/617f4fc4E1ca685fc/3953a92a6072fba4.png', - javaImg: 'https://img14.360buyimg.com/imagetools/jfs/t1/213752/24/2703/4803/617f4fc4E037da291/5f8050641d4d73d2.png', - npmImg: 'https://img11.360buyimg.com/imagetools/jfs/t1/200551/24/15367/3145/617f4fc4Ea153dc2e/b4bbf2de8807f42d.png', - parallelComputingImg: - 'https://img14.360buyimg.com/imagetools/jfs/t1/207198/23/7638/3037/617f4fc4E0e20ab9d/40197a6c79c5a33f.png', - springbootImg: - 'https://img13.360buyimg.com/imagetools/jfs/t1/171775/10/24915/4127/617f4fc4Eeb3d356e/cfbfe8d7c3155047.png', - sqlImg: 'https://img13.360buyimg.com/imagetools/jfs/t1/208027/11/7347/3074/617f4fc4Ef11e9495/1093903301db1d1d.png', - systemDesignImg: - 'https://img12.360buyimg.com/imagetools/jfs/t1/206967/24/7622/3629/617f4fc4E60a188b3/cb659847c5d4232a.png', - algorithmImg: - 'https://img14.360buyimg.com/imagetools/jfs/t1/215758/34/2633/4128/617f4fc4E5dcdab66/727be155858a06a5.png', - defaultImg: - 'https://img13.360buyimg.com/imagetools/jfs/t1/155957/24/22934/2028/617a147cE8bcbb57a/7a4885e4ae99a895.png', -}; \ No newline at end of file + clickImg: + host + + '/jichi/icon/%E7%83%AD%E9%97%A8.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20231102%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231102T153146Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=e6b8cdb3231b1c3d7114212cb9278ecc17cf6d4ec0f759ea0200e04156d4c8b7' +} diff --git a/src/imgs/ranking1Img.png b/src/imgs/ranking1Img.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec2a1df706eaa320766e7852f4de143125befcd GIT binary patch literal 3750 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 Q$p8QV07*qoM6N<$f+pwICjbBd literal 0 HcmV?d00001 diff --git a/src/imgs/ranking2Img.png b/src/imgs/ranking2Img.png new file mode 100644 index 0000000000000000000000000000000000000000..367aae03668b7f01c4747efd51bb202467d46403 GIT binary patch literal 4360 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 AdjJ3c literal 0 HcmV?d00001 diff --git a/src/imgs/rankingImg.png b/src/imgs/rankingImg.png new file mode 100644 index 0000000000000000000000000000000000000000..bfd4c2d5adc51e5dc570156f0c9f0bf456df8b45 GIT binary patch literal 603 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!o0(?STf%KPezyJUL|MmNCAo}+6 z50DK6K*6uye}U1TZ$H3NKYo4v@%#ICAo~CH+pn)61;4+5)BwrfKrWE|<@=xS-~W68 zEBp5A*Uz8-fBg9W6>K0#3s@yk@t1GE-qvV@1MOBX3GxeOn8^6!aUeI_o4bpqcQ@sv z+RL5W^!eKHy{lIyM!VUV>Z(c#U)WMvaryZcIR*yCY)==*kc@k8XLaT^8wj`@u5BxL zqNHy5{Qv(AUQ5+lml@88ox0+;U4q-Dk6h;~Of-CsYj7PlbhnuyEIt2*uvoXr@wqmt z)6aWd(J&6GEYDfkXj=ACtUmWK=eJoI+GWLm4%N6T)N_1n`fwrm-fq8-lU`nZz4$## zfRM$lPrq5CHr~iSDX+Xm&8jT^&k=X_KT95m<)pnhk#pH`pVk7$z^!w+H?r!kxshu+ zr8eX7YWAOI?)snBW@&t1c1FZGQv9nzd5%D$^?AQA7NHih}w|$s-Et>m(%jSqF-HpYHGY?9TZok)wXjVR?^_?pc2p zD%7v}sSv%${B)0H)HA;0|LyMW51hO3;7%#Oql-d?c-KCA6?TPpYu29JqpqRT;`St7 z-@EG2FI%nhXYS1Xj`w6vU0I@j$FlbCi_@% literal 0 HcmV?d00001 diff --git a/src/utils/request.ts b/src/utils/request.ts index f689f5f..ea1e690 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -1,66 +1,71 @@ -import axios from 'axios'; -import { message, Modal } from 'antd'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { message } from 'antd' +import axios from 'axios' export const baseHttp = () => { - const http = axios.create({ - baseURL: "/subject", - timeout: 5 * 60 * 1000, // request timeout - withCredentials: true, // send cookies when cross-domain requests - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, - }); + const http = axios.create({ + baseURL: '/subject', + timeout: 5 * 60 * 1000, // request timeout + withCredentials: true, // send cookies when cross-domain requests + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } + }) - return http; -}; + return http +} export default function request(config, url) { - // const navigate = useNavigate() + console.log(config, url, 'config url') + // const navigate = useNavigate() + const userInfoStorage = localStorage.getItem('userInfo') + const userInfo = userInfoStorage ? JSON.parse(userInfoStorage) : {} + const baseURL = url || '/subject/subject' + // 1.创建axios的实例 + const instance = axios.create({ + baseURL, + timeout: 5 * 60 * 1000, // request timeout + withCredentials: true, // send cookies when cross-domain requests + headers: { + 'Content-Type': 'application/json; charset=utf-8', + [userInfo.tokenName]: 'jichi ' + userInfo.tokenValue + } + }) - const baseURL = url || '/subject'; - // 1.创建axios的实例 - const instance = axios.create({ - baseURL, - timeout: 5 * 60 * 1000, // request timeout - withCredentials: true, // send cookies when cross-domain requests - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, - }); + // 2.axios的拦截器 + // 2.1.请求拦截的作用 + instance.interceptors.request.use( + config => { + return config + }, + err => { + console.log(err) + } + ) - // 2.axios的拦截器 - // 2.1.请求拦截的作用 - instance.interceptors.request.use( - (config) => { - return config; - }, - (err) => { - console.log(err); - } - ); + // 2.2.响应拦截 + instance.interceptors.response.use( + res => { + let { code } = res.data + if (code === 500) { + message.error(res.data.message) + } + if (code === 401) { + window.location.replace('/login') + } + return res.data + }, + err => { + let { status } = err?.response ?? {} + if (status === 401 || !status) { + message.info('页面异常') + window.location.replace('/login') + } else if (status === 500 || status === 503) { + message.error('服务器错误') + } + return Promise.reject(err) + } + ) - // 2.2.响应拦截 - instance.interceptors.response.use( - (res) => { - let { code } = res.data; - if (code === 500) { - message.error(res.data.message); - } - return res.data; - }, - (err) => { - let { status } = err?.response ?? {}; - if (status === 401 || !status) { - message.info('页面异常') - window.location.replace('/login') - } else if (status === 500 || status === 503) { - message.error('服务器错误'); - } - return Promise.reject(err); - } - ); - - // 3.发送真正的网络请求 - return instance(config); + // 3.发送真正的网络请求 + return instance(config) } diff --git a/src/views/login/index.less b/src/views/login/index.less index 4423abd..7be6d1f 100644 --- a/src/views/login/index.less +++ b/src/views/login/index.less @@ -1,35 +1,39 @@ -.login-box{ +.login-box { + width: 100%; + height: calc(100% - 100px); + background: url(../../imgs/login_bg.jpg) no-repeat 50%; + background-size: cover; + min-height: 600px; + position: relative; + .login-container-inner { + background: transparent; + position: absolute; + top: 50%; + left: 50%; + height: 534px; + transform: translate(-50%, -50%); + clear: both; + max-width: 1520px; + display: flex; + justify-content: space-between; + align-items: center; width: 100%; - height: calc(100% - 100px); - background: url(../../imgs/login_bg.jpg) no-repeat 50%; - background-size: cover; - min-height: 600px; - position: relative; - .login-container-inner{ - background: transparent; - position: absolute; - top: 50%; - left: 50%; - height: 534px; - transform: translate(-50%,-50%); - clear: both; - max-width: 1520px; - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - .notes{ - color: white; - max-width: 400px; - line-height: 30px; - } - .qrcode-box{ - width: 400px; - height: 500px; - background: white; - border-radius: 10px; - text-align: center; - padding: 20px; - } + .notes { + color: white; + max-width: 400px; + line-height: 30px; } -} \ No newline at end of file + .qrcode-box { + width: 400px; + height: 500px; + background: white; + border-radius: 10px; + text-align: center; + padding: 20px; + .qrcode-desc { + padding: 20px 0; + line-height: 30px; + } + } + } +} diff --git a/src/views/login/index.tsx b/src/views/login/index.tsx index e4a398f..fed0a22 100644 --- a/src/views/login/index.tsx +++ b/src/views/login/index.tsx @@ -1,45 +1,70 @@ -import { useState } from 'react' -import { Input, Button, Space } from 'antd' import LoginQrcode from '@imgs/login_qrcode.jpg' -import req from '@utils/request'; +import req from '@utils/request' +import { Button, Input, Space, message } from 'antd' +import { useState } from 'react' +import { useNavigate } from 'react-router-dom' import './index.less' const loginApiName = '/user/doLogin' const Login = () => { + const [validCode, setValidCode] = useState('') + const navigate = useNavigate() - const [validCode, setValidCode] = useState('') - const changeCode = e => { - setValidCode(e.target.value) - } + const changeCode = e => { + setValidCode(e.target.value) + } - const doLogin = () => { - if (!validCode) return - req({ - method: 'get', - url: loginApiName, - data: { validCode } - }) - } + const doLogin = () => { + console.log(validCode) + if (!validCode) return + req( + { + method: 'get', + url: loginApiName, + params: { validCode } + }, + '/auth' + ).then(res => { + if (res.success && res.data) { + message.success('登录成功') + localStorage.setItem('userInfo', JSON.stringify(res.data)) + setTimeout(() => { + navigate('/question-bank') + }, 1000) + } + }) + } - return (
-
-
LeNet-5 诞生 - 1998 年 11 月,早期经典卷积神经网络 LeNet-5 诞生。杨立昆、莱昂·伯托等发表经典论文“Gradient-Based Learning Applied to Document Recognition”,文章总结了应用于手写字符识别的各种模型并进行了比对,结果显示卷积神经网络表现超群。
-
-
- -
-
- - - - -
-
+ return ( +
+
+
+ LeNet-5 诞生 1998 年 11 月,早期经典卷积神经网络 LeNet-5 + 诞生。杨立昆、莱昂·伯托等发表经典论文“Gradient-Based Learning Applied to Document + Recognition”,文章总结了应用于手写字符识别的各种模型并进行了比对,结果显示卷积神经网络表现超群。
-
) +
+
+

微信扫码关注公众号

+

获取验证码登录

+
+
+ +
+
+ + + + +
+
+
+
+ ) } -export default Login \ No newline at end of file +export default Login diff --git a/src/views/question-bank/components/ranking-box/index.jsx b/src/views/question-bank/components/ranking-box/index.jsx index 1094e54..a255149 100644 --- a/src/views/question-bank/components/ranking-box/index.jsx +++ b/src/views/question-bank/components/ranking-box/index.jsx @@ -1,20 +1,23 @@ -import React from 'react' -import { Popover, Spin } from 'antd' +import ClickImg from '@/imgs/clickImg.png' +import Ranking1Img from '@/imgs/ranking1Img.png' +import Ranking2Img from '@/imgs/ranking2Img.png' +import Ranking3Img from '@/imgs/ranking3Img.png' +import RankingImg from '@/imgs/rankingImg.png' import { debounce } from '@utils' -import { RankingTypeText, RankingTypeBtnText } from '../../constant' +import { Popover, Spin, message } from 'antd' +import React from 'react' +import { RankingTypeBtnText, RankingTypeText } from '../../constant' import './index.less' -import { message } from 'antd' -import { imgObject } from '@constants' const rankingBackImg = { - 0: imgObject.ranking1Img, - 1: imgObject.ranking2Img, - 2: imgObject.ranking3Img, + 0: Ranking1Img, + 1: Ranking2Img, + 2: Ranking3Img } export default function RankingBox(props) { const { isLoading = false, currentActive, rankingType, contributionList } = props - const onChangeRanking = (index) => + const onChangeRanking = index => debounce(() => { props.onHandleRanking && props.onHandleRanking(index) }) @@ -36,17 +39,19 @@ export default function RankingBox(props) { let rankingList = contributionList || [] return ( -
-
-
{RankingTypeText[rankingType]}
-
+
+
+
{RankingTypeText[rankingType]}
+
{tabList.length > 0 && tabList.map((item, index) => { return (
{item.tab}
@@ -55,56 +60,52 @@ export default function RankingBox(props) {
-
+
{rankingList?.length > 0 && rankingList.map((item, index) => { return ( -
-
+
+
{index > 2 && index + 1}
-
- +
+
- {item.name} -
- } + title={
{item.name}
} content={ -
+
{item.name}
{/*
{item.organizationFullName}
*/}
} > -
-
{item.name}
+
+
{item.name}
{/*
{item.organizationName}
*/}
-
🔥 {item.count}
+
🔥 {item.count}
) })}
-
+
-
{RankingTypeBtnText[rankingType]}
+
{RankingTypeBtnText[rankingType]}
) diff --git a/src/views/user-info/index.tsx b/src/views/user-info/index.tsx index 92105c1..93473ce 100644 --- a/src/views/user-info/index.tsx +++ b/src/views/user-info/index.tsx @@ -1,10 +1,14 @@ import Head from '@/imgs/head.jpg' import { LoadingOutlined, PlusOutlined } from '@ant-design/icons' -import { Button, Card, Col, Form, Input, Radio, Row } from 'antd' +import req from '@utils/request' +import { Button, Card, Col, Form, Input, Radio, Row, message } from 'antd' import { memo, useState } from 'react' +import { useNavigate } from 'react-router-dom' + import './index.less' const { TextArea } = Input +const apiName = '/user/update' const layout = { labelCol: { span: 4 }, @@ -15,9 +19,43 @@ const UserInfo = () => { const [form] = Form.useForm() const [editFlag, setEditFlag] = useState(false) const [loading, setLoading] = useState(false) + const navigate = useNavigate() - const onFinish = values => { - console.log(values) + const onFinish = () => { + setLoading(true) + const userInfoStorage = localStorage.getItem('userInfo') + const { loginId = '' } = userInfoStorage ? JSON.parse(userInfoStorage) : {} + const values = form.getFieldsValue() + if (!Object.values(values).filter(Boolean).length) { + setLoading(false) + return + } + const params = { + userName: loginId, + ...values + } + req( + { + method: 'post', + url: apiName, + data: { ...params } + }, + '/auth' + ) + .then(res => { + if (res.success) { + message.success('更新成功') + setTimeout(() => { + navigate('/question-bank') + }, 1000) + } + setLoading(false) + setEditFlag(false) + }) + .catch(() => { + message.error('更新失败') + setLoading(false) + }) } const uploadButton = ( @@ -50,10 +88,7 @@ const UserInfo = () => { {editFlag ? ( - + @@ -65,6 +100,17 @@ const UserInfo = () => { )} + + {editFlag ? ( + + + + ) : ( + + <>暂无 + + )} + {editFlag ? ( { {editFlag ? ( <> - diff --git a/vite.config.ts b/vite.config.ts index 4d474fd..1501217 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,10 +1,10 @@ -import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' +import { defineConfig, loadEnv } from 'vite' const path = require('path') // https://vitejs.dev/config/ export default ({ mode }) => { - const env = loadEnv(mode, process.cwd()); + const env = loadEnv(mode, process.cwd()) return defineConfig({ resolve: { alias: { @@ -14,17 +14,21 @@ export default ({ mode }) => { '@utils': path.resolve(__dirname, 'src/utils'), '@components': path.resolve(__dirname, 'src/components'), '@imgs': path.resolve(__dirname, 'src/imgs'), - '@constants': path.resolve(__dirname, 'src/constants'), + '@constants': path.resolve(__dirname, 'src/constants') } }, plugins: [react()], server: { proxy: { - "/subject": { + '/subject': { target: env.VITE_API_HOST, - changeOrigin: true, + changeOrigin: true }, - }, + '/auth': { + target: env.VITE_API_HOST, + changeOrigin: true + } + } } }) }