89 lines
4.1 KiB
Markdown
89 lines
4.1 KiB
Markdown
# drag 拖拽编程画布模块
|
||
|
||
元景 W-09 拖拽编程画布模块:把可视化拖拽块(事件/逻辑/动作/变量/表达式)连线成流程,
|
||
编译为 script_engine 可执行 Python 脚本(script_type=0)。
|
||
|
||
## 功能
|
||
|
||
- **画布**:打开/加块/移动/连接/删除/保存(graph_save)
|
||
- **块体系**:事件(开始/点击/悬停/定时/碰撞/键盘)、逻辑(顺序/循环/条件判断/分叉/等待/并行/函数定义/函数调用)、
|
||
动作(移动/旋转/缩放/改属性/播放动画/播放声音/显隐/相机)、变量(创建/赋值/读取)、表达式(算术/比较/逻辑)
|
||
- **实体选择器**:绑定块(entity 参数 → 实体下拉)
|
||
- **参数校验**:必填/类型/范围/枚举/标识符/变量引用/函数引用/孤立块/无入口/环形连线
|
||
- **编译**:compile_graph → script_engine 可执行脚本(变量提升、函数区、事件入口分支、控制流展开)
|
||
- **发布**:graph_publish 写入 script_engine 模块(script_type=0)
|
||
- **模板**:drag_template 表 + template_use 一键生成新画布
|
||
|
||
## 数据表(drag 库)
|
||
|
||
| 表 | 说明 |
|
||
|----|------|
|
||
| drag_graph | 画布:name / description / blocks(JSON) / connections(JSON) / content(编译产物) / status |
|
||
| drag_template | 模板:name / category / description / blocks(JSON) / connections(JSON) |
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
drag/
|
||
├── drag/ # Python 包
|
||
│ ├── __init__.py # 导出(三处同步注册)
|
||
│ ├── init.py # load_drag() 挂载全部函数
|
||
│ ├── blocks.py # 块定义 JSON(唯一事实源)
|
||
│ ├── validator.py # 图校验器
|
||
│ └── compiler.py # 图 → Python 脚本编译器
|
||
├── wwwroot/ # index.ui / editor.ui / drag-canvas.js / drag-editor.js / drag.css / api/*.dspy
|
||
├── models/ # drag_graph.json / drag_template.json
|
||
├── json/ # drag_graph.json / drag_template.json(CRUD)
|
||
├── init/data.json # appcodes(drag_status)
|
||
├── scripts/load_path.py # RBAC
|
||
└── skill/SKILL.md # 模块技能
|
||
```
|
||
|
||
## 安装与集成
|
||
|
||
1. `pip install .` 安装模块包
|
||
2. 宿主应用 `app/scense.py`:`from drag.init import load_drag` + `load_drag()`(init() 内)
|
||
3. `build.sh`:生成 DDL / CRUD UI / 软链 wwwroot 到宿主 `/d/scense/scense_app/wwwroot/drag`
|
||
4. RBAC:执行 `scripts/load_path.py`(或在中心 load_path.py 添加 drag 路径)
|
||
5. 菜单:global_menu.ui 增加 `{"name":"drag","label":"拖拽编程","url":"{{entire_url('/drag/index.ui')}}"}`
|
||
|
||
## 关键接口(load_drag() 挂载)
|
||
|
||
| 函数 | 说明 |
|
||
|------|------|
|
||
| get_block_defs_api() | 块定义(categories + blocks) |
|
||
| graph_save(ns) | 保存画布(新建/更新,保存即校验+编译) |
|
||
| graph_compile(ns) | 编译 → {success, content, errors} |
|
||
| graph_validate(ns) | 校验 → {valid, errors, warnings} |
|
||
| graph_publish(ns) | 发布到 script_engine |
|
||
| list/get/create/update/delete_drag_graph | 画布 CRUD |
|
||
| list/get/create/update/delete_drag_template | 模板 CRUD |
|
||
| template_use(ns) | 模板 → 新画布 |
|
||
| get_entity_options() | 实体下拉 |
|
||
|
||
## 编译产物示例
|
||
|
||
```python
|
||
# ===== 变量声明 =====
|
||
score = 0
|
||
# ===== 函数定义 =====
|
||
def jump():
|
||
move(entity='hero', x=0, y=100, duration=0.5)
|
||
# ===== 入口: 开始 =====
|
||
if score > 100:
|
||
play_animation(entity='hero', animation='run')
|
||
else:
|
||
wait(seconds=1)
|
||
```
|
||
|
||
## 陷阱
|
||
|
||
- 取库名用 `ServerEnv().get_module_dbname('drag')`,禁止硬编码 DBNAME
|
||
- 块定义修改需同步:blocks.py(唯一源)+ 前端渲染自动读取(block_defs.dspy 下发)
|
||
- .dspy 无 import/print/uuid/f-string,显式 return;helper 全部在 init.py
|
||
- `sor.C/U/D/R` 只有这四个 sqlor 方法;分页用 `sor.sqlPaging`,不硬编码 LIMIT
|
||
- 保存时 `created_at/updated_at = curDateString()`,否则 sor.C 静默丢记录
|
||
- 编译产物仅含白名单语法(赋值/def/for/while/if-else/函数调用/注释),供 script_engine 白名单执行
|
||
- 事件块无输入端口 = 天然入口;事件块不能作为连线目标
|
||
- 动态端口(分叉/并行)由 `dynamic_outputs` 声明,按 branch_count 生成输出端口
|