feat(协作): 老师协作时右栏顶上一条协作条,结果页签先摆学生最近一次交的,抽屉变成「他的提交」

- 协作条:「正在帮 谁 · 语言 · 看他交过什么 ↗ · 结束协作」,从工具栏里挪出来,一眼看得出
  编辑器里是学生的代码。「看他交过什么」带上学生用户名、开新标签(原来只带题号,还得再筛一遍)
- 老师接单后「结果」页签原来是空的:现在摆学生在这道题上最近一次交的结果,可刷新;
  不给 AI 提示(那是按登录的人自己的失败次数解锁的)
- 抽屉「我的提交」在协作中变成「他的提交」,列的是学生的提交,只能复制、不能放回编辑器
  (放回去会经协作通道直接盖掉学生正在写的代码),也不显示老师自己的排名
- 学生排队求助中、或者老师正在帮他时换题:先确认一句。换题会断开协作 / 撤掉举手,
  原来一点「下一题」就把正在帮他的老师踢出去了
- 求助按钮文案:「举手求助」→「已举手 · 前面 2 人」→「某某 老师在帮你」
- 提交列表加 exactUsername=1:用户名精确匹配。原来只有「包含」,ks24a1 会把 ks24a10 的提交
  也捞进来

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-28 18:28:53 +08:00
1 parent 11368813cc
commit 0c2ff68e9b
13 files changed
+287 -45

No files matched your search

@@ -296,6 +296,19 @@ async function astOnlyByUser(where: SQL | undefined, userIds: number[]) {
* 快照实测 count 65ms → 0.6ms。`ks2` 这种匹配上千个账号的宽前缀退回扫表,30~50ms,
* 和原来持平。
*/
/**
* 用户名**精确**匹配。usernameFilter 是「包含」,学号互相包含是常态(ks24a1 包含在 ks24a10 里),
* 协作中老师看「这个学生」的提交时不能把别人的也捞进来。查无此人留恒假条件
*/
export async function exactUsernameFilter(username: string) {
const [row] = await db
.select({ id: schema.user.id })
.from(schema.user)
.where(eq(schema.user.username, username))
.limit(1)
return row ? eq(schema.submission.userId, row.id) : sql`false`
}
export async function usernameFilter(username: string) {
const like = `%${username}%`
const users = await db
+11 -2
View File
@@ -32,7 +32,12 @@ import { problemSetJoinTimes } from "../services/problemset"
import { consumeToken } from "../services/throttling"
import { dayStart } from "../time"
import { asFilterValue, asRecord, isAdminRole, queryInteger } from "./helpers"
import { problemFilter, submissionStatisticsRoutes, usernameFilter } from "./submission-statistics"
import {
exactUsernameFilter,
problemFilter,
submissionStatisticsRoutes,
usernameFilter,
} from "./submission-statistics"
export const submissionRoutes = new Hono<ContestEnv>()
@@ -489,7 +494,11 @@ submissionRoutes.get("/submissions", optionalAuth, async (c) => {
filters.push(
...(await Promise.all([
displayId ? problemFilter(displayId, null) : undefined,
username ? usernameFilter(username) : undefined,
username
? c.req.query("exactUsername") === "1"
? exactUsernameFilter(username)
: usernameFilter(username)
: undefined,
])),
)
if (myself) filters.push(eq(schema.submission.userId, myself.id))