From 7bba28aaa456f0f4362b0e9d193d3537e580183e Mon Sep 17 00:00:00 2001 From: hLinx <327159425@qq.com> Date: Thu, 7 Nov 2024 22:15:47 +0800 Subject: [PATCH] =?UTF-8?q?perf(frontend):=20table=20=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E4=BC=98=E5=8C=96=20#7818=20#=20Reviewed,=20?= =?UTF-8?q?transaction=20id:=2023212?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/package.json | 1 + dbm-ui/frontend/src/common/importComps.ts | 14 +- dbm-ui/frontend/src/common/table/BkTable.vue | 186 ++++++++++++++++++ .../src/common/table/BkTableColumn.vue | 63 ++++++ dbm-ui/frontend/src/common/table/adapter.ts | 105 ++++++++++ .../src/common/table/components/RenderCell.ts | 25 +++ .../src/common/table/components/RenderHead.ts | 35 ++++ .../components/setting-column/ActionTab.vue | 25 +++ .../table/components/setting-column/Index.vue | 173 ++++++++++++++++ .../setting-column/useOutSideClick.ts | 26 +++ .../common/table/style/vxe-table-path.less | 113 +++++++++++ .../frontend/src/common/table/utils/index.ts | 1 + .../src/common/table/utils/makeMap.ts | 20 ++ .../list/components/list/Index.vue | 1 + 14 files changed, 786 insertions(+), 2 deletions(-) create mode 100644 dbm-ui/frontend/src/common/table/BkTable.vue create mode 100644 dbm-ui/frontend/src/common/table/BkTableColumn.vue create mode 100644 dbm-ui/frontend/src/common/table/adapter.ts create mode 100644 dbm-ui/frontend/src/common/table/components/RenderCell.ts create mode 100644 dbm-ui/frontend/src/common/table/components/RenderHead.ts create mode 100644 dbm-ui/frontend/src/common/table/components/setting-column/ActionTab.vue create mode 100644 dbm-ui/frontend/src/common/table/components/setting-column/Index.vue create mode 100644 dbm-ui/frontend/src/common/table/components/setting-column/useOutSideClick.ts create mode 100644 dbm-ui/frontend/src/common/table/style/vxe-table-path.less create mode 100644 dbm-ui/frontend/src/common/table/utils/index.ts create mode 100644 dbm-ui/frontend/src/common/table/utils/makeMap.ts diff --git a/dbm-ui/frontend/package.json b/dbm-ui/frontend/package.json index 1d38e3939a..b10ca6cb84 100644 --- a/dbm-ui/frontend/package.json +++ b/dbm-ui/frontend/package.json @@ -24,6 +24,7 @@ "@blueking/login-modal": "^1.0.5", "@blueking/notice-component": "2.0.5", "@blueking/sub-saas": "0.0.0-beta.6", + "@blueking/vxe-table": "^4.8.0-beta.7.1", "@icon-cool/bk-icon-bk-biz-components": "0.0.4", "@vueuse/core": "^11.0.3", "axios": "^1.7.7", diff --git a/dbm-ui/frontend/src/common/importComps.ts b/dbm-ui/frontend/src/common/importComps.ts index 9f4a9be534..89463a6dde 100644 --- a/dbm-ui/frontend/src/common/importComps.ts +++ b/dbm-ui/frontend/src/common/importComps.ts @@ -11,7 +11,6 @@ * the specific language governing permissions and limitations under the License. */ -import { Table } from 'bkui-vue'; import type { App } from 'vue'; import AuthButton from '@components/auth-component/button.vue'; @@ -39,6 +38,9 @@ import { ipSelector } from '@components/vue2/ip-selector'; import UserSelector from '@patch/user-selector/selector.vue'; +import Table from './table/BkTable.vue'; +import TableColumn from './table/BkTableColumn.vue'; + export const setGlobalComps = (app: App) => { app.component('DbCard', DbCard); app.component('DbForm', DbForm); @@ -63,5 +65,13 @@ export const setGlobalComps = (app: App) => { app.component('AuthOption', AuthOption); app.component('AuthSwitcher', AuthSwitch); app.component('AuthRouterLink', AuthRouterLink); - app.component('BKTableColumn', Table.Column); + setTimeout(() => { + // eslint-disable-next-line + delete app._context.components.BkTable; + // eslint-disable-next-line + delete app._context.components.BkTableColumn; + + app.component('BkTable', Table); + app.component('BkTableColumn', TableColumn); + }); }; diff --git a/dbm-ui/frontend/src/common/table/BkTable.vue b/dbm-ui/frontend/src/common/table/BkTable.vue new file mode 100644 index 0000000000..42796ef97b --- /dev/null +++ b/dbm-ui/frontend/src/common/table/BkTable.vue @@ -0,0 +1,186 @@ + + + diff --git a/dbm-ui/frontend/src/common/table/BkTableColumn.vue b/dbm-ui/frontend/src/common/table/BkTableColumn.vue new file mode 100644 index 0000000000..cce9448f27 --- /dev/null +++ b/dbm-ui/frontend/src/common/table/BkTableColumn.vue @@ -0,0 +1,63 @@ + + diff --git a/dbm-ui/frontend/src/common/table/adapter.ts b/dbm-ui/frontend/src/common/table/adapter.ts new file mode 100644 index 0000000000..7e4fabf270 --- /dev/null +++ b/dbm-ui/frontend/src/common/table/adapter.ts @@ -0,0 +1,105 @@ +import _ from 'lodash'; + +import { makeMap } from './utils'; + +export const columnConfig = (bkColumnConfig: any) => { + const vxeColumnConfig = { + ...bkColumnConfig, + slots: {}, + }; + + if (bkColumnConfig.label) { + if (_.isString(bkColumnConfig.label)) { + vxeColumnConfig.title = bkColumnConfig.label; + } else if (_.isFunction(bkColumnConfig.label)) { + const renderLabel = bkColumnConfig.label; + Object.assign(vxeColumnConfig.slots, { + header: (payload: any) => { + const res = renderLabel({ + column: payload.column, + index: payload.$rowIndex, + }); + + return res; + }, + }); + } + delete vxeColumnConfig.label; + } + + if (_.has(bkColumnConfig, 'sort')) { + vxeColumnConfig.sortable = bkColumnConfig.sort; + delete vxeColumnConfig.sort; + } + + if (bkColumnConfig.filter && bkColumnConfig.filter.list) { + const checkedMap = makeMap(bkColumnConfig.filter.checked || []); + vxeColumnConfig.filters = bkColumnConfig.filter.list.map((item: any) => ({ + label: item.text, + value: item.value, + checked: Boolean(checkedMap[item.value]), + })); + vxeColumnConfig.filterMultiple = true; + delete vxeColumnConfig.filter; + } + + if (bkColumnConfig.render) { + const cellRender = bkColumnConfig.render; + Object.assign(vxeColumnConfig.slots, { + default: (payload: any) => + cellRender({ + cell: payload.row[payload.column.field], + data: payload.row, + column: payload.column, + index: payload.$rowIndex, + rows: payload.data, + }), + }); + delete vxeColumnConfig.render; + } + + if (bkColumnConfig.renderHead) { + const headRender = bkColumnConfig.renderHead; + Object.assign(vxeColumnConfig.slots, { + header: (payload: any) => + headRender({ + column: payload.column, + index: payload.$rowIndex, + }), + }); + delete vxeColumnConfig.renderHead; + } + + delete vxeColumnConfig.label; + delete vxeColumnConfig.sort; + delete vxeColumnConfig.textAlign; + + // 废弃属性 + delete vxeColumnConfig.children; + delete vxeColumnConfig.titleHelp; + + return vxeColumnConfig; +}; + +export const tableConfig = (bkTableConfig: any) => { + const bkTableConfigMemo = _.cloneDeep(bkTableConfig); + const vxeTableConfig = { + ...bkTableConfig, + }; + + if (bkTableConfigMemo.columns) { + delete vxeTableConfig.columns; + } + if (bkTableConfigMemo.rowClass) { + if (typeof bkTableConfigMemo.rowClass === 'string') { + vxeTableConfig.rowClassName = bkTableConfigMemo.rowClas; + } else if (typeof bkTableConfigMemo.rowClass === 'function') { + const { rowClass } = bkTableConfigMemo; + + vxeTableConfig.rowClassName = ({ row }: { row: any }) => rowClass(row); + } + delete vxeTableConfig.rowClass; + } + + return vxeTableConfig; +}; diff --git a/dbm-ui/frontend/src/common/table/components/RenderCell.ts b/dbm-ui/frontend/src/common/table/components/RenderCell.ts new file mode 100644 index 0000000000..925328e853 --- /dev/null +++ b/dbm-ui/frontend/src/common/table/components/RenderCell.ts @@ -0,0 +1,25 @@ +import { defineComponent } from 'vue'; + +export default defineComponent({ + name: 'RenderCell', + props: { + column: { + type: Object, + required: true, + }, + params: { + type: Object, + required: true, + }, + }, + setup(props) { + return () => + props.column.render({ + cell: props.column.field ? props.params.row[props.column.field] : '', + data: props.params.row, + column: props.params.column, + index: props.params.$rowIndex, + rows: props.params.data, + }); + }, +}); diff --git a/dbm-ui/frontend/src/common/table/components/RenderHead.ts b/dbm-ui/frontend/src/common/table/components/RenderHead.ts new file mode 100644 index 0000000000..8cff5de6a6 --- /dev/null +++ b/dbm-ui/frontend/src/common/table/components/RenderHead.ts @@ -0,0 +1,35 @@ +import _ from 'lodash'; +import { defineComponent } from 'vue'; + +export default defineComponent({ + name: 'RenderHead', + props: { + column: { + type: Object, + required: true, + }, + index: { + type: Number, + required: true, + }, + }, + setup(props) { + if (_.isFunction(props.column.renderHead)) { + return () => + props.column.renderHead({ + column: props.column, + index: props.index, + }); + } + + if (_.isFunction(props.column.label)) { + return () => + props.column.label({ + column: props.column, + index: props.index, + }); + } + + return () => null; + }, +}); diff --git a/dbm-ui/frontend/src/common/table/components/setting-column/ActionTab.vue b/dbm-ui/frontend/src/common/table/components/setting-column/ActionTab.vue new file mode 100644 index 0000000000..dccc9f9c4c --- /dev/null +++ b/dbm-ui/frontend/src/common/table/components/setting-column/ActionTab.vue @@ -0,0 +1,25 @@ + + diff --git a/dbm-ui/frontend/src/common/table/components/setting-column/Index.vue b/dbm-ui/frontend/src/common/table/components/setting-column/Index.vue new file mode 100644 index 0000000000..e7de8fff4a --- /dev/null +++ b/dbm-ui/frontend/src/common/table/components/setting-column/Index.vue @@ -0,0 +1,173 @@ + + + diff --git a/dbm-ui/frontend/src/common/table/components/setting-column/useOutSideClick.ts b/dbm-ui/frontend/src/common/table/components/setting-column/useOutSideClick.ts new file mode 100644 index 0000000000..750d4e8d88 --- /dev/null +++ b/dbm-ui/frontend/src/common/table/components/setting-column/useOutSideClick.ts @@ -0,0 +1,26 @@ +import { onBeforeUnmount, onMounted } from 'vue'; + +export default (callback: () => void) => { + const handeOutsideClick = (event: Event) => { + const eventPath = event.composedPath(); + // eslint-disable-next-line no-plusplus + for (let i = 0; i < eventPath.length; i++) { + const target = eventPath[i] as HTMLElement; + if ( + /bk-vxe-table-setting-column-btn/.test(target.className) || + /bk-vxe-table-setting-column-theme/.test(target.className) + ) { + return; + } + } + callback(); + }; + + onMounted(() => { + document.body.addEventListener('click', handeOutsideClick); + }); + + onBeforeUnmount(() => { + document.body.removeEventListener('click', handeOutsideClick); + }); +}; diff --git a/dbm-ui/frontend/src/common/table/style/vxe-table-path.less b/dbm-ui/frontend/src/common/table/style/vxe-table-path.less new file mode 100644 index 0000000000..6de4878c5a --- /dev/null +++ b/dbm-ui/frontend/src/common/table/style/vxe-table-path.less @@ -0,0 +1,113 @@ +.bk-vxe-table { + --vxe-ui-table-column-padding-mini: 9px 0; + --vxe-ui-font-size-small: 12px; + --vxe-ui-table-cell-padding-left: 16px; + --vxe-ui-table-cell-padding-right: 16px; + + .vxe-header--column { + font-weight: normal; + color: var(--table-head-font-color); + + .vxe-resizable{ + right: -5px; + + &.is--line{ + &:hover{ + &::before{ + background: var(--primary-color); + } + } + + &::before{ + width: 5px; + height: 100%; + background: transparent; + } + } + } + } + + .vxe-table--render-default { + color: var(--table-body-font-color); + + .vxe-table--resizable-bar { + &::before{ + background: var(--primary-color); + } + } + + &.column--highlight .vxe-header--column:not(.col--seq):hover{ + background: var(--table-row-active-bg-color); + } + } + + [class*='vxe-table-icon-'] { + font-size: 12px; + } + + .is--filter-active .vxe-cell--filter .vxe-filter--btn { + color: var(--primary-color); + } + + .vxe-table--filter-wrapper { + min-width: 148px; + + .vxe-table--filter-option { + &.is--checked { + color: var(--primary-color); + } + + .vxe-checkbox--icon { + color: var(--primary-color) !important; + } + } + + .vxe-table--filter-footer { + button { + display: inline-flex; + height: var(--component-size-small); + padding: var(--component-size-small-padding); + font-size: var(--font-size-base); + color: var(--default-color); + text-decoration: none; + white-space: nowrap; + cursor: pointer; + background: var(--white-color); + border: 1px solid var(--light-gray); + border-radius: var(--border-radius-base); + outline: none; + box-sizing: border-box; + transition: background-color ease 0.3s; + appearance: none; + align-items: center; + justify-content: center; + + &:first-child { + color: var(--white-color); + background: var(--primary-color); + border-color: var(--primary-color); + + &:hover { + background: var(--button-primary-hover-color); + border-color: var(--button-primary-hover-color); + } + + &.is--disabled { + color: var(--white-color); + background: var(--disable-color); + border-color: var(--disable-color); + } + } + + & ~ button { + margin-left: 8px; + + &:hover { + color: var(--default-color); + border-color: var(--button-default-hover-border-color); + } + } + } + } + } +} \ No newline at end of file diff --git a/dbm-ui/frontend/src/common/table/utils/index.ts b/dbm-ui/frontend/src/common/table/utils/index.ts new file mode 100644 index 0000000000..7d5838ab30 --- /dev/null +++ b/dbm-ui/frontend/src/common/table/utils/index.ts @@ -0,0 +1 @@ +export * from './makeMap'; diff --git a/dbm-ui/frontend/src/common/table/utils/makeMap.ts b/dbm-ui/frontend/src/common/table/utils/makeMap.ts new file mode 100644 index 0000000000..550fb9d37e --- /dev/null +++ b/dbm-ui/frontend/src/common/table/utils/makeMap.ts @@ -0,0 +1,20 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for + * the specific language governing permissions and limitations under the License. + */ + +export const makeMap = (list: Array = []): Record => { + const map = Object.create(null); + list.forEach((item) => { + map[item] = true; + }); + return map; +}; diff --git a/dbm-ui/frontend/src/views/db-manage/tendb-cluster/list/components/list/Index.vue b/dbm-ui/frontend/src/views/db-manage/tendb-cluster/list/components/list/Index.vue index 31e062359c..e1f12a8945 100644 --- a/dbm-ui/frontend/src/views/db-manage/tendb-cluster/list/components/list/Index.vue +++ b/dbm-ui/frontend/src/views/db-manage/tendb-cluster/list/components/list/Index.vue @@ -79,6 +79,7 @@ :row-class="setRowClass" selectable :settings="settings" + :show-overflow="false" @clear-search="clearSearchValue" @column-filter="columnFilterChange" @column-sort="columnSortChange"