feat: 改造

This commit is contained in:
秋水浮尘
2023-12-02 23:31:54 +08:00
parent 40e5a94d91
commit 0cb65254f4
33 changed files with 2107 additions and 332 deletions

View File

@@ -22,6 +22,7 @@
},
"dependencies": {
"@ant-design/icons": "^5.2.6",
"@reduxjs/toolkit": "^1.9.7",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-react": "^1.0.6",
"antd": "^5.9.4",
@@ -30,6 +31,7 @@
"pubsub-js": "^1.9.4",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-redux": "^8.1.3",
"react-router-dom": "^6.16.0",
"swiper": "^11.0.4",
"wangeditor": "^4.7.15"

157
pnpm-lock.yaml generated
View File

@@ -8,6 +8,9 @@ dependencies:
'@ant-design/icons':
specifier: ^5.2.6
version: registry.npmmirror.com/@ant-design/icons@5.2.6(react-dom@18.1.0)(react@18.1.0)
'@reduxjs/toolkit':
specifier: ^1.9.7
version: registry.npmmirror.com/@reduxjs/toolkit@1.9.7(react-redux@8.1.3)(react@18.1.0)
'@wangeditor/editor':
specifier: ^5.1.23
version: registry.npmmirror.com/@wangeditor/editor@5.1.23
@@ -32,6 +35,9 @@ dependencies:
react-dom:
specifier: ^18.1.0
version: 18.1.0(react@18.1.0)
react-redux:
specifier: ^8.1.3
version: registry.npmmirror.com/react-redux@8.1.3(@types/react-dom@18.0.5)(@types/react@18.0.9)(react-dom@18.1.0)(react@18.1.0)(redux@4.2.1)
react-router-dom:
specifier: ^6.16.0
version: registry.npmmirror.com/react-router-dom@6.16.0(react-dom@18.1.0)(react@18.1.0)
@@ -701,13 +707,11 @@ packages:
/@types/prop-types@15.7.5:
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
dev: true
/@types/react-dom@18.0.5:
resolution: {integrity: sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA==}
dependencies:
'@types/react': 18.0.9
dev: true
/@types/react@18.0.9:
resolution: {integrity: sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==}
@@ -715,11 +719,9 @@ packages:
'@types/prop-types': 15.7.5
'@types/scheduler': 0.16.2
csstype: 3.1.0
dev: true
/@types/scheduler@0.16.2:
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
dev: true
/@typescript-eslint/eslint-plugin@5.27.0(@typescript-eslint/parser@5.27.0)(eslint@8.16.0)(typescript@4.7.2):
resolution: {integrity: sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==}
@@ -1227,7 +1229,6 @@ packages:
/csstype@3.1.0:
resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==}
dev: true
/cz-customizable@6.3.0:
resolution: {integrity: sha512-MWGmWa45v4Ds3NJNNwQc3GCFdjtH3k4ypDWoWkwultMVLf7aOHR9VaXGYGZHLOQS4sMfbkBSjNUYoXCSmLuRSA==}
@@ -4382,6 +4383,28 @@ packages:
react-dom: 18.1.0(react@18.1.0)
dev: false
registry.npmmirror.com/@reduxjs/toolkit@1.9.7(react-redux@8.1.3)(react@18.1.0):
resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@reduxjs/toolkit/-/toolkit-1.9.7.tgz}
id: registry.npmmirror.com/@reduxjs/toolkit/1.9.7
name: '@reduxjs/toolkit'
version: 1.9.7
peerDependencies:
react: ^16.9.0 || ^17.0.0 || ^18
react-redux: ^7.2.1 || ^8.0.2
peerDependenciesMeta:
react:
optional: true
react-redux:
optional: true
dependencies:
immer: registry.npmmirror.com/immer@9.0.21
react: 18.1.0
react-redux: registry.npmmirror.com/react-redux@8.1.3(@types/react-dom@18.0.5)(@types/react@18.0.9)(react-dom@18.1.0)(react@18.1.0)(redux@4.2.1)
redux: registry.npmmirror.com/redux@4.2.1
redux-thunk: registry.npmmirror.com/redux-thunk@2.4.2(redux@4.2.1)
reselect: registry.npmmirror.com/reselect@4.1.8
dev: false
registry.npmmirror.com/@remix-run/router@1.9.0:
resolution: {integrity: sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@remix-run/router/-/router-1.9.0.tgz}
name: '@remix-run/router'
@@ -4425,6 +4448,15 @@ packages:
version: 0.3.4
dev: false
registry.npmmirror.com/@types/hoist-non-react-statics@3.3.5:
resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz}
name: '@types/hoist-non-react-statics'
version: 3.3.5
dependencies:
'@types/react': registry.npmmirror.com/@types/react@18.0.9
hoist-non-react-statics: registry.npmmirror.com/hoist-non-react-statics@3.3.2
dev: false
registry.npmmirror.com/@types/json-schema@7.0.11:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz}
name: '@types/json-schema'
@@ -4437,6 +4469,34 @@ packages:
version: 17.0.36
dev: true
registry.npmmirror.com/@types/prop-types@15.7.5:
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.5.tgz}
name: '@types/prop-types'
version: 15.7.5
dev: false
registry.npmmirror.com/@types/react@18.0.9:
resolution: {integrity: sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/react/-/react-18.0.9.tgz}
name: '@types/react'
version: 18.0.9
dependencies:
'@types/prop-types': registry.npmmirror.com/@types/prop-types@15.7.5
'@types/scheduler': registry.npmmirror.com/@types/scheduler@0.16.2
csstype: registry.npmmirror.com/csstype@3.1.0
dev: false
registry.npmmirror.com/@types/scheduler@0.16.2:
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.2.tgz}
name: '@types/scheduler'
version: 0.16.2
dev: false
registry.npmmirror.com/@types/use-sync-external-store@0.0.3:
resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz}
name: '@types/use-sync-external-store'
version: 0.0.3
dev: false
registry.npmmirror.com/@uppy/companion-client@2.2.2:
resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@uppy/companion-client/-/companion-client-2.2.2.tgz}
name: '@uppy/companion-client'
@@ -5438,6 +5498,14 @@ packages:
engines: {node: '>=8'}
dev: true
registry.npmmirror.com/hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz}
name: hoist-non-react-statics
version: 3.3.2
dependencies:
react-is: registry.npmmirror.com/react-is@16.13.1
dev: false
registry.npmmirror.com/html-void-elements@2.0.1:
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/html-void-elements/-/html-void-elements-2.0.1.tgz}
name: html-void-elements
@@ -6900,6 +6968,49 @@ packages:
version: 16.13.1
dev: false
registry.npmmirror.com/react-is@18.2.0:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/react-is/-/react-is-18.2.0.tgz}
name: react-is
version: 18.2.0
dev: false
registry.npmmirror.com/react-redux@8.1.3(@types/react-dom@18.0.5)(@types/react@18.0.9)(react-dom@18.1.0)(react@18.1.0)(redux@4.2.1):
resolution: {integrity: sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/react-redux/-/react-redux-8.1.3.tgz}
id: registry.npmmirror.com/react-redux/8.1.3
name: react-redux
version: 8.1.3
peerDependencies:
'@types/react': ^16.8 || ^17.0 || ^18.0
'@types/react-dom': ^16.8 || ^17.0 || ^18.0
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
react-native: '>=0.59'
redux: ^4 || ^5.0.0-beta.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
react-dom:
optional: true
react-native:
optional: true
redux:
optional: true
dependencies:
'@babel/runtime': registry.npmmirror.com/@babel/runtime@7.23.1
'@types/hoist-non-react-statics': registry.npmmirror.com/@types/hoist-non-react-statics@3.3.5
'@types/react': 18.0.9
'@types/react-dom': 18.0.5
'@types/use-sync-external-store': registry.npmmirror.com/@types/use-sync-external-store@0.0.3
hoist-non-react-statics: registry.npmmirror.com/hoist-non-react-statics@3.3.2
react: 18.1.0
react-dom: 18.1.0(react@18.1.0)
react-is: registry.npmmirror.com/react-is@18.2.0
redux: registry.npmmirror.com/redux@4.2.1
use-sync-external-store: registry.npmmirror.com/use-sync-external-store@1.2.0(react@18.1.0)
dev: false
registry.npmmirror.com/react-router-dom@6.16.0(react-dom@18.1.0)(react@18.1.0):
resolution: {integrity: sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.16.0.tgz}
id: registry.npmmirror.com/react-router-dom/6.16.0
@@ -6929,12 +7040,37 @@ packages:
react: 18.1.0
dev: false
registry.npmmirror.com/redux-thunk@2.4.2(redux@4.2.1):
resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/redux-thunk/-/redux-thunk-2.4.2.tgz}
id: registry.npmmirror.com/redux-thunk/2.4.2
name: redux-thunk
version: 2.4.2
peerDependencies:
redux: ^4
dependencies:
redux: registry.npmmirror.com/redux@4.2.1
dev: false
registry.npmmirror.com/redux@4.2.1:
resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/redux/-/redux-4.2.1.tgz}
name: redux
version: 4.2.1
dependencies:
'@babel/runtime': registry.npmmirror.com/@babel/runtime@7.23.1
dev: false
registry.npmmirror.com/regenerator-runtime@0.14.0:
resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz}
name: regenerator-runtime
version: 0.14.0
dev: false
registry.npmmirror.com/reselect@4.1.8:
resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/reselect/-/reselect-4.1.8.tgz}
name: reselect
version: 4.1.8
dev: false
registry.npmmirror.com/resize-observer-polyfill@1.5.1:
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz}
name: resize-observer-polyfill
@@ -7208,6 +7344,17 @@ packages:
punycode: registry.npmmirror.com/punycode@2.1.1
dev: true
registry.npmmirror.com/use-sync-external-store@1.2.0(react@18.1.0):
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz}
id: registry.npmmirror.com/use-sync-external-store/1.2.0
name: use-sync-external-store
version: 1.2.0
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
react: 18.1.0
dev: false
registry.npmmirror.com/util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz}
name: util-deprecate

