diff --git a/apps/web/package.json b/apps/web/package.json index 52e5714..e596a16 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -40,6 +40,7 @@ "date-fns": "^4.4.0", "fflate": "^0.8.3", "highlight.js": "^11.12.0", + "lib0": "0.2.117", "md-editor-v3": "^6.5.6", "mermaid": "^11.17.2", "mermaid-legacy": "npm:mermaid@^9.4.3", diff --git a/apps/web/src/shared/components/Header.vue b/apps/web/src/shared/components/Header.vue index 4924de5..6a4dea5 100644 --- a/apps/web/src/shared/components/Header.vue +++ b/apps/web/src/shared/components/Header.vue @@ -4,6 +4,7 @@ import { RouterLink } from "vue-router" import { useBreakpoints } from "shared/composables/breakpoints" import { useLearnProgress } from "shared/composables/learnProgress" import { useAuthModalStore } from "shared/store/authModal" +import { useCollabStore } from "shared/store/collab" import { useScreenModeStore } from "shared/store/screenMode" import { logout } from "../api" import CollabModal from "./CollabModal.vue" @@ -14,6 +15,23 @@ import { trickOrTreat } from "utils/functions" const userStore = useUserStore() const configStore = useConfigStore() +const collabStore = useCollabStore() +const message = useMessage() + +/** + * 课堂求助的一次性提示,统一在这里弹。 + * + * 原来挂在题目页的 Form.vue 上:学生排着队切去看提交记录,老师这时候取消了 + * 他的求助,那条「老师已取消你的求助」就永远没人消费。顶栏是全局的,放这儿 + * 才收得全 —— 教师端的 error 提示(比如「请先退出当前协作」)同理。 + */ +watch( + () => collabStore.noticeSeq, + () => { + const text = collabStore.consumeNotice() + if (text) message.info(text) + }, +) const authStore = useAuthModalStore() const screenModeStore = useScreenModeStore() const route = useRoute() diff --git a/apps/web/src/shared/store/collab.ts b/apps/web/src/shared/store/collab.ts index c1d8b7b..06a34f6 100644 --- a/apps/web/src/shared/store/collab.ts +++ b/apps/web/src/shared/store/collab.ts @@ -32,8 +32,21 @@ export const useCollabStore = defineStore("collab", () => { const teacherName = ref("") /** 双方:当前房间。null 表示不在协作中 */ const room = ref(null) - /** 一次性提示,由组件消费后清空 */ + /** 一次性提示,由 Header 统一消费后清空 */ const notice = ref("") + /** + * 提示序号,每次设置都自增。 + * + * 消费方 watch 的是这个,不是 notice 本身:连着两次同样的文案(老师取消了 + * 求助、学生又求助、又被取消)在 Vue 眼里 `===` 相等,watch(notice) 不会 + * 第二次触发,第二条提示就这么没了。 + */ + const noticeSeq = ref(0) + + function setNotice(text: string) { + notice.value = text + noticeSeq.value += 1 + } const pendingCount = computed( () => requests.value.filter((it) => it.status === "pending").length, @@ -74,10 +87,10 @@ export const useCollabStore = defineStore("collab", () => { teacherName.value = String(data.teacherName ?? "") } else if (data.status === "cancelled") { helpStatus.value = "idle" - notice.value = "老师已取消你的求助" + setNotice("老师已取消你的求助") } else if (data.status === "no_teacher") { helpStatus.value = "idle" - notice.value = "当前没有老师在线" + setNotice("当前没有老师在线") } return case "room_open": @@ -97,11 +110,12 @@ export const useCollabStore = defineStore("collab", () => { // 这里先归零,那条 pending 补发会立刻把它纠正回来,不会被这次重置盖掉 room.value = null helpStatus.value = "idle" - notice.value = - data.reason === "peer_offline" ? "对方已断开连接" : "协作已结束" + setNotice( + data.reason === "peer_offline" ? "对方已断开连接" : "协作已结束", + ) return case "error": - notice.value = String(data.message ?? "") + setNotice(String(data.message ?? "")) return } } @@ -179,6 +193,7 @@ export const useCollabStore = defineStore("collab", () => { teacherName, room, notice, + noticeSeq, isTeacher: computed(() => userStore.isTeacherOrAbove), connect, disconnect, diff --git a/bun.lock b/bun.lock index d28cd3d..5a6a447 100644 --- a/bun.lock +++ b/bun.lock @@ -67,6 +67,7 @@ "date-fns": "^4.4.0", "fflate": "^0.8.3", "highlight.js": "^11.12.0", + "lib0": "0.2.117", "md-editor-v3": "^6.5.6", "mermaid": "^11.17.2", "mermaid-legacy": "npm:mermaid@^9.4.3",