<template>
<!--{{ t('yl.addBotom') }}这样的都是国际化的中英文,可替换成任意文字 -->
<div class="department">
<div class="departData">
<div class="treeName public-checktree">
<!-- :load-data="onLoadData" -->
<a-tree ref="tree1" :tree-data="treeData" show-icon :defaultExpandAll="true" :selectedKeys="selectedKeys" blockNode>
<template v-slot:title="nodeData">
<a-row>
<a-col :span="24">
<div class="contentTree">
<div class="treeTitle">
<span :style="{ color: formState.id === nodeData.key ? '#F7931E' : '#161616' }">
<span style="color: #161616; font-size: 12px !important" v-if="nodeData.spaceType == '0'"> ● </span
>{{ nodeData.title }}</span
>
</div>
<div class="treeDrop">
<a-dropdown>
<a class="ant-dropdown-link" @click.prevent>
<span style="color: #161616; font-size: 12px !important"> ●●● </span>
</a>
<template #overlay>
<a-menu @click="onClick">
<a-menu-item key="1">
<span v-if="nodeData.spaceType != '1'" size="small" @click="addNode(nodeData)"
><PlusOutlined /></span
></a-menu-item
>
<a-menu-item key="2">
<span size="small" @click="editNode(nodeData)"
><EditOutlined />{{ t('yl.editSpace') }}</span
></a-menu-item
>
<a-menu-item key="3">
<span size="small" @click="deleteNode(nodeData)"
><DeleteOutlined />{{ t('yl.deleteSpace') }}</span
></a-menu-item
>
</a-menu>
</template>
</a-dropdown>
</div>
</div>
</a-col>
</a-row>
</template>
</a-tree>
</div>
<div class="botHandle">
<div class="line"></div>
<div class="botTitle" @click="handleAdd">{{ t('yl.newSpace') }}</div>
</div>
</div>
<div class="departData" v-if="visible">
<div class="treeName" style="padding: 10px">
<a-form ref="formRef" :model="formState" layout="vertical" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row>
<a-col :span="24">
<a-form-item ref="spaceName" :label="t('yl.spaceName')" name="spaceName">
<div class="publicSearch2">
<a-input
style="width: 400px"
v-model:value="formState.spaceName"
:placeholder="t('yl.pleaceSpaceName')"
:disabled="formState.disabled"
@change="inputChange"
/>
</div>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-item ref="spaceType" :label="t('yl.spaceType')" name="spaceType">
<div class="public-radio">
<a-radio-group v-model:value="formState.spaceType" name="radioGroup">
<a-radio value="0">{{ t('yl.regionalSpace') }}</a-radio>
<a-radio value="1">{{ t('yl.entranceExit') }}</a-radio>
</a-radio-group>
</div>
</a-form-item></a-col
>
</a-row>
</a-form>
</div>
<div class="botHandle">
<div class="line"></div>
<div class="botTitle" @click="handleOk">{{ t('yl.save') }}</div>
</div>
</div>
</div>
<!--
<PlusOutlined /> +
<EditOutlined /> 编辑
<DeleteOutlined />
-->
</template>
<script lang="ts">
import { message } from 'ant-design-vue';
import { defineComponent, reactive, toRefs, onMounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import {
DownOutlined,
PlusOutlined,
EditOutlined,
DeleteOutlined,
EllipsisOutlined,
SmileOutlined,
FrownOutlined,
FrownFilled,
} from '@ant-design/icons-vue';
export default defineComponent({
name: 'entranceExit',
components: {
DownOutlined,
PlusOutlined,
EditOutlined,
DeleteOutlined,
EllipsisOutlined,
SmileOutlined,
FrownOutlined,
FrownFilled,
},
props: {
dataList: {
type: Array,
default: () => [],
},
},
emits: ['submitTree', 'checkMast'],
setup(props, { emit }) {
const { t } = useI18n();
const tree = reactive({
treeData: props.dataList,
childrens: [],
});
const selectedKeys = ref();
const visible = ref(false);
const modalTitle = ref('新增空间');
const formRef = ref();
const levelId = ref(0);
const checkSpvoce = ref('0');
const checkStatus = ref(false);
const formState = reactive({
spaceName: '',
depDes: '',
parentId: '',
id: '',
disabled: false,
spaceType: '0',
spaceVos: [],
});
const rules = {
spaceName: [
{
required: true,
message: t('yl.pleaceSpaceName'),
trigger: 'blur',
},
],
spaceType: [
{
required: true,
message: '请选择空间类型',
trigger: 'blur',
},
],
};
// 新增下级按钮
const addNode = (e: any) => {
levelId.value = e.level;
checkSpvoce.value = e.spaceType;
formState.id = e.key;
modalTitle.value = '添加下级';
visible.value = true;
};
// 新增同级
const addNodePeer = (val: any) => {
formState.id = val.key;
formState.spaceName = val.title;
modalTitle.value = '新增同级';
visible.value = true;
};
// 修改按钮
const editNode = (e: any) => {
visible.value = true;
formState.spaceName = e.title;
formState.spaceType = e.spaceType.toString();
formState.id = e.key;
tree.childrens = e.children;
modalTitle.value = '编辑空间';
checkStatus.value = true;
};
// 删除按钮事件
const deleteNode = (e: any) => {
formState.id = e.key;
modalTitle.value = '删除空间';
removeNodeInTree(tree.treeData, formState.id);
};
// 新增下级节点函数
const appendNodeInTree = (id: any, tree: any, obj: any) => {
tree.forEach((ele: any) => {
if (ele.key === id) {
ele.children ? ele.children.push(obj) : (ele.children = [obj]);
} else {
if (ele.children) {
appendNodeInTree(id, ele.children, obj);
}
}
});
return tree;
};
// 删除节点函数
const removeNodeInTree = (treeList: any, id: any) => {
// 通过id从数组(树结构)中移除元素
if (!treeList || !treeList.length) {
return;
}
for (let i = 0; i < treeList.length; i++) {
if (treeList[i].key === id) {
treeList.splice(i, 1);
break;
}
removeNodeInTree(treeList[i].children, id);
}
};
// 增加同级函数
const addSameLevel = (id: any, tree: any, obj: any) => {
let nakeTree = { children: tree };
let parentNode = findParentNode(id, nakeTree);
if (!parentNode.children) {
parentNode.children = [];
}
parentNode.children.push(obj);
return nakeTree.children;
};
// 查找父节点
const findParentNode = (key: any, node: any) => {
if (!node) {
return null;
}
if (node.children) {
let children = node.children;
for (let i = 0; i < children.length; i++) {
if (children[i].key === key) {
return node;
} else {
const res: any = findParentNode(key, children[i]);
if (res) {
return res;
}
}
}
}
return null;
};
// 修改当前节点数据
const updateNodeInTree = (treeList: any, id: any, obj: any) => {
if (!treeList || !treeList.length) {
return;
}
for (let i = 0; i < treeList.length; i++) {
if (treeList[i].key == id) {
treeList[i] = obj;
break;
}
updateNodeInTree(treeList[i].children, id, obj);
}
};
// 给树添加层级
const handleTreeData = (data: any, level: any) => {
if (data instanceof Array) {
data.map((item) => {
item['level'] = level;
if (item.children instanceof Array) {
handleTreeData(item.children, level + 1);
}
});
}
return data;
};
//递归修改属性结构
const mapTree = (list: any) => {
let TreeList = list.map((item: any) => {
return {
spaceName: item.title,
key: item.key,
spaceType: item.spaceType ? item.spaceType : '0',
childrens: item.children && item.children.length ? mapTree(item.children) : [],
slots: {
icon: 'smile',
},
};
});
return TreeList;
};
watch(
() => tree.treeData,
(list) => {
mapTree(tree.treeData);
handleTreeData(list, 0);
emit('submitTree', mapTree(tree.treeData));
},
{
deep: true,
}
);
const handleAdd = () => {
visible.value = true;
modalTitle.value = '新增空间';
};
const handleOk = () => {
formRef.value
.validate()
.then(() => {
let params = {
title: formState.spaceName,
key: new Date().getTime(),
children: [],
spaceType: formState.spaceType,
};
if (modalTitle.value == '添加下级' && checkSpvoce.value === '1') return message.warn('出入口下不可创建');
if (levelId.value >= 5) return message.warn('最多可添加6级');
if (modalTitle.value == '添加下级') {
//新增部门
appendNodeInTree(formState.id, tree.treeData, params);
} else if (modalTitle.value == '新增同级') {
addSameLevel(formState.id, tree.treeData, params);
} else if (modalTitle.value == '编辑空间') {
const tree_list = {
title: formState.spaceName,
key: new Date().getTime(),
spaceType: formState.spaceType,
children: tree.childrens ? tree.childrens : [],
};
if (tree.childrens.length > 0 && formState.spaceType == '1') {
return message.warn('该节点下有子节点,不可修改为出入口类型');
}
updateNodeInTree(tree.treeData, formState.id, tree_list);
} else if (modalTitle.value == '新增空间') {
let faterData: any = {
title: formState.spaceName,
key: new Date().getTime(),
children: [],
spaceType: formState.spaceType,
};
tree.treeData.push(faterData);
} else {
message.warn('请选择节点');
}
// mapTree(tree.treeData);
// handleTreeData(list, 0);
visible.value = false;
checkStatus.value = false;
emit('checkMast', false);
return tree.treeData;
})
.catch((error: any) => {});
};
const inputChange = (e) => {
emit('checkMast', true);
};
onMounted(() => {});
return {
...toRefs(tree),
selectedKeys,
addNode,
addNodePeer,
deleteNode,
editNode,
visible,
handleOk,
formRef,
t,
formState,
rules,
modalTitle,
removeNodeInTree,
handleAdd,
levelId,
checkSpvoce,
checkStatus,
inputChange,
};
},
});
</script>
<style lang="scss" scoped>
.department {
display: flex;
justify-content: space-between;
.departData {
width: 49%;
background: #f6f6f6;
border-radius: 6px 6px;
padding: 16px;
.treeName {
min-height: 400px;
overflow: auto;
.contentTree {
display: flex;
justify-content: space-between;
}
}
.botHandle {
text-align: center;
.line {
border: 1px solid #e6e6e6;
}
.botTitle {
font-size: 14px;
font-weight: 400;
color: #f7931e;
padding-top: 16px;
}
}
}
}
:deep(.ant-input) {
border-radius: 26px !important;
background: #ffffff !important;
widows: 400px !important;
}
:deep(.anticon svg) {
color: #161616;
font-size: 16px;
}
// 叶子在右
:deep(.ant-tree li span.ant-tree-switcher) {
float: left !important;
}
</style>
vue3 + ant deigin vue + js 实现树的增删改
最新推荐文章于 2023-12-20 21:31:08 发布