perf: speed up student navigation loading

dev-QQq^2
chenyuan 5 days ago
parent d9e0239720
commit d604db38ba

@ -1,8 +1,11 @@
import request from "@/utils/request";
import { getUserInfo } from "@/utils/auth";
// 学生页面和全局“补充步骤”导航会在同一轮路由渲染中读取同一任务配置。
// 仅合并进行中的请求:教师保存后下一次读取仍会获得最新配置,不引入陈旧缓存。
const pendingTaskRequests = new Map();
const pendingStudentTaskListRequests = new Map();
const STUDENT_TASK_NAVIGATION_CACHE_PREFIX = "student-training-task-navigation:v1:";
function notifyStudentTaskConfigLoading(taskKey, loading) {
if (typeof window === "undefined") return;
@ -17,6 +20,51 @@ export function listTrainingTasks(params) {
});
}
function getStudentTaskNavigationCacheKey() {
try {
const userInfo = JSON.parse(getUserInfo() || "{}");
const userId = userInfo.userId || userInfo.user_id || userInfo.username || userInfo.userName;
return userId ? `${STUDENT_TASK_NAVIGATION_CACHE_PREFIX}${userId}` : "";
} catch (error) {
return "";
}
}
export function getCachedStudentTrainingTasks() {
const cacheKey = getStudentTaskNavigationCacheKey();
if (!cacheKey || typeof window === "undefined") return [];
try {
const cached = JSON.parse(window.sessionStorage.getItem(cacheKey) || "[]");
return Array.isArray(cached) ? cached : [];
} catch (error) {
return [];
}
}
/**
* The navigation and top bar both need the same enabled task list. Reuse one
* in-flight request and retain the last successful response for immediate menu rendering.
*/
export function loadStudentTrainingTasks() {
const cacheKey = getStudentTaskNavigationCacheKey() || "anonymous";
if (pendingStudentTaskListRequests.has(cacheKey)) {
return pendingStudentTaskListRequests.get(cacheKey);
}
const requestPromise = listTrainingTasks({ enabledOnly: true }).then((res) => {
const tasks = Array.isArray(res?.data) ? res.data : [];
if (cacheKey !== "anonymous" && typeof window !== "undefined") {
window.sessionStorage.setItem(cacheKey, JSON.stringify(tasks));
}
return { ...res, data: tasks };
});
pendingStudentTaskListRequests.set(cacheKey, requestPromise);
requestPromise.then(
() => pendingStudentTaskListRequests.delete(cacheKey),
() => pendingStudentTaskListRequests.delete(cacheKey)
);
return requestPromise;
}
export function getTrainingTaskByKey(taskKey) {
const normalizedTaskKey = String(taskKey || "").trim();
if (pendingTaskRequests.has(normalizedTaskKey)) {

@ -81,7 +81,7 @@ import useAppStore from "@/store/modules/app";
import useUserStore from "@/store/modules/user";
import useSettingsStore from "@/store/modules/settings";
import * as indexApi from "@/api/teacher";
import { listTrainingTasks } from "@/api/trainingTask";
import { getCachedStudentTrainingTasks, loadStudentTrainingTasks } from "@/api/trainingTask";
import { getStudentDemoSession, isStudentDemo } from "@/utils/studentDemo";
import { getComprehensiveTopTask } from "@/utils/studentTrainingNavigation";
const { proxy } = getCurrentInstance();
@ -289,11 +289,17 @@ async function loadStudentTopTask() {
studentTopTask.value = null;
return;
}
const cachedTasks = getCachedStudentTrainingTasks();
if (cachedTasks.length) {
studentTopTask.value = getComprehensiveTopTask(cachedTasks);
}
try {
const res = await listTrainingTasks({ enabledOnly: true });
const res = await loadStudentTrainingTasks();
studentTopTask.value = getComprehensiveTopTask(res.data || []);
} catch (error) {
studentTopTask.value = null;
if (!cachedTasks.length) {
studentTopTask.value = null;
}
}
}
//

@ -62,7 +62,7 @@ import useSettingsStore from "@/store/modules/settings";
import usePermissionStore from "@/store/modules/permission";
import { constantRoutes, dynamicRoutes, teacherRoutes, platformAdminRoutes, schoolAdminRoutes } from "@/router/index.js";
import useUserStore from "@/store/modules/user";
import { listTrainingTasks } from "@/api/trainingTask";
import { getCachedStudentTrainingTasks, loadStudentTrainingTasks } from "@/api/trainingTask";
import { buildStudentTaskSections } from "@/utils/studentTrainingNavigation";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
const { proxy } = getCurrentInstance();
@ -469,11 +469,17 @@ async function loadStudentTaskNavigation() {
studentTaskSections.value = [];
return;
}
const cachedTasks = getCachedStudentTrainingTasks();
if (cachedTasks.length) {
studentTaskSections.value = buildStudentTaskSections(cachedTasks);
}
try {
const res = await listTrainingTasks({ enabledOnly: true });
const res = await loadStudentTrainingTasks();
studentTaskSections.value = buildStudentTaskSections(res.data || []);
} catch (error) {
studentTaskSections.value = [];
if (!cachedTasks.length) {
studentTaskSections.value = [];
}
}
}
function groupAndSortModules(modules) {

Loading…
Cancel
Save