From ea9b7ec569a0b2ccc96cb833137e5800ecb64e9f Mon Sep 17 00:00:00 2001 From: cat_shark <1716967236@qq.com> Date: Sun, 5 Jul 2026 11:15:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E4=BC=9A=E8=AF=9D)=EF=BC=9A=E8=B7=A8?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E8=87=AA=E5=8A=A8=E6=81=A2=E5=A4=8D=20+=20?= =?UTF-8?q?=E9=98=BB=E6=AD=A2=E5=A4=9A=E4=BB=BB=E5=8A=A1=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端: - 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 时页面顶部显示恢复提示已恢复上次 --- src/api/studySessions.ts | 7 +++++++ src/components/StartTask.vue | 19 +++++++++++++++++++ src/components/Study.vue | 23 +++++++++++++++++++++-- src/router/index.ts | 12 ++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/api/studySessions.ts b/src/api/studySessions.ts index 084be25..981a3a8 100644 --- a/src/api/studySessions.ts +++ b/src/api/studySessions.ts @@ -37,6 +37,13 @@ export const getReportDraft = (sessionNum: string) => { return request.get(`/study-sessions/${sessionNum}/report-draft`); }; +/** 查询当前是否有活跃会话 */ +export const getActiveSession = (excludeTaskNum?: string) => { + const params: Record = {}; + if (excludeTaskNum) params.excludeTaskNum = excludeTaskNum; + return request.get('/study-sessions/active', params); +}; + /** 分页查询任务的历史残片 */ export const getTaskFragments = (taskNum: string, page: number, size: number, keyword?: string) => { const params: Record = { page, size }; diff --git a/src/components/StartTask.vue b/src/components/StartTask.vue index e4323fc..607bc8a 100644 --- a/src/components/StartTask.vue +++ b/src/components/StartTask.vue @@ -150,6 +150,9 @@ const BREAK_END_KEY = computed(() => `breakEnd_${taskNum}`); const isBreak = ref(false); const breakAudio = new Audio('/resource/notification.mp3'); +// 恢复提示 +const showResumeHint = ref(route.query.resume === "true"); + const progress = computed(() => { const total = isBreak.value ? 5 * 60 : 25 * 60; const remaining = timerMinutes.value * 60 + timerSeconds.value; @@ -303,6 +306,7 @@ const endTimer = async (content: string) => { } clear(); clearBreakState(); + localStorage.removeItem("activeSession"); await router.push("/study"); } catch { ElMessage.error("结束会话失败,请重试"); @@ -389,6 +393,13 @@ const loadTaskSession = async () => { } } + // 持久化活跃会话(用于跨页面恢复 + 阻止多任务) + localStorage.setItem("activeSession", JSON.stringify({ + taskNum: taskInfo.value.taskNum, + sessionNum: taskInfo.value.sessionNum, + taskName: taskInfo.value.taskName, + })); + if (taskInfo.value.sessionState === "ONGOING") { startTimer(); } else { @@ -516,6 +527,14 @@ onUnmounted(() => {