fix(班级筛选): 输入 ks251 会把 2511 班的学生也算进来
Deploy / deploy (push) Canceled after 0s

班级号 3~4 位并存,按用户名前缀/包含匹配时 ks251 会捞到 ks2510~ks2519。
新增 classPrefixCondition:ks + 3 位以上数字按具体班级匹配(后面不能再跟数字),
1~2 位仍是年级前缀。后台首页的用户排名、随机抽签,以及题单的学生进度筛选
(只填数字时补上 ks)都改用它。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-27 19:34:28 +08:00
1 parent 41cd141769
commit 23844ae301
4 files changed
+46 -9

No files matched your search

+6 -2
View File
@@ -34,7 +34,7 @@ import { revokeUserSessions } from "../../auth/session"
import { requireSuperAdmin, type AppEnv } from "../../auth/middleware"
import { db, schema } from "../../db"
import { failure, parseBody, success } from "../../http"
import { queryInteger, sampleUser } from "../helpers"
import { classPrefixCondition, queryInteger, sampleUser } from "../helpers"
export const adminAccountRoutes = new Hono<AppEnv>()
@@ -130,7 +130,11 @@ adminAccountRoutes.get("/rankings/users", requireSuperAdmin, async (c) => {
const where = and(
inArray(schema.user.adminType, [...STUDENT_ROLES]),
eq(schema.user.isDisabled, false),
keyword ? ilike(schema.user.username, `%${keyword}%`) : undefined,
// 输入班级前缀(ks251)按班级匹配,否则照旧按用户名包含
keyword
? (classPrefixCondition(keyword) ??
ilike(schema.user.username, `%${keyword}%`))
: undefined,
)
const [totalRows, rows] = await Promise.all([
+7 -4
View File
@@ -26,7 +26,7 @@ import { failure, parseBody, success } from "../../http"
import { sniffImageExtension } from "../../services/image"
import { getWebsiteOptions } from "../../services/options"
import { dayStart } from "../../time"
import { queryInteger } from "../helpers"
import { classPrefixCondition, queryInteger } from "../helpers"
export const adminConfRoutes = new Hono<AppEnv>()
@@ -253,14 +253,17 @@ adminConfRoutes.get("/dashboard", requireSuperAdmin, async (c) => {
adminConfRoutes.get("/random-usernames", requireSuperAdmin, async (c) => {
// 传的是**班级前缀**(形如 ks251),不是班级号 —— 前端输入框写的就是「班级前缀」,
// 拿到结果后按这个前缀 split 取姓名。这里按前缀匹配,与旧 istartswith 一致,
// 不额外按 className 过滤:那会改变旧行为,而这个功能就是随机点名,宁可宽松
// 拿到结果后按这个前缀 split 取姓名。班级前缀走 classPrefixCondition(ks251 不带上
// ks2511);别的形状的输入照旧 istartswith,与旧接口一致
const classroom = c.req.query("classroom")?.trim()
if (!classroom) return failure(c, 400, "invalid-request", "需要班级号")
const rows = await db
.select({ username: schema.user.username })
.from(schema.user)
.where(ilike(schema.user.username, `${classroom}%`))
.where(
classPrefixCondition(classroom) ??
ilike(schema.user.username, `${classroom}%`),
)
.orderBy(sql`random()`)
.limit(10)
return success(