import { Component, Vue, Prop } from 'vue-property-decorator'; import { CreateElement } from 'vue'; import { Addon, Cell, CellView, Graph } from '@antv/x6'; import { IPanelAbsoluteLayoutContext } from '../../../interface/i-panel-absolute-layout-context'; import './panel-absolute-layout-content.less'; import { PanelAbsoluteLayoutController } from '../../..'; import { Options } from '@antv/x6/lib/graph/options'; import { IPSSysViewPanelItem } from '@ibizstudio/api'; import { clone } from 'ramda'; @Component export class PanelAbsoluteLayoutContent extends Vue { @Prop() ctx!: IPanelAbsoluteLayoutContext; /** * 控制器 * * @type {PanelAbsoluteLayoutController} * @memberof PanelAbsoluteLayoutContent */ ctrl!: PanelAbsoluteLayoutController; /** * 当前dom实例对象 * * @type {HTMLDivElement} * @memberof PanelAbsoluteLayoutContent */ el!: HTMLDivElement; /** * 图表大小变更事件监听 * * @type {*} * @memberof PanelAbsoluteLayoutContent */ resizeGraph: any; /** * Vue实例创建完成 * * @memberof PanelAbsoluteLayoutContent */ async created() { this.ctrl = this.ctx.ctrl; this.loaded = this.loaded.bind(this); this.ctx.ctrl.evt.on('loaded', this.loaded); } async loaded() { await this.initNodeContainer(); await this.loadChildrenNode(); } /** * Vue生命周期,实例挂载完毕 * * @memberof PanelAbsoluteLayoutContent */ async mounted() { await this.initGraph(); await this.elasticGraph(); await this.initDnd(); await this.ctrl.registerEvent(); } /** * Vue生命周期,实例销毁前 * * @memberof PanelAbsoluteLayoutContent */ beforeDestroy() { document.removeEventListener('resize', this.resizeGraph); } /** * 初始化画布 * * @memberof PanelAbsoluteLayoutContent */ async initGraph() { this.el = this.$refs.panel_graph as any; const { ctrl } = this; const graphConfig: Partial = {}; Object.assign(graphConfig, { container: this.el, background: { color: '#f0f0f0', }, scroller: { enabled: true, //是否启动滚动条 pannable: true, //是否拖拽移动画布 background: { color: '#f0f0f0', }, autoResize: true, padding: 50, }, translating: { restrict(view: any) { const cell = view.cell; if (cell.isNode()) { const parent = cell.getParent(); if (parent) { return parent.getBBox(); } } return null as any; }, }, interacting: { nodeMovable: function(this: Graph, cellView: CellView) { const cell = cellView?.cell; if (Object.is(cell?.id, ctrl.masterData.srfkey)) { return false; } return true; }, }, mousewheel: { enabled: true, modifiers: ['ctrl', 'meta'], }, resizing: { enabled(this: Graph, arg: any) { if (Object.is(arg?.id, ctrl.masterData.srfkey)) { return false; } return true; }, }, snapline: { enabled: true, resizing: true, }, }); const minimap = this.$refs.minimap; if (minimap) { Object.assign(graphConfig, { minimap: { enabled: true, container: minimap, }, }); } const graph = new Graph(graphConfig); graph.setScrollbarPosition(-50, -50); this.ctrl.graph = graph; } /** * 图表根据窗体大小变化重写绘制 * * @memberof PanelAbsoluteLayoutContent */ async elasticGraph() { this.resizeGraph = addEventListener('resize', () => { this.ctrl.graph?.resize(document.body.offsetWidth - 600, document.body.offsetHeight - 38); }); } /** * 初始化节点容器 * * @memberof PanelAbsoluteLayoutContent */ async initNodeContainer() { const data = this.ctrl.masterData; if (!data.panelwidth || !data.panelheight) { data.panelwidth = 1000; data.panelheight = 1000; const s = await this.ctrl.getService(); s.UpdateTemp(this.ctx.context, data); this.ctrl.masterData = data; } const nodeContainer = this.ctrl.graph.createNode({ id: data.srfkey, x: 0, y: 0, width: data.panelwidth, height: data.panelheight, zIndex: 1, attrs: { body: { stroke: '#000', }, item: data, }, }); this.ctrl.nodeContainer = nodeContainer; this.ctrl.graph.addNode(nodeContainer); } /** * 加载子节点 * * @memberof PanelAbsoluteLayoutContent */ async loadChildrenNode() { const items = await this.ctrl.itemCtrl.selectPanelItems(); if (items && items.length > 0) { items.forEach((item: IPSSysViewPanelItem) => { this.ctrl.addNode(null, item); }); } } /** * 初始化拖拽控制器 * * @memberof PanelAbsoluteLayoutContent */ async initDnd() { const graph = this.ctrl.graph; if (graph) { const { Dnd } = Addon; const dnd = new Dnd({ target: graph, scaled: false, animation: true, validateNode: async (droppingNode: any, options) => { const bbox = droppingNode.getBBox(); if (!this.ctrl.isNodeContainerInner(bbox.x, bbox.y, bbox.width, bbox.height)) { return false; } this.ctrl.nodeContainer.addChild(droppingNode); const item = droppingNode.getAttrs()?.item; if (item) { Object.assign(item, this.ctrl.computePos(bbox)); const res = await this.ctrl.itemCtrl.s.GetDraftTemp(this.ctx.context, { ...item, pssysviewpanelid: this.ctx.context.pssysviewpanel, }); if (res.ok) { droppingNode.id = res.data.srfkey; const attrs = droppingNode.getAttrs(); droppingNode.setAttrs(Object.assign(attrs, { item: res.data })); this.ctrl.itemCtrl.addPanelItem(res.data); this.ctrl.itemCtrl.evt.emit('added'); } } return true; }, }); this.ctrl.dnd = dnd; } } /** * 注册按键 * * @memberof PanelAbsoluteLayoutContent */ registerKey() { window.addEventListener('keydown', this.onKeyDown); } /** * 销毁按键事件 * * @memberof PanelAbsoluteLayoutContent */ destroyKey() { window.removeEventListener('keydown', this.onKeyDown); } /** * 按键按下触发 * * @param {KeyboardEvent} evt * @memberof PanelAbsoluteLayoutContent */ async onKeyDown(evt: KeyboardEvent) { const k = evt.keyCode || evt.keyCode; const { context } = this.ctx; const { itemCtrl } = this.ctrl; if (k === 8 && this.ctrl.select.data) { await itemCtrl.s.RemoveTemp({ ...context, [itemCtrl.entityName.toLocaleLowerCase()]: this.ctrl.select.data.srfkey, }); this.ctrl.graph.removeCell(this.ctrl.select.data.srfkey!); const s = await this.ctrl.getService(); const res = await s.GetTemp(context); if (res.ok) { this.ctx.ctrl.select.set(res.data); } } } /** * 绘制函数 * * @param {CreateElement} h * @memberof PanelAbsoluteLayoutContent */ render(h: CreateElement) { return (
this.registerKey()} on-mouseleave={() => this.destroyKey()} >
); } }