From 708a5648dbef06a08463d72bd74e8ff9103abd8f Mon Sep 17 00:00:00 2001 From: ShineKOT <1917095344@qq.com> Date: Mon, 28 Jul 2025 15:04:14 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E6=B3=B3=E9=81=93=E7=9C=8B?= =?UTF-8?q?=E6=9D=BF=E6=96=B0=E5=A2=9E=E5=88=86=E7=BB=84=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++ src/common/index.ts | 2 + src/common/kanben-setting/kanben-setting.scss | 12 ++++ src/common/kanben-setting/kanben-setting.tsx | 69 +++++++++++++++++++ .../swimlane-kanban/swimlane-kanban.scss | 1 + .../swimlane-kanban/swimlane-kanban.tsx | 8 ++- src/locale/en/index.ts | 3 + src/locale/zh-CN/index.ts | 3 + 8 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/common/kanben-setting/kanben-setting.scss create mode 100644 src/common/kanben-setting/kanben-setting.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fa778465..36db9edc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ ## [Unreleased] +### Added + +- 泳道看板新增分组隐藏功能 + ## [0.7.41-alpha.15] - 2025-07-27 ### Added diff --git a/src/common/index.ts b/src/common/index.ts index aa80cec41..7abd94e9b 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -41,6 +41,7 @@ import { IBizGanttSetting } from './gantt-setting/gantt-setting'; import { IBizNavSplit } from './nav-split/nav-split'; import { IBizCropping } from './cropping/cropping'; import { IBizEditorEmptyText } from './editor-empty-text/editor-empty-text'; +import { IBizKanbanSetting } from './kanben-setting/kanben-setting'; export * from './col/col'; export * from './row/row'; @@ -54,6 +55,7 @@ export { DoingNotice } from './doing-notice/doing-notice'; export const IBizCommonComponents = { install: (v: App): void => { + v.component(IBizKanbanSetting.name, IBizKanbanSetting); v.component(IBizEditorEmptyText.name, IBizEditorEmptyText); v.component(IBizCropping.name, IBizCropping); v.component(IBizControlBase.name, IBizControlBase); diff --git a/src/common/kanben-setting/kanben-setting.scss b/src/common/kanben-setting/kanben-setting.scss new file mode 100644 index 000000000..98e6290c3 --- /dev/null +++ b/src/common/kanben-setting/kanben-setting.scss @@ -0,0 +1,12 @@ +@include b('kanban-setting') { + + @include e('popover') { + @include m('content') { + display: flex; + flex-direction: column; + width: 100%; + max-height: 500px; + overflow-y: auto; + } + } +} diff --git a/src/common/kanben-setting/kanben-setting.tsx b/src/common/kanben-setting/kanben-setting.tsx new file mode 100644 index 000000000..fc03520b4 --- /dev/null +++ b/src/common/kanben-setting/kanben-setting.tsx @@ -0,0 +1,69 @@ +/* eslint-disable no-nested-ternary */ +import { PropType, computed, defineComponent } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import { KanbanController } from '@ibiz-template/runtime'; +import './kanben-setting.scss'; + +export const IBizKanbanSetting = defineComponent({ + name: 'IBizKanbanSetting', + props: { + controller: { + type: Object as PropType, + required: true, + }, + }, + setup(props) { + const ns = useNamespace('kanban-setting'); + + const groups = computed(() => { + return props.controller.state.groups; + }); + + return { + ns, + groups, + }; + }, + render() { + return ( +
+ + {{ + reference: () => { + return ( + + + + ); + }, + default: () => { + return ( +
+ {this.groups.map(group => { + return ( + { + group.hidden = !val; + }} + /> + ); + })} +
+ ); + }, + }} +
+
+ ); + }, +}); diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss index 74180d790..8c40f1c24 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss @@ -32,6 +32,7 @@ $swimlane-kanban: ( box-sizing: border-box; width: 100%; min-width: fit-content; + overflow: hidden scroll; border-top: 1px solid getCssVar('color', 'border'); @include m('action') { visibility: hidden; diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx b/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx index 93ee1d777..473750265 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx @@ -21,9 +21,6 @@ export const SwimlaneKanban = defineComponent({ draggable, }, props: { - /** - * @description 面板直接内容控制器 - */ controller: { type: Object as PropType, required: true, @@ -366,9 +363,13 @@ export const SwimlaneKanban = defineComponent({ {ibiz.i18n.t('control.kanban.lane')} +
+ +
{c.state.groups.map(group => { + if (group.hidden) return undefined; return renderHeaderCell(group); })} @@ -632,6 +633,7 @@ export const SwimlaneKanban = defineComponent({ {c.state.groups.map(group => { + if (group.hidden) return undefined; return renderBodyCell(index, lane, group); })} diff --git a/src/locale/en/index.ts b/src/locale/en/index.ts index 5fd49a8a2..6ac668d32 100644 --- a/src/locale/en/index.ts +++ b/src/locale/en/index.ts @@ -592,6 +592,9 @@ export default { gridSetting: { hideControl: 'Column selection', }, + kanbanSetting: { + hideGroup: 'Group selection', + }, ganttSetting: { resultDefault: 'Restore defaults', headerCaption: 'Header display attributes', diff --git a/src/locale/zh-CN/index.ts b/src/locale/zh-CN/index.ts index 77af98144..a5ddc87b5 100644 --- a/src/locale/zh-CN/index.ts +++ b/src/locale/zh-CN/index.ts @@ -549,6 +549,9 @@ export default { gridSetting: { hideControl: '列选择', }, + kanbanSetting: { + hideGroup: '分组选择', + }, ganttSetting: { resultDefault: '恢复默认值', headerCaption: '表头显示属性', -- Gitee From 154779275572efa1a6fba75164d2d6f4b1def70f Mon Sep 17 00:00:00 2001 From: ShineKOT <1917095344@qq.com> Date: Mon, 28 Jul 2025 16:04:46 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/control/kanban/swimlane-kanban/swimlane-kanban.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss index 8c40f1c24..a71681193 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss @@ -32,7 +32,7 @@ $swimlane-kanban: ( box-sizing: border-box; width: 100%; min-width: fit-content; - overflow: hidden scroll; + padding-right: 4px; border-top: 1px solid getCssVar('color', 'border'); @include m('action') { visibility: hidden; -- Gitee From 396e6c1a28ff47c0137598198bc458aa4df4cbcc Mon Sep 17 00:00:00 2001 From: ShineKOT <1917095344@qq.com> Date: Tue, 29 Jul 2025 18:30:24 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E7=9C=8B=E6=9D=BF=E8=AF=86?= =?UTF-8?q?=E5=88=ABenableFullScreen=EF=BC=88=E5=90=AF=E7=94=A8=E5=85=A8?= =?UTF-8?q?=E5=B1=8F=EF=BC=89=E5=92=8C=20enableGroupHidden=EF=BC=88?= =?UTF-8?q?=E5=90=AF=E7=94=A8=E5=88=86=E7=BB=84=E9=9A=90=E8=97=8F=EF=BC=89?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 ++ src/common/kanben-setting/kanben-setting.tsx | 6 +- src/control/kanban/kanban.scss | 86 +++++++++---------- src/control/kanban/kanban.tsx | 26 ++++-- .../swimlane-kanban/swimlane-kanban.scss | 11 ++- .../swimlane-kanban/swimlane-kanban.tsx | 46 ++++++---- src/locale/en/index.ts | 2 + src/locale/zh-CN/index.ts | 2 + 8 files changed, 111 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36db9edc1..f6437625e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ ### Added - 泳道看板新增分组隐藏功能 +- 看板识别enableFullScreen(启用全屏)和 enableGroupHidden(启用分组隐藏)参数 + +### Fixed + +- 修复泳道看板快速操作栏和批操作栏异常 ## [0.7.41-alpha.15] - 2025-07-27 diff --git a/src/common/kanben-setting/kanben-setting.tsx b/src/common/kanben-setting/kanben-setting.tsx index fc03520b4..f88c6924a 100644 --- a/src/common/kanben-setting/kanben-setting.tsx +++ b/src/common/kanben-setting/kanben-setting.tsx @@ -11,6 +11,10 @@ export const IBizKanbanSetting = defineComponent({ type: Object as PropType, required: true, }, + buttonStyle: { + type: Object as PropType<{ circle: boolean; type: string }>, + default: () => ({ circle: false, type: 'info' }), + }, }, setup(props) { const ns = useNamespace('kanban-setting'); @@ -35,7 +39,7 @@ export const IBizKanbanSetting = defineComponent({ {{ reference: () => { return ( - + * + *{ + & > * + * { margin-left: getCssVar(spacing, base); } } @@ -36,7 +33,7 @@ $control-kanban: ( flex-direction: column; align-items: start; height: 100%; - padding: getCssVar('spacing','none'); + padding: getCssVar('spacing', 'none'); ion-icon { position: absolute; @@ -47,7 +44,8 @@ $control-kanban: ( } @include e(header-caption) { align-self: center; - transform: rotate(90deg) translate(calc(100% / 2 - var(--ibiz-spacing-tight)), 0); + transform: rotate(90deg) + translate(calc(100% / 2 - var(--ibiz-spacing-tight)), 0); } } } @@ -59,7 +57,7 @@ $control-kanban: ( flex-direction: column; - & > * + *{ + & > * + * { margin-top: getCssVar(spacing, base); } } @@ -77,8 +75,7 @@ $control-kanban: ( } @include b(control-kanban-group-container) { - width: 100%; - height: 100%; + flex: 1; } @include b(control-kanban-group) { @@ -91,7 +88,7 @@ $control-kanban: ( @include e(header) { position: relative; height: getCssVar(control-kanban, group-header-height); - padding: getCssVar('spacing','none') getCssVar(spacing, base); + padding: getCssVar('spacing', 'none') getCssVar(spacing, base); font-size: getCssVar(control-kanban, font-size); font-weight: getCssVar(control-kanban, font-weight); cursor: pointer; @@ -129,8 +126,15 @@ $control-kanban: ( flex: auto; width: 100%; height: calc(100% - 48px); - padding: getCssVar('spacing','none') getCssVar(spacing, tight); + padding: getCssVar('spacing', 'none') getCssVar(spacing, tight); overflow: auto; + + &:hover { + .#{bem(control-kanban, quicktoolbar)} { + visibility: visible; + } + } + @include e(draggable) { min-height: 100%; padding: getCssVar(spacing, base) 0; @@ -142,12 +146,12 @@ $control-kanban: ( flex-shrink: 0; min-height: 0; } - .#{bem(control-kanban, quicktoolbar)}{ + .#{bem(control-kanban, quicktoolbar)} { flex-grow: 1; width: calc(100% - getCssVar(spacing, base)); } - .#{bem(control-toolbar, item)}{ + .#{bem(control-toolbar, item)} { justify-content: center; } } @@ -158,11 +162,11 @@ $control-kanban: ( width: 32px; height: 32px; padding: getCssVar(spacing, tight); - margin-left: getCssVar('spacing','extra-tight'); + margin-left: getCssVar('spacing', 'extra-tight'); font-size: getCssVar(control-kanban, font-size); color: getCssVar(color, primary); cursor: pointer; - border-radius: getCssVar('border','radius','circle'); + border-radius: getCssVar('border', 'radius', 'circle'); &:hover { background-color: getCssVar(color, fill, 0); @@ -170,10 +174,10 @@ $control-kanban: ( } @include e(actions-dropdown) { &:has(.el-button) { - padding: getCssVar(spacing, extra, tight) getCssVar('spacing','none'); + padding: getCssVar(spacing, extra, tight) getCssVar('spacing', 'none'); } .#{bem(action-toolbar)} { - @include flex(column) + @include flex(column); } .el-button { @@ -182,7 +186,7 @@ $control-kanban: ( justify-content: flex-start; width: 100%; padding: getCssVar(spacing, tight) getCssVar(spacing, base); - margin: getCssVar('spacing','none'); + margin: getCssVar('spacing', 'none'); font-size: getCssVar('font-size', 'regular'); color: getCssVar(color, primary, text); @@ -230,7 +234,7 @@ $control-kanban: ( &.is-has-caption { margin: 0; } - } + } } } } @@ -241,40 +245,30 @@ $control-kanban: ( @include b(control-kanban) { position: relative; - padding-right: calc(getCssVar(control-kanban, group-header-height) + getCssVar(spacing, base)); - @include e(quicktoolbar) { - @include flex(column); + @include e(quicktoolbar) { margin-bottom: getCssVar(spacing, base); + visibility: hidden; + @include flex(column); - & > * + *{ + & > * + * { margin-top: getCssVar(spacing, tight); } } - @include e(full-btn) { - @include flex(row, center, center); - - position: absolute; - top: 0; - right: 0; - width: getCssVar(control-kanban, group-header-height); - height: getCssVar(control-kanban, group-header-height); - font-size: getCssVar(font-size, header, 4); - font-weight: getCssVar('font-weight', 'regular'); - color: getCssVar(color, primary); - background-color: getCssVar(color, bg, 2); - border: 1px solid getCssVar(color, border); - } - @include when(full) { padding: getCssVar(spacing, base); - padding-right: calc(getCssVar(control-kanban, group-header-height) + getCssVar(spacing, extra, loose)); background-color: getCssVar(color, bg, 2); - @include e(full-btn) { - top: getCssVar(spacing, base); - right: getCssVar(spacing, base); - } + } +} + +@include b(control-kanban-toolbar) { + display: flex; + flex-shrink: 0; + gap: getCssVar(spacing, tight); + + .el-button { + border: 1px solid getCssVar(color, border); } } @@ -283,7 +277,7 @@ $control-kanban: ( border-bottom: 1px solid getCssVar(color, border); @include e(toolbar) { - .#{bem(control-toolbar)}{ + .#{bem(control-toolbar)} { flex-wrap: wrap; row-gap: getCssVar(spacing, tight); } @@ -298,7 +292,7 @@ $control-kanban: ( @include e(info) { span { - margin: getCssVar('spacing','none') getCssVar(spacing, extra, tight); + margin: getCssVar('spacing', 'none') getCssVar(spacing, extra, tight); color: getCssVar(color, primary); } } diff --git a/src/control/kanban/kanban.tsx b/src/control/kanban/kanban.tsx index ccf8089a1..8077f6e96 100644 --- a/src/control/kanban/kanban.tsx +++ b/src/control/kanban/kanban.tsx @@ -636,15 +636,29 @@ export const KanbanControl = defineComponent({
{groups.length > 0 && groups.map(group => { - return this.renderGroup(group as IKanbanGroupState); + if (group.hidden) return null; + return this.renderGroup(group); })}
, groups.length > 0 && ( -
- {this.isFull ? ( - - ) : ( - +
+ {this.c.enableGroupHidden && ( + + )} + {this.c.enableFullScreen && ( + + + )}
), diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss index a71681193..a18cb279c 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.scss +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.scss @@ -119,12 +119,12 @@ $swimlane-kanban: ( } .el-button { - color: getCssVar('color', 'text', 3); + color: getCssVar('color', 'text', 2); --el-button-bg-color: #{getCssVar('color', 'white')}; --el-button-hover-bg-color: #{getCssVar('color', 'fill', 0)}; --el-button-active-bg-color: #{getCssVar('color', 'fill', 0)}; - --el-button-text-color: #{getCssVar('color', 'text', 3)}; + --el-button-text-color: #{getCssVar('color', 'text', 2)}; --el-button-hover-text-color: #{getCssVar('color', 'primary')}; --el-button-active-text-color: #{getCssVar('color', 'primary')}; @@ -294,4 +294,11 @@ $swimlane-kanban: ( width: 100%; } } + + @include e('quicktoolbar') { + flex-flow: column nowrap; + gap: getCssVar(spacing, tight); + align-items: center; + justify-content: center; + } } diff --git a/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx b/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx index 473750265..09a2378d7 100644 --- a/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx +++ b/src/control/kanban/swimlane-kanban/swimlane-kanban.tsx @@ -33,7 +33,7 @@ export const SwimlaneKanban = defineComponent({ /** * popper样式 */ - const popperStyle = { zIndex: zIndex.increment(), position: 'unset' }; + const popperStyle = { zIndex: zIndex.increment() }; /** * 展开所有 @@ -239,7 +239,6 @@ export const SwimlaneKanban = defineComponent({ {showActionBar && ( (
- { - c.onGroupToolbarClick(detail, event, group); - }} - > + {c.model.groupUIActionGroup && ( + { + c.onGroupToolbarClick(detail, event, group); + }} + > + )} {batchToolbarModel && (
-
- -
+ {c.enableGroupHidden && ( +
+ +
+ )}
{c.state.groups.map(group => { @@ -443,6 +449,10 @@ export const SwimlaneKanban = defineComponent({ lane: IKanbanSwimlane, group: IKanbanGroupState, ) => { + const { swimlaneAppDEFieldId } = c.model; + const items = group.children.filter( + item => item[swimlaneAppDEFieldId!] === lane.key, + ); return (
{c.enableNew && !c.state.readonly && ( @@ -457,7 +467,7 @@ export const SwimlaneKanban = defineComponent({ {ibiz.i18n.t('app.newlyBuild')} )} - {quickToolbarModel && ( + {quickToolbarModel && items.length === 0 && ( Date: Tue, 29 Jul 2025 19:20:13 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E6=96=B0=E5=BB=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/control/data-view/data-view.scss | 11 +++++++ src/control/data-view/data-view.tsx | 43 ++++++++++++++++++++++++++-- src/control/kanban/kanban.tsx | 4 +-- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6437625e..0d5d4caf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - 泳道看板新增分组隐藏功能 - 看板识别enableFullScreen(启用全屏)和 enableGroupHidden(启用分组隐藏)参数 +- 新增卡片新建功能 ### Fixed diff --git a/src/control/data-view/data-view.scss b/src/control/data-view/data-view.scss index 32dfcd760..409d19a32 100644 --- a/src/control/data-view/data-view.scss +++ b/src/control/data-view/data-view.scss @@ -124,6 +124,17 @@ $control-dataview-group-item-content: ( background-color: getCssVar(control-dataview, hover-bg-color); } + @include e(new) { + color: getCssVar(color, text, 3); + border: 2px dashed getCssVar(color, border); + + .el-card__body { + display: flex; + align-items: center; + justify-content: center; + } + } + @include e(content) { display: flex; align-items: center; diff --git a/src/control/data-view/data-view.tsx b/src/control/data-view/data-view.tsx index 866fb6a51..00eb9bb55 100644 --- a/src/control/data-view/data-view.tsx +++ b/src/control/data-view/data-view.tsx @@ -220,6 +220,30 @@ export const DataViewControl = defineComponent({ return c.onDbRowClick(item); }; + /** + * @description 绘制新建卡片项 + * @param {IMDControlGroupState} [group] + * @returns {*} + */ + const renderNewCard = (group?: IMDControlGroupState) => { + return ( + { + c.onClickNew(event, group?.key); + }} + > + + + ); + }; + // 绘制项布局面板 const renderPanelItem = (item: IData, modelData: ILayoutPanel): VNode => { const { context, params } = c; @@ -238,6 +262,7 @@ export const DataViewControl = defineComponent({ > ); }; + // 绘制项行为 const renderItemAction = (item: IData): VNode => { return ( @@ -323,7 +348,7 @@ export const DataViewControl = defineComponent({ * @param {IData[]} items * @return {*} */ - const renderCardLayout = (items: IData[]) => { + const renderCardLayout = (items: IData[], group?: IMDControlGroupState) => { const { cardColXS, cardColSM, cardColMD, cardColLG } = c.model; if (cardColXS || cardColSM || cardColMD || cardColLG) return ( @@ -341,6 +366,17 @@ export const DataViewControl = defineComponent({ ); })} + {c.enableNew && !c.state.readonly && ( + +
{renderNewCard(group)}
+
+ )} ); return ( @@ -348,6 +384,9 @@ export const DataViewControl = defineComponent({ {items.map(item => { return
{renderCard(item)}
; })} + {c.enableNew && !c.state.readonly && ( +
{renderNewCard(group)}
+ )}
); }; @@ -389,7 +428,7 @@ export const DataViewControl = defineComponent({ {group.children.length > 0 ? ( - renderCardLayout(group.children) + renderCardLayout(group.children, group) ) : (
{ibiz.i18n.t('app.noData')} diff --git a/src/control/kanban/kanban.tsx b/src/control/kanban/kanban.tsx index 8077f6e96..39947e8cb 100644 --- a/src/control/kanban/kanban.tsx +++ b/src/control/kanban/kanban.tsx @@ -30,7 +30,7 @@ import { KanbanController, IKanbanGroupState, } from '@ibiz-template/runtime'; -import { NOOP, listenJSEvent, showTitle } from '@ibiz-template/core'; +import { NOOP, listenJSEvent } from '@ibiz-template/core'; import { SwimlaneKanban } from './swimlane-kanban/swimlane-kanban'; import './kanban.scss'; @@ -462,7 +462,7 @@ export const KanbanControl = defineComponent({ > )} -- Gitee