From 84bfb44c208162e6b14bb146762ac582b2f17efe Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Fri, 9 Oct 2026 16:51:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=A2=98=E7=9B=AE=E5=88=97=E8=A1=A8):=20S?= =?UTF-8?q?QL=20=E9=A2=98=E6=B7=B7=E5=9C=A8=E4=B8=80=E8=88=AC=E9=A2=98?= =?UTF-8?q?=E9=87=8C=E7=9C=8B=E4=B8=8D=E5=87=BA=E6=9D=A5=EF=BC=8C=E7=82=B9?= =?UTF-8?q?=E8=BF=9B=E5=8E=BB=E6=89=8D=E5=8F=91=E7=8E=B0=E4=B8=8D=E6=98=AF?= =?UTF-8?q?=E5=86=99=20C=E2=80=94=E2=80=94=E5=92=8C=E7=94=BB=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=9B=BE=E4=B8=80=E6=A0=B7=E6=8C=82=E3=80=8CSQL?= =?UTF-8?q?=E3=80=8D=E6=A0=87=E7=AD=BE=EF=BC=8C=E3=80=8C=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E3=80=8D=E9=87=8C=E4=B9=9F=E8=83=BD=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E7=AD=9B?= 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/contest.ts | 1 + apps/api/src/routes/problem.ts | 2 ++ .../oj/problem/components/ProblemTypeTag.vue | 32 +++++++++++++++++-- apps/web/src/oj/problem/list.vue | 2 +- apps/web/src/oj/problem/utils/problemType.ts | 6 +++- apps/web/src/oj/transforms.ts | 1 + apps/web/src/utils/types.ts | 1 + packages/contract/src/problem.ts | 6 ++-- 8 files changed, 45 insertions(+), 6 deletions(-) diff --git a/apps/api/src/routes/contest.ts b/apps/api/src/routes/contest.ts index d64462f..4d15a17 100644 --- a/apps/api/src/routes/contest.ts +++ b/apps/api/src/routes/contest.ts @@ -244,6 +244,7 @@ contestRoutes.get( allowFlowchart: problem.allowFlowchart, showFlowchart: problem.showFlowchart, hasAstRules: problem.astRules !== null, + isSql: problem.languages.includes("SQL"), myStatus: myStatusOf(statuses, problem.id), // 按人数是公开题库列表的列;比赛题表看的是榜单,不下发 solvedUsers: 0, diff --git a/apps/api/src/routes/problem.ts b/apps/api/src/routes/problem.ts index c362900..8f92857 100644 --- a/apps/api/src/routes/problem.ts +++ b/apps/api/src/routes/problem.ts @@ -110,6 +110,7 @@ function listItem( allowFlowchart: row.problem.allowFlowchart, showFlowchart: row.problem.showFlowchart, hasAstRules: row.problem.astRules !== null, + isSql: row.problem.languages.includes("SQL"), // 流程图评到 A / S 也打勾:problemStates 已经把它算进 solved myStatus: states?.solved.has(id) ? JudgeStatus.ACCEPTED @@ -157,6 +158,7 @@ problemRoutes.get("/problems", optionalAuth, async (c) => { if (type === "reference") filters.push(eq(schema.problem.showFlowchart, true)) if (type === "flowchart") filters.push(eq(schema.problem.allowFlowchart, true)) if (type === "ast") filters.push(sql`${schema.problem.astRules} is not null`) + if (type === "sql") filters.push(sql`${schema.problem.languages} @> '["SQL"]'::jsonb`) const states = user ? await problemStates(user.id) : null if (undone && states && states.solved.size > 0) diff --git a/apps/web/src/oj/problem/components/ProblemTypeTag.vue b/apps/web/src/oj/problem/components/ProblemTypeTag.vue index f042ccb..75964f0 100644 --- a/apps/web/src/oj/problem/components/ProblemTypeTag.vue +++ b/apps/web/src/oj/problem/components/ProblemTypeTag.vue @@ -5,7 +5,8 @@ import { useThemeVars } from "naive-ui" import { PROBLEM_TYPE_LABEL } from "../utils/problemType" /** - * 三类特殊题的小标签(设计稿「题目列表重设计 · 改版」)。轻重按对学生意味着什么分: + * 几类特殊题的小标签(设计稿「题目列表重设计 · 改版」)。轻重按对学生意味着什么分: + * - SQL:和画流程图一样重(实心底)—— 写的根本不是 C / Python,点进去之前就得知道 * - 画流程图:最醒目(浅紫底)—— 只有这类题能交流程图,要做的事和普通题不一样 * - 语法要求:蓝描边 —— 判题时会检查写法,要看得见 * - 有参考图:灰描边,最轻 —— 是帮助,不用提醒 @@ -16,6 +17,7 @@ const props = defineProps<{ kind: ProblemTypeFilter }>() const theme = useThemeVars() const ICON: Record = { + sql: "ph:database-bold", flowchart: "ph:pencil-simple-line-bold", ast: "ph:code-bold", reference: "ph:flow-arrow-bold", @@ -67,12 +69,38 @@ html.dark .type-tag.flowchart { background: rgba(160, 120, 240, 0.18); } +/* 青色:绿 / 橙 / 红是难度、紫是画流程图、蓝是语法要求,剩下它不和谁撞 */ +.type-tag.sql { + font-weight: 600; + color: #0b6470; + background: #dcf1f3; + border-color: transparent; +} + +html.dark .type-tag.sql { + color: #8fd8e0; + background: rgba(60, 180, 195, 0.18); +} + .type-tag.ast { color: var(--tag-info); border-color: #b9cdee; } -html.dark .type-tag.ast { +html.dark /* 青色:绿 / 橙 / 红是难度、紫是画流程图、蓝是语法要求,剩下它不和谁撞 */ +.type-tag.sql { + font-weight: 600; + color: #0b6470; + background: #dcf1f3; + border-color: transparent; +} + +html.dark .type-tag.sql { + color: #8fd8e0; + background: rgba(60, 180, 195, 0.18); +} + +.type-tag.ast { color: var(--tag-info-dark); border-color: rgba(112, 192, 232, 0.45); } diff --git a/apps/web/src/oj/problem/list.vue b/apps/web/src/oj/problem/list.vue index 560afbf..1875408 100644 --- a/apps/web/src/oj/problem/list.vue +++ b/apps/web/src/oj/problem/list.vue @@ -44,7 +44,7 @@ const DIFFICULTIES = [ { label: "困难", value: "High" }, ] -const TYPES: ProblemTypeFilter[] = ["reference", "flowchart", "ast"] +const TYPES: ProblemTypeFilter[] = ["sql", "reference", "flowchart", "ast"] /** 新生一道还没做对时,顶行引去的知识点 */ const START_TAG = "输出入门" diff --git a/apps/web/src/oj/problem/utils/problemType.ts b/apps/web/src/oj/problem/utils/problemType.ts index 9fc73f5..894f4a2 100644 --- a/apps/web/src/oj/problem/utils/problemType.ts +++ b/apps/web/src/oj/problem/utils/problemType.ts @@ -2,6 +2,7 @@ import type { ProblemTypeFilter } from "@oj2/contract" /** 名字和题目页一致:「语法要求」(题目页原来叫「代码要求」,一起改了) */ export const PROBLEM_TYPE_LABEL: Record = { + sql: "SQL", flowchart: "画流程图", ast: "语法要求", reference: "有参考图", @@ -9,18 +10,21 @@ export const PROBLEM_TYPE_LABEL: Record = { /** 「全部类型」下拉里每项下面那句话 */ export const PROBLEM_TYPE_HINT: Record = { + sql: "写 SQL 语句查数据库,不是写 C / Python 程序", reference: "题目里附了老师画好的流程图,照着写代码", flowchart: "除了写代码,也可以交流程图;评到 A 或 S 级算做对", ast: "要求用(或者不能用)某种写法,交了会检查", } -/** 一道题挂哪几个标签,从醒目到轻:画流程图 → 语法要求 → 有参考图 */ +/** 一道题挂哪几个标签,从醒目到轻:SQL → 画流程图 → 语法要求 → 有参考图 */ export function problemTypes(problem: { + isSql: boolean allowFlowchart: boolean hasAstRules: boolean showFlowchart: boolean }): ProblemTypeFilter[] { const kinds: ProblemTypeFilter[] = [] + if (problem.isSql) kinds.push("sql") if (problem.allowFlowchart) kinds.push("flowchart") if (problem.hasAstRules) kinds.push("ast") if (problem.showFlowchart) kinds.push("reference") diff --git a/apps/web/src/oj/transforms.ts b/apps/web/src/oj/transforms.ts index fc94c04..5140432 100644 --- a/apps/web/src/oj/transforms.ts +++ b/apps/web/src/oj/transforms.ts @@ -23,6 +23,7 @@ export function toProblemRow(result: ProblemListItem): ProblemRow { allowFlowchart: result.allowFlowchart, showFlowchart: result.showFlowchart, hasAstRules: result.hasAstRules, + isSql: result.isSql, solvedUsers: result.solvedUsers, triedUsers: result.triedUsers, } diff --git a/apps/web/src/utils/types.ts b/apps/web/src/utils/types.ts index f612404..cbd1b2d 100644 --- a/apps/web/src/utils/types.ts +++ b/apps/web/src/utils/types.ts @@ -167,6 +167,7 @@ export interface ProblemRow { allowFlowchart: boolean showFlowchart: boolean hasAstRules: boolean + isSql: boolean solvedUsers: number triedUsers: number } diff --git a/packages/contract/src/problem.ts b/packages/contract/src/problem.ts index e4fd85e..a3cc665 100644 --- a/packages/contract/src/problem.ts +++ b/packages/contract/src/problem.ts @@ -424,6 +424,8 @@ export const problemListItemSchema = z.object({ allowFlowchart: z.boolean(), showFlowchart: z.boolean(), hasAstRules: z.boolean(), + /** SQL 题(可选语言里有 SQL):写 SQL 语句查数据库,和写 C / Python 是两回事,列表里单独标出来 */ + isSql: z.boolean(), /** 0 = 做对了。画流程图的题,流程图评到 A / S 也给 0(和题单、课堂条一个口径) */ myStatus: z.number().int().nullable(), /** @@ -436,8 +438,8 @@ export const problemListItemSchema = z.object({ export const problemListSchema = paginatedSchema(problemListItemSchema) -/** 题目列表「全部类型」下拉:有参考图 / 画流程图 / 语法要求 */ -export const problemTypeFilterSchema = z.enum(["reference", "flowchart", "ast"]) +/** 题目列表「全部类型」下拉:SQL / 有参考图 / 画流程图 / 语法要求 */ +export const problemTypeFilterSchema = z.enum(["sql", "reference", "flowchart", "ast"]) /** * 题目列表的排序。值沿用原来的(旧链接照样能用):空串 = 最新创建、create_time = 最早创建,