feat: 🎸 新增了一个全局加载组件
This commit is contained in:
@@ -16,12 +16,15 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@arco-design/web-react": "^2.66.4",
|
"@arco-design/web-react": "^2.66.4",
|
||||||
|
"@reduxjs/toolkit": "^2.8.2",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"echarts": "^6.0.0",
|
"echarts": "^6.0.0",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-echarts": "^0.1.1",
|
"react-echarts": "^0.1.1",
|
||||||
"react-router-dom": "^7.7.1"
|
"react-redux": "^9.2.0",
|
||||||
|
"react-router-dom": "^7.7.1",
|
||||||
|
"redux": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.30.1",
|
"@eslint/js": "^9.30.1",
|
||||||
|
|||||||
101
pnpm-lock.yaml
generated
101
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
|||||||
'@arco-design/web-react':
|
'@arco-design/web-react':
|
||||||
specifier: ^2.66.4
|
specifier: ^2.66.4
|
||||||
version: 2.66.4(@types/react@19.1.10)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
version: 2.66.4(@types/react@19.1.10)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
|
'@reduxjs/toolkit':
|
||||||
|
specifier: ^2.8.2
|
||||||
|
version: 2.8.2(react-redux@9.2.0(@types/react@19.1.10)(react@19.1.1)(redux@5.0.1))(react@19.1.1)
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.11.0
|
specifier: ^1.11.0
|
||||||
version: 1.11.0
|
version: 1.11.0
|
||||||
@@ -26,9 +29,15 @@ importers:
|
|||||||
react-echarts:
|
react-echarts:
|
||||||
specifier: ^0.1.1
|
specifier: ^0.1.1
|
||||||
version: 0.1.1(react@19.1.1)
|
version: 0.1.1(react@19.1.1)
|
||||||
|
react-redux:
|
||||||
|
specifier: ^9.2.0
|
||||||
|
version: 9.2.0(@types/react@19.1.10)(react@19.1.1)(redux@5.0.1)
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^7.7.1
|
specifier: ^7.7.1
|
||||||
version: 7.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
version: 7.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
|
redux:
|
||||||
|
specifier: ^5.0.1
|
||||||
|
version: 5.0.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.30.1
|
specifier: ^9.30.1
|
||||||
@@ -396,6 +405,17 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.30':
|
'@jridgewell/trace-mapping@0.3.30':
|
||||||
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
||||||
|
|
||||||
|
'@reduxjs/toolkit@2.8.2':
|
||||||
|
resolution: {integrity: sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.9.0 || ^17.0.0 || ^18 || ^19
|
||||||
|
react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-redux:
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@rolldown/pluginutils@1.0.0-beta.27':
|
'@rolldown/pluginutils@1.0.0-beta.27':
|
||||||
resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
|
resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
|
||||||
|
|
||||||
@@ -510,6 +530,12 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@standard-schema/spec@1.0.0':
|
||||||
|
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
|
||||||
|
|
||||||
|
'@standard-schema/utils@0.3.0':
|
||||||
|
resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
|
||||||
|
|
||||||
'@types/babel__core@7.20.5':
|
'@types/babel__core@7.20.5':
|
||||||
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
||||||
|
|
||||||
@@ -536,6 +562,9 @@ packages:
|
|||||||
'@types/react@19.1.10':
|
'@types/react@19.1.10':
|
||||||
resolution: {integrity: sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==}
|
resolution: {integrity: sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==}
|
||||||
|
|
||||||
|
'@types/use-sync-external-store@0.0.6':
|
||||||
|
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
|
||||||
|
|
||||||
'@vitejs/plugin-react@4.7.0':
|
'@vitejs/plugin-react@4.7.0':
|
||||||
resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
|
resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
@@ -878,6 +907,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
immer@10.1.1:
|
||||||
|
resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
|
||||||
|
|
||||||
import-fresh@3.3.1:
|
import-fresh@3.3.1:
|
||||||
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -1075,6 +1107,18 @@ packages:
|
|||||||
react-is@18.3.1:
|
react-is@18.3.1:
|
||||||
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
||||||
|
|
||||||
|
react-redux@9.2.0:
|
||||||
|
resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^18.2.25 || ^19
|
||||||
|
react: ^18.0 || ^19
|
||||||
|
redux: ^5.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
redux:
|
||||||
|
optional: true
|
||||||
|
|
||||||
react-refresh@0.17.0:
|
react-refresh@0.17.0:
|
||||||
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -1106,6 +1150,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==}
|
resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
redux-thunk@3.1.0:
|
||||||
|
resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
|
||||||
|
peerDependencies:
|
||||||
|
redux: ^5.0.0
|
||||||
|
|
||||||
|
redux@5.0.1:
|
||||||
|
resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
|
||||||
|
|
||||||
|
reselect@5.1.1:
|
||||||
|
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1:
|
resize-observer-polyfill@1.5.1:
|
||||||
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
|
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
|
||||||
|
|
||||||
@@ -1200,6 +1255,11 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
use-sync-external-store@1.5.0:
|
||||||
|
resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
vite@7.1.2:
|
vite@7.1.2:
|
||||||
resolution: {integrity: sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==}
|
resolution: {integrity: sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==}
|
||||||
engines: {node: ^20.19.0 || >=22.12.0}
|
engines: {node: ^20.19.0 || >=22.12.0}
|
||||||
@@ -1557,6 +1617,18 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
'@reduxjs/toolkit@2.8.2(react-redux@9.2.0(@types/react@19.1.10)(react@19.1.1)(redux@5.0.1))(react@19.1.1)':
|
||||||
|
dependencies:
|
||||||
|
'@standard-schema/spec': 1.0.0
|
||||||
|
'@standard-schema/utils': 0.3.0
|
||||||
|
immer: 10.1.1
|
||||||
|
redux: 5.0.1
|
||||||
|
redux-thunk: 3.1.0(redux@5.0.1)
|
||||||
|
reselect: 5.1.1
|
||||||
|
optionalDependencies:
|
||||||
|
react: 19.1.1
|
||||||
|
react-redux: 9.2.0(@types/react@19.1.10)(react@19.1.1)(redux@5.0.1)
|
||||||
|
|
||||||
'@rolldown/pluginutils@1.0.0-beta.27': {}
|
'@rolldown/pluginutils@1.0.0-beta.27': {}
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.46.2':
|
'@rollup/rollup-android-arm-eabi@4.46.2':
|
||||||
@@ -1619,6 +1691,10 @@ snapshots:
|
|||||||
'@rollup/rollup-win32-x64-msvc@4.46.2':
|
'@rollup/rollup-win32-x64-msvc@4.46.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@standard-schema/spec@1.0.0': {}
|
||||||
|
|
||||||
|
'@standard-schema/utils@0.3.0': {}
|
||||||
|
|
||||||
'@types/babel__core@7.20.5':
|
'@types/babel__core@7.20.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.28.0
|
'@babel/parser': 7.28.0
|
||||||
@@ -1652,6 +1728,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
|
'@types/use-sync-external-store@0.0.6': {}
|
||||||
|
|
||||||
'@vitejs/plugin-react@4.7.0(vite@7.1.2)':
|
'@vitejs/plugin-react@4.7.0(vite@7.1.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.0
|
'@babel/core': 7.28.0
|
||||||
@@ -2025,6 +2103,8 @@ snapshots:
|
|||||||
|
|
||||||
ignore@5.3.2: {}
|
ignore@5.3.2: {}
|
||||||
|
|
||||||
|
immer@10.1.1: {}
|
||||||
|
|
||||||
import-fresh@3.3.1:
|
import-fresh@3.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
parent-module: 1.0.1
|
parent-module: 1.0.1
|
||||||
@@ -2194,6 +2274,15 @@ snapshots:
|
|||||||
|
|
||||||
react-is@18.3.1: {}
|
react-is@18.3.1: {}
|
||||||
|
|
||||||
|
react-redux@9.2.0(@types/react@19.1.10)(react@19.1.1)(redux@5.0.1):
|
||||||
|
dependencies:
|
||||||
|
'@types/use-sync-external-store': 0.0.6
|
||||||
|
react: 19.1.1
|
||||||
|
use-sync-external-store: 1.5.0(react@19.1.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.10
|
||||||
|
redux: 5.0.1
|
||||||
|
|
||||||
react-refresh@0.17.0: {}
|
react-refresh@0.17.0: {}
|
||||||
|
|
||||||
react-router-dom@7.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
|
react-router-dom@7.8.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
|
||||||
@@ -2221,6 +2310,14 @@ snapshots:
|
|||||||
|
|
||||||
react@19.1.1: {}
|
react@19.1.1: {}
|
||||||
|
|
||||||
|
redux-thunk@3.1.0(redux@5.0.1):
|
||||||
|
dependencies:
|
||||||
|
redux: 5.0.1
|
||||||
|
|
||||||
|
redux@5.0.1: {}
|
||||||
|
|
||||||
|
reselect@5.1.1: {}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1: {}
|
resize-observer-polyfill@1.5.1: {}
|
||||||
|
|
||||||
resolve-from@4.0.0: {}
|
resolve-from@4.0.0: {}
|
||||||
@@ -2319,6 +2416,10 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.1.10
|
'@types/react': 19.1.10
|
||||||
|
|
||||||
|
use-sync-external-store@1.5.0(react@19.1.1):
|
||||||
|
dependencies:
|
||||||
|
react: 19.1.1
|
||||||
|
|
||||||
vite@7.1.2:
|
vite@7.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.9
|
esbuild: 0.25.9
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #f2f3f5;
|
background-color: #f2f3f5;
|
||||||
|
|
||||||
.app-layout-skeleton {
|
.app-layout-spin {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
box-sizing: border-box;
|
position: relative;
|
||||||
padding: 100px;
|
|
||||||
background-color: aqua;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 主内容区域 */
|
/* 主内容区域 */
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState } from "react";
|
||||||
import { Skeleton } from "@arco-design/web-react";
|
import { Spin } from "@arco-design/web-react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import Sidebar from "../Sidebar";
|
import Sidebar from "../Sidebar";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
const Layout = ({ children }) => {
|
const Layout = ({ children }) => {
|
||||||
|
const loading = useSelector((state) => state.loading.value);
|
||||||
const [isCollapsed, setIsCollapsed] = useState(true);
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app-layout">
|
<div className="app-layout">
|
||||||
<Sidebar isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} />
|
<Sidebar isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} />
|
||||||
<Skeleton loading={false} animation className="app-layout-skeleton">
|
<Spin loading={loading} size={40} className="app-layout-spin">
|
||||||
<main className="main-content">{children}</main>
|
<main className="main-content">{children}</main>
|
||||||
</Skeleton>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import { StrictMode } from "react";
|
import { StrictMode } from "react";
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
|
import { Provider } from "react-redux";
|
||||||
|
import store from "./store";
|
||||||
import App from "./App.jsx";
|
import App from "./App.jsx";
|
||||||
|
|
||||||
createRoot(document.getElementById("root")).render(
|
createRoot(document.getElementById("root")).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
|
<Provider store={store}>
|
||||||
<App />
|
<App />
|
||||||
|
</Provider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { jobAPI, interviewAPI, studentAPI } from "@/services/api";
|
import { jobAPI, interviewAPI, studentAPI } from "@/services/api";
|
||||||
import { mapJobList, mapInterviewList } from "@/utils/dataMapper";
|
import { mapJobList, mapInterviewList } from "@/utils/dataMapper";
|
||||||
import JobList from "./components/JobList";
|
import JobList from "./components/JobList";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { setLoadingTrue, setLoadingFalse } from "@/store/slices/loadingSlice";
|
||||||
|
// 从Redux store中获取loading状态
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
const CompanyJobsPage = () => {
|
const CompanyJobsPage = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const [jobs, setJobs] = useState([]);
|
const [jobs, setJobs] = useState([]);
|
||||||
const [interviews, setInterviews] = useState([]);
|
const [interviews, setInterviews] = useState([]);
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [isExpand, setIsExpand] = useState(false); // 是否展开
|
const [isExpand, setIsExpand] = useState(false); // 是否展开
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
dispatch(setLoadingTrue());
|
||||||
|
|
||||||
// Get current user's student ID from API
|
// Get current user's student ID from API
|
||||||
let studentId = null;
|
let studentId = null;
|
||||||
try {
|
try {
|
||||||
@@ -59,12 +57,14 @@ const CompanyJobsPage = () => {
|
|||||||
setJobs(mappedJobs);
|
setJobs(mappedJobs);
|
||||||
setInterviews(mappedInterviews);
|
setInterviews(mappedInterviews);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
dispatch(setLoadingFalse());
|
||||||
|
|
||||||
console.error("Failed to fetch data:", error);
|
console.error("Failed to fetch data:", error);
|
||||||
// Fallback to empty data
|
// Fallback to empty data
|
||||||
setJobs([]);
|
setJobs([]);
|
||||||
setInterviews([]);
|
setInterviews([]);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
dispatch(setLoadingFalse());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -72,18 +72,9 @@ const CompanyJobsPage = () => {
|
|||||||
navigate("/company-jobs-list");
|
navigate("/company-jobs-list");
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
useEffect(() => {
|
||||||
return (
|
fetchData();
|
||||||
<div className="company-jobs-page-wrapper">
|
}, []);
|
||||||
<div
|
|
||||||
className="company-jobs-page"
|
|
||||||
style={{ justifyContent: "center", alignItems: "center" }}
|
|
||||||
>
|
|
||||||
<p>加载中...</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="company-jobs-page-wrapper">
|
<div className="company-jobs-page-wrapper">
|
||||||
|
|||||||
10
src/store/index.js
Normal file
10
src/store/index.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
|
import loadingReducer from './slices/loadingSlice';
|
||||||
|
import userReducer from './slices/userSlice'; // 导入新的用户reducer
|
||||||
|
|
||||||
|
export default configureStore({
|
||||||
|
reducer: {
|
||||||
|
loading: loadingReducer,
|
||||||
|
user: userReducer // 添加用户reducer到store
|
||||||
|
}
|
||||||
|
});
|
||||||
25
src/store/slices/loadingSlice.js
Normal file
25
src/store/slices/loadingSlice.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
// 创建slice
|
||||||
|
const loadingSlice = createSlice({
|
||||||
|
name: "loading",
|
||||||
|
initialState: {
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
// 设置loading状态为true
|
||||||
|
setLoadingTrue: (state) => {
|
||||||
|
state.value = true;
|
||||||
|
},
|
||||||
|
// 设置loading状态为false
|
||||||
|
setLoadingFalse: (state) => {
|
||||||
|
state.value = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 导出actions
|
||||||
|
export const { setLoadingTrue, setLoadingFalse } = loadingSlice.actions;
|
||||||
|
|
||||||
|
// 导出reducer
|
||||||
|
export default loadingSlice.reducer;
|
||||||
38
src/store/slices/userSlice.js
Normal file
38
src/store/slices/userSlice.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
// 定义初始状态
|
||||||
|
const initialState = {
|
||||||
|
userInfo: null, // 用户信息初始为null
|
||||||
|
isLoggedIn: false // 登录状态初始为false
|
||||||
|
};
|
||||||
|
|
||||||
|
const userSlice = createSlice({
|
||||||
|
name: 'user',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
// 设置用户信息
|
||||||
|
setUserInfo: (state, action) => {
|
||||||
|
state.userInfo = action.payload;
|
||||||
|
state.isLoggedIn = true;
|
||||||
|
},
|
||||||
|
// 清除用户信息
|
||||||
|
clearUserInfo: (state) => {
|
||||||
|
state.userInfo = null;
|
||||||
|
state.isLoggedIn = false;
|
||||||
|
},
|
||||||
|
// 更新用户信息的部分字段
|
||||||
|
updateUserInfo: (state, action) => {
|
||||||
|
if (state.userInfo) {
|
||||||
|
state.userInfo = {
|
||||||
|
...state.userInfo,
|
||||||
|
...action.payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 导出actions
|
||||||
|
export const { setUserInfo, clearUserInfo, updateUserInfo } = userSlice.actions;
|
||||||
|
|
||||||
|
export default userSlice.reducer;
|
||||||
@@ -22,7 +22,7 @@ export default defineConfig({
|
|||||||
// 分割第三方库
|
// 分割第三方库
|
||||||
vendor: ["react", "react-dom", "react-router-dom"],
|
vendor: ["react", "react-dom", "react-router-dom"],
|
||||||
// 分割大型组件
|
// 分割大型组件
|
||||||
components: ["@/components/CoursesVideoPlayer"],
|
components: [],
|
||||||
// 分割工具函数
|
// 分割工具函数
|
||||||
utils: ["@/utils/LinePathGenerator", "@/utils/request"],
|
utils: ["@/utils/LinePathGenerator", "@/utils/request"],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user