feat: 🎸 新增了一个全局加载组件

This commit is contained in:
2025-08-20 11:43:10 +08:00
parent 14f722263b
commit 95a099f613
10 changed files with 207 additions and 35 deletions

View File

@@ -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;
}
}
/* 主内容区域 */

View File

@@ -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>
);
};

View File

@@ -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>
);

View File

@@ -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
View 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
}
});

View 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;

View 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;