From 12217e2d97c0fa300782e6caa6203d6594c3ed0c Mon Sep 17 00:00:00 2001 From: "jlj05024111@163.com" Date: Fri, 24 Oct 2025 21:47:18 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E6=95=B0=E6=8D=AE=E9=83=A8=E4=BB=B6=E5=92=8C?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E6=96=B0=E5=BB=BA=E6=95=B0=E6=8D=AE=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/common/add-btn/add-btn-event.ts | 8 +++++++ src/common/add-btn/add-btn.scss | 12 ++++++++++ src/common/add-btn/add-btn.tsx | 34 +++++++++++++++++++++++++++ src/common/index.ts | 3 +++ src/control/data-view/data-view.scss | 7 ------ src/control/data-view/data-view.tsx | 10 +++----- src/control/list/list-render-util.tsx | 22 +++++++++++++---- src/control/list/md-ctrl/md-ctrl.scss | 4 ++-- src/control/list/md-ctrl/md-ctrl.tsx | 21 ++++++++++------- src/locale/en/index.ts | 1 + src/locale/zh-CN/index.ts | 1 + 12 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 src/common/add-btn/add-btn-event.ts create mode 100644 src/common/add-btn/add-btn.scss create mode 100644 src/common/add-btn/add-btn.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 19707d1896a..fb3ed3957dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added +- 新增支持多数据部件和卡片新建数据功能 - 新增移动端分割容器组件 - 新增数组编辑器 - 多数据、卡片支持simple模式 diff --git a/src/common/add-btn/add-btn-event.ts b/src/common/add-btn/add-btn-event.ts new file mode 100644 index 00000000000..6429006bbb0 --- /dev/null +++ b/src/common/add-btn/add-btn-event.ts @@ -0,0 +1,8 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +export const AddBtnEvent = { + /* + * 点击添加按钮 + * @param event + */ + addClick: (_event: PointerEvent) => true, +}; diff --git a/src/common/add-btn/add-btn.scss b/src/common/add-btn/add-btn.scss new file mode 100644 index 00000000000..e8f3accb741 --- /dev/null +++ b/src/common/add-btn/add-btn.scss @@ -0,0 +1,12 @@ +$att-btn: ( + button-padding: getCssVar(spacing, tight) 0, + button-color: getCssVar(color, primary), + add-border: 2px dashed getCssVar(color, border), +); +@include b('add-btn') { + @include set-component-css-var('add-btn', $att-btn); + width: 100%; + border: getCssVar(add-btn, add-border); + margin: getCssVar(add-btn, button-padding); + color: getCssVar(add-btn, button-color); +} diff --git a/src/common/add-btn/add-btn.tsx b/src/common/add-btn/add-btn.tsx new file mode 100644 index 00000000000..4463c05293d --- /dev/null +++ b/src/common/add-btn/add-btn.tsx @@ -0,0 +1,34 @@ +import { defineComponent } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import { AddBtnEvent } from './add-btn-event'; +import './add-btn.scss'; + +export const IBizAddBtn = defineComponent({ + name: 'IBizAddBtn', + props: { + addCaption: { + type: String, + default: () => ibiz.i18n.t('control.common.addbtn'), + }, + }, + emits: AddBtnEvent, + setup(props, { emit }) { + const ns = useNamespace('add-btn'); + // 点击添加按钮 + const onAddClick = (event: PointerEvent) => { + emit('addClick', event); + }; + return { ns, onAddClick }; + }, + render() { + return ( + this.onAddClick(event)} + > + {this.addCaption} + + ); + }, +}); diff --git a/src/common/index.ts b/src/common/index.ts index 1b77d9b027e..a6fcb15216b 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -29,14 +29,17 @@ import { ViewMessage } from './view-message/view-message'; import { IBizMdSortSetting } from './md-sort-setting/md-sort-setting'; import { IBizSplit } from './split/split'; import { IBizSplitTrigger } from './split-trigger/split-trigger'; +import { IBizAddBtn } from './add-btn/add-btn'; export * from './col/col'; export * from './row/row'; export * from './keep-alive/keep-alive'; export * from './md-sort-setting/md-sort-setting'; +export * from './add-btn/add-btn'; export const IBizCommonComponents = { install: (v: App): void => { + v.component(IBizAddBtn.name!, IBizAddBtn); v.component(IBizSplit.name!, IBizSplit); v.component(IBizSplitTrigger.name!, IBizSplitTrigger); v.component(IBizActionGroup.name!, IBizActionGroup); diff --git a/src/control/data-view/data-view.scss b/src/control/data-view/data-view.scss index edbe243bf49..2faf3ee74be 100644 --- a/src/control/data-view/data-view.scss +++ b/src/control/data-view/data-view.scss @@ -189,11 +189,4 @@ $control-dataview: ( display: flex; align-items: center; justify-content: center; -} - -@include b('control-dataview-add-btn'){ - width: 100%; - margin: getCssVar(control-dataview, button-padding); - border: getCssVar(control-dataview, add-border); - color: getCssVar(control-dataview, button-color); } \ No newline at end of file diff --git a/src/control/data-view/data-view.tsx b/src/control/data-view/data-view.tsx index 98e0ff08f37..54c8af34f49 100644 --- a/src/control/data-view/data-view.tsx +++ b/src/control/data-view/data-view.tsx @@ -152,13 +152,9 @@ export const DataViewControl = defineComponent({ return; } return ( - c.onClickNew(event, group?.key)} - > - 新增 - + c.onClickNew(event, group?.key)} + > ); }; diff --git a/src/control/list/list-render-util.tsx b/src/control/list/list-render-util.tsx index 684e7c122d4..37e584e55e9 100644 --- a/src/control/list/list-render-util.tsx +++ b/src/control/list/list-render-util.tsx @@ -27,6 +27,7 @@ export function useListRender( renderItem: (row: IData) => VNode | undefined; renderNoData: () => VNode | undefined; renderLoadMore: () => JSX.Element | null; + renderAddItem: (group?: IData) => JSX.Element | null; } { const isSelect = (row: IData) => { const findIndex = c.state.selectedData.findIndex(data => { @@ -73,7 +74,7 @@ export function useListRender( Object.assign(slotOption, { icon: renderIcon(row) }); } if (props.mode === 'SELECT') { - Object.assign(slotOption, { 'right-icon': renderRightSlot(row) }); + Object.assign(slotOption, { icon: renderRightSlot(row) }); } return ( - {content} c.onRowClick(item, event)} > + {content} ); } @@ -181,5 +182,18 @@ export function useListRender( return icon; }; - return { renderNoData, renderItem, renderLoadMore }; + // 添加项 + const renderAddItem = (group?: IData) => { + return ( +
+ { + c.onClickNew(event, group?.key); + }} + > +
+ ); + }; + + return { renderNoData, renderItem, renderLoadMore, renderAddItem }; } diff --git a/src/control/list/md-ctrl/md-ctrl.scss b/src/control/list/md-ctrl/md-ctrl.scss index 6f335ce0ac5..8e21dfb3caa 100644 --- a/src/control/list/md-ctrl/md-ctrl.scss +++ b/src/control/list/md-ctrl/md-ctrl.scss @@ -16,7 +16,7 @@ $control-mobmdctrl: ( item-bg-color: getCssVar(color, bg, 2), item-under-line-right: getCssVar(spacing, base), item-under-line-left: getCssVar(spacing, base), - item-right-padding: 0 0 0 getCssVar('spacing', 'tight'), + item-right-padding: 0 getCssVar('spacing', 'tight') 0 0 , group-font-size: getCssVar(font-size, header-6), group-bg-color: getCssVar(color, bg, 0), group-text-color: getCssVar(color, text, 1), @@ -191,7 +191,7 @@ $control-mobmdctrl: ( background-color: getCssVar(control-mobmdctrl, item-bg-color); padding: getCssVar(control-mobmdctrl, padding); - @include e(right) { + @include e(left) { padding: getCssVar(control-mobmdctrl, item-right-padding); } diff --git a/src/control/list/md-ctrl/md-ctrl.tsx b/src/control/list/md-ctrl/md-ctrl.tsx index bc71d72fa78..cf1b9ec99fc 100644 --- a/src/control/list/md-ctrl/md-ctrl.tsx +++ b/src/control/list/md-ctrl/md-ctrl.tsx @@ -74,11 +74,8 @@ export const MDCtrlControl = defineComponent({ setup(props) { const c = useControlController((...args) => new MDCtrlController(...args)); const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); - const { renderItem, renderNoData, renderLoadMore } = useListRender( - props, - c, - ns, - ); + const { renderItem, renderNoData, renderLoadMore, renderAddItem } = + useListRender(props, c, ns); const listRef = ref(); @@ -255,9 +252,16 @@ export const MDCtrlControl = defineComponent({ }; const renderDefault = () => { - return c.state.items.map((item: IData) => { - return renderDefaultItem(item); - }); + const result = []; + result.push( + c.state.items.map((item: IData) => { + return renderDefaultItem(item); + }), + ); + if (c.enableNew) { + result.push(renderAddItem()); + } + return result; }; const renderGroup = () => { @@ -273,6 +277,7 @@ export const MDCtrlControl = defineComponent({ {group.children.map(item => { return renderDefaultItem(item.data); })} + {c.enableNew ? renderAddItem(group) : null} ); })} diff --git a/src/locale/en/index.ts b/src/locale/en/index.ts index 62d249bd2c9..e2d9b6f09f2 100644 --- a/src/locale/en/index.ts +++ b/src/locale/en/index.ts @@ -80,6 +80,7 @@ export default { control: { common: { loadMore: 'Load more', + addbtn: 'Add', }, appmenu: { more: 'More', diff --git a/src/locale/zh-CN/index.ts b/src/locale/zh-CN/index.ts index ab277cd0df9..5fd7f223414 100644 --- a/src/locale/zh-CN/index.ts +++ b/src/locale/zh-CN/index.ts @@ -64,6 +64,7 @@ export default { control: { common: { loadMore: '加载更多', + addbtn: '新增', }, dataView: { end: '我已经到底啦~' }, appmenu: { -- Gitee From b9cdc0ed70660a6cff0da87273735af8d4546278 Mon Sep 17 00:00:00 2001 From: "jlj05024111@163.com" Date: Fri, 24 Oct 2025 21:48:35 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=A4=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=83=A8=E4=BB=B6=E5=92=8C=E5=8D=A1=E7=89=87?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=A1=A8=E5=8D=95=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/common/index.ts | 3 + .../md-advaned-searchform.scss | 68 ++++++++++++++ .../md-advaned-searchform.tsx | 92 +++++++++++++++++++ .../setting-container.controller.ts | 24 ++++- .../setting-container/setting-container.scss | 11 +++ .../setting-container/setting-container.tsx | 36 +++++++- 7 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 src/common/md-advaned-searchform/md-advaned-searchform.scss create mode 100644 src/common/md-advaned-searchform/md-advaned-searchform.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3ed3957dd..b037587e57e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added +- 新增多数据部件和卡片支持表单搜索 - 新增支持多数据部件和卡片新建数据功能 - 新增移动端分割容器组件 - 新增数组编辑器 diff --git a/src/common/index.ts b/src/common/index.ts index a6fcb15216b..6a116581efc 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -29,17 +29,20 @@ import { ViewMessage } from './view-message/view-message'; import { IBizMdSortSetting } from './md-sort-setting/md-sort-setting'; import { IBizSplit } from './split/split'; import { IBizSplitTrigger } from './split-trigger/split-trigger'; +import { IBizMdAdvanedSearchfrom } from './md-advaned-searchform/md-advaned-searchform'; import { IBizAddBtn } from './add-btn/add-btn'; export * from './col/col'; export * from './row/row'; export * from './keep-alive/keep-alive'; export * from './md-sort-setting/md-sort-setting'; +export * from './md-advaned-searchform/md-advaned-searchform'; export * from './add-btn/add-btn'; export const IBizCommonComponents = { install: (v: App): void => { v.component(IBizAddBtn.name!, IBizAddBtn); + v.component(IBizMdAdvanedSearchfrom.name!, IBizMdAdvanedSearchfrom); v.component(IBizSplit.name!, IBizSplit); v.component(IBizSplitTrigger.name!, IBizSplitTrigger); v.component(IBizActionGroup.name!, IBizActionGroup); diff --git a/src/common/md-advaned-searchform/md-advaned-searchform.scss b/src/common/md-advaned-searchform/md-advaned-searchform.scss new file mode 100644 index 00000000000..7c952eaa951 --- /dev/null +++ b/src/common/md-advaned-searchform/md-advaned-searchform.scss @@ -0,0 +1,68 @@ +$md-advaned-searchform: ( + content-padding: getCssVar(spacing, base), + footer-padding: getCssVar(spacing, base), + footer-item-padding: getCssVar(spacing, base), + footer-item-gap: getCssVar(spacing, base, tight), + footer-group-padding: 0 getCssVar(spacing, base), + footer-more-color: getCssVar(color, link), + footer-item-shadow: getCssVar(shadow, elevated), + footer-item-border-radius: getCssVar(border, radius, small), + footer-reset-color: getCssVar(color, text), + footer-reset-bg-color: transparent, + footer-confirm-color: getCssVar(color, default), + footer-confirm-bg-color: getCssVar(color, primary) +); +@include b('md-advaned-searchform') { + @include set-component-css-var( + 'md-advaned-searchform', + $md-advaned-searchform + ); + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + @include e('searchform') { + flex: 1; + overflow: auto; + padding: getCssVar(md-advaned-searchform, content-padding); + } + @include e('footer') { + flex-shrink: 0; + display: flex; + gap: getCssVar(md-advaned-searchform, footer-item-gap); + padding: getCssVar(md-advaned-searchform, footer-padding); + @include m('reset') { + flex: 1; + padding: getCssVar(md-advaned-searchform, footer-item-padding); + box-shadow: getCssVar(md-advaned-searchform, footer-item-shadow); + background-color: getCssVar( + md-advaned-searchform, + footer-reset-bg-color + ); + color: getCssVar(md-advaned-searchform, text-color); + width: 100%; + text-align: center; + border-radius: getCssVar( + md-advaned-searchform, + footer-item-border-radius + ); + } + @include m('confirm') { + flex: 1; + padding: getCssVar(md-advaned-searchform, footer-item-padding); + box-shadow: getCssVar(md-advaned-searchform, footer-item-shadow); + background-color: getCssVar( + md-advaned-searchform, + footer-confirm-bg-color + ); + color: getCssVar(md-advaned-searchform, footer-confirm-color); + width: 100%; + text-align: center; + opacity: 0.9; + border-radius: getCssVar( + md-advaned-searchform, + footer-item-border-radius + ); + } + } +} diff --git a/src/common/md-advaned-searchform/md-advaned-searchform.tsx b/src/common/md-advaned-searchform/md-advaned-searchform.tsx new file mode 100644 index 00000000000..698f38d323f --- /dev/null +++ b/src/common/md-advaned-searchform/md-advaned-searchform.tsx @@ -0,0 +1,92 @@ +import { + IControlProvider, + IModal, + ISearchFormController, +} from '@ibiz-template/runtime'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import { IDESearchForm } from '@ibiz/model-core'; +import { defineComponent, PropType, reactive } from 'vue'; +import './md-advaned-searchform.scss'; + +export const IBizMdAdvanedSearchfrom = defineComponent({ + name: 'IBizMdAdvanedSearchfrom', + props: { + modal: { + type: Object as PropType, + }, + /** + * @description 搜索表单模型数据 + */ + modelData: { + type: Object as PropType, + required: true, + }, + /** + * @description 部件适配器 + */ + provider: { type: Object as PropType }, + /** + * @description 应用上下文对象 + */ + context: { type: Object as PropType, required: true }, + /** + * @description 视图参数对象 + * @default {} + */ + params: { type: Object as PropType, default: () => ({}) }, + /** + * @description 搜索表单控制器 + */ + controller: { type: Object as PropType }, + }, + setup(props) { + const ns = useNamespace('md-advaned-searchform'); + const c = props.controller; + + c!.evt.on('onCreated', () => { + const keys = Object.keys(c!.details); + keys.forEach(key => { + const detail = c!.details[key]; + detail.state = reactive(detail.state); + }); + }); + + // 重置按钮 + const onCancel = () => { + c!.reset(); + props.modal!.dismiss(); + }; + + // 确认搜索按钮 + const onConfirm = () => { + c!.onSearchButtonClick(); + props.modal!.dismiss(); + }; + + return { c, ns, onCancel, onConfirm }; + }, + render() { + return ( +
+ +
+
this.onCancel()} + > + {ibiz.i18n.t('control.form.searchForm.reset')} +
+
this.onConfirm()} + > + {ibiz.i18n.t('control.form.searchForm.search')} +
+
+
+ ); + }, +}); diff --git a/src/panel-component/setting-container/setting-container.controller.ts b/src/panel-component/setting-container/setting-container.controller.ts index bbac9054faf..d6e5f2ce923 100644 --- a/src/panel-component/setting-container/setting-container.controller.ts +++ b/src/panel-component/setting-container/setting-container.controller.ts @@ -1,5 +1,6 @@ import { IMobMDCtrlController, + ISearchFormController, PanelContainerController, } from '@ibiz-template/runtime'; import { IPanelContainer } from '@ibiz/model-core'; @@ -41,6 +42,27 @@ export class SettingContainerController extends PanelContainerController { + const searchform = c.panel.view.providers.searchform; + await ibiz.overlay.drawer( + (modal: IModal) => { + return h(IBizMdAdvanedSearchfrom, { + modal, + modelData: c.searchform.model, + context: c.searchform.context, + params: c.searchform.params, + provider: searchform, + controller: c.searchform, + }); + }, + {}, + { + attrs: { + position: 'bottom', + closeable: false, + }, + }, + ); + }; + + return { c, ns, handleClick, handleAdvanedClick }; }, render() { if (!this.c.visible) return; @@ -90,6 +114,14 @@ export const SettingContainer = defineComponent({ )} + {this.c.isMDSearchformBtn && ( + + + + )} ); -- Gitee