feat: 重新设计作品展管理
Deploy / deploy (build, debian, 22) (push) Canceled after 0s

- 作品改成缩略图卡片:手动排序时用 ← → 调整顺序,有新提交的显示“换成最新的”,
  点缩略图在抽屉里打开批改面板,撤下用页面内确认
- 奖项列表可以上下调整顺序(不用再填排序数字);设置有改动才能保存;删除奖项说明会撤下几件作品
- 去掉按提交 ID 添加作品(前端、类型和 /manage/submissions 接口),改为提示在批改面板里“加入作品展”
- 管理接口返回作品代码,画缩略图用

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-27 12:02:53 +08:00
1 parent 4c9617caf1
commit 951a6e0826
4 files changed
+549 -603

No files matched your search

-10
View File
@@ -17,7 +17,6 @@ import type {
AwardItemManageOut,
GradebookOut,
GradebookQuery,
ShowcaseSubmissionLookupOut,
ShowcaseDetail,
PromptRound,
RandomRatingItem,
@@ -519,15 +518,6 @@ export const Showcase = {
return res.data
},
async findSubmissionForAward(
submissionId: string,
): Promise<ShowcaseSubmissionLookupOut> {
const res = await http.get(
`/submission/showcase/manage/submissions/${submissionId}`,
)
return res.data
},
async addAwardItem(
id: number,
payload: AwardItemIn,
File diff suppressed because it is too large. Load diff
+3 -11
View File
@@ -302,17 +302,6 @@ export interface AwardItemUpdateIn {
sort_order: number
}
export interface ShowcaseSubmissionLookupOut {
submission_id: string
username: string
task_title: string
task_display: number
task_type: TASK_TYPE
score: number
view_count: number
has_prompt_chain: boolean
}
export interface AwardItemManageOut {
id: number
submission_id: string
@@ -326,6 +315,9 @@ export interface AwardItemManageOut {
awarded_at: string
has_prompt_chain: boolean
is_stale: boolean
html: string | null
css: string | null
js: string | null
}
export interface ShowcaseDetail {
+4 -26
View File
@@ -41,6 +41,10 @@ function itemManageOut(r: any) {
awarded_at: iso(r.awarded_at),
has_prompt_chain: bool(r.has_prompt_chain),
is_stale: bool(r.is_stale),
// 管理页的缩略图要用
html: r.html,
css: r.css,
js: r.js,
}
}
@@ -164,32 +168,6 @@ router.delete("/manage/awards/:award_id", (c) => {
return c.json({ message: "删除成功" })
})
router.get("/manage/submissions/:submission_id", (c) => {
requireAdmin(c)
const id = uuidParam(c, "submission_id")
const s = orNotFound(
get(
`SELECT s.id, u.username, t.title AS task_title, t.display AS task_display, t.task_type,
s.score, s.view_count, ${HAS_CHAIN}
FROM submission_submission s
JOIN account_user u ON u.id = s.user_id
JOIN task_task t ON t.id = s.task_id
WHERE s.id = $id`,
{ id },
),
)
return c.json({
submission_id: uuidOut(s.id),
username: s.username,
task_title: s.task_title,
task_display: s.task_display,
task_type: s.task_type,
score: s.score,
view_count: s.view_count,
has_prompt_chain: bool(s.has_prompt_chain),
})
})
router.get("/manage/awards/:award_id/items", (c) => {
requireAdmin(c)
const award = orNotFound(