需求:vue树形结构图显示

需求: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>

也是拷贝别人之后改了些代码的,这样方便点

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值