- 前端 oj/api.ts、admin/api.ts、shared/api.ts 的 post / put 请求体一律 `satisfies XxxRequest`, 只在编译期检查,不加运行时校验(和「只在三处挂运行时闸门」的规矩一致) - 契约里的 XxxRequest 从 z.infer 改成 z.input:请求类型描述的是「客户端可以发什么」, 带默认值的字段可以不传。后端从不用这些类型(它用 parse 出来的 data),不受影响 - 补了四个漏导出的请求类型(比赛题目排序、题单题目排序、标签分类、检查用户名) - 接上之后对不上的几处:编辑用户的角色和题目权限经 toAdminType / toProblemPermission 收窄,导入用户的行改成四元组,练习题数据改成 Record,格式化的语言只收后端认的四种 (isFormatLanguage)。出题页和成就的请求体是「表单校验兜底、出站补默认值」, 用 Partial<…> 只核键名和值的类型 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
309ca0ece2
commit
4dfd14f95b
18 files changed
+251
-131
No files matched your search
+145
-47
@@ -1,3 +1,44 @@
|
|||||||
|
import { toAdminType, toProblemPermission } from "@oj2/contract"
|
||||||
|
import type {
|
||||||
|
AddContestProblemRequest,
|
||||||
|
AddProblemsToSetRequest,
|
||||||
|
BatchProblemTagRequest,
|
||||||
|
BatchProblemVisibleRequest,
|
||||||
|
CheckUsernamesRequest,
|
||||||
|
CreateAchievementRequest,
|
||||||
|
CreateAnnouncementRequest,
|
||||||
|
CreateContestRequest,
|
||||||
|
CreateExerciseRequest,
|
||||||
|
CreateProblemRequest,
|
||||||
|
CreateProblemSetBadgeRequest,
|
||||||
|
CreateProblemSetRequest,
|
||||||
|
CreateTutorialRequest,
|
||||||
|
GenerateFlowchartRequest,
|
||||||
|
GenerateSqlTestCaseRequest,
|
||||||
|
ImportUsersRequest,
|
||||||
|
MakeProblemPublicRequest,
|
||||||
|
RenameTagRequest,
|
||||||
|
RenameTutorialProjectRequest,
|
||||||
|
ReorderContestProblemsRequest,
|
||||||
|
ReorderProblemSetProblemsRequest,
|
||||||
|
ReorderTutorialsRequest,
|
||||||
|
SetTagCategoryRequest,
|
||||||
|
SetTutorialProblemsRequest,
|
||||||
|
SetTutorialVisibilityRequest,
|
||||||
|
SqlPreviewRequest,
|
||||||
|
UpdateAchievementRequest,
|
||||||
|
UpdateAcmHelperRequest,
|
||||||
|
UpdateAnnouncementRequest,
|
||||||
|
UpdateContestRequest,
|
||||||
|
UpdateExerciseRequest,
|
||||||
|
UpdateProblemInSetRequest,
|
||||||
|
UpdateProblemRequest,
|
||||||
|
UpdateProblemSetBadgeRequest,
|
||||||
|
UpdateProblemSetRequest,
|
||||||
|
UpdateTutorialRequest,
|
||||||
|
UpdateUserRequest,
|
||||||
|
UpdateWebsiteConfigRequest,
|
||||||
|
} from "@oj2/contract"
|
||||||
import api from "utils/api"
|
import api from "utils/api"
|
||||||
import { toAdminProblemRow } from "admin/transforms"
|
import { toAdminProblemRow } from "admin/transforms"
|
||||||
import type {
|
import type {
|
||||||
@@ -101,7 +142,7 @@ export function batchSetProblemVisible(problemIds: number[], visible: boolean) {
|
|||||||
return api.post<{ problemCount: number }>("admin/problems/batch-visible", {
|
return api.post<{ problemCount: number }>("admin/problems/batch-visible", {
|
||||||
problemIds,
|
problemIds,
|
||||||
visible,
|
visible,
|
||||||
})
|
} satisfies BatchProblemVisibleRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 比赛「从题库中选择」用:列所有可见的公开题,不只是自己创建的
|
// 比赛「从题库中选择」用:列所有可见的公开题,不只是自己创建的
|
||||||
@@ -129,7 +170,7 @@ export function deleteContestProblem(id: number) {
|
|||||||
export function editProblem(problem: AdminProblem | BlankProblem) {
|
export function editProblem(problem: AdminProblem | BlankProblem) {
|
||||||
return api.put<AdminProblem>(
|
return api.put<AdminProblem>(
|
||||||
`admin/problems/${(problem as AdminProblem).id}`,
|
`admin/problems/${(problem as AdminProblem).id}`,
|
||||||
toProblemBody(problem),
|
toProblemBody(problem) satisfies Partial<UpdateProblemRequest>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +181,7 @@ export function toggleProblemVisible(problemID: number) {
|
|||||||
export function generateFlowchartFromPythonCode(python: string) {
|
export function generateFlowchartFromPythonCode(python: string) {
|
||||||
return api.post<{ doc: Record<string, unknown> }>("admin/problems/flowchart", {
|
return api.post<{ doc: Record<string, unknown> }>("admin/problems/flowchart", {
|
||||||
python,
|
python,
|
||||||
})
|
} satisfies GenerateFlowchartRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProblem(id: string | number) {
|
export function getProblem(id: string | number) {
|
||||||
@@ -153,11 +194,13 @@ export function getTagAdminList(keyword = "") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function renameTag(id: number, name: string) {
|
export function renameTag(id: number, name: string) {
|
||||||
return api.put<RenameTagResponse>(`admin/problem-tags/${id}`, { name })
|
return api.put<RenameTagResponse>(`admin/problem-tags/${id}`, { name } satisfies RenameTagRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setTagCategory(id: number, category: TagCategory) {
|
export function setTagCategory(id: number, category: TagCategory) {
|
||||||
return api.put<null>(`admin/problem-tags/${id}/category`, { category })
|
return api.put<null>(`admin/problem-tags/${id}/category`, {
|
||||||
|
category,
|
||||||
|
} satisfies SetTagCategoryRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteTag(id: number) {
|
export function deleteTag(id: number) {
|
||||||
@@ -173,7 +216,7 @@ export function batchTagProblems(
|
|||||||
problemIds,
|
problemIds,
|
||||||
tagNames,
|
tagNames,
|
||||||
action,
|
action,
|
||||||
})
|
} satisfies BatchProblemTagRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户排名(后台版,无 100 名上限;公开榜单是 oj/api.ts 的 getRank)
|
// 用户排名(后台版,无 100 名上限;公开榜单是 oj/api.ts 的 getRank)
|
||||||
@@ -209,20 +252,23 @@ export function getUserList(
|
|||||||
|
|
||||||
/** 批量建号之前查重:这些用户名哪些已经有了 */
|
/** 批量建号之前查重:这些用户名哪些已经有了 */
|
||||||
export function checkUsernames(usernames: string[]) {
|
export function checkUsernames(usernames: string[]) {
|
||||||
return api.post<CheckUsernamesResponse>("admin/users/check", { usernames })
|
return api.post<CheckUsernamesResponse>("admin/users/check", {
|
||||||
|
usernames,
|
||||||
|
} satisfies CheckUsernamesRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑用户
|
// 编辑用户
|
||||||
export function editUser(user: AdminUserForm) {
|
export function editUser(user: AdminUserForm) {
|
||||||
return api.put<AdminUser>(`admin/users/${user.id}`, {
|
return api.put<AdminUser>(`admin/users/${user.id}`, {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
email: user.email,
|
// 库里 email 没有空的(2026-10 核过),响应类型是 nullable 只因为列可空
|
||||||
adminType: user.adminType,
|
email: user.email ?? "",
|
||||||
problemPermission: user.problemPermission,
|
adminType: toAdminType(user.adminType),
|
||||||
|
problemPermission: toProblemPermission(user.problemPermission),
|
||||||
realName: user.realName ?? null,
|
realName: user.realName ?? null,
|
||||||
isDisabled: user.isDisabled,
|
isDisabled: user.isDisabled,
|
||||||
password: user.password ?? "",
|
password: user.password ?? "",
|
||||||
})
|
} satisfies UpdateUserRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置用户密码,返回新密码
|
// 重置用户密码,返回新密码
|
||||||
@@ -233,8 +279,10 @@ export async function resetPassword(userID: number) {
|
|||||||
|
|
||||||
// 导入用户
|
// 导入用户
|
||||||
/** 批量建号。addedClasses:这批里的新班级,后端已经顺手加进了班级列表 */
|
/** 批量建号。addedClasses:这批里的新班级,后端已经顺手加进了班级列表 */
|
||||||
export function importUsers(users: string[][]) {
|
export function importUsers(users: ImportUsersRequest["users"]) {
|
||||||
return api.post<{ imported: number; addedClasses: string[] }>("admin/users", { users })
|
return api.post<{ imported: number; addedClasses: string[] }>("admin/users", {
|
||||||
|
users,
|
||||||
|
} satisfies ImportUsersRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量删除用户
|
// 批量删除用户
|
||||||
@@ -282,7 +330,7 @@ export function previewSQLTestcase(data: {
|
|||||||
/** 是不是题面上展示的那组(第 1 组):增删改题只有它必须改到行 */
|
/** 是不是题面上展示的那组(第 1 组):增删改题只有它必须改到行 */
|
||||||
shown: boolean
|
shown: boolean
|
||||||
}) {
|
}) {
|
||||||
return api.post<SqlDisplay>("admin/sql-test-cases/preview", data)
|
return api.post<SqlDisplay>("admin/sql-test-cases/preview", data satisfies SqlPreviewRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回显已上传的 SQL 测试点脚本内容(按 1.sql, 2.sql... 排序)
|
// 回显已上传的 SQL 测试点脚本内容(按 1.sql, 2.sql... 排序)
|
||||||
@@ -292,7 +340,10 @@ export function getSQLTestcaseScripts(problemId: number) {
|
|||||||
|
|
||||||
// AI 根据标准答案生成一个 SQL 测试点初始化脚本
|
// AI 根据标准答案生成一个 SQL 测试点初始化脚本
|
||||||
export function generateSQLTestcase(data: { refSql: string; mode: "query" | "modify" }) {
|
export function generateSQLTestcase(data: { refSql: string; mode: "query" | "modify" }) {
|
||||||
return api.post<GenerateSqlTestCaseResponse>("admin/sql-test-cases/generate", data)
|
return api.post<GenerateSqlTestCaseResponse>(
|
||||||
|
"admin/sql-test-cases/generate",
|
||||||
|
data satisfies GenerateSqlTestCaseRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编程题出题页:读回已有测试点的原文(太大的只给数量和大小)
|
// 编程题出题页:读回已有测试点的原文(太大的只给数量和大小)
|
||||||
@@ -302,12 +353,15 @@ export function getTestCaseFiles(problemId: number) {
|
|||||||
|
|
||||||
// 拿标准答案自测语法要求
|
// 拿标准答案自测语法要求
|
||||||
export function checkAstRules(data: AstCheckRequest) {
|
export function checkAstRules(data: AstCheckRequest) {
|
||||||
return api.post<AstCheckResponse>("admin/ast-check", data)
|
return api.post<AstCheckResponse>("admin/ast-check", data satisfies AstCheckRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI 按题面和标准答案想几组测试输入(输出由标准答案跑)
|
// AI 按题面和标准答案想几组测试输入(输出由标准答案跑)
|
||||||
export function generateTestInputs(data: GenerateTestInputsRequest) {
|
export function generateTestInputs(data: GenerateTestInputsRequest) {
|
||||||
return api.post<GenerateTestInputsResponse>("admin/test-inputs/generate", data)
|
return api.post<GenerateTestInputsResponse>(
|
||||||
|
"admin/test-inputs/generate",
|
||||||
|
data satisfies GenerateTestInputsRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 出站补默认值。字段名两边已经一致,不再做键名转换 */
|
/** 出站补默认值。字段名两边已经一致,不再做键名转换 */
|
||||||
@@ -346,14 +400,17 @@ function toProblemBody(problem: AdminProblem | BlankProblem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createProblem(problem: BlankProblem) {
|
export function createProblem(problem: BlankProblem) {
|
||||||
return api.post<AdminProblem>("admin/problems", toProblemBody(problem))
|
return api.post<AdminProblem>(
|
||||||
|
"admin/problems",
|
||||||
|
toProblemBody(problem) satisfies Partial<CreateProblemRequest>,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createContestProblem(problem: BlankProblem) {
|
export function createContestProblem(problem: BlankProblem) {
|
||||||
// contestId 由 detail.vue 在提交前写进 problem 对象
|
// contestId 由 detail.vue 在提交前写进 problem 对象
|
||||||
return api.post<AdminProblem>(
|
return api.post<AdminProblem>(
|
||||||
`admin/contests/${problem.contestId}/problems`,
|
`admin/contests/${problem.contestId}/problems`,
|
||||||
toProblemBody(problem),
|
toProblemBody(problem) satisfies Partial<CreateProblemRequest>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,13 +428,16 @@ function toContestBody(contest: AdminContest | BlankContest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createContest(contest: BlankContest) {
|
export function createContest(contest: BlankContest) {
|
||||||
return api.post<AdminContest>("admin/contests", toContestBody(contest))
|
return api.post<AdminContest>(
|
||||||
|
"admin/contests",
|
||||||
|
toContestBody(contest) satisfies CreateContestRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editContest(contest: AdminContest | BlankContest) {
|
export function editContest(contest: AdminContest | BlankContest) {
|
||||||
return api.put<AdminContest>(
|
return api.put<AdminContest>(
|
||||||
`admin/contests/${(contest as AdminContest).id}`,
|
`admin/contests/${(contest as AdminContest).id}`,
|
||||||
toContestBody(contest),
|
toContestBody(contest) satisfies UpdateContestRequest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,12 +453,14 @@ export function addProblemForContest(contestID: string, problemID: number, displ
|
|||||||
return api.post<AdminProblem>(`admin/contests/${contestID}/problems/from-public`, {
|
return api.post<AdminProblem>(`admin/contests/${contestID}/problems/from-public`, {
|
||||||
problemId: problemID,
|
problemId: problemID,
|
||||||
displayId: displayID,
|
displayId: displayID,
|
||||||
})
|
} satisfies AddContestProblemRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 比赛题按这个顺序重新编号 1、2、3…(要给全这场比赛的题) */
|
/** 比赛题按这个顺序重新编号 1、2、3…(要给全这场比赛的题) */
|
||||||
export function reorderContestProblems(contestID: string, problemIds: number[]) {
|
export function reorderContestProblems(contestID: string, problemIds: number[]) {
|
||||||
return api.put(`admin/contests/${contestID}/problems/order`, { problemIds })
|
return api.put(`admin/contests/${contestID}/problems/order`, {
|
||||||
|
problemIds,
|
||||||
|
} satisfies ReorderContestProblemsRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWebsite() {
|
export function getWebsite() {
|
||||||
@@ -406,7 +468,7 @@ export function getWebsite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function editWebsite(data: WebsiteConfig) {
|
export function editWebsite(data: WebsiteConfig) {
|
||||||
return api.post<WebsiteConfig>("admin/website", data)
|
return api.post<WebsiteConfig>("admin/website", data satisfies UpdateWebsiteConfigRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listInvalidTestcases() {
|
export function listInvalidTestcases() {
|
||||||
@@ -441,12 +503,18 @@ export function deleteAnnouncement(id: number) {
|
|||||||
|
|
||||||
export function editAnnouncement(announcement: AnnouncementEdit) {
|
export function editAnnouncement(announcement: AnnouncementEdit) {
|
||||||
const { id, ...body } = announcement
|
const { id, ...body } = announcement
|
||||||
return api.put<AdminAnnouncement>(`admin/announcements/${id}`, body)
|
return api.put<AdminAnnouncement>(
|
||||||
|
`admin/announcements/${id}`,
|
||||||
|
body satisfies UpdateAnnouncementRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createAnnouncement(announcement: AnnouncementEdit) {
|
export function createAnnouncement(announcement: AnnouncementEdit) {
|
||||||
const { id: _id, ...body } = announcement
|
const { id: _id, ...body } = announcement
|
||||||
return api.post<AdminAnnouncement>("admin/announcements", body)
|
return api.post<AdminAnnouncement>(
|
||||||
|
"admin/announcements",
|
||||||
|
body satisfies CreateAnnouncementRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTutorialList() {
|
export function getTutorialList() {
|
||||||
@@ -470,15 +538,20 @@ function toTutorialBody(data: TutorialEdit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createTutorial(data: TutorialEdit) {
|
export function createTutorial(data: TutorialEdit) {
|
||||||
return api.post<Tutorial>("admin/tutorials", toTutorialBody(data))
|
return api.post<Tutorial>("admin/tutorials", toTutorialBody(data) satisfies CreateTutorialRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateTutorial(data: TutorialEdit) {
|
export function updateTutorial(data: TutorialEdit) {
|
||||||
return api.put<Tutorial>(`admin/tutorials/${data.id}`, toTutorialBody(data))
|
return api.put<Tutorial>(
|
||||||
|
`admin/tutorials/${data.id}`,
|
||||||
|
toTutorialBody(data) satisfies UpdateTutorialRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setTutorialProblems(id: number, problemIds: number[]) {
|
export function setTutorialProblems(id: number, problemIds: number[]) {
|
||||||
return api.put<Tutorial>(`admin/tutorials/${id}/problems`, { problemIds })
|
return api.put<Tutorial>(`admin/tutorials/${id}/problems`, {
|
||||||
|
problemIds,
|
||||||
|
} satisfies SetTutorialProblemsRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTutorialProblemCandidates(keyword: string) {
|
export function getTutorialProblemCandidates(keyword: string) {
|
||||||
@@ -488,11 +561,15 @@ export function getTutorialProblemCandidates(keyword: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function reorderTutorials(ids: number[]) {
|
export function reorderTutorials(ids: number[]) {
|
||||||
return api.put<null>("admin/tutorial-order", { ids })
|
return api.put<null>("admin/tutorial-order", { ids } satisfies ReorderTutorialsRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renameTutorialProject(type: "python" | "c", from: string, to: string) {
|
export function renameTutorialProject(type: "python" | "c", from: string, to: string) {
|
||||||
return api.put<null>("admin/tutorial-projects", { type, from, to })
|
return api.put<null>("admin/tutorial-projects", {
|
||||||
|
type,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
} satisfies RenameTutorialProjectRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteTutorial(id: number) {
|
export function deleteTutorial(id: number) {
|
||||||
@@ -500,7 +577,9 @@ export function deleteTutorial(id: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function setTutorialVisibility(id: number, isPublic: boolean) {
|
export function setTutorialVisibility(id: number, isPublic: boolean) {
|
||||||
return api.put<Tutorial>(`admin/tutorials/${id}/visibility`, { isPublic })
|
return api.put<Tutorial>(`admin/tutorials/${id}/visibility`, {
|
||||||
|
isPublic,
|
||||||
|
} satisfies SetTutorialVisibilityRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAdminExercises(tutorialId: number) {
|
export function getAdminExercises(tutorialId: number) {
|
||||||
@@ -510,16 +589,16 @@ export function getAdminExercises(tutorialId: number) {
|
|||||||
export async function createExercise(data: {
|
export async function createExercise(data: {
|
||||||
tutorialId: number
|
tutorialId: number
|
||||||
type: ExerciseType
|
type: ExerciseType
|
||||||
data: object
|
data: Record<string, unknown>
|
||||||
order: number
|
order: number
|
||||||
}) {
|
}) {
|
||||||
return api.post<Exercise>("admin/exercises", data)
|
return api.post<Exercise>("admin/exercises", data satisfies CreateExerciseRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateExercise(data: {
|
export async function updateExercise(data: {
|
||||||
id: number
|
id: number
|
||||||
type: ExerciseType
|
type: ExerciseType
|
||||||
data: object
|
data: Record<string, unknown>
|
||||||
order: number
|
order: number
|
||||||
resetAttempts: boolean
|
resetAttempts: boolean
|
||||||
}) {
|
}) {
|
||||||
@@ -528,7 +607,7 @@ export async function updateExercise(data: {
|
|||||||
data: data.data,
|
data: data.data,
|
||||||
order: data.order,
|
order: data.order,
|
||||||
resetAttempts: data.resetAttempts,
|
resetAttempts: data.resetAttempts,
|
||||||
})
|
} satisfies UpdateExerciseRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteExercise(id: number) {
|
export function deleteExercise(id: number) {
|
||||||
@@ -539,7 +618,7 @@ export function deleteExercise(id: number) {
|
|||||||
export function makeProblemPublic(id: number, displayId: string) {
|
export function makeProblemPublic(id: number, displayId: string) {
|
||||||
return api.post<AdminProblem>(`admin/problems/${id}/make-public`, {
|
return api.post<AdminProblem>(`admin/problems/${id}/make-public`, {
|
||||||
displayId,
|
displayId,
|
||||||
})
|
} satisfies MakeProblemPublicRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 比赛辅助检查
|
// 比赛辅助检查
|
||||||
@@ -553,7 +632,7 @@ export function updateACMHelperChecked(
|
|||||||
rankId: rank_id,
|
rankId: rank_id,
|
||||||
problemId: problem_id,
|
problemId: problem_id,
|
||||||
checked,
|
checked,
|
||||||
})
|
} satisfies UpdateAcmHelperRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 题单管理 API
|
// 题单管理 API
|
||||||
@@ -576,11 +655,14 @@ export interface ProblemSetBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createProblemSet(data: ProblemSetBody) {
|
export function createProblemSet(data: ProblemSetBody) {
|
||||||
return api.post<AdminProblemSet>("admin/problem-sets", data)
|
return api.post<AdminProblemSet>("admin/problem-sets", data satisfies CreateProblemSetRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editProblemSet(id: number, data: ProblemSetBody) {
|
export function editProblemSet(id: number, data: ProblemSetBody) {
|
||||||
return api.put<AdminProblemSet>(`admin/problem-sets/${id}`, data)
|
return api.put<AdminProblemSet>(
|
||||||
|
`admin/problem-sets/${id}`,
|
||||||
|
data satisfies UpdateProblemSetRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteProblemSet(id: number) {
|
export function deleteProblemSet(id: number) {
|
||||||
@@ -600,15 +682,19 @@ export function getProblemSetProblems(problemSetId: number) {
|
|||||||
export function addProblemsToSet(problemSetId: number, problemIds: string[]) {
|
export function addProblemsToSet(problemSetId: number, problemIds: string[]) {
|
||||||
return api.post<AddProblemsToSetResult>(`admin/problem-sets/${problemSetId}/problems`, {
|
return api.post<AddProblemsToSetResult>(`admin/problem-sets/${problemSetId}/problems`, {
|
||||||
problemIds,
|
problemIds,
|
||||||
})
|
} satisfies AddProblemsToSetRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setProblemRequired(problemSetId: number, itemId: number, isRequired: boolean) {
|
export function setProblemRequired(problemSetId: number, itemId: number, isRequired: boolean) {
|
||||||
return api.put(`admin/problem-sets/${problemSetId}/problems/${itemId}`, { isRequired })
|
return api.put(`admin/problem-sets/${problemSetId}/problems/${itemId}`, {
|
||||||
|
isRequired,
|
||||||
|
} satisfies UpdateProblemInSetRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reorderProblemSetProblems(problemSetId: number, ids: number[]) {
|
export function reorderProblemSetProblems(problemSetId: number, ids: number[]) {
|
||||||
return api.put(`admin/problem-sets/${problemSetId}/problems/order`, { ids })
|
return api.put(`admin/problem-sets/${problemSetId}/problems/order`, {
|
||||||
|
ids,
|
||||||
|
} satisfies ReorderProblemSetProblemsRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeProblemFromSet(problemSetId: number, itemId: number) {
|
export function removeProblemFromSet(problemSetId: number, itemId: number) {
|
||||||
@@ -629,11 +715,17 @@ export interface BadgeBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createProblemSetBadge(problemSetId: number, data: BadgeBody) {
|
export function createProblemSetBadge(problemSetId: number, data: BadgeBody) {
|
||||||
return api.post<AdminProblemSetBadge>(`admin/problem-sets/${problemSetId}/badges`, data)
|
return api.post<AdminProblemSetBadge>(
|
||||||
|
`admin/problem-sets/${problemSetId}/badges`,
|
||||||
|
data satisfies CreateProblemSetBadgeRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editProblemSetBadge(problemSetId: number, badgeId: number, data: BadgeBody) {
|
export function editProblemSetBadge(problemSetId: number, badgeId: number, data: BadgeBody) {
|
||||||
return api.put<AdminProblemSetBadge>(`admin/problem-sets/${problemSetId}/badges/${badgeId}`, data)
|
return api.put<AdminProblemSetBadge>(
|
||||||
|
`admin/problem-sets/${problemSetId}/badges/${badgeId}`,
|
||||||
|
data satisfies UpdateProblemSetBadgeRequest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteProblemSetBadge(problemSetId: number, badgeId: number) {
|
export function deleteProblemSetBadge(problemSetId: number, badgeId: number) {
|
||||||
@@ -728,11 +820,17 @@ export function getMetricOptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createAchievement(data: Partial<AdminAchievement>) {
|
export function createAchievement(data: Partial<AdminAchievement>) {
|
||||||
return api.post<AdminAchievement>("admin/achievements", toAchievementBody(data))
|
return api.post<AdminAchievement>(
|
||||||
|
"admin/achievements",
|
||||||
|
toAchievementBody(data) satisfies Partial<CreateAchievementRequest>,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateAchievement(data: Partial<AdminAchievement>) {
|
export function updateAchievement(data: Partial<AdminAchievement>) {
|
||||||
return api.put<AdminAchievement>(`admin/achievements/${data.id}`, toAchievementBody(data))
|
return api.put<AdminAchievement>(
|
||||||
|
`admin/achievements/${data.id}`,
|
||||||
|
toAchievementBody(data) satisfies Partial<UpdateAchievementRequest>,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteAchievement(id: number) {
|
export function deleteAchievement(id: number) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { ImportUsersRequest } from "@oj2/contract"
|
||||||
import { downloadAccountsCsv } from "./accountsCsv"
|
import { downloadAccountsCsv } from "./accountsCsv"
|
||||||
import PageHeader from "admin/components/PageHeader.vue"
|
import PageHeader from "admin/components/PageHeader.vue"
|
||||||
import { classLabel } from "utils/classes"
|
import { classLabel } from "utils/classes"
|
||||||
@@ -127,7 +128,7 @@ async function submit() {
|
|||||||
// 占位邮箱必须全站唯一:注册、编辑用户、导入三条路都查重。每批一段随机后缀错开,
|
// 占位邮箱必须全站唯一:注册、编辑用户、导入三条路都查重。每批一段随机后缀错开,
|
||||||
// 同一个班分两批导也不会撞。这个地址不发给任何人,纯占位
|
// 同一个班分两批导也不会撞。这个地址不发给任何人,纯占位
|
||||||
const batch = Math.random().toString(36).slice(2, 8)
|
const batch = Math.random().toString(36).slice(2, 8)
|
||||||
const payload = rows.value.map((row, i) => [
|
const payload: ImportUsersRequest["users"] = rows.value.map((row, i) => [
|
||||||
row.username,
|
row.username,
|
||||||
row.password,
|
row.password,
|
||||||
`${prefix.value || "user"}.${batch}.${i + 1}@example.com`,
|
`${prefix.value || "user"}.${batch}.${i + 1}@example.com`,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import UserNameCell from "./components/UserNameCell.vue"
|
|||||||
import PasswordCell from "./components/PasswordCell.vue"
|
import PasswordCell from "./components/PasswordCell.vue"
|
||||||
import { PROBLEM_PERMISSION, USER_TYPE } from "utils/constants"
|
import { PROBLEM_PERMISSION, USER_TYPE } from "utils/constants"
|
||||||
import { useRouteQuery } from "@vueuse/router"
|
import { useRouteQuery } from "@vueuse/router"
|
||||||
import { NO_CLASS, STUDENT_ROLES } from "@oj2/contract"
|
import { NO_CLASS, STUDENT_ROLES, type ImportUsersRequest } from "@oj2/contract"
|
||||||
import { downloadAccountsCsv } from "./accountsCsv"
|
import { downloadAccountsCsv } from "./accountsCsv"
|
||||||
import { classLabel, groupClassOptions } from "utils/classes"
|
import { classLabel, groupClassOptions } from "utils/classes"
|
||||||
import { useConfigStore } from "shared/store/config"
|
import { useConfigStore } from "shared/store/config"
|
||||||
@@ -338,7 +338,7 @@ async function handleEditUser() {
|
|||||||
// 其余业务错误(比如班级号位数不对)不接住就什么都不显示
|
// 其余业务错误(比如班级号位数不对)不接住就什么都不显示
|
||||||
try {
|
try {
|
||||||
if (create.value) {
|
if (create.value) {
|
||||||
const newUser = [
|
const newUser: ImportUsersRequest["users"] = [
|
||||||
[
|
[
|
||||||
userEditing.value.username,
|
userEditing.value.username,
|
||||||
password.value,
|
password.value,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { MarkAchievementsRead } from "@oj2/contract"
|
||||||
import api from "utils/api"
|
import api from "utils/api"
|
||||||
import type { AchievementList, PendingAchievement } from "utils/types"
|
import type { AchievementList, PendingAchievement } from "utils/types"
|
||||||
|
|
||||||
@@ -12,5 +13,5 @@ export function getPendingAchievements() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function markAchievementsRead(ids: number[]) {
|
export function markAchievementsRead(ids: number[]) {
|
||||||
return api.post("achievements/pending/read", { ids })
|
return api.post("achievements/pending/read", { ids } satisfies MarkAchievementsRead)
|
||||||
}
|
}
|
||||||
+33
-17
@@ -1,3 +1,14 @@
|
|||||||
|
import type {
|
||||||
|
ClassLessonRequest,
|
||||||
|
ContestPasswordRequest,
|
||||||
|
CreateFlowchartRequest,
|
||||||
|
CreateSubmissionRequest,
|
||||||
|
FormatCodeRequest,
|
||||||
|
JoinProblemSetRequest,
|
||||||
|
RankHiddenRequest,
|
||||||
|
SetReactionRequest,
|
||||||
|
UpdateProfileRequest,
|
||||||
|
} from "@oj2/contract"
|
||||||
import {
|
import {
|
||||||
type AiAnalysisRecord,
|
type AiAnalysisRecord,
|
||||||
type LearningPeriod,
|
type LearningPeriod,
|
||||||
@@ -144,21 +155,20 @@ export async function getSubmission(id: string, attempts = false): Promise<Submi
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function submitCode(data: SubmitCodePayload) {
|
export function submitCode(data: SubmitCodePayload) {
|
||||||
return api.post<CreateSubmissionResponse>("submissions", data)
|
return api.post<CreateSubmissionResponse>("submissions", data satisfies CreateSubmissionRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatCode(data: { code: string; language: string; problemId: number }) {
|
/** 后端格式化认的四种(ruff / clang-format / sqlparse),别的语言提交前不格式化 */
|
||||||
const languages: Record<string, string> = {
|
export function isFormatLanguage(value: string): value is FormatCodeRequest["language"] {
|
||||||
Python: "python",
|
return ["python", "c", "cpp", "sql"].includes(value)
|
||||||
C: "c",
|
}
|
||||||
"C++": "cpp",
|
|
||||||
SQL: "sql",
|
export function formatCode(data: FormatCodeRequest & { problemId: number }) {
|
||||||
}
|
|
||||||
return api.post<FormatCodeResponse>("code/format", {
|
return api.post<FormatCodeResponse>("code/format", {
|
||||||
code: data.code,
|
code: data.code,
|
||||||
language: languages[data.language] ?? data.language.toLowerCase(),
|
language: data.language,
|
||||||
problemId: data.problemId,
|
problemId: data.problemId,
|
||||||
})
|
} satisfies FormatCodeRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSubmissions(params: Partial<SubmissionListPayload>) {
|
export function getSubmissions(params: Partial<SubmissionListPayload>) {
|
||||||
@@ -262,7 +272,7 @@ export function getWeeklyChampions(className?: string) {
|
|||||||
|
|
||||||
/** 老师把学生设成不计入排名 / 恢复 */
|
/** 老师把学生设成不计入排名 / 恢复 */
|
||||||
export function setRankHidden(userId: number, hidden: boolean) {
|
export function setRankHidden(userId: number, hidden: boolean) {
|
||||||
return api.put<null>(`rankings/hidden/${userId}`, { hidden })
|
return api.put<null>(`rankings/hidden/${userId}`, { hidden } satisfies RankHiddenRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 老师清空一个学生的个性签名 */
|
/** 老师清空一个学生的个性签名 */
|
||||||
@@ -294,7 +304,11 @@ export function setClassLesson(
|
|||||||
problemDisplayIds: string[],
|
problemDisplayIds: string[],
|
||||||
language: LessonLanguage | null,
|
language: LessonLanguage | null,
|
||||||
) {
|
) {
|
||||||
return api.put<null>("classroom/lesson", { className, problemDisplayIds, language })
|
return api.put<null>("classroom/lesson", {
|
||||||
|
className,
|
||||||
|
problemDisplayIds,
|
||||||
|
language,
|
||||||
|
} satisfies ClassLessonRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 我的知识点地图(只有自己的,不能查别人) */
|
/** 我的知识点地图(只有自己的,不能查别人) */
|
||||||
@@ -350,7 +364,7 @@ export function getContestAccess(id: string) {
|
|||||||
export function checkContestPassword(contestID: string, password: string) {
|
export function checkContestPassword(contestID: string, password: string) {
|
||||||
return api.post<boolean>(`contests/${encodeURIComponent(contestID)}/access`, {
|
return api.post<boolean>(`contests/${encodeURIComponent(contestID)}/access`, {
|
||||||
password,
|
password,
|
||||||
})
|
} satisfies ContestPasswordRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getContestProblems(contestID: string) {
|
export async function getContestProblems(contestID: string) {
|
||||||
@@ -375,7 +389,7 @@ export function uploadAvatar(file: File) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function updateProfile(data: { realName?: string; mood?: string }) {
|
export function updateProfile(data: { realName?: string; mood?: string }) {
|
||||||
return api.put<Profile>("me/profile", data)
|
return api.put<Profile>("me/profile", data satisfies UpdateProfileRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAnnouncementList(offset = 0, limit = 10) {
|
export function getAnnouncementList(offset = 0, limit = 10) {
|
||||||
@@ -393,7 +407,9 @@ export function getReaction(problemID: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function setReaction(problemID: number, type: ReactionKey) {
|
export function setReaction(problemID: number, type: ReactionKey) {
|
||||||
return api.post<ReactionState>(`problems/${problemID}/reaction`, { type })
|
return api.post<ReactionState>(`problems/${problemID}/reaction`, {
|
||||||
|
type,
|
||||||
|
} satisfies SetReactionRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 个人主页那一页的数据:做对的题、四个时间、本班第几、成就,本人和老师多拿知识点和没做对的题 */
|
/** 个人主页那一页的数据:做对的题、四个时间、本班第几、成就,本人和老师多拿知识点和没做对的题 */
|
||||||
@@ -450,7 +466,7 @@ export function submitFlowchart(data: {
|
|||||||
mermaidCode: string
|
mermaidCode: string
|
||||||
flowchartData: Record<string, unknown> // 压缩之后的,元数据太长了
|
flowchartData: Record<string, unknown> // 压缩之后的,元数据太长了
|
||||||
}) {
|
}) {
|
||||||
return api.post<CreateFlowchartResponse>("flowcharts", data)
|
return api.post<CreateFlowchartResponse>("flowcharts", data satisfies CreateFlowchartRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFlowchartSubmission(id: string) {
|
export function getFlowchartSubmission(id: string) {
|
||||||
@@ -507,7 +523,7 @@ export function getProblemSetProblems(problemSetId: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function joinProblemSet(problemSetId: number) {
|
export function joinProblemSet(problemSetId: number) {
|
||||||
return api.post("problem-set-progress", { problemSetId })
|
return api.post("problem-set-progress", { problemSetId } satisfies JoinProblemSetRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserBadges(username?: string) {
|
export function getUserBadges(username?: string) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from "pinia"
|
import { defineStore } from "pinia"
|
||||||
import { errorCode, errorMessage } from "utils/api"
|
import { errorCode, errorMessage } from "utils/api"
|
||||||
import { formatCode, submitCode } from "oj/api"
|
import { formatCode, isFormatLanguage, submitCode } from "oj/api"
|
||||||
import { useCodeStore } from "oj/store/code"
|
import { useCodeStore } from "oj/store/code"
|
||||||
import { useProblemStore } from "oj/store/problem"
|
import { useProblemStore } from "oj/store/problem"
|
||||||
import { useSubmissionMonitor } from "oj/problem/composables/useSubmissionMonitor"
|
import { useSubmissionMonitor } from "oj/problem/composables/useSubmissionMonitor"
|
||||||
@@ -106,7 +106,7 @@ export const useSubmissionStore = defineStore("submission", () => {
|
|||||||
// Python 在格式化之前先由服务端的 CPython 查一遍语法,有错就不提交;
|
// Python 在格式化之前先由服务端的 CPython 查一遍语法,有错就不提交;
|
||||||
// C / C++ 先在判题机上编一遍,编不过就原样交(格式化会把错的几行并成一行)
|
// C / C++ 先在判题机上编一遍,编不过就原样交(格式化会把错的几行并成一行)
|
||||||
const formatLang = LANGUAGE_FORMAT_VALUE[codeStore.code.language]
|
const formatLang = LANGUAGE_FORMAT_VALUE[codeStore.code.language]
|
||||||
if (["python", "c", "cpp", "sql"].includes(formatLang)) {
|
if (isFormatLanguage(formatLang)) {
|
||||||
isFormatting.value = true
|
isFormatting.value = true
|
||||||
try {
|
try {
|
||||||
const res = await formatCode({
|
const res = await formatCode({
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
|
import type { LoginRequest, RegisterRequest } from "@oj2/contract"
|
||||||
import type { Quote, WebsiteConfig } from "@oj2/contract"
|
import type { Quote, WebsiteConfig } from "@oj2/contract"
|
||||||
import api from "utils/api"
|
import api from "utils/api"
|
||||||
import { contractDeferred } from "utils/contract"
|
import { contractDeferred } from "utils/contract"
|
||||||
import type { Profile, Tag } from "utils/types"
|
import type { Profile, Tag } from "utils/types"
|
||||||
|
|
||||||
export function login(data: { username: string; password: string }) {
|
export function login(data: { username: string; password: string }) {
|
||||||
return api.post("auth/login", data)
|
return api.post("auth/login", data satisfies LoginRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function signup(data: { username: string; email: string; password: string }) {
|
export function signup(data: { username: string; email: string; password: string }) {
|
||||||
return api.post("users", data)
|
return api.post("users", data satisfies RegisterRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ export const problemRankSchema = z.object({
|
|||||||
|
|
||||||
export const publicProfileSchema = userProfileSchema
|
export const publicProfileSchema = userProfileSchema
|
||||||
|
|
||||||
export type RegisterRequest = z.infer<typeof registerRequestSchema>
|
export type RegisterRequest = z.input<typeof registerRequestSchema>
|
||||||
export type UpdateProfileRequest = z.infer<typeof updateProfileRequestSchema>
|
export type UpdateProfileRequest = z.input<typeof updateProfileRequestSchema>
|
||||||
export type ProblemRank = z.infer<typeof problemRankSchema>
|
export type ProblemRank = z.infer<typeof problemRankSchema>
|
||||||
export type RankProfile = z.infer<typeof rankProfileSchema>
|
export type RankProfile = z.infer<typeof rankProfileSchema>
|
||||||
export type WeeklyRankItem = z.infer<typeof weeklyRankItemSchema>
|
export type WeeklyRankItem = z.infer<typeof weeklyRankItemSchema>
|
||||||
|
|||||||
@@ -1118,7 +1118,7 @@ export type AchievementMetric = z.infer<typeof achievementMetricSchema>
|
|||||||
export type AdminProblem = z.infer<typeof adminProblemSchema>
|
export type AdminProblem = z.infer<typeof adminProblemSchema>
|
||||||
export type AdminProblemListItem = z.infer<typeof adminProblemListItemSchema>
|
export type AdminProblemListItem = z.infer<typeof adminProblemListItemSchema>
|
||||||
export type AdminProblemList = z.infer<typeof adminProblemListSchema>
|
export type AdminProblemList = z.infer<typeof adminProblemListSchema>
|
||||||
export type CreateProblemRequest = z.infer<typeof createProblemRequestSchema>
|
export type CreateProblemRequest = z.input<typeof createProblemRequestSchema>
|
||||||
|
|
||||||
export type AdminContest = z.infer<typeof adminContestSchema>
|
export type AdminContest = z.infer<typeof adminContestSchema>
|
||||||
export type AdminContestList = z.infer<typeof adminContestListSchema>
|
export type AdminContestList = z.infer<typeof adminContestListSchema>
|
||||||
@@ -1153,67 +1153,70 @@ export type BatchProblemTagResponse = z.infer<typeof batchProblemTagResponseSche
|
|||||||
export type SqlTestCaseScript = z.infer<typeof sqlTestCaseScriptSchema>
|
export type SqlTestCaseScript = z.infer<typeof sqlTestCaseScriptSchema>
|
||||||
export type GenerateSqlTestCaseResponse = z.infer<typeof generateSqlTestCaseResponseSchema>
|
export type GenerateSqlTestCaseResponse = z.infer<typeof generateSqlTestCaseResponseSchema>
|
||||||
export type TestCaseFiles = z.infer<typeof testCaseFilesSchema>
|
export type TestCaseFiles = z.infer<typeof testCaseFilesSchema>
|
||||||
export type AstCheckRequest = z.infer<typeof astCheckRequestSchema>
|
export type AstCheckRequest = z.input<typeof astCheckRequestSchema>
|
||||||
export type AstCheckResponse = z.infer<typeof astCheckResponseSchema>
|
export type AstCheckResponse = z.infer<typeof astCheckResponseSchema>
|
||||||
export type GenerateTestInputsRequest = z.infer<typeof generateTestInputsRequestSchema>
|
export type GenerateTestInputsRequest = z.input<typeof generateTestInputsRequestSchema>
|
||||||
export type GenerateTestInputsResponse = z.infer<typeof generateTestInputsResponseSchema>
|
export type GenerateTestInputsResponse = z.infer<typeof generateTestInputsResponseSchema>
|
||||||
|
|
||||||
export type AdminAnnouncementList = z.infer<typeof adminAnnouncementListSchema>
|
export type AdminAnnouncementList = z.infer<typeof adminAnnouncementListSchema>
|
||||||
export type CreateAnnouncementRequest = z.infer<typeof createAnnouncementRequestSchema>
|
export type CreateAnnouncementRequest = z.input<typeof createAnnouncementRequestSchema>
|
||||||
export type UpdateAnnouncementRequest = z.infer<typeof updateAnnouncementRequestSchema>
|
export type UpdateAnnouncementRequest = z.input<typeof updateAnnouncementRequestSchema>
|
||||||
export type TutorialType = z.infer<typeof tutorialTypeSchema>
|
export type TutorialType = z.infer<typeof tutorialTypeSchema>
|
||||||
export type AdminTutorial = z.infer<typeof adminTutorialSchema>
|
export type AdminTutorial = z.infer<typeof adminTutorialSchema>
|
||||||
export type AdminTutorialListItem = z.infer<typeof adminTutorialListItemSchema>
|
export type AdminTutorialListItem = z.infer<typeof adminTutorialListItemSchema>
|
||||||
export type AdminTutorialGroups = z.infer<typeof adminTutorialGroupsSchema>
|
export type AdminTutorialGroups = z.infer<typeof adminTutorialGroupsSchema>
|
||||||
export type AdminTutorialProblem = z.infer<typeof adminTutorialProblemSchema>
|
export type AdminTutorialProblem = z.infer<typeof adminTutorialProblemSchema>
|
||||||
export type TutorialProblemCandidate = z.infer<typeof tutorialProblemCandidateSchema>
|
export type TutorialProblemCandidate = z.infer<typeof tutorialProblemCandidateSchema>
|
||||||
export type SetTutorialProblemsRequest = z.infer<typeof setTutorialProblemsRequestSchema>
|
export type SetTutorialProblemsRequest = z.input<typeof setTutorialProblemsRequestSchema>
|
||||||
export type ReorderTutorialsRequest = z.infer<typeof reorderTutorialsRequestSchema>
|
export type ReorderTutorialsRequest = z.input<typeof reorderTutorialsRequestSchema>
|
||||||
export type RenameTutorialProjectRequest = z.infer<typeof renameTutorialProjectRequestSchema>
|
export type RenameTutorialProjectRequest = z.input<typeof renameTutorialProjectRequestSchema>
|
||||||
export type CreateTutorialRequest = z.infer<typeof createTutorialRequestSchema>
|
export type CreateTutorialRequest = z.input<typeof createTutorialRequestSchema>
|
||||||
export type UpdateTutorialRequest = z.infer<typeof updateTutorialRequestSchema>
|
export type UpdateTutorialRequest = z.input<typeof updateTutorialRequestSchema>
|
||||||
export type SetTutorialVisibilityRequest = z.infer<typeof setTutorialVisibilityRequestSchema>
|
export type SetTutorialVisibilityRequest = z.input<typeof setTutorialVisibilityRequestSchema>
|
||||||
export type ExerciseType = z.infer<typeof exerciseTypeSchema>
|
export type ExerciseType = z.infer<typeof exerciseTypeSchema>
|
||||||
export type AdminExercise = z.infer<typeof adminExerciseSchema>
|
export type AdminExercise = z.infer<typeof adminExerciseSchema>
|
||||||
export type CreateExerciseRequest = z.infer<typeof createExerciseRequestSchema>
|
export type CreateExerciseRequest = z.input<typeof createExerciseRequestSchema>
|
||||||
export type UpdateExerciseRequest = z.infer<typeof updateExerciseRequestSchema>
|
export type UpdateExerciseRequest = z.input<typeof updateExerciseRequestSchema>
|
||||||
export type ToggleAiReportPinResponse = z.infer<typeof toggleAiReportPinResponseSchema>
|
export type ToggleAiReportPinResponse = z.infer<typeof toggleAiReportPinResponseSchema>
|
||||||
export type AchievementOperator = z.infer<typeof achievementOperatorSchema>
|
export type AchievementOperator = z.infer<typeof achievementOperatorSchema>
|
||||||
export type CreateAchievementRequest = z.infer<typeof createAchievementRequestSchema>
|
export type CreateAchievementRequest = z.input<typeof createAchievementRequestSchema>
|
||||||
export type UpdateAchievementRequest = z.infer<typeof updateAchievementRequestSchema>
|
export type UpdateAchievementRequest = z.input<typeof updateAchievementRequestSchema>
|
||||||
export type UpdateUserRequest = z.infer<typeof updateUserRequestSchema>
|
export type UpdateUserRequest = z.input<typeof updateUserRequestSchema>
|
||||||
export type ImportUsersRequest = z.infer<typeof importUsersRequestSchema>
|
export type ImportUsersRequest = z.input<typeof importUsersRequestSchema>
|
||||||
export type DeleteUsersRequest = z.infer<typeof deleteUsersRequestSchema>
|
export type DeleteUsersRequest = z.input<typeof deleteUsersRequestSchema>
|
||||||
export type ResetPasswordResponse = z.infer<typeof resetPasswordResponseSchema>
|
export type ResetPasswordResponse = z.infer<typeof resetPasswordResponseSchema>
|
||||||
export type UpdateWebsiteConfigRequest = z.infer<typeof updateWebsiteConfigRequestSchema>
|
export type UpdateWebsiteConfigRequest = z.input<typeof updateWebsiteConfigRequestSchema>
|
||||||
export type UpdateJudgeServerRequest = z.infer<typeof updateJudgeServerRequestSchema>
|
export type UpdateJudgeServerRequest = z.input<typeof updateJudgeServerRequestSchema>
|
||||||
export type UploadImageResponse = z.infer<typeof uploadImageResponseSchema>
|
export type UploadImageResponse = z.infer<typeof uploadImageResponseSchema>
|
||||||
export type CreateContestRequest = z.infer<typeof createContestRequestSchema>
|
export type CreateContestRequest = z.input<typeof createContestRequestSchema>
|
||||||
export type UpdateContestRequest = z.infer<typeof updateContestRequestSchema>
|
export type UpdateContestRequest = z.input<typeof updateContestRequestSchema>
|
||||||
export type UpdateAcmHelperRequest = z.infer<typeof updateAcmHelperRequestSchema>
|
export type UpdateAcmHelperRequest = z.input<typeof updateAcmHelperRequestSchema>
|
||||||
export type AdminProblemSet = z.infer<typeof adminProblemSetSchema>
|
export type AdminProblemSet = z.infer<typeof adminProblemSetSchema>
|
||||||
export type AdminProblemSetList = z.infer<typeof adminProblemSetListSchema>
|
export type AdminProblemSetList = z.infer<typeof adminProblemSetListSchema>
|
||||||
export type CreateProblemSetRequest = z.infer<typeof createProblemSetRequestSchema>
|
export type CreateProblemSetRequest = z.input<typeof createProblemSetRequestSchema>
|
||||||
export type UpdateProblemSetRequest = z.infer<typeof updateProblemSetRequestSchema>
|
export type UpdateProblemSetRequest = z.input<typeof updateProblemSetRequestSchema>
|
||||||
export type AdminProblemSetProblem = z.infer<typeof adminProblemSetProblemSchema>
|
export type AdminProblemSetProblem = z.infer<typeof adminProblemSetProblemSchema>
|
||||||
export type AddProblemsToSetRequest = z.infer<typeof addProblemsToSetRequestSchema>
|
export type AddProblemsToSetRequest = z.input<typeof addProblemsToSetRequestSchema>
|
||||||
export type AddProblemsToSetResult = z.infer<typeof addProblemsToSetResultSchema>
|
export type AddProblemsToSetResult = z.infer<typeof addProblemsToSetResultSchema>
|
||||||
export type ReorderProblemSetProblemsRequest = z.infer<
|
export type UpdateProblemInSetRequest = z.input<typeof updateProblemInSetRequestSchema>
|
||||||
|
export type AdminProblemSetBadge = z.infer<typeof adminProblemSetBadgeSchema>
|
||||||
|
export type CreateProblemSetBadgeRequest = z.input<typeof createProblemSetBadgeRequestSchema>
|
||||||
|
export type UpdateProblemSetBadgeRequest = z.input<typeof updateProblemSetBadgeRequestSchema>
|
||||||
|
export type RenameTagRequest = z.input<typeof renameTagRequestSchema>
|
||||||
|
export type BatchProblemTagRequest = z.input<typeof batchProblemTagRequestSchema>
|
||||||
|
export type BatchProblemVisibleRequest = z.input<typeof batchProblemVisibleRequestSchema>
|
||||||
|
export type GenerateFlowchartRequest = z.input<typeof generateFlowchartRequestSchema>
|
||||||
|
export type GenerateFlowchartResponse = z.infer<typeof generateFlowchartResponseSchema>
|
||||||
|
export type UpdateProblemRequest = z.input<typeof updateProblemRequestSchema>
|
||||||
|
export type MakeProblemPublicRequest = z.input<typeof makeProblemPublicRequestSchema>
|
||||||
|
export type AddContestProblemRequest = z.input<typeof addContestProblemRequestSchema>
|
||||||
|
export type ReorderContestProblemsRequest = z.input<typeof reorderContestProblemsRequestSchema>
|
||||||
|
export type ReorderProblemSetProblemsRequest = z.input<
|
||||||
typeof reorderProblemSetProblemsRequestSchema
|
typeof reorderProblemSetProblemsRequestSchema
|
||||||
>
|
>
|
||||||
export type UpdateProblemInSetRequest = z.infer<typeof updateProblemInSetRequestSchema>
|
export type SetTagCategoryRequest = z.input<typeof setTagCategoryRequestSchema>
|
||||||
export type AdminProblemSetBadge = z.infer<typeof adminProblemSetBadgeSchema>
|
export type CheckUsernamesRequest = z.input<typeof checkUsernamesRequestSchema>
|
||||||
export type CreateProblemSetBadgeRequest = z.infer<typeof createProblemSetBadgeRequestSchema>
|
|
||||||
export type UpdateProblemSetBadgeRequest = z.infer<typeof updateProblemSetBadgeRequestSchema>
|
|
||||||
export type RenameTagRequest = z.infer<typeof renameTagRequestSchema>
|
|
||||||
export type BatchProblemTagRequest = z.infer<typeof batchProblemTagRequestSchema>
|
|
||||||
export type BatchProblemVisibleRequest = z.infer<typeof batchProblemVisibleRequestSchema>
|
|
||||||
export type GenerateFlowchartRequest = z.infer<typeof generateFlowchartRequestSchema>
|
|
||||||
export type GenerateFlowchartResponse = z.infer<typeof generateFlowchartResponseSchema>
|
|
||||||
export type UpdateProblemRequest = z.infer<typeof updateProblemRequestSchema>
|
|
||||||
export type MakeProblemPublicRequest = z.infer<typeof makeProblemPublicRequestSchema>
|
|
||||||
export type AddContestProblemRequest = z.infer<typeof addContestProblemRequestSchema>
|
|
||||||
export type TestCaseEntry = z.infer<typeof testCaseEntrySchema>
|
export type TestCaseEntry = z.infer<typeof testCaseEntrySchema>
|
||||||
export type UploadTestCaseResponse = z.infer<typeof uploadTestCaseResponseSchema>
|
export type UploadTestCaseResponse = z.infer<typeof uploadTestCaseResponseSchema>
|
||||||
export type SqlPreviewRequest = z.infer<typeof sqlPreviewRequestSchema>
|
export type SqlPreviewRequest = z.input<typeof sqlPreviewRequestSchema>
|
||||||
export type GenerateSqlTestCaseRequest = z.infer<typeof generateSqlTestCaseRequestSchema>
|
export type GenerateSqlTestCaseRequest = z.input<typeof generateSqlTestCaseRequestSchema>
|
||||||
@@ -248,9 +248,9 @@ export type LearningDay = z.infer<typeof learningDaySchema>
|
|||||||
export type LearningReport = z.infer<typeof learningReportSchema>
|
export type LearningReport = z.infer<typeof learningReportSchema>
|
||||||
export type AiAnalysisRecord = z.infer<typeof aiAnalysisRecordSchema>
|
export type AiAnalysisRecord = z.infer<typeof aiAnalysisRecordSchema>
|
||||||
|
|
||||||
export type AiAnalysisRequest = z.infer<typeof aiAnalysisRequestSchema>
|
export type AiAnalysisRequest = z.input<typeof aiAnalysisRequestSchema>
|
||||||
export type AiHintRequest = z.infer<typeof aiHintRequestSchema>
|
export type AiHintRequest = z.input<typeof aiHintRequestSchema>
|
||||||
export type AiHintDone = z.infer<typeof aiHintDoneSchema>
|
export type AiHintDone = z.infer<typeof aiHintDoneSchema>
|
||||||
export type AiHintFeedbackRequest = z.infer<typeof aiHintFeedbackRequestSchema>
|
export type AiHintFeedbackRequest = z.input<typeof aiHintFeedbackRequestSchema>
|
||||||
export type ClassAnalysisRequest = z.infer<typeof classAnalysisRequestSchema>
|
export type ClassAnalysisRequest = z.input<typeof classAnalysisRequestSchema>
|
||||||
export type ClassPkAnalysisRequest = z.infer<typeof classPkAnalysisRequestSchema>
|
export type ClassPkAnalysisRequest = z.input<typeof classPkAnalysisRequestSchema>
|
||||||
@@ -28,6 +28,6 @@ export const userProfileSchema = z.object({
|
|||||||
submissionNumber: z.number().int(),
|
submissionNumber: z.number().int(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type LoginRequest = z.infer<typeof loginRequestSchema>
|
export type LoginRequest = z.input<typeof loginRequestSchema>
|
||||||
export type SessionUser = z.infer<typeof sessionUserSchema>
|
export type SessionUser = z.infer<typeof sessionUserSchema>
|
||||||
export type UserProfile = z.infer<typeof userProfileSchema>
|
export type UserProfile = z.infer<typeof userProfileSchema>
|
||||||
@@ -225,7 +225,7 @@ export const classTodaySchema = z.object({
|
|||||||
export type ClassActivity = z.infer<typeof classActivitySchema>
|
export type ClassActivity = z.infer<typeof classActivitySchema>
|
||||||
export type ClassToday = z.infer<typeof classTodaySchema>
|
export type ClassToday = z.infer<typeof classTodaySchema>
|
||||||
export type LastVisit = z.infer<typeof lastVisitSchema>
|
export type LastVisit = z.infer<typeof lastVisitSchema>
|
||||||
export type ClassLessonRequest = z.infer<typeof classLessonRequestSchema>
|
export type ClassLessonRequest = z.input<typeof classLessonRequestSchema>
|
||||||
export type ClassBoard = z.infer<typeof classBoardSchema>
|
export type ClassBoard = z.infer<typeof classBoardSchema>
|
||||||
export type ClassLesson = z.infer<typeof classLessonSchema>
|
export type ClassLesson = z.infer<typeof classLessonSchema>
|
||||||
export type ClassBoardProblem = z.infer<typeof classBoardProblemSchema>
|
export type ClassBoardProblem = z.infer<typeof classBoardProblemSchema>
|
||||||
|
|||||||
@@ -182,13 +182,13 @@ export type AnnouncementList = z.infer<typeof announcementListSchema>
|
|||||||
export type ReactionKey = z.infer<typeof reactionKeySchema>
|
export type ReactionKey = z.infer<typeof reactionKeySchema>
|
||||||
export type ReactionCounts = z.infer<typeof reactionCountsSchema>
|
export type ReactionCounts = z.infer<typeof reactionCountsSchema>
|
||||||
export type ReactionState = z.infer<typeof reactionStateSchema>
|
export type ReactionState = z.infer<typeof reactionStateSchema>
|
||||||
export type SetReactionRequest = z.infer<typeof setReactionRequestSchema>
|
export type SetReactionRequest = z.input<typeof setReactionRequestSchema>
|
||||||
export type Tutorial = z.infer<typeof tutorialSchema>
|
export type Tutorial = z.infer<typeof tutorialSchema>
|
||||||
export type TutorialProblem = z.infer<typeof tutorialProblemSchema>
|
export type TutorialProblem = z.infer<typeof tutorialProblemSchema>
|
||||||
export type Exercise = z.infer<typeof exerciseSchema>
|
export type Exercise = z.infer<typeof exerciseSchema>
|
||||||
export type TutorialProgress = z.infer<typeof tutorialProgressSchema>
|
export type TutorialProgress = z.infer<typeof tutorialProgressSchema>
|
||||||
export type TutorialProgressPing = z.infer<typeof tutorialProgressPingSchema>
|
export type TutorialProgressPing = z.infer<typeof tutorialProgressPingSchema>
|
||||||
export type ExerciseAttemptRequest = z.infer<typeof exerciseAttemptRequestSchema>
|
export type ExerciseAttemptRequest = z.input<typeof exerciseAttemptRequestSchema>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 「学完一课」的口径:**这课的练一练全做对**。没有练一练的课,打开过就算。
|
* 「学完一课」的口径:**这课的练一练全做对**。没有练一练的课,打开过就算。
|
||||||
|
|||||||
@@ -152,5 +152,5 @@ export type ContestScoreboard = z.infer<typeof contestScoreboardSchema>
|
|||||||
export type ContestClassView = z.infer<typeof contestClassViewSchema>
|
export type ContestClassView = z.infer<typeof contestClassViewSchema>
|
||||||
|
|
||||||
export type ContestStatus = z.infer<typeof contestStatusSchema>
|
export type ContestStatus = z.infer<typeof contestStatusSchema>
|
||||||
export type ContestPasswordRequest = z.infer<typeof contestPasswordRequestSchema>
|
export type ContestPasswordRequest = z.input<typeof contestPasswordRequestSchema>
|
||||||
export type ContestProblems = z.infer<typeof contestProblemsSchema>
|
export type ContestProblems = z.infer<typeof contestProblemsSchema>
|
||||||
@@ -175,6 +175,6 @@ export type FlowchartListItem = z.infer<typeof flowchartListItemSchema>
|
|||||||
export type FlowchartList = z.infer<typeof flowchartListSchema>
|
export type FlowchartList = z.infer<typeof flowchartListSchema>
|
||||||
export type FlowchartScores = z.infer<typeof flowchartScoresSchema>
|
export type FlowchartScores = z.infer<typeof flowchartScoresSchema>
|
||||||
export type CreateFlowchartResponse = z.infer<typeof createFlowchartResponseSchema>
|
export type CreateFlowchartResponse = z.infer<typeof createFlowchartResponseSchema>
|
||||||
export type CreateFlowchartRequest = z.infer<typeof createFlowchartRequestSchema>
|
export type CreateFlowchartRequest = z.input<typeof createFlowchartRequestSchema>
|
||||||
|
|
||||||
export type FlowchartStatus = z.infer<typeof flowchartStatusSchema>
|
export type FlowchartStatus = z.infer<typeof flowchartStatusSchema>
|
||||||
@@ -164,4 +164,4 @@ export type UserBadge = z.infer<typeof userBadgeSchema>
|
|||||||
export type BadgeConditionType = z.infer<typeof badgeConditionTypeSchema>
|
export type BadgeConditionType = z.infer<typeof badgeConditionTypeSchema>
|
||||||
|
|
||||||
export type ProblemSetUserProgressSummary = z.infer<typeof problemSetUserProgressSummarySchema>
|
export type ProblemSetUserProgressSummary = z.infer<typeof problemSetUserProgressSummarySchema>
|
||||||
export type JoinProblemSetRequest = z.infer<typeof joinProblemSetRequestSchema>
|
export type JoinProblemSetRequest = z.input<typeof joinProblemSetRequestSchema>
|
||||||
@@ -118,7 +118,7 @@ export type RankTrend = z.infer<typeof rankTrendSchema>
|
|||||||
export type RankBoard = z.infer<typeof rankBoardSchema>
|
export type RankBoard = z.infer<typeof rankBoardSchema>
|
||||||
export type ClassBattleItem = z.infer<typeof classBattleItemSchema>
|
export type ClassBattleItem = z.infer<typeof classBattleItemSchema>
|
||||||
export type WeeklyChampion = z.infer<typeof weeklyChampionSchema>
|
export type WeeklyChampion = z.infer<typeof weeklyChampionSchema>
|
||||||
export type RankHiddenRequest = z.infer<typeof rankHiddenRequestSchema>
|
export type RankHiddenRequest = z.input<typeof rankHiddenRequestSchema>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 班级详情(设计稿「班级详情 · 老师 / 学生」)。原来弹框里的四分位数、四分位距、标准差、
|
* 班级详情(设计稿「班级详情 · 老师 / 学生」)。原来弹框里的四分位数、四分位距、标准差、
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ export type TrialRunResponse =
|
|||||||
|
|
||||||
export type StatisticInfo = z.infer<typeof statisticInfoSchema>
|
export type StatisticInfo = z.infer<typeof statisticInfoSchema>
|
||||||
export type SubmissionTrace = z.infer<typeof submissionTraceSchema>
|
export type SubmissionTrace = z.infer<typeof submissionTraceSchema>
|
||||||
export type CreateSubmissionRequest = z.infer<typeof createSubmissionRequestSchema>
|
export type CreateSubmissionRequest = z.input<typeof createSubmissionRequestSchema>
|
||||||
export type SubmissionDetail = z.infer<typeof submissionDetailSchema>
|
export type SubmissionDetail = z.infer<typeof submissionDetailSchema>
|
||||||
export type SubmissionUpdate = z.infer<typeof submissionUpdateSchema>
|
export type SubmissionUpdate = z.infer<typeof submissionUpdateSchema>
|
||||||
export type SubmissionStatistics = z.infer<typeof submissionStatisticsSchema>
|
export type SubmissionStatistics = z.infer<typeof submissionStatisticsSchema>
|
||||||
@@ -633,5 +633,5 @@ export type SubmissionList = z.infer<typeof submissionListSchema>
|
|||||||
export type CreateSubmissionResponse = z.infer<typeof createSubmissionResponseSchema>
|
export type CreateSubmissionResponse = z.infer<typeof createSubmissionResponseSchema>
|
||||||
export type FormatCodeResponse = z.infer<typeof formatCodeResponseSchema>
|
export type FormatCodeResponse = z.infer<typeof formatCodeResponseSchema>
|
||||||
|
|
||||||
export type FormatCodeRequest = z.infer<typeof formatCodeRequestSchema>
|
export type FormatCodeRequest = z.input<typeof formatCodeRequestSchema>
|
||||||
export type TrialRunRequest = z.infer<typeof trialRunRequestSchema>
|
export type TrialRunRequest = z.input<typeof trialRunRequestSchema>
|
||||||
Reference in new issue
Block a user