Skip to content
Return to top
On this page

# FatTableSelect #

`FatTableSelect` 是一个基于 `FatTable` 扩展的一个`Select Table`; 在使用上也基本类似，`FatTable`上能使用的基本上都可以在`FatTableSelect`上使用

## 1. 快速创建一个页面 #

查看代码
tsx

    import { defineFatTableSelect } 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 defineFatTableSelect<Item, Query, { name: string; id: number }>(({ column }) => {
      return () => ({
        title: '明月如霜',
        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,
          };
        },
        renderBottomToolbar(_, selectedList) {
          const item = selectedList[0];
          if (item) {
            return () => (
              <div>
                当前选中:
                <div>
                  名称 -{'>'} {item.name}
                </div>
                <div>
                  id -{'>'} {item.id}
                </div>
              </div>
            );
          }
        },
        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',
            minWidth: 110,
          }),
        ],
      });
    });

可以发现，在点击了选择之后，无论是点击搜索还是重置，我们的选择值都不会发生变化，这非常符合表格选择的逻辑，即选中的值跟当前表格所展示的数据并没有什么太多的关联

## 2. defineFatTableSelect（推荐） #

我们推荐使用 `defineFatTableSelect` + `TSX` 来快速定义一个表格组件，使用 `defineFatTableSelect` 可以获取到更好的智能提示和类型检查。

`defineFatTableSelect` 大致用法如下：

tsx

    interface Item {
      // 列表项类型声明
    }

    interface Query {
      // 表单查询类型声明
    }
    interface Selection {
      // 已选择项类型声明
    }

    export const MySelectTable = defineFatTableSelect<Item, Item, Selection>(({ table, column }) => {
      // 和 vue 的 setup 方法一样, 这里可以放置 Vue Composition API
      const someRef = ref(0);
      const someMethod = () => {};

      // 返回 FatTableSelect props
      return () => ({
        // 列表请求
        async request(params) {
          // ...
        },
        // 列定义
        columns: [
          // ...
        ],
        // 是否多选
        multiple: true,
        // 已选择的值
        value: [
          { name: '沙溪急', id: 229 },
          { name: '霜溪冷', id: 170 },
          { name: '月溪明', id: 155 },
        ],
        // ... 其他 FatTableSelect props
      });
    });

`defineFatTableSelect` 类似于 `defineFatTable`。

当然也可以用 `template` 来写, 会丢失上下文信息(vue 组件不支持`泛型`)。 其用法与`fatTable`基本一致，除此之外，因为`FatTableSelect`是表单项，因此也支持`v-model`语法。

## 3. 操作 #

默认情况下，`FatTableSelect`会有一些预定义场景:

1. 如果`multiple`为`true`的话，那么会自动开启`enableSelect`，并且会插入一个默认的`BottomToolbar`；
2. 如果`multiple`为`false`的话, 如果用户没有传入`action`列的话，那么会自动插入一条默认的`action`列;当然，我们也可以传入自定义的`action`来处理我们的操作逻辑。

WARNING

`FatTableSelect`会忽略用户传入的`enableSelect`。

即`enableSelect`跟`multiple`是强绑定的。

查看代码
tsx

    import { defineFatTableSelect } from '@wakeadmin/components';

    export default defineFatTableSelect<any, any, { name: string }>(() => {
      return () => ({
        title: '表格操作',
        async request() {
          return {
            list: new Array(10).fill('S').map((_, i) => ({
              name: `MentalHealth${i + 1}`,
              id: i,
            })),
            total: 10,
          };
        },
        renderBottomToolbar(_, selectedList) {
          const item = selectedList[0];
          if (item) {
            return () => (
              <div>
                当前选中:
                <div>
                  名称 -{'>'} {item.name}
                </div>
              </div>
            );
          }
        },
        enablePagination: false,

        rowKey: 'id',

        columns: [
          { label: '名称', prop: 'name' },
          {
            type: 'actions',
            label: '操作',
            // 支持传入一个函数，常用于一些需要动态计算的场景
            actions: () => {
              return [
                {
                  name: 'Are you Ready?',
                  title: '提示信息',
                },
                {
                  name: '我好了',
                  type: 'danger',
                  onClick(table, row) {
                    table.select(row);
                  },
                },
                {
                  name: '等一下，我还没好',
                  type: 'warning',
                  onClick(table, row) {
                    table.unselect(row);
                  },
                },
              ];
            },
          },
        ],
      });
    });

