Files

2117 lines
36 KiB
Plaintext
Raw Permalink Normal View History

2025-11-24 23:24:06 +08:00
---
description: cl-table 组件示例
globs: *.tsx, *.ts, *.vue
---
## 起步 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>base</el-tag>
<span>起步</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/base.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="起步" width="80%">
<!--【很重要】需要包含在 cl-crud 组件内 -->
<cl-crud ref="Crud">
<cl-row>
<!-- 参数文档查看https://element-plus.org/zh-CN/component/table.html#table-%E5%B1%9E%E6%80%A7 -->
<cl-table ref="Table" stripe></cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
// 测试数据,移步到 cl-crud 例子查看
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
// 是否自动计算表格高度,表格高度等于减去上区域和下区域的高度
//【很重要】在弹窗或者上级不确定高度中,设置 autoHeight: false避免显示异常。也可以手动设置最大高度 maxHeight: 500
autoHeight: false,
// 右键菜单,移步到右键菜单示例中查看
contextMenu: ['refresh'],
// 列配置,点击 columns 查看描述
// 更多配置查看 el-table-column 文档https://element-plus.org/zh-CN/component/table.html#table-column-%E5%B1%9E%E6%80%A7
columns: [
{
// 是否为多选框操作列
type: 'selection'
// 是否为序号列
// type: "index"
},
{
// 表头标题
label: '姓名',
// 绑定值
prop: 'name',
// 最小宽度
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
// 字典匹配,移步到字典示例中查看
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
// 是否排序desc, asc
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 多级表头 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>children</el-tag>
<span>多级表头</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/children.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="多级表头" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '用户信息',
prop: 'baseInfo',
minWidth: 250,
// 配置 children 参数
children: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
}
]
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 自定义列展示 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>column-custom</el-tag>
<span>自定义列展示</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/column-custom.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="自定义列展示" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!--【很重要】组件配置,设置为 Table 的 columns也可以自定义 -->
<cl-column-custom :columns="Table?.columns" />
</cl-row>
<cl-row>
<cl-table ref="Table"></cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '状态',
prop: 'status',
dict: [
{
label: '启用',
value: 1,
type: 'success'
},
{
label: '禁用',
value: 0,
type: 'danger'
}
],
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 组件渲染 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>component</el-tag>
<span>组件渲染</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/component/index.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="组件渲染" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table"></cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { ElMessage } from 'element-plus';
import UserInfo from './user-info.vue';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
type: 'selection'
},
{
label: '姓名',
prop: 'name',
minWidth: 140,
//【很重要】组件实例方式渲染
component: {
vm: UserInfo
}
},
{
label: '手机号',
prop: 'phone',
minWidth: 140,
//【很重要】组件名方式渲染
component: {
// 组件名,组件必须全局注册了
name: 'el-input',
// 传入参数
props: {
onChange(val) {
ElMessage.info(val);
}
}
}
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## user-info 示例
```vue
<template>
<div class="user-info">
<cl-avatar :size="36" />
<div class="det">
<p>{{ scope?.name }}</p>
</div>
</div>
</template>
<!-- name 必须填写且唯一 -->
<script setup lang="ts">
defineOptions({
name: 'user-info'
});
const props = defineProps({
prop: String, // 列配置的 prop
scope: null // 列数据
});
</script>
<style lang="scss" scoped>
.user-info {
display: flex;
align-items: center;
.det {
flex: 1;
margin-left: 10px;
text-align: left;
}
}
</style>
```
## 右键菜单 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>context-menu</el-tag>
<span>右键菜单</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/context-menu.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="右键菜单">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table"></cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!-- 新增、编辑 -->
<cl-upsert ref="Upsert" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { ElMessage } from 'element-plus';
import { EditPen, MoreFilled } from '@element-plus/icons-vue';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
// 右键菜单配置,为 [] 时则不显示内容
contextMenu: [
'refresh', // 刷新
'check', // 选择行
'edit', // 弹出编辑框
'delete', // 弹出删除提示
'info', // 弹出详情
'order-desc', // 使列倒序
'order-asc', // 使列升序
{
label: '禁用状态',
disabled: true
},
{
label: '带图标',
prefixIcon: EditPen,
suffixIcon: MoreFilled
},
{
label: '超出隐藏,看我有很多字非常多',
ellipsis: true
},
{
label: '多层级',
children: [
{
label: 'A',
children: [
{
label: 'A-1',
callback(done) {
ElMessage.success('点击了A-1');
done();
}
}
]
},
{
label: 'B'
},
{
label: 'C'
}
]
},
// row 行数据
// column 列属性
// event 事件对象
(row, column, event) => {
// 必须返回一个对象
return {
label: '自定义2',
callback(done) {
ElMessage.info('获取中');
setTimeout(() => {
ElMessage.success('Ta 是' + row.name);
// 关闭右键菜单,只有在用到 callback 方法时才需要
done();
}, 500);
}
};
}
],
columns: [
{
type: 'selection'
},
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-upsert 配置,详细移步到 cl-upsert 示例查看
const Upsert = useUpsert({
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input'
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input'
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 字典匹配 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>dict</el-tag>
<span>字典匹配</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/dict.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="字典匹配" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { computed, reactive, ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
const options = reactive({
occupation: [] as { label: string; value: any }[]
});
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
//【很重要】字典匹配
// 使用字典模块的 get 方法绑定,菜单地址 /dict/list
dict: dict.get('occupation'),
// 是否使用不同颜色区分
dictColor: true,
minWidth: 140
},
{
label: '等级',
prop: 'occupation',
//【很重要】动态匹配列表的情况,使用 computed
dict: computed(() => options.occupation),
minWidth: 140
},
{
label: '状态',
prop: 'status',
// 自定义匹配列表
dict: [
{
label: '启用',
value: 1,
type: 'success'
},
{
label: '禁用',
value: 0,
type: 'danger'
}
],
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
// 模拟接口获取数据
setTimeout(() => {
options.occupation = [
{
label: 'A',
value: 0
},
{
label: 'B',
value: 1
},
{
label: 'C',
value: 2
},
{
label: 'D',
value: 3
},
{
label: 'E',
value: 4
},
{
label: 'F',
value: 5
}
];
}, 1500);
}
</script>
```
## 数据格式化 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>formatter</el-tag>
<span>数据格式化</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/formatter.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="数据格式化" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-09-26</span>
</div>
</div>
</template>
<script setup lang="tsx">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140,
formatter(row) {
return '📱' + row.phone;
}
},
{
label: '用户信息',
minWidth: 200,
// tsx 方式渲染
// 【很重要】使用 tsx 语法时script 的 lang 一定要设置为 tsx
formatter(row) {
// row 为当前行数据
return (
<el-row>
<cl-avatar size={30} />
<el-text style={{ marginLeft: '10px' }}>{row.name}</el-text>
</el-row>
);
}
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 隐藏/显示 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>hidden</el-tag>
<span>隐藏/显示</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/hidden.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="隐藏/显示" width="80%">
<cl-crud ref="Crud">
<!--配置一个 tab -->
<el-tabs v-model="active">
<el-tab-pane label="员工" name="user"></el-tab-pane>
<el-tab-pane label="企业" name="company"></el-tab-pane>
</el-tabs>
<cl-row>
<!-- 使用方法 showColumn 显示 -->
<el-button @click="showColumn('account')">显示账号</el-button>
<!-- 使用方法 hideColumn 隐藏 -->
<el-button @click="hideColumn('account')">隐藏账号</el-button>
</cl-row>
<cl-row>
<cl-table ref="Table"></cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { computed, ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
// 测试数据,移步到 cl-crud 例子查看
service: 'test'
},
app => {
app.refresh();
}
);
const active = ref('user');
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: 'ID',
prop: 'id',
minWidth: 140,
//【很重要】配置 hidden 参数,格式为 boolean 或者 Vue.ComputedRef<boolean>
hidden: computed(() => {
return active.value != 'company';
})
},
{
label: '账号',
prop: 'account',
minWidth: 140,
hidden: true // 默认 false
},
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
function showColumn(prop: string) {
Table.value?.showColumn(prop);
}
function hideColumn(prop: string) {
Table.value?.hideColumn(prop);
}
</script>
```
## 操作栏 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>op</el-tag>
<span>操作栏</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/op.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="操作栏" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table">
<!-- 插槽的渲染方式 #[component.name] -->
<template #slot-btns="{ scope }">
<el-button
@click="
() => {
ElMessage.info(scope.row.name);
}
"
>插槽按钮</el-button
>
</template>
</cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!-- 新增、编辑 -->
<cl-upsert ref="Upsert" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { ElMessage } from 'element-plus';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
},
{
//【很重要】type 必须是 op
type: 'op',
width: 410, // 宽度
//【很重要】操作按钮配置edit 和 info 必须搭配 cl-upsert 实现
// edit 编辑,预先获取 service 的 info 接口数据,并带入 cl-upsert 的表单值中
// info 详情cl-upsert 内的组件全部传入 disabled 参数
// delete 删除,调用 service 的 delete 接口删除行数据
buttons: [
{
label: '编辑',
type: 'primary',
onClick({ scope }) {
ElMessage.info(scope.row.name);
}
},
{
label: '删除',
type: 'danger',
onClick({ scope }) {
ElMessage.info(scope.row.name);
}
},
{
label: '更多',
type: 'success',
children: [
{
label: '查看',
onClick({ scope }) {
ElMessage.info(scope.row.name);
}
},
{
label: '禁用',
onClick({ scope }) {
ElMessage.info(scope.row.name);
}
}
]
},
{
name: 'slot-btns'
}
]
}
]
});
// cl-upsert 配置,详细移步到 cl-upsert 示例查看
const Upsert = useUpsert({
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input'
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input'
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true, // 树形方式选择
checkStrictly: true, // 任意层级都能点
options: dict.get('occupation') // 使用字典数据
}
}
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 插件的使用 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>plugin</el-tag>
<span>插件的使用</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/plugin/base.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="插件的使用" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="tsx">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { merge } from 'lodash-es';
import { defineComponent } from 'vue';
// 插件:列标签匹配,方便多个列表公用同一个组件
function setColumn(): ClTable.Plugin {
const columns = {
UserInfo: {
label: '用户信息',
minWidth: 200,
component: {
vm: defineComponent({
name: 'user-info',
props: {
scope: null
},
setup(props) {
return () => {
return (
<div>
<p>{props.scope.name}</p>
<p>{props.scope.phone}</p>
</div>
);
};
}
})
}
}
} as { [key: string]: DeepPartial<ClTable.Column> };
return ({ exposed }) => {
function deep(arr: ClTable.Column[]) {
arr.forEach(e => {
if (e.tag) {
merge(e, columns[e.tag]);
}
deep(e.children || []);
});
}
deep(exposed.columns);
};
}
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
type: 'selection'
},
{
tag: 'UserInfo'
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
],
//【很重要】配置插件
plugins: [setColumn()]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 行编辑 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>row-edit</el-tag>
<span>行编辑</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/plugin/row-edit.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="行编辑" width="80%">
<cl-crud ref="Crud">
<el-text class="mb-4" tag="p">点击姓名、手机号可以进行编辑</el-text>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { Plugins } from '/#/crud';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140,
// 【很重要】行编辑,默认 el-input
edit: true
},
{
label: '手机号',
prop: 'phone',
minWidth: 140,
// 【很重要】行编辑,开启、关闭
edit: {
enable: true
}
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140,
edit: {
enable: true,
// 【很重要】行编辑,组件配置
component: {
name: 'cl-select',
props: {
options: dict.get('occupation'),
tree: true
}
}
}
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc',
// 【很重要】行编辑,组件配置
edit: {
enable: true,
component: {
name: 'el-date-picker',
props: {
type: 'date',
valueFormat: 'YYYY-MM-DD'
}
}
}
},
{
type: 'op',
buttons: ['delete']
}
],
//【很重要】行编辑插件
plugins: [Plugins.Table.rowEdit()]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 表头搜索 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>search</el-tag>
<span>表头搜索</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/search.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="表头搜索" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="tsx">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { Plus } from '@element-plus/icons-vue';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140,
//【很重要】搜索参数配置
search: {
isInput: false, // 默认false是否输入框模式
value: '', // 默认值
refreshOnChange: true, // 默认false搜索时刷新数据service 的 page 接口请求参数为 { page: 1, [绑定的prop]: 输入值 }
// 自定义渲染组件
component: {
name: 'el-input',
props: {
placeholder: '搜索姓名'
}
}
}
},
{
label: '手机号',
prop: 'phone',
minWidth: 140,
//【很重要】搜索参数配置
search: {
// 是否显示搜索图标
icon: () => <Plus />,
// 自定义渲染组件
component: {
name: 'el-input',
props: {
placeholder: '搜索手机号',
// 自定义 change 事件
onChange(val) {
Crud.value?.refresh({
page: 1,
phone: val
});
}
}
}
}
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140,
//【很重要】搜索参数配置
search: {
// 是否显示搜索图标
icon: () => <cl-svg name="icon-app" size={13} />,
// 自定义渲染组件
component: {
name: 'cl-select',
props: {
placeholder: '搜索工作',
options: dict.get('occupation')
}
}
}
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 多选框数据 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>selection</el-tag>
<span>多选框数据</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/selection.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="多选框数据" width="80%">
<cl-crud ref="Crud">
<cl-row>
<el-button @click="selectRow">选中2行</el-button>
<el-button :disabled="Table?.selection.length == 0" @click="clear">
取消选择
</el-button>
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<el-text>已选 {{ Table?.selection.length }} 人</el-text>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh', 'check'],
columns: [
{
type: 'selection'
},
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
function selectRow() {
const [a, b] = Table.value?.data || [];
// 选中2个
Table.value?.toggleRowSelection(a);
Table.value?.toggleRowSelection(b);
}
function clear() {
Table.value?.clearSelection();
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 插槽的使用 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>slot</el-tag>
<span>插槽的使用</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/slot.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="插槽的使用" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table">
<!--【很重要】必须与 prop 名保持一致格式column-[prop] -->
<template #column-name="{ scope }">
<cl-row type="flex" align="middle">
<cl-avatar :size="36" :style="{ marginRight: '10px' }" />
<el-text>{{ scope.row.name }}</el-text>
</cl-row>
</template>
<template #column-phone="{ scope }"> 📱{{ scope.row.phone }} </template>
</cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
headerAlign: 'left',
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 合并行或列 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>span-method</el-tag>
<span>合并行或列</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/span-method.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="合并行或列" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" :span-method="onSpanMethod" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '存款',
prop: 'wages',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
interface SpanMethodProps {
row: any;
column: any;
rowIndex: number;
columnIndex: number;
}
function onSpanMethod({ row, column, rowIndex, columnIndex }: SpanMethodProps) {
// 根据实际业务需求调整返回值 { rowspan, colspan }
if (columnIndex === 0) {
if (rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1
};
} else {
return {
rowspan: 0,
colspan: 0
};
}
}
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 表尾合计行 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>summary</el-tag>
<span>表尾合计行</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['table/summary.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="表尾合计行" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-table ref="Table" show-summary :summary-method="getSummaries" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '存款',
prop: 'wages',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
function getSummaries() {
return ['合计', '$' + Table.value?.data.reduce((a, b) => a + b.wages, 0)];
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```