View File

@@ -20,141 +20,10 @@
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently not supported by any browser */
scrollbar-width: none;
.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;
}
.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;
}
.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);
}
.jump-box {
font-size: 14px;
margin-right: 20px;
}
.info-time-box {
display: flex;
}
.time-box {
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;
}
.head-navigator {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0 auto;
width: 1435px;
}
.head-navigator-left {
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;
}
.head-navigator-select-box {
display: flex;
justify-content: space-between;
align-items: center;
width: 500px;
}
.head-navigator-menu-box {
display: flex;
}
.head-navigator-menu-box .ant-menu-horizontal {
border-bottom: 0;
}
.ant-menu-horizontal > .ant-menu-item,
.ant-menu-horizontal > .ant-menu-submenu {
padding: 0px;
margin: 0 12px;
}
.head-navigator-input-box {
margin-right: 24px;
}
.head-navigator-input-box .ant-input {
border-radius: 16px;
}
.head-navigator-user-box {
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;
}
.head-navigator-bell:hover {
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);
}

View File

@@ -133,7 +133,8 @@ const QuestionList = props => {
* @returns
*/
const onChangeAction = item => () => {
navigate('/brush-question/' + item.id)
// navigate('/brush-question/' + item.id)
window.open('/brush-question/' + item.id, '_blank')
// let { isNotToDetail } = props;
// !isNotToDetail &&
// if (!isNotToDetail) return;

View File

@@ -1,18 +1,17 @@
import './main.less'
import React from 'react'
import ReactDOM from 'react-dom/client'
import router from '@/router'
import {
RouterProvider,
} from "react-router-dom";
import { ConfigProvider } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import { ConfigProvider } from 'antd'
import zhCN from 'antd/locale/zh_CN'
import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import { RouterProvider } from 'react-router-dom'
import store from './store/index.ts'
import './main.less'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<ConfigProvider locale={zhCN}>
<Provider store={store}>
<RouterProvider router={router} />
</Provider>
</ConfigProvider>
</React.StrictMode>
)

View File

@@ -36,8 +36,8 @@ const router = createBrowserRouter([
Component: lazy(() => import('@views/search-details'))
},
{
path: 'search-question',
Component: lazy(() => import('@views/search-question'))
path: 'personal-center',
Component: lazy(() => import('@views/personal-center'))
}
]
}

View File

@@ -0,0 +1,28 @@
import { createSlice } from '@reduxjs/toolkit'
export interface CounterState {
value: number
title: string
}
const initialState: CounterState = {
value: 0,
title: 'redux toolkit pre'
}
// 创建一个 Slice
export const userInfoSlice = createSlice({
name: 'userInfo',
initialState,
// 定义 reducers 并生成关联的操作
reducers: {
// 定义一个加的方法
saveUserInfo: (state, { payload }) => {
state.value = payload
}
}
})
// 导出加减的方法
export const { saveUserInfo } = userInfoSlice.actions
// 默认导出
export default userInfoSlice.reducer

