vue树形结构,实现无限级分类,可移动排序

2019-10-16  本文已影响0人  芸芸众生ing

需要配合 VUEX 实现,ui组件用的是element-ui

import Vue from 'vue'
import Vuex from 'vuex';

Vue.use(Vuex)
const module = {
  state: {
      menuList: null, 
  },
  mutations: {
    setMenuList(state, data) {
      state.menuList = data
    }
  }
};
const store = new Vuex.Store(module);
export default store

组件代码

<template>
  <!-- 菜单结构 -->
  <div>
    <div class="menu-box menu-box-margin" v-for="(v,i) in value" :key="i">
      <div class="menu-box-item">
        <!-- 单条菜单 -->
        <div class="menu-box-item-title">
          <div>
            <i class="el-icon-caret-bottom" @click.stop="v.check = !v.check"></i>
            <span>{{v.title}}</span>
          </div>
          <div>
            <i class="el-icon-back" @click.stop="onMoveLeft(i,v)"></i>
            <i class="el-icon-right" @click.stop="onMoveRight(i,v)"></i>
            <i class="el-icon-top" @click.stop="onMoveTop(i,v)"></i>
            <i class="el-icon-bottom" @click.stop="onMoveBottom(i,v)"></i>
            <i class="el-icon-close" @click.stop="_delOneNavItem(v)"></i>
          </div>
        </div>
        <!-- 菜单设置 -->
        <div class="menu-box-content" v-show="v.check">
          <el-form-item label="菜单标题">
            <el-input size="mini" v-model="v.title" />
          </el-form-item>
          <el-form-item label="菜单副标题">
            <el-input size="mini" v-model="v.subTitle" />
          </el-form-item>
          <div class="space-between">
            <el-form-item label="对应页面名称">
              <el-select value="s" size="mini">
                <el-option :label="v.title" value />
              </el-select>
            </el-form-item>
            <el-form-item label="那些设备上显示">
              <el-select value="s" size="mini" multiple>
                <el-option label="--" value="a" />
              </el-select>
            </el-form-item>
          </div>
        </div>
      </div>
      <!-- 递归循环遍历 -->
      <tree v-if="v.children" :value="v.children" />
    </div>
  </div>
</template>
<script>
import { mapMutations,mapState } from "vuex";
export default {
  name: "tree",
  props: {
    value: null
  },
  computed: {
    ...mapState(["menuList"])
  },
  methods: {
    ...mapMutations(["setMenuList"]),
    _navListSort() {
      let menuList = this._setDept(this.menuList);
      this.setMenuList(this.menuList);
    },
    _setDept(arr, dept = 1, id = null, address = null) {
      if (!arr) {
        return null;
      }
      for (let k = 0; k < arr.length; k++) {
        arr[k].dept = dept;
        arr[k].parentId = id;
        arr[k].position = k;
        arr[k].parentPosition = address;
        if (arr[k].children && arr[k].children.constructor == Array) {
          arr[k].children = this._setDept(
            arr[k].children,
            arr[k].dept + 1,
            arr[k].id,
            k
          );
        }
      }
      return arr;
    },
    _getDept(dept, arr, parentId) {
      dept--;
      if (dept == 0) {
        return arr;
      }
      for (let k in arr) {
        if (arr[k].dept == dept) {
          if (arr[k].id == parentId) {
            return arr;
          }
        }
        if (arr[k].children && arr[k].children.constructor == Array) {
          return this._getDept(dept, arr[k].children, parentId);
        }
      }
      return [];
    },
    onMoveLeft(index, v) {
      let current = this._getDept(v.dept - 1, this.menuList, v.parentId);
      if (v.dept == 1) return;
      let item = this.value.splice(index, 1)[0];
      current.splice(item.parentPosition + 1, 0, item);
      this._navListSort();
    },
    onMoveRight(index, v) {
      if (index == 0) return;
      let current = this.value;
      let item = current.splice(index, 1);
      item[0].parentId = current[index - 1].id;
      if (current[index - 1].children) {
        current[index - 1].children.push(...item);
      } else {
        current[index - 1].children = item;
      }
      this._navListSort();
    },

    onMoveBottom(index, v) {
      let current = this.value;
      if (index + 1 == current.length) return;
      let item = current.splice(index, 1);
      current.splice(index + 1, 0, ...item);
      this._navListSort();
    },
    onMoveTop(index, v) {
      if (index == 0) return;
      let current = this.value;
      let item = current.splice(index, 1);
      current.splice(index - 1, 0, ...item);
      this._navListSort();
    },

    // 删除一个子菜单
    async _delOneNavItem(e) {
      this.value.splice(this.value.findIndex(k => k.id == e.id), 1);
      let result = await this.$http({
        url: "/manager/menuitem/" + e.id,
        method: "delete",
        headers: {
          "X-TENANT-ID": this.$route.params.organizationId
        }
      });
    }
  }
};

</script>
<style lang="less" scoped>
.menu-box {
  width: 100%;
  height: 100%;
  overflow: hidden;
  .menu-box-item {
    margin-top: 10px;
    border: solid 1px #e6ebf1;
    border-radius: 6px;
    min-width: 300px;
    max-width: 500px;
    background: #fff;
    .menu-box-item-title {
      padding: 0 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      height: 40px;
      i {
        padding: 2px;
        background-color: #e6ebf1;
        border-radius: 6px;
        color: #838eab;
        cursor: pointer;
        margin: 0 2px;
      }
    }
    .menu-box-content {
      padding: 0 20px;
      border-top: 1px solid #e6ebf1;
    }
  }
  .menu-box-margin {
    margin-left: 40px;
  }
}
</style>
上一篇 下一篇

猜你喜欢

热点阅读