瀏覽代碼

主页修改

zhangjie 2 年之前
父節點
當前提交
d768593887

+ 154 - 45
src/assets/styles/home.scss

@@ -50,54 +50,163 @@
   top: 61px;
   left: 0;
   bottom: 0;
-  z-index: 99;
+  z-index: 100;
   overflow: auto;
-  background: #fff;
-  padding: 15px 0;
-  text-align: left;
-  transition: width 0.2s ease;
-  border-right: 1px solid $--border-color-light;
-}
-.nav-item {
-  overflow: hidden;
-}
-.nav-item-main {
-  padding: 15px 35px 15px 45px;
-  line-height: 20px;
-  min-height: 50px;
-  position: relative;
-  font-weight: 600;
-}
-.nav-item-icon {
-  display: block;
-  position: absolute;
-  width: 20px;
-  height: 20px;
-  top: 14px;
-  text-align: center;
-}
-.nav-item-icon-left {
-  left: 15px;
-  font-size: 18px;
-  transition: all 0.2s ease;
-}
-.nav-item-sublist {
-  overflow: hidden;
-  transition: height 0.2s linear;
-}
+  font-size: 14px;
+  background: $--color-white;
 
-.nav-item-sub {
-  line-height: 20px;
-  padding: 8px 5px 8px 45px;
-  cursor: pointer;
-  position: relative;
-}
-.nav-item-sub:hover {
-  color: $--color-primary;
+  &::before {
+    content: "";
+    display: block;
+    position: absolute;
+    height: 100%;
+    width: 1px;
+    right: 0;
+    bottom: 0;
+    z-index: 9;
+    background: rgba(229, 229, 229, 1);
+  }
+
+  .head-logo {
+    padding: 0 40px;
+    font-size: 20px;
+    line-height: 40px;
+    text-align: center;
+
+    &-content {
+      display: block;
+      padding: 30px 0;
+      border-bottom: 1px solid #eff0f5;
+      cursor: pointer;
+
+      &:hover {
+        opacity: 0.8;
+      }
+    }
+
+    img {
+      display: block;
+      max-width: 160px;
+      height: 40px;
+    }
+  }
+
+  .nav-part {
+    padding: 20px 0;
+    border-top: 1px solid $--color-border;
+  }
+
+  .nav-head {
+    padding: 10px 0;
+    color: $--color-text-secondary;
+    font-size: $--font-size-base;
+    line-height: 20px;
+    position: relative;
+    font-weight: 500;
+
+    > span {
+      display: inline-block;
+      vertical-align: top;
+      font-weight: 600;
+    }
+
+    &-right-icon {
+      position: absolute;
+      right: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      color: #d3d5e0;
+      font-size: 12px;
+    }
+  }
+
+  // .nav-list {
+  //   padding: 0 0 0 23px;
+  // }
+  .nav-item {
+    overflow: hidden;
+    color: $--color-text-primary;
+
+    &-main {
+      padding: 10px 0;
+      line-height: 20px;
+      position: relative;
+      font-weight: 500;
+      cursor: pointer;
+
+      &-act,
+      &:hover {
+        font-weight: 600;
+        color: $--color-primary;
+      }
+    }
+
+    &-icon {
+      display: block;
+      position: absolute;
+      width: 20px;
+      height: 20px;
+      top: 50%;
+      margin-top: -10px;
+      text-align: center;
+      line-height: 20px;
+    }
+
+    &-icon-right {
+      right: 5px;
+    }
+
+    &-info {
+      display: block;
+      position: absolute;
+      padding: 0 3px;
+      min-width: 16px;
+      height: 16px;
+      font-size: 12px;
+      line-height: 16px;
+      top: 12px;
+      right: 40px;
+      background-color: $--color-warning;
+      color: #fff;
+      text-align: center;
+      border-radius: 3px;
+    }
+  }
 }
-.nav-item-sub-act {
-  font-weight: 600;
-  color: $--color-primary !important;
+
+.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-menu-item {
+    height: auto;
+    min-height: 40px;
+    line-height: 20px;
+    padding: 10px 40px !important;
+    white-space: normal;
+  }
+
+  .el-menu-item.is-active {
+    font-weight: 600;
+  }
+
+  .el-submenu__icon-arrow {
+    right: 40px;
+  }
 }
 
 /* head */

+ 12 - 3
src/assets/styles/variables.scss

@@ -7,16 +7,22 @@ $--border-color-base: #dcdfe6 !default;
 $--border-color-light: #e4e7ed !default;
 $--border-color-lighter: #ebeef5 !default;
 $--border-color-extra-light: #f2f6fc !default;
+$--color-text-gray-2: #8b8fa1 !default;
+
 // status
