# C-03 · 在线代码运行器(JS+Python,学练一体) | 字段 | 值 | |---|---| | 项目 | 可乐工具 · `chunyu_project_react`(主体),后端可选 | | 优先级 | P0 · M2 | | 建议模型 | deepseek-v4.1-flash(主)/ **gpt-5.6-luna(安全审查)** | | 依赖 | 无 | | 预估 | 3.5 天 | ## 一、背景(为什么做) 1. 报告结论:学习模块讲编程课程却无处练代码——**课程与工具割裂**;"学完即练"是全竞品都没有的组合(`docs/产品问题分析与改造路线.md` P0-3)。 2. 竞品:菜鸟工具 24 种语言在线编译、ToolFk 有 Online Code Compiler——但它们都是**独立工具**,没有与课程内容绑定。我们的差异化 = 嵌在章节页里的随堂运行。 ## 二、目标(交付物) **MVP 技术路线(已拍板):纯前端沙箱,零服务端执行** - JS:`Web Worker` 沙箱执行(`postMessage` 收发,`importScripts` 禁用,超时 `terminate()`) - Python:`Pyodide`(WASM,浏览器内运行;懒加载,独立 chunk) - **不做服务端执行**(judge0 容器留到 Phase 2 按需评审)——安全与运维成本双低。 **组件交付** 1. `src/components/CodeRunner/`: - `CodeRunner.tsx`:编辑器(复用项目现有编辑器风格,如 CodeMirror/Monaco 依项目现状)+ 运行按钮 + 输出面板 + 状态行(运行中/超时/错误) - `worker-js.ts`:JS 执行 worker(捕获 console、异常;**硬超时 3s** 后 terminate 并显示"执行超时") - `pyodide-runner.ts`:Pyodide 加载(版本锁定;加载失败降级提示;执行超时同一策略) 2. 集成到 `CourseLearn.tsx` 章节页:本章节含代码示例时显示"随堂运行"面板(读章节内容里的代码块,一键装载)。 3. 独立工具入口(可选加分):`/code-runner` 页面。 4. 安全设计(交 gpt-5.6-luna 审查): - worker 内无 DOM 访问;主线程无 `eval`/`new Function` - Pyodide 网络请求策略(默认断网:不加载额外包) - CSP 兼容性说明 ## 三、执行步骤 ```text 1. 侦察项目现有编辑器依赖与 CourseLearn 章节数据结构(代码块字段) 2. 实现 worker-js + 超时控制(先跑通最小闭环) 3. 接入 Pyodide(懒加载 + 失败降级) 4. 集成 CourseLearn 章节页 5. 安全自查清单逐条过 → 交安全审查模型复核 6. 构建体积核对(runner chunk 懒加载,不拖累主包) ``` ## 四、验收标准 - [ ] JS 代码运行并显示输出(console.log、返回值、异常信息) - [ ] Python(Pyodide)代码运行并显示输出 - [ ] **死循环(`while(1){}`)3 秒内终止,页面不冻结、可继续操作** - [ ] 章节页"随堂运行"面板可用:装载本章代码 → 运行 → 看输出 - [ ] 首次加载 Pyodide 有 loading 态;失败有降级提示 - [ ] runner 相关代码全部懒加载(主包体积不增加 >10KB) - [ ] 安全审查清单通过(审查模型签署) ## 五、验收命令(参考) ```bash cd chunyu_project_react && npm run build # 检查懒加载 chunk 分离 ls dist/assets | grep -iE "runner|pyodide" # 浏览器手工:死循环用例、异常用例、中文输出用例 ``` ## 六、边界(不许做) - 不做服务端代码执行(MVP 红线) - 不引入重量级 IDE 依赖(不装完整 Monaco + language server;按项目现有编辑器能力办事) - 不修改课程数据结构(只读章节内容) - 不在 worker 里放开网络能力 ## 七、交接 写 `PROGRESS_C-03.md`(含死循环终止的录屏/截图说明、安全审查结论、构建体积数据)。