Quellcode durchsuchen

布局优化,文件统一格式化

zhangyu vor 4 Jahren
Ursprung
Commit
9fa5fd775d
39 geänderte Dateien mit 1367 neuen und 1529 gelöschten Zeilen
  1. 34 28
      .eslintrc.js
  2. 3 0
      src/App.vue
  3. 4 4
      src/api/articles.ts
  4. 15 15
      src/api/types.d.ts
  5. 10 10
      src/api/users.ts
  6. 57 72
      src/components/Breadcrumb/index.vue
  7. 11 18
      src/components/Hamburger/index.vue
  8. 8 11
      src/layout/components/AppMain.vue
  9. 116 127
      src/layout/components/Navbar/index.vue
  10. 113 138
      src/layout/components/Sidebar/SidebarItem.vue
  11. 11 21
      src/layout/components/Sidebar/SidebarItemLink.vue
  12. 64 70
      src/layout/components/Sidebar/index.vue
  13. 4 4
      src/layout/components/index.ts
  14. 84 93
      src/layout/index.vue
  15. 18 18
      src/layout/mixin/resize.ts
  16. 19 19
      src/main.ts
  17. 27 27
      src/permission.ts
  18. 14 12
      src/registerServiceWorker.ts
  19. 17 11
      src/router/index.ts
  20. 3 3
      src/shims-vue.d.ts
  21. 8 8
      src/store/index.ts
  22. 30 24
      src/store/modules/app.ts
  23. 54 46
      src/store/modules/user.ts
  24. 9 8
      src/utils/cookies.ts
  25. 28 28
      src/utils/request.ts
  26. 4 2
      src/utils/validate.ts
  27. 77 105
      src/views/error-page/401.vue
  28. 209 234
      src/views/error-page/404.vue
  29. 211 231
      src/views/login/index.vue
  30. 72 101
      src/views/maintain/device/index.vue
  31. 2 3
      src/views/maintain/relationship/index.vue
  32. 2 3
      src/views/maintain/space/index.vue
  33. 2 3
      src/views/maintain/system/index.vue
  34. 2 3
      src/views/manage/build/index.vue
  35. 2 3
      src/views/manage/model/index.vue
  36. 17 17
      src/views/project/index.vue
  37. 2 3
      src/views/scene/plane/index.vue
  38. 2 3
      src/views/scene/system/index.vue
  39. 2 3
      src/views/scene/tiepoint/index.vue

+ 34 - 28
.eslintrc.js

@@ -4,51 +4,57 @@ module.exports = {
     node: true
   },
   extends: [
-    'plugin:vue/essential',
-    '@vue/standard',
-    '@vue/typescript/recommended'
+    "plugin:vue/essential",
+    // '@vue/standard',
+    "eslint:recommended",
+    "@vue/typescript/recommended"
   ],
   parserOptions: {
     ecmaVersion: 2020
   },
   rules: {
-    '@typescript-eslint/ban-types': 'off',
-    '@typescript-eslint/explicit-module-boundary-types': 'off',
-    '@typescript-eslint/member-delimiter-style': ['error',
+    "@typescript-eslint/ban-types": "off",
+    "@typescript-eslint/explicit-module-boundary-types": "off",
+    "@typescript-eslint/member-delimiter-style": [
+      "error",
       {
         multiline: {
-          delimiter: 'none'
+          delimiter: "none"
         },
         singleline: {
-          delimiter: 'comma'
+          delimiter: "comma"
         }
-      }],
-    '@typescript-eslint/no-explicit-any': 'off',
-    '@typescript-eslint/no-var-requires': 'off',
-    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
-    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
-    'space-before-function-paren': ['error', 'never'],
-    'vue/array-bracket-spacing': 'error',
-    'vue/arrow-spacing': 'error',
-    'vue/block-spacing': 'error',
-    'vue/brace-style': 'error',
-    'vue/camelcase': 'error',
-    'vue/comma-dangle': 'error',
-    'vue/component-name-in-template-casing': ['error', 'kebab-case'],
-    'vue/eqeqeq': 'error',
-    'vue/key-spacing': 'error',
-    'vue/match-component-file-name': 'error',
-    'vue/object-curly-spacing': 'error'
+      }
+    ],
+    "@typescript-eslint/no-explicit-any": "off",
+    "@typescript-eslint/no-var-requires": "off",
+    "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
+    "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
+    "space-before-function-paren": [
+      "error",
+      { anonymous: "always", named: "never", asyncArrow: "always" }
+    ],
+    "vue/array-bracket-spacing": "error",
+    "vue/arrow-spacing": "error",
+    "vue/block-spacing": "error",
+    "vue/brace-style": "error",
+    "vue/camelcase": "error",
+    "vue/comma-dangle": "error",
+    "vue/component-name-in-template-casing": ["error", "kebab-case"],
+    "vue/eqeqeq": "error",
+    "vue/key-spacing": "error",
+    "vue/match-component-file-name": "error",
+    "vue/object-curly-spacing": ["error", "always"]
   },
   overrides: [
     {
       files: [
-        '**/__tests__/*.{j,t}s?(x)',
-        '**/tests/unit/**/*.spec.{j,t}s?(x)'
+        "**/__tests__/*.{j,t}s?(x)",
+        "**/tests/unit/**/*.spec.{j,t}s?(x)"
       ],
       env: {
         jest: true
       }
     }
   ]
-}
+};

+ 3 - 0
src/App.vue

@@ -18,6 +18,9 @@ export default class extends Vue {
 <style lang="scss">
 .el-scrollbar {
   height: 100%;
+  .el-scrollbar__wrap{
+      overflow-x: auto;
+  }
   .el-scrollbar__view{
     height: 100%;
 

+ 4 - 4
src/api/articles.ts

@@ -1,8 +1,8 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 export const getArticles = (params: any) =>
   request({
-    url: '/articles',
-    method: 'get',
+    url: "/articles",
+    method: "get",
     params
-  })
+  });

+ 15 - 15
src/api/types.d.ts

@@ -1,17 +1,17 @@
 export interface IArticleData {
-  id: number
-  status: string
-  title: string
-  abstractContent: string
-  fullContent: string
-  sourceURL: string
-  imageURL: string
-  timestamp: string | number
-  platforms: string[]
-  disableComment: boolean
-  importance: number
-  author: string
-  reviewer: string
-  type: string
-  pageviews: number
+  id: number;
+  status: string;
+  title: string;
+  abstractContent: string;
+  fullContent: string;
+  sourceURL: string;
+  imageURL: string;
+  timestamp: string | number;
+  platforms: string[];
+  disableComment: boolean;
+  importance: number;
+  author: string;
+  reviewer: string;
+  type: string;
+  pageviews: number;
 }

+ 10 - 10
src/api/users.ts

@@ -1,21 +1,21 @@
-import request from '@/utils/request'
+import request from "@/utils/request";
 
 export const getUserInfo = (data: any) =>
   request({
-    url: '/users/info',
-    method: 'post',
+    url: "/users/info",
+    method: "post",
     data
-  })
+  });
 
 export const login = (data: any) =>
   request({
-    url: '/users/login',
-    method: 'post',
+    url: "/users/login",
+    method: "post",
     data
-  })
+  });
 
 export const logout = () =>
   request({
-    url: '/users/logout',
-    method: 'post'
-  })
+    url: "/users/logout",
+    method: "post"
+  });

+ 57 - 72
src/components/Breadcrumb/index.vue

@@ -1,101 +1,86 @@
 <template>
-  <el-breadcrumb
-    class="app-breadcrumb"
-    separator="/"
-  >
-    <transition-group name="breadcrumb">
-      <el-breadcrumb-item
-        v-for="(item, index) in breadcrumbs"
-        :key="item.path"
-      >
-        <span
-          v-if="item.redirect === 'noredirect' || index === breadcrumbs.length-1"
-          class="no-redirect"
-        >{{ item.meta.title }}</span>
-        <a
-          v-else
-          @click.prevent="handleLink(item)"
-        >{{ item.meta.title }}</a>
-      </el-breadcrumb-item>
-    </transition-group>
-  </el-breadcrumb>
+    <el-breadcrumb class="app-breadcrumb" separator="/">
+        <transition-group name="breadcrumb">
+            <el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
+                <span v-if="item.redirect === 'noredirect' || index === breadcrumbs.length - 1" class="no-redirect">{{ item.meta.title }}</span>
+                <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
+            </el-breadcrumb-item>
+        </transition-group>
+    </el-breadcrumb>
 </template>
 
 <script lang="ts">
