第一次提交
This commit is contained in:
122
jeecgboot-vue3/src/views/demo/table/AntdTableSummary.vue
Normal file
122
jeecgboot-vue3/src/views/demo/table/AntdTableSummary.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, h } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { BasicColumn } from '/@/components/Table/src/types/table';
|
||||
/**
|
||||
相比原先的优势:
|
||||
1、Table 列头拖动时合计行不会错位;
|
||||
2、合计行使用TableSummary方式渲染;
|
||||
3、支持slot自定义合计行展示;
|
||||
4、列添加customSummaryRender自定义渲染函数
|
||||
5、能解决在非配置api情况下,列进行过滤时,合计行统计值未更新的问题
|
||||
*/
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
function handleSummary(tableData: Recordable[]) {
|
||||
const totalAge = tableData.reduce((prev, next) => {
|
||||
prev += next.age;
|
||||
return prev;
|
||||
}, 0);
|
||||
const totalScore = tableData.reduce((prev, next) => {
|
||||
prev += next.score;
|
||||
return prev;
|
||||
}, 0);
|
||||
return [
|
||||
{
|
||||
_row: '合计',
|
||||
_index: '平均值',
|
||||
age: Math.round(totalAge / tableData.length),
|
||||
score: Math.round(totalScore / tableData.length),
|
||||
},
|
||||
{
|
||||
_row: '合计',
|
||||
_index: '总计',
|
||||
age: totalAge,
|
||||
score: totalScore,
|
||||
},
|
||||
];
|
||||
}
|
||||
const getBasicColumns = () :BasicColumn[] => {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 200,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
customSummaryRender: ({ text }) => {
|
||||
// return <span style="color: red;">{text}</span>;
|
||||
return h('span', { style: { color: 'red' } }, [text]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '得分',
|
||||
dataIndex: 'score',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
defaultHidden: true,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const [registerTable] = useTable({
|
||||
title: '原生总结栏(表尾合计)示例',
|
||||
api: demoListApi,
|
||||
rowSelection: { type: 'checkbox' },
|
||||
columns: getBasicColumns(),
|
||||
summaryFunc: handleSummary,
|
||||
scroll: { x: 1000 },
|
||||
canResize: false,
|
||||
});
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
127
jeecgboot-vue3/src/views/demo/table/AuthColumn.vue
Normal file
127
jeecgboot-vue3/src/views/demo/table/AuthColumn.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: 'other', // 根据权限控制是否显示: 无权限,不显示
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ic:outline-delete-outline',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
auth: 'super', // 根据权限控制是否显示: 有权限,会显示
|
||||
},
|
||||
]"
|
||||
:dropDownActions="[
|
||||
{
|
||||
label: '启用',
|
||||
popConfirm: {
|
||||
title: '是否启用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
ifShow: (_action) => {
|
||||
return record.status !== 'enable'; // 根据业务控制是否显示: 非enable状态的不显示启用按钮
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
popConfirm: {
|
||||
title: '是否禁用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
ifShow: () => {
|
||||
return record.status === 'enable'; // 根据业务控制是否显示: enable状态的显示禁用按钮
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '同时控制',
|
||||
popConfirm: {
|
||||
title: '是否动态显示?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
auth: 'super', // 同时根据权限和业务控制是否显示
|
||||
ifShow: () => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
auth: 'test', // 根据权限控制是否显示: 无权限,不显示
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
auth: 'super', // 同时根据权限和业务控制是否显示
|
||||
ifShow: (_column) => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: 'TableAction组件及固定列示例',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
bordered: true,
|
||||
actionColumn: {
|
||||
width: 250,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
});
|
||||
function handleEdit(record: Recordable) {
|
||||
console.log('点击了编辑', record);
|
||||
}
|
||||
function handleDelete(record: Recordable) {
|
||||
console.log('点击了删除', record);
|
||||
}
|
||||
function handleOpen(record: Recordable) {
|
||||
console.log('点击了启用', record);
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleOpen,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
81
jeecgboot-vue3/src/views/demo/table/Basic.vue
Normal file
81
jeecgboot-vue3/src/views/demo/table/Basic.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable
|
||||
title="基础示例"
|
||||
titleHelpMessage="温馨提醒"
|
||||
:columns="columns"
|
||||
:dataSource="data"
|
||||
:canResize="canResize"
|
||||
:loading="loading"
|
||||
:striped="striped"
|
||||
:bordered="border"
|
||||
showTableSetting
|
||||
:pagination="pagination"
|
||||
@columns-change="handleColumnChange"
|
||||
>
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="toggleCanResize">
|
||||
{{ !canResize ? '自适应高度' : '取消自适应' }}
|
||||
</a-button>
|
||||
<a-button type="primary" @click="toggleBorder">
|
||||
{{ !border ? '显示边框' : '隐藏边框' }}
|
||||
</a-button>
|
||||
<a-button type="primary" @click="toggleLoading"> 开启loading </a-button>
|
||||
<a-button type="primary" @click="toggleStriped">
|
||||
{{ !striped ? '显示斑马纹' : '隐藏斑马纹' }}
|
||||
</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { BasicTable, ColumnChangeParam } from '/@/components/Table';
|
||||
import { getBasicColumns, getBasicData } from './tableData';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const canResize = ref(false);
|
||||
const loading = ref(false);
|
||||
const striped = ref(true);
|
||||
const border = ref(true);
|
||||
const pagination = ref<any>(false);
|
||||
function toggleCanResize() {
|
||||
canResize.value = !canResize.value;
|
||||
}
|
||||
function toggleStriped() {
|
||||
striped.value = !striped.value;
|
||||
}
|
||||
function toggleLoading() {
|
||||
loading.value = true;
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
pagination.value = { pageSize: 20 };
|
||||
}, 3000);
|
||||
}
|
||||
function toggleBorder() {
|
||||
border.value = !border.value;
|
||||
}
|
||||
|
||||
function handleColumnChange(data: ColumnChangeParam[]) {
|
||||
console.log('ColumnChanged', data);
|
||||
}
|
||||
|
||||
return {
|
||||
columns: getBasicColumns(),
|
||||
data: getBasicData(),
|
||||
canResize,
|
||||
loading,
|
||||
striped,
|
||||
border,
|
||||
toggleStriped,
|
||||
toggleCanResize,
|
||||
toggleLoading,
|
||||
toggleBorder,
|
||||
pagination,
|
||||
handleColumnChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
104
jeecgboot-vue3/src/views/demo/table/CustomerCell.vue
Normal file
104
jeecgboot-vue3/src/views/demo/table/CustomerCell.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #id="{ record }"> ID: {{ record.id }} </template>
|
||||
<template #no="{ record }">
|
||||
<Tag color="green">
|
||||
{{ record.no }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<Avatar v-if="column.key === 'avatar'" :size="60" :src="record.avatar" />
|
||||
</template>
|
||||
<template #img="{ text }">
|
||||
<TableImg :size="60" :simpleShow="true" :imgList="text" />
|
||||
</template>
|
||||
<template #imgs="{ text }"> <TableImg :size="60" :imgList="text" /> </template>
|
||||
|
||||
<template #category="{ record }">
|
||||
<Tag color="green">
|
||||
{{ record.no }}
|
||||
</Tag>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn, TableImg } from '/@/components/Table';
|
||||
import { Tag, Avatar } from 'ant-design-vue';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
slots: { customRender: 'id' },
|
||||
},
|
||||
{
|
||||
title: '头像',
|
||||
dataIndex: 'avatar',
|
||||
width: 100,
|
||||
slots: { customRender: 'avatar' },
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'category',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
defaultHidden: true,
|
||||
slots: { customRender: 'category' },
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '图片列表1',
|
||||
dataIndex: 'imgArr',
|
||||
helpMessage: ['这是简单模式的图片列表', '只会显示一张在表格中', '但点击可预览多张图片'],
|
||||
width: 140,
|
||||
slots: { customRender: 'img' },
|
||||
},
|
||||
{
|
||||
title: '照片列表2',
|
||||
dataIndex: 'imgs',
|
||||
width: 160,
|
||||
slots: { customRender: 'imgs' },
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
slots: { customRender: 'no' },
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableImg, Tag, Avatar },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: '自定义列内容',
|
||||
titleHelpMessage: '表格中所有头像、图片均为mock生成,仅用于演示图片占位',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
bordered: true,
|
||||
showTableSetting: true,
|
||||
});
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
219
jeecgboot-vue3/src/views/demo/table/EditCellTable.vue
Normal file
219
jeecgboot-vue3/src/views/demo/table/EditCellTable.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" @edit-end="handleEditEnd" @edit-cancel="handleEditCancel" :beforeEditSubmit="beforeEditSubmit" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
||||
import { optionsListApi } from '/@/api/demo/select';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { treeOptionsListApi } from '/@/api/demo/tree';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { mapTableTotalSummary } from "@/utils/common/compUtils";
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '输入框',
|
||||
dataIndex: 'name',
|
||||
edit: true,
|
||||
editComponentProps: {
|
||||
prefix: '$',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '默认输入状态',
|
||||
dataIndex: 'name7',
|
||||
edit: true,
|
||||
editable: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '输入框校验',
|
||||
dataIndex: 'name1',
|
||||
edit: true,
|
||||
// 默认必填校验
|
||||
editRule: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '输入框函数校验',
|
||||
dataIndex: 'name2',
|
||||
edit: true,
|
||||
editRule: async (text) => {
|
||||
if (text === '2') {
|
||||
return '不能输入该值';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '数字输入框',
|
||||
dataIndex: 'id',
|
||||
edit: true,
|
||||
editRule: true,
|
||||
editComponent: 'InputNumber',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '下拉框',
|
||||
dataIndex: 'name3',
|
||||
edit: true,
|
||||
editComponent: 'Select',
|
||||
editComponentProps: {
|
||||
options: [
|
||||
{
|
||||
label: 'Option1',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: 'Option2',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉',
|
||||
dataIndex: 'name4',
|
||||
edit: true,
|
||||
editComponent: 'ApiSelect',
|
||||
editComponentProps: {
|
||||
api: optionsListApi,
|
||||
resultField: 'list',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉树',
|
||||
dataIndex: 'name71',
|
||||
edit: true,
|
||||
editComponent: 'ApiTreeSelect',
|
||||
editRule: false,
|
||||
editComponentProps: {
|
||||
api: treeOptionsListApi,
|
||||
resultField: 'list',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '日期选择',
|
||||
dataIndex: 'date',
|
||||
edit: true,
|
||||
editComponent: 'DatePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '时间选择',
|
||||
dataIndex: 'time',
|
||||
edit: true,
|
||||
editComponent: 'TimePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'HH:mm',
|
||||
format: 'HH:mm',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '勾选框',
|
||||
dataIndex: 'name5',
|
||||
edit: true,
|
||||
editComponent: 'Checkbox',
|
||||
editValueMap: (value) => {
|
||||
return value ? '是' : '否';
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '开关',
|
||||
dataIndex: 'name6',
|
||||
edit: true,
|
||||
editComponent: 'Switch',
|
||||
editValueMap: (value) => {
|
||||
return value ? '开' : '关';
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: '可编辑单元格示例',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
showIndexColumn: false,
|
||||
bordered: true,
|
||||
showSummary: true,
|
||||
summaryFunc: onSummary
|
||||
});
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
function handleEditEnd({ record, index, key, value }: Recordable) {
|
||||
console.log(record, index, key, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 模拟将指定数据保存
|
||||
function feakSave({ value, key, id }) {
|
||||
createMessage.loading({
|
||||
content: `正在模拟保存${key}`,
|
||||
key: '_save_fake_data',
|
||||
duration: 0,
|
||||
});
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
if (value === '') {
|
||||
createMessage.error({
|
||||
content: '保存失败:不能为空',
|
||||
key: '_save_fake_data',
|
||||
duration: 2,
|
||||
});
|
||||
resolve(false);
|
||||
} else {
|
||||
createMessage.success({
|
||||
content: `记录${id}的${key}已保存`,
|
||||
key: '_save_fake_data',
|
||||
duration: 2,
|
||||
});
|
||||
resolve(true);
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
async function beforeEditSubmit({ record, index, key, value }) {
|
||||
console.log('单元格数据正在准备提交', { record, index, key, value });
|
||||
return await feakSave({ id: record.id, key, value });
|
||||
}
|
||||
|
||||
function handleEditCancel() {
|
||||
console.log('cancel');
|
||||
}
|
||||
|
||||
function onSummary(tableData: Recordable[]) {
|
||||
// 可用工具方法自动计算合计
|
||||
const totals = mapTableTotalSummary(tableData, ['id']);
|
||||
return [
|
||||
totals
|
||||
];
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
handleEditEnd,
|
||||
handleEditCancel,
|
||||
beforeEditSubmit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
253
jeecgboot-vue3/src/views/demo/table/EditRowTable.vue
Normal file
253
jeecgboot-vue3/src/views/demo/table/EditRowTable.vue
Normal file
@@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" @edit-change="onEditChange">
|
||||
<template #action="{ record, column }">
|
||||
<TableAction :actions="createActions(record, column)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { BasicTable, useTable, TableAction, BasicColumn, ActionItem, EditRecordRow } from '/@/components/Table';
|
||||
import { optionsListApi } from '/@/api/demo/select';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { treeOptionsListApi } from '/@/api/demo/tree';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '输入框',
|
||||
dataIndex: 'name',
|
||||
editRow: true,
|
||||
editComponentProps: {
|
||||
prefix: '$',
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '默认输入状态',
|
||||
dataIndex: 'name7',
|
||||
editRow: true,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '输入框校验',
|
||||
dataIndex: 'name1',
|
||||
editRow: true,
|
||||
align: 'left',
|
||||
// 默认必填校验
|
||||
editRule: true,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '输入框函数校验',
|
||||
dataIndex: 'name2',
|
||||
editRow: true,
|
||||
align: 'right',
|
||||
editRule: async (text) => {
|
||||
if (text === '2') {
|
||||
return '不能输入该值';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '数字输入框',
|
||||
dataIndex: 'id',
|
||||
editRow: true,
|
||||
editRule: true,
|
||||
editComponent: 'InputNumber',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '下拉框',
|
||||
dataIndex: 'name3',
|
||||
editRow: true,
|
||||
editComponent: 'Select',
|
||||
editComponentProps: {
|
||||
options: [
|
||||
{
|
||||
label: 'Option1',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: 'Option2',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: 'Option3',
|
||||
value: '3',
|
||||
},
|
||||
],
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉',
|
||||
dataIndex: 'name4',
|
||||
editRow: true,
|
||||
editComponent: 'ApiSelect',
|
||||
editComponentProps: {
|
||||
api: optionsListApi,
|
||||
resultField: 'list',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉树',
|
||||
dataIndex: 'name8',
|
||||
editRow: true,
|
||||
editComponent: 'ApiTreeSelect',
|
||||
editRule: false,
|
||||
editComponentProps: {
|
||||
api: treeOptionsListApi,
|
||||
resultField: 'list',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '日期选择',
|
||||
dataIndex: 'date',
|
||||
editRow: true,
|
||||
editComponent: 'DatePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '时间选择',
|
||||
dataIndex: 'time',
|
||||
editRow: true,
|
||||
editComponent: 'TimePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'HH:mm',
|
||||
format: 'HH:mm',
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '勾选框',
|
||||
dataIndex: 'name5',
|
||||
editRow: true,
|
||||
|
||||
editComponent: 'Checkbox',
|
||||
editValueMap: (value) => {
|
||||
return value ? '是' : '否';
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '开关',
|
||||
dataIndex: 'name6',
|
||||
editRow: true,
|
||||
editComponent: 'Switch',
|
||||
editValueMap: (value) => {
|
||||
return value ? '开' : '关';
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction },
|
||||
setup() {
|
||||
const { createMessage: msg } = useMessage();
|
||||
const currentEditKeyRef = ref('');
|
||||
const [registerTable] = useTable({
|
||||
title: '可编辑行示例',
|
||||
titleHelpMessage: ['本例中修改[数字输入框]这一列时,同一行的[远程下拉]列的当前编辑数据也会同步发生改变'],
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
showIndexColumn: false,
|
||||
showTableSetting: true,
|
||||
tableSetting: { fullScreen: true },
|
||||
actionColumn: {
|
||||
width: 160,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
});
|
||||
|
||||
function handleEdit(record: EditRecordRow) {
|
||||
currentEditKeyRef.value = record.key;
|
||||
record.onEdit?.(true);
|
||||
}
|
||||
|
||||
function handleCancel(record: EditRecordRow) {
|
||||
currentEditKeyRef.value = '';
|
||||
record.onEdit?.(false, false);
|
||||
}
|
||||
|
||||
async function handleSave(record: EditRecordRow) {
|
||||
// 校验
|
||||
msg.loading({ content: '正在保存...', duration: 0, key: 'saving' });
|
||||
const valid = await record.onValid?.();
|
||||
if (valid) {
|
||||
try {
|
||||
const data = cloneDeep(record.editValueRefs);
|
||||
console.log(data);
|
||||
//TODO 此处将数据提交给服务器保存
|
||||
// ...
|
||||
// 保存之后提交编辑状态
|
||||
const pass = await record.onEdit?.(false, true);
|
||||
if (pass) {
|
||||
currentEditKeyRef.value = '';
|
||||
}
|
||||
msg.success({ content: '数据已保存', key: 'saving' });
|
||||
} catch (error) {
|
||||
msg.error({ content: '保存失败', key: 'saving' });
|
||||
}
|
||||
} else {
|
||||
msg.error({ content: '请填写正确的数据', key: 'saving' });
|
||||
}
|
||||
}
|
||||
|
||||
function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
|
||||
if (!record.editable) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
disabled: currentEditKeyRef.value ? currentEditKeyRef.value !== record.key : false,
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
label: '保存',
|
||||
onClick: handleSave.bind(null, record, column),
|
||||
},
|
||||
{
|
||||
label: '取消',
|
||||
popConfirm: {
|
||||
title: '是否取消编辑',
|
||||
confirm: handleCancel.bind(null, record, column),
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function onEditChange({ column, value, record }) {
|
||||
// 本例
|
||||
if (column.dataIndex === 'id') {
|
||||
record.editValueRefs.name4.value = `${value}`;
|
||||
}
|
||||
console.log(column, value, record);
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
handleEdit,
|
||||
createActions,
|
||||
onEditChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
252
jeecgboot-vue3/src/views/demo/table/EditableCellIdTest.vue
Normal file
252
jeecgboot-vue3/src/views/demo/table/EditableCellIdTest.vue
Normal file
@@ -0,0 +1,252 @@
|
||||
<template>
|
||||
<PageWrapper title="EditableCell ID字段测试 (Issue #8924)">
|
||||
<a-alert
|
||||
message="🧪 测试目的:验证 beforeEditSubmit 是否会过滤掉 id 字段"
|
||||
description="请编辑任意单元格并点击对号,查看下方的测试结果。如果 record 中没有 id 字段,说明问题存在。"
|
||||
type="warning"
|
||||
show-icon
|
||||
class="mb-4"
|
||||
/>
|
||||
|
||||
<div class="p-4">
|
||||
<a-card title="🔬 测试场景1:id 字段不在 columns 中(最常见场景)" class="mb-4">
|
||||
<a-alert
|
||||
message="⚠️ 核心测试:id 在数据中,但不在 columns 中显示"
|
||||
description="这是最常见的场景:主键字段通常不需要在表格中显示,但在更新数据时必须使用。"
|
||||
type="info"
|
||||
show-icon
|
||||
class="mb-3"
|
||||
/>
|
||||
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-card size="small" title="📋 测试数据说明" :bordered="false">
|
||||
<p><strong>数据源包含:</strong>id, name, age, email, address</p>
|
||||
<p><strong>Columns 显示:</strong>name, age, email, address(⚠️ 没有 id 列)</p>
|
||||
<p><strong>rowKey 配置:</strong>'id'</p>
|
||||
</a-card>
|
||||
|
||||
<BasicTable
|
||||
@register="registerTable1"
|
||||
:beforeEditSubmit="handleBeforeEditSubmit1"
|
||||
/>
|
||||
|
||||
<a-card
|
||||
size="small"
|
||||
:title="testResult1.title"
|
||||
:bordered="false"
|
||||
:headStyle="{ backgroundColor: testResult1.bgColor, color: 'white' }"
|
||||
>
|
||||
<a-descriptions bordered :column="1" size="small">
|
||||
<a-descriptions-item label="是否包含 id">
|
||||
<a-tag :color="testResult1.hasId ? 'success' : 'error'">
|
||||
{{ testResult1.hasId ? '✅ 包含' : '❌ 不包含' }}
|
||||
{{ testResult1.hasId ? `(id=${testResult1.idValue})` : '' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="record 包含的字段">
|
||||
<a-tag v-for="field in testResult1.fields" :key="field" color="blue">{{ field }}</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="完整 record 内容">
|
||||
<pre class="test-result-json">{{ testResult1.recordJson }}</pre>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="测试结论">
|
||||
<a-alert
|
||||
:message="testResult1.conclusion"
|
||||
:type="testResult1.hasId ? 'success' : 'error'"
|
||||
show-icon
|
||||
/>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</a-card>
|
||||
|
||||
<a-card title="💡 测试说明" class="mb-4">
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-alert
|
||||
message="如何进行测试?"
|
||||
description="1. 点击上方表格任意单元格进行编辑
|
||||
2. 修改内容后点击对号 ✓ 提交
|
||||
3. 查看测试结果,观察 record 是否包含 id 字段"
|
||||
type="info"
|
||||
show-icon
|
||||
/>
|
||||
|
||||
<a-alert
|
||||
message="预期结果"
|
||||
type="success"
|
||||
show-icon
|
||||
>
|
||||
<template #description>
|
||||
<p><strong>如果代码正常:</strong></p>
|
||||
<p>✅ record 应该包含 id 字段</p>
|
||||
<p>✅ 可以使用 record.id 进行数据更新</p>
|
||||
<p>✅ 控制台显示绿色成功消息</p>
|
||||
</template>
|
||||
</a-alert>
|
||||
|
||||
<a-alert
|
||||
message="Bug 症状(Issue #8924)"
|
||||
type="error"
|
||||
show-icon
|
||||
>
|
||||
<template #description>
|
||||
<p><strong>如果存在 Bug:</strong></p>
|
||||
<p>❌ record 中没有 id 字段</p>
|
||||
<p>❌ record 只包含 columns 中定义的字段(name, age, email, address)</p>
|
||||
<p>❌ 无法执行数据更新操作</p>
|
||||
<p>❌ 控制台显示红色错误消息</p>
|
||||
</template>
|
||||
</a-alert>
|
||||
|
||||
<a-card size="small" title="🔍 原因分析" :bordered="false">
|
||||
<p>原代码使用 <code>pick(record, keys)</code> 过滤字段:</p>
|
||||
<pre class="code-block">const keys = columns.map(c => c.dataIndex).filter(f => !!f);
|
||||
// keys = ['name', 'age', 'email', 'address'] // ⚠️ 没有 id
|
||||
|
||||
record: pick(record, keys)
|
||||
// 只保留 keys 中的字段,id 被过滤掉了</pre>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</a-card>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
// ============ 测试场景1:id字段不在columns中 ============
|
||||
const testResult1 = ref<{
|
||||
title: string;
|
||||
bgColor: string;
|
||||
hasId: boolean;
|
||||
idValue: any;
|
||||
fields: string[];
|
||||
recordJson: string;
|
||||
conclusion: string;
|
||||
}>({
|
||||
title: '📊 测试结果(点击对号后显示)',
|
||||
bgColor: '#909399',
|
||||
hasId: false,
|
||||
idValue: null,
|
||||
fields: [],
|
||||
recordJson: '暂无数据,请编辑单元格并点击对号',
|
||||
conclusion: '等待测试...',
|
||||
});
|
||||
|
||||
const columns1: BasicColumn[] = [
|
||||
// 注意:这里没有 id 列
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
edit: true,
|
||||
editComponent: 'Input',
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
width: 120,
|
||||
edit: true,
|
||||
editComponent: 'InputNumber',
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
width: 200,
|
||||
edit: true,
|
||||
editComponent: 'Input',
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 200,
|
||||
edit: true,
|
||||
editComponent: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
const dataSource1 = [
|
||||
{ id: 1, name: '张三', age: 25, email: 'zhangsan@example.com', address: '北京市朝阳区' },
|
||||
{ id: 2, name: '李四', age: 30, email: 'lisi@example.com', address: '上海市浦东新区' },
|
||||
{ id: 3, name: '王五', age: 28, email: 'wangwu@example.com', address: '广州市天河区' },
|
||||
];
|
||||
|
||||
const [registerTable1] = useTable({
|
||||
rowKey: 'id', // 使用默认id字段作为主键,
|
||||
columns: columns1,
|
||||
dataSource: dataSource1,
|
||||
pagination: false,
|
||||
showIndexColumn: true,
|
||||
canResize: false,
|
||||
});
|
||||
|
||||
async function handleBeforeEditSubmit1({ record, index, key, value }) {
|
||||
console.log('🧪 场景1 测试 - beforeEditSubmit 接收到的数据:', { record, index, key, value });
|
||||
console.log('🔍 record 详细内容:', JSON.stringify(record, null, 2));
|
||||
|
||||
// 分析 record
|
||||
const hasId = 'id' in record;
|
||||
const fields = Object.keys(record);
|
||||
|
||||
// 更新测试结果
|
||||
testResult1.value = {
|
||||
title: hasId ? '✅ 测试通过' : '❌ 测试失败 - 发现 Bug!',
|
||||
bgColor: hasId ? '#67C23A' : '#F56C6C',
|
||||
hasId: hasId,
|
||||
idValue: record.id || null,
|
||||
fields: fields,
|
||||
recordJson: JSON.stringify(record, null, 2),
|
||||
conclusion: hasId
|
||||
? `✅ record 中包含 id 字段(值为 ${record.id}),可以正常更新数据`
|
||||
: `❌ Bug 确认:record 中缺少 id 字段!只包含 ${fields.join(', ')}。这会导致无法执行数据更新操作。`,
|
||||
};
|
||||
|
||||
if (!hasId) {
|
||||
createMessage.error('❌ 测试失败:record 中缺少 id 字段!这就是 Issue #8924 描述的问题。');
|
||||
console.error('❌ Bug 重现:数据源中有 id,但 beforeEditSubmit 收到的 record 中没有 id');
|
||||
return false;
|
||||
}
|
||||
|
||||
createMessage.success(`✅ 测试通过:获取到 id=${record.id}`);
|
||||
console.log('✅ 模拟更新请求:', {
|
||||
url: '/api/user/update',
|
||||
params: { id: record.id, [key]: value },
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.test-result-json {
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
background-color: #f5f5f5;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
background-color: #282c34;
|
||||
color: #abb2bf;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
</style>
|
||||
74
jeecgboot-vue3/src/views/demo/table/ExpandTable.vue
Normal file
74
jeecgboot-vue3/src/views/demo/table/ExpandTable.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<PageWrapper
|
||||
title="可展开表格"
|
||||
content="不可与scroll共用。TableAction组件可配置stopButtonPropagation来阻止操作按钮的点击事件冒泡,以便配合Table组件的expandRowByClick"
|
||||
>
|
||||
<BasicTable @register="registerTable">
|
||||
<template #expandedRowRender="{ record }">
|
||||
<span>No: {{ record.no }} </span>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
stopButtonPropagation
|
||||
:actions="[
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ic:outline-delete-outline',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
},
|
||||
]"
|
||||
:dropDownActions="[
|
||||
{
|
||||
label: '启用',
|
||||
popConfirm: {
|
||||
title: '是否启用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { getBasicColumns } from './tableData';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction, PageWrapper },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
api: demoListApi,
|
||||
title: '可展开表格演示',
|
||||
titleHelpMessage: ['已启用expandRowByClick', '已启用stopButtonPropagation'],
|
||||
columns: getBasicColumns(),
|
||||
rowKey: 'id',
|
||||
canResize: false,
|
||||
expandRowByClick: true,
|
||||
actionColumn: {
|
||||
width: 160,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
});
|
||||
function handleDelete(record: Recordable) {
|
||||
console.log('点击了删除', record);
|
||||
}
|
||||
function handleOpen(record: Recordable) {
|
||||
console.log('点击了启用', record);
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
handleDelete,
|
||||
handleOpen,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
43
jeecgboot-vue3/src/views/demo/table/FetchTable.vue
Normal file
43
jeecgboot-vue3/src/views/demo/table/FetchTable.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<PageWrapper contentBackground contentClass="flex" dense contentFullHeight fixedHeight>
|
||||
<BasicTable @register="registerTable">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="handleReloadCurrent"> 刷新当前页 </a-button>
|
||||
<a-button type="primary" @click="handleReload"> 刷新并返回第一页 </a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { getBasicColumns } from './tableData';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
export default defineComponent({
|
||||
components: { BasicTable, PageWrapper },
|
||||
setup() {
|
||||
const [registerTable, { reload }] = useTable({
|
||||
title: '远程加载示例',
|
||||
api: demoListApi,
|
||||
columns: getBasicColumns(),
|
||||
pagination: { pageSize: 10 },
|
||||
});
|
||||
function handleReloadCurrent() {
|
||||
reload();
|
||||
}
|
||||
|
||||
function handleReload() {
|
||||
reload({
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
handleReloadCurrent,
|
||||
handleReload,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
93
jeecgboot-vue3/src/views/demo/table/FixedColumn.vue
Normal file
93
jeecgboot-vue3/src/views/demo/table/FixedColumn.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ic:outline-delete-outline',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
},
|
||||
]"
|
||||
:dropDownActions="[
|
||||
{
|
||||
label: '启用',
|
||||
popConfirm: {
|
||||
title: '是否启用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 280,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 260,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 200,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: 'TableAction组件及固定列示例',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
rowSelection: { type: 'radio' },
|
||||
bordered: true,
|
||||
actionColumn: {
|
||||
width: 160,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
});
|
||||
function handleDelete(record: Recordable) {
|
||||
console.log('点击了删除', record);
|
||||
}
|
||||
function handleOpen(record: Recordable) {
|
||||
console.log('点击了启用', record);
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
handleDelete,
|
||||
handleOpen,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
41
jeecgboot-vue3/src/views/demo/table/FixedHeight.vue
Normal file
41
jeecgboot-vue3/src/views/demo/table/FixedHeight.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #customTitle>
|
||||
<span>
|
||||
姓名
|
||||
<BasicHelp class="ml-2" text="姓名" />
|
||||
</span>
|
||||
</template>
|
||||
<template #customAddress>
|
||||
地址
|
||||
<FormOutlined class="ml-2" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { getCustomHeaderColumns } from './tableData';
|
||||
import { FormOutlined } from '@ant-design/icons-vue';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { BasicHelp } from '/@/components/Basic';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable, FormOutlined, BasicHelp },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: '定高/头部自定义',
|
||||
api: demoListApi,
|
||||
columns: getCustomHeaderColumns(),
|
||||
canResize: false,
|
||||
scroll: { y: 100 },
|
||||
});
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
110
jeecgboot-vue3/src/views/demo/table/FooterTable.vue
Normal file
110
jeecgboot-vue3/src/views/demo/table/FooterTable.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { BasicColumn } from '/@/components/Table/src/types/table';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
function handleSummary(tableData: Recordable[]) {
|
||||
const totalAge = tableData.reduce((prev, next) => {
|
||||
prev += next.age;
|
||||
return prev;
|
||||
}, 0);
|
||||
const totalScore = tableData.reduce((prev, next) => {
|
||||
prev += next.score;
|
||||
return prev;
|
||||
}, 0);
|
||||
return [
|
||||
{
|
||||
_row: '合计',
|
||||
_index: '平均值',
|
||||
age: Math.round(totalAge / tableData.length),
|
||||
score: Math.round(totalScore / tableData.length),
|
||||
},
|
||||
{
|
||||
_row: '合计',
|
||||
_index: '平均值',
|
||||
age: totalAge,
|
||||
score: totalScore,
|
||||
},
|
||||
];
|
||||
}
|
||||
const getBasicColumns = (): BasicColumn[] => {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '得分',
|
||||
dataIndex: 'score',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
defaultHidden: true,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
};
|
||||
const [registerTable] = useTable({
|
||||
title: '表尾行合计示例',
|
||||
api: demoListApi,
|
||||
rowSelection: { type: 'checkbox' },
|
||||
columns: getBasicColumns(),
|
||||
// showSummary: true使用的是自定义的表尾行合计方式,如果不设置或者为false使用的antd
|
||||
showSummary: true,
|
||||
summaryFunc: handleSummary,
|
||||
scroll: { x: 1000 },
|
||||
canResize: false,
|
||||
});
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
63
jeecgboot-vue3/src/views/demo/table/FormTable.vue
Normal file
63
jeecgboot-vue3/src/views/demo/table/FormTable.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<BasicTable @register="registerTable" :rowSelection="{ type: 'checkbox', selectedRowKeys: checkedKeys, onChange: onSelectChange }">
|
||||
<template #form-custom> custom-slot </template>
|
||||
<template #headerTop>
|
||||
<a-alert type="info" show-icon>
|
||||
<template #message>
|
||||
<template v-if="checkedKeys.length > 0">
|
||||
<span>已选中{{ checkedKeys.length }}条记录(可跨页)</span>
|
||||
<a-button type="link" @click="checkedKeys = []" size="small">清空</a-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>未选中任何项目</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-alert>
|
||||
</template>
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="getFormValues">获取表单数据</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { getBasicColumns, getFormConfig } from './tableData';
|
||||
import { Alert } from 'ant-design-vue';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable, AAlert: Alert },
|
||||
setup() {
|
||||
const checkedKeys = ref<Array<string | number>>([]);
|
||||
const [registerTable, { getForm }] = useTable({
|
||||
title: '开启搜索区域',
|
||||
api: demoListApi,
|
||||
columns: getBasicColumns(),
|
||||
useSearchForm: true,
|
||||
formConfig: getFormConfig(),
|
||||
showTableSetting: true,
|
||||
tableSetting: { fullScreen: true },
|
||||
showIndexColumn: false,
|
||||
rowKey: 'id',
|
||||
});
|
||||
|
||||
function getFormValues() {
|
||||
console.log(getForm().getFieldsValue());
|
||||
}
|
||||
|
||||
function onSelectChange(selectedRowKeys: (string | number)[]) {
|
||||
console.log(selectedRowKeys);
|
||||
checkedKeys.value = selectedRowKeys;
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
getFormValues,
|
||||
checkedKeys,
|
||||
onSelectChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
27
jeecgboot-vue3/src/views/demo/table/MergeHeader.vue
Normal file
27
jeecgboot-vue3/src/views/demo/table/MergeHeader.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { getMergeHeaderColumns } from './tableData';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: '多级表头示例',
|
||||
api: demoListApi,
|
||||
columns: getMergeHeaderColumns(),
|
||||
});
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
26
jeecgboot-vue3/src/views/demo/table/MultipleHeader.vue
Normal file
26
jeecgboot-vue3/src/views/demo/table/MultipleHeader.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { getMultipleHeaderColumns } from './tableData';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: '多级表头示例',
|
||||
api: demoListApi,
|
||||
columns: getMultipleHeaderColumns(),
|
||||
});
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
113
jeecgboot-vue3/src/views/demo/table/NestedTable.vue
Normal file
113
jeecgboot-vue3/src/views/demo/table/NestedTable.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<a-table :columns="columns" :data-source="data" class="components-table-demo-nested">
|
||||
<template #bodyCell="{ column }">
|
||||
<template v-if="column.key === 'operation'">
|
||||
<a>Publish</a>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender>
|
||||
<a-table :columns="innerColumns" :data-source="innerData" :pagination="false">
|
||||
<template #bodyCell="{ column }">
|
||||
<template v-if="column.dataIndex === 'state'">
|
||||
<span>
|
||||
<a-badge status="success" />
|
||||
Finished
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'operation'">
|
||||
<span class="table-operation">
|
||||
<a>Pause</a>
|
||||
<a>Stop</a>
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>Action 1</a-menu-item>
|
||||
<a-menu-item>Action 2</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a> More </a>
|
||||
</a-dropdown>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
const columns = [
|
||||
{ title: 'Name', dataIndex: 'name', key: 'name' },
|
||||
{ title: 'Platform', dataIndex: 'platform', key: 'platform' },
|
||||
{ title: 'Version', dataIndex: 'version', key: 'version' },
|
||||
{ title: 'Upgraded', dataIndex: 'upgradeNum', key: 'upgradeNum' },
|
||||
{ title: 'Creator', dataIndex: 'creator', key: 'creator' },
|
||||
{ title: 'Date', dataIndex: 'createdAt', key: 'createdAt' },
|
||||
{ title: 'Action', key: 'operation' },
|
||||
];
|
||||
|
||||
interface DataItem {
|
||||
key: number;
|
||||
name: string;
|
||||
platform: string;
|
||||
version: string;
|
||||
upgradeNum: number;
|
||||
creator: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
const data: DataItem[] = [];
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
data.push({
|
||||
key: i,
|
||||
name: 'Screem',
|
||||
platform: 'iOS',
|
||||
version: '10.3.4.5654',
|
||||
upgradeNum: 500,
|
||||
creator: 'Jack',
|
||||
createdAt: '2014-12-24 23:12:00',
|
||||
});
|
||||
}
|
||||
|
||||
const innerColumns = [
|
||||
{ title: 'Date', dataIndex: 'date', key: 'date' },
|
||||
{ title: 'Name', dataIndex: 'name', key: 'name' },
|
||||
{ title: 'Status', dataIndex: 'state', key: 'state' },
|
||||
{ title: 'Upgrade Status', dataIndex: 'upgradeNum', key: 'upgradeNum' },
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: 'operation',
|
||||
key: 'operation',
|
||||
},
|
||||
];
|
||||
|
||||
interface innerDataItem {
|
||||
key: number;
|
||||
date: string;
|
||||
name: string;
|
||||
upgradeNum: string;
|
||||
}
|
||||
|
||||
const innerData: innerDataItem[] = [];
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
innerData.push({
|
||||
key: i,
|
||||
date: '2014-12-24 23:12:00',
|
||||
name: 'This is production name',
|
||||
upgradeNum: 'Upgraded: 56',
|
||||
});
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: {},
|
||||
setup() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
innerColumns,
|
||||
innerData,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
125
jeecgboot-vue3/src/views/demo/table/RefTable.vue
Normal file
125
jeecgboot-vue3/src/views/demo/table/RefTable.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<div class="mb-4">
|
||||
<a-button class="mr-2" @click="reloadTable"> 还原 </a-button>
|
||||
<a-button class="mr-2" @click="changeLoading"> 开启loading </a-button>
|
||||
<a-button class="mr-2" @click="changeColumns"> 更改Columns </a-button>
|
||||
<a-button class="mr-2" @click="getColumn"> 获取Columns </a-button>
|
||||
<a-button class="mr-2" @click="getTableData"> 获取表格数据 </a-button>
|
||||
<a-button class="mr-2" @click="getTableRawData"> 获取接口原始数据 </a-button>
|
||||
<a-button class="mr-2" @click="setPaginationInfo"> 跳转到第2页 </a-button>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<a-button class="mr-2" @click="getSelectRowList"> 获取选中行 </a-button>
|
||||
<a-button class="mr-2" @click="getSelectRowKeyList"> 获取选中行Key </a-button>
|
||||
<a-button class="mr-2" @click="setSelectedRowKeyList"> 设置选中行 </a-button>
|
||||
<a-button class="mr-2" @click="clearSelect"> 清空选中行 </a-button>
|
||||
<a-button class="mr-2" @click="getPagination"> 获取分页信息 </a-button>
|
||||
</div>
|
||||
<BasicTable
|
||||
:canResize="false"
|
||||
title="RefTable示例"
|
||||
titleHelpMessage="使用Ref调用表格内方法"
|
||||
ref="tableRef"
|
||||
:api="api"
|
||||
:columns="columns"
|
||||
rowKey="id"
|
||||
:rowSelection="{ type: 'checkbox' }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, unref } from 'vue';
|
||||
import { BasicTable, TableActionType } from '/@/components/Table';
|
||||
import { getBasicColumns, getBasicShortColumns } from './tableData';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const tableRef = ref<Nullable<TableActionType>>(null);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
function getTableAction() {
|
||||
const tableAction = unref(tableRef);
|
||||
if (!tableAction) {
|
||||
throw new Error('tableAction is null');
|
||||
}
|
||||
return tableAction;
|
||||
}
|
||||
function changeLoading() {
|
||||
getTableAction().setLoading(true);
|
||||
setTimeout(() => {
|
||||
getTableAction().setLoading(false);
|
||||
}, 1000);
|
||||
}
|
||||
function changeColumns() {
|
||||
getTableAction().setColumns(getBasicShortColumns());
|
||||
}
|
||||
function reloadTable() {
|
||||
getTableAction().setColumns(getBasicColumns());
|
||||
|
||||
getTableAction().reload({
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
function getColumn() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getTableAction().getColumns());
|
||||
}
|
||||
|
||||
function getTableData() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getTableAction().getDataSource());
|
||||
}
|
||||
function getTableRawData() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getTableAction().getRawDataSource());
|
||||
}
|
||||
|
||||
function getPagination() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getTableAction().getPaginationRef());
|
||||
}
|
||||
|
||||
function setPaginationInfo() {
|
||||
getTableAction().setPagination({
|
||||
current: 2,
|
||||
});
|
||||
getTableAction().reload();
|
||||
}
|
||||
function getSelectRowList() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getTableAction().getSelectRows());
|
||||
}
|
||||
function getSelectRowKeyList() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getTableAction().getSelectRowKeys());
|
||||
}
|
||||
function setSelectedRowKeyList() {
|
||||
getTableAction().setSelectedRowKeys(['0', '1', '2']);
|
||||
}
|
||||
function clearSelect() {
|
||||
getTableAction().clearSelectedRowKeys();
|
||||
}
|
||||
|
||||
return {
|
||||
tableRef,
|
||||
api: demoListApi,
|
||||
columns: getBasicColumns(),
|
||||
changeLoading,
|
||||
changeColumns,
|
||||
reloadTable,
|
||||
getColumn,
|
||||
getTableData,
|
||||
getTableRawData,
|
||||
getPagination,
|
||||
setPaginationInfo,
|
||||
getSelectRowList,
|
||||
getSelectRowKeyList,
|
||||
setSelectedRowKeyList,
|
||||
clearSelect,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
41
jeecgboot-vue3/src/views/demo/table/TreeTable.vue
Normal file
41
jeecgboot-vue3/src/views/demo/table/TreeTable.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="register">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="expandAll">展开全部</a-button>
|
||||
<a-button type="primary" @click="collapseAll">折叠全部</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { getBasicColumns, getTreeTableData } from './tableData';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const [register, { expandAll, collapseAll }] = useTable({
|
||||
title: '树形表格',
|
||||
isTreeTable: true,
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
getCheckboxProps(record: Recordable) {
|
||||
// Demo: 第一行(id为0)的选择框禁用
|
||||
if (record.id === '0') {
|
||||
return { disabled: true };
|
||||
} else {
|
||||
return { disabled: false };
|
||||
}
|
||||
},
|
||||
},
|
||||
titleHelpMessage: '树形组件不能和序列号列同时存在',
|
||||
columns: getBasicColumns(),
|
||||
dataSource: getTreeTableData(),
|
||||
rowKey: 'id',
|
||||
});
|
||||
return { register, expandAll, collapseAll };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
147
jeecgboot-vue3/src/views/demo/table/UseTable.vue
Normal file
147
jeecgboot-vue3/src/views/demo/table/UseTable.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<div class="mb-4">
|
||||
<a-button class="mr-2" @click="reloadTable"> 还原 </a-button>
|
||||
<a-button class="mr-2" @click="changeLoading"> 开启loading </a-button>
|
||||
<a-button class="mr-2" @click="changeColumns"> 更改Columns </a-button>
|
||||
<a-button class="mr-2" @click="getColumn"> 获取Columns </a-button>
|
||||
<a-button class="mr-2" @click="getTableData"> 获取表格数据 </a-button>
|
||||
<a-button class="mr-2" @click="getTableRawData"> 获取接口原始数据 </a-button>
|
||||
<a-button class="mr-2" @click="setPaginationInfo"> 跳转到第2页 </a-button>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<a-button class="mr-2" @click="getSelectRowList"> 获取选中行 </a-button>
|
||||
<a-button class="mr-2" @click="getSelectRowKeyList"> 获取选中行Key </a-button>
|
||||
<a-button class="mr-2" @click="setSelectedRowKeyList"> 设置选中行 </a-button>
|
||||
<a-button class="mr-2" @click="clearSelect"> 清空选中行 </a-button>
|
||||
<a-button class="mr-2" @click="getPagination"> 获取分页信息 </a-button>
|
||||
</div>
|
||||
<BasicTable @register="registerTable" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, ColumnChangeParam, useTable } from '/@/components/Table';
|
||||
import { getBasicColumns, getBasicShortColumns } from './tableData';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const { createMessage } = useMessage();
|
||||
function onChange() {
|
||||
console.log('onChange', arguments);
|
||||
}
|
||||
const [
|
||||
registerTable,
|
||||
{
|
||||
setLoading,
|
||||
setColumns,
|
||||
getColumns,
|
||||
getDataSource,
|
||||
getRawDataSource,
|
||||
reload,
|
||||
getPaginationRef,
|
||||
setPagination,
|
||||
getSelectRows,
|
||||
getSelectRowKeys,
|
||||
setSelectedRowKeys,
|
||||
clearSelectedRowKeys,
|
||||
},
|
||||
] = useTable({
|
||||
canResize: true,
|
||||
title: 'useTable示例',
|
||||
titleHelpMessage: '使用useTable调用表格内方法',
|
||||
api: demoListApi,
|
||||
columns: getBasicColumns(),
|
||||
defSort: {
|
||||
field: 'name',
|
||||
order: 'ascend',
|
||||
},
|
||||
rowKey: 'id',
|
||||
showTableSetting: true,
|
||||
onChange,
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
},
|
||||
onColumnsChange: (data: ColumnChangeParam[]) => {
|
||||
console.log('ColumnsChanged', data);
|
||||
},
|
||||
});
|
||||
|
||||
function changeLoading() {
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 1000);
|
||||
}
|
||||
function changeColumns() {
|
||||
setColumns(getBasicShortColumns());
|
||||
}
|
||||
function reloadTable() {
|
||||
setColumns(getBasicColumns());
|
||||
|
||||
reload({
|
||||
page: 1,
|
||||
});
|
||||
}
|
||||
function getColumn() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getColumns());
|
||||
}
|
||||
|
||||
function getTableData() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getDataSource());
|
||||
}
|
||||
|
||||
function getTableRawData() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getRawDataSource());
|
||||
}
|
||||
|
||||
function getPagination() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getPaginationRef());
|
||||
}
|
||||
|
||||
function setPaginationInfo() {
|
||||
setPagination({
|
||||
current: 2,
|
||||
});
|
||||
reload();
|
||||
}
|
||||
function getSelectRowList() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getSelectRows());
|
||||
}
|
||||
function getSelectRowKeyList() {
|
||||
createMessage.info('请在控制台查看!');
|
||||
console.log(getSelectRowKeys());
|
||||
}
|
||||
function setSelectedRowKeyList() {
|
||||
setSelectedRowKeys(['0', '1', '2']);
|
||||
}
|
||||
function clearSelect() {
|
||||
clearSelectedRowKeys();
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
changeLoading,
|
||||
changeColumns,
|
||||
reloadTable,
|
||||
getColumn,
|
||||
getTableData,
|
||||
getTableRawData,
|
||||
getPagination,
|
||||
setPaginationInfo,
|
||||
getSelectRowList,
|
||||
getSelectRowKeyList,
|
||||
setSelectedRowKeyList,
|
||||
clearSelect,
|
||||
onChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
318
jeecgboot-vue3/src/views/demo/table/tableData.tsx
Normal file
318
jeecgboot-vue3/src/views/demo/table/tableData.tsx
Normal file
@@ -0,0 +1,318 @@
|
||||
import { FormProps, FormSchema } from '/@/components/Table';
|
||||
import { BasicColumn } from '/@/components/Table/src/types/table';
|
||||
|
||||
export function getBasicColumns(): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
defaultHidden: true,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getBasicShortColumns(): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
width: 150,
|
||||
dataIndex: 'id',
|
||||
sorter: true,
|
||||
sortOrder: 'ascend',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 80,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getMultipleHeaderColumns(): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
sorter: true,
|
||||
children: [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 120,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male', children: [] },
|
||||
{ text: 'Female', value: 'female', children: [] },
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 120,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getCustomHeaderColumns(): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
// title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
slots: { title: 'customTitle' },
|
||||
},
|
||||
{
|
||||
// title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 120,
|
||||
slots: { title: 'customAddress' },
|
||||
sorter: true,
|
||||
},
|
||||
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 120,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male', children: [] },
|
||||
{ text: 'Female', value: 'female', children: [] },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 120,
|
||||
},
|
||||
];
|
||||
}
|
||||
const renderContent = (filed) => {
|
||||
return (record, rowIndex) => {
|
||||
const obj: any = {
|
||||
children: record[filed],
|
||||
attrs: {},
|
||||
};
|
||||
if (rowIndex === 9) {
|
||||
obj.attrs.colSpan = 0;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
};
|
||||
export function getMergeHeaderColumns(): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 300,
|
||||
customCell: renderContent('id'),
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 300,
|
||||
customCell: renderContent('name'),
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
colSpan: 2,
|
||||
width: 120,
|
||||
sorter: true,
|
||||
customCell: (record: any, rowIndex) => {
|
||||
const obj: any = {
|
||||
children: record['address'],
|
||||
attrs: {},
|
||||
};
|
||||
if (rowIndex === 2) {
|
||||
obj.attrs.rowSpan = 2;
|
||||
}
|
||||
if (rowIndex === 3) {
|
||||
obj.attrs.colSpan = 0;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
colSpan: 0,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male', children: [] },
|
||||
{ text: 'Female', value: 'female', children: [] },
|
||||
],
|
||||
customCell: renderContent('no'),
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
width: 200,
|
||||
customCell: renderContent('beginTime'),
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 200,
|
||||
customCell: renderContent('endTime'),
|
||||
},
|
||||
];
|
||||
}
|
||||
export const getAdvanceSchema = (itemNumber = 6): FormSchema[] => {
|
||||
const arr: any = [];
|
||||
for (let index = 0; index < itemNumber; index++) {
|
||||
arr.push({
|
||||
field: `field${index}`,
|
||||
label: `字段${index}`,
|
||||
component: 'Input',
|
||||
colProps: {
|
||||
xl: 12,
|
||||
xxl: 8,
|
||||
},
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
export function getFormConfig(): Partial<FormProps> {
|
||||
return {
|
||||
labelWidth: 100,
|
||||
schemas: [
|
||||
...getAdvanceSchema(5),
|
||||
{
|
||||
field: `field11`,
|
||||
label: `Slot示例`,
|
||||
component: 'Select',
|
||||
slot: 'custom',
|
||||
colProps: {
|
||||
xl: 12,
|
||||
xxl: 8,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
export function getBasicData() {
|
||||
const data: any = (() => {
|
||||
const arr: any = [];
|
||||
for (let index = 0; index < 40; index++) {
|
||||
arr.push({
|
||||
id: `${index}`,
|
||||
name: 'John Brown',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
})();
|
||||
return data;
|
||||
}
|
||||
|
||||
export function getTreeTableData() {
|
||||
const data: any = (() => {
|
||||
const arr: any = [];
|
||||
for (let index = 0; index < 40; index++) {
|
||||
arr.push({
|
||||
id: `${index}`,
|
||||
name: 'John Brown',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
children: [
|
||||
{
|
||||
id: `l2-${index}`,
|
||||
name: 'John Brown',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
},
|
||||
{
|
||||
id: `l3-${index}`,
|
||||
name: 'John Mary',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
})();
|
||||
|
||||
return data;
|
||||
}
|
||||
Reference in New Issue
Block a user