设计器指针与触摸交互
在可视化设计器中安全使用鼠标、触摸和触控笔新增、排序及移动控件。
表单设计器的 Pointer Events 与触摸交互
目的
表单设计器在不改变持久化表单 Schema 的前提下,同时支持统一的 Pointer Events 拖动和明确的点选添加备用流程。
- 鼠标、触摸和触控笔都可以把面板控件或现有控件拖到插入目标。
- 键盘和触摸用户也可以先选择面板控件,再激活“在这里添加”目标。
- 根列表、嵌套容器、Pane 和表格单元格共用同一套目标和数据变更规则。
架构与数据流
`designerPointerDrag.js` 管理唯一的活动指针会话。会话记录 pointer ID、来源类型、控件深复制、起点、当前目标和显示名称。手势移动达到 8 像素后才会进入拖动状态,因此普通点击不会被误判为拖动。
`ComponentPanel.vue`、`DesignArea.vue`、`FormRenderer.vue` 和 `FormTable.vue` 建立三种来源会话:
- `palette`:建立新控件;
- `component`:移动已有根级或嵌套控件,并保留其 ID;
- `table`:移动 Form Table 已占用单元格中的控件。
`DesignerTapInsertTarget.vue` 通过 DOM data 属性提供统一目标协议。指针拖动期间,它显示为紧凑的插入条或表格单元格目标;点选添加期间,它仍是具有本地化无障碍名称、可由键盘操作的按钮。`DesignArea.vue` 负责验证,并在目标被接受后对 Pinia 表单树执行一次数据变更。
管理器通过 `document.elementsFromPoint()` 命中测试,显示不截获事件的拖动预览,并高亮当前有效目标。指针靠近边缘时,它会持续滚动最近的可滚动祖先。Pointer cancel、浏览器窗口失焦或 Escape 会结束会话而不修改表单。成功拖动后会抑制同一手势产生的后续 click,避免意外进入点选添加模式。
支持的来源与目标
| 来源 | 根列表 | 可编辑容器或 Pane | 空 Form Table 单元格 |
|---|---|---|---|
| 面板控件 | 新增 | 新增 | 类型兼容时新增 |
| 根级或嵌套控件 | 移动/排序 | 移动/排序 | 类型兼容时移入 |
| Form Table 单元格控件 | 移出 | 移出 | 在空兼容单元格之间移动 |
每个根级或嵌套控件之前及列表末尾都有插入位置。可编辑目标包括 DIV、Form、Form Group、占位模式 Custom Block、当前 Tabs/Pagination Pane,以及各个 Grid Layout Pane。
从表单或 JSON 加载的 Custom Block 内容仍然只读。已有内容的表格单元格绝不被覆盖。容器不能放进自身或其任何后代;通过 Pane 或表格单元格到达的后代同样受保护。无效目标不会高亮,在其上松开不会改变来源控件。
点选与键盘备用流程
通过触摸、点击、Enter 或空格选择面板控件,会进入一次性添加模式。激活“在这里添加”目标后,只插入一个控件并立即消费待添加项。再次选择同一个面板控件可取消;开始 Pointer 拖动也会取消待处理的点选添加。
该临时选择保存在 `formDesigner.js`,不会导出或写入表单 Schema。
兼容性与安全边界
- 使用 Pointer Events 代替浏览器 `DataTransfer` 作为主要拖动路径,同一实现覆盖鼠标、触摸和触控笔。
- 移动已有控件时保留控件 ID;从面板新增时继续使用原有的 ID 和默认属性生成逻辑。
- Viewer 渲染、表单 JSON、服务器 API、权限和数据库结构均不改变。
- 管理器只接受设计器自己渲染的目标,并在真正修改前按当前控件树重新验证。
- 表格类型限制、占用单元格保护和容器循环保护均采用失败关闭。
- 指针坐标及表单内容不会发送到服务器。
手工验证
重新构建前端后,分别用鼠标、真实触摸设备或浏览器触摸模拟检查:
1. 通过触摸和键盘选择面板控件,将其加入根级、容器、Pane 和表格目标,并可取消模式。
2. 把面板控件拖到根列表和嵌套列表的开头、中间及末尾。
3. 把列表第一项移到末尾,并把末项移到开头。
4. 在根级、嵌套容器、Tabs/Pagination/Grid Pane 和空兼容表格单元格之间移动控件。
5. 把表格控件移到另一个空单元格及移出到列表,确认 ID 保持不变。
6. 确认占用单元格、不兼容的表格控件类型、自身目标和后代目标都会拒绝,且来源不会被删除。
7. 拖到各可滚动区域边缘并停留,确认自动滚动持续发生且目标高亮跟随内容。
8. 分别用 Escape、系统 pointer cancel 和窗口失焦取消,确认表单没有变化。
9. 确认短按仍会选择面板控件,完成拖动后不会额外触发一次点击。