From 6436dcdd85bbbb042815d0188ad797ceb24a1cc6 Mon Sep 17 00:00:00 2001 From: whyzxhnd Date: Wed, 20 Aug 2025 13:17:27 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/components/Lock/DetailPointModal.vue | 2 +- web/src/components/Lock/LockPointNode.vue | 390 +++++++++++++++++++++ web/src/components/Lock/LockPointNodeAdapter.ts | 129 +++++++ web/src/components/LogicFlow/LockPointNode.vue | 390 --------------------- .../components/LogicFlow/LockPointNodeAdapter.ts | 129 ------- web/src/components/Map/index.vue | 15 + web/src/views/lock/isolation/plan/PlanForm.vue | 2 +- 7 files changed, 536 insertions(+), 521 deletions(-) create mode 100644 web/src/components/Lock/LockPointNode.vue create mode 100644 web/src/components/Lock/LockPointNodeAdapter.ts delete mode 100644 web/src/components/LogicFlow/LockPointNode.vue delete mode 100644 web/src/components/LogicFlow/LockPointNodeAdapter.ts create mode 100644 web/src/components/Map/index.vue diff --git a/web/src/components/Lock/DetailPointModal.vue b/web/src/components/Lock/DetailPointModal.vue index 0ef7d08..9fec792 100644 --- a/web/src/components/Lock/DetailPointModal.vue +++ b/web/src/components/Lock/DetailPointModal.vue @@ -78,7 +78,7 @@ import { PlanItemDetail } from '@/api/isolation/planitemdetail' import { DICT_TYPE } from '@/utils/dict' import { Lock } from '@/api/electron/lock' import { PlanItem } from '@/api/isolation/planitem' -import LockPointNodeAdapter from '@/components/LogicFlow/LockPointNodeAdapter' +import LockPointNodeAdapter from './LockPointNodeAdapter' defineOptions({ name: 'DetaiPointModal' }) const elLockStore = useElLockStore() diff --git a/web/src/components/Lock/LockPointNode.vue b/web/src/components/Lock/LockPointNode.vue new file mode 100644 index 0000000..3b6f14e --- /dev/null +++ b/web/src/components/Lock/LockPointNode.vue @@ -0,0 +1,390 @@ + + + + + diff --git a/web/src/components/Lock/LockPointNodeAdapter.ts b/web/src/components/Lock/LockPointNodeAdapter.ts new file mode 100644 index 0000000..f437fc3 --- /dev/null +++ b/web/src/components/Lock/LockPointNodeAdapter.ts @@ -0,0 +1,129 @@ +import { HtmlNode, HtmlNodeModel } from '@logicflow/core' +import { createApp, h, App as VueApp } from 'vue' +import LockPointVueNode from './LockPointNode.vue' + +class LockPointNodeModel extends HtmlNodeModel { + setAttributes() { + // 设置节点的默认属性 + this.text.editable = false // 禁用默认文本编辑 + this.text.value = '' // 清空默认文本 + this.draggable = false + // 初始占位,后续通过 ResizeObserver 自适应 + this.width = 400 + this.height = 200 + } + + /** + * 获取节点样式 + */ + getNodeStyle() { + const style = super.getNodeStyle() + return { + ...style, + stroke: 'transparent', + fill: 'transparent' + } + } +} + +class LockPointNode extends HtmlNode { + private vueApp: VueApp | null = null + private resizeObserver: ResizeObserver | null = null + + /** + * 设置HTML内容 + */ + setHtml(rootEl: SVGForeignObjectElement) { + const node = this.props.model + const pointId = node.properties.pointId + + // 创建Vue应用实例 + this.vueApp = createApp({ + components: { + LockPointVueNode + }, + render: () => h(LockPointVueNode, { + ...node.properties + }) + }) + + // 创建容器元素 + const container = document.createElement('div') + container.id = `lock-point-node-${pointId}` + container.style.position = 'relative' + container.style.pointerEvents = 'auto' + container.style.display = 'inline-block' + + // 挂载Vue应用 + this.vueApp.mount(container) + rootEl.appendChild(container) + + // 使用 ResizeObserver 监听容器尺寸变化,并同步到模型与 foreignObject + const syncSize = () => { + const width = Math.ceil(container.offsetWidth) + const height = Math.ceil(container.offsetHeight) + if (!width || !height) return + + if (this.props.model.width !== width || this.props.model.height !== height) { + this.props.model.width = width + this.props.model.height = height + rootEl.setAttribute('width', String(width)) + rootEl.setAttribute('height', String(height)) + } + } + + // 初次挂载后同步一次 + requestAnimationFrame(syncSize) + this.resizeObserver = new ResizeObserver(() => { + syncSize() + }) + this.resizeObserver.observe(container) + } + /** + * 组件销毁时清理Vue应用 + */ + destroy() { + if (this.resizeObserver) { + this.resizeObserver.disconnect() + this.resizeObserver = null + } + if (this.vueApp) { + this.vueApp.unmount() + this.vueApp = null + } + } +} + +// 导出节点配置 +export default { + type: 'lock-point-node', + view: LockPointNode, + model: LockPointNodeModel +} + +// 导出节点类型 +export const LockPointNodeType = 'lock-point-node' + +// 导出节点属性接口 +export interface LockPointNodeProperties { + pointId?: number + planId?: number +} + +// 导出创建节点的辅助函数 +export function createLockPointNode( + id: string, + x: number, + y: number, + properties: LockPointNodeProperties = {} +) { + return { + id, + type: LockPointNodeType, + x, + y, + properties: { + ...properties + } + } +} diff --git a/web/src/components/LogicFlow/LockPointNode.vue b/web/src/components/LogicFlow/LockPointNode.vue deleted file mode 100644 index 3b6f14e..0000000 --- a/web/src/components/LogicFlow/LockPointNode.vue +++ /dev/null @@ -1,390 +0,0 @@ - - - - - diff --git a/web/src/components/LogicFlow/LockPointNodeAdapter.ts b/web/src/components/LogicFlow/LockPointNodeAdapter.ts deleted file mode 100644 index f437fc3..0000000 --- a/web/src/components/LogicFlow/LockPointNodeAdapter.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { HtmlNode, HtmlNodeModel } from '@logicflow/core' -import { createApp, h, App as VueApp } from 'vue' -import LockPointVueNode from './LockPointNode.vue' - -class LockPointNodeModel extends HtmlNodeModel { - setAttributes() { - // 设置节点的默认属性 - this.text.editable = false // 禁用默认文本编辑 - this.text.value = '' // 清空默认文本 - this.draggable = false - // 初始占位,后续通过 ResizeObserver 自适应 - this.width = 400 - this.height = 200 - } - - /** - * 获取节点样式 - */ - getNodeStyle() { - const style = super.getNodeStyle() - return { - ...style, - stroke: 'transparent', - fill: 'transparent' - } - } -} - -class LockPointNode extends HtmlNode { - private vueApp: VueApp | null = null - private resizeObserver: ResizeObserver | null = null - - /** - * 设置HTML内容 - */ - setHtml(rootEl: SVGForeignObjectElement) { - const node = this.props.model - const pointId = node.properties.pointId - - // 创建Vue应用实例 - this.vueApp = createApp({ - components: { - LockPointVueNode - }, - render: () => h(LockPointVueNode, { - ...node.properties - }) - }) - - // 创建容器元素 - const container = document.createElement('div') - container.id = `lock-point-node-${pointId}` - container.style.position = 'relative' - container.style.pointerEvents = 'auto' - container.style.display = 'inline-block' - - // 挂载Vue应用 - this.vueApp.mount(container) - rootEl.appendChild(container) - - // 使用 ResizeObserver 监听容器尺寸变化,并同步到模型与 foreignObject - const syncSize = () => { - const width = Math.ceil(container.offsetWidth) - const height = Math.ceil(container.offsetHeight) - if (!width || !height) return - - if (this.props.model.width !== width || this.props.model.height !== height) { - this.props.model.width = width - this.props.model.height = height - rootEl.setAttribute('width', String(width)) - rootEl.setAttribute('height', String(height)) - } - } - - // 初次挂载后同步一次 - requestAnimationFrame(syncSize) - this.resizeObserver = new ResizeObserver(() => { - syncSize() - }) - this.resizeObserver.observe(container) - } - /** - * 组件销毁时清理Vue应用 - */ - destroy() { - if (this.resizeObserver) { - this.resizeObserver.disconnect() - this.resizeObserver = null - } - if (this.vueApp) { - this.vueApp.unmount() - this.vueApp = null - } - } -} - -// 导出节点配置 -export default { - type: 'lock-point-node', - view: LockPointNode, - model: LockPointNodeModel -} - -// 导出节点类型 -export const LockPointNodeType = 'lock-point-node' - -// 导出节点属性接口 -export interface LockPointNodeProperties { - pointId?: number - planId?: number -} - -// 导出创建节点的辅助函数 -export function createLockPointNode( - id: string, - x: number, - y: number, - properties: LockPointNodeProperties = {} -) { - return { - id, - type: LockPointNodeType, - x, - y, - properties: { - ...properties - } - } -} diff --git a/web/src/components/Map/index.vue b/web/src/components/Map/index.vue new file mode 100644 index 0000000..9d93743 --- /dev/null +++ b/web/src/components/Map/index.vue @@ -0,0 +1,15 @@ + + + diff --git a/web/src/views/lock/isolation/plan/PlanForm.vue b/web/src/views/lock/isolation/plan/PlanForm.vue index 5dfe2a2..d3344e4 100644 --- a/web/src/views/lock/isolation/plan/PlanForm.vue +++ b/web/src/views/lock/isolation/plan/PlanForm.vue @@ -348,7 +348,7 @@ import { Document, Lock, Unlock } from '@element-plus/icons-vue' import dayjs from 'dayjs' import LogicFlow from '@logicflow/core' import '@logicflow/core/lib/style/index.css' -import LockPointNodeAdapter from '@/components/LogicFlow/LockPointNodeAdapter' +import LockPointNodeAdapter from '@/components/Lock/LockPointNodeAdapter' import { useAppStore } from '@/store/modules/app' // 类型定义 interface PlanItem {