除此之外，我们也挺支持全选、反选。不仅如此，还可以传入一个`selectable`来处理该项是否允许选择。在多选情况下，我们也支持传入`limit`来限制用户的选择个数。

查看代码
tsx

    import { defineFatTableSelect } from '@wakeadmin/components';
    import { defineComponent, ref } from 'vue';
    import { ElButton } from 'element-plus';

    export default defineComponent({
      name: 'TableSelectDisabledActions',
      setup() {
        const multiple = ref(false);
        const Table = defineFatTableSelect<any, any, { name: string; id: number }>(({ column }) => {
          const list = [
            { name: '女曰鸡鸣', id: 51024 },
            { name: '士曰昧旦', id: 15629 },
            { name: '子兴视夜', id: 588 },
            { name: '明星有烂', id: 5836 },
            { name: '将翱将翔', id: 9170 },
            { name: '弋凫与雁', id: 51658 },
            { name: '弋言加之', id: 4416 },
            { name: '与子宜之', id: 69 },
            { name: '宜言饮酒', id: 51918 },
            { name: '与子偕老', id: 52751 },
            { name: '琴瑟在御', id: 11157 },
            { name: '莫不静好', id: 56022 },
          ];
          return () => ({
            title: '好风如水',
            rowKey: 'id',
            limit: 6,
            batchActions: table => [
              {
                name: '全选',
                onClick: () => table.selectAll(),
              },
              {
                name: '反选',
                onClick: () => table.toggleAll(),
              },
              {
                name: '取消全选',
                onClick: () => table.unselectAll(),
              },
              {
                name: '清空',
                onClick: () => table.clear(),
              },
            ],
            async request(params) {
              const {
                pagination: { page, pageSize },
              } = params;

              return {
                list: list.slice((page - 1) * pageSize, pageSize * page),
                total: list.length,
              };
            },

            selectable(item) {
              return item.id % 10 !== 9;
            },
            onChange(payload) {
              console.log(payload.values);
            },
            columns: [
              column({
                prop: 'name',
                label: '名称',
              }),
              column({
                prop: 'id',
                label: 'id',
              }),
            ],
          });
        });

        return () => {
          return (
            <div>
              <ElButton
                onClick={() => {
                  multiple.value = !multiple.value;
                }}
              >
                切换选择状态
              </ElButton>

              {multiple.value ? <Table key="s"></Table> : <Table key="m" multiple></Table>}
            </div>
          );
        };
      },
    });

WARNING

暴露出来的`selectAll`、`unSelectAll`、`toggleAll`都是针对于当前页面的数据，并且如果页面里的某条数据不允许操作，那么也不会对其进行处理。

但是`select`、`unSelect`这两个方法则没有过多的额外操作，传入什么就处理什么，不会关注于该条数据是否在当前页面里、是否禁用等

## 4. V-Model #

`FatTableSelect`的返回值跟传入的`value`值相关。对于传入的`value`值，我们约定其数据格式类型为`Selection`。`Selection`的定义如下

- 基础数据类型， 即 `string` 或者为`number`。 该模式下，`FatTableSelect`会直接返回对应的`rowKey`的值

- `Object`，且该`Object`必须为`Item`的子集。 该模式下， `FatTableSelect`会按照传入的数据格式返回对应的值

- `undefined`，该模式下，会直接返回整个`item`对象

