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.jsonCRUD
├── init/data.json   # appcodesdrag_status
├── scripts/load_path.py  # RBAC
└── skill/SKILL.md   # 模块技能

安装与集成

  1. pip install . 安装模块包
  2. 宿主应用 app/scense.pyfrom 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() 实体下拉

编译产物示例

# ===== 变量声明 =====
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显式 returnhelper 全部在 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 生成输出端口
Description
No description provided
Readme 25 KiB