From b5d2f1589ed69a4b6d0469a3f4649be84eb55bcc Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Mon, 28 Sep 2026 18:42:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=AF=BE=E5=A0=82=E7=9C=8B=E6=9D=BF):=20?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=9B=BE=E7=94=BB=E5=88=B0=20A=20/=20S=20?= =?UTF-8?q?=E5=9C=A8=E8=80=81=E5=B8=88=E7=9A=84=E7=9C=8B=E6=9D=BF=E4=B8=8A?= =?UTF-8?q?=E4=B9=9F=E7=AE=97=E5=81=9A=E5=AE=8C=EF=BC=8C=E5=8F=AA=E7=94=BB?= =?UTF-8?q?=E4=BA=86=E5=9B=BE=E7=9A=84=E5=AD=A6=E7=94=9F=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E3=80=8C=E6=B2=A1=E5=BC=80=E5=A7=8B=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 和学生首页的课堂条同一个口径:格子的状态、做对的时间、尝试次数都把流程图提交算进去; 「最后一次提交」也算上今天画的图。有的题这节课整个班都在画流程图,原来看板上是满屏「没开始」 Co-Authored-By: Claude Opus 5.5 --- apps/api/src/routes/classroom.ts | 47 +++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/apps/api/src/routes/classroom.ts b/apps/api/src/routes/classroom.ts index 1e9826f..9cfefd5 100644 --- a/apps/api/src/routes/classroom.ts +++ b/apps/api/src/routes/classroom.ts @@ -516,8 +516,44 @@ classroomRoutes.get("/classroom/board", requireTeacher, async (c) => { .groupBy(schema.submission.userId) : [], ]) + /** + * 流程图作业:画到 A / S 也算这道题做完,和学生首页的课堂条同一个口径(/me/class-activity)。 + * 有的题这节课整个班都在画流程图,只数代码提交的话,看板上满屏「没开始」 + */ + const drawn = + ids.length && userIds.length + ? await db + .select({ + userId: schema.flowchartSubmission.userId, + problemId: schema.flowchartSubmission.problemId, + attempts: sql`count(*) filter (where ${gte(schema.flowchartSubmission.createTime, start)})::int`, + firstPassedAt: sql< + string | null + >`min(${schema.flowchartSubmission.createTime}) filter (where ${and(eq(schema.flowchartSubmission.status, 2), inArray(schema.flowchartSubmission.aiGrade, FLOWCHART_PASS_GRADES))})`, + lastAt: sql< + string | null + >`max(${schema.flowchartSubmission.createTime}) filter (where ${gte(schema.flowchartSubmission.createTime, start)})`, + }) + .from(schema.flowchartSubmission) + .where( + and( + inArray(schema.flowchartSubmission.userId, userIds), + inArray(schema.flowchartSubmission.problemId, ids), + ), + ) + .groupBy(schema.flowchartSubmission.userId, schema.flowchartSubmission.problemId) + : [] const cellByKey = new Map(cells.map((row) => [`${row.userId}:${row.problemId}`, row])) + const drawnByKey = new Map(drawn.map((row) => [`${row.userId}:${row.problemId}`, row])) const lastByUser = new Map(lastSubmits.map((row) => [row.userId, row.lastAt])) + // 今天只画了流程图的学生,「最后一次提交」也得算上画图,不然他在看板上是一直没动手 + for (const row of drawn) { + if (!row.lastAt) continue + const known = lastByUser.get(row.userId) + if (!known || Date.parse(row.lastAt) > Date.parse(known)) lastByUser.set(row.userId, row.lastAt) + } + const earliest = (a: string | null | undefined, b: string | null | undefined) => + !a ? (b ?? null) : !b ? a : Date.parse(a) <= Date.parse(b) ? a : b const attendedByUser = new Map(attendance.map((row) => [row.userId, row.days])) return success(c, { @@ -536,11 +572,14 @@ classroomRoutes.get("/classroom/board", requireTeacher, async (c) => { username: student.username, realName: student.realName ?? null, cells: ids.map((id) => { - const cell = cellByKey.get(`${student.userId}:${id}`) + const key = `${student.userId}:${id}` + const cell = cellByKey.get(key) + const flow = drawnByKey.get(key) + const acceptedAt = earliest(cell?.firstAcceptedAt, flow?.firstPassedAt) return { - status: !cell ? "none" : cell.firstAcceptedAt ? "accepted" : "tried", - attempts: cell?.attempts ?? 0, - acceptedAt: cell?.firstAcceptedAt ?? null, + status: !cell && !flow ? "none" : acceptedAt ? "accepted" : "tried", + attempts: (cell?.attempts ?? 0) + (flow?.attempts ?? 0), + acceptedAt, } }), lastSubmitAt: lastByUser.get(student.userId) ?? null,