feat: 修改

This commit is contained in:
秋水浮尘
2024-03-03 00:02:50 +08:00
parent 76a300cab0
commit cca31e8de2
16 changed files with 943 additions and 1145 deletions

View File

@@ -38,7 +38,9 @@ const App = () => {
} }
useEffect(() => { useEffect(() => {
getUserInfo() if (location.pathname !== '/login' && loginId) {
getUserInfo()
}
}, []) }, [])
useEffect(() => { useEffect(() => {

View File

@@ -23,8 +23,9 @@ const LabelList = props => {
}) })
.then(res => { .then(res => {
if (res.data && res.data.length > 0) { if (res.data && res.data.length > 0) {
const ids = `${res.data[0].id}_${res.data[0].labelDTOList[0].id}` const filterData = [...res.data].filter(item => item?.labelDTOList?.length > 0)
setCategoryAndLabelList(res.data) const ids = `${filterData[0].id}_${filterData[0].labelDTOList[0].id}`
setCategoryAndLabelList(filterData)
setCheckedLabelId(ids) setCheckedLabelId(ids)
changeLabel(ids) changeLabel(ids)
} else { } else {
@@ -32,10 +33,8 @@ const LabelList = props => {
setCheckedLabelId('') setCheckedLabelId('')
changeLabel('') changeLabel('')
} }
// setSpinning(false)
}) })
.catch(err => { .catch(err => {
// setSpinning(false)
console.log(err) console.log(err)
}) })
} }

View File

@@ -1,177 +1,58 @@
import { HeartTwoTone, InfoCircleTwoTone, LikeTwoTone } from '@ant-design/icons' import { LikeTwoTone } from '@ant-design/icons'
import req from '@utils/request' import req from '@utils/request'
import { Input, Modal, Radio, message } from 'antd'
import React, { Component } from 'react' import React, { Component } from 'react'
import './index.less' import './index.less'
const { TextArea } = Input
export default class GoodCollectionError extends Component { export default class GoodCollectionError extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
isGood: false, //是否点赞 isGood: false, //是否点赞
isCollection: false, //是否收藏
goodAmount: 0, //点赞数量 goodAmount: 0, //点赞数量
collectionAmount: 0, //收藏数量
// index: 1,
question: [], //题目列表 question: [], //题目列表
isModal: false, //是否显示纠错弹框
value: 1, //纠错类型对应值
inputValue: '', //纠错详情内容
questionId: '' //题目id questionId: '' //题目id
} }
} }
/**纠错类型 */
errorType = [
{
value: 1,
content: '答案错误'
},
{
value: 2,
content: '题目与答案不符'
}
]
componentDidMount() { componentDidMount() {
// this.getDetail() const {
detail: { id, liked, likedCount }
} = this.props
this.setState({
isGood: liked,
goodAmount: likedCount,
questionId: id
})
} }
getDetail() {
let params = {
subjectId: this.props.questionId
}
req({
method: 'post',
data: params,
url: 'admin/question/collect/getDetail'
})
.then(res => {
if (res.data) {
this.setState({
isGood: res.data.isThump,
goodAmount: res.data.thumpCount,
isCollection: res.data.isCollect,
collectionAmount: res.data.collectCount
})
}
})
.catch(err => console.log(err))
}
/**
* 点击纠错按钮
*/
handleModal = () => {
return message.info('敬请期待')
this.setState({
isModal: true
})
}
/**
* 点击弹框确认按钮
*/
handleOk = () => {
const { value, inputValue } = this.state
const { questionId } = this.props
let params = {
subjectId: questionId,
errorType: value,
errorMsg: inputValue
}
if (inputValue.length === 0) {
message.warning('请填写纠错详情!')
} else {
this.setState({
isModal: false,
inputValue: ''
})
message.success('感谢纠错,立即更改!')
req({
method: 'post',
data: params,
url: '/admin/question/subjectError/add'
})
}
}
/**
* 点击弹框取消按钮
*/
handleCancel = () => {
this.setState({
isModal: false,
inputValue: ''
})
}
/**
*
* @param {选择纠错类型} e
*/
handleChangeRadio = e => {
this.setState({
value: e.target.value
})
}
/**
*
* @param {纠错详情中填写内容} e
*/
handleChangeInput = e => {
this.setState({
inputValue: e.target.value
})
}
/** /**
* *
* @returns 点击点赞按钮 * @returns 点击点赞按钮
*/ */
handleChangeGood = () => { handleChangeGood = () => {
return message.info('敬请期待') const { isGood, goodAmount, questionId } = this.state
const { isGood, goodAmount } = this.state
const { questionId } = this.props
let params = { let params = {
subjectId: questionId subjectId: questionId,
status: isGood ? 0 : 1
} }
this.setState( this.setState(
{ {
isGood: isGood === true ? false : true, isGood: !isGood,
goodAmount: isGood === true ? goodAmount - 1 : goodAmount + 1 goodAmount: isGood ? goodAmount - 1 : goodAmount + 1
}, },
() => { () => {
req({ req(
method: 'post', {
data: params, method: 'post',
url: 'admin/question/thump/addOrCancel' data: params,
}).catch(err => console.log(err)) url: '/subjectLiked/add'
} },
) '/subject'
} ).catch(err => console.log(err))
/**
* 点击收藏按钮
*/
handleChangeCollection = () => {
return message.info('敬请期待')
const { isCollection, collectionAmount } = this.state
const { questionId } = this.props
let params = {
subjectId: questionId
}
this.setState(
{
isCollection: isCollection === true ? false : true,
collectionAmount: isCollection === true ? collectionAmount - 1 : collectionAmount + 1
},
() => {
req({
method: 'post',
data: params,
url: 'admin/question/collect/addOrCancel'
}).catch(err => console.log(err))
} }
) )
} }
render() { render() {
const { isCollection, isGood, isModal, value, collectionAmount, goodAmount } = this.state const { isGood, goodAmount } = this.state
return ( return (
<div className='left'> <div className='left'>
<div <div
@@ -181,87 +62,9 @@ export default class GoodCollectionError extends Component {
this.handleChangeGood() this.handleChangeGood()
}} }}
> >
<LikeTwoTone <LikeTwoTone twoToneColor={!isGood ? 'grey' : 'blue'} style={{ marginRight: 4 }} />(
twoToneColor={isGood == false ? 'grey' : 'blue'} {goodAmount})
style={{ marginRight: 4 }}
/>
({goodAmount})
</div> </div>
<div
className='collection'
onClick={() => {
this.handleChangeCollection()
}}
>
<HeartTwoTone
twoToneColor={isCollection == false ? 'grey' : 'blue'}
style={{ marginRight: 4 }}
/>
({collectionAmount})
</div>
{/* <div className="comment">
<MessageTwoTone twoToneColor="blue" style={{ marginRight: 4 }} />
评论
</div> */}
<div
className='error-collection'
onClick={() => {
this.handleModal()
}}
>
<InfoCircleTwoTone twoToneColor='red' style={{ marginRight: 4 }} />
纠错
</div>
<Modal
className='error-modal'
title='题目纠错'
open={isModal}
destroyOnClose={true}
onOk={() => {
this.handleOk()
}}
onCancel={() => {
this.handleCancel()
}}
okText='确认'
cancelText='取消'
style={{ fontWeight: 500 }}
>
<div>
<div className='error-collection-title'>纠错类型</div>
<div className='error-collection-type'>
{this.errorType.map((item, index) => {
return (
<div key={index} className='error-collection-type-detail'>
<Radio.Group
onChange={e => {
this.handleChangeRadio(e)
}}
defaultValue={1}
buttonStyle='solid'
value={value}
>
<Radio.Button value={item.value} className='ll'>
{item.content}
</Radio.Button>
</Radio.Group>
</div>
)
})}
</div>
<div className='error-collection-title'>纠错详情</div>
<TextArea
className='error-input'
placeholder='请输入...'
maxLength={256}
rows={4}
showCount={true}
onChange={e => {
this.handleChangeInput(e)
}}
/>
</div>
</Modal>
</div> </div>
) )
} }

