4.1 KiB
4.1 KiB
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 # 模块技能
安装与集成
pip install .安装模块包- 宿主应用
app/scense.py:from drag.init import load_drag+load_drag()(init() 内) build.sh:生成 DDL / CRUD UI / 软链 wwwroot 到宿主/d/scense/scense_app/wwwroot/drag- RBAC:执行
scripts/load_path.py(或在中心 load_path.py 添加 drag 路径) - 菜单: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() | 实体下拉 |
编译产物示例
# ===== 变量声明 =====
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 生成输出端口