import { message } from 'ant-design-vue'; import { AbsoluteLayoutController } from '@ibizstudio/absolute-layout-design'; import { acc, IBzEvent, IEntity, IParams } from '@ibizstudio/api'; import { clone, mergeRight } from 'ramda'; import { CreateElement } from 'vue'; import { Item } from '../../config/absolute-layout-material/item/item'; import { IPanelAbsoluteLayoutContext } from '../../interface/i-panel-absolute-layout-context'; import { PanelItemAbsoluteLayoutController } from './panel-item-absolute-layout-controller'; /** * 面板绝对布局控制器 * * @export * @class PanelAbsoluteLayoutController * @extends {AbsoluteLayoutController} */ export class PanelAbsoluteLayoutController extends AbsoluteLayoutController { /** * 实体名称 * * @type {string} * @memberof PanelAbsoluteLayoutController */ entityName: string = 'PSSysViewPanel'; /** * 加载状态 * * @type {Subject} * @memberof PanelAbsoluteLayoutController */ readonly evt: IBzEvent<{ loaded: IEntity }> = new IBzEvent(); /** * 主数据对象 * * @type {*} * @memberof PanelAbsoluteLayoutController */ masterData: any = {}; /** * 项控制器 * * @type {PanelItemAbsoluteLayoutController} * @memberof PanelAbsoluteLayoutController */ itemCtrl: PanelItemAbsoluteLayoutController = new PanelItemAbsoluteLayoutController(this.ctx); /** * @description acc订阅标识 * @type {string[]} * @memberof PanelAbsoluteLayoutController */ accSubs: string[] = []; /** * 绘制子 * * @param {CreateElement} h * @param {IPanelAbsoluteLayoutContext} ctx * @param {*} item * @return {*} * @memberof PanelAbsoluteLayoutController */ renderChildItem(h: CreateElement, ctx: IPanelAbsoluteLayoutContext, item: any) { const key = item.srfkey || 'tempkey'; const data = { ctx: ctx, item: item.data ? item.data : item, text: item.text, }; switch (data.item.itemtype) { case 'FIELD': Object.assign(data, { renderType: 'item' }); Object.assign(data, { componentName: 'panel-absolute-layout-item' }); return { template: ``, data() { return data; }, }; default: Object.assign(data, { renderType: 'other' }); Object.assign(data, { componentName: 'panel-absolute-layout-other' }); return { template: ``, data() { return data; }, }; } } /** * 订阅数据变更 * * @memberof PanelAbsoluteLayoutController */ subscription() { this.accSubs.push( acc.commandLocal( async (entity: any) => { const cell: any = this.graph.getCellById(entity.srfkey); cell.resize(entity.panelwidth, entity.panelheight); this.masterData = entity; const items = await this.itemCtrl.selectPanelItems(); items.forEach((item: any) => { const node: any = this.graph.getCellById(item.srfkey); const { x, y } = this.computeOffsetXY(item); node.setPosition(x, y); if (Object.is(item.al_pos, 'LTRB')) { const { width, height } = this.computeBox(item); node.resize(width, height); } }); }, 'update', this.entityName.toUpperCase(), ) ); } /** * 节点默认填充值 * * @param {*} item * @memberof PanelAbsoluteLayoutController */ defaultNodeConfig(item: any) { return { ...this.computeBox(item), ...this.computeOffsetXY(item), }; } /** * 计算盒子宽高 * * @param {*} item * @memberof PanelAbsoluteLayoutController */ computeBox(item: any) { if (item.al_pos && Object.is(item.al_pos, 'LTRB')) { return { width: this.masterData.panelwidth - item.leftpos - item.rightpos, height: this.masterData.panelheight - item.toppos - item.bottompos, }; } else { return { width: item.width ? item.width : Item[item.itemtype]?.width ? Item[item.itemtype]?.width : 0, height: item.height ? item.height : Item[item.itemtype]?.height ? Item[item.itemtype]?.height : 0, }; } } /** * 计算节点位置 * * @param {*} item * @memberof PanelAbsoluteLayoutController */ computeOffsetXY(item: any): any { if (item.al_pos) { if (Object.is(item.al_pos, 'LTWH') || Object.is(item.al_pos, 'LTRB')) { return { x: item.leftpos, y: item.toppos, }; } else if (Object.is(item.al_pos, 'RBWH')) { return { x: this.masterData.panelwidth - (item.rightpos + item.width), y: this.masterData.panelheight - (item.bottompos + item.height), }; } } else { return { x: item.leftpos, y: item.toppos, }; } } /** * 获取服务对象 * * @return {*} {Promise} * @memberof PanelAbsoluteLayoutController */ getService(): Promise { const getServiceName = `get${this.entityName}Service`; return (___ibz___.gs as any)[getServiceName](); } /** * 加载面板模型数据 * * @param {IParams} [params] * @memberof FormDesignController */ async load(params: IParams = {}): Promise { const { ctrl, context } = this.ctx; const s = await this.getService(); const res = await s.Get(mergeRight(context, params)); if (res.ok) { this.subscription(); this.itemCtrl.subscription(); const temp = await s.GetTemp(context, params); if (temp.ok) { this.masterData = temp.data; this.setMainInfo(temp.data); ctrl.select.set(this.masterData); return this.masterData; } else { message.error('看板内容加载失败: ' + temp.statusText); } return null; } else { message.error('看板内容加载失败: ' + res.statusText); } return null; } /** * 事件注册 * * @memberof PanelAbsoluteLayoutController */ registerEvent() { this.registerNodeClick(); this.registerNodeDragEnd(); this.registerNodeResize(); } /** * 节点单击事件注册 * * @memberof PanelAbsoluteLayoutController */ registerNodeClick() { this.graph?.on('node:click', async ({ e, x, y, node, view }: any) => { const item = node.getAttrs()?.item; if (Object.is(item.srfkey, this.masterData.srfkey)) { this.ctx.ctrl.select.set(item); } else { const s = await this.itemCtrl.getService(); const res = await s.GetTemp({ ...this.ctx.context, [this.itemCtrl.entityName.toLocaleLowerCase()]: item?.srfkey, }); if (res.ok) { this.ctx.ctrl.select.set(res.data); } } }); } /** * 注册节点拖拽结束事件 * * @memberof PanelAbsoluteLayoutController */ registerNodeDragEnd() { this.graph?.on('node:moved', async ({ e, x, y, node, view }: any) => { const item = node.getAttrs()?.item; const s = await this.itemCtrl.getService(); const { context } = this.ctx; const res = await s.GetTemp( Object.assign(clone(context), { [this.itemCtrl.entityName.toLocaleLowerCase()]: item?.srfkey }), ); if (res.ok) { const data = res.data; const bbox = node.getBBox(); Object.assign(data, this.computePos(bbox)); await s.UpdateTemp(context, data); } }); } /** * 通过盒子与位置返回属性 * * @param {*} {x,y,width,height} * @memberof PanelAbsoluteLayoutController */ computePos({ x, y, width, height }: any) { const leftpos = x; const toppos = y; const rightpos = this.masterData.panelwidth - (width + x); const bottompos = this.masterData.panelheight - (height + y); return { leftpos: leftpos, toppos: toppos, rightpos: rightpos, bottompos: bottompos }; } /** * 是否在顶级容器内部 * * @memberof PanelAbsoluteLayoutController */ isNodeContainerInner(x: number, y: number, width: number, height: number): boolean { if (x < 0 || x > this.masterData.width - width) { return false; } if (y < 0 || y > this.masterData.height - height) { return false; } return true; } /** * 注册节点大小变更事件 * * @memberof PanelAbsoluteLayoutController */ registerNodeResize() { this.graph?.on('node:resized', async ({ e, x, y, node, view }) => { const item = node.getAttrs()?.item; if (Object.is(item.srfkey, this.masterData.srfkey)) { } else { const bbox = node.getBBox(); const s = await this.itemCtrl.getService(); const { context } = this.ctx; const res = await s.GetTemp({ ...context, [this.itemCtrl.entityName.toLocaleLowerCase()]: item?.srfkey, }); if (res.ok) { const data = res.data; Object.assign(data, { width: bbox.width, height: bbox.height }); Object.assign(data, this.computePos(bbox)); const updateRes = await s.UpdateTemp(context, data); if (updateRes.ok) { this.select.set(updateRes.data); } } } }); } destroy() { this.itemCtrl.destroy(); this.accSubs.forEach(item => { acc.unsubscribeLocal(item); }); } }