12
src/store/index.ts Normal file
View File

@@ -0,0 +1,12 @@
import { configureStore } from '@reduxjs/toolkit'
import userInfoSlice from './features/userInfoSlice.ts'
// configureStore创建一个redux数据
const store = configureStore({
// 合并多个Slice
reducer: {
userInfo: userInfoSlice
}
})
export default store

155
src/views/header/index.less Normal file
View File

@@ -0,0 +1,155 @@
.header-navigator {
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;
}
.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);
}
.jump-box {
font-size: 14px;
margin-right: 20px;
}
.drop-down-box {
display: flex;
background-color: #fff;
padding: 24px;
border-radius: 8px;
box-shadow:
0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 3px 6px -4px rgba(0, 0, 0, 0.12),
0 9px 28px 8px rgba(0, 0, 0, 0.05);
.drop-down-item {
background-color: #eee;
padding: 20px 30px;
text-align: center;
width: 200px;
border-radius: 8px;
cursor: pointer;
&:hover {
background-color: rgba(60, 110, 238, 0.9);
color: white;
}
&-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
&-content {
font-size: 12px;
}
}
}
.head-navigator-box {
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;
}
.head-navigator-left {
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;
}
.head-navigator-select-box {
display: flex;
justify-content: space-between;
align-items: center;
width: 500px;
}
.head-navigator-menu-box {
display: flex;
}
.head-navigator-menu-box .ant-menu-horizontal {
border-bottom: 0;
}
.ant-menu-horizontal > .ant-menu-item,
.ant-menu-horizontal > .ant-menu-submenu {
padding: 0px;
margin: 0 12px;
}
.head-navigator-input-box {
margin-right: 24px;
}
.head-navigator-input-box .ant-input {
border-radius: 16px;
}
.head-navigator-user-box {
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;
}
.head-navigator-bell:hover {
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);
}

View File

