From 53e57bb16fcfeb1c35637ac7a0fed136ce8dc5ab Mon Sep 17 00:00:00 2001 From: ShineKOT <1917095344@qq.com> Date: Wed, 27 Aug 2025 20:53:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA=E7=BB=84=EF=BC=8C=E8=AF=86=E5=88=AB=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E7=95=8C=E9=9D=A2=E8=A1=8C=E4=B8=BA=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/common/action-toolbar/action-toolbar.scss | 12 +++ src/common/action-toolbar/action-toolbar.tsx | 83 ++++++++++++++++--- src/control/dashboard/dashboard.tsx | 28 ++++--- .../actionbar-portlet/actionbar-portlet.tsx | 5 +- .../portlet/portlet-layout/portlet-layout.tsx | 8 +- src/control/data-view/data-view.scss | 1 + src/control/data-view/data-view.tsx | 4 + .../form-group-panel/form-group-panel.tsx | 5 +- .../form-detail/form-mdctrl/form-mdctrl.tsx | 12 ++- src/control/form/form/form.tsx | 15 ++-- src/control/grid/grid/grid.tsx | 6 +- src/control/kanban/kanban.scss | 14 ++++ src/control/kanban/kanban.tsx | 39 +++++---- .../swimlane-kanban/swimlane-kanban.scss | 5 ++ .../swimlane-kanban/swimlane-kanban.tsx | 1 + src/control/list/list.tsx | 14 +++- .../tree-grid-ex-field-column.tsx | 12 ++- src/control/tree-grid-ex/tree-grid-ex.tsx | 19 +++-- src/control/tree-grid/tree-grid.tsx | 3 + 20 files changed, 223 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86267213..094fca70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### Changed - 调整属性列自定义参数(columntype)为小写,此参数的作用是允许在表格列中预览文件数据,配置示例:columntype=attachment +- 优化表格列界面行为组,树表格列界面行为组,树表格增强列界面行为组,列表项,分组界面行为组,卡片项,分组界面行为组,看板项,分组界面行为组,表单分组面板界面行为组,表单多数据部件界面行为组,门户部件操作栏,门户部件界面行为组,识别引用界面行为组 ## Fixed diff --git a/src/common/action-toolbar/action-toolbar.scss b/src/common/action-toolbar/action-toolbar.scss index 1482acd6..798d166c 100644 --- a/src/common/action-toolbar/action-toolbar.scss +++ b/src/common/action-toolbar/action-toolbar.scss @@ -47,6 +47,18 @@ $action-toolbar: ( } } + @include e(group-item) { + > span { + width: 100%; + } + @include m(caption) { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + } + } + @include e('separator'){ height: auto; } diff --git a/src/common/action-toolbar/action-toolbar.tsx b/src/common/action-toolbar/action-toolbar.tsx index 273f0a20..a5f11ce3 100644 --- a/src/common/action-toolbar/action-toolbar.tsx +++ b/src/common/action-toolbar/action-toolbar.tsx @@ -1,3 +1,5 @@ +/* eslint-disable no-use-before-define */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { defineComponent, PropType, Ref, ref, VNode } from 'vue'; import { useNamespace, usePopoverVisible } from '@ibiz-template/vue3-util'; import { IButtonContainerState } from '@ibiz-template/runtime'; @@ -122,8 +124,8 @@ export const IBizActionToolbar = defineComponent({ ns, dropdownRef, popoverIndex, - expandDetails, groupDetails, + expandDetails, groupButtonRef, popoverVisible, handleClick, @@ -143,11 +145,76 @@ export const IBizActionToolbar = defineComponent({ ); }; + // 绘制引用界面行为组 + const renderActionGroup = ( + detail: IAppDEUIActionGroupDetail, + isExpand = true, + ) => { + const actionGroup = detail.refUIActionGroup; + if (!actionGroup?.uiactionGroupDetails?.length) return null; + // 子项所有项都隐藏,父项也应该隐藏 + const pvisible = + actionGroup.uiactionGroupDetails.findIndex(item => { + return this.actionsState[item.id!].visible === true; + }) !== -1; + if (!pvisible) return null; + return [ + detail.addSeparator && renderDivider(isExpand), + + {{ + reference: () => { + return ( + +
+ {actionGroup.id} + +
+
+ ); + }, + default: () => { + return renderActions( + actionGroup.uiactionGroupDetails || [], + isExpand, + ); + }, + }} +
, + ]; + }; + const renderActions = ( items: IAppDEUIActionGroupDetail[], isExpand = true, - ) => { + ): any => { return items.map(detail => { + if (detail.detailType === 'DEUIACTIONGROUP' && detail.refUIActionGroup) + return renderActionGroup(detail); if (this.actionsState[detail.id!]?.visible) { return [ detail.addSeparator && renderDivider(isExpand), @@ -195,17 +262,13 @@ export const IBizActionToolbar = defineComponent({ }; const renderGroup = () => { - if (this.groupDetails.length === 0) { - return null; - } + if (this.groupDetails.length === 0) return null; // 子项所有项都隐藏,父项也应该隐藏 const pvisible = this.groupDetails.findIndex(item => { return this.actionsState[item.id!].visible === true; }) !== -1; - if (!pvisible) { - return null; - } + if (!pvisible) return null; // 当前项禁用或子项所有项都禁用,父项也应该禁用 const pdisabled = this.groupDetails.findIndex(item => { @@ -249,9 +312,7 @@ export const IBizActionToolbar = defineComponent({ ]; }; - if (!this.actionsState?.visible) { - return; - } + if (!this.actionsState?.visible) return; if (this.mode === 'buttons') { // 按钮模式 diff --git a/src/control/dashboard/dashboard.tsx b/src/control/dashboard/dashboard.tsx index c4d8ef1b..6a28c7a2 100644 --- a/src/control/dashboard/dashboard.tsx +++ b/src/control/dashboard/dashboard.tsx @@ -1,26 +1,30 @@ -import { useControlController, useNamespace } from '@ibiz-template/vue3-util'; import { - ConcreteComponent, - defineComponent, - getCurrentInstance, + useNamespace, + useControlController, + useControlPopoverzIndex, +} from '@ibiz-template/vue3-util'; +import { h, - isReactive, - PropType, - reactive, Ref, ref, - resolveComponent, VNode, + PropType, + reactive, + isReactive, + defineComponent, + resolveComponent, + ConcreteComponent, + getCurrentInstance, } from 'vue'; import { IDashboard, - IDBContainerPortletPart, - IDBPortletPart, IModelObject, + IDBPortletPart, + IDBContainerPortletPart, } from '@ibiz/model-core'; -import './dashboard.scss'; import { DashboardController, IControlProvider } from '@ibiz-template/runtime'; import { uniqueId } from 'lodash-es'; +import './dashboard.scss'; // 刷新标记 const refreshTagObj: IData = {}; @@ -113,6 +117,8 @@ export const DashboardControl = defineComponent({ (...args) => new DashboardController(...args), ); + useControlPopoverzIndex(c); + const vue = getCurrentInstance()!.proxy!; // 自定义门户模型数组 diff --git a/src/control/dashboard/portlet/actionbar-portlet/actionbar-portlet.tsx b/src/control/dashboard/portlet/actionbar-portlet/actionbar-portlet.tsx index 484493fe..74bca87c 100644 --- a/src/control/dashboard/portlet/actionbar-portlet/actionbar-portlet.tsx +++ b/src/control/dashboard/portlet/actionbar-portlet/actionbar-portlet.tsx @@ -20,6 +20,8 @@ export const ActionBarPortlet = defineComponent({ `portlet-${props.modelData.portletType?.toLowerCase()}`, ); + const zIndex = props.controller.dashboard.state.zIndex; + // 点击工具栏处理 const onActionClick = async ( detail: IUIActionGroupDetail, @@ -28,7 +30,7 @@ export const ActionBarPortlet = defineComponent({ await props.controller.onActionClick(detail, event); }; - return { ns, onActionClick }; + return { ns, zIndex, onActionClick }; }, render() { @@ -42,6 +44,7 @@ export const ActionBarPortlet = defineComponent({ {this.modelData.uiactionGroup && ( { const classNames = [ns.em('toolbar', `${portletType}-${c.model.id}`)]; const { codeName } = c.dashboard.view.model; @@ -67,12 +67,13 @@ export const PortletLayout = defineComponent({ return { c, ns, + zIndex, popperClass, portletType, isShowHeader, - onActionClick, openLink, clickPorlet, + onActionClick, }; }, render() { @@ -115,6 +116,7 @@ export const PortletLayout = defineComponent({
{model.portletType !== 'ACTIONBAR' && model.uiactionGroup && ( new DataViewControlController(...args), ); const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); + useControlPopoverzIndex(c); const classNames = computed(() => { return [ns.is('enable-page', c.model.enablePagingBar === true)]; @@ -309,6 +311,7 @@ export const DataViewControl = defineComponent({ class={ns.bem('item-content', 'bottom', 'actions')} action-details={c.getOptItemModel()} actions-state={c.state.uaState[item.srfkey]} + zIndex={c.state.zIndex} onActionClick={( detail: IUIActionGroupDetail, event: MouseEvent, @@ -497,6 +500,7 @@ export const DataViewControl = defineComponent({ {c.model.groupUIActionGroup && group.groupActionGroupState && ( { if (!c.disableClose) { c.state.collapse = !c.state.collapse; @@ -43,7 +45,7 @@ export const FormGroupPanel = defineComponent({ return caption; }); - return { ns, captionText, changeCollapse, onActionClick }; + return { ns, zIndex, captionText, changeCollapse, onActionClick }; }, render() { const { state } = this.controller; @@ -109,6 +111,7 @@ export const FormGroupPanel = defineComponent({
{this.modelData.uiactionGroup && ( {model.uiactionGroup && ( { - zIndex.decrement(); if (cleanup !== NOOP) cleanup(); if (cleanClick !== NOOP) cleanClick(); if (cleanEnter !== NOOP) cleanEnter(); diff --git a/src/control/kanban/kanban.scss b/src/control/kanban/kanban.scss index 5a047293..56db6dde 100644 --- a/src/control/kanban/kanban.scss +++ b/src/control/kanban/kanban.scss @@ -90,6 +90,11 @@ $control-kanban: ( } } } + + .#{bem(control-kanban, default-item)}, + .#{bem(control-kanban, panel-item)} { + flex-grow: 1; + } } @include b(control-kanban-group-container) { @@ -276,6 +281,15 @@ $control-kanban: ( @include b(control-kanban) { position: relative; + @include e(popover) { + >.el-scrollbar { + overflow: visible; + } + .#{bem(action-toolbar, popover)} { + background-color: getCssVar(color, primary) !important; + } + } + @include e(quicktoolbar) { margin-bottom: getCssVar(spacing, base); visibility: hidden; diff --git a/src/control/kanban/kanban.tsx b/src/control/kanban/kanban.tsx index eafaccc9..6d4f296e 100644 --- a/src/control/kanban/kanban.tsx +++ b/src/control/kanban/kanban.tsx @@ -4,6 +4,7 @@ import { IBizCustomRender, useControlController, hasEmptyPanelRenderer, + useControlPopoverzIndex, } from '@ibiz-template/vue3-util'; import { ref, @@ -81,7 +82,10 @@ export const KanbanControl = defineComponent({ loadDefault: { type: Boolean, default: true }, }, setup(props) { - const c = useControlController((...args) => new KanbanController(...args)); + const c: KanbanController = useControlController( + (...args) => new KanbanController(...args), + ); + useControlPopoverzIndex(c); const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); const kanban = ref(); const isFull: Ref = ref(false); @@ -202,9 +206,7 @@ export const KanbanControl = defineComponent({ // 组件销毁前销毁监听 onBeforeUnmount(() => { - if (cleanup !== NOOP) { - cleanup(); - } + if (cleanup !== NOOP) cleanup(); }); // 绘制项布局面板 @@ -216,6 +218,7 @@ export const KanbanControl = defineComponent({ return ( { return ( { const actionModel = c.getOptItemModel(); - return [ -
-
{item.srfmajortext}
-
{item.content}
-
, - actionModel.length ? ( -
- {renderItemAction(item, group)} + return ( +
+
+
+ {item.srfmajortext} +
+
+ {item.content} +
- ) : null, - ]; + {actionModel.length ? ( +
+ {renderItemAction(item, group)} +
+ ) : null} +
+ ); }; // 绘制卡片 @@ -497,6 +507,7 @@ export const KanbanControl = defineComponent({ class={ns.be('group', 'header-actions')} trigger='click' teleported={false} + popper-class={ns.e('popover')} > {{ default: (): VNode => ( diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss index 799393ba..2370e047 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss @@ -12,6 +12,11 @@ $swimlane-kanban: ( padding: getCssVar('spacing', 'tight'); background-color: getCssVar('color', 'white'); + .#{bem(swimlane-kanban, default-item)}, + .#{bem(swimlane-kanban, panel-item)} { + flex-grow: 1; + } + @include e('default') { .#{bem('swimlane-kanban', 'cell')}:not(.is-collapsed) { width: getCssVar('swimlane-kanban', 'width'); diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx b/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx index 4ab1b3af..210b8358 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx @@ -473,6 +473,7 @@ export const SwimlaneKanban = defineComponent({ {actionModel.length ? (
new ListController(...args)); const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); + useControlPopoverzIndex(c); + const { onPageChange, onPageRefresh, onPageSizeChange } = usePagination(c); // 是否可以加载更多 @@ -262,6 +272,7 @@ export const ListControl = defineComponent({ class={ns.bem('item', 'right', 'actions')} action-details={c.getOptItemModel()} actions-state={c.state.uaState[item.srfkey]} + zIndex={c.state.zIndex} onActionClick={( detail: IUIActionGroupDetail, event: MouseEvent, @@ -316,6 +327,7 @@ export const ListControl = defineComponent({ if (c.model.groupUIActionGroup && group.groupActionGroupState) { return ( { // 非实体节点行的第一列显示文本值 @@ -125,14 +127,15 @@ export const TreeGridExFieldColumn = defineComponent({ return { ns, - nodeColumn, - fieldValue, + zIndex, + tooltip, showText, clickable, - tooltip, - onInfoTextChange, + nodeColumn, + fieldValue, onTextClick, onActionClick, + onInfoTextChange, }; }, render() { @@ -175,6 +178,7 @@ export const TreeGridExFieldColumn = defineComponent({ } else if (this.row.columnActionsStates[this.controller.name]) { actions = ( new TreeGridExController(...args), ); + useControlPopoverzIndex(c); + const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); const renderNoData = (): VNode | false => { diff --git a/src/control/tree-grid/tree-grid.tsx b/src/control/tree-grid/tree-grid.tsx index 4a270293..4a523432 100644 --- a/src/control/tree-grid/tree-grid.tsx +++ b/src/control/tree-grid/tree-grid.tsx @@ -3,6 +3,7 @@ import { IBizCustomRender, useControlController, hasEmptyPanelRenderer, + useControlPopoverzIndex, } from '@ibiz-template/vue3-util'; import { VNode, @@ -76,6 +77,8 @@ export const TreeGridControl = defineComponent({ const c: TreeGridController = useControlController( (...args) => new TreeGridController(...args), ); + useControlPopoverzIndex(c); + // 继承表格部件样式 const ns = useNamespace(`control-grid`); const ns2 = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); -- Gitee