From f6edbf43b16e04aadd7876af1ffe62a3dd1cd279 Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Wed, 6 Nov 2024 21:05:24 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E7=94=98=E7=89=B9=E9=83=A8?= =?UTF-8?q?=E4=BB=B6=E9=80=82=E9=85=8D=E6=BB=91=E5=9D=97=E7=B2=98=E6=80=A7?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E6=A0=B7=E5=BC=8F=E5=8F=8A=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=BB=91=E5=9D=97=E9=A3=98=E7=AA=97=E6=89=93=E5=BC=80=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/control/gantt/gantt.scss | 58 ++++++++++++++++++ src/control/gantt/gantt.tsx | 110 ++++++++++++++++++++++++----------- 3 files changed, 136 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 020c77e8..d038d097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ### Changed - 菜单、分页导航样式变量提取,树节点样式调整 +- 甘特部件适配滑块粘性布局样式及调整滑块飘窗打开方式 ## [0.7.38-alpha.22] - 2024-11-04 diff --git a/src/control/gantt/gantt.scss b/src/control/gantt/gantt.scss index e432b2b9..55c3fa33 100644 --- a/src/control/gantt/gantt.scss +++ b/src/control/gantt/gantt.scss @@ -49,6 +49,46 @@ height: 100%; } } + + // 适配滑块粘性布局 + .xg-row.xg-gantt-row { + overflow: visible; + + .xg-slider{ + &.xg-slider-drag.xg-slider-level0 { + overflow: visible; + } + + .xg-slider-block { + overflow: visible; + } + + // 任务滑块宽度为0时不显示 + &.is-no-width { + display: none; + } + } + } + .#{bem('control-gantt__slider--caption')} { + position: sticky; + left: 8px; + } + + // 滑块超出结束时间的总范围时 + .is-exceeds-range { + .#{bem('control-gantt__slider')} { + &::after { + position: absolute; + right: 0; + z-index: 99; + display: block; + width: 16px; + height: 100%; + content: ''; + background-color: var(--ibiz-color-primary); + } + } + } } @include m(empty) { .xg-table-body { @@ -56,6 +96,8 @@ } } @include e(slider) { + display: flex; + align-items: center; height: 100%; padding: getCssVar(spacing,none) getCssVar(spacing,base-tight); cursor: pointer; @@ -93,6 +135,13 @@ align-items: center; } } + + @include m(caption) { + overflow: hidden; + color: getCssVar(color, 'primary', 'text'); + text-overflow: ellipsis; + white-space: nowrap; + } } @include e('setting') { display: flex; @@ -102,6 +151,15 @@ fill: getCssVar('color','primary'); } } + + @include e('slider-popover') { + z-index: 300; + 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; diff --git a/src/control/gantt/gantt.tsx b/src/control/gantt/gantt.tsx index 215c2ea5..92cd1abc 100644 --- a/src/control/gantt/gantt.tsx +++ b/src/control/gantt/gantt.tsx @@ -5,6 +5,7 @@ import { useControlController, useNamespace, useUIStore, + IBizControlShell, } from '@ibiz-template/vue3-util'; import { computed, @@ -37,6 +38,7 @@ import { IModal, IModalData, IColumnState, + IOverlayPopoverContainer, } from '@ibiz-template/runtime'; import { showTitle } from '@ibiz-template/core'; import { MenuItem } from '@imengyu/vue3-context-menu'; @@ -70,6 +72,9 @@ export const GanttControl = defineComponent({ const isInited: Ref = ref(false); const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); + // 滑块模态 + let overlay: null | IOverlayPopoverContainer = null; + // 滑块移动 const sliderMove = ref(false); @@ -559,14 +564,12 @@ export const GanttControl = defineComponent({ * @return {*} */ const renderNodePanel = (modelData: IPanel, item: IData) => { - return ( - - ); + return h(IBizControlShell, { + data: item, + modelData, + context: c.context, + params: c.params, + }); }; /** @@ -591,6 +594,49 @@ export const GanttControl = defineComponent({ ); }; + /** + * 打开 popover + * + * @param {IGanttNodeData} item + * @param {MouseEvent} evt + * @return {*} + */ + const openPopover = (row: IGanttNodeData, evt: MouseEvent): void => { + if (overlay) { + return; + } + const panel = findNodeLayoutPanel(row._nodeId); + const component = panel + ? renderNodePanel(panel, row._deData!) + : renderNodeInfo(row); + overlay = ibiz.overlay.createPopover( + (modal: IModal): VNode => { + return h(component, { modal }); + }, + undefined, + { + width: 'auto', + height: 'auto', + noArrow: true, + placement: 'bottom', + modalClass: ns.e('slider-popover'), + }, + ); + setTimeout(() => { + overlay?.present((evt.target as IParams).children[0] as HTMLElement); + }, 300); + }; + + /** + * 关闭 popover + * + * @return {*} + */ + const closePopover = (): void => { + overlay?.dismiss(); + overlay = null; + }; + /** * 绘制滑块 * @@ -605,35 +651,33 @@ export const GanttControl = defineComponent({ resize-right={c.state.sliderDraggable} > {{ - content: ({ row }: { row: IGanttNodeData }): VNode => { + content: ({ + row, + left, + }: { + row: IGanttNodeData; + left: number; + }): JSX.Element => { const { sysCss } = c.getNodeModel(row._nodeId)!; const sysCssName = sysCss?.cssName || ''; - + const marginLeft = left < 0 ? `${-left}px` : ''; + const caption = row?._text; return ( - onNodeClick(row, evt)} + onDblclick={() => onNodeDbClick(row)} + onContextmenu={evt => onNodeContextmenu(row, evt)} + onMouseenter={evt => openPopover(row, evt)} + onMouseleave={closePopover} > - {{ - reference: () => { - return ( -
onNodeClick(row, evt)} - onDblclick={() => onNodeDbClick(row)} - onContextmenu={evt => onNodeContextmenu(row, evt)} - >
- ); - }, - default: () => { - const panel = findNodeLayoutPanel(row._nodeId); - return panel - ? renderNodePanel(panel, row._deData!) - : renderNodeInfo(row); - }, - }} -
+
+ ); }, }} -- Gitee