diff --git a/CHANGELOG.md b/CHANGELOG.md index 80be60d53636bbbf941d6c1a4a285762be7a3f06..22809a911ca5d4931ef18dfbc03e13f979d8dfcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ### Added +- 表单分页面板新增样式2,无法直接展示全部分页项时,提供【全部】项用于弹出显示全部分页项进行选择,同时左右两侧的滚动按钮在无法滚动时,隐藏按钮 +- 图表新增内置导航功能 - 新增部件参数batchtoolbarmode、全局参数batchToolbarMode,用于设置批操作工具栏显示模式(default 选数据即显示,multiple 需选 2 条以上),仅限卡片、列表、表格、树表格使用 - 新增列表部件样式-扩展视图3:仅非分组列表和分组样式2列表支持,实现列表的从下往上的绘制,同时滚动加载也支持上滚加载 diff --git a/src/common/control-navigation/provider/chart-navigation.provider.ts b/src/common/control-navigation/provider/chart-navigation.provider.ts new file mode 100644 index 0000000000000000000000000000000000000000..839ea7e77cc3603c4c7124ee87f21d5b060bbab8 --- /dev/null +++ b/src/common/control-navigation/provider/chart-navigation.provider.ts @@ -0,0 +1,163 @@ +import { + ChartController, + convertNavData, + EventBase, + INavViewMsg, + MDControlController, +} from '@ibiz-template/runtime'; +import { INavigatable } from '@ibiz/model-core'; +import { NavgationBaseProvider } from './navigation-base.provider'; + +export class ChartNavigationProvider extends NavgationBaseProvider { + /** + * 图表导航栈数据 + * + * @type {IData[]} + * @memberof ChartNavigationProvider + */ + chartNavStack: IData[] = []; + + declare controller: ChartController; + + constructor(controller: MDControlController) { + super(controller); + if (controller.state.enableNavView) { + controller.evt.on('onActive', event => { + this.xDataActive(event); + }); + } + } + + /** + * 获取默认激活数据 + * + * @return {*} {(IData | undefined)} + * @memberof ChartNavigationProvider + */ + getDefaultActiveData(): IData | undefined { + const activeSeriesGenerator = + this.controller.generator.seriesGenerators.find(generator => { + return ( + generator.chartDataArr.length > 0 && generator.model.navAppViewId + ); + }); + if (activeSeriesGenerator && activeSeriesGenerator.groupData) { + const firstGroupName = Object.keys(activeSeriesGenerator.groupData)[0]; + const { chartData } = activeSeriesGenerator.groupData[firstGroupName] + .values() + .next().value as IData; + return chartData; + } + } + + /** + * 图表数据激活 + * + * @param {EventBase} event + * @memberof ChartNavigationProvider + */ + xDataActive(event: EventBase): void { + const { data } = event; + this.navViewMsg.value = this.getNavViewMsg(data[0]); + // 缓存用户导航数据,放置在最前 + this.chartNavStack.unshift(data[0]); + } + + /** + * 通过栈数据导航 + * + * @return {*} {void} + * @memberof ChartNavigationProvider + */ + onNavDataByStack(): void { + const data = this.getDefaultActiveData(); + if (!data) return this.clearNavigation(); + this.controller.setActive(data); + this.controller.setSelection([data]); + } + + /** + * 解析参数 + * + * @param {(INavigatable & { appDataEntityId?: string })} XDataModel + * @param {IData} data + * @param {IContext} context + * @param {IParams} params + * @return {*} {{ context: IContext; params: IParams }} + * @memberof ChartNavigationProvider + */ + prepareParams( + XDataModel: INavigatable & { appDataEntityId?: string }, + data: IData, + context: IContext, + params: IParams, + ): { context: IContext; params: IParams } { + const { context: tempContext, params: tempParams } = super.prepareParams( + XDataModel, + data, + context, + params, + ); + // 序列上或配置导航相关参数 + if (data._seriesModelId) { + const seriesModel = this.controller.model.dechartSerieses?.find( + series => { + return series.id === data._seriesModelId; + }, + ); + if (seriesModel) { + const { navigateContexts, navigateParams } = seriesModel; + // 序列上配的导航视图参数和上下文 + const tempContext2 = convertNavData( + navigateContexts, + data, + params, + tempContext, + ); + const tempParams2 = convertNavData( + navigateParams, + data, + params, + tempParams, + ); + if (data.navParams) Object.assign(tempParams2, data.navParams); + return { + context: Object.assign(tempContext.clone(), tempContext2), + params: tempParams2, + }; + } + } + return { context: tempContext, params: tempParams }; + } + + /** + * 获取导航视图信息 + * + * @param {IData} data + * @return {*} {INavViewMsg} + * @memberof ChartNavigationProvider + */ + public getNavViewMsg(data: IData): INavViewMsg { + let viewModelId; + if (data._seriesModelId) { + const seriesModel = this.controller.model.dechartSerieses?.find( + series => { + return series.id === data._seriesModelId; + }, + ); + viewModelId = seriesModel?.navAppViewId; + } + const result = this.prepareParams( + this.controller.model!, + data, + this.controller.context, + this.controller.params, + ); + return { + key: data._uuid, + context: result.context, + params: result.params, + viewId: viewModelId, + }; + } +} diff --git a/src/common/control-navigation/provider/index.ts b/src/common/control-navigation/provider/index.ts index b4e53033491f62b38d5fe573c0fc466395dae617..448822e88db26c00a00cc907f344bb9bd4eec1c2 100644 --- a/src/common/control-navigation/provider/index.ts +++ b/src/common/control-navigation/provider/index.ts @@ -3,6 +3,7 @@ import { NavgationBaseProvider } from './navigation-base.provider'; import { CalendarNavigationProvider } from './calendar-navigation.provider'; import { TreeNavigationProvider } from './tree-navigation.provider'; import { MapNavigationProvider } from './map-navigation.provider'; +import { ChartNavigationProvider } from './chart-navigation.provider'; /** * 获取部件导航适配器 @@ -20,5 +21,6 @@ export function getNavigationProvider( if (controlType === 'TREEVIEW' || controlType === 'TREEGRIDEX') return new TreeNavigationProvider(controller); if (controlType === 'MAP') return new MapNavigationProvider(controller); + if (controlType === 'CHART') return new ChartNavigationProvider(controller); return new NavgationBaseProvider(controller); } diff --git a/src/control/chart/chart.tsx b/src/control/chart/chart.tsx index d85dfe9c3a389285f090cd38e167f841c10b1f68..87f7211ad86480a056899829c411a261d7bcec7f 100644 --- a/src/control/chart/chart.tsx +++ b/src/control/chart/chart.tsx @@ -300,70 +300,72 @@ const ChartControl = defineComponent({ }, render() { return ( - -
- {this.renderNoData()} -
+ + +
+ {this.renderNoData()}
-
- {ibiz.i18n.t('control.chart.chartPlaceholder')} -
- {this.showCheck ? ( -
-
- - +
+ {ibiz.i18n.t('control.chart.chartPlaceholder')} +
+ {this.showCheck ? ( +
+
+ - - - -
- {ibiz.i18n.t('control.chart.drillDetail')} + + + + +
+ {ibiz.i18n.t('control.chart.drillDetail')} +
-
+ ) : null} +
+ {this.c.state.showGrid ? ( +
{this.renderGrid()}
) : null}
- {this.c.state.showGrid ? ( -
{this.renderGrid()}
- ) : null}
-
-
+ +
); }, }); 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 32b556b1c2cfad52c8f83e8b37b21b855d4e0fbb..010afc39f254f15c7cfac543afb06f49f7809860 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 @@ -8,6 +8,7 @@ $form-tab-panel: ( 'active-text-color': getCssVar(color, primary), 'active-bg-color': transparent, 'active-border-color': getCssVar(color, primary), + 'select-all-height': 40px, ); @include b(form-tab-panel) { @@ -68,6 +69,76 @@ $form-tab-panel: ( } } } - + @include m('style2'){ + .el-tabs__nav-prev.is-disabled, + .el-tabs__nav-next.is-disabled{ + display: none; + } + + .el-tabs__nav-wrap.is-top{ + &:has(.el-tabs__nav-prev.is-disabled){ + padding-left: 0; + } + + &:has(.el-tabs__nav-next.is-disabled){ + padding-right: 0; + } + } + } +} + +@include b('form-tab-panel-tab-panel-container-style2') { + position: relative; + display: flex; + width: 100%; + @include set-component-css-var('form-tab-panel', $form-tab-panel); + + .#{bem(form-tab-panel)} { + width: 100%; + + .el-tabs__header { + width: calc(100% - 72px); + } + } + @include e('popover') { + @include set-component-css-var('form-tab-panel', $form-tab-panel); + + &.el-popover { + padding: 0; + } + } + @include e('select') { + position: absolute; + top: 0; + right: 0; + display: flex; + gap: getCssVar(spacing, extra-tight); + align-items: center; + justify-content: center; + width: 72px; + height: getCssVar('form-tab-panel', 'select-all-height'); + font-size: getCssVar('form-tab-panel', 'font-size'); + color: getCssVar('form-tab-panel', 'text-color'); + cursor: pointer; + border-bottom: 1px solid getCssVar('form-tab-panel', 'header-border-color'); + } + @include e('content') { + padding: getCssVar(spacing, base) 0; + } + @include e('tab-item-content') { + width: 100%; + padding: getCssVar(spacing, extra-tight) getCssVar(spacing, extra-tight) getCssVar(spacing, extra-tight) getCssVar(spacing, base); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; + &:hover{ + color: getCssVar('form-tab-panel', 'hover-text-color'); + background-color: getCssVar('form-tab-panel', 'hover-bg-color'); + } + @include when('active'){ + color: getCssVar('form-tab-panel', 'active-text-color'); + } + } } diff --git a/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx b/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx index c27ec1dfa29e6ea333da72bb647a28e620356f2b..8fa60330cd0fbb3052936584b0a7724ad5d7d51c 100644 --- a/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx +++ b/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx @@ -1,4 +1,5 @@ -import { defineComponent, PropType, VNode } from 'vue'; +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { defineComponent, PropType, ref, VNode } from 'vue'; import { useController, useNamespace } from '@ibiz-template/vue3-util'; import './form-tab-panel.scss'; import { IDEFormTabPanel } from '@ibiz/model-core'; @@ -22,22 +23,55 @@ export const FormTabPanel = defineComponent({ setup(props) { const ns = useNamespace('form-tab-panel'); useController(props.controller); + const popoverVisible = ref(false); - const onTabClick = (tabIns: IData, event: MouseEvent) => { - props.controller.onTabChange(tabIns.props.name); - + const triggerClick = (key: string, event: MouseEvent) => { // 触发对应FormTabPage的点击事件 - const pageC = props.controller.form.details[ - tabIns.props.name - ] as FormTabPageController; + const pageC = props.controller.form.details[key] as FormTabPageController; if (pageC) { pageC.onClick(event); } }; + const onTabClick = (tabIns: IData, event: MouseEvent) => { + props.controller.onTabChange(tabIns.props.name); + triggerClick(tabIns.props.name, event); + }; + + const onPopoverClick = (key: string, event: MouseEvent) => { + props.controller.selectTab(key); + popoverVisible.value = false; + triggerClick(key, event); + }; + + const renderAllTabContent = () => { + return ( +
+ {props.modelData.deformTabPages?.map(page => { + return ( +
+ onPopoverClick(page.codeName!, event) + } + title={page.caption} + > + {page.caption} +
+ ); + })} +
+ ); + }; + return { ns, + popoverVisible, onTabClick, + renderAllTabContent, }; }, render() { @@ -50,7 +84,7 @@ export const FormTabPanel = defineComponent({ ); }; - return ( + const tabContent = ( ); + if (this.modelData.detailStyle === 'STYLE2') { + return ( +
+ {tabContent} + + {{ + reference: () => { + return ( +
+
+ {ibiz.i18n.t('control.form.formTabPnel.all')} +
+ +
+ ); + }, + default: () => { + return this.renderAllTabContent(); + }, + }} +
+
+ ); + } + return tabContent; }, }); export default FormTabPanel; diff --git a/src/control/list/list.tsx b/src/control/list/list.tsx index 9ac706f22982cf48e228319c2b125a105bdc96da..fe78f198ee674e6909a3451c24654d853ea9d83b 100644 --- a/src/control/list/list.tsx +++ b/src/control/list/list.tsx @@ -9,7 +9,7 @@ import { } from '@ibiz-template/vue3-util'; import { ref, VNode, watch, PropType, computed, defineComponent } from 'vue'; import { IDEList, ILayoutPanel, IUIActionGroupDetail } from '@ibiz/model-core'; -import { isNil } from 'lodash-es'; +import { isNil, debounce } from 'lodash-es'; import { ControlVO, ListController, @@ -19,7 +19,6 @@ import { } from '@ibiz-template/runtime'; import draggable from 'vuedraggable'; import { showTitle } from '@ibiz-template/core'; -import { debounce } from 'lodash-es'; import { usePagination } from '../../util'; import './list.scss'; diff --git a/src/locale/en/index.ts b/src/locale/en/index.ts index 9027535b40c3e1b1483d719676a71ca8364a5680..60e3ef06e6ccc50a0b3a4d63724e48267f627cac 100644 --- a/src/locale/en/index.ts +++ b/src/locale/en/index.ts @@ -465,6 +465,9 @@ export default { errorText: 'Error tips', defaultText: 'Direct content', }, + formTabPnel: { + all: 'All', + }, }, gantt: { complete: 'Completed amount', diff --git a/src/locale/zh-CN/index.ts b/src/locale/zh-CN/index.ts index 325721d47f47af01fbcc9215618ed2ac6bd4948e..51772b6f1c5a5bc29c934b9f20fda870b2243e91 100644 --- a/src/locale/zh-CN/index.ts +++ b/src/locale/zh-CN/index.ts @@ -425,6 +425,9 @@ export default { errorText: '错误提示(ERROR)', defaultText: '直接内容', }, + formTabPnel: { + all: '全部', + }, }, gantt: { complete: '完成量',