# CloudTable 表格
基于 VTable (opens new window) 的高性能企业级表格组件,支持大数据量渲染、单元格编辑、导入导出、拖拽排序、分页等功能。
# 何时使用
- 需要展示大量结构化数据时(支持 2000 行 × 50 列)
- 需要单元格级别的编辑功能时
- 需要子表数据的导入导出时
- 需要行拖拽排序时
# 代码演示
下方示例展示了 500 条 mock 数据 的可编辑表格,包含文本、下拉选择、数字、日期、开关等全部编辑器类型。
# API
# Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| records | 表格数据 | any[] | [] |
| columns | 列配置(可由 serializeColumn 生成或手动构建) | VTableColumn[] | [] |
| options | 表格配置 | VTableOptions | - |
| loading | 加载状态 | boolean | false |
# VTableOptions
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| mode | 模式 | 'edit' \| 'view' | 'view' |
| showTotal | 是否显示汇总行 | boolean | false |
| showPageNation | 是否启用分页 | boolean | false |
| defaultPageSize | 每页行数 | number | 50 |
| defaultRows | 默认行数 | string | - |
| enableRowDrag | 是否启用行拖拽 | boolean | false |
| workItemId | 工作项 ID | string | - |
| bizObject | 业务对象数据 | any | - |
| bizSheet | 业务表单数据 | any | - |
| permiss | 权限配置 | any | - |
| buttonPermiss | 按钮权限 | any | - |
| subSheetKey | 子表字段编码 | string | - |
| importFormRelevanceForm | 关联表单导入配置 | string | - |
| statistics | 统计列配置 | any[] | - |
# VTableColumn
| 参数 | 说明 | 类型 |
|---|---|---|
| field | 字段编码 | string |
| title | 列标题 | string |
| width | 列宽度 | number |
| fieldType | 表单控件类型 | FormControlType |
| editable | 是否可编辑 | boolean |
| editor | 编辑器标识(唯一 ID) | string |
| editorType | 编辑器类型 | CustomEditorType |
| editorOptions | 编辑器选项 | object |
# 手动构建可编辑列
除了通过 serializeColumn 从表单配置自动生成列之外,你也可以手动构建列配置:
const columns = [
{
field: 'name', title: '姓名', width: 120,
editable: true,
editorType: 'text',
editor: 'text-name', // 必须唯一
},
{
field: 'department', title: '部门', width: 120,
editable: true,
editorType: 'select',
editor: 'select-department',
editorOptions: {
option: {
optionsSet: {
optionsType: 'custom', // 'custom' | 'dictionary' | 'businessModel'
custom: [
{ code: '技术部', value: '技术部' },
{ code: '产品部', value: '产品部' },
],
},
},
},
},
{
field: 'salary', title: '薪资', width: 120,
editable: true,
editorType: 'number',
editor: 'number-salary',
editorOptions: { option: { format: 'number' } },
},
{
field: 'joinDate', title: '入职日期', width: 140,
editable: true,
editorType: 'date',
editor: 'date-joinDate',
editorOptions: { option: { format: 'YYYY-MM-DD' } },
},
{
field: 'active', title: '在职', width: 80,
editable: true,
editorType: 'switch',
editor: 'switch-active',
},
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 云枢子表集成(sheetMode)
CloudTable 在云枢产品中作为子表的高性能渲染引擎使用。通过子表控件的 sheetMode 属性来切换传统子表与 CloudTable 表格模式。
接入 CloudTable 子表总共需要修改 3 个位置:
# 第 1 步:修改子表控件入口
文件路径:cloudpivot-form/form/src/components/Sheet/index.ts
将子表 PC 端的组件入口指向新的 index.vue(内含模式切换逻辑):
export default {
// ...
components: {
pc: () => import('./components/index.vue'), // 新入口,支持 sheetMode 切换
// pc: () => import('./components/pc-sheet.vue'), // 旧入口,仅传统子表
mobile: () => import('./components/mobile-sheet/mobile-sheet.vue'),
},
} as any;
2
3
4
5
6
7
8
# 第 2 步:子表模式切换组件(index.vue)
文件路径:cloudpivot-form/form/src/components/Sheet/components/index.vue
CloudSheet 组件根据 control.options.sheetMode 的值动态切换渲染组件:
sheetMode = 'default'— 使用传统子表PcSheetsheetMode = 'grid'— 使用 CloudTable 高性能表格CloudTableSheet
<template>
<div class="cloud-table-wrapper">
<component
:is="currentComponent"
v-bind="componentProps"
v-on="componentEvents"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import PcSheet from './pc-sheet.vue';
import CloudTableSheet from './cloud-table-sheet.vue';
export default defineComponent({
name: 'CloudSheet',
components: { CloudTableSheet, PcSheet },
props: {
frozenKeys: { type: Array, default: () => [] },
isFullScreen: { type: Boolean, default: false },
canFull: { type: Boolean, default: false },
formPermission: { type: Object, default: () => ({}) },
control: { type: Object, default: () => ({}) },
},
setup(props, { emit, attrs, listeners }) {
const sheetMode = computed(
() => props.control?.options?.sheetMode || 'default',
);
// sheetMode 为 'grid' 时使用 CloudTableSheet,否则使用传统 PcSheet
const currentComponent = computed(() => {
return sheetMode.value === 'grid' ? 'CloudTableSheet' : 'PcSheet';
});
const componentProps = computed(() => ({ ...props, ...attrs }));
const componentEvents = computed(() => ({ ...listeners }));
return { sheetMode, currentComponent, componentProps, componentEvents };
},
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 第 3 步:CloudTableSheet 子表封装(cloud-table-sheet.vue)
文件路径:cloudpivot-form/form/src/components/Sheet/components/cloud-table-sheet.vue
CloudTableSheet 是 CloudTable 在云枢子表中的完整封装,包含权限过滤、列序列化、数据变更通知等逻辑:
<template>
<div class="cloud-table-sheet-wrapper">
<a-collapse :activeKey="activeKey" :bordered="false" @change="handleCollapseChange">
<a-collapse-panel key="sheetPanel" :showArrow="false">
<template #header>
<span class="sheet-name-wrapper">
{{ sheetName }}
<a-icon :type="activeKey === 'sheetPanel' ? 'down' : 'right'" />
</span>
</template>
<CloudTable
v-if="isLoaded"
:options="tableOptions"
:columns="columns"
:records="data"
@change="handleSheetChange"
/>
</a-collapse-panel>
</a-collapse>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed, onMounted, inject } from 'vue';
import {
CloudTable,
VTableOptions,
filterColumnByPermiss,
serializeColumn,
VTableColumn,
} from '@h3/cloudpivot-nexus-ui/dist/es/index';
export default defineComponent({
name: 'CloudTableSheet',
props: {
formPermission: { type: Object, default: () => ({}) },
control: { type: Object, default: () => ({}) },
},
setup(props, { emit }) {
const handleSheetControlChange = inject('handleSheetControlChange', null);
const isLoaded = ref(false);
const data = ref([]);
const columns = ref([]);
const tableOptions = ref({
mode: 'view',
enableRowDrag: true,
showTotal: false,
defaultPageSize: 10,
showPageNation: false,
// ...其他业务配置
});
const initColumns = async () => {
const permiss = props.formPermission?.dataPermissions?.[props.control.key];
const columnList = filterColumnByPermiss(props.control?.columns, permiss);
columns.value = serializeColumn(columnList || [], props.control?.key, /* ... */);
};
const initData = async (editable) => {
data.value = props.control?.value || [];
handleSheetControlChange?.(props.control.key, data.value, [], []);
};
const handleSheetChange = (newData, deleteRows, sortedData) => {
data.value = newData;
handleSheetControlChange?.(props.control.key, newData, deleteRows, sortedData);
};
onMounted(async () => {
// 初始化配置 → 初始化数据 → 初始化列
await initData(/* editable */);
await initColumns();
isLoaded.value = true;
});
return { tableOptions, columns, data, isLoaded, handleSheetChange };
},
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 关键工具函数
| 函数 | 说明 | 引入路径 |
|---|---|---|
serializeColumn | 将表单列配置序列化为 VTable 列配置 | @h3/cloudpivot-nexus-ui/dist/es/index |
filterColumnByPermiss | 根据数据权限过滤可见列 | @h3/cloudpivot-nexus-ui/dist/es/index |
# 数据变更通知
子表数据发生变化时,通过 inject('handleSheetControlChange') 通知父级表单:
// 父级表单通过 provide 注入
provide('handleSheetControlChange', (key: string, value: any[], deleteRows: any[], sortedData: any[]) => {
// 处理子表数据变更
});
// CloudTableSheet 内部在数据变化时调用
handleSheetControlChange(props.control.key, newData, deleteRows, sortedData);
2
3
4
5
6
7
# 事件
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| change | 数据变化时回调 | (records, deletedRecords, sortedRecords) => void |
# 实例方法
通过 ref 获取组件实例后可调用:
| 方法名 | 说明 | 参数 |
|---|---|---|
| getAllRecords | 获取所有记录 | - |
| getDeletedRecords | 获取已删除记录 | - |
# 支持的编辑器类型
CloudTable 通过 CustomEditor 桥接层支持以下编辑器:
| 类型 | 组件 | 说明 |
|---|---|---|
text | Text | 单行文本 |
textarea | Textarea | 长文本 |
select | Select | 下拉选择 |
date | Date | 日期选择 |
time | Time | 时间选择 |
switch | Switch | 开关 |
radio | Radio | 单选 |
checkbox | Checkbox | 复选 |
number | Number | 数字输入 |
staff | StaffSelect | 人员选择 |
relevanceSelect | RelevanceSelect | 关联选择 |
← 快速开始 StaffSelect 员工选择 →