两件事: 1. 内嵌的 submission 之前复用 submissionDetailSchema 并把 info / ip 写死成空值, 于是键仍留在响应里。旧 SubmissionSafeModelSerializer 是 exclude,这三个键 根本不出现。改成独立的 embeddedSubmissionSchema —— 形状对上了,将来有人 把空值改成真值也不会变成泄露,因为这里压根没有这三个字段。 2. 顺带修掉一个评审没覆盖的真回归:内嵌 submission 给的是 problemId(数字主键), 而旧 serializer 的 problem 是 SlugRelatedField(slug_field="_id"),即展示用题号。 oj/user/message.vue:20 拿它拼 /problem/<题号>,迁移后拼出的是 /problem/undefined, 题号那一栏也是空的。改为下发 problem,实测返回 "1004"。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75 lines
1.9 KiB
TypeScript
75 lines
1.9 KiB
TypeScript
import { z } from "zod"
|
|
|
|
import { paginatedSchema, sampleUserSchema } from "./common"
|
|
import { embeddedSubmissionSchema } from "./submission"
|
|
|
|
export const announcementSchema = z.object({
|
|
id: z.number().int(),
|
|
title: z.string(),
|
|
tag: z.string(),
|
|
content: z.string().optional(),
|
|
top: z.boolean(),
|
|
createdBy: sampleUserSchema,
|
|
createTime: z.string(),
|
|
lastUpdateTime: z.string(),
|
|
})
|
|
|
|
export const announcementListSchema = paginatedSchema(announcementSchema)
|
|
|
|
export const messageSchema = z.object({
|
|
id: z.number().int(),
|
|
sender: sampleUserSchema,
|
|
createTime: z.string(),
|
|
message: z.string(),
|
|
submission: embeddedSubmissionSchema,
|
|
})
|
|
|
|
export const messageListSchema = paginatedSchema(messageSchema)
|
|
|
|
export const createMessageRequestSchema = z.object({
|
|
recipientId: z.number().int().positive(),
|
|
submissionId: z.string().min(1),
|
|
message: z.string().min(1).max(1024 * 1024),
|
|
})
|
|
|
|
export const reactionKeySchema = z.enum([
|
|
"too_easy",
|
|
"too_hard",
|
|
"confusing",
|
|
"buggy",
|
|
"learned",
|
|
"interesting",
|
|
"want_explain",
|
|
])
|
|
|
|
export const reactionCountsSchema = z.record(reactionKeySchema, z.number().int())
|
|
export const reactionStateSchema = z.object({
|
|
mine: reactionKeySchema.nullable(),
|
|
counts: reactionCountsSchema.nullable(),
|
|
})
|
|
|
|
export const setReactionRequestSchema = z.object({ type: reactionKeySchema })
|
|
|
|
export const tutorialSummarySchema = z.object({
|
|
id: z.number().int(),
|
|
title: z.string(),
|
|
})
|
|
|
|
export const tutorialSchema = tutorialSummarySchema.extend({
|
|
content: z.string(),
|
|
code: z.string().nullable(),
|
|
isPublic: z.boolean(),
|
|
order: z.number().int(),
|
|
type: z.enum(["python", "c"]),
|
|
createdBy: sampleUserSchema,
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
})
|
|
|
|
export const exerciseSchema = z.object({
|
|
id: z.number().int(),
|
|
type: z.enum(["mcq", "sort", "fill", "match", "predict", "debug", "group"]),
|
|
data: z.record(z.string(), z.unknown()),
|
|
order: z.number().int(),
|
|
})
|