fix: 修复中危问题:注册接口、模型名、LLM 超时、WebSocket 断线、未公开任务泄露等

服务端
- 删掉没人用的 /account/register,外网不能再批量注册小号
- 模型名只放行豆包和配置的 LLM_MODEL,浏览器里存的旧模型名换成默认模型;
  聊天默认模型改读 LLM_MODEL
- 流式生成改成 120 秒无数据才超时(另有 15 分钟总上限),思考模型不会被中途掐断;
  SSE 最后一行没有换行时不再丢内容
- WebSocket:token 无效 401、任务不存在 404,建对话失败时关闭连接;
  引导出错时把没有回复的提问移出上下文
- 未公开的教程只有超管能看,未公开的挑战和素材管理员也能看,其他人 404
- Caddy:/media 加 CSP sandbox 和 nosniff,上传的 html/svg 直接打开不能跑脚本;
  加 CORS,预览 iframe 里的代码可以读取字体和 fetch 素材

前端
- 新增 ReconnectingSocket:意外断开后退避重连,握手失败先刷新 token;
  断线时清掉“生成中”状态,旧连接的事件不再改写新连接
- marked 扩展抽到 utils/markdown.ts:教程用独立实例,不再改全局 marked;
  学生内容的渲染保留高亮,不带会渲染原始 HTML 的 preview 扩展
- 挑战页、创作页加载完成前离开时不再建立连接,离开时关闭引导弹窗
- 教程、提交列表、用户管理跟随浏览器前进后退;快速翻页只用最后一次结果,
  改筛选条件不再请求两次
- 随机评分弹窗在 AI 回复完之后不再弹出

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-26 21:33:44 +08:00
1 parent 73788c4595
commit cdeb7c18ef
22 files changed
+489 -210

No files matched your search

+2 -32
View File
@@ -8,42 +8,12 @@ import { addAPIProvider } from "@iconify/vue"
import "github-markdown-css/github-markdown-light.css"
import { marked } from "marked"
import alert from "marked-alert"
import { markedHighlight } from "marked-highlight"
import preview from "marked-code-preview"
import { alertVariants } from "./utils/const"
import hljs from "highlight.js/lib/core"
import xml from "highlight.js/lib/languages/xml"
import css from "highlight.js/lib/languages/css"
import javascript from "highlight.js/lib/languages/javascript"
import plaintext from "highlight.js/lib/languages/plaintext"
import { trustedExtensions } from "./utils/markdown"
//@ts-ignore
import "highlight.js/styles/github.min.css"
import { router } from "./router"
hljs.registerLanguage("html", xml)
hljs.registerLanguage("css", css)
hljs.registerLanguage("js", javascript)
hljs.registerLanguage("javascript", javascript)
hljs.registerLanguage("plaintext", plaintext)
marked.use({
gfm: true,
})
marked.use(
markedHighlight({
langPrefix: "hljs language-",
highlight(code, lang) {
const language = hljs.getLanguage(lang) ? lang : "plaintext"
return hljs.highlight(code, { language }).value
},
}),
)
marked.use(alert({ variants: alertVariants }))
const template = `<div class="markedown-body-preview">{preview}</div>`
marked.use(preview({ template }))
marked.use(...trustedExtensions)
const app = createApp(App)
const naive = create()