From b130d805be1d36c43a5041312e86667b37e06ce4 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Thu, 3 Sep 2026 20:49:57 -0600 Subject: [PATCH] =?UTF-8?q?fix(=E5=90=8E=E5=8F=B0=E9=A2=98=E5=8D=95):=20?= =?UTF-8?q?=E4=BF=AE=E6=8E=89=E4=B8=80=E4=B8=B2=E5=89=8D=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=90=8D=E5=AF=B9=E4=B8=8D=E4=B8=8A=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E7=A9=BA=E5=88=97=E4=B8=8E=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后台题单接口下发的是扁平结构(displayId / title / isRequired),前端却按前台 题单页的嵌套结构取值,naive-ui 的 key 也不解析点号路径,于是「题目ID」「题目 标题」两列永远是空的。同一处还连累了另外几个操作: - 编辑题目弹窗读 problem.problem.title,点「编辑」直接抛错; - 添加题目发 problem_id / is_required,api 层取 problemId,出站是 undefined, 被后端按参数错误 400 掉; - 编辑题目发 is_required,「必做」怎么改都不生效; - 新建/编辑奖章发 condition_type,toBadgeBody 读 conditionType,同样 400。 根因是 admin/api.ts 把这批后台接口的返回值标成了 oj 侧的 ProblemSet / ProblemSetBadge / ProblemSetProblem,加上 detail.vue 四个 handler 用 data: any 接弹窗数据,字段拼错编译器一句都不吭。现在返回值全部换成 Admin* 契约类型, handler 换成 AddProblemToSetRequest / UpdateProblemInSetRequest 和一个本地 BadgeFormData(条件类型是「完成所有题目」时不带 conditionValue,后端补 0), 两个奖章弹窗里的 const data: any 也一并拆掉。 验证:dev 栈实跑,列表两列有值、编辑弹窗正常打开、加题 / 改必做 / 建奖章 / 改奖章四条链路走完界面都成功落库;bun run type-check 通过。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011WmMi9tPrnSAwwAy2i4WAa --- apps/web/src/admin/api.ts | 34 +++++++++--------- .../problemset/components/AddBadgeModal.vue | 21 +++++------ .../problemset/components/AddProblemModal.vue | 8 ++--- .../problemset/components/BadgeManagement.vue | 6 ++-- .../problemset/components/EditBadgeModal.vue | 25 ++++++------- .../components/EditProblemModal.vue | 10 +++--- .../components/ProblemManagement.vue | 12 +++---- .../problemset/components/ProblemSetInfo.vue | 4 +-- apps/web/src/admin/problemset/detail.vue | 36 +++++++++++-------- apps/web/src/admin/problemset/list.vue | 6 ++-- apps/web/src/utils/types.ts | 7 ++++ 11 files changed, 89 insertions(+), 80 deletions(-) diff --git a/apps/web/src/admin/api.ts b/apps/web/src/admin/api.ts index 52052ba..e1945ef 100644 --- a/apps/web/src/admin/api.ts +++ b/apps/web/src/admin/api.ts @@ -38,10 +38,10 @@ import type { Tutorial, User, WebsiteConfig, - ProblemSet, - ProblemSetBadge, - ProblemSetList, - ProblemSetProblem, + AdminProblemSetBadge, + AdminProblemSetList, + AdminProblemSet, + AdminProblemSetProblem, TutorialListItem, } from "utils/types" @@ -498,20 +498,20 @@ export function getProblemSetList( difficulty = "", status = "", ) { - return api.get("admin/problem-sets", { + return api.get("admin/problem-sets", { params: { offset, limit, keyword, difficulty, status }, }) } export function getProblemSetDetail(id: number) { - return api.get(`admin/problem-sets/${id}`) + return api.get(`admin/problem-sets/${id}`) } interface ProblemSetBody { title?: string description?: string - difficulty?: ProblemSet["difficulty"] - status?: ProblemSet["status"] + difficulty?: AdminProblemSet["difficulty"] + status?: AdminProblemSet["status"] // 表单里是 Date,出站要 ISO 串 endTime?: Date | null visible?: boolean @@ -529,11 +529,11 @@ function toProblemSetBody(data: ProblemSetBody) { } export function createProblemSet(data: ProblemSetBody) { - return api.post("admin/problem-sets", toProblemSetBody(data)) + return api.post("admin/problem-sets", toProblemSetBody(data)) } export function editProblemSet(data: ProblemSetBody & { id: number }) { - return api.put( + return api.put( `admin/problem-sets/${data.id}`, toProblemSetBody(data), ) @@ -544,16 +544,16 @@ export function deleteProblemSet(id: number) { } export function toggleProblemSetVisible(id: number) { - return api.put(`admin/problem-sets/${id}/visibility`) + return api.put(`admin/problem-sets/${id}/visibility`) } export function updateProblemSetStatus(id: number, status: string) { - return api.put(`admin/problem-sets/${id}/status`, { status }) + return api.put(`admin/problem-sets/${id}/status`, { status }) } // 题单题目管理 API export function getProblemSetProblems(problemSetId: number) { - return api.get( + return api.get( `admin/problem-sets/${problemSetId}/problems`, ) } @@ -604,7 +604,7 @@ export function removeProblemFromSet( // 题单奖章管理 API export function getProblemSetBadges(problemSetId: number) { - return api.get( + return api.get( `admin/problem-sets/${problemSetId}/badges`, ) } @@ -613,7 +613,7 @@ interface BadgeBody { name?: string description?: string icon?: string - conditionType?: ProblemSetBadge["conditionType"] + conditionType?: AdminProblemSetBadge["conditionType"] conditionValue?: number } @@ -628,7 +628,7 @@ function toBadgeBody(data: BadgeBody) { } export function createProblemSetBadge(problemSetId: number, data: BadgeBody) { - return api.post( + return api.post( `admin/problem-sets/${problemSetId}/badges`, toBadgeBody(data), ) @@ -639,7 +639,7 @@ export function editProblemSetBadge( badgeId: number, data: BadgeBody, ) { - return api.put( + return api.put( `admin/problem-sets/${problemSetId}/badges/${badgeId}`, toBadgeBody(data), ) diff --git a/apps/web/src/admin/problemset/components/AddBadgeModal.vue b/apps/web/src/admin/problemset/components/AddBadgeModal.vue index 5213901..49392e2 100644 --- a/apps/web/src/admin/problemset/components/AddBadgeModal.vue +++ b/apps/web/src/admin/problemset/components/AddBadgeModal.vue @@ -11,8 +11,8 @@ interface Emits { name: string description: string icon: string - condition_type: "all_problems" | "problem_count" | "score" - condition_value?: number + conditionType: "all_problems" | "problem_count" | "score" + conditionValue?: number }, ): void } @@ -45,19 +45,16 @@ const conditionTypeOptions = [ ] function handleConfirm() { - const data: any = { + emit("confirm", { name: newBadgeName.value, description: newBadgeDescription.value, icon: newBadgeIcon.value, - condition_type: newBadgeConditionType.value, - } - - // 只有非"完成所有题目"时才添加条件值 - if (newBadgeConditionType.value !== "all_problems") { - data.conditionValue = newBadgeConditionValue.value - } - - emit("confirm", data) + conditionType: newBadgeConditionType.value, + // 只有非"完成所有题目"时才带条件值 + ...(newBadgeConditionType.value === "all_problems" + ? {} + : { conditionValue: newBadgeConditionValue.value }), + }) } function handleCancel() { diff --git a/apps/web/src/admin/problemset/components/AddProblemModal.vue b/apps/web/src/admin/problemset/components/AddProblemModal.vue index 90cfece..1a6ef62 100644 --- a/apps/web/src/admin/problemset/components/AddProblemModal.vue +++ b/apps/web/src/admin/problemset/components/AddProblemModal.vue @@ -8,9 +8,9 @@ interface Emits { ( e: "confirm", data: { - problem_id: string + problemId: string order: number - is_required: boolean + isRequired: boolean score: number hint: string }, @@ -28,9 +28,9 @@ const newProblemHint = ref("") function handleConfirm() { emit("confirm", { - problem_id: newProblemId.value, + problemId: newProblemId.value, order: newProblemOrder.value, - is_required: newProblemRequired.value, + isRequired: newProblemRequired.value, score: newProblemScore.value, hint: newProblemHint.value, }) diff --git a/apps/web/src/admin/problemset/components/BadgeManagement.vue b/apps/web/src/admin/problemset/components/BadgeManagement.vue index b6a81c4..c424cda 100644 --- a/apps/web/src/admin/problemset/components/BadgeManagement.vue +++ b/apps/web/src/admin/problemset/components/BadgeManagement.vue @@ -1,15 +1,15 @@