-import { compile } from 'path-to-regexp'
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { RouteRecord, Route } from 'vue-router'
+import { compile } from "path-to-regexp";
+import { Component, Vue, Watch } from "vue-property-decorator";
+import { RouteRecord, Route } from "vue-router";
 
 @Component({
-  name: 'Breadcrumb'
+    name: "Breadcrumb",
 })
 export default class extends Vue {
-  private breadcrumbs: RouteRecord[] = [];
+    private breadcrumbs: RouteRecord[] = [];
 
-  @Watch('$route')
-  private onRouteChange(route: Route) {
-    // if you go to the redirect page, do not update the breadcrumbs
-    if (route.path.startsWith('/redirect/')) {
-      return
+    @Watch("$route")
+    private onRouteChange(route: Route) {
+        // if you go to the redirect page, do not update the breadcrumbs
+        if (route.path.startsWith("/redirect/")) {
+            return;
+        }
+        this.getBreadcrumb();
     }
-    this.getBreadcrumb()
-  }
 
-  created() {
-    this.getBreadcrumb()
-  }
+    created() {
+        this.getBreadcrumb();
+    }
 
-  private getBreadcrumb() {
-    let matched = this.$route.matched.filter(
-      item => item.meta && item.meta.title
-    )
-    const first = matched[0]
+    private getBreadcrumb() {
+        let matched = this.$route.matched.filter((item) => item.meta && item.meta.title);
+        const first = matched[0];
 
-    this.breadcrumbs = matched.filter(item => {
-      return item.meta && item.meta.title && item.meta.breadcrumb !== false
-    })
-  }
+        this.breadcrumbs = matched.filter((item) => {
+            return item.meta && item.meta.title && item.meta.breadcrumb !== false;
+        });
+    }
 
-  private isDashboard(route: RouteRecord) {
-    const name = route && route.meta && route.meta.title
-    return name === 'Dashboard'
-  }
+    private isDashboard(route: RouteRecord) {
+        const name = route && route.meta && route.meta.title;
+        return name === "Dashboard";
+    }
 
-  private pathCompile(path: string) {
-    // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
-    const { params } = this.$route
-    const toPath = compile(path)
-    return toPath(params)
-  }
+    private pathCompile(path: string) {
+        // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
+        const { params } = this.$route;
+        const toPath = compile(path);
+        return toPath(params);
+    }
 
-  private handleLink(item: any) {
-    const { redirect, path } = item
-    if (redirect) {
-      this.$router.push(redirect)
-      return
+    private handleLink(item: any) {
+        const { redirect, path } = item;
+        if (redirect) {
+            this.$router.push(redirect);
+            return;
+        }
+        this.$router.push(this.pathCompile(path));
     }
-    this.$router.push(this.pathCompile(path))
-  }
 }
 </script>
 
 <style lang="scss" scoped>
 .el-breadcrumb__inner,
 .el-breadcrumb__inner a {
-  font-weight: 400 !important;
-
+    font-weight: 400 !important;
 }
 
 .app-breadcrumb.el-breadcrumb {
-  display: inline-block;
-  font-size: 14px;
-  height: 30px;
-  line-height: 40px;
-  margin-left: 8px;
+    display: inline-block;
+    font-size: 14px;
+    height: 30px;
+    line-height: 40px;
+    margin-left: 8px;
 
-  .no-redirect {
-    color: #97a8be;
-    cursor: text;
-  }
+    .no-redirect {
+        color: #97a8be;
+        cursor: text;
+    }
 }
 </style>

+ 11 - 18
src/components/Hamburger/index.vue

@@ -1,37 +1,30 @@
 <template>
-  <div
-    :class="[{'is-active': isActive}]"
-    @click="toggleClick"
-  >
-    <svg-icon
-      name="hamburger"
-      width="20"
-      height="20"
-    />
-  </div>
+    <div :class="[{ 'is-active': isActive }]" @click="toggleClick">
+        <svg-icon name="hamburger" width="20" height="20" />
+    </div>
 </template>
 
 <script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator'
+import { Component, Prop, Vue } from "vue-property-decorator";
 
 @Component({
-  name: 'Hamburger'
+    name: "Hamburger",
 })
 export default class extends Vue {
-  @Prop({ default: false }) private isActive!: boolean
+    @Prop({ default: false }) private isActive!: boolean;
 
-  private toggleClick() {
-    this.$emit('toggle-click')
-  }
+    private toggleClick() {
+        this.$emit("toggle-click");
+    }
 }
 </script>
 
 <style lang="scss" scoped>
 .svg-icon {
-  vertical-align: middle;
+    vertical-align: middle;
 }
 
 .is-active {
-  transform: rotate(180deg);
+    transform: rotate(180deg);
 }
 </style>

+ 8 - 11
src/layout/components/AppMain.vue

@@ -1,25 +1,22 @@
 <template>
-  <section class="app-main">
-    <transition
-      name="fade-transform"
-      mode="out-in"
-    >
-      <router-view />
-    </transition>
-  </section>
+    <section class="app-main">
+        <transition name="fade-transform" mode="out-in">
+            <router-view />
+        </transition>
+    </section>
 </template>
 
 <script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
+import { Component, Vue } from "vue-property-decorator";
 
 @Component({
-  name: 'AppMain'
+    name: "AppMain",
 })
 export default class extends Vue {}
 </script>
 
 <style lang="scss" scoped>
 .app-main {
-  overflow: hidden;
+    height: calc(100% - 48px);
 }
 </style>

+ 116 - 127
src/layout/components/Navbar/index.vue

@@ -1,157 +1,146 @@
 <template>
-  <div class="navbar">
-    <span class="title" v-show="sidebar.opened">万达数字化运维平台</span>
-    <hamburger
-      id="hamburger-container"
-      :is-active="sidebar.opened"
-      class="hamburger-container"
-      @toggle-click="toggleSideBar"
-    />
-
-    <div class="right-menu">
-      <el-dropdown
-        class="avatar-container right-menu-item hover-effect"
-      >
-        <div class="avatar-wrapper">
-        <span> yanruolan </span>
-          <i class="el-icon-user-solid"/>
+    <div class="navbar">
+        <span class="title" v-show="sidebar.opened">万达数字化运维平台</span>
+        <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggle-click="toggleSideBar" />
+
+        <div class="right-menu">
+            <el-dropdown class="avatar-container right-menu-item hover-effect">
+                <div class="avatar-wrapper">
+                    <span> yanruolan </span>
+                    <i class="el-icon-user-solid" />
+                </div>
+                <el-dropdown-menu slot="dropdown">
+                    <router-link to="/">
+                        <el-dropdown-item> 退出 </el-dropdown-item>
+                    </router-link>
+                </el-dropdown-menu>
+            </el-dropdown>
         </div>
-        <el-dropdown-menu slot="dropdown">
-          <router-link to="/">
-            <el-dropdown-item>
-              退出
-            </el-dropdown-item>
-          </router-link>
-
-        </el-dropdown-menu>
-      </el-dropdown>
     </div>
-  </div>
 </template>
 
 <script lang="ts">
-import {Component, Vue} from 'vue-property-decorator'
-import {AppModule} from '@/store/modules/app'
-import {UserModule} from '@/store/modules/user'
-import Breadcrumb from '@/components/Breadcrumb/index.vue'
-import Hamburger from '@/components/Hamburger/index.vue'
+import { Component, Vue } from "vue-property-decorator";
+import { AppModule } from "@/store/modules/app";
+import { UserModule } from "@/store/modules/user";
+import Breadcrumb from "@/components/Breadcrumb/index.vue";
+import Hamburger from "@/components/Hamburger/index.vue";
 
 @Component({
-  name: 'Navbar',
-  components: {
-    Breadcrumb,
-    Hamburger
-  }
+    name: "Navbar",
+    components: {
+        Breadcrumb,
+        Hamburger,
+    },
 })
 export default class extends Vue {
-  get sidebar() {
-    return AppModule.sidebar
-  }
-
-  get device() {
-    return AppModule.device.toString()
-  }
-
-  get avatar() {
-    return UserModule.avatar
-  }
-
-  private toggleSideBar() {
-    AppModule.ToggleSideBar(false)
-  }
-
-  private async logout() {
-    await UserModule.LogOut()
-    // this.$router.push(`/login?redirect=${this.$route.fullPath}`)
-  }
-}
-</script>
+    get sidebar() {
+        return AppModule.sidebar;
+    }
 
-<style lang="scss" scoped>
-.navbar {
-  height: 50px;
-  overflow: hidden;
-  position: relative;
-  background-color: #2b3643;
-  box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
-  z-index: 1002;
-
-  .title {
-    float: left;
-    padding: 0 20px;
-    margin: 0 auto;
-    line-height: 46px;
-    height: 100%;
-    color: #fff;
-  }
-
-  .hamburger-container {
-    color: #fff;
-    line-height: 46px;
-    height: 100%;
-    float: left;
-    width: 60px;
-    //padding: 0 15px;
-    cursor: pointer;
-    transition: background .3s;
-    -webkit-tap-highlight-color: transparent;
-
-    &:hover {
-      background: rgba(0, 0, 0, .025)
+    get device() {
+        return AppModule.device.toString();
     }
-  }
 
+    get avatar() {
+        return UserModule.avatar;
+    }
 
-  .right-menu {
-    float: right;
-    height: 100%;
-    line-height: 50px;
+    private toggleSideBar() {
+        AppModule.ToggleSideBar(false);
+    }
 
-    &:focus {
-      outline: none;
+    private async logout() {
+        await UserModule.LogOut();
+        // this.$router.push(`/login?redirect=${this.$route.fullPath}`)
     }
+}
+</script>
 
-    .right-menu-item {
-      display: inline-block;
-      padding: 0 8px;
-      height: 100%;
-      font-size: 18px;
-      color: #5a5e66;
-      vertical-align: text-bottom;
+<style lang="scss" scoped>
+.navbar {
+    height: 50px;
+    overflow: hidden;
+    position: relative;
+    background-color: #2b3643;
+    box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+    z-index: 1002;
+
+    .title {
+        float: left;
+        padding: 0 20px;
+        margin: 0 auto;
+        line-height: 46px;
+        height: 100%;
+        color: #fff;
+    }
 
-      &.hover-effect {
+    .hamburger-container {
+        color: #fff;
+        line-height: 46px;
+        height: 100%;
+        float: left;
+        width: 60px;
+        //padding: 0 15px;
         cursor: pointer;
-        transition: background .3s;
+        transition: background 0.3s;
+        -webkit-tap-highlight-color: transparent;
 
         &:hover {
-          background: rgba(0, 0, 0, .025)
+            background: rgba(0, 0, 0, 0.025);
         }
-      }
     }
 
-    .avatar-container {
-      margin-right: 30px;
-
-      .avatar-wrapper {
-        position: relative;
-        color: #409eff;
-        font-size: 18px;
-        .user-avatar {
-          cursor: pointer;
-          width: 40px;
-          height: 40px;
-          border-radius: 10px;
+    .right-menu {
+        float: right;
+        height: 100%;
+        line-height: 50px;
+
+        &:focus {
+            outline: none;
+        }
+
+        .right-menu-item {
+            display: inline-block;
+            padding: 0 8px;
+            height: 100%;
+            font-size: 18px;
+            color: #5a5e66;
+            vertical-align: text-bottom;
+
+            &.hover-effect {
+                cursor: pointer;
+                transition: background 0.3s;
+
+                &:hover {
+                    background: rgba(0, 0, 0, 0.025);
+                }
+            }
         }
 
-        .el-icon-caret-bottom {
-          cursor: pointer;
-          position: absolute;
-          right: -20px;
-          top: 25px;
-          font-size: 12px;
+        .avatar-container {
+            margin-right: 30px;
+
+            .avatar-wrapper {
+                position: relative;
+                color: #409eff;
+                font-size: 18px;
+                .user-avatar {
+                    cursor: pointer;
+                    width: 40px;
+                    height: 40px;
+                    border-radius: 10px;
+                }
+
+                .el-icon-caret-bottom {
+                    cursor: pointer;
+                    position: absolute;
+                    right: -20px;
+                    top: 25px;
+                    font-size: 12px;
+                }
+            }
         }
-      }
     }
-  }
 }
 </style>

+ 113 - 138
src/layout/components/Sidebar/SidebarItem.vue

@@ -1,182 +1,157 @@
 <template>
-  <div
-    v-if="!item.meta || !item.meta.hidden"
-    :class="['menu-wrapper', isCollapse ? 'simple-mode' : 'full-mode', {'first-level': isFirstLevel}]">
-    <template v-if="theOnlyOneChild && !theOnlyOneChild.children">
-      <sidebar-item-link
-        v-if="theOnlyOneChild.meta"
-        :to="resolvePath(theOnlyOneChild.path)"
-      >
-        <el-menu-item
-          :index="resolvePath(theOnlyOneChild.path)"
-          :class="{'submenu-title-noDropdown': isFirstLevel}"
-        >
-          <svg-icon
-            v-if="theOnlyOneChild.meta.icon"
-            :name="theOnlyOneChild.meta.icon"
-          />
-          <span
-            v-if="theOnlyOneChild.meta.title"
-            slot="title"
-            class="title-name"
-          >{{ theOnlyOneChild.meta.title }}</span>
-        </el-menu-item>
-      </sidebar-item-link>
-    </template>
-    <el-submenu
-      v-else
-      :index="resolvePath(item.path)"
-      popper-append-to-body
-    >
-      <template slot="title">
-        <svg-icon
-          v-if="item.meta && item.meta.icon"
-          :name="item.meta.icon"
-        />
-        <span
-          v-if="item.meta && item.meta.title"
-          slot="title"
-        >{{ item.meta.title }}</span>
-      </template>
-      <template v-if="item.children">
-        <sidebar-item
-          v-for="child in item.children"
-          :key="child.path"
-          :item="child"
-          :is-collapse="isCollapse"
-          :is-first-level="false"
-          :base-path="resolvePath(child.path)"
-          class="nest-menu"
-        />
-      </template>
-    </el-submenu>
-  </div>
+    <div v-if="!item.meta || !item.meta.hidden" :class="['menu-wrapper', isCollapse ? 'simple-mode' : 'full-mode', { 'first-level': isFirstLevel }]">
+        <template v-if="theOnlyOneChild && !theOnlyOneChild.children">
+            <sidebar-item-link v-if="theOnlyOneChild.meta" :to="resolvePath(theOnlyOneChild.path)">
+                <el-menu-item :index="resolvePath(theOnlyOneChild.path)" :class="{ 'submenu-title-noDropdown': isFirstLevel }">
+                    <svg-icon v-if="theOnlyOneChild.meta.icon" :name="theOnlyOneChild.meta.icon" />
+                    <span v-if="theOnlyOneChild.meta.title" slot="title" class="title-name">{{ theOnlyOneChild.meta.title }}</span>
+                </el-menu-item>
+            </sidebar-item-link>
+        </template>
+        <el-submenu v-else :index="resolvePath(item.path)" popper-append-to-body>
+            <template slot="title">
+                <svg-icon v-if="item.meta && item.meta.icon" :name="item.meta.icon" />
+                <span v-if="item.meta && item.meta.title" slot="title">{{ item.meta.title }}</span>
+            </template>
+            <template v-if="item.children">
+                <sidebar-item
+                    v-for="child in item.children"
+                    :key="child.path"
+                    :item="child"
+                    :is-collapse="isCollapse"
+                    :is-first-level="false"
+                    :base-path="resolvePath(child.path)"
+                    class="nest-menu"
+                />
+            </template>
+        </el-submenu>
+    </div>
 </template>
 
 <script lang="ts">
-import path from 'path'
-import { Component, Prop, Vue } from 'vue-property-decorator'
-import { RouteConfig } from 'vue-router'
-import { isExternal } from '@/utils/validate'
-import SidebarItemLink from './SidebarItemLink.vue'
+import path from "path";
+import { Component, Prop, Vue } from "vue-property-decorator";
+import { RouteConfig } from "vue-router";
+import { isExternal } from "@/utils/validate";
+import SidebarItemLink from "./SidebarItemLink.vue";
 
 @Component({
-  // Set 'name' here to prevent uglifyjs from causing recursive component not work
-  // See https://medium.com/haiiro-io/element-component-name-with-vue-class-component-f3b435656561 for detail
-  name: 'SidebarItem',
-  components: {
-    SidebarItemLink
-  }
+    // Set 'name' here to prevent uglifyjs from causing recursive component not work
+    // See https://medium.com/haiiro-io/element-component-name-with-vue-class-component-f3b435656561 for detail
+    name: "SidebarItem",
+    components: {
+        SidebarItemLink,
+    },
 })
 export default class extends Vue {
-  @Prop({ required: true }) private item!: RouteConfig
-  @Prop({ default: false }) private isCollapse!: boolean
-  @Prop({ default: true }) private isFirstLevel!: boolean
-  @Prop({ default: '' }) private basePath!: string
-
-  get showingChildNumber() {
-    if (this.item.children) {
-      const showingChildren = this.item.children.filter((item) => {
-        if (item.meta && item.meta.hidden) {
-          return false
-        } else {
-          return true
+    @Prop({ required: true }) private item!: RouteConfig;
+    @Prop({ default: false }) private isCollapse!: boolean;
+    @Prop({ default: true }) private isFirstLevel!: boolean;
+    @Prop({ default: "" }) private basePath!: string;
+
+    get showingChildNumber() {
+        if (this.item.children) {
+            const showingChildren = this.item.children.filter((item) => {
+                if (item.meta && item.meta.hidden) {
+                    return false;
+                } else {
+                    return true;
+                }
+            });
+            return showingChildren.length;
         }
-      })
-      return showingChildren.length
+        return 0;
     }
-    return 0
-  }
 
-  get theOnlyOneChild() {
-    if (this.showingChildNumber > 1) {
-      return null
-    }
-    if (this.item.children) {
-      for (const child of this.item.children) {
-        if (!child.meta || !child.meta.hidden) {
-          return child
+    get theOnlyOneChild() {
+        if (this.showingChildNumber > 1) {
+            return null;
         }
-      }
-    }
-    // If there is no children, return itself with path removed,
-    // because this.basePath already conatins item's path information
-    return { ...this.item, path: '' }
-  }
-
-  private resolvePath(routePath: string) {
-    if (isExternal(routePath)) {
-      return routePath
+        if (this.item.children) {
+            for (const child of this.item.children) {
+                if (!child.meta || !child.meta.hidden) {
+                    return child;
+                }
+            }
+        }
+        // If there is no children, return itself with path removed,
+        // because this.basePath already conatins item's path information
+        return { ...this.item, path: "" };
     }
-    if (isExternal(this.basePath)) {
-      return this.basePath
+
+    private resolvePath(routePath: string) {
+        if (isExternal(routePath)) {
+            return routePath;
+        }
+        if (isExternal(this.basePath)) {
+            return this.basePath;
+        }
+        return path.resolve(this.basePath, routePath);
     }
-    return path.resolve(this.basePath, routePath)
-  }
 }
 </script>
 
 <style lang="scss">
 .el-submenu.is-active > .el-submenu__title {
-  color: $subMenuActiveText !important;
+    color: $subMenuActiveText !important;
 }
 
 .full-mode {
-  .nest-menu .el-submenu>.el-submenu__title,
-  .el-submenu .el-menu-item {
-    min-width: $sideBarWidth !important;
-    background-color: $subMenuBg !important;
+    .nest-menu .el-submenu > .el-submenu__title,
+    .el-submenu .el-menu-item {
+        min-width: $sideBarWidth !important;
+        background-color: $subMenuBg !important;
 
-    &:hover {
-      background-color: $subMenuHover !important;
-    }
-    &:active{
-      background-color: $subMenuHover !important;
+        &:hover {
+            background-color: $subMenuHover !important;
+        }
+        &:active {
+            background-color: $subMenuHover !important;
+        }
     }
-  }
 }
 
 .simple-mode {
-  &.first-level {
-    .submenu-title-noDropdown {
-      padding: 0 !important;
-      position: relative;
-
-      .el-tooltip {
-        padding: 0 !important;
-      }
-    }
+    &.first-level {
+        .submenu-title-noDropdown {
+            padding: 0 !important;
+            position: relative;
+
+            .el-tooltip {
+                padding: 0 !important;
+            }
+        }
 
-    .el-submenu {
-      overflow: hidden;
+        .el-submenu {
+            overflow: hidden;
 
-      &>.el-submenu__title {
-        padding: 0px !important;
+            & > .el-submenu__title {
+                padding: 0px !important;
 
-        .el-submenu__icon-arrow {
-          display: none;
-        }
+                .el-submenu__icon-arrow {
+                    display: none;
+                }
 
-        &>span {
-          visibility: hidden;
+                & > span {
+                    visibility: hidden;
+                }
+            }
         }
-      }
     }
-  }
 }
 </style>
 
 <style lang="scss" scoped>
-.title-name{
-  color: #ffffff;
+.title-name {
+    color: #ffffff;
 }
 .svg-icon {
-  margin-right: 16px;
+    margin-right: 16px;
 }
 
 .simple-mode {
-  .svg-icon {
-    margin-left: 20px;
-  }
+    .svg-icon {
+        margin-left: 20px;
+    }
 }
 </style>

+ 11 - 21
src/layout/components/Sidebar/SidebarItemLink.vue

@@ -1,34 +1,24 @@
 <template>
-  <a
-    v-if="isExternal(to)"
-    :href="to"
-    target="_blank"
-    rel="noopener"
-  >
-    <slot/>
-  </a>
-  <router-link
-    v-else
-    :to="to"
-    active-class="active"
-  >
-    <slot/>
-  </router-link>
+    <a v-if="isExternal(to)" :href="to" target="_blank" rel="noopener">
+        <slot />
+    </a>
+    <router-link v-else :to="to" active-class="active">
+        <slot />
+    </router-link>
 </template>
 
 <script lang="ts">
-import {Component, Prop, Vue} from 'vue-property-decorator'
-import {isExternal} from '@/utils/validate'
+import { Component, Prop, Vue } from "vue-property-decorator";
+import { isExternal } from "@/utils/validate";
 
 @Component({
-  name: 'SidebarItemLink'
+    name: "SidebarItemLink",
 })
 export default class extends Vue {
-  @Prop({required: true}) private to!: string
+    @Prop({ required: true }) private to!: string;
 
-  private isExternal = isExternal
+    private isExternal = isExternal;
 }
 </script>
 <style lang="scss">
-
 </style>

+ 64 - 70
src/layout/components/Sidebar/index.vue

@@ -1,103 +1,97 @@
 <template>
-  <el-scrollbar wrap-class="scrollbar-wrapper">
-    <el-menu
-      :default-active="activeMenu"
-      :collapse="isCollapse"
-      :background-color="variables.menuBg"
-      :text-color="variables.menuText"
-      :active-text-color="variables.menuActiveText"
-      :unique-opened="false"
-      :collapse-transition="false"
-      mode="vertical"
-    >
-      <sidebar-item
-        v-for="route in routes"
-        :key="route.path"
-        :item="route"
-        :base-path="route.path"
-        :is-collapse="isCollapse"
-      />
-    </el-menu>
-  </el-scrollbar>
+    <el-scrollbar wrap-class="scrollbar-wrapper">
+        <el-menu
+            :default-active="activeMenu"
+            :collapse="isCollapse"
+            :background-color="variables.menuBg"
+            :text-color="variables.menuText"
+            :active-text-color="variables.menuActiveText"
+            :unique-opened="false"
+            :collapse-transition="false"
+            mode="vertical"
+        >
+            <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" :is-collapse="isCollapse" />
+        </el-menu>
+    </el-scrollbar>
 </template>
 
 <script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { AppModule } from '@/store/modules/app'
-import SidebarItem from './SidebarItem.vue'
-import variables from '@/styles/_variables.scss'
+import { Component, Vue } from "vue-property-decorator";
+import { AppModule } from "@/store/modules/app";
+import SidebarItem from "./SidebarItem.vue";
+import variables from "@/styles/_variables.scss";
 
 @Component({
-  name: 'SideBar',
-  components: {
-    SidebarItem
-  }
+    name: "SideBar",
+    components: {
+        SidebarItem,
+    },
 })
 export default class extends Vue {
-  get sidebar() {
-    return AppModule.sidebar
-  }
+    get sidebar() {
+        return AppModule.sidebar;
+    }
 
-  get routes() {
-    return (this.$router as any).options.routes
-  }
+    get routes() {
+        return (this.$router as any).options.routes;
+    }
 
-  get variables() {
-    return variables
-  }
+    get variables() {
+        return variables;
+    }
 
-  get activeMenu() {
-    const route = this.$route
-    const { meta, path } = route
-    if (meta.activeMenu) {
-      return meta.activeMenu
+    get activeMenu() {
+        const route = this.$route;
+        const { meta, path } = route;
+        if (meta.activeMenu) {
+            return meta.activeMenu;
+        }
+        return path;
     }
-    return path
-  }
 
-  get isCollapse() {
-    return !this.sidebar.opened
-  }
+    get isCollapse() {
+        return !this.sidebar.opened;
+    }
 }
 </script>
 
 <style lang="scss">
 .sidebar-container {
-  // reset element-ui css
-  .horizontal-collapse-transition {
-    transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
-  }
-
-  .scrollbar-wrapper {
-    overflow-x: hidden !important;
-  }
+    // reset element-ui css
+    .horizontal-collapse-transition {
+        transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
+    }
 
-  .el-scrollbar__view {
-    height:calc(100% - 50px);
-    background: #2b3643;
-  }
+    .scrollbar-wrapper {
+        overflow-x: hidden !important;
+    }
 
-  .el-scrollbar__bar {
-    &.is-vertical {
-      right: 0px;
+    .el-scrollbar__view {
+        height: calc(100% - 50px);
+        background: #2b3643;
     }
 
-    &.is-horizontal {
-      display: none;
+    .el-scrollbar__bar {
+        &.is-vertical {
+            right: 0px;
+        }
+
+        &.is-horizontal {
+            display: none;
+        }
     }
-  }
 }
 </style>
 
 <style lang="scss" scoped>
 .el-scrollbar {
-  height: 100%;
+    height: 100%;
 }
 
 .el-menu {
-  margin-top: 50px;
-  border: none;
-  height: 100%;
-  width: 100% !important;
+    margin-top: 50px;
+    border: none;
+    height: 100%;
+    width: 100% !important;
 }
 </style>

+ 4 - 4
src/layout/components/index.ts

@@ -1,4 +1,4 @@
-export {default as AppMain} from './AppMain.vue'
-export {default as Navbar} from './Navbar/index.vue'
-export {default as Sidebar} from './Sidebar/index.vue'
-export {default as Breadcrumb} from '@/components/Breadcrumb/index.vue'
+export { default as AppMain } from "./AppMain.vue";
+export { default as Navbar } from "./Navbar/index.vue";
+export { default as Sidebar } from "./Sidebar/index.vue";
+export { default as Breadcrumb } from "@/components/Breadcrumb/index.vue";

+ 84 - 93
src/layout/index.vue

@@ -1,135 +1,126 @@
 <template>
-  <div
-    :class="classObj"
-    class="app-wrapper"
-  >
-    <div
-      v-if="classObj.mobile && sidebar.opened"
-      class="drawer-bg"
-      @click="handleClickOutside"
-    />
-    <sidebar class="sidebar-container"/>
-    <navbar/>
-    <div class="main-container">
-      <breadcrumb
-        id="breadcrumb-container"
-        class="breadcrumb-container"
-      />
-      <hr>
-      <app-main/>
+    <div :class="classObj" class="app-wrapper">
+        <div v-if="classObj.mobile && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
+        <sidebar class="sidebar-container" />
+        <navbar />
+        <div class="main-container">
+            <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
+            <hr />
+            <app-main />
+        </div>
     </div>
-  </div>
 </template>
 
 <script lang="ts">
-import {Component} from 'vue-property-decorator'
-import {mixins} from 'vue-class-component'
-import {DeviceType, AppModule} from '@/store/modules/app'
-import {AppMain, Navbar, Sidebar, Breadcrumb} from './components'
-import ResizeMixin from './mixin/resize'
+import { Component } from "vue-property-decorator";
+import { mixins } from "vue-class-component";
+import { DeviceType, AppModule } from "@/store/modules/app";
+import { AppMain, Navbar, Sidebar, Breadcrumb } from "./components";
+import ResizeMixin from "./mixin/resize";
 
 @Component({
-  name: 'Layout',
-  components: {
-    AppMain,
-    Navbar,
-    Sidebar,
-    Breadcrumb
-  }
+    name: "Layout",
+    components: {
+        AppMain,
+        Navbar,
+        Sidebar,
+        Breadcrumb,
+    },
 })
 export default class extends mixins(ResizeMixin) {
-  get classObj() {
-    return {
-      hideSidebar: !this.sidebar.opened,
-      openSidebar: this.sidebar.opened,
-      withoutAnimation: this.sidebar.withoutAnimation,
-      mobile: this.device === DeviceType.Mobile
+    get classObj() {
+        return {
+            hideSidebar: !this.sidebar.opened,
+            openSidebar: this.sidebar.opened,
+            withoutAnimation: this.sidebar.withoutAnimation,
+            mobile: this.device === DeviceType.Mobile,
+        };
     }
-  }
 
-  private handleClickOutside() {
-    AppModule.CloseSideBar(false)
-  }
+    private handleClickOutside() {
+        AppModule.CloseSideBar(false);
+    }
 }
 </script>
 
 <style lang="scss" scoped>
 .app-wrapper {
-  @include clearfix;
-  position: relative;
-  height: 100%;
-  width: 100%;
+    @include clearfix;
+    position: relative;
+    height: 100%;
+    width: 100%;
 }
 
 .drawer-bg {
-  background: #000;
-  opacity: 0.3;
-  width: 100%;
-  top: 0;
-  height: 100%;
-  position: absolute;
-  z-index: 999;
+    background: #000;
+    opacity: 0.3;
+    width: 100%;
+    top: 0;
+    height: 100%;
+    position: absolute;
+    z-index: 999;
 }
 
 .main-container {
-  min-height: 100%;
-  transition: margin-left .28s;
-  margin-left: $sideBarWidth;
-  position: relative;
+    height: calc(100% - 50px);
+    transition: margin-left 0.28s;
+    margin-left: $sideBarWidth;
+    position: relative;
+    overflow-y: hidden;
 }
 
 .sidebar-container {
-  transition: width 0.28s;
-  width: $sideBarWidth !important;
-  height: 100%;
-  position: fixed;
-  font-size: 0px;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  z-index: 1001;
-  overflow: hidden;
+    transition: width 0.28s;
+    width: $sideBarWidth !important;
+    height: 100%;
+    position: fixed;
+    font-size: 0px;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    z-index: 1001;
+    overflow: hidden;
 }
 
 .hideSidebar {
-  .main-container {
-    margin-left: 54px;
-  }
+    .main-container {
+        margin-left: 54px;
+    }
 
-  .sidebar-container {
-    width: 54px !important;
-  }
+    .sidebar-container {
+        width: 54px !important;
+    }
 }
 
 /* for mobile response 适配移动端 */
 .mobile {
-  .main-container {
-    margin-left: 0px;
-  }
+    .main-container {
+        margin-left: 0px;
+    }
 
-  .sidebar-container {
-    transition: transform .28s;
-    width: $sideBarWidth !important;
-  }
+    .sidebar-container {
+        transition: transform 0.28s;
+        width: $sideBarWidth !important;
+    }
 
-  &.openSidebar {
-    position: fixed;
-    top: 0;
-  }
+    &.openSidebar {
+        position: fixed;
+        top: 0;
+    }
 
-  &.hideSidebar {
-    .sidebar-container {
-      pointer-events: none;
-      transition-duration: 0.3s;
-      transform: translate3d(-$sideBarWidth, 0, 0);
+    &.hideSidebar {
+        .sidebar-container {
+            pointer-events: none;
+            transition-duration: 0.3s;
+            transform: translate3d(-$sideBarWidth, 0, 0);
+        }
     }
-  }
 }
 
 .withoutAnimation {
-  .main-container,
-  .sidebar-container {
-    transition: none;
-  }
+    .main-container,
+    .sidebar-container {
+        transition: none;
+    }
 }
 </style>

+ 18 - 18
src/layout/mixin/resize.ts

@@ -1,54 +1,54 @@
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { AppModule, DeviceType } from '@/store/modules/app'
+import { Component, Vue, Watch } from "vue-property-decorator";
+import { AppModule, DeviceType } from "@/store/modules/app";
 
-const WIDTH = 992 // refer to Bootstrap's responsive design
+const WIDTH = 992; // refer to Bootstrap's responsive design
 
 @Component({
-  name: 'ResizeMixin'
+  name: "ResizeMixin"
 })
 export default class extends Vue {
   get device() {
-    return AppModule.device
+    return AppModule.device;
   }
 
   get sidebar() {
-    return AppModule.sidebar
+    return AppModule.sidebar;
   }
 
-  @Watch('$route')
+  @Watch("$route")
   private onRouteChange() {
     if (this.device === DeviceType.Mobile && this.sidebar.opened) {
-      AppModule.CloseSideBar(false)
+      AppModule.CloseSideBar(false);
     }
   }
 
   beforeMount() {
-    window.addEventListener('resize', this.resizeHandler)
+    window.addEventListener("resize", this.resizeHandler);
   }
 
   mounted() {
-    const isMobile = this.isMobile()
+    const isMobile = this.isMobile();
     if (isMobile) {
-      AppModule.ToggleDevice(DeviceType.Mobile)
-      AppModule.CloseSideBar(true)
+      AppModule.ToggleDevice(DeviceType.Mobile);
+      AppModule.CloseSideBar(true);
     }
   }
 
   beforeDestroy() {
-    window.removeEventListener('resize', this.resizeHandler)
+    window.removeEventListener("resize", this.resizeHandler);
   }
 
   private isMobile() {
-    const rect = document.body.getBoundingClientRect()
-    return rect.width - 1 < WIDTH
+    const rect = document.body.getBoundingClientRect();
+    return rect.width - 1 < WIDTH;
   }
 
   private resizeHandler() {
     if (!document.hidden) {
-      const isMobile = this.isMobile()
-      AppModule.ToggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop)
+      const isMobile = this.isMobile();
+      AppModule.ToggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop);
       if (isMobile) {
-        AppModule.CloseSideBar(true)
+        AppModule.CloseSideBar(true);
       }
     }
   }

+ 19 - 19
src/main.ts

@@ -1,29 +1,29 @@
-import Vue from 'vue'
+import Vue from "vue";
 
-import 'normalize.css'
-import ElementUI from 'element-ui'
-import SvgIcon from 'vue-svgicon'
+import "normalize.css";
+import ElementUI from "element-ui";
+import SvgIcon from "vue-svgicon";
 
-import '@/styles/element-variables.scss'
-import '@/styles/index.scss'
+import "@/styles/element-variables.scss";
+import "@/styles/index.scss";
 
-import App from '@/App.vue'
-import store from '@/store'
-import router from '@/router/index'
-import '@/icons/components'
-import '@/permission'
+import App from "@/App.vue";
+import store from "@/store";
+import router from "@/router/index";
+import "@/icons/components";
+import "@/permission";
 
-Vue.use(ElementUI)
+Vue.use(ElementUI);
 Vue.use(SvgIcon, {
-  tagName: 'svg-icon',
-  defaultWidth: '1em',
-  defaultHeight: '1em'
-})
+  tagName: "svg-icon",
+  defaultWidth: "1em",
+  defaultHeight: "1em"
+});
 
-Vue.config.productionTip = false
+Vue.config.productionTip = false;
 
 new Vue({
   router,
   store,
-  render: (h) => h(App)
-}).$mount('#app')
+  render: h => h(App)
+}).$mount("#app");

+ 27 - 27
src/permission.ts

@@ -1,60 +1,60 @@
-import router from './router/index'
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
-import { Message } from 'element-ui'
-import { Route } from 'vue-router'
-import { UserModule } from '@/store/modules/user'
+import router from "./router/index";
+import NProgress from "nprogress";
+import "nprogress/nprogress.css";
+import { Message } from "element-ui";
+import { Route } from "vue-router";
+import { UserModule } from "@/store/modules/user";
 
-NProgress.configure({ showSpinner: false })
+NProgress.configure({ showSpinner: false });
 
-const whiteList = ['/login']
+const whiteList = ["/login"];
 
-router.beforeEach(async(to: Route, _: Route, next: any) => {
+router.beforeEach(async (to: Route, _: Route, next: any) => {
   // Start progress bar
-  NProgress.start()
+  NProgress.start();
 
   // Determine whether the user has logged in
   if (UserModule.token) {
-    if (to.path === '/login') {
+    if (to.path === "/login") {
       // If is logged in, redirect to the home page
-      next({ path: '/' })
-      NProgress.done()
+      next({ path: "/" });
+      NProgress.done();
     } else {
       // Check whether the user has obtained his permission roles
       if (UserModule.roles.length === 0) {
         try {
           // Get user info, including roles
-          await UserModule.GetUserInfo()
+          await UserModule.GetUserInfo();
           // Set the replace: true, so the navigation will not leave a history record
-          next({ ...to, replace: true })
+          next({ ...to, replace: true });
         } catch (err) {
           // Remove token and redirect to login page
-          UserModule.ResetToken()
-          Message.error(err || 'Has Error')
-          next(`/login?redirect=${to.path}`)
-          NProgress.done()
+          UserModule.ResetToken();
+          Message.error(err || "Has Error");
+          next(`/login?redirect=${to.path}`);
+          NProgress.done();
         }
       } else {
-        next()
+        next();
       }
     }
   } else {
     // Has no token
     if (whiteList.indexOf(to.path) !== -1) {
       // In the free login whitelist, go directly
-      next()
+      next();
     } else {
       // Other pages that do not have permission to access are redirected to the login page.
-      next(`/login?redirect=${to.path}`)
-      NProgress.done()
+      next(`/login?redirect=${to.path}`);
+      NProgress.done();
     }
   }
-})
+});
 
 router.afterEach((to: Route) => {
   // Finish progress bar
-  NProgress.done()
+  NProgress.done();
 
   // set page title
-  document.title = to.meta.title
-})
+  document.title = to.meta.title;
+});

+ 14 - 12
src/registerServiceWorker.ts

@@ -1,32 +1,34 @@
 /* eslint-disable no-console */
 
-import { register } from 'register-service-worker'
+import { register } from "register-service-worker";
 
-if (process.env.NODE_ENV === 'production') {
+if (process.env.NODE_ENV === "production") {
   register(`${process.env.BASE_URL}service-worker.js`, {
     ready() {
       console.log(
-        'App is being served from cache by a service worker.\n' +
-        'For more details, visit https://goo.gl/AFskqB'
-      )
+        "App is being served from cache by a service worker.\n" +
+          "For more details, visit https://goo.gl/AFskqB"
+      );
     },
     registered() {
-      console.log('Service worker has been registered.')
+      console.log("Service worker has been registered.");
     },
     cached() {
-      console.log('Content has been cached for offline use.')
+      console.log("Content has been cached for offline use.");
     },
     updatefound() {
-      console.log('New content is downloading.')
+      console.log("New content is downloading.");
     },
     updated() {
-      console.log('New content is available; please refresh.')
+      console.log("New content is available; please refresh.");
     },
     offline() {
-      console.log('No internet connection found. App is running in offline mode.')
+      console.log(
+        "No internet connection found. App is running in offline mode."
+      );
     },
     error(error) {
-      console.error('Error during service worker registration:', error)
+      console.error("Error during service worker registration:", error);
     }
-  })
+  });
 }

+ 17 - 11
src/router/index.ts

@@ -177,29 +177,35 @@ export default new Router({
       }
     },
     {
-      path: '/error',
+      path: "/error",
       component: Layout,
-      redirect: 'noredirect',
+      redirect: "noredirect",
       meta: {
-        title: '错误页面',
+        title: "错误页面",
         icon: "nested"
       },
       children: [
         {
-          path: '401',
-          component: () => import(/* webpackChunkName: "error-page-401" */ '@/views/error-page/401.vue'),
-          name: 'Page401',
+          path: "401",
+          component: () =>
+            import(
+              /* webpackChunkName: "error-page-401" */ "@/views/error-page/401.vue"
+            ),
+          name: "Page401",
           meta: {
-            title: '401',
+            title: "401",
             noCache: true
           }
         },
         {
-          path: '404',
-          component: () => import(/* webpackChunkName: "error-page-404" */ '@/views/error-page/404.vue'),
-          name: '404',
+          path: "404",
+          component: () =>
+            import(
+              /* webpackChunkName: "error-page-404" */ "@/views/error-page/404.vue"
+            ),
+          name: "404",
           meta: {
-            title: '404',
+            title: "404",
             noCache: true
           }
         }

+ 3 - 3
src/shims-vue.d.ts

@@ -1,4 +1,4 @@
-declare module '*.vue' {
-  import Vue from 'vue'
-  export default Vue
+declare module "*.vue" {
+  import Vue from "vue";
+  export default Vue;
 }

+ 8 - 8
src/store/index.ts

@@ -1,14 +1,14 @@
-import Vue from 'vue'
-import Vuex from 'vuex'
-import { IAppState } from './modules/app'
-import { IUserState } from './modules/user'
+import Vue from "vue";
+import Vuex from "vuex";
+import { IAppState } from "./modules/app";
+import { IUserState } from "./modules/user";
 
-Vue.use(Vuex)
+Vue.use(Vuex);
 
 export interface IRootState {
-  app: IAppState
-  user: IUserState
+  app: IAppState;
+  user: IUserState;
 }
 
 // Declare empty store first, dynamically register all modules later.
-export default new Vuex.Store<IRootState>({})
+export default new Vuex.Store<IRootState>({});

+ 30 - 24
src/store/modules/app.ts

@@ -1,66 +1,72 @@
-import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
-import { getSidebarStatus, setSidebarStatus } from '@/utils/cookies'
-import store from '@/store'
+import {
+  VuexModule,
+  Module,
+  Mutation,
+  Action,
+  getModule
+} from "vuex-module-decorators";
+import { getSidebarStatus, setSidebarStatus } from "@/utils/cookies";
+import store from "@/store";
 
 export enum DeviceType {
   Mobile,
-  Desktop,
+  Desktop
 }
 
 export interface IAppState {
-  device: DeviceType
+  device: DeviceType;
   sidebar: {
-    opened: boolean
-    withoutAnimation: boolean
-  }
+    opened: boolean;
+    withoutAnimation: boolean;
+  };
 }
 
-@Module({ dynamic: true, store, name: 'app' })
+@Module({ dynamic: true, store, name: "app" })
 class App extends VuexModule implements IAppState {
   public sidebar = {
-    opened: getSidebarStatus() !== 'closed',
+    opened: getSidebarStatus() !== "closed",
     withoutAnimation: false
-  }
+  };
 
-  public device = DeviceType.Desktop
+  public device = DeviceType.Desktop;
 
   @Mutation
   private TOGGLE_SIDEBAR(withoutAnimation: boolean) {
-    this.sidebar.opened = !this.sidebar.opened
-    this.sidebar.withoutAnimation = withoutAnimation
+    this.sidebar.opened = !this.sidebar.opened;
+    this.sidebar.withoutAnimation = withoutAnimation;
     if (this.sidebar.opened) {
-      setSidebarStatus('opened')
+      setSidebarStatus("opened");
     } else {
-      setSidebarStatus('closed')
+      setSidebarStatus("closed");
     }
   }
 
   @Mutation
   private CLOSE_SIDEBAR(withoutAnimation: boolean) {
-    this.sidebar.opened = false
-    this.sidebar.withoutAnimation = withoutAnimation
-    setSidebarStatus('closed')
+    this.sidebar.opened = false;
+    this.sidebar.withoutAnimation = withoutAnimation;
+    setSidebarStatus("closed");
   }
 
   @Mutation
   private TOGGLE_DEVICE(device: DeviceType) {
-    this.device = device
+    this.device = device;
   }
 
   @Action
   public ToggleSideBar(withoutAnimation: boolean) {
-    this.TOGGLE_SIDEBAR(withoutAnimation)
+    this.TOGGLE_SIDEBAR(withoutAnimation);
   }
 
   @Action
   public CloseSideBar(withoutAnimation: boolean) {
-    this.CLOSE_SIDEBAR(withoutAnimation)
+    this.CLOSE_SIDEBAR(withoutAnimation);
   }
 
   @Action
   public ToggleDevice(device: DeviceType) {
-    this.TOGGLE_DEVICE(device)
+    this.TOGGLE_DEVICE(device);
   }
 }
 
-export const AppModule = getModule(App)
+export const AppModule = getModule(App);

+ 54 - 46
src/store/modules/user.ts

@@ -1,95 +1,103 @@
-import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators'
-import { login, logout, getUserInfo } from '@/api/users'
-import { getToken, setToken, removeToken } from '@/utils/cookies'
-import store from '@/store'
+import {
+  VuexModule,
+  Module,
+  Action,
+  Mutation,
+  getModule
+} from "vuex-module-decorators";
+import { login, logout, getUserInfo } from "@/api/users";
+import { getToken, setToken, removeToken } from "@/utils/cookies";
+import store from "@/store";
 
 export interface IUserState {
-  token: string
-  name: string
-  avatar: string
-  introduction: string
-  roles: string[]
+  token: string;
+  name: string;
+  avatar: string;
+  introduction: string;
+  roles: string[];
 }
 
-@Module({ dynamic: true, store, name: 'user' })
+@Module({ dynamic: true, store, name: "user" })
 class User extends VuexModule implements IUserState {
-  public token = getToken() || ''
-  public name = ''
-  public avatar = ''
-  public introduction = ''
-  public roles: string[] = []
+  public token = getToken() || "";
+  public name = "";
+  public avatar = "";
+  public introduction = "";
+  public roles: string[] = [];
 
   @Mutation
   private SET_TOKEN(token: string) {
-    this.token = token
+    this.token = token;
   }
 
   @Mutation
   private SET_NAME(name: string) {
-    this.name = name
+    this.name = name;
   }
 
   @Mutation
   private SET_AVATAR(avatar: string) {
-    this.avatar = avatar
+    this.avatar = avatar;
   }
 
   @Mutation
   private SET_INTRODUCTION(introduction: string) {
-    this.introduction = introduction
+    this.introduction = introduction;
   }
 
   @Mutation
   private SET_ROLES(roles: string[]) {
-    this.roles = roles
+    this.roles = roles;
   }
 
   @Action
-  public async Login(userInfo: { username: string, password: string }) {
-    let { username, password } = userInfo
-    username = username.trim()
-    const { data } = await login({ username, password })
-    setToken(data.accessToken)
-    this.SET_TOKEN(data.accessToken)
+  public async Login(userInfo: { username: string; password: string }) {
+    let { username, password } = userInfo;
+    username = username.trim();
+    const { data } = await login({ username, password });
+    setToken(data.accessToken);
+    this.SET_TOKEN(data.accessToken);
   }
 
   @Action
   public ResetToken() {
-    removeToken()
-    this.SET_TOKEN('')
-    this.SET_ROLES([])
+    removeToken();
+    this.SET_TOKEN("");
+    this.SET_ROLES([]);
   }
 
   @Action
   public async GetUserInfo() {
-    if (this.token === '') {
-      throw Error('GetUserInfo: token is undefined!')
+    if (this.token === "") {
+      throw Error("GetUserInfo: token is undefined!");
     }
-    const { data } = await getUserInfo({ /* Your params here */ })
+    const { data } = await getUserInfo({
+      /* Your params here */
+    });
     if (!data) {
-      throw Error('Verification failed, please Login again.')
+      throw Error("Verification failed, please Login again.");
     }
-    const { roles, name, avatar, introduction } = data.user
+    const { roles, name, avatar, introduction } = data.user;
     // roles must be a non-empty array
     if (!roles || roles.length <= 0) {
-      throw Error('GetUserInfo: roles must be a non-null array!')
+      throw Error("GetUserInfo: roles must be a non-null array!");
     }
-    this.SET_ROLES(roles)
-    this.SET_NAME(name)
-    this.SET_AVATAR(avatar)
-    this.SET_INTRODUCTION(introduction)
+    this.SET_ROLES(roles);
+    this.SET_NAME(name);
+    this.SET_AVATAR(avatar);
+    this.SET_INTRODUCTION(introduction);
   }
 
   @Action
   public async LogOut() {
-    if (this.token === '') {
-      throw Error('LogOut: token is undefined!')
+    if (this.token === "") {
+      throw Error("LogOut: token is undefined!");
     }
-    await logout()
-    removeToken()
-    this.SET_TOKEN('')
-    this.SET_ROLES([])
+    await logout();
+    removeToken();
+    this.SET_TOKEN("");
+    this.SET_ROLES([]);
   }
 }
 
-export const UserModule = getModule(User)
+export const UserModule = getModule(User);

+ 9 - 8
src/utils/cookies.ts

@@ -1,12 +1,13 @@
-import Cookies from 'js-cookie'
+import Cookies from "js-cookie";
 
 // App
-const sidebarStatusKey = 'sidebar_status'
-export const getSidebarStatus = () => Cookies.get(sidebarStatusKey)
-export const setSidebarStatus = (sidebarStatus: string) => Cookies.set(sidebarStatusKey, sidebarStatus)
+const sidebarStatusKey = "sidebar_status";
+export const getSidebarStatus = () => Cookies.get(sidebarStatusKey);
+export const setSidebarStatus = (sidebarStatus: string) =>
+  Cookies.set(sidebarStatusKey, sidebarStatus);
 
 // User
-const tokenKey = 'vue_typescript_admin_access_token'
-export const getToken = () => Cookies.get(tokenKey)
-export const setToken = (token: string) => Cookies.set(tokenKey, token)
-export const removeToken = () => Cookies.remove(tokenKey)
+const tokenKey = "vue_typescript_admin_access_token";
+export const getToken = () => Cookies.get(tokenKey);
+export const setToken = (token: string) => Cookies.set(tokenKey, token);
+export const removeToken = () => Cookies.remove(tokenKey);

+ 28 - 28
src/utils/request.ts

@@ -1,26 +1,26 @@
 // @ts-ignore
-import axios from 'axios'
-import { Message, MessageBox } from 'element-ui'
-import { UserModule } from '@/store/modules/user'
+import axios from "axios";
+import { Message, MessageBox } from "element-ui";
+import { UserModule } from "@/store/modules/user";
 
 const service = axios.create({
-  baseURL: process.env.VUE_APP_BASE_API,// url = base url + request url
+  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
   timeout: 5000
-})
+});
 
 // Request interceptors
 service.interceptors.request.use(
   (config: { headers: { [x: string]: string } }) => {
     // Add X-Access-Token header to every request, you can add other custom headers here
     if (UserModule.token) {
-      config.headers['X-Access-Token'] = UserModule.token
+      config.headers["X-Access-Token"] = UserModule.token;
     }
-    return config
+    return config;
   },
   (error: any) => {
-    Promise.reject(error)
+    Promise.reject(error);
   }
-)
+);
 
 // Response interceptors
 service.interceptors.response.use(
@@ -33,40 +33,40 @@ service.interceptors.response.use(
     // code == 50004: invalid user (user not exist)
     // code == 50005: username or password is incorrect
     // You can change this part for your own usage.
-    const res = response.data
+    const res = response.data;
     if (res.code !== 20000) {
       Message({
-        message: res.message || 'Error',
-        type: 'error',
+        message: res.message || "Error",
+        type: "error",
         duration: 5 * 1000
-      })
+      });
       if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
         MessageBox.confirm(
-          '你已被登出,可以取消继续留在该页面,或者重新登录',
-          '确定登出',
+          "你已被登出,可以取消继续留在该页面,或者重新登录",
+          "确定登出",
           {
-            confirmButtonText: '重新登录',
-            cancelButtonText: '取消',
-            type: 'warning'
+            confirmButtonText: "重新登录",
+            cancelButtonText: "取消",
+            type: "warning"
           }
         ).then(() => {
-          UserModule.ResetToken()
-          location.reload() // To prevent bugs from vue-router
-        })
+          UserModule.ResetToken();
+          location.reload(); // To prevent bugs from vue-router
+        });
       }
-      return Promise.reject(new Error(res.message || 'Error'))
+      return Promise.reject(new Error(res.message || "Error"));
     } else {
-      return response.data
+      return response.data;
     }
   },
   (error: { message: any }) => {
     Message({
       message: error.message,
-      type: 'error',
+      type: "error",
       duration: 5 * 1000
-    })
-    return Promise.reject(error)
+    });
+    return Promise.reject(error);
   }
-)
+);
 
-export default service
+export default service;

+ 4 - 2
src/utils/validate.ts

@@ -1,3 +1,5 @@
-export const isValidUsername = (str: string) => ['admin', 'editor'].indexOf(str.trim()) >= 0
+export const isValidUsername = (str: string) =>
+  ["admin", "editor"].indexOf(str.trim()) >= 0;
 
-export const isExternal = (path: string) => /^(https?:|mailto:|tel:)/.test(path)
+export const isExternal = (path: string) =>
+  /^(https?:|mailto:|tel:)/.test(path);

+ 77 - 105
src/views/error-page/401.vue

@@ -1,131 +1,103 @@
 <template>
-  <div class="errPage-container">
-    <el-button
-      icon="el-icon-arrow-left"
-      class="back-btn"
-      @click="back"
-    >
-      返回
-    </el-button>
-    <el-row>
-      <el-col :span="12">
-        <h1 class="text-jumbo text-ginormous">
-          Oops!
-        </h1>
-        gif来源<a
-          href="https://zh.airbnb.com/"
-          target="_blank"
-        >airbnb</a> 页面
-        <h2>你没有权限去该页面</h2>
-        <h6>如有不满请联系你领导</h6>
-        <ul class="list-unstyled">
-          <li>或者你可以去:</li>
-          <li class="link-type">
-            <router-link to="/project/index">
-              回首页
-            </router-link>
-          </li>
-          <li class="link-type">
-            <a href="#">随便看看</a>
-          </li>
-          <li>
-            <a
-              href="#"
-              @click.prevent="dialogVisible=true"
-            >点我看图</a>
-          </li>
-        </ul>
-      </el-col>
-      <el-col :span="12">
-        <img
-          :src="errGif"
-          class="some-gif"
-          width="313"
-          height="428"
-          alt="Girl has dropped her ice cream."
-        >
-      </el-col>
-    </el-row>
-    <el-dialog
-      :visible.sync="dialogVisible"
-      title="随便看"
-    >
-      <img
-        :src="ewizardClap"
-        class="some-img"
-      >
-    </el-dialog>
-  </div>
+    <div class="errPage-container">
+        <el-button icon="el-icon-arrow-left" class="back-btn" @click="back"> 返回 </el-button>
+        <el-row>
+            <el-col :span="12">
+                <h1 class="text-jumbo text-ginormous">Oops!</h1>
+                gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
+                <h2>你没有权限去该页面</h2>
+                <h6>如有不满请联系你领导</h6>
+                <ul class="list-unstyled">
+                    <li>或者你可以去:</li>
+                    <li class="link-type">
+                        <router-link to="/project/index"> 回首页 </router-link>
+                    </li>
+                    <li class="link-type">
+                        <a href="#">随便看看</a>
+                    </li>
+                    <li>
+                        <a href="#" @click.prevent="dialogVisible = true">点我看图</a>
+                    </li>
+                </ul>
+            </el-col>
+            <el-col :span="12">
+                <img :src="errGif" class="some-gif" width="313" height="428" alt="Girl has dropped her ice cream." />
+            </el-col>
+        </el-row>
+        <el-dialog :visible.sync="dialogVisible" title="随便看">
+            <img :src="ewizardClap" class="some-img" />
+        </el-dialog>
+    </div>
 </template>
 
 <script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import errGif from '@/assets/401-images/401.gif'
+import { Component, Vue } from "vue-property-decorator";
+import errGif from "@/assets/401-images/401.gif";
 
 @Component({
-  name: 'Page401'
+    name: "Page401",
 })
 export default class extends Vue {
-  private errGif = errGif + '?' + +new Date()
-  private ewizardClap = 'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646'
-  private dialogVisible = false
+    private errGif = errGif + "?" + +new Date();
+    private ewizardClap = "https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646";
+    private dialogVisible = false;
 
-  private back() {
-    if (this.$route.query.noGoBack) {
-      this.$router.push({ path: '/dashboard' }).catch(err => {
-        console.warn(err)
-      })
-    } else {
-      this.$router.go(-1)
+    private back() {
+        if (this.$route.query.noGoBack) {
+            this.$router.push({ path: "/dashboard" }).catch((err) => {
+                console.warn(err);
+            });
+        } else {
+            this.$router.go(-1);
+        }
     }
-  }
 }
 </script>
 
 <style lang="scss" scoped>
 .errPage-container {
-  width: 800px;
-  max-width: 100%;
-  margin: 100px auto;
+    width: 800px;
+    max-width: 100%;
+    margin: 100px auto;
 
-  .back-btn {
-    background: #008489;
-    color: #fff;
-    border: none!important;
-  }
+    .back-btn {
+        background: #008489;
+        color: #fff;
+        border: none !important;
+    }
 
-  .some-gif {
-    margin: 0 auto;
-    display: block;
-  }
+    .some-gif {
+        margin: 0 auto;
+        display: block;
+    }
 
-  .some-img {
-    display: block;
-    margin: 0 auto;
-    width: 100%;
-  }
+    .some-img {
+        display: block;
+        margin: 0 auto;
+        width: 100%;
+    }
 
-  .text-jumbo {
-    font-size: 60px;
-    font-weight: 700;
-    color: #484848;
-  }
+    .text-jumbo {
+        font-size: 60px;
+        font-weight: 700;
+        color: #484848;
+    }
 
-  .list-unstyled {
-    font-size: 14px;
+    .list-unstyled {
+        font-size: 14px;
 
-    li {
-      padding-bottom: 5px;
-    }
+        li {
+            padding-bottom: 5px;
+        }
 
-    a {
-      color: #008489;
-      text-decoration: none;
+        a {
+            color: #008489;
+            text-decoration: none;
 
-      &:hover {
-        text-decoration: underline;
-      }
+            &:hover {
+                text-decoration: underline;
+            }
+        }
     }
-  }
 }
 </style>

+ 209 - 234
src/views/error-page/404.vue

@@ -1,283 +1,258 @@
 <template>
-  <div class="wscn-http404-container">
-    <div class="wscn-http404">
-      <div class="pic-404">
-        <img
-          class="pic-404__parent"
-          src="@/assets/404-images/404.png"
-          alt="404"
-        >
-        <img
-          class="pic-404__child left"
-          src="@/assets/404-images/404-cloud.png"
-          alt="404"
-        >
-        <img
-          class="pic-404__child mid"
-          src="@/assets/404-images/404-cloud.png"
-          alt="404"
-        >
-        <img
-          class="pic-404__child right"
-          src="@/assets/404-images/404-cloud.png"
-          alt="404"
-        >
-      </div>
-      <div class="text-404">
-        <div class="text-404__oops">
-          OOPS!
+    <div class="wscn-http404-container">
+        <div class="wscn-http404">
+            <div class="pic-404">
+                <img class="pic-404__parent" src="@/assets/404-images/404.png" alt="404" />
+                <img class="pic-404__child left" src="@/assets/404-images/404-cloud.png" alt="404" />
+                <img class="pic-404__child mid" src="@/assets/404-images/404-cloud.png" alt="404" />
+                <img class="pic-404__child right" src="@/assets/404-images/404-cloud.png" alt="404" />
+            </div>
+            <div class="text-404">
+                <div class="text-404__oops">OOPS!</div>
+                <div class="text-404__info">
+                    All rights reserved
+                    <a style="color: #20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
+                </div>
+                <div class="text-404__headline">
+                    {{ message }}
+                </div>
+                <div class="text-404__info">
+                    Please check that the URL you entered is correct, or click the button below to return to the homepage.
+                </div>
+                <a href="" class="text-404__return-home">Back to home</a>
+            </div>
         </div>
-        <div class="text-404__info">
-          All rights reserved
-          <a
-            style="color:#20a0ff"
-            href="https://wallstreetcn.com"
-            target="_blank"
-          >wallstreetcn</a>
-        </div>
-        <div class="text-404__headline">
-          {{ message }}
-        </div>
-        <div class="text-404__info">
-          Please check that the URL you entered is correct, or click the button below to return to the homepage.
-        </div>
-        <a
-          href=""
-          class="text-404__return-home"
-        >Back to home</a>
-      </div>
     </div>
-  </div>
 </template>
 
 <script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
+import { Component, Vue } from "vue-property-decorator";
 
 @Component({
-  name: 'Page404'
+    name: "Page404",
 })
 export default class extends Vue {
-  private message = '404 Page Not Found'
+    private message = "404 Page Not Found";
 }
 </script>
 
 <style lang="scss" scoped>
 .wscn-http404-container {
-  transform: translate(-50%,-50%);
-  position: absolute;
-  top: 40%;
-  left: 50%;
+    transform: translate(-50%, -50%);
+    position: absolute;
+    top: 40%;
+    left: 50%;
 }
 
 .wscn-http404 {
-  position: relative;
-  width: 1200px;
-  padding: 0 50px;
-  overflow: hidden;
-
-  .pic-404 {
     position: relative;
-    float: left;
-    width: 600px;
+    width: 1200px;
+    padding: 0 50px;
     overflow: hidden;
 
-    &__parent {
-      width: 100%;
-    }
+    .pic-404 {
+        position: relative;
+        float: left;
+        width: 600px;
+        overflow: hidden;
 
-    &__child {
-      position: absolute;
+        &__parent {
+            width: 100%;
+        }
 
-      &.left {
-        width: 80px;
-        top: 17px;
-        left: 220px;
-        opacity: 0;
-        animation-name: cloudLeft;
-        animation-duration: 2s;
-        animation-timing-function: linear;
-        animation-fill-mode: forwards;
-        animation-delay: 1s;
-      }
+        &__child {
+            position: absolute;
 
-      &.mid {
-        width: 46px;
-        top: 10px;
-        left: 420px;
-        opacity: 0;
-        animation-name: cloudMid;
-        animation-duration: 2s;
-        animation-timing-function: linear;
-        animation-fill-mode: forwards;
-        animation-delay: 1.2s;
-      }
+            &.left {
+                width: 80px;
+                top: 17px;
+                left: 220px;
+                opacity: 0;
+                animation-name: cloudLeft;
+                animation-duration: 2s;
+                animation-timing-function: linear;
+                animation-fill-mode: forwards;
+                animation-delay: 1s;
+            }
 
-      &.right {
-        width: 62px;
-        top: 100px;
-        left: 500px;
-        opacity: 0;
-        animation-name: cloudRight;
-        animation-duration: 2s;
-        animation-timing-function: linear;
-        animation-fill-mode: forwards;
-        animation-delay: 1s;
-      }
+            &.mid {
+                width: 46px;
+                top: 10px;
+                left: 420px;
+                opacity: 0;
+                animation-name: cloudMid;
+                animation-duration: 2s;
+                animation-timing-function: linear;
+                animation-fill-mode: forwards;
+                animation-delay: 1.2s;
+            }
 
-      @keyframes cloudLeft {
-        0% {
-          top: 17px;
-          left: 220px;
-          opacity: 0;
-        }
+            &.right {
+                width: 62px;
+                top: 100px;
+                left: 500px;
+                opacity: 0;
+                animation-name: cloudRight;
+                animation-duration: 2s;
+                animation-timing-function: linear;
+                animation-fill-mode: forwards;
+                animation-delay: 1s;
+            }
 
-        20% {
-          top: 33px;
-          left: 188px;
-          opacity: 1;
-        }
+            @keyframes cloudLeft {
+                0% {
+                    top: 17px;
+                    left: 220px;
+                    opacity: 0;
+                }
 
-        80% {
-          top: 81px;
-          left: 92px;
-          opacity: 1;
-        }
+                20% {
+                    top: 33px;
+                    left: 188px;
+                    opacity: 1;
+                }
 
-        100% {
-          top: 97px;
-          left: 60px;
-          opacity: 0;
-        }
-      }
+                80% {
+                    top: 81px;
+                    left: 92px;
+                    opacity: 1;
+                }
 
-      @keyframes cloudMid {
-        0% {
-          top: 10px;
-          left: 420px;
-          opacity: 0;
-        }
+                100% {
+                    top: 97px;
+                    left: 60px;
+                    opacity: 0;
+                }
+            }
 
-        20% {
-          top: 40px;
-          left: 360px;
-          opacity: 1;
-        }
+            @keyframes cloudMid {
+                0% {
+                    top: 10px;
+                    left: 420px;
+                    opacity: 0;
+                }
 
-        70% {
-          top: 130px;
-          left: 180px;
-          opacity: 1;
-        }
+                20% {
+                    top: 40px;
+                    left: 360px;
+                    opacity: 1;
+                }
 
-        100% {
-          top: 160px;
-          left: 120px;
-          opacity: 0;
-        }
-      }
+                70% {
+                    top: 130px;
+                    left: 180px;
+                    opacity: 1;
+                }
 
-      @keyframes cloudRight {
-        0% {
-          top: 100px;
-          left: 500px;
-          opacity: 0;
-        }
+                100% {
+                    top: 160px;
+                    left: 120px;
+                    opacity: 0;
+                }
+            }
 
-        20% {
-          top: 120px;
-          left: 460px;
-          opacity: 1;
-        }
+            @keyframes cloudRight {
+                0% {
+                    top: 100px;
+                    left: 500px;
+                    opacity: 0;
+                }
 
-        80% {
-          top: 180px;
-          left: 340px;
-          opacity: 1;
-        }
+                20% {
+                    top: 120px;
+                    left: 460px;
+                    opacity: 1;
+                }
 
-        100% {
-          top: 200px;
-          left: 300px;
-          opacity: 0;
+                80% {
+                    top: 180px;
+                    left: 340px;
+                    opacity: 1;
+                }
+
+                100% {
+                    top: 200px;
+                    left: 300px;
+                    opacity: 0;
+                }
+            }
         }
-      }
     }
-  }
 
-  .text-404 {
-    position: relative;
-    float: left;
-    width: 300px;
-    padding: 30px 0;
-    overflow: hidden;
+    .text-404 {
+        position: relative;
+        float: left;
+        width: 300px;
+        padding: 30px 0;
+        overflow: hidden;
 
-    &__oops {
-      font-size: 32px;
-      font-weight: bold;
-      line-height: 40px;
-      color: #1482f0;
-      opacity: 0;
-      margin-bottom: 20px;
-      animation-name: slideUp;
-      animation-duration: 0.5s;
-      animation-fill-mode: forwards;
-    }
+        &__oops {
+            font-size: 32px;
+            font-weight: bold;
+            line-height: 40px;
+            color: #1482f0;
+            opacity: 0;
+            margin-bottom: 20px;
+            animation-name: slideUp;
+            animation-duration: 0.5s;
+            animation-fill-mode: forwards;
+        }
 
-    &__headline {
-      font-size: 20px;
-      line-height: 24px;
-      color: #222;
-      font-weight: bold;
-      opacity: 0;
-      margin-bottom: 10px;
-      animation-name: slideUp;
-      animation-duration: 0.5s;
-      animation-delay: 0.1s;
-      animation-fill-mode: forwards;
-    }
+        &__headline {
+            font-size: 20px;
+            line-height: 24px;
+            color: #222;
+            font-weight: bold;
+            opacity: 0;
+            margin-bottom: 10px;
+            animation-name: slideUp;
+            animation-duration: 0.5s;
+            animation-delay: 0.1s;
+            animation-fill-mode: forwards;
+        }
 
-    &__info {
-      font-size: 13px;
-      line-height: 21px;
-      color: grey;
-      opacity: 0;
-      margin-bottom: 30px;
-      animation-name: slideUp;
-      animation-duration: 0.5s;
-      animation-delay: 0.2s;
-      animation-fill-mode: forwards;
-    }
+        &__info {
+            font-size: 13px;
+            line-height: 21px;
+            color: grey;
+            opacity: 0;
+            margin-bottom: 30px;
+            animation-name: slideUp;
+            animation-duration: 0.5s;
+            animation-delay: 0.2s;
+            animation-fill-mode: forwards;
+        }
 
-    &__return-home {
-      display: block;
-      float: left;
-      width: 110px;
-      height: 36px;
-      background: #1482f0;
-      border-radius: 100px;
-      text-align: center;
-      color: #ffffff;
-      opacity: 0;
-      font-size: 14px;
-      line-height: 36px;
-      cursor: pointer;
-      animation-name: slideUp;
-      animation-duration: 0.5s;
-      animation-delay: 0.3s;
-      animation-fill-mode: forwards;
-    }
+        &__return-home {
+            display: block;
+            float: left;
+            width: 110px;
+            height: 36px;
+            background: #1482f0;
+            border-radius: 100px;
+            text-align: center;
+            color: #ffffff;
+            opacity: 0;
+            font-size: 14px;
+            line-height: 36px;
+            cursor: pointer;
+            animation-name: slideUp;
+            animation-duration: 0.5s;
+            animation-delay: 0.3s;
+            animation-fill-mode: forwards;
+        }
 
-    @keyframes slideUp {
-      0% {
-        transform: translateY(60px);
-        opacity: 0;
-      }
+        @keyframes slideUp {
+            0% {
+                transform: translateY(60px);
+                opacity: 0;
+            }
 
-      100% {
-        transform: translateY(0);
-        opacity: 1;
-      }
+            100% {
+                transform: translateY(0);
+                opacity: 1;
+            }
+        }
     }
-  }
 }
 </style>

+ 211 - 231
src/views/login/index.vue

@@ -1,275 +1,255 @@
 <template>
-  <div class="login-container">
-    <el-form
-      ref="loginForm"
-      :model="loginForm"
-      :rules="loginRules"
-      class="login-form"
-      autocomplete="on"
-      label-position="left"
-    >
-      <div class="title-container">
-        <h3 class="title">
-          Login Form
-        </h3>
-      </div>
-
-      <el-form-item prop="username">
-        <span class="svg-container">
-          <svg-icon name="user" />
-        </span>
-        <el-input
-          ref="username"
-          v-model="loginForm.username"
-          name="username"
-          type="text"
-          autocomplete="on"
-          placeholder="username"
-        />
-      </el-form-item>
-
-      <el-form-item prop="password">
-        <span class="svg-container">
-          <svg-icon name="password" />
-        </span>
-        <el-input
-          :key="passwordType"
-          ref="password"
-          v-model="loginForm.password"
-          :type="passwordType"
-          placeholder="password"
-          name="password"
-          autocomplete="on"
-          @keyup.enter.native="handleLogin"
-        />
-        <span
-          class="show-pwd"
-          @click="showPwd"
-        >
-          <svg-icon :name="passwordType === 'password' ? 'eye-off' : 'eye-on'" />
-        </span>
-      </el-form-item>
-
-      <el-button
-        :loading="loading"
-        type="primary"
-        style="width:100%; margin-bottom:30px;"
-        @click.native.prevent="handleLogin"
-      >
-        Sign in
-      </el-button>
-
-      <div style="position:relative">
-        <div class="tips">
-          <span> username: admin </span>
-          <span> password: any </span>
-        </div>
-      </div>
-    </el-form>
-  </div>
+    <div class="login-container">
+        <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left">
+            <div class="title-container">
+                <h3 class="title">Login Form</h3>
+            </div>
+
+            <el-form-item prop="username">
+                <span class="svg-container">
+                    <svg-icon name="user" />
+                </span>
+                <el-input ref="username" v-model="loginForm.username" name="username" type="text" autocomplete="on" placeholder="username" />
+            </el-form-item>
+
+            <el-form-item prop="password">
+                <span class="svg-container">
+                    <svg-icon name="password" />
+                </span>
+                <el-input
+                    :key="passwordType"
+                    ref="password"
+                    v-model="loginForm.password"
+                    :type="passwordType"
+                    placeholder="password"
+                    name="password"
+                    autocomplete="on"
+                    @keyup.enter.native="handleLogin"
+                />
+                <span class="show-pwd" @click="showPwd">
+                    <svg-icon :name="passwordType === 'password' ? 'eye-off' : 'eye-on'" />
+                </span>
+            </el-form-item>
+
+            <el-button :loading="loading" type="primary" style="width: 100%; margin-bottom: 30px" @click.native.prevent="handleLogin">
+                Sign in
+            </el-button>
+
+            <div style="position: relative">
+                <div class="tips">
+                    <span> username: admin </span>
+                    <span> password: any </span>
+                </div>
+            </div>
+        </el-form>
+    </div>
 </template>
 
 <script lang="ts">
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { Route } from 'vue-router'
-import { Dictionary } from 'vue-router/types/router'
-import { Form as ElForm, Input } from 'element-ui'
-import { UserModule } from '@/store/modules/user'
-import { isValidUsername } from '@/utils/validate'
+import { Component, Vue, Watch } from "vue-property-decorator";
+import { Route } from "vue-router";
+import { Dictionary } from "vue-router/types/router";
+import { Form as ElForm, Input } from "element-ui";
+import { UserModule } from "@/store/modules/user";
+import { isValidUsername } from "@/utils/validate";
 
 @Component({
-  name: 'Login'
+    name: "Login",
 })
 export default class extends Vue {
-  private validateUsername = (rule: any, value: string, callback: Function) => {
-    if (!isValidUsername(value)) {
-      callback(new Error('Please enter the correct user name'))
-    } else {
-      callback()
+    private validateUsername = (rule: any, value: string, callback: Function) => {
+        if (!isValidUsername(value)) {
+            callback(new Error("Please enter the correct user name"));
+        } else {
+            callback();
+        }
+    };
+
+    private validatePassword = (rule: any, value: string, callback: Function) => {
+        if (value.length < 6) {
+            callback(new Error("The password can not be less than 6 digits"));
+        } else {
+            callback();
+        }
+    };
+
+    private loginForm = {
+        username: "admin",
+        password: "111111",
+    };
+
+    private loginRules = {
+        username: [{ validator: this.validateUsername, trigger: "blur" }],
+        password: [{ validator: this.validatePassword, trigger: "blur" }],
+    };
+
+    private passwordType = "password";
+    private loading = false;
+    private showDialog = false;
+    private redirect?: string;
+    private otherQuery: Dictionary<string> = {};
+
+    @Watch("$route", { immediate: true })
+    private onRouteChange(route: Route) {
+        // TODO: remove the "as Dictionary<string>" hack after v4 release for vue-router
+        // See https://github.com/vuejs/vue-router/pull/2050 for details
+        const query = route.query as Dictionary<string>;
+        if (query) {
+            this.redirect = query.redirect;
+            this.otherQuery = this.getOtherQuery(query);
+        }
     }
-  }
 
-  private validatePassword = (rule: any, value: string, callback: Function) => {
-    if (value.length < 6) {
-      callback(new Error('The password can not be less than 6 digits'))
-    } else {
-      callback()
+    mounted() {
+        if (this.loginForm.username === "") {
+            (this.$refs.username as Input).focus();
+        } else if (this.loginForm.password === "") {
+            (this.$refs.password as Input).focus();
+        }
     }
-  }
-
-  private loginForm = {
-    username: 'admin',
-    password: '111111'
-  }
 
-  private loginRules = {
-    username: [{ validator: this.validateUsername, trigger: 'blur' }],
-    password: [{ validator: this.validatePassword, trigger: 'blur' }]
-  }
-
-  private passwordType = 'password'
-  private loading = false
-  private showDialog = false
-  private redirect?: string
-  private otherQuery: Dictionary<string> = {}
-
-  @Watch('$route', { immediate: true })
-  private onRouteChange(route: Route) {
-    // TODO: remove the "as Dictionary<string>" hack after v4 release for vue-router
-    // See https://github.com/vuejs/vue-router/pull/2050 for details
-    const query = route.query as Dictionary<string>
-    if (query) {
-      this.redirect = query.redirect
-      this.otherQuery = this.getOtherQuery(query)
+    private showPwd() {
+        if (this.passwordType === "password") {
+            this.passwordType = "";
+        } else {
+            this.passwordType = "password";
+        }
+        this.$nextTick(() => {
+            (this.$refs.password as Input).focus();
+        });
     }
-  }
 
-  mounted() {
-    if (this.loginForm.username === '') {
-      (this.$refs.username as Input).focus()
-    } else if (this.loginForm.password === '') {
-      (this.$refs.password as Input).focus()
+    private handleLogin() {
+        (this.$refs.loginForm as ElForm).validate(async (valid: boolean) => {
+            if (valid) {
+                this.loading = true;
+                await UserModule.Login(this.loginForm);
+                this.$router.push({
+                    path: this.redirect || "/",
+                    query: this.otherQuery,
+                });
+                // Just to simulate the time of the request
+                setTimeout(() => {
+                    this.loading = false;
+                }, 0.5 * 1000);
+            } else {
+                return false;
+            }
+        });
     }
-  }
 
-  private showPwd() {
-    if (this.passwordType === 'password') {
-      this.passwordType = ''
-    } else {
-      this.passwordType = 'password'
+    private getOtherQuery(query: Dictionary<string>) {
+        return Object.keys(query).reduce((acc, cur) => {
+            if (cur !== "redirect") {
+                acc[cur] = query[cur];
+            }
+            return acc;
+        }, {} as Dictionary<string>);
     }
-    this.$nextTick(() => {
-      (this.$refs.password as Input).focus()
-    })
-  }
-
-  private handleLogin() {
-    (this.$refs.loginForm as ElForm).validate(async(valid: boolean) => {
-      if (valid) {
-        this.loading = true
-        await UserModule.Login(this.loginForm)
-        this.$router.push({
-          path: this.redirect || '/',
-          query: this.otherQuery
-        })
-        // Just to simulate the time of the request
-        setTimeout(() => {
-          this.loading = false
-        }, 0.5 * 1000)
-      } else {
-        return false
-      }
-    })
-  }
-
-  private getOtherQuery(query: Dictionary<string>) {
-    return Object.keys(query).reduce((acc, cur) => {
-      if (cur !== 'redirect') {
-        acc[cur] = query[cur]
-      }
-      return acc
-    }, {} as Dictionary<string>)
-  }
 }
 </script>
 
 <style lang="scss">
 // References: https://www.zhangxinxu.com/wordpress/2018/01/css-caret-color-first-line/
 @supports (-webkit-mask: none) and (not (cater-color: $loginCursorColor)) {
-  .login-container .el-input {
-    input { color: $loginCursorColor; }
-    input::first-line { color: $lightGray; }
-  }
+    .login-container .el-input {
+        input {
+            color: $loginCursorColor;
+        }
+        input::first-line {
+            color: $lightGray;
+        }
+    }
 }
 
 .login-container {
-  .el-input {
-    display: inline-block;
-    height: 47px;
-    width: 85%;
-
-    input {
-      height: 47px;
-      background: transparent;
-      border: 0px;
-      border-radius: 0px;
-      padding: 12px 5px 12px 15px;
-      color: $lightGray;
-      caret-color: $loginCursorColor;
-      -webkit-appearance: none;
-
-      &:-webkit-autofill {
-        box-shadow: 0 0 0px 1000px $loginBg inset !important;
-        -webkit-text-fill-color: #fff !important;
-      }
+    .el-input {
+        display: inline-block;
+        height: 47px;
+        width: 85%;
+
+        input {
+            height: 47px;
+            background: transparent;
+            border: 0px;
+            border-radius: 0px;
+            padding: 12px 5px 12px 15px;
+            color: $lightGray;
+            caret-color: $loginCursorColor;
+            -webkit-appearance: none;
+
+            &:-webkit-autofill {
+                box-shadow: 0 0 0px 1000px $loginBg inset !important;
+                -webkit-text-fill-color: #fff !important;
+            }
+        }
     }
-  }
 
-  .el-form-item {
-    border: 1px solid rgba(255, 255, 255, 0.1);
-    background: rgba(0, 0, 0, 0.1);
-    border-radius: 5px;
-    color: #454545;
-  }
+    .el-form-item {
+        border: 1px solid rgba(255, 255, 255, 0.1);
+        background: rgba(0, 0, 0, 0.1);
+        border-radius: 5px;
+        color: #454545;
+    }
 }
 </style>
 
 <style lang="scss" scoped>
 .login-container {
-  height: 100%;
-  width: 100%;
-  overflow: hidden;
-  background-color: $loginBg;
-
-  .login-form {
-    position: relative;
-    width: 520px;
-    max-width: 100%;
-    padding: 160px 35px 0;
-    margin: 0 auto;
+    height: 100%;
+    width: 100%;
     overflow: hidden;
-  }
+    background-color: $loginBg;
+
+    .login-form {
+        position: relative;
+        width: 520px;
+        max-width: 100%;
+        padding: 160px 35px 0;
+        margin: 0 auto;
+        overflow: hidden;
+    }
 
-  .tips {
-    font-size: 14px;
-    color: #fff;
-    margin-bottom: 10px;
+    .tips {
+        font-size: 14px;
+        color: #fff;
+        margin-bottom: 10px;
 
-    span {
-      &:first-of-type {
-        margin-right: 16px;
-      }
+        span {
+            &:first-of-type {
+                margin-right: 16px;
+            }
+        }
     }
-  }
 
-  .svg-container {
-    padding: 6px 5px 6px 15px;
-    color: $darkGray;
-    vertical-align: middle;
-    width: 30px;
-    display: inline-block;
-  }
+    .svg-container {
+        padding: 6px 5px 6px 15px;
+        color: $darkGray;
+        vertical-align: middle;
+        width: 30px;
+        display: inline-block;
+    }
 
-  .title-container {
-    position: relative;
+    .title-container {
+        position: relative;
 
-    .title {
-      font-size: 26px;
-      color: $lightGray;
-      margin: 0px auto 40px auto;
-      text-align: center;
-      font-weight: bold;
+        .title {
+            font-size: 26px;
+            color: $lightGray;
+            margin: 0px auto 40px auto;
+            text-align: center;
+            font-weight: bold;
+        }
     }
-  }
 
-  .show-pwd {
-    position: absolute;
-    right: 10px;
-    top: 7px;
-    font-size: 16px;
-    color: $darkGray;
-    cursor: pointer;
-    user-select: none;
-  }
+    .show-pwd {
+        position: absolute;
+        right: 10px;
+        top: 7px;
+        font-size: 16px;
+        color: $darkGray;
+        cursor: pointer;
+        user-select: none;
+    }
 }
 </style>

+ 72 - 101
src/views/maintain/device/index.vue

@@ -1,114 +1,85 @@
 <template>
-  <div class="app-container">
-    demo 组件引用,接口调用
-    <el-table
-      v-loading="listLoading"
-      :data="list"
-      element-loading-text="Loading"
-      border
-      fit
-      highlight-current-row
-    >
-      <el-table-column
-        align="center"
-        label="ID"
-        width="95"
-      >
-        <template slot-scope="scope">
-          {{ scope.$index }}
-        </template>
-      </el-table-column>
-      <el-table-column label="Title">
-        <template slot-scope="scope">
-          {{ scope.row.title }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="Author"
-        width="180"
-        align="center"
-      >
-        <template slot-scope="scope">
-          <span>{{ scope.row.author }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="Pageviews"
-        width="110"
-        align="center"
-      >
-        <template slot-scope="scope">
-          {{ scope.row.pageviews }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        class-name="status-col"
-        label="Status"
-        width="110"
-        align="center"
-      >
-        <template slot-scope="scope">
-          <el-tag :type="scope.row.status | statusFilter">
-            {{ scope.row.status }}
-          </el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column
-        align="center"
-        prop="created_at"
-        label="Created at"
-        width="250"
-      >
-        <template slot-scope="scope">
-          <i class="el-icon-time" />
-          <span>{{ scope.row.timestamp | parseTime }}</span>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
+    <div class="app-container">
+        demo 组件引用,接口调用
+        <el-table v-loading="listLoading" :data="list" element-loading-text="Loading" border fit highlight-current-row>
+            <el-table-column align="center" label="ID" width="95">
+                <template slot-scope="scope">
+                    {{ scope.$index }}
+                </template>
+            </el-table-column>
+            <el-table-column label="Title">
+                <template slot-scope="scope">
+                    {{ scope.row.title }}
+                </template>
+            </el-table-column>
+            <el-table-column label="Author" width="180" align="center">
+                <template slot-scope="scope">
+                    <span>{{ scope.row.author }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="Pageviews" width="110" align="center">
+                <template slot-scope="scope">
+                    {{ scope.row.pageviews }}
+                </template>
+            </el-table-column>
+            <el-table-column class-name="status-col" label="Status" width="110" align="center">
+                <template slot-scope="scope">
+                    <el-tag :type="scope.row.status | statusFilter">
+                        {{ scope.row.status }}
+                    </el-tag>
+                </template>
+            </el-table-column>
+            <el-table-column align="center" prop="created_at" label="Created at" width="250">
+                <template slot-scope="scope">
+                    <i class="el-icon-time" />
+                    <span>{{ scope.row.timestamp | parseTime }}</span>
+                </template>
+            </el-table-column>
+        </el-table>
+    </div>
 </template>
 
 <script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { getArticles } from '@/api/articles'
-import { IArticleData } from '@/api/types'
+import { Component, Vue } from "vue-property-decorator";
+import { getArticles } from "@/api/articles";
+import { IArticleData } from "@/api/types";
 
 @Component({
-  name: 'Table',
-  filters: {
-    statusFilter: (status: string) => {
-      const statusMap: { [key: string]: string } = {
-        published: 'success',
-        draft: 'gray',
-        deleted: 'danger'
-      }
-      return statusMap[status]
+    name: "Table",
+    filters: {
+        statusFilter: (status: string) => {
+            const statusMap: { [key: string]: string } = {
+                published: "success",
+                draft: "gray",
+                deleted: "danger",
+            };
+            return statusMap[status];
+        },
+        parseTime: (timestamp: string) => {
+            return new Date(timestamp).toISOString();
+        },
     },
-    parseTime: (timestamp: string) => {
-      return new Date(timestamp).toISOString()
-    }
-  }
 })
 export default class extends Vue {
-  private list: IArticleData[] = []
-  private listLoading = true
-  private listQuery = {
-    page: 1,
-    limit: 20
-  }
+    private list: IArticleData[] = [];
+    private listLoading = true;
+    private listQuery = {
+        page: 1,
+        limit: 20,
+    };
 
-  created() {
-    this.getList()
-  }
+    created() {
+        this.getList();
+    }
 
-  private async getList() {
-    this.listLoading = true
-    const { data } = await getArticles(this.listQuery)
-    this.list = data.items
-    // Just to simulate the time of the request
-    setTimeout(() => {
-      this.listLoading = false
-    }, 0.5 * 1000)
-  }
+    private async getList() {
+        this.listLoading = true;
+        const { data } = await getArticles(this.listQuery);
+        this.list = data.items;
+        // Just to simulate the time of the request
+        setTimeout(() => {
+            this.listLoading = false;
+        }, 0.5 * 1000);
+    }
 }
 </script>

+ 2 - 3
src/views/maintain/relationship/index.vue

@@ -1,13 +1,12 @@
 <template>
-<div>关系</div>
+    <div>关系</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/maintain/space/index.vue

@@ -1,13 +1,12 @@
 <template>
-<div>空间</div>
+    <div>空间</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/maintain/system/index.vue

@@ -1,13 +1,12 @@
 <template>
-<div>系统</div>
+    <div>系统</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/manage/build/index.vue

@@ -1,13 +1,12 @@
 <template>
-  <div>建筑</div>
+    <div>建筑</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/manage/model/index.vue

@@ -1,13 +1,12 @@
 <template>
-<div>模型</div>
+    <div>模型</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 17 - 17
src/views/project/index.vue

@@ -1,31 +1,31 @@
 <template>
-  <div>
-    <p>用户信息接口userinfo:</p>
-    <p>name:{{ name }}</p>
-    <p>roles:
-      <span v-for="role in roles" :key="role">{{ role }}</span>
-    </p>
-  </div>
+    <div>
+        <p>用户信息接口userinfo:</p>
+        <p>name:{{ name }}</p>
+        <p>
+            roles:
+            <span v-for="role in roles" :key="role">{{ role }}</span>
+        </p>
+    </div>
 </template>
 
 <script lang="ts">
-import {Component, Vue} from "vue-property-decorator";
-import {UserModule} from "../../store/modules/user";
+import { Component, Vue } from "vue-property-decorator";
+import { UserModule } from "../../store/modules/user";
 
 @Component({
-  name: 'index'
+    name: "index",
 })
 export default class extends Vue {
-  get name() {
-    return UserModule.name
-  }
+    get name() {
+        return UserModule.name;
+    }
 
-  get roles() {
-    return UserModule.roles
-  }
+    get roles() {
+        return UserModule.roles;
+    }
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/scene/plane/index.vue

@@ -1,13 +1,12 @@
 <template>
-<div>平面图</div>
+    <div>平面图</div>
 </template>
 
 <script>
 export default {
-  name: "平面图"
+    name: "平面图"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/scene/system/index.vue

@@ -1,13 +1,12 @@
 <template>
-  <div>系统</div>
+    <div>系统</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>

+ 2 - 3
src/views/scene/tiepoint/index.vue

@@ -1,13 +1,12 @@
 <template>
-<div>绑点</div>
+    <div>绑点</div>
 </template>
 
 <script>
 export default {
-  name: "index"
+    name: "index"
 }
 </script>
 
 <style scoped>
-
 </style>