feat: 🎸 新增了redux用于全局自动loading

This commit is contained in:
2025-08-20 23:56:04 +08:00
parent 9895101fde
commit a493f2773c
11 changed files with 477 additions and 150 deletions

View File

@@ -9,7 +9,9 @@ import "./index.css";
const Layout = ({ children }) => { const Layout = ({ children }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [isCollapsed, setIsCollapsed] = useState(true); const [isCollapsed, setIsCollapsed] = useState(true);
const loading = useSelector((state) => state.loading.value); const globalLoading = useSelector(
(state) => state?.loading?.effect?.globalLoading
);
const studentInfo = useSelector((state) => state.student.studentInfo); const studentInfo = useSelector((state) => state.student.studentInfo);
const queryLoginStudentInfo = async () => { const queryLoginStudentInfo = async () => {
@@ -27,7 +29,7 @@ const Layout = ({ children }) => {
return ( return (
<div className="app-layout"> <div className="app-layout">
<Sidebar isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} /> <Sidebar isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} />
<Spin block loading={loading} size={40} className="app-layout-spin"> <Spin block loading={globalLoading} size={40} className="app-layout-spin">
<main className="main-content">{children}</main> <main className="main-content">{children}</main>
</Spin> </Spin>
</div> </div>

View File

@@ -57,7 +57,8 @@ const CompanyJobsPage = () => {
pageSize: PAGE_SIZE, pageSize: PAGE_SIZE,
isActive: true, isActive: true,
}); });
if (res.success) {
if (res?.success) {
const mappedJobs = mapJobList(res.data); const mappedJobs = mapJobList(res.data);
setJobs((prevList) => { setJobs((prevList) => {
const newList = [...prevList, ...mappedJobs]; const newList = [...prevList, ...mappedJobs];

View File

@@ -1,211 +1,464 @@
import request from '@/utils/request'; import request from "@/utils/request";
// Student API // Student API
export const studentAPI = { export const studentAPI = {
// Get current logged-in student // Get current logged-in student
getCurrentStudent: () => request.get('/api/students/me'), getCurrentStudent: async () =>
request({
url: "/api/students/me",
method: "GET",
}),
// Get student list // Get student list
getList: (params) => request.get('/api/students', { params }), getList: async (params) =>
request({
url: "/api/students",
method: "GET",
params,
}),
// Get student detail // Get student detail
getDetail: (id) => request.get(`/api/students/${id}`), getDetail: async (id) =>
request({
url: `/api/students/${id}`,
method: "GET",
}),
// Create student // Create student
create: (data) => request.post('/api/students', data), create: async (data) =>
request({
url: "/api/students",
method: "POST",
data,
}),
// Update student // Update student
update: (id, data) => request.put(`/api/students/${id}`, data), update: async (id, data) =>
request({
url: `/api/students/${id}`,
method: "PUT",
data,
}),
// Get student progress // Get student progress
getProgress: (id) => request.get(`/api/students/${id}/progress`), getProgress: async (id) =>
request({
url: `/api/students/${id}/progress`,
method: "GET",
}),
}; };
// Course API // Course API
export const courseAPI = { export const courseAPI = {
// Get course list // Get course list
getList: (params) => request.get('/api/courses', { params }), getList: async (params) =>
request({
url: "/api/courses",
method: "GET",
params,
}),
// Get course detail // Get course detail
getDetail: (id) => request.get(`/api/courses/${id}`), getDetail: async (id) =>
request({
url: `/api/courses/${id}`,
method: "GET",
}),
// Create course // Create course
create: (data) => request.post('/api/courses', data), create: async (data) =>
request({
url: "/api/courses",
method: "POST",
data,
}),
// Update course // Update course
update: (id, data) => request.put(`/api/courses/${id}`, data), update: async (id, data) =>
request({
url: `/api/courses/${id}`,
method: "PUT",
data,
}),
// Enroll student in course // Enroll student in course
enroll: (courseId, studentId) => enroll: async (courseId, studentId) =>
request.post(`/api/courses/${courseId}/enroll`, { studentId }), request({
url: `/api/courses/${courseId}/enroll`,
method: "POST",
data: { studentId },
}),
// Update enrollment progress // Update enrollment progress
updateEnrollment: (courseId, enrollmentId, data) => updateEnrollment: async (courseId, enrollmentId, data) =>
request.put(`/api/courses/${courseId}/enrollment/${enrollmentId}`, data), request({
url: `/api/courses/${courseId}/enrollment/${enrollmentId}`,
method: "PUT",
data,
}),
// Get course students // Get course students
getStudents: (id) => request.get(`/api/courses/${id}/students`), getStudents: async (id) =>
request({
url: `/api/courses/${id}/students`,
method: "GET",
}),
}; };
// Job API // Job API
export const jobAPI = { export const jobAPI = {
// Get job list // Get job list
getList: (params) => request.get('/api/jobs', { params }), getList: async (params) =>
request({
url: "/api/jobs",
method: "GET",
params,
}),
// Get job detail // Get job detail
getDetail: (id) => request.get(`/api/jobs/${id}`), getDetail: async (id) =>
request({
url: `/api/jobs/${id}`,
method: "GET",
}),
// Create job // Create job
create: (data) => request.post('/api/jobs', data), create: async (data) =>
request({
url: "/api/jobs",
method: "POST",
data,
}),
// Update job // Update job
update: (id, data) => request.put(`/api/jobs/${id}`, data), update: async (id, data) =>
request({
url: `/api/jobs/${id}`,
method: "PUT",
data,
}),
// Get recommended jobs for student // Get recommended jobs for student
getRecommended: (studentId) => request.get(`/api/jobs/recommend/${studentId}`), getRecommended: async (studentId) =>
request({
url: `/api/jobs/recommend/${studentId}`,
method: "GET",
}),
}; };
// Company API // Company API
export const companyAPI = { export const companyAPI = {
// Get company list // Get company list
getList: (params) => request.get('/api/companies', { params }), getList: async (params) =>
request({
url: "/api/companies",
method: "GET",
params,
}),
// Get company detail // Get company detail
getDetail: (id) => request.get(`/api/companies/${id}`), getDetail: async (id) =>
request({
url: `/api/companies/${id}`,
method: "GET",
}),
// Create company // Create company
create: (data) => request.post('/api/companies', data), create: async (data) =>
request({
url: "/api/companies",
method: "POST",
data,
}),
// Update company // Update company
update: (id, data) => request.put(`/api/companies/${id}`, data), update: async (id, data) =>
request({
url: `/api/companies/${id}`,
method: "PUT",
data,
}),
// Get company jobs // Get company jobs
getJobs: (id) => request.get(`/api/companies/${id}/jobs`), getJobs: async (id) =>
request({
url: `/api/companies/${id}/jobs`,
method: "GET",
}),
}; };
// Resume API // Resume API
export const resumeAPI = { export const resumeAPI = {
// Get resume list // Get resume list
getList: (params) => request.get('/api/resumes', { params }), getList: async (params) =>
request({
url: "/api/resumes",
method: "GET",
params,
}),
// Get resume detail // Get resume detail
getDetail: (id) => request.get(`/api/resumes/${id}`), getDetail: async (id) =>
request({
url: `/api/resumes/${id}`,
method: "GET",
}),
// Create resume // Create resume
create: (data) => request.post('/api/resumes', data), create: async (data) =>
request({
url: "/api/resumes",
method: "POST",
data,
}),
// Update resume // Update resume
update: (id, data) => request.put(`/api/resumes/${id}`, data), update: async (id, data) =>
request({
url: `/api/resumes/${id}`,
method: "PUT",
data,
}),
// Delete resume // Delete resume
delete: (id) => request.delete(`/api/resumes/${id}`), delete: async (id) =>
request({
url: `/api/resumes/${id}`,
method: "DELETE",
}),
// Get student's active resume // Get student's active resume
getStudentActive: (studentId) => getStudentActive: async (studentId) =>
request.get(`/api/resumes/student/${studentId}/active`), request({
url: `/api/resumes/student/${studentId}/active`,
method: "GET",
}),
}; };
// Interview API // Interview API
export const interviewAPI = { export const interviewAPI = {
// Get interview list // Get interview list
getList: (params) => request.get('/api/interviews', { params }), getList: async (params) =>
request({
url: "/api/interviews",
method: "GET",
params,
}),
// Get interview detail // Get interview detail
getDetail: (id) => request.get(`/api/interviews/${id}`), getDetail: async (id) =>
request({
url: `/api/interviews/${id}`,
method: "GET",
}),
// Schedule interview // Schedule interview
schedule: (data) => request.post('/api/interviews', data), schedule: async (data) =>
request({
url: "/api/interviews",
method: "POST",
data,
}),
// Update interview // Update interview
update: (id, data) => request.put(`/api/interviews/${id}`, data), update: async (id, data) =>
request({
url: `/api/interviews/${id}`,
method: "PUT",
data,
}),
// Cancel interview // Cancel interview
cancel: (id, reason) => cancel: async (id, reason) =>
request.post(`/api/interviews/${id}/cancel`, { reason }), request({
url: `/api/interviews/${id}/cancel`,
method: "POST",
data: { reason },
}),
// Submit feedback // Submit feedback
submitFeedback: (id, data) => submitFeedback: async (id, data) =>
request.post(`/api/interviews/${id}/feedback`, data), request({
url: `/api/interviews/${id}/feedback`,
method: "POST",
data,
}),
// Get student interview history // Get student interview history
getStudentHistory: (studentId) => getStudentHistory: async (studentId) =>
request.get(`/api/interviews/student/${studentId}/history`), request({
url: `/api/interviews/student/${studentId}/history`,
method: "GET",
}),
}; };
// Class API // Class API
export const classAPI = { export const classAPI = {
// Get class list // Get class list
getList: (params) => request.get('/api/classes', { params }), getList: async (params) =>
request({
url: "/api/classes",
method: "GET",
params,
}),
// Get class detail // Get class detail
getDetail: (id) => request.get(`/api/classes/${id}`), getDetail: async (id) =>
request({
url: `/api/classes/${id}`,
method: "GET",
}),
// Create class // Create class
create: (data) => request.post('/api/classes', data), create: async (data) =>
request({
url: "/api/classes",
method: "POST",
data,
}),
// Update class // Update class
update: (id, data) => request.put(`/api/classes/${id}`, data), update: async (id, data) =>
request({
url: `/api/classes/${id}`,
method: "PUT",
data,
}),
// Get class students // Get class students
getStudents: (id) => request.get(`/api/classes/${id}/students`), getStudents: async (id) =>
request({
url: `/api/classes/${id}/students`,
method: "GET",
}),
// Add student to class // Add student to class
addStudent: (classId, studentId) => addStudent: async (classId, studentId) =>
request.post(`/api/classes/${classId}/students`, { studentId }), request({
url: `/api/classes/${classId}/students`,
method: "POST",
data: { studentId },
}),
// Remove student from class // Remove student from class
removeStudent: (classId, studentId) => removeStudent: async (classId, studentId) =>
request.delete(`/api/classes/${classId}/students/${studentId}`), request({
url: `/api/classes/${classId}/students/${studentId}`,
method: "DELETE",
}),
// Get class statistics // Get class statistics
getStats: (id) => request.get(`/api/classes/${id}/stats`), getStats: async (id) =>
request({
url: `/api/classes/${id}/stats`,
method: "GET",
}),
}; };
// Learning Stage API // Learning Stage API
export const stageAPI = { export const stageAPI = {
// Get all stages // Get all stages
getList: () => request.get('/api/stages'), getList: async () =>
request({
url: "/api/stages",
method: "GET",
}),
// Get stage detail // Get stage detail
getDetail: (id) => request.get(`/api/stages/${id}`), getDetail: async (id) =>
request({
url: `/api/stages/${id}`,
method: "GET",
}),
// Create stage // Create stage
create: (data) => request.post('/api/stages', data), create: async (data) =>
request({
url: "/api/stages",
method: "POST",
data,
}),
// Update stage // Update stage
update: (id, data) => request.put(`/api/stages/${id}`, data), update: async (id, data) =>
request({
url: `/api/stages/${id}`,
method: "PUT",
data,
}),
// Delete stage // Delete stage
delete: (id) => request.delete(`/api/stages/${id}`), delete: async (id) =>
request({
url: `/api/stages/${id}`,
method: "DELETE",
}),
// Get stage courses // Get stage courses
getCourses: (id) => request.get(`/api/stages/${id}/courses`), getCourses: async (id) =>
request({
url: `/api/stages/${id}/courses`,
method: "GET",
}),
// Get stage students // Get stage students
getStudents: (id) => request.get(`/api/stages/${id}/students`), getStudents: async (id) =>
request({
url: `/api/stages/${id}/students`,
method: "GET",
}),
// Advance student to next stage // Advance student to next stage
advanceStudent: (stageId, studentId) => advanceStudent: async (stageId, studentId) =>
request.post(`/api/stages/${stageId}/advance/${studentId}`), request({
url: `/api/stages/${stageId}/advance/${studentId}`,
method: "POST",
}),
}; };
// Auth API // Auth API
export const authAPI = { export const authAPI = {
// Login // Login
login: (data) => request.post('/api/auth/login', data), login: async (data) =>
request({
url: "/api/auth/login",
method: "POST",
data,
}),
// Register // Register
register: (data) => request.post('/api/auth/register', data), register: async (data) =>
request({
url: "/api/auth/register",
method: "POST",
data,
}),
// Logout // Logout
logout: () => request.post('/api/auth/logout'), logout: async () =>
request({
url: "/api/auth/logout",
method: "POST",
}),
// Get current user // Get current user
getCurrentUser: () => request.get('/api/auth/me'), getCurrentUser: async () =>
request({
url: "/api/auth/me",
method: "GET",
}),
}; };
// Health Check // Health Check
export const healthAPI = { export const healthAPI = {
check: () => request.get('/health'), check: async () =>
checkDB: () => request.get('/health/db'), request({
url: "/health",
method: "GET",
}),
checkDB: async () =>
request({
url: "/health/db",
method: "GET",
}),
}; };

View File

@@ -2,9 +2,17 @@ import request from "@/utils/request";
// 获取企业内推岗位 // 获取企业内推岗位
export async function getJobsList(params) { export async function getJobsList(params) {
return request.get("/api/jobs", { params }); return request({
url: `/api/jobs`,
method: "GET",
params,
});
} }
// 获取企业内推岗位面试 // 获取企业内推岗位面试
export async function getInterviewsList(params) { export async function getInterviewsList(params) {
return request.get("/api/interviews", { params }); return request({
url: `/api/interviews`,
method: "GET",
params,
});
} }

View File

@@ -1,14 +1,23 @@
import request from "@/utils/request"; import request from "@/utils/request";
// 获取主页信息 // 获取主页信息
export async function getDashboardStatistics(studentId) { export async function getDashboardStatistics(studentId) {
return request.get(`/api/dashboard/stats/${studentId}`); return request({
url: `/api/dashboard/stats/${studentId}`,
method: "GET",
});
} }
// 获取学习进度 // 获取学习进度
export async function getLearningProgressSummary(studentId) { export async function getLearningProgressSummary(studentId) {
return request.get(`/api/dashboard/learning-summary/${studentId}`); return request({
url: `/api/dashboard/learning-summary/${studentId}`,
method: "GET",
});
} }
// 获取班级排名 // 获取班级排名
export async function getClassRanking(classId) { export async function getClassRanking(classId) {
return request.get(`/api/rankings/class/${classId}`); return request({
url: `/api/rankings/class/${classId}`,
method: "GET",
});
} }

View File

@@ -2,5 +2,9 @@ import request from "@/utils/request";
// 获取当前登录学生信息 // 获取当前登录学生信息
export async function getLoginStudentInfo() { export async function getLoginStudentInfo() {
return request.get("/api/students/me"); return request({
url: `/api/students/me`,
method: "GET",
namespace: "globalLoading",
});
} }

View File

@@ -1,3 +1,4 @@
// 此处是已经调试的api
import { import {
getDashboardStatistics, getDashboardStatistics,
getLearningProgressSummary, getLearningProgressSummary,

View File

@@ -2,5 +2,8 @@ import request from "@/utils/request";
// 获取当前登录学生学习进度 // 获取当前登录学生学习进度
export async function getLoginStudentProgress(id) { export async function getLoginStudentProgress(id) {
return request.get(`/api/students/${id}/progress`); return request({
url: `/api/students/${id}/progress`,
method: "GET",
});
} }

View File

@@ -1,5 +1,9 @@
import request from "@/utils/request"; import request from "@/utils/request";
// 获取项目列表 // 获取项目列表
export async function getProjectsList(params) { export async function getProjectsList(params) {
return request.get(`/api/projects`, { params }); return request({
url: `/api/projects`,
method: "GET",
params,
});
} }

View File

@@ -1,25 +1,31 @@
// 导入 Redux Toolkit 的 createSlice
import { createSlice } from "@reduxjs/toolkit"; import { createSlice } from "@reduxjs/toolkit";
// 创建slice // 定义初始状态
const initialState = {
effect: {}, // 全局加载状态对象
};
// 创建 loading slice
const loadingSlice = createSlice({ const loadingSlice = createSlice({
name: "loading", name: "loading", // slice 名称
initialState: { initialState,
value: false,
},
reducers: { reducers: {
// 设置loading状态为true // 显示全局加载状态
setLoadingTrue: (state) => { showGlobalLoading: (state, action) => {
state.value = true; const { namespace } = action.payload;
state.effect[namespace] = true;
}, },
// 设置loading状态为false // 隐藏全局加载状态
setLoadingFalse: (state) => { hideGlobalLoading: (state, action) => {
state.value = false; const { namespace } = action.payload;
state.effect[namespace] = false;
}, },
}, },
}); });
// 导出actions // 导出 action creators
export const { setLoadingTrue, setLoadingFalse } = loadingSlice.actions; export const { showGlobalLoading, hideGlobalLoading } = loadingSlice.actions;
// 导出 reducer // 导出 reducer
export default loadingSlice.reducer; export default loadingSlice.reducer;

View File

@@ -1,9 +1,24 @@
// 引入axios // 引入axios
import axios from "axios"; import axios from "axios";
import store from "@/store/index";
import {
showGlobalLoading,
hideGlobalLoading,
} from "@/store/slices/loadingSlice";
const baseURL = import.meta.env.VITE_API_BASE_URL || "http://localhost:3000";
// 全局加载状态loading基于redux
const handleGlobalLoading = (namespace, type) => {
if (!namespace) return;
store.dispatch(
type === "show"
? showGlobalLoading({ namespace })
: hideGlobalLoading({ namespace })
);
};
// 创建axios实例 // 创建axios实例
const service = axios.create({ const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:3000", // 基础URL baseURL, // 基础URL
timeout: 10000, // 请求超时时间 timeout: 10000, // 请求超时时间
headers: { headers: {
"Content-Type": "application/json;charset=utf-8", "Content-Type": "application/json;charset=utf-8",
@@ -11,7 +26,7 @@ const service = axios.create({
}); });
// 请求拦截器 // 请求拦截器
service.interceptors.request.use( axiosInstance.interceptors.request.use(
(config) => { (config) => {
// 开发阶段使用固定的 x-user-id // 开发阶段使用固定的 x-user-id
// 这个ID对应种子数据中的开发默认用户 // 这个ID对应种子数据中的开发默认用户
@@ -30,7 +45,7 @@ service.interceptors.request.use(
); );
// 响应拦截器 // 响应拦截器
service.interceptors.response.use( axiosInstance.interceptors.response.use(
(response) => { (response) => {
// 处理响应数据 // 处理响应数据
const res = response.data; const res = response.data;
@@ -57,10 +72,31 @@ service.interceptors.response.use(
(error) => { (error) => {
// 处理响应错误 // 处理响应错误
console.error("请求错误:", error); console.error("请求错误:", error);
const message = error.response?.data?.message || error.message || "网络错误"; const message =
error.response?.data?.message || error.message || "网络错误";
return Promise.reject(new Error(message)); return Promise.reject(new Error(message));
} }
); );
// 导出请求方法 // 导出请求方法
export default service; export default function request({
url,
apiUrl,
namespace,
method = "get",
data,
params,
headers = {},
}) {
handleGlobalLoading(namespace, "show");
// 返回Promise对象
return axiosInstance({
method,
url: `${apiUrl ? apiUrl : baseURL}${url}`,
data,
params,
headers,
}).finally(() => {
handleGlobalLoading(namespace, "hide");
});
}