-$--color-primary: #409eff !default;
-$--color-success: #1cd1a1 !default;
-$--color-warning: #e6a23c !default;
+$--color-primary: #3a5ae5 !default;
+$--color-success: #3fcb98 !default;
+$--color-warning: #ff9427 !default;
 $--color-danger: #f56c6c !default;
 $--color-info: #909399 !default;
+$--color-white: #ffffff;
+
 // skin
 $--color-background: #f0f4f9;
 $--color-background-dark: #21252b;
 $--color-background-act-dark: #2c313a;
+$--color-border: #eff0f5;
+$--color-border-bold: #e6e6e6;
 // text
 $--color-text-base: #abb2bf;
 // shadow
@@ -26,6 +32,9 @@ $--shadow-light: 0 0 1px rgba(0, 0, 0, 0.15) !default;
 $--font-size-base: 14px !default;
 $--font-size-large: 18px !default;
 $--font-size-medium: 16px !default;
+$--border-radius: 8px;
+$--border-radius-large: 12px;
+$--border-radius-huge: 20px;
 
 $--font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
   "Microsoft YaHei", "微软雅黑", Arial, sans-serif;

+ 23 - 15
src/constants/navs.js

@@ -1,19 +1,27 @@
-const navs = [
+export const navs = [
   {
-    title: "管理",
-    icon: "icon-base",
-    showList: true,
-    children: [
-      {
-        title: "应用管理",
-        router: "AppManage"
-      },
-      {
-        title: "用户管理",
-        router: "UserManage"
-      }
-    ]
+    id: "1",
+    parentId: "-1",
+    name: "管理",
+    url: "admin"
+  },
+  {
+    id: "2",
+    parentId: "1",
+    name: "用户管理",
+    url: "UserManage"
+  },
+  {
+    id: "3",
+    parentId: "1",
+    name: "应用管理",
+    url: "AppManage"
   }
 ];
 
-export default navs;
+export const ROLE_NAV = {
+  DEV: [""],
+  TEST: [""],
+  OPS: ["admin", "AppManage"],
+  ADMIN: ["admin", "UserManage", "AppManage"]
+};

+ 6 - 0
src/modules/admin/router.js

@@ -1,9 +1,15 @@
 import AppManage from "./views/AppManage.vue";
+import UserManage from "./views/UserManage.vue";
 
 export default [
   {
     path: "app-manage",
     name: "AppManage",
     component: AppManage
+  },
+  {
+    path: "user-manage",
+    name: "UserManage",
+    component: UserManage
   }
 ];

+ 15 - 0
src/modules/admin/views/UserManage.vue

@@ -0,0 +1,15 @@
+<template>
+  <div class="user-manage">
+    user-manage
+  </div>
+</template>
+
+<script>
+export default {
+  name: "user-manage",
+  data() {
+    return {};
+  },
+  methods: {}
+};
+</script>

+ 9 - 2
src/modules/login/api.js

@@ -1,5 +1,12 @@
-import { $postParam } from "@/plugins/axios";
+// import { $postParam } from "@/plugins/axios";
 
 export const login = datas => {
-  return $postParam("/api/admin/user/login", datas);
+  // return $postParam("/api/admin/user/login", datas);
+  return Promise.resolve({
+    role: ["DEV", "TEST", "OPS", "ADMIN"],
+    session: "1212121212",
+    token: "token 121212",
+    name: "测试员",
+    ...datas
+  });
 };

+ 124 - 69
src/views/Home.vue

@@ -12,7 +12,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>
@@ -24,32 +24,41 @@
     </div>
 
     <div class="home-navs">
-      <ul>
-        <li class="nav-item" v-for="(nav, index) in navs" :key="index">
-          <div class="nav-item-main" @click="switchNav(nav, index)">
-            <span class="nav-item-icon nav-item-icon-left">
-              <i :class="['icon', `${nav.icon}`]"></i>
-            </span>
-            <p class="nav-item-cont">{{ nav.title }}</p>
-          </div>
-          <ul
-            class="nav-item-sublist"
-            v-if="nav.children && nav.children.length"
+      <el-menu
+        v-if="menus && menus.length"
+        class="el-menu-home"
+        active-text-color="#3a5ae5"
+        text-color="#434656"
+        router
+        :default-active="curRouteName"
+        :collapse="false"
+      >
+        <template v-for="submenu in menus">
+          <el-submenu
+            v-if="submenu.children && submenu.children.length"
+            :key="submenu.id"
+            :index="submenu.url"
           >
-            <li
-              v-for="(subnav, sindex) in nav.children"
-              :key="sindex"
-              :class="[
-                'nav-item-sub',
-                { 'nav-item-sub-act': curSub === index + '-' + sindex }
-              ]"
-              @click="toPage(index, sindex)"
+            <span slot="title">{{ submenu.name }}</span>
+            <el-menu-item
+              v-for="nav in submenu.children"
+              :key="nav.id"
+              :index="nav.url"
+              :route="{ name: nav.url }"
             >
