소스 검색

home菜单调整

zhangjie 3 년 전
부모
커밋
c5517df129
5개의 변경된 파일272개의 추가작업 그리고 295개의 파일을 삭제
  1. 32 5
      src/assets/styles/home.scss
  2. 22 21
      src/constants/adminNavs.js
  3. 87 63
      src/modules/admin/views/Admin.vue
  4. 22 14
      src/modules/admin/views/SchoolMenuManage.vue
  5. 109 192
      src/views/Home.vue

+ 32 - 5
src/assets/styles/home.scss

@@ -31,7 +31,6 @@
   z-index: 100;
   overflow: auto;
   font-size: 14px;
-  padding: 30px 40px;
   background: $--color-white;
   border-top-right-radius: $--border-radius-huge;
   border-bottom-right-radius: $--border-radius-huge;
@@ -49,13 +48,15 @@
   }
 
   .head-logo {
+    padding: 0 40px;
     font-size: 20px;
     line-height: 40px;
-    border-radius: $--border-radius;
-    // background-color: $--color-background;
     text-align: center;
-    margin-bottom: 30px;
-
+    &-content {
+      display: block;
+      padding: 30px 0;
+      border-bottom: 1px solid #eff0f5;
+    }
     img {
       display: block;
       max-width: 160px;
@@ -138,6 +139,32 @@
     }
   }
 }
+.el-menu-home {
+  padding-top: 20px;
+  .el-submenu {
+    margin-bottom: 20px;
+  }
+  .el-submenu__title {
+    padding: 0 40px !important;
+    height: 50px;
+    line-height: 50px;
+    font-weight: 600;
+
+    > .icon {
+      margin-right: 12px;
+    }
+  }
+  .el-submenu .el-menu-item {
+    height: 40px;
+    line-height: 40px;
+  }
+  .el-submenu .el-menu-item.is-active {
+    font-weight: 600;
+  }
+  .el-submenu__icon-arrow {
+    right: 40px;
+  }
+}
 
 /* head */
 .home-header {

+ 22 - 21
src/constants/adminNavs.js

@@ -1,26 +1,27 @@
 const navs = [
   {
-    title: "超管中心",
-    name: "admin",
-    icon: "el-icon-help",
-    children: [
-      {
-        title: "用户管理",
-        router: "AdminUserManage"
-      },
-      {
-        title: "系统角色管理",
-        router: "SystemRoleManage"
-      },
-      {
-        title: "菜单管理",
-        router: "SchoolMenuManage"
-      }
-      // {
-      //   title: "权限管理",
-      //   router: "PrivilegeManage"
-      // }
-    ]
+    id: "1",
+    parentId: "-1",
+    name: "超管中心",
+    url: "admin"
+  },
+  {
+    id: "2",
+    parentId: "1",
+    name: "用户管理",
+    url: "AdminUserManage"
+  },
+  {
+    id: "3",
+    parentId: "1",
+    name: "系统角色管理",
+    url: "SystemRoleManage"
+  },
+  {
+    id: "4",
+    parentId: "1",
+    name: "菜单管理",
+    url: "SchoolMenuManage"
   }
 ];
 

+ 87 - 63
src/modules/admin/views/Admin.vue

@@ -20,31 +20,37 @@
 
     <div class="home-navs">
       <div class="head-logo">
-        <h1>分布式印刷</h1>
-      </div>
-      <div v-for="(menu, sindex) in menus" :key="sindex" class="nav-part">
-        <div class="nav-head">
-          <span>{{ menu.title }}</span>
-          <i class="nav-head-right-icon el-icon-caret-bottom"></i>
+        <div class="head-logo-content">
+          <h1>分布式印刷</h1>
         </div>
-        <ul class="nav-list">
-          <li
-            class="nav-item"
-            v-for="(nav, navNo) in menu.children"
-            :key="navNo"
-          >
-            <div
-              :class="[
-                'nav-item-main',
-                { 'nav-item-main-act': curActNav === nav.router }
-              ]"
-              @click="toNav(nav)"
-            >
-              <p class="nav-item-cont">{{ nav.title }}</p>
-            </div>
-          </li>
-        </ul>
       </div>
