scense_drag/skill/SKILL.md
2026-08-29 21:10:23 +08:00

90 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: drag
description: 拖拽编程画布模块(W-09)——可视化块编排、连线、参数校验、编译为 script_engine 可执行脚本,提供画布/模板 CRUD 与 block_defs/graph_save/graph_compile/graph_validate/graph_publish 接口,通过 load_drag() 挂载。
---
# drag 拖拽编程画布模块
元景 W-09:把事件/逻辑/动作/变量/表达式块拖拽连线成流程图,校验后编译为
script_engine 可执行 Python 脚本(script_type=0)。宿主应用:scense(/d/scense/scense_app)。
## 架构
```
bricks 前端 (editor.ui + drag-canvas.js + drag-editor.js)
│ block_defs / graph_save / graph_compile / graph_validate / graph_publish
▼
drag 模块 (init.py 挂载)
├── blocks.py 块定义 JSON(categories + blocks,唯一事实源)
├── validator.py 图校验(无入口/孤立/环形/参数/变量引用)
└── compiler.py 图 → Python 脚本(变量提升/函数区/事件分支/控制流)
▼
drag_graph / drag_template 表(drag 库)+ script_engine 发布
```
## 数据模型
- `drag_graph`:id(32 PK)、name(100)、description(255)、blocks(text JSON)、
connections(text JSON)、content(text 编译产物)、status(16, drag_status 0草稿/1启用)、
created_at、updated_at。索引 idx_drag_graph_name/status。
- `drag_template`:id、name、category(32, 通用/移动/弹球/计时)、description、
blocks(text)、connections(text)、created_at、updated_at。
- 编码:drag_status(0 草稿 / 1 启用)→ appcodes(init/data.json Format B)。
## 块契约(block JSON)
```json
{"type":"action_move","category":"action","label":"移动","icon":"fa fa-arrows-alt",
"params":[{"name":"entity","label":"目标实体","uitype":"entity","required":true},
{"name":"x","label":"X 位移","uitype":"number","default":"0"}],
"ports":{"inputs":[{"name":"in","label":"上一步"}],
"outputs":[{"name":"out","label":"下一步"}]}}
```
- 事件块(category=event)无输入端口 = 天然入口,不能作为连线目标。
- 分叉/并行块用 `dynamic_outputs={"param":"branch_count","prefix":"branch"}` 声明动态端口。
- 参数 uitype:text/number/select/boolean/entity/expression/variable/textarea。
- 表达式参数支持 `@变量名` 引用(validator 校验已创建变量)。
## 关键端点(/drag/api/*.dspy,宿主挂载后 /drag/api/*.dspy)
| 端点 | 方法 | 入参 | 返回 |
|------|------|------|------|
| block_defs.dspy | GET | - | {categories, blocks} |
| graph_save.dspy | POST | {id?, name, blocks, connections} | {success, id, valid, errors, content} |
| graph_list.dspy | GET | {page, rows, name?, status?} | {list, total} |
| graph_get.dspy | GET | {id} | {data:{blocks, connections, content}} |
| graph_delete.dspy | POST | {id} | {success} |
| graph_compile.dspy | POST | {name?, blocks, connections} | {success, content, entry_points} |
| graph_validate.dspy | POST | {blocks, connections} | {valid, errors:[{code,message,block_id,field}]} |
| graph_publish.dspy | POST | {id, script_name?} | {success, script_id, script_name} |
| template_save/list/delete/use.dspy | - | - | - |
| get_search_entity.dspy | GET | - | [{value,text}] 实体下拉 |
## 错误码
PARAM_REQUIRED / PARAM_TYPE / PARAM_RANGE / PARAM_OPTION / INVALID_IDENTIFIER /
VAR_UNDEFINED / FUNC_UNDEFINED / BLOCK_UNKNOWN_TYPE / NO_ENTRY / ORPHAN_BLOCK /
UNREACHABLE_BLOCK / CONN_BLOCK_NOT_FOUND / CONN_PORT_NOT_FOUND / CONN_DUPLICATE /
CONN_SELF_LOOP / CONN_CYCLE / EVENT_AS_TARGET / NOT_FOUND / DB_ERROR / COMPILE_ERROR
## 模块陷阱
- 取库名:.py 用 `ServerEnv().get_module_dbname('drag')`;.dspy 直接 `get_module_dbname('drag')`。
- dspy 无 import/print/uuid;显式 return;helper 在 init.py;三处同步注册
(drag/__init__.py 导出 ← drag/init.py 实现 ← load_drag() env.xxx 注册)。
- sor.C/U/D/R + sqlPaging;created_at/updated_at 必须显式设置。
- CRUD 复数别名 create_drag_graphs 等已注册(CRUD 框架约定)。
- 编译产物仅白名单语法(赋值/def/for/while/if-else/函数调用/注释),
动作函数(move/rotate/scale/set_property/play_animation/play_sound/show_hide/camera/wait)
需宿主演绎层注册到 script_engine 白名单。
- 前端 .js/.css 必须在 load_path.py 注册 any 角色,否则 403。
- 修改 blocks.py 后前端自动通过 block_defs.dspy 拿到新定义,无需改前端。
## 验收口径(W-09a~W-09au)
- 拖块连块存画布:graph_save 落库 drag_graph,blocks/connections JSON 往返一致。
- 编译产出可执行脚本:graph_compile 返回 Python 源码,无校验错误时可被 script_engine 执行。
- 校验能报孤立块/无入口:graph_validate 对孤立块报 ORPHAN_BLOCK、无事件块报 NO_ENTRY。
- 正反用例按 feature-granularity-and-testing:每功能点至少 1 正例 + 1 反例。