View File

@@ -14,7 +14,8 @@ export default function request(config, url) {
withCredentials: true, // send cookies when cross-domain requests withCredentials: true, // send cookies when cross-domain requests
headers: { headers: {
'Content-Type': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8',
[userInfo.tokenName]: 'jichi ' + userInfo.tokenValue [userInfo.tokenName]: 'jichi ' + userInfo.tokenValue,
loginId: userInfo.loginId || ''
} }
}) })

View File

@@ -1,20 +1,19 @@
import { Pagination, Button, Modal, Input, Radio, message } from 'antd'
import React, { Component, Fragment, useState, useEffect } from 'react'
import { useParams } from 'react-router-dom'
import GoodCollectionError from '@components/good-collection-error' import GoodCollectionError from '@components/good-collection-error'
import './index.less'
import req from '@utils/request' import req from '@utils/request'
import { Pagination } from 'antd'
import { Component, Fragment, useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import './index.less'
const grade: Record<string, string> = { const grade: Record<string, string> = {
1: '初级', 1: '初级',
2: '中级', 2: '中级',
3: '高级', 3: '高级',
4: '资深', 4: '资深',
5: '专家', 5: '专家'
} }
const BrushQuestions = () => { const BrushQuestions = () => {
const { id } = useParams() const { id } = useParams()
const [question, setQuestion] = useState<Record<string, any>>(null) const [question, setQuestion] = useState<Record<string, any>>(null)
const [index, setIndex] = useState(1) const [index, setIndex] = useState(1)
@@ -26,51 +25,49 @@ const BrushQuestions = () => {
data: { data: {
id id
}, },
url: '/querySubjectInfo', url: '/querySubjectInfo'
}) })
.then((res) => { .then(res => {
if (res.success && res.data) { if (res.success && res.data) {
setQuestion(res.data) setQuestion(res.data)
} }
}) })
.catch((err) => console.log(err)) .catch(err => console.log(err))
}, [id]) }, [id])
return ( return (
<div className="brush-questions-box"> <div className='brush-questions-box'>
<div className="question-box"> <div className='question-box'>
<div className="question"> <div className='question'>
<div className="question-type"> <div className='question-type'>
<div className="number">{index}</div> <div className='number'>{index}</div>
<div className="type"></div> <div className='type'></div>
</div> </div>
</div> </div>
</div> </div>
{ {question ? (
question ? <Fragment> <Fragment>
<div className="question-content"> <div className='question-content'>
<div className="difficulty"> <div className='difficulty'>
{grade[question.subjectDifficult]}-{question?.labelName.join('、')} {grade[question.subjectDifficult]}-{question?.labelName.join('、')}
</div> </div>
<div>{question.subjectName}</div> <div>{question.subjectName}</div>
</div> </div>
<div className="answer-box"> <div className='answer-box'>
<div className="reference-answer"></div> <div className='reference-answer'></div>
<div <div
className="answer-content wang-editor-style" className='answer-content wang-editor-style'
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: question.subjectAnswer, __html: question.subjectAnswer
}} }}
></div> ></div>
<br /> <br />
</div> </div>
<div className="change-question-box"> <div className='change-question-box'>
<GoodCollectionError <GoodCollectionError detail={question} />
questionId={question.id}
/>
</div> </div>
</Fragment> : null </Fragment>
} ) : null}
</div> </div>
) )
} }
@@ -84,16 +81,22 @@ class BrushQuestions1 extends Component {
isGood: 0, isGood: 0,
isCollection: 0, isCollection: 0,
index: 1, index: 1,
question: [{ question: [
id: 1, labelNames: ["原理"], subjectName: 'JDK 和 JRE 有什么区别?', difficulty: 1, {
subjectAnswer: `<p>JDKJava Development Kit 的简称Java 开发工具包,提供了 Java 的开发环境和运行环境。</p> id: 1,
labelNames: ['原理'],
subjectName: 'JDK 和 JRE 有什么区别?',
difficulty: 1,
subjectAnswer: `<p>JDKJava Development Kit 的简称Java 开发工具包,提供了 Java 的开发环境和运行环境。</p>
<p>JREJava Runtime Environment 的简称Java 运行环境,为 Java 的运行提供了所需环境。</p> <p>JREJava Runtime Environment 的简称Java 运行环境,为 Java 的运行提供了所需环境。</p>
<p>具体来说 JDK 其实包含了 JRE同时还包含了编译 Java 源码的编译器 Javac还包含了很多 Java 程序调试和分析的工具。</p> <p>具体来说 JDK 其实包含了 JRE同时还包含了编译 Java 源码的编译器 Javac还包含了很多 Java 程序调试和分析的工具。</p>
<p>简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。</p>` }], <p>简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。</p>`
}
],
// answer: '', // answer: '',
isModal: false, //是否显示纠错弹框 isModal: false, //是否显示纠错弹框
value: 1, //纠错类型对应值 value: 1, //纠错类型对应值
inputValue: '', //纠错详情内容 inputValue: '' //纠错详情内容
} }
} }
pageIndex = 1 pageIndex = 1
@@ -106,7 +109,7 @@ class BrushQuestions1 extends Component {
2: '中级', 2: '中级',
3: '高级', 3: '高级',
4: '资深', 4: '资深',
5: '专家', 5: '专家'
} }
goodCollectionError = GoodCollectionError | null goodCollectionError = GoodCollectionError | null
componentDidMount() { componentDidMount() {
@@ -127,23 +130,23 @@ class BrushQuestions1 extends Component {
let params = { let params = {
pageInfo: { pageInfo: {
pageIndex: this.pageIndex, pageIndex: this.pageIndex,
pageSize: 1, pageSize: 1
}, },
difficulty: this.difficulty, difficulty: this.difficulty,
primaryCategoryId: this.primaryCategoryId, primaryCategoryId: this.primaryCategoryId,
assembleIds: this.assembleIds, assembleIds: this.assembleIds
} }
return await req({ return await req({
method: 'post', method: 'post',
data: params, data: params,
url: '/querySubjectInfo', url: '/querySubjectInfo'
}) })
.then((res) => { .then(res => {
if (res.data && res.data?.pageList?.length > 0) { if (res.data && res.data?.pageList?.length > 0) {
this.total = res.data.pageInfo.total this.total = res.data.pageInfo.total
this.setState( this.setState(
{ {
question: res.data.pageList, question: res.data.pageList
}, },
() => { () => {
this.goodCollectionError.getDetail() this.goodCollectionError.getDetail()
@@ -151,21 +154,21 @@ class BrushQuestions1 extends Component {
) )
} }
}) })
.catch((err) => console.log(err)) .catch(err => console.log(err))
} }
onChangePagination = async (pageIndex) => { onChangePagination = async pageIndex => {
this.pageIndex = pageIndex this.pageIndex = pageIndex
this.setState({ index: pageIndex }) this.setState({ index: pageIndex })
// await this.getInterviewSubjectList() // await this.getInterviewSubjectList()
} }
handleNextQuestion = async (value) => { handleNextQuestion = async value => {
let { index } = this.state let { index } = this.state
this.pageIndex += value this.pageIndex += value
index += value index += value
this.setState({ this.setState({
index: index, index: index
}) })
// await this.getInterviewSubjectList() // await this.getInterviewSubjectList()
} }
@@ -173,12 +176,12 @@ class BrushQuestions1 extends Component {
render() { render() {
const { index, question } = this.state const { index, question } = this.state
return ( return (
<div className="brush-questions-box"> <div className='brush-questions-box'>
<div className="question-box"> <div className='question-box'>
<div className="question"> <div className='question'>
<div className="question-type"> <div className='question-type'>
<div className="number">{index}</div> <div className='number'>{index}</div>
<div className="type"></div> <div className='type'></div>
</div> </div>
{/* <div className="question-number"> {/* <div className="question-number">
<div className="now-number">{index}</div> <div className="now-number">{index}</div>
@@ -190,27 +193,27 @@ class BrushQuestions1 extends Component {
{question.map((item, index) => { {question.map((item, index) => {
return ( return (
<div key={index}> <div key={index}>
<div className="question-content"> <div className='question-content'>
<div className="difficulty"> <div className='difficulty'>
{this.grade[item.difficulty]}-{item.labelNames.join('、')} {this.grade[item.difficulty]}-{item.labelNames.join('、')}
</div> </div>
<div>{item.subjectName}</div> <div>{item.subjectName}</div>
</div> </div>
<div className="answer-box"> <div className='answer-box'>
<div className="reference-answer"></div> <div className='reference-answer'></div>
<div <div
className="answer-content wang-editor-style" className='answer-content wang-editor-style'
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
// __html: item.subjectAnswer, // __html: item.subjectAnswer,
__html: item.subjectAnswer, __html: item.subjectAnswer
}} }}
></div> ></div>
<br /> <br />
</div> </div>
<div className="change-question-box"> <div className='change-question-box'>
<GoodCollectionError <GoodCollectionError
questionId={question[0].id} questionId={question[0].id}
ref={(ref) => { ref={ref => {
this.goodCollectionError = ref this.goodCollectionError = ref
}} }}
/> />
@@ -241,12 +244,12 @@ class BrushQuestions1 extends Component {
})} })}
</Fragment> </Fragment>
<div className="jump-question"> <div className='jump-question'>
{this.total > 0 && ( {this.total > 0 && (
<Pagination <Pagination
style={{ style={{
padding: '24px 0', padding: '24px 0',
textAlign: 'center', textAlign: 'center'
}} }}
showQuickJumper showQuickJumper
current={this.pageIndex} current={this.pageIndex}

View File

@@ -1,5 +1,5 @@
import Logo from '@/imgs/logo.jpg' import Logo from '@/imgs/logo.jpg'
import { HeartOutlined, LikeOutlined, LoginOutlined, UserOutlined } from '@ant-design/icons' import { LikeOutlined, LoginOutlined, UserOutlined } from '@ant-design/icons'
import TopMenu from '@components/top-menu' import TopMenu from '@components/top-menu'
import LoginQrcode from '@imgs/personal_qr_code.jpg' import LoginQrcode from '@imgs/personal_qr_code.jpg'
import req from '@utils/request' import req from '@utils/request'
@@ -18,12 +18,12 @@ const menuItems = [
icon: <UserOutlined style={{ fontSize: '16px' }} />, icon: <UserOutlined style={{ fontSize: '16px' }} />,
path: '/user-info' path: '/user-info'
}, },
{ // {
label: '我的收藏', // label: '我的收藏',
key: 2, // key: 2,
icon: <HeartOutlined style={{ fontSize: '16px' }} />, // icon: <HeartOutlined style={{ fontSize: '16px' }} />,
path: '/personal-center/0' // path: '/personal-center/0'
}, // },
{ {
label: '我的点赞', label: '我的点赞',
key: 3, key: 3,

View File

@@ -66,7 +66,7 @@ const Login = () => {
<div className='qrcode-box'> <div className='qrcode-box'>
<div className='qrcode-desc'> <div className='qrcode-desc'>
<p></p> <p></p>
<p></p> <p> </p>
</div> </div>
<div className='qrcode-img'> <div className='qrcode-img'>
<img src={LoginQrcode} alt='' /> <img src={LoginQrcode} alt='' />

View File

@@ -1,3 +1,4 @@
import req from '@utils/request'
import { Card, Pagination, Spin } from 'antd' import { Card, Pagination, Spin } from 'antd'
import React, { Component } from 'react' import React, { Component } from 'react'
import { goodTabType } from '../../constant' import { goodTabType } from '../../constant'
@@ -53,23 +54,47 @@ export default class GoodBag extends Component {
* 获取一级分类数据 * 获取一级分类数据
*/ */
getGoodList() { getGoodList() {
this.total = 3 req(
this.setState({ {
goodList: [ method: 'post',
{ url: '/subjectLiked/getSubjectLikedPage',
id: 100, data: {
subjectName: 'Redis支持哪几种数据类型' pageNo: 1,
}, pageSize: 10
{
id: 101,
subjectName: 'Redis的高级数据类型有什么'
},
{
id: 102,
subjectName: 'Redis的优点有什么'
} }
] },
'/subject'
).then(res => {
if (res.success && res.code === 200) {
this.total = res.data?.total || 0
this.setState({
goodList: res.data.result
})
} else {
this.total = 0
this.setState({
goodList: []
})
}
}) })
// this.total = 3
// this.setState({
// goodList: [
// {
// id: 100,
// subjectName: 'Redis支持哪几种数据类型'
// },
// {
// id: 101,
// subjectName: 'Redis的高级数据类型有什么'
// },
// {
// id: 102,
// subjectName: 'Redis的优点有什么'
// }
// ]
// })
} }
/** /**

View File

@@ -24,12 +24,12 @@ const CollectionQuestion = props => {
return ( return (
<div <div
className='collection-bag-component-tab1-body-item' className='collection-bag-component-tab1-body-item'
key={`collection_question_${item.id}`} key={`collection_question_${item.subjectId}`}
> >
<div className='collection-bag-component-tab1-body-item-question'> <div className='collection-bag-component-tab1-body-item-question'>
<span <span
className='collection-bag-component-tab1-body-item-question-content' className='collection-bag-component-tab1-body-item-question-content'
onClick={() => handleJump(item.id)} onClick={() => handleJump(item.subjectId)}
> >
{item.subjectName} {item.subjectName}
</span> </span>

View File

@@ -1,9 +1,4 @@
import { LikeTwoTone, StarTwoTone } from '@ant-design/icons' import React from 'react'
import { Menu } from 'antd'
import React, { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
import { useParams } from 'react-router-dom'
import CollectionBag from './components/collection-bag'
import GoodBag from './components/good-bag' import GoodBag from './components/good-bag'
import './index.less' import './index.less'
@@ -12,86 +7,89 @@ const personList = {
1: '点赞' 1: '点赞'
} }
// const PersonalCenter = props => {
// const [currentKeyMap, setCurrentKeyMap] = useState(0)
// const { userInfo } = useSelector(store => store.userInfo)
// const [selectedKeys, setSelectedKeys] = useState('0')
// const { tab } = useParams()
// useEffect(() => {
// setCurrentKeyMap(+tab)
// setSelectedKeys(tab)
// }, [tab])
// const handleClick = ({ key }) => {
// setCurrentKeyMap(Number(key))
// setSelectedKeys(key)
// }
// return (
// <div className='personal-center-box'>
// <div className='personal-center-introduction'>
// <div className='personal-center-introduction-detail'>
// <div className='personal-center-introduction-detail-headImg'>
// <img src={userInfo.avatar} style={{ width: 60, height: 60, borderRadius: '50%' }} />
// </div>
// <div className='personal-center-introduction-detail-text'>
// <div className='personal-center-introduction-detail-name'>{userInfo.nickName}</div>
// {/* <div className='personal-center-introduction-detail-information'>
// <span className='personal-center-introduction-detail-information-content'>
// <IdcardOutlined style={{ color: 'blue', marginRight: '3px' }} />
// </span>
// <span className='personal-center-introduction-detail-information-content'>
// <MailOutlined style={{ color: 'blue', marginRight: '3px' }} />
// </span>
// </div> */}
// </div>
// </div>
// <div className='personal-center-introduction-result'>
// {/* <div className='personal-center-introduction-result-item'>
// <div className='personal-center-introduction-result-item-number'>{10}</div>
// <div>练题</div>
// </div> */}
// {/* <div className='personal-center-introduction-result-item'>
// <div className='personal-center-introduction-result-item-number'>{inputAmount}</div>
// <div>录题</div>
// </div> */}
// <div className='personal-center-introduction-result-item'>
// <div className='personal-center-introduction-result-item-number'>{20}</div>
// <div>点赞</div>
// </div>
// <div className='personal-center-introduction-result-item'>
// <div className='personal-center-introduction-result-item-number'>{30}</div>
// <div>收藏</div>
// </div>
// </div>
// </div>
// <div className='personal-center-content'>
// <div className='personal-center-content-left'>
// <Menu
// mode='inline'
// onClick={handleClick}
// style={{ width: 256 }}
// selectedKeys={[selectedKeys]}
// >
// <Menu.Item key={0}>
// <StarTwoTone twoToneColor='rgb(252,132,67)' />
// <span>{personList[0]}</span>
// </Menu.Item>
// <Menu.Item key={1}>
// <LikeTwoTone twoToneColor='#99bbff' />
// <span>{personList[1]}</span>
// </Menu.Item>
// </Menu>
// </div>
// <div className='personal-center-content-right'>
// {currentKeyMap === 0 && <CollectionBag />}
// {currentKeyMap === 1 && <GoodBag />}
// </div>
// </div>
// </div>
// )
// }
const PersonalCenter = props => { const PersonalCenter = props => {
const [currentKeyMap, setCurrentKeyMap] = useState(0) return <GoodBag />
const { userInfo } = useSelector(store => store.userInfo)
const [selectedKeys, setSelectedKeys] = useState('0')
const { tab } = useParams()
useEffect(() => {
setCurrentKeyMap(+tab)
setSelectedKeys(tab)
}, [tab])
const handleClick = ({ key }) => {
setCurrentKeyMap(Number(key))
setSelectedKeys(key)
}
return (
<div className='personal-center-box'>
<div className='personal-center-introduction'>
<div className='personal-center-introduction-detail'>
<div className='personal-center-introduction-detail-headImg'>
<img src={userInfo.avatar} style={{ width: 60, height: 60, borderRadius: '50%' }} />
</div>
<div className='personal-center-introduction-detail-text'>
<div className='personal-center-introduction-detail-name'>{userInfo.nickName}</div>
{/* <div className='personal-center-introduction-detail-information'>
<span className='personal-center-introduction-detail-information-content'>
<IdcardOutlined style={{ color: 'blue', marginRight: '3px' }} />
</span>
<span className='personal-center-introduction-detail-information-content'>
<MailOutlined style={{ color: 'blue', marginRight: '3px' }} />
</span>
</div> */}
</div>
</div>
<div className='personal-center-introduction-result'>
{/* <div className='personal-center-introduction-result-item'>
<div className='personal-center-introduction-result-item-number'>{10}</div>
<div>练题</div>
</div> */}
{/* <div className='personal-center-introduction-result-item'>
<div className='personal-center-introduction-result-item-number'>{inputAmount}</div>
<div>录题</div>
</div> */}
<div className='personal-center-introduction-result-item'>
<div className='personal-center-introduction-result-item-number'>{20}</div>
<div>点赞</div>
</div>
<div className='personal-center-introduction-result-item'>
<div className='personal-center-introduction-result-item-number'>{30}</div>
<div>收藏</div>
</div>
</div>
</div>
<div className='personal-center-content'>
<div className='personal-center-content-left'>
<Menu
mode='inline'
onClick={handleClick}
style={{ width: 256 }}
selectedKeys={[selectedKeys]}
>
<Menu.Item key={0}>
<StarTwoTone twoToneColor='rgb(252,132,67)' />
<span>{personList[0]}</span>
</Menu.Item>
<Menu.Item key={1}>
<LikeTwoTone twoToneColor='#99bbff' />
<span>{personList[1]}</span>
</Menu.Item>
</Menu>
</div>
<div className='personal-center-content-right'>
{currentKeyMap === 0 && <CollectionBag />}
{currentKeyMap === 1 && <GoodBag />}
</div>
</div>
</div>
)
} }
export default PersonalCenter export default PersonalCenter

View File

@@ -1,84 +1,83 @@
import React, { Fragment, Component } from 'react'; import req from '@utils/request'
import req from '@utils/request'; import React, { Component, Fragment } from 'react'
import RankingBox from '../ranking-box'; import { RankingType, apiName } from '../../constant'
import { apiName, RankingType } from '../../constant'; import { mockRankingModuleList } from '../../mock'
import { mockRankingModuleList } from '../../mock'; import RankingBox from '../ranking-box'
class PracticeList extends Component { class PracticeList extends Component {
constructor(props) { constructor(props) {
super(props); super(props)
this.state = { this.state = {
contributionList: mockRankingModuleList[0].rankingList, contributionList: mockRankingModuleList[0].rankingList,
contributeType: 0, contributeType: 0,
isLoading: false, isLoading: false
};
} }
}
componentDidMount() { componentDidMount() {
// this.getPracticeRankList(); this.getPracticeRankList()
} }
/** /**
* 获得练习榜 * 获得练习榜
*/ */
getPracticeRankList() { getPracticeRankList() {
req({ req({
method: 'post', method: 'post',
data: {}, url: apiName.getPracticeRankList
url: apiName.getPracticeRankList, })
}) .then(res => {
.then((res) => { if (res.data && res.data.length > 0) {
if (res.data && res.data.length > 0) { this.setState({
this.setState({ contributionList: res.data,
contributionList: res.data, isLoading: false
isLoading: false, })
}); } else {
} else { this.setState({
this.setState({ contributionList: [],
contributionList: [], isLoading: false
isLoading: false, })
}); }
} })
}) .catch(err => console.log(err))
.catch((err) => console.log(err)); }
}
/** /**
* 切换排行榜 * 切换排行榜
* @param {*} index * @param {*} index
* @returns * @returns
*/ */
onChangeRanking = (index) => { onChangeRanking = index => {
console.log(index, 'practice index') console.log(index, 'practice index')
this.setState({ this.setState({
contributeType: index, contributeType: index
}); })
}; }
/** /**
* 去练题 * 去练题
*/ */
onChangeJump = () => { onChangeJump = () => {
this.props.history.push('/practice-questions'); this.props.history.push('/practice-questions')
}; }
render() { render() {
const { contributionList, isLoading, contributeType } = this.state; const { contributionList, isLoading, contributeType } = this.state
return ( return (
<Fragment> <Fragment>
{contributionList?.length > 0 && ( {contributionList?.length > 0 && (
<RankingBox <RankingBox
isLoading={isLoading} isLoading={isLoading}
contributionList={contributionList} contributionList={contributionList}
currentActive={contributeType} currentActive={contributeType}
rankingType={RankingType.practice} rankingType={RankingType.practice}
onHandleRanking={this.onChangeRanking} onHandleRanking={this.onChangeRanking}
onHandleJump={this.onChangeJump} onHandleJump={this.onChangeJump}
/> />
)} )}
</Fragment> </Fragment>
); )
} }
} }
export default PracticeList; export default PracticeList

View File

@@ -29,16 +29,24 @@ export default function RankingBox(props) {
} }
// props.onHandleJump && props.onHandleJump() // props.onHandleJump && props.onHandleJump()
}) })
const tabList = [ const tabList =
{ rankingType === 1
tab: '本月排行', ? [
key: 'month' {
}, tab: '本月排行',
{ key: 'month'
tab: '总榜', },
key: 'total' {
} tab: '总榜',
] key: 'total'
}
]
: [
{
tab: '总榜',
key: 'total'
}
]
// 获得当前下标的数据 // 获得当前下标的数据
let rankingList = contributionList || [] let rankingList = contributionList || []
@@ -79,24 +87,24 @@ export default function RankingBox(props) {
{index > 2 && index + 1} {index > 2 && index + 1}
</div> </div>
<div className='ranking-head-img'> <div className='ranking-head-img'>
<img src={item.headImg} className='ranking-head-icon' /> <img src={item.createUserAvatar} className='ranking-head-icon' />
</div> </div>
<Popover <Popover
title={<div>{item.name}</div>} title={<div>{item.createUser}</div>}
content={ content={
<div className='tooltip-info'> <div className='tooltip-info'>
<div>{item.name}</div> <div>{item.createUser}</div>
{/* <div>{item.organizationFullName}</div> */} {/* <div>{item.organizationFullName}</div> */}
</div> </div>
} }
> >
<div className='ranking-info'> <div className='ranking-info'>
<div className='ranking-name'>{item.name}</div> <div className='ranking-name'>{item.createUser}</div>
{/* <div className="ranking-department">{item.organizationName}</div> */} {/* <div className="ranking-department">{item.organizationName}</div> */}
</div> </div>
</Popover> </Popover>
</div> </div>
<div className='ranking-right'>🔥 {item.count}</div> <div className='ranking-right'>🔥 {item.subjectCount}</div>
</div> </div>
) )
})} })}

