fix(collab): 提示会丢、排队位置不刷新;显式声明 lib0
Some checks failed
Deploy / deploy (push) Has been cancelled

- 一次性提示原来挂在题目页的 Form.vue 上消费:学生排着队切去看提交记录,
  老师这时取消了他的求助,那条提示就永远没人消费。挪到顶栏统一弹,
  教师端的 error 提示同理。另外加了序号——连着两次同样的文案在 Vue 眼里
  === 相等,watch(notice) 不会第二次触发。

- queueAhead 原来只在「建请求 / 重连 / 退回排队」推过,前面的人被接走或
  被取消之后不重算,第五个学生会一直显示「前面还有 4 人」。跟着
  broadcastRequests 一起推,两件事永远同时发生。

- collabDoc 动态 import 了 lib0/encoding 和 lib0/decoding,但 lib0 不在
  package.json 里,靠 yjs 提升到根 node_modules 才能解析。上游依赖树一变
  就断,而且断在运行时不在构建时。按现装的 0.2.117 钉住。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016DHxhKNxXfG89JnVzHbvgj
This commit is contained in:
2026-08-30 09:38:04 -06:00
parent 4abaf9c7e4
commit ffabcd4a0d
4 changed files with 41 additions and 6 deletions

View File

@@ -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",

View File

@@ -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()

View File

@@ -32,8 +32,21 @@ export const useCollabStore = defineStore("collab", () => {
const teacherName = ref("")
/** 双方当前房间。null 表示不在协作中 */
const room = ref<RoomInfo | null>(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,