diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d18ca11acacffa6e75019e76cc28591163bc0e7..e05699d59d4fea5f329514581ccab7bc75730441 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,17 +10,23 @@ ### Fixed - 多数据排序通用组件调整配置图标及图标样式 +- 多数据部件添加动画帧与防抖,防止多次加载 +- 修复视图内容溢出异常 ### Change - 修复树导航引擎未往下传递srfnav - 添加部件滚动默认变量 +- 门户视图样式调整 +- 表单分组支持样式表、分组样式 +- 编辑器placeholder颜色、行高统一,富文本多语言修复 ### Added - 表单项支持显示边框配置 - 新增图片预览组件 - 树部件适配树节点图标展示及快捷搜索 +- 新增分页搜索视图 ## [0.0.29] - 2024-10-22 diff --git a/src/control/dashboard/portlet/portlet-layout/portlet-layout.scss b/src/control/dashboard/portlet/portlet-layout/portlet-layout.scss index 6af6419c5e40198be76410b007ddf78f626c6a83..9e39a047bf9150d239eaf08d161352c5dc227b92 100644 --- a/src/control/dashboard/portlet/portlet-layout/portlet-layout.scss +++ b/src/control/dashboard/portlet/portlet-layout/portlet-layout.scss @@ -1,17 +1,18 @@ -$portlet-layout: (bg-color: transparent, +$portlet-layout: ( header-height: rem(40px), - header-padding: rem(16px), + header-padding: 0 getCssVar(spacing, base), header-margin: 0, - header-bg-color: getCssVar(color, bg, 0), + bg-color: getCssVar(color, bg, 1), + header-bg-color: transparent, header-border-bottom: rem(1px) solid getCssVar(color, border), caption-max-width: rem(300px), caption-font-weight: 600, caption-font-size: getCssVar(font-size, header, 5), caption-color: getCssVar(color, text, 1), content-bg-color: transparent, - content-padding: 0, + content-padding: 0 0 getCssVar(border-radius, medium), content-margin: 0, - border-radius:getCssVar(border-radius, medium), + border-radius: getCssVar(border-radius, medium), ); @include b(portlet-layout) { @@ -52,7 +53,7 @@ $portlet-layout: (bg-color: transparent, @include flex(row, space-between); height: getCssVar(portlet-layout, header-height); - padding-left: getCssVar(portlet-layout, header-padding); + padding: getCssVar(portlet-layout, header-padding); margin: getCssVar(portlet-layout, header-margin); line-height: getCssVar(portlet-layout, header-height); background-color: getCssVar(portlet-layout, header-bg-color); diff --git a/src/control/form/form-detail/form-group-panel/form-group-panel.scss b/src/control/form/form-detail/form-group-panel/form-group-panel.scss index a9ac7967cd6e08668d0d5b05e0e3c31db25e2d57..658d00d60ffab481600c8853761417dc0ae2feef 100644 --- a/src/control/form/form-detail/form-group-panel/form-group-panel.scss +++ b/src/control/form/form-detail/form-group-panel/form-group-panel.scss @@ -1,15 +1,14 @@ $form-group: ( - bg-color: getCssVar(color, bg, 0), - // bg-color: red, + bg-color: getCssVar(color, bg, 1), footer-padding: getCssVar(spacing, tight) getCssVar(spacing, base), show-more-color: getCssVar(color-primary), - margin: getCssVar(spacing-extra-tight), + padding: getCssVar(spacing-extra-tight), border-radius: getCssVar('border-radius', 'large'), ); $form-group-header: ( bg-color: getCssVar(color, bg, 1), - padding: getCssVar(spacing, tight) getCssVar(spacing, base), + padding: getCssVar(spacing, base) getCssVar(spacing, base) getCssVar(spacing, tight), border-color: getCssVar(color, border), ); @@ -34,12 +33,9 @@ $form-group-content: ( // 分组基础样式 @include b(form-group) { - width: calc(100% - 2 * getCssVar('form-group', 'margin')); - height: calc(100% - 2 * getCssVar('form-group', 'margin')); overflow: hidden; background-color: getCssVar('form-group', 'bg-color'); - border-radius: getCssVar('form-group', 'border-radius'); - margin: getCssVar('form-group', 'margin'); + padding: getCssVar('form-group', 'padding'); // 分组标题 @include e(caption) { @@ -55,6 +51,10 @@ $form-group-content: ( text-align: right; } + @include m(style2) { + background-color: getCssVar(color, bg, 0); + border-radius: getCssVar('form-group', 'border-radius'); + } } // 清除分组下form-item的弧度 diff --git a/src/control/form/form-detail/form-group-panel/form-group-panel.tsx b/src/control/form/form-detail/form-group-panel/form-group-panel.tsx index 4c141695c28e2e4e42e2c3f2ddffdb266f7c29fe..c876fb0ae00d2c98494c7dbb60ea69977e4cdeed 100644 --- a/src/control/form/form-detail/form-group-panel/form-group-panel.tsx +++ b/src/control/form/form-detail/form-group-panel/form-group-panel.tsx @@ -66,9 +66,12 @@ export const FormGroupPanel = defineComponent({ })} ); + const { detailStyle = 'DEFAULT' } = this.modelData; const classArr: string[] = [ this.ns.b(), this.ns.m(this.modelData.codeName), + this.ns.m(detailStyle.toLowerCase()), + ...this.controller.containerClass, ]; if (this.modelData.showCaption === true) { classArr.push(this.ns.m('show-header')); @@ -88,7 +91,9 @@ export const FormGroupPanel = defineComponent({ header = (
-
{this.captionText}
+
+ {this.captionText} +
{this.modelData.uiactionGroup && (
diff --git a/src/control/form/form-detail/form-item/form-item-container/form-item-container.tsx b/src/control/form/form-detail/form-item/form-item-container/form-item-container.tsx index 8c9d97d5e794cbd8375c1b0a32cc30e83cde4cc8..2b74c9f18ce8d11689193274e3aacf18dba050af 100644 --- a/src/control/form/form-detail/form-item/form-item-container/form-item-container.tsx +++ b/src/control/form/form-detail/form-item/form-item-container/form-item-container.tsx @@ -20,6 +20,9 @@ export const IBizFormItemContainer = defineComponent({ label: { type: String, }, + labelClass: { + type: Array, + }, labelPos: { type: String, required: true, @@ -91,6 +94,7 @@ export const IBizFormItemContainer = defineComponent({ return { ns, cssVars, showUnderLine, showEditorBorder }; }, render() { + const labelClassList = [this.ns.e('label'), ...(this.labelClass || [])]; return (
{this.labelPos === 'LEFT' || this.labelPos === 'TOP' ? ( -
+
{this.label}
) : null}
{this.$slots.default?.()}
{this.labelPos === 'RIGHT' || this.labelPos === 'BOTTOM' ? ( -
+
{this.label}
) : null} diff --git a/src/control/form/form-detail/form-item/form-item.tsx b/src/control/form/form-detail/form-item/form-item.tsx index 87b80bf63c673b04d1142204067214720094139d..ddfb54e2c3d7d0bcabc712f49f26607ffabf0405 100644 --- a/src/control/form/form-detail/form-item/form-item.tsx +++ b/src/control/form/form-detail/form-item/form-item.tsx @@ -82,10 +82,12 @@ export const FormItem = defineComponent({ this.ns.m(this.modelData.id), { [this.ns.m('disabled')]: this.c.state.disabled }, { [this.ns.m('readonly')]: this.controller.model.editor!.readOnly }, + ...this.controller.containerClass, ]} required={this.c.state.required} error={this.c.state.error} label={this.captionText} + labelClass={this.controller.labelClass} label-pos={this.c.model.labelPos} controller={this.c} label-width={this.c.model.labelWidth} diff --git a/src/control/form/form-detail/form-tab-panel/form-tab-panel.scss b/src/control/form/form-detail/form-tab-panel/form-tab-panel.scss index 72c252b03a6a1ba3b0e2919354931d5dc6b3b3e1..a848896d845447e89371e2920ae326497cf7bd7b 100644 --- a/src/control/form/form-detail/form-tab-panel/form-tab-panel.scss +++ b/src/control/form/form-detail/form-tab-panel/form-tab-panel.scss @@ -1,7 +1,13 @@ +$form-tab-panel: ( + 'bg-color': getCssVar(color, bg, 0), +); + @include b(form-tab-panel) { + @include set-component-css-var('form-tab-panel', $form-tab-panel); width: 100%; height: 100%; overflow: auto; + background-color: getCssVar('form-tab-panel', 'bg-color');; @include e(caption) { @include flex(row, center, center) @@ -9,4 +15,7 @@ >.van-tabs__wrap { margin-bottom: getCssVar(spacing, tight); } + >.van-tabs__content { + padding: 0 getCssVar(spacing-extra-tight); + } } \ No newline at end of file diff --git a/src/control/form/form/form.scss b/src/control/form/form/form.scss index aeba2bb71450e49311ca085b714fb0486ecb87af..638aff5ab5bddf24e595fa92992fc57832976afe 100644 --- a/src/control/form/form/form.scss +++ b/src/control/form/form/form.scss @@ -1,5 +1,5 @@ $control-form: ( - 'bg-color': getCssVar(color, bg, 0) + 'bg-color': getCssVar(color, bg, 1) ); @include b(control-form) { diff --git a/src/control/list/md-ctrl/md-ctrl.tsx b/src/control/list/md-ctrl/md-ctrl.tsx index 8ef451bb0019a59429ab4db08326bc94c29d526f..24038e103293ef4a925a5c45e6e6904766a702ac 100644 --- a/src/control/list/md-ctrl/md-ctrl.tsx +++ b/src/control/list/md-ctrl/md-ctrl.tsx @@ -1,5 +1,6 @@ import { useControlController, useNamespace } from '@ibiz-template/vue3-util'; -import { computed, defineComponent, PropType } from 'vue'; +import { computed, defineComponent, PropType, ref } from 'vue'; +import { debounce } from 'lodash-es'; import { IDEMobMDCtrl, IUIActionGroup } from '@ibiz/model-core'; import { IControlProvider, @@ -32,6 +33,8 @@ export const MDCtrlControl = defineComponent({ ns, ); + const isUpdating = ref(false); + // 不分页 0 分页栏 1 滚动加载 2 加载更多 3 // 是否可以加载更多 const isLodeMoreDisabled = computed(() => { @@ -79,9 +82,25 @@ export const MDCtrlControl = defineComponent({ // 处理排序配置回调 const onSortChange = (sort: { key: string; order: 'asc' | 'desc' }) => { c.setSort(sort.key, sort.order); - c.load(); + c.load({ isInitialLoad: true }); + }; + + // 加载更多 + const debounceLoadMore = debounce(async () => { + c.loadMore(); + }, 500); + const onLoadMore = () => { + debounceLoadMore(); }; + // 添加动画帧,反正加载多次 + c.evt.on('onLoadSuccess', () => { + isUpdating.value = true; + window.requestAnimationFrame(() => { + isUpdating.value = false; + }); + }); + // 是否显示数据伸缩图标 // 如果未开启分组,并且加载模式为【加载更多】,并且已经加载过一次更多,则为 true const showCollapseOrExpandIcon = computed(() => { @@ -172,9 +191,12 @@ export const MDCtrlControl = defineComponent({ ns.e('content'), ns.is('show-underLine', c.model.controlStyle !== 'EXTVIEW1'), ]} - finished={isLodeMoreDisabled.value} + loading={c.state.isLoading} + finished={ + isLodeMoreDisabled.value || c.state.isLoading || isUpdating.value + } immediate-check={false} - onLoad={() => c.loadMore()} + onLoad={() => onLoadMore()} > {c.model.groupMode !== 'NONE' ? renderGroup() : renderDefault()} diff --git a/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.scss b/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.scss index d229134b4379452d9515bd38748df853ca3992d6..05fc2aabd42e08985e1c8e670b743cee29f13f5d 100644 --- a/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.scss +++ b/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.scss @@ -12,6 +12,7 @@ input::placeholder { color: getCssVar('form-item', 'placeholder-color'); + -webkit-text-fill-color: getCssVar('form-item', 'placeholder-color'); } input[disabled] { diff --git a/src/editor/dropdown-list/ibiz-dropdown/ibiz-dropdown.scss b/src/editor/dropdown-list/ibiz-dropdown/ibiz-dropdown.scss index 210e885f3626f2670ae33a58492d7bf8a3285bb2..a3fdfe755c6c678ec5434fa5fbacb2659d839062 100644 --- a/src/editor/dropdown-list/ibiz-dropdown/ibiz-dropdown.scss +++ b/src/editor/dropdown-list/ibiz-dropdown/ibiz-dropdown.scss @@ -34,6 +34,13 @@ border-radius: getCssVar(spacing, base); } + .van-cell { + line-height: getCssVar(form-item, line-height); + .van-field__control--custom { + min-height: getCssVar(form-item, line-height); + } + } + .van-picker { .van-picker__mask { background-image: getCssVar(color, overlay, bg); diff --git a/src/editor/html/quill-editor/quill-editor.scss b/src/editor/html/quill-editor/quill-editor.scss index 49a859e3f6e9d74b3d3209a0151b6abd3df1a9c6..c4b71840bda8f7dd3e7083a5270964f5a277b86e 100644 --- a/src/editor/html/quill-editor/quill-editor.scss +++ b/src/editor/html/quill-editor/quill-editor.scss @@ -39,54 +39,56 @@ } // quill多语言特殊处理,后续补充多语言 @include m(zh-cn) { - .ql-snow .ql-picker.ql-size { - .ql-picker-label::before, - .ql-picker-item::before { - content: '默认' + .ql-snow { + .ql-picker.ql-size { + .ql-picker-label::before, + .ql-picker-item::before { + content: '默认' + } + .ql-picker-label[data-value=small]::before, + .ql-picker-item[data-value=small]::before { + content: '小' + } + .ql-picker-label[data-value=large]::before, + .ql-picker-item[data-value=large]::before { + content: '大' + } + .ql-picker-label[data-value=huge]::before, + .ql-picker-item[data-value=huge]::before { + content: '超大' + } } - .ql-picker-label[data-value=small]::before, - .ql-picker-item[data-value=small]::before { - content: '小' - } - .ql-picker-label[data-value=large]::before, - .ql-picker-item[data-value=large]::before { - content: '大' - } - .ql-picker-label[data-value=huge]::before, - .ql-picker-item[data-value=huge]::before { - content: '超大' + .ql-picker.ql-header { + .ql-picker-label::before, + .ql-picker-item::before { + content: '正文' + } + .ql-picker-label[data-value="1"]::before, + .ql-picker-item[data-value="1"]::before { + content: 'H 1'; + } + .ql-picker-label[data-value="2"]::before, + .ql-picker-item[data-value="2"]::before { + content: 'H 2'; + } + .ql-picker-label[data-value="3"]::before, + .ql-picker-item[data-value="3"]::before { + content: 'H 3'; + } + .ql-picker-label[data-value="4"]::before, + .ql-picker-item[data-value="4"]::before { + content: 'H 4'; + } + .ql-picker-label[data-value="5"]::before, + .ql-picker-item[data-value="5"]::before { + content: 'H 5'; + } + .ql-picker-label[data-value="6"]::before, + .ql-picker-item[data-value="6"]::before { + content: 'H 6'; + } } } - .ql-picker.ql-header { - .ql-picker-label::before, - .ql-picker-item::before { - content: '正文' - } - .ql-picker-label[data-value="1"]::before, - .ql-picker-item[data-value="1"]::before { - content: 'H 1'; - } - .ql-picker-label[data-value="2"]::before, - .ql-picker-item[data-value="2"]::before { - content: 'H 2'; - } - .ql-picker-label[data-value="3"]::before, - .ql-picker-item[data-value="3"]::before { - content: 'H 3'; - } - .ql-picker-label[data-value="4"]::before, - .ql-picker-item[data-value="4"]::before { - content: 'H 4'; - } - .ql-picker-label[data-value="5"]::before, - .ql-picker-item[data-value="5"]::before { - content: 'H 5'; - } - .ql-picker-label[data-value="6"]::before, - .ql-picker-item[data-value="6"]::before { - content: 'H 6'; - } - } } } \ No newline at end of file diff --git a/src/editor/text-box/ibiz-input-number/ibiz-input-number.scss b/src/editor/text-box/ibiz-input-number/ibiz-input-number.scss index 42af8ccbb2091b00635302f2c9d3105cf7c05405..40400c24a3dd915002aa4f23e2279b0a00e394fd 100644 --- a/src/editor/text-box/ibiz-input-number/ibiz-input-number.scss +++ b/src/editor/text-box/ibiz-input-number/ibiz-input-number.scss @@ -12,7 +12,7 @@ input::placeholder { color: getCssVar('form-item', 'placeholder-color'); - -webkit-text-fill-color: getCssVar('form-item', 'text-color'); + -webkit-text-fill-color: getCssVar('form-item', 'placeholder-color'); } input:disabled { diff --git a/src/panel-component/view-content-panel-container/view-content-panel-container.scss b/src/panel-component/view-content-panel-container/view-content-panel-container.scss index 19083742682de3c0ad4b93f8a222307172efdc4c..b23abf9d0e569a4932c8d353c62ef7d31279719e 100644 --- a/src/panel-component/view-content-panel-container/view-content-panel-container.scss +++ b/src/panel-component/view-content-panel-container/view-content-panel-container.scss @@ -15,7 +15,7 @@ $control: ( height: 100%; margin-top: getCssVar('panel-component-view-content', 'margin'); - overflow: visible; + overflow: auto; background-color: getCssVar(view, bg, color); @include when(scroll) { diff --git a/src/view-engine/index.ts b/src/view-engine/index.ts index 7a7afefb04eb117c69a32efdadf8493a90b71a61..224f15b4addffe48abf6eb1572435569ede1296b 100644 --- a/src/view-engine/index.ts +++ b/src/view-engine/index.ts @@ -22,6 +22,7 @@ import { MobChartViewEngine } from './mob-chart-view.engine'; import { MobCalendarViewEngine } from './mob-calendar-view.engine'; import { MobWizardViewEngine } from './mob-wizard-view-engine'; import { MobTreeExpViewEngine } from './mob-tree-exp-view.engine'; +import { MobTabSearchViewEngine } from './mob-tab-search-view.engine'; export const IBizViewEngine = { install: (): void => { @@ -151,5 +152,9 @@ export const IBizViewEngine = { `VIEW_MobWizardView`, (c: IMobViewController) => new MobWizardViewEngine(c), ); + ibiz.engine.register( + 'VIEW_DEMOBTABSEARCHVIEW', + (c: IViewController) => new MobTabSearchViewEngine(c), + ); }, }; diff --git a/src/view-engine/mob-tab-search-view.engine.ts b/src/view-engine/mob-tab-search-view.engine.ts new file mode 100644 index 0000000000000000000000000000000000000000..bbcb065518f6adb88e94468d163443b82b1cf2cb --- /dev/null +++ b/src/view-engine/mob-tab-search-view.engine.ts @@ -0,0 +1,198 @@ +import { + ISearchBarController, + ISearchFormController, + ITabExpPanelController, + ITabSearchViewEvent, + ITabSearchViewState, + SysUIActionTag, + ViewController, +} from '@ibiz-template/runtime'; +import { IAppDETabSearchView } from '@ibiz/model-core'; +import { MobTabExpViewEngine } from './mob-tab-exp-view.engine'; + +/** + * 分页搜索视图 + * + * @export + * @class MobTabSearchViewEngine + * @extends {EditViewEngine} + */ +export class MobTabSearchViewEngine extends MobTabExpViewEngine { + /** + * 视图控制器 + * + * @protected + * @type {ViewController< + * IAppDETabSearchView, + * ITabSearchViewState, + * ITabSearchViewEvent + * >} + * @memberof MobTabSearchViewEngine + */ + protected declare view: ViewController< + IAppDETabSearchView, + ITabSearchViewState, + ITabSearchViewEvent + >; + + /** + * 搜索表单控制器 + * @author lxm + * @date 2023-05-22 01:56:25 + * @readonly + */ + protected get searchForm(): ISearchFormController { + return this.view.getController('searchform') as ISearchFormController; + } + + /** + * 搜索栏控制器 + * @author lxm + * @date 2023-05-22 01:56:25 + * @readonly + */ + protected get searchBar(): ISearchBarController { + return this.view.getController('searchbar') as ISearchBarController; + } + + /** + * 分页导航面板控制器 + * @author lxm + * @date 2023-05-22 01:56:25 + * @readonly + */ + public get tabExpPanel(): ITabExpPanelController { + return this.view.getController('tabexppanel') as ITabExpPanelController; + } + + protected preprocessTabExpModelLayout(): void { + // 不进行模型处理 + } + + async onCreated(): Promise { + await super.onCreated(); + const { childNames } = this.view; + childNames.push('searchform', 'searchbar'); + } + + async onMounted(): Promise { + await super.onMounted(); + // 计算是否默认展开搜索表单 + const controller = this.viewLayoutPanel!.panelItems.view_searchform; + if (controller) { + const formExists = !!this.searchForm; + controller.state.keepAlive = formExists; + controller.state.visible = formExists; + } + + const searchbarC = this.viewLayoutPanel!.panelItems.view_searchbar; + if (searchbarC) { + const visible = + this.searchBar && + !!( + this.searchBar.model.enableQuickSearch || + this.searchBar.model.enableGroup || + this.searchBar.model.enableFilter === true + ); + searchbarC.state.visible = visible; + } + + // 搜索表单搜索触发加载 + if (this.searchForm) { + this.searchForm.evt.on('onSearch', () => { + this.calcViewParams(); + }); + } + + // 搜索栏搜索触发加载 + if (this.searchBar) { + this.searchBar.evt.on('onSearch', () => { + this.calcViewParams(); + }); + } + // 分页导航面板切换 + if (this.tabExpPanel) { + this.tabExpPanel.evt.on('onTabChange', () => { + this.calcViewParams(); + }); + } + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types + async call(key: string, args: any): Promise { + if (key === SysUIActionTag.SEARCH) { + await this.searchForm.search(); + return null; + } + if (key === SysUIActionTag.RESET) { + await this.searchForm.reset(); + return null; + } + if (key === SysUIActionTag.REFRESH) { + await this.calcViewParams(); + return null; + } + return super.call(key, args); + } + + /** + * 获取搜索相关的查询参数 + * @author lxm + * @date 2023-05-22 03:26:04 + * @return {*} {IParams} + */ + protected getSearchParams(): IParams { + const params: IParams = {}; + // 有搜索表单的整合相关参数 + if (this.searchForm) { + Object.assign(params, this.searchForm.getFilterParams()); + } + // 有搜索栏的整合相关参数 + if (this.searchBar) { + Object.assign(params, this.searchBar.getFilterParams()); + } + return params; + } + + /** + * 计算视图头部元素的显示与否 + * 所有部件容器名称均为:view_部件名称 + * - 注意 分页导航和分页搜索的默认布局不一致 + * + * 分页导航:分页导航栏在视图头中 + * + * 分页搜索:分页导航栏不在视图头中 + * @protected + */ + protected calcViewHeaderVisible(): boolean { + let showHeader: boolean = false; + const { model } = this.view; + + // 标题栏 + if (model.showCaptionBar) { + showHeader = true; + } + if (ibiz.env.isMob) { + if (this.isExistAndInLayout('lefttoolbar')) { + showHeader = true; + } + + if (this.isExistAndInLayout('righttoolbar')) { + showHeader = true; + } + } else if (this.isExistAndInLayout('toolbar')) { + showHeader = true; + } + return showHeader; + } + + /** + * 重新计算视图参数 + * @author lxm + * @date 2024-03-18 05:00:02 + */ + calcViewParams(): void { + this.tabExpPanel.state.expViewParams = this.getSearchParams(); + this.tabExpPanel.refresh(); + } +} diff --git a/src/view/portal-view/portal-view.scss b/src/view/portal-view/portal-view.scss index 5f350785935557a9f2643ef9d202538e8f098646..6d8ec872396cce80767a06fa5e5a9a0b95a80d99 100644 --- a/src/view/portal-view/portal-view.scss +++ b/src/view/portal-view/portal-view.scss @@ -1,4 +1,5 @@ @include b(portal-view) { display: flex; flex-direction: column; + #{getCssVarName(view, bg, color)}: getCssVar(color, bg, 0); } \ No newline at end of file