From 34514fb892c85aa4389212e7556f9a4566342844 Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 7 Aug 2025 21:03:20 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E7=94=98?= =?UTF-8?q?=E7=89=B9=E5=9B=BE=E6=BB=91=E5=9D=97=E7=9A=84=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E7=BA=BF=E7=BB=98=E5=88=B6=EF=BC=8C=E6=96=B0=E5=A2=9E=E9=83=A8?= =?UTF-8?q?=E4=BB=B6=E5=8F=82=E6=95=B0linkdatasourcetype=EF=BC=88=E9=93=BE?= =?UTF-8?q?=E6=8E=A5=E6=95=B0=E6=8D=AE=E8=8E=B7=E5=8F=96=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=EF=BC=89=E3=80=81linkappdataentityname=EF=BC=88=E9=93=BE?= =?UTF-8?q?=E6=8E=A5=E6=95=B0=E6=8D=AE=E9=9B=86=E5=BA=94=E7=94=A8=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E5=90=8D=E7=A7=B0=EF=BC=89=E3=80=81linkappdedatasetna?= =?UTF-8?q?me=EF=BC=88=E9=93=BE=E6=8E=A5=E5=BA=94=E7=94=A8=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E7=BB=93=E6=9E=9C=E9=9B=86=E5=90=8D=E7=A7=B0=EF=BC=89?= =?UTF-8?q?=E3=80=81linknodedataname=EF=BC=88=E9=93=BE=E6=8E=A5=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=95=B0=E6=8D=AE=E5=B1=9E=E6=80=A7=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=EF=BC=89=E3=80=81fromdataitemname=EF=BC=88=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E8=B5=B7=E5=A7=8B=E6=95=B0=E6=8D=AE=E9=A1=B9=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=EF=BC=89=E3=80=81todataitemname=EF=BC=88?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E7=BB=93=E6=9D=9F=E6=95=B0=E6=8D=AE=E9=A1=B9?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=90=8D=E7=A7=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control/gantt/gantt.scss | 17 ++++++- src/control/gantt/gantt.tsx | 93 +++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/control/gantt/gantt.scss b/src/control/gantt/gantt.scss index 3695f64dd..900990c9e 100644 --- a/src/control/gantt/gantt.scss +++ b/src/control/gantt/gantt.scss @@ -33,6 +33,11 @@ // 警示色 --gantt-warning: var(--ibiz-color-warning); + // 链接线颜色 + + --gantt-color-linking: #{getCssVar(color, primary)}; + --gantt-link-path-hover: #{getCssVar(color, primary)}; + .xg-table-body .xg-table-row { cursor: pointer; @@ -161,6 +166,16 @@ border: none; box-shadow: getCssVar('shadow', 'elevated'); } + + @include e('link-path-popover') { + z-index: 300 !important; + width: auto; + min-width: 300px; + padding: 12px; + border: none; + box-shadow: getCssVar('shadow', 'elevated'); + } + .#{bem('tree-grid-ex-field-column','','ellipsis')} { .#{bem('tree-grid-ex-field-column-text-container')} { min-width: 0; @@ -177,5 +192,5 @@ .xg-view-toolbar-switch-action { // 文本 --gantt-text-switch-item: var(--ibiz-color-text-3); - --gantt-bg-hover-switch-item: var(--ibiz-color-bg-0);; + --gantt-bg-hover-switch-item: var(--ibiz-color-bg-0); } diff --git a/src/control/gantt/gantt.tsx b/src/control/gantt/gantt.tsx index c8ef52fef..9b5d0ae5b 100644 --- a/src/control/gantt/gantt.tsx +++ b/src/control/gantt/gantt.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable no-unused-vars */ /* eslint-disable no-restricted-syntax */ @@ -99,6 +100,8 @@ export const GanttControl = defineComponent({ // 滑块模态 let overlay: null | IOverlayPopoverContainer = null; + // 滑块链接线模态 + let linkOverlay: null | IOverlayPopoverContainer = null; // 滑块移动 const sliderMove = ref(false); @@ -219,13 +222,38 @@ export const GanttControl = defineComponent({ let layoutPanel: IPanel | undefined; const nodeModel = c.getNodeModel(id); nodeModel?.controlRenders?.forEach(renderItem => { - if (renderItem.renderType === 'LAYOUTPANEL') { + if ( + renderItem.renderType === 'LAYOUTPANEL' && + (renderItem.id || '').split('_')[0] !== 'nodelinkrender' + ) { layoutPanel = renderItem.layoutPanel; } }); return layoutPanel; }; + /** + * 查找对应节点链接的布局面板 + * + * @param {string} id + * @return {*} {(IPanel | undefined)} + */ + const findNodeLinkLayoutPanel = (id: string): IPanel | undefined => { + let layoutPanel: IPanel | undefined; + const nodeModel = c.getNodeModel(id); + nodeModel?.controlRenders?.find(renderItem => { + if ( + renderItem.renderType === 'LAYOUTPANEL' && + (renderItem.id || '').split('_')[0] === 'nodelinkrender' + ) { + layoutPanel = renderItem.layoutPanel; + return true; + } + return false; + }); + return layoutPanel; + }; + /** * 多选时选中节点变更 * @@ -802,6 +830,61 @@ export const GanttControl = defineComponent({ } }; + /** + * 打开链接 popover + * + * @param {IGanttNodeData} item + * @param {MouseEvent} evt + * @return {*} + */ + const openLinkPathPopover = async ( + row: IGanttNodeData, + panelData: IData, + evt: MouseEvent, + ): Promise => { + const panel = findNodeLinkLayoutPanel(row._nodeId); + if (linkOverlay || !panel) { + return; + } + const component = renderNodePanel(panel, panelData); + linkOverlay = ibiz.overlay.createPopover( + (modal: IModal): VNode => { + return h(component, { modal }); + }, + undefined, + { + width: 'auto', + height: 'auto', + noArrow: true, + autoClose: true, + modalClass: ns.e('link-path-popover'), + }, + ); + linkOverlay?.present(evt.currentTarget as HTMLElement); + + await linkOverlay.onWillDismiss(); + linkOverlay = null; + }; + + /** + * 处理点击链接线 + * + * @param {IData} [_link] + * @param {MouseEvent} [_event] + */ + const handleClickLink = (_link?: IData, _event?: MouseEvent): void => { + if (_link && _event) { + const curLink = c.state.links.find(_item => _item._uuid === _link.id); + if (curLink) { + openLinkPathPopover( + curLink._fromData as IGanttNodeData, + curLink._deData, + _event, + ); + } + } + }; + return { c, ns, @@ -825,6 +908,7 @@ export const GanttControl = defineComponent({ allowDrag, handleDrop, onHeaderDragend, + handleClickLink, }; }, render() { @@ -841,6 +925,7 @@ export const GanttControl = defineComponent({ ref='ganttRef' data-id='_id' data={this.data} + links={this.c.state.links} row-height={46} expand-all={false} headerDrag={true} @@ -849,6 +934,11 @@ export const GanttControl = defineComponent({ children='_children' leaf='_leaf' expand-key='_defaultExpand' + link-props={{ + fromKey: '_from', + toKey: '_to', + linkKey: '_uuid', + }} locale={this.locale} unit={this.c.state.unit} draggable={{ level: 'all', draggable: true }} @@ -863,6 +953,7 @@ export const GanttControl = defineComponent({ onRowChecked={this.onCheck} onHeaderDragend={this.onHeaderDragend} onMoveSlider={this.onSliderMove} + onClickLink={this.handleClickLink} primaryColor={this.ganttStyle.primaryColor} headerStyle={{ textColor: this.ganttStyle.textColor, -- Gitee From 7b9da3c07bf14bf6825994b9411afcfba14c439a Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 7 Aug 2025 21:03:47 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat=EF=BC=9A=E9=80=82=E9=85=8D=E5=A4=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=83=A8=E4=BB=B6=E5=88=B7=E6=96=B0=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E6=AF=8F=E6=AC=A1=E5=88=B7=E6=96=B0=E5=90=8E?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=94=98=E7=89=B9=E5=9B=BE=E9=80=89=E4=B8=AD?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E7=9A=84=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control/gantt/gantt.tsx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/control/gantt/gantt.tsx b/src/control/gantt/gantt.tsx index 9b5d0ae5b..38b150131 100644 --- a/src/control/gantt/gantt.tsx +++ b/src/control/gantt/gantt.tsx @@ -22,6 +22,7 @@ import { getCurrentInstance, ref, Ref, + nextTick, } from 'vue'; import { IDEGantt, @@ -110,6 +111,7 @@ export const GanttControl = defineComponent({ const iBizIcon = resolveComponent('IBizIcon'); let forbidClick: boolean = false; + let forbidOperation: boolean = false; const selection: IGanttNodeData[] = []; @@ -212,6 +214,28 @@ export const GanttControl = defineComponent({ return ibiz.i18n.getLang().toLowerCase(); }); + // 监听选中数据,操作甘特来处理界面回显选中效果。 + watch( + [() => ganttRef.value, (): IGanttNodeData[] => c.state.selectedData], + ([table, newVal]) => { + if (forbidOperation || !table) return; + nextTick(() => { + if (c.state.singleSelect) { + // 单选,选中效果回显。 + if (newVal[0]) { + ganttRef.value?.setSelected(newVal[0]); + } else { + ganttRef.value?.setSelected(); + } + } else { + selection.length = 0; + selection.push(...newVal); + newVal.forEach(item => ganttRef.value?.setChecked(item, true)); + } + }); + }, + ); + /** * 查找对应节点的布局面板 * @@ -261,6 +285,7 @@ export const GanttControl = defineComponent({ * @param {IGanttNodeData} item 当前数据 */ const onCheck = (state: boolean, item: IGanttNodeData) => { + forbidOperation = true; if (state) { selection.push(item); } else { @@ -272,6 +297,7 @@ export const GanttControl = defineComponent({ } } c.setSelection(selection); + forbidOperation = false; }; /** @@ -285,12 +311,14 @@ export const GanttControl = defineComponent({ sliderMove.value = false; return; } + forbidOperation = true; c.onTreeNodeClick(nodeData, evt); forbidClick = true; setTimeout(() => { forbidClick = false; }, 200); + forbidOperation = false; }; /** -- Gitee From 4ab836b86b89c8321e0971408c5232cbeb3b6207 Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 7 Aug 2025 21:05:24 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E6=A0=91?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E6=95=B0=E6=8D=AE=E6=8B=96=E6=8B=BD=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control/gantt/gantt.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/control/gantt/gantt.tsx b/src/control/gantt/gantt.tsx index 38b150131..218aa6d9e 100644 --- a/src/control/gantt/gantt.tsx +++ b/src/control/gantt/gantt.tsx @@ -969,7 +969,11 @@ export const GanttControl = defineComponent({ }} locale={this.locale} unit={this.c.state.unit} - draggable={{ level: 'all', draggable: true }} + draggable={{ + level: 'all', + draggable: false, + draggableStateKey: '_draggable', + }} allow-drop={this.allowDrop} allow-drag={this.allowDrag} onNodeDrop={this.handleDrop} -- Gitee From 556559c30126c19dc4271e2f9c396a828561b6d4 Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 7 Aug 2025 21:06:02 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat=EF=BC=9A=E6=9B=B4=E6=96=B0CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c53c655ee..584d2c940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,15 @@ ## [Unreleased] +### Added + +- 新增甘特图滑块的链接线绘制,新增部件参数linkdatasourcetype(链接数据获取模式)、linkappdataentityname(链接数据集应用实体名称)、linkappdedatasetname(链接应用实体结果集名称)、linknodedataname(链接节点数据属性名称)、fromdataitemname(链接起始数据项属性名称)、todataitemname(链接结束数据项属性名称) +- 新增树节点数据拖拽状态属性 + ### Changed - 更新drtab流布局导航栏样式 +- 适配多数据部件刷新模式,每次刷新后更新甘特图选中节点的样式 ## Fixed -- Gitee From 933223b9a27623987736675a64ee1b1a042d1d7f Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 7 Aug 2025 21:19:43 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat=EF=BC=9A=E8=B0=83=E6=95=B4=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=94=98=E7=89=B9=E5=9B=BE=E9=80=89=E4=B8=AD=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E7=9A=84=E6=A0=B7=E5=BC=8F=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control/gantt/gantt.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/control/gantt/gantt.tsx b/src/control/gantt/gantt.tsx index 218aa6d9e..195e18920 100644 --- a/src/control/gantt/gantt.tsx +++ b/src/control/gantt/gantt.tsx @@ -297,7 +297,9 @@ export const GanttControl = defineComponent({ } } c.setSelection(selection); - forbidOperation = false; + setTimeout(() => { + forbidOperation = false; + }, 200); }; /** @@ -317,8 +319,8 @@ export const GanttControl = defineComponent({ forbidClick = true; setTimeout(() => { forbidClick = false; + forbidOperation = false; }, 200); - forbidOperation = false; }; /** -- Gitee