From e852bf44981ce581bf6f95751ca22383c6f699f5 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Fri, 9 Oct 2026 12:58:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E9=A2=98=E7=9B=AE=E5=88=97=E8=A1=A8):=20?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=E9=87=8C=E5=A4=9A=E4=BA=86=E4=B8=AA=E7=94=A8?= =?UTF-8?q?=E4=B8=8D=E4=B8=8A=E7=9A=84=E3=80=8C=E6=8C=89=E9=A2=98=E5=8F=B7?= =?UTF-8?q?=E3=80=8D=EF=BC=8C=E5=8E=9F=E6=9D=A5=E7=9A=84=E6=9C=80=E6=97=A9?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E3=80=81=E6=9C=80=E5=A4=9A=20/=20=E6=9C=80?= =?UTF-8?q?=E5=B0=91=E6=8F=90=E4=BA=A4=E3=80=81=E9=80=9A=E8=BF=87=E9=83=BD?= =?UTF-8?q?=E6=B2=A1=E4=BA=86=E2=80=94=E2=80=94=E6=8D=A2=E5=9B=9E=E5=8E=9F?= =?UTF-8?q?=E6=9D=A5=E9=82=A3=E4=B8=80=E5=A5=97?= 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/problem.ts | 33 +++++++++++++++----------------- apps/web/src/oj/problem/list.vue | 9 ++++++--- packages/contract/src/problem.ts | 14 ++++++++++++-- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/apps/api/src/routes/problem.ts b/apps/api/src/routes/problem.ts index 5425175..dc8e505 100644 --- a/apps/api/src/routes/problem.ts +++ b/apps/api/src/routes/problem.ts @@ -121,12 +121,6 @@ function listItem( } satisfies ProblemListItem } -/** 题号排序:先按长度再按字面,1001 < 1100 < P026 < SQL09,不会排成 1001、1100、11、2 */ -const displayIdOrder = [ - asc(sql`length(${schema.problem.displayId})`), - asc(schema.problem.displayId), -] - problemRoutes.get("/problems", optionalAuth, async (c) => { const user = c.get("user") const limit = queryInteger(c.req.query("limit"), 20, { min: 1, max: 250 }) @@ -169,23 +163,26 @@ problemRoutes.get("/problems", optionalAuth, async (c) => { filters.push(notInArray(schema.problem.id, [...states.solved])) const where = and(...filters) - // 默认按最新创建(选了知识点也一样)。旧的排序值(最多提交、画流程图……)落到默认 —— - // 类型已经拆成了单独的筛选 + // 排序值沿用原来的(地址栏里存着的旧链接照样能用),但「最多 / 最少」现在按**人数**排, + // 和列表最后一列「做对 / 做过」对得上:submission_number 是做过的人,accepted_number 是做对的人。 + // 旧的「画流程图 / 语法检查」排序已经拆成类型筛选,传进来落到默认(最新创建) const sort = problemListSortSchema.safeParse(c.req.query("sort") ?? "").data ?? "" - const effective = sort || "new" - const allCounts = effective === "popular" ? await problemUserCounts() : null - const popularity = allCounts + const byPeople = sort.endsWith("submission_number") || sort.endsWith("accepted_number") + const allCounts = byPeople ? await problemUserCounts() : null + const people = allCounts ? sql`case ${schema.problem.id} ${sql.join( - [...allCounts].map(([id, n]) => sql`when ${id} then ${n.solved}`), + [...allCounts].map( + ([id, n]) => + sql`when ${id} then ${sort.endsWith("accepted_number") ? n.solved : n.tried}`, + ), sql` `, )} else 0 end` : null - const order = - effective === "id" - ? displayIdOrder - : popularity - ? [desc(popularity), ...displayIdOrder] - : [desc(schema.problem.createTime)] + const order = people + ? [sort.startsWith("-") ? desc(people) : asc(people), desc(schema.problem.createTime)] + : sort === "create_time" + ? [asc(schema.problem.createTime)] + : [desc(schema.problem.createTime)] const [totalRow] = await db .select({ value: countDistinct(schema.problem.id) }) .from(schema.problem) diff --git a/apps/web/src/oj/problem/list.vue b/apps/web/src/oj/problem/list.vue index 3863f15..c95b933 100644 --- a/apps/web/src/oj/problem/list.vue +++ b/apps/web/src/oj/problem/list.vue @@ -179,11 +179,14 @@ const countText = computed(() => { return { kind: "total" as const, n: total.value } }) -// ---- 排序:默认按最新创建(选了知识点也一样) ---- +// ---- 排序:和原来同一套,「最多 / 最少」按人数(和最后一列「做对 / 做过」对得上) ---- const sortOptions = [ { label: "最新创建", value: "" }, - { label: "按题号", value: "id" }, - { label: "最多人做对", value: "popular" }, + { label: "最早创建", value: "create_time" }, + { label: "最多人做过", value: "-submission_number" }, + { label: "最少人做过", value: "submission_number" }, + { label: "最多人做对", value: "-accepted_number" }, + { label: "最少人做对", value: "accepted_number" }, ] // ---- 出题者 ---- diff --git a/packages/contract/src/problem.ts b/packages/contract/src/problem.ts index 34af3f0..e4fd85e 100644 --- a/packages/contract/src/problem.ts +++ b/packages/contract/src/problem.ts @@ -439,8 +439,18 @@ export const problemListSchema = paginatedSchema(problemListItemSchema) /** 题目列表「全部类型」下拉:有参考图 / 画流程图 / 语法要求 */ export const problemTypeFilterSchema = z.enum(["reference", "flowchart", "ast"]) -/** 题目列表的排序。空串是默认:按最新创建 */ -export const problemListSortSchema = z.enum(["", "id", "new", "popular"]) +/** + * 题目列表的排序。值沿用原来的(旧链接照样能用):空串 = 最新创建、create_time = 最早创建, + * ±submission_number / ±accepted_number 是做过 / 做对的**人数**,带 - 是从多到少 + */ +export const problemListSortSchema = z.enum([ + "", + "create_time", + "-submission_number", + "submission_number", + "-accepted_number", + "accepted_number", +]) /** * 题目列表顶上那行和左栏的进度。**只说做到了什么**:做对几道、这周新做对几道、