Commit 6a735f15a7a105a4176fbece3cac0036c65438ae
Exists in
master
Merge branch 'master' into 'master'
Master See merge request !3
Showing
29 changed files
Show diff stats
.eslintrc.js
babel.config.js
1 | +// module.exports = { | |
2 | +// presets: [ | |
3 | +// '@vue/app' | |
4 | +// ] | |
5 | +// } | |
6 | + // "@babel/preset-env", | |
7 | + // { | |
8 | + // "modules": false | |
9 | + // }, | |
1 | 10 | module.exports = { |
2 | - presets: [ | |
3 | - '@vue/app' | |
11 | + "presets": [ | |
12 | + [ | |
13 | + '@vue/app', | |
14 | + // '@babel/preset-env', | |
15 | + { | |
16 | + // "modules": false, | |
17 | + // "targets": { // 配置代码的运行环境 | |
18 | + // "chrome": 64 | |
19 | + // }, | |
20 | + // "useBuiltIns": true // 开启对 babel-polyfill 的优化 | |
21 | + } | |
22 | + ] | |
23 | + ], | |
24 | + "plugins": [ | |
25 | + [ | |
26 | + "component", | |
27 | + { | |
28 | + "libraryName": "element-ui", | |
29 | + "styleLibraryName": "theme-chalk" | |
30 | + } | |
31 | + ] | |
4 | 32 | ] |
5 | 33 | } | ... | ... |
mock/index.js
1 | 1 | import Mock from 'mockjs' |
2 | -import { param2Obj } from '../src/utils' | |
2 | +import { | |
3 | + param2Obj | |
4 | +} from '../src/utils' | |
3 | 5 | |
4 | 6 | import user from './user' |
5 | 7 | import table from './table' |
... | ... | @@ -16,7 +18,7 @@ export function mockXHR() { |
16 | 18 | // mock patch |
17 | 19 | // https://github.com/nuysoft/Mock/issues/300 |
18 | 20 | Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send |
19 | - Mock.XHR.prototype.send = function() { | |
21 | + Mock.XHR.prototype.send = function () { | |
20 | 22 | if (this.custom.xhr) { |
21 | 23 | this.custom.xhr.withCredentials = this.withCredentials || false |
22 | 24 | |
... | ... | @@ -28,10 +30,14 @@ export function mockXHR() { |
28 | 30 | } |
29 | 31 | |
30 | 32 | function XHR2ExpressReqWrap(respond) { |
31 | - return function(options) { | |
33 | + return function (options) { | |
32 | 34 | let result = null |
33 | 35 | if (respond instanceof Function) { |
34 | - const { body, type, url } = options | |
36 | + const { | |
37 | + body, | |
38 | + type, | |
39 | + url | |
40 | + } = options | |
35 | 41 | // https://expressjs.com/en/4x/api.html#req |
36 | 42 | result = respond({ |
37 | 43 | method: type, | ... | ... |
mock/table.js
... | ... | @@ -3,11 +3,13 @@ import Mock from 'mockjs' |
3 | 3 | const data = Mock.mock({ |
4 | 4 | 'items|10': [{ |
5 | 5 | id: '@id', |
6 | - title: '@sentence(3, 10)', | |
6 | + title: '@sentence(10, 10)', | |
7 | 7 | 'status|1': ['published', 'draft', 'deleted'], |
8 | - author: 'name@integer(300, 5000)', | |
9 | - display_time: '@datetime', | |
10 | - pageviews: '@integer(300, 5000)' | |
8 | + username: '@sentence(1, 2)', | |
9 | + create_at: '@datetime', | |
10 | + pageviews: '@integer(10, 500)', | |
11 | + openid: '@sentence(1, 1)', | |
12 | + avatar:'----' | |
11 | 13 | }] |
12 | 14 | }) |
13 | 15 | ... | ... |
package.json
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | }, |
17 | 17 | "dependencies": { |
18 | 18 | "axios": "0.18.1", |
19 | + "babel-polyfill": "^6.26.0", | |
19 | 20 | "echarts": "^4.7.0", |
20 | 21 | "element-ui": "2.13.0", |
21 | 22 | "js-cookie": "2.2.0", |
... | ... | @@ -29,6 +30,7 @@ |
29 | 30 | }, |
30 | 31 | "devDependencies": { |
31 | 32 | "@babel/core": "7.0.0", |
33 | + "@babel/preset-env": "^7.9.6", | |
32 | 34 | "@babel/register": "7.0.0", |
33 | 35 | "@vue/cli-plugin-babel": "3.6.0", |
34 | 36 | "@vue/cli-plugin-eslint": "^3.9.1", |
... | ... | @@ -36,9 +38,12 @@ |
36 | 38 | "@vue/cli-service": "3.6.0", |
37 | 39 | "@vue/test-utils": "1.0.0-beta.29", |
38 | 40 | "autoprefixer": "^9.5.1", |
41 | + "babel-cli": "^6.26.0", | |
39 | 42 | "babel-core": "7.0.0-bridge.0", |
40 | 43 | "babel-eslint": "10.0.1", |
41 | 44 | "babel-jest": "23.6.0", |
45 | + "babel-plugin-component": "^1.1.1", | |
46 | + "babel-preset-env": "^1.7.0", | |
42 | 47 | "chalk": "2.4.2", |
43 | 48 | "connect": "3.6.6", |
44 | 49 | "eslint": "5.15.3", |
... | ... | @@ -53,6 +58,7 @@ |
53 | 58 | "serve-static": "^1.13.2", |
54 | 59 | "svg-sprite-loader": "4.1.3", |
55 | 60 | "svgo": "1.2.2", |
61 | + "vue-schart": "^2.0.0", | |
56 | 62 | "vue-template-compiler": "2.6.10" |
57 | 63 | }, |
58 | 64 | "engines": { | ... | ... |
src/api/admin.js
1 | -import request from '@/utils/request' | |
2 | - | |
3 | -export function login(data) { | |
4 | - console.log('login....', data) | |
5 | - return request({ | |
6 | - url: '/yp/user/login', | |
7 | - method: 'post', | |
8 | - data | |
9 | - }) | |
10 | -} | |
11 | - | |
12 | -export function getInfo(token) { | |
13 | - console.log('getInfo....', token) | |
14 | - return request({ | |
15 | - url: '/yp/user/info', | |
16 | - method: 'get', | |
17 | - params: { token } | |
18 | - }) | |
19 | -} | |
20 | - | |
21 | -export function logout() { | |
22 | - console.log('logout....') | |
23 | - return request({ | |
24 | - url: '/yp/user/logout', | |
25 | - method: 'post' | |
26 | - }) | |
27 | -} | |
1 | +// import request from '@/utils/request' | ... | ... |
src/api/meta.js
... | ... | @@ -0,0 +1,33 @@ |
1 | +import request from '@/utils/request' | |
2 | + | |
3 | +export function listMeta(params) { | |
4 | + return request({ | |
5 | + url: '/yp/meta/list', | |
6 | + method: 'get', | |
7 | + params | |
8 | + }) | |
9 | +} | |
10 | + | |
11 | +export function addMeta(params) { | |
12 | + return request({ | |
13 | + url: '/yp/meta/add', | |
14 | + method: 'get', | |
15 | + params | |
16 | + }) | |
17 | +} | |
18 | + | |
19 | +export function delMeta(params) { | |
20 | + return request({ | |
21 | + url: '/yp/meta/del', | |
22 | + method: 'get', | |
23 | + params | |
24 | + }) | |
25 | +} | |
26 | + | |
27 | +export function modiMeta(params) { | |
28 | + return request({ | |
29 | + url: '/yp/meta/modi', | |
30 | + method: 'get', | |
31 | + params | |
32 | + }) | |
33 | +} | ... | ... |
src/api/relation.js
... | ... | @@ -0,0 +1,17 @@ |
1 | +import request from '@/utils/request' | |
2 | + | |
3 | +export function build(params) { | |
4 | + return request({ | |
5 | + url: '/yp/relation/build', | |
6 | + method: 'get', | |
7 | + params | |
8 | + }) | |
9 | +} | |
10 | + | |
11 | +export function del(params) { | |
12 | + return request({ | |
13 | + url: '/yp/relation/del', | |
14 | + method: 'get', | |
15 | + params | |
16 | + }) | |
17 | +} | ... | ... |
src/api/user.js
... | ... | @@ -27,6 +27,24 @@ export function list(token) { |
27 | 27 | }) |
28 | 28 | } |
29 | 29 | |
30 | +export function add(token) { | |
31 | + console.log('addUser....', token) | |
32 | + return request({ | |
33 | + url: '/yp/user/add', | |
34 | + method: 'get', | |
35 | + params: { token } | |
36 | + }) | |
37 | +} | |
38 | + | |
39 | +export function modi(token) { | |
40 | + console.log('modiUser....', token) | |
41 | + return request({ | |
42 | + url: '/yp/user/modi', | |
43 | + method: 'get', | |
44 | + params: { token } | |
45 | + }) | |
46 | +} | |
47 | + | |
30 | 48 | export function logout() { |
31 | 49 | console.log('logout....') |
32 | 50 | return request({ | ... | ... |
src/assets/img/img.jpg
6 KB
src/assets/img/login-bg.jpg
68.9 KB
src/common/Header.vue
... | ... | @@ -0,0 +1,191 @@ |
1 | +<template> | |
2 | + <div class="header"> | |
3 | + <!-- 折叠按钮 --> | |
4 | + <div class="collapse-btn" @click="collapseChage"> | |
5 | + <i v-if="!collapse" class="el-icon-s-fold"></i> | |
6 | + <i v-else class="el-icon-s-unfold"></i> | |
7 | + </div> | |
8 | + <div class="logo">后台管理系统</div> | |
9 | + <div class="header-right"> | |
10 | + <div class="header-user-con"> | |
11 | + <!-- 全屏显示 --> | |
12 | + <div class="btn-fullscreen" @click="handleFullScreen"> | |
13 | + <el-tooltip effect="dark" :content="fullscreen?`取消全屏`:`全屏`" placement="bottom"> | |
14 | + <i class="el-icon-rank"></i> | |
15 | + </el-tooltip> | |
16 | + </div> | |
17 | + <!-- 消息中心 --> | |
18 | + <div class="btn-bell"> | |
19 | + <el-tooltip | |
20 | + effect="dark" | |
21 | + :content="message?`有${message}条未读消息`:`消息中心`" | |
22 | + placement="bottom" | |
23 | + > | |
24 | + <router-link to="/tabs"> | |
25 | + <i class="el-icon-bell"></i> | |
26 | + </router-link> | |
27 | + </el-tooltip> | |
28 | + <span class="btn-bell-badge" v-if="message"></span> | |
29 | + </div> | |
30 | + <!-- 用户头像 --> | |
31 | + <div class="user-avator"> | |
32 | + <img src="../assets/img/img.jpg" /> | |
33 | + </div> | |
34 | + <!-- 用户名下拉菜单 --> | |
35 | + <el-dropdown class="user-name" trigger="click" @command="handleCommand"> | |
36 | + <span class="el-dropdown-link"> | |
37 | + {{username}} | |
38 | + <i class="el-icon-caret-bottom"></i> | |
39 | + </span> | |
40 | + <el-dropdown-menu slot="dropdown"> | |
41 | + <a href="https://github.com/lin-xin/vue-manage-system" target="_blank"> | |
42 | + <el-dropdown-item>项目仓库</el-dropdown-item> | |
43 | + </a> | |
44 | + <el-dropdown-item divided command="loginout">退出登录</el-dropdown-item> | |
45 | + </el-dropdown-menu> | |
46 | + </el-dropdown> | |
47 | + </div> | |
48 | + </div> | |
49 | + </div> | |
50 | +</template> | |
51 | +<script> | |
52 | +import bus from './bus'; | |
53 | +export default { | |
54 | + data() { | |
55 | + return { | |
56 | + collapse: false, | |
57 | + fullscreen: false, | |
58 | + name: 'linxin', | |
59 | + message: 2 | |
60 | + }; | |
61 | + }, | |
62 | + computed: { | |
63 | + username() { | |
64 | + let username = localStorage.getItem('ms_username'); | |
65 | + return username ? username : this.name; | |
66 | + } | |
67 | + }, | |
68 | + methods: { | |
69 | + // 用户名下拉菜单选择事件 | |
70 | + handleCommand(command) { | |
71 | + if (command == 'loginout') { | |
72 | + localStorage.removeItem('ms_username'); | |
73 | + this.$router.push('/login'); | |
74 | + } | |
75 | + }, | |
76 | + // 侧边栏折叠 | |
77 | + collapseChage() { | |
78 | + this.collapse = !this.collapse; | |
79 | + bus.$emit('collapse', this.collapse); | |
80 | + }, | |
81 | + // 全屏事件 | |
82 | + handleFullScreen() { | |
83 | + let element = document.documentElement; | |
84 | + if (this.fullscreen) { | |
85 | + if (document.exitFullscreen) { | |
86 | + document.exitFullscreen(); | |
87 | + } else if (document.webkitCancelFullScreen) { | |
88 | + document.webkitCancelFullScreen(); | |
89 | + } else if (document.mozCancelFullScreen) { | |
90 | + document.mozCancelFullScreen(); | |
91 | + } else if (document.msExitFullscreen) { | |
92 | + document.msExitFullscreen(); | |
93 | + } | |
94 | + } else { | |
95 | + if (element.requestFullscreen) { | |
96 | + element.requestFullscreen(); | |
97 | + } else if (element.webkitRequestFullScreen) { | |
98 | + element.webkitRequestFullScreen(); | |
99 | + } else if (element.mozRequestFullScreen) { | |
100 | + element.mozRequestFullScreen(); | |
101 | + } else if (element.msRequestFullscreen) { | |
102 | + // IE11 | |
103 | + element.msRequestFullscreen(); | |
104 | + } | |
105 | + } | |
106 | + this.fullscreen = !this.fullscreen; | |
107 | + } | |
108 | + }, | |
109 | + mounted() { | |
110 | + if (document.body.clientWidth < 1500) { | |
111 | + this.collapseChage(); | |
112 | + } | |
113 | + } | |
114 | +}; | |
115 | +</script> | |
116 | +<style scoped> | |
117 | +.header { | |
118 | + position: relative; | |
119 | + box-sizing: border-box; | |
120 | + width: 100%; | |
121 | + height: 70px; | |
122 | + font-size: 22px; | |
123 | + color: #fff; | |
124 | +} | |
125 | +.collapse-btn { | |
126 | + float: left; | |
127 | + padding: 0 21px; | |
128 | + cursor: pointer; | |
129 | + line-height: 70px; | |
130 | +} | |
131 | +.header .logo { | |
132 | + float: left; | |
133 | + width: 250px; | |
134 | + line-height: 70px; | |
135 | +} | |
136 | +.header-right { | |
137 | + float: right; | |
138 | + padding-right: 50px; | |
139 | +} | |
140 | +.header-user-con { | |
141 | + display: flex; | |
142 | + height: 70px; | |
143 | + align-items: center; | |
144 | +} | |
145 | +.btn-fullscreen { | |
146 | + transform: rotate(45deg); | |
147 | + margin-right: 5px; | |
148 | + font-size: 24px; | |
149 | +} | |
150 | +.btn-bell, | |
151 | +.btn-fullscreen { | |
152 | + position: relative; | |
153 | + width: 30px; | |
154 | + height: 30px; | |
155 | + text-align: center; | |
156 | + border-radius: 15px; | |
157 | + cursor: pointer; | |
158 | +} | |
159 | +.btn-bell-badge { | |
160 | + position: absolute; | |
161 | + right: 0; | |
162 | + top: -2px; | |
163 | + width: 8px; | |
164 | + height: 8px; | |
165 | + border-radius: 4px; | |
166 | + background: #f56c6c; | |
167 | + color: #fff; | |
168 | +} | |
169 | +.btn-bell .el-icon-bell { | |
170 | + color: #fff; | |
171 | +} | |
172 | +.user-name { | |
173 | + margin-left: 10px; | |
174 | +} | |
175 | +.user-avator { | |
176 | + margin-left: 20px; | |
177 | +} | |
178 | +.user-avator img { | |
179 | + display: block; | |
180 | + width: 40px; | |
181 | + height: 40px; | |
182 | + border-radius: 50%; | |
183 | +} | |
184 | +.el-dropdown-link { | |
185 | + color: #fff; | |
186 | + cursor: pointer; | |
187 | +} | |
188 | +.el-dropdown-menu__item { | |
189 | + text-align: center; | |
190 | +} | |
191 | +</style> | |
0 | 192 | \ No newline at end of file | ... | ... |
src/common/Home.vue
... | ... | @@ -0,0 +1,50 @@ |
1 | +<template> | |
2 | + <div class="wrapper"> | |
3 | + <v-head></v-head> | |
4 | + <v-sidebar></v-sidebar> | |
5 | + <div class="content-box" :class="{'content-collapse':collapse}"> | |
6 | + <v-tags></v-tags> | |
7 | + <div class="content"> | |
8 | + <transition name="move" mode="out-in"> | |
9 | + <keep-alive :include="tagsList"> | |
10 | + <router-view></router-view> | |
11 | + </keep-alive> | |
12 | + </transition> | |
13 | + <el-backtop target=".content"></el-backtop> | |
14 | + </div> | |
15 | + </div> | |
16 | + </div> | |
17 | +</template> | |
18 | + | |
19 | +<script> | |
20 | +import vHead from './Header.vue'; | |
21 | +import vSidebar from './Sidebar.vue'; | |
22 | +import vTags from './Tags.vue'; | |
23 | +import bus from './bus'; | |
24 | +export default { | |
25 | + data() { | |
26 | + return { | |
27 | + tagsList: [], | |
28 | + collapse: false | |
29 | + }; | |
30 | + }, | |
31 | + components: { | |
32 | + vHead, | |
33 | + vSidebar, | |
34 | + vTags | |
35 | + }, | |
36 | + created() { | |
37 | + bus.$on('collapse-content', msg => { | |
38 | + this.collapse = msg; | |
39 | + }); | |
40 | + // 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。 | |
41 | + bus.$on('tags', msg => { | |
42 | + let arr = []; | |
43 | + for (let i = 0, len = msg.length; i < len; i++) { | |
44 | + msg[i].name && arr.push(msg[i].name); | |
45 | + } | |
46 | + this.tagsList = arr; | |
47 | + }); | |
48 | + } | |
49 | +}; | |
50 | +</script> | |
0 | 51 | \ No newline at end of file | ... | ... |
src/common/Sidebar.vue
... | ... | @@ -0,0 +1,189 @@ |
1 | +<template> | |
2 | + <div class="sidebar"> | |
3 | + <el-menu | |
4 | + class="sidebar-el-menu" | |
5 | + :default-active="onRoutes" | |
6 | + :collapse="collapse" | |
7 | + background-color="#324157" | |
8 | + text-color="#bfcbd9" | |
9 | + active-text-color="#20a0ff" | |
10 | + unique-opened | |
11 | + router | |
12 | + > | |
13 | + <template v-for="item in items"> | |
14 | + <template v-if="item.subs"> | |
15 | + <el-submenu :index="item.index" :key="item.index"> | |
16 | + <template slot="title"> | |
17 | + <i :class="item.icon"></i> | |
18 | + <span slot="title">{{ item.title }}</span> | |
19 | + </template> | |
20 | + <template v-for="subItem in item.subs"> | |
21 | + <el-submenu | |
22 | + v-if="subItem.subs" | |
23 | + :index="subItem.index" | |
24 | + :key="subItem.index" | |
25 | + > | |
26 | + <template slot="title">{{ subItem.title }}</template> | |
27 | + <el-menu-item | |
28 | + v-for="(threeItem,i) in subItem.subs" | |
29 | + :key="i" | |
30 | + :index="threeItem.index" | |
31 | + >{{ threeItem.title }}</el-menu-item> | |
32 | + </el-submenu> | |
33 | + <el-menu-item | |
34 | + v-else | |
35 | + :index="subItem.index" | |
36 | + :key="subItem.index" | |
37 | + >{{ subItem.title }}</el-menu-item> | |
38 | + </template> | |
39 | + </el-submenu> | |
40 | + </template> | |
41 | + <template v-else> | |
42 | + <el-menu-item :index="item.index" :key="item.index"> | |
43 | + <i :class="item.icon"></i> | |
44 | + <span slot="title">{{ item.title }}</span> | |
45 | + </el-menu-item> | |
46 | + </template> | |
47 | + </template> | |
48 | + </el-menu> | |
49 | + </div> | |
50 | +</template> | |
51 | + | |
52 | +<script> | |
53 | +import bus from './bus'; | |
54 | +export default { | |
55 | + data() { | |
56 | + return { | |
57 | + collapse: false, | |
58 | + items: [ | |
59 | + { | |
60 | + icon: 'el-icon-lx-home', | |
61 | + index: 'dashboard', | |
62 | + title: '系统首页' | |
63 | + }, | |
64 | + { | |
65 | + icon: 'el-icon-lx-cascades', | |
66 | + index: 'table', | |
67 | + title: '基础表格' | |
68 | + }, | |
69 | + { | |
70 | + icon: 'el-icon-lx-copy', | |
71 | + index: 'tabs', | |
72 | + title: 'tab选项卡' | |
73 | + }, | |
74 | + { | |
75 | + icon: 'el-icon-lx-calendar', | |
76 | + index: '3', | |
77 | + title: '表单相关', | |
78 | + subs: [ | |
79 | + { | |
80 | + index: 'form', | |
81 | + title: '基本表单' | |
82 | + }, | |
83 | + { | |
84 | + index: '3-2', | |
85 | + title: '三级菜单', | |
86 | + subs: [ | |
87 | + { | |
88 | + index: 'editor', | |
89 | + title: '富文本编辑器' | |
90 | + }, | |
91 | + { | |
92 | + index: 'markdown', | |
93 | + title: 'markdown编辑器' | |
94 | + } | |
95 | + ] | |
96 | + }, | |
97 | + { | |
98 | + index: 'upload', | |
99 | + title: '文件上传' | |
100 | + } | |
101 | + ] | |
102 | + }, | |
103 | + { | |
104 | + icon: 'el-icon-lx-emoji', | |
105 | + index: 'icon', | |
106 | + title: '自定义图标' | |
107 | + }, | |
108 | + { | |
109 | + icon: 'el-icon-pie-chart', | |
110 | + index: 'charts', | |
111 | + title: 'schart图表' | |
112 | + }, | |
113 | + { | |
114 | + icon: 'el-icon-rank', | |
115 | + index: '6', | |
116 | + title: '拖拽组件', | |
117 | + subs: [ | |
118 | + { | |
119 | + index: 'drag', | |
120 | + title: '拖拽列表' | |
121 | + }, | |
122 | + { | |
123 | + index: 'dialog', | |
124 | + title: '拖拽弹框' | |
125 | + } | |
126 | + ] | |
127 | + }, | |
128 | + { | |
129 | + icon: 'el-icon-lx-global', | |
130 | + index: 'i18n', | |
131 | + title: '国际化功能' | |
132 | + }, | |
133 | + { | |
134 | + icon: 'el-icon-lx-warn', | |
135 | + index: '7', | |
136 | + title: '错误处理', | |
137 | + subs: [ | |
138 | + { | |
139 | + index: 'permission', | |
140 | + title: '权限测试' | |
141 | + }, | |
142 | + { | |
143 | + index: '404', | |
144 | + title: '404页面' | |
145 | + } | |
146 | + ] | |
147 | + }, | |
148 | + { | |
149 | + icon: 'el-icon-lx-redpacket_fill', | |
150 | + index: '/donate', | |
151 | + title: '支持作者' | |
152 | + } | |
153 | + ] | |
154 | + }; | |
155 | + }, | |
156 | + computed: { | |
157 | + onRoutes() { | |
158 | + return this.$route.path.replace('/', ''); | |
159 | + } | |
160 | + }, | |
161 | + created() { | |
162 | + // 通过 Event Bus 进行组件间通信,来折叠侧边栏 | |
163 | + bus.$on('collapse', msg => { | |
164 | + this.collapse = msg; | |
165 | + bus.$emit('collapse-content', msg); | |
166 | + }); | |
167 | + } | |
168 | +}; | |
169 | +</script> | |
170 | + | |
171 | +<style scoped> | |
172 | +.sidebar { | |
173 | + display: block; | |
174 | + position: absolute; | |
175 | + left: 0; | |
176 | + top: 70px; | |
177 | + bottom: 0; | |
178 | + overflow-y: scroll; | |
179 | +} | |
180 | +.sidebar::-webkit-scrollbar { | |
181 | + width: 0; | |
182 | +} | |
183 | +.sidebar-el-menu:not(.el-menu--collapse) { | |
184 | + width: 250px; | |
185 | +} | |
186 | +.sidebar > ul { | |
187 | + height: 100%; | |
188 | +} | |
189 | +</style> | |
0 | 190 | \ No newline at end of file | ... | ... |
src/common/Tags.vue
... | ... | @@ -0,0 +1,177 @@ |
1 | +<template> | |
2 | + <div class="tags" v-if="showTags"> | |
3 | + <ul> | |
4 | + <li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index"> | |
5 | + <router-link :to="item.path" class="tags-li-title"> | |
6 | + {{item.title}} | |
7 | + </router-link> | |
8 | + <span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span> | |
9 | + </li> | |
10 | + </ul> | |
11 | + <div class="tags-close-box"> | |
12 | + <el-dropdown @command="handleTags"> | |
13 | + <el-button size="mini" type="primary"> | |
14 | + 标签选项<i class="el-icon-arrow-down el-icon--right"></i> | |
15 | + </el-button> | |
16 | + <el-dropdown-menu size="small" slot="dropdown"> | |
17 | + <el-dropdown-item command="other">关闭其他</el-dropdown-item> | |
18 | + <el-dropdown-item command="all">关闭所有</el-dropdown-item> | |
19 | + </el-dropdown-menu> | |
20 | + </el-dropdown> | |
21 | + </div> | |
22 | + </div> | |
23 | +</template> | |
24 | + | |
25 | +<script> | |
26 | + import bus from './bus'; | |
27 | + export default { | |
28 | + data() { | |
29 | + return { | |
30 | + tagsList: [] | |
31 | + } | |
32 | + }, | |
33 | + methods: { | |
34 | + isActive(path) { | |
35 | + return path === this.$route.fullPath; | |
36 | + }, | |
37 | + // 关闭单个标签 | |
38 | + closeTags(index) { | |
39 | + const delItem = this.tagsList.splice(index, 1)[0]; | |
40 | + const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1]; | |
41 | + if (item) { | |
42 | + delItem.path === this.$route.fullPath && this.$router.push(item.path); | |
43 | + }else{ | |
44 | + this.$router.push('/'); | |
45 | + } | |
46 | + }, | |
47 | + // 关闭全部标签 | |
48 | + closeAll(){ | |
49 | + this.tagsList = []; | |
50 | + this.$router.push('/'); | |
51 | + }, | |
52 | + // 关闭其他标签 | |
53 | + closeOther(){ | |
54 | + const curItem = this.tagsList.filter(item => { | |
55 | + return item.path === this.$route.fullPath; | |
56 | + }) | |
57 | + this.tagsList = curItem; | |
58 | + }, | |
59 | + // 设置标签 | |
60 | + setTags(route){ | |
61 | + const isExist = this.tagsList.some(item => { | |
62 | + return item.path === route.fullPath; | |
63 | + }) | |
64 | + if(!isExist){ | |
65 | + if(this.tagsList.length >= 8){ | |
66 | + this.tagsList.shift(); | |
67 | + } | |
68 | + this.tagsList.push({ | |
69 | + title: route.meta.title, | |
70 | + path: route.fullPath, | |
71 | + name: route.matched[1].components.default.name | |
72 | + }) | |
73 | + } | |
74 | + bus.$emit('tags', this.tagsList); | |
75 | + }, | |
76 | + handleTags(command){ | |
77 | + command === 'other' ? this.closeOther() : this.closeAll(); | |
78 | + } | |
79 | + }, | |
80 | + computed: { | |
81 | + showTags() { | |
82 | + return this.tagsList.length > 0; | |
83 | + } | |
84 | + }, | |
85 | + watch:{ | |
86 | + $route(newValue, oldValue){ | |
87 | + this.setTags(newValue); | |
88 | + } | |
89 | + }, | |
90 | + created(){ | |
91 | + this.setTags(this.$route); | |
92 | + // 监听关闭当前页面的标签页 | |
93 | + bus.$on('close_current_tags', () => { | |
94 | + for (let i = 0, len = this.tagsList.length; i < len; i++) { | |
95 | + const item = this.tagsList[i]; | |
96 | + if(item.path === this.$route.fullPath){ | |
97 | + if(i < len - 1){ | |
98 | + this.$router.push(this.tagsList[i+1].path); | |
99 | + }else if(i > 0){ | |
100 | + this.$router.push(this.tagsList[i-1].path); | |
101 | + }else{ | |
102 | + this.$router.push('/'); | |
103 | + } | |
104 | + this.tagsList.splice(i, 1); | |
105 | + break; | |
106 | + } | |
107 | + } | |
108 | + }) | |
109 | + } | |
110 | + } | |
111 | +</script> | |
112 | + | |
113 | + | |
114 | +<style> | |
115 | + .tags { | |
116 | + position: relative; | |
117 | + height: 30px; | |
118 | + overflow: hidden; | |
119 | + background: #fff; | |
120 | + padding-right: 120px; | |
121 | + box-shadow: 0 5px 10px #ddd; | |
122 | + } | |
123 | + .tags ul { | |
124 | + box-sizing: border-box; | |
125 | + width: 100%; | |
126 | + height: 100%; | |
127 | + } | |
128 | + .tags-li { | |
129 | + float: left; | |
130 | + margin: 3px 5px 2px 3px; | |
131 | + border-radius: 3px; | |
132 | + font-size: 12px; | |
133 | + overflow: hidden; | |
134 | + cursor: pointer; | |
135 | + height: 23px; | |
136 | + line-height: 23px; | |
137 | + border: 1px solid #e9eaec; | |
138 | + background: #fff; | |
139 | + padding: 0 5px 0 12px; | |
140 | + vertical-align: middle; | |
141 | + color: #666; | |
142 | + -webkit-transition: all .3s ease-in; | |
143 | + -moz-transition: all .3s ease-in; | |
144 | + transition: all .3s ease-in; | |
145 | + } | |
146 | + .tags-li:not(.active):hover { | |
147 | + background: #f8f8f8; | |
148 | + } | |
149 | + .tags-li.active { | |
150 | + color: #fff; | |
151 | + } | |
152 | + .tags-li-title { | |
153 | + float: left; | |
154 | + max-width: 80px; | |
155 | + overflow: hidden; | |
156 | + white-space: nowrap; | |
157 | + text-overflow: ellipsis; | |
158 | + margin-right: 5px; | |
159 | + color: #666; | |
160 | + } | |
161 | + .tags-li.active .tags-li-title { | |
162 | + color: #fff; | |
163 | + } | |
164 | + .tags-close-box { | |
165 | + position: absolute; | |
166 | + right: 0; | |
167 | + top: 0; | |
168 | + box-sizing: border-box; | |
169 | + padding-top: 1px; | |
170 | + text-align: center; | |
171 | + width: 110px; | |
172 | + height: 30px; | |
173 | + background: #fff; | |
174 | + box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1); | |
175 | + z-index: 10; | |
176 | + } | |
177 | +</style> | |
0 | 178 | \ No newline at end of file | ... | ... |
src/common/bus.js
src/common/directives.js
... | ... | @@ -0,0 +1,80 @@ |
1 | +import Vue from 'vue'; | |
2 | + | |
3 | +// v-dialogDrag: 弹窗拖拽属性 | |
4 | +Vue.directive('dialogDrag', { | |
5 | + bind(el, binding, vnode, oldVnode) { | |
6 | + const dialogHeaderEl = el.querySelector('.el-dialog__header'); | |
7 | + const dragDom = el.querySelector('.el-dialog'); | |
8 | + | |
9 | + dialogHeaderEl.style.cssText += ';cursor:move;' | |
10 | + dragDom.style.cssText += ';top:0px;' | |
11 | + | |
12 | + // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); | |
13 | + const sty = (() => { | |
14 | + if (window.document.currentStyle) { | |
15 | + return (dom, attr) => dom.currentStyle[attr]; | |
16 | + } else { | |
17 | + return (dom, attr) => getComputedStyle(dom, false)[attr]; | |
18 | + } | |
19 | + })() | |
20 | + | |
21 | + dialogHeaderEl.onmousedown = (e) => { | |
22 | + // 鼠标按下,计算当前元素距离可视区的距离 | |
23 | + const disX = e.clientX - dialogHeaderEl.offsetLeft; | |
24 | + const disY = e.clientY - dialogHeaderEl.offsetTop; | |
25 | + | |
26 | + const screenWidth = document.body.clientWidth; // body当前宽度 | |
27 | + const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取) | |
28 | + | |
29 | + const dragDomWidth = dragDom.offsetWidth; // 对话框宽度 | |
30 | + const dragDomheight = dragDom.offsetHeight; // 对话框高度 | |
31 | + | |
32 | + const minDragDomLeft = dragDom.offsetLeft; | |
33 | + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth; | |
34 | + | |
35 | + const minDragDomTop = dragDom.offsetTop; | |
36 | + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight; | |
37 | + | |
38 | + | |
39 | + // 获取到的值带px 正则匹配替换 | |
40 | + let styL = sty(dragDom, 'left'); | |
41 | + let styT = sty(dragDom, 'top'); | |
42 | + | |
43 | + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px | |
44 | + if (styL.includes('%')) { | |
45 | + styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100); | |
46 | + styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100); | |
47 | + } else { | |
48 | + styL = +styL.replace(/\px/g, ''); | |
49 | + styT = +styT.replace(/\px/g, ''); | |
50 | + }; | |
51 | + | |
52 | + document.onmousemove = function (e) { | |
53 | + // 通过事件委托,计算移动的距离 | |
54 | + let left = e.clientX - disX; | |
55 | + let top = e.clientY - disY; | |
56 | + | |
57 | + // 边界处理 | |
58 | + if (-(left) > minDragDomLeft) { | |
59 | + left = -(minDragDomLeft); | |
60 | + } else if (left > maxDragDomLeft) { | |
61 | + left = maxDragDomLeft; | |
62 | + } | |
63 | + | |
64 | + if (-(top) > minDragDomTop) { | |
65 | + top = -(minDragDomTop); | |
66 | + } else if (top > maxDragDomTop) { | |
67 | + top = maxDragDomTop; | |
68 | + } | |
69 | + | |
70 | + // 移动当前元素 | |
71 | + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`; | |
72 | + }; | |
73 | + | |
74 | + document.onmouseup = function (e) { | |
75 | + document.onmousemove = null; | |
76 | + document.onmouseup = null; | |
77 | + }; | |
78 | + } | |
79 | + } | |
80 | +}) | |
0 | 81 | \ No newline at end of file | ... | ... |
src/common/i18n.js
... | ... | @@ -0,0 +1,30 @@ |
1 | +export const messages = { | |
2 | + 'zh': { | |
3 | + i18n: { | |
4 | + breadcrumb: '国际化产品', | |
5 | + tips: '通过切换语言按钮,来改变当前内容的语言。', | |
6 | + btn: '切换英文', | |
7 | + title1: '常用用法', | |
8 | + p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。', | |
9 | + p2: '没有什么比信念更能支撑我们度过艰难的时光了。', | |
10 | + p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。', | |
11 | + title2: '组件插值', | |
12 | + info: 'Element组件需要国际化,请参考 {action}。', | |
13 | + value: '文档' | |
14 | + } | |
15 | + }, | |
16 | + 'en': { | |
17 | + i18n: { | |
18 | + breadcrumb: 'International Products', | |
19 | + tips: 'Click on the button to change the current language. ', | |
20 | + btn: 'Switch Chinese', | |
21 | + title1: 'Common usage', | |
22 | + p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.", | |
23 | + p2: "Nothing can help us endure dark times better than our faith. ", | |
24 | + p3: "If you can do what you do best and be happy, you're further along in life than most people.", | |
25 | + title2: 'Component interpolation', | |
26 | + info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.', | |
27 | + value: 'documentation' | |
28 | + } | |
29 | + } | |
30 | +} | |
0 | 31 | \ No newline at end of file | ... | ... |
src/layout/components/Navbar.vue
1 | 1 | <template> |
2 | 2 | <div class="navbar"> |
3 | - <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> | |
3 | + <hamburger | |
4 | + :is-active="sidebar.opened" | |
5 | + class="hamburger-container" | |
6 | + @toggleClick="toggleSideBar" | |
7 | + /> | |
4 | 8 | |
5 | 9 | <breadcrumb class="breadcrumb-container" /> |
6 | 10 | |
7 | 11 | <div class="right-menu"> |
8 | - 语言设置 | |
9 | - <el-dropdown class="avatar-container" trigger="click"> | |
10 | - <div class="avatar-wrapper"> | |
11 | - <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar"> | |
12 | - <i class="el-icon-caret-bottom" /> | |
13 | - </div> | |
14 | - <el-dropdown-menu slot="dropdown" class="user-dropdown"> | |
15 | - <router-link to="/"> | |
16 | - <el-dropdown-item> | |
17 | - Home | |
18 | - </el-dropdown-item> | |
19 | - </router-link> | |
20 | - <router-link to="/seting"> | |
21 | - <el-dropdown-item> | |
22 | - 个人设置 | |
23 | - </el-dropdown-item> | |
24 | - </router-link> | |
25 | - <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/"> | |
12 | + <el-menu | |
13 | + :default-active="activeIndex" | |
14 | + class="el-menu-demo" | |
15 | + mode="horizontal" | |
16 | + @select="handleSelect" | |
17 | + > | |
18 | + <el-menu-item index="1"> | |
19 | + <i class="el-icon-bell"></i>通知中心 | |
20 | + <el-badge class="mark" :value="12" /> | |
21 | + </el-menu-item> | |
22 | + <el-submenu index="2"> | |
23 | + <template slot="title"> | |
24 | + <i class="el-icon-custom"></i>个人设置 | |
25 | + </template> | |
26 | + <el-menu-item index="2-1">选项1</el-menu-item> | |
27 | + <el-menu-item index="2-2">选项2</el-menu-item> | |
28 | + <el-menu-item index="2-3">选项3</el-menu-item> | |
29 | + </el-submenu> | |
30 | + <el-dropdown class="avatar-container" trigger="click"> | |
31 | + <div class="avatar-wrapper"> | |
32 | + <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar" /> | |
33 | + <i class="el-icon-caret-bottom" /> | |
34 | + </div> | |
35 | + <el-dropdown-menu slot="dropdown" class="user-dropdown"> | |
36 | + <router-link to="/"> | |
37 | + <el-dropdown-item>Home</el-dropdown-item> | |
38 | + </router-link> | |
39 | + <router-link to="/seting"> | |
40 | + <el-dropdown-item>个人设置</el-dropdown-item> | |
41 | + </router-link> | |
42 | + <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/"> | |
26 | 43 | <el-dropdown-item>Github</el-dropdown-item> |
27 | - </a> --> | |
28 | - <!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/"> | |
44 | + </a>--> | |
45 | + <!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/"> | |
29 | 46 | <el-dropdown-item>Docs</el-dropdown-item> |
30 | - </a> --> | |
31 | - <el-dropdown-item divided @click.native="logout"> | |
32 | - <span style="display:block;">退出系统</span> | |
33 | - </el-dropdown-item> | |
34 | - </el-dropdown-menu> | |
35 | - </el-dropdown> | |
47 | + </a>--> | |
48 | + <el-dropdown-item divided @click.native="logout"> | |
49 | + <span style="display:block;">退出系统</span> | |
50 | + </el-dropdown-item> | |
51 | + </el-dropdown-menu> | |
52 | + </el-dropdown> | |
53 | + <el-menu-item index="3" disabled>ddd</el-menu-item> | |
54 | + <el-menu-item index="4"> | |
55 | + <a href="https://glass.xiuyetang.com" target="_blank">跳到外部链接</a> | |
56 | + </el-menu-item> | |
57 | + </el-menu> | |
36 | 58 | </div> |
37 | 59 | </div> |
38 | 60 | </template> |
39 | 61 | |
40 | 62 | <script> |
41 | -import { mapGetters } from 'vuex' | |
42 | -import Breadcrumb from '@/components/Breadcrumb' | |
43 | -import Hamburger from '@/components/Hamburger' | |
63 | +import { mapGetters } from "vuex"; | |
64 | +import Breadcrumb from "@/components/Breadcrumb"; | |
65 | +import Hamburger from "@/components/Hamburger"; | |
44 | 66 | |
45 | 67 | export default { |
46 | 68 | components: { |
... | ... | @@ -48,41 +70,42 @@ export default { |
48 | 70 | Hamburger |
49 | 71 | }, |
50 | 72 | computed: { |
51 | - ...mapGetters([ | |
52 | - 'sidebar', | |
53 | - 'avatar' | |
54 | - ]) | |
73 | + ...mapGetters(["sidebar", "avatar"]) | |
55 | 74 | }, |
56 | 75 | methods: { |
57 | 76 | toggleSideBar() { |
58 | - this.$store.dispatch('app/toggleSideBar') | |
77 | + this.$store.dispatch("app/toggleSideBar"); | |
59 | 78 | }, |
60 | 79 | async logout() { |
61 | - await this.$store.dispatch('user/logout') | |
62 | - this.$router.push(`/login?redirect=${this.$route.fullPath}`) | |
80 | + await this.$store.dispatch("user/logout"); | |
81 | + this.$router.push(`/login?redirect=${this.$route.fullPath}`); | |
63 | 82 | } |
64 | 83 | } |
65 | -} | |
84 | +}; | |
66 | 85 | </script> |
67 | 86 | |
68 | 87 | <style lang="scss" scoped> |
88 | +.item { | |
89 | + margin-top: 10px; | |
90 | + margin-right: 20px; | |
91 | +} | |
69 | 92 | .navbar { |
70 | 93 | height: 50px; |
71 | 94 | overflow: hidden; |
72 | 95 | position: relative; |
73 | 96 | background: #fff; |
74 | - box-shadow: 0 1px 4px rgba(0,21,41,.08); | |
97 | + box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); | |
75 | 98 | |
76 | 99 | .hamburger-container { |
77 | 100 | line-height: 46px; |
78 | 101 | height: 100%; |
79 | 102 | float: left; |
80 | 103 | cursor: pointer; |
81 | - transition: background .3s; | |
82 | - -webkit-tap-highlight-color:transparent; | |
104 | + transition: background 0.3s; | |
105 | + -webkit-tap-highlight-color: transparent; | |
83 | 106 | |
84 | 107 | &:hover { |
85 | - background: rgba(0, 0, 0, .025) | |
108 | + background: rgba(0, 0, 0, 0.025); | |
86 | 109 | } |
87 | 110 | } |
88 | 111 | |
... | ... | @@ -109,10 +132,10 @@ export default { |
109 | 132 | |
110 | 133 | &.hover-effect { |
111 | 134 | cursor: pointer; |
112 | - transition: background .3s; | |
135 | + transition: background 0.3s; | |
113 | 136 | |
114 | 137 | &:hover { |
115 | - background: rgba(0, 0, 0, .025) | |
138 | + background: rgba(0, 0, 0, 0.025); | |
116 | 139 | } |
117 | 140 | } |
118 | 141 | } | ... | ... |
src/layout/components/index.js
src/main.js
... | ... | @@ -4,7 +4,7 @@ import 'normalize.css/normalize.css' // A modern alternative to CSS resets |
4 | 4 | |
5 | 5 | import ElementUI from 'element-ui' |
6 | 6 | import 'element-ui/lib/theme-chalk/index.css' |
7 | -import locale from 'element-ui/lib/locale/lang/en' // lang i18n | |
7 | +// import locale from 'element-ui/lib/locale/lang/en' // lang i18n | |
8 | 8 | // import local_zh from 'element-ui/lib/locale/lang/zh-CN' // 在node_module里面 |
9 | 9 | |
10 | 10 | import '@/styles/index.scss' // global css |
... | ... | @@ -29,11 +29,11 @@ if (process.env.NODE_ENV === 'production') { |
29 | 29 | mockXHR() |
30 | 30 | } |
31 | 31 | |
32 | +Vue.use(ElementUI, { size: 'small', zIndex: 3000 }) | |
32 | 33 | // set ElementUI lang to EN |
33 | -Vue.use(ElementUI, { locale }) | |
34 | +// Vue.use(ElementUI, { locale }) | |
34 | 35 | // 如果想要中文版 element-ui,按如下方式声明 |
35 | 36 | // Vue.use(ElementUI, {local_zh}) |
36 | - | |
37 | 37 | Vue.config.productionTip = false |
38 | 38 | |
39 | 39 | new Vue({ | ... | ... |
src/router/index.js
... | ... | @@ -30,8 +30,7 @@ import Layout from '@/layout' |
30 | 30 | * a base page that does not have permission requirements |
31 | 31 | * all roles can be accessed |
32 | 32 | */ |
33 | -export const constantRoutes = [ | |
34 | - { | |
33 | +export const constantRoutes = [{ | |
35 | 34 | path: '/login', |
36 | 35 | component: () => import('@/views/login/index'), |
37 | 36 | hidden: true |
... | ... | @@ -51,7 +50,10 @@ export const constantRoutes = [ |
51 | 50 | path: 'dashboard', |
52 | 51 | name: 'Dashboard', |
53 | 52 | component: () => import('@/views/dashboard/index'), |
54 | - meta: { title: '中控台', icon: 'dashboard' } | |
53 | + meta: { | |
54 | + title: '中控台', | |
55 | + icon: 'dashboard' | |
56 | + } | |
55 | 57 | }] |
56 | 58 | }, |
57 | 59 | { |
... | ... | @@ -59,19 +61,27 @@ export const constantRoutes = [ |
59 | 61 | component: Layout, |
60 | 62 | redirect: '/user/list', |
61 | 63 | name: 'user', |
62 | - meta: { title: '用户管理', icon: 'example' }, | |
63 | - children: [ | |
64 | - { | |
64 | + meta: { | |
65 | + title: '用户管理', | |
66 | + icon: 'example' | |
67 | + }, | |
68 | + children: [{ | |
65 | 69 | path: 'user', |
66 | 70 | name: 'User', |
67 | 71 | component: () => import('@/views/table/index'), |
68 | - meta: { title: '用户列表', icon: 'table' } | |
72 | + meta: { | |
73 | + title: '用户列表', | |
74 | + icon: 'table' | |
75 | + } | |
69 | 76 | }, |
70 | 77 | { |
71 | 78 | path: 'tree', |
72 | 79 | name: 'Table', |
73 | 80 | component: () => import('@/views/tree/index'), |
74 | - meta: { title: 'Tree', icon: 'tree' } | |
81 | + meta: { | |
82 | + title: 'Tree', | |
83 | + icon: 'tree' | |
84 | + } | |
75 | 85 | } |
76 | 86 | ] |
77 | 87 | }, |
... | ... | @@ -80,110 +90,229 @@ export const constantRoutes = [ |
80 | 90 | component: Layout, |
81 | 91 | redirect: '/example/table', |
82 | 92 | name: 'Example', |
83 | - meta: { title: 'E1111xample', icon: 'example' }, | |
84 | - children: [ | |
85 | - { | |
93 | + meta: { | |
94 | + title: '商家管理', | |
95 | + icon: 'example' | |
96 | + }, | |
97 | + children: [{ | |
86 | 98 | path: 'table', |
87 | 99 | name: 'Table', |
88 | 100 | component: () => import('@/views/table/index'), |
89 | - meta: { title: 'Table', icon: 'table' } | |
101 | + meta: { | |
102 | + title: 'Table', | |
103 | + icon: 'table' | |
104 | + } | |
90 | 105 | }, |
91 | 106 | { |
92 | 107 | path: 'tree', |
93 | 108 | name: 'Tree', |
94 | 109 | component: () => import('@/views/tree/index'), |
95 | - meta: { title: 'Tree', icon: 'tree' } | |
110 | + meta: { | |
111 | + title: 'Tree', | |
112 | + icon: 'tree' | |
113 | + } | |
96 | 114 | } |
97 | 115 | ] |
98 | 116 | }, |
99 | - | |
100 | 117 | { |
101 | - path: '/form', | |
118 | + path: '/example', | |
102 | 119 | component: Layout, |
103 | - children: [ | |
120 | + redirect: '/example/table', | |
121 | + name: 'Example', | |
122 | + meta: { | |
123 | + title: '产品管理', | |
124 | + icon: 'example' | |
125 | + }, | |
126 | + children: [{ | |
127 | + path: 'table', | |
128 | + name: 'Table', | |
129 | + component: () => import('@/views/table/index'), | |
130 | + meta: { | |
131 | + title: 'Table', | |
132 | + icon: 'table' | |
133 | + } | |
134 | + }, | |
104 | 135 | { |
105 | - path: 'index', | |
106 | - name: 'Form', | |
107 | - component: () => import('@/views/form/index'), | |
108 | - meta: { title: 'Form', icon: 'form' } | |
136 | + path: 'tree', | |
137 | + name: 'Tree', | |
138 | + component: () => import('@/views/tree/index'), | |
139 | + meta: { | |
140 | + title: 'Tree', | |
141 | + icon: 'tree' | |
142 | + } | |
109 | 143 | } |
110 | 144 | ] |
111 | - } | |
112 | -] | |
113 | - | |
114 | -/** | |
115 | - * asyncRoutes | |
116 | - * the routes that need to be dynamically loaded based on user roles | |
117 | - */ | |
118 | -export const asyncRoutes = [ | |
145 | + }, | |
119 | 146 | { |
120 | - path: '/nested', | |
147 | + path: '/example', | |
121 | 148 | component: Layout, |
122 | - redirect: '/nested/menu1', | |
123 | - name: 'Nested', | |
149 | + redirect: '/example/table', | |
150 | + name: 'Example', | |
124 | 151 | meta: { |
125 | - title: 'Nested', | |
126 | - icon: 'nested' | |
152 | + title: '元管理', | |
153 | + icon: 'example' | |
127 | 154 | }, |
128 | - children: [ | |
129 | - { | |
130 | - path: 'menu1', | |
131 | - component: () => import('@/views/nested/menu1/index'), // Parent router-view | |
132 | - name: 'Menu1', | |
133 | - meta: { title: 'Menu1' }, | |
134 | - children: [ | |
135 | - { | |
136 | - path: 'menu1-1', | |
137 | - component: () => import('@/views/nested/menu1/menu1-1'), | |
138 | - name: 'Menu1-1', | |
139 | - meta: { title: 'Menu1-1' } | |
140 | - }, | |
141 | - { | |
142 | - path: 'menu1-2', | |
143 | - component: () => import('@/views/nested/menu1/menu1-2'), | |
144 | - name: 'Menu1-2', | |
145 | - meta: { title: 'Menu1-2' }, | |
146 | - children: [ | |
147 | - { | |
148 | - path: 'menu1-2-1', | |
149 | - component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'), | |
150 | - name: 'Menu1-2-1', | |
151 | - meta: { title: 'Menu1-2-1' } | |
152 | - }, | |
153 | - { | |
154 | - path: 'menu1-2-2', | |
155 | - component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'), | |
156 | - name: 'Menu1-2-2', | |
157 | - meta: { title: 'Menu1-2-2' } | |
158 | - } | |
159 | - ] | |
160 | - }, | |
161 | - { | |
162 | - path: 'menu1-3', | |
163 | - component: () => import('@/views/nested/menu1/menu1-3'), | |
164 | - name: 'Menu1-3', | |
165 | - meta: { title: 'Menu1-3' } | |
166 | - } | |
167 | - ] | |
155 | + children: [{ | |
156 | + path: 'table', | |
157 | + name: 'Table', | |
158 | + component: () => import('@/views/table/index'), | |
159 | + meta: { | |
160 | + title: 'Table', | |
161 | + icon: 'table' | |
162 | + } | |
168 | 163 | }, |
169 | 164 | { |
170 | - path: 'menu2', | |
171 | - component: () => import('@/views/nested/menu2/index'), | |
172 | - meta: { title: 'menu2' } | |
165 | + path: 'tree', | |
166 | + name: 'Tree', | |
167 | + component: () => import('@/views/tree/index'), | |
168 | + meta: { | |
169 | + title: 'Tree', | |
170 | + icon: 'tree' | |
171 | + } | |
173 | 172 | } |
174 | 173 | ] |
175 | 174 | }, |
176 | - | |
177 | 175 | { |
178 | - path: 'external-link', | |
176 | + path: '/example', | |
177 | + component: Layout, | |
178 | + redirect: '/example/table', | |
179 | + name: 'Example', | |
180 | + meta: { | |
181 | + title: '交易管理', | |
182 | + icon: 'example' | |
183 | + }, | |
184 | + children: [{ | |
185 | + path: 'table', | |
186 | + name: 'Table', | |
187 | + component: () => import('@/views/table/index'), | |
188 | + meta: { | |
189 | + title: 'Table', | |
190 | + icon: 'table' | |
191 | + } | |
192 | + }, | |
193 | + { | |
194 | + path: 'tree', | |
195 | + name: 'Tree', | |
196 | + component: () => import('@/views/tree/index'), | |
197 | + meta: { | |
198 | + title: 'Tree', | |
199 | + icon: 'tree' | |
200 | + } | |
201 | + } | |
202 | + ] | |
203 | + }, { | |
204 | + path: '/example', | |
179 | 205 | component: Layout, |
180 | - children: [ | |
206 | + redirect: '/example/table', | |
207 | + name: 'Example', | |
208 | + meta: { | |
209 | + title: '推荐系统', | |
210 | + icon: 'example' | |
211 | + }, | |
212 | + children: [{ | |
213 | + path: 'table', | |
214 | + name: 'Table', | |
215 | + component: () => import('@/views/table/index'), | |
216 | + meta: { | |
217 | + title: 'Table', | |
218 | + icon: 'table' | |
219 | + } | |
220 | + }, | |
221 | + { | |
222 | + path: 'tree', | |
223 | + name: 'Tree', | |
224 | + component: () => import('@/views/tree/index'), | |
225 | + meta: { | |
226 | + title: 'Tree', | |
227 | + icon: 'tree' | |
228 | + } | |
229 | + } | |
230 | + ] | |
231 | + }, { | |
232 | + path: '/system', | |
233 | + component: Layout, | |
234 | + redirect: '/system/table', | |
235 | + name: 'System', | |
236 | + meta: { | |
237 | + title: '系统设置', | |
238 | + icon: 'example' | |
239 | + }, | |
240 | + children: [{ | |
241 | + path: 'table', | |
242 | + name: 'Table', | |
243 | + component: () => import('@/views/table/index'), | |
244 | + meta: { | |
245 | + title: '行业设置', | |
246 | + icon: 'table' | |
247 | + } | |
248 | + }, | |
249 | + { | |
250 | + path: 'tree', | |
251 | + name: 'Tree', | |
252 | + component: () => import('@/views/tree/index'), | |
253 | + meta: { | |
254 | + title: '语言设置', | |
255 | + icon: 'tree' | |
256 | + } | |
257 | + }, | |
258 | + { | |
259 | + path: 'tree', | |
260 | + name: 'Tree', | |
261 | + component: () => import('@/views/tree/index'), | |
262 | + meta: { | |
263 | + title: '货币设置', | |
264 | + icon: 'tree' | |
265 | + } | |
266 | + }, | |
267 | + { | |
268 | + path: 'tree', | |
269 | + name: 'Tree', | |
270 | + component: () => import('@/views/tree/index'), | |
271 | + meta: { | |
272 | + title: '站点类型设置', | |
273 | + icon: 'tree' | |
274 | + } | |
275 | + }, | |
276 | + { | |
277 | + path: 'tree', | |
278 | + name: 'Tree', | |
279 | + component: () => import('@/views/tree/index'), | |
280 | + meta: { | |
281 | + title: '模版设置', | |
282 | + icon: 'tree' | |
283 | + } | |
284 | + }, | |
181 | 285 | { |
182 | - path: 'https://panjiachen.github.io/vue-element-admin-site/#/', | |
183 | - meta: { title: 'External Link', icon: 'link' } | |
286 | + path: 'tree', | |
287 | + name: 'Tree', | |
288 | + component: () => import('@/views/tree/index'), | |
289 | + meta: { | |
290 | + title: '权限设置', | |
291 | + icon: 'tree' | |
292 | + } | |
184 | 293 | } |
185 | 294 | ] |
186 | 295 | }, |
296 | + { | |
297 | + path: '/form', | |
298 | + component: Layout, | |
299 | + children: [{ | |
300 | + path: 'index', | |
301 | + name: 'Form', | |
302 | + component: () => import('@/views/form/index'), | |
303 | + meta: { | |
304 | + title: 'Form', | |
305 | + icon: 'form' | |
306 | + } | |
307 | + }] | |
308 | + } | |
309 | +] | |
310 | + | |
311 | +/** | |
312 | + * asyncRoutes | |
313 | + * the routes that need to be dynamically loaded based on user roles | |
314 | + */ | |
315 | +export const asyncRoutes = [ | |
187 | 316 | // 404 page must be placed at the end !!! |
188 | 317 | { |
189 | 318 | path: '*', |
... | ... | @@ -193,7 +322,9 @@ export const asyncRoutes = [ |
193 | 322 | |
194 | 323 | const createRouter = () => new Router({ |
195 | 324 | // mode: 'history', // require service support |
196 | - scrollBehavior: () => ({ y: 0 }), | |
325 | + scrollBehavior: () => ({ | |
326 | + y: 0 | |
327 | + }), | |
197 | 328 | routes: constantRoutes |
198 | 329 | }) |
199 | 330 | ... | ... |
src/views/403.vue
... | ... | @@ -0,0 +1,59 @@ |
1 | +<template> | |
2 | + <div class="error-page"> | |
3 | + <div class="error-code"> | |
4 | + 4 | |
5 | + <span>0</span>3 | |
6 | + </div> | |
7 | + <div class="error-desc">啊哦~ 你没有权限访问该页面哦</div> | |
8 | + <div class="error-handle"> | |
9 | + <router-link to="/"> | |
10 | + <el-button type="primary" size="large">返回首页</el-button> | |
11 | + </router-link> | |
12 | + <el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button> | |
13 | + </div> | |
14 | + </div> | |
15 | +</template> | |
16 | + | |
17 | +<script> | |
18 | +export default { | |
19 | + methods: { | |
20 | + goBack() { | |
21 | + this.$router.go(-1); | |
22 | + } | |
23 | + } | |
24 | +}; | |
25 | +</script> | |
26 | + | |
27 | + | |
28 | +<style scoped> | |
29 | +.error-page { | |
30 | + display: flex; | |
31 | + justify-content: center; | |
32 | + align-items: center; | |
33 | + flex-direction: column; | |
34 | + width: 100%; | |
35 | + height: 100%; | |
36 | + background: #f3f3f3; | |
37 | + box-sizing: border-box; | |
38 | +} | |
39 | +.error-code { | |
40 | + line-height: 1; | |
41 | + font-size: 250px; | |
42 | + font-weight: bolder; | |
43 | + color: #f02d2d; | |
44 | +} | |
45 | +.error-code span { | |
46 | + color: #00a854; | |
47 | +} | |
48 | +.error-desc { | |
49 | + font-size: 30px; | |
50 | + color: #777; | |
51 | +} | |
52 | +.error-handle { | |
53 | + margin-top: 30px; | |
54 | + padding-bottom: 200px; | |
55 | +} | |
56 | +.error-btn { | |
57 | + margin-left: 100px; | |
58 | +} | |
59 | +</style> | |
0 | 60 | \ No newline at end of file | ... | ... |
src/views/404.vue
... | ... | @@ -2,39 +2,45 @@ |
2 | 2 | <div class="wscn-http404-container"> |
3 | 3 | <div class="wscn-http404"> |
4 | 4 | <div class="pic-404"> |
5 | - <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404"> | |
6 | - <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404"> | |
7 | - <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404"> | |
8 | - <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404"> | |
5 | + <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404" /> | |
6 | + <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404" /> | |
7 | + <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404" /> | |
8 | + <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404" /> | |
9 | 9 | </div> |
10 | 10 | <div class="bullshit"> |
11 | 11 | <div class="bullshit__oops">OOPS!</div> |
12 | - <div class="bullshit__info">All rights reserved | |
13 | - <a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a> | |
12 | + <div class="bullshit__info"> | |
13 | + All rights reserved | |
14 | + <a | |
15 | + style="color:#20a0ff" | |
16 | + href="https://wallstreetcn.com" | |
17 | + target="_blank" | |
18 | + >wallstreetcn</a> | |
14 | 19 | </div> |
15 | 20 | <div class="bullshit__headline">{{ message }}</div> |
16 | - <div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div> | |
17 | - <a href="" class="bullshit__return-home">Back to home</a> | |
21 | + <div | |
22 | + class="bullshit__info" | |
23 | + >Please check that the URL you entered is correct, or click the button below to return to the homepage.</div> | |
24 | + <a href class="bullshit__return-home">Back to home</a> | |
18 | 25 | </div> |
19 | 26 | </div> |
20 | 27 | </div> |
21 | 28 | </template> |
22 | 29 | |
23 | 30 | <script> |
24 | - | |
25 | 31 | export default { |
26 | - name: 'Page404', | |
32 | + name: "Page404", | |
27 | 33 | computed: { |
28 | 34 | message() { |
29 | - return 'The webmaster said that you can not enter this page...' | |
35 | + return "The webmaster said that you can not enter this page..."; | |
30 | 36 | } |
31 | 37 | } |
32 | -} | |
38 | +}; | |
33 | 39 | </script> |
34 | 40 | |
35 | 41 | <style lang="scss" scoped> |
36 | -.wscn-http404-container{ | |
37 | - transform: translate(-50%,-50%); | |
42 | +.wscn-http404-container { | |
43 | + transform: translate(-50%, -50%); | |
38 | 44 | position: absolute; |
39 | 45 | top: 40%; |
40 | 46 | left: 50%; | ... | ... |
src/views/502.vue
... | ... | @@ -0,0 +1,57 @@ |
1 | +<template> | |
2 | + <div class="error-page"> | |
3 | + <div class="error-code"> | |
4 | + 5 | |
5 | + <span>0</span>2 | |
6 | + </div> | |
7 | + <div class="error-desc">啊哦~ 系统出了故障!</div> | |
8 | + <div class="error-handle"> | |
9 | + <router-link to="/"> | |
10 | + <el-button type="primary" size="large">返回首页</el-button> | |
11 | + </router-link> | |
12 | + <el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button> | |
13 | + </div> | |
14 | + </div> | |
15 | +</template> | |
16 | + | |
17 | +<script> | |
18 | +export default { | |
19 | + methods: { | |
20 | + goBack() { | |
21 | + this.$router.go(-1); | |
22 | + } | |
23 | + } | |
24 | +}; | |
25 | +</script> | |
26 | +<style scoped> | |
27 | +.error-page { | |
28 | + display: flex; | |
29 | + justify-content: center; | |
30 | + align-items: center; | |
31 | + flex-direction: column; | |
32 | + width: 100%; | |
33 | + height: 100%; | |
34 | + background: #f3f3f3; | |
35 | + box-sizing: border-box; | |
36 | +} | |
37 | +.error-code { | |
38 | + line-height: 1; | |
39 | + font-size: 250px; | |
40 | + font-weight: bolder; | |
41 | + color: #f02d2d; | |
42 | +} | |
43 | +.error-code span { | |
44 | + color: #00a854; | |
45 | +} | |
46 | +.error-desc { | |
47 | + font-size: 30px; | |
48 | + color: #777; | |
49 | +} | |
50 | +.error-handle { | |
51 | + margin-top: 30px; | |
52 | + padding-bottom: 200px; | |
53 | +} | |
54 | +.error-btn { | |
55 | + margin-left: 100px; | |
56 | +} | |
57 | +</style> | |
0 | 58 | \ No newline at end of file | ... | ... |
src/views/dashboard/index.vue
1 | 1 | <template> |
2 | - <div class="dashboard-container"> | |
3 | - <div class="dashboard-text">用户名: {{ name }}</div> | |
4 | - <div class="dashboard-text">角色: <span v-for="role in roles" :key="role">{{ role }}</span></div> | |
2 | + <div> | |
3 | + <el-row :gutter="20"> | |
4 | + <el-col :span="8"> | |
5 | + <el-card shadow="hover" class="mgb20" style="height:252px;"> | |
6 | + <div class="user-info"> | |
7 | + <img src="../../assets/img/img.jpg" class="user-avator" alt /> | |
8 | + <div class="user-info-cont"> | |
9 | + <div class="user-info-name">{{name}}</div> | |
10 | + <div>{{role}}</div> | |
11 | + </div> | |
12 | + </div> | |
13 | + <div class="user-info-list"> | |
14 | + 上次登录时间: | |
15 | + <span>2019-11-01</span> | |
16 | + </div> | |
17 | + <div class="user-info-list"> | |
18 | + 上次登录地点: | |
19 | + <span>东莞</span> | |
20 | + </div> | |
21 | + </el-card> | |
22 | + <el-card shadow="hover" style="height:252px;"> | |
23 | + <div slot="header" class="clearfix"> | |
24 | + <span>语言详情</span> | |
25 | + </div>Vue | |
26 | + <el-progress :percentage="71.3" color="#42b983"></el-progress>JavaScript | |
27 | + <el-progress :percentage="24.1" color="#f1e05a"></el-progress>CSS | |
28 | + <el-progress :percentage="13.7"></el-progress>HTML | |
29 | + <el-progress :percentage="5.9" color="#f56c6c"></el-progress> | |
30 | + </el-card> | |
31 | + </el-col> | |
32 | + <el-col :span="16"> | |
33 | + <el-row :gutter="20" class="mgb20"> | |
34 | + <el-col :span="8"> | |
35 | + <el-card shadow="hover" :body-style="{padding: '0px'}"> | |
36 | + <div class="grid-content grid-con-1"> | |
37 | + <i class="el-icon-lx-people grid-con-icon"></i> | |
38 | + <div class="grid-cont-right"> | |
39 | + <div class="grid-num">1234</div> | |
40 | + <div>用户访问量</div> | |
41 | + </div> | |
42 | + </div> | |
43 | + </el-card> | |
44 | + </el-col> | |
45 | + <el-col :span="8"> | |
46 | + <el-card shadow="hover" :body-style="{padding: '0px'}"> | |
47 | + <div class="grid-content grid-con-2"> | |
48 | + <i class="el-icon-lx-notice grid-con-icon"></i> | |
49 | + <div class="grid-cont-right"> | |
50 | + <div class="grid-num">321</div> | |
51 | + <div>系统消息</div> | |
52 | + </div> | |
53 | + </div> | |
54 | + </el-card> | |
55 | + </el-col> | |
56 | + <el-col :span="8"> | |
57 | + <el-card shadow="hover" :body-style="{padding: '0px'}"> | |
58 | + <div class="grid-content grid-con-3"> | |
59 | + <i class="el-icon-lx-goods grid-con-icon"></i> | |
60 | + <div class="grid-cont-right"> | |
61 | + <div class="grid-num">5000</div> | |
62 | + <div>数量</div> | |
63 | + </div> | |
64 | + </div> | |
65 | + </el-card> | |
66 | + </el-col> | |
67 | + </el-row> | |
68 | + <el-card shadow="hover" style="height:403px;"> | |
69 | + <div slot="header" class="clearfix"> | |
70 | + <span>待办事项</span> | |
71 | + <el-button style="float: right; padding: 3px 0" type="text" @click="addAction">添加</el-button> | |
72 | + </div> | |
73 | + <el-table :show-header="false" :data="todoList" style="width:100%;"> | |
74 | + <el-table-column width="40"> | |
75 | + <template slot-scope="scope"> | |
76 | + <el-checkbox v-model="scope.row.status"></el-checkbox> | |
77 | + </template> | |
78 | + </el-table-column> | |
79 | + <el-table-column> | |
80 | + <template slot-scope="scope"> | |
81 | + <div | |
82 | + class="todo-item" | |
83 | + :class="{'todo-item-del': scope.row.status}" | |
84 | + >{{scope.row.title}}</div> | |
85 | + </template> | |
86 | + </el-table-column> | |
87 | + <el-table-column width="60"> | |
88 | + <template> | |
89 | + <i class="el-icon-edit" @click="modiAction"></i> | |
90 | + <i class="el-icon-delete" @click="delAction"></i> | |
91 | + </template> | |
92 | + </el-table-column> | |
93 | + </el-table> | |
94 | + </el-card> | |
95 | + </el-col> | |
96 | + </el-row> | |
97 | + <el-row :gutter="20"> | |
98 | + <el-col :span="12"> | |
99 | + <el-card shadow="hover"> | |
100 | + <schart ref="bar" class="schart" canvasId="bar" :options="options"></schart> | |
101 | + </el-card> | |
102 | + </el-col> | |
103 | + <el-col :span="12"> | |
104 | + <el-card shadow="hover"> | |
105 | + <schart ref="line" class="schart" canvasId="line" :options="options2"></schart> | |
106 | + </el-card> | |
107 | + </el-col> | |
108 | + </el-row> | |
5 | 109 | </div> |
6 | 110 | </template> |
7 | 111 | |
8 | 112 | <script> |
9 | -import { mapGetters } from 'vuex' | |
113 | +import { mapGetters } from "vuex"; | |
114 | +import Vue from "vue"; | |
115 | +import { | |
116 | + Pagination, | |
117 | + Dialog, | |
118 | + Autocomplete, | |
119 | + Dropdown, | |
120 | + DropdownMenu, | |
121 | + DropdownItem, | |
122 | + Menu, | |
123 | + Submenu, | |
124 | + MenuItem, | |
125 | + MenuItemGroup, | |
126 | + Input, | |
127 | + InputNumber, | |
128 | + Radio, | |
129 | + RadioGroup, | |
130 | + RadioButton, | |
131 | + Checkbox, | |
132 | + CheckboxButton, | |
133 | + CheckboxGroup, | |
134 | + Switch, | |
135 | + Select, | |
136 | + Option, | |
137 | + OptionGroup, | |
138 | + Button, | |
139 | + ButtonGroup, | |
140 | + Table, | |
141 | + TableColumn, | |
142 | + DatePicker, | |
143 | + TimeSelect, | |
144 | + TimePicker, | |
145 | + Popover, | |
146 | + Tooltip, | |
147 | + Breadcrumb, | |
148 | + BreadcrumbItem, | |
149 | + Form, | |
150 | + FormItem, | |
151 | + Tabs, | |
152 | + TabPane, | |
153 | + Tag, | |
154 | + Tree, | |
155 | + Alert, | |
156 | + Slider, | |
157 | + Icon, | |
158 | + Row, | |
159 | + Col, | |
160 | + Upload, | |
161 | + Progress, | |
162 | + Spinner, | |
163 | + Badge, | |
164 | + Card, | |
165 | + Rate, | |
166 | + Steps, | |
167 | + Step, | |
168 | + Carousel, | |
169 | + CarouselItem, | |
170 | + Collapse, | |
171 | + CollapseItem, | |
172 | + Cascader, | |
173 | + ColorPicker, | |
174 | + Transfer, | |
175 | + Container, | |
176 | + Header, | |
177 | + Aside, | |
178 | + Main, | |
179 | + Footer, | |
180 | + Timeline, | |
181 | + TimelineItem, | |
182 | + Link, | |
183 | + Divider, | |
184 | + Image, | |
185 | + Calendar, | |
186 | + Backtop, | |
187 | + PageHeader, | |
188 | + CascaderPanel, | |
189 | + Loading, | |
190 | + MessageBox, | |
191 | + Message, | |
192 | + Notification | |
193 | +} from "element-ui"; | |
10 | 194 | // import ElementUI from 'element-ui' |
195 | +Vue.prototype.$ELEMENT = { size: "small", zIndex: 3000 }; | |
196 | +Vue.use(Pagination); | |
197 | +Vue.use(Dialog); | |
198 | +Vue.use(Autocomplete); | |
199 | +Vue.use(Dropdown); | |
200 | +Vue.use(DropdownMenu); | |
201 | +Vue.use(DropdownItem); | |
202 | +Vue.use(Menu); | |
203 | +Vue.use(Submenu); | |
204 | +Vue.use(MenuItem); | |
205 | +Vue.use(MenuItemGroup); | |
206 | +Vue.use(Input); | |
207 | +Vue.use(InputNumber); | |
208 | +Vue.use(Radio); | |
209 | +Vue.use(RadioGroup); | |
210 | +Vue.use(RadioButton); | |
211 | +Vue.use(Checkbox); | |
212 | +Vue.use(CheckboxButton); | |
213 | +Vue.use(CheckboxGroup); | |
214 | +Vue.use(Switch); | |
215 | +Vue.use(Select); | |
216 | +Vue.use(Option); | |
217 | +Vue.use(OptionGroup); | |
218 | +Vue.use(Button); | |
219 | +Vue.use(ButtonGroup); | |
220 | +Vue.use(Table); | |
221 | +Vue.use(TableColumn); | |
222 | +Vue.use(DatePicker); | |
223 | +Vue.use(TimeSelect); | |
224 | +Vue.use(TimePicker); | |
225 | +Vue.use(Popover); | |
226 | +Vue.use(Tooltip); | |
227 | +Vue.use(Breadcrumb); | |
228 | +Vue.use(BreadcrumbItem); | |
229 | +Vue.use(Form); | |
230 | +Vue.use(FormItem); | |
231 | +Vue.use(Tabs); | |
232 | +Vue.use(TabPane); | |
233 | +Vue.use(Tag); | |
234 | +Vue.use(Tree); | |
235 | +Vue.use(Alert); | |
236 | +Vue.use(Slider); | |
237 | +Vue.use(Icon); | |
238 | +Vue.use(Row); | |
239 | +Vue.use(Col); | |
240 | +Vue.use(Upload); | |
241 | +Vue.use(Progress); | |
242 | +Vue.use(Spinner); | |
243 | +Vue.use(Badge); | |
244 | +Vue.use(Card); | |
245 | +Vue.use(Rate); | |
246 | +Vue.use(Steps); | |
247 | +Vue.use(Step); | |
248 | +Vue.use(Carousel); | |
249 | +Vue.use(CarouselItem); | |
250 | +Vue.use(Collapse); | |
251 | +Vue.use(CollapseItem); | |
252 | +Vue.use(Cascader); | |
253 | +Vue.use(ColorPicker); | |
254 | +Vue.use(Transfer); | |
255 | +Vue.use(Container); | |
256 | +Vue.use(Header); | |
257 | +Vue.use(Aside); | |
258 | +Vue.use(Main); | |
259 | +Vue.use(Footer); | |
260 | +Vue.use(Timeline); | |
261 | +Vue.use(TimelineItem); | |
262 | +Vue.use(Link); | |
263 | +Vue.use(Divider); | |
264 | +Vue.use(Image); | |
265 | +Vue.use(Calendar); | |
266 | +Vue.use(Backtop); | |
267 | +Vue.use(PageHeader); | |
268 | +Vue.use(CascaderPanel); | |
269 | +Vue.use(Loading.directive); | |
270 | + | |
271 | +import Schart from "vue-schart"; | |
272 | +import bus from "../../common/bus"; | |
273 | + | |
11 | 274 | // 按需引入 引入 ECharts 主模块 |
12 | 275 | // var echarts = require('echarts/lib/echarts') |
13 | 276 | // 引入柱状图 |
... | ... | @@ -19,24 +282,239 @@ import { mapGetters } from 'vuex' |
19 | 282 | // var echarts = require('echarts') |
20 | 283 | |
21 | 284 | export default { |
22 | - name: 'Dashboard', | |
285 | + name: "Dashboard", | |
286 | + data() { | |
287 | + return { | |
288 | + name: localStorage.getItem("ms_username"), | |
289 | + todoList: [ | |
290 | + { | |
291 | + title: "今天要修复100个bug", | |
292 | + status: true | |
293 | + }, | |
294 | + { | |
295 | + title: "今天要写100行代码加几个bug吧", | |
296 | + status: true | |
297 | + } | |
298 | + ], | |
299 | + data: [ | |
300 | + { | |
301 | + name: "2018/09/04", | |
302 | + value: 1083 | |
303 | + }, | |
304 | + { | |
305 | + name: "2018/09/10", | |
306 | + value: 1065 | |
307 | + } | |
308 | + ], | |
309 | + options: { | |
310 | + type: "bar", | |
311 | + title: { | |
312 | + text: "最近一周各品类销售图" | |
313 | + }, | |
314 | + xRorate: 25, | |
315 | + labels: ["周一", "周二", "周三", "周四", "周五"], | |
316 | + datasets: [ | |
317 | + { | |
318 | + label: "百货", | |
319 | + data: [164, 178, 190, 135, 160] | |
320 | + }, | |
321 | + { | |
322 | + label: "食品", | |
323 | + data: [144, 198, 150, 235, 120] | |
324 | + } | |
325 | + ] | |
326 | + }, | |
327 | + options2: { | |
328 | + type: "line", | |
329 | + title: { | |
330 | + text: "最近几个月各品类销售趋势图" | |
331 | + }, | |
332 | + labels: ["6月", "7月", "8月", "9月", "10月"], | |
333 | + datasets: [ | |
334 | + { | |
335 | + label: "百货", | |
336 | + data: [164, 178, 150, 135, 160] | |
337 | + }, | |
338 | + { | |
339 | + label: "食品", | |
340 | + data: [74, 118, 200, 235, 90] | |
341 | + } | |
342 | + ] | |
343 | + } | |
344 | + }; | |
345 | + }, | |
346 | + components: { | |
347 | + Schart | |
348 | + }, | |
23 | 349 | computed: { |
24 | - ...mapGetters([ | |
25 | - 'name', | |
26 | - 'roles' | |
27 | - ]) | |
350 | + // ...mapGetters(["name", "roles"]) | |
351 | + role() { | |
352 | + return this.name === "admin" ? "超级管理员" : "普通用户"; | |
353 | + } | |
354 | + }, | |
355 | + methods: { | |
356 | + addAction(){ | |
357 | + this.$prompt("请输入内容", "提示", { | |
358 | + confirmButtonText: "确定", | |
359 | + cancelButtonText: "取消", | |
360 | + inputErrorMessage: "内容不能为空" | |
361 | + }) | |
362 | + .then(({ value }) => { | |
363 | + this.$message({ | |
364 | + type: "success", | |
365 | + message: "你的邮箱是: " + value | |
366 | + }); | |
367 | + }) | |
368 | + .catch(() => { | |
369 | + this.$message({ | |
370 | + type: "info", | |
371 | + message: "取消输入" | |
372 | + }); | |
373 | + }); | |
374 | + }, | |
375 | + modiAction() { | |
376 | + // this.$prompt("请输入邮箱", "提示", { | |
377 | + // confirmButtonText: "确定", | |
378 | + // cancelButtonText: "取消", | |
379 | + // inputPattern: /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/, | |
380 | + // inputErrorMessage: "邮箱格式不正确" | |
381 | + // }) | |
382 | + this.$prompt("请输入内容", "提示", { | |
383 | + confirmButtonText: "确定", | |
384 | + cancelButtonText: "取消", | |
385 | + inputErrorMessage: "内容不能为空" | |
386 | + }) | |
387 | + .then(({ value }) => { | |
388 | + this.$message({ | |
389 | + type: "success", | |
390 | + message: "你的邮箱是: " + value | |
391 | + }); | |
392 | + }) | |
393 | + .catch(() => { | |
394 | + this.$message({ | |
395 | + type: "info", | |
396 | + message: "取消输入" | |
397 | + }); | |
398 | + }); | |
399 | + }, | |
400 | + delAction() { | |
401 | + this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", { | |
402 | + confirmButtonText: "确定", | |
403 | + cancelButtonText: "取消", | |
404 | + type: "warning" | |
405 | + }) | |
406 | + .then(() => { | |
407 | + this.$message({ | |
408 | + type: "success", | |
409 | + message: "删除成功!" | |
410 | + }); | |
411 | + }) | |
412 | + .catch(() => { | |
413 | + this.$message({ | |
414 | + type: "info", | |
415 | + message: "已取消删除" | |
416 | + }); | |
417 | + }); | |
418 | + }, | |
419 | + changeDate() { | |
420 | + const now = new Date().getTime(); | |
421 | + this.data.forEach((item, index) => { | |
422 | + const date = new Date(now - (6 - index) * 86400000); | |
423 | + item.name = `${date.getFullYear()}/${date.getMonth() + | |
424 | + 1}/${date.getDate()}`; | |
425 | + }); | |
426 | + } | |
28 | 427 | } |
29 | -} | |
428 | +}; | |
30 | 429 | </script> |
31 | 430 | |
32 | -<style lang="scss" scoped> | |
33 | -.dashboard { | |
34 | - &-container { | |
35 | - margin: 30px; | |
36 | - } | |
37 | - &-text { | |
38 | - font-size: 30px; | |
39 | - line-height: 46px; | |
40 | - } | |
431 | +<style scoped> | |
432 | +.el-row { | |
433 | + margin-bottom: 20px; | |
434 | +} | |
435 | +.grid-content { | |
436 | + display: flex; | |
437 | + align-items: center; | |
438 | + height: 100px; | |
439 | +} | |
440 | +.grid-cont-right { | |
441 | + flex: 1; | |
442 | + text-align: center; | |
443 | + font-size: 14px; | |
444 | + color: #999; | |
445 | +} | |
446 | +.grid-num { | |
447 | + font-size: 30px; | |
448 | + font-weight: bold; | |
449 | +} | |
450 | +.grid-con-icon { | |
451 | + font-size: 50px; | |
452 | + width: 100px; | |
453 | + height: 100px; | |
454 | + text-align: center; | |
455 | + line-height: 100px; | |
456 | + color: #fff; | |
457 | +} | |
458 | +.grid-con-1 .grid-con-icon { | |
459 | + background: rgb(45, 140, 240); | |
460 | +} | |
461 | +.grid-con-1 .grid-num { | |
462 | + color: rgb(45, 140, 240); | |
463 | +} | |
464 | +.grid-con-2 .grid-con-icon { | |
465 | + background: rgb(100, 213, 114); | |
466 | +} | |
467 | +.grid-con-2 .grid-num { | |
468 | + color: rgb(45, 140, 240); | |
469 | +} | |
470 | +.grid-con-3 .grid-con-icon { | |
471 | + background: rgb(242, 94, 67); | |
472 | +} | |
473 | +.grid-con-3 .grid-num { | |
474 | + color: rgb(242, 94, 67); | |
475 | +} | |
476 | +.user-info { | |
477 | + display: flex; | |
478 | + align-items: center; | |
479 | + padding-bottom: 20px; | |
480 | + border-bottom: 2px solid #ccc; | |
481 | + margin-bottom: 20px; | |
482 | +} | |
483 | +.user-avator { | |
484 | + width: 120px; | |
485 | + height: 120px; | |
486 | + border-radius: 50%; | |
487 | +} | |
488 | +.user-info-cont { | |
489 | + padding-left: 50px; | |
490 | + flex: 1; | |
491 | + font-size: 14px; | |
492 | + color: #999; | |
493 | +} | |
494 | +.user-info-cont div:first-child { | |
495 | + font-size: 30px; | |
496 | + color: #222; | |
497 | +} | |
498 | +.user-info-list { | |
499 | + font-size: 14px; | |
500 | + color: #999; | |
501 | + line-height: 25px; | |
502 | +} | |
503 | +.user-info-list span { | |
504 | + margin-left: 70px; | |
505 | +} | |
506 | +.mgb20 { | |
507 | + margin-bottom: 20px; | |
508 | +} | |
509 | +.todo-item { | |
510 | + font-size: 14px; | |
511 | +} | |
512 | +.todo-item-del { | |
513 | + text-decoration: line-through; | |
514 | + color: #999; | |
515 | +} | |
516 | +.schart { | |
517 | + width: 100%; | |
518 | + height: 300px; | |
41 | 519 | } |
42 | 520 | </style> | ... | ... |
src/views/form/index.vue
... | ... | @@ -12,11 +12,21 @@ |
12 | 12 | </el-form-item> |
13 | 13 | <el-form-item label="Activity time"> |
14 | 14 | <el-col :span="11"> |
15 | - <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%;" /> | |
15 | + <el-date-picker | |
16 | + v-model="form.date1" | |
17 | + type="date" | |
18 | + placeholder="Pick a date" | |
19 | + style="width: 100%;" | |
20 | + /> | |
16 | 21 | </el-col> |
17 | 22 | <el-col :span="2" class="line">-</el-col> |
18 | 23 | <el-col :span="11"> |
19 | - <el-time-picker v-model="form.date2" type="fixed-time" placeholder="Pick a time" style="width: 100%;" /> | |
24 | + <el-time-picker | |
25 | + v-model="form.date2" | |
26 | + type="fixed-time" | |
27 | + placeholder="Pick a time" | |
28 | + style="width: 100%;" | |
29 | + /> | |
20 | 30 | </el-col> |
21 | 31 | </el-form-item> |
22 | 32 | <el-form-item label="Instant delivery"> |
... | ... | @@ -52,33 +62,33 @@ export default { |
52 | 62 | data() { |
53 | 63 | return { |
54 | 64 | form: { |
55 | - name: '', | |
56 | - region: '', | |
57 | - date1: '', | |
58 | - date2: '', | |
65 | + name: "", | |
66 | + region: "", | |
67 | + date1: "", | |
68 | + date2: "", | |
59 | 69 | delivery: false, |
60 | 70 | type: [], |
61 | - resource: '', | |
62 | - desc: '' | |
71 | + resource: "", | |
72 | + desc: "" | |
63 | 73 | } |
64 | - } | |
74 | + }; | |
65 | 75 | }, |
66 | 76 | methods: { |
67 | 77 | onSubmit() { |
68 | - this.$message('submit!') | |
78 | + this.$message("submit!"); | |
69 | 79 | }, |
70 | 80 | onCancel() { |
71 | 81 | this.$message({ |
72 | - message: 'cancel!', | |
73 | - type: 'warning' | |
74 | - }) | |
82 | + message: "cancel!", | |
83 | + type: "warning" | |
84 | + }); | |
75 | 85 | } |
76 | 86 | } |
77 | -} | |
87 | +}; | |
78 | 88 | </script> |
79 | 89 | |
80 | 90 | <style scoped> |
81 | -.line{ | |
91 | +.line { | |
82 | 92 | text-align: center; |
83 | 93 | } |
84 | 94 | </style> | ... | ... |
src/views/nested/menu1/menu1-1/index.vue
src/views/table/index.vue
... | ... | @@ -8,73 +8,86 @@ |
8 | 8 | fit |
9 | 9 | highlight-current-row |
10 | 10 | > |
11 | - <el-table-column align="center" label="ID" width="95"> | |
12 | - <template slot-scope="scope"> | |
13 | - {{ scope.$index }} | |
14 | - </template> | |
11 | + <el-table-column align="center" label="用户id"> | |
12 | + <template slot-scope="scope">{{ scope.$index }}</template> | |
13 | + </el-table-column> | |
14 | + | |
15 | + <el-table-column label="openid"> | |
16 | + <template slot-scope="scope">{{ scope.row.openid }}</template> | |
15 | 17 | </el-table-column> |
16 | - <el-table-column label="Title"> | |
18 | + | |
19 | + <el-table-column label="昵称" width="110" align="center"> | |
17 | 20 | <template slot-scope="scope"> |
18 | - {{ scope.row.title }} | |
21 | + <span>{{ scope.row.username }}</span> | |
19 | 22 | </template> |
20 | 23 | </el-table-column> |
21 | - <el-table-column label="Author" width="110" align="center"> | |
24 | + | |
25 | + <el-table-column label="头像" width="110" align="center"> | |
26 | + <template slot-scope="scope">{{ scope.row.avatar }}</template> | |
27 | + </el-table-column> | |
28 | + | |
29 | + <el-table-column class-name="status-col" label="状态" align="center"> | |
22 | 30 | <template slot-scope="scope"> |
23 | - <span>{{ scope.row.author }}</span> | |
31 | + <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag> | |
24 | 32 | </template> |
25 | 33 | </el-table-column> |
26 | - <el-table-column label="Pageviews" width="110" align="center"> | |
34 | + | |
35 | + <el-table-column align="center" prop="created_at" label="注册时间"> | |
27 | 36 | <template slot-scope="scope"> |
28 | - {{ scope.row.pageviews }} | |
37 | + <i class="el-icon-time" /> | |
38 | + <span>{{ scope.row.create_at }}</span> | |
29 | 39 | </template> |
30 | 40 | </el-table-column> |
31 | - <el-table-column class-name="status-col" label="Status" width="110" align="center"> | |
41 | + <el-table-column align="center" prop="created_at" label="成交记录"> | |
32 | 42 | <template slot-scope="scope"> |
33 | - <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag> | |
43 | + <i class="el-icon-time" /> | |
44 | + <span>{{ scope.row.pageviews }}</span> | |
34 | 45 | </template> |
35 | 46 | </el-table-column> |
36 | - <el-table-column align="center" prop="created_at" label="Display_time" width="200"> | |
47 | + <el-table-column align="center" prop="created_at" label="引流图"> | |
37 | 48 | <template slot-scope="scope"> |
38 | - <i class="el-icon-time" /> | |
39 | - <span>{{ scope.row.display_time }}</span> | |
49 | + <span> | |
50 | + <el-button type="primary">子用户{{scope.row.pageviews}}</el-button> | |
51 | + </span> | |
40 | 52 | </template> |
41 | 53 | </el-table-column> |
42 | 54 | </el-table> |
55 | + <el-pagination background layout="prev, pager, next" :total="100"></el-pagination> | |
43 | 56 | </div> |
44 | 57 | </template> |
45 | 58 | |
46 | 59 | <script> |
47 | -import { getList } from '@/api/table' | |
60 | +import { getList } from "@/api/table"; | |
48 | 61 | |
49 | 62 | export default { |
50 | 63 | filters: { |
51 | 64 | statusFilter(status) { |
52 | 65 | const statusMap = { |
53 | - published: 'success', | |
54 | - draft: 'gray', | |
55 | - deleted: 'danger' | |
56 | - } | |
57 | - return statusMap[status] | |
66 | + published: "success", | |
67 | + draft: "gray", | |
68 | + deleted: "danger" | |
69 | + }; | |
70 | + return statusMap[status]; | |
58 | 71 | } |
59 | 72 | }, |
60 | 73 | data() { |
61 | 74 | return { |
62 | 75 | list: null, |
63 | 76 | listLoading: true |
64 | - } | |
77 | + }; | |
65 | 78 | }, |
66 | 79 | created() { |
67 | - this.fetchData() | |
80 | + this.fetchData(); | |
68 | 81 | }, |
69 | 82 | methods: { |
70 | 83 | fetchData() { |
71 | - this.listLoading = true | |
84 | + this.listLoading = true; | |
72 | 85 | getList().then(response => { |
73 | - console.log('----getList---', response) | |
74 | - this.list = response.data.items | |
75 | - this.listLoading = false | |
76 | - }) | |
86 | + console.log("----getList---", response); | |
87 | + this.list = response.data.items; | |
88 | + this.listLoading = false; | |
89 | + }); | |
77 | 90 | } |
78 | 91 | } |
79 | -} | |
92 | +}; | |
80 | 93 | </script> | ... | ... |