feat(会话):跨页面自动恢复 + 阻止多任务同时进行

后端:
- StudySessionsServiceImpl.getActiveSession(excludeTaskNum):
  查询 ONGOING/PAUSED 状态的活跃会话,可排除指定任务
- Controller 新增 GET /study-sessions/active?excludeTaskNum=

前端:
- router beforeEach 守卫:读取 localStorage 中 activeSession,
  非 start-task 页面时自动重定向恢复
- Study.vue 开始任务按钮:调用 getActiveSession() 检测是否
  有其他任务正在进行,提示用户前往继续
- StartTask.vue loadTaskSession 成功后将活跃会话写入
  localStorage(taskNum/sessionNum/taskName)
- endSession 成功时清除 localStorage 中的 activeSession
- 路由参数 ?resume=true 时页面顶部显示恢复提示已恢复上次
This commit is contained in:
2026-07-05 11:15:22 +08:00
parent 85bee1d311
commit ea9b7ec569
4 changed files with 59 additions and 2 deletions
+21 -2
View File
@@ -4,6 +4,7 @@ import request from "@/utils/request";
import router from "@/router";
import { ElMessage, ElMessageBox } from "element-plus";
import { getReviewTaskStatsByTask } from "@/api/review";
import { getActiveSession } from "@/api/studySessions";
import {
getPriorityWeights,
getTaskApplications,
@@ -174,12 +175,30 @@ watch(selectedTaskId, (newId) => {
}
});
const startTask = () => {
const startTask = async () => {
if (!selectedTask.value) {
ElMessage.warning("请先选择一个任务");
return;
}
router.push(`/start-task/${encodeURIComponent(selectedTask.value.taskNum)}`);
const taskNum = selectedTask.value.taskNum;
try {
const res = await getActiveSession(taskNum);
if (res?.code === 200 && res.data) {
// 有其他任务的活跃会话
const active = res.data;
ElMessageBox.confirm(
`你还有一个未完成的学习任务「${active.taskName}」(${active.sessionNum}),是否前往继续?`,
"有其他任务正在进行",
{ confirmButtonText: "前往继续", cancelButtonText: "取消", type: "warning" }
).then(() => {
router.push(`/start-task/${encodeURIComponent(active.taskNum)}`);
}).catch(() => {});
return;
}
} catch {
// 查询失败不阻塞,直接跳转
}
router.push(`/start-task/${encodeURIComponent(taskNum)}`);
};
const addTask = () => {