+      <el-menu
+        class="el-menu-home"
+        active-text-color="#705eff"
+        text-color="#383b4a"
+        router
+        :default-active="curRouteName"
+        :default-openeds="curSubMenuNames"
+      >
+        <el-submenu
+          v-for="submenu in menus"
+          :key="submenu.url"
+          :index="submenu.url"
+        >
+          <template slot="title">
+            <span>{{ submenu.name }}</span>
+          </template>
+
+          <el-menu-item
+            v-for="nav in submenu.children"
+            :key="nav.url"
+            :index="nav.url"
+            :route="{ name: nav.url }"
+          >
+            <span>{{ nav.name }}</span>
+          </el-menu-item>
+        </el-submenu>
+      </el-menu>
     </div>
 
     <div class="home-body">
@@ -58,7 +64,7 @@
             <el-breadcrumb-item
               v-for="(bread, index) in breadcrumbs"
               :key="index"
-              >{{ bread.title }}</el-breadcrumb-item
+              >{{ bread.name }}</el-breadcrumb-item
             >
           </el-breadcrumb>
         </div>
@@ -92,8 +98,10 @@ export default {
     const user = this.$ls.get("user", { id: "", realName: "", roleList: [] });
 
     return {
-      menus: localNavs,
-      curActNav: "",
+      menus: [],
+      privileges: [],
+      curRouteName: "",
+      curSubMenuNames: [],
       breadcrumbs: [],
       username: user.realName,
       userInfo: {
@@ -122,51 +130,67 @@ export default {
         name: "AdminUserManage"
       });
     }
-    this.actCurNav();
+    this.initData();
   },
   methods: {
-    toNav(nav) {
-      if (nav.router === this.$route.name) return;
-      this.curActNav = nav.router;
-      this.$router.push({ name: nav.router });
+    initData() {
+      this.privileges = localNavs;
+      this.menus = this.getMenu();
+      this.curSubMenuNames = this.menus.map(item => item.url);
+
+      if (this.$route.name === "Admin") {
+        const firstRouteName = this.getFirstRouter();
+        this.$router.replace({
+          name: firstRouteName
+        });
+        return;
+      }
+
+      this.actCurNav();
     },
-    actCurNav() {
-      const routerName = this.$route.name;
-      let breadcrumbs = [];
-      const getRouterPath = (navs, pathList) => {
-        navs.forEach(nav => {
-          let navPathList = [...pathList];
-          if (breadcrumbs.length) return;
-          if (nav["router"] === routerName) {
-            breadcrumbs = [
-              ...navPathList,
-              { title: nav.title, router: nav.router, isRouter: true }
-            ];
-            return;
-          } else {
-            const routerOrName = nav["router"] || nav["name"];
-            navPathList = [
-              ...navPathList,
-              {
-                title: nav.title,
-                router: routerOrName,
-                isRouter: !!nav["router"]
-              }
-            ];
-            if (nav["children"]) {
-              getRouterPath(nav.children, navPathList);
-            }
+    getFirstRouter() {
+      let childNavs = this.privileges;
+      let firstRouteName = "";
+      while (childNavs.length) {
+        firstRouteName = childNavs[0].url;
+        childNavs = this.privileges.filter(
+          item => item.parentId === childNavs[0].id
+        );
+      }
+
+      return firstRouteName;
+    },
+    getMenu() {
+      let menus = this.privileges.filter(item => item.parentId === "-1");
+      const toTree = menus => {
+        menus.forEach(menu => {
+          const children = this.privileges.filter(
+            item => item.parentId === menu.id
+          );
+          if (children.length) {
+            menu.children = children;
+            toTree(menu.children);
           }
         });
       };
+      toTree(menus);
 
-      getRouterPath(this.menus, []);
-
-      const curRouter = breadcrumbs.find(item => item.isRouter);
-      this.curActNav = curRouter.router;
-      this.curMenu = this.menus.find(
-        menu => menu.name === breadcrumbs[0].router
+      return menus;
+    },
+    actCurNav() {
+      this.curRouteName = this.$route.name;
+      let breadcrumbs = [];
+      let curBreadcrumb = this.menus.find(
+        item => item.url === this.curRouteName
       );
+      breadcrumbs.push({ ...curBreadcrumb });
+
+      while (curBreadcrumb && curBreadcrumb.parentId !== "-1") {
+        curBreadcrumb = this.privileges.find(
+          item => item.id === curBreadcrumb.parentId
+        );
+        if (curBreadcrumb) breadcrumbs.unshift({ ...curBreadcrumb });
+      }
 
       this.breadcrumbs = breadcrumbs;
     },

+ 22 - 14
src/modules/admin/views/SchoolMenuManage.vue

@@ -24,17 +24,11 @@
     </div>
 
     <div class="part-box part-box-pad">
-      <el-tree
-        :data="menus"
-        show-checkbox
-        default-expand-all
-        node-key="id"
-        ref="MenuTree"
-        :props="defaultProps"
-        check-on-click-node
-        :expand-on-click-node="false"
-      >
-      </el-tree>
+      <privilege-set
+        v-if="menus && menus.length"
+        ref="PrivilegeSet"
+        :menus="menus"
+      ></privilege-set>
     </div>
   </div>
 </template>
@@ -45,9 +39,11 @@ import {
   schoolSelectedMenuTree,
   updateSchoolMenu
 } from "../api";
+import PrivilegeSet from "../../base/components/PrivilegeSet";
 
 export default {
   name: "school-menu-manage",
+  components: { PrivilegeSet },
   data() {
     return {
       schoolId: "",
@@ -64,8 +60,20 @@ export default {
   },
   methods: {
     async getPrivileges() {
+      const needHideModules = ["common", "customer"];
       const data = await schoolMenuTree();
-      this.menus = data || [];
+      const menus = data || [];
+
+      this.menus = menus
+        .filter(item => !needHideModules.includes(item.url))
+        .map(item => {
+          item.parentId = null;
+          return item;
+        });
+
+      this.$nextTick(() => {
+        this.$refs.PrivilegeSet.buildTableData([]);
+      });
     },
     async search() {
       if (!this.schoolId) return;
@@ -74,10 +82,10 @@ export default {
       this.fetching = false;
 
       const privilegeIds = data || [];
-      this.$refs.MenuTree.setCheckedKeys(privilegeIds);
+      this.$refs.PrivilegeSet.buildTableData(privilegeIds);
     },
     async save() {
-      const privilegeIds = this.$refs.MenuTree.getCheckedKeys();
+      const privilegeIds = this.$refs.PrivilegeSet.getSelectedPrivilegeIds();
 
       if (!this.schoolId || !privilegeIds.length) {
         this.$message.error("学校和权限都必须选择!");

+ 109 - 192
src/views/Home.vue

@@ -12,7 +12,7 @@
             ]"
             @click="toMenu(menu)"
           >
-            <i :class="menu.icon"></i>
+            <i :class="['icon', `icon-${MENU_ICONS[menu.url]}`]"></i>
             <span>{{ menu.name }}</span>
           </li>
         </ul>
@@ -32,48 +32,48 @@
           </li>
         </ul>
       </div>
-      <div class="head-menu-btn" @click="showMenu">
-        <span><i class="el-icon-menu"></i></span>
-      </div>
     </div>
 
-    <div class="home-navs" v-if="curMenu.children">
+    <div class="home-navs">
       <div class="head-logo">
-        <img v-if="schoolLogo" :src="schoolLogo" alt="分布式印刷" />
-        <h1 v-else>分布式印刷</h1>
+        <div class="head-logo-content">
+          <img v-if="schoolLogo" :src="schoolLogo" alt="分布式印刷" />
+          <h1 v-else>分布式印刷</h1>
+        </div>
       </div>
-      <div
-        v-for="(submenu, sindex) in curMenu.children"
-        :key="sindex"
-        class="nav-part"
+
+      <el-menu
+        class="el-menu-home"
+        active-text-color="#705eff"
+        text-color="#383b4a"
+        router
+        :default-active="curRouteName"
+        :default-openeds="curSubMenuNames"
       >
-        <div class="nav-head">
-          <span>{{ submenu.name }}</span>
-          <i class="nav-head-right-icon el-icon-caret-bottom"></i>
-        </div>
-        <ul class="nav-list">
-          <li
-            class="nav-item"
-            v-for="(nav, navNo) in submenu.children"
-            :key="navNo"
+        <el-submenu
+          v-for="submenu in curMenu.children"
+          :key="submenu.id"
+          :index="submenu.url"
+        >
+          <template slot="title">
+            <span>{{ submenu.name }}</span>
+          </template>
+
+          <el-menu-item
+            v-for="nav in submenu.children"
+            :key="nav.id"
+            :index="nav.url"
+            :route="{ name: nav.url }"
           >
-            <div
-              :class="[
-                'nav-item-main',
-                { 'nav-item-main-act': curActNav === nav.url }
-              ]"
-              @click="toNav(nav)"
+            <span>{{ nav.name }}</span>
+            <span
+              class="nav-item-info"
+              v-if="nav.url === 'WaitTask' && waitTaskCount"
+              >{{ waitTaskCount }}</span
             >
-              <p class="nav-item-cont">{{ nav.name }}</p>
-              <span
-                class="nav-item-info"
-                v-if="nav.url === 'WaitTask' && waitTaskCount"
-                >{{ waitTaskCount }}</span
-              >
-            </div>
-          </li>
-        </ul>
-      </div>
+          </el-menu-item>
+        </el-submenu>
+      </el-menu>
     </div>
 
     <div class="home-body">
@@ -84,11 +84,9 @@
             <span>当前所在位置:</span>
           </span>
           <el-breadcrumb separator="/">
-            <el-breadcrumb-item
-              v-for="(bread, index) in breadcrumbs"
-              :key="index"
-              >{{ bread.title }}</el-breadcrumb-item
-            >
+            <el-breadcrumb-item v-for="bread in breadcrumbs" :key="bread.url">{{
+              bread.name
+            }}</el-breadcrumb-item>
           </el-breadcrumb>
         </div>
 
@@ -99,70 +97,6 @@
       </div>
     </div>
 
-    <!-- popover menu-->
-    <el-dialog
-      class="menu-dialog"
-      :visible.sync="menuDailogIsShow"
-      title="导航菜单"
-      top="60px"
-      fullscreen
-      :close-on-click-modal="false"
-      :close-on-press-escape="false"
-      append-to-body
-    >
-      <div
-        class="home-navs home-navs-full"
-        v-for="(curMenu, mainNo) in menus"
-        :key="mainNo"
-      >
-        <div
-          v-for="(submenu, sindex) in curMenu.children"
-          :key="sindex"
-          class="nav-part"
-        >
-          <div class="nav-head">
-            <i :class="submenu.icon"></i>
-            <span>{{ curMenu.name }} - {{ submenu.name }}</span>
-          </div>
-          <ul class="nav-list">
-            <li
-              class="nav-item"
-              v-for="(nav, navNo) in submenu.children"
-              :key="navNo"
-            >
-              <div
-                :class="[
-                  'nav-item-main',
-                  { 'nav-item-main-act': curActNav === nav.url }
-                ]"
-                @click="toNav(nav)"
-              >
-                <p class="nav-item-cont">{{ nav.name }}</p>
-                <span class="nav-item-icon nav-item-icon-right">
-                  <i
-                    :class="[
-                      'icon',
-                      curActNav === nav.url
-                        ? 'icon-arrow-right-act'
-                        : 'icon-arrow-right'
-                    ]"
-                  ></i>
-                </span>
-                <span
-                  class="nav-item-info"
-                  v-if="nav.url === 'WaitTask' && waitTaskCount"
-                  >{{ waitTaskCount }}</span
-                >
-              </div>
-            </li>
-          </ul>
-        </div>
-      </div>
-      <div class="menu-logout" @click="toLogout">
-        <i class="el-icon-switch-button"></i>
-      </div>
-    </el-dialog>
-
     <!-- 修改密码 -->
     <reset-pwd
       :user-info="userInfo"
@@ -175,11 +109,16 @@
 <script>
 import { mapState, mapActions } from "vuex";
 import localNavs from "@/constants/navs";
-import { deepCopy } from "@/plugins/utils";
 import { sysMenu, logout } from "../modules/login/api";
 import ResetPwd from "../modules/base/components/ResetPwd";
 import { SYS_ADMIN_NAME } from "@/constants/enumerate";
 
+const MENU_ICONS = {
+  base: "base",
+  exam: "exam",
+  customer: "customer"
+};
+
 export default {
   name: "home",
   components: { ResetPwd },
@@ -188,16 +127,18 @@ export default {
     const IS_SUPER_ADMIN = user.loginName === SYS_ADMIN_NAME;
 
     return {
+      MENU_ICONS,
+      privileges: [],
       menus: [],
       curMenu: { url: "", children: [] },
-      curActNav: "",
+      curRouteName: "",
+      curSubMenuNames: [],
       breadcrumbs: [],
       validRoutes: [],
       username: user.realName,
       userRoles: user.roleList,
       schoolLogo: this.$ls.get("schoolLogo"),
       schoolName: this.$ls.get("schoolName"),
-      menuDailogIsShow: false,
       userInfo: {
         pwdCount: 0,
         mobileNumber: 1,
@@ -216,7 +157,7 @@ export default {
     ...mapState("exam", ["waitTaskCount"])
   },
   created() {
-    this.getMenus();
+    this.initData();
   },
   methods: {
     ...mapActions("exam", ["updateWaitTaskCount"]),
@@ -230,16 +171,17 @@ export default {
         this.actCurNav();
       }
     },
-    async getMenus() {
-      // TODO:根据后台返回页面层级展示菜单,前端不再维护菜单树
+    async initData() {
       const data = await sysMenu();
+      this.privileges = data.privileges;
+      this.menus = this.getMenu();
+      this.toMenu(this.menus[0]);
       this.initPrivilegeMap(data.privileges);
-      const { menus, firstRouter } = this.menusToTree(data.privileges);
-      this.menus = menus;
 
       if (this.$route.name === "Home") {
+        const firstRouteName = this.getFirstRouter();
         this.$router.replace({
-          name: firstRouter
+          name: firstRouteName
         });
         return;
       } else {
@@ -249,9 +191,42 @@ export default {
           });
           return;
         }
+      }
 
-        this.actCurNav();
+      this.actCurNav();
+    },
+    getMenu() {
+      let menus = this.privileges.filter(item => item.parentId === "-1");
+      let validRoutes = [];
+      const toTree = menus => {
+        menus.forEach(menu => {
+          const children = this.privileges.filter(
+            item => item.parentId === menu.id
+          );
+          if (children.length) {
+            menu.children = children;
+            toTree(menu.children);
+          } else {
+            validRoutes.push(menu.url);
+          }
+        });
+      };
+      toTree(menus);
+
+      this.validRoutes = validRoutes;
+      return menus;
+    },
+    getFirstRouter() {
+      let childNavs = this.privileges;
+      let firstRouteName = "";
+      while (childNavs.length) {
+        firstRouteName = childNavs[0].url;
+        childNavs = this.privileges.filter(
+          item => item.parentId === childNavs[0].id
+        );
       }
+
+      return firstRouteName;
     },
     initPrivilegeMap(data) {
       let privilegeMap = {};
@@ -275,83 +250,33 @@ export default {
       this.$store.commit("setPrivilegeMap", privilegeMap);
       this.$ls.set("privilegeMap", privilegeMap);
     },
-    menusToTree(menus) {
-      let navTree = deepCopy(localNavs);
-      let validRoutes = [];
-      let validMenuDict = {};
-      let firstRouter = "";
-      menus.forEach(item => (validMenuDict[item.url] = item.name));
-
-      const anchorNav = menus => {
-        let list = [];
-        menus.forEach(item => {
-          const routerOrName = item.url;
-          if (!validMenuDict[routerOrName]) return;
-
-          if (!firstRouter && item.isRouter) firstRouter = item.url;
-          item.name = validMenuDict[routerOrName];
-          validRoutes.push(routerOrName);
-          let navItem = { ...item };
-          if (item["children"]) {
-            navItem.children = anchorNav(item.children);
-          }
-          list.push(navItem);
-        });
-        return list;
-      };
-
-      this.validRoutes = validRoutes;
-
-      return { menus: anchorNav(navTree), firstRouter };
+    getSubMenus(menu) {
+      return this.privileges.filter(
+        m => m.parentId === menu.id && m.type === "MENU"
+      );
     },
     toMenu(menu) {
       if (this.curMenu.url === menu.url) return;
       this.curMenu = menu;
-      const firstRouter = menu.children[0].children[0];
-      this.toNav(firstRouter);
-    },
-    toNav(nav) {
-      if (nav.url === this.$route.name) return;
-      this.curActNav = nav.url;
-      this.$router.push({ name: nav.url });
-      this.menuDailogIsShow = false;
+
+      this.curSubMenuNames = this.privileges
+        .filter(item => item.parentId === menu.id)
+        .map(item => item.url);
     },
     actCurNav() {
-      const routerName = this.$route.name;
+      this.curRouteName = this.$route.name;
       let breadcrumbs = [];
-      const getRouterPath = (navs, pathList) => {
-        navs.forEach(nav => {
-          let navPathList = [...pathList];
-          if (breadcrumbs.length) return;
-          if (nav.url === routerName) {
-            breadcrumbs = [
-              ...navPathList,
-              { title: nav.name, router: nav.url, isRouter: true }
-            ];
-            return;
-          } else {
-            navPathList = [
-              ...navPathList,
-              {
-                title: nav.name,
-                router: nav.url,
-                isRouter: !!nav.isRouter
-              }
-            ];
-            if (nav["children"]) {
-              getRouterPath(nav.children, navPathList);
-            }
-          }
-        });
-      };
-
-      getRouterPath(this.menus, []);
-
-      const curRouter = breadcrumbs.find(item => item.isRouter);
-      this.curActNav = curRouter.router;
-      this.curMenu = this.menus.find(
-        menu => menu.url === breadcrumbs[0].router
+      let curBreadcrumb = this.privileges.find(
+        item => item.url === this.curRouteName
       );
+      breadcrumbs.push({ ...curBreadcrumb });
+
+      while (curBreadcrumb && curBreadcrumb.parentId !== "-1") {
+        curBreadcrumb = this.privileges.find(
+          item => item.id === curBreadcrumb.parentId
+        );
+        if (curBreadcrumb) breadcrumbs.unshift({ ...curBreadcrumb });
+      }
 
       this.breadcrumbs = breadcrumbs;
 
@@ -385,14 +310,6 @@ export default {
     },
     resetPwdModified() {
       this.logoutAction();
-    },
-    // popover menu
-    showMenu() {
-      this.menuDailogIsShow = !this.menuDailogIsShow;
-    },
-    toNavDetail(mainNo, subNo) {
-      this.toNav(subNo);
-      this.showMenu();
     }
   }
 };