aura
轮次管理
你现在的 /rounds / /rounds/r1 若是 Lovable 上的演示页,要变成「真轮次」,核心不是把 UI 做更炫,而是在后端确立「轮次」这一层数据,再让提交、规则、排行榜都挂在它下面。
下面分「怎么管」和「怎么落在你这套 Aura 上」两部分说。
1. 轮次在业务上管什么
把一轮黑客松想成一条有生命周期的容器,里面装四样东西:
| 维度 | 建议 |
|---|---|
| 时间 | 报名/提交截止、评审窗口、结果公布;一律用明确时区(例如 Asia/Shanghai)存 UTC 或带 offset。 |
| 规则 | 本轮绑定的评审 YAML(维度、权重、等级带);换轮次可以换规则,旧结果仍指向旧规则版本。 |
| 项目 | 每条提交/每个 README 属于唯一 round_id;禁止「同一项目同时参加两轮」除非你们明确支持复制/晋级。 |
| 可见性 | 草稿 / 进行中 / 已归档;排行榜是否公开、是否隐藏分数细项,按状态切换。 |
状态机可以尽量简单,例如:draft → open(收作品)→ judging → closed(只读展示)。复杂活动再加 extended(延期)即可。
2. 和「排行榜」的关系(避免再造假数据)
排行榜预览要真,只需要约定:
- 查询维度:
GET /api/ranking?round_id=xxx(或路径/api/rounds/:id/ranking)。 - 数据怎么筛:只统计
file_name/submission属于该round_id的裁决 JSON;或裁决结果里写入round_id冗余字段便于过滤。 - 和现有
prefer_search=1兼容:先按round_id过滤,再在子集上做「每条 readme 优选带搜索元数据的那次运行」。
这样 /rounds/r1 只是前端用 r1 去拉真实 API,而不是本地 mock。
3. 落在你当前后端上的几种做法(由简到繁)
A. 最简(适合快速上线)
- 在
submission.json(或提交接口)里增加round_id(或hackathon_id)。 - 磁盘目录仍可用现有
submissions/<id>,只是在元数据里带轮次。 - 排行榜、管理台列表:先读所有 submission / 结果,再按
round_id过滤。 - 轮次列表存在单独
rounds.json或小表即可(id、名称、起止时间、状态、绑定的rule_version_id)。
B. 目录隔离(适合运维喜欢「一整包拷走」)
submissions/<round_id>/<submission_id>/、word/<round_id>/...、judge-result/<round_id>/...。- 备份、清空一轮数据很直观;实现改动比 A 大。
C. 上数据库(多届、多主办方、权限细)
rounds、submissions、audit_runs分表;适合以后要 SaaS 或多活动并行。
对你现在以文件为主的 Aura 裁决服务,多数团队会先选 A,必要时再演进到 B。
4. 管理后台建议功能(按优先级)
- 轮次 CRUD + 状态(草稿/开放/评审/结束)。
- 绑定规则版本:创建轮次时选「生效规则」或上传本轮专用规则(可复用你们已有的 rules API)。
- 项目列表:按轮次筛
submission,显示是否已生成 word 里的 readme、是否已有裁决结果。 - 只读排行榜链接:
/rounds/:slugOrId仅展示公开字段;管理页可看明细。 - 导出:CSV(项目、分数、GitHub);后期再加评委人工分与 AI 分合并若需要。
5. 常见坑(提前规避)
- 没有轮次字段:所有提交堆在一起,历史届次无法拆分排行榜。
- 规则与轮次脱钩:换了全局 active 规则后,旧轮次结果难以解释「按哪套规则打的」。
- 时间只写在 UI:应用层应对「已过截止仍允许提交」做服务端校验(至少管理员可覆盖)。
- slug 与 id:对外链接用可读
slug(如spring-2025),内部持久化用稳定id(UUID 或 snowflake),避免改名断链。
6. 小结
更好管理黑客松轮次,本质是:轮次 = 时间边界 + 规则版本 + 项目集合 + 可见性;技术上用 round_id 贯穿提交与裁决结果,排行榜 API 按轮次过滤,前端 /rounds 只做配置与列表,/rounds/xxx 只消费真实接口。
若你打算在现有 /root/aura Go 服务里落地,下一步可以是:定 rounds 的 JSON schema、扩展 /api/submit 与 /api/ranking,我可以按你选的方案(A/B)拆成具体接口清单与字段设计。
已完成
目录隔离已按方案 B 落地,说明如下。
目录结构(相对原来的三个根路径)
| 根(环境变量不变) | 新结构 |
|---|---|
AURA_SUBMISSION_DIR |
…/submissions/<round_id>/<submission_id>/submission.json |
AURA_WORD_DIR |
…/word/<round_id>/<文件名> |
AURA_RESULT_DIR |
…/judge-result/<round_id>/*.json |
后端行为
AURA_DEFAULT_ROUND_ID(默认default):请求里没有round_id时使用该轮次。round_id校验:仅允许字母、数字、.、_、-,最长 80,禁止..与路径分隔符。- 新接口
GET /api/rounds:返回rounds(轮次子目录列表)和default_round_id。
若某目录下直接有submission.json,视为旧版扁平提交目录,不会当作轮次(避免把纯数字submission_id当成 round)。 /api/admin-config增加字段default_round_id。- 提交:
SubmissionRecord/ 响应里的round_id会写入或回传;GitHub 自动审计在对应word/<round_id>/下写 readme 并打分。
需带 round_id 的接口(可省略则用默认轮次)
GET/POST 通过 query 或 JSON/form 传 round_id(与现有文档一致):ranking、files、results、file-content、judge-result、file-github-urls、submission/:id、DELETE submission/:id、submissions(管理员)、audit(JSON 里 round_id)、submit(form 字段 round_id)。
前端
- 设置
VITE_ROUND_ID(例如r1)后,会通过withRoundQuery自动给上述请求带上round_id;提交表单也会追加round_id。 - 未设置时依赖后端
AURA_DEFAULT_ROUND_ID(一般为default)。
数据迁移(旧数据在根下平铺时)
在备份后,把旧提交迁进默认轮次(名称需与 AURA_DEFAULT_ROUND_ID 一致,例如 default):
1 | |
(路径按你机器上的 AURA_* 调整。)
运维
- 新的一轮:在三个根下建同名子目录即可(例如
mkdir -p submissions/spring25 word/spring25 judge-result/spring25),或等第一次向该round_id提交时由ensureRoundDirs自动创建。 - 整轮打包:打包
submissions/<round_id>、word/<round_id>、judge-result/<round_id>即可。
go build 已通过;若需要,我可以再帮你加一条 GET /api/rounds 的前端封装或在管理页展示轮次下拉框。