需要配合 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>
网友评论