vue + Ant Design Vue 表格自定义勾选状态
// 勾选规则
// 1.勾选当前不勾联动选子级
// 2.勾选当前需要联动勾选父级
// 3.勾选当前取消需要联动取消子级和联动取消父级,如果存在平级则不取消父级
<template>
<a-spin :spinning="state.spining">
<div>
<a-modal ref="mModal" id="mModal" class="partiallyUpdatedModals" :maskClosable="false" :visible="props.visible"
v-if="props.visible" :destroy-on-close="true" title="素材部分更新" @ok="handleOk" width="1200px"
@cancel="handleCancle">
<div class="partiallyUpdatedModals_box">
<a-table :columns="state.columns" :data-source="state.tableData" :pagination="false" row-key="id"
:row-selection="{
checkStrictly: true,
hideSelectAll: true,
selectedRowKeys: state.selectedRowKeys,
onSelect: onSelectList,
}">
<template #bodyCell="{ text, record, index, column }">
<template v-if="column.dataIndex == 'name'">
<span v-if="record.pd == 0" style="color: red">{{
record.name
}}</span>
</template>
<template v-if="column.dataIndex === 'operation' && record.pd == 0">
<a style="margin: 0 5px" @click="onEmpty(record)">清空</a>
<a style="margin: 0 5px; color: #ff7875" @click="onDelete(record)">删除</a>
</template>
</template>
</a-table>
</div>
<template #footer>
<a-button @click="handleOk" type="primary">确定</a-button>
<a-button @click="handleCancle">返回</a-button>
</template>
</a-modal>
</div>
</a-spin>
</template>
<script setup lang="ts">
import { createVNode, onMounted, reactive, watch, ref } from "vue";
import { message, Modal } from "ant-design-vue";
import {
ExclamationCircleOutlined,
} from "@ant-design/icons-vue";
const props = defineProps<{
visible: boolean;
}>();
const emit = defineEmits(["handleOk", "partiallyUpdated"]);
const state = reactive({
spining: false,
columns: [
{
title: "素材名称",
dataIndex: "name",
key: "name",
width: "200"
},
{
title: "素材编码",
dataIndex: "key",
key: "200px",
},
{
title: "所属分类",
dataIndex: "age",
key: "age",
width: "200px",
},
{
title: "更新素材明细",
dataIndex: "address",
key: "address",
},
{
title: "操作",
dataIndex: "operation",
width: "200px",
key: "operation",
},
],
tableData: [
{
id: 1,
key: 1,
name: "1",
pd: 0,
age: 60,
address: "1",
parentId: null,
children: [
{
id: 11,
key: 11,
name: "1-1",
age: 42,
parentId: 1,
},
{
id: 12,
key: 12,
name: "1-2",
age: 30,
parentId: 1,
children: [
{
id: 121,
key: 121,
name: "1-2-1",
age: 16,
parentId: 12,
},
],
},
{
id: 13,
key: 13,
name: "1-3",
age: 72,
parentId: 1,
children: [
{
id: 131,
key: 131,
name: "1-3-1",
age: 42,
parentId: 13,
children: [
{
id: 1311,
key: 1311,
name: "1-3-1-1",
age: 25,
parentId: 131,
},
{
id: 1312,
key: 1312,
name: "1-3-1-2",
age: 18,
parentId: 131,
},
],
},
],
}
],
},
{
id: 2,
key: 2,
name: "2",
age: 32,
address: "2",
pd: 0,
parentId: null,
},
{
id: 31,
key: 31,
name: "31",
pd: 0,
age: 60,
address: "31",
parentId: null,
children: [
{
id: 311,
key: 211,
name: "31-1",
age: 42,
parentId: 31,
},
{
id: 312,
key: 312,
name: "31-2",
age: 30,
parentId: 1,
children: [
{
id: 3121,
key: 3121,
name: "31-2-1",
age: 16,
parentId: 312,
},
],
},
{
id: 313,
key: 313,
name: "31-3",
age: 72,
parentId: 31,
children: [
{
id: 3131,
key: 3131,
name: "31-3-1",
age: 42,
parentId: 313,
children: [
{
id: 31311,
key: 31311,
name: "31-3-1-1",
age: 25,
parentId: 3131,
},
{
id: 31312,
key: 31312,
name: "31-3-1-2",
age: 18,
parentId: 3131,
},
],
},
],
}
],
},
],
selectedRowKeys: [] as any,
});
const handleOk = () => { };
const handleCancle = () => {
emit("partiallyUpdated", false);
};
// 规则
// 1.勾选当前不勾选子级
// 2.勾选当前需要联动勾选父级
// 3.勾选当前取消需要联动取消子级
// 4 勾选当前需要联动取消父级,如果存在平级则不取消父级
const onSelectList = (record: any, selected: any, selectedRows: any) => {
console.log('onSelect----record', record);
console.log('onSelect,----selected', selected);
console.log('onSelect---selectedRows', selectedRows);
if (selected) {
onTableSelectChange(record.id);
} else {
onCancellation(record);
}
}
// 选中
const onTableSelectChange = (id: any) => {
let arr = JSON.parse(JSON.stringify(state.tableData))
const result5 = getParentNode(arr, (item: any) => {
return {
// 递归结果
result: item,
// 递归结束条件
endTag: item.id === id,
// 子项的名称
childName: 'children',
// 得到的结果是否删除子项
deleteChildren: true
};
});
if (state.selectedRowKeys.length == 0) {
state.selectedRowKeys = result5.map((itme: any) => itme.id);
} else {
let res = result5.map((itme: any) => itme.id);
res.forEach((item: any) => {
// 检查第二个数组中的元素在第一个数组中是否已存在
let found = state.selectedRowKeys.some((elem: any) => elem == item);
// // 如果未找到,则将该元素添加到结果数组中
if (!found) {
state.selectedRowKeys.push(item);
}
});
}
};
// 取消
const onCancellation = (record: any) => {
// 勾选当前取消需要联动取消子级
let chArr1 = getAllChildIds(record);
let chArr2 = JSON.parse(JSON.stringify(state.selectedRowKeys));
const chResult = chArr2.filter((item: any) => !chArr1.includes(item));
state.selectedRowKeys = chResult;
// 勾选当前需要联动取消父级,如果存在平级则不取消父级
let arr = JSON.parse(JSON.stringify(state.tableData))
const result5 = getParentNode(arr, (item: any) => {
return {
// 递归结果
result: item,
// 递归结束条件
endTag: item.id === record.id,
// 子项的名称
childName: 'children',
// 得到的结果是否删除子项
deleteChildren: true
};
});
let array1 = result5.map((itme: any) => itme.id)
let array2 = state.selectedRowKeys;
const result = array2.filter((item: any) => !array1.includes(item));
state.selectedRowKeys = result;
result.forEach((element: any) => {
onTableSelectChange(element)
});
};
// 递归查找子节点id
function getAllChildIds(obj: any) {
let ids: any = [];
// 获取当前对象的id
if (obj.id) {
ids.push(obj.id);
}
// 检查是否有子节点
if (Array.isArray(obj.children)) {
// 遍历子节点
obj.children.forEach((child: any) => {
// 递归获取子节点的id
const childIds = getAllChildIds(child);
// 将子节点的id添加到数组中
ids = ids.concat(childIds);
});
}
return ids;
}
// 递归查找 当前父级
const getParentNode = (list: any = [], fn = new Function('return {}')) => {
if (!Array.isArray(list)) throw new Error(`'${list}' not an array.`);
if (typeof fn !== 'function') throw new Error(`'${fn}' not a function.`);
for (let i in list) {
let item = JSON.parse(JSON.stringify(list[i])),
{ result = item.id, endTag = item.id === 10, childName = 'children', deleteChildren = true } = fn(item),
isDelet = deleteChildren && item[childName] && typeof result === 'object';
if (endTag) {
if (isDelet) delete item[childName];
return [result];
}
if (item[childName]) {
let node: any = getParentNode(item[childName], fn);
if (node !== undefined) {
if (isDelet) delete item[childName];
return node.concat(result);
}
}
}
}
// 删除
const onDelete = (val: any) => {
Modal.confirm({
title: "提示",
icon: createVNode(ExclamationCircleOutlined),
content: "是否删除?",
width: 460,
okText: "确认",
okType: "danger",
cancelText: "取消",
onOk() {
state.tableData = state.tableData.filter(item => item.key != val.key);
},
onCancel() { },
});
}
// 清空
const onEmpty = (val: any) => {
Modal.confirm({
title: "提示",
icon: createVNode(ExclamationCircleOutlined),
content: "是否清空勾选状态?",
width: 460,
okText: "确认",
okType: "danger",
cancelText: "取消",
onOk() {
let array1 = getAllChildIds(val);
let array2 = state.selectedRowKeys;
const result = array2.filter((item: any) => !array1.includes(item));
state.selectedRowKeys = result;
},
onCancel() { },
});
}
</script>
<style scoped lang="scss">
.partiallyUpdatedModals_box {
height: 600px;
overflow: auto;
}
</style>
<style lang="scss">
.partiallyUpdatedModals .ant-modal-footer {
text-align: center !important;
}
</style>