树形组件(子组件)
<template>
<div class="tree-table">
<div class="table-header">
<div class="table-row">
<div class="table-cell">标题</div>
<div class="table-cell">项目进度</div>
<div class="table-cell">开始时间</div>
<div class="table-cell">截至时间</div>
<div class="table-cell">所属模块</div>
<div class="table-cell">负责人</div>
<div class="table-cell">优先级</div>
<div class="table-cell">状态</div>
</div>
</div>
<!-- <div class="table-body">
<TreeNode v-for="item in data" :key="item.id" :node="item" :parentNode="data" />
</div> -->
<div class="table-body" v-for="item in data" :key="item.id">
<TreeNode :parentNode="data" :node="item" />
</div>
</div>
</template>
<script>
import TreeNode from './components/TreeNode.vue'; // 递归组件
export default {
components: {
TreeNode
},
data() {
return {
data: [
{
id: 1,
level: 1,
title: '节点1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [
{
id: 3,
level: 2,
title: '子节点1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [
{
id: 5,
level: 3,
title: '孙节点1-1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: true,
children: [{
id: 6,
title: '孙孙节点1-1-1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
children: [], //一定要有这个字段,否则子级不会显示出来
// expanded: true,
}]
},
],
},
{
id: 4,
level: 2,
title: '子节点1-2',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [],
},
],
},
{
id: 1,
level: 1,
title: '节点1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [
{
id: 3,
level: 2,
title: '子节点1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [
{
id: 5,
level: 3,
title: '孙节点1-1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: true,
children: [{
id: 6,
title: '孙孙节点1-1-1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
children: [], //一定要有这个字段,否则子级不会显示出来
// expanded: true,
}]
},
],
},
{
id: 4,
level: 2,
title: '子节点1-2',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [],
},
],
},
{
id: 1,
level: 1,
title: '节点1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [
{
id: 3,
level: 2,
title: '子节点1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [
{
id: 5,
level: 3,
title: '孙节点1-1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: true,
children: [{
id: 6,
title: '孙孙节点1-1-1-1',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
children: [], //一定要有这个字段,否则子级不会显示出来
// expanded: true,
}]
},
],
},
{
id: 4,
level: 2,
title: '子节点1-2',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [],
},
],
}
],
};
},
};
</script>
<style>
.tree-table {
border: 1px solid #ccc;
width: 100%;
}
.table-header {
background: #f1f1f1;
}
.table-row {
display: flex;
/* padding: 8px; */
cursor: pointer;
}
.table-cell {
display: flex;
border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
flex: 1;
height: 48px;
line-height: 48px;
/* text-align: center; */
}
.children {
/* padding-left: 20px; */
}
.toggle-icon {
/* margin-right: 5px; */
}
</style>
父组件中引入树形表格
<template>
<div>
<div class="table-row" v-if="node.level == 1">
<div class="table-cell">
<!-- <span @click="toggleExpand"
style="display: inline-block;width: 48px;height:48px;line-height:48px;text-align: center;"
class="el-icon-arrow-down toggle-icon" v-if="node.children.length && node.expanded"></span>
<span @click="toggleExpand"
style="display: inline-block;width: 48px;height:48px;line-height:48px;text-align: center;"
class="el-icon-arrow-right toggle-icon" v-if="node.children.length && !node.expanded"></span> -->
<span @click="toggleExpand"
style="display: inline-block;width: 48px;height:48px;line-height:48px;text-align: center;"
:class="['toggle-icon', node.expanded ? 'el-icon-arrow-down' : 'el-icon-arrow-right']"></span>
<span @click="textToInput(node.title)" v-if="oneLevel">{{ node.title }}</span>
<el-input @blur="closeOneLevelInput" v-model="oneInput" v-else style="width: 120px;"></el-input>
</div>
</div>
<div class="table-row" v-else>
<div class="table-cell">
<span
style="border-right:1px solid #ccc;display: inline-block;width: 48px;height: 48px;line-height: 48px;text-align: center;">{{
node.id }}</span>
<div :style="{ paddingLeft: `${depth * 20}px` }">
<!-- <span style="display: inline-block;width: 20px;text-align: center;"
class="el-icon-arrow-down toggle-icon" v-if="node.children.length && node.expanded"></span>
<span style="display: inline-block;width: 20px;text-align: center;"
class="el-icon-arrow-right toggle-icon" v-if="node.children.length && !node.expanded"></span> -->
<span v-if="node.children.length" @click="toggleExpand"
style="display: inline-block;width: 20px;text-align: center;"
:class="['toggle-icon', node.expanded ? 'el-icon-arrow-down' : 'el-icon-arrow-right']"></span>
<span>{{ node.title }}</span>
</div>
</div>
<div class="table-cell">{{ node.progress }}</div>
<div class="table-cell">
<span @click="textToSDatePicker(node.startTime)" v-if="!isShowStartTimePicker">{{ node.startTime
}}</span>
<el-date-picker @blur="closeSDatePicker" v-model="startTime" type="date" placeholder="选择日期"
v-if="isShowStartTimePicker">
</el-date-picker>
</div>
<div class="table-cell">
<span @click="textToEDatePicker(node.endTime)" v-if="!isShowEndTimePicker">{{ node.endTime }}</span>
<el-date-picker @blur="closeEDatePicker" v-model="endTime" type="date" placeholder="选择日期"
v-if="isShowEndTimePicker">
</el-date-picker>
</div>
<div class="table-cell">{{ node.module }}</div>
<div class="table-cell">{{ node.director }}</div>
<div class="table-cell">{{ node.priority }}</div>
<div class="table-cell">{{ node.status }}</div>
</div>
<div v-if="node.expanded && node.children.length" class="children">
<TreeNode v-for="child in node.children" :key="child.id" :node="child" :parentNode="node.children"
:depth="depth + 1" />
</div>
<div v-if="node.level == 2 && isLastChild(node, parentNode)"
style="height: 48px;border-top: 1px solid #ccc;padding-left:10px;display: flex;align-items: center;">
<span @click="addRow(node, parentNode)" class="el-icon-circle-plus-outline" style="font-size: 22px;"></span>
</div>
</div>
</template>
<script>
export default {
name: 'TreeNode',
props: {
parentNode: {
type: Array,
required: true,
},
node: {
type: Object,
required: true,
},
depth: {
type: Number,
default: 0
}
},
data() {
return {
startTime: '',
endTime: '',
oneLevel: true,
isShowStartTimePicker: false,
isShowEndTimePicker: false,
oneInput: '',
}
},
methods: {
addRow(node, parentNode) {
this.parentNode.push({
id: 7,
level: 2,
title: '子节点1-3',
progress: 0.3,
startTime: '2024-06-30',
endTime: '2024-09-30',
module: '热电偶',
director: '文歆',
priority: 1,
status: 0,
expanded: false,
children: [],
})
},
closeSDatePicker() {
console.log("执行了");
this.isShowStartTimePicker = false;
},
closeEDatePicker() {
this.isShowEndTimePicker = false;
},
textToSDatePicker(date) {
this.isShowStartTimePicker = true;
},
textToEDatePicker(date) {
this.isShowEndTimePicker = true;
},
textToInput(title) {
this.oneLevel = false;
this.oneInput = title;
},
closeOneLevelInput() {
console.log("执行了");
this.oneLevel = true;
},
isLastChild(node, parentNode) {
// console.log("node", node);
// console.log("parentNode", parentNode);
//判断是否是最后一个子节点
return parentNode[parentNode.length - 1] === node;
},
toggleExpand() {
this.node.expanded = !this.node.expanded;
},
},
};
</script>
<style scoped>
.children {
/* padding-left: 20px; */
}
.toggle-icon {
/* margin-right: 5px; */
}
</style>