樹形結構實現

最近在寫樹形結構,發現能夠直接拿來用又很舒服的很難找,就本身寫了兩種~css

如下是效果~html


前者是本身徹底用jquery寫的,後者藉助element-UI寫的,下邊是代碼。本人Node後端,大佬輕噴~node

<template>  <div class="md-layout user-relation">    <!-- 分割線 -->    <div class="md-layout-item md-size-100 line1">      <v-divider />    </div>    <!-- 1.搜索(Safumax LIVE)待審覈入金記錄 -->    <!-- <md-button class="md-primary md-sm padding" @click="$router.push({name:'agentForm'})">建立代理</md-button> -->    <span class="buttonspace"></span>    <!-- 2.代理管理表 -->    <div class="md-layout-item md-size-100">      <md-card>        <!-- 標題 -->        <md-card-header class="md-card-header-icon md-card-header-green">          <div class="card-icon">            <md-icon>repeat</md-icon>          </div>          <h4 class="title">客戶層級關係</h4>        </md-card-header>        <md-card-header>          <div class="md-layout">            <!-- 1.暱稱 -->            <div class="input md-layout-item md-size-30 md-xsmall-size-100">              <el-select                clearable                filterable                v-model="filter.id"                remote                placeholder="請輸入中文名或MT帳號"                :remote-method="remoteMethod"                @change="getData"                :loading="loading"              >                <el-option                  v-for="item in users"                  :key="item.id"                  :label="`${item.chineseName}--${item.phone}--${item.email}`"                  :value="item.id"                ></el-option>              </el-select>            </div>            <!-- 7.表單提交按鈕 -->            <div class="md-layout-item md-size-70">              <el-button                type="success" size=""                style="float:left;margin-top:0px"                @click="getData()"              >查詢</el-button>            </div>          </div>        </md-card-header>        <!-- 內容 -->        <md-card-content>          <div v-show="powershow && item" :class="isbeyong? 'powerleft':'powertop'" id="powerdiv">            <div class="item_div">              <md-icon>face</md-icon>              {{item.chineseName}}            </div>            <div class="item_div">              <span class="item_span">帳戶ID: {{item.id}}</span>              <span class="item_span">註冊時間: {{$method.timeformatYMD(item.create_time)}}</span>              <span class="item_span">手機號碼: {{item.phone}}</span>            </div>            <!-- <div class="item_div">            </div> -->            <div class="item_div">              <span class="item_span">電子郵箱: {{item.email}}</span>            </div>            <div class="item_div">              <span class="item_span mtid">MT帳號: {{(item.mtids && item.mtids.length>5)? item.mtids.slice(0,5).join()+'......' : item.mtids && item.mtids.join()}}</span>            </div>            <div class="item_div">              <md-icon>hdr_weak</md-icon>            </div>          </div>          <div class="all">            <div class="first-main">              <div class="item firstItem" v-for="item in data" :key="item.id" :id="item.id" @click="loadAndCreate(item)">                {{item.chineseName}}                <span :id="`${item.id}content`" style="display:none">{{JSON.stringify(item)}}</span>                <i v-show="item.agentCount>0" class="icon el-icon-arrow-right"></i>              </div>            </div>          </div>        </md-card-content>      </md-card>    </div>  </div></template><script>import $ from "jquery";import { setTimeout, setInterval } from 'timers';export default {  data() {    return {      loading: false,      data: [],      getRelation: false,      users: [],      powershow:false,      isbeyong: false,      createtime:0,      destroytime:0,      item:{},      filter: {        id: ""      }    };  },  async mounted() {    await this.loadAndCreate();    this.bindEvent()  },  methods: {    async getData() {      this.data = await this.list();      $('.main').remove()    },    // 查找    async list(id) {      if (this.getRelation) return;      this.getRelation = true;      const data = { ...this.filter };      if (id) data.id = id;      const res = await this.$axios.get("userRelation", { params: data });      this.getRelation = false;      this.addchildren(res.data.result.user.children);      return [...[res.data.result.user]];    },    // 處理children    addchildren(list) {      for (let item of list) {        if (item.agentCount > 0) {          item.children = [{}];        }      }    },    // 遠程搜索    async remoteMethod(query) {      this.loading = true;      this.loading = false;      const res = await this.$axios.get("getUsersByName", {        params: { content: query }      });      this.users = res.data.result.users;    },    // html拼接    async loadAndCreate(data){      const _this = this;      const id = (data && data.id) || (data && data.currentTarget && data.currentTarget.id) || '';      let result = await this.list(id);      if(!result) return;      if(!id) this.data = result      let html = '<div class="main">'      const user = result[0];      $(`#${user.id}`).siblings().css({'background-color': '','color': ''}) $(`#${user.id}`).css({'background-color': '#f2f7fa','color': '#5992c8'}) if( user.children.length < 1) return user.children.forEach(item=>{ html += ` <div class="item" id="${item.id}"> ${item.chineseName} <span id="${item.id}content" style="display:none">${JSON.stringify(item)}</span> ${item.children? `<i class="icon el-icon-arrow-right"></i>`:``} </div>` }) html += '</div>' $(`#${user.id}`).parent().nextAll().remove() $(`#${user.id}`).parent().parent().append(html) this.bindEvent() }, // 給須要的元素動態綁定事件 bindEvent(){ const _this = this; $('.item').click(this.loadAndCreate) $('.item').mouseover(function(){ // 時間判斷 const now = new Date().getTime(); // if(now-_this.destroytime<1000) return; _this.powershow = true _this.createtime = new Date().getTime(); // 獲取頁面寬度 const isBeyong = $(this).position().left > document.body.clientWidth/2 let thistop,thisleft; // 判斷是否是當前列的第一個元素 if(isBeyong){ _this.isbeyong = true thistop = $(this).position().top thisleft = $(this).position().left - parseInt($('#powerdiv').css('width')) - 10; }else{ _this.isbeyong = false thistop = $(this).position().top - parseInt($('#powerdiv').css('height')) - 10; thisleft = $(this).position().left } // 判斷不是第一個元素則往下移動10 if($('.firstItem').position().top !== $(this).position().top){ thistop = thistop + 10 } $('#powerdiv').css({'top': thistop, 'left': thisleft}); _this.item = JSON.parse($(`#${$(this).attr('id')}content`).text()); }).mouseout(function(event){ // 消失的時候延時消失 _this.destroytime = new Date().getTime(); setTimeout(()=>{ const now = new Date().getTime(); if(now - _this.createtime > 1000){ _this.powershow = false } },1000) }) $('#powerdiv').hover(function(){ _this.powershow = true _this.createtime = new Date().getTime(); },function(event){ // 消失的時候延時消失 setTimeout(()=>{ const now = new Date().getTime(); if(now - _this.createtime > 1000){ _this.powershow = false } },1000) }) } }};</script><style lang="scss">.user-relation { .powerleft,.powertop{ border: 1px solid #F5F4F4; border-radius: 3px; position: relative; width: 400px; font-size: 12px; line-height: 1.5; position: absolute; background: #fff; box-sizing: border-box; box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.08); } .powertop:after{ content: ""; display: block; width: 10px; height: 10px; background: #F5F4F4; border-left: 1px solid rgba(226, 222, 222, 0.849); border-bottom: 1px solid rgba(226, 222, 222, 0.849); position: absolute; /* 加上border的高度 */ top: 98%; left: 10%; transform: rotate(-45deg); } .powerleft:after{ content: ""; display: block; width: 10px; height: 10px; background: #F5F4F4; border-left: 1px solid rgba(226, 222, 222, 0.849); border-bottom: 1px solid rgba(226, 222, 222, 0.849); position: absolute; /* 加上border的高度 */ top: 10%; left: 99%; transform: rotate(225deg); } .item_div{ font-size:12px; border-bottom: 1px solid #F5F4F4; height: 40px; line-height: 40px; padding:0px 10px; } .item_div:first-child { background-color: #F5F4F4; } .item_div:last-child { float: right; border: none; height: 100%; width:100%; background-color: #F5F4F4; .md-icon{ margin-left:90%; line-height: 40px; } } .item_div:nth-child(4) > .item_span { width: 100%; } .item_span{ display: inline-block; padding: 10px; // width:50%; } .all{ border: 1px solid rgba(226, 222, 222, 0.849); padding: 20px; width: 100%; overflow: auto; display: flex; } .first-main{ min-height: 500px; width: 160px; border: 1px solid rgba(226, 222, 222, 0.849); float: left; } .main { min-height: 500px; width: 160px; margin-left: -1px; border: 1px solid rgba(226, 222, 222, 0.849); float: left; } .item { margin-top:-1px; width: 160px; line-height: 42px; text-align: left; height: 40px; font-size: 12px; display: inline-block; padding-left: 5px; } .icon { margin-right:8px; float: right; line-height: 42px; }}</style>複製代碼

<--------------------------------------第二種實現方式-------------------------------------->
<template>  <div class="md-layout">    <!-- 分割線 -->    <div class="md-layout-item md-size-100 line1">      <v-divider />    </div>    <!-- 1.搜索(Safumax LIVE)待審覈入金記錄 -->    <!-- <md-button class="md-primary md-sm padding" @click="$router.push({name:'agentForm'})">建立代理</md-button> -->    <span class="buttonspace"></span>    <!-- 2.代理管理表 -->    <div class="md-layout-item md-size-100">      <md-card>        <!-- 標題 -->        <md-card-header class="md-card-header-icon md-card-header-green">          <div class="card-icon">            <md-icon>repeat</md-icon>          </div>          <h4 class="title">客戶層級關係</h4>        </md-card-header>        <md-card-header>          <div class="md-layout">            <!-- 1.暱稱 -->            <div class="input md-layout-item md-size-30 md-xsmall-size-100">              <el-select                clearable                filterable                v-model="filter.id"                remote                placeholder="請輸入中文名或MT帳號"                :remote-method="remoteMethod"                :loading="loading"              >                <el-option                  v-for="item in users"                  :key="item.id"                  :label="`${item.chineseName}--${item.phone}--${item.email}`"                  :value="item.id"                ></el-option>              </el-select>            </div>            <!-- 7.表單提交按鈕 -->            <div class="md-layout-item md-size-70">              <el-button                type="success" size=""                style="float:left;margin-top:0px"                @click="getData()"              >查詢</el-button>            </div>          </div>        </md-card-header>        <!-- 內容 -->        <md-card-content>            <el-tree              highlight-current              ref="tree"              :data="data"                            :render-after-expand="false"              node-key="id"              check-strictly              @node-expand="nodeClick"              :expand-on-click-node="true"            >              <span slot-scope="{ data }">                <div>                  <md-icon                    style="color:#f173ac;margin-top:-5px"                    type="md-warning"                    v-if="data.agentCount<1"                  >person</md-icon>                  <md-icon style="color:#FFC125;margin-top:-5px" type="md-warning" v-else>group</md-icon>                  <el-popover                    placement="top-start"                    title="MT帳號詳情"                    width="200"                    trigger="hover"                    :content="data.mtids.join(',')">                    <span class="tree-span" slot="reference">{{ formatData(data) }}</span>                  </el-popover>                </div>              </span>            </el-tree>          <!-- </el-popover> -->        </md-card-content>      </md-card>    </div>  </div></template><script>import { isArray } from 'util';export default {  data() {    return {      loading: false,      data: [],      getRelation: false,      users: [],      filter: {        id: ""      }    };  },  async mounted() {    this.data = await this.list();    console.log("data", this.data);  },  methods: {    async getData() {      this.data = await this.list();    },    // 查找    async list(id) {      if (this.getRelation) {        return;      }      this.getRelation = true;      const data = { ...this.filter };      if (id) data.id = id;      const res = await this.$axios.get("userRelation", { params: data });      this.getRelation = false;      this.addchildren(res.data.result.user.children);      return [...[res.data.result.user]];    },    // node樹拼接    async nodeClick(data, node) {      // console.log(1,data);      if (data.children) {        data.children = [];        let result = await this.list(data.id);        // console.log(2,result)        if (result && result.length > 0) {          this.$nextTick(() => {            // console.log(3,data.id, result[0].children)            this.$refs["tree"].updateKeyChildren(data.id, result[0].children);          });        }      }    },    // 數據處理    formatData(data) {      let str = `${data.chineseName} [直屬客戶數: ${data.agentCount};`;      if (isArray(data.mtids) && data.mtids.length === 1) str += `MT帳號: ${data.mtids[0]}`;      if (isArray(data.mtids) && data.mtids.length > 1) str += `MT帳號: ${data.mtids[0]}...`;      return str += ` ]`;    },    // 處理children    addchildren(list) {      for (let item of list) {        if (item.agentCount > 0) {          item.children = [{}];        }      }    },    // 遠程搜索    remoteMethod(query) {      const res = await this.$axios.get("getUsersByName", {        params: { content: query }      });      // console.log(res.data.result.users)      this.users = res.data.result.users;    }  }};</script><style>.md-menu-content.md-select-menu {  z-index: 9999 !important;  width: 100% !important;}.el-tree {  color: rgb(1, 26, 3);  text-align: center;  font-size: 15px;  margin: 0px !important;  font-weight: 500;}.el-tree-node__content {  height: 45px !important;}.el-tree-node__children {  border-style: none none none none;  border-width: 0.05em;  border-color: #aaa;}.tree-span { margin-top: 0px; margin-left: 5px; display: inline-block;}.md-rose md-simple table-button tree-icon { margin-left: -30px;}</style>複製代碼
相關文章
相關標籤/搜索