feat: vxe/antd可编辑表格适配器 & 可编辑demo

master
dap 5 months ago
parent 97231de753
commit c92d6a2b1d

@ -4,7 +4,6 @@ import type { VxeGridProps } from '#/adapter/vxe-table';
import { nextTick, onMounted } from 'vue'; import { nextTick, onMounted } from 'vue';
import { JsonPreview } from '@vben/common-ui'; import { JsonPreview } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { import {
Button, Button,
@ -18,6 +17,16 @@ import {
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
/**
* 与antdv集成 可以参考这里使用自定义插槽
* https://vxetable.cn/other4/#/table/other/antd
*/
const options = ['前端佬', '后端佬', '组长'].map((item) => ({
label: item,
value: item,
}));
const gridOptions: VxeGridProps = { const gridOptions: VxeGridProps = {
editConfig: { editConfig: {
// //
@ -32,12 +41,19 @@ const gridOptions: VxeGridProps = {
}, },
checkboxConfig: {}, checkboxConfig: {},
editRules: { editRules: {
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }], name: [{ required: true, message: '请输入姓名' }],
age: [ age: [
{ required: true, message: '请输入年龄', trigger: 'blur' }, { required: true, message: '请输入年龄' },
{ min: 0, max: 200, message: '年龄必须为1-200' }, { type: 'number', min: 0, max: 200, message: '年龄必须为1-200' },
],
job: [{ required: true, message: '请选择工作' }],
phone: [
{
required: true,
message: '请输入正确的手机号',
pattern: /^1[3-9]\d{9}$/,
},
], ],
job: [{ required: true, message: '请选择工作', trigger: 'blur' }],
}, },
columns: [ columns: [
{ {
@ -61,8 +77,16 @@ const gridOptions: VxeGridProps = {
} }
return <span>{row.name}</span>; return <span>{row.name}</span>;
}, },
edit: ({ row }) => { edit: (props) => {
return <Input placeholder={'请输入'} v-model:value={row.name} />; const { row, $grid } = props;
return (
<Input
onChange={() => $grid?.updateStatus(props)}
placeholder={'请输入'}
v-model:value={row.name}
/>
);
}, },
}, },
}, },
@ -78,10 +102,12 @@ const gridOptions: VxeGridProps = {
} }
return <span>{row.age}</span>; return <span>{row.age}</span>;
}, },
edit: ({ row }) => { edit: (props) => {
const { row, $grid } = props;
return ( return (
<InputNumber <InputNumber
class="w-full" class="w-full"
onChange={() => $grid?.updateStatus(props)}
placeholder={'请输入'} placeholder={'请输入'}
v-model:value={row.age} v-model:value={row.age}
/> />
@ -90,8 +116,8 @@ const gridOptions: VxeGridProps = {
}, },
}, },
{ {
field: '工作', field: 'job',
title: 'job', title: '工作',
align: 'left', align: 'left',
editRender: {}, editRender: {},
slots: { slots: {
@ -101,15 +127,14 @@ const gridOptions: VxeGridProps = {
} }
return <span>{row.job}</span>; return <span>{row.job}</span>;
}, },
edit: ({ row }) => { edit: (props) => {
const options = ['前端佬', '后端佬', '组长'].map((item) => ({ const { row, $grid } = props;
label: item,
value: item,
}));
return ( return (
<Select <Select
allowClear={true}
class="w-full" class="w-full"
getPopupContainer={getPopupContainer} onChange={() => $grid?.updateStatus(props)}
options={options} options={options}
placeholder={'请选择'} placeholder={'请选择'}
v-model:value={row.job} v-model:value={row.job}
@ -118,6 +143,31 @@ const gridOptions: VxeGridProps = {
}, },
}, },
}, },
{
field: 'phone',
title: '手机号',
align: 'left',
editRender: {},
slots: {
default: ({ row }) => {
if (!row.phone) {
return <span class="text-red-500">未填写</span>;
}
return <span>{row.phone}</span>;
},
edit: (props) => {
const { row, $grid } = props;
// $grid?.updateStatus
return (
<Input
onChange={() => $grid?.updateStatus(props)}
placeholder={'请输入'}
v-model:value={row.phone}
/>
);
},
},
},
{ {
field: 'action', field: 'action',
title: '操作', title: '操作',
@ -136,18 +186,22 @@ const gridOptions: VxeGridProps = {
}, },
}, },
], ],
height: 'auto', // height: 500,
keepSource: true, keepSource: true,
pagerConfig: { pagerConfig: {
enabled: false, enabled: false,
}, },
proxyConfig: { proxyConfig: {
enabled: false, enabled: true,
}, },
toolbarConfig: { toolbarConfig: {
enabled: false, enabled: false,
}, },
showOverflow: false, showOverflow: false,
cellConfig: {
//
height: 50,
},
}; };
const [BasicTable, tableApi] = useVbenVxeGrid({ const [BasicTable, tableApi] = useVbenVxeGrid({
@ -160,16 +214,19 @@ onMounted(async () => {
name: '张三', name: '张三',
age: 18, age: 18,
job: '前端佬', job: '前端佬',
phone: '',
}, },
{ {
name: '李四', name: '李四',
age: 19, age: 19,
job: '后端佬', job: '后端佬',
phone: '',
}, },
{ {
name: '王五', name: '王五',
age: 20, age: 20,
job: '组长', job: '组长',
phone: '',
}, },
]; ];
await nextTick(); await nextTick();
@ -187,6 +244,7 @@ async function handleRemove() {
async function handleValidate() { async function handleValidate() {
const result = await tableApi.grid.validate(true); const result = await tableApi.grid.validate(true);
console.log(result);
if (result) { if (result) {
message.error('校验失败'); message.error('校验失败');
} else { } else {
@ -210,20 +268,23 @@ function getData() {
</script> </script>
<template> <template>
<BasicTable> <div>
<template #toolbar-tools> <div class="mb-4">
<Space> <!--
https://github.com/x-extends/vxe-table/issues/1752#issuecomment-1623165630
因为编辑表格判断点击单元格之外的元素会取消编辑状态此时需要事件拦截
vxe-table 提供了更加简单的方法
只需要在弹出框不属于单元格之内的元素添加class=vxe-table--ignore-clear 即可
element-plus el-select 为例设置 popper-class "vxe-table--ignore-clear" 可以解决
需要更高级拦截方法可以参考 https://vxetable.cn/#/table/interceptor/api
-->
<Space class="vxe-table--ignore-clear">
<a-button @click="getData"></a-button> <a-button @click="getData"></a-button>
<a-button @click="handleValidate"></a-button> <a-button @click="handleValidate"></a-button>
<a-button danger @click="handleRemove"> </a-button> <a-button danger @click="handleRemove"> </a-button>
<a-button <a-button type="primary" @click="handleAdd"> </a-button>
type="primary"
v-access:code="['system:config:add']"
@click="handleAdd"
>
{{ $t('pages.common.add') }}
</a-button>
</Space> </Space>
</template> </div>
</BasicTable> <BasicTable />
</div>
</template> </template>

@ -39,6 +39,7 @@
"@vben/utils": "workspace:*", "@vben/utils": "workspace:*",
"@vueuse/core": "catalog:", "@vueuse/core": "catalog:",
"@vueuse/motion": "catalog:", "@vueuse/motion": "catalog:",
"@vxe-ui/plugin-render-antd": "^4.0.18",
"echarts": "catalog:", "echarts": "catalog:",
"vue": "catalog:", "vue": "catalog:",
"vxe-pc-ui": "catalog:", "vxe-pc-ui": "catalog:",

@ -6,6 +6,15 @@ import { usePreferences } from '@vben/preferences';
import { useVbenForm } from '@vben-core/form-ui'; import { useVbenForm } from '@vben-core/form-ui';
/**
* ant-design-vue
*
* (select)
*
* @see https://vxeui.com/other4/#/plugin-render-antd/start/full/npmInstall
* @see https://vxetable.cn/other4/#/table/other/antd
*/
import VxeUIPluginRenderAntd from '@vxe-ui/plugin-render-antd';
import { import {
VxeButton, VxeButton,
VxeCheckbox, VxeCheckbox,
@ -47,6 +56,8 @@ import {
import { extendsDefaultFormatter } from './extends'; import { extendsDefaultFormatter } from './extends';
import '@vxe-ui/plugin-render-antd/dist/style.css';
// 是否加载过 // 是否加载过
let isInit = false; let isInit = false;
@ -96,6 +107,7 @@ export function initVxeTable() {
// VxeUI.component(VxeTextarea); // VxeUI.component(VxeTextarea);
VxeUI.component(VxeTooltip); VxeUI.component(VxeTooltip);
VxeUI.component(VxeUpload); VxeUI.component(VxeUpload);
VxeUI.use(VxeUIPluginRenderAntd);
isInit = true; isInit = true;
} }

Loading…
Cancel
Save