提交 551fe50a 编写于 作者: V Vben

perf(table): the table fills the height according to the screen close #310

上级 745fcfc0
......@@ -9,6 +9,8 @@
- 表格关闭分页时不再携带分页参数
- 登录页监听回车事件进行登录
- 当表格设置自适应大小时,根据屏幕来铺满了高度.
- Tree 滚动条优化
### 🐛 Bug Fixes
......
<template>
<div :class="getClass">
<PageHeader :ghost="ghost" v-bind="$attrs" ref="headerRef">
<PageHeader
:ghost="ghost"
v-bind="$attrs"
ref="headerRef"
v-if="content || $slots.headerContent"
>
<template #default>
<template v-if="content">
{{ content }}
......@@ -11,7 +16,11 @@
<slot :name="item" v-bind="data"></slot>
</template>
</PageHeader>
<div :class="[`${prefixCls}-content`, $attrs.contentClass]" :style="getContentStyle">
<div
class="m-4 overflow-hidden"
:class="[`${prefixCls}-content`, contentClass]"
:style="getContentStyle"
>
<slot></slot>
</div>
<PageFooter v-if="getShowFooter" ref="footerRef">
......@@ -48,6 +57,8 @@
},
contentBackground: propTypes.bool,
contentFullHeight: propTypes.bool,
contentClass: propTypes.string,
fixedHeight: propTypes.bool,
},
setup(props, { slots }) {
const headerRef = ref<ComponentRef>(null);
......@@ -73,15 +84,17 @@
const getContentStyle = computed(
(): CSSProperties => {
const { contentBackground, contentFullHeight, contentStyle } = props;
const { contentBackground, contentFullHeight, contentStyle, fixedHeight } = props;
const bg = contentBackground ? { backgroundColor: '#fff' } : {};
if (!contentFullHeight) {
return { ...bg, ...contentStyle };
}
const height = `${unref(pageHeight)}px`;
return {
...bg,
...contentStyle,
minHeight: `${unref(pageHeight)}px`,
minHeight: height,
...(fixedHeight ? { height } : {}),
paddingBottom: `${unref(footerHeight)}px`,
};
}
......@@ -137,18 +150,11 @@
position: relative;
.ant-page-header {
// padding: 12px 16px;
&:empty {
padding: 0;
}
}
&-content {
// padding: 12px;
margin: 16px;
}
&--dense {
.@{prefix-cls}-content {
margin: 0;
......
......@@ -3,6 +3,7 @@
ref="wrapRef"
:class="[
prefixCls,
$attrs.class,
{
[`${prefixCls}-form-container`]: getBindValues.useSearchForm,
[`${prefixCls}--inset`]: getBindValues.inset,
......@@ -211,6 +212,8 @@
propsData = omit(propsData, 'scroll');
}
propsData = omit(propsData, 'class');
return propsData;
});
......
......@@ -55,6 +55,7 @@ export function useTableScroll(
// No need to repeat queries
let paginationEl: HTMLElement | null;
let footerEl: HTMLElement | null;
let bodyEl: HTMLElement | null;
async function calcTableHeight() {
const { resizeHeightOffset, pagination, maxHeight } = unref(propsRef);
......@@ -68,6 +69,7 @@ export function useTableScroll(
if (!tableEl) return;
const headEl = tableEl.querySelector('.ant-table-thead ');
if (!headEl) return;
// Table height from bottom
......@@ -117,6 +119,11 @@ export function useTableScroll(
height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
setHeight(height);
if (!bodyEl) {
bodyEl = tableEl.querySelector('.ant-table-body');
}
bodyEl!.style.height = `${height}px`;
}
useWindowSizeFn(calcTableHeight, 200);
......
......@@ -4,12 +4,11 @@
.@{prefix-cls} {
&-form-container {
width: 100%;
padding: 16px;
.ant-form {
padding: 16px 16px 6px 12px;
margin-bottom: 18px;
padding: 12px 10px 6px 10px;
margin-bottom: 16px;
background: #fff;
border-radius: 4px;
}
......@@ -74,40 +73,6 @@
}
}
// .ant-table-bordered .ant-table-header > table,
// .ant-table-bordered .ant-table-body > table,
// .ant-table-bordered .ant-table-fixed-left table,
// .ant-table-bordered .ant-table-fixed-right table {
// border: 1px solid @border-color !important;
// }
// .ant-table-thead {
// tr {
// border: none;
// }
// th {
// border: none;
// }
// }
// .ant-table-bordered .ant-table-tbody > tr > td {
// border-bottom: 1px solid @border-color !important;
// &:last-child {
// border-right: none !important;
// }
// }
// .ant-table.ant-table-bordered .ant-table-footer,
// .ant-table.ant-table-bordered .ant-table-title {
// border: 1px solid @border-color !important;
// }
// .ant-table-bordered.ant-table-empty .ant-table-placeholder {
// border: 1px solid @border-color !important;
// }
.ant-table-tbody > tr > td,
.ant-table-tbody > tr > th,
.ant-table-thead > tr > td,
......@@ -115,62 +80,10 @@
white-space: pre;
}
// .ant-table-row-cell-last {
// border-right: none !important;
// }
// .ant-table-bordered .ant-table-thead > tr > th,
// .ant-table-bordered .ant-table-tbody > tr > td {
// border-right: 1px solid @border-color !important;
// }
.ant-pagination {
margin: 10px 0 0 0;
}
// .ant-table-body {
// overflow-x: auto !important;
// overflow-y: scroll !important;
// }
// .ant-table-header {
// margin-bottom: 0 !important;
// overflow-x: hidden !important;
// overflow-y: scroll !important;
// }
// .ant-table-fixed-right {
// right: -1px;
// .ant-table-header {
// border-left: 1px solid @border-color !important;
// .ant-table-fixed {
// border-bottom: none;
// .ant-table-thead th {
// background: rgb(241, 243, 244);
// }
// }
// }
// }
// .ant-table-fixed-left {
// .ant-table-header {
// overflow-y: hidden !important;
// }
// .ant-table-fixed {
// border-bottom: none;
// }
// }
// .ant-table-bordered .ant-table-thead > tr:not(:last-child) > th,
// .ant-table-tbody > tr > td {
// word-break: break-word;
// // border-color: @border-color !important;
// }
.ant-table-footer {
padding: 0;
......
<script lang="tsx">
import type { ReplaceFields, Keys, CheckKeys, TreeActionType, TreeItem } from './types';
import { defineComponent, reactive, computed, unref, ref, watchEffect, toRaw, watch } from 'vue';
import { Tree } from 'ant-design-vue';
import {
defineComponent,
reactive,
computed,
unref,
ref,
watchEffect,
toRaw,
watch,
CSSProperties,
} from 'vue';
import { Tree, Empty } from 'ant-design-vue';
import { TreeIcon } from './TreeIcon';
import TreeHeader from './TreeHeader.vue';
import { ScrollContainer } from '/@/components/Container';
// import { DownOutlined } from '@ant-design/icons-vue';
import { omit, get } from 'lodash-es';
......@@ -95,6 +106,11 @@
emit('update:value', rawVal);
},
onRightClick: handleRightClick,
// onSelect: (k, e) => {
// setTimeout(() => {
// emit('select', k, e);
// }, 16);
// },
};
propsData = omit(propsData, 'treeData', 'class');
return propsData;
......@@ -104,6 +120,10 @@
searchState.startSearch ? searchState.searchData : unref(treeDataRef)
);
const getNotFound = computed((): boolean => {
return searchState.startSearch && searchState.searchData?.length === 0;
});
const {
deleteNodeByKey,
insertNodeByKey,
......@@ -178,10 +198,10 @@
return;
}
searchState.startSearch = true;
const { title: titleField } = unref(getReplaceFields);
searchState.searchData = filter(unref(treeDataRef), (node) => {
const { title } = node;
return title?.includes(searchValue) ?? false;
return node[titleField]?.includes(searchValue) ?? false;
});
}
......@@ -284,7 +304,7 @@
title: () => (
<span
class={`${prefixCls}-title pl-2`}
onClick={handleClickNode.bind(null, item.key, children)}
onClick={handleClickNode.bind(null, item[keyField], item[childrenField])}
>
{icon && <TreeIcon icon={icon} />}
<span
......@@ -304,9 +324,11 @@
}
return () => {
const { title, helpMessage, toolbar, search } = props;
const showTitle = title || toolbar || search;
const scrollStyle: CSSProperties = { height: 'calc(100% - 38px)' };
return (
<div class={[prefixCls, 'h-full bg-white', attrs.class]}>
{(title || toolbar || search) && (
{showTitle && (
<TreeHeader
checkAll={checkAll}
expandAll={expandAll}
......@@ -318,13 +340,17 @@
onSearch={handleSearch}
/>
)}
<Tree {...unref(getBindValues)} showIcon={false}>
{{
// switcherIcon: () => <DownOutlined />,
default: () => renderTreeNode({ data: unref(getTreeData), level: 1 }),
...extendSlots(slots),
}}
</Tree>
<ScrollContainer style={scrollStyle} v-show={!unref(getNotFound)}>
<Tree {...unref(getBindValues)} showIcon={false}>
{{
// switcherIcon: () => <DownOutlined />,
default: () => renderTreeNode({ data: unref(getTreeData), level: 1 }),
...extendSlots(slots),
}}
</Tree>
</ScrollContainer>
<Empty v-show={unref(getNotFound)} class="!mt-4" />
</div>
);
};
......
<template>
<div class="bg-white m-4 mr-0 overflow-hidden">
<BasicTree
title="部门列表"
toolbar
search
:clickRowToExpand="false"
:treeData="treeData"
:replaceFields="{ key: 'id', title: 'deptName' }"
@select="handleSelect"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import { BasicTree, TreeItem } from '/@/components/Tree';
import { getDeptList } from '/@/api/demo/system';
export default defineComponent({
name: 'DeptTree',
components: { BasicTree },
emits: ['select'],
setup(_, { emit }) {
const treeData = ref<TreeItem[]>([]);
async function fetch() {
treeData.value = ((await getDeptList()) as unknown) as TreeItem[];
}
function handleSelect(keys: string, e) {
emit('select', keys[0]);
console.log(keys, e);
}
onMounted(() => {
fetch();
});
return { treeData, handleSelect };
},
});
</script>
<template>
<div :class="[prefixCls]">
<BasicTable @register="registerTable">
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<DeptTree class="w-1/4 xl:w-1/5" @select="handleSelect" />
<BasicTable @register="registerTable" class="w-3/4 xl:w-4/5">
<template #toolbar>
<a-button type="primary" @click="handleCreate"> 新增账号 </a-button>
</template>
......@@ -24,14 +25,15 @@
</template>
</BasicTable>
<AccountModal @register="registerModal" @success="handleSuccess" />
</div>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { getAccountList } from '/@/api/demo/system';
import { PageWrapper } from '/@/components/Page';
import DeptTree from './DeptTree.vue';
import { useModal } from '/@/components/Modal';
import AccountModal from './AccountModal.vue';
......@@ -40,10 +42,8 @@
export default defineComponent({
name: 'AccountManagement',
components: { BasicTable, AccountModal, TableAction },
components: { BasicTable, PageWrapper, DeptTree, AccountModal, TableAction },
setup() {
const { prefixCls } = useDesign('account-management');
const [registerModal, { openModal }] = useModal();
const [registerTable, { reload }] = useTable({
title: '账号列表',
......@@ -86,22 +86,19 @@
reload();
}
function handleSelect(deptId: string = '') {
reload({ searchInfo: { deptId } });
}
return {
prefixCls,
registerTable,
registerModal,
handleCreate,
handleEdit,
handleDelete,
handleSuccess,
handleSelect,
};
},
});
</script>
<style lang="less" scoped>
@prefix-cls: ~'@{namespace}-account-management';
.@{prefix-cls} {
display: flex;
}
</style>
......@@ -3662,10 +3662,10 @@ es-module-lexer@^0.3.26:
resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b"
integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==
es-module-lexer@^0.4.0:
version "0.4.0"
resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.0.tgz#21f4181cc8b7eee06855f1c59e6087c7bc4f77b0"
integrity sha512-iuEGihqqhKWFgh72Q/Jtch7V2t/ft8w8IPP2aEN8ArYKO+IWyo6hsi96hCdgyeEDQIV3InhYQ9BlwUFPGXrbEQ==
es-module-lexer@^0.4.1:
version "0.4.1"
resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e"
integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==
es-to-primitive@^1.2.1:
version "1.2.1"
......@@ -9120,15 +9120,15 @@ vite-plugin-pwa@^0.5.6:
pretty-bytes "^5.6.0"
workbox-build "^6.1.1"
vite-plugin-style-import@^0.7.6:
version "0.7.6"
resolved "https://registry.npmjs.org/vite-plugin-style-import/-/vite-plugin-style-import-0.7.6.tgz#909a5402f3a915fb2512e2a039e9cdb360fd2882"
integrity sha512-EDjscCzMsmi6mJ0UbMLMkCGLo7LCdFsRJZdjO7sfUIB+2wsC1FjDJcIEGWg0Lzl+4gghv9rk+AP+WCibI83WNw==
vite-plugin-style-import@^0.8.1:
version "0.8.1"
resolved "https://registry.npmjs.org/vite-plugin-style-import/-/vite-plugin-style-import-0.8.1.tgz#e098c633cba3abef9b5a156aaf47f001567ebbb9"
integrity sha512-qZg73SA2+tbuEk7b0VjubjceUKVzHB6NwDYd3R9Hd6At4+sJ/85UIlTkzxSWHNgkTQh4sIOMQi1olXjkSF7tjg==
dependencies:
"@rollup/pluginutils" "^4.1.0"
change-case "^4.1.2"
debug "^4.3.2"
es-module-lexer "^0.4.0"
es-module-lexer "^0.4.1"
magic-string "^0.25.7"
vite-plugin-svg-icons@^0.2.1:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册