feat(后台比赛): 比赛列表带上每场几道题、几人参加,按开始时间排,复制出来的旧比赛不再跑到最前面
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c59e31eeb2
commit
591c7bcab9
2 files changed
+38
-4
No files matched your search
@@ -5,7 +5,7 @@ import {
|
|||||||
type AdminContest,
|
type AdminContest,
|
||||||
type AdminContestList,
|
type AdminContestList,
|
||||||
} from "@oj2/contract"
|
} from "@oj2/contract"
|
||||||
import { and, count, desc, eq, ilike, inArray } from "drizzle-orm"
|
import { and, count, countDistinct, desc, eq, ilike, inArray } from "drizzle-orm"
|
||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
|
|
||||||
import { requireTeacher, type AppEnv } from "../../auth/middleware"
|
import { requireTeacher, type AppEnv } from "../../auth/middleware"
|
||||||
@@ -93,12 +93,39 @@ adminContestRoutes.get("/contests", requireTeacher, async (c) => {
|
|||||||
.innerJoin(schema.user, eq(schema.contest.createdById, schema.user.id))
|
.innerJoin(schema.user, eq(schema.contest.createdById, schema.user.id))
|
||||||
.leftJoin(schema.userProfile, eq(schema.userProfile.userId, schema.user.id))
|
.leftJoin(schema.userProfile, eq(schema.userProfile.userId, schema.user.id))
|
||||||
.where(where)
|
.where(where)
|
||||||
.orderBy(desc(schema.contest.createTime))
|
// 按开始时间:原来按创建时间,「复制一份」出来的旧比赛会排到最前面
|
||||||
|
.orderBy(desc(schema.contest.startTime), desc(schema.contest.id))
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset),
|
.offset(offset),
|
||||||
])
|
])
|
||||||
|
const ids = rows.map((row) => row.contest.id)
|
||||||
|
const [problemCounts, participantCounts] = ids.length
|
||||||
|
? await Promise.all([
|
||||||
|
db
|
||||||
|
.select({ contestId: schema.problem.contestId, value: count() })
|
||||||
|
.from(schema.problem)
|
||||||
|
.where(inArray(schema.problem.contestId, ids))
|
||||||
|
.groupBy(schema.problem.contestId),
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
contestId: schema.submission.contestId,
|
||||||
|
value: countDistinct(schema.submission.userId),
|
||||||
|
})
|
||||||
|
.from(schema.submission)
|
||||||
|
.where(inArray(schema.submission.contestId, ids))
|
||||||
|
.groupBy(schema.submission.contestId),
|
||||||
|
])
|
||||||
|
: [[], []]
|
||||||
|
const problemsOf = new Map(problemCounts.map((row) => [row.contestId, row.value]))
|
||||||
|
const peopleOf = new Map(participantCounts.map((row) => [row.contestId, row.value]))
|
||||||
return success(c, {
|
return success(c, {
|
||||||
results: await Promise.all(rows.map(serialize)),
|
results: await Promise.all(
|
||||||
|
rows.map(async (row) => ({
|
||||||
|
...(await serialize(row)),
|
||||||
|
problemCount: problemsOf.get(row.contest.id) ?? 0,
|
||||||
|
participantCount: peopleOf.get(row.contest.id) ?? 0,
|
||||||
|
})),
|
||||||
|
),
|
||||||
total: totalRows[0]?.value ?? 0,
|
total: totalRows[0]?.value ?? 0,
|
||||||
} satisfies AdminContestList)
|
} satisfies AdminContestList)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -394,7 +394,13 @@ export const adminContestSchema = z.object({
|
|||||||
contestType: z.enum(["Public", "Password Protected"]),
|
contestType: z.enum(["Public", "Password Protected"]),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const adminContestListSchema = paginatedSchema(adminContestSchema)
|
/** 后台比赛列表的一行:比赛本身,加几道题、几人参加(交过题的人数) */
|
||||||
|
export const adminContestListItemSchema = adminContestSchema.extend({
|
||||||
|
problemCount: z.number().int(),
|
||||||
|
participantCount: z.number().int(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const adminContestListSchema = paginatedSchema(adminContestListItemSchema)
|
||||||
|
|
||||||
export const createContestRequestSchema = z.object({
|
export const createContestRequestSchema = z.object({
|
||||||
title: z.string().trim().min(1).max(128),
|
title: z.string().trim().min(1).max(128),
|
||||||
@@ -1008,6 +1014,7 @@ export type CreateProblemRequest = z.infer<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>
|
||||||
|
export type AdminContestListItem = z.infer<typeof adminContestListItemSchema>
|
||||||
export type AdminUser = z.infer<typeof adminUserSchema>
|
export type AdminUser = z.infer<typeof adminUserSchema>
|
||||||
export type AdminUserList = z.infer<typeof adminUserListSchema>
|
export type AdminUserList = z.infer<typeof adminUserListSchema>
|
||||||
export type CheckUsernamesResponse = z.infer<typeof checkUsernamesResponseSchema>
|
export type CheckUsernamesResponse = z.infer<typeof checkUsernamesResponseSchema>
|
||||||
|
|||||||
Reference in new issue
Block a user