Fat Table
FatTable
用于快速创建一个表格页面。
1. 快速创建一个表格页面
查看代码
import { defineFatTable } from '@wakeadmin/components';
import { ElButton } from 'element-plus';
enum ItemStatus {
Initial,
Pending,
Done,
}
/**
* 列表项定义
*/
interface Item {
id: number;
name: string;
status: ItemStatus;
createdDate: number;
}
/**
* 表单查询
*/
interface Query {
name: string;
status: ItemStatus;
}
export default defineFatTable<Item, Query>(({ column }) => {
return () => ({
title: 'Hello',
rowKey: 'id',
async request(params) {
const { pagination, query } = params;
// 模拟请求
const mockData: Item[] = new Array(pagination.pageSize).fill(0).map((_, idx) => {
const r = Math.floor(Math.random() * 1000);
return {
id: idx,
name: `${r}-${pagination.page}-${query?.name ?? ''}`,
status: r % 3 === 0 ? ItemStatus.Pending : r % 2 === 0 ? ItemStatus.Initial : ItemStatus.Done,
createdDate: Date.now(),
};
});
return {
list: mockData,
total: 100,
};
},
renderNavBar() {
return (
<span>
<ElButton type="primary">创建</ElButton>
</span>
);
},
columns: [
column({
prop: 'name',
label: '名称',
queryable: true,
valueType: 'search',
}),
column({
prop: 'status',
label: '状态',
queryable: true,
valueType: 'select',
valueProps: {
options: [
{ label: '未开始', value: ItemStatus.Initial, color: 'blue' },
{ label: '正在进行', value: ItemStatus.Pending, color: 'green' },
{ label: '已结束', value: ItemStatus.Done, color: 'gray' },
],
},
}),
column({
prop: 'createdDate',
label: '创建时间',
valueType: 'date-time',
}),
column({
type: 'actions',
label: '操作',
actions: (table, row) => {
const ended = row.status === ItemStatus.Done;
const pending = row.status === ItemStatus.Pending;
return [
{
name: pending ? '结束' : '开始',
visible: !ended,
},
{
name: '删除',
type: 'danger',
onClick: () => table.remove(row),
},
];
},
}),
],
});
});
2. defineFatTable(推荐)
我们推荐使用 defineFatTable
+ TSX
来快速定义一个表格组件,使用 defineFatTable 可以获取到更好的智能提示和类型检查。
defineFatTable
大致用法如下:
interface T {
// 列表项类型声明
}
interface Q {
// 表单查询类型声明
}
export const MyTable = defineFatTable<T, Q>(({ table, column }) => {
// 和 vue 的 setup 方法一样, 这里可以放置 Vue Composition API
const someRef = ref(0);
const someMethod = () => {};
// 返回 FatTable props
return () => ({
// 列表请求
async request(params) {
// ...
},
// 列定义
columns: [
// ...
],
// ... 其他 FatTable props
});
});
defineFatTable 类似于 Vue 的 defineComponent, 支持放置 Vue Hooks,只不过要求返回的是 FatTable 的 props 定义。
同样的功能使用 template 来写, 会丢失上下文信息(vue 组件不支持泛型
):
<template>
<FatTable :request="request" :columns="columns" ref="tableRef"> </FatTable>
</template>
<script setup>
import { ref } from 'vue';
import { FatTable, useFatTableRef } from '@wakeadmin/components';
const someRef = ref(0);
const someMethod = () => {};
const tableRef = useFatTableRef();
const request = async () => {
// ...
};
const columns = [
/* ... */
];
</script>
显然 defineFatTable 可以让你更关注 FatTable 本身的配置。
3. 原件
原件是 FatTable 的’原子‘组成单位,表格的单元格、查询表单都使用原件进行声明。
我们的组件库针对常用的场景内置了很多原件,如果这些原件不能满足你的需求,我们也支持传入自定义原件。
单元格中默认使用的是原件的预览形态
, 而查询表单中使用的是编辑形态
。 以下是部分原件的使用示例:
查看代码
import { defineFatTable } from '@wakeadmin/components';
export default defineFatTable(({ column }) => {
return () => ({
title: '原件示例',
async request() {
return {
total: 1,
list: [
{
text: '文本, 默认原件',
status: 0,
date: Date.now(),
progress: 50,
currency: 1024,
image:
'https://images.unsplash.com/photo-1663774026607-6836c94f93e6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=927&q=80',
},
],
};
},
enablePagination: false,
columns: [
column({
prop: 'text',
label: '文本',
// 同时作为查询表单,
queryable: true,
valueProps: { placeholder: '搜索关键字' },
}),
column({
prop: 'status',
label: '下拉列表',
queryable: true,
valueType: 'select',
valueProps: {
colorMode: 'dot',
options: [
{ label: '选项1', value: 0, color: 'red' },
{ label: '选项2', value: 1, color: 'blue' },
],
},
}),
column({
prop: 'date',
label: '时间',
queryable: true,
valueType: 'date',
}),
column({
prop: 'progress',
label: '进度',
valueType: 'progress',
}),
column({ prop: 'currency', label: '货币', valueType: 'currency' }),
column({ prop: 'image', label: '图片', valueType: 'image' }),
],
});
});
4. 表单查询
大部分场景下,查询表单字段
和表格列
是匹配的,换句话说,表单筛选是针对表格的列进行的:
基于这个前提,我们可以利用原件的预览态
和编辑态
来快速开发表单页面。比如上图,columns 代码如下:
[
column({ prop: 'name', name: '旅程名称', queryable: true }), // 🔴 queryable 表示该列同时作为查询字段
column({ prop: 'enterUserNumber', name: '进入人数' }),
column({ prop: 'enterNumber', name: '进入次数' }),
column({
prop: 'type',
name: '旅程类型',
valueType: 'select',
valueProps: { options: [{ label: '实时触发', value: 0 } /*...*/] },
order: 100, // 🔴 可以使用 order 调整查询表单的顺序,默认为 1000, 值越小,越靠前
}),
column({
prop: 'status',
name: '旅程状态',
valueType: 'select',
valueProps: { options: [{ label: '草稿', value: 0, color: 'red' } /*...*/] },
}),
column({
prop: 'updateTime',
name: '更新时间',
}),
column({
prop: 'createTime',
name: '创建时间',
valueType: 'date-time-range',
valueProps: {
valueFormat: 'YYYY-MM-DD HH:mm:ss',
},
}),
column({
type: 'actions',
actions: [
/*...*/
],
}),
column({
type: 'query', // 🔴 只作为查询表单,不作为表格列
valueType: 'checkbox',
valueProps: {
label: '预警旅程',
},
}),
];
TIP
FatTable
的表单底层使用 FatForm
渲染,你可以通过 formProps
深入定义它的行为,比如修改提交按钮文案等等.
5. 操作按钮
FatTable 中通过 actions 来定义表格的操作:
查看代码
import { defineFatTable } from '@wakeadmin/components';
import { reactive } from 'vue';
import ActionsForm from './ActionsForm';
export default defineFatTable(() => {
const initialValue = reactive({
disableDelete: false,
editable: true,
});
return () => ({
title: '表格操作',
async request() {
return { list: [{ id: 0 }], total: 1 };
},
renderAfterForm() {
return <ActionsForm initialValue={initialValue} />;
},
enablePagination: false,
rowKey: 'id',
async remove(list) {
// 在这里进行表格删除数据请求
},
columns: [
{
type: 'actions',
label: '操作',
// 支持传入一个函数,常用于一些需要动态计算的场景
actions: () => {
return [
{
name: '标题',
title: '提示信息',
},
{
name: '危险',
type: 'danger',
},
{
name: '警告',
type: 'warning',
confirm: '可以设置确认信息',
onClick: () => {
console.log('点击了警告操作');
},
},
{
name: '删除',
type: 'danger',
// 禁用
disabled: initialValue.disableDelete,
// FatTable 内置了删除功能
onClick: (table, row) => {
table.remove(row);
},
},
{
name: '编辑',
// 支持 vue router
visible: initialValue.editable,
link: { name: 'someRoute', query: { id: 'someId' } },
},
];
},
},
{
type: 'actions',
label: '按钮操作',
actionsType: 'button',
actions: () => {
return [{ name: '快乐' }, { name: '星球' }];
},
},
{
type: 'actions',
label: '无操作',
actions: [],
},
],
});
});
6. 批量操作按钮 / 表格设置
和操作按钮类似, FatTable 也支持快速创建批量操作按钮:
查看代码
import { defineFatTable } from '@wakeadmin/components';
import { reactive } from 'vue';
import ActionsForm from './ActionsForm';
export default defineFatTable(() => {
const initialValue = reactive({
disableDelete: false,
editable: true,
});
return () => ({
title: '表格操作',
async request() {
return {
list: new Array(10).fill(0).map((_, idx) => {
return { id: idx };
}),
total: 10,
};
},
rowKey: 'id',
async remove(list) {
// 在这里进行表格删除数据请求
},
enableSelect: true,
batchActions: table => [
{
name: '删除',
onClick: table.removeSelected,
},
{
name: '导出',
confirm: '确认导出',
onClick: () => console.log('导出操作'),
},
],
columns: [
{
label: '快乐',
prop: 'id',
},
],
});
});
表格设置
查看代码
import { defineFatTable } from '@wakeadmin/components';
import { reactive } from 'vue';
export default defineFatTable(({ column }) => {
const initialValue = reactive({
disableDelete: false,
editable: true,
});
return () => ({
title: '表格设置',
async request() {
return {
list: new Array(10).fill(0).map((_, idx) => {
return { id: idx, name: `name-${idx}` };
}),
total: 10,
};
},
rowKey: 'id',
async remove(list) {
// 在这里进行表格删除数据请求
},
enableSelect: true,
enableSetting: true,
settingProps: {
persistentKey: 'hello-world',
},
renderToolbar() {
return <div style={{ marginRight: '10px' }}>custom toolbar</div>;
},
batchActions: table => [
{
name: '删除',
onClick: table.removeSelected,
},
{
name: '导出',
confirm: '确认导出',
onClick: () => console.log('导出操作'),
},
],
columns: [
column({
queryable: true,
label: 'ID',
prop: 'id',
}),
column({
label: '名称',
prop: 'name',
}),
column({
label: '创建时间',
prop: 'createdAt',
}),
column({
type: 'query',
prop: 'start',
// 关联到 createdAt 字段的设置
columnKey: 'createdAt',
label: '开始时间',
valueType: 'date',
}),
column({
type: 'query',
prop: 'end',
// 关联到 createdAt 字段的设置
columnKey: 'createdAt',
label: '结束时间',
valueType: 'date',
}),
// 不受控制
column({
type: 'query',
prop: 'fake',
label: '额外请求条件',
}),
column({
type: 'actions',
label: '操作',
actions: [
{
name: '编辑',
},
],
}),
],
});
});
7. 插槽
FatTable 提供了丰富的插槽,用于满足复杂的自定义需求:
上图,红色矩形部分为 FatTable 提供的插槽。 插槽渲染有两种使用方式:
- 在 Vue template 里面使用, 例如
<template>
<FatTable>
<template #toolbar>
<el-button>删除</el-button>
</template>
</FatTable>
</template>
- 使用
render*
方法。使用 defineFatTable 时,用这种方式比较合适:
defineFatTable({
renderToolbar() {
return <ElButton>删除</ElButton>;
},
});
示例:
查看代码
import { ElButton } from 'element-plus';
import { defineFatTable } from '@wakeadmin/components';
export default defineFatTable(() => {
return () => ({
title: '表格插槽',
async request() {
return {
list: new Array(10).fill(0).map((_, idx) => {
return { id: idx };
}),
total: 10,
};
},
renderToolbar() {
return (
<div>
<ElButton>批量操作</ElButton>
<ElButton>批量操作</ElButton>
</div>
);
},
renderBottomToolbar() {
return (
<div>
<ElButton>批量操作</ElButton>
<ElButton>批量操作</ElButton>
</div>
);
},
columns: [
{
label: '快乐',
prop: 'id',
},
],
});
});
8. 自定义布局
FatTable 默认使用惟客云 UI 规范的布局。你也可以 layout
属性自定义布局,布局协议如下:
export type FatTableLayout = (slots: {
/**
* 根节点属性
*/
rootProps: { class?: ClassValue; style?: StyleValue; [key: string]: unknown };
/**
* 自定义布局参数
*/
layoutProps: any;
/**
* 渲染标题栏
*/
renderTitle?: () => any;
/**
* 渲染导航栏
*/
renderNavBar?: () => any;
/**
* 渲染查询表单
*/
renderQuery?: () => any;
/**
* 渲染错误提示
*/
renderError?: () => any;
/**
* 渲染工具栏
*/
renderToolbar?: () => any;
/**
* 渲染表格
*/
renderTable?: () => any;
/**
* 渲染底部工具栏
*/
renderBottomToolbar?: () => any;
/**
* 渲染分页
*/
renderPagination?: () => any;
}) => VNodeChild;
默认实现:
const DefaultLayout: FatTableLayout = props => {
return (
<FatContainer
{...props.rootProps}
{...props.layoutProps}
class={normalizeClassName(props.rootProps.class, 'fat-table', 'fat-table--default')}
v-slots={{ title: props.renderTitle, extra: props.renderNavBar, query: props.renderQuery }}
>
<div class="fat-table__body">
{!!props.renderError && <div class="fat-table__error">{props.renderError()}</div>}
{!!props.renderToolbar && <div class="fat-table__toolbar">{props.renderToolbar()}</div>}
<div class="fat-table__table">{props.renderTable?.()}</div>
</div>
<div class="fat-table__footer">
{!!props.renderBottomToolbar && <div class="fat-table__bottom-toolbar">{props.renderBottomToolbar()}</div>}
{!!props.renderPagination && <div class="fat-table__pagination">{props.renderPagination()}</div>}
</div>
</FatContainer>
);
};
TIP
当插槽不存在时会传入 undefined
,你可以根据这个决定要不要渲染包裹器
WARNING
默认布局使用的是 FatContainer, 在惟客云微前端底座下,FatContainer 默认复用基座提供的 wkc-header
。如果要关闭这个行为,可以通过 layoutProps#reuseBayIfNeed
关闭掉
TIP
可以配合 FatConfigurableProvider
实现全局配置。
9. API
9.1 FatTable 属性
9.2 FatTable 事件
9.3 FatTable 实例方法
FatTable
实例方式获取有两种方式:
defineFatTable
函数参数 table 属性中获取:tsdefineFatTable(({ table }) => {});
<template>
中,使用useFatTableRef
:vue<template> <FatTable ref="tableRef">...</FatTable> </template> <script setup lang="tsx"> import { FatTable, useFatTableRef } from '@wakeadmin/components'; const tableRef = useFatTableRef(); </script>