diff --git a/README.md b/README.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..db4af39385a4fbb9351a589ca174f3cb1b3b272d 100644 --- a/README.md +++ b/README.md @@ -0,0 +1 @@ +https://vue-pivottable.vercel.app/ \ No newline at end of file diff --git a/src/components/group-pivottable-body/group-pivottable-body.scss b/src/components/group-pivottable-body/group-pivottable-body.scss new file mode 100644 index 0000000000000000000000000000000000000000..a7e63833c0f2808a294e098836fe8a8a997c76d9 --- /dev/null +++ b/src/components/group-pivottable-body/group-pivottable-body.scss @@ -0,0 +1,12 @@ +/* stylelint-disable selector-class-pattern */ +@include b(group-pivottable-body) { + .el-tree { + height: 100%; + + --el-tree-node-content-height: 32px; + + .el-tree-node__content { + border-bottom: 1px solid #1d1f231a; + } + } +} diff --git a/src/components/group-pivottable-body/group-pivottable-body.tsx b/src/components/group-pivottable-body/group-pivottable-body.tsx new file mode 100644 index 0000000000000000000000000000000000000000..63116ef66707ce3ad671b35915d2b873e45ffe63 --- /dev/null +++ b/src/components/group-pivottable-body/group-pivottable-body.tsx @@ -0,0 +1,155 @@ +/* eslint-disable no-param-reassign */ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { useNamespace } from '@ibiz-template/vue3-util'; +import { computed, defineComponent, Ref, ref } from 'vue'; + +import './group-pivottable-body.scss'; + +export const GroupPivotTableBody = defineComponent({ + name: 'IBizGroupPivotTableBody', + props: { + groupData: { + type: Array, + required: true, + }, + colKeys: { + type: Array, + required: true, + }, + rowKeys: { + type: Array, + required: true, + }, + rowAttrs: { + type: Array, + required: true, + }, + }, + setup(props) { + const ns = useNamespace(`group-pivottable-body`); + + const collapseKeys: Ref = ref([]); + + const colFields = computed(() => { + return props.colKeys.map((tags: any) => { + return tags.join(String.fromCharCode(0)); + }); + }); + + const parseRows = (item: IData) => { + const result: IData = {}; + if (item.items) { + item.items.forEach((x: IData) => { + result[x.codeName] = x.format; + }); + } + result.pvtTotal = item.format; + result.srfkey = item.srfkey; + return result; + }; + + const fillRows = (items: IData[]) => { + const result: IData[] = []; + items.forEach((item: IData) => { + result.push(parseRows(item)); + if (item.children && item.children.length) { + result.push(...fillRows(item.children)); + } + }); + return result; + }; + + const fillColKeys = (item: IData) => { + const keys = Object.keys(item); + props.colKeys.forEach((tags: any) => { + const tag = tags.join(String.fromCharCode(0)); + if (!keys.includes(tag)) { + item[tag] = ''; + } + }); + return item; + }; + + const rows = computed(() => { + const items = fillRows(props.groupData); + const result: IData[] = items.map(x => fillColKeys(x)); + const res = result.filter(x => !collapseKeys.value.includes(x.srfkey)); + return res; + }); + + const calcNodeExpand = ( + data: IData, + expand: boolean, + keySet: Set, + ) => { + const children = data.children || []; + if (expand) { + children.forEach((x: IData) => { + keySet.delete(x.srfkey); + if (x.children && x.children.length) { + calcNodeExpand(x, expand, keySet); + } + }); + } else { + children.forEach((x: IData) => { + keySet.add(x.srfkey); + if (x.children && x.children.length) { + calcNodeExpand(x, expand, keySet); + } + }); + } + }; + + const updateNodeExpand = (data: IData, expand: boolean) => { + const keySet = new Set(collapseKeys.value); + calcNodeExpand(data, expand, keySet); + collapseKeys.value = Array.from(keySet); + }; + + const renderRow = (item: IData) => { + return colFields.value.map(key => { + return {item[key]}; + }); + }; + + const renderDropdown = (index: number) => { + if (index !== 0) { + return; + } + const content = ( + { + updateNodeExpand(data, true); + }} + onNodeCollapse={(data: IData) => { + updateNodeExpand(data, false); + }} + /> + ); + return ( + + {content} + + ); + }; + return { + ns, + rows, + renderRow, + renderDropdown, + }; + }, + render() { + return this.rows.map((column: IData, index: number) => { + return ( + + {this.renderDropdown(index)} + {this.renderRow(column)} + + ); + }); + }, +}); diff --git a/src/index.ts b/src/index.ts index c3395fb23bed4233c8dd958c468a868b2cc18848..ace8d7ce9624869cb69f5d44fd96ea7e19f62232 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,10 +3,12 @@ import { withInstall } from '@ibiz-template/vue3-util'; import { ControlType, registerControlProvider } from '@ibiz-template/runtime'; import { PivotTable } from './pivottable'; import { PivotTableProvider } from './pivottable.provider'; +import { GroupPivotTableBody } from './components/group-pivottable-body/group-pivottable-body'; import './pivottable/styles/vue-pivottable.css'; export const IBizPivotTable = withInstall(PivotTable, (v: any) => { v.component(PivotTable.name, PivotTable); + v.component(GroupPivotTableBody.name, GroupPivotTableBody); registerControlProvider( `${ControlType.GRID}_PIVOTTABLE`, () => new PivotTableProvider(), diff --git a/src/pivottable.controller.ts b/src/pivottable.controller.ts index f9267a86aa282673b3ff5b77236ce65d8e11bd83..19a4df81a46f5473abde0b9e6e33ce39c7bc079a 100644 --- a/src/pivottable.controller.ts +++ b/src/pivottable.controller.ts @@ -23,6 +23,13 @@ export class PivotTableController extends GridController { */ declare state: IPivotTableState; + /** + * @description 分组模式 + * @type {('default' | 'tree')} + * @memberof PivotTableController + */ + public groupMode: 'default' | 'tree' = 'default'; + constructor(model: IDEGrid, context: IContext, params: IParams, ctx: CTX) { super(model, context, params, ctx); this.initConfig(); @@ -37,6 +44,9 @@ export class PivotTableController extends GridController { protected async onCreated(): Promise { await super.onCreated(); this.initFields(); + if (this.controlParams.groupmode) { + this.groupMode = this.controlParams.groupmode; + } } async afterLoad( @@ -91,7 +101,9 @@ export class PivotTableController extends GridController { this.configService = new ConfigService( this.model.appId!, 'pivottable', - `pivottable_${(this.view as IData).name.toLowerCase()}_${this.model.codeName?.toLowerCase()}`, + `pivottable_${( + this.view as IData + ).name.toLowerCase()}_${this.model.codeName?.toLowerCase()}`, ); } diff --git a/src/pivottable.scss b/src/pivottable.scss index b35a35a533d554e6355ce5199a41bde6c4e806e6..be5ff7f30117e284f4ac485254d7c1c64eccb381 100644 --- a/src/pivottable.scss +++ b/src/pivottable.scss @@ -1,3 +1,21 @@ +/* stylelint-disable selector-class-pattern */ @include b(pivot-table) { - -} \ No newline at end of file + table.pvtTable thead tr th, + table.pvtTable tbody tr th { + min-width: 100px; + height: 32px; + min-height: 32px; + padding: 0; + line-height: 32px; + text-align: center; + } + + table.pvtTable tbody tr td { + height: 32px; + min-height: 32px; + padding: 0; + line-height: 31px; + text-align: center; + vertical-align:middle; + } +} diff --git a/src/pivottable.tsx b/src/pivottable.tsx index c3463f788e551469a44310a5e7a00de7a48a6d77..eb4c0133968b51da3801ef0041c4b56a9e3238f8 100644 --- a/src/pivottable.tsx +++ b/src/pivottable.tsx @@ -141,6 +141,7 @@ export const PivotTable = defineComponent({ rows={rows} vals={vals} fields={this.c.state.fields} + groupMode={this.c.groupMode} onChange={(data: IData) => { this.c.saveConfig(data); }} diff --git a/src/pivottable/components/pivottable-ui/VPivottableUi.vue b/src/pivottable/components/pivottable-ui/VPivottableUi.vue index c7f28024d8b05e0a223d64bc58c0d057f674afde..e26b4a9242c48e43df4a41a1c966888be3ae98b8 100644 --- a/src/pivottable/components/pivottable-ui/VPivottableUi.vue +++ b/src/pivottable/components/pivottable-ui/VPivottableUi.vue @@ -112,7 +112,7 @@ diff --git a/src/pivottable/components/pivottable/VPivottableBody.vue b/src/pivottable/components/pivottable/VPivottableBody.vue index 0877df94eeb9d1d349aa53a5f7ff67377ddc507b..a3064280753ff848a1c133cc2b5bee79b548fe25 100644 --- a/src/pivottable/components/pivottable/VPivottableBody.vue +++ b/src/pivottable/components/pivottable/VPivottableBody.vue @@ -1,11 +1,15 @@