View File

@@ -1,46 +1,49 @@
export const apiName = { export const apiName = {
/** /**
* 查询分类 * 查询分类
*/ */
queryPrimaryCategory: '/category/queryPrimaryCategory', queryPrimaryCategory: '/category/queryPrimaryCategory',
/** /**
* 查询大类下分类 * 查询大类下分类
*/ */
queryCategoryByPrimary: '/category/queryCategoryByPrimary', queryCategoryByPrimary: '/category/queryCategoryByPrimary',
// 获取题目列表 // 获取题目列表
getSubjectPage: '/getSubjectPage' getSubjectPage: '/getSubjectPage',
}; /**
* 练题排行榜
*/
getPracticeRankList: '/getContributeList'
}
/** /**
* 模块类型 * 模块类型
*/ */
export const RankingType = { export const RankingType = {
/** /**
* 贡献榜 * 贡献榜
*/ */
contribution: 1, contribution: 1,
/** /**
* 排行榜 * 排行榜
*/ */
practice: 2, practice: 2
}; }
/** /**
* 模块名称 * 模块名称
*/ */
export const RankingTypeText = { export const RankingTypeText = {
[RankingType.contribution]: '贡献榜', [RankingType.contribution]: '出题贡献榜',
[RankingType.practice]: '综合练习榜', [RankingType.practice]: '综合练习榜'
}; }
/** /**
* 对应按钮名字 * 对应按钮名字
*/ */
export const RankingTypeBtnText = { export const RankingTypeBtnText = {
[RankingType.contribution]: '去出题', [RankingType.contribution]: '去出题',
[RankingType.practice]: '去练习', [RankingType.practice]: '去练习'
}; }

