feat: 改版阶段 2:挑战和自由创作共用工作台,学生自己选版本提交
- 新的 Workbench:左边题目(可收起)+ AI 对话,右边预览 / 代码(可编辑),底部版本条; 挑战页和自由创作页都用它,原来的“手动提交”“历史对话”标签换成“粘贴外部代码”和“全部历史” - 不再每轮 AI 回复自动提交:学生点“交这一版”,可交多次,成绩仍取最高分;已交的版本不能重复点 - 手改代码、粘贴外部 AI 代码都存成版本(POST /prompt/versions,source 为 edit / manual), 在版本条和提示词链里标“手改”“外部 AI”;它们进入 AI 上下文,AI 在手改后的代码上继续改; 以前手动提交的回复正文为空时用代码补上;edit 的占位提问不参与提示词层级分类 - 互评从全屏弹窗改成对话里的卡片,打分前不显示作者,每个分数写明含义 - 编辑器代码按任务各存一份(useTaskCode),挑战页“清空”不再清掉教程的代码; 提交列表“复制到编辑器”对挑战写入该任务自己的代码 - 抽出 utils/code.ts(整理代码、拆分整页 HTML);删除 RandomRatingModal、ExternalAIPanel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ff1eb2982e
commit
9c6c01eba1
29 files changed
+1748
-1069
No files matched your search
+13
-4
@@ -1,7 +1,12 @@
|
||||
import type { Server, ServerWebSocket, WebSocketHandler } from "bun"
|
||||
import { all, get, run, iso, uuidOut } from "./db"
|
||||
import { userFromAccessToken, type User } from "./auth"
|
||||
import { canAccessTask, getOrCreateActiveConversation, insertMessage } from "./services/prompt"
|
||||
import {
|
||||
canAccessTask,
|
||||
codeAsMarkdown,
|
||||
getOrCreateActiveConversation,
|
||||
insertMessage,
|
||||
} from "./services/prompt"
|
||||
import {
|
||||
extractCode,
|
||||
parseGuidanceResponse,
|
||||
@@ -80,6 +85,7 @@ function conversationHistory(conversationId: string) {
|
||||
return all<{
|
||||
id: number
|
||||
role: string
|
||||
source: string
|
||||
content: string
|
||||
code_html: string | null
|
||||
code_css: string | null
|
||||
@@ -87,8 +93,9 @@ function conversationHistory(conversationId: string) {
|
||||
submission_id: string | null
|
||||
created: string
|
||||
}>(
|
||||
`SELECT id, role, content, code_html, code_css, code_js, submission_id, created
|
||||
FROM prompt_message WHERE conversation_id = $id AND source = 'conversation'
|
||||
// 除了 AI 对话,还有学生手改(edit)和粘贴外部 AI 代码(manual)的版本;引导对话(guidance)不算
|
||||
`SELECT id, role, source, content, code_html, code_css, code_js, submission_id, created
|
||||
FROM prompt_message WHERE conversation_id = $id AND source IN ('conversation', 'edit', 'manual')
|
||||
ORDER BY created, id`,
|
||||
{ id: conversationId },
|
||||
)
|
||||
@@ -117,7 +124,8 @@ async function handlePrompt(ws: WS, data: any) {
|
||||
try {
|
||||
const history: ChatMessage[] = conversationHistory(ws.data.conversationId).map((m) => ({
|
||||
role: m.role as ChatMessage["role"],
|
||||
content: m.content,
|
||||
// 以前“手动提交”存的 AI 回复正文是空的,代码只在 code_* 里
|
||||
content: m.role === "assistant" && !m.content ? codeAsMarkdown(m) : m.content,
|
||||
}))
|
||||
let full: string
|
||||
try {
|
||||
@@ -211,6 +219,7 @@ export const websocket: WebSocketHandler<WsData> = {
|
||||
messages: conversationHistory(d.conversationId).map((m) => ({
|
||||
id: m.id,
|
||||
role: m.role,
|
||||
source: m.source,
|
||||
content: m.content,
|
||||
code:
|
||||
m.role === "assistant" ? { html: m.code_html, css: m.code_css, js: m.code_js } : null,
|
||||
|
||||
Reference in new issue
Block a user