需求:vue树形结构图显示
树形分支图,接口和路由要自己写.直接上代码
按需做,有些地方自己改改就好了
报错安装less的话看我上一篇发布的就可以解决
// 组织架构
<template>
<div id='newTreeView'>
<div class="ntv-company">
<div class="ntvc-child">
<span id="10">信息列表</span>
<span></span>
</div>
</div>
<div class="ntv-line1">
<div></div>
</div>
<div class="ntv-list" v-for='(el, inx) in departmentList' :key='el.id' :style='{"margin-top": inx === 0 ? "120px" : "0"}'> <!-- 循环显示每行 -->
<div :id='"ntvList" + inx'></div> <!-- 用来撑开每一行与左侧的距离 -->
<div class="ntv-item" v-for='(item, index) in el' :key='item.id' :style='{"flex": inx === 0 && el.length < 6 ? "1" : ""}' @dblclick='twoClick(item.id)' > <!-- 循环显示每个部门 -->
<div class='ntv-line2'> <!-- 部门上方的线条 -->
<div class="ntvl2-left" :style='{"border-top": index === 0 ? "0" : ""}'></div>
<div class="ntvl2-right" :style='{"border-top": index === el.length - 1 ? "0" : ""}'></div>
</div>
<div @click='showChildDepartment(item, inx, index)' v-if='item.areaName !== "新增部门"' class="ntv-content"> <!-- 部门详情 -->
<span class='ntv-span1'>{{item.areaName}}</span>
<!--添加名牌下边的ID数字-->
<span class='ntv-span2'></span>
</div>
<div v-else class="ntv-addcontent"> <!-- 新增部门 -->
<span>{{item.areaName}}</span>
</div>
<div v-if='curDepartmentId[inx] === item.id && item.children' class="ntv-line3"> <!-- 部门下方的线条 -->
<div></div>
</div>
</div>
</div>
<!--弹出表格框-->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body >
<el-form ref="form" :model="form" :rules="rules" label-width="80px" >
<el-form-item label="手机号" prop="mobile">
<el-input v-model="form.mobile" placeholder="请输入手机号" />
</el-form-item>
<el-form-item label="姓名" prop="userName">
<el-input v-model="form.userName" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="推荐人" prop="referrer">
<el-input v-model="form.referrer" placeholder="请输入推荐人" />
</el-form-item>
<!--<el-form-item label="账号推荐人" prop="referrerAccount">
<el-input v-model="form.referrerAccount" placeholder="请输入账号推荐人" />
</el-form-item>
<el-form-item label="推荐链" prop="referrerChain">
<el-input v-model="form.referrerChain" placeholder="请输入推荐链" />
</el-form-item>-->
<el-form-item label="用户类型" prop="userType">
<el-select v-model="form.userType" placeholder="请选择用户类型">
<el-option
v-for="dict in userTypeOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="parseInt(dict.dictValue)"
></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="账户余额" prop="accountBalance">
<el-input v-model="form.accountBalance" placeholder="请输入账户余额" />
</el-form-item>
<el-form-item label="删除标志" prop="delFlag">
<el-input v-model="form.delFlag" placeholder="请输入删除标志" />
</el-form-item>-->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
//注:自己的地址,此处引入树形图配置文件(写接口的地方)
import { accountListById, addBox} from "@/api/cms/treeAccount";
export default {
name: 'newTreeView',
methods: {
//树形图数据,接口地址,带参传
accountListById1() {
accountListById(1).then(response => {
console.log("response",response.row)
this.tree_data = response.row;
console.log("this.tree_data",this.tree_data)
this.departmentList.push(this.tree_data)
});
},
//点击弹出对话框
twoClick (e){
//当前点击id值
console.log(e)
this.reset();
this.form.userId = e;
this.open = true;
this.title = "请输入信息 ";
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
userId: null,
mobile: null,
//passWord: null,
userName: null,
//avatar: null,
referrer: null,
//referrerAccount: null,
//referrerChain: null,
userType: null,
//accountBalance: null,
//allBonusAmount: null,
//allWalletAmount: null,
//allTakeCashAmount: null,
//delFlag: null,
//createTime: null,
// updateTime: null,
//reserved1: null,
//reserved2: null,
//reserved3: null,
};
this.resetForm("form");
},
//提交按钮,返回后台数据
submitForm() {
addBox(this.form,).then(response => {
if (response.code === 200) {
this.msgSuccess("新增成功");
this.open = false;
this.form();
}
});
},
showChildDepartment (item, inx, index) { // 当前部门对象, 父部门下标, 当前部门对象下标
/* 封装数据结构 */
if (this.curDepartmentId[inx]) {
this.departmentList = this.departmentList.splice(0, inx + 1) // 如果点击过该行 则删除该行下方所有行
for (let i in this.curDepartmentId) {
if (i > inx) {
delete this.curDepartmentId[i] // 删除行点击过的部门的记录
}
}
this.curDepartmentId[inx] = item.id
} else { // 如果没有点击过该行 则添加该行 以该行下标为key 当前点击部门id为value 用来控制点击过的部门下方的竖线的显示
this.curDepartmentId[inx] = item.id
}
if (!item.children) return // 如果点击的该部门没有子部门 则结束方法
let flag = true
item.children.forEach(item => { // 如果子部门中没有新增部门则添加 有则跳过
if (item.areaName === '新增部门') {
flag = false
}
})
if (flag) {
item.children.push({id: new Date().valueOf(), areaName: '新增部门', children: []})
}
this.departmentList.push(item.children)
/* 设置每一行的左边距 */
let curId = 'ntvList' + (inx + 1) // 每一行list的id
if (inx === 0) { // 当点击第一行部门时 设置子部门的左边距
if (item.children.length / 2 > index + 1) { // 如果子部门长度 / 2 超出了当前点击的部门到最左侧的宽度 则子部门左边距为0
this.listMarginLeft = 0
} else { // 如果子部门的长度 / 2 不大于当前点击部门到最左侧的距离 则设置子部门在当前部门下居中显示
this.listMarginLeft = ((index + 4) * 128) - (item.children.length / 2 * 128)
}
}
let marginLeft = document.getElementById('ntvList' + inx).style.marginLeft.replace('px', '') // 获取当前点击部门所在行的左边距 用来计算下一行(子部门的左边距)
if (inx !== 0 && item.children) { // 设置点击第二行及后面的行时 子部门的左边距
// 子部门的左边距 = 上一列(父部门)左边距 + (当前点击部门的下标 + 0.5) * 128(单个部门的长度) - 子部门行一般的长度 (结合树状图理解)
this.listMarginLeft = Number(marginLeft) + ((index + 0.5) * 128) - (item.children.length / 2 * 128)
this.listMarginLeft = this.listMarginLeft >= 0 ? this.listMarginLeft : 0
}
setTimeout(() => {
document.getElementById(curId).style.marginLeft = this.listMarginLeft + 'px'
}, 50)
}
},
data () {
return {
listMarginLeft: 0, // 子部门左边距
curDepartmentId: {}, // 存放所有点击过的部门id 控制点击过的部门下方的 竖线的显示
departmentList: [], // 存放每一行数据的数组,结构为 [[{第一行部门}], [{第二行部门}], [{第三行部门}]...]
tree_data: [], // 总数据 一般是从后台请求接口得到
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 用户类型字典
userTypeOptions: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
mobile: null,
referrer: null,
referrerAccount: null,
referrerChain: null,
userType: null,
createTime: null,
},
// 表单参数
form: {},
// 表单校验
rules: {
mobile: [
{ required: true, message: "手机号不能为空", trigger: "blur" }
],
}
}
},
created () {
/* 数据结构为对象数组,每个对象中也有子对象数组,以此类推 */
//调用方法,此处显示后台数据
this.accountListById1();
console.log("created tree_data",this.tree_data)
}
}
</script>
<style lang="less">
#newTreeView {
overflow: auto;
padding-bottom: 20px;
.ntv-line3 {
width: 100%;
height: 30px;
margin-top: 10px;
> div {
width: 50%;
height: 100%;
border-right: 2px solid #ACB7C3;
}
}
.ntv-line2 {
margin-bottom: 10px;
width: 100%;
height: 33px;
display: flex;
.ntvl2-left {
width: 50%;
height: 100%;
border-right: 2px solid #ACB7C3;
border-top: 2px solid #ACB7C3;
}
.ntvl2-right {
width: calc(100% - 50% - 2px);
height: 100%;
border-top: 2px solid #ACB7C3;
}
}
.ntv-line1 {
margin-top: 8px;
position: absolute;
top: 117px;
left: 399px;
> div {
height: 30px;
width: 2px;
background-color: #ACB7C3;
}
}
.ntvc-child {
width: 132px;
height: 66px;
background: rgba(22,119,255,1);
border-radius: 6px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.ntv-company {
width: 142px;
height: 76px;
background: rgba(22,119,255,0.4);
box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.1);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
color: #FFFFFF;
position: absolute;
left: 590px;
top: 42px;
}
.ntv-span1 {
color: #4A4A4A;
font-size: 14px;
font-weight: 600;
}
.ntv-span2 {
color: #ACB7C3;
font-size: 12px;
}
.ntv-addcontent {
width: 108px;
height: 52px;
background: rgba(255,255,255,1);
box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.1);
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
color: #9B9B9B;
font-size: 14px;
}
.ntv-content {
width: 108px;
height: 52px;
background: rgba(255,255,255,1);
box-shadow: 0px 2px 8px 0px rgb(0, 0, 0);
border-radius: 4px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: pointer;
}
.ntv-item {
min-width: 128px;
display: flex;
flex-direction: column;
align-items: center;
}
.ntv-list {
display: flex;
margin-top: 114px;
position: relative;
}
}
</style>
也是拷贝别人之后改了些代码的,这样方便点