查看代码
vue

    <template>
      <div>
        <Table0 v-model="value0"></Table0>
        <Table1 v-model="value1"></Table1>
        <Table2 v-model="value2"></Table2>
        <Table3 v-model="value3"></Table3>
      </div>
    </template>
    <script setup lang="ts">
      import { defineFatTableSelect } from '@wakeadmin/components';
      import { ref, effect } from 'vue';

      interface Item {
        name: string;
        id: number;
      }
      type Selection = Partial<Item> | number | string;

      function createTableSelect<T extends Selection>(title: string) {
        return defineFatTableSelect<Item, any, T>({
          title,
          rowKey: 'id',
          limit: 6,
          multiple: true,
          columns: [
            {
              prop: 'name',
              label: '名称',
            },
            {
              prop: 'id',
              label: 'id',
            },
          ],
          async request() {
            return {
              list: [
                { name: '女曰鸡鸣', id: 51024 },
                { name: '士曰昧旦', id: 15629 },
                { name: '子兴视夜', id: 588 },
                { name: '明星有烂', id: 5836 },
                { name: '将翱将翔', id: 9170 },
                { name: '弋凫与雁', id: 51658 },
                { name: '弋言加之', id: 4416 },
                { name: '与子宜之', id: 69 },
                { name: '宜言饮酒', id: 51918 },
                { name: '与子偕老', id: 52751 },
              ],
              total: 10,
            };
          },
        });
      }

      const Table0 = createTableSelect('传入的是undefined');
      const Table1 = createTableSelect<string>('传入的是基本数据类型');
      const Table2 = createTableSelect<{ id: number }>('传入一个单独的id对象');
      const Table3 = createTableSelect<{ id: number; name: string }>('传入其他的对象');

      const value0 = ref([]);
      const value1 = ref([51024]);
      const value2 = ref([{ id: 51024 }]);
      const value3 = ref([{ id: 51024, name: '女曰鸡鸣' }]);

      effect(() => {
        console.log('Table0 ->', value0.value);
      });
      effect(() => {
        console.log('Table1 ->', value1.value);
      });
      effect(() => {
        console.log('Table2 ->', value2.value);
      });
      effect(() => {
        console.log('Table3 ->', value3.value);
      });
    </script>

可以打开控制台查看其具体的输出

## 5. 自定义布局 #

FatTableSelect 默认布局使用的是 FatContainer， 你也可以按照自己的需求实现自定义的布局。

## 6. 与`FatTable`的区别 #

1. 本质上 `FatTableSelect` 属于表单项， 与 `Select` 类似

2. 以下`props`将由`FatTableSelect`控制，不允许用户自定义

   - `enableSelect`
   - `selectable`
   - `onSelect`
   - `onLoad`

3. 不支持以下几个`FatTable`的`props`

- `enableCacheQuery`
- `onQueryCacheRestore`
- `confirmBeforeRemove`
- `messageOnRemoved`
- `messageOnRemoveFailed`
- `remove`
- `requestOnRemoved`
- `confirmBeforeRemove`
- `onSelect-all`

4. 默认情况下 会对`FatTableColumns`做一些处理

   - 如果`multiple`为`true`的话，那么会自动开启`enableSelect`，并且会插入一个默认的`BottomToolbar`；

   - 如果`multiple`为`false`的话, 如果用户没有传入`action`列的话，那么会自动插入一条默认的`action`列;当然，我们也可以传入自定义的`action`来处理我们的操作逻辑。

5. 提供了一系列操作`API`

6. 对外暴露的对象中里没有以下属性

- `selected`

## 7. API #

### 7.1 FatTableSelect 属性 #

### 7.2 FatTableSelect 事件 #

### 7.3 FatTableSelect 实例方法 #

`FatTableSelect` 实例方式获取有两种方式：

1. `defineFatTableSelect` 函数参数 table 属性中获取：

   ts

       defineFatTableSelect(({ tableSelect }) => {});

2. `<template>` 中，使用 `useFatTableSelectRef`:

   vue

       <template>
         <FatTableSelect ref="tableRef">...</FatTableSelect>
       </template>

       <script setup lang="tsx">
         import { FatTableSelect, useFatTableSelectRef } from '@wakeadmin/components';

         const tableRef = useFatTableSelectRef();
       </script>

### 7.4 FatTableSelect 插槽 #

跟`FatTable`一致

### 7.5 列定义 #

跟`FatTable`一致