feat: 🎸 新增了一个全局加载组件
This commit is contained in:
@@ -5,11 +5,9 @@
|
||||
width: 100%;
|
||||
background-color: #f2f3f5;
|
||||
|
||||
.app-layout-skeleton {
|
||||
.app-layout-spin {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
padding: 100px;
|
||||
background-color: aqua;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
/* 主内容区域 */
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Skeleton } from "@arco-design/web-react";
|
||||
import { useState } from "react";
|
||||
import { Spin } from "@arco-design/web-react";
|
||||
import { useSelector } from "react-redux";
|
||||
import Sidebar from "../Sidebar";
|
||||
import "./index.css";
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
const loading = useSelector((state) => state.loading.value);
|
||||
const [isCollapsed, setIsCollapsed] = useState(true);
|
||||
|
||||
return (
|
||||
<div className="app-layout">
|
||||
<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>
|
||||
</Skeleton>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Provider } from "react-redux";
|
||||
import store from "./store";
|
||||
import App from "./App.jsx";
|
||||
|
||||
createRoot(document.getElementById("root")).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { jobAPI, interviewAPI, studentAPI } from "@/services/api";
|
||||
import { mapJobList, mapInterviewList } from "@/utils/dataMapper";
|
||||
import JobList from "./components/JobList";
|
||||
|
||||
import { useDispatch } from "react-redux";
|
||||
import { setLoadingTrue, setLoadingFalse } from "@/store/slices/loadingSlice";
|
||||
// 从Redux store中获取loading状态
|
||||
import "./index.css";
|
||||
|
||||
const CompanyJobsPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [jobs, setJobs] = useState([]);
|
||||
const [interviews, setInterviews] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isExpand, setIsExpand] = useState(false); // 是否展开
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
dispatch(setLoadingTrue());
|
||||
// Get current user's student ID from API
|
||||
let studentId = null;
|
||||
try {
|
||||
@@ -59,12 +57,14 @@ const CompanyJobsPage = () => {
|
||||
setJobs(mappedJobs);
|
||||
setInterviews(mappedInterviews);
|
||||
} catch (error) {
|
||||
dispatch(setLoadingFalse());
|
||||
|
||||
console.error("Failed to fetch data:", error);
|
||||
// Fallback to empty data
|
||||
setJobs([]);
|
||||
setInterviews([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
dispatch(setLoadingFalse());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,18 +72,9 @@ const CompanyJobsPage = () => {
|
||||
navigate("/company-jobs-list");
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="company-jobs-page-wrapper">
|
||||
<div
|
||||
className="company-jobs-page"
|
||||
style={{ justifyContent: "center", alignItems: "center" }}
|
||||
>
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<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;
|
||||
Reference in New Issue
Block a user