refactor(web): Header 只管顶栏,全局的东西挂回 App
Header 一直兼着「全局挂载点」:课堂求助的提示、新求助 toast、求助列表和 教师端协作弹框都寄生在里面,只因为顶栏是全局的。它其实不是 —— /admin/* 走的是 admin.vue,没有 Header,老师一进后台这四个消费者全部 卸载:求助照收,提示、角标、弹框一个都不出现,正好是 collab.ts 里写的 「老师可能正在后台改题时收到求助」那个场景。 这些东西跟着连接走,而连接在 App.vue 按登录态开关,所以搬进 CollabHost 挂在同一层。Header 因此不必再是单根组件,default.vue 那个靠 class 传 居中样式的写法也换成外层 div,连带删掉「必须挂在根 n-flex 内部」那段 补丁注释。 顺带: - 圆环扩散的暗黑切换抽成 useDarkTransition - 求助的角标/toast/列表不再限桌面端 —— 老师缩窗口也得知道有人在等; 接单确实要在电脑上写代码,那道闸挪进 HelpRequestList - 站名改 text 按钮,能 tab 到、回车能按 - logout 的两步收进 userStore.signOut() - 清掉死代码:handleMenuSelect 只认一个不存在的 key、active 里 ["user","setting"] 永远不生效的排除、两个 show:false 的菜单项 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QqqZwxtXLo2GTqMi51C94D
This commit is contained in:
1 parent
cbe6955c26
commit
e62f41f6c7
8 files changed
+233
-179
No files matched your search
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue"
|
||||
import { useBreakpoints } from "shared/composables/breakpoints"
|
||||
import { useCollabStore } from "shared/store/collab"
|
||||
|
||||
/** 由顶栏的姓名下拉菜单打开 */
|
||||
@@ -7,6 +8,10 @@ const show = defineModel<boolean>("show", { default: false })
|
||||
|
||||
const collabStore = useCollabStore()
|
||||
|
||||
// 接单之后要在弹框里替学生写代码,那个编辑器窄屏上没法用 —— 所以窄屏只让看
|
||||
// 「谁在等」(角标、toast、这张列表照常给),接单留到桌面端
|
||||
const { isDesktop } = useBreakpoints()
|
||||
|
||||
// 等待时长要每秒走一格,所以自己转一个 now。
|
||||
// 只在弹框开着时转 —— 这个组件跟着顶栏常驻,关着的时候没人看这个数。
|
||||
const now = ref(Date.now())
|
||||
@@ -40,7 +45,7 @@ const waited = (createdAt: number) => {
|
||||
|
||||
const handleAccept = (studentId: number, status: string) => {
|
||||
// 已被别的老师接走的不能点
|
||||
if (status === "active") return
|
||||
if (status === "active" || !isDesktop.value) return
|
||||
collabStore.accept(studentId)
|
||||
// 接单后马上要弹 CollabModal,这个列表得让位
|
||||
show.value = false
|
||||
@@ -55,7 +60,19 @@ const handleAccept = (studentId: number, status: string) => {
|
||||
:style="{ width: '420px' }"
|
||||
>
|
||||
<div style="max-height: 60vh; overflow: auto">
|
||||
<n-empty v-if="collabStore.groupedRequests.length === 0" description="暂无求助" />
|
||||
<n-alert
|
||||
v-if="!isDesktop"
|
||||
type="info"
|
||||
:bordered="false"
|
||||
style="margin-bottom: 8px"
|
||||
>
|
||||
接单要在电脑上打开
|
||||
</n-alert>
|
||||
|
||||
<n-empty
|
||||
v-if="collabStore.groupedRequests.length === 0"
|
||||
description="暂无求助"
|
||||
/>
|
||||
|
||||
<div v-for="group in collabStore.groupedRequests" :key="group.problemId">
|
||||
<!-- 同题多人是个教学信号:该停下来全班讲,而不是挨个救 -->
|
||||
@@ -77,14 +94,17 @@ const handleAccept = (studentId: number, status: string) => {
|
||||
padding: '6px 8px',
|
||||
borderRadius: '4px',
|
||||
opacity: item.status === 'active' ? 0.5 : 1,
|
||||
cursor: item.status === 'active' ? 'default' : 'pointer',
|
||||
cursor:
|
||||
item.status === 'active' || !isDesktop ? 'default' : 'pointer',
|
||||
}"
|
||||
@click="handleAccept(item.studentId, item.status)"
|
||||
>
|
||||
<n-flex vertical :size="2">
|
||||
<n-text>
|
||||
{{ item.studentName }}
|
||||
<n-text depth="3" v-if="item.className">({{ item.className }})</n-text>
|
||||
<n-text depth="3" v-if="item.className"
|
||||
>({{ item.className }})</n-text
|
||||
>
|
||||
</n-text>
|
||||
<n-text depth="3" style="font-size: 12px">
|
||||
{{
|
||||
|
||||
Reference in new issue
Block a user