-              {{ subnav.title }}
-            </li>
-          </ul>
-        </li>
-      </ul>
+              <span>{{ nav.name }}</span>
+            </el-menu-item>
+          </el-submenu>
+          <el-menu-item
+            v-else
+            :key="submenu.id"
+            :index="submenu.url"
+            :route="{ name: submenu.url }"
+          >
+            <span>{{ submenu.name }}</span>
+          </el-menu-item>
+        </template>
+      </el-menu>
     </div>
 
     <div class="home-body">
@@ -63,74 +72,120 @@
 </template>
 
 <script>
-import navs from "@/constants/navs";
+import { navs, ROLE_NAV } from "@/constants/navs";
 import { APP_TITLE } from "../constants/app";
 
 export default {
   name: "home",
   data() {
+    const user = this.$ls.get("user", { id: "", name: "", role: [] });
+
     return {
-      isCollapsed: false,
       APP_TITLE,
       navs,
+      privileges: [],
+      menus: [],
+      curRouteName: "",
+      validRoutes: [],
+      username: user.name,
+      userRoles: user.role,
       curMain: 0,
       curSub: "",
-      avatar: "",
       breadcrumbs: []
     };
   },
-  computed: {
-    rotateIcon() {
-      return [
-        "menu-icon",
-        this.isCollapsed ? "el-icon-s-unfold" : "el-icon-s-fold"
-      ];
-    }
-  },
   watch: {
     $route(val) {
-      this.actCurNav();
+      if (val.name === "Home") return;
+
+      this.updateBreadcrumbs();
     }
   },
-  mounted() {
-    this.actCurNav();
+  created() {
+    this.initData();
   },
   methods: {
-    collapsedSider() {
-      this.isCollapsed = !this.isCollapsed;
+    initData() {
+      this.privileges = this.getPrivileges(navs);
+      this.menus = this.getMenu();
+
+      if (this.$route.name === "Home") {
+        console.log(this.getMenuFirstRouter());
+        this.$router.replace({ name: this.getMenuFirstRouter() });
+        return;
+      }
+
+      if (!this.validRoutes.includes(this.$route.name)) {
+        this.$router.replace({
+          name: "404"
+        });
+        return;
+      }
+
+      this.updateBreadcrumbs();
     },
-    switchNav(item, mainIndex) {
-      if (item.children) {
-        item.showList = !item.showList;
-      } else {
-        this.breadcrumbs = [{ title: item.title, router: item.router }];
-        this.curMain = mainIndex;
-        this.curSub = "";
-        this.$router.push({ name: item.router });
+    getPrivileges(navList) {
+      let privilegesUrls = [];
+      this.userRoles.forEach(role => {
+        const urls = ROLE_NAV[role] || [];
+        privilegesUrls.push(...urls);
+      });
+      return navList.filter(item => privilegesUrls.includes(item.url));
+    },
+    getMenuFirstRouter() {
+      let firstRouteName = "";
+      let menu = this.menus[0];
+      while (menu) {
+        firstRouteName = menu.url;
+        menu = menu.children && menu.children[0];
       }
+
+      return firstRouteName;
     },
-    actCurNav() {
-      let router = this.$route.name;
-      this.navs.forEach((item, index) => {
-        if (item.children && item.children.length) {
-          item.children.forEach((elem, pindex) => {
-            if (elem.router === router) {
-              this.curSub = index + "-" + pindex;
-              this.curMain = index;
-              this.breadcrumbs = [
-                { title: item.title, router: item.router },
-                { title: elem.title, router: elem.router }
-              ];
-            }
+    getMenu() {
+      const getChildren = id => {
+        return this.privileges
+          .filter(item => item.parentId === id)
+          .map(item => {
+            return { ...item };
           });
-        } else {
-          if (item.router === router) {
-            this.curMain = index;
-            this.breadcrumbs = [{ title: item.title, router: item.router }];
+      };
+
+      let menus = getChildren("-1");
+      let validRoutes = [];
+      const toTree = menus => {
+        menus.forEach(menu => {
+          const children = getChildren(menu.id);
+          if (children.length) {
+            menu.children = children;
+            toTree(menu.children);
+          } else {
+            validRoutes.push(menu.url);
           }
-        }
-      });
-      this.navs[this.curMain].showList = true;
+        });
+      };
+      toTree(menus);
+
+      this.validRoutes = validRoutes;
+      // console.log(JSON.stringify(menus));
+      return menus;
+    },
+    updateBreadcrumbs() {
+      this.curRouteName = this.$route.name;
+      let breadcrumbs = [];
+      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;
     },
     toPage(mainIndex, subIndex) {
       const item = this.navs[mainIndex];