增加拖拽操作按钮
在二开场景中,你可能希望给画布上的组件增加“额外的快捷操作”,例如:一键高亮、快速生成联动、绑定业务数据、打开自定义弹窗配置等。本文讲清楚在设计器中如何在组件右下角的操作区新增一个按钮,并通过事件把“目标组件规则(rule)”传递出去执行自定义逻辑。
你可以把它理解为:仿照已有的
copy/delete,新增一个custom(或任意名称)的“组件操作”事件。
你需要了解
画布上每个组件都会被
DragTool包一层,用于渲染“移动/复制/删除”等操作按钮DragTool只负责$emit(...)抛事件,真正的“复制/删除”等逻辑在FcDesigner.vue的handleToolCopy / handleToolDelete中实现
你要改哪些地方?
增加一个“组件操作按钮”通常涉及 2 个文件:
- 操作按钮 UI 与事件抛出:
src/designer/DragTool.vue- 新增一个按钮
- 增加对应的
emits事件名
- 事件接收与执行自定义逻辑:
src/designer/FcDesigner.vue- 在构造
DragTool节点时补齐on: { custom: ... }的监听 - 新增一个
handleToolCustom(命名自定)方法,统一拿到targetRule并执行自定义操作
- 在构造
参考样例:copy / delete 的完整链路
在源码中,copy/delete 的链路非常典型:
1. DragTool.vue 里只做 $emit
copy/delete 按钮点击后,直接触发:
$emit('copy')$emit('delete')
你新增按钮时沿用这个模式即可。
2. FcDesigner.vue 里把事件映射到处理函数
FcDesigner.vue 在把组件规则包装成 DragTool 时,会在 on 中绑定事件处理:
copy: ({ self }) => methods.handleToolCopy({ self, inside: true/false })delete: ({ self }) => methods.handleToolDelete({ self, inside: true/false })
3. handleToolCopy/handleToolDelete 统一拿到 targetRule
关键点在于:同一个按钮事件,需要兼容两种包装模式:
inside === true:DragTool在规则的children内(“内嵌模式”)inside === false:DragTool是外层 wrapper(“外包裹模式”)
所以源码里会用同样的判断统一得到“真正被操作的规则”:
targetRule = inside ? methods.getParent(self).parent : self.children[0]
新增自定义操作,也建议复用这一套 targetRule 计算方式。
方案设计与约定
事件命名建议
- 按钮事件名建议用语义清晰、可扩展的名字,例如:
custom(通用)highlight(高亮)bind(绑定)linkage(联动)
显隐与权限
DragTool.vue 对 copy/delete 的显示控制包含两层:
- 按钮白名单:通过
handleBtn(数组)控制显示哪些按钮(例如['copy','delete']) - 权限对象:通过
permission.xxx !== false控制某个按钮是否允许
新增按钮时建议也按同样方式接入(这样业务方可以用“配置/权限”控制按钮显隐,而不是写死在源码里)。
实现步骤
下面以新增一个 custom 操作为例(你可以替换成任意事件名)。
1. 在 DragTool.vue 新增按钮并抛出事件
文件:src/designer/DragTool.vue
1.1 增加 emits 声明
把 custom 加到 emits 数组中(示例):
emits: ['create', 'copy', 'addChild', 'delete', 'custom', 'active', 'action', 'fc.el'],1.2 在操作区增加按钮
参照 copy/delete 的写法,新增一段按钮(示例用 icon-setting,你也可以换成你们的业务图标):
<div
class="_fd-drag-btn"
@click.stop
v-if="permission.custom !== false && (btns === true || btns.indexOf('custom') > -1)"
@click="$emit('custom')"
>
<i class="fc-icon icon-setting"></i>
</div>建议
如果你希望按钮只在“选中激活”时显示,不需要额外处理:DragTool 已有样式逻辑,会在 active/hover 时显示按钮。
2. 在 FcDesigner.vue 接收事件并执行自定义逻辑
文件:src/designer/FcDesigner.vue
2.1 在 DragTool 的事件映射里补齐 custom
在构造 DragTool 的两处 on: { ... } 里都加上(inside: true 与 inside: false 各一处):
custom: ({ self }) => methods.handleToolCustom({ self, inside: true }),custom: ({ self }) => methods.handleToolCustom({ self, inside: false }),2.2 增加处理函数 handleToolCustom
仿照 handleToolCopy/handleToolDelete,统一拿到 targetRule 后执行你的业务操作。最推荐的方式是:
- 在
FcDesigner内部完成“默认行为”(例如弹窗、改规则、写入扩展字段等) - 同时对外
emit('custom', targetRule),让集成项目可监听(按需)
示例(伪代码):
handleToolCustom({ self, inside }) {
const targetRule = inside ? methods.getParent(self).parent : self.children[0];
// 1) 执行你的自定义逻辑(示例:给规则打标记)
targetRule.props = targetRule.props || {};
targetRule.props.__bizTagged = true;
// 2) 如果影响了右侧面板/画布展示,可按需刷新
if (data.activeRule === targetRule) {
methods.updateRuleFormData();
}
// 3) 对外抛事件(按需:让集成项目接管)
vm.emit('custom', targetRule);
},2.3(可选)把 custom 加到组件的 emits 列表
如果你希望在集成项目里这样监听:
<FcDesigner @custom="onCustomTool" />那么需要把 custom 加到 FcDesigner.vue 的 emits: [...] 中(与 copy/delete/create 同级)。
常见问题排查
1. 按钮显示了,但点击没有反应
- 最可能原因:
DragTool.vue里只新增了按钮,但没有把事件名加入emits,导致 Vue 丢弃事件 - 定位路径:
src/designer/DragTool.vue的emits: [...] - 修复方式:把
custom加入emits
2. 点击触发了,但拿到的 rule 不对(删错/改错组件)
- 最可能原因:没有按
inside区分取targetRule - 定位路径:
src/designer/FcDesigner.vue的handleToolCopy/handleToolDelete(对照它们的取值方式) - 修复方式:使用统一写法
targetRule = inside ? methods.getParent(self).parent : self.children[0]
3. 集成项目监听不到 @custom
- 最可能原因:
FcDesigner.vue的emits列表没加入custom - 定位路径:
src/designer/FcDesigner.vue顶部emits: [...] - 修复方式:加入
custom,并在handleToolCustom中vm.emit('custom', targetRule)
附录:相关文件路径速查
- 工具栏组件:
src/designer/DragTool.vue - 工具栏事件处理:
src/designer/FcDesigner.vue


