2026-08-29 21:10:23 +08:00

4.8 KiB
Raw Permalink Blame History

name description
drag 拖拽编程画布模块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    块定义 JSONcategories + blocks唯一事实源
   ├── validator.py 图校验(无入口/孤立/环形/参数/变量引用)
   └── compiler.py  图 → Python 脚本(变量提升/函数区/事件分支/控制流)
   ▼
drag_graph / drag_template 表drag 库)+ script_engine 发布

数据模型

  • drag_graphid(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_templateid、name、category(32, 通用/移动/弹球/计时)、description、 blocks(text)、connections(text)、created_at、updated_at。
  • 编码drag_status0 草稿 / 1 启用)→ appcodesinit/data.json Format B

块契约block 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"} 声明动态端口。
  • 参数 uitypetext/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显式 returnhelper 在 init.py三处同步注册 drag/init.py 导出 ← drag/init.py 实现 ← load_drag() env.xxx 注册)。
  • sor.C/U/D/R + sqlPagingcreated_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_graphblocks/connections JSON 往返一致。
  • 编译产出可执行脚本graph_compile 返回 Python 源码,无校验错误时可被 script_engine 执行。
  • 校验能报孤立块/无入口graph_validate 对孤立块报 ORPHAN_BLOCK、无事件块报 NO_ENTRY。
  • 正反用例按 feature-granularity-and-testing每功能点至少 1 正例 + 1 反例。