本文主要实现一下两个功能
环境搭建
文章链接
已录制视频
视频链接
这个功能是table-tree功能的附属产品。是为了能在新增表单中,更方便选择上级节点所开发的功能。因此,我们得先把新增表单组件
开发出来
新增、修改逻辑
tree形组件
/src/views/welcome/treeAddOrUpdate.vue
<script setup lang="ts">
import { UnitEntity } from "@/api/tree";
import { ref, reactive } from "vue";
const dialogVisible = ref(false);
let form = reactive(new UnitEntity());
const title = ref("新增表单");
// 定义init方法, 让父组件调用
const init = data => {
console.log(data);
if (data) {
form = data;
title.value = "编辑表单";
} else {
title.value = "新增表单";
}
dialogVisible.value = true;
};
// 暴露方法
defineExpose({ init });
// 提交表单
const submit = () => {
console.log(form);
};
</script>
<template>
<el-dialog v-model="dialogVisible" :title="title">
<el-form :model="form">
<el-form-item label="单元">
<el-input v-model="form.unit" />
</el-form-item>
<el-form-item label="父id">
<el-input v-model="form.pid" />
</el-form-item>
</el-form>
<el-button @click="submit">提交</el-button>
</el-dialog>
</template>
<style lang="scss" scoped></style>
/src/views/welcome/index.vue
<script setup lang="ts">
import { ref, onMounted, nextTick } from "vue";
import TreeAddOrUpdate from "./treeAddOrUpdate.vue";
const dialogVisible = ref(false);
// 引用子组件
const treeAddOrUpdateRef = ref();
// ...
</script>
<template>
<!--ref引用组件-->
<tree-add-or-update v-if="dialogVisible" ref="treeAddOrUpdateRef" />
</template>
/src/views/welcome/index.vue
<script setup lang="ts">
// 新增/修改 都可以使用该方法
const addOrUpdate = data => {
console.log(data);
dialogVisible.value = true;
// nextTick保证treeAddOrUpdateRef能够引用到子组件
nextTick(() => {
// 调用子组件暴露的init方法, 设置数据
treeAddOrUpdateRef.value.init(data);
});
};
</script>
<template>
<el-button type="primary" @click="addOrUpdate">新增</el-button>
</template>
完成以上步骤,我们就可以点击新增表单,但这个界面对于用户来说其实并不美好。谁知道父id是什么?因此我们采用tree-select的形式来提高界面的可使用性
我们使用的是element plus的TreeSelect组件,具体文档如下:[TreeSelect 树形选择 | Element Plus (element-plus.org)]()
export class LabelVo {
id: Number;
label: String;
value: String;
children: Array<LabelVo>;
}
/** 获取全部的treeLabel */
export const getLabelTree = () => {
return http.request<R<Array<LabelVo>>>(
"get",
baseUrlApi("unit/listTreeSelect")
);
};
/** 根据id查询节点 */
export const getNodeById = (id: Number) => {
return http.request<R<LabelVo>>("get", baseUrlApi(`unit/listNode?id=${id}`));
};
<template>
<el-tree-select
v-model="value"
:data="data"
check-strictly
show-checkbox
@check-change="handleCheckChange"
style="width: 240px"
/>
</template>
<script>
// 定义init方法, 让父组件调用
const init = data => {
console.log(data);
if (data) {
form = data;
title.value = "编辑表单";
// 查询上级节点数据(根据id返回{value, label, id})
getNodeById(form.pid).then(res => {
if (res.code === 0) {
value.value = res.data.value;
}
});
} else {
title.value = "新增表单";
}
console.log(form);
dialogVisible.value = true;
};
const value = ref();
const data = ref<Array<LabelVo>>();
const handleCheckChange = (data: LabelVo, checked, indeterminate) => {
console.log(data);
console.log(checked);
if (checked) {
form.pid = data.id;
}
};
</script>
tip: init方法改动
返回tree-selector展示所需数据
@RequestMapping("/listTreeSelect")
public R listTreeSelect() {
List<TbUnit> tbUnitList = unitService.list();
List<LabelVo> list = tbUnitList.stream().map(e -> {
LabelVo vo = new LabelVo();
vo.setValue(e.getUnit());
vo.setLabel(e.getUnit());
vo.setId(e.getId());
vo.setPid(e.getPid());
return vo;
}).collect(Collectors.toList());
// TbUnit -> LabelVo
// 建立map映射(id->index)
HashMap<Integer, Integer> map = new HashMap<>();
for (int index = 0; index < list.size(); index++) {
Integer id = list.get(index).getId();
map.put(id, index);
}
// ...
for (int i = 0; i < list.size(); i++) {
LabelVo node = list.get(i);
Integer pid = node.getPid();
// 有父亲
if (pid != null) {
// 找到pid的父亲, 并把当前节点(node)添加到父亲节点的children里面
Integer indexParent = map.get(pid);
// 获取父亲节点
LabelVo parent = list.get(indexParent);
if (parent.getChildren() == null) {
parent.setChildren(new ArrayList<>());
}
// 向父亲节点的children字段添加当前node
parent.getChildren().add(node);
}
}
// 过滤出一级节点
List<LabelVo> ans = list.stream().filter(e -> e.getPid() == null).collect(Collectors.toList());
return R.ok().put("data", ans);
}
根据id查询数据
// 根据id查询节点数据{value id label}
@RequestMapping("/listNode")
public R listNode(@RequestParam Integer id) {
TbUnit unit = unitService.getById(id);
LabelVo labelVo = new LabelVo();
labelVo.setLabel(unit.getUnit());
labelVo.setValue(unit.getUnit());
labelVo.setId(unit.getId());
return R.ok().put("data", labelVo);
}