44 lines
3.0 KiB
Markdown
44 lines
3.0 KiB
Markdown
---
|
||
name: demo
|
||
description: W-07 实时演示模块 —— demo 会话管理、three.js 预览、状态隔离(演示改动不污染正式数据)、多人预览。开发/修改 demo 相关功能前必读。
|
||
---
|
||
|
||
# demo 模块技能
|
||
|
||
## 架构
|
||
- 交互层业务模块(有自己的数据表 + dspy + bricks 前端),通过 `load_demo(env)` 挂到宿主。
|
||
- 依赖宿主提供:sqlor/ahserver/ServerEnv;跨模块校验 world 存在性时按需用 world 模块(防御式 try/except)。
|
||
|
||
## 数据模型(models/*.json)
|
||
| 表 | 作用 | 关键字段 |
|
||
|----|------|----------|
|
||
| demo_session | 演示会话 | status(preview/paused/ended), camera_mode(orbit/topdown/firstperson), viewer_count, extra_json |
|
||
| demo_session_state | 实体状态覆盖层 | session_id, entity_id, base_json(基线), demo_json(当前) |
|
||
| demo_hot_script | 热加载脚本 | session_id, script_id, script_type(python/expr), script_content |
|
||
| demo_presence | 多人预览在线 | session_id, user_id, user_name, last_seen_at |
|
||
|
||
## 关键端点(wwwroot/api/*.dspy,全部 logined)
|
||
- `start.dspy` — world_id 必填;重复开始同世界 → 409
|
||
- `stop.dspy` — 删除覆盖层/脚本/在线表(状态隔离核心)
|
||
- `entity_edit.dspy` — session_id+entity_id+fields(对象) 必填;只写覆盖层
|
||
- `entity_attrs.dspy` — 返回 base/demo/merged
|
||
- `hotload.dspy` — 语法校验(compile)通过才落库;SyntaxError → 400
|
||
- `camera.dspy` — camera_mode 白名单 orbit/topdown/firstperson
|
||
- `pause.dspy` — paused=true/false
|
||
- `presence.dspy` — action=join/leave,viewer_count 实时回写
|
||
- `fullscreen.dspy` — enabled true/false,写入 extra_json
|
||
- `state.dspy` — 前端 500ms 轮询,聚合实体状态+脚本+在线人数
|
||
|
||
## 状态机(会话级)
|
||
preview ⇄ paused(pause.dspy);preview/paused → ended(stop.dspy,唯一出口);ended 后任何操作 → 400。
|
||
|
||
## 模块专属坑
|
||
1. **状态隔离是硬约束**:任何实体修改只允许写 `demo_session_state`,严禁写 entity/scene/world 正式表。stop_demo 必须级联删除 3 张子表,否则正式数据被"演示污染"。
|
||
2. **三处同步注册**:新增函数必须同步 demo/demo.py、demo/__init__.py、demo/init.py 三处(env.xxx = xxx)。
|
||
3. **异常→状态码映射**:DemoParamError→400、DemoNotFoundError→404、DemoDuplicateError→409、DemoStateError→400;dspy 里必须 try/except 后返回 `{"status":..., "message":...}`。
|
||
4. **sor.C 必须显式带 created_at**:sqlor 不自动补时间戳,缺 created_at 会导致插入静默丢失。
|
||
5. **dspy 禁止 import**:所有函数经 load_demo 注册为全局;dspy 里直接 `await start_demo(...)`。
|
||
6. **取库名**:`get_module_dbname('demo')`(dspy 全局)或 `ServerEnv().get_module_dbname('demo')`(.py),禁止硬编码 DBNAME。
|
||
7. **dspy 显式 return**:ahserver 包裹 async 函数,裸表达式返回 None。
|
||
8. 前端 `.js` 里可用 fetch/setInterval(非 script actiontype);bricks script actiontype 内禁止 fetch/setInterval。
|