@melt-js/tpl-vue2-admin-ele 0.0.0-stage → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +68 -3
- package/hel_dist/entry.js +37 -0
- package/hel_dist/favicon.ico +0 -0
- package/hel_dist/hel-meta.json +127 -0
- package/hel_dist/hel_userChunk_1.js +1 -0
- package/hel_dist/index.html +1 -0
- package/hel_dist/static/css/chunk-017edab0.c58e968f.css +1 -0
- package/hel_dist/static/css/chunk-5eaa4e8c.fdc15fc9.css +1 -0
- package/hel_dist/static/css/chunk-67ce6001.3f0a3a92.css +1 -0
- package/hel_dist/static/css/chunk-6d379bf5.f23be7e7.css +1 -0
- package/hel_dist/static/css/chunk-718db1ae.6eddafbb.css +1 -0
- package/hel_dist/static/css/chunk-7ba44fd1.85e72a0e.css +1 -0
- package/hel_dist/static/css/chunk-de514d9e.00a6d6a6.css +1 -0
- package/hel_dist/static/css/chunk-elementUI.5646d24e.css +1 -0
- package/hel_dist/static/fonts/element-icons.535877f5.woff +0 -0
- package/hel_dist/static/fonts/element-icons.732389de.ttf +0 -0
- package/hel_dist/static/img/404.a57b6f31.png +0 -0
- package/hel_dist/static/img/404_cloud.0f4bc32b.png +0 -0
- package/hel_dist/static/img/logo.82b9c7a5.png +0 -0
- package/hel_dist/static/js/app.4c22465f.js +1 -0
- package/hel_dist/static/js/chunk-017edab0.362048d2.js +1 -0
- package/hel_dist/static/js/chunk-2d0c8bf7.70b29a00.js +1 -0
- package/hel_dist/static/js/chunk-2d0cfaef.084b1334.js +1 -0
- package/hel_dist/static/js/chunk-2d0d0f79.d7d27267.js +1 -0
- package/hel_dist/static/js/chunk-2d0e4b0c.3835385f.js +1 -0
- package/hel_dist/static/js/chunk-2d0e4e1f.0c68ea9c.js +1 -0
- package/hel_dist/static/js/chunk-2d0e944c.5d7311c9.js +1 -0
- package/hel_dist/static/js/chunk-2d2104c6.b1e1cf15.js +1 -0
- package/hel_dist/static/js/chunk-2d226cab.f4b20d3f.js +1 -0
- package/hel_dist/static/js/chunk-2d229205.b6def72f.js +1 -0
- package/hel_dist/static/js/chunk-5eaa4e8c.62e343d1.js +1 -0
- package/hel_dist/static/js/chunk-67ce6001.c7dec55f.js +1 -0
- package/hel_dist/static/js/chunk-6d379bf5.3d4baab7.js +1 -0
- package/hel_dist/static/js/chunk-718db1ae.a79def1c.js +1 -0
- package/hel_dist/static/js/chunk-7ba44fd1.b80386b8.js +33 -0
- package/hel_dist/static/js/chunk-de514d9e.96bc330f.js +1 -0
- package/hel_dist/static/js/chunk-elementUI.f4fd50f4.js +9 -0
- package/hel_dist/static/js/chunk-libs.8a568f76.js +17 -0
- package/hel_proxy/entry.js +37 -0
- package/hel_proxy_es/entry.js +28 -0
- package/package.json +95 -4
- package/scripts/check.js +13 -0
- package/scripts/meta.js +19 -0
- package/scripts/prepublishOnly.js +26 -0
- package/src/App.vue +11 -0
- package/src/api/table.js +9 -0
- package/src/api/user.js +24 -0
- package/src/assets/404_images/404.png +0 -0
- package/src/assets/404_images/404_cloud.png +0 -0
- package/src/components/Breadcrumb/index.vue +78 -0
- package/src/components/Hamburger/index.vue +44 -0
- package/src/components/SvgIcon/index.vue +62 -0
- package/src/components/index.js +2 -0
- package/src/configs/subApp.js +9 -0
- package/src/entrance/libProperties.js +10 -0
- package/src/entrance/libTypes.ts +24 -0
- package/src/icons/index.js +9 -0
- package/src/icons/svg/dashboard.svg +1 -0
- package/src/icons/svg/example.svg +1 -0
- package/src/icons/svg/eye-open.svg +1 -0
- package/src/icons/svg/eye.svg +1 -0
- package/src/icons/svg/form.svg +1 -0
- package/src/icons/svg/link.svg +1 -0
- package/src/icons/svg/nested.svg +1 -0
- package/src/icons/svg/password.svg +1 -0
- package/src/icons/svg/table.svg +1 -0
- package/src/icons/svg/tree.svg +1 -0
- package/src/icons/svg/user.svg +1 -0
- package/src/icons/svgo.config.js +9 -0
- package/src/layout/components/AppMain.vue +40 -0
- package/src/layout/components/Navbar.vue +139 -0
- package/src/layout/components/Sidebar/FixiOSBug.js +26 -0
- package/src/layout/components/Sidebar/Item.vue +41 -0
- package/src/layout/components/Sidebar/Link.vue +43 -0
- package/src/layout/components/Sidebar/Logo.vue +82 -0
- package/src/layout/components/Sidebar/SidebarItem.vue +95 -0
- package/src/layout/components/Sidebar/index.vue +56 -0
- package/src/layout/components/index.js +3 -0
- package/src/layout/index.vue +93 -0
- package/src/layout/mixin/ResizeHandler.js +45 -0
- package/src/loadApp.js +43 -0
- package/src/main.js +13 -0
- package/src/permission.js +64 -0
- package/src/router/index.js +181 -0
- package/src/settings.js +16 -0
- package/src/store/getters.js +8 -0
- package/src/store/index.js +19 -0
- package/src/store/modules/app.js +48 -0
- package/src/store/modules/settings.js +32 -0
- package/src/store/modules/user.js +97 -0
- package/src/styles/element-ui.scss +49 -0
- package/src/styles/index.scss +65 -0
- package/src/styles/mixin.scss +28 -0
- package/src/styles/sidebar.scss +226 -0
- package/src/styles/transition.scss +48 -0
- package/src/styles/variables.scss +25 -0
- package/src/utils/auth.js +15 -0
- package/src/utils/get-page-title.js +10 -0
- package/src/utils/index.js +117 -0
- package/src/utils/request.js +85 -0
- package/src/utils/validate.js +20 -0
- package/src/views/404.vue +228 -0
- package/src/views/dashboard/index.vue +37 -0
- package/src/views/form/index.vue +85 -0
- package/src/views/login/index.vue +237 -0
- package/src/views/nested/menu1/index.vue +7 -0
- package/src/views/nested/menu1/menu1-1/index.vue +7 -0
- package/src/views/nested/menu1/menu1-2/index.vue +7 -0
- package/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue +5 -0
- package/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue +5 -0
- package/src/views/nested/menu1/menu1-3/index.vue +5 -0
- package/src/views/nested/menu2/index.vue +5 -0
- package/src/views/table/index.vue +79 -0
- package/src/views/tree/index.vue +78 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="!item.hidden">
|
|
3
|
+
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
|
|
4
|
+
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
|
|
5
|
+
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
|
6
|
+
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
|
|
7
|
+
</el-menu-item>
|
|
8
|
+
</app-link>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
|
|
12
|
+
<template slot="title">
|
|
13
|
+
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
|
|
14
|
+
</template>
|
|
15
|
+
<sidebar-item
|
|
16
|
+
v-for="child in item.children"
|
|
17
|
+
:key="child.path"
|
|
18
|
+
:is-nest="true"
|
|
19
|
+
:item="child"
|
|
20
|
+
:base-path="resolvePath(child.path)"
|
|
21
|
+
class="nest-menu"
|
|
22
|
+
/>
|
|
23
|
+
</el-submenu>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
import path from 'path'
|
|
29
|
+
import { isExternal } from '@/utils/validate'
|
|
30
|
+
import Item from './Item'
|
|
31
|
+
import AppLink from './Link'
|
|
32
|
+
import FixiOSBug from './FixiOSBug'
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
name: 'SidebarItem',
|
|
36
|
+
components: { Item, AppLink },
|
|
37
|
+
mixins: [FixiOSBug],
|
|
38
|
+
props: {
|
|
39
|
+
// route object
|
|
40
|
+
item: {
|
|
41
|
+
type: Object,
|
|
42
|
+
required: true
|
|
43
|
+
},
|
|
44
|
+
isNest: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false
|
|
47
|
+
},
|
|
48
|
+
basePath: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: ''
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
data() {
|
|
54
|
+
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
|
|
55
|
+
// TODO: refactor with render function
|
|
56
|
+
this.onlyOneChild = null
|
|
57
|
+
return {}
|
|
58
|
+
},
|
|
59
|
+
methods: {
|
|
60
|
+
hasOneShowingChild(children = [], parent) {
|
|
61
|
+
const showingChildren = children.filter(item => {
|
|
62
|
+
if (item.hidden) {
|
|
63
|
+
return false
|
|
64
|
+
} else {
|
|
65
|
+
// Temp set(will be used if only has one showing child)
|
|
66
|
+
this.onlyOneChild = item
|
|
67
|
+
return true
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// When there is only one child router, the child router is displayed by default
|
|
72
|
+
if (showingChildren.length === 1) {
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Show parent if there are no child router to display
|
|
77
|
+
if (showingChildren.length === 0) {
|
|
78
|
+
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return false
|
|
83
|
+
},
|
|
84
|
+
resolvePath(routePath) {
|
|
85
|
+
if (isExternal(routePath)) {
|
|
86
|
+
return routePath
|
|
87
|
+
}
|
|
88
|
+
if (isExternal(this.basePath)) {
|
|
89
|
+
return this.basePath
|
|
90
|
+
}
|
|
91
|
+
return path.resolve(this.basePath, routePath)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="{'has-logo':showLogo}">
|
|
3
|
+
<logo v-if="showLogo" :collapse="isCollapse" />
|
|
4
|
+
<el-scrollbar wrap-class="scrollbar-wrapper">
|
|
5
|
+
<el-menu
|
|
6
|
+
:default-active="activeMenu"
|
|
7
|
+
:collapse="isCollapse"
|
|
8
|
+
:background-color="variables.menuBg"
|
|
9
|
+
:text-color="variables.menuText"
|
|
10
|
+
:unique-opened="false"
|
|
11
|
+
:active-text-color="variables.menuActiveText"
|
|
12
|
+
:collapse-transition="false"
|
|
13
|
+
mode="vertical"
|
|
14
|
+
>
|
|
15
|
+
<sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" />
|
|
16
|
+
</el-menu>
|
|
17
|
+
</el-scrollbar>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script>
|
|
22
|
+
import { mapGetters } from 'vuex'
|
|
23
|
+
import Logo from './Logo'
|
|
24
|
+
import SidebarItem from './SidebarItem'
|
|
25
|
+
import variables from '@/styles/variables.scss'
|
|
26
|
+
|
|
27
|
+
export default {
|
|
28
|
+
components: { SidebarItem, Logo },
|
|
29
|
+
computed: {
|
|
30
|
+
...mapGetters([
|
|
31
|
+
'sidebar'
|
|
32
|
+
]),
|
|
33
|
+
routes() {
|
|
34
|
+
return this.$router.options.routes
|
|
35
|
+
},
|
|
36
|
+
activeMenu() {
|
|
37
|
+
const route = this.$route
|
|
38
|
+
const { meta, path } = route
|
|
39
|
+
// if set path, the sidebar will highlight the path you set
|
|
40
|
+
if (meta.activeMenu) {
|
|
41
|
+
return meta.activeMenu
|
|
42
|
+
}
|
|
43
|
+
return path
|
|
44
|
+
},
|
|
45
|
+
showLogo() {
|
|
46
|
+
return this.$store.state.settings.sidebarLogo
|
|
47
|
+
},
|
|
48
|
+
variables() {
|
|
49
|
+
return variables
|
|
50
|
+
},
|
|
51
|
+
isCollapse() {
|
|
52
|
+
return !this.sidebar.opened
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="classObj" class="app-wrapper">
|
|
3
|
+
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
|
|
4
|
+
<sidebar class="sidebar-container" />
|
|
5
|
+
<div class="main-container">
|
|
6
|
+
<div :class="{'fixed-header':fixedHeader}">
|
|
7
|
+
<navbar />
|
|
8
|
+
</div>
|
|
9
|
+
<app-main />
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import { Navbar, Sidebar, AppMain } from './components'
|
|
16
|
+
import ResizeMixin from './mixin/ResizeHandler'
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
name: 'Layout',
|
|
20
|
+
components: {
|
|
21
|
+
Navbar,
|
|
22
|
+
Sidebar,
|
|
23
|
+
AppMain
|
|
24
|
+
},
|
|
25
|
+
mixins: [ResizeMixin],
|
|
26
|
+
computed: {
|
|
27
|
+
sidebar() {
|
|
28
|
+
return this.$store.state.app.sidebar
|
|
29
|
+
},
|
|
30
|
+
device() {
|
|
31
|
+
return this.$store.state.app.device
|
|
32
|
+
},
|
|
33
|
+
fixedHeader() {
|
|
34
|
+
return this.$store.state.settings.fixedHeader
|
|
35
|
+
},
|
|
36
|
+
classObj() {
|
|
37
|
+
return {
|
|
38
|
+
hideSidebar: !this.sidebar.opened,
|
|
39
|
+
openSidebar: this.sidebar.opened,
|
|
40
|
+
withoutAnimation: this.sidebar.withoutAnimation,
|
|
41
|
+
mobile: this.device === 'mobile'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
methods: {
|
|
46
|
+
handleClickOutside() {
|
|
47
|
+
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<style lang="scss" scoped>
|
|
54
|
+
@import "~@/styles/mixin.scss";
|
|
55
|
+
@import "~@/styles/variables.scss";
|
|
56
|
+
|
|
57
|
+
.app-wrapper {
|
|
58
|
+
@include clearfix;
|
|
59
|
+
position: relative;
|
|
60
|
+
height: 100%;
|
|
61
|
+
width: 100%;
|
|
62
|
+
&.mobile.openSidebar{
|
|
63
|
+
position: fixed;
|
|
64
|
+
top: 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
.drawer-bg {
|
|
68
|
+
background: #000;
|
|
69
|
+
opacity: 0.3;
|
|
70
|
+
width: 100%;
|
|
71
|
+
top: 0;
|
|
72
|
+
height: 100%;
|
|
73
|
+
position: absolute;
|
|
74
|
+
z-index: 999;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.fixed-header {
|
|
78
|
+
position: fixed;
|
|
79
|
+
top: 0;
|
|
80
|
+
right: 0;
|
|
81
|
+
z-index: 9;
|
|
82
|
+
width: calc(100% - #{$sideBarWidth});
|
|
83
|
+
transition: width 0.28s;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.hideSidebar .fixed-header {
|
|
87
|
+
width: calc(100% - 54px)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.mobile .fixed-header {
|
|
91
|
+
width: 100%;
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import store from '@/store'
|
|
2
|
+
|
|
3
|
+
const { body } = document
|
|
4
|
+
const WIDTH = 992 // refer to Bootstrap's responsive design
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
watch: {
|
|
8
|
+
$route(route) {
|
|
9
|
+
if (this.device === 'mobile' && this.sidebar.opened) {
|
|
10
|
+
store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
beforeMount() {
|
|
15
|
+
window.addEventListener('resize', this.$_resizeHandler)
|
|
16
|
+
},
|
|
17
|
+
beforeDestroy() {
|
|
18
|
+
window.removeEventListener('resize', this.$_resizeHandler)
|
|
19
|
+
},
|
|
20
|
+
mounted() {
|
|
21
|
+
const isMobile = this.$_isMobile()
|
|
22
|
+
if (isMobile) {
|
|
23
|
+
store.dispatch('app/toggleDevice', 'mobile')
|
|
24
|
+
store.dispatch('app/closeSideBar', { withoutAnimation: true })
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
methods: {
|
|
28
|
+
// use $_ for mixins properties
|
|
29
|
+
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
|
30
|
+
$_isMobile() {
|
|
31
|
+
const rect = body.getBoundingClientRect()
|
|
32
|
+
return rect.width - 1 < WIDTH
|
|
33
|
+
},
|
|
34
|
+
$_resizeHandler() {
|
|
35
|
+
if (!document.hidden) {
|
|
36
|
+
const isMobile = this.$_isMobile()
|
|
37
|
+
store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
|
|
38
|
+
|
|
39
|
+
if (isMobile) {
|
|
40
|
+
store.dispatch('app/closeSideBar', { withoutAnimation: true })
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/loadApp.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
|
|
3
|
+
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
|
4
|
+
|
|
5
|
+
import ElementUI from 'element-ui'
|
|
6
|
+
import 'element-ui/lib/theme-chalk/index.css'
|
|
7
|
+
import locale from 'element-ui/lib/locale/lang/en' // lang i18n
|
|
8
|
+
|
|
9
|
+
import '@/styles/index.scss' // global css
|
|
10
|
+
|
|
11
|
+
import App from './App'
|
|
12
|
+
import store from './store'
|
|
13
|
+
import router from './router'
|
|
14
|
+
|
|
15
|
+
import '@/icons' // icon
|
|
16
|
+
import '@/permission' // permission control
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* If you don't want to use mock-server
|
|
20
|
+
* you want to use MockJs for mock api
|
|
21
|
+
* you can execute: mockXHR()
|
|
22
|
+
*
|
|
23
|
+
* Currently MockJs will be used in the production environment,
|
|
24
|
+
* please remove it before going online ! ! !
|
|
25
|
+
*/
|
|
26
|
+
if (process.env.NODE_ENV === 'production') {
|
|
27
|
+
const { mockXHR } = require('../mock')
|
|
28
|
+
mockXHR()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// set ElementUI lang to EN
|
|
32
|
+
Vue.use(ElementUI, { locale })
|
|
33
|
+
// 如果想要中文版 element-ui,按如下方式声明
|
|
34
|
+
// Vue.use(ElementUI)
|
|
35
|
+
|
|
36
|
+
Vue.config.productionTip = false
|
|
37
|
+
|
|
38
|
+
new Vue({
|
|
39
|
+
el: '#app',
|
|
40
|
+
router,
|
|
41
|
+
store,
|
|
42
|
+
render: h => h(App)
|
|
43
|
+
})
|
package/src/main.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LIB_NAME } from './configs/subApp'
|
|
2
|
+
import { libReady, isMasterApp } from 'hel-lib-proxy'
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
if (isMasterApp()) {
|
|
6
|
+
await import('./loadApp')
|
|
7
|
+
} else {
|
|
8
|
+
const libProperties = await import('./entrance/libProperties')
|
|
9
|
+
libReady(LIB_NAME, libProperties.default)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
main().catch(console.error)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import router from './router'
|
|
2
|
+
import store from './store'
|
|
3
|
+
import { Message } from 'element-ui'
|
|
4
|
+
import NProgress from 'nprogress' // progress bar
|
|
5
|
+
import 'nprogress/nprogress.css' // progress bar style
|
|
6
|
+
import { getToken } from '@/utils/auth' // get token from cookie
|
|
7
|
+
import getPageTitle from '@/utils/get-page-title'
|
|
8
|
+
|
|
9
|
+
NProgress.configure({ showSpinner: false }) // NProgress Configuration
|
|
10
|
+
|
|
11
|
+
const whiteList = ['/login'] // no redirect whitelist
|
|
12
|
+
|
|
13
|
+
router.beforeEach(async(to, from, next) => {
|
|
14
|
+
// start progress bar
|
|
15
|
+
NProgress.start()
|
|
16
|
+
|
|
17
|
+
// set page title
|
|
18
|
+
document.title = getPageTitle(to.meta.title)
|
|
19
|
+
|
|
20
|
+
// determine whether the user has logged in
|
|
21
|
+
const hasToken = getToken()
|
|
22
|
+
|
|
23
|
+
if (hasToken) {
|
|
24
|
+
if (to.path === '/login') {
|
|
25
|
+
// if is logged in, redirect to the home page
|
|
26
|
+
next({ path: '/' })
|
|
27
|
+
NProgress.done()
|
|
28
|
+
} else {
|
|
29
|
+
const hasGetUserInfo = store.getters.name
|
|
30
|
+
if (hasGetUserInfo) {
|
|
31
|
+
next()
|
|
32
|
+
} else {
|
|
33
|
+
try {
|
|
34
|
+
// get user info
|
|
35
|
+
await store.dispatch('user/getInfo')
|
|
36
|
+
|
|
37
|
+
next()
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// remove token and go to login page to re-login
|
|
40
|
+
await store.dispatch('user/resetToken')
|
|
41
|
+
Message.error(error || 'Has Error')
|
|
42
|
+
next(`/login?redirect=${to.path}`)
|
|
43
|
+
NProgress.done()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
/* has no token*/
|
|
49
|
+
|
|
50
|
+
if (whiteList.indexOf(to.path) !== -1) {
|
|
51
|
+
// in the free login whitelist, go directly
|
|
52
|
+
next()
|
|
53
|
+
} else {
|
|
54
|
+
// other pages that do not have permission to access are redirected to the login page.
|
|
55
|
+
next(`/login?redirect=${to.path}`)
|
|
56
|
+
NProgress.done()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
router.afterEach(() => {
|
|
62
|
+
// finish progress bar
|
|
63
|
+
NProgress.done()
|
|
64
|
+
})
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import Router from 'vue-router'
|
|
3
|
+
|
|
4
|
+
Vue.use(Router)
|
|
5
|
+
|
|
6
|
+
/* Layout */
|
|
7
|
+
import Layout from '@/layout'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Note: sub-menu only appear when route children.length >= 1
|
|
11
|
+
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
|
|
12
|
+
*
|
|
13
|
+
* hidden: true if set true, item will not show in the sidebar(default is false)
|
|
14
|
+
* alwaysShow: true if set true, will always show the root menu
|
|
15
|
+
* if not set alwaysShow, when item has more than one children route,
|
|
16
|
+
* it will becomes nested mode, otherwise not show the root menu
|
|
17
|
+
* redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
|
|
18
|
+
* name:'router-name' the name is used by <keep-alive> (must set!!!)
|
|
19
|
+
* meta : {
|
|
20
|
+
roles: ['admin','editor'] control the page roles (you can set multiple roles)
|
|
21
|
+
title: 'title' the name show in sidebar and breadcrumb (recommend set)
|
|
22
|
+
icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
|
|
23
|
+
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
|
|
24
|
+
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
|
|
25
|
+
}
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* constantRoutes
|
|
30
|
+
* a base page that does not have permission requirements
|
|
31
|
+
* all roles can be accessed
|
|
32
|
+
*/
|
|
33
|
+
export const constantRoutes = [
|
|
34
|
+
{
|
|
35
|
+
path: '/login',
|
|
36
|
+
component: () => import('@/views/login/index'),
|
|
37
|
+
hidden: true
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
path: '/404',
|
|
42
|
+
component: () => import('@/views/404'),
|
|
43
|
+
hidden: true
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
{
|
|
47
|
+
path: '/',
|
|
48
|
+
component: Layout,
|
|
49
|
+
redirect: '/dashboard',
|
|
50
|
+
children: [{
|
|
51
|
+
path: 'dashboard',
|
|
52
|
+
name: 'Dashboard',
|
|
53
|
+
component: () => import('@/views/dashboard/index'),
|
|
54
|
+
meta: { title: 'Dashboard', icon: 'dashboard' }
|
|
55
|
+
}]
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
path: '/example',
|
|
60
|
+
component: Layout,
|
|
61
|
+
redirect: '/example/table',
|
|
62
|
+
name: 'Example',
|
|
63
|
+
meta: { title: 'Example', icon: 'el-icon-s-help' },
|
|
64
|
+
children: [
|
|
65
|
+
{
|
|
66
|
+
path: 'table',
|
|
67
|
+
name: 'Table',
|
|
68
|
+
component: () => import('@/views/table/index'),
|
|
69
|
+
meta: { title: 'Table', icon: 'table' }
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
path: 'tree',
|
|
73
|
+
name: 'Tree',
|
|
74
|
+
component: () => import('@/views/tree/index'),
|
|
75
|
+
meta: { title: 'Tree', icon: 'tree' }
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
{
|
|
81
|
+
path: '/form',
|
|
82
|
+
component: Layout,
|
|
83
|
+
children: [
|
|
84
|
+
{
|
|
85
|
+
path: 'index',
|
|
86
|
+
name: 'Form',
|
|
87
|
+
component: () => import('@/views/form/index'),
|
|
88
|
+
meta: { title: 'Form', icon: 'form' }
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
path: '/nested',
|
|
95
|
+
component: Layout,
|
|
96
|
+
redirect: '/nested/menu1',
|
|
97
|
+
name: 'Nested',
|
|
98
|
+
meta: {
|
|
99
|
+
title: 'Nested',
|
|
100
|
+
icon: 'nested'
|
|
101
|
+
},
|
|
102
|
+
children: [
|
|
103
|
+
{
|
|
104
|
+
path: 'menu1',
|
|
105
|
+
component: () => import('@/views/nested/menu1/index'), // Parent router-view
|
|
106
|
+
name: 'Menu1',
|
|
107
|
+
meta: { title: 'Menu1' },
|
|
108
|
+
children: [
|
|
109
|
+
{
|
|
110
|
+
path: 'menu1-1',
|
|
111
|
+
component: () => import('@/views/nested/menu1/menu1-1'),
|
|
112
|
+
name: 'Menu1-1',
|
|
113
|
+
meta: { title: 'Menu1-1' }
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
path: 'menu1-2',
|
|
117
|
+
component: () => import('@/views/nested/menu1/menu1-2'),
|
|
118
|
+
name: 'Menu1-2',
|
|
119
|
+
meta: { title: 'Menu1-2' },
|
|
120
|
+
children: [
|
|
121
|
+
{
|
|
122
|
+
path: 'menu1-2-1',
|
|
123
|
+
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
|
|
124
|
+
name: 'Menu1-2-1',
|
|
125
|
+
meta: { title: 'Menu1-2-1' }
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
path: 'menu1-2-2',
|
|
129
|
+
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
|
|
130
|
+
name: 'Menu1-2-2',
|
|
131
|
+
meta: { title: 'Menu1-2-2' }
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
path: 'menu1-3',
|
|
137
|
+
component: () => import('@/views/nested/menu1/menu1-3'),
|
|
138
|
+
name: 'Menu1-3',
|
|
139
|
+
meta: { title: 'Menu1-3' }
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
path: 'menu2',
|
|
145
|
+
component: () => import('@/views/nested/menu2/index'),
|
|
146
|
+
name: 'Menu2',
|
|
147
|
+
meta: { title: 'menu2' }
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
{
|
|
153
|
+
path: 'external-link',
|
|
154
|
+
component: Layout,
|
|
155
|
+
children: [
|
|
156
|
+
{
|
|
157
|
+
path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
|
|
158
|
+
meta: { title: 'External Link', icon: 'link' }
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
// 404 page must be placed at the end !!!
|
|
164
|
+
{ path: '*', redirect: '/404', hidden: true }
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
const createRouter = () => new Router({
|
|
168
|
+
// mode: 'history', // require service support
|
|
169
|
+
scrollBehavior: () => ({ y: 0 }),
|
|
170
|
+
routes: constantRoutes
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const router = createRouter()
|
|
174
|
+
|
|
175
|
+
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
|
|
176
|
+
export function resetRouter() {
|
|
177
|
+
const newRouter = createRouter()
|
|
178
|
+
router.matcher = newRouter.matcher // reset router
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export default router
|
package/src/settings.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
|
|
3
|
+
title: 'Vue Admin Template',
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @type {boolean} true | false
|
|
7
|
+
* @description Whether fix the header
|
|
8
|
+
*/
|
|
9
|
+
fixedHeader: false,
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @type {boolean} true | false
|
|
13
|
+
* @description Whether show the logo in sidebar
|
|
14
|
+
*/
|
|
15
|
+
sidebarLogo: false
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import Vuex from 'vuex'
|
|
3
|
+
import getters from './getters'
|
|
4
|
+
import app from './modules/app'
|
|
5
|
+
import settings from './modules/settings'
|
|
6
|
+
import user from './modules/user'
|
|
7
|
+
|
|
8
|
+
Vue.use(Vuex)
|
|
9
|
+
|
|
10
|
+
const store = new Vuex.Store({
|
|
11
|
+
modules: {
|
|
12
|
+
app,
|
|
13
|
+
settings,
|
|
14
|
+
user
|
|
15
|
+
},
|
|
16
|
+
getters
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export default store
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import Cookies from 'js-cookie'
|
|
2
|
+
|
|
3
|
+
const state = {
|
|
4
|
+
sidebar: {
|
|
5
|
+
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
|
|
6
|
+
withoutAnimation: false
|
|
7
|
+
},
|
|
8
|
+
device: 'desktop'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const mutations = {
|
|
12
|
+
TOGGLE_SIDEBAR: state => {
|
|
13
|
+
state.sidebar.opened = !state.sidebar.opened
|
|
14
|
+
state.sidebar.withoutAnimation = false
|
|
15
|
+
if (state.sidebar.opened) {
|
|
16
|
+
Cookies.set('sidebarStatus', 1)
|
|
17
|
+
} else {
|
|
18
|
+
Cookies.set('sidebarStatus', 0)
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
|
22
|
+
Cookies.set('sidebarStatus', 0)
|
|
23
|
+
state.sidebar.opened = false
|
|
24
|
+
state.sidebar.withoutAnimation = withoutAnimation
|
|
25
|
+
},
|
|
26
|
+
TOGGLE_DEVICE: (state, device) => {
|
|
27
|
+
state.device = device
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const actions = {
|
|
32
|
+
toggleSideBar({ commit }) {
|
|
33
|
+
commit('TOGGLE_SIDEBAR')
|
|
34
|
+
},
|
|
35
|
+
closeSideBar({ commit }, { withoutAnimation }) {
|
|
36
|
+
commit('CLOSE_SIDEBAR', withoutAnimation)
|
|
37
|
+
},
|
|
38
|
+
toggleDevice({ commit }, device) {
|
|
39
|
+
commit('TOGGLE_DEVICE', device)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default {
|
|
44
|
+
namespaced: true,
|
|
45
|
+
state,
|
|
46
|
+
mutations,
|
|
47
|
+
actions
|
|
48
|
+
}
|