@@ -2,10 +2,13 @@ import Head from '@/imgs/head.jpg'
import Logo from '@/imgs/logo.jpg'
import { HeartOutlined, LikeOutlined, LoginOutlined, UserOutlined } from '@ant-design/icons'
import TopMenu from '@components/top-menu'
import LoginQrcode from '@imgs/login_qrcode.jpg'
import req from '@utils/request'
import { Dropdown, Input, Modal, message } from 'antd'
import { Button, Dropdown, Input, Modal, Popover, Space, message } from 'antd'
import { useNavigate } from 'react-router-dom'
import './index.less'
const { Search } = Input
const menuItems = [
@@ -34,6 +37,32 @@ const menuItems = [
}
]
const discoverItems = [
{
title: '联系我',
subTitle: '一键添加鸡哥微信',
key: 'wechat'
},
{
title: '跟我做',
subTitle: '从0到1做鸡翅Club项目',
key: 'club',
path: ''
},
{
title: '更深入',
subTitle: '从0到1做企业级框架项目',
key: 'deep',
path: ''
},
{
title: '加星球',
subTitle: '一键进入鸡哥的知识星球',
key: 'star',
path: ''
}
]
const Header = () => {
const { pathname } = window.location
const navigate = useNavigate()
@@ -87,6 +116,12 @@ const Header = () => {
navigate('/search-detail?t=' + value)
}
const goPath = item => {
if (item.path) {
window.open(item.path, '_blank')
}
}
return (
<div className='head-navigator-box'>
<div className='head-navigator'>
@@ -97,7 +132,50 @@ const Header = () => {
<TopMenu />
</div>
<div className='head-navigator-user-box'>
<div className='time-box'></div>
<Dropdown
placement='bottom'
trigger={['click']}
destroyPopupOnHide
dropdownRender={() => {
return (
<div className='drop-down-box'>
<Space size='large'>
{discoverItems.map(item => {
return (
<div className='drop-down-item' key={item.key} onClick={() => goPath(item)}>
{item.key === 'wechat' ? (
<>
<Popover
zIndex={2000}
placement='bottom'
content={() => {
return (
<div>
<img src={LoginQrcode} />
</div>
)
}}
>
<div className='drop-down-item-title'>{item.title}</div>
<div className='drop-down-item-content'>{item.subTitle}</div>
</Popover>
</>
) : (
<>
<div className='drop-down-item-title'>{item.title}</div>
<div className='drop-down-item-content'>{item.subTitle}</div>
</>
)}
</div>
)
})}
</Space>
</div>
)
}}
>
<Button type='link'></Button>
</Dropdown>
{'/question-bank' == pathname && (
<div className='head-navigator-input-box'>
<Search
@@ -111,9 +189,6 @@ const Header = () => {
/>
</div>
)}
{/* <div className="head-navigator-bell"> */}
{/* <Icon type="bell" /> */}
{/* </div> */}
<div className='head-navigator-user-img'>
<Dropdown
menu={{

View File

@@ -0,0 +1,435 @@
import { ClockCircleTwoTone, ContainerTwoTone, SnippetsTwoTone } from '@ant-design/icons'
import { Button, Card, Checkbox, Pagination, Table } from 'antd'
import React, { Component } from 'react'
import './index.less'
export default class BrushQuestion extends Component {
constructor(props) {
super(props)
this.state = {
currentKey: 'tab1', //选中的tab
lookFinish: false, //是否只看已完成,默认否
total: 9
}
}
pageIndex = 1
tabList = [
{
key: 'tab1',
tab: '试卷'
},
{
key: 'tab2',
tab: '错题集'
}
]
columns = [
{
title: '题目',
dataIndex: 'question',
key: 'qusetion',
render: text => <a>{text}</a>
},
{
title: '知识点',
dataIndex: 'knowledge',
key: 'knowledge'
},
{
title: '来自',
dataIndex: 'from',
key: 'from'
},
{
title: () => <Checkbox onChange={this.onLookErrorChange}>只看已完成的</Checkbox>,
key: 'tags',
dataIndex: 'tags',
render: () => <Button type='primary'>查看详情</Button>
}
]
data = [
{
key: '1',
question: '在哈希法存储中,冲突指的是 ',
knowledge: '哈希',
from: '考卷1'
// tags: ['nice', 'developer'],
},
{
key: '2',
question: '在深度为5的满二叉树中结点的个数为多少个',
knowledge: '树',
from: '考卷2'
// tags: ['loser'],
}
]
onTabChange = key => {
console.log('----', key)
this.setState({
currentKey: key
})
}
onLookChange = () => {
this.setState({
lookFinish: true
})
}
onLookErrorChange = key => {
console.log('----', key)
}
handleNext() {
console.log('再做一次')
}
handleLook() {
console.log('查看详情')
}
onChangePagination = pageIndex => {
this.pageIndex = pageIndex
}
render() {
const { currentKey, total } = this.state
return (
<div className='brush-question-component'>
<Card
style={{ width: '100%' }}
tabList={this.tabList}
bordered={false}
activeTabKey={currentKey}
onTabChange={key => {
this.onTabChange(key, 'key')
}}
>
{currentKey === 'tab1' && (
<div>
<div className='brush-question-component-tab1-head'>
<div className='brush-question-component-tab1-head-title'>
<div className='brush-question-component-tab1-head-title-icon'>
<SnippetsTwoTone twoToneColor='#FF0000' />
</div>
<div>练习的试卷21</div>
</div>
<div className='brush-question-component-tab1-head-filter'>
<Checkbox onChange={this.onLookChange}>只看已完成的</Checkbox>
</div>
</div>
<div className='brush-question-component-tab1-body'>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
<div className='brush-question-component-tab1-body-item'>
<div style={{ backgroundColor: 'rgb(234, 235, 236)' }}>
<div className='brush-question-component-tab1-body-label'>专项练习</div>
<div className='brush-question-component-tab1-body-item-title'>
计算机专业技能-网络基础专项练习
</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ClockCircleTwoTone twoToneColor='#AAAAAA' />
</div>
<div>完成时间2021-12-13</div>
</div>
<div className='brush-question-component-tab1-body-item-content'>
<div className='brush-question-component-tab1-body-item-content-icon'>
<ContainerTwoTone twoToneColor='#AAAAAA' />
</div>
<div>得分0</div>
</div>
<div className='brush-question-component-tab1-body-item-footer'>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleNext}
>
再做一次
</div>
<div
className='brush-question-component-tab1-body-item-footer-button'
onClick={this.handleLook}
>
查看详情
</div>
</div>
</div>
</div>
<div className='brush-question-component-tab1-page'>
{total > 8 && (
<Pagination
style={{
padding: '24px 0',
textAlign: 'center'
}}
showQuickJumper
current={this.pageIndex}
defaultCurrent={1}
total={total}
defaultPageSize={8}
onChange={this.onChangePagination}
/>
)}
</div>
</div>
</div>
)}
{currentKey === 'tab2' && (
<div>
<div className='brush-question-component-tab2-head'>
<div className='brush-question-component-tab2-head-title'>
<div className='brush-question-component-tab2-head-title-icon'>
<SnippetsTwoTone twoToneColor='#FF0000' />
</div>
<div>历史错题总数21</div>
</div>
<div className='brush-question-component-tab2-head-button'>
<Button type='primary'>错题组卷练习</Button>
</div>
</div>
<div className='brush-question-component-tab2-body'>
<Table columns={this.columns} dataSource={this.data} />
</div>
</div>
)}
</Card>
</div>
)
}
}

View File

@@ -0,0 +1,97 @@
.brush-question-component {
.brush-question-component-tab1-head {
display: flex;
justify-content: space-between;
padding: 0 0 20px 0;
.brush-question-component-tab1-head-title {
display: flex;
color: #333;
font-size: 16px;
font-weight: 400;
.brush-question-component-tab1-head-title-icon {
margin-right: 8px;
}
}
.brush-question-component-tab1-head-filter {
font-weight: 400;
}
}
.brush-question-component-tab1-body {
padding: 0 50px;
// display: flex;
// flex-wrap: wrap;
.brush-question-component-tab1-body-item {
border-radius: 2px;
box-shadow: 0 6px 20px 0 #bababa;
cursor: pointer;
display: block;
height: 230px;
margin-bottom: 17px;
margin-right: 17px;
width: 216px;
transition: all 0.5s;
&:hover {
transform: scale(1.04);
}
&:hover .brush-question-component-tab1-body-item-footer {
display: flex;
}
.brush-question-component-tab1-body-label {
width: 76px;
height: 20px;
background-image: linear-gradient(136deg, #ffe324, #e7920f 100%, #ffb533 0);
box-shadow: 2px 0 2px 0 rgb(175, 130, 6);
position: relative;
top: -3%;
left: -8px;
text-align: center;
}
.brush-question-component-tab1-body-item-title {
background-color: rgb(234, 235, 236);
color: #333;
font-size: 14px;
font-weight: 700;
height: 80px;
// line-height: 50px;
overflow: auto;
padding: 20px 10px 0;
text-align: center;
}
.brush-question-component-tab1-body-item-content {
display: flex;
margin: 10px;
color: #000000a6;
.brush-question-component-tab1-body-item-content-icon {
margin-right: 5px;
}
}
.brush-question-component-tab1-body-item-footer {
display: none;
margin-top: 40px;
.brush-question-component-tab1-body-item-footer-button {
flex: 1;
text-align: center;
&:hover {
color: #3c6eee;
}
}
}
}
}
.brush-question-component-tab2-head {
display: flex;
justify-content: space-between;
padding: 0 0 20px 0;
.brush-question-component-tab2-head-title {
display: flex;
color: #333;
font-size: 16px;
font-weight: 400;
.brush-question-component-tab2-head-title-icon {
margin-right: 8px;
}
}
}
}

View File

@@ -0,0 +1,145 @@
import { Card, Pagination, Spin } from 'antd'
import React, { Component } from 'react'
import { collectTabType } from '../../constant'
import CollectionQuestion from '../collection-question'
import EmptyBox from '../empty-box'
import './index.less'
const tabList = [
{
key: 'testQuestions',
tab: '收藏的试题'
}
// {
// key: 'posts',
// tab: '收藏的帖子',
// },
]
export default class CollectionBag extends Component {
constructor(props) {
super(props)
this.state = {
currentKey: collectTabType.testQuestions, // 选中的tab 默认选中第一个
collectionList: [],
isShowSpin: true,
isShowSkeleton: true
}
}
total = 0 // 总题数
pageIndex = 1
pageSize = 10
componentDidMount() {
this.getCollectionList()
}
/**
* 切换tab
* @param {*} key
*/
onTabChange = key => {
this.setState(
{
currentKey: key
},
() => {
this.pageIndex = 1
this.getCollectionList()
}
)
}
/**
* 获取一级分类数据
*/
getCollectionList() {
// JDreq({
// method: 'post',
// data: {
// pageInfo: {
// pageIndex: this.pageIndex,
// pageSize: this.pageSize,
// },
// },
// url: apiName.getCollectionList,
// })
// .then((res) => {
// if (res.data && res.data.pageList?.length > 0) {
// this.total = res.data.pageInfo.total
// this.setState({
// collectionList: res.data.pageList,
// isShowSpin: false,
// isShowSkeleton: false,
// })
// } else {
// this.total = 0
// this.setState({
// collectionList: [],
// isShowSpin: false,
// })
// }
// })
// .catch((err) => console.log(err))
}
/**
* 分页
* @param {*} pageIndex
*/
onChangePagination = pageIndex => {
this.pageIndex = pageIndex
this.getCollectionList()
}
render() {
const { currentKey, collectionList, isShowSpin } = this.state
return (
<div className='collection-bag-component'>
<Card
style={{ width: '100%' }}
tabList={tabList}
activeTabKey={currentKey}
onTabChange={key => {
this.onTabChange(key)
}}
>
<Spin spinning={isShowSpin}>
{collectionList?.length > 0 ? this.renderContent(currentKey) : <EmptyBox />}
{this.total > 10 && (
<Pagination
style={{
padding: '24px 0',
textAlign: 'center'
}}
showQuickJumper
current={this.pageIndex}
defaultCurrent={this.pageIndex}
total={this.total}
onChange={this.onChangePagination}
/>
)}
</Spin>
</Card>
</div>
)
}
/**
* 渲染内容
* @param {*} type
* @returns
*/
renderContent = type => {
const { collectionList } = this.state
switch (type) {
// 收藏的试题
case collectTabType.testQuestions:
return (
<div>
<CollectionQuestion collectionList={collectionList} collectionTotal={this.total} />
</div>
)
}
}
}

View File

@@ -0,0 +1,16 @@
.collection-bag-component {
.collection-bag-component-tab1-head {
display: flex;
justify-content: space-between;
padding: 0 0 20px 0;
.collection-bag-component-tab1-head-title {
display: flex;
color: #333;
font-size: 16px;
font-weight: 400;
.collection-bag-component-tab1-head-title-icon {
margin-right: 8px;
}
}
}
}

View File

@@ -0,0 +1,103 @@
import { SnippetsTwoTone } from '@ant-design/icons'
import { debounce, splicingQuery } from '@utils'
import React, { Component } from 'react'
import './index.less'
class CollectionQuestion extends Component {
constructor(props) {
super(props)
this.state = {
isModalVisible: false //对话框默认不可见
}
}
handleCancelCollection = () => {
console.log('取消收藏')
this.setState({
isModalVisible: true
})
}
handleCancel = () => {
// console.log('点了取消');
this.setState({
isModalVisible: false
})
}
handleOk = () => {
console.log('点了确认')
this.setState({
isModalVisible: false
})
}
handleJump = id =>
debounce(() => {
this.props.history.push(
splicingQuery('good-collection-question', {
subjectType: 4,
subjectId: id
})
)
})
render() {
const { collectionList, collectionTotal } = this.props
const { isModalVisible } = this.state
return (
<div className='collection-bag-component-tab1-body'>
<div className='collection-bag-component-tab1-head-title'>
<div className='collection-bag-component-tab1-head-title-icon'>
<SnippetsTwoTone twoToneColor='#FF0000' />
</div>
<div>收藏的题目({collectionTotal})</div>
</div>
{collectionList.map(item => {
return (
<div
className='collection-bag-component-tab1-body-item'
key={`collection_question_${item.id}`}
>
<div className='collection-bag-component-tab1-body-item-question'>
<span
className='collection-bag-component-tab1-body-item-question-content'
onClick={this.handleJump(item.id)}
>
{item.subjectName}
</span>
</div>
{/* <div className="collection-bag-component-tab1-body-item-foot">
<span
className="collection-bag-component-tab1-body-item-foot-button"
onClick={this.handleCancelCollection}
>
取消收藏
</span>
<Modal
title="提示"
visible={isModalVisible}
cancelText="取消"
okText="确认"
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<p
style={{
fontSize: '17px',
textAlign: 'center',
}}
>
确认取消收藏吗?
</p>
</Modal>
</div> */}
</div>
)
})}
</div>
)
}
}
export default CollectionQuestion

View File

@@ -0,0 +1,44 @@
.collection-bag-component-tab1-body {
padding: 0 20px 20px 20px;
.collection-bag-component-tab1-head-title {
display: flex;
color: #333;
font-size: 16px;
font-weight: 400;
.collection-bag-component-tab1-head-title-icon {
margin-right: 8px;
}
}
.collection-bag-component-tab1-body-item {
margin: 10px 0;
overflow: auto;
position: relative;
clear: both;
// height: 60px;
border-bottom: 1px solid #e5e5e5;
.collection-bag-component-tab1-body-item-question {
font-size: 14px;
line-height: 1.8;
.collection-bag-component-tab1-body-item-question-content {
width: 600px;
cursor: pointer;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
&:hover {
color: #3c6eee;
}
}
}
.collection-bag-component-tab1-body-item-foot {
margin-top: 10px;
float: right;
.collection-bag-component-tab1-body-item-foot-button {
cursor: pointer;
color: #3c6eee;
}
}
}
}

View File

@@ -0,0 +1,13 @@
import React from 'react'
import './index.less'
export default function EmptyBox() {
return (
<div className='empty-box'>
<img
src='https://img11.360buyimg.com/imagetools/jfs/t1/161028/16/25609/6746/61a08d83E06659dfa/e6418acdab948134.png'
className='empty-inco'
/>
<span className='empty-text'>这里什么也没有哦</span>
</div>
)
}

View File

@@ -0,0 +1,17 @@
.empty-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 100px 0;
.empty-inco {
width: 100px;
height: 100px;
}
.empty-text {
margin-top: 20px;
color: #b2bac2;
font-weight: 500;
font-size: 14px;
}
}

View File

@@ -0,0 +1,139 @@
import { Card, Pagination, Spin } from 'antd'
import React, { Component } from 'react'
import { goodTabType } from '../../constant'
import EmptyBox from '../empty-box'
import GoodQuestion from '../good-question'
import './index.less'
const tabList = [
{
key: 'testQuestions',
tab: '点赞的试题'
}
// {
// key: 'posts',
// tab: '点赞的帖子',
// },
]
export default class GoodBag extends Component {
constructor(props) {
super(props)
this.state = {
currentKey: goodTabType.testQuestions, // 选中的tab 默认选中第一个
goodList: [],
isShowSpin: true
}
}
total = 0 // 总题数
pageIndex = 1
pageSize = 10
componentDidMount() {
this.getGoodList()
}
/**
* 切换tab
* @param {*} key
*/
onTabChange = key => {
this.setState(
{
currentKey: key
},
() => {
this.pageIndex = 1
this.getGoodList()
}
)
}
/**
* 获取一级分类数据
*/
getGoodList() {
// JDreq({
// method: 'post',
// data: {
// pageInfo: {
// pageIndex: this.pageIndex,
// pageSize: this.pageSize,
// },
// },
// url: apiName.getGoodList,
// })
// .then((res) => {
// if (res.data && res.data.pageList?.length > 0) {
// this.total = res.data.pageInfo.total
// this.setState({
// goodList: res.data.pageList,
// isShowSpin: false,
// })
// } else {
// this.total = 0
// this.setState({
// goodList: [],
// isShowSpin: false,
// })
// }
// })
// .catch((err) => console.log(err))
}
/**
* 分页
* @param {*} pageIndex
*/
onChangePagination = pageIndex => {
this.pageIndex = pageIndex
this.getGoodList()
}
render() {
const { currentKey, goodList, isShowSpin } = this.state
return (
<div className='good-bag-component'>
<Card
style={{ width: '100%' }}
tabList={tabList}
activeTabKey={currentKey}
onTabChange={key => {
this.onTabChange(key)
}}
>
<Spin spinning={isShowSpin}>
{goodList?.length > 0 ? this.renderContent(currentKey) : <EmptyBox />}
{this.total > 10 && (
<Pagination
style={{
padding: '24px 0',
textAlign: 'center'
}}
showQuickJumper
current={this.pageIndex}
defaultCurrent={this.pageIndex}
total={this.total}
onChange={this.onChangePagination}
/>
)}
</Spin>
</Card>
</div>
)
}
/**
* 渲染内容
* @param {*} type
* @returns
*/
renderContent = type => {
const { goodList } = this.state
switch (type) {
// 收藏的试题
case goodTabType.testQuestions:
return <GoodQuestion goodList={goodList} goodTotal={this.total} />
}
}
}

View File

@@ -0,0 +1,16 @@
.good-bag-component {
.good-bag-component-tab1-head {
display: flex;
justify-content: space-between;
padding: 0 0 20px 0;
.good-bag-component-tab1-head-title {
display: flex;
color: #333;
font-size: 16px;
font-weight: 400;
.good-bag-component-tab1-head-title-icon {
margin-right: 8px;
}
}
}
}

View File

@@ -0,0 +1,97 @@
import { SnippetsTwoTone } from '@ant-design/icons'
import { debounce, splicingQuery } from '@utils'
import React, { Component } from 'react'
import './index.less'
class GoodQuestion extends Component {
constructor(props) {
super(props)
this.state = {
isModalVisible: false //对话框默认不可见
}
}
handleCancelGood = () => {
console.log('取消点赞')
this.setState({
isModalVisible: true
})
}
handleCancel = () => {
// console.log('点了取消');
this.setState({
isModalVisible: false
})
}
handleOk = () => {
console.log('点了确认')
this.setState({
isModalVisible: false
})
}
handleJump = id =>
debounce(() => {
this.props.history.push(
splicingQuery('good-collection-question', {
subjectType: 4,
subjectId: id
})
)
})
render() {
const { goodList, goodTotal } = this.props
const { isModalVisible } = this.state
return (
<div className='good-bag-component-tab1-body'>
<div className='good-bag-component-tab1-head-title'>
<div className='good-bag-component-tab1-head-title-icon'>
<SnippetsTwoTone twoToneColor='#FF0000' />
</div>
<div>点赞的题目{goodTotal}</div>
</div>
{goodList.map(item => {
return (
<div className='good-bag-component-tab1-body-item' key={`good_question_${item.id}`}>
<div className='good-bag-component-tab1-body-item-question'>
<span
className='good-bag-component-tab1-body-item-question-content'
onClick={this.handleJump(item.id)}
>
{item.subjectName}
</span>
</div>
{/* <div className="good-bag-component-tab1-body-item-foot">
<span className="good-bag-component-tab1-body-item-foot-button" onClick={this.handleCancelGood}>
取消点赞
</span>
<Modal
title="提示"
visible={isModalVisible}
cancelText="取消"
okText="确认"
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<p
style={{
fontSize: '17px',
textAlign: 'center',
}}
>
确认取消点赞吗?
</p>
</Modal>
</div> */}
</div>
)
})}
</div>
)
}
}
export default GoodQuestion

View File

@@ -0,0 +1,44 @@
.good-bag-component-tab1-body {
padding: 0 20px 20px 20px;
.good-bag-component-tab1-head-title {
display: flex;
color: #333;
font-size: 16px;
font-weight: 400;
.good-bag-component-tab1-head-title-icon {
margin-right: 8px;
}
}
.good-bag-component-tab1-body-item {
margin: 10px 0;
overflow: auto;
position: relative;
clear: both;
// height: 60px;
border-bottom: 1px solid #e5e5e5;
.good-bag-component-tab1-body-item-question {
font-size: 14px;
line-height: 1.8;
.good-bag-component-tab1-body-item-question-content {
width: 600px;
cursor: pointer;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
&:hover {
color: #3c6eee;
}
}
}
.good-bag-component-tab1-body-item-foot {
margin-top: 10px;
float: right;
.good-bag-component-tab1-body-item-foot-button {
cursor: pointer;
color: #3c6eee;
}
}
}
}

View File

@@ -0,0 +1,19 @@
export const apiName = {
/**
* 获取收藏数据
*/
getCollectionList: '/admin/question/collect/list',
getGoodList: 'admin/question/thump/list',
}
// 收藏-tab类型
export const collectTabType = {
testQuestions: 'testQuestions', //试题
posts: 'posts', //帖子
}
// 点赞-tab类型
export const goodTabType = {
testQuestions: 'testQuestions', //试题
posts: 'posts', //帖子
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,160 @@
import { IdcardOutlined, LikeTwoTone, MailOutlined, StarTwoTone } from '@ant-design/icons'
import { Menu } from 'antd'
import React, { Component } from 'react'
// import JDreq from '@common/JDreq'
import PubSub from 'pubsub-js'
// import headLog from './headLog.png'
import CollectionBag from './components/collection-bag'
import GoodBag from './components/good-bag'
import './index.less'
export default class PersonalCenter extends Component {
constructor(props) {
super(props)
this.state = {
currentKeyMap: 0, //选中的menu
userName: '', //姓名
intervieweEamil: '', //邮箱
headImg: '', //头像
department: '', //部门
practiceAmount: 0, //练题数
inputAmount: 0, //录题数
goodAmount: 0, //点赞数
collectionAmount: 0, //收藏数
subMenuList: []
}
}
personList = {
// 0: '刷题',
0: '收藏',
1: '点赞'
}
componentDidMount() {
// JDreq({
// method: 'post',
// url: 'admin/person/home/getPersonInfo'
// }).then(res => {
// this.setState(
// {
// userName: res.data?.name ?? '',
// intervieweEamil: res.data?.email ?? '',
// headImg: res.data?.headImg ?? '',
// department: res.data?.departmentName ?? '',
// goodAmount: res.data?.thumpCount ?? 0,
// collectionAmount: res.data?.collectCount ?? 0,
// practiceAmount: res.data?.practiceCount ?? 0,
// inputAmount: res.data?.subjectCount ?? 0
// },
// () => {
// window.localStorage.setItem('interviewName', res.data?.name ?? 'XXX')
// window.localStorage.setItem('interviewEamil', res.data?.email ?? 'XXX')
// }
// )
// })
PubSub.subscribe('handleToRender', () => {
this.setState({})
})
}
/**
* 切换菜单
* @param {*} e
*/
handleClick = e => {
console.log('--------', e)
//截取_后的字符
let index = e.keyPath[0].lastIndexOf('_')
let index2 = e.keyPath[0].substring(index + 1, e.keyPath[0].length)
//
console.log('index2>>>>', index2)
this.setState({
currentKeyMap: Number(index2)
})
}
render() {
let {
headImg,
userName,
intervieweEamil,
department,
goodAmount,
collectionAmount,
practiceAmount,
inputAmount
} = this.state
const { currentKeyMap } = this.state
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={headImg} style={{ width: 60, height: 60, borderRadius: '50%' }} />
</div>
<div className='personal-center-introduction-detail-text'>
<div className='personal-center-introduction-detail-name'>{userName}</div>
<div className='personal-center-introduction-detail-information'>
<span className='personal-center-introduction-detail-information-content'>
<IdcardOutlined style={{ color: 'blue', marginRight: '3px' }} />
{/* 部门:{department} */}
</span>
<span className='personal-center-introduction-detail-information-content'>
<MailOutlined style={{ color: 'blue', marginRight: '3px' }} />
{/* 邮箱:{intervieweEamil} */}
</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'>
{practiceAmount}
</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'>{goodAmount}</div>
<div>点赞</div>
</div>
<div className='personal-center-introduction-result-item'>
<div className='personal-center-introduction-result-item-number'>
{collectionAmount}
</div>
<div>收藏</div>
</div>
</div>
</div>
<div className='personal-center-content'>
<div className='personal-center-content-left'>
<Menu
mode='inline'
onClick={this.handleClick}
style={{ width: 256 }}
defaultSelectedKeys={['personList_0']}
>
{/* <Menu.Item key={`personList_0`}>
<MailOutlined style={{ color: 'rgb(171,214,97)' }} />
<span>{this.personList[0]}</span>
</Menu.Item> */}
<Menu.Item key={`personList_0`}>
<StarTwoTone twoToneColor='rgb(252,132,67)' />
<span>{this.personList[0]}</span>
</Menu.Item>
<Menu.Item key={`personList_1`}>
<LikeTwoTone twoToneColor='#99bbff' />
<span>{this.personList[1]}</span>
</Menu.Item>
</Menu>
</div>
<div className='personal-center-content-right'>
{/* {currentKeyMap === 0 && <BrushQuestion />} */}
{currentKeyMap === 0 && <CollectionBag />}
{currentKeyMap === 1 && <GoodBag />}
</div>
</div>
</div>
)
}
}

View File

@@ -0,0 +1,68 @@
.personal-center-box {
margin: 0 auto;
width: 1439px;
// padding: 20px 50px;
border-radius: 5px;
overflow: auto;
.personal-center-introduction {
background-color: #fff;
border-radius: 3px;
height: 100px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
.personal-center-introduction-detail {
margin-left: 50px;
padding-top: 20px;
display: flex;
.personal-center-introduction-detail-headImg {
margin-right: 20px;
align-items: center;
}
.personal-center-introduction-detail-text {
.personal-center-introduction-detail-name {
color: #3c6eee;
font-weight: 570;
}
.personal-center-introduction-detail-information {
margin: 15px 0;
.personal-center-introduction-detail-information-content {
margin-right: 15px;
}
}
}
}
.personal-center-introduction-result {
margin-right: 50px;
padding-top: 30px;
display: flex;
.personal-center-introduction-result-item {
text-align: center;
padding-right: 10px;
.personal-center-introduction-result-item-number {
font-weight: 570;
color: #3c6eee;
}
}
}
}
.personal-center-content {
display: flex;
align-items: flex-start;
.personal-center-content-left {
background-color: #fff;
overflow-y: auto;
border-radius: 3px;
width: 300px;
height: 720px;
}
.personal-center-content-right {
background-color: #fff;
flex-direction: column;
overflow: auto;
border-radius: 4px;
margin: 0 0 0 10px;
width: 100%;
}
}
}

View File

@@ -0,0 +1,58 @@
export const getCollectionList = {
pageInfo: {
pageSize: 10,
totalPage: 2,
pageIndex: 1,
total: 12,
firstPage: true,
lastPage: false,
startRecord: 0,
endRecord: 10,
},
pageList: [
{
id: 1717,
subjectName: '说说 React组件开发中关于作用域的常见问题。',
},
{
id: 1710,
subjectName: '概述一下 React中的事件处理逻辑。',
},
{
id: 1706,
subjectName: 'React中Diff算法的原理是什么',
},
{
id: 1698,
subjectName: 'shouldComponentUpdate有什么用为什么它很重要',
},
{
id: 1695,
subjectName: '在哪个生命周期中你会发出Ajax请求为什么',
},
{
id: 1692,
subjectName: '类组件和函数组件之间的区别是什么?',
},
{
id: 1691,
subjectName: '详细解释 React 组件的生命周期方法?',
},
{
id: 1689,
subjectName: '什么是 Props?',
},
{
id: 1579,
subjectName: '横竖屏切换的Activity 生命周期变化?',
},
{
id: 1578,
subjectName: '谈下MVC MVPMVVM',
},
{
id: 1532,
subjectName: 'get 和post 请求在缓存方面的区别是什么?',
},
],
}

View File

@@ -67,12 +67,12 @@ const ContributionList = props => {
).then(res => {
if (res.success && res.data) {
if (res.data.includes('subject:add')) {
navigate('/upload-questions')
window.open('/upload-question')
} else {
message.info('敬请期待')
message.info('暂无权限')
}
} else {
message.info('敬请期待')
message.info('暂无权限')
}
})
}

View File

@@ -1,5 +1,5 @@
.brief-questions-container {
width: 1000px;
// width: 1000px;
display: flex;
align-items: center;
padding: 0 24px;

View File

@@ -18,8 +18,6 @@
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(208, 212, 222, 1);
border-radius: 12px;
&:hover {
}
}
.upload-left-layout-item-active {
color: rgba(60, 110, 238, 1);

View File

@@ -4,7 +4,7 @@
width: 1439px;
overflow-y: auto;
border-radius: 5px;
height: calc(100vh - 90px);
height: calc(100vh - 100px);
.ant-card-head {
position: sticky;
top: 0;

View File

@@ -1,49 +1,66 @@
import React, { Component } from 'react';
import { Card } from 'antd';
import SingleBox from './pages/single-box';
import BatchleBox from './pages/batch-box';
import './index.less';
import req from '@utils/request'
import { Card, message } from 'antd'
import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import BatchleBox from './pages/batch-box'
import SingleBox from './pages/single-box'
import './index.less'
const tabList = [
{
key: 'singleBox',
tab: '单题录入',
tab: '单题录入'
}
]
const UploadQuestions = () => {
const [currentKey, setCurrentKey] = useState('singleBox')
const navigate = useNavigate()
useEffect(() => {
const userInfoStorage = localStorage.getItem('userInfo')
if (!userInfoStorage) {
return message.info('请登录')
}
const { loginId } = JSON.parse(userInfoStorage)
req(
{
method: 'get',
url: '/permission/getPermission',
params: {
userName: loginId
}
},
// {
// key: 'batchBox',
// tab: '批量导入',
// },
];
export default class UploadQuestions extends Component {
constructor(props) {
super(props);
this.state = { currentKey: 'singleBox' };
'/auth'
).then(res => {
if (res.success && res.data) {
if (!res.data.includes('subject:add')) {
message.info('暂无权限')
navigate('/question-bank')
}
}
})
}, [])
const contentList = {
singleBox: <SingleBox />,
batchBox: <BatchleBox />
}
contentList = {
singleBox: <SingleBox />,
batchBox: <BatchleBox />,
};
onTabChange = (e) => {
this.setState({
currentKey: e,
});
};
render() {
const { currentKey } = this.state;
return (
<div className="upload-questions-box">
<div className='upload-questions-box'>
<Card
style={{ width: '100%' }}
tabList={tabList}
bordered={false}
activeTabKey={currentKey}
onTabChange={(key) => {
this.onTabChange(key, 'key');
}}>
{this.contentList[currentKey]}
onTabChange={key => {
setCurrentKey(key)
}}
>
{contentList[currentKey]}
</Card>
</div>
);
}
)
}
export default UploadQuestions

View File

@@ -1,64 +1,65 @@
import React, { Component } from 'react';
import UploadLeftLayout from '../../components/upload-left-layout';
import BriefQuestions from '../../components/brief-questions';
import SingleQuestions from '../../components/single-questions';
import MultipleQuestions from '../../components/multiple-questions';
import JudgeQuestions from '../../components/judge-questions';
import { uploadLayout } from '../../constant';
import './index.less';
import React, { Component } from 'react'
import BriefQuestions from '../../components/brief-questions'
import JudgeQuestions from '../../components/judge-questions'
import MultipleQuestions from '../../components/multiple-questions'
import SingleQuestions from '../../components/single-questions'
import UploadLeftLayout from '../../components/upload-left-layout'
import { uploadLayout } from '../../constant'
import './index.less'
export default class SingleBox extends Component {
constructor(props) {
super(props);
super(props)
this.state = {
layoutList: uploadLayout,
currentIndex: 0,
};
currentIndex: 0
}
}
/**
* 切换题型
* @param {*} id
*/
onChangeQuestionsType = (layoutIndex) => {
let { layoutList, currentIndex } = this.state;
onChangeQuestionsType = layoutIndex => {
let { layoutList, currentIndex } = this.state
if (currentIndex === layoutIndex) {
return;
return
}
let list = layoutList.map((item, index) => {
let flag = false;
let flag = false
if (layoutIndex === index) {
flag = true;
flag = true
}
return {
...item,
active: flag,
};
});
active: flag
}
})
this.setState({
layoutList: list,
currentIndex: layoutIndex,
});
};
currentIndex: layoutIndex
})
}
render() {
const { currentIndex, layoutList } = this.state;
const { currentIndex, layoutList } = this.state
return (
<div style={{ display: 'flex' }}>
<UploadLeftLayout layoutList={layoutList} onChange={this.onChangeQuestionsType} />
<div className="upload-questions-modular">{this.changeReander(currentIndex)}</div>
<div className='upload-questions-modular'>{this.changeReander(currentIndex)}</div>
</div>
);
)
}
changeReander = (i) => {
changeReander = i => {
switch (i) {
case 0:
return <BriefQuestions questionsType={i + 1} key={`question_${i}`} />;
return <BriefQuestions questionsType={i + 1} key={`question_${i}`} />
case 1:
return <SingleQuestions questionsType={i + 1} key={`question_${i}`} />;
return <SingleQuestions questionsType={i + 1} key={`question_${i}`} />
case 2:
return <MultipleQuestions questionsType={i + 1} key={`question_${i}`} />;
return <MultipleQuestions questionsType={i + 1} key={`question_${i}`} />
case 3:
return <JudgeQuestions questionsType={i + 1} key={`question_${i}`} />;
return <JudgeQuestions questionsType={i + 1} key={`question_${i}`} />
}
}
};
}