- 根目录加入 docker-compose、Caddyfile、文档等原本不在仓库里的文件 - 前后端两份 GitHub Actions 合并成根目录的一个 deploy workflow: 构建前端上传到 build/,再在服务器上 git pull 并重建容器 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.0 KiB
作品广场功能设计
日期: 2026-04-29
状态: 待审阅
背景
WebPreview 目前已有挑战、提交、评分、分区、人气统计和 AI 对话生成代码能力。现有机制偏向提交管理和评分结果展示,还缺少一个面向学生的优秀作品展示入口。作品广场用于把老师选出的优秀提交集中展示,让学生通过最终效果和创作提示词链学习同伴作品。
目标
- 学生登录后可以进入全站统一的作品广场,浏览获奖作品效果。
- 老师可以在后台维护奖项,并把提交作品授予一个或多个奖项。
- 每个奖项可以配置自己的作品排序方式。
- 作品广场只展示运行效果,不开放代码查看。
- 如果获奖作品有关联 AI 提示词链,所有登录学生都可以查看创作过程。
不在本期范围
- 学生提名、投票、评论、收藏。
- 对外公开展示。
- 作品代码公开。
- 复杂拖拽排序界面。初版用后台排序字段实现手动排序。
- 为奖项做单独的前端管理页。初版通过 Django 后台维护奖项和授奖关系。
核心规则
访问权限
/showcase需要登录。- 普通学生只能浏览作品广场。
- 管理员和超级管理员可以通过 Django 后台维护奖项和授奖关系。
奖项
奖项由后台配置,不写死在前端。每个奖项包含:
- 名称,例如“最佳游戏”“最佳设计”。
- 简介,用于解释该专区的评选标准。
- 排序值,用于控制奖项专区在作品广场中的顺序。
- 是否启用。停用后不在前台展示。
- 作品排序方式。
作品排序方式初版支持:
manual: 手动排序,按授奖关系上的排序值升序。awarded_at: 按授奖时间倒序。score: 按提交评分倒序。view_count: 按浏览量倒序。
默认排序方式为 manual。
授奖
- 一个提交作品可以获得多个奖项。
- 一个奖项可以包含多个提交作品。
- 同一个提交和同一个奖项只能建立一条授奖关系。
- 授奖关系包含手动排序值和授奖时间。
作品展示
作品广场按奖项分区展示,全站统一混合所有挑战作品,不按单个挑战拆分。
每个作品卡片展示:
- 作品运行效果。
- 作者用户名。
- 挑战标题。
- 奖项标签。
- 评分。
- 浏览量。
点击作品进入详情页,只展示运行效果和作品信息,不提供查看代码入口。
提示词链展示
如果提交作品关联到 prompt.Message.submission,作品详情展示“创作过程”区域。
展示内容:
- 每一轮学生提示词。
- 提示词来源:对话或手动。
- L1-L6 提示词层级,如果已分类。
- 每一轮 assistant 消息提取出的网页效果。
不展示内容:
- 系统提示词。
- 模型配置。
- API 信息。
- 代码文本。
创作过程默认折叠,学生点击后展开。
数据模型
Award
建议放在 submission/models.py,因为奖项直接服务于提交作品展示。
字段:
name: 奖项名称,唯一。description: 奖项简介,可为空。sort_order: 奖项排序值,默认 0。is_active: 是否启用,默认 true。item_ordering: 作品排序方式,默认manual。created/modified: 复用TimeStampedModel。
SubmissionAward
授奖关系表。
字段:
submission: 外键到Submission。award: 外键到Award。sort_order: 手动排序值,默认 0。awarded_at: 授奖时间。created/modified: 复用TimeStampedModel。
约束:
(submission, award)唯一。
查询优化:
award,submission,sort_order,awarded_at建索引或通过外键索引满足主要查询。- API 查询时
select_related("submission", "submission__user", "submission__task", "award")。
后端接口
作品广场列表
GET /api/submission/showcase/
登录后可访问。
返回启用奖项及其作品列表。无获奖作品的奖项默认不返回,避免前台出现空专区。
响应结构建议:
[
{
"id": 1,
"name": "最佳设计",
"description": "视觉完成度高、布局清晰的作品",
"item_ordering": "manual",
"items": [
{
"submission_id": "uuid",
"username": "student01",
"task_title": "挑战标题",
"task_display": 3,
"score": 4.6,
"view_count": 28,
"html": "...",
"css": "...",
"js": "...",
"has_prompt_chain": true
}
]
}
]
作品详情
GET /api/submission/showcase/{submission_id}/
登录后可访问。仅允许访问已授奖的提交作品。
返回:
- 提交作品运行所需的
html/css/js。 - 作者、挑战、评分、浏览量。
- 当前作品获得的奖项列表。
- 是否存在提示词链。
作品提示词链
GET /api/submission/showcase/{submission_id}/prompt-chain/
登录后可访问。仅允许访问已授奖且有关联提示词链的提交作品。
后端通过 Submission.source_message 找到关联 assistant 消息,再回到同一 Conversation,按时间顺序构造用户提示词和 assistant 生成效果的轮次。
返回结构可复用 ChainModal.vue 当前使用的数据概念,但需要针对作品广场隐藏代码文本,只返回提示词内容、层级、来源和可预览的生成结果。
如果提交没有关联提示词链,作品详情接口返回 has_prompt_chain: false,该接口返回 404。
后台管理
在 Django admin 注册:
AwardSubmissionAward
SubmissionAward 后台字段:
- submission
- award
- sort_order
- awarded_at
列表页显示:
- 奖项名称
- 提交作者
- 挑战标题
- 评分
- 浏览量
- 手动排序值
- 授奖时间
筛选:
- award
- submission.task
- submission.user.classname
搜索:
- award.name
- submission.user.username
- submission.task.title
前端页面
路由
新增:
/showcase
路由 meta.auth = true。
入口
在主页/任务面板中新增“作品广场”入口,学生登录后可见。
作品广场页面
布局:
- 顶部标题和简短说明。
- 奖项专区纵向排列。
- 每个专区展示奖项名称、简介和作品网格。
- 每个作品卡片内嵌预览效果,显示作者、挑战、分数、浏览量。
空状态:
- 如果没有任何获奖作品,显示“暂无展示作品”。
作品详情页
新增或复用现有提交详情页,但需要隐藏代码查看能力。
内容:
- 作品运行效果。
- 作者、挑战、奖项、评分、浏览量。
- “创作过程”折叠区域。
创作过程:
- 有提示词链才显示入口。
- 默认折叠。
- 展开后显示提示词轮次和每轮生成效果。
安全与隐私
- 作品广场需要登录。
- 仅展示被授奖的提交。
- 不展示代码文本。
- 提示词链公开范围限定为登录用户。
- 提示词链只取用户消息和 assistant 生成效果,不展示系统提示词或接口配置。
测试计划
后端:
- 普通未登录用户访问作品广场接口返回 401/403。
- 登录用户可以查看已授奖作品。
- 未授奖提交不能通过详情接口访问。
- 一个提交可以获得多个奖项。
- 同一提交同一奖项不能重复授奖。
- 奖项停用后不在广场接口返回。
- 不同排序方式返回顺序正确。
- 有
source_message的提交可以返回提示词链。 - 无
source_message的提交在详情中返回has_prompt_chain: false,请求提示词链接口返回 404。
前端:
- 未登录访问
/showcase触发登录逻辑。 - 登录后能看到作品广场入口。
- 作品卡片只展示效果和元信息,不出现查看代码入口。
- 详情页能展示作品效果。
- 有提示词链时显示创作过程入口,无提示词链时隐藏。
后续扩展
- 学生点赞、收藏、评论。
- 奖项专题封面图。
- 老师在提交列表中直接授奖。
- 作品广场按班级、挑战、作者筛选。
- “本周精选”或“最近上榜”专区。