|
@@ -0,0 +1,376 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="edit-view">
|
|
|
|
|
+ <el-button type="text" @click="addRootMenu" style="margin-left: 24px">添加
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-tree :data="menus" :render-content="renderContent"
|
|
|
|
|
+ :highlight-current="true" :expand-on-click-node="true" node-key="id"
|
|
|
|
|
+ default-expand-all v-loading="loading" class="my-tree">
|
|
|
|
|
+ </el-tree>
|
|
|
|
|
+ <el-dialog :visible.sync="dialogVisible" title="添加分类">
|
|
|
|
|
+ <el-form :model="menu" ref="form" label-position="top">
|
|
|
|
|
+ <el-form-item label="分类名" prop="name"
|
|
|
|
|
+ :rules="[{required: true, message: '请填写分类名', trigger: 'blur'}]">
|
|
|
|
|
+ <el-input v-model="menu.name"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+<!-- <el-form-item label="菜单地址" prop="path">-->
|
|
|
|
|
+<!-- <el-input v-model="menu.path"></el-input>-->
|
|
|
|
|
+<!-- </el-form-item>-->
|
|
|
|
|
+<!-- <el-form-item prop="icon">-->
|
|
|
|
|
+<!-- <template slot="label">图标-->
|
|
|
|
|
+<!-- <a href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free"-->
|
|
|
|
|
+<!-- target="_blank"-->
|
|
|
|
|
+<!-- class="available-icons">查看所有可用图标</a></template>-->
|
|
|
|
|
+<!-- <el-input v-model="icon">-->
|
|
|
|
|
+<!-- <template slot="append"><span ref="iconContainer"-->
|
|
|
|
|
+<!-- style="font-size: 18px"><i-->
|
|
|
|
|
+<!-- class="fas fa-"></i></span></template>-->
|
|
|
|
|
+<!-- </el-input>-->
|
|
|
|
|
+<!-- </el-form-item>-->
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <div slot="footer">
|
|
|
|
|
+ <el-button @click="dialogVisible = false">取消
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button type="primary" @click="addMenu" :loading="loading">保存
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script>
|
|
|
|
|
+ export default {
|
|
|
|
|
+ created() {
|
|
|
|
|
+ this.getData();
|
|
|
|
|
+ },
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ dialogVisible: false,
|
|
|
|
|
+ curr: null,
|
|
|
|
|
+ loading: false,
|
|
|
|
|
+ menus: [],
|
|
|
|
|
+ menu: {
|
|
|
|
|
+ name: "",
|
|
|
|
|
+ // path: "",
|
|
|
|
|
+ // icon: "",
|
|
|
|
|
+ // root: false,
|
|
|
|
|
+ // active: true
|
|
|
|
|
+ },
|
|
|
|
|
+ parent: null,
|
|
|
|
|
+ currentRef: null,
|
|
|
|
|
+ edit: false,
|
|
|
|
|
+ // icon: ""
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ addRootMenu() {
|
|
|
|
|
+ this.menu = {
|
|
|
|
|
+ name: "",
|
|
|
|
|
+ // path: "",
|
|
|
|
|
+ // active: true,
|
|
|
|
|
+ // root: true,
|
|
|
|
|
+ // icon: "bars"
|
|
|
|
|
+ };
|
|
|
|
|
+ this.parent = 1;
|
|
|
|
|
+ // this.icon = "bars";
|
|
|
|
|
+ this.dialogVisible = true;
|
|
|
|
|
+ // setTimeout(() => {
|
|
|
|
|
+ // this.showIcon("bars");
|
|
|
|
|
+ // }, 100);
|
|
|
|
|
+ },
|
|
|
|
|
+ showAddDialog(node, data) {
|
|
|
|
|
+ this.edit = false;
|
|
|
|
|
+ this.parent = node.data;
|
|
|
|
|
+ this.menu = {
|
|
|
|
|
+ parent: node.data.id,
|
|
|
|
|
+ name: "",
|
|
|
|
|
+ // path: "",
|
|
|
|
|
+ // active: true,
|
|
|
|
|
+ // root: false,
|
|
|
|
|
+ // icon: null
|
|
|
|
|
+ };
|
|
|
|
|
+ // this.icon = "";
|
|
|
|
|
+ this.dialogVisible = true;
|
|
|
|
|
+ // setTimeout(() => {
|
|
|
|
|
+ // this.showIcon("");
|
|
|
|
|
+ // }, 100);
|
|
|
|
|
+ },
|
|
|
|
|
+ showEditDialog(node, data) {
|
|
|
|
|
+ this.edit = true;
|
|
|
|
|
+ this.currentRef = node.data;
|
|
|
|
|
+ // const getIconName = icon => {
|
|
|
|
|
+ // let iconName = "";
|
|
|
|
|
+ // if (icon) {
|
|
|
|
|
+ // iconName = icon
|
|
|
|
|
+ // .replace("fas ", "")
|
|
|
|
|
+ // .replace("fab ", "")
|
|
|
|
|
+ // .replace("fa-", "");
|
|
|
|
|
+ // }
|
|
|
|
|
+ // return iconName || null;
|
|
|
|
|
+ // };
|
|
|
|
|
+ // let iconName = getIconName(data.icon);
|
|
|
|
|
+ this.menu = {
|
|
|
|
|
+ ...data
|
|
|
|
|
+ };
|
|
|
|
|
+ // this.icon = iconName;
|
|
|
|
|
+ this.dialogVisible = true;
|
|
|
|
|
+ // setTimeout(() => {
|
|
|
|
|
+ // this.showIcon(iconName);
|
|
|
|
|
+ // }, 100);
|
|
|
|
|
+ },
|
|
|
|
|
+ addMenu() {
|
|
|
|
|
+ this.$refs.form.validate(valid => {
|
|
|
|
|
+ if (valid) {
|
|
|
|
|
+ this.loading = true;
|
|
|
|
|
+ let menu = { ...this.menu };
|
|
|
|
|
+ delete menu.children;
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .post("/category/save", menu)
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.$message.success("添加成功");
|
|
|
|
|
+ this.dialogVisible = false;
|
|
|
|
|
+ if (this.edit) {
|
|
|
|
|
+ for (let [key, value] of Object.entries(res)) {
|
|
|
|
|
+ console.log(`${key}: ${value}`);
|
|
|
|
|
+ this.$set(this.currentRef, key, value);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (this.parent) {
|
|
|
|
|
+ this.parent.children =
|
|
|
|
|
+ this.parent.children || [];
|
|
|
|
|
+ this.parent.children.push(res);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.menus.push(res);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e);
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.$message.error(e.error);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ remove(node, data) {
|
|
|
|
|
+ console.log(node);
|
|
|
|
|
+ this.$confirm("确定删除菜单?", "提示", {
|
|
|
|
|
+ confirmButtonText: "确定",
|
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
|
+ type: "error"
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(() => {
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .post("/category/save", {
|
|
|
|
|
+ ...data,
|
|
|
|
|
+ active: false,
|
|
|
|
|
+ children: null
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.$message.success("删除成功");
|
|
|
|
|
+ let index = node.parent.data.children.findIndex(
|
|
|
|
|
+ i => {
|
|
|
|
|
+ return i.id === data.id;
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+ if (index > -1) {
|
|
|
|
|
+ node.parent.data.children.splice(index, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e);
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.$message.error(e.error);
|
|
|
|
|
+ });
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(() => {});
|
|
|
|
|
+ },
|
|
|
|
|
+/* moveUp(node, data) {
|
|
|
|
|
+ if (node.previousSibling) {
|
|
|
|
|
+ this.loading = true;
|
|
|
|
|
+ let sort0 = node.previousSibling.data.sort,
|
|
|
|
|
+ sort1 = node.data.sort;
|
|
|
|
|
+ Promise.all([
|
|
|
|
|
+ this.$http.post("/category/save", {
|
|
|
|
|
+ ...node.data,
|
|
|
|
|
+ children: null,
|
|
|
|
|
+ sort: sort0
|
|
|
|
|
+ }),
|
|
|
|
|
+ this.$http.post("/category/save", {
|
|
|
|
|
+ ...node.previousSibling.data,
|
|
|
|
|
+ children: null,
|
|
|
|
|
+ sort: sort1
|
|
|
|
|
+ })
|
|
|
|
|
+ ])
|
|
|
|
|
+ .then(_ => {
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ let tmp = { ...node.previousSibling.data, sort: sort1 };
|
|
|
|
|
+ node.previousSibling.data = {
|
|
|
|
|
+ ...node.data,
|
|
|
|
|
+ sort: sort0
|
|
|
|
|
+ };
|
|
|
|
|
+ node.data = tmp;
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e);
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.$message.error(e.error);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ moveDown(node, data) {
|
|
|
|
|
+ if (node.nextSibling) {
|
|
|
|
|
+ this.loading = true;
|
|
|
|
|
+ let sort0 = node.data.sort,
|
|
|
|
|
+ sort1 = node.nextSibling.data.sort;
|
|
|
|
|
+ Promise.all([
|
|
|
|
|
+ this.$http.post("/category/save", {
|
|
|
|
|
+ ...node.data,
|
|
|
|
|
+ children: null,
|
|
|
|
|
+ sort: sort1
|
|
|
|
|
+ }),
|
|
|
|
|
+ this.$http.post("/category/save", {
|
|
|
|
|
+ ...node.nextSibling.data,
|
|
|
|
|
+ children: null,
|
|
|
|
|
+ sort: sort0
|
|
|
|
|
+ })
|
|
|
|
|
+ ])
|
|
|
|
|
+ .then(_ => {
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ let tmp = { ...node.nextSibling.data, sort: sort0 };
|
|
|
|
|
+ node.nextSibling.data = { ...node.data, sort: sort1 };
|
|
|
|
|
+ node.data = tmp;
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e);
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.$message.error(e.error);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },*/
|
|
|
|
|
+ getData() {
|
|
|
|
|
+ this.$http
|
|
|
|
|
+ .get("/category/tree",{
|
|
|
|
|
+ id : 1
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ this.menus = res;
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e);
|
|
|
|
|
+ this.$message.error(e.error);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ renderContent(h, { node, data, store }) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <span class="custom-tree-node">
|
|
|
|
|
+ <span>{data.name}</span>
|
|
|
|
|
+ <span class="url">{data.path}</span>
|
|
|
|
|
+ <span class="opt">
|
|
|
|
|
+
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ on-click={e => {
|
|
|
|
|
+ this.showEditDialog(node, data),
|
|
|
|
|
+ e.stopPropagation();
|
|
|
|
|
+ }}
|
|
|
|
|
+ icon="el-icon-edit"
|
|
|
|
|
+ >
|
|
|
|
|
+ 编辑
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ on-click={e => {
|
|
|
|
|
+ this.showAddDialog(node, data),
|
|
|
|
|
+ e.stopPropagation();
|
|
|
|
|
+ }}
|
|
|
|
|
+ icon="el-icon-plus"
|
|
|
|
|
+ >
|
|
|
|
|
+ 添加
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ on-click={e => {
|
|
|
|
|
+ this.remove(node, data), e.stopPropagation();
|
|
|
|
|
+ }}
|
|
|
|
|
+ icon="el-icon-delete"
|
|
|
|
|
+ >
|
|
|
|
|
+ 删除
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ );
|
|
|
|
|
+ },
|
|
|
|
|
+ // showIcon(val) {
|
|
|
|
|
+ // if (!this.$refs.iconContainer) return;
|
|
|
|
|
+ // if (FontAwesome.icon({ prefix: "fas", iconName: val })) {
|
|
|
|
|
+ // this.$refs.iconContainer.innerHTML = "";
|
|
|
|
|
+ // let i = document.createElement("i");
|
|
|
|
|
+ // i.className = "fas fa-" + val;
|
|
|
|
|
+ // this.$refs.iconContainer.append(i);
|
|
|
|
|
+ // FontAwesome.dom.i2svg();
|
|
|
|
|
+ // this.menu.icon = "fas fa-" + val;
|
|
|
|
|
+ // } else if (FontAwesome.icon({ prefix: "fab", iconName: val })) {
|
|
|
|
|
+ // this.$refs.iconContainer.innerHTML = "";
|
|
|
|
|
+ // let i = document.createElement("i");
|
|
|
|
|
+ // i.className = "fab fa-" + val;
|
|
|
|
|
+ // this.$refs.iconContainer.append(i);
|
|
|
|
|
+ // FontAwesome.dom.i2svg();
|
|
|
|
|
+ // this.menu.icon = "fab fa-" + val;
|
|
|
|
|
+ // } else {
|
|
|
|
|
+ // this.$refs.iconContainer.innerHTML = "";
|
|
|
|
|
+ // let i = document.createElement("i");
|
|
|
|
|
+ // i.className = "fab fa-" + val;
|
|
|
|
|
+ // this.$refs.iconContainer.append(i);
|
|
|
|
|
+ // FontAwesome.dom.i2svg();
|
|
|
|
|
+ // this.menu.icon = "";
|
|
|
|
|
+ // }
|
|
|
|
|
+ // }
|
|
|
|
|
+ },
|
|
|
|
|
+ // watch: {
|
|
|
|
|
+ // icon(val) {
|
|
|
|
|
+ // this.showIcon(val);
|
|
|
|
|
+ // }
|
|
|
|
|
+ // }
|
|
|
|
|
+ };
|
|
|
|
|
+</script>
|
|
|
|
|
+<style lang="less">
|
|
|
|
|
+ .custom-tree-node {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ padding-right: 8px;
|
|
|
|
|
+ .url {
|
|
|
|
|
+ flex-grow: 1;
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+ margin-right: 20px;
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ }
|
|
|
|
|
+ .opt {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .custom-tree-node:hover {
|
|
|
|
|
+ .opt {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .available-icons {
|
|
|
|
|
+ color: #409eff;
|
|
|
|
|
+ text-decoration: none;
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ color: #409eff;
|
|
|
|
|
+ text-decoration: none;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .my-tree {
|
|
|
|
|
+ border-top: 1px solid #f2f4f5;
|
|
|
|
|
+ .el-tree-node__content {
|
|
|
|
|
+ height: 42px;
|
|
|
|
|
+ border: 1px solid #f2f4f5;
|
|
|
|
|
+ border-top: none;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|