View File

@@ -132,8 +132,8 @@ const QuestionBank = () => {
</div> </div>
</div> </div>
<div className='ranking-box'> <div className='ranking-box'>
<RankingList />
<ContributionList /> <ContributionList />
<RankingList />
</div> </div>
</div> </div>
) )

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +1,57 @@
import { ExclamationCircleOutlined } from '@ant-design/icons' import { ExclamationCircleOutlined } from '@ant-design/icons'
import { queryParse } from '@utils' import { queryParse } from '@utils'
import req from '@utils/request'
import { Card, Input, Pagination, Skeleton, message } from 'antd' import { Card, Input, Pagination, Skeleton, message } from 'antd'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import './index.less' import './index.less'
const { Search } = Input const { Search } = Input
const mockList = [
{
id: 100,
subjectName: 'Redis支持哪几种数据类型',
subjectDifficult: 1,
subjectType: 4,
subjectScore: 1,
subjectParse: '解析什么',
subjectAnswer:
'<p><br></p><ol><li>String字符串</li><li>List列表</li><li>Hash字典</li><li>Set集合</li><li>Sorted Set有序集合</li></ol><p><br></p><p><strong>String</strong></p><p><br></p><p>String是简单的 key-value 键值对value 不仅可以是 String也可以是数字。String在redis内部存储默认就是一个字符串被redisObject所引用当遇到incr,decr等操作时会转成数值型进行计算此时redisObject的encoding字段为int。</p><p><br></p><p><strong>List</strong></p><p><br></p><p>Redis列表是简单的字符串列表可以类比到C++中的std::list简单的说就是一个链表或者说是一个队列。可以从头部或尾部向Redis列表添加元素。列表的最大长度为2^32 - 1也即每个列表支持超过40亿个元素。</p><p><br></p><p>Redis list的实现为一个双向链表即可以支持反向查找和遍历更方便操作不过带来了部分额外的内存开销Redis内部的很多实现包括发送缓冲队列等也都是用的这个数据结构。</p><p><br></p><p><strong>Hash</strong></p><p><br></p><p>Redis Hash对应Value内部实际就是一个HashMap实际这里会有2种不同实现这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储而不会采用真正的HashMap结构对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap。</p><p><br></p><p><strong>Set</strong></p><p><br></p><p>set 的内部实现是一个 value永远为null的HashMap实际就是通过计算hash的方式来快速排重的这也是set能提供判断一个成员是否在集合内的原因。</p><p><br></p><p><strong>Sorted Set</strong></p><p><br></p><p>Redis有序集合类似Redis集合不同的是增加了一个功能即集合是有序的。一个有序集合的每个成员带有分数用于进行排序。</p><p><br></p><p>Redis有序集合添加、删除和测试的时间复杂度均为O(1)(固定时间,无论里面包含的元素集合的数量)。列表的最大长度为2^32- 1元素(4294967295超过40亿每个元素的集合)。</p><p><br></p><p>Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序HashMap里放的是成员到score的映射而跳跃表里存放的是所有的成员排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。</p>',
labelName: ['Redis']
},
{
id: 101,
subjectName: 'Redis的高级数据类型有什么',
subjectDifficult: 2,
subjectType: 4,
subjectScore: 1,
subjectParse: '解析什么',
subjectAnswer:
'<p><br></p><p>bitmapbitmap是一种位数据类型常常用于统计大家比较知名的就是布隆过滤器。也可以统计一些大数据量的东西比如每天有多少优惠券被使用。</p><p><br></p><p>hyperloglog用于基数统计基数是数据集去重后元素个数运用了LogLog的算法。{1,3,5,7,5,7,8} &nbsp; 基数集:{1,3,5,7,8} &nbsp;基数:5</p><p><br></p><p>geo应用于地理位置计算主要是经纬度的计算常见的就是附近的人可以以当前人的坐标获取周围附近的成员可以计算经纬度计算地理位置</p>',
labelName: ['Redis']
},
{
id: 102,
subjectName: 'Redis的优点有什么',
subjectDifficult: 1,
subjectType: 4,
subjectScore: 1,
subjectParse: '解析什么',
subjectAnswer:
'<p><br></p><p>(1) 速度快因为数据存在内存中类似于HashMapHashMap的优势就是查找和操作的时间复杂度都是O(1)</p><p><br></p><p>(2) 支持丰富数据类型支持stringlistsetZsethash等</p><p><br></p><p>(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行</p><p><br></p><p>(4) 丰富的特性可用于缓存消息按key设置过期时间过期后将会自动删除</p>',
labelName: ['Redis']
},
{
id: 103,
subjectName: 'Redis相比Memcached有哪些优势',
subjectDifficult: 1,
subjectType: 4,
subjectScore: 1,
subjectParse: '解析什么',
subjectAnswer:
'<p><br></p><p>(1) Memcached所有的值均是简单的字符串redis作为其替代者支持更为丰富的数据类型</p><p><br></p><p>(2) Redis的速度比Memcached快很多</p><p><br></p><p>(3) Redis可以持久化其数据</p>',
labelName: ['Redis']
},
{
id: 106,
subjectName: 'redis过期策略都有哪些',
subjectDifficult: 1,
subjectType: 4,
subjectScore: 1,
subjectParse: '解析什么',
subjectAnswer:
'<p><br></p><p>noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错。</p><p><br></p><p>allkeys-lru当内存不足以容纳新写入数据时在键空间中移除最近最少使用的 key。</p><p><br></p><p>allkeys-random当内存不足以容纳新写入数据时在键空间中随机移除某个 key这个一般没人用吧为啥要随机肯定是把最近最少使用的 key 给干掉啊。</p><p><br></p><p>volatile-lru当内存不足以容纳新写入数据时在设置了过期时间的键空间中移除最近最少使用的 key。</p><p><br></p><p>volatile-random当内存不足以容纳新写入数据时在设置了过期时间的键空间中随机移除某个 key。</p><p><br></p><p>volatile-ttl当内存不足以容纳新写入数据时在设置了过期时间的键空间中有更早过期时间的 key 优先移除。</p>',
labelName: ['Redis']
}
]
const defaultValue = queryParse(location.search).t
const SearchDetails = () => { const SearchDetails = () => {
const defaultValue = queryParse(location.search).t
const navigate = useNavigate() const navigate = useNavigate()
const [isShowSkeleton, setIsShowSkeleton] = useState(true) const [isShowSkeleton, setIsShowSkeleton] = useState(true)
const [questionList, setQuestionList] = useState(mockList) const [questionList, setQuestionList] = useState()
const [total, setTotal] = useState(0) const [total, setTotal] = useState(0)
const [pageIndex, setPageIndex] = useState(0) const [pageIndex, setPageIndex] = useState(0)
const [searchValue, setSearchValue] = useState(defaultValue) const [searchValue, setSearchValue] = useState()
useEffect(() => {
setSearchValue(defaultValue)
}, [])
const searchSubject = () => { const searchSubject = () => {
setIsShowSkeleton(false) setIsShowSkeleton(false)
req({
method: 'post',
url: '/getSubjectPageBySearch',
data: {
pageSize: 10,
pageNo: pageIndex,
keyWord: searchValue
}
}).then(res => {
if (res.success && res.data) {
setTotal(res.data.total)
setQuestionList(res.data.result)
}
})
} }
const handleJump = id => { const handleJump = id => {
navigate('/brush-question/' + id) navigate('/brush-question/' + id)
} }
const onChangePagination = () => {} const onChangePagination = curPage => {
setPageIndex(curPage)
}
useEffect(() => { useEffect(() => {
searchSubject() searchSubject()
}, [searchValue]) }, [searchValue, pageIndex])
return ( return (
<div className='search-details-box'> <div className='search-details-box'>
@@ -97,9 +61,8 @@ const SearchDetails = () => {
placeholder='请输入感兴趣的内容' placeholder='请输入感兴趣的内容'
onSearch={value => { onSearch={value => {
if (value) { if (value) {
// this.state.searchText = value setSearchValue(value)
// this.pageIndex = 1 setPageIndex(1)
// this.searchSubject()
} else { } else {
message.info('搜索词不能为空') message.info('搜索词不能为空')
} }
@@ -117,13 +80,7 @@ const SearchDetails = () => {
> >
<div className='search-details-box-content'> <div className='search-details-box-content'>
<div className='search-details-box-content-card'> <div className='search-details-box-content-card'>
<Card <Card style={{ width: '100%' }}>
style={{ width: '100%' }}
// tabList={this.tabList}
// onTabChange={key => {
// this.onTabChange(key, 'key')
// }}
>
<div className='search-details-box-content-main'> <div className='search-details-box-content-main'>
{questionList?.length > 0 ? ( {questionList?.length > 0 ? (
questionList.map((item, index) => { questionList.map((item, index) => {
@@ -133,7 +90,7 @@ const SearchDetails = () => {
<div <div
className='search-details-box-content-main-item-question' className='search-details-box-content-main-item-question'
key={`search-details-question_${index}`} key={`search-details-question_${index}`}
onClick={() => handleJump(item.id)} onClick={() => handleJump(item.subjectId)}
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: item.subjectName __html: item.subjectName
}} }}
@@ -141,7 +98,7 @@ const SearchDetails = () => {
<div <div
className='search-details-box-content-main-item-answer' className='search-details-box-content-main-item-answer'
key={`search-details-answer_${index}`} key={`search-details-answer_${index}`}
onClick={() => handleJump(item.id)} onClick={() => handleJump(item.subjectId)}
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: item.subjectAnswer + '...' __html: item.subjectAnswer + '...'
}} }}
@@ -181,7 +138,7 @@ const SearchDetails = () => {
</Card> </Card>
</div> </div>
<div className='search-details-box-content-paging'> <div className='search-details-box-content-paging'>
{total > 20 && ( {total > 10 && (
<Pagination <Pagination
style={{ style={{
padding: '24px 0', padding: '24px 0',
@@ -191,7 +148,7 @@ const SearchDetails = () => {
current={pageIndex} current={pageIndex}
defaultCurrent={1} defaultCurrent={1}
total={total} total={total}
defaultPageSize={20} defaultPageSize={10}
onChange={onChangePagination} onChange={onChangePagination}
/> />
)} )}