Commit 50760eab92891e7022d2759fd55c1f173659e9d8
1 parent
3d3cdb68fc
Exists in
master
auto commit the code by alias command
Showing
34 changed files
with
1508 additions
and
414 deletions
Show diff stats
mock/article.js
1 | import Mock from 'mockjs' | 1 | import Mock from 'mockjs' |
2 | 2 | ||
3 | const List = [] | 3 | const List = [] |
4 | const count = 100 | 4 | const count = 100 |
5 | 5 | ||
6 | const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>' | 6 | const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>' |
7 | const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3' | 7 | const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3' |
8 | 8 | ||
9 | for (let i = 0; i < count; i++) { | 9 | for (let i = 0; i < count; i++) { |
10 | List.push(Mock.mock({ | 10 | List.push(Mock.mock({ |
11 | id: '@increment', | 11 | id: '@increment', |
12 | timestamp: +Mock.Random.date('T'), | 12 | timestamp: +Mock.Random.date('T'), |
13 | author: '@first', | 13 | author: '@first', |
14 | reviewer: '@first', | 14 | reviewer: '@first', |
15 | title: '@title(5, 10)', | 15 | title: '@title(5, 10)', |
16 | content_short: 'mock data', | 16 | content_short: 'mock data', |
17 | content: baseContent, | 17 | content: baseContent, |
18 | forecast: '@float(0, 100, 2, 2)', | 18 | forecast: '@float(0, 100, 2, 2)', |
19 | importance: '@integer(1, 3)', | 19 | importance: '@integer(1, 3)', |
20 | 'type|1': ['CN', 'US', 'JP', 'EU'], | 20 | 'type|1': ['CN', 'US', 'JP', 'EU'], |
21 | 'status|1': ['published', 'draft'], | 21 | 'status|1': ['published', 'draft'], |
22 | display_time: '@datetime', | 22 | display_time: '@datetime', |
23 | comment_disabled: true, | 23 | comment_disabled: true, |
24 | pageviews: '@integer(300, 5000)', | 24 | pageviews: '@integer(300, 5000)', |
25 | image_uri, | 25 | image_uri, |
26 | platforms: ['a-platform'] | 26 | platforms: ['a-platform'] |
27 | })) | 27 | })) |
28 | } | 28 | } |
29 | 29 | ||
30 | export default [ | 30 | export default [{ |
31 | { | 31 | url: '/yp/article/list', |
32 | url: '/vue-element-admin/article/list', | ||
33 | type: 'get', | 32 | type: 'get', |
34 | response: config => { | 33 | response: config => { |
35 | const { importance, type, title, page = 1, limit = 20, sort } = config.query | 34 | const { |
35 | importance, | ||
36 | type, | ||
37 | title, | ||
38 | page = 1, | ||
39 | limit = 20, | ||
40 | sort | ||
41 | } = config.query | ||
36 | 42 | ||
37 | let mockList = List.filter(item => { | 43 | let mockList = List.filter(item => { |
38 | if (importance && item.importance !== +importance) return false | 44 | if (importance && item.importance !== +importance) return false |
39 | if (type && item.type !== type) return false | 45 | if (type && item.type !== type) return false |
40 | if (title && item.title.indexOf(title) < 0) return false | 46 | if (title && item.title.indexOf(title) < 0) return false |
41 | return true | 47 | return true |
42 | }) | 48 | }) |
43 | 49 | ||
44 | if (sort === '-id') { | 50 | if (sort === '-id') { |
45 | mockList = mockList.reverse() | 51 | mockList = mockList.reverse() |
46 | } | 52 | } |
47 | 53 | ||
48 | const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) | 54 | const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) |
49 | 55 | ||
50 | return { | 56 | return { |
51 | code: 20000, | 57 | code: 20000, |
52 | data: { | 58 | data: { |
53 | total: mockList.length, | 59 | total: mockList.length, |
54 | items: pageList | 60 | items: pageList |
55 | } | 61 | } |
56 | } | 62 | } |
57 | } | 63 | } |
58 | }, | 64 | }, |
59 | 65 | ||
60 | { | 66 | { |
61 | url: '/vue-element-admin/article/detail', | 67 | url: '/yp/article/detail', |
62 | type: 'get', | 68 | type: 'get', |
63 | response: config => { | 69 | response: config => { |
64 | const { id } = config.query | 70 | const { |
71 | id | ||
72 | } = config.query | ||
65 | for (const article of List) { | 73 | for (const article of List) { |
66 | if (article.id === +id) { | 74 | if (article.id === +id) { |
67 | return { | 75 | return { |
68 | code: 20000, | 76 | code: 20000, |
69 | data: article | 77 | data: article |
70 | } | 78 | } |
71 | } | 79 | } |
72 | } | 80 | } |
73 | } | 81 | } |
74 | }, | 82 | }, |
75 | 83 | ||
76 | { | 84 | { |
77 | url: '/vue-element-admin/article/pv', | 85 | url: '/yp/article/pv', |
78 | type: 'get', | 86 | type: 'get', |
79 | response: _ => { | 87 | response: _ => { |
80 | return { | 88 | return { |
81 | code: 20000, | 89 | code: 20000, |
82 | data: { | 90 | data: { |
83 | pvData: [ | 91 | pvData: [{ |
84 | { key: 'PC', pv: 1024 }, | 92 | key: 'PC', |
85 | { key: 'mobile', pv: 1024 }, | 93 | pv: 1024 |
86 | { key: 'ios', pv: 1024 }, | 94 | }, |
87 | { key: 'android', pv: 1024 } | 95 | { |
96 | key: 'mobile', | ||
97 | pv: 1024 | ||
98 | }, | ||
99 | { | ||
100 | key: 'ios', | ||
101 | pv: 1024 | ||
102 | }, | ||
103 | { | ||
104 | key: 'android', | ||
105 | pv: 1024 | ||
106 | } | ||
88 | ] | 107 | ] |
89 | } | 108 | } |
90 | } | 109 | } |
91 | } | 110 | } |
92 | }, | 111 | }, |
93 | 112 | ||
94 | { | 113 | { |
95 | url: '/vue-element-admin/article/create', | 114 | url: '/yp/article/create', |
96 | type: 'post', | 115 | type: 'post', |
97 | response: _ => { | 116 | response: _ => { |
98 | return { | 117 | return { |
99 | code: 20000, | 118 | code: 20000, |
100 | data: 'success' | 119 | data: 'success' |
101 | } | 120 | } |
102 | } | 121 | } |
103 | }, | 122 | }, |
104 | 123 | ||
105 | { | 124 | { |
106 | url: '/vue-element-admin/article/update', | 125 | url: '/yp/article/update', |
107 | type: 'post', | 126 | type: 'post', |
108 | response: _ => { | 127 | response: _ => { |
109 | return { | 128 | return { |
110 | code: 20000, | 129 | code: 20000, |
111 | data: 'success' | 130 | data: 'success' |
112 | } | 131 | } |
113 | } | 132 | } |
114 | } | 133 | } |
115 | ] | 134 | ] |
mock/remote-search.js
1 | import Mock from 'mockjs' | 1 | import Mock from 'mockjs' |
2 | 2 | ||
3 | const NameList = [] | 3 | const NameList = [] |
4 | const count = 100 | 4 | const count = 100 |
5 | 5 | ||
6 | for (let i = 0; i < count; i++) { | 6 | for (let i = 0; i < count; i++) { |
7 | NameList.push(Mock.mock({ | 7 | NameList.push(Mock.mock({ |
8 | name: '@first' | 8 | name: '@first' |
9 | })) | 9 | })) |
10 | } | 10 | } |
11 | NameList.push({ name: 'mock-Pan' }) | 11 | NameList.push({ name: 'mock-Pan' }) |
12 | 12 | ||
13 | export default [ | 13 | export default [ |
14 | // username search | 14 | // username search |
15 | { | 15 | { |
16 | url: '/vue-element-admin/search/user', | 16 | url: '/yp/search/user', |
17 | type: 'get', | 17 | type: 'get', |
18 | response: config => { | 18 | response: config => { |
19 | const { name } = config.query | 19 | const { name } = config.query |
20 | const mockNameList = NameList.filter(item => { | 20 | const mockNameList = NameList.filter(item => { |
21 | const lowerCaseName = item.name.toLowerCase() | 21 | const lowerCaseName = item.name.toLowerCase() |
22 | return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0) | 22 | return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0) |
23 | }) | 23 | }) |
24 | return { | 24 | return { |
25 | code: 20000, | 25 | code: 20000, |
26 | data: { items: mockNameList } | 26 | data: { items: mockNameList } |
27 | } | 27 | } |
28 | } | 28 | } |
29 | }, | 29 | }, |
30 | 30 | ||
31 | // transaction list | 31 | // transaction list |
32 | { | 32 | { |
33 | url: '/vue-element-admin/transaction/list', | 33 | url: '/yp/transaction/list', |
34 | type: 'get', | 34 | type: 'get', |
35 | response: _ => { | 35 | response: _ => { |
36 | return { | 36 | return { |
37 | code: 20000, | 37 | code: 20000, |
38 | data: { | 38 | data: { |
39 | total: 20, | 39 | total: 20, |
40 | 'items|20': [{ | 40 | 'items|20': [{ |
41 | order_no: '@guid()', | 41 | order_no: '@guid()', |
42 | timestamp: +Mock.Random.date('T'), | 42 | timestamp: +Mock.Random.date('T'), |
43 | username: '@name()', | 43 | username: '@name()', |
44 | price: '@float(1000, 15000, 0, 2)', | 44 | price: '@float(1000, 15000, 0, 2)', |
45 | 'status|1': ['success', 'pending'] | 45 | 'status|1': ['success', 'pending'] |
46 | }] | 46 | }] |
47 | } | 47 | } |
48 | } | 48 | } |
49 | } | 49 | } |
50 | } | 50 | } |
51 | ] | 51 | ] |
52 | 52 |
mock/role/index.js
1 | import Mock from 'mockjs' | 1 | import Mock from 'mockjs' |
2 | import { deepClone } from '../../src/utils/index.js' | 2 | import { deepClone } from '../../src/utils/index.js' |
3 | import { asyncRoutes, constantRoutes } from './routes.js' | 3 | import { asyncRoutes, constantRoutes } from './routes.js' |
4 | 4 | ||
5 | const routes = deepClone([...constantRoutes, ...asyncRoutes]) | 5 | const routes = deepClone([...constantRoutes, ...asyncRoutes]) |
6 | 6 | ||
7 | const roles = [ | 7 | const roles = [ |
8 | { | 8 | { |
9 | key: 'admin', | 9 | key: 'admin', |
10 | name: 'admin', | 10 | name: 'admin', |
11 | description: 'Super Administrator. Have access to view all pages.', | 11 | description: 'Super Administrator. Have access to view all pages.', |
12 | routes: routes | 12 | routes: routes |
13 | }, | 13 | }, |
14 | { | 14 | { |
15 | key: 'assistant', | 15 | key: 'assistant', |
16 | name: 'assistant', | 16 | name: 'assistant', |
17 | description: 'assistant Administrator. Can see all pages except permission page', | 17 | description: 'assistant Administrator. Can see all pages except permission page', |
18 | routes: routes.filter(i => i.path !== '/permission')// just a mock | 18 | routes: routes.filter(i => i.path !== '/permission')// just a mock |
19 | }, | 19 | }, |
20 | { | 20 | { |
21 | key: 'runner', | 21 | key: 'runner', |
22 | name: 'runner', | 22 | name: 'runner', |
23 | description: 'Normal runner. Can see runner pages except permission page', | 23 | description: 'Normal runner. Can see runner pages except permission page', |
24 | routes: routes.filter(i => i.path !== '/permission')// just a mock | 24 | routes: routes.filter(i => i.path !== '/permission')// just a mock |
25 | }, | 25 | }, |
26 | { | 26 | { |
27 | key: 'shoper', | 27 | key: 'shoper', |
28 | name: 'shoper', | 28 | name: 'shoper', |
29 | description: 'Normal shoper. Can see shoper pages except permission page', | 29 | description: 'Normal shoper. Can see shoper pages except permission page', |
30 | routes: routes.filter(i => i.path !== '/permission')// just a mock | 30 | routes: routes.filter(i => i.path !== '/permission')// just a mock |
31 | }, | 31 | }, |
32 | // { | 32 | // { |
33 | // key: 'visitor', | 33 | // key: 'visitor', |
34 | // name: 'visitor', | 34 | // name: 'visitor', |
35 | // description: 'Just a visitor. Can only see the home page and the document page', | 35 | // description: 'Just a visitor. Can only see the home page and the document page', |
36 | // routes: [{ | 36 | // routes: [{ |
37 | // path: '', | 37 | // path: '', |
38 | // redirect: 'dashboard', | 38 | // redirect: 'dashboard', |
39 | // children: [ | 39 | // children: [ |
40 | // { | 40 | // { |
41 | // path: 'dashboard', | 41 | // path: 'dashboard', |
42 | // name: 'Dashboard', | 42 | // name: 'Dashboard', |
43 | // meta: { title: 'dashboard', icon: 'dashboard' } | 43 | // meta: { title: 'dashboard', icon: 'dashboard' } |
44 | // } | 44 | // } |
45 | // ] | 45 | // ] |
46 | // }] | 46 | // }] |
47 | // } | 47 | // } |
48 | ] | 48 | ] |
49 | 49 | ||
50 | export default [ | 50 | export default [ |
51 | // mock get all routes form server | 51 | // mock get all routes form server |
52 | { | 52 | { |
53 | url: '/vue-element-admin/routes', | 53 | url: '/yp/routes', |
54 | type: 'get', | 54 | type: 'get', |
55 | response: _ => { | 55 | response: _ => { |
56 | return { | 56 | return { |
57 | code: 20000, | 57 | code: 20000, |
58 | data: routes | 58 | data: routes |
59 | } | 59 | } |
60 | } | 60 | } |
61 | }, | 61 | }, |
62 | 62 | ||
63 | // mock get all roles form server | 63 | // mock get all roles form server |
64 | { | 64 | { |
65 | url: '/vue-element-admin/roles', | 65 | url: '/yp/roles', |
66 | type: 'get', | 66 | type: 'get', |
67 | response: _ => { | 67 | response: _ => { |
68 | return { | 68 | return { |
69 | code: 20000, | 69 | code: 20000, |
70 | data: roles | 70 | data: roles |
71 | } | 71 | } |
72 | } | 72 | } |
73 | }, | 73 | }, |
74 | 74 | ||
75 | // add role | 75 | // add role |
76 | { | 76 | { |
77 | url: '/vue-element-admin/role', | 77 | url: '/yp/role', |
78 | type: 'post', | 78 | type: 'post', |
79 | response: { | 79 | response: { |
80 | code: 20000, | 80 | code: 20000, |
81 | data: { | 81 | data: { |
82 | key: Mock.mock('@integer(300, 5000)') | 82 | key: Mock.mock('@integer(300, 5000)') |
83 | } | 83 | } |
84 | } | 84 | } |
85 | }, | 85 | }, |
86 | 86 | ||
87 | // update role | 87 | // update role |
88 | { | 88 | { |
89 | url: '/vue-element-admin/role/[A-Za-z0-9]', | 89 | url: '/yp/role/[A-Za-z0-9]', |
90 | type: 'put', | 90 | type: 'put', |
91 | response: { | 91 | response: { |
92 | code: 20000, | 92 | code: 20000, |
93 | data: { | 93 | data: { |
94 | status: 'success' | 94 | status: 'success' |
95 | } | 95 | } |
96 | } | 96 | } |
97 | }, | 97 | }, |
98 | 98 | ||
99 | // delete role | 99 | // delete role |
100 | { | 100 | { |
101 | url: '/vue-element-admin/role/[A-Za-z0-9]', | 101 | url: '/yp/role/[A-Za-z0-9]', |
102 | type: 'delete', | 102 | type: 'delete', |
103 | response: { | 103 | response: { |
104 | code: 20000, | 104 | code: 20000, |
105 | data: { | 105 | data: { |
106 | status: 'success' | 106 | status: 'success' |
107 | } | 107 | } |
108 | } | 108 | } |
109 | } | 109 | } |
110 | ] | 110 | ] |
111 | 111 |
mock/role/routes.js
1 | // Just a mock data | 1 | // Just a mock data |
2 | 2 | ||
3 | export const constantRoutes = [ | 3 | export const constantRoutes = [ |
4 | { | 4 | { |
5 | path: '/redirect', | 5 | path: '/redirect', |
6 | component: 'layout/Layout', | 6 | component: 'layout/Layout', |
7 | hidden: true, | 7 | hidden: true, |
8 | children: [ | 8 | children: [ |
9 | { | 9 | { |
10 | path: '/redirect/:path*', | 10 | path: '/redirect/:path*', |
11 | component: 'views/redirect/index' | 11 | component: 'views/redirect/index' |
12 | } | 12 | } |
13 | ] | 13 | ] |
14 | }, | 14 | }, |
15 | { | 15 | { |
16 | path: '/login', | 16 | path: '/login', |
17 | component: 'views/login/index', | 17 | component: 'views/login/index', |
18 | hidden: true | 18 | hidden: true |
19 | }, | 19 | }, |
20 | { | 20 | { |
21 | path: '/auth-redirect', | 21 | path: '/auth-redirect', |
22 | component: 'views/login/auth-redirect', | 22 | component: 'views/login/auth-redirect', |
23 | hidden: true | 23 | hidden: true |
24 | }, | 24 | }, |
25 | { | 25 | { |
26 | path: '/401', | ||
27 | component: 'views/error-page/401', | ||
28 | hidden: true | ||
29 | }, | ||
30 | { | ||
31 | path: '/403', | ||
32 | component: 'views/error-page/403', | ||
33 | hidden: true | ||
34 | }, | ||
35 | { | ||
26 | path: '/404', | 36 | path: '/404', |
27 | component: 'views/error-page/404', | 37 | component: 'views/error-page/404', |
28 | hidden: true | 38 | hidden: true |
29 | }, | 39 | }, |
30 | { | 40 | { |
31 | path: '/401', | 41 | path: '/500', |
32 | component: 'views/error-page/401', | 42 | component: 'views/error-page/500', |
33 | hidden: true | 43 | hidden: true |
34 | }, | 44 | }, |
35 | { | 45 | { |
36 | path: '', | 46 | path: '', |
37 | component: 'layout/Layout', | 47 | component: 'layout/Layout', |
38 | redirect: 'dashboard', | 48 | redirect: 'dashboard', |
39 | children: [ | 49 | children: [ |
40 | { | 50 | { |
41 | path: 'dashboard', | 51 | path: 'dashboard', |
42 | component: 'views/dashboard/index', | 52 | component: 'views/dashboard/index', |
43 | name: 'Dashboard', | 53 | name: 'Dashboard', |
44 | meta: { title: 'dashboard', icon: 'dashboard', affix: true } | 54 | meta: { title: 'dashboard', icon: 'dashboard', affix: true } |
45 | } | 55 | } |
46 | ] | 56 | ] |
47 | }, | 57 | }, |
48 | { | 58 | { |
49 | path: '/documentation', | 59 | path: '/documentation', |
50 | component: 'layout/Layout', | 60 | component: 'layout/Layout', |
51 | children: [ | 61 | children: [ |
52 | { | 62 | { |
53 | path: 'index', | 63 | path: 'index', |
54 | component: 'views/documentation/index', | 64 | component: 'views/documentation/index', |
55 | name: 'Documentation', | 65 | name: 'Documentation', |
56 | meta: { title: 'documentation', icon: 'documentation', affix: true } | 66 | meta: { title: 'documentation', icon: 'documentation', affix: true } |
57 | } | 67 | } |
58 | ] | 68 | ] |
59 | }, | 69 | }, |
60 | { | 70 | { |
61 | path: '/guide', | 71 | path: '/guide', |
62 | component: 'layout/Layout', | 72 | component: 'layout/Layout', |
63 | redirect: '/guide/index', | 73 | redirect: '/guide/index', |
64 | children: [ | 74 | children: [ |
65 | { | 75 | { |
66 | path: 'index', | 76 | path: 'index', |
67 | component: 'views/guide/index', | 77 | component: 'views/guide/index', |
68 | name: 'Guide', | 78 | name: 'Guide', |
69 | meta: { title: 'guide', icon: 'guide', noCache: true } | 79 | meta: { title: 'guide', icon: 'guide', noCache: true } |
70 | } | 80 | } |
71 | ] | 81 | ] |
72 | } | 82 | } |
73 | ] | 83 | ] |
74 | 84 | ||
75 | export const asyncRoutes = [ | 85 | export const asyncRoutes = [ |
76 | { | 86 | // { |
77 | path: '/permission', | 87 | // path: '/permission', |
78 | component: 'layout/Layout', | 88 | // component: 'layout/Layout', |
79 | redirect: '/permission/index', | 89 | // redirect: '/permission/index', |
80 | alwaysShow: true, | 90 | // alwaysShow: true, |
81 | meta: { | 91 | // meta: { |
82 | title: 'permission', | 92 | // title: 'permission', |
83 | icon: 'lock', | 93 | // icon: 'lock', |
84 | roles: ['admin', 'assistant', 'runner', 'shoper'] | 94 | // // roles: ['admin', 'assistant', 'runner', 'shoper'] |
85 | }, | 95 | // }, |
86 | children: [ | 96 | // children: [ |
87 | { | 97 | // { |
88 | path: 'page', | 98 | // path: 'page', |
89 | component: 'views/permission/page', | 99 | // component: 'views/permission/page', |
90 | name: 'PagePermission', | 100 | // name: 'PagePermission', |
91 | meta: { | 101 | // meta: { |
92 | title: 'pagePermission', | 102 | // title: 'pagePermission', |
93 | roles: ['admin','assistant'] | 103 | // roles: ['admin','assistant'] |
94 | } | 104 | // } |
95 | }, | 105 | // }, |
96 | { | 106 | // { |
97 | path: 'directive', | 107 | // path: 'directive', |
98 | component: 'views/permission/directive', | 108 | // component: 'views/permission/directive', |
99 | name: 'DirectivePermission', | 109 | // name: 'DirectivePermission', |
100 | meta: { | 110 | // meta: { |
101 | title: 'directivePermission', | 111 | // title: 'directivePermission', |
102 | roles:['shoper'] | 112 | // roles:['shoper'] |
103 | } | 113 | // } |
104 | }, | 114 | // }, |
105 | { | 115 | // { |
106 | path: 'role', | 116 | // path: 'role', |
107 | component: 'views/permission/role', | 117 | // component: 'views/permission/role', |
108 | name: 'RolePermission', | 118 | // name: 'RolePermission', |
109 | meta: { | 119 | // meta: { |
110 | title: 'rolePermission', | 120 | // title: 'rolePermission', |
111 | roles: ['runner'] | 121 | // roles: ['runner'] |
112 | } | 122 | // } |
113 | } | 123 | // } |
114 | ] | 124 | // ] |
115 | }, | 125 | // }, |
116 | 126 | ||
117 | { | 127 | { |
118 | path: '/icon', | 128 | path: '/icon', |
119 | component: 'layout/Layout', | 129 | component: 'layout/Layout', |
120 | meta: { | 130 | meta: { |
121 | title: 'ddddd', | 131 | title: 'ddddd', |
122 | icon:'people', | 132 | icon:'people', |
123 | roles: ['runner'] | 133 | roles: ['runner'] |
124 | }, | 134 | }, |
125 | children: [ | 135 | children: [ |
126 | { | 136 | { |
127 | path: 'index', | 137 | path: 'index', |
128 | component: 'views/icons/index', | 138 | component: 'views/icons/index', |
129 | name: 'Icons', | 139 | name: 'Icons', |
130 | meta: { title: 'icons', icon: 'icon', noCache: true } | 140 | meta: { title: 'icons', icon: 'icon', noCache: true } |
131 | } | 141 | } |
132 | ] | 142 | ] |
133 | }, | 143 | }, |
134 | 144 | ||
135 | { | 145 | { |
136 | path: '/components', | 146 | path: '/components', |
137 | component: 'layout/Layout', | 147 | component: 'layout/Layout', |
138 | redirect: 'noRedirect', | 148 | redirect: 'noRedirect', |
139 | name: 'ComponentDemo', | 149 | name: 'ComponentDemo', |
140 | meta: { | 150 | meta: { |
141 | title: 'components', | 151 | title: 'components', |
142 | icon: 'component' | 152 | icon: 'component' |
143 | }, | 153 | }, |
144 | children: [ | 154 | children: [ |
145 | { | 155 | { |
146 | path: 'tinymce', | 156 | path: 'tinymce', |
147 | component: 'views/components-demo/tinymce', | 157 | component: 'views/components-demo/tinymce', |
148 | name: 'TinymceDemo', | 158 | name: 'TinymceDemo', |
149 | meta: { title: 'tinymce' } | 159 | meta: { title: 'tinymce' } |
150 | }, | 160 | }, |
151 | { | 161 | { |
152 | path: 'markdown', | 162 | path: 'markdown', |
153 | component: 'views/components-demo/markdown', | 163 | component: 'views/components-demo/markdown', |
154 | name: 'MarkdownDemo', | 164 | name: 'MarkdownDemo', |
155 | meta: { title: 'markdown' } | 165 | meta: { title: 'markdown' } |
156 | }, | 166 | }, |
157 | { | 167 | { |
158 | path: 'json-editor', | 168 | path: 'json-editor', |
159 | component: 'views/components-demo/json-editor', | 169 | component: 'views/components-demo/json-editor', |
160 | name: 'JsonEditorDemo', | 170 | name: 'JsonEditorDemo', |
161 | meta: { title: 'jsonEditor' } | 171 | meta: { title: 'jsonEditor' } |
162 | }, | 172 | }, |
163 | { | 173 | { |
164 | path: 'split-pane', | 174 | path: 'split-pane', |
165 | component: 'views/components-demo/split-pane', | 175 | component: 'views/components-demo/split-pane', |
166 | name: 'SplitpaneDemo', | 176 | name: 'SplitpaneDemo', |
167 | meta: { title: 'splitPane' } | 177 | meta: { title: 'splitPane' } |
168 | }, | 178 | }, |
169 | { | 179 | { |
170 | path: 'avatar-upload', | 180 | path: 'avatar-upload', |
171 | component: 'views/components-demo/avatar-upload', | 181 | component: 'views/components-demo/avatar-upload', |
172 | name: 'AvatarUploadDemo', | 182 | name: 'AvatarUploadDemo', |
173 | meta: { title: 'avatarUpload' } | 183 | meta: { title: 'avatarUpload' } |
174 | }, | 184 | }, |
175 | { | 185 | { |
176 | path: 'dropzone', | 186 | path: 'dropzone', |
177 | component: 'views/components-demo/dropzone', | 187 | component: 'views/components-demo/dropzone', |
178 | name: 'DropzoneDemo', | 188 | name: 'DropzoneDemo', |
179 | meta: { title: 'dropzone' } | 189 | meta: { title: 'dropzone' } |
180 | }, | 190 | }, |
181 | { | 191 | { |
182 | path: 'sticky', | 192 | path: 'sticky', |
183 | component: 'views/components-demo/sticky', | 193 | component: 'views/components-demo/sticky', |
184 | name: 'StickyDemo', | 194 | name: 'StickyDemo', |
185 | meta: { title: 'sticky' } | 195 | meta: { title: 'sticky' } |
186 | }, | 196 | }, |
187 | { | 197 | { |
188 | path: 'count-to', | 198 | path: 'count-to', |
189 | component: 'views/components-demo/count-to', | 199 | component: 'views/components-demo/count-to', |
190 | name: 'CountToDemo', | 200 | name: 'CountToDemo', |
191 | meta: { title: 'countTo' } | 201 | meta: { title: 'countTo' } |
192 | }, | 202 | }, |
193 | { | 203 | { |
194 | path: 'mixin', | 204 | path: 'mixin', |
195 | component: 'views/components-demo/mixin', | 205 | component: 'views/components-demo/mixin', |
196 | name: 'ComponentMixinDemo', | 206 | name: 'ComponentMixinDemo', |
197 | meta: { title: 'componentMixin' } | 207 | meta: { title: 'componentMixin' } |
198 | }, | 208 | }, |
199 | { | 209 | { |
200 | path: 'back-to-top', | 210 | path: 'back-to-top', |
201 | component: 'views/components-demo/back-to-top', | 211 | component: 'views/components-demo/back-to-top', |
202 | name: 'BackToTopDemo', | 212 | name: 'BackToTopDemo', |
203 | meta: { title: 'backToTop' } | 213 | meta: { title: 'backToTop' } |
204 | }, | 214 | }, |
205 | { | 215 | { |
206 | path: 'drag-dialog', | 216 | path: 'drag-dialog', |
207 | component: 'views/components-demo/drag-dialog', | 217 | component: 'views/components-demo/drag-dialog', |
208 | name: 'DragDialogDemo', | 218 | name: 'DragDialogDemo', |
209 | meta: { title: 'dragDialog' } | 219 | meta: { title: 'dragDialog' } |
210 | }, | 220 | }, |
211 | { | 221 | { |
212 | path: 'drag-select', | 222 | path: 'drag-select', |
213 | component: 'views/components-demo/drag-select', | 223 | component: 'views/components-demo/drag-select', |
214 | name: 'DragSelectDemo', | 224 | name: 'DragSelectDemo', |
215 | meta: { title: 'dragSelect' } | 225 | meta: { title: 'dragSelect' } |
216 | }, | 226 | }, |
217 | { | 227 | { |
218 | path: 'dnd-list', | 228 | path: 'dnd-list', |
219 | component: 'views/components-demo/dnd-list', | 229 | component: 'views/components-demo/dnd-list', |
220 | name: 'DndListDemo', | 230 | name: 'DndListDemo', |
221 | meta: { title: 'dndList' } | 231 | meta: { title: 'dndList' } |
222 | }, | 232 | }, |
223 | { | 233 | { |
224 | path: 'drag-kanban', | 234 | path: 'drag-kanban', |
225 | component: 'views/components-demo/drag-kanban', | 235 | component: 'views/components-demo/drag-kanban', |
226 | name: 'DragKanbanDemo', | 236 | name: 'DragKanbanDemo', |
227 | meta: { title: 'dragKanban' } | 237 | meta: { title: 'dragKanban' } |
228 | } | 238 | } |
229 | ] | 239 | ] |
230 | }, | 240 | }, |
231 | { | 241 | { |
232 | path: '/charts', | 242 | path: '/charts', |
233 | component: 'layout/Layout', | 243 | component: 'layout/Layout', |
234 | redirect: 'noRedirect', | 244 | redirect: 'noRedirect', |
235 | name: 'Charts', | 245 | name: 'Charts', |
236 | meta: { | 246 | meta: { |
237 | title: 'charts', | 247 | title: 'charts', |
238 | icon: 'chart' | 248 | icon: 'chart' |
239 | }, | 249 | }, |
240 | children: [ | 250 | children: [ |
241 | { | 251 | { |
242 | path: 'keyboard', | 252 | path: 'keyboard', |
243 | component: 'views/charts/keyboard', | 253 | component: 'views/charts/keyboard', |
244 | name: 'KeyboardChart', | 254 | name: 'KeyboardChart', |
245 | meta: { title: 'keyboardChart', noCache: true } | 255 | meta: { title: 'keyboardChart', noCache: true } |
246 | }, | 256 | }, |
247 | { | 257 | { |
248 | path: 'line', | 258 | path: 'line', |
249 | component: 'views/charts/line', | 259 | component: 'views/charts/line', |
250 | name: 'LineChart', | 260 | name: 'LineChart', |
251 | meta: { title: 'lineChart', noCache: true } | 261 | meta: { title: 'lineChart', noCache: true } |
252 | }, | 262 | }, |
253 | { | 263 | { |
254 | path: 'mixchart', | 264 | path: 'mixchart', |
255 | component: 'views/charts/mixChart', | 265 | component: 'views/charts/mixChart', |
256 | name: 'MixChart', | 266 | name: 'MixChart', |
257 | meta: { title: 'mixChart', noCache: true } | 267 | meta: { title: 'mixChart', noCache: true } |
258 | } | 268 | } |
259 | ] | 269 | ] |
260 | }, | 270 | }, |
261 | { | 271 | { |
262 | path: '/nested', | 272 | path: '/nested', |
263 | component: 'layout/Layout', | 273 | component: 'layout/Layout', |
264 | redirect: '/nested/menu1/menu1-1', | 274 | redirect: '/nested/menu1/menu1-1', |
265 | name: 'Nested', | 275 | name: 'Nested', |
266 | meta: { | 276 | meta: { |
267 | title: 'nested', | 277 | title: 'nested', |
268 | icon: 'nested' | 278 | icon: 'nested' |
269 | }, | 279 | }, |
270 | children: [ | 280 | children: [ |
271 | { | 281 | { |
272 | path: 'menu1', | 282 | path: 'menu1', |
273 | component: 'views/nested/menu1/index', | 283 | component: 'views/nested/menu1/index', |
274 | name: 'Menu1', | 284 | name: 'Menu1', |
275 | meta: { title: 'menu1' }, | 285 | meta: { title: 'menu1' }, |
276 | redirect: '/nested/menu1/menu1-1', | 286 | redirect: '/nested/menu1/menu1-1', |
277 | children: [ | 287 | children: [ |
278 | { | 288 | { |
279 | path: 'menu1-1', | 289 | path: 'menu1-1', |
280 | component: 'views/nested/menu1/menu1-1', | 290 | component: 'views/nested/menu1/menu1-1', |
281 | name: 'Menu1-1', | 291 | name: 'Menu1-1', |
282 | meta: { title: 'menu1-1' } | 292 | meta: { title: 'menu1-1' } |
283 | }, | 293 | }, |
284 | { | 294 | { |
285 | path: 'menu1-2', | 295 | path: 'menu1-2', |
286 | component: 'views/nested/menu1/menu1-2', | 296 | component: 'views/nested/menu1/menu1-2', |
287 | name: 'Menu1-2', | 297 | name: 'Menu1-2', |
288 | redirect: '/nested/menu1/menu1-2/menu1-2-1', | 298 | redirect: '/nested/menu1/menu1-2/menu1-2-1', |
289 | meta: { title: 'menu1-2' }, | 299 | meta: { title: 'menu1-2' }, |
290 | children: [ | 300 | children: [ |
291 | { | 301 | { |
292 | path: 'menu1-2-1', | 302 | path: 'menu1-2-1', |
293 | component: 'views/nested/menu1/menu1-2/menu1-2-1', | 303 | component: 'views/nested/menu1/menu1-2/menu1-2-1', |
294 | name: 'Menu1-2-1', | 304 | name: 'Menu1-2-1', |
295 | meta: { title: 'menu1-2-1' } | 305 | meta: { title: 'menu1-2-1' } |
296 | }, | 306 | }, |
297 | { | 307 | { |
298 | path: 'menu1-2-2', | 308 | path: 'menu1-2-2', |
299 | component: 'views/nested/menu1/menu1-2/menu1-2-2', | 309 | component: 'views/nested/menu1/menu1-2/menu1-2-2', |
300 | name: 'Menu1-2-2', | 310 | name: 'Menu1-2-2', |
301 | meta: { title: 'menu1-2-2' } | 311 | meta: { title: 'menu1-2-2' } |
302 | } | 312 | } |
303 | ] | 313 | ] |
304 | }, | 314 | }, |
305 | { | 315 | { |
306 | path: 'menu1-3', | 316 | path: 'menu1-3', |
307 | component: 'views/nested/menu1/menu1-3', | 317 | component: 'views/nested/menu1/menu1-3', |
308 | name: 'Menu1-3', | 318 | name: 'Menu1-3', |
309 | meta: { title: 'menu1-3' } | 319 | meta: { title: 'menu1-3' } |
310 | } | 320 | } |
311 | ] | 321 | ] |
312 | }, | 322 | }, |
313 | { | 323 | { |
314 | path: 'menu2', | 324 | path: 'menu2', |
315 | name: 'Menu2', | 325 | name: 'Menu2', |
316 | component: 'views/nested/menu2/index', | 326 | component: 'views/nested/menu2/index', |
317 | meta: { title: 'menu2' } | 327 | meta: { title: 'menu2' } |
318 | } | 328 | } |
319 | ] | 329 | ] |
320 | }, | 330 | }, |
321 | 331 | ||
322 | { | 332 | { |
323 | path: '/example', | 333 | path: '/example', |
324 | component: 'layout/Layout', | 334 | component: 'layout/Layout', |
325 | redirect: '/example/list', | 335 | redirect: '/example/list', |
326 | name: 'Example', | 336 | name: 'Example', |
327 | meta: { | 337 | meta: { |
328 | title: 'example', | 338 | title: 'example', |
329 | icon: 'example' | 339 | icon: 'example' |
330 | }, | 340 | }, |
331 | children: [ | 341 | children: [ |
332 | { | 342 | { |
333 | path: 'create', | 343 | path: 'create', |
334 | component: 'views/example/create', | 344 | component: 'views/example/create', |
335 | name: 'CreateArticle', | 345 | name: 'CreateArticle', |
336 | meta: { title: 'createArticle', icon: 'edit' } | 346 | meta: { title: 'createArticle', icon: 'edit' } |
337 | }, | 347 | }, |
338 | { | 348 | { |
339 | path: 'edit/:id(\\d+)', | 349 | path: 'edit/:id(\\d+)', |
340 | component: 'views/example/edit', | 350 | component: 'views/example/edit', |
341 | name: 'EditArticle', | 351 | name: 'EditArticle', |
342 | meta: { title: 'editArticle', noCache: true }, | 352 | meta: { title: 'editArticle', noCache: true }, |
343 | hidden: true | 353 | hidden: true |
344 | }, | 354 | }, |
345 | { | 355 | { |
346 | path: 'list', | 356 | path: 'list', |
347 | component: 'views/example/list', | 357 | component: 'views/example/list', |
348 | name: 'ArticleList', | 358 | name: 'ArticleList', |
349 | meta: { title: 'articleList', icon: 'list' } | 359 | meta: { title: 'articleList', icon: 'list' } |
350 | } | 360 | } |
351 | ] | 361 | ] |
352 | }, | 362 | }, |
353 | 363 | ||
354 | { | 364 | { |
355 | path: '/tab', | 365 | path: '/tab', |
356 | component: 'layout/Layout', | 366 | component: 'layout/Layout', |
357 | children: [ | 367 | children: [ |
358 | { | 368 | { |
359 | path: 'index', | 369 | path: 'index', |
360 | component: 'views/tab/index', | 370 | component: 'views/tab/index', |
361 | name: 'Tab', | 371 | name: 'Tab', |
362 | meta: { title: 'tab', icon: 'tab' } | 372 | meta: { title: 'tab', icon: 'tab' } |
363 | } | 373 | } |
364 | ] | 374 | ] |
365 | }, | 375 | }, |
366 | 376 | ||
367 | { | 377 | { |
368 | path: '/error', | 378 | path: '/error', |
369 | component: 'layout/Layout', | 379 | component: 'layout/Layout', |
370 | redirect: 'noRedirect', | 380 | redirect: 'noRedirect', |
371 | name: 'ErrorPages', | 381 | name: 'ErrorPages', |
372 | meta: { | 382 | meta: { |
373 | title: 'errorPages', | 383 | title: 'errorPages', |
374 | icon: '404' | 384 | icon: '404' |
375 | }, | 385 | }, |
376 | children: [ | 386 | children: [ |
377 | { | 387 | { |
378 | path: '401', | 388 | path: '401', |
379 | component: 'views/error-page/401', | 389 | component: 'views/error-page/401', |
380 | name: 'Page401', | 390 | name: 'Page401', |
381 | meta: { title: 'page401', noCache: true } | 391 | meta: { title: 'page401', noCache: true } |
382 | }, | 392 | }, |
383 | { | 393 | { |
384 | path: '404', | 394 | path: '404', |
385 | component: 'views/error-page/404', | 395 | component: 'views/error-page/404', |
386 | name: 'Page404', | 396 | name: 'Page404', |
387 | meta: { title: 'page404', noCache: true } | 397 | meta: { title: 'page404', noCache: true } |
398 | }, | ||
399 | { | ||
400 | path: '500', | ||
401 | component: 'views/error-page/500', | ||
402 | name: 'Page500', | ||
403 | meta: { title: 'page500', noCache: true } | ||
388 | } | 404 | } |
389 | ] | 405 | ] |
390 | }, | 406 | }, |
391 | 407 | ||
392 | { | 408 | { |
393 | path: '/error-log', | 409 | path: '/error-log', |
394 | component: 'layout/Layout', | 410 | component: 'layout/Layout', |
395 | redirect: 'noRedirect', | 411 | redirect: 'noRedirect', |
396 | children: [ | 412 | children: [ |
397 | { | 413 | { |
398 | path: 'log', | 414 | path: 'log', |
399 | component: 'views/error-log/index', | 415 | component: 'views/error-log/index', |
400 | name: 'ErrorLog', | 416 | name: 'ErrorLog', |
401 | meta: { title: 'errorLog', icon: 'bug' } | 417 | meta: { title: 'errorLog', icon: 'bug' } |
402 | } | 418 | } |
403 | ] | 419 | ] |
404 | }, | 420 | }, |
405 | 421 | ||
406 | { | 422 | { |
407 | path: '/excel', | 423 | path: '/excel', |
408 | component: 'layout/Layout', | 424 | component: 'layout/Layout', |
409 | redirect: '/excel/export-excel', | 425 | redirect: '/excel/export-excel', |
410 | name: 'Excel', | 426 | name: 'Excel', |
411 | meta: { | 427 | meta: { |
412 | title: 'excel', | 428 | title: 'excel', |
413 | icon: 'excel' | 429 | icon: 'excel' |
414 | }, | 430 | }, |
415 | children: [ | 431 | children: [ |
416 | { | 432 | { |
417 | path: 'export-excel', | 433 | path: 'export-excel', |
418 | component: 'views/excel/export-excel', | 434 | component: 'views/excel/export-excel', |
419 | name: 'ExportExcel', | 435 | name: 'ExportExcel', |
420 | meta: { title: 'exportExcel' } | 436 | meta: { title: 'exportExcel' } |
421 | }, | 437 | }, |
422 | { | 438 | { |
423 | path: 'export-selected-excel', | 439 | path: 'export-selected-excel', |
424 | component: 'views/excel/select-excel', | 440 | component: 'views/excel/select-excel', |
425 | name: 'SelectExcel', | 441 | name: 'SelectExcel', |
426 | meta: { title: 'selectExcel' } | 442 | meta: { title: 'selectExcel' } |
427 | }, | 443 | }, |
428 | { | 444 | { |
429 | path: 'export-merge-header', | 445 | path: 'export-merge-header', |
430 | component: 'views/excel/merge-header', | 446 | component: 'views/excel/merge-header', |
431 | name: 'MergeHeader', | 447 | name: 'MergeHeader', |
432 | meta: { title: 'mergeHeader' } | 448 | meta: { title: 'mergeHeader' } |
433 | }, | 449 | }, |
434 | { | 450 | { |
435 | path: 'upload-excel', | 451 | path: 'upload-excel', |
436 | component: 'views/excel/upload-excel', | 452 | component: 'views/excel/upload-excel', |
437 | name: 'UploadExcel', | 453 | name: 'UploadExcel', |
438 | meta: { title: 'uploadExcel' } | 454 | meta: { title: 'uploadExcel' } |
439 | } | 455 | } |
440 | ] | 456 | ] |
441 | }, | 457 | }, |
442 | 458 | ||
443 | { | 459 | { |
444 | path: '/zip', | 460 | path: '/zip', |
445 | component: 'layout/Layout', | 461 | component: 'layout/Layout', |
446 | redirect: '/zip/download', | 462 | redirect: '/zip/download', |
447 | alwaysShow: true, | 463 | alwaysShow: true, |
448 | meta: { title: 'zip', icon: 'zip' }, | 464 | meta: { title: 'zip', icon: 'zip' }, |
449 | children: [ | 465 | children: [ |
450 | { | 466 | { |
451 | path: 'download', | 467 | path: 'download', |
452 | component: 'views/zip/index', | 468 | component: 'views/zip/index', |
453 | name: 'ExportZip', | 469 | name: 'ExportZip', |
454 | meta: { title: 'exportZip' } | 470 | meta: { title: 'exportZip' } |
455 | } | 471 | } |
456 | ] | 472 | ] |
457 | }, | 473 | }, |
458 | 474 | ||
459 | { | 475 | { |
460 | path: '/pdf', | 476 | path: '/pdf', |
461 | component: 'layout/Layout', | 477 | component: 'layout/Layout', |
462 | redirect: '/pdf/index', | 478 | redirect: '/pdf/index', |
463 | children: [ | 479 | children: [ |
464 | { | 480 | { |
465 | path: 'index', | 481 | path: 'index', |
466 | component: 'views/pdf/index', | 482 | component: 'views/pdf/index', |
467 | name: 'PDF', | 483 | name: 'PDF', |
468 | meta: { title: 'pdf', icon: 'pdf' } | 484 | meta: { title: 'pdf', icon: 'pdf' } |
469 | } | 485 | } |
470 | ] | 486 | ] |
471 | }, | 487 | }, |
472 | { | 488 | { |
473 | path: '/pdf/download', | 489 | path: '/pdf/download', |
474 | component: 'views/pdf/download', | 490 | component: 'views/pdf/download', |
475 | hidden: true | 491 | hidden: true |
476 | }, | 492 | }, |
477 | 493 | ||
478 | { | 494 | { |
479 | path: '/theme', | 495 | path: '/theme', |
480 | component: 'layout/Layout', | 496 | component: 'layout/Layout', |
481 | redirect: 'noRedirect', | 497 | redirect: 'noRedirect', |
482 | children: [ | 498 | children: [ |
483 | { | 499 | { |
484 | path: 'index', | 500 | path: 'index', |
485 | component: 'views/theme/index', | 501 | component: 'views/theme/index', |
486 | name: 'Theme', | 502 | name: 'Theme', |
487 | meta: { title: 'theme', icon: 'theme' } | 503 | meta: { title: 'theme', icon: 'theme' } |
488 | } | 504 | } |
489 | ] | 505 | ] |
490 | }, | 506 | }, |
491 | 507 | ||
492 | { | 508 | { |
493 | path: '/clipboard', | 509 | path: '/clipboard', |
494 | component: 'layout/Layout', | 510 | component: 'layout/Layout', |
495 | redirect: 'noRedirect', | 511 | redirect: 'noRedirect', |
496 | children: [ | 512 | children: [ |
497 | { | 513 | { |
498 | path: 'index', | 514 | path: 'index', |
499 | component: 'views/clipboard/index', | 515 | component: 'views/clipboard/index', |
500 | name: 'ClipboardDemo', | 516 | name: 'ClipboardDemo', |
501 | meta: { title: 'clipboardDemo', icon: 'clipboard' } | 517 | meta: { title: 'clipboardDemo', icon: 'clipboard' } |
502 | } | 518 | } |
503 | ] | 519 | ] |
504 | }, | 520 | }, |
505 | 521 | ||
506 | { | 522 | { |
507 | path: '/i18n', | 523 | path: '/i18n', |
508 | component: 'layout/Layout', | 524 | component: 'layout/Layout', |
509 | children: [ | 525 | children: [ |
510 | { | 526 | { |
511 | path: 'index', | 527 | path: 'index', |
512 | component: 'views/i18n-demo/index', | 528 | component: 'views/i18n-demo/index', |
513 | name: 'I18n', | 529 | name: 'I18n', |
514 | meta: { title: 'i18n', icon: 'international' } | 530 | meta: { title: 'i18n', icon: 'international' } |
515 | } | 531 | } |
516 | ] | 532 | ] |
517 | }, | 533 | }, |
518 | 534 | ||
519 | { | 535 | { |
520 | path: 'external-link', | 536 | path: 'external-link', |
521 | component: 'layout/Layout', | 537 | component: 'layout/Layout', |
522 | children: [ | 538 | children: [ |
523 | { | 539 | { |
524 | path: 'https://github.com/PanJiaChen/vue-element-admin', | 540 | path: 'https://github.com/PanJiaChen/vue-element-admin', |
525 | meta: { title: 'externalLink', icon: 'link' } | 541 | meta: { title: 'externalLink', icon: 'link' } |
526 | } | 542 | } |
527 | ] | 543 | ] |
528 | }, | 544 | }, |
529 | 545 | ||
530 | { path: '*', redirect: '/404', hidden: true } | 546 | { path: '*', redirect: '/404', hidden: true } |
531 | ] | 547 | ] |
532 | 548 |
mock/user.js
1 | 1 | ||
2 | import Mock from 'mockjs' | ||
3 | |||
2 | const tokens = { | 4 | const tokens = { |
3 | admin: { | 5 | admin: { |
4 | token: 'admin-token' | 6 | token: 'admin-token' |
5 | }, | 7 | }, |
6 | assistant: { | 8 | assistant: { |
7 | token: 'assistant-token' | 9 | token: 'assistant-token' |
8 | }, | 10 | }, |
9 | runner: { | 11 | runner: { |
10 | token: 'runner-token' | 12 | token: 'runner-token' |
11 | }, | 13 | }, |
12 | shoper: { | 14 | shoper: { |
13 | token: 'shoper-token' | 15 | token: 'shoper-token' |
14 | } | 16 | } |
15 | } | 17 | } |
16 | 18 | ||
17 | const users = { | 19 | const users = { |
18 | 'admin-token': { | 20 | 'admin-token': { |
19 | roles: ['admin'], | 21 | roles: ['admin'], |
20 | introduction: 'I am a super administrator', | 22 | introduction: 'I am a super administrator', |
21 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', | 23 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', |
22 | name: 'Super Admin' | 24 | name: 'Super Admin' |
23 | }, | 25 | }, |
24 | 'assistant-token': { | 26 | 'assistant-token': { |
25 | roles: ['assistant'], | 27 | roles: ['assistant'], |
26 | introduction: 'I am an assistant', | 28 | introduction: 'I am an assistant', |
27 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', | 29 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', |
28 | name: 'Normal assistant' | 30 | name: 'Normal assistant' |
29 | }, | 31 | }, |
30 | 'runner-token': { | 32 | 'runner-token': { |
31 | roles: ['runner'], | 33 | roles: ['runner'], |
32 | introduction: 'I am an runner', | 34 | introduction: 'I am an runner', |
33 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', | 35 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', |
34 | name: 'Normal runner' | 36 | name: 'Normal runner' |
35 | }, | 37 | }, |
36 | 'shoper-token': { | 38 | 'shoper-token': { |
37 | roles: ['shoper'], | 39 | roles: ['shoper'], |
38 | introduction: 'I am an shoper', | 40 | introduction: 'I am an shoper', |
39 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', | 41 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', |
40 | name: 'Normal shoper' | 42 | name: 'Normal shoper' |
41 | } | 43 | } |
42 | } | 44 | } |
43 | 45 | ||
46 | const List = [] | ||
47 | const count = 100 | ||
48 | |||
49 | const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>' | ||
50 | const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3' | ||
51 | |||
52 | for (let i = 0; i < count; i++) { | ||
53 | List.push(Mock.mock({ | ||
54 | uid: '@increment', | ||
55 | create_time: +Mock.Random.date('T'), | ||
56 | nickname: '@first', | ||
57 | reviewer: '@first', | ||
58 | title: '@title(5, 10)', | ||
59 | openid:'@sentence(12,12)', | ||
60 | content_short: 'mock data', | ||
61 | content: baseContent, | ||
62 | forecast: '@float(0, 100, 2, 2)', | ||
63 | importance: '@integer(1, 3)', | ||
64 | 'type|1': ['CN', 'US', 'JP', 'EU'], | ||
65 | 'status|1': ['published', 'draft'], | ||
66 | display_time: '@datetime', | ||
67 | comment_disabled: true, | ||
68 | son_of_adv: '@integer(300, 5000)',//下线 | ||
69 | souceof:'@integer(300, 5000)',//源自 | ||
70 | image_uri, | ||
71 | 'roles|1': ['admin', 'assistant', 'shoper', 'runner'], | ||
72 | platforms: ['a-platform']//哪个平台 | ||
73 | })) | ||
74 | } | ||
75 | |||
44 | export default [ | 76 | export default [ |
45 | // user login | 77 | // user login |
46 | { | 78 | { |
47 | url: '/vue-element-admin/user/login', | 79 | url: '/yp/user/login', |
48 | type: 'post', | 80 | type: 'post', |
49 | response: config => { | 81 | response: config => { |
50 | const { username } = config.body | 82 | const { username } = config.body |
51 | const token = tokens[username] | 83 | const token = tokens[username] |
52 | 84 | ||
53 | // mock error | 85 | // mock error |
54 | if (!token) { | 86 | if (!token) { |
55 | return { | 87 | return { |
56 | code: 60204, | 88 | code: 60204, |
57 | message: 'Account and password are incorrect.' | 89 | message: 'Account and password are incorrect.' |
58 | } | 90 | } |
59 | } | 91 | } |
60 | 92 | ||
61 | return { | 93 | return { |
62 | code: 20000, | 94 | code: 20000, |
63 | data: token | 95 | data: token |
64 | } | 96 | } |
65 | } | 97 | } |
66 | }, | 98 | }, |
67 | 99 | ||
68 | // get user info | 100 | // get user info |
69 | { | 101 | { |
70 | url: '/vue-element-admin/user/info\.*', | 102 | url: '/yp/user/info\.*', |
71 | type: 'get', | 103 | type: 'get', |
72 | response: config => { | 104 | response: config => { |
73 | const { token } = config.query | 105 | const { token } = config.query |
74 | const info = users[token] | 106 | const info = users[token] |
75 | 107 | ||
76 | // mock error | 108 | // mock error |
77 | if (!info) { | 109 | if (!info) { |
78 | return { | 110 | return { |
79 | code: 50008, | 111 | code: 50008, |
80 | message: 'Login failed, unable to get user details.' | 112 | message: 'Login failed, unable to get user details.' |
81 | } | 113 | } |
82 | } | 114 | } |
83 | 115 | ||
84 | return { | 116 | return { |
85 | code: 20000, | 117 | code: 20000, |
86 | data: info | 118 | data: info |
87 | } | 119 | } |
88 | } | 120 | } |
89 | }, | 121 | }, |
90 | 122 | ||
91 | // user logout | 123 | // user logout |
92 | { | 124 | { |
93 | url: '/vue-element-admin/user/logout', | 125 | url: '/yp/user/logout', |
126 | type: 'post', | ||
127 | response: _ => { | ||
128 | return { | ||
129 | code: 20000, | ||
130 | data: 'success' | ||
131 | } | ||
132 | } | ||
133 | }, | ||
134 | // user create | ||
135 | { | ||
136 | url: '/yp/user/create', | ||
137 | type: 'post', | ||
138 | response: _ => { | ||
139 | return { | ||
140 | code: 20000, | ||
141 | data: 'success' | ||
142 | } | ||
143 | } | ||
144 | }, | ||
145 | // user update | ||
146 | { | ||
147 | url: '/yp/user/update', | ||
94 | type: 'post', | 148 | type: 'post', |
95 | response: _ => { | 149 | response: _ => { |
96 | return { | 150 | return { |
97 | code: 20000, | 151 | code: 20000, |
98 | data: 'success' | 152 | data: 'success' |
99 | } | 153 | } |
100 | } | 154 | } |
155 | }, | ||
156 | // user del | ||
157 | { | ||
158 | url: '/yp/user/del', | ||
159 | type: 'post', | ||
160 | response: _ => { | ||
161 | return { | ||
162 | code: 20000, | ||
163 | data: 'success' | ||
164 | } | ||
165 | } | ||
166 | }, | ||
167 | // user list | ||
168 | { | ||
169 | url: '/yp/user/list', | ||
170 | type: 'get', | ||
171 | response: config => { | ||
172 | const { | ||
173 | importance, | ||
174 | type, | ||
175 | title, | ||
176 | page = 1, | ||
177 | limit = 20, | ||
178 | sort | ||
179 | } = config.query | ||
180 | |||
181 | let mockList = List.filter(item => { | ||
182 | if (importance && item.importance !== +importance) return false | ||
183 | if (type && item.type !== type) return false | ||
184 | if (title && item.title.indexOf(title) < 0) return false | ||
185 | return true | ||
186 | }) | ||
187 | |||
188 | if (sort === '-id') { | ||
189 | mockList = mockList.reverse() | ||
190 | } | ||
191 | |||
192 | const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) | ||
193 | |||
194 | return { | ||
195 | code: 20000, | ||
196 | data: { | ||
197 | total: mockList.length, | ||
198 | items: pageList | ||
199 | } | ||
200 | } | ||
201 | } | ||
101 | } | 202 | } |
102 | ] | 203 | ] |
103 | 204 |
package.json
1 | { | 1 | { |
2 | "name": "vue-element-admin", | 2 | "name": "vue-element-admin", |
3 | "version": "4.2.1", | 3 | "version": "4.2.1", |
4 | "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features", | 4 | "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features", |
5 | "author": "Pan <panfree23@gmail.com>", | 5 | "author": "Pan <panfree23@gmail.com>", |
6 | "license": "MIT", | 6 | "license": "MIT", |
7 | "scripts": { | 7 | "scripts": { |
8 | "dev": "vue-cli-service serve", | 8 | "dev": "vue-cli-service serve", |
9 | "build:prod": "vue-cli-service build", | 9 | "build:prod": "vue-cli-service build", |
10 | "build:stage": "vue-cli-service build --mode staging", | 10 | "build:stage": "vue-cli-service build --mode staging", |
11 | "preview": "node build/index.js --preview", | 11 | "preview": "node build/index.js --preview", |
12 | "lint": "eslint --ext .js,.vue src", | 12 | "lint": "eslint --fix --ext .js,.vue src", |
13 | "test:unit": "jest --clearCache && vue-cli-service test:unit", | 13 | "test:unit": "jest --clearCache && vue-cli-service test:unit", |
14 | "test:ci": "npm run lint && npm run test:unit", | 14 | "test:ci": "npm run lint && npm run test:unit", |
15 | "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml", | 15 | "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml", |
16 | "new": "plop" | 16 | "new": "plop" |
17 | }, | 17 | }, |
18 | "husky": { | 18 | "husky": { |
19 | "hooks": { | 19 | "hooks": { |
20 | "pre-commit": "lint-staged" | 20 | "pre-commit": "lint-staged" |
21 | } | 21 | } |
22 | }, | 22 | }, |
23 | "lint-staged": { | 23 | "lint-staged": { |
24 | "src/**/*.{js,vue}": [ | 24 | "src/**/*.{js,vue}": [ |
25 | "eslint --fix", | 25 | "eslint --fix", |
26 | "git add" | 26 | "git add" |
27 | ] | 27 | ] |
28 | }, | 28 | }, |
29 | "keywords": [ | 29 | "keywords": [ |
30 | "vue", | 30 | "vue", |
31 | "admin", | 31 | "admin", |
32 | "dashboard", | 32 | "dashboard", |
33 | "element-ui", | 33 | "element-ui", |
34 | "boilerplate", | 34 | "boilerplate", |
35 | "admin-template", | 35 | "admin-template", |
36 | "management-system" | 36 | "management-system" |
37 | ], | 37 | ], |
38 | "repository": { | 38 | "repository": { |
39 | "type": "git", | 39 | "type": "git", |
40 | "url": "git+https://github.com/PanJiaChen/vue-element-admin.git" | 40 | "url": "git+https://github.com/PanJiaChen/vue-element-admin.git" |
41 | }, | 41 | }, |
42 | "bugs": { | 42 | "bugs": { |
43 | "url": "https://github.com/PanJiaChen/vue-element-admin/issues" | 43 | "url": "https://github.com/PanJiaChen/vue-element-admin/issues" |
44 | }, | 44 | }, |
45 | "dependencies": { | 45 | "dependencies": { |
46 | "ant-design-vue": "^1.5.5", | ||
46 | "axios": "0.18.1", | 47 | "axios": "0.18.1", |
47 | "clipboard": "2.0.4", | 48 | "clipboard": "2.0.4", |
48 | "codemirror": "5.45.0", | 49 | "codemirror": "5.45.0", |
49 | "driver.js": "0.9.5", | 50 | "driver.js": "0.9.5", |
50 | "dropzone": "5.5.1", | 51 | "dropzone": "5.5.1", |
51 | "echarts": "4.2.1", | 52 | "echarts": "4.2.1", |
52 | "element-ui": "2.13.0", | 53 | "element-ui": "2.13.0", |
53 | "file-saver": "2.0.1", | 54 | "file-saver": "2.0.1", |
54 | "fuse.js": "3.4.4", | 55 | "fuse.js": "3.4.4", |
55 | "js-cookie": "2.2.0", | 56 | "js-cookie": "2.2.0", |
56 | "jsonlint": "1.6.3", | 57 | "jsonlint": "1.6.3", |
57 | "jszip": "3.2.1", | 58 | "jszip": "3.2.1", |
59 | "less-loader": "^6.1.0", | ||
58 | "normalize.css": "7.0.0", | 60 | "normalize.css": "7.0.0", |
59 | "nprogress": "0.2.0", | 61 | "nprogress": "0.2.0", |
60 | "path-to-regexp": "2.4.0", | 62 | "path-to-regexp": "2.4.0", |
61 | "pinyin": "2.9.0", | 63 | "pinyin": "2.9.0", |
64 | "qs": "^6.9.4", | ||
62 | "screenfull": "4.2.0", | 65 | "screenfull": "4.2.0", |
63 | "showdown": "1.9.0", | 66 | "showdown": "1.9.0", |
64 | "sortablejs": "1.8.4", | 67 | "sortablejs": "1.8.4", |
65 | "tui-editor": "1.3.3", | 68 | "tui-editor": "1.3.3", |
69 | "vant": "^2.8.0", | ||
66 | "vue": "2.6.10", | 70 | "vue": "2.6.10", |
67 | "vue-count-to": "1.0.13", | 71 | "vue-count-to": "1.0.13", |
68 | "vue-i18n": "7.3.2", | 72 | "vue-i18n": "7.3.2", |
69 | "vue-router": "3.0.2", | 73 | "vue-router": "3.0.2", |
70 | "vue-splitpane": "1.0.4", | 74 | "vue-splitpane": "1.0.4", |
71 | "vuedraggable": "2.20.0", | 75 | "vuedraggable": "2.20.0", |
72 | "vuex": "3.1.0", | 76 | "vuex": "3.1.0", |
73 | "xlsx": "0.14.1" | 77 | "xlsx": "0.14.1" |
74 | }, | 78 | }, |
75 | "devDependencies": { | 79 | "devDependencies": { |
76 | "@babel/core": "7.0.0", | 80 | "@babel/core": "7.0.0", |
77 | "@babel/register": "7.0.0", | 81 | "@babel/register": "7.0.0", |
78 | "@vue/cli-plugin-babel": "3.5.3", | 82 | "@vue/cli-plugin-babel": "3.5.3", |
79 | "@vue/cli-plugin-eslint": "^3.9.1", | 83 | "@vue/cli-plugin-eslint": "^3.9.1", |
80 | "@vue/cli-plugin-unit-jest": "3.5.3", | 84 | "@vue/cli-plugin-unit-jest": "3.5.3", |
81 | "@vue/cli-service": "3.5.3", | 85 | "@vue/cli-service": "3.5.3", |
82 | "@vue/test-utils": "1.0.0-beta.29", | 86 | "@vue/test-utils": "1.0.0-beta.29", |
83 | "autoprefixer": "^9.5.1", | 87 | "autoprefixer": "^9.5.1", |
84 | "babel-core": "7.0.0-bridge.0", | 88 | "babel-core": "7.0.0-bridge.0", |
85 | "babel-eslint": "10.0.1", | 89 | "babel-eslint": "10.0.1", |
86 | "babel-jest": "23.6.0", | 90 | "babel-jest": "23.6.0", |
87 | "chalk": "2.4.2", | 91 | "chalk": "2.4.2", |
88 | "chokidar": "2.1.5", | 92 | "chokidar": "2.1.5", |
89 | "connect": "3.6.6", | 93 | "connect": "3.6.6", |
90 | "eslint": "5.15.3", | 94 | "eslint": "5.15.3", |
91 | "eslint-plugin-vue": "5.2.2", | 95 | "eslint-plugin-vue": "5.2.2", |
92 | "html-webpack-plugin": "3.2.0", | 96 | "html-webpack-plugin": "3.2.0", |
93 | "husky": "1.3.1", | 97 | "husky": "1.3.1", |
94 | "lint-staged": "8.1.5", | 98 | "lint-staged": "8.1.5", |
95 | "mockjs": "1.0.1-beta3", | 99 | "mockjs": "1.0.1-beta3", |
96 | "node-sass": "^4.9.0", | 100 | "node-sass": "^4.9.0", |
97 | "plop": "2.3.0", | 101 | "plop": "2.3.0", |
98 | "runjs": "^4.3.2", | 102 | "runjs": "^4.3.2", |
99 | "sass-loader": "^7.1.0", | 103 | "sass-loader": "^7.1.0", |
100 | "script-ext-html-webpack-plugin": "2.1.3", | 104 | "script-ext-html-webpack-plugin": "2.1.3", |
101 | "script-loader": "0.7.2", | 105 | "script-loader": "0.7.2", |
102 | "serve-static": "^1.13.2", | 106 | "serve-static": "^1.13.2", |
103 | "svg-sprite-loader": "4.1.3", | 107 | "svg-sprite-loader": "4.1.3", |
104 | "svgo": "1.2.0", | 108 | "svgo": "1.2.0", |
105 | "vue-template-compiler": "2.6.10" | 109 | "vue-template-compiler": "2.6.10" |
106 | }, | 110 | }, |
107 | "engines": { | 111 | "engines": { |
108 | "node": ">=8.9", | 112 | "node": ">=8.9", |
109 | "npm": ">= 3.0.0" | 113 | "npm": ">= 3.0.0" |
110 | }, | 114 | }, |
111 | "browserslist": [ | 115 | "browserslist": [ |
112 | "> 1%", | 116 | "> 1%", |
113 | "last 2 versions" | 117 | "last 2 versions" |
114 | ] | 118 | ] |
115 | } | 119 | } |
116 | 120 |
src/api/article.js
1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
2 | 2 | ||
3 | // export const getPersonInfo = data => { | ||
4 | // return service({ | ||
5 | // url: '/person_pay/getpersoninfo', | ||
6 | // method: 'post', | ||
7 | // data | ||
8 | // }) | ||
9 | // } | ||
10 | |||
3 | export function fetchList(query) { | 11 | export function fetchList(query) { |
4 | return request({ | 12 | return request({ |
5 | url: '/vue-element-admin/article/list', | 13 | url: '/yp/article/list', |
6 | method: 'get', | 14 | method: 'get', |
7 | params: query | 15 | params: query |
8 | }) | 16 | }) |
9 | } | 17 | } |
10 | 18 | ||
11 | export function fetchArticle(id) { | 19 | export function fetchArticle(id) { |
12 | return request({ | 20 | return request({ |
13 | url: '/vue-element-admin/article/detail', | 21 | url: '/yp/article/detail', |
14 | method: 'get', | 22 | method: 'get', |
15 | params: { id } | 23 | params: { |
24 | id | ||
25 | } | ||
16 | }) | 26 | }) |
17 | } | 27 | } |
18 | 28 | ||
19 | export function fetchPv(pv) { | 29 | export function fetchPv(pv) { |
20 | return request({ | 30 | return request({ |
21 | url: '/vue-element-admin/article/pv', | 31 | url: '/yp/article/pv', |
22 | method: 'get', | 32 | method: 'get', |
23 | params: { pv } | 33 | params: { |
34 | pv | ||
35 | } | ||
24 | }) | 36 | }) |
25 | } | 37 | } |
26 | 38 | ||
27 | export function createArticle(data) { | 39 | export function createArticle(data) { |
28 | return request({ | 40 | return request({ |
29 | url: '/vue-element-admin/article/create', | 41 | url: '/yp/article/create', |
30 | method: 'post', | 42 | method: 'post', |
31 | data | 43 | data |
32 | }) | 44 | }) |
33 | } | 45 | } |
34 | 46 | ||
35 | export function updateArticle(data) { | 47 | export function updateArticle(data) { |
36 | return request({ | 48 | return request({ |
37 | url: '/vue-element-admin/article/update', | 49 | url: '/yp/article/update', |
38 | method: 'post', | 50 | method: 'post', |
39 | data | 51 | data |
40 | }) | 52 | }) |
41 | } | 53 | } |
42 | 54 |
src/api/remote-search.js
1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
2 | 2 | ||
3 | export function searchUser(name) { | 3 | export function searchUser(name) { |
4 | return request({ | 4 | return request({ |
5 | url: '/vue-element-admin/search/user', | 5 | url: '/yp/search/user', |
6 | method: 'get', | 6 | method: 'get', |
7 | params: { name } | 7 | params: { name } |
8 | }) | 8 | }) |
9 | } | 9 | } |
10 | 10 | ||
11 | export function transactionList(query) { | 11 | export function transactionList(query) { |
12 | return request({ | 12 | return request({ |
13 | url: '/vue-element-admin/transaction/list', | 13 | url: '/yp/transaction/list', |
14 | method: 'get', | 14 | method: 'get', |
15 | params: query | 15 | params: query |
16 | }) | 16 | }) |
17 | } | 17 | } |
18 | 18 |
src/api/role.js
1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
2 | 2 | ||
3 | export function getRoutes() { | 3 | export function getRoutes() { |
4 | return request({ | 4 | return request({ |
5 | url: '/vue-element-admin/routes', | 5 | url: '/yp/routes', |
6 | method: 'get' | 6 | method: 'get' |
7 | }) | 7 | }) |
8 | } | 8 | } |
9 | 9 | ||
10 | export function getRoles() { | 10 | export function getRoles() { |
11 | return request({ | 11 | return request({ |
12 | url: '/vue-element-admin/roles', | 12 | url: '/yp/roles', |
13 | method: 'get' | 13 | method: 'get' |
14 | }) | 14 | }) |
15 | } | 15 | } |
16 | 16 | ||
17 | export function addRole(data) { | 17 | export function addRole(data) { |
18 | return request({ | 18 | return request({ |
19 | url: '/vue-element-admin/role', | 19 | url: '/yp/role', |
20 | method: 'post', | 20 | method: 'post', |
21 | data | 21 | data |
22 | }) | 22 | }) |
23 | } | 23 | } |
24 | 24 | ||
25 | export function updateRole(id, data) { | 25 | export function updateRole(id, data) { |
26 | return request({ | 26 | return request({ |
27 | url: `/vue-element-admin/role/${id}`, | 27 | url: `/vue-element-admin/role/${id}`, |
28 | method: 'put', | 28 | method: 'put', |
29 | data | 29 | data |
30 | }) | 30 | }) |
31 | } | 31 | } |
32 | 32 | ||
33 | export function deleteRole(id) { | 33 | export function deleteRole(id) { |
34 | return request({ | 34 | return request({ |
35 | url: `/vue-element-admin/role/${id}`, | 35 | url: `/vue-element-admin/role/${id}`, |
36 | method: 'delete' | 36 | method: 'delete' |
37 | }) | 37 | }) |
38 | } | 38 | } |
39 | 39 |
src/api/user.js
1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
2 | 2 | ||
3 | export function login(data) { | 3 | export function login(data) { |
4 | return request({ | 4 | return request({ |
5 | url: '/vue-element-admin/user/login', | 5 | url: '/yp/user/login', |
6 | method: 'post', | 6 | method: 'post', |
7 | data | 7 | data |
8 | }) | 8 | }) |
9 | } | 9 | } |
10 | 10 | ||
11 | export function getInfo(token) { | 11 | export function getInfo(token) { |
12 | return request({ | 12 | return request({ |
13 | url: '/vue-element-admin/user/info', | 13 | url: '/yp/user/info', |
14 | method: 'get', | 14 | method: 'get', |
15 | params: { token } | 15 | params: { token } |
16 | }) | 16 | }) |
17 | } | 17 | } |
18 | 18 | ||
19 | export function logout() { | 19 | export function logout() { |
20 | return request({ | 20 | return request({ |
21 | url: '/vue-element-admin/user/logout', | 21 | url: '/yp/user/logout', |
22 | method: 'post' | 22 | method: 'post' |
23 | }) | 23 | }) |
24 | } | 24 | } |
25 | |||
26 | export function fetchList(query) { | ||
27 | return request({ | ||
28 | url: '/yp/user/list', | ||
29 | method: 'get', | ||
30 | params: query | ||
31 | }) | ||
32 | } | ||
33 | |||
34 | export function createUser(query) { | ||
35 | return request({ | ||
36 | url: '/yp/user/create', | ||
37 | method: 'post', | ||
38 | params: query | ||
39 | }) | ||
40 | } | ||
41 | |||
42 | export function updateUser(query) { | ||
43 | return request({ | ||
44 | url: '/yp/user/update', | ||
45 | method: 'post', | ||
46 | params: query | ||
47 | }) | ||
48 | } | ||
49 | |||
50 | export function delUser(query) { | ||
51 | return request({ | ||
52 | url: '/yp/user/del', | ||
53 | method: 'post', | ||
54 | params: query | ||
55 | }) | ||
56 | } | ||
25 | 57 |
src/lang/en.js
1 | export default { | 1 | export default { |
2 | // 添加的新词条------start | ||
3 | prod: { | ||
4 | menu_title: 'products' | ||
5 | }, | ||
6 | order: { | ||
7 | |||
8 | }, | ||
9 | users: { | ||
10 | |||
11 | }, | ||
12 | site: { | ||
13 | |||
14 | }, | ||
15 | meta: { | ||
16 | |||
17 | }, | ||
18 | system: { | ||
19 | memu: '系统' | ||
20 | }, | ||
2 | route: { | 21 | route: { |
22 | users: 'users', | ||
23 | usersList: 'user list', | ||
24 | shopers: 'shoper suply chain', | ||
25 | prods: 'products', | ||
26 | orders: 'orders', | ||
27 | sites: 'sites', | ||
28 | metas: { | ||
29 | metas: 'meta', | ||
30 | list: 'tree' | ||
31 | }, | ||
32 | systems: { | ||
33 | systems: 'system', | ||
34 | sites: 'site seting', | ||
35 | money: 'money seting', | ||
36 | industry: 'industry seting', | ||
37 | template: 'template seting' | ||
38 | }, | ||
39 | // 添加的新词条------end | ||
3 | dashboard: 'Dashboard', | 40 | dashboard: 'Dashboard', |
4 | documentation: 'Documentation', | 41 | documentation: 'Documentation', |
5 | guide: 'Guide', | 42 | guide: 'Guide', |
6 | permission: 'Permission', | 43 | permission: 'Permission', |
7 | pagePermission: 'Page Permission', | 44 | pagePermission: 'Page Permission', |
8 | rolePermission: 'Role Permission', | 45 | rolePermission: 'Role Permission', |
9 | directivePermission: 'Directive Permission', | 46 | directivePermission: 'Directive Permission', |
10 | icons: 'Icons', | 47 | icons: 'Icons', |
11 | components: 'Components', | 48 | components: 'Components', |
12 | tinymce: 'Tinymce', | 49 | tinymce: 'Tinymce', |
13 | markdown: 'Markdown', | 50 | markdown: 'Markdown', |
14 | jsonEditor: 'JSON Editor', | 51 | jsonEditor: 'JSON Editor', |
15 | dndList: 'Dnd List', | 52 | dndList: 'Dnd List', |
16 | splitPane: 'SplitPane', | 53 | splitPane: 'SplitPane', |
17 | avatarUpload: 'Avatar Upload', | 54 | avatarUpload: 'Avatar Upload', |
18 | dropzone: 'Dropzone', | 55 | dropzone: 'Dropzone', |
19 | sticky: 'Sticky', | 56 | sticky: 'Sticky', |
20 | countTo: 'Count To', | 57 | countTo: 'Count To', |
21 | componentMixin: 'Mixin', | 58 | componentMixin: 'Mixin', |
22 | backToTop: 'Back To Top', | 59 | backToTop: 'Back To Top', |
23 | dragDialog: 'Drag Dialog', | 60 | dragDialog: 'Drag Dialog', |
24 | dragSelect: 'Drag Select', | 61 | dragSelect: 'Drag Select', |
25 | dragKanban: 'Drag Kanban', | 62 | dragKanban: 'Drag Kanban', |
26 | charts: 'Charts', | 63 | charts: 'Charts', |
27 | keyboardChart: 'Keyboard Chart', | 64 | keyboardChart: 'Keyboard Chart', |
28 | lineChart: 'Line Chart', | 65 | lineChart: 'Line Chart', |
29 | mixChart: 'Mix Chart', | 66 | mixChart: 'Mix Chart', |
30 | example: 'Example', | 67 | example: 'Example', |
31 | nested: 'Nested Routes', | 68 | nested: 'Nested Routes', |
32 | menu1: 'Menu 1', | 69 | menu1: 'Menu 1', |
33 | 'menu1-1': 'Menu 1-1', | 70 | 'menu1-1': 'Menu 1-1', |
34 | 'menu1-2': 'Menu 1-2', | 71 | 'menu1-2': 'Menu 1-2', |
35 | 'menu1-2-1': 'Menu 1-2-1', | 72 | 'menu1-2-1': 'Menu 1-2-1', |
36 | 'menu1-2-2': 'Menu 1-2-2', | 73 | 'menu1-2-2': 'Menu 1-2-2', |
37 | 'menu1-3': 'Menu 1-3', | 74 | 'menu1-3': 'Menu 1-3', |
38 | menu2: 'Menu 2', | 75 | menu2: 'Menu 2', |
39 | Table: 'Table', | 76 | Table: 'Table', |
40 | dynamicTable: 'Dynamic Table', | 77 | dynamicTable: 'Dynamic Table', |
41 | dragTable: 'Drag Table', | 78 | dragTable: 'Drag Table', |
42 | inlineEditTable: 'Inline Edit', | 79 | inlineEditTable: 'Inline Edit', |
43 | complexTable: 'Complex Table', | 80 | complexTable: 'Complex Table', |
44 | tab: 'Tab', | 81 | tab: 'Tab', |
45 | form: 'Form', | 82 | form: 'Form', |
46 | createArticle: 'Create Article', | 83 | createArticle: 'Create Article', |
47 | editArticle: 'Edit Article', | 84 | editArticle: 'Edit Article', |
48 | articleList: 'Article List', | 85 | articleList: 'Article List', |
49 | errorPages: 'Error Pages', | 86 | errorPages: 'Error Pages', |
50 | page401: '401', | 87 | page401: '401', |
51 | page404: '404', | 88 | page404: '404', |
52 | errorLog: 'Error Log', | 89 | errorLog: 'Error Log', |
53 | excel: 'Excel', | 90 | excel: 'Excel', |
54 | exportExcel: 'Export Excel', | 91 | exportExcel: 'Export Excel', |
55 | selectExcel: 'Export Selected', | 92 | selectExcel: 'Export Selected', |
56 | mergeHeader: 'Merge Header', | 93 | mergeHeader: 'Merge Header', |
57 | uploadExcel: 'Upload Excel', | 94 | uploadExcel: 'Upload Excel', |
58 | zip: 'Zip', | 95 | zip: 'Zip', |
59 | pdf: 'PDF', | 96 | pdf: 'PDF', |
60 | exportZip: 'Export Zip', | 97 | exportZip: 'Export Zip', |
61 | theme: 'Theme', | 98 | theme: 'Theme', |
62 | clipboardDemo: 'Clipboard', | 99 | clipboardDemo: 'Clipboard', |
63 | i18n: 'I18n', | 100 | i18n: 'I18n', |
64 | externalLink: 'External Link', | 101 | externalLink: 'External Link', |
65 | profile: 'Profile' | 102 | profile: 'Profile' |
66 | }, | 103 | }, |
67 | navbar: { | 104 | navbar: { |
68 | dashboard: 'Dashboard', | 105 | dashboard: 'Dashboard', |
69 | github: 'Github', | 106 | github: 'Github', |
70 | logOut: 'Log Out', | 107 | logOut: 'Log Out', |
71 | profile: 'Profile', | 108 | profile: 'Profile', |
72 | theme: 'Theme', | 109 | theme: 'Theme', |
73 | size: 'Global Size' | 110 | size: 'Global Size' |
74 | }, | 111 | }, |
75 | login: { | 112 | login: { |
76 | title: 'Login Form', | 113 | runner: 'officer Runner', |
114 | shoper: 'shop of Suply Chain', | ||
115 | assistant: 'worker in system', | ||
116 | signup: 'sign up', | ||
117 | forgetpassword: 'forget password', | ||
118 | rememberpassword: 'remember password', | ||
119 | |||
120 | // title: 'let\'s conquer the world', | ||
121 | title: 'LET\'S FUCK THE WORLD', | ||
77 | logIn: 'Login', | 122 | logIn: 'Login', |
78 | username: 'Username', | 123 | username: 'Username', |
79 | password: 'Password', | 124 | password: 'Password', |
80 | any: 'any', | 125 | any: 'any', |
81 | thirdparty: 'Or connect with', | 126 | thirdparty: 'Or connect with', |
82 | thirdpartyTips: 'Can not be simulated on local, so please combine you own business simulation! ! !' | 127 | thirdpartyTips: 'Can not be simulated on local, so please combine you own business simulation! ! !' |
83 | }, | 128 | }, |
84 | documentation: { | 129 | documentation: { |
85 | documentation: 'Documentation', | 130 | documentation: 'Documentation', |
86 | github: 'Github Repository' | 131 | github: 'Github Repository' |
87 | }, | 132 | }, |
88 | permission: { | 133 | permission: { |
89 | addRole: 'New Role', | 134 | addRole: 'New Role', |
90 | editPermission: 'Edit', | 135 | editPermission: 'Edit', |
91 | roles: 'Your roles', | 136 | roles: 'Your roles', |
92 | switchRoles: 'Switch roles', | 137 | switchRoles: 'Switch roles', |
93 | tips: 'In some cases, using v-permission will have no effect. For example: Element-UI el-tab or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.', | 138 | tips: 'In some cases, using v-permission will have no effect. For example: Element-UI el-tab or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.', |
94 | delete: 'Delete', | 139 | delete: 'Delete', |
95 | confirm: 'Confirm', | 140 | confirm: 'Confirm', |
96 | cancel: 'Cancel' | 141 | cancel: 'Cancel' |
97 | }, | 142 | }, |
98 | guide: { | 143 | guide: { |
99 | description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', | 144 | description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', |
100 | button: 'Show Guide' | 145 | button: 'Show Guide' |
101 | }, | 146 | }, |
102 | components: { | 147 | components: { |
103 | documentation: 'Documentation', | 148 | documentation: 'Documentation', |
104 | tinymceTips: 'Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.', | 149 | tinymceTips: 'Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.', |
105 | dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.', | 150 | dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.', |
106 | stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.', | 151 | stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.', |
107 | backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner', | 152 | backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner', |
108 | backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally', | 153 | backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally', |
109 | imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.' | 154 | imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.' |
110 | }, | 155 | }, |
111 | table: { | 156 | table: { |
112 | dynamicTips1: 'Fixed header, sorted by header order', | 157 | dynamicTips1: 'Fixed header, sorted by header order', |
113 | dynamicTips2: 'Not fixed header, sorted by click order', | 158 | dynamicTips2: 'Not fixed header, sorted by click order', |
114 | dragTips1: 'The default order', | 159 | dragTips1: 'The default order', |
115 | dragTips2: 'The after dragging order', | 160 | dragTips2: 'The after dragging order', |
116 | title: 'Title', | 161 | title: 'Title', |
117 | importance: 'Imp', | 162 | importance: 'Imp', |
118 | type: 'Type', | 163 | type: 'Type', |
119 | remark: 'Remark', | 164 | remark: 'Remark', |
120 | search: 'Search', | 165 | search: 'Search', |
121 | add: 'Add', | 166 | add: 'Add', |
122 | export: 'Export', | 167 | export: 'Export', |
123 | reviewer: 'reviewer', | 168 | reviewer: 'reviewer', |
124 | id: 'ID', | 169 | id: 'ID', |
125 | date: 'Date', | 170 | date: 'Date', |
126 | author: 'Author', | 171 | author: 'Author', |
127 | readings: 'Readings', | 172 | readings: 'Readings', |
128 | status: 'Status', | 173 | status: 'Status', |
129 | actions: 'Actions', | 174 | actions: 'Actions', |
130 | edit: 'Edit', | 175 | edit: 'Edit', |
131 | publish: 'Publish', | 176 | publish: 'Publish', |
132 | draft: 'Draft', | 177 | draft: 'Draft', |
133 | delete: 'Delete', | 178 | delete: 'Delete', |
134 | cancel: 'Cancel', | 179 | cancel: 'Cancel', |
135 | confirm: 'Confirm' | 180 | confirm: 'Confirm' |
136 | }, | 181 | }, |
137 | example: { | 182 | example: { |
138 | warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details' | 183 | warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details' |
139 | }, | 184 | }, |
140 | errorLog: { | 185 | errorLog: { |
141 | tips: 'Please click the bug icon in the upper right corner', | 186 | tips: 'Please click the bug icon in the upper right corner', |
142 | description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.', | 187 | description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.', |
143 | documentation: 'Document introduction' | 188 | documentation: 'Document introduction' |
144 | }, | 189 | }, |
145 | excel: { | 190 | excel: { |
146 | export: 'Export', | 191 | export: 'Export', |
147 | selectedExport: 'Export Selected Items', | 192 | selectedExport: 'Export Selected Items', |
148 | placeholder: 'Please enter the file name (default excel-list)' | 193 | placeholder: 'Please enter the file name (default excel-list)' |
149 | }, | 194 | }, |
150 | zip: { | 195 | zip: { |
151 | export: 'Export', | 196 | export: 'Export', |
152 | placeholder: 'Please enter the file name (default file)' | 197 | placeholder: 'Please enter the file name (default file)' |
153 | }, | 198 | }, |
154 | pdf: { | 199 | pdf: { |
155 | tips: 'Here we use window.print() to implement the feature of downloading PDF.' | 200 | tips: 'Here we use window.print() to implement the feature of downloading PDF.' |
156 | }, | 201 | }, |
157 | theme: { | 202 | theme: { |
158 | change: 'Change Theme', | 203 | change: 'Change Theme', |
159 | documentation: 'Theme documentation', | 204 | documentation: 'Theme documentation', |
160 | tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.' | 205 | tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.' |
161 | }, | 206 | }, |
162 | tagsView: { | 207 | tagsView: { |
163 | refresh: 'Refresh', | 208 | refresh: 'Refresh', |
164 | close: 'Close', | 209 | close: 'Close', |
165 | closeOthers: 'Close Others', | 210 | closeOthers: 'Close Others', |
166 | closeAll: 'Close All' | 211 | closeAll: 'Close All' |
167 | }, | 212 | }, |
168 | settings: { | 213 | settings: { |
169 | title: 'Page style setting', | 214 | title: 'Page style setting', |
170 | theme: 'Theme Color', | 215 | theme: 'Theme Color', |
171 | tagsView: 'Open Tags-View', | 216 | tagsView: 'Open Tags-View', |
172 | fixedHeader: 'Fixed Header', | 217 | fixedHeader: 'Fixed Header', |
173 | sidebarLogo: 'Sidebar Logo' | 218 | sidebarLogo: 'Sidebar Logo' |
174 | } | 219 | } |
175 | } | 220 | } |
176 | 221 |
src/lang/es.js
1 | export default { | 1 | export default { |
2 | // 添加的新词条------start | ||
3 | prod: { | ||
4 | menu_title: 'products' | ||
5 | }, | ||
6 | order: { | ||
7 | |||
8 | }, | ||
9 | users: { | ||
10 | |||
11 | }, | ||
12 | site: { | ||
13 | |||
14 | }, | ||
15 | meta: { | ||
16 | |||
17 | }, | ||
18 | system: { | ||
19 | memu: '系统' | ||
20 | }, | ||
2 | route: { | 21 | route: { |
22 | users: 'users', | ||
23 | usersList: 'user list', | ||
24 | shopers: 'shoper suply chain', | ||
25 | prods: 'products', | ||
26 | orders: 'orders', | ||
27 | sites: 'sites', | ||
28 | metas: { | ||
29 | metas: '元', | ||
30 | list: '树' | ||
31 | }, | ||
32 | systems: { | ||
33 | systems: '系统设置', | ||
34 | sites: '站点设置', | ||
35 | money: '货币设置', | ||
36 | industry: '行业设置', | ||
37 | template: '模版设置' | ||
38 | }, | ||
39 | // 添加的新词条------end | ||
3 | dashboard: 'Panel de control', | 40 | dashboard: 'Panel de control', |
4 | documentation: 'Documentación', | 41 | documentation: 'Documentación', |
5 | guide: 'Guía', | 42 | guide: 'Guía', |
6 | permission: 'Permisos', | 43 | permission: 'Permisos', |
7 | rolePermission: 'Permisos de rol', | 44 | rolePermission: 'Permisos de rol', |
8 | pagePermission: 'Permisos de la página', | 45 | pagePermission: 'Permisos de la página', |
9 | directivePermission: 'Permisos de la directiva', | 46 | directivePermission: 'Permisos de la directiva', |
10 | icons: 'Iconos', | 47 | icons: 'Iconos', |
11 | components: 'Componentes', | 48 | components: 'Componentes', |
12 | tinymce: 'Tinymce', | 49 | tinymce: 'Tinymce', |
13 | markdown: 'Markdown', | 50 | markdown: 'Markdown', |
14 | jsonEditor: 'Editor JSON', | 51 | jsonEditor: 'Editor JSON', |
15 | dndList: 'Lista Dnd', | 52 | dndList: 'Lista Dnd', |
16 | splitPane: 'Panel dividido', | 53 | splitPane: 'Panel dividido', |
17 | avatarUpload: 'Subir avatar', | 54 | avatarUpload: 'Subir avatar', |
18 | dropzone: 'Subir ficheros', | 55 | dropzone: 'Subir ficheros', |
19 | sticky: 'Sticky', | 56 | sticky: 'Sticky', |
20 | countTo: 'CountTo', | 57 | countTo: 'CountTo', |
21 | componentMixin: 'Mixin', | 58 | componentMixin: 'Mixin', |
22 | backToTop: 'Ir arriba', | 59 | backToTop: 'Ir arriba', |
23 | dragDialog: 'Drag Dialog', | 60 | dragDialog: 'Drag Dialog', |
24 | dragSelect: 'Drag Select', | 61 | dragSelect: 'Drag Select', |
25 | dragKanban: 'Drag Kanban', | 62 | dragKanban: 'Drag Kanban', |
26 | charts: 'Gráficos', | 63 | charts: 'Gráficos', |
27 | keyboardChart: 'Keyboard Chart', | 64 | keyboardChart: 'Keyboard Chart', |
28 | lineChart: 'Gráfico de líneas', | 65 | lineChart: 'Gráfico de líneas', |
29 | mixChart: 'Mix Chart', | 66 | mixChart: 'Mix Chart', |
30 | example: 'Ejemplo', | 67 | example: 'Ejemplo', |
31 | nested: 'Rutas anidadass', | 68 | nested: 'Rutas anidadass', |
32 | menu1: 'Menu 1', | 69 | menu1: 'Menu 1', |
33 | 'menu1-1': 'Menu 1-1', | 70 | 'menu1-1': 'Menu 1-1', |
34 | 'menu1-2': 'Menu 1-2', | 71 | 'menu1-2': 'Menu 1-2', |
35 | 'menu1-2-1': 'Menu 1-2-1', | 72 | 'menu1-2-1': 'Menu 1-2-1', |
36 | 'menu1-2-2': 'Menu 1-2-2', | 73 | 'menu1-2-2': 'Menu 1-2-2', |
37 | 'menu1-3': 'Menu 1-3', | 74 | 'menu1-3': 'Menu 1-3', |
38 | menu2: 'Menu 2', | 75 | menu2: 'Menu 2', |
39 | Table: 'Tabla', | 76 | Table: 'Tabla', |
40 | dynamicTable: 'Tabla dinámica', | 77 | dynamicTable: 'Tabla dinámica', |
41 | dragTable: 'Arrastrar tabla', | 78 | dragTable: 'Arrastrar tabla', |
42 | inlineEditTable: 'Editor', | 79 | inlineEditTable: 'Editor', |
43 | complexTable: 'Complex Table', | 80 | complexTable: 'Complex Table', |
44 | tab: 'Pestaña', | 81 | tab: 'Pestaña', |
45 | form: 'Formulario', | 82 | form: 'Formulario', |
46 | createArticle: 'Crear artículo', | 83 | createArticle: 'Crear artículo', |
47 | editArticle: 'Editar artículo', | 84 | editArticle: 'Editar artículo', |
48 | articleList: 'Listado de artículos', | 85 | articleList: 'Listado de artículos', |
49 | errorPages: 'Páginas de error', | 86 | errorPages: 'Páginas de error', |
50 | page401: '401', | 87 | page401: '401', |
51 | page404: '404', | 88 | page404: '404', |
52 | errorLog: 'Registro de errores', | 89 | errorLog: 'Registro de errores', |
53 | excel: 'Excel', | 90 | excel: 'Excel', |
54 | exportExcel: 'Exportar a Excel', | 91 | exportExcel: 'Exportar a Excel', |
55 | selectExcel: 'Export seleccionado', | 92 | selectExcel: 'Export seleccionado', |
56 | mergeHeader: 'Merge Header', | 93 | mergeHeader: 'Merge Header', |
57 | uploadExcel: 'Subir Excel', | 94 | uploadExcel: 'Subir Excel', |
58 | zip: 'Zip', | 95 | zip: 'Zip', |
59 | pdf: 'PDF', | 96 | pdf: 'PDF', |
60 | exportZip: 'Exportar a Zip', | 97 | exportZip: 'Exportar a Zip', |
61 | theme: 'Tema', | 98 | theme: 'Tema', |
62 | clipboardDemo: 'Clipboard', | 99 | clipboardDemo: 'Clipboard', |
63 | i18n: 'I18n', | 100 | i18n: 'I18n', |
64 | externalLink: 'Enlace externo', | 101 | externalLink: 'Enlace externo', |
65 | profile: 'Profile' | 102 | profile: 'Profile' |
66 | }, | 103 | }, |
67 | navbar: { | 104 | navbar: { |
68 | logOut: 'Salir', | 105 | logOut: 'Salir', |
69 | dashboard: 'Panel de control', | 106 | dashboard: 'Panel de control', |
70 | github: 'Github', | 107 | github: 'Github', |
71 | theme: 'Tema', | 108 | theme: 'Tema', |
72 | size: 'Tamaño global', | 109 | size: 'Tamaño global', |
73 | profile: 'Profile' | 110 | profile: 'Profile' |
74 | }, | 111 | }, |
75 | login: { | 112 | login: { |
113 | runner: 'officer Runner', | ||
114 | shoper: 'shop of Suply Chain', | ||
115 | assistant: 'worker in system', | ||
116 | signup: 'sign up', | ||
117 | forgetpassword: 'forget password', | ||
118 | rememberpassword: 'remember password', | ||
119 | |||
76 | title: 'Formulario de acceso', | 120 | title: 'Formulario de acceso', |
77 | logIn: 'Acceso', | 121 | logIn: 'Acceso', |
78 | username: 'Usuario', | 122 | username: 'Usuario', |
79 | password: 'Contraseña', | 123 | password: 'Contraseña', |
80 | any: 'nada', | 124 | any: 'nada', |
81 | thirdparty: 'Conectar con', | 125 | thirdparty: 'Conectar con', |
82 | thirdpartyTips: 'No se puede simular en local, así que combine su propia simulación de negocios. ! !' | 126 | thirdpartyTips: 'No se puede simular en local, así que combine su propia simulación de negocios. ! !' |
83 | }, | 127 | }, |
84 | documentation: { | 128 | documentation: { |
85 | documentation: 'Documentación', | 129 | documentation: 'Documentación', |
86 | github: 'Repositorio Github' | 130 | github: 'Repositorio Github' |
87 | }, | 131 | }, |
88 | permission: { | 132 | permission: { |
89 | addRole: 'Nuevo rol', | 133 | addRole: 'Nuevo rol', |
90 | editPermission: 'Permiso de edición', | 134 | editPermission: 'Permiso de edición', |
91 | roles: 'Tus permisos', | 135 | roles: 'Tus permisos', |
92 | switchRoles: 'Cambiar permisos', | 136 | switchRoles: 'Cambiar permisos', |
93 | tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.', | 137 | tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.', |
94 | delete: 'Borrar', | 138 | delete: 'Borrar', |
95 | confirm: 'Confirmar', | 139 | confirm: 'Confirmar', |
96 | cancel: 'Cancelar' | 140 | cancel: 'Cancelar' |
97 | }, | 141 | }, |
98 | guide: { | 142 | guide: { |
99 | description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', | 143 | description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', |
100 | button: 'Ver guía' | 144 | button: 'Ver guía' |
101 | }, | 145 | }, |
102 | components: { | 146 | components: { |
103 | documentation: 'Documentación', | 147 | documentation: 'Documentación', |
104 | tinymceTips: 'Rich text editor is a core part of management system, but at the same time is a place with lots of problems. In the process of selecting rich texts, I also walked a lot of detours. The common rich text editors in the market are basically used, and the finally chose Tinymce. See documentation for more detailed rich text editor comparisons and introductions.', | 148 | tinymceTips: 'Rich text editor is a core part of management system, but at the same time is a place with lots of problems. In the process of selecting rich texts, I also walked a lot of detours. The common rich text editors in the market are basically used, and the finally chose Tinymce. See documentation for more detailed rich text editor comparisons and introductions.', |
105 | dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.', | 149 | dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.', |
106 | stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.', | 150 | stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.', |
107 | backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner', | 151 | backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner', |
108 | backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally', | 152 | backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally', |
109 | imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.' | 153 | imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.' |
110 | }, | 154 | }, |
111 | table: { | 155 | table: { |
112 | dynamicTips1: 'Fixed header, sorted by header order', | 156 | dynamicTips1: 'Fixed header, sorted by header order', |
113 | dynamicTips2: 'Not fixed header, sorted by click order', | 157 | dynamicTips2: 'Not fixed header, sorted by click order', |
114 | dragTips1: 'Orden por defecto', | 158 | dragTips1: 'Orden por defecto', |
115 | dragTips2: 'The after dragging order', | 159 | dragTips2: 'The after dragging order', |
116 | title: 'Título', | 160 | title: 'Título', |
117 | importance: 'Importancia', | 161 | importance: 'Importancia', |
118 | type: 'Tipo', | 162 | type: 'Tipo', |
119 | remark: 'Remark', | 163 | remark: 'Remark', |
120 | search: 'Buscar', | 164 | search: 'Buscar', |
121 | add: 'Añadir', | 165 | add: 'Añadir', |
122 | export: 'Exportar', | 166 | export: 'Exportar', |
123 | reviewer: 'reviewer', | 167 | reviewer: 'reviewer', |
124 | id: 'ID', | 168 | id: 'ID', |
125 | date: 'Fecha', | 169 | date: 'Fecha', |
126 | author: 'Autor', | 170 | author: 'Autor', |
127 | readings: 'Lector', | 171 | readings: 'Lector', |
128 | status: 'Estado', | 172 | status: 'Estado', |
129 | actions: 'Acciones', | 173 | actions: 'Acciones', |
130 | edit: 'Editar', | 174 | edit: 'Editar', |
131 | publish: 'Publicar', | 175 | publish: 'Publicar', |
132 | draft: 'Draft', | 176 | draft: 'Draft', |
133 | delete: 'Eliminar', | 177 | delete: 'Eliminar', |
134 | cancel: 'Cancelar', | 178 | cancel: 'Cancelar', |
135 | confirm: 'Confirmar' | 179 | confirm: 'Confirmar' |
136 | }, | 180 | }, |
137 | example: { | 181 | example: { |
138 | warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details' | 182 | warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details' |
139 | }, | 183 | }, |
140 | errorLog: { | 184 | errorLog: { |
141 | tips: 'Please click the bug icon in the upper right corner', | 185 | tips: 'Please click the bug icon in the upper right corner', |
142 | description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.', | 186 | description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.', |
143 | documentation: 'Documento de introducción' | 187 | documentation: 'Documento de introducción' |
144 | }, | 188 | }, |
145 | excel: { | 189 | excel: { |
146 | export: 'Exportar', | 190 | export: 'Exportar', |
147 | selectedExport: 'Exportar seleccionados', | 191 | selectedExport: 'Exportar seleccionados', |
148 | placeholder: 'Por favor escribe un nombre de fichero' | 192 | placeholder: 'Por favor escribe un nombre de fichero' |
149 | }, | 193 | }, |
150 | zip: { | 194 | zip: { |
151 | export: 'Exportar', | 195 | export: 'Exportar', |
152 | placeholder: 'Por favor escribe un nombre de fichero' | 196 | placeholder: 'Por favor escribe un nombre de fichero' |
153 | }, | 197 | }, |
154 | pdf: { | 198 | pdf: { |
155 | tips: 'Here we use window.print() to implement the feature of downloading pdf.' | 199 | tips: 'Here we use window.print() to implement the feature of downloading pdf.' |
156 | }, | 200 | }, |
157 | theme: { | 201 | theme: { |
158 | change: 'Cambiar tema', | 202 | change: 'Cambiar tema', |
159 | documentation: 'Documentación del tema', | 203 | documentation: 'Documentación del tema', |
160 | tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.' | 204 | tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.' |
161 | }, | 205 | }, |
162 | tagsView: { | 206 | tagsView: { |
163 | refresh: 'Actualizar', | 207 | refresh: 'Actualizar', |
164 | close: 'Cerrar', | 208 | close: 'Cerrar', |
165 | closeOthers: 'Cerrar otros', | 209 | closeOthers: 'Cerrar otros', |
166 | closeAll: 'Cerrar todos' | 210 | closeAll: 'Cerrar todos' |
167 | }, | 211 | }, |
168 | settings: { | 212 | settings: { |
169 | title: 'Page style setting', | 213 | title: 'Page style setting', |
170 | theme: 'Theme Color', | 214 | theme: 'Theme Color', |
171 | tagsView: 'Open Tags-View', | 215 | tagsView: 'Open Tags-View', |
172 | fixedHeader: 'Fixed Header', | 216 | fixedHeader: 'Fixed Header', |
173 | sidebarLogo: 'Sidebar Logo' | 217 | sidebarLogo: 'Sidebar Logo' |
174 | } | 218 | } |
175 | } | 219 | } |
176 | 220 |
src/lang/ja.js
1 | export default { | 1 | export default { |
2 | // 添加的新词条------start | ||
3 | prod: { | ||
4 | menu_title: 'products' | ||
5 | }, | ||
6 | order: { | ||
7 | |||
8 | }, | ||
9 | users: { | ||
10 | |||
11 | }, | ||
12 | site: { | ||
13 | |||
14 | }, | ||
15 | meta: { | ||
16 | |||
17 | }, | ||
18 | system: { | ||
19 | memu: '系统' | ||
20 | }, | ||
2 | route: { | 21 | route: { |
22 | users: 'users', | ||
23 | usersList: 'user list', | ||
24 | shopers: 'shoper suply chain', | ||
25 | prods: 'products', | ||
26 | orders: 'orders', | ||
27 | sites: 'sites', | ||
28 | metas: { | ||
29 | metas: '元', | ||
30 | list: '树' | ||
31 | }, | ||
32 | systems: { | ||
33 | systems: '系统设置', | ||
34 | sites: '站点设置', | ||
35 | money: '货币设置', | ||
36 | industry: '行业设置', | ||
37 | template: '模版设置' | ||
38 | }, | ||
39 | // 添加的新词条------end | ||
3 | dashboard: 'トップ', | 40 | dashboard: 'トップ', |
4 | documentation: 'ドキュメント', | 41 | documentation: 'ドキュメント', |
5 | guide: 'ガイド', | 42 | guide: 'ガイド', |
6 | permission: '権限', | 43 | permission: '権限', |
7 | rolePermission: '権限ロール', | 44 | rolePermission: '権限ロール', |
8 | pagePermission: 'ページ権限', | 45 | pagePermission: 'ページ権限', |
9 | directivePermission: 'ディレクティブ権限', | 46 | directivePermission: 'ディレクティブ権限', |
10 | icons: 'アイコン', | 47 | icons: 'アイコン', |
11 | components: 'コンポーネント', | 48 | components: 'コンポーネント', |
12 | tinymce: 'TinyMCE', | 49 | tinymce: 'TinyMCE', |
13 | markdown: 'Markdown', | 50 | markdown: 'Markdown', |
14 | jsonEditor: 'JSON Editor', | 51 | jsonEditor: 'JSON Editor', |
15 | dndList: 'Drag-And-Drop', | 52 | dndList: 'Drag-And-Drop', |
16 | splitPane: 'パネル', | 53 | splitPane: 'パネル', |
17 | avatarUpload: 'アバターアップロード', | 54 | avatarUpload: 'アバターアップロード', |
18 | dropzone: 'Dropzone', | 55 | dropzone: 'Dropzone', |
19 | sticky: 'Sticky', | 56 | sticky: 'Sticky', |
20 | countTo: 'Count To', | 57 | countTo: 'Count To', |
21 | componentMixin: 'コンポーネントMixin', | 58 | componentMixin: 'コンポーネントMixin', |
22 | backToTop: 'BackToTop', | 59 | backToTop: 'BackToTop', |
23 | dragDialog: 'Drag Dialog', | 60 | dragDialog: 'Drag Dialog', |
24 | dragSelect: 'Drag Select', | 61 | dragSelect: 'Drag Select', |
25 | dragKanban: 'Drag 看板', | 62 | dragKanban: 'Drag 看板', |
26 | charts: 'チャート', | 63 | charts: 'チャート', |
27 | keyboardChart: 'Keyboardチャート', | 64 | keyboardChart: 'Keyboardチャート', |
28 | lineChart: 'Lineチャート', | 65 | lineChart: 'Lineチャート', |
29 | mixChart: 'Mixチャート', | 66 | mixChart: 'Mixチャート', |
30 | example: 'Example', | 67 | example: 'Example', |
31 | nested: 'Nested Routes', | 68 | nested: 'Nested Routes', |
32 | menu1: 'メニュー1', | 69 | menu1: 'メニュー1', |
33 | 'menu1-1': 'メニュー 1-1', | 70 | 'menu1-1': 'メニュー 1-1', |
34 | 'menu1-2': 'メニュー 1-2', | 71 | 'menu1-2': 'メニュー 1-2', |
35 | 'menu1-2-1': 'メニュー 1-2-1', | 72 | 'menu1-2-1': 'メニュー 1-2-1', |
36 | 'menu1-2-2': 'メニュー 1-2-2', | 73 | 'menu1-2-2': 'メニュー 1-2-2', |
37 | 'menu1-3': 'メニュー 1-3', | 74 | 'menu1-3': 'メニュー 1-3', |
38 | menu2: 'メニュー 2', | 75 | menu2: 'メニュー 2', |
39 | Table: 'Table', | 76 | Table: 'Table', |
40 | dynamicTable: '可変 Table', | 77 | dynamicTable: '可変 Table', |
41 | dragTable: 'Drag Table', | 78 | dragTable: 'Drag Table', |
42 | inlineEditTable: 'Inline Edit Table', | 79 | inlineEditTable: 'Inline Edit Table', |
43 | complexTable: 'Complex Table', | 80 | complexTable: 'Complex Table', |
44 | tab: 'Tab', | 81 | tab: 'Tab', |
45 | form: 'フォーム', | 82 | form: 'フォーム', |
46 | createArticle: '投稿作成', | 83 | createArticle: '投稿作成', |
47 | editArticle: '投稿編集', | 84 | editArticle: '投稿編集', |
48 | articleList: '投稿リスト', | 85 | articleList: '投稿リスト', |
49 | errorPages: 'エラーページ', | 86 | errorPages: 'エラーページ', |
50 | page401: '401', | 87 | page401: '401', |
51 | page404: '404', | 88 | page404: '404', |
52 | errorLog: 'エラーログ', | 89 | errorLog: 'エラーログ', |
53 | excel: 'Excel', | 90 | excel: 'Excel', |
54 | exportExcel: '一括エクスポート', | 91 | exportExcel: '一括エクスポート', |
55 | selectExcel: '複数選択エクスポート', | 92 | selectExcel: '複数選択エクスポート', |
56 | mergeHeader: 'ヘッダーマージ', | 93 | mergeHeader: 'ヘッダーマージ', |
57 | uploadExcel: 'アップロード', | 94 | uploadExcel: 'アップロード', |
58 | zip: 'Zip', | 95 | zip: 'Zip', |
59 | pdf: 'PDF', | 96 | pdf: 'PDF', |
60 | exportZip: 'Export Zip', | 97 | exportZip: 'Export Zip', |
61 | theme: 'テーマ変更', | 98 | theme: 'テーマ変更', |
62 | clipboardDemo: 'Clipboard', | 99 | clipboardDemo: 'Clipboard', |
63 | i18n: '多言語', | 100 | i18n: '多言語', |
64 | externalLink: '外部リンク', | 101 | externalLink: '外部リンク', |
65 | profile: 'プロフィール' | 102 | profile: 'プロフィール' |
66 | }, | 103 | }, |
67 | navbar: { | 104 | navbar: { |
68 | dashboard: 'トップ', | 105 | dashboard: 'トップ', |
69 | github: 'GitHub', | 106 | github: 'GitHub', |
70 | logOut: 'ログアウト', | 107 | logOut: 'ログアウト', |
71 | profile: 'プロフィール', | 108 | profile: 'プロフィール', |
72 | theme: 'テーマ変更', | 109 | theme: 'テーマ変更', |
73 | size: '画面サイズ' | 110 | size: '画面サイズ' |
74 | }, | 111 | }, |
75 | login: { | 112 | login: { |
113 | runner: 'officer Runner', | ||
114 | shoper: 'shop of Suply Chain', | ||
115 | assistant: 'worker in system', | ||
116 | signup: 'sign up', | ||
117 | forgetpassword: 'forget password', | ||
118 | rememberpassword: 'remember password', | ||
119 | |||
76 | title: 'ユーザログイン', | 120 | title: 'ユーザログイン', |
77 | logIn: 'ログイン', | 121 | logIn: 'ログイン', |
78 | username: 'ユーザ名', | 122 | username: 'ユーザ名', |
79 | password: 'パスワード', | 123 | password: 'パスワード', |
80 | any: 'password', | 124 | any: 'password', |
81 | thirdparty: '外部IDでログイン', | 125 | thirdparty: '外部IDでログイン', |
82 | thirdpartyTips: 'ローカル環境ではログインできません。実装が必要です。' | 126 | thirdpartyTips: 'ローカル環境ではログインできません。実装が必要です。' |
83 | }, | 127 | }, |
84 | documentation: { | 128 | documentation: { |
85 | documentation: 'ドキュメント', | 129 | documentation: 'ドキュメント', |
86 | github: 'Github Link' | 130 | github: 'Github Link' |
87 | }, | 131 | }, |
88 | permission: { | 132 | permission: { |
89 | addRole: 'ロール追加', | 133 | addRole: 'ロール追加', |
90 | editPermission: 'ロール変更', | 134 | editPermission: 'ロール変更', |
91 | roles: 'ロール', | 135 | roles: 'ロール', |
92 | switchRoles: 'ロール切替', | 136 | switchRoles: 'ロール切替', |
93 | tips: 'v-permissionは使えない時があります。例えば: Element-UI の el-tab、 el-table-column 及び他の dom。v-ifを使う必要があります。', | 137 | tips: 'v-permissionは使えない時があります。例えば: Element-UI の el-tab、 el-table-column 及び他の dom。v-ifを使う必要があります。', |
94 | delete: '削除', | 138 | delete: '削除', |
95 | confirm: '確認', | 139 | confirm: '確認', |
96 | cancel: 'キャンセル' | 140 | cancel: 'キャンセル' |
97 | }, | 141 | }, |
98 | guide: { | 142 | guide: { |
99 | description: 'ガイドは各機能の説明です。', | 143 | description: 'ガイドは各機能の説明です。', |
100 | button: 'ガイドを見る' | 144 | button: 'ガイドを見る' |
101 | }, | 145 | }, |
102 | components: { | 146 | components: { |
103 | documentation: 'ドキュメント', | 147 | documentation: 'ドキュメント', |
104 | tinymceTips: 'tinymceは管理画面に重要な機能ですが、その同時に落とし穴がありあす。tinymceを使う道のりが大変でした。Tinymceを使う時に各自のプロジェクト状況で判断が必要です。ドキュメントはこちら', | 148 | tinymceTips: 'tinymceは管理画面に重要な機能ですが、その同時に落とし穴がありあす。tinymceを使う道のりが大変でした。Tinymceを使う時に各自のプロジェクト状況で判断が必要です。ドキュメントはこちら', |
105 | dropzoneTips: 'Third partyのパッケージを使わず、独自の実装しています。詳細は @/components/Dropzone', | 149 | dropzoneTips: 'Third partyのパッケージを使わず、独自の実装しています。詳細は @/components/Dropzone', |
106 | stickyTips: 'ページの指定位置へスクロールした場合、表示されます。', | 150 | stickyTips: 'ページの指定位置へスクロールした場合、表示されます。', |
107 | backToTopTips1: 'トップへスクロールが表示されます。', | 151 | backToTopTips1: 'トップへスクロールが表示されます。', |
108 | backToTopTips2: 'ボタンのスタイルはカスタマイズできます。例えば、show/hide、height、position。 またはElementのel-tooltipを使って、ツールチップを実装できます。', | 152 | backToTopTips2: 'ボタンのスタイルはカスタマイズできます。例えば、show/hide、height、position。 またはElementのel-tooltipを使って、ツールチップを実装できます。', |
109 | imageUploadTips: 'mockjsは使えないため、カスタマイズしています。公式の最新バージョンを使ってください。' | 153 | imageUploadTips: 'mockjsは使えないため、カスタマイズしています。公式の最新バージョンを使ってください。' |
110 | }, | 154 | }, |
111 | table: { | 155 | table: { |
112 | dynamicTips1: '先頭は固定、最後に追加', | 156 | dynamicTips1: '先頭は固定、最後に追加', |
113 | dynamicTips2: '戦後に追加せず、指定列に追加', | 157 | dynamicTips2: '戦後に追加せず、指定列に追加', |
114 | dragTips1: 'デフォルト順番', | 158 | dragTips1: 'デフォルト順番', |
115 | dragTips2: 'Drag後の順番', | 159 | dragTips2: 'Drag後の順番', |
116 | title: 'タイトル', | 160 | title: 'タイトル', |
117 | importance: '重要', | 161 | importance: '重要', |
118 | type: 'タイプ', | 162 | type: 'タイプ', |
119 | remark: '評価', | 163 | remark: '評価', |
120 | search: '検索', | 164 | search: '検索', |
121 | add: '追加', | 165 | add: '追加', |
122 | export: 'エクスポート', | 166 | export: 'エクスポート', |
123 | reviewer: 'レビュアー', | 167 | reviewer: 'レビュアー', |
124 | id: '番号', | 168 | id: '番号', |
125 | date: '日時', | 169 | date: '日時', |
126 | author: '作成者', | 170 | author: '作成者', |
127 | readings: '閲覧数', | 171 | readings: '閲覧数', |
128 | status: 'ステータス', | 172 | status: 'ステータス', |
129 | actions: '操作', | 173 | actions: '操作', |
130 | edit: '編集', | 174 | edit: '編集', |
131 | publish: '公開', | 175 | publish: '公開', |
132 | draft: '下書き', | 176 | draft: '下書き', |
133 | delete: 'キャンセル', | 177 | delete: 'キャンセル', |
134 | cancel: 'キャンセル', | 178 | cancel: 'キャンセル', |
135 | confirm: '確認' | 179 | confirm: '確認' |
136 | }, | 180 | }, |
137 | example: { | 181 | example: { |
138 | warning: '新規作成と編集画面は keep-alive を使えないです。keep-alive の include はrouteのキャッシュは使えないです。そのため、component name を使ってキャッシュさせるようにします。このようなキャッシュ機能を作りたい場合,localStorageを使う手があります。もしくは keep-alive の includeを使って、全ページキャッシュする方法はあります。' | 182 | warning: '新規作成と編集画面は keep-alive を使えないです。keep-alive の include はrouteのキャッシュは使えないです。そのため、component name を使ってキャッシュさせるようにします。このようなキャッシュ機能を作りたい場合,localStorageを使う手があります。もしくは keep-alive の includeを使って、全ページキャッシュする方法はあります。' |
139 | }, | 183 | }, |
140 | errorLog: { | 184 | errorLog: { |
141 | tips: '右上のbugアイコンをクリックしてください。', | 185 | tips: '右上のbugアイコンをクリックしてください。', |
142 | description: '管理画面はspaを使う場合が多い、ユーザ体現向上はできますが、想定外エラーが発生する場合があります。Vueはそのエラーハンドリング機能を提供し、エラーレポートができます。', | 186 | description: '管理画面はspaを使う場合が多い、ユーザ体現向上はできますが、想定外エラーが発生する場合があります。Vueはそのエラーハンドリング機能を提供し、エラーレポートができます。', |
143 | documentation: 'ドキュメント' | 187 | documentation: 'ドキュメント' |
144 | }, | 188 | }, |
145 | excel: { | 189 | excel: { |
146 | export: 'エクスポート', | 190 | export: 'エクスポート', |
147 | selectedExport: 'エクスポート対象を選択してください。', | 191 | selectedExport: 'エクスポート対象を選択してください。', |
148 | placeholder: 'ファイル名を入力してください。' | 192 | placeholder: 'ファイル名を入力してください。' |
149 | }, | 193 | }, |
150 | zip: { | 194 | zip: { |
151 | export: 'エクスポート', | 195 | export: 'エクスポート', |
152 | placeholder: 'ファイル名を入力してください。' | 196 | placeholder: 'ファイル名を入力してください。' |
153 | }, | 197 | }, |
154 | pdf: { | 198 | pdf: { |
155 | tips: 'window.print() を使ってPDFダウンロードしています。' | 199 | tips: 'window.print() を使ってPDFダウンロードしています。' |
156 | }, | 200 | }, |
157 | theme: { | 201 | theme: { |
158 | change: 'テーマ切替', | 202 | change: 'テーマ切替', |
159 | documentation: 'ドキュメント', | 203 | documentation: 'ドキュメント', |
160 | tips: 'Tips: テーマの切り替え方法はnavbarのtheme-pickと異なります、使い方はドキュメントを確認してください。' | 204 | tips: 'Tips: テーマの切り替え方法はnavbarのtheme-pickと異なります、使い方はドキュメントを確認してください。' |
161 | }, | 205 | }, |
162 | tagsView: { | 206 | tagsView: { |
163 | refresh: '更新', | 207 | refresh: '更新', |
164 | close: '閉じる', | 208 | close: '閉じる', |
165 | closeOthers: 'その他閉じる', | 209 | closeOthers: 'その他閉じる', |
166 | closeAll: 'すべて閉じる' | 210 | closeAll: 'すべて閉じる' |
167 | }, | 211 | }, |
168 | settings: { | 212 | settings: { |
169 | title: 'システムテーマ', | 213 | title: 'システムテーマ', |
170 | theme: 'テーマ色', | 214 | theme: 'テーマ色', |
171 | tagsView: 'Tags-View 開く', | 215 | tagsView: 'Tags-View 開く', |
172 | fixedHeader: 'Fixed Header', | 216 | fixedHeader: 'Fixed Header', |
173 | sidebarLogo: 'Sidebar Logo' | 217 | sidebarLogo: 'Sidebar Logo' |
174 | } | 218 | } |
175 | } | 219 | } |
176 | 220 |
src/lang/zh.js
1 | export default { | 1 | export default { |
2 | // 添加的新词条------start | ||
3 | prod: { | ||
4 | menu_title: 'products' | ||
5 | }, | ||
6 | order: { | ||
7 | |||
8 | }, | ||
9 | users: { | ||
10 | |||
11 | }, | ||
12 | site: { | ||
13 | |||
14 | }, | ||
15 | meta: { | ||
16 | |||
17 | }, | ||
18 | system: { | ||
19 | memu: '系统' | ||
20 | }, | ||
2 | route: { | 21 | route: { |
22 | users: '用户', | ||
23 | usersList: '列表', | ||
24 | shopers: '厂商', | ||
25 | prods: '产品', | ||
26 | orders: '订单', | ||
27 | sites: '站点', | ||
28 | metas: { | ||
29 | metas: '元', | ||
30 | list: '树' | ||
31 | }, | ||
32 | systems: { | ||
33 | systems: '系统设置', | ||
34 | sites: '站点设置', | ||
35 | money: '货币设置', | ||
36 | industry: '行业设置', | ||
37 | template: '模版设置' | ||
38 | }, | ||
39 | // 添加的新词条------end | ||
3 | dashboard: '首页', | 40 | dashboard: '首页', |
4 | documentation: '文档', | 41 | documentation: '文档', |
5 | guide: '引导页', | 42 | guide: '引导页', |
6 | permission: '权限测试页', | 43 | permission: '权限测试页', |
7 | rolePermission: '角色权限', | 44 | rolePermission: '角色权限', |
8 | pagePermission: '页面权限', | 45 | pagePermission: '页面权限', |
9 | directivePermission: '指令权限', | 46 | directivePermission: '指令权限', |
10 | icons: '图标', | 47 | icons: '图标', |
11 | components: '组件', | 48 | components: '组件', |
12 | tinymce: '富文本编辑器', | 49 | tinymce: '富文本编辑器', |
13 | markdown: 'Markdown', | 50 | markdown: 'Markdown', |
14 | jsonEditor: 'JSON 编辑器', | 51 | jsonEditor: 'JSON 编辑器', |
15 | dndList: '列表拖拽', | 52 | dndList: '列表拖拽', |
16 | splitPane: 'Splitpane', | 53 | splitPane: 'Splitpane', |
17 | avatarUpload: '头像上传', | 54 | avatarUpload: '头像上传', |
18 | dropzone: 'Dropzone', | 55 | dropzone: 'Dropzone', |
19 | sticky: 'Sticky', | 56 | sticky: 'Sticky', |
20 | countTo: 'Count To', | 57 | countTo: 'Count To', |
21 | componentMixin: '小组件', | 58 | componentMixin: '小组件', |
22 | backToTop: '返回顶部', | 59 | backToTop: '返回顶部', |
23 | dragDialog: '拖拽 Dialog', | 60 | dragDialog: '拖拽 Dialog', |
24 | dragSelect: '拖拽 Select', | 61 | dragSelect: '拖拽 Select', |
25 | dragKanban: '可拖拽看板', | 62 | dragKanban: '可拖拽看板', |
26 | charts: '图表', | 63 | charts: '图表', |
27 | keyboardChart: '键盘图表', | 64 | keyboardChart: '键盘图表', |
28 | lineChart: '折线图', | 65 | lineChart: '折线图', |
29 | mixChart: '混合图表', | 66 | mixChart: '混合图表', |
30 | example: '综合实例', | 67 | example: '综合实例', |
31 | nested: '路由嵌套', | 68 | nested: '路由嵌套', |
32 | menu1: '菜单1', | 69 | menu1: '菜单1', |
33 | 'menu1-1': '菜单 1-1', | 70 | 'menu1-1': '菜单 1-1', |
34 | 'menu1-2': '菜单 1-2', | 71 | 'menu1-2': '菜单 1-2', |
35 | 'menu1-2-1': '菜单 1-2-1', | 72 | 'menu1-2-1': '菜单 1-2-1', |
36 | 'menu1-2-2': '菜单 1-2-2', | 73 | 'menu1-2-2': '菜单 1-2-2', |
37 | 'menu1-3': '菜单 1-3', | 74 | 'menu1-3': '菜单 1-3', |
38 | menu2: '菜单 2', | 75 | menu2: '菜单 2', |
39 | Table: 'Table', | 76 | Table: 'Table', |
40 | dynamicTable: '动态 Table', | 77 | dynamicTable: '动态 Table', |
41 | dragTable: '拖拽 Table', | 78 | dragTable: '拖拽 Table', |
42 | inlineEditTable: 'Table 内编辑', | 79 | inlineEditTable: 'Table 内编辑', |
43 | complexTable: '综合 Table', | 80 | complexTable: '综合 Table', |
44 | tab: 'Tab', | 81 | tab: 'Tab', |
45 | form: '表单', | 82 | form: '表单', |
46 | createArticle: '创建文章', | 83 | createArticle: '创建文章', |
47 | editArticle: '编辑文章', | 84 | editArticle: '编辑文章', |
48 | articleList: '文章列表', | 85 | articleList: '文章列表', |
49 | errorPages: '错误页面', | 86 | errorPages: '错误页面', |
50 | page401: '401', | 87 | page401: '401', |
51 | page404: '404', | 88 | page404: '404', |
52 | errorLog: '错误日志', | 89 | errorLog: '错误日志', |
53 | excel: 'Excel', | 90 | excel: 'Excel', |
54 | exportExcel: '导出 Excel', | 91 | exportExcel: '导出 Excel', |
55 | selectExcel: '导出 已选择项', | 92 | selectExcel: '导出 已选择项', |
56 | mergeHeader: '导出 多级表头', | 93 | mergeHeader: '导出 多级表头', |
57 | uploadExcel: '上传 Excel', | 94 | uploadExcel: '上传 Excel', |
58 | zip: 'Zip', | 95 | zip: 'Zip', |
59 | pdf: 'PDF', | 96 | pdf: 'PDF', |
60 | exportZip: 'Export Zip', | 97 | exportZip: 'Export Zip', |
61 | theme: '换肤', | 98 | theme: '换肤', |
62 | clipboardDemo: 'Clipboard', | 99 | clipboardDemo: 'Clipboard', |
63 | i18n: '国际化', | 100 | i18n: '国际化', |
64 | externalLink: '外链', | 101 | externalLink: '外链', |
65 | profile: '个人中心' | 102 | profile: '个人中心' |
66 | }, | 103 | }, |
67 | navbar: { | 104 | navbar: { |
68 | dashboard: '首页', | 105 | dashboard: '首页', |
69 | github: '项目地址', | 106 | github: '项目地址', |
70 | logOut: '退出登录', | 107 | logOut: '退出登录', |
71 | profile: '个人中心', | 108 | profile: '个人中心', |
72 | theme: '换肤', | 109 | theme: '换肤', |
73 | size: '布局大小' | 110 | size: '布局大小' |
74 | }, | 111 | }, |
75 | login: { | 112 | login: { |
76 | title: '系统登录', | 113 | runner: '运营官', |
114 | shoper: '商家', | ||
115 | assistant: '操作员', | ||
116 | signup: '注册', | ||
117 | forgetpassword: '忘记密码', | ||
118 | rememberpassword: 'remember password', | ||
119 | |||
120 | title: '鱼皮出海', | ||
77 | logIn: '登录', | 121 | logIn: '登录', |
78 | username: '账号', | 122 | username: '账号', |
79 | password: '密码', | 123 | password: '密码', |
80 | any: '随便填', | 124 | any: '随便填', |
81 | thirdparty: '第三方登录', | 125 | thirdparty: '第三方登录', |
82 | thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!' | 126 | thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!' |
83 | }, | 127 | }, |
84 | documentation: { | 128 | documentation: { |
85 | documentation: '文档', | 129 | documentation: '文档', |
86 | github: 'Github 地址' | 130 | github: 'Github 地址' |
87 | }, | 131 | }, |
88 | permission: { | 132 | permission: { |
89 | addRole: '新增角色', | 133 | addRole: '新增角色', |
90 | editPermission: '编辑权限', | 134 | editPermission: '编辑权限', |
91 | roles: '你的权限', | 135 | roles: '你的权限', |
92 | switchRoles: '切换权限', | 136 | switchRoles: '切换权限', |
93 | tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。', | 137 | tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。', |
94 | delete: '删除', | 138 | delete: '删除', |
95 | confirm: '确定', | 139 | confirm: '确定', |
96 | cancel: '取消' | 140 | cancel: '取消' |
97 | }, | 141 | }, |
98 | guide: { | 142 | guide: { |
99 | description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于', | 143 | description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于', |
100 | button: '打开引导' | 144 | button: '打开引导' |
101 | }, | 145 | }, |
102 | components: { | 146 | components: { |
103 | documentation: '文档', | 147 | documentation: '文档', |
104 | tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见', | 148 | tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见', |
105 | dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone', | 149 | dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone', |
106 | stickyTips: '当页面滚动到预设的位置会吸附在顶部', | 150 | stickyTips: '当页面滚动到预设的位置会吸附在顶部', |
107 | backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮', | 151 | backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮', |
108 | backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素', | 152 | backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素', |
109 | imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。' | 153 | imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。' |
110 | }, | 154 | }, |
111 | table: { | 155 | table: { |
112 | dynamicTips1: '固定表头, 按照表头顺序排序', | 156 | dynamicTips1: '固定表头, 按照表头顺序排序', |
113 | dynamicTips2: '不固定表头, 按照点击顺序排序', | 157 | dynamicTips2: '不固定表头, 按照点击顺序排序', |
114 | dragTips1: '默认顺序', | 158 | dragTips1: '默认顺序', |
115 | dragTips2: '拖拽后顺序', | 159 | dragTips2: '拖拽后顺序', |
116 | title: '标题', | 160 | title: '标题', |
117 | importance: '重要性', | 161 | importance: '重要性', |
118 | type: '类型', | 162 | type: '类型', |
119 | remark: '点评', | 163 | remark: '点评', |
120 | search: '搜索', | 164 | search: '搜索', |
121 | add: '添加', | 165 | add: '添加', |
122 | export: '导出', | 166 | export: '导出', |
123 | reviewer: '审核人', | 167 | reviewer: '审核人', |
124 | id: '序号', | 168 | id: '序号', |
125 | date: '时间', | 169 | date: '时间', |
126 | author: '作者', | 170 | author: '作者', |
127 | readings: '阅读数', | 171 | readings: '阅读数', |
128 | status: '状态', | 172 | status: '状态', |
129 | actions: '操作', | 173 | actions: '操作', |
130 | edit: '编辑', | 174 | edit: '编辑', |
131 | publish: '发布', | 175 | publish: '发布', |
132 | draft: '草稿', | 176 | draft: '草稿', |
133 | delete: '删除', | 177 | delete: '删除', |
134 | cancel: '取 消', | 178 | cancel: '取 消', |
135 | confirm: '确 定' | 179 | confirm: '确 定' |
136 | }, | 180 | }, |
137 | example: { | 181 | example: { |
138 | warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见' | 182 | warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见' |
139 | }, | 183 | }, |
140 | errorLog: { | 184 | errorLog: { |
141 | tips: '请点击右上角bug小图标', | 185 | tips: '请点击右上角bug小图标', |
142 | description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。', | 186 | description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。', |
143 | documentation: '文档介绍' | 187 | documentation: '文档介绍' |
144 | }, | 188 | }, |
145 | excel: { | 189 | excel: { |
146 | export: '导出', | 190 | export: '导出', |
147 | selectedExport: '导出已选择项', | 191 | selectedExport: '导出已选择项', |
148 | placeholder: '请输入文件名(默认excel-list)' | 192 | placeholder: '请输入文件名(默认excel-list)' |
149 | }, | 193 | }, |
150 | zip: { | 194 | zip: { |
151 | export: '导出', | 195 | export: '导出', |
152 | placeholder: '请输入文件名(默认file)' | 196 | placeholder: '请输入文件名(默认file)' |
153 | }, | 197 | }, |
154 | pdf: { | 198 | pdf: { |
155 | tips: '这里使用 window.print() 来实现下载pdf的功能' | 199 | tips: '这里使用 window.print() 来实现下载pdf的功能' |
156 | }, | 200 | }, |
157 | theme: { | 201 | theme: { |
158 | change: '换肤', | 202 | change: '换肤', |
159 | documentation: '换肤文档', | 203 | documentation: '换肤文档', |
160 | tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。' | 204 | tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。' |
161 | }, | 205 | }, |
162 | tagsView: { | 206 | tagsView: { |
163 | refresh: '刷新', | 207 | refresh: '刷新', |
164 | close: '关闭', | 208 | close: '关闭', |
165 | closeOthers: '关闭其它', | 209 | closeOthers: '关闭其它', |
166 | closeAll: '关闭所有' | 210 | closeAll: '关闭所有' |
167 | }, | 211 | }, |
168 | settings: { | 212 | settings: { |
169 | title: '系统布局配置', | 213 | title: '系统布局配置', |
170 | theme: '主题色', | 214 | theme: '主题色', |
171 | tagsView: '开启 Tags-View', | 215 | tagsView: '开启 Tags-View', |
172 | fixedHeader: '固定 Header', | 216 | fixedHeader: '固定 Header', |
173 | sidebarLogo: '侧边栏 Logo' | 217 | sidebarLogo: '侧边栏 Logo' |
174 | } | 218 | } |
175 | } | 219 | } |
176 | 220 |
src/layout/components/Settings/index.vue
1 | <template> | 1 | <template> |
2 | <div class="drawer-container"> | 2 | <div class="drawer-container"> |
3 | <div> | 3 | <div> |
4 | <h3 class="drawer-title">{{ $t('settings.title') }}</h3> | 4 | <h3 class="drawer-title">{{ $t('settings.title') }}</h3> |
5 | 5 | ||
6 | <div class="drawer-item"> | 6 | <div class="drawer-item"> |
7 | <span>{{ $t('settings.theme') }}</span> | 7 | <span>{{ $t('settings.theme') }}</span> |
8 | <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" /> | 8 | <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" /> |
9 | </div> | 9 | </div> |
10 | 10 | ||
11 | <div class="drawer-item"> | 11 | <div class="drawer-item"> |
12 | <span>{{ $t('settings.tagsView') }}</span> | 12 | <span>{{ $t('settings.tagsView') }}</span> |
13 | <el-switch v-model="tagsView" class="drawer-switch" /> | 13 | <el-switch v-model="tagsView" class="drawer-switch" /> |
14 | </div> | 14 | </div> |
15 | 15 | ||
16 | <div class="drawer-item"> | 16 | <div class="drawer-item"> |
17 | <span>{{ $t('settings.fixedHeader') }}</span> | 17 | <span>{{ $t('settings.fixedHeader') }}</span> |
18 | <el-switch v-model="fixedHeader" class="drawer-switch" /> | 18 | <el-switch v-model="fixedHeader" class="drawer-switch" /> |
19 | </div> | 19 | </div> |
20 | 20 | ||
21 | <div class="drawer-item"> | 21 | <div class="drawer-item"> |
22 | <span>{{ $t('settings.sidebarLogo') }}</span> | 22 | <span>{{ $t('settings.sidebarLogo') }}</span> |
23 | <el-switch v-model="sidebarLogo" class="drawer-switch" /> | 23 | <el-switch v-model="sidebarLogo" class="drawer-switch" /> |
24 | </div> | 24 | </div> |
25 | <a v-if="isShowJob" href="https://panjiachen.github.io/vue-element-admin-site/zh/job/" target="_blank" class="job-link"> | 25 | |
26 | <a v-if="isShowJob" href="https://glass.xiuyetang.com/" target="_blank" class="job-link"> | ||
26 | <el-alert | 27 | <el-alert |
27 | title="部门目前非常缺人!有兴趣的可以点击了解详情。坐标: 字节跳动" | 28 | title="鱼皮计划极为宏大,而且极为可行,我们要努力写代码,尽快打通任督二脉,要做好很有钱的思想准备" |
28 | type="success" | 29 | type="success" |
29 | :closable="false" | 30 | :closable="true" |
30 | /> | 31 | /> |
31 | </a> | 32 | </a> |
32 | 33 | ||
33 | <div v-if="lang === 'zh'" class="drawer-item"> | 34 | <div v-if="lang === 'zh'" class="drawer-item"> |
34 | <span>菜单支持拼音搜索</span> | 35 | <span>菜单支持拼音搜索</span> |
35 | <el-switch v-model="supportPinyinSearch" class="drawer-switch" /> | 36 | <el-switch v-model="supportPinyinSearch" class="drawer-switch" /> |
36 | </div> | 37 | </div> |
37 | 38 | ||
38 | </div> | 39 | </div> |
39 | </div> | 40 | </div> |
40 | </template> | 41 | </template> |
41 | 42 | ||
42 | <script> | 43 | <script> |
43 | import ThemePicker from '@/components/ThemePicker' | 44 | import ThemePicker from '@/components/ThemePicker' |
44 | 45 | ||
45 | export default { | 46 | export default { |
46 | components: { ThemePicker }, | 47 | components: { ThemePicker }, |
47 | data() { | 48 | data() { |
48 | return {} | 49 | return {} |
49 | }, | 50 | }, |
50 | computed: { | 51 | computed: { |
51 | isShowJob() { | 52 | isShowJob() { |
52 | return this.$store.getters.language === 'zh' | 53 | return this.$store.getters.language === 'zh' |
53 | }, | 54 | }, |
54 | fixedHeader: { | 55 | fixedHeader: { |
55 | get() { | 56 | get() { |
56 | return this.$store.state.settings.fixedHeader | 57 | return this.$store.state.settings.fixedHeader |
57 | }, | 58 | }, |
58 | set(val) { | 59 | set(val) { |
59 | this.$store.dispatch('settings/changeSetting', { | 60 | this.$store.dispatch('settings/changeSetting', { |
60 | key: 'fixedHeader', | 61 | key: 'fixedHeader', |
61 | value: val | 62 | value: val |
62 | }) | 63 | }) |
63 | } | 64 | } |
64 | }, | 65 | }, |
65 | tagsView: { | 66 | tagsView: { |
66 | get() { | 67 | get() { |
67 | return this.$store.state.settings.tagsView | 68 | return this.$store.state.settings.tagsView |
68 | }, | 69 | }, |
69 | set(val) { | 70 | set(val) { |
70 | this.$store.dispatch('settings/changeSetting', { | 71 | this.$store.dispatch('settings/changeSetting', { |
71 | key: 'tagsView', | 72 | key: 'tagsView', |
72 | value: val | 73 | value: val |
73 | }) | 74 | }) |
74 | } | 75 | } |
75 | }, | 76 | }, |
76 | sidebarLogo: { | 77 | sidebarLogo: { |
77 | get() { | 78 | get() { |
78 | return this.$store.state.settings.sidebarLogo | 79 | return this.$store.state.settings.sidebarLogo |
79 | }, | 80 | }, |
80 | set(val) { | 81 | set(val) { |
81 | this.$store.dispatch('settings/changeSetting', { | 82 | this.$store.dispatch('settings/changeSetting', { |
82 | key: 'sidebarLogo', | 83 | key: 'sidebarLogo', |
83 | value: val | 84 | value: val |
84 | }) | 85 | }) |
85 | } | 86 | } |
86 | }, | 87 | }, |
87 | supportPinyinSearch: { | 88 | supportPinyinSearch: { |
88 | get() { | 89 | get() { |
89 | return this.$store.state.settings.supportPinyinSearch | 90 | return this.$store.state.settings.supportPinyinSearch |
90 | }, | 91 | }, |
91 | set(val) { | 92 | set(val) { |
92 | this.$store.dispatch('settings/changeSetting', { | 93 | this.$store.dispatch('settings/changeSetting', { |
93 | key: 'supportPinyinSearch', | 94 | key: 'supportPinyinSearch', |
94 | value: val | 95 | value: val |
95 | }) | 96 | }) |
96 | } | 97 | } |
97 | }, | 98 | }, |
98 | lang() { | 99 | lang() { |
99 | return this.$store.getters.language | 100 | return this.$store.getters.language |
100 | } | 101 | } |
101 | }, | 102 | }, |
102 | methods: { | 103 | methods: { |
103 | themeChange(val) { | 104 | themeChange(val) { |
104 | this.$store.dispatch('settings/changeSetting', { | 105 | this.$store.dispatch('settings/changeSetting', { |
105 | key: 'theme', | 106 | key: 'theme', |
106 | value: val | 107 | value: val |
107 | }) | 108 | }) |
108 | } | 109 | } |
109 | } | 110 | } |
110 | } | 111 | } |
111 | </script> | 112 | </script> |
112 | 113 | ||
113 | <style lang="scss" scoped> | 114 | <style lang="scss" scoped> |
114 | .drawer-container { | 115 | .drawer-container { |
115 | padding: 24px; | 116 | padding: 24px; |
116 | font-size: 14px; | 117 | font-size: 14px; |
117 | line-height: 1.5; | 118 | line-height: 1.5; |
118 | word-wrap: break-word; | 119 | word-wrap: break-word; |
119 | 120 | ||
120 | .drawer-title { | 121 | .drawer-title { |
121 | margin-bottom: 12px; | 122 | margin-bottom: 12px; |
122 | color: rgba(0, 0, 0, .85); | 123 | color: rgba(0, 0, 0, .85); |
123 | font-size: 14px; | 124 | font-size: 14px; |
124 | line-height: 22px; | 125 | line-height: 22px; |
125 | } | 126 | } |
126 | 127 | ||
127 | .drawer-item { | 128 | .drawer-item { |
128 | color: rgba(0, 0, 0, .65); | 129 | color: rgba(0, 0, 0, .65); |
129 | font-size: 14px; | 130 | font-size: 14px; |
130 | padding: 12px 0; | 131 | padding: 12px 0; |
131 | } | 132 | } |
132 | 133 | ||
133 | .drawer-switch { | 134 | .drawer-switch { |
134 | float: right | 135 | float: right |
135 | } | 136 | } |
136 | 137 | ||
137 | .job-link{ | 138 | .job-link{ |
138 | display: block; | 139 | display: block; |
139 | position: absolute; | 140 | position: absolute; |
140 | width: 100%; | 141 | width: 100%; |
141 | left: 0; | 142 | left: 0; |
142 | bottom: 0; | 143 | bottom: 0; |
143 | } | 144 | } |
144 | } | 145 | } |
145 | </style> | 146 | </style> |
146 | 147 |
src/router/index.js
1 | import Vue from 'vue' | 1 | import Vue from 'vue' |
2 | import Router from 'vue-router' | 2 | import Router from 'vue-router' |
3 | 3 | ||
4 | Vue.use(Router) | 4 | Vue.use(Router) |
5 | 5 | ||
6 | /* Layout */ | 6 | /* Layout */ |
7 | import Layout from '@/layout' | 7 | import Layout from '@/layout' |
8 | 8 | ||
9 | /* Router Modules */ | 9 | /* Router Modules */ |
10 | import componentsRouter from './modules/components' | 10 | // import componentsRouter from './modules/components' |
11 | import chartsRouter from './modules/charts' | 11 | // import chartsRouter from './modules/charts' |
12 | import tableRouter from './modules/table' | 12 | import tableRouter from './modules/table' |
13 | // import nestedRouter from './modules/nested' | 13 | // import nestedRouter from './modules/nested' |
14 | import userRouter from './modules/user' | 14 | import userRouter from './modules/user' |
15 | import systemRouter from './modules/system' | ||
16 | import prodRouter from './modules/prod' | ||
17 | import metaRouter from './modules/meta' | ||
15 | 18 | ||
16 | /** | 19 | /** |
17 | * Note: sub-menu only appear when route children.length >= 1 | 20 | * Note: sub-menu only appear when route children.length >= 1 |
18 | * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html | 21 | * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html |
19 | * | 22 | * |
20 | * hidden: true if set true, item will not show in the sidebar(default is false) | 23 | * hidden: true if set true, item will not show in the sidebar(default is false) |
21 | * alwaysShow: true if set true, will always show the root menu | 24 | * alwaysShow: true if set true, will always show the root menu |
22 | * if not set alwaysShow, when item has more than one children route, | 25 | * if not set alwaysShow, when item has more than one children route, |
23 | * it will becomes nested mode, otherwise not show the root menu | 26 | * it will becomes nested mode, otherwise not show the root menu |
24 | * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb | 27 | * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb |
25 | * name:'router-name' the name is used by <keep-alive> (must set!!!) | 28 | * name:'router-name' the name is used by <keep-alive> (must set!!!) |
26 | * meta : { | 29 | * meta : { |
27 | roles: ['admin','assistant','runner', 'shoper'] control the page roles (you can set multiple roles) | 30 | roles: ['admin','assistant','runner', 'shoper'] control the page roles (you can set multiple roles) |
28 | title: 'title' the name show in sidebar and breadcrumb (recommend set) | 31 | title: 'title' the name show in sidebar and breadcrumb (recommend set) |
29 | icon: 'svg-name' the icon show in the sidebar | 32 | icon: 'svg-name' the icon show in the sidebar |
30 | noCache: true if set true, the page will no be cached(default is false) | 33 | noCache: true if set true, the page will no be cached(default is false) |
31 | affix: true if set true, the tag will affix in the tags-view | 34 | affix: true if set true, the tag will affix in the tags-view |
32 | breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) | 35 | breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) |
33 | activeMenu: '/example/list' if set path, the sidebar will highlight the path you set | 36 | activeMenu: '/example/list' if set path, the sidebar will highlight the path you set |
34 | } | 37 | } |
35 | */ | 38 | */ |
36 | 39 | ||
37 | /** | 40 | /** |
38 | * constantRoutes | 41 | * constantRoutes |
39 | * a base page that does not have permission requirements | 42 | * a base page that does not have permission requirements |
40 | * all roles can be accessed | 43 | * all roles can be accessed |
41 | */ | 44 | */ |
42 | export const constantRoutes = [ | 45 | export const constantRoutes = [ |
43 | { | 46 | { |
44 | path: '/redirect', | 47 | path: '/redirect', |
45 | component: Layout, | 48 | component: Layout, |
46 | hidden: true, | 49 | hidden: true, |
47 | children: [ | 50 | children: [ |
48 | { | 51 | { |
49 | path: '/redirect/:path*', | 52 | path: '/redirect/:path*', |
50 | component: () => import('@/views/redirect/index') | 53 | component: () => import('@/views/redirect/index') |
51 | } | 54 | } |
52 | ] | 55 | ] |
53 | }, | 56 | }, |
54 | { | 57 | { |
55 | path: '/login', | 58 | path: '/login', |
56 | component: () => import('@/views/login/index'), | 59 | component: () => import('@/views/login/index'), |
57 | hidden: true | 60 | hidden: true |
58 | }, | 61 | }, |
59 | { | 62 | { |
60 | path: '/auth-redirect', | 63 | path: '/auth-redirect', |
61 | component: () => import('@/views/login/auth-redirect'), | 64 | component: () => import('@/views/login/auth-redirect'), |
62 | hidden: true | 65 | hidden: true |
63 | }, | 66 | }, |
64 | { | 67 | { |
65 | path: '/404', | 68 | path: '/404', |
66 | component: () => import('@/views/error-page/404'), | 69 | component: () => import('@/views/error-page/404'), |
67 | hidden: true | 70 | hidden: true |
68 | }, | 71 | }, |
69 | { | 72 | { |
73 | path: '/500', | ||
74 | component: () => import('@/views/error-page/500'), | ||
75 | hidden: true | ||
76 | }, | ||
77 | { | ||
70 | path: '/401', | 78 | path: '/401', |
71 | component: () => import('@/views/error-page/401'), | 79 | component: () => import('@/views/error-page/401'), |
72 | hidden: true | 80 | hidden: true |
73 | }, | 81 | }, |
74 | { | 82 | { |
75 | path: '/', | 83 | path: '/', |
76 | component: Layout, | 84 | component: Layout, |
77 | redirect: '/dashboard', | 85 | redirect: '/dashboard', |
78 | children: [ | 86 | children: [ |
79 | { | 87 | { |
80 | path: 'dashboard', | 88 | path: 'dashboard', |
81 | component: () => import('@/views/dashboard/index'), | 89 | component: () => import('@/views/dashboard/index'), |
82 | name: 'Dashboard', | 90 | name: 'Dashboard', |
83 | meta: { title: 'dashboard', icon: 'dashboard', affix: true } | 91 | meta: { title: 'dashboard', icon: 'dashboard', affix: true } |
84 | } | 92 | } |
85 | ] | 93 | ] |
86 | }, | 94 | }, |
87 | // { | 95 | // { |
88 | // path: '/documentation', | 96 | // path: '/documentation', |
89 | // component: Layout, | 97 | // component: Layout, |
90 | // children: [ | 98 | // children: [ |
91 | // { | 99 | // { |
92 | // path: 'index', | 100 | // path: 'index', |
93 | // component: () => import('@/views/documentation/index'), | 101 | // component: () => import('@/views/documentation/index'), |
94 | // name: 'Documentation', | 102 | // name: 'Documentation', |
95 | // meta: { title: 'documentation', icon: 'documentation', affix: true } | 103 | // meta: { title: 'documentation', icon: 'documentation', affix: true } |
96 | // } | 104 | // } |
97 | // ] | 105 | // ] |
98 | // }, | 106 | // }, |
99 | // { | ||
100 | // path: '/guide', | ||
101 | // component: Layout, | ||
102 | // redirect: '/guide/index', | ||
103 | // children: [ | ||
104 | // { | ||
105 | // path: 'index', | ||
106 | // component: () => import('@/views/guide/index'), | ||
107 | // name: 'Guide', | ||
108 | // meta: { title: 'guide', icon: 'guide', noCache: true } | ||
109 | // } | ||
110 | // ] | ||
111 | // }, | ||
112 | { | 107 | { |
113 | path: '/profile', | 108 | path: '/guide', |
114 | component: Layout, | 109 | component: Layout, |
115 | redirect: '/profile/index', | 110 | redirect: '/guide/index', |
116 | hidden: true, | ||
117 | children: [ | 111 | children: [ |
118 | { | 112 | { |
119 | path: 'index', | 113 | path: 'index', |
120 | component: () => import('@/views/profile/index'), | 114 | component: () => import('@/views/guide/index'), |
121 | name: 'Profile', | 115 | name: 'Guide', |
122 | meta: { title: 'profile', icon: 'user', noCache: true } | 116 | meta: { title: 'guide', icon: 'guide', noCache: true } |
123 | } | 117 | } |
124 | ] | 118 | ] |
125 | } | 119 | } |
120 | // { | ||
121 | // path: '/profile', | ||
122 | // component: Layout, | ||
123 | // redirect: '/profile/index', | ||
124 | // hidden: true, | ||
125 | // children: [ | ||
126 | // { | ||
127 | // path: 'index', | ||
128 | // component: () => import('@/views/profile/index'), | ||
129 | // name: 'Profile', | ||
130 | // meta: { title: 'profile', icon: 'user', noCache: true } | ||
131 | // } | ||
132 | // ] | ||
133 | // } | ||
126 | ] | 134 | ] |
127 | 135 | ||
128 | /** | 136 | /** |
129 | * asyncRoutes | 137 | * asyncRoutes |
130 | * the routes that need to be dynamically loaded based on user roles | 138 | * the routes that need to be dynamically loaded based on user roles |
131 | */ | 139 | */ |
132 | export const asyncRoutes = [ | 140 | export const asyncRoutes = [ |
133 | // { | 141 | // { |
134 | // path: '/permission', | 142 | // path: '/permission', |
135 | // component: Layout, | 143 | // component: Layout, |
136 | // redirect: '/permission/page', | 144 | // redirect: '/permission/page', |
137 | // alwaysShow: true, // will always show the root menu | 145 | // alwaysShow: true, // will always show the root menu |
138 | // name: 'Permission', | 146 | // name: 'Permission', |
139 | // meta: { | 147 | // meta: { |
140 | // title: 'permission', | 148 | // title: 'permission', |
141 | // icon: 'lock', | 149 | // icon: 'lock', |
142 | // roles: ['admin', 'assistant'] // you can set roles in root nav | 150 | // roles: ['admin', 'assistant'] // you can set roles in root nav |
143 | // }, | 151 | // }, |
144 | // children: [ | 152 | // children: [ |
145 | // { | 153 | // { |
146 | // path: 'page', | 154 | // path: 'page', |
147 | // component: () => import('@/views/permission/page'), | 155 | // component: () => import('@/views/permission/page'), |
148 | // name: 'PagePermission', | 156 | // name: 'PagePermission', |
149 | // meta: { | 157 | // meta: { |
150 | // title: 'pagePermission', | 158 | // title: 'pagePermission', |
151 | // roles: ['admin','assistant'] // or you can only set roles in sub nav | 159 | // roles: ['admin','assistant'] // or you can only set roles in sub nav |
152 | // } | 160 | // } |
153 | // }, | 161 | // }, |
154 | // { | 162 | // { |
155 | // path: 'directive', | 163 | // path: 'directive', |
156 | // component: () => import('@/views/permission/directive'), | 164 | // component: () => import('@/views/permission/directive'), |
157 | // name: 'DirectivePermission', | 165 | // name: 'DirectivePermission', |
158 | // meta: { | 166 | // meta: { |
159 | // title: 'directivePermission', | 167 | // title: 'directivePermission', |
160 | // roles: ['admin', 'shoper'] | 168 | // roles: ['admin', 'shoper'] |
161 | // // if do not set roles, means: this page does not require permission | 169 | // // if do not set roles, means: this page does not require permission |
162 | // } | 170 | // } |
163 | // }, | 171 | // }, |
164 | // { | 172 | // { |
165 | // path: 'role', | 173 | // path: 'role', |
166 | // component: () => import('@/views/permission/role'), | 174 | // component: () => import('@/views/permission/role'), |
167 | // name: 'RolePermission', | 175 | // name: 'RolePermission', |
168 | // meta: { | 176 | // meta: { |
169 | // title: 'rolePermission', | 177 | // title: 'rolePermission', |
170 | // roles: ['admin', 'runner'] | 178 | // roles: ['admin', 'runner'] |
171 | // } | 179 | // } |
172 | // } | 180 | // } |
173 | // ] | 181 | // ] |
174 | // }, | 182 | // }, |
183 | tableRouter, | ||
184 | metaRouter, | ||
185 | userRouter, | ||
186 | prodRouter, | ||
175 | { | 187 | { |
176 | path: '/meta', | 188 | path: '/orders', |
177 | component: Layout, | ||
178 | redirect: '/meta/page', | ||
179 | alwaysShow: true, // will always show the root menu | ||
180 | name: 'Meta', | ||
181 | meta: { | ||
182 | title: 'Meta', | ||
183 | icon: 'lock', | ||
184 | roles: ['admin', 'assistant'] // you can set roles in root nav | ||
185 | }, | ||
186 | children: [ | ||
187 | { | ||
188 | path: 'page', | ||
189 | component: () => import('@/views/permission/page'), | ||
190 | name: 'MetaList', | ||
191 | meta: { | ||
192 | title: 'MetaList', | ||
193 | roles: ['admin', 'assistant'] // or you can only set roles in sub nav | ||
194 | } | ||
195 | }, | ||
196 | { | ||
197 | path: 'defined', | ||
198 | component: () => import('@/views/permission/directive'), | ||
199 | name: 'MetaDefiend', | ||
200 | meta: { | ||
201 | title: 'MetaDefiend', | ||
202 | roles: ['admin', 'assistant'] | ||
203 | // if do not set roles, means: this page does not require permission | ||
204 | } | ||
205 | } | ||
206 | ] | ||
207 | }, | ||
208 | { | ||
209 | path: '/users', | ||
210 | component: Layout, | ||
211 | redirect: '/users/page', | ||
212 | alwaysShow: true, // will always show the root menu | ||
213 | name: 'Users', | ||
214 | meta: { | ||
215 | title: 'Users', | ||
216 | icon: 'lock', | ||
217 | roles: ['admin', 'assistant'] // you can set roles in root nav | ||
218 | }, | ||
219 | children: [ | ||
220 | { | ||
221 | path: 'page', | ||
222 | component: () => import('@/views/permission/page'), | ||
223 | name: 'UserList', | ||
224 | meta: { | ||
225 | title: 'UserList', | ||
226 | roles: ['admin', 'assistant'] // or you can only set roles in sub nav | ||
227 | } | ||
228 | }, | ||
229 | { | ||
230 | path: 'defined', | ||
231 | component: () => import('@/views/permission/directive'), | ||
232 | name: 'UserDefiend', | ||
233 | meta: { | ||
234 | title: 'UserDefiend', | ||
235 | roles: ['admin', 'assistant'] | ||
236 | // if do not set roles, means: this page does not require permission | ||
237 | } | ||
238 | } | ||
239 | ] | ||
240 | }, | ||
241 | { | ||
242 | path: '/prod', | ||
243 | component: Layout, | ||
244 | redirect: '/prod/page', | ||
245 | alwaysShow: true, // will always show the root menu | ||
246 | name: 'Prod', | ||
247 | meta: { | ||
248 | title: 'Prod', | ||
249 | icon: 'lock', | ||
250 | roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav | ||
251 | }, | ||
252 | children: [ | ||
253 | { | ||
254 | path: 'page', | ||
255 | component: () => import('@/views/permission/page'), | ||
256 | name: 'ProdList', | ||
257 | meta: { | ||
258 | title: 'ProdList', | ||
259 | roles: ['admin', 'assistant', 'runner', 'shoper'] // or you can only set roles in sub nav | ||
260 | } | ||
261 | }, | ||
262 | { | ||
263 | path: 'defined', | ||
264 | component: () => import('@/views/permission/directive'), | ||
265 | name: 'ProdDefiend', | ||
266 | meta: { | ||
267 | title: 'ProdDefiend', | ||
268 | roles: ['admin', 'assistant', 'shoper'] | ||
269 | // if do not set roles, means: this page does not require permission | ||
270 | } | ||
271 | } | ||
272 | ] | ||
273 | }, | ||
274 | { | ||
275 | path: '/order', | ||
276 | component: Layout, | 189 | component: Layout, |
277 | redirect: '/order/page', | 190 | redirect: '/order/page', |
278 | alwaysShow: true, // will always show the root menu | 191 | alwaysShow: true, // will always show the root menu |
279 | name: 'Order', | 192 | name: 'Order', |
280 | meta: { | 193 | meta: { |
281 | title: 'Order', | 194 | title: 'orders', |
282 | icon: 'lock', | 195 | icon: 'shopping', |
283 | roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav | 196 | roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav |
284 | }, | 197 | }, |
285 | children: [ | 198 | children: [ |
286 | { | 199 | { |
287 | path: 'page', | 200 | path: 'page', |
288 | component: () => import('@/views/permission/page'), | 201 | component: () => import('@/views/permission/page'), |
289 | name: 'OrderList', | 202 | name: 'OrderList', |
290 | meta: { | 203 | meta: { |
291 | title: 'OrderList', | 204 | title: 'OrderList', |
292 | roles: ['admin', 'assistant', 'runner', 'shoper'] // or you can only set roles in sub nav | 205 | roles: ['admin', 'assistant', 'runner', 'shoper'] // or you can only set roles in sub nav |
293 | } | 206 | } |
294 | }, | 207 | }, |
295 | { | 208 | { |
296 | path: 'defined', | 209 | path: 'defined', |
297 | component: () => import('@/views/permission/directive'), | 210 | component: () => import('@/views/permission/directive'), |
298 | name: 'OrderDefiend', | 211 | name: 'OrderDefiend', |
299 | meta: { | 212 | meta: { |
300 | title: 'OrderDefiend', | 213 | title: 'OrderDefiend', |
301 | roles: ['admin', 'assistant', 'runner', 'shoper'] | 214 | roles: ['admin', 'assistant', 'runner', 'shoper'] |
302 | // if do not set roles, means: this page does not require permission | 215 | // if do not set roles, means: this page does not require permission |
303 | } | 216 | } |
304 | } | 217 | } |
305 | ] | 218 | ] |
306 | }, | 219 | }, |
307 | { | 220 | { |
308 | path: '/site', | 221 | path: '/sites', |
309 | component: Layout, | 222 | component: Layout, |
310 | redirect: '/site/page', | 223 | redirect: '/site/page', |
311 | alwaysShow: true, // will always show the root menu | 224 | alwaysShow: true, // will always show the root menu |
312 | name: 'Site', | 225 | name: 'Site', |
313 | meta: { | 226 | meta: { |
314 | title: 'Site', | 227 | title: 'sites', |
315 | icon: 'lock', | 228 | icon: 'people', |
316 | roles: ['admin', 'assistant', 'runner'] // you can set roles in root nav | 229 | roles: ['admin', 'assistant', 'runner'] // you can set roles in root nav |
317 | }, | 230 | }, |
318 | children: [ | 231 | children: [ |
319 | { | 232 | { |
320 | path: 'page', | 233 | path: 'page', |
321 | component: () => import('@/views/permission/page'), | 234 | component: () => import('@/views/permission/page'), |
322 | name: 'SiteList', | 235 | name: 'SiteList', |
323 | meta: { | 236 | meta: { |
324 | title: 'SiteList', | 237 | title: 'SiteList', |
325 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav | 238 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav |
326 | } | 239 | } |
327 | }, | 240 | }, |
328 | { | 241 | { |
329 | path: 'defined', | 242 | path: 'defined', |
330 | component: () => import('@/views/permission/directive'), | 243 | component: () => import('@/views/permission/directive'), |
331 | name: 'SiteDefiend', | 244 | name: 'SiteDefiend', |
332 | meta: { | 245 | meta: { |
333 | title: 'SiteDefiend', | 246 | title: 'SiteDefiend', |
334 | roles: ['admin', 'assistant', 'runner'] | 247 | roles: ['admin', 'assistant', 'runner'] |
335 | // if do not set roles, means: this page does not require permission | 248 | // if do not set roles, means: this page does not require permission |
336 | } | 249 | } |
337 | } | 250 | } |
338 | ] | 251 | ] |
339 | }, | 252 | }, |
340 | { | 253 | |
341 | path: '/system', | ||
342 | component: Layout, | ||
343 | redirect: '/system/page', | ||
344 | alwaysShow: true, // will always show the root menu | ||
345 | name: 'System', | ||
346 | meta: { | ||
347 | title: 'System', | ||
348 | icon: 'lock', | ||
349 | roles: ['admin', 'assistant', 'runner'] // you can set roles in root nav | ||
350 | }, | ||
351 | children: [ | ||
352 | { | ||
353 | path: 'page', | ||
354 | component: () => import('@/views/permission/page'), | ||
355 | name: 'SystemList', | ||
356 | meta: { | ||
357 | title: 'SystemList', | ||
358 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav | ||
359 | } | ||
360 | }, | ||
361 | { | ||
362 | path: 'defined', | ||
363 | component: () => import('@/views/permission/directive'), | ||
364 | name: 'SystemDefiend', | ||
365 | meta: { | ||
366 | title: 'SystemDefiend', | ||
367 | roles: ['admin', 'assistant', 'runner'] | ||
368 | // if do not set roles, means: this page does not require permission | ||
369 | } | ||
370 | } | ||
371 | ] | ||
372 | }, | ||
373 | // { | 254 | // { |
374 | // path: '/icon', | 255 | // path: '/icon', |
375 | // component: Layout, | 256 | // component: Layout, |
376 | // children: [ | 257 | // children: [ |
377 | // { | 258 | // { |
378 | // path: 'index', | 259 | // path: 'index', |
379 | // component: () => import('@/views/icons/index'), | 260 | // component: () => import('@/views/icons/index'), |
380 | // name: 'Icons', | 261 | // name: 'Icons', |
381 | // meta: { title: 'icons', icon: 'icon', noCache: true } | 262 | // meta: { title: 'icons', icon: 'icon', noCache: true } |
382 | // } | 263 | // } |
383 | // ] | 264 | // ] |
384 | // }, | 265 | // }, |
385 | 266 | systemRouter, | |
386 | /** when your routing map is too long, you can split it into small modules **/ | 267 | /** when your routing map is too long, you can split it into small modules **/ |
387 | componentsRouter, | 268 | // componentsRouter, |
388 | chartsRouter, | 269 | // chartsRouter, |
389 | // nestedRouter, | 270 | // nestedRouter, |
390 | tableRouter, | 271 | // tableRouter, |
391 | userRouter, | ||
392 | 272 | ||
393 | // { | 273 | // { |
394 | // path: '/example', | 274 | // path: '/example', |
395 | // component: Layout, | 275 | // component: Layout, |
396 | // redirect: '/example/list', | 276 | // redirect: '/example/list', |
397 | // name: 'Example', | 277 | // name: 'Example', |
398 | // meta: { | 278 | // meta: { |
399 | // title: 'example', | 279 | // title: 'example', |
400 | // icon: 'example' | 280 | // icon: 'example' |
401 | // }, | 281 | // }, |
402 | // children: [ | 282 | // children: [ |
403 | // { | 283 | // { |
404 | // path: 'create', | 284 | // path: 'create', |
405 | // component: () => import('@/views/example/create'), | 285 | // component: () => import('@/views/example/create'), |
406 | // name: 'CreateArticle', | 286 | // name: 'CreateArticle', |
407 | // meta: { title: 'createArticle', icon: 'edit' } | 287 | // meta: { title: 'createArticle', icon: 'edit' } |
408 | // }, | 288 | // }, |
409 | // { | 289 | // { |
410 | // path: 'edit/:id(\\d+)', | 290 | // path: 'edit/:id(\\d+)', |
411 | // component: () => import('@/views/example/edit'), | 291 | // component: () => import('@/views/example/edit'), |
412 | // name: 'EditArticle', | 292 | // name: 'EditArticle', |
413 | // meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' }, | 293 | // meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' }, |
414 | // hidden: true | 294 | // hidden: true |
415 | // }, | 295 | // }, |
416 | // { | 296 | // { |
417 | // path: 'list', | 297 | // path: 'list', |
418 | // component: () => import('@/views/example/list'), | 298 | // component: () => import('@/views/example/list'), |
419 | // name: 'ArticleList', | 299 | // name: 'ArticleList', |
420 | // meta: { title: 'articleList', icon: 'list' } | 300 | // meta: { title: 'articleList', icon: 'list' } |
421 | // } | 301 | // } |
422 | // ] | 302 | // ] |
423 | // }, | 303 | // }, |
424 | 304 | ||
425 | // { | 305 | // { |
426 | // path: '/tab', | 306 | // path: '/tab', |
427 | // component: Layout, | 307 | // component: Layout, |
428 | // children: [ | 308 | // children: [ |
429 | // { | 309 | // { |
430 | // path: 'index', | 310 | // path: 'index', |
431 | // component: () => import('@/views/tab/index'), | 311 | // component: () => import('@/views/tab/index'), |
432 | // name: 'Tab', | 312 | // name: 'Tab', |
433 | // meta: { title: 'tab', icon: 'tab' } | 313 | // meta: { title: 'tab', icon: 'tab' } |
434 | // } | 314 | // } |
435 | // ] | 315 | // ] |
436 | // }, | 316 | // }, |
437 | 317 | ||
438 | // { | 318 | // { |
439 | // path: '/error', | 319 | // path: '/error', |
440 | // component: Layout, | 320 | // component: Layout, |
441 | // redirect: 'noRedirect', | 321 | // redirect: 'noRedirect', |
442 | // name: 'ErrorPages', | 322 | // name: 'ErrorPages', |
443 | // meta: { | 323 | // meta: { |
444 | // title: 'errorPages', | 324 | // title: 'errorPages', |
445 | // icon: '404' | 325 | // icon: '404' |
446 | // }, | 326 | // }, |
447 | // children: [ | 327 | // children: [ |
448 | // { | 328 | // { |
449 | // path: '401', | 329 | // path: '401', |
450 | // component: () => import('@/views/error-page/401'), | 330 | // component: () => import('@/views/error-page/401'), |
451 | // name: 'Page401', | 331 | // name: 'Page401', |
452 | // meta: { title: 'page401', noCache: true } | 332 | // meta: { title: 'page401', noCache: true } |
453 | // }, | 333 | // }, |
454 | // { | 334 | // { |
455 | // path: '404', | 335 | // path: '404', |
456 | // component: () => import('@/views/error-page/404'), | 336 | // component: () => import('@/views/error-page/404'), |
457 | // name: 'Page404', | 337 | // name: 'Page404', |
458 | // meta: { title: 'page404', noCache: true } | 338 | // meta: { title: 'page404', noCache: true } |
459 | // } | 339 | // } |
460 | // ] | 340 | // ] |
461 | // }, | 341 | // }, |
462 | 342 | ||
463 | // { | 343 | // { |
464 | // path: '/error-log', | 344 | // path: '/error-log', |
465 | // component: Layout, | 345 | // component: Layout, |
466 | // children: [ | 346 | // children: [ |
467 | // { | 347 | // { |
468 | // path: 'log', | 348 | // path: 'log', |
469 | // component: () => import('@/views/error-log/index'), | 349 | // component: () => import('@/views/error-log/index'), |
470 | // name: 'ErrorLog', | 350 | // name: 'ErrorLog', |
471 | // meta: { title: 'errorLog', icon: 'bug' } | 351 | // meta: { title: 'errorLog', icon: 'bug' } |
472 | // } | 352 | // } |
473 | // ] | 353 | // ] |
474 | // }, | 354 | // }, |
475 | 355 | ||
476 | // { | 356 | // { |
477 | // path: '/excel', | 357 | // path: '/excel', |
478 | // component: Layout, | 358 | // component: Layout, |
479 | // redirect: '/excel/export-excel', | 359 | // redirect: '/excel/export-excel', |
480 | // name: 'Excel', | 360 | // name: 'Excel', |
481 | // meta: { | 361 | // meta: { |
482 | // title: 'excel', | 362 | // title: 'excel', |
483 | // icon: 'excel' | 363 | // icon: 'excel' |
484 | // }, | 364 | // }, |
485 | // children: [ | 365 | // children: [ |
486 | // { | 366 | // { |
487 | // path: 'export-excel', | 367 | // path: 'export-excel', |
488 | // component: () => import('@/views/excel/export-excel'), | 368 | // component: () => import('@/views/excel/export-excel'), |
489 | // name: 'ExportExcel', | 369 | // name: 'ExportExcel', |
490 | // meta: { title: 'exportExcel' } | 370 | // meta: { title: 'exportExcel' } |
491 | // }, | 371 | // }, |
492 | // { | 372 | // { |
493 | // path: 'export-selected-excel', | 373 | // path: 'export-selected-excel', |
494 | // component: () => import('@/views/excel/select-excel'), | 374 | // component: () => import('@/views/excel/select-excel'), |
495 | // name: 'SelectExcel', | 375 | // name: 'SelectExcel', |
496 | // meta: { title: 'selectExcel' } | 376 | // meta: { title: 'selectExcel' } |
497 | // }, | 377 | // }, |
498 | // { | 378 | // { |
499 | // path: 'export-merge-header', | 379 | // path: 'export-merge-header', |
500 | // component: () => import('@/views/excel/merge-header'), | 380 | // component: () => import('@/views/excel/merge-header'), |
501 | // name: 'MergeHeader', | 381 | // name: 'MergeHeader', |
502 | // meta: { title: 'mergeHeader' } | 382 | // meta: { title: 'mergeHeader' } |
503 | // }, | 383 | // }, |
504 | // { | 384 | // { |
505 | // path: 'upload-excel', | 385 | // path: 'upload-excel', |
506 | // component: () => import('@/views/excel/upload-excel'), | 386 | // component: () => import('@/views/excel/upload-excel'), |
507 | // name: 'UploadExcel', | 387 | // name: 'UploadExcel', |
508 | // meta: { title: 'uploadExcel' } | 388 | // meta: { title: 'uploadExcel' } |
509 | // } | 389 | // } |
510 | // ] | 390 | // ] |
511 | // }, | 391 | // }, |
512 | 392 | ||
513 | // { | 393 | // { |
514 | // path: '/zip', | 394 | // path: '/zip', |
515 | // component: Layout, | 395 | // component: Layout, |
516 | // redirect: '/zip/download', | 396 | // redirect: '/zip/download', |
517 | // alwaysShow: true, | 397 | // alwaysShow: true, |
518 | // name: 'Zip', | 398 | // name: 'Zip', |
519 | // meta: { title: 'zip', icon: 'zip' }, | 399 | // meta: { title: 'zip', icon: 'zip' }, |
520 | // children: [ | 400 | // children: [ |
521 | // { | 401 | // { |
522 | // path: 'download', | 402 | // path: 'download', |
523 | // component: () => import('@/views/zip/index'), | 403 | // component: () => import('@/views/zip/index'), |
524 | // name: 'ExportZip', | 404 | // name: 'ExportZip', |
525 | // meta: { title: 'exportZip' } | 405 | // meta: { title: 'exportZip' } |
526 | // } | 406 | // } |
527 | // ] | 407 | // ] |
528 | // }, | 408 | // }, |
529 | 409 | ||
530 | // { | 410 | // { |
531 | // path: '/pdf', | 411 | // path: '/pdf', |
532 | // component: Layout, | 412 | // component: Layout, |
533 | // redirect: '/pdf/index', | 413 | // redirect: '/pdf/index', |
534 | // children: [ | 414 | // children: [ |
535 | // { | 415 | // { |
536 | // path: 'index', | 416 | // path: 'index', |
537 | // component: () => import('@/views/pdf/index'), | 417 | // component: () => import('@/views/pdf/index'), |
538 | // name: 'PDF', | 418 | // name: 'PDF', |
539 | // meta: { title: 'pdf', icon: 'pdf' } | 419 | // meta: { title: 'pdf', icon: 'pdf' } |
540 | // } | 420 | // } |
541 | // ] | 421 | // ] |
542 | // }, | 422 | // }, |
543 | // { | 423 | // { |
544 | // path: '/pdf/download', | 424 | // path: '/pdf/download', |
545 | // component: () => import('@/views/pdf/download'), | 425 | // component: () => import('@/views/pdf/download'), |
546 | // hidden: true | 426 | // hidden: true |
547 | // }, | 427 | // }, |
548 | 428 | ||
549 | // { | 429 | // { |
550 | // path: '/theme', | 430 | // path: '/theme', |
551 | // component: Layout, | 431 | // component: Layout, |
552 | // children: [ | 432 | // children: [ |
553 | // { | 433 | // { |
554 | // path: 'index', | 434 | // path: 'index', |
555 | // component: () => import('@/views/theme/index'), | 435 | // component: () => import('@/views/theme/index'), |
556 | // name: 'Theme', | 436 | // name: 'Theme', |
557 | // meta: { title: 'theme', icon: 'theme' } | 437 | // meta: { title: 'theme', icon: 'theme' } |
558 | // } | 438 | // } |
559 | // ] | 439 | // ] |
560 | // }, | 440 | // }, |
561 | 441 | ||
562 | // { | 442 | // { |
563 | // path: '/clipboard', | 443 | // path: '/clipboard', |
564 | // component: Layout, | 444 | // component: Layout, |
565 | // children: [ | 445 | // children: [ |
566 | // { | 446 | // { |
567 | // path: 'index', | 447 | // path: 'index', |
568 | // component: () => import('@/views/clipboard/index'), | 448 | // component: () => import('@/views/clipboard/index'), |
569 | // name: 'ClipboardDemo', | 449 | // name: 'ClipboardDemo', |
570 | // meta: { title: 'clipboardDemo', icon: 'clipboard' } | 450 | // meta: { title: 'clipboardDemo', icon: 'clipboard' } |
571 | // } | 451 | // } |
572 | // ] | 452 | // ] |
573 | // }, | 453 | // }, |
574 | 454 | ||
575 | // { | 455 | // { |
576 | // path: '/i18n', | 456 | // path: '/i18n', |
577 | // component: Layout, | 457 | // component: Layout, |
578 | // children: [ | 458 | // children: [ |
579 | // { | 459 | // { |
580 | // path: 'index', | 460 | // path: 'index', |
581 | // component: () => import('@/views/i18n-demo/index'), | 461 | // component: () => import('@/views/i18n-demo/index'), |
582 | // name: 'I18n', | 462 | // name: 'I18n', |
583 | // meta: { title: 'i18n', icon: 'international' } | 463 | // meta: { title: 'i18n', icon: 'international' } |
584 | // } | 464 | // } |
585 | // ] | 465 | // ] |
586 | // }, | 466 | // }, |
587 | 467 | ||
588 | // { | 468 | // { |
589 | // path: 'external-link', | 469 | // path: 'external-link', |
590 | // component: Layout, | 470 | // component: Layout, |
591 | // children: [ | 471 | // children: [ |
592 | // { | 472 | // { |
src/router/modules/meta.js
File was created | 1 | import Layout from '@/layout' | |
2 | |||
3 | const metaRouter = { | ||
4 | path: '/meta', | ||
5 | component: Layout, | ||
6 | redirect: '/meta/page', | ||
7 | alwaysShow: true, // will always show the root menu | ||
8 | name: 'Meta', | ||
9 | meta: { | ||
10 | title: 'metas.metas', | ||
11 | icon: 'zip', | ||
12 | roles: ['admin', 'assistant'] // you can set roles in root nav | ||
13 | }, | ||
14 | children: [{ | ||
15 | path: 'page', | ||
16 | component: () => import('@/views/meta/complex-table'), | ||
17 | name: 'MetaList', | ||
18 | meta: { | ||
19 | title: 'MetaList', | ||
20 | icon: 'zip', | ||
21 | roles: ['admin', 'assistant'] // or you can only set roles in sub nav | ||
22 | } | ||
23 | }] | ||
24 | } | ||
25 | export default metaRouter | ||
26 |
src/router/modules/prod.js
File was created | 1 | /** When your routing table is too long, you can split it into small modules**/ | |
2 | |||
3 | import Layout from '@/layout' | ||
4 | |||
5 | const prodRouter = { | ||
6 | path: '/prods', | ||
7 | component: Layout, | ||
8 | redirect: '/prod/page', | ||
9 | alwaysShow: true, // will always show the root menu | ||
10 | name: 'Prod', | ||
11 | meta: { | ||
12 | title: 'prods', // 会自动被i18n替换 | ||
13 | icon: 'star', | ||
14 | roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav | ||
15 | }, | ||
16 | children: [{ | ||
17 | path: 'page', | ||
18 | component: () => import('@/views/permission/page'), | ||
19 | name: 'ProdList', | ||
20 | meta: { | ||
21 | title: 'ProdList', | ||
22 | roles: ['admin', 'assistant', 'runner', 'shoper'] // or you can only set roles in sub nav | ||
23 | } | ||
24 | }, | ||
25 | { | ||
26 | path: 'defined', | ||
27 | component: () => import('@/views/permission/directive'), | ||
28 | name: 'ProdDefiend', | ||
29 | meta: { | ||
30 | title: 'ProdDefiend', | ||
31 | roles: ['admin', 'assistant', 'shoper'] | ||
32 | // if do not set roles, means: this page does not require permission | ||
33 | } | ||
34 | } | ||
35 | ] | ||
36 | } | ||
37 | |||
38 | export default prodRouter | ||
39 |
src/router/modules/system.js
File was created | 1 | import Layout from '@/layout' | |
2 | |||
3 | const systemRouter = { | ||
4 | path: '/system', | ||
5 | component: Layout, | ||
6 | redirect: '/system/page', | ||
7 | alwaysShow: true, // will always show the root menu | ||
8 | name: 'System', | ||
9 | meta: { | ||
10 | title: 'systems.systems', | ||
11 | icon: 'component', | ||
12 | roles: ['admin', 'assistant', 'runner'] // you can set roles in root nav | ||
13 | }, | ||
14 | children: [{ | ||
15 | path: 'page', | ||
16 | component: () => import('@/views/example/list'), | ||
17 | name: 'SystemList', | ||
18 | meta: { | ||
19 | title: 'systems.sites', | ||
20 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav | ||
21 | } | ||
22 | }, | ||
23 | { | ||
24 | path: 'page', | ||
25 | component: () => import('@/views/example/list'), | ||
26 | name: 'SystemList', | ||
27 | meta: { | ||
28 | title: 'systems.money', | ||
29 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav | ||
30 | } | ||
31 | }, | ||
32 | { | ||
33 | path: 'page', | ||
34 | component: () => import('@/views/example/list'), | ||
35 | name: 'SystemList', | ||
36 | meta: { | ||
37 | title: 'systems.industry', | ||
38 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav | ||
39 | } | ||
40 | }, | ||
41 | { | ||
42 | path: 'page', | ||
43 | component: () => import('@/views/example/list'), | ||
44 | name: 'SystemList', | ||
45 | meta: { | ||
46 | title: 'systems.template', | ||
47 | roles: ['admin', 'assistant', 'runner'] // or you can only set roles in sub nav | ||
48 | } | ||
49 | } | ||
50 | |||
51 | ] | ||
52 | } | ||
53 | |||
54 | export default systemRouter | ||
55 |
src/router/modules/user.js
1 | /** When your routing table is too long, you can split it into small modules**/ | 1 | /** When your routing table is too long, you can split it into small modules**/ |
2 | 2 | ||
3 | import Layout from '@/layout' | 3 | import Layout from '@/layout' |
4 | 4 | ||
5 | const chartsRouter = { | 5 | const chartsRouter = { |
6 | path: '/users', | 6 | path: '/users', |
7 | component: Layout, | 7 | component: Layout, |
8 | redirect: 'noRedirect', | 8 | redirect: '/users/page', |
9 | alwaysShow: true, // will always show the root menu | ||
9 | name: 'Users', | 10 | name: 'Users', |
10 | meta: { | 11 | meta: { |
11 | title: '用户管理', | 12 | title: 'users', |
12 | icon: 'peoples' | 13 | icon: 'peoples', |
14 | roles: ['admin', 'assistant'] // you can set roles in root nav | ||
13 | }, | 15 | }, |
14 | children: [ | 16 | children: [{ |
15 | { | 17 | path: 'page', |
16 | path: 'keyboard', | 18 | component: () => import('@/views/users/list'), |
17 | component: () => import('@/views/charts/keyboard'), | 19 | name: 'UserList', |
18 | name: 'KeyboardChart', | 20 | meta: { |
19 | meta: { title: 'keyboardChart', noCache: true } | 21 | title: 'UserList', |
20 | }, | 22 | roles: ['admin', 'assistant', 'shoper', 'runner'] // or you can only set roles in sub nav |
21 | { | ||
22 | path: 'line', | ||
23 | component: () => import('@/views/charts/line'), | ||
24 | name: 'LineChart', | ||
25 | meta: { title: 'lineChart', noCache: true } | ||
26 | }, | ||
27 | { | ||
28 | path: 'mix-chart', | ||
29 | component: () => import('@/views/charts/mix-chart'), | ||
30 | name: 'MixChart', | ||
31 | meta: { title: 'mixChart', noCache: true } | ||
32 | } | 23 | } |
24 | } | ||
25 | // ,{ | ||
26 | // path: '/icons', | ||
27 | // component: () => import('@/views/icons/index'), |
src/settings.js
1 | module.exports = { | 1 | module.exports = { |
2 | title: 'Vue Element Admin', | 2 | title: 'Let\'s fuck this workd', |
3 | 3 | ||
4 | /** | 4 | /** |
5 | * @type {boolean} true | false | 5 | * @type {boolean} true | false |
6 | * @description Whether show the settings right-panel | 6 | * @description Whether show the settings right-panel |
7 | */ | 7 | */ |
8 | showSettings: true, | 8 | showSettings: true, |
9 | 9 | ||
10 | /** | 10 | /** |
11 | * @type {boolean} true | false | 11 | * @type {boolean} true | false |
12 | * @description Whether need tagsView | 12 | * @description Whether need tagsView |
13 | */ | 13 | */ |
14 | tagsView: true, | 14 | tagsView: true, |
15 | 15 | ||
16 | /** | 16 | /** |
17 | * @type {boolean} true | false | 17 | * @type {boolean} true | false |
18 | * @description Whether fix the header | 18 | * @description Whether fix the header |
19 | */ | 19 | */ |
20 | fixedHeader: false, | 20 | fixedHeader: true, |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @type {boolean} true | false | 23 | * @type {boolean} true | false |
24 | * @description Whether show the logo in sidebar | 24 | * @description Whether show the logo in sidebar |
25 | */ | 25 | */ |
26 | sidebarLogo: false, | 26 | sidebarLogo: true, |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * @type {boolean} true | false | 29 | * @type {boolean} true | false |
30 | * @description Whether support pinyin search in headerSearch | 30 | * @description Whether support pinyin search in headerSearch |
31 | * Bundle size minified 47.3kb,minified + gzipped 63kb | 31 | * Bundle size minified 47.3kb,minified + gzipped 63kb |
32 | */ | 32 | */ |
33 | supportPinyinSearch: true, | 33 | supportPinyinSearch: true, |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * @type {string | array} 'production' | ['production', 'development'] | 36 | * @type {string | array} 'production' | ['production', 'development'] |
37 | * @description Need show err logs component. | 37 | * @description Need show err logs component. |
38 | * The default is only used in the production env | 38 | * The default is only used in the production env |
39 | * If you want to also use it in dev, you can pass ['production', 'development'] | 39 | * If you want to also use it in dev, you can pass ['production', 'development'] |
40 | */ | 40 | */ |
41 | errorLog: 'production' | 41 | errorLog: 'production' |
42 | } | 42 | } |
43 | 43 |
src/utils/request.js
1 | import axios from 'axios' | 1 | import axios from 'axios' |
2 | import { MessageBox, Message } from 'element-ui' | 2 | import qs from 'qs' |
3 | import { | ||
4 | MessageBox, | ||
5 | Message, | ||
6 | // Loading, | ||
7 | Notification | ||
8 | } from 'element-ui' | ||
3 | import store from '@/store' | 9 | import store from '@/store' |
4 | import { getToken } from '@/utils/auth' | 10 | import { |
11 | getToken | ||
12 | } from '@/utils/auth' | ||
5 | 13 | ||
6 | // create an axios instance | 14 | // create an axios instance |
7 | const service = axios.create({ | 15 | const service = axios.create({ |
8 | baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url | 16 | baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url |
9 | // withCredentials: true, // send cookies when cross-domain requests | 17 | withCredentials: true, // send cookies when cross-domain requests |
10 | timeout: 5000 // request timeout | 18 | timeout: 3000 // request timeout |
11 | }) | 19 | }) |
12 | 20 | // let loadingInstance | |
13 | // request interceptor | 21 | // request interceptor |
14 | service.interceptors.request.use( | 22 | service.interceptors.request.use( |
15 | config => { | 23 | config => { |
16 | // do something before request is sent | 24 | const token = sessionStorage.getItem('access_token') |
17 | 25 | // const csrf = store.getters.csrf | |
26 | if (token) { | ||
27 | config.headers = { | ||
28 | 'access-token': token, | ||
29 | 'Content-Type': 'application/x-www-form-urlencoded' | ||
30 | } | ||
31 | } | ||
32 | if (config.url === 'refresh') { | ||
33 | config.headers = { | ||
34 | 'refresh-token': sessionStorage.getItem('refresh_token'), | ||
35 | 'Content-Type': 'application/x-www-form-urlencoded' | ||
36 | } | ||
37 | } | ||
38 | // let options = { | ||
39 | // lock: true, | ||
40 | // fullscreen: false, | ||
41 | // text: '数据加载中……', | ||
42 | // // background: '#FFCC00', | ||
43 | // spinner: 'el-icon-loading' | ||
44 | // }; | ||
45 | const options = { | ||
46 | type: 'success', | ||
47 | message: config.url, | ||
48 | title: 'request axios ', | ||
49 | showClose: true, | ||
50 | duration: 3000 | ||
51 | } | ||
52 | Notification(options) | ||
53 | // loadingInstance = Loading.service(options); | ||
54 | config.method === 'post' | ||
55 | ? config.data = qs.stringify({ | ||
56 | ...config.data | ||
57 | }) | ||
58 | : config.params = { | ||
59 | ...config.params | ||
60 | } | ||
18 | if (store.getters.token) { | 61 | if (store.getters.token) { |
19 | // let each request carry token | 62 | // let each request carry token |
20 | // ['X-Token'] is a custom headers key | 63 | // ['X-Token'] is a custom headers key |
21 | // please modify it according to the actual situation | 64 | // please modify it according to the actual situation |
22 | config.headers['X-Token'] = getToken() | 65 | config.headers['X-Token'] = getToken() |
23 | } | 66 | } |
67 | config.headers['Content-Type'] = 'application/x-www-form-urlencoded' | ||
68 | |||
24 | return config | 69 | return config |
70 | // do something before request is sent | ||
25 | }, | 71 | }, |
26 | error => { | 72 | error => { |
27 | // do something with request error | 73 | // do something with request error |
74 | Message({ | ||
75 | message: error || 'Error', | ||
76 | type: 'error', | ||
77 | duration: 5 * 1000 | ||
78 | }) | ||
28 | console.log(error) // for debug | 79 | console.log(error) // for debug |
29 | return Promise.reject(error) | 80 | return Promise.reject(error) |
30 | } | 81 | } |
31 | ) | 82 | ) |
32 | 83 | ||
33 | // response interceptor | 84 | // response interceptor |
34 | service.interceptors.response.use( | 85 | service.interceptors.response.use( |
35 | /** | 86 | /** |
36 | * If you want to get http information such as headers or status | 87 | * If you want to get http information such as headers or status |
37 | * Please return response => response | 88 | * Please return response => response |
38 | */ | 89 | */ |
39 | 90 | ||
40 | /** | 91 | /** |
41 | * Determine the request status by custom code | 92 | * Determine the request status by custom code |
42 | * Here is just an example | 93 | * Here is just an example |
43 | * You can also judge the status by HTTP Status Code | 94 | * You can also judge the status by HTTP Status Code |
44 | */ | 95 | */ |
45 | response => { | 96 | response => { |
97 | const options = { | ||
98 | type: 'error', | ||
99 | message: response.status, | ||
100 | title: 'response status value ', | ||
101 | showClose: true, | ||
102 | duration: 1000 | ||
103 | } | ||
104 | Notification(options) | ||
105 | // Notification.close() | ||
106 | // 这里根据后端提供的数据进行对应的处理 | ||
107 | console.log('response===>', response) | ||
108 | // 定时刷新access-token | ||
109 | // if (!response.data.value && response.data.data.message === 'token invalid') { | ||
110 | // // 刷新token | ||
111 | // store.dispatch('refresh').then(response => { | ||
112 | // sessionStorage.setItem('access_token', response.data) | ||
113 | // }).catch(error => { | ||
114 | // throw new Error('token刷新' + error) | ||
115 | // }) | ||
116 | // } | ||
117 | |||
46 | const res = response.data | 118 | const res = response.data |
47 | 119 | ||
48 | // if the custom code is not 20000, it is judged as an error. | 120 | // if the custom code is not 20000, it is judged as an error. |
49 | if (res.code !== 20000) { | 121 | if (res.code !== 20000) { |
50 | Message({ | 122 | Message({ |
51 | message: res.message || 'Error', | 123 | message: res.message || 'Error', |
52 | type: 'error', | 124 | type: 'error', |
53 | duration: 5 * 1000 | 125 | duration: 5 * 1000 |
54 | }) | 126 | }) |
55 | 127 | ||
56 | // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; | 128 | // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; |
57 | if (res.code === 50008 || res.code === 50012 || res.code === 50014) { | 129 | if (res.code === 50008 || res.code === 50012 || res.code === 50014) { |
58 | // to re-login | 130 | // to re-login |
59 | MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { | 131 | MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { |
60 | confirmButtonText: 'Re-Login', | 132 | confirmButtonText: 'Re-Login', |
61 | cancelButtonText: 'Cancel', | 133 | cancelButtonText: 'Cancel', |
62 | type: 'warning' | 134 | type: 'warning' |
63 | }).then(() => { | 135 | }).then(() => { |
64 | store.dispatch('user/resetToken').then(() => { | 136 | store.dispatch('user/resetToken').then(() => { |
65 | location.reload() | 137 | location.reload() |
66 | }) | 138 | }) |
67 | }) | 139 | }) |
68 | } | 140 | } |
69 | return Promise.reject(new Error(res.message || 'Error')) | 141 | return Promise.reject(new Error(res.message || 'Error')) |
70 | } else { | 142 | } else { |
71 | return res | 143 | return res |
72 | } | 144 | } |
73 | }, | 145 | }, |
74 | error => { | 146 | error => { |
75 | console.log('err' + error) // for debug | 147 | console.log('error', error) |
148 | // console.log(JSON.stringify(error)); | ||
149 | // 500的状态也应该处理一下 | ||
150 | // 401-403的状态也应该处理一下 | ||
151 | const text = JSON.parse(JSON.stringify(error)).response.status === 404 | ||
152 | ? '404' | ||
153 | : '网络异常,请重试' | ||
76 | Message({ | 154 | Message({ |
77 | message: error.message, | 155 | message: text || 'Error', |
78 | type: 'error', | 156 | type: 'error', |
79 | duration: 5 * 1000 | 157 | duration: 5 * 1000 |
80 | }) | 158 | }) |
159 | |||
81 | return Promise.reject(error) | 160 | return Promise.reject(error) |
82 | } | 161 | } |
83 | ) | 162 | ) |
84 | 163 | ||
164 | // 假设你想移除拦截器 | ||
165 | // axios.interceptors.request.eject(service); | ||
166 | |||
85 | export default service | 167 | export default service |
86 | 168 |
src/views/dashboard/admin/index.vue
1 | <template> | 1 | <template> |
2 | <div class="dashboard-editor-container"> | 2 | <div class="dashboard-editor-container"> |
3 | <github-corner class="github-corner" /> | 3 | <!-- <github-corner class="github-corner" /> --> |
4 | 4 | ||
5 | <panel-group @handleSetLineChartData="handleSetLineChartData" /> | 5 | <panel-group @handleSetLineChartData="handleSetLineChartData" /> |
6 | 6 | ||
7 | <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> | 7 | <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> |
8 | <line-chart :chart-data="lineChartData" /> | 8 | <line-chart :chart-data="lineChartData" /> |
9 | </el-row> | 9 | </el-row> |
10 | 10 | ||
11 | <el-row :gutter="32"> | 11 | <el-row :gutter="32"> |
12 | <el-col :xs="24" :sm="24" :lg="8"> | 12 | <el-col :xs="24" :sm="24" :lg="8"> |
13 | <div class="chart-wrapper"> | 13 | <div class="chart-wrapper"> |
14 | <raddar-chart /> | 14 | <raddar-chart /> |
15 | </div> | 15 | </div> |
16 | </el-col> | 16 | </el-col> |
17 | <el-col :xs="24" :sm="24" :lg="8"> | 17 | <el-col :xs="24" :sm="24" :lg="8"> |
18 | <div class="chart-wrapper"> | 18 | <div class="chart-wrapper"> |
19 | <pie-chart /> | 19 | <pie-chart /> |
20 | </div> | 20 | </div> |
21 | </el-col> | 21 | </el-col> |
22 | <el-col :xs="24" :sm="24" :lg="8"> | 22 | <el-col :xs="24" :sm="24" :lg="8"> |
23 | <div class="chart-wrapper"> | 23 | <div class="chart-wrapper"> |
24 | <bar-chart /> | 24 | <bar-chart /> |
25 | </div> | 25 | </div> |
26 | </el-col> | 26 | </el-col> |
27 | </el-row> | 27 | </el-row> |
28 | 28 | ||
29 | <el-row :gutter="8"> | 29 | <el-row :gutter="8"> |
30 | <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;"> | 30 | <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;"> |
31 | <transaction-table /> | 31 | <transaction-table /> |
32 | </el-col> | 32 | </el-col> |
33 | <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;"> | 33 | <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;"> |
34 | <todo-list /> | 34 | <todo-list /> |
35 | </el-col> | 35 | </el-col> |
36 | <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;"> | 36 | <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;"> |
37 | <box-card /> | 37 | <box-card /> |
38 | </el-col> | 38 | </el-col> |
39 | </el-row> | 39 | </el-row> |
40 | </div> | 40 | </div> |
41 | </template> | 41 | </template> |
42 | 42 | ||
43 | <script> | 43 | <script> |
44 | import GithubCorner from '@/components/GithubCorner' | 44 | // import GithubCorner from '@/components/GithubCorner' |
45 | import PanelGroup from './components/PanelGroup' | 45 | import PanelGroup from './components/PanelGroup' |
46 | import LineChart from './components/LineChart' | 46 | import LineChart from './components/LineChart' |
47 | import RaddarChart from './components/RaddarChart' | 47 | import RaddarChart from './components/RaddarChart' |
48 | import PieChart from './components/PieChart' | 48 | import PieChart from './components/PieChart' |
49 | import BarChart from './components/BarChart' | 49 | import BarChart from './components/BarChart' |
50 | import TransactionTable from './components/TransactionTable' | 50 | import TransactionTable from './components/TransactionTable' |
51 | import TodoList from './components/TodoList' | 51 | import TodoList from './components/TodoList' |
52 | import BoxCard from './components/BoxCard' | 52 | import BoxCard from './components/BoxCard' |
53 | 53 | ||
54 | const lineChartData = { | 54 | const lineChartData = { |
55 | newVisitis: { | 55 | newVisitis: { |
56 | expectedData: [100, 120, 161, 134, 105, 160, 165], | 56 | expectedData: [100, 120, 161, 134, 105, 160, 165], |
57 | actualData: [120, 82, 91, 154, 162, 140, 145] | 57 | actualData: [120, 82, 91, 154, 162, 140, 145] |
58 | }, | 58 | }, |
59 | messages: { | 59 | messages: { |
60 | expectedData: [200, 192, 120, 144, 160, 130, 140], | 60 | expectedData: [200, 192, 120, 144, 160, 130, 140], |
61 | actualData: [180, 160, 151, 106, 145, 150, 130] | 61 | actualData: [180, 160, 151, 106, 145, 150, 130] |
62 | }, | 62 | }, |
63 | purchases: { | 63 | purchases: { |
64 | expectedData: [80, 100, 121, 104, 105, 90, 100], | 64 | expectedData: [80, 100, 121, 104, 105, 90, 100], |
65 | actualData: [120, 90, 100, 138, 142, 130, 130] | 65 | actualData: [120, 90, 100, 138, 142, 130, 130] |
66 | }, | 66 | }, |
67 | shoppings: { | 67 | shoppings: { |
68 | expectedData: [130, 140, 141, 142, 145, 150, 160], | 68 | expectedData: [130, 140, 141, 142, 145, 150, 160], |
69 | actualData: [120, 82, 91, 154, 162, 140, 130] | 69 | actualData: [120, 82, 91, 154, 162, 140, 130] |
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | export default { | 73 | export default { |
74 | name: 'DashboardAdmin', | 74 | name: 'DashboardAdmin', |
75 | components: { | 75 | components: { |
76 | GithubCorner, | 76 | // GithubCorner, |
77 | PanelGroup, | 77 | PanelGroup, |
78 | LineChart, | 78 | LineChart, |
79 | RaddarChart, | 79 | RaddarChart, |
80 | PieChart, | 80 | PieChart, |
81 | BarChart, | 81 | BarChart, |
82 | TransactionTable, | 82 | TransactionTable, |
83 | TodoList, | 83 | TodoList, |
84 | BoxCard | 84 | BoxCard |
85 | }, | 85 | }, |
86 | data() { | 86 | data() { |
87 | return { | 87 | return { |
88 | lineChartData: lineChartData.newVisitis | 88 | lineChartData: lineChartData.newVisitis |
89 | } | 89 | } |
90 | }, | 90 | }, |
91 | methods: { | 91 | methods: { |
92 | handleSetLineChartData(type) { | 92 | handleSetLineChartData(type) { |
93 | this.lineChartData = lineChartData[type] | 93 | this.lineChartData = lineChartData[type] |
94 | } | 94 | } |
95 | } | 95 | } |
96 | } | 96 | } |
97 | </script> | 97 | </script> |
98 | 98 | ||
99 | <style lang="scss" scoped> | 99 | <style lang="scss" scoped> |
100 | .dashboard-editor-container { | 100 | .dashboard-editor-container { |
101 | padding: 32px; | 101 | padding: 32px; |
102 | background-color: rgb(240, 242, 245); | 102 | background-color: rgb(240, 242, 245); |
103 | position: relative; | 103 | position: relative; |
104 | 104 | ||
105 | .github-corner { | 105 | .github-corner { |
106 | position: absolute; | 106 | position: absolute; |
107 | top: 0px; | 107 | top: 0px; |
108 | border: 0; | 108 | border: 0; |
109 | right: 0; | 109 | right: 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | .chart-wrapper { | 112 | .chart-wrapper { |
113 | background: #fff; | 113 | background: #fff; |
114 | padding: 16px 16px 0; | 114 | padding: 16px 16px 0; |
115 | margin-bottom: 32px; | 115 | margin-bottom: 32px; |
116 | } | 116 | } |
117 | } | 117 | } |
118 | 118 | ||
119 | @media (max-width:1024px) { | 119 | @media (max-width:1024px) { |
120 | .chart-wrapper { | 120 | .chart-wrapper { |
121 | padding: 8px; | 121 | padding: 8px; |
122 | } | 122 | } |
123 | } | 123 | } |
124 | </style> | 124 | </style> |
125 | 125 |
src/views/dashboard/editor/index.vue
1 | <template> | 1 | <template> |
2 | <div class="dashboard-editor-container"> | 2 | <div class="dashboard-editor-container"> |
3 | <div class=" clearfix"> | 3 | <div class="clearfix"> |
4 | <pan-thumb :image="avatar" style="float: left"> | 4 | <pan-thumb :image="avatar" style="float: left"> |
5 | Your roles: | 5 | Your roles: |
6 | <span v-for="item in roles" :key="item" class="pan-info-roles">{{ item }}</span> | 6 | <span v-for="item in roles" :key="item" class="pan-info-roles">{{ item }}</span> |
7 | </pan-thumb> | 7 | </pan-thumb> |
8 | <github-corner style="position: absolute; top: 0px; border: 0; right: 0;" /> | 8 | <github-corner style="position: absolute; top: 0px; border: 0; right: 0;" /> |
9 | <div class="info-container"> | 9 | <div class="info-container"> |
10 | <span class="display_name">{{ name }}</span> | 10 | <span class="display_name">{{ name }}</span> |
11 | <span style="font-size:20px;padding-top:20px;display:inline-block;">{{ roles }}'s Dashboard</span> | 11 | <span style="font-size:20px;padding-top:20px;display:inline-block;">{{ roles }}'s Dashboard</span> |
12 | </div> | 12 | </div> |
13 | </div> | 13 | </div> |
14 | <div> | 14 | <div> |
15 | <img :src="emptyGif" class="emptyGif"> | 15 | <img :src="emptyGif" class="emptyGif"> |
16 | </div> | 16 | </div> |
17 | </div> | 17 | </div> |
18 | </template> | 18 | </template> |
19 | 19 | ||
20 | <script> | 20 | <script> |
21 | import { mapGetters } from 'vuex' | 21 | import { mapGetters } from 'vuex' |
22 | import PanThumb from '@/components/PanThumb' | 22 | import PanThumb from '@/components/PanThumb' |
23 | import GithubCorner from '@/components/GithubCorner' | 23 | // import GithubCorner from '@/components/GithubCorner' |
24 | 24 | ||
25 | export default { | 25 | export default { |
26 | name: 'DashboardEditor', | 26 | name: 'DashboardEditor', |
27 | components: { PanThumb, GithubCorner }, | 27 | // components: { PanThumb, GithubCorner }, |
28 | components: { PanThumb }, | ||
28 | data() { | 29 | data() { |
29 | return { | 30 | return { |
30 | emptyGif: 'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3' | 31 | emptyGif: |
32 | 'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3' | ||
31 | } | 33 | } |
32 | }, | 34 | }, |
33 | computed: { | 35 | computed: { |
34 | ...mapGetters([ | 36 | ...mapGetters(['name', 'avatar', 'roles']) |
35 | 'name', | ||
36 | 'avatar', | ||
37 | 'roles' | ||
38 | ]) | ||
39 | } | 37 | } |
40 | } | 38 | } |
41 | </script> | 39 | </script> |
42 | 40 | ||
43 | <style lang="scss" scoped> | 41 | <style lang="scss" scoped> |
44 | .emptyGif { | 42 | .emptyGif { |
43 | display: block; | ||
44 | width: 45%; | ||
45 | margin: 0 auto; | ||
46 | } | ||
47 | |||
48 | .dashboard-editor-container { | ||
49 | background-color: #e3e3e3; | ||
50 | min-height: 100vh; | ||
51 | padding: 50px 60px 0px; | ||
52 | .pan-info-roles { | ||
53 | font-size: 12px; | ||
54 | font-weight: 700; | ||
55 | color: #333; | ||
45 | display: block; | 56 | display: block; |
46 | width: 45%; | ||
47 | margin: 0 auto; | ||
48 | } | 57 | } |
49 | 58 | .info-container { | |
50 | .dashboard-editor-container { | 59 | position: relative; |
51 | background-color: #e3e3e3; | 60 | margin-left: 190px; |
52 | min-height: 100vh; | 61 | height: 150px; |
53 | padding: 50px 60px 0px; | 62 | line-height: 200px; |
54 | .pan-info-roles { | 63 | .display_name { |
55 | font-size: 12px; | 64 | font-size: 48px; |
56 | font-weight: 700; | 65 | line-height: 48px; |
57 | color: #333; | 66 | color: #212121; |
58 | display: block; | 67 | position: absolute; |
59 | } | 68 | top: 25px; |
60 | .info-container { |
src/views/error-page/500.vue
File was created | 1 | <template> | |
2 | <div class="error-page"> | ||
3 | <div class="error-code"> | ||
4 | 5 | ||
5 | <span>0</span>0 | ||
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> | ||
58 |
src/views/error-page/502.vue
1 | <template> | File was deleted | |
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> | ||
58 | 1 | <template> |
src/views/login/index.vue
1 | <template> | 1 | <template> |
2 | <div class="login-container"> | 2 | <div class="login-container"> |
3 | <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left"> | 3 | <el-form |
4 | 4 | ref="loginForm" | |
5 | :model="loginForm" | ||
6 | :rules="loginRules" | ||
7 | class="login-form" | ||
8 | autocomplete="on" | ||
9 | label-position="left" | ||
10 | > | ||
5 | <div class="title-container"> | 11 | <div class="title-container"> |
6 | <h3 class="title"> | 12 | <h3 class="title">{{ $t('login.title') }}</h3> |
7 | {{ $t('login.title') }} | ||
8 | </h3> | ||
9 | <lang-select class="set-language" /> | 13 | <lang-select class="set-language" /> |
10 | </div> | 14 | </div> |
11 | 15 | ||
12 | <el-form-item prop="username"> | 16 | <el-form-item prop="username"> |
13 | <span class="svg-container"> | 17 | <span class="svg-container"> |
14 | <svg-icon icon-class="user" /> | 18 | <svg-icon icon-class="user" /> |
15 | </span> | 19 | </span> |
16 | <el-input | 20 | <el-input |
17 | ref="username" | 21 | ref="username" |
18 | v-model="loginForm.username" | 22 | v-model="loginForm.username" |
19 | :placeholder="$t('login.username')" | 23 | :placeholder="$t('login.username')" |
20 | name="username" | 24 | name="username" |
21 | type="text" | 25 | type="text" |
22 | tabindex="1" | 26 | tabindex="1" |
23 | autocomplete="on" | 27 | autocomplete="on" |
24 | /> | 28 | /> |
25 | </el-form-item> | 29 | </el-form-item> |
26 | 30 | ||
27 | <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual> | 31 | <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual> |
28 | <el-form-item prop="password"> | 32 | <el-form-item prop="password"> |
29 | <span class="svg-container"> | 33 | <span class="svg-container"> |
30 | <svg-icon icon-class="password" /> | 34 | <svg-icon icon-class="password" /> |
31 | </span> | 35 | </span> |
32 | <el-input | 36 | <el-input |
33 | :key="passwordType" | 37 | :key="passwordType" |
34 | ref="password" | 38 | ref="password" |
35 | v-model="loginForm.password" | 39 | v-model="loginForm.password" |
36 | :type="passwordType" | 40 | :type="passwordType" |
37 | :placeholder="$t('login.password')" | 41 | :placeholder="$t('login.password')" |
38 | name="password" | 42 | name="password" |
39 | tabindex="2" | 43 | tabindex="2" |
40 | autocomplete="on" | 44 | autocomplete="on" |
41 | @keyup.native="checkCapslock" | 45 | @keyup.native="checkCapslock" |
42 | @blur="capsTooltip = false" | 46 | @blur="capsTooltip = false" |
43 | @keyup.enter.native="handleLogin" | 47 | @keyup.enter.native="handleLogin" |
44 | /> | 48 | /> |
45 | <span class="show-pwd" @click="showPwd"> | 49 | <span class="show-pwd" @click="showPwd"> |
46 | <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> | 50 | <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> |
47 | </span> | 51 | </span> |
48 | </el-form-item> | 52 | </el-form-item> |
49 | </el-tooltip> | 53 | </el-tooltip> |
50 | 54 | <div | |
51 | <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin"> | 55 | style="position:relative;text-align:right;height:30px;line-height:30px;border:0px #000 solid;margin-top:-20px;" |
52 | {{ $t('login.logIn') }} | 56 | > |
53 | </el-button> | 57 | <!-- <el-checkbox v-model="checked">{{$t('rememberpassword')}}</el-checkbox> --> |
54 | 58 | <el-link type="primary">{{ $t('login.forgetpassword') }}</el-link> | |
59 | </div> | ||
60 | <el-button | ||
61 | :loading="loading" | ||
62 | type="primary" | ||
63 | style="width:100%;" | ||
64 | @click.native.prevent="handleLogin" | ||
65 | >{{ $t('login.logIn') }}</el-button> | ||
66 | <div | ||
67 | style="position:relative;text-align:right;height:30px;line-height:30px;border:0px #000 solid;margin-bottom:30px;" | ||
68 | > | ||
69 | <div class="tips"> | ||
70 | <el-link type="primary">{{ $t('login.signup') }}</el-link> | ||
71 | </div> | ||
72 | </div> | ||
55 | <div style="position:relative"> | 73 | <div style="position:relative"> |
56 | <div class="tips"> | 74 | <div class="tips"> |
57 | <span>{{ $t('login.username') }} : admin</span> | 75 | <span>{{ $t('login.username') }} : admin</span> |
58 | <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span> | 76 | <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span> |
59 | </div> | 77 | </div> |
60 | <div class="tips"> | 78 | <div class="tips"> |
61 | <span style="margin-right:18px;"> | 79 | <span style="margin-right:18px;">{{ $t('login.username') }} : assistant</span> |
62 | {{ $t('login.username') }} : editor | ||
63 | </span> | ||
64 | <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span> | 80 | <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span> |
65 | </div> | 81 | </div> |
66 | 82 | <div class="tips"> | |
67 | <el-button class="thirdparty-button" type="primary" @click="showDialog=true"> | 83 | <span style="margin-right:18px;">{{ $t('login.username') }} : runner</span> |
68 | {{ $t('login.thirdparty') }} | 84 | <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span> |
69 | </el-button> | 85 | </div> |
86 | <div class="tips"> | ||
87 | <span style="margin-right:18px;">{{ $t('login.username') }} : shoper</span> | ||
88 | <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span> | ||
89 | </div> | ||
90 | <el-button | ||
91 | class="thirdparty-button" | ||
92 | type="primary" | ||
93 | @click="showDialog=true" | ||
94 | >{{ $t('login.thirdparty') }}</el-button> | ||
70 | </div> | 95 | </div> |
71 | </el-form> | 96 | </el-form> |
72 | 97 | ||
73 | <el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog"> | 98 | <el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog"> |
74 | {{ $t('login.thirdpartyTips') }} | 99 | {{ $t('login.thirdpartyTips') }} |
75 | <br> | 100 | <br> |
76 | <br> | 101 | <br> |
77 | <br> | 102 | <br> |
78 | <social-sign /> | 103 | <social-sign /> |
79 | </el-dialog> | 104 | </el-dialog> |
105 | <!-- <vfd></vfd> --> | ||
80 | </div> | 106 | </div> |
81 | </template> | 107 | </template> |
82 | 108 | ||
83 | <script> | 109 | <script> |
84 | import { validUsername } from '@/utils/validate' | 110 | import { validUsername } from '@/utils/validate' |
85 | import LangSelect from '@/components/LangSelect' | 111 | import LangSelect from '@/components/LangSelect' |
86 | import SocialSign from './components/SocialSignin' | 112 | import SocialSign from './components/SocialSignin' |
87 | 113 | // import vfd from "vfd"; | |
88 | export default { | 114 | export default { |
89 | name: 'Login', | 115 | name: 'Login', |
116 | // components: { LangSelect, SocialSign, vfd }, | ||
90 | components: { LangSelect, SocialSign }, | 117 | components: { LangSelect, SocialSign }, |
91 | data() { | 118 | data() { |
92 | const validateUsername = (rule, value, callback) => { | 119 | const validateUsername = (rule, value, callback) => { |
93 | if (!validUsername(value)) { | 120 | if (!validUsername(value)) { |
94 | callback(new Error('Please enter the correct user name')) | 121 | callback(new Error('Please enter the correct user name')) |
95 | } else { | 122 | } else { |
96 | callback() | 123 | callback() |
97 | } | 124 | } |
98 | } | 125 | } |
99 | const validatePassword = (rule, value, callback) => { | 126 | const validatePassword = (rule, value, callback) => { |
100 | if (value.length < 6) { | 127 | if (value.length < 6) { |
101 | callback(new Error('The password can not be less than 6 digits')) | 128 | callback(new Error('The password can not be less than 6 digits')) |
102 | } else { | 129 | } else { |
103 | callback() | 130 | callback() |
104 | } | 131 | } |
105 | } | 132 | } |
106 | return { | 133 | return { |
107 | loginForm: { | 134 | loginForm: { |
108 | username: 'admin', | 135 | username: 'admin', |
109 | password: '111111' | 136 | password: '111111' |
110 | }, | 137 | }, |
111 | loginRules: { | 138 | loginRules: { |
112 | username: [{ required: true, trigger: 'blur', validator: validateUsername }], | 139 | username: [ |
113 | password: [{ required: true, trigger: 'blur', validator: validatePassword }] | 140 | { required: true, trigger: 'blur', validator: validateUsername } |
141 | ], | ||
142 | password: [ | ||
143 | { required: true, trigger: 'blur', validator: validatePassword } | ||
144 | ] | ||
114 | }, | 145 | }, |
115 | passwordType: 'password', | 146 | passwordType: 'password', |
116 | capsTooltip: false, | 147 | capsTooltip: false, |
117 | loading: false, | 148 | loading: false, |
118 | showDialog: false, | 149 | showDialog: false, |
119 | redirect: undefined, | 150 | redirect: undefined, |
120 | otherQuery: {} | 151 | otherQuery: {} |
121 | } | 152 | } |
122 | }, | 153 | }, |
123 | watch: { | 154 | watch: { |
124 | $route: { | 155 | $route: { |
125 | handler: function(route) { | 156 | handler: function(route) { |
126 | const query = route.query | 157 | const query = route.query |
127 | if (query) { | 158 | if (query) { |
128 | this.redirect = query.redirect | 159 | this.redirect = query.redirect |
129 | this.otherQuery = this.getOtherQuery(query) | 160 | this.otherQuery = this.getOtherQuery(query) |
130 | } | 161 | } |
131 | }, | 162 | }, |
132 | immediate: true | 163 | immediate: true |
133 | } | 164 | } |
134 | }, | 165 | }, |
135 | created() { | 166 | created() { |
136 | // window.addEventListener('storage', this.afterQRScan) | 167 | // window.addEventListener('storage', this.afterQRScan) |
137 | }, | 168 | }, |
138 | mounted() { | 169 | mounted() { |
139 | if (this.loginForm.username === '') { | 170 | if (this.loginForm.username === '') { |
140 | this.$refs.username.focus() | 171 | this.$refs.username.focus() |
141 | } else if (this.loginForm.password === '') { | 172 | } else if (this.loginForm.password === '') { |
142 | this.$refs.password.focus() | 173 | this.$refs.password.focus() |
143 | } | 174 | } |
144 | }, | 175 | }, |
145 | destroyed() { | 176 | destroyed() { |
146 | // window.removeEventListener('storage', this.afterQRScan) | 177 | // window.removeEventListener('storage', this.afterQRScan) |
147 | }, | 178 | }, |
148 | methods: { | 179 | methods: { |
149 | checkCapslock(e) { | 180 | checkCapslock(e) { |
150 | const { key } = e | 181 | const { key } = e |
151 | this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z') | 182 | this.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z' |
152 | }, | 183 | }, |
153 | showPwd() { | 184 | showPwd() { |
154 | if (this.passwordType === 'password') { | 185 | if (this.passwordType === 'password') { |
155 | this.passwordType = '' | 186 | this.passwordType = '' |
156 | } else { | 187 | } else { |
157 | this.passwordType = 'password' | 188 | this.passwordType = 'password' |
158 | } | 189 | } |
159 | this.$nextTick(() => { | 190 | this.$nextTick(() => { |
160 | this.$refs.password.focus() | 191 | this.$refs.password.focus() |
161 | }) | 192 | }) |
162 | }, | 193 | }, |
163 | handleLogin() { | 194 | handleLogin() { |
164 | this.$refs.loginForm.validate(valid => { | 195 | this.$refs.loginForm.validate(valid => { |
165 | if (valid) { | 196 | if (valid) { |
166 | this.loading = true | 197 | this.loading = true |
167 | this.$store.dispatch('user/login', this.loginForm) | 198 | this.$store |
199 | .dispatch('user/login', this.loginForm) | ||
168 | .then(() => { | 200 | .then(() => { |
169 | this.$router.push({ path: this.redirect || '/', query: this.otherQuery }) | 201 | this.$router.push({ |
202 | path: this.redirect || '/', | ||
203 | query: this.otherQuery | ||
204 | }) | ||
170 | this.loading = false | 205 | this.loading = false |
171 | }) | 206 | }) |
172 | .catch(() => { | 207 | .catch(() => { |
173 | this.loading = false | 208 | this.loading = false |
174 | }) | 209 | }) |
175 | } else { | 210 | } else { |
176 | console.log('error submit!!') | 211 | console.log('error submit!!') |
177 | return false | 212 | return false |
178 | } | 213 | } |
179 | }) | 214 | }) |
180 | }, | 215 | }, |
181 | getOtherQuery(query) { | 216 | getOtherQuery(query) { |
182 | return Object.keys(query).reduce((acc, cur) => { | 217 | return Object.keys(query).reduce((acc, cur) => { |
183 | if (cur !== 'redirect') { | 218 | if (cur !== 'redirect') { |
184 | acc[cur] = query[cur] | 219 | acc[cur] = query[cur] |
185 | } | 220 | } |
186 | return acc | 221 | return acc |
187 | }, {}) | 222 | }, {}) |
188 | } | 223 | } |
189 | // afterQRScan() { | 224 | // afterQRScan() { |
190 | // if (e.key === 'x-admin-oauth-code') { | 225 | // if (e.key === 'x-admin-oauth-code') { |
191 | // const code = getQueryObject(e.newValue) | 226 | // const code = getQueryObject(e.newValue) |
192 | // const codeMap = { | 227 | // const codeMap = { |
193 | // wechat: 'code', | 228 | // wechat: 'code', |
194 | // tencent: 'code' | 229 | // tencent: 'code' |
195 | // } | 230 | // } |
196 | // const type = codeMap[this.auth_type] | 231 | // const type = codeMap[this.auth_type] |
197 | // const codeName = code[type] | 232 | // const codeName = code[type] |
198 | // if (codeName) { | 233 | // if (codeName) { |
199 | // this.$store.dispatch('LoginByThirdparty', codeName).then(() => { | 234 | // this.$store.dispatch('LoginByThirdparty', codeName).then(() => { |
200 | // this.$router.push({ path: this.redirect || '/' }) | 235 | // this.$router.push({ path: this.redirect || '/' }) |
201 | // }) | 236 | // }) |
202 | // } else { | 237 | // } else { |
203 | // alert('第三方登录失败') | 238 | // alert('第三方登录失败') |
204 | // } | 239 | // } |
205 | // } | 240 | // } |
206 | // } | 241 | // } |
207 | } | 242 | } |
208 | } | 243 | } |
209 | </script> | 244 | </script> |
210 | 245 | ||
211 | <style lang="scss"> | 246 | <style lang="scss"> |
212 | /* 修复input 背景不协调 和光标变色 */ | 247 | /* 修复input 背景不协调 和光标变色 */ |
213 | /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ | 248 | /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ |
214 | 249 | ||
215 | $bg:#283443; | 250 | $bg: #283443; |
216 | $light_gray:#fff; | 251 | $light_gray: #fff; |
217 | $cursor: #fff; | 252 | $cursor: #fff; |
218 | 253 | ||
219 | @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { | 254 | @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { |
220 | .login-container .el-input input { | 255 | .login-container .el-input input { |
221 | color: $cursor; | 256 | color: $cursor; |
222 | } | 257 | } |
223 | } | 258 | } |
224 | 259 | ||
225 | /* reset element-ui css */ | 260 | /* reset element-ui css */ |
226 | .login-container { | 261 | .login-container { |
227 | .el-input { | 262 | .el-input { |
228 | display: inline-block; | 263 | display: inline-block; |
229 | height: 47px; | 264 | height: 47px; |
230 | width: 85%; | 265 | width: 85%; |
231 | 266 | ||
232 | input { | 267 | input { |
233 | background: transparent; | 268 | background: transparent; |
234 | border: 0px; | 269 | border: 0px; |
235 | -webkit-appearance: none; | 270 | -webkit-appearance: none; |
236 | border-radius: 0px; | 271 | border-radius: 0px; |
237 | padding: 12px 5px 12px 15px; | 272 | padding: 12px 5px 12px 15px; |
238 | color: $light_gray; | 273 | color: $light_gray; |
239 | height: 47px; | 274 | height: 47px; |
240 | caret-color: $cursor; | 275 | caret-color: $cursor; |
241 | 276 | ||
242 | &:-webkit-autofill { | 277 | &:-webkit-autofill { |
243 | box-shadow: 0 0 0px 1000px $bg inset !important; | 278 | box-shadow: 0 0 0px 1000px $bg inset !important; |
244 | -webkit-text-fill-color: $cursor !important; | 279 | -webkit-text-fill-color: $cursor !important; |
245 | } | 280 | } |
246 | } | 281 | } |
247 | } | 282 | } |
248 | 283 | ||
249 | .el-form-item { | 284 | .el-form-item { |
250 | border: 1px solid rgba(255, 255, 255, 0.1); | 285 | border: 1px solid rgba(255, 255, 255, 0.1); |
251 | background: rgba(0, 0, 0, 0.1); | 286 | background: rgba(0, 0, 0, 0.1); |
252 | border-radius: 5px; | 287 | border-radius: 5px; |
253 | color: #454545; | 288 | color: #454545; |
254 | } | 289 | } |
255 | } | 290 | } |
256 | </style> | 291 | </style> |
257 | 292 | ||
258 | <style lang="scss" scoped> | 293 | <style lang="scss" scoped> |
259 | $bg:#2d3a4b; | 294 | $bg: #2d3a4b; |
260 | $dark_gray:#889aa4; | 295 | $dark_gray: #889aa4; |
261 | $light_gray:#eee; | 296 | $light_gray: #eee; |
262 | 297 | ||
263 | .login-container { | 298 | .login-container { |
264 | min-height: 100%; | 299 | min-height: 100%; |
265 | width: 100%; | 300 | width: 100%; |
266 | background-color: $bg; | 301 | background-color: $bg; |
267 | overflow: hidden; | 302 | overflow: hidden; |
268 | 303 | ||
269 | .login-form { | 304 | .login-form { |
270 | position: relative; | 305 | position: relative; |
271 | width: 520px; | 306 | width: 520px; |
272 | max-width: 100%; | 307 | max-width: 100%; |
273 | padding: 160px 35px 0; | 308 | padding: 160px 35px 0; |
274 | margin: 0 auto; | 309 | margin: 0 auto; |
275 | overflow: hidden; | 310 | overflow: hidden; |
276 | } | 311 | } |
277 | 312 | ||
278 | .tips { | 313 | .tips { |
279 | font-size: 14px; | 314 | font-size: 14px; |
280 | color: #fff; | 315 | color: #fff; |
281 | margin-bottom: 10px; | 316 | margin-bottom: 10px; |
282 | 317 | ||
283 | span { | 318 | span { |
284 | &:first-of-type { | 319 | &:first-of-type { |
285 | margin-right: 16px; | 320 | margin-right: 16px; |
286 | } | 321 | } |
287 | } | 322 | } |
288 | } | 323 | } |
289 | 324 | ||
290 | .svg-container { | 325 | .svg-container { |
291 | padding: 6px 5px 6px 15px; | 326 | padding: 6px 5px 6px 15px; |
292 | color: $dark_gray; | 327 | color: $dark_gray; |
293 | vertical-align: middle; | 328 | vertical-align: middle; |
294 | width: 30px; | 329 | width: 30px; |
295 | display: inline-block; | 330 | display: inline-block; |
296 | } | 331 | } |
297 | 332 | ||
298 | .title-container { | 333 | .title-container { |
299 | position: relative; | 334 | position: relative; |
300 | 335 | ||
301 | .title { | 336 | .title { |
302 | font-size: 26px; | 337 | font-size: 26px; |
303 | color: $light_gray; | 338 | color: $light_gray; |
304 | margin: 0px auto 40px auto; | 339 | margin: 0px auto 40px auto; |
305 | text-align: center; | 340 | text-align: center; |
306 | font-weight: bold; | 341 | font-weight: bold; |
307 | } | 342 | } |
308 | 343 | ||
309 | .set-language { | 344 | .set-language { |
310 | color: #fff; | 345 | color: #fff; |
311 | position: absolute; | 346 | position: absolute; |
312 | top: 3px; | 347 | top: 3px; |
313 | font-size: 18px; | 348 | font-size: 18px; |
314 | right: 0px; | 349 | right: 0px; |
315 | cursor: pointer; | 350 | cursor: pointer; |
316 | } | 351 | } |
317 | } | 352 | } |
318 | 353 | ||
319 | .show-pwd { | 354 | .show-pwd { |
320 | position: absolute; | 355 | position: absolute; |
321 | right: 10px; | 356 | right: 10px; |
322 | top: 7px; | 357 | top: 7px; |
323 | font-size: 16px; | 358 | font-size: 16px; |
324 | color: $dark_gray; | 359 | color: $dark_gray; |
325 | cursor: pointer; | 360 | cursor: pointer; |
326 | user-select: none; | 361 | user-select: none; |
327 | } | 362 | } |
328 | 363 | ||
329 | .thirdparty-button { | 364 | .thirdparty-button { |
330 | position: absolute; | 365 | position: absolute; |
331 | right: 0; | 366 | right: 0; |
332 | bottom: 6px; | 367 | bottom: 6px; |
333 | } | 368 | } |
334 | 369 | ||
335 | @media only screen and (max-width: 470px) { | 370 | @media only screen and (max-width: 470px) { |
336 | .thirdparty-button { | 371 | .thirdparty-button { |
337 | display: none; | 372 | display: none; |
338 | } | 373 | } |
src/views/meta/complex-table.vue
1 | <template> | 1 | <template> |
2 | <div class="app-container"> | 2 | <div class="app-container"> |
3 | <div class="filter-container"> | 3 | <div class="filter-container"> |
4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> | 4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> |
5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> | 5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> |
6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> | 6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> |
7 | </el-select> | 7 | </el-select> |
8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> | 8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> |
9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> | 9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> |
10 | </el-select> | 10 | </el-select> |
11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> | 11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> |
12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> | 12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
13 | </el-select> | 13 | </el-select> |
14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> | 14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
15 | {{ $t('table.search') }} | 15 | {{ $t('table.search') }} |
16 | </el-button> | 16 | </el-button> |
17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> | 17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> |
18 | {{ $t('table.add') }} | 18 | {{ $t('table.add') }} |
19 | </el-button> | 19 | </el-button> |
20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> | 20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> |
21 | {{ $t('table.export') }} | 21 | {{ $t('table.export') }} |
22 | </el-button> | 22 | </el-button> |
23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> | 23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> |
24 | {{ $t('table.reviewer') }} | 24 | {{ $t('table.reviewer') }} |
25 | </el-checkbox> | 25 | </el-checkbox> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <el-table | 28 | <el-table |
29 | :key="tableKey" | 29 | :key="tableKey" |
30 | v-loading="listLoading" | 30 | v-loading="listLoading" |
31 | :data="list" | 31 | :data="list" |
32 | border | 32 | border |
33 | fit | 33 | fit |
34 | highlight-current-row | 34 | highlight-current-row |
35 | style="width: 100%;" | 35 | style="width: 100%;" |
36 | @sort-change="sortChange" | 36 | @sort-change="sortChange" |
37 | > | 37 | > |
38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> | 38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> |
39 | <template slot-scope="{row}"> | 39 | <template slot-scope="{row}"> |
40 | <span>{{ row.id }}</span> | 40 | <span>{{ row.id }}</span> |
41 | </template> | 41 | </template> |
42 | </el-table-column> | 42 | </el-table-column> |
43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> | 43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> |
44 | <template slot-scope="{row}"> | 44 | <template slot-scope="{row}"> |
45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> | 45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> |
46 | </template> | 46 | </template> |
47 | </el-table-column> | 47 | </el-table-column> |
48 | <el-table-column :label="$t('table.title')" min-width="150px"> | 48 | <el-table-column :label="$t('table.title')" min-width="150px"> |
49 | <template slot-scope="{row}"> | 49 | <template slot-scope="{row}"> |
50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> | 50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> |
51 | <el-tag>{{ row.type | typeFilter }}</el-tag> | 51 | <el-tag>{{ row.type | typeFilter }}</el-tag> |
52 | </template> | 52 | </template> |
53 | </el-table-column> | 53 | </el-table-column> |
54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> | 54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> |
55 | <template slot-scope="{row}"> | 55 | <template slot-scope="{row}"> |
56 | <span>{{ row.author }}</span> | 56 | <span>{{ row.author }}</span> |
57 | </template> | 57 | </template> |
58 | </el-table-column> | 58 | </el-table-column> |
59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> | 59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> |
60 | <template slot-scope="{row}"> | 60 | <template slot-scope="{row}"> |
61 | <span style="color:red;">{{ row.reviewer }}</span> | 61 | <span style="color:red;">{{ row.reviewer }}</span> |
62 | </template> | 62 | </template> |
63 | </el-table-column> | 63 | </el-table-column> |
64 | <el-table-column :label="$t('table.importance')" width="80px"> | 64 | <el-table-column :label="$t('table.importance')" width="80px"> |
65 | <template slot-scope="{row}"> | 65 | <template slot-scope="{row}"> |
66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> | 66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> |
67 | </template> | 67 | </template> |
68 | </el-table-column> | 68 | </el-table-column> |
69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> | 69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> |
70 | <template slot-scope="{row}"> | 70 | <template slot-scope="{row}"> |
71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> | 71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> |
72 | <span v-else>0</span> | 72 | <span v-else>0</span> |
73 | </template> | 73 | </template> |
74 | </el-table-column> | 74 | </el-table-column> |
75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> | 75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> |
76 | <template slot-scope="{row}"> | 76 | <template slot-scope="{row}"> |
77 | <el-tag :type="row.status | statusFilter"> | 77 | <el-tag :type="row.status | statusFilter"> |
78 | {{ row.status }} | 78 | {{ row.status }} |
79 | </el-tag> | 79 | </el-tag> |
80 | </template> | 80 | </template> |
81 | </el-table-column> | 81 | </el-table-column> |
82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> | 82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> |
83 | <template slot-scope="{row,$index}"> | 83 | <template slot-scope="{row,$index}"> |
84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> | 84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> |
85 | {{ $t('table.edit') }} | 85 | {{ $t('table.edit') }} |
86 | </el-button> | 86 | </el-button> |
87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> | 87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> |
88 | {{ $t('table.publish') }} | 88 | {{ $t('table.publish') }} |
89 | </el-button> | 89 | </el-button> |
90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> | 90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> |
91 | {{ $t('table.draft') }} | 91 | {{ $t('table.draft') }} |
92 | </el-button> | 92 | </el-button> |
93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> | 93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> |
94 | {{ $t('table.delete') }} | 94 | {{ $t('table.delete') }} |
95 | </el-button> | 95 | </el-button> |
96 | </template> | 96 | </template> |
97 | </el-table-column> | 97 | </el-table-column> |
98 | </el-table> | 98 | </el-table> |
99 | 99 | ||
100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> | 100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> |
101 | 101 | ||
102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> | 102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> |
103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> | 103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> |
104 | <el-form-item :label="$t('table.type')" prop="type"> | 104 | <el-form-item :label="$t('table.type')" prop="type"> |
105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> | 105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> |
106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> | 106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> |
107 | </el-select> | 107 | </el-select> |
108 | </el-form-item> | 108 | </el-form-item> |
109 | <el-form-item :label="$t('table.date')" prop="timestamp"> | 109 | <el-form-item :label="$t('table.date')" prop="timestamp"> |
110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> | 110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> |
111 | </el-form-item> | 111 | </el-form-item> |
112 | <el-form-item :label="$t('table.title')" prop="title"> | 112 | <el-form-item :label="$t('table.title')" prop="title"> |
113 | <el-input v-model="temp.title" /> | 113 | <el-input v-model="temp.title" /> |
114 | </el-form-item> | 114 | </el-form-item> |
115 | <el-form-item :label="$t('table.status')"> | 115 | <el-form-item :label="$t('table.status')"> |
116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> | 116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> |
117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> | 117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> |
118 | </el-select> | 118 | </el-select> |
119 | </el-form-item> | 119 | </el-form-item> |
120 | <el-form-item :label="$t('table.importance')"> | 120 | <el-form-item :label="$t('table.importance')"> |
121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> | 121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> |
122 | </el-form-item> | 122 | </el-form-item> |
123 | <el-form-item :label="$t('table.remark')"> | 123 | <el-form-item :label="$t('table.remark')"> |
124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> | 124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> |
125 | </el-form-item> | 125 | </el-form-item> |
126 | </el-form> | 126 | </el-form> |
127 | <div slot="footer" class="dialog-footer"> | 127 | <div slot="footer" class="dialog-footer"> |
128 | <el-button @click="dialogFormVisible = false"> | 128 | <el-button @click="dialogFormVisible = false"> |
129 | {{ $t('table.cancel') }} | 129 | {{ $t('table.cancel') }} |
130 | </el-button> | 130 | </el-button> |
131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> | 131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> |
132 | {{ $t('table.confirm') }} | 132 | {{ $t('table.confirm') }} |
133 | </el-button> | 133 | </el-button> |
134 | </div> | 134 | </div> |
135 | </el-dialog> | 135 | </el-dialog> |
136 | 136 | ||
137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> | 137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> |
138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> | 138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> |
139 | <el-table-column prop="key" label="Channel" /> | 139 | <el-table-column prop="key" label="Channel" /> |
140 | <el-table-column prop="pv" label="Pv" /> | 140 | <el-table-column prop="pv" label="Pv" /> |
141 | </el-table> | 141 | </el-table> |
142 | <span slot="footer" class="dialog-footer"> | 142 | <span slot="footer" class="dialog-footer"> |
143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> | 143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> |
144 | </span> | 144 | </span> |
145 | </el-dialog> | 145 | </el-dialog> |
146 | </div> | 146 | </div> |
147 | </template> | 147 | </template> |
148 | 148 | ||
149 | <script> | 149 | <script> |
150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' | 150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' |
151 | import waves from '@/directive/waves' // waves directive | 151 | import waves from '@/directive/waves' // waves directive |
152 | import { parseTime } from '@/utils' | 152 | import { parseTime } from '@/utils' |
153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination | 153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
154 | 154 | ||
155 | const calendarTypeOptions = [ | 155 | const calendarTypeOptions = [ |
156 | { key: 'CN', display_name: 'China' }, | 156 | { key: 'CN', display_name: 'China' }, |
157 | { key: 'US', display_name: 'USA' }, | 157 | { key: 'US', display_name: 'USA' }, |
158 | { key: 'JP', display_name: 'Japan' }, | 158 | { key: 'JP', display_name: 'Japan' }, |
159 | { key: 'EU', display_name: 'Eurozone' } | 159 | { key: 'EU', display_name: 'Eurozone' } |
160 | ] | 160 | ] |
161 | 161 | ||
162 | // arr to obj, such as { CN : "China", US : "USA" } | 162 | // arr to obj, such as { CN : "China", US : "USA" } |
163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { | 163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { |
164 | acc[cur.key] = cur.display_name | 164 | acc[cur.key] = cur.display_name |
165 | return acc | 165 | return acc |
166 | }, {}) | 166 | }, {}) |
167 | 167 | ||
168 | export default { | 168 | export default { |
169 | name: 'ComplexTable', | 169 | name: 'ComplexTable', |
170 | components: { Pagination }, | 170 | components: { Pagination }, |
171 | directives: { waves }, | 171 | directives: { waves }, |
172 | filters: { | 172 | filters: { |
173 | statusFilter(status) { | 173 | statusFilter(status) { |
174 | const statusMap = { | 174 | const statusMap = { |
175 | published: 'success', | 175 | published: 'success', |
176 | draft: 'info', | 176 | draft: 'info', |
177 | deleted: 'danger' | 177 | deleted: 'danger' |
178 | } | 178 | } |
179 | return statusMap[status] | 179 | return statusMap[status] |
180 | }, | 180 | }, |
181 | typeFilter(type) { | 181 | typeFilter(type) { |
182 | return calendarTypeKeyValue[type] | 182 | return calendarTypeKeyValue[type] |
183 | } | 183 | } |
184 | }, | 184 | }, |
185 | data() { | 185 | data() { |
186 | return { | 186 | return { |
187 | tableKey: 0, | 187 | tableKey: 0, |
188 | list: null, | 188 | list: null, |
189 | total: 0, | 189 | total: 0, |
190 | listLoading: true, | 190 | listLoading: true, |
191 | listQuery: { | 191 | listQuery: { |
192 | page: 1, | 192 | page: 1, |
193 | limit: 20, | 193 | limit: 20, |
194 | importance: undefined, | 194 | importance: undefined, |
195 | title: undefined, | 195 | title: undefined, |
196 | type: undefined, | 196 | type: undefined, |
197 | sort: '+id' | 197 | sort: '+id' |
198 | }, | 198 | }, |
199 | importanceOptions: [1, 2, 3], | 199 | importanceOptions: [1, 2, 3], |
200 | calendarTypeOptions, | 200 | calendarTypeOptions, |
201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], | 201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], |
202 | statusOptions: ['published', 'draft', 'deleted'], | 202 | statusOptions: ['published', 'draft', 'deleted'], |
203 | showReviewer: false, | 203 | showReviewer: false, |
204 | temp: { | 204 | temp: { |
205 | id: undefined, | 205 | id: undefined, |
206 | importance: 1, | 206 | importance: 1, |
207 | remark: '', | 207 | remark: '', |
208 | timestamp: new Date(), | 208 | timestamp: new Date(), |
209 | title: '', | 209 | title: '', |
210 | type: '', | 210 | type: '', |
211 | status: 'published' | 211 | status: 'published' |
212 | }, | 212 | }, |
213 | dialogFormVisible: false, | 213 | dialogFormVisible: false, |
214 | dialogStatus: '', | 214 | dialogStatus: '', |
215 | textMap: { | 215 | textMap: { |
216 | update: 'Edit', | 216 | update: 'Edit', |
217 | create: 'Create' | 217 | create: 'Create' |
218 | }, | 218 | }, |
219 | dialogPvVisible: false, | 219 | dialogPvVisible: false, |
220 | pvData: [], | 220 | pvData: [], |
221 | rules: { | 221 | rules: { |
222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], | 222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], |
223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], | 223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], |
224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] | 224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] |
225 | }, | 225 | }, |
226 | downloadLoading: false | 226 | downloadLoading: false |
227 | } | 227 | } |
228 | }, | 228 | }, |
229 | created() { | 229 | created() { |
230 | this.getList() | 230 | this.getList() |
231 | }, | 231 | }, |
232 | methods: { | 232 | methods: { |
233 | getList() { | 233 | getList() { |
234 | this.listLoading = true | 234 | this.listLoading = true |
235 | fetchList(this.listQuery).then(response => { | 235 | fetchList(this.listQuery).then(response => { |
236 | this.list = response.data.items | 236 | this.list = response.data.items |
237 | this.total = response.data.total | 237 | this.total = response.data.total |
238 | 238 | ||
239 | // Just to simulate the time of the request | 239 | // Just to simulate the time of the request |
240 | setTimeout(() => { | 240 | setTimeout(() => { |
241 | this.listLoading = false | 241 | this.listLoading = false |
242 | }, 1.5 * 1000) | 242 | }, 1.5 * 1000) |
243 | }) | 243 | }) |
244 | }, | 244 | }, |
245 | handleFilter() { | 245 | handleFilter() { |
246 | this.listQuery.page = 1 | 246 | this.listQuery.page = 1 |
247 | this.getList() | 247 | this.getList() |
248 | }, | 248 | }, |
249 | handleModifyStatus(row, status) { | 249 | handleModifyStatus(row, status) { |
250 | this.$message({ | 250 | this.$message({ |
251 | message: '操作成功', | 251 | message: '操作成功', |
252 | type: 'success' | 252 | type: 'success' |
253 | }) | 253 | }) |
254 | row.status = status | 254 | row.status = status |
255 | }, | 255 | }, |
256 | sortChange(data) { | 256 | sortChange(data) { |
257 | const { prop, order } = data | 257 | const { prop, order } = data |
258 | if (prop === 'id') { | 258 | if (prop === 'id') { |
259 | this.sortByID(order) | 259 | this.sortByID(order) |
260 | } | 260 | } |
261 | }, | 261 | }, |
262 | sortByID(order) { | 262 | sortByID(order) { |
263 | if (order === 'ascending') { | 263 | if (order === 'ascending') { |
264 | this.listQuery.sort = '+id' | 264 | this.listQuery.sort = '+id' |
265 | } else { | 265 | } else { |
266 | this.listQuery.sort = '-id' | 266 | this.listQuery.sort = '-id' |
267 | } | 267 | } |
268 | this.handleFilter() | 268 | this.handleFilter() |
269 | }, | 269 | }, |
270 | resetTemp() { | 270 | resetTemp() { |
271 | this.temp = { | 271 | this.temp = { |
272 | id: undefined, | 272 | id: undefined, |
273 | importance: 1, | 273 | importance: 1, |
274 | remark: '', | 274 | remark: '', |
275 | timestamp: new Date(), | 275 | timestamp: new Date(), |
276 | title: '', | 276 | title: '', |
277 | status: 'published', | 277 | status: 'published', |
278 | type: '' | 278 | type: '' |
279 | } | 279 | } |
280 | }, | 280 | }, |
281 | handleCreate() { | 281 | handleCreate() { |
282 | this.resetTemp() | 282 | this.resetTemp() |
283 | this.dialogStatus = 'create' | 283 | this.dialogStatus = 'create' |
284 | this.dialogFormVisible = true | 284 | this.dialogFormVisible = true |
285 | this.$nextTick(() => { | 285 | this.$nextTick(() => { |
286 | this.$refs['dataForm'].clearValidate() | 286 | this.$refs['dataForm'].clearValidate() |
287 | }) | 287 | }) |
288 | }, | 288 | }, |
289 | createData() { | 289 | createData() { |
290 | this.$refs['dataForm'].validate((valid) => { | 290 | this.$refs['dataForm'].validate((valid) => { |
291 | if (valid) { | 291 | if (valid) { |
292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id | 292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id |
293 | this.temp.author = 'vue-element-admin' | 293 | this.temp.author = '秀野堂主' |
294 | createArticle(this.temp).then(() => { | 294 | createArticle(this.temp).then(() => { |
295 | this.list.unshift(this.temp) | 295 | this.list.unshift(this.temp) |
296 | this.dialogFormVisible = false | 296 | this.dialogFormVisible = false |
297 | this.$notify({ | 297 | this.$notify({ |
298 | title: '成功', | 298 | title: '成功', |
299 | message: '创建成功', | 299 | message: '创建成功', |
300 | type: 'success', | 300 | type: 'success', |
301 | duration: 2000 | 301 | duration: 2000 |
302 | }) | 302 | }) |
303 | }) | 303 | }) |
304 | } | 304 | } |
305 | }) | 305 | }) |
306 | }, | 306 | }, |
307 | handleUpdate(row) { | 307 | handleUpdate(row) { |
308 | this.temp = Object.assign({}, row) // copy obj | 308 | this.temp = Object.assign({}, row) // copy obj |
309 | this.temp.timestamp = new Date(this.temp.timestamp) | 309 | this.temp.timestamp = new Date(this.temp.timestamp) |
310 | this.dialogStatus = 'update' | 310 | this.dialogStatus = 'update' |
311 | this.dialogFormVisible = true | 311 | this.dialogFormVisible = true |
312 | this.$nextTick(() => { | 312 | this.$nextTick(() => { |
313 | this.$refs['dataForm'].clearValidate() | 313 | this.$refs['dataForm'].clearValidate() |
314 | }) | 314 | }) |
315 | }, | 315 | }, |
316 | updateData() { | 316 | updateData() { |
317 | this.$refs['dataForm'].validate((valid) => { | 317 | this.$refs['dataForm'].validate((valid) => { |
318 | if (valid) { | 318 | if (valid) { |
319 | const tempData = Object.assign({}, this.temp) | 319 | const tempData = Object.assign({}, this.temp) |
320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 | 320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 |
321 | updateArticle(tempData).then(() => { | 321 | updateArticle(tempData).then(() => { |
322 | const index = this.list.findIndex(v => v.id === this.temp.id) | 322 | const index = this.list.findIndex(v => v.id === this.temp.id) |
323 | this.list.splice(index, 1, this.temp) | 323 | this.list.splice(index, 1, this.temp) |
324 | this.dialogFormVisible = false | 324 | this.dialogFormVisible = false |
325 | this.$notify({ | 325 | this.$notify({ |
326 | title: '成功', | 326 | title: '成功', |
327 | message: '更新成功', | 327 | message: '更新成功', |
328 | type: 'success', | 328 | type: 'success', |
329 | duration: 2000 | 329 | duration: 2000 |
330 | }) | 330 | }) |
331 | }) | 331 | }) |
332 | } | 332 | } |
333 | }) | 333 | }) |
334 | }, | 334 | }, |
335 | handleDelete(row, index) { | 335 | handleDelete(row, index) { |
336 | this.$notify({ | 336 | this.$notify({ |
337 | title: '成功', | 337 | title: '成功', |
338 | message: '删除成功', | 338 | message: '删除成功', |
339 | type: 'success', | 339 | type: 'success', |
340 | duration: 2000 | 340 | duration: 2000 |
341 | }) | 341 | }) |
342 | this.list.splice(index, 1) | 342 | this.list.splice(index, 1) |
343 | }, | 343 | }, |
344 | handleFetchPv(pv) { | 344 | handleFetchPv(pv) { |
345 | fetchPv(pv).then(response => { | 345 | fetchPv(pv).then(response => { |
346 | this.pvData = response.data.pvData | 346 | this.pvData = response.data.pvData |
347 | this.dialogPvVisible = true | 347 | this.dialogPvVisible = true |
348 | }) | 348 | }) |
349 | }, | 349 | }, |
350 | handleDownload() { | 350 | handleDownload() { |
351 | this.downloadLoading = true | 351 | this.downloadLoading = true |
352 | import('@/vendor/Export2Excel').then(excel => { | 352 | import('@/vendor/Export2Excel').then(excel => { |
353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] | 353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] |
354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] | 354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] |
355 | const data = this.formatJson(filterVal) | 355 | const data = this.formatJson(filterVal) |
356 | excel.export_json_to_excel({ | 356 | excel.export_json_to_excel({ |
357 | header: tHeader, | 357 | header: tHeader, |
358 | data, | 358 | data, |
359 | filename: 'table-list' | 359 | filename: 'table-list' |
360 | }) | 360 | }) |
361 | this.downloadLoading = false | 361 | this.downloadLoading = false |
362 | }) | 362 | }) |
363 | }, | 363 | }, |
364 | formatJson(filterVal) { | 364 | formatJson(filterVal) { |
365 | return this.list.map(v => filterVal.map(j => { | 365 | return this.list.map(v => filterVal.map(j => { |
366 | if (j === 'timestamp') { | 366 | if (j === 'timestamp') { |
367 | return parseTime(v[j]) | 367 | return parseTime(v[j]) |
368 | } else { | 368 | } else { |
369 | return v[j] | 369 | return v[j] |
370 | } | 370 | } |
371 | })) | 371 | })) |
372 | }, | 372 | }, |
373 | getSortClass: function(key) { | 373 | getSortClass: function(key) { |
374 | const sort = this.listQuery.sort | 374 | const sort = this.listQuery.sort |
375 | return sort === `+${key}` ? 'ascending' : 'descending' | 375 | return sort === `+${key}` ? 'ascending' : 'descending' |
376 | } | 376 | } |
377 | } | 377 | } |
378 | } | 378 | } |
379 | </script> | 379 | </script> |
380 | 380 |
src/views/order/complex-table.vue
1 | <template> | 1 | <template> |
2 | <div class="app-container"> | 2 | <div class="app-container"> |
3 | <div class="filter-container"> | 3 | <div class="filter-container"> |
4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> | 4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> |
5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> | 5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> |
6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> | 6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> |
7 | </el-select> | 7 | </el-select> |
8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> | 8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> |
9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> | 9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> |
10 | </el-select> | 10 | </el-select> |
11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> | 11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> |
12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> | 12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
13 | </el-select> | 13 | </el-select> |
14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> | 14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
15 | {{ $t('table.search') }} | 15 | {{ $t('table.search') }} |
16 | </el-button> | 16 | </el-button> |
17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> | 17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> |
18 | {{ $t('table.add') }} | 18 | {{ $t('table.add') }} |
19 | </el-button> | 19 | </el-button> |
20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> | 20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> |
21 | {{ $t('table.export') }} | 21 | {{ $t('table.export') }} |
22 | </el-button> | 22 | </el-button> |
23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> | 23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> |
24 | {{ $t('table.reviewer') }} | 24 | {{ $t('table.reviewer') }} |
25 | </el-checkbox> | 25 | </el-checkbox> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <el-table | 28 | <el-table |
29 | :key="tableKey" | 29 | :key="tableKey" |
30 | v-loading="listLoading" | 30 | v-loading="listLoading" |
31 | :data="list" | 31 | :data="list" |
32 | border | 32 | border |
33 | fit | 33 | fit |
34 | highlight-current-row | 34 | highlight-current-row |
35 | style="width: 100%;" | 35 | style="width: 100%;" |
36 | @sort-change="sortChange" | 36 | @sort-change="sortChange" |
37 | > | 37 | > |
38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> | 38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> |
39 | <template slot-scope="{row}"> | 39 | <template slot-scope="{row}"> |
40 | <span>{{ row.id }}</span> | 40 | <span>{{ row.id }}</span> |
41 | </template> | 41 | </template> |
42 | </el-table-column> | 42 | </el-table-column> |
43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> | 43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> |
44 | <template slot-scope="{row}"> | 44 | <template slot-scope="{row}"> |
45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> | 45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> |
46 | </template> | 46 | </template> |
47 | </el-table-column> | 47 | </el-table-column> |
48 | <el-table-column :label="$t('table.title')" min-width="150px"> | 48 | <el-table-column :label="$t('table.title')" min-width="150px"> |
49 | <template slot-scope="{row}"> | 49 | <template slot-scope="{row}"> |
50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> | 50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> |
51 | <el-tag>{{ row.type | typeFilter }}</el-tag> | 51 | <el-tag>{{ row.type | typeFilter }}</el-tag> |
52 | </template> | 52 | </template> |
53 | </el-table-column> | 53 | </el-table-column> |
54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> | 54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> |
55 | <template slot-scope="{row}"> | 55 | <template slot-scope="{row}"> |
56 | <span>{{ row.author }}</span> | 56 | <span>{{ row.author }}</span> |
57 | </template> | 57 | </template> |
58 | </el-table-column> | 58 | </el-table-column> |
59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> | 59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> |
60 | <template slot-scope="{row}"> | 60 | <template slot-scope="{row}"> |
61 | <span style="color:red;">{{ row.reviewer }}</span> | 61 | <span style="color:red;">{{ row.reviewer }}</span> |
62 | </template> | 62 | </template> |
63 | </el-table-column> | 63 | </el-table-column> |
64 | <el-table-column :label="$t('table.importance')" width="80px"> | 64 | <el-table-column :label="$t('table.importance')" width="80px"> |
65 | <template slot-scope="{row}"> | 65 | <template slot-scope="{row}"> |
66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> | 66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> |
67 | </template> | 67 | </template> |
68 | </el-table-column> | 68 | </el-table-column> |
69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> | 69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> |
70 | <template slot-scope="{row}"> | 70 | <template slot-scope="{row}"> |
71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> | 71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> |
72 | <span v-else>0</span> | 72 | <span v-else>0</span> |
73 | </template> | 73 | </template> |
74 | </el-table-column> | 74 | </el-table-column> |
75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> | 75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> |
76 | <template slot-scope="{row}"> | 76 | <template slot-scope="{row}"> |
77 | <el-tag :type="row.status | statusFilter"> | 77 | <el-tag :type="row.status | statusFilter"> |
78 | {{ row.status }} | 78 | {{ row.status }} |
79 | </el-tag> | 79 | </el-tag> |
80 | </template> | 80 | </template> |
81 | </el-table-column> | 81 | </el-table-column> |
82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> | 82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> |
83 | <template slot-scope="{row,$index}"> | 83 | <template slot-scope="{row,$index}"> |
84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> | 84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> |
85 | {{ $t('table.edit') }} | 85 | {{ $t('table.edit') }} |
86 | </el-button> | 86 | </el-button> |
87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> | 87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> |
88 | {{ $t('table.publish') }} | 88 | {{ $t('table.publish') }} |
89 | </el-button> | 89 | </el-button> |
90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> | 90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> |
91 | {{ $t('table.draft') }} | 91 | {{ $t('table.draft') }} |
92 | </el-button> | 92 | </el-button> |
93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> | 93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> |
94 | {{ $t('table.delete') }} | 94 | {{ $t('table.delete') }} |
95 | </el-button> | 95 | </el-button> |
96 | </template> | 96 | </template> |
97 | </el-table-column> | 97 | </el-table-column> |
98 | </el-table> | 98 | </el-table> |
99 | 99 | ||
100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> | 100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> |
101 | 101 | ||
102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> | 102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> |
103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> | 103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> |
104 | <el-form-item :label="$t('table.type')" prop="type"> | 104 | <el-form-item :label="$t('table.type')" prop="type"> |
105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> | 105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> |
106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> | 106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> |
107 | </el-select> | 107 | </el-select> |
108 | </el-form-item> | 108 | </el-form-item> |
109 | <el-form-item :label="$t('table.date')" prop="timestamp"> | 109 | <el-form-item :label="$t('table.date')" prop="timestamp"> |
110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> | 110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> |
111 | </el-form-item> | 111 | </el-form-item> |
112 | <el-form-item :label="$t('table.title')" prop="title"> | 112 | <el-form-item :label="$t('table.title')" prop="title"> |
113 | <el-input v-model="temp.title" /> | 113 | <el-input v-model="temp.title" /> |
114 | </el-form-item> | 114 | </el-form-item> |
115 | <el-form-item :label="$t('table.status')"> | 115 | <el-form-item :label="$t('table.status')"> |
116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> | 116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> |
117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> | 117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> |
118 | </el-select> | 118 | </el-select> |
119 | </el-form-item> | 119 | </el-form-item> |
120 | <el-form-item :label="$t('table.importance')"> | 120 | <el-form-item :label="$t('table.importance')"> |
121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> | 121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> |
122 | </el-form-item> | 122 | </el-form-item> |
123 | <el-form-item :label="$t('table.remark')"> | 123 | <el-form-item :label="$t('table.remark')"> |
124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> | 124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> |
125 | </el-form-item> | 125 | </el-form-item> |
126 | </el-form> | 126 | </el-form> |
127 | <div slot="footer" class="dialog-footer"> | 127 | <div slot="footer" class="dialog-footer"> |
128 | <el-button @click="dialogFormVisible = false"> | 128 | <el-button @click="dialogFormVisible = false"> |
129 | {{ $t('table.cancel') }} | 129 | {{ $t('table.cancel') }} |
130 | </el-button> | 130 | </el-button> |
131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> | 131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> |
132 | {{ $t('table.confirm') }} | 132 | {{ $t('table.confirm') }} |
133 | </el-button> | 133 | </el-button> |
134 | </div> | 134 | </div> |
135 | </el-dialog> | 135 | </el-dialog> |
136 | 136 | ||
137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> | 137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> |
138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> | 138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> |
139 | <el-table-column prop="key" label="Channel" /> | 139 | <el-table-column prop="key" label="Channel" /> |
140 | <el-table-column prop="pv" label="Pv" /> | 140 | <el-table-column prop="pv" label="Pv" /> |
141 | </el-table> | 141 | </el-table> |
142 | <span slot="footer" class="dialog-footer"> | 142 | <span slot="footer" class="dialog-footer"> |
143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> | 143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> |
144 | </span> | 144 | </span> |
145 | </el-dialog> | 145 | </el-dialog> |
146 | </div> | 146 | </div> |
147 | </template> | 147 | </template> |
148 | 148 | ||
149 | <script> | 149 | <script> |
150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' | 150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' |
151 | import waves from '@/directive/waves' // waves directive | 151 | import waves from '@/directive/waves' // waves directive |
152 | import { parseTime } from '@/utils' | 152 | import { parseTime } from '@/utils' |
153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination | 153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
154 | 154 | ||
155 | const calendarTypeOptions = [ | 155 | const calendarTypeOptions = [ |
156 | { key: 'CN', display_name: 'China' }, | 156 | { key: 'CN', display_name: 'China' }, |
157 | { key: 'US', display_name: 'USA' }, | 157 | { key: 'US', display_name: 'USA' }, |
158 | { key: 'JP', display_name: 'Japan' }, | 158 | { key: 'JP', display_name: 'Japan' }, |
159 | { key: 'EU', display_name: 'Eurozone' } | 159 | { key: 'EU', display_name: 'Eurozone' } |
160 | ] | 160 | ] |
161 | 161 | ||
162 | // arr to obj, such as { CN : "China", US : "USA" } | 162 | // arr to obj, such as { CN : "China", US : "USA" } |
163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { | 163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { |
164 | acc[cur.key] = cur.display_name | 164 | acc[cur.key] = cur.display_name |
165 | return acc | 165 | return acc |
166 | }, {}) | 166 | }, {}) |
167 | 167 | ||
168 | export default { | 168 | export default { |
169 | name: 'ComplexTable', | 169 | name: 'ComplexTable', |
170 | components: { Pagination }, | 170 | components: { Pagination }, |
171 | directives: { waves }, | 171 | directives: { waves }, |
172 | filters: { | 172 | filters: { |
173 | statusFilter(status) { | 173 | statusFilter(status) { |
174 | const statusMap = { | 174 | const statusMap = { |
175 | published: 'success', | 175 | published: 'success', |
176 | draft: 'info', | 176 | draft: 'info', |
177 | deleted: 'danger' | 177 | deleted: 'danger' |
178 | } | 178 | } |
179 | return statusMap[status] | 179 | return statusMap[status] |
180 | }, | 180 | }, |
181 | typeFilter(type) { | 181 | typeFilter(type) { |
182 | return calendarTypeKeyValue[type] | 182 | return calendarTypeKeyValue[type] |
183 | } | 183 | } |
184 | }, | 184 | }, |
185 | data() { | 185 | data() { |
186 | return { | 186 | return { |
187 | tableKey: 0, | 187 | tableKey: 0, |
188 | list: null, | 188 | list: null, |
189 | total: 0, | 189 | total: 0, |
190 | listLoading: true, | 190 | listLoading: true, |
191 | listQuery: { | 191 | listQuery: { |
192 | page: 1, | 192 | page: 1, |
193 | limit: 20, | 193 | limit: 20, |
194 | importance: undefined, | 194 | importance: undefined, |
195 | title: undefined, | 195 | title: undefined, |
196 | type: undefined, | 196 | type: undefined, |
197 | sort: '+id' | 197 | sort: '+id' |
198 | }, | 198 | }, |
199 | importanceOptions: [1, 2, 3], | 199 | importanceOptions: [1, 2, 3], |
200 | calendarTypeOptions, | 200 | calendarTypeOptions, |
201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], | 201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], |
202 | statusOptions: ['published', 'draft', 'deleted'], | 202 | statusOptions: ['published', 'draft', 'deleted'], |
203 | showReviewer: false, | 203 | showReviewer: false, |
204 | temp: { | 204 | temp: { |
205 | id: undefined, | 205 | id: undefined, |
206 | importance: 1, | 206 | importance: 1, |
207 | remark: '', | 207 | remark: '', |
208 | timestamp: new Date(), | 208 | timestamp: new Date(), |
209 | title: '', | 209 | title: '', |
210 | type: '', | 210 | type: '', |
211 | status: 'published' | 211 | status: 'published' |
212 | }, | 212 | }, |
213 | dialogFormVisible: false, | 213 | dialogFormVisible: false, |
214 | dialogStatus: '', | 214 | dialogStatus: '', |
215 | textMap: { | 215 | textMap: { |
216 | update: 'Edit', | 216 | update: 'Edit', |
217 | create: 'Create' | 217 | create: 'Create' |
218 | }, | 218 | }, |
219 | dialogPvVisible: false, | 219 | dialogPvVisible: false, |
220 | pvData: [], | 220 | pvData: [], |
221 | rules: { | 221 | rules: { |
222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], | 222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], |
223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], | 223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], |
224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] | 224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] |
225 | }, | 225 | }, |
226 | downloadLoading: false | 226 | downloadLoading: false |
227 | } | 227 | } |
228 | }, | 228 | }, |
229 | created() { | 229 | created() { |
230 | this.getList() | 230 | this.getList() |
231 | }, | 231 | }, |
232 | methods: { | 232 | methods: { |
233 | getList() { | 233 | getList() { |
234 | this.listLoading = true | 234 | this.listLoading = true |
235 | fetchList(this.listQuery).then(response => { | 235 | fetchList(this.listQuery).then(response => { |
236 | this.list = response.data.items | 236 | this.list = response.data.items |
237 | this.total = response.data.total | 237 | this.total = response.data.total |
238 | 238 | ||
239 | // Just to simulate the time of the request | 239 | // Just to simulate the time of the request |
240 | setTimeout(() => { | 240 | setTimeout(() => { |
241 | this.listLoading = false | 241 | this.listLoading = false |
242 | }, 1.5 * 1000) | 242 | }, 1.5 * 1000) |
243 | }) | 243 | }) |
244 | }, | 244 | }, |
245 | handleFilter() { | 245 | handleFilter() { |
246 | this.listQuery.page = 1 | 246 | this.listQuery.page = 1 |
247 | this.getList() | 247 | this.getList() |
248 | }, | 248 | }, |
249 | handleModifyStatus(row, status) { | 249 | handleModifyStatus(row, status) { |
250 | this.$message({ | 250 | this.$message({ |
251 | message: '操作成功', | 251 | message: '操作成功', |
252 | type: 'success' | 252 | type: 'success' |
253 | }) | 253 | }) |
254 | row.status = status | 254 | row.status = status |
255 | }, | 255 | }, |
256 | sortChange(data) { | 256 | sortChange(data) { |
257 | const { prop, order } = data | 257 | const { prop, order } = data |
258 | if (prop === 'id') { | 258 | if (prop === 'id') { |
259 | this.sortByID(order) | 259 | this.sortByID(order) |
260 | } | 260 | } |
261 | }, | 261 | }, |
262 | sortByID(order) { | 262 | sortByID(order) { |
263 | if (order === 'ascending') { | 263 | if (order === 'ascending') { |
264 | this.listQuery.sort = '+id' | 264 | this.listQuery.sort = '+id' |
265 | } else { | 265 | } else { |
266 | this.listQuery.sort = '-id' | 266 | this.listQuery.sort = '-id' |
267 | } | 267 | } |
268 | this.handleFilter() | 268 | this.handleFilter() |
269 | }, | 269 | }, |
270 | resetTemp() { | 270 | resetTemp() { |
271 | this.temp = { | 271 | this.temp = { |
272 | id: undefined, | 272 | id: undefined, |
273 | importance: 1, | 273 | importance: 1, |
274 | remark: '', | 274 | remark: '', |
275 | timestamp: new Date(), | 275 | timestamp: new Date(), |
276 | title: '', | 276 | title: '', |
277 | status: 'published', | 277 | status: 'published', |
278 | type: '' | 278 | type: '' |
279 | } | 279 | } |
280 | }, | 280 | }, |
281 | handleCreate() { | 281 | handleCreate() { |
282 | this.resetTemp() | 282 | this.resetTemp() |
283 | this.dialogStatus = 'create' | 283 | this.dialogStatus = 'create' |
284 | this.dialogFormVisible = true | 284 | this.dialogFormVisible = true |
285 | this.$nextTick(() => { | 285 | this.$nextTick(() => { |
286 | this.$refs['dataForm'].clearValidate() | 286 | this.$refs['dataForm'].clearValidate() |
287 | }) | 287 | }) |
288 | }, | 288 | }, |
289 | createData() { | 289 | createData() { |
290 | this.$refs['dataForm'].validate((valid) => { | 290 | this.$refs['dataForm'].validate((valid) => { |
291 | if (valid) { | 291 | if (valid) { |
292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id | 292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id |
293 | this.temp.author = 'vue-element-admin' | 293 | this.temp.author = '秀野堂主' |
294 | createArticle(this.temp).then(() => { | 294 | createArticle(this.temp).then(() => { |
295 | this.list.unshift(this.temp) | 295 | this.list.unshift(this.temp) |
296 | this.dialogFormVisible = false | 296 | this.dialogFormVisible = false |
297 | this.$notify({ | 297 | this.$notify({ |
298 | title: '成功', | 298 | title: '成功', |
299 | message: '创建成功', | 299 | message: '创建成功', |
300 | type: 'success', | 300 | type: 'success', |
301 | duration: 2000 | 301 | duration: 2000 |
302 | }) | 302 | }) |
303 | }) | 303 | }) |
304 | } | 304 | } |
305 | }) | 305 | }) |
306 | }, | 306 | }, |
307 | handleUpdate(row) { | 307 | handleUpdate(row) { |
308 | this.temp = Object.assign({}, row) // copy obj | 308 | this.temp = Object.assign({}, row) // copy obj |
309 | this.temp.timestamp = new Date(this.temp.timestamp) | 309 | this.temp.timestamp = new Date(this.temp.timestamp) |
310 | this.dialogStatus = 'update' | 310 | this.dialogStatus = 'update' |
311 | this.dialogFormVisible = true | 311 | this.dialogFormVisible = true |
312 | this.$nextTick(() => { | 312 | this.$nextTick(() => { |
313 | this.$refs['dataForm'].clearValidate() | 313 | this.$refs['dataForm'].clearValidate() |
314 | }) | 314 | }) |
315 | }, | 315 | }, |
316 | updateData() { | 316 | updateData() { |
317 | this.$refs['dataForm'].validate((valid) => { | 317 | this.$refs['dataForm'].validate((valid) => { |
318 | if (valid) { | 318 | if (valid) { |
319 | const tempData = Object.assign({}, this.temp) | 319 | const tempData = Object.assign({}, this.temp) |
320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 | 320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 |
321 | updateArticle(tempData).then(() => { | 321 | updateArticle(tempData).then(() => { |
322 | const index = this.list.findIndex(v => v.id === this.temp.id) | 322 | const index = this.list.findIndex(v => v.id === this.temp.id) |
323 | this.list.splice(index, 1, this.temp) | 323 | this.list.splice(index, 1, this.temp) |
324 | this.dialogFormVisible = false | 324 | this.dialogFormVisible = false |
325 | this.$notify({ | 325 | this.$notify({ |
326 | title: '成功', | 326 | title: '成功', |
327 | message: '更新成功', | 327 | message: '更新成功', |
328 | type: 'success', | 328 | type: 'success', |
329 | duration: 2000 | 329 | duration: 2000 |
330 | }) | 330 | }) |
331 | }) | 331 | }) |
332 | } | 332 | } |
333 | }) | 333 | }) |
334 | }, | 334 | }, |
335 | handleDelete(row, index) { | 335 | handleDelete(row, index) { |
336 | this.$notify({ | 336 | this.$notify({ |
337 | title: '成功', | 337 | title: '成功', |
338 | message: '删除成功', | 338 | message: '删除成功', |
339 | type: 'success', | 339 | type: 'success', |
340 | duration: 2000 | 340 | duration: 2000 |
341 | }) | 341 | }) |
342 | this.list.splice(index, 1) | 342 | this.list.splice(index, 1) |
343 | }, | 343 | }, |
344 | handleFetchPv(pv) { | 344 | handleFetchPv(pv) { |
345 | fetchPv(pv).then(response => { | 345 | fetchPv(pv).then(response => { |
346 | this.pvData = response.data.pvData | 346 | this.pvData = response.data.pvData |
347 | this.dialogPvVisible = true | 347 | this.dialogPvVisible = true |
348 | }) | 348 | }) |
349 | }, | 349 | }, |
350 | handleDownload() { | 350 | handleDownload() { |
351 | this.downloadLoading = true | 351 | this.downloadLoading = true |
352 | import('@/vendor/Export2Excel').then(excel => { | 352 | import('@/vendor/Export2Excel').then(excel => { |
353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] | 353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] |
354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] | 354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] |
355 | const data = this.formatJson(filterVal) | 355 | const data = this.formatJson(filterVal) |
356 | excel.export_json_to_excel({ | 356 | excel.export_json_to_excel({ |
357 | header: tHeader, | 357 | header: tHeader, |
358 | data, | 358 | data, |
359 | filename: 'table-list' | 359 | filename: 'table-list' |
360 | }) | 360 | }) |
361 | this.downloadLoading = false | 361 | this.downloadLoading = false |
362 | }) | 362 | }) |
363 | }, | 363 | }, |
364 | formatJson(filterVal) { | 364 | formatJson(filterVal) { |
365 | return this.list.map(v => filterVal.map(j => { | 365 | return this.list.map(v => filterVal.map(j => { |
366 | if (j === 'timestamp') { | 366 | if (j === 'timestamp') { |
367 | return parseTime(v[j]) | 367 | return parseTime(v[j]) |
368 | } else { | 368 | } else { |
369 | return v[j] | 369 | return v[j] |
370 | } | 370 | } |
371 | })) | 371 | })) |
372 | }, | 372 | }, |
373 | getSortClass: function(key) { | 373 | getSortClass: function(key) { |
374 | const sort = this.listQuery.sort | 374 | const sort = this.listQuery.sort |
375 | return sort === `+${key}` ? 'ascending' : 'descending' | 375 | return sort === `+${key}` ? 'ascending' : 'descending' |
376 | } | 376 | } |
377 | } | 377 | } |
378 | } | 378 | } |
379 | </script> | 379 | </script> |
380 | 380 |
src/views/prod/complex-table.vue
1 | <template> | 1 | <template> |
2 | <div class="app-container"> | 2 | <div class="app-container"> |
3 | <div class="filter-container"> | 3 | <div class="filter-container"> |
4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> | 4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> |
5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> | 5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> |
6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> | 6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> |
7 | </el-select> | 7 | </el-select> |
8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> | 8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> |
9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> | 9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> |
10 | </el-select> | 10 | </el-select> |
11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> | 11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> |
12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> | 12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
13 | </el-select> | 13 | </el-select> |
14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> | 14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
15 | {{ $t('table.search') }} | 15 | {{ $t('table.search') }} |
16 | </el-button> | 16 | </el-button> |
17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> | 17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> |
18 | {{ $t('table.add') }} | 18 | {{ $t('table.add') }} |
19 | </el-button> | 19 | </el-button> |
20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> | 20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> |
21 | {{ $t('table.export') }} | 21 | {{ $t('table.export') }} |
22 | </el-button> | 22 | </el-button> |
23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> | 23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> |
24 | {{ $t('table.reviewer') }} | 24 | {{ $t('table.reviewer') }} |
25 | </el-checkbox> | 25 | </el-checkbox> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <el-table | 28 | <el-table |
29 | :key="tableKey" | 29 | :key="tableKey" |
30 | v-loading="listLoading" | 30 | v-loading="listLoading" |
31 | :data="list" | 31 | :data="list" |
32 | border | 32 | border |
33 | fit | 33 | fit |
34 | highlight-current-row | 34 | highlight-current-row |
35 | style="width: 100%;" | 35 | style="width: 100%;" |
36 | @sort-change="sortChange" | 36 | @sort-change="sortChange" |
37 | > | 37 | > |
38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> | 38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> |
39 | <template slot-scope="{row}"> | 39 | <template slot-scope="{row}"> |
40 | <span>{{ row.id }}</span> | 40 | <span>{{ row.id }}</span> |
41 | </template> | 41 | </template> |
42 | </el-table-column> | 42 | </el-table-column> |
43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> | 43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> |
44 | <template slot-scope="{row}"> | 44 | <template slot-scope="{row}"> |
45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> | 45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> |
46 | </template> | 46 | </template> |
47 | </el-table-column> | 47 | </el-table-column> |
48 | <el-table-column :label="$t('table.title')" min-width="150px"> | 48 | <el-table-column :label="$t('table.title')" min-width="150px"> |
49 | <template slot-scope="{row}"> | 49 | <template slot-scope="{row}"> |
50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> | 50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> |
51 | <el-tag>{{ row.type | typeFilter }}</el-tag> | 51 | <el-tag>{{ row.type | typeFilter }}</el-tag> |
52 | </template> | 52 | </template> |
53 | </el-table-column> | 53 | </el-table-column> |
54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> | 54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> |
55 | <template slot-scope="{row}"> | 55 | <template slot-scope="{row}"> |
56 | <span>{{ row.author }}</span> | 56 | <span>{{ row.author }}</span> |
57 | </template> | 57 | </template> |
58 | </el-table-column> | 58 | </el-table-column> |
59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> | 59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> |
60 | <template slot-scope="{row}"> | 60 | <template slot-scope="{row}"> |
61 | <span style="color:red;">{{ row.reviewer }}</span> | 61 | <span style="color:red;">{{ row.reviewer }}</span> |
62 | </template> | 62 | </template> |
63 | </el-table-column> | 63 | </el-table-column> |
64 | <el-table-column :label="$t('table.importance')" width="80px"> | 64 | <el-table-column :label="$t('table.importance')" width="80px"> |
65 | <template slot-scope="{row}"> | 65 | <template slot-scope="{row}"> |
66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> | 66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> |
67 | </template> | 67 | </template> |
68 | </el-table-column> | 68 | </el-table-column> |
69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> | 69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> |
70 | <template slot-scope="{row}"> | 70 | <template slot-scope="{row}"> |
71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> | 71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> |
72 | <span v-else>0</span> | 72 | <span v-else>0</span> |
73 | </template> | 73 | </template> |
74 | </el-table-column> | 74 | </el-table-column> |
75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> | 75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> |
76 | <template slot-scope="{row}"> | 76 | <template slot-scope="{row}"> |
77 | <el-tag :type="row.status | statusFilter"> | 77 | <el-tag :type="row.status | statusFilter"> |
78 | {{ row.status }} | 78 | {{ row.status }} |
79 | </el-tag> | 79 | </el-tag> |
80 | </template> | 80 | </template> |
81 | </el-table-column> | 81 | </el-table-column> |
82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> | 82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> |
83 | <template slot-scope="{row,$index}"> | 83 | <template slot-scope="{row,$index}"> |
84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> | 84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> |
85 | {{ $t('table.edit') }} | 85 | {{ $t('table.edit') }} |
86 | </el-button> | 86 | </el-button> |
87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> | 87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> |
88 | {{ $t('table.publish') }} | 88 | {{ $t('table.publish') }} |
89 | </el-button> | 89 | </el-button> |
90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> | 90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> |
91 | {{ $t('table.draft') }} | 91 | {{ $t('table.draft') }} |
92 | </el-button> | 92 | </el-button> |
93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> | 93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> |
94 | {{ $t('table.delete') }} | 94 | {{ $t('table.delete') }} |
95 | </el-button> | 95 | </el-button> |
96 | </template> | 96 | </template> |
97 | </el-table-column> | 97 | </el-table-column> |
98 | </el-table> | 98 | </el-table> |
99 | 99 | ||
100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> | 100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> |
101 | 101 | ||
102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> | 102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> |
103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> | 103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> |
104 | <el-form-item :label="$t('table.type')" prop="type"> | 104 | <el-form-item :label="$t('table.type')" prop="type"> |
105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> | 105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> |
106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> | 106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> |
107 | </el-select> | 107 | </el-select> |
108 | </el-form-item> | 108 | </el-form-item> |
109 | <el-form-item :label="$t('table.date')" prop="timestamp"> | 109 | <el-form-item :label="$t('table.date')" prop="timestamp"> |
110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> | 110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> |
111 | </el-form-item> | 111 | </el-form-item> |
112 | <el-form-item :label="$t('table.title')" prop="title"> | 112 | <el-form-item :label="$t('table.title')" prop="title"> |
113 | <el-input v-model="temp.title" /> | 113 | <el-input v-model="temp.title" /> |
114 | </el-form-item> | 114 | </el-form-item> |
115 | <el-form-item :label="$t('table.status')"> | 115 | <el-form-item :label="$t('table.status')"> |
116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> | 116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> |
117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> | 117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> |
118 | </el-select> | 118 | </el-select> |
119 | </el-form-item> | 119 | </el-form-item> |
120 | <el-form-item :label="$t('table.importance')"> | 120 | <el-form-item :label="$t('table.importance')"> |
121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> | 121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> |
122 | </el-form-item> | 122 | </el-form-item> |
123 | <el-form-item :label="$t('table.remark')"> | 123 | <el-form-item :label="$t('table.remark')"> |
124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> | 124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> |
125 | </el-form-item> | 125 | </el-form-item> |
126 | </el-form> | 126 | </el-form> |
127 | <div slot="footer" class="dialog-footer"> | 127 | <div slot="footer" class="dialog-footer"> |
128 | <el-button @click="dialogFormVisible = false"> | 128 | <el-button @click="dialogFormVisible = false"> |
129 | {{ $t('table.cancel') }} | 129 | {{ $t('table.cancel') }} |
130 | </el-button> | 130 | </el-button> |
131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> | 131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> |
132 | {{ $t('table.confirm') }} | 132 | {{ $t('table.confirm') }} |
133 | </el-button> | 133 | </el-button> |
134 | </div> | 134 | </div> |
135 | </el-dialog> | 135 | </el-dialog> |
136 | 136 | ||
137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> | 137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> |
138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> | 138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> |
139 | <el-table-column prop="key" label="Channel" /> | 139 | <el-table-column prop="key" label="Channel" /> |
140 | <el-table-column prop="pv" label="Pv" /> | 140 | <el-table-column prop="pv" label="Pv" /> |
141 | </el-table> | 141 | </el-table> |
142 | <span slot="footer" class="dialog-footer"> | 142 | <span slot="footer" class="dialog-footer"> |
143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> | 143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> |
144 | </span> | 144 | </span> |
145 | </el-dialog> | 145 | </el-dialog> |
146 | </div> | 146 | </div> |
147 | </template> | 147 | </template> |
148 | 148 | ||
149 | <script> | 149 | <script> |
150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' | 150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' |
151 | import waves from '@/directive/waves' // waves directive | 151 | import waves from '@/directive/waves' // waves directive |
152 | import { parseTime } from '@/utils' | 152 | import { parseTime } from '@/utils' |
153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination | 153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
154 | 154 | ||
155 | const calendarTypeOptions = [ | 155 | const calendarTypeOptions = [ |
156 | { key: 'CN', display_name: 'China' }, | 156 | { key: 'CN', display_name: 'China' }, |
157 | { key: 'US', display_name: 'USA' }, | 157 | { key: 'US', display_name: 'USA' }, |
158 | { key: 'JP', display_name: 'Japan' }, | 158 | { key: 'JP', display_name: 'Japan' }, |
159 | { key: 'EU', display_name: 'Eurozone' } | 159 | { key: 'EU', display_name: 'Eurozone' } |
160 | ] | 160 | ] |
161 | 161 | ||
162 | // arr to obj, such as { CN : "China", US : "USA" } | 162 | // arr to obj, such as { CN : "China", US : "USA" } |
163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { | 163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { |
164 | acc[cur.key] = cur.display_name | 164 | acc[cur.key] = cur.display_name |
165 | return acc | 165 | return acc |
166 | }, {}) | 166 | }, {}) |
167 | 167 | ||
168 | export default { | 168 | export default { |
169 | name: 'ComplexTable', | 169 | name: 'ComplexTable', |
170 | components: { Pagination }, | 170 | components: { Pagination }, |
171 | directives: { waves }, | 171 | directives: { waves }, |
172 | filters: { | 172 | filters: { |
173 | statusFilter(status) { | 173 | statusFilter(status) { |
174 | const statusMap = { | 174 | const statusMap = { |
175 | published: 'success', | 175 | published: 'success', |
176 | draft: 'info', | 176 | draft: 'info', |
177 | deleted: 'danger' | 177 | deleted: 'danger' |
178 | } | 178 | } |
179 | return statusMap[status] | 179 | return statusMap[status] |
180 | }, | 180 | }, |
181 | typeFilter(type) { | 181 | typeFilter(type) { |
182 | return calendarTypeKeyValue[type] | 182 | return calendarTypeKeyValue[type] |
183 | } | 183 | } |
184 | }, | 184 | }, |
185 | data() { | 185 | data() { |
186 | return { | 186 | return { |
187 | tableKey: 0, | 187 | tableKey: 0, |
188 | list: null, | 188 | list: null, |
189 | total: 0, | 189 | total: 0, |
190 | listLoading: true, | 190 | listLoading: true, |
191 | listQuery: { | 191 | listQuery: { |
192 | page: 1, | 192 | page: 1, |
193 | limit: 20, | 193 | limit: 20, |
194 | importance: undefined, | 194 | importance: undefined, |
195 | title: undefined, | 195 | title: undefined, |
196 | type: undefined, | 196 | type: undefined, |
197 | sort: '+id' | 197 | sort: '+id' |
198 | }, | 198 | }, |
199 | importanceOptions: [1, 2, 3], | 199 | importanceOptions: [1, 2, 3], |
200 | calendarTypeOptions, | 200 | calendarTypeOptions, |
201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], | 201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], |
202 | statusOptions: ['published', 'draft', 'deleted'], | 202 | statusOptions: ['published', 'draft', 'deleted'], |
203 | showReviewer: false, | 203 | showReviewer: false, |
204 | temp: { | 204 | temp: { |
205 | id: undefined, | 205 | id: undefined, |
206 | importance: 1, | 206 | importance: 1, |
207 | remark: '', | 207 | remark: '', |
208 | timestamp: new Date(), | 208 | timestamp: new Date(), |
209 | title: '', | 209 | title: '', |
210 | type: '', | 210 | type: '', |
211 | status: 'published' | 211 | status: 'published' |
212 | }, | 212 | }, |
213 | dialogFormVisible: false, | 213 | dialogFormVisible: false, |
214 | dialogStatus: '', | 214 | dialogStatus: '', |
215 | textMap: { | 215 | textMap: { |
216 | update: 'Edit', | 216 | update: 'Edit', |
217 | create: 'Create' | 217 | create: 'Create' |
218 | }, | 218 | }, |
219 | dialogPvVisible: false, | 219 | dialogPvVisible: false, |
220 | pvData: [], | 220 | pvData: [], |
221 | rules: { | 221 | rules: { |
222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], | 222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], |
223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], | 223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], |
224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] | 224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] |
225 | }, | 225 | }, |
226 | downloadLoading: false | 226 | downloadLoading: false |
227 | } | 227 | } |
228 | }, | 228 | }, |
229 | created() { | 229 | created() { |
230 | this.getList() | 230 | this.getList() |
231 | }, | 231 | }, |
232 | methods: { | 232 | methods: { |
233 | getList() { | 233 | getList() { |
234 | this.listLoading = true | 234 | this.listLoading = true |
235 | fetchList(this.listQuery).then(response => { | 235 | fetchList(this.listQuery).then(response => { |
236 | this.list = response.data.items | 236 | this.list = response.data.items |
237 | this.total = response.data.total | 237 | this.total = response.data.total |
238 | 238 | ||
239 | // Just to simulate the time of the request | 239 | // Just to simulate the time of the request |
240 | setTimeout(() => { | 240 | setTimeout(() => { |
241 | this.listLoading = false | 241 | this.listLoading = false |
242 | }, 1.5 * 1000) | 242 | }, 1.5 * 1000) |
243 | }) | 243 | }) |
244 | }, | 244 | }, |
245 | handleFilter() { | 245 | handleFilter() { |
246 | this.listQuery.page = 1 | 246 | this.listQuery.page = 1 |
247 | this.getList() | 247 | this.getList() |
248 | }, | 248 | }, |
249 | handleModifyStatus(row, status) { | 249 | handleModifyStatus(row, status) { |
250 | this.$message({ | 250 | this.$message({ |
251 | message: '操作成功', | 251 | message: '操作成功', |
252 | type: 'success' | 252 | type: 'success' |
253 | }) | 253 | }) |
254 | row.status = status | 254 | row.status = status |
255 | }, | 255 | }, |
256 | sortChange(data) { | 256 | sortChange(data) { |
257 | const { prop, order } = data | 257 | const { prop, order } = data |
258 | if (prop === 'id') { | 258 | if (prop === 'id') { |
259 | this.sortByID(order) | 259 | this.sortByID(order) |
260 | } | 260 | } |
261 | }, | 261 | }, |
262 | sortByID(order) { | 262 | sortByID(order) { |
263 | if (order === 'ascending') { | 263 | if (order === 'ascending') { |
264 | this.listQuery.sort = '+id' | 264 | this.listQuery.sort = '+id' |
265 | } else { | 265 | } else { |
266 | this.listQuery.sort = '-id' | 266 | this.listQuery.sort = '-id' |
267 | } | 267 | } |
268 | this.handleFilter() | 268 | this.handleFilter() |
269 | }, | 269 | }, |
270 | resetTemp() { | 270 | resetTemp() { |
271 | this.temp = { | 271 | this.temp = { |
272 | id: undefined, | 272 | id: undefined, |
273 | importance: 1, | 273 | importance: 1, |
274 | remark: '', | 274 | remark: '', |
275 | timestamp: new Date(), | 275 | timestamp: new Date(), |
276 | title: '', | 276 | title: '', |
277 | status: 'published', | 277 | status: 'published', |
278 | type: '' | 278 | type: '' |
279 | } | 279 | } |
280 | }, | 280 | }, |
281 | handleCreate() { | 281 | handleCreate() { |
282 | this.resetTemp() | 282 | this.resetTemp() |
283 | this.dialogStatus = 'create' | 283 | this.dialogStatus = 'create' |
284 | this.dialogFormVisible = true | 284 | this.dialogFormVisible = true |
285 | this.$nextTick(() => { | 285 | this.$nextTick(() => { |
286 | this.$refs['dataForm'].clearValidate() | 286 | this.$refs['dataForm'].clearValidate() |
287 | }) | 287 | }) |
288 | }, | 288 | }, |
289 | createData() { | 289 | createData() { |
290 | this.$refs['dataForm'].validate((valid) => { | 290 | this.$refs['dataForm'].validate((valid) => { |
291 | if (valid) { | 291 | if (valid) { |
292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id | 292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id |
293 | this.temp.author = 'vue-element-admin' | 293 | this.temp.author = '秀野堂主' |
294 | createArticle(this.temp).then(() => { | 294 | createArticle(this.temp).then(() => { |
295 | this.list.unshift(this.temp) | 295 | this.list.unshift(this.temp) |
296 | this.dialogFormVisible = false | 296 | this.dialogFormVisible = false |
297 | this.$notify({ | 297 | this.$notify({ |
298 | title: '成功', | 298 | title: '成功', |
299 | message: '创建成功', | 299 | message: '创建成功', |
300 | type: 'success', | 300 | type: 'success', |
301 | duration: 2000 | 301 | duration: 2000 |
302 | }) | 302 | }) |
303 | }) | 303 | }) |
304 | } | 304 | } |
305 | }) | 305 | }) |
306 | }, | 306 | }, |
307 | handleUpdate(row) { | 307 | handleUpdate(row) { |
308 | this.temp = Object.assign({}, row) // copy obj | 308 | this.temp = Object.assign({}, row) // copy obj |
309 | this.temp.timestamp = new Date(this.temp.timestamp) | 309 | this.temp.timestamp = new Date(this.temp.timestamp) |
310 | this.dialogStatus = 'update' | 310 | this.dialogStatus = 'update' |
311 | this.dialogFormVisible = true | 311 | this.dialogFormVisible = true |
312 | this.$nextTick(() => { | 312 | this.$nextTick(() => { |
313 | this.$refs['dataForm'].clearValidate() | 313 | this.$refs['dataForm'].clearValidate() |
314 | }) | 314 | }) |
315 | }, | 315 | }, |
316 | updateData() { | 316 | updateData() { |
317 | this.$refs['dataForm'].validate((valid) => { | 317 | this.$refs['dataForm'].validate((valid) => { |
318 | if (valid) { | 318 | if (valid) { |
319 | const tempData = Object.assign({}, this.temp) | 319 | const tempData = Object.assign({}, this.temp) |
320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 | 320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 |
321 | updateArticle(tempData).then(() => { | 321 | updateArticle(tempData).then(() => { |
322 | const index = this.list.findIndex(v => v.id === this.temp.id) | 322 | const index = this.list.findIndex(v => v.id === this.temp.id) |
323 | this.list.splice(index, 1, this.temp) | 323 | this.list.splice(index, 1, this.temp) |
324 | this.dialogFormVisible = false | 324 | this.dialogFormVisible = false |
325 | this.$notify({ | 325 | this.$notify({ |
326 | title: '成功', | 326 | title: '成功', |
327 | message: '更新成功', | 327 | message: '更新成功', |
328 | type: 'success', | 328 | type: 'success', |
329 | duration: 2000 | 329 | duration: 2000 |
330 | }) | 330 | }) |
331 | }) | 331 | }) |
332 | } | 332 | } |
333 | }) | 333 | }) |
334 | }, | 334 | }, |
335 | handleDelete(row, index) { | 335 | handleDelete(row, index) { |
336 | this.$notify({ | 336 | this.$notify({ |
337 | title: '成功', | 337 | title: '成功', |
338 | message: '删除成功', | 338 | message: '删除成功', |
339 | type: 'success', | 339 | type: 'success', |
340 | duration: 2000 | 340 | duration: 2000 |
341 | }) | 341 | }) |
342 | this.list.splice(index, 1) | 342 | this.list.splice(index, 1) |
343 | }, | 343 | }, |
344 | handleFetchPv(pv) { | 344 | handleFetchPv(pv) { |
345 | fetchPv(pv).then(response => { | 345 | fetchPv(pv).then(response => { |
346 | this.pvData = response.data.pvData | 346 | this.pvData = response.data.pvData |
347 | this.dialogPvVisible = true | 347 | this.dialogPvVisible = true |
348 | }) | 348 | }) |
349 | }, | 349 | }, |
350 | handleDownload() { | 350 | handleDownload() { |
351 | this.downloadLoading = true | 351 | this.downloadLoading = true |
352 | import('@/vendor/Export2Excel').then(excel => { | 352 | import('@/vendor/Export2Excel').then(excel => { |
353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] | 353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] |
354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] | 354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] |
355 | const data = this.formatJson(filterVal) | 355 | const data = this.formatJson(filterVal) |
356 | excel.export_json_to_excel({ | 356 | excel.export_json_to_excel({ |
357 | header: tHeader, | 357 | header: tHeader, |
358 | data, | 358 | data, |
359 | filename: 'table-list' | 359 | filename: 'table-list' |
360 | }) | 360 | }) |
361 | this.downloadLoading = false | 361 | this.downloadLoading = false |
362 | }) | 362 | }) |
363 | }, | 363 | }, |
364 | formatJson(filterVal) { | 364 | formatJson(filterVal) { |
365 | return this.list.map(v => filterVal.map(j => { | 365 | return this.list.map(v => filterVal.map(j => { |
366 | if (j === 'timestamp') { | 366 | if (j === 'timestamp') { |
367 | return parseTime(v[j]) | 367 | return parseTime(v[j]) |
368 | } else { | 368 | } else { |
369 | return v[j] | 369 | return v[j] |
370 | } | 370 | } |
371 | })) | 371 | })) |
372 | }, | 372 | }, |
373 | getSortClass: function(key) { | 373 | getSortClass: function(key) { |
374 | const sort = this.listQuery.sort | 374 | const sort = this.listQuery.sort |
375 | return sort === `+${key}` ? 'ascending' : 'descending' | 375 | return sort === `+${key}` ? 'ascending' : 'descending' |
376 | } | 376 | } |
377 | } | 377 | } |
378 | } | 378 | } |
379 | </script> | 379 | </script> |
380 | 380 |
src/views/system/complex-table.vue
1 | <template> | 1 | <template> |
2 | <div class="app-container"> | 2 | <div class="app-container"> |
3 | <div class="filter-container"> | 3 | <div class="filter-container"> |
4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> | 4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> |
5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> | 5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> |
6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> | 6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> |
7 | </el-select> | 7 | </el-select> |
8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> | 8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> |
9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> | 9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> |
10 | </el-select> | 10 | </el-select> |
11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> | 11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> |
12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> | 12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
13 | </el-select> | 13 | </el-select> |
14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> | 14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
15 | {{ $t('table.search') }} | 15 | {{ $t('table.search') }} |
16 | </el-button> | 16 | </el-button> |
17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> | 17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> |
18 | {{ $t('table.add') }} | 18 | {{ $t('table.add') }} |
19 | </el-button> | 19 | </el-button> |
20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> | 20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> |
21 | {{ $t('table.export') }} | 21 | {{ $t('table.export') }} |
22 | </el-button> | 22 | </el-button> |
23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> | 23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> |
24 | {{ $t('table.reviewer') }} | 24 | {{ $t('table.reviewer') }} |
25 | </el-checkbox> | 25 | </el-checkbox> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <el-table | 28 | <el-table |
29 | :key="tableKey" | 29 | :key="tableKey" |
30 | v-loading="listLoading" | 30 | v-loading="listLoading" |
31 | :data="list" | 31 | :data="list" |
32 | border | 32 | border |
33 | fit | 33 | fit |
34 | highlight-current-row | 34 | highlight-current-row |
35 | style="width: 100%;" | 35 | style="width: 100%;" |
36 | @sort-change="sortChange" | 36 | @sort-change="sortChange" |
37 | > | 37 | > |
38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> | 38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> |
39 | <template slot-scope="{row}"> | 39 | <template slot-scope="{row}"> |
40 | <span>{{ row.id }}</span> | 40 | <span>{{ row.id }}</span> |
41 | </template> | 41 | </template> |
42 | </el-table-column> | 42 | </el-table-column> |
43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> | 43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> |
44 | <template slot-scope="{row}"> | 44 | <template slot-scope="{row}"> |
45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> | 45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> |
46 | </template> | 46 | </template> |
47 | </el-table-column> | 47 | </el-table-column> |
48 | <el-table-column :label="$t('table.title')" min-width="150px"> | 48 | <el-table-column :label="$t('table.title')" min-width="150px"> |
49 | <template slot-scope="{row}"> | 49 | <template slot-scope="{row}"> |
50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> | 50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> |
51 | <el-tag>{{ row.type | typeFilter }}</el-tag> | 51 | <el-tag>{{ row.type | typeFilter }}</el-tag> |
52 | </template> | 52 | </template> |
53 | </el-table-column> | 53 | </el-table-column> |
54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> | 54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> |
55 | <template slot-scope="{row}"> | 55 | <template slot-scope="{row}"> |
56 | <span>{{ row.author }}</span> | 56 | <span>{{ row.author }}</span> |
57 | </template> | 57 | </template> |
58 | </el-table-column> | 58 | </el-table-column> |
59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> | 59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> |
60 | <template slot-scope="{row}"> | 60 | <template slot-scope="{row}"> |
61 | <span style="color:red;">{{ row.reviewer }}</span> | 61 | <span style="color:red;">{{ row.reviewer }}</span> |
62 | </template> | 62 | </template> |
63 | </el-table-column> | 63 | </el-table-column> |
64 | <el-table-column :label="$t('table.importance')" width="80px"> | 64 | <el-table-column :label="$t('table.importance')" width="80px"> |
65 | <template slot-scope="{row}"> | 65 | <template slot-scope="{row}"> |
66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> | 66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> |
67 | </template> | 67 | </template> |
68 | </el-table-column> | 68 | </el-table-column> |
69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> | 69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> |
70 | <template slot-scope="{row}"> | 70 | <template slot-scope="{row}"> |
71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> | 71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> |
72 | <span v-else>0</span> | 72 | <span v-else>0</span> |
73 | </template> | 73 | </template> |
74 | </el-table-column> | 74 | </el-table-column> |
75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> | 75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> |
76 | <template slot-scope="{row}"> | 76 | <template slot-scope="{row}"> |
77 | <el-tag :type="row.status | statusFilter"> | 77 | <el-tag :type="row.status | statusFilter"> |
78 | {{ row.status }} | 78 | {{ row.status }} |
79 | </el-tag> | 79 | </el-tag> |
80 | </template> | 80 | </template> |
81 | </el-table-column> | 81 | </el-table-column> |
82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> | 82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> |
83 | <template slot-scope="{row,$index}"> | 83 | <template slot-scope="{row,$index}"> |
84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> | 84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> |
85 | {{ $t('table.edit') }} | 85 | {{ $t('table.edit') }} |
86 | </el-button> | 86 | </el-button> |
87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> | 87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> |
88 | {{ $t('table.publish') }} | 88 | {{ $t('table.publish') }} |
89 | </el-button> | 89 | </el-button> |
90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> | 90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> |
91 | {{ $t('table.draft') }} | 91 | {{ $t('table.draft') }} |
92 | </el-button> | 92 | </el-button> |
93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> | 93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> |
94 | {{ $t('table.delete') }} | 94 | {{ $t('table.delete') }} |
95 | </el-button> | 95 | </el-button> |
96 | </template> | 96 | </template> |
97 | </el-table-column> | 97 | </el-table-column> |
98 | </el-table> | 98 | </el-table> |
99 | 99 | ||
100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> | 100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> |
101 | 101 | ||
102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> | 102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> |
103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> | 103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> |
104 | <el-form-item :label="$t('table.type')" prop="type"> | 104 | <el-form-item :label="$t('table.type')" prop="type"> |
105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> | 105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> |
106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> | 106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> |
107 | </el-select> | 107 | </el-select> |
108 | </el-form-item> | 108 | </el-form-item> |
109 | <el-form-item :label="$t('table.date')" prop="timestamp"> | 109 | <el-form-item :label="$t('table.date')" prop="timestamp"> |
110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> | 110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> |
111 | </el-form-item> | 111 | </el-form-item> |
112 | <el-form-item :label="$t('table.title')" prop="title"> | 112 | <el-form-item :label="$t('table.title')" prop="title"> |
113 | <el-input v-model="temp.title" /> | 113 | <el-input v-model="temp.title" /> |
114 | </el-form-item> | 114 | </el-form-item> |
115 | <el-form-item :label="$t('table.status')"> | 115 | <el-form-item :label="$t('table.status')"> |
116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> | 116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> |
117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> | 117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> |
118 | </el-select> | 118 | </el-select> |
119 | </el-form-item> | 119 | </el-form-item> |
120 | <el-form-item :label="$t('table.importance')"> | 120 | <el-form-item :label="$t('table.importance')"> |
121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> | 121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> |
122 | </el-form-item> | 122 | </el-form-item> |
123 | <el-form-item :label="$t('table.remark')"> | 123 | <el-form-item :label="$t('table.remark')"> |
124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> | 124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> |
125 | </el-form-item> | 125 | </el-form-item> |
126 | </el-form> | 126 | </el-form> |
127 | <div slot="footer" class="dialog-footer"> | 127 | <div slot="footer" class="dialog-footer"> |
128 | <el-button @click="dialogFormVisible = false"> | 128 | <el-button @click="dialogFormVisible = false"> |
129 | {{ $t('table.cancel') }} | 129 | {{ $t('table.cancel') }} |
130 | </el-button> | 130 | </el-button> |
131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> | 131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> |
132 | {{ $t('table.confirm') }} | 132 | {{ $t('table.confirm') }} |
133 | </el-button> | 133 | </el-button> |
134 | </div> | 134 | </div> |
135 | </el-dialog> | 135 | </el-dialog> |
136 | 136 | ||
137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> | 137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> |
138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> | 138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> |
139 | <el-table-column prop="key" label="Channel" /> | 139 | <el-table-column prop="key" label="Channel" /> |
140 | <el-table-column prop="pv" label="Pv" /> | 140 | <el-table-column prop="pv" label="Pv" /> |
141 | </el-table> | 141 | </el-table> |
142 | <span slot="footer" class="dialog-footer"> | 142 | <span slot="footer" class="dialog-footer"> |
143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> | 143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> |
144 | </span> | 144 | </span> |
145 | </el-dialog> | 145 | </el-dialog> |
146 | </div> | 146 | </div> |
147 | </template> | 147 | </template> |
148 | 148 | ||
149 | <script> | 149 | <script> |
150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' | 150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' |
151 | import waves from '@/directive/waves' // waves directive | 151 | import waves from '@/directive/waves' // waves directive |
152 | import { parseTime } from '@/utils' | 152 | import { parseTime } from '@/utils' |
153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination | 153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
154 | 154 | ||
155 | const calendarTypeOptions = [ | 155 | const calendarTypeOptions = [ |
156 | { key: 'CN', display_name: 'China' }, | 156 | { key: 'CN', display_name: 'China' }, |
157 | { key: 'US', display_name: 'USA' }, | 157 | { key: 'US', display_name: 'USA' }, |
158 | { key: 'JP', display_name: 'Japan' }, | 158 | { key: 'JP', display_name: 'Japan' }, |
159 | { key: 'EU', display_name: 'Eurozone' } | 159 | { key: 'EU', display_name: 'Eurozone' } |
160 | ] | 160 | ] |
161 | 161 | ||
162 | // arr to obj, such as { CN : "China", US : "USA" } | 162 | // arr to obj, such as { CN : "China", US : "USA" } |
163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { | 163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { |
164 | acc[cur.key] = cur.display_name | 164 | acc[cur.key] = cur.display_name |
165 | return acc | 165 | return acc |
166 | }, {}) | 166 | }, {}) |
167 | 167 | ||
168 | export default { | 168 | export default { |
169 | name: 'ComplexTable', | 169 | name: 'ComplexTable', |
170 | components: { Pagination }, | 170 | components: { Pagination }, |
171 | directives: { waves }, | 171 | directives: { waves }, |
172 | filters: { | 172 | filters: { |
173 | statusFilter(status) { | 173 | statusFilter(status) { |
174 | const statusMap = { | 174 | const statusMap = { |
175 | published: 'success', | 175 | published: 'success', |
176 | draft: 'info', | 176 | draft: 'info', |
177 | deleted: 'danger' | 177 | deleted: 'danger' |
178 | } | 178 | } |
179 | return statusMap[status] | 179 | return statusMap[status] |
180 | }, | 180 | }, |
181 | typeFilter(type) { | 181 | typeFilter(type) { |
182 | return calendarTypeKeyValue[type] | 182 | return calendarTypeKeyValue[type] |
183 | } | 183 | } |
184 | }, | 184 | }, |
185 | data() { | 185 | data() { |
186 | return { | 186 | return { |
187 | tableKey: 0, | 187 | tableKey: 0, |
188 | list: null, | 188 | list: null, |
189 | total: 0, | 189 | total: 0, |
190 | listLoading: true, | 190 | listLoading: true, |
191 | listQuery: { | 191 | listQuery: { |
192 | page: 1, | 192 | page: 1, |
193 | limit: 20, | 193 | limit: 20, |
194 | importance: undefined, | 194 | importance: undefined, |
195 | title: undefined, | 195 | title: undefined, |
196 | type: undefined, | 196 | type: undefined, |
197 | sort: '+id' | 197 | sort: '+id' |
198 | }, | 198 | }, |
199 | importanceOptions: [1, 2, 3], | 199 | importanceOptions: [1, 2, 3], |
200 | calendarTypeOptions, | 200 | calendarTypeOptions, |
201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], | 201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], |
202 | statusOptions: ['published', 'draft', 'deleted'], | 202 | statusOptions: ['published', 'draft', 'deleted'], |
203 | showReviewer: false, | 203 | showReviewer: false, |
204 | temp: { | 204 | temp: { |
205 | id: undefined, | 205 | id: undefined, |
206 | importance: 1, | 206 | importance: 1, |
207 | remark: '', | 207 | remark: '', |
208 | timestamp: new Date(), | 208 | timestamp: new Date(), |
209 | title: '', | 209 | title: '', |
210 | type: '', | 210 | type: '', |
211 | status: 'published' | 211 | status: 'published' |
212 | }, | 212 | }, |
213 | dialogFormVisible: false, | 213 | dialogFormVisible: false, |
214 | dialogStatus: '', | 214 | dialogStatus: '', |
215 | textMap: { | 215 | textMap: { |
216 | update: 'Edit', | 216 | update: 'Edit', |
217 | create: 'Create' | 217 | create: 'Create' |
218 | }, | 218 | }, |
219 | dialogPvVisible: false, | 219 | dialogPvVisible: false, |
220 | pvData: [], | 220 | pvData: [], |
221 | rules: { | 221 | rules: { |
222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], | 222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], |
223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], | 223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], |
224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] | 224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] |
225 | }, | 225 | }, |
226 | downloadLoading: false | 226 | downloadLoading: false |
227 | } | 227 | } |
228 | }, | 228 | }, |
229 | created() { | 229 | created() { |
230 | this.getList() | 230 | this.getList() |
231 | }, | 231 | }, |
232 | methods: { | 232 | methods: { |
233 | getList() { | 233 | getList() { |
234 | this.listLoading = true | 234 | this.listLoading = true |
235 | fetchList(this.listQuery).then(response => { | 235 | fetchList(this.listQuery).then(response => { |
236 | this.list = response.data.items | 236 | this.list = response.data.items |
237 | this.total = response.data.total | 237 | this.total = response.data.total |
238 | 238 | ||
239 | // Just to simulate the time of the request | 239 | // Just to simulate the time of the request |
240 | setTimeout(() => { | 240 | setTimeout(() => { |
241 | this.listLoading = false | 241 | this.listLoading = false |
242 | }, 1.5 * 1000) | 242 | }, 1.5 * 1000) |
243 | }) | 243 | }) |
244 | }, | 244 | }, |
245 | handleFilter() { | 245 | handleFilter() { |
246 | this.listQuery.page = 1 | 246 | this.listQuery.page = 1 |
247 | this.getList() | 247 | this.getList() |
248 | }, | 248 | }, |
249 | handleModifyStatus(row, status) { | 249 | handleModifyStatus(row, status) { |
250 | this.$message({ | 250 | this.$message({ |
251 | message: '操作成功', | 251 | message: '操作成功', |
252 | type: 'success' | 252 | type: 'success' |
253 | }) | 253 | }) |
254 | row.status = status | 254 | row.status = status |
255 | }, | 255 | }, |
256 | sortChange(data) { | 256 | sortChange(data) { |
257 | const { prop, order } = data | 257 | const { prop, order } = data |
258 | if (prop === 'id') { | 258 | if (prop === 'id') { |
259 | this.sortByID(order) | 259 | this.sortByID(order) |
260 | } | 260 | } |
261 | }, | 261 | }, |
262 | sortByID(order) { | 262 | sortByID(order) { |
263 | if (order === 'ascending') { | 263 | if (order === 'ascending') { |
264 | this.listQuery.sort = '+id' | 264 | this.listQuery.sort = '+id' |
265 | } else { | 265 | } else { |
266 | this.listQuery.sort = '-id' | 266 | this.listQuery.sort = '-id' |
267 | } | 267 | } |
268 | this.handleFilter() | 268 | this.handleFilter() |
269 | }, | 269 | }, |
270 | resetTemp() { | 270 | resetTemp() { |
271 | this.temp = { | 271 | this.temp = { |
272 | id: undefined, | 272 | id: undefined, |
273 | importance: 1, | 273 | importance: 1, |
274 | remark: '', | 274 | remark: '', |
275 | timestamp: new Date(), | 275 | timestamp: new Date(), |
276 | title: '', | 276 | title: '', |
277 | status: 'published', | 277 | status: 'published', |
278 | type: '' | 278 | type: '' |
279 | } | 279 | } |
280 | }, | 280 | }, |
281 | handleCreate() { | 281 | handleCreate() { |
282 | this.resetTemp() | 282 | this.resetTemp() |
283 | this.dialogStatus = 'create' | 283 | this.dialogStatus = 'create' |
284 | this.dialogFormVisible = true | 284 | this.dialogFormVisible = true |
285 | this.$nextTick(() => { | 285 | this.$nextTick(() => { |
286 | this.$refs['dataForm'].clearValidate() | 286 | this.$refs['dataForm'].clearValidate() |
287 | }) | 287 | }) |
288 | }, | 288 | }, |
289 | createData() { | 289 | createData() { |
290 | this.$refs['dataForm'].validate((valid) => { | 290 | this.$refs['dataForm'].validate((valid) => { |
291 | if (valid) { | 291 | if (valid) { |
292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id | 292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id |
293 | this.temp.author = 'vue-element-admin' | 293 | this.temp.author = '秀野堂主' |
294 | createArticle(this.temp).then(() => { | 294 | createArticle(this.temp).then(() => { |
295 | this.list.unshift(this.temp) | 295 | this.list.unshift(this.temp) |
296 | this.dialogFormVisible = false | 296 | this.dialogFormVisible = false |
297 | this.$notify({ | 297 | this.$notify({ |
298 | title: '成功', | 298 | title: '成功', |
299 | message: '创建成功', | 299 | message: '创建成功', |
300 | type: 'success', | 300 | type: 'success', |
301 | duration: 2000 | 301 | duration: 2000 |
302 | }) | 302 | }) |
303 | }) | 303 | }) |
304 | } | 304 | } |
305 | }) | 305 | }) |
306 | }, | 306 | }, |
307 | handleUpdate(row) { | 307 | handleUpdate(row) { |
308 | this.temp = Object.assign({}, row) // copy obj | 308 | this.temp = Object.assign({}, row) // copy obj |
309 | this.temp.timestamp = new Date(this.temp.timestamp) | 309 | this.temp.timestamp = new Date(this.temp.timestamp) |
310 | this.dialogStatus = 'update' | 310 | this.dialogStatus = 'update' |
311 | this.dialogFormVisible = true | 311 | this.dialogFormVisible = true |
312 | this.$nextTick(() => { | 312 | this.$nextTick(() => { |
313 | this.$refs['dataForm'].clearValidate() | 313 | this.$refs['dataForm'].clearValidate() |
314 | }) | 314 | }) |
315 | }, | 315 | }, |
316 | updateData() { | 316 | updateData() { |
317 | this.$refs['dataForm'].validate((valid) => { | 317 | this.$refs['dataForm'].validate((valid) => { |
318 | if (valid) { | 318 | if (valid) { |
319 | const tempData = Object.assign({}, this.temp) | 319 | const tempData = Object.assign({}, this.temp) |
320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 | 320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 |
321 | updateArticle(tempData).then(() => { | 321 | updateArticle(tempData).then(() => { |
322 | const index = this.list.findIndex(v => v.id === this.temp.id) | 322 | const index = this.list.findIndex(v => v.id === this.temp.id) |
323 | this.list.splice(index, 1, this.temp) | 323 | this.list.splice(index, 1, this.temp) |
324 | this.dialogFormVisible = false | 324 | this.dialogFormVisible = false |
325 | this.$notify({ | 325 | this.$notify({ |
326 | title: '成功', | 326 | title: '成功', |
327 | message: '更新成功', | 327 | message: '更新成功', |
328 | type: 'success', | 328 | type: 'success', |
329 | duration: 2000 | 329 | duration: 2000 |
330 | }) | 330 | }) |
331 | }) | 331 | }) |
332 | } | 332 | } |
333 | }) | 333 | }) |
334 | }, | 334 | }, |
335 | handleDelete(row, index) { | 335 | handleDelete(row, index) { |
336 | this.$notify({ | 336 | this.$notify({ |
337 | title: '成功', | 337 | title: '成功', |
338 | message: '删除成功', | 338 | message: '删除成功', |
339 | type: 'success', | 339 | type: 'success', |
340 | duration: 2000 | 340 | duration: 2000 |
341 | }) | 341 | }) |
342 | this.list.splice(index, 1) | 342 | this.list.splice(index, 1) |
343 | }, | 343 | }, |
344 | handleFetchPv(pv) { | 344 | handleFetchPv(pv) { |
345 | fetchPv(pv).then(response => { | 345 | fetchPv(pv).then(response => { |
346 | this.pvData = response.data.pvData | 346 | this.pvData = response.data.pvData |
347 | this.dialogPvVisible = true | 347 | this.dialogPvVisible = true |
348 | }) | 348 | }) |
349 | }, | 349 | }, |
350 | handleDownload() { | 350 | handleDownload() { |
351 | this.downloadLoading = true | 351 | this.downloadLoading = true |
352 | import('@/vendor/Export2Excel').then(excel => { | 352 | import('@/vendor/Export2Excel').then(excel => { |
353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] | 353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] |
354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] | 354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] |
355 | const data = this.formatJson(filterVal) | 355 | const data = this.formatJson(filterVal) |
356 | excel.export_json_to_excel({ | 356 | excel.export_json_to_excel({ |
357 | header: tHeader, | 357 | header: tHeader, |
358 | data, | 358 | data, |
359 | filename: 'table-list' | 359 | filename: 'table-list' |
360 | }) | 360 | }) |
361 | this.downloadLoading = false | 361 | this.downloadLoading = false |
362 | }) | 362 | }) |
363 | }, | 363 | }, |
364 | formatJson(filterVal) { | 364 | formatJson(filterVal) { |
365 | return this.list.map(v => filterVal.map(j => { | 365 | return this.list.map(v => filterVal.map(j => { |
366 | if (j === 'timestamp') { | 366 | if (j === 'timestamp') { |
367 | return parseTime(v[j]) | 367 | return parseTime(v[j]) |
368 | } else { | 368 | } else { |
369 | return v[j] | 369 | return v[j] |
370 | } | 370 | } |
371 | })) | 371 | })) |
372 | }, | 372 | }, |
373 | getSortClass: function(key) { | 373 | getSortClass: function(key) { |
374 | const sort = this.listQuery.sort | 374 | const sort = this.listQuery.sort |
375 | return sort === `+${key}` ? 'ascending' : 'descending' | 375 | return sort === `+${key}` ? 'ascending' : 'descending' |
376 | } | 376 | } |
377 | } | 377 | } |
378 | } | 378 | } |
379 | </script> | 379 | </script> |
380 | 380 |
src/views/table/complex-table.vue
1 | <template> | 1 | <template> |
2 | <div class="app-container"> | 2 | <div class="app-container"> |
3 | <div class="filter-container"> | 3 | <div class="filter-container"> |
4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> | 4 | <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" /> |
5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> | 5 | <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item"> |
6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> | 6 | <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" /> |
7 | </el-select> | 7 | </el-select> |
8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> | 8 | <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px"> |
9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> | 9 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" /> |
10 | </el-select> | 10 | </el-select> |
11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> | 11 | <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter"> |
12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> | 12 | <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" /> |
13 | </el-select> | 13 | </el-select> |
14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> | 14 | <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter"> |
15 | {{ $t('table.search') }} | 15 | {{ $t('table.search') }} |
16 | </el-button> | 16 | </el-button> |
17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> | 17 | <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate"> |
18 | {{ $t('table.add') }} | 18 | {{ $t('table.add') }} |
19 | </el-button> | 19 | </el-button> |
20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> | 20 | <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload"> |
21 | {{ $t('table.export') }} | 21 | {{ $t('table.export') }} |
22 | </el-button> | 22 | </el-button> |
23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> | 23 | <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1"> |
24 | {{ $t('table.reviewer') }} | 24 | {{ $t('table.reviewer') }} |
25 | </el-checkbox> | 25 | </el-checkbox> |
26 | </div> | 26 | </div> |
27 | 27 | ||
28 | <el-table | 28 | <el-table |
29 | :key="tableKey" | 29 | :key="tableKey" |
30 | v-loading="listLoading" | 30 | v-loading="listLoading" |
31 | :data="list" | 31 | :data="list" |
32 | border | 32 | border |
33 | fit | 33 | fit |
34 | highlight-current-row | 34 | highlight-current-row |
35 | style="width: 100%;" | 35 | style="width: 100%;" |
36 | @sort-change="sortChange" | 36 | @sort-change="sortChange" |
37 | > | 37 | > |
38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> | 38 | <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')"> |
39 | <template slot-scope="{row}"> | 39 | <template slot-scope="{row}"> |
40 | <span>{{ row.id }}</span> | 40 | <span>{{ row.id }}</span> |
41 | </template> | 41 | </template> |
42 | </el-table-column> | 42 | </el-table-column> |
43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> | 43 | <el-table-column :label="$t('table.date')" width="150px" align="center"> |
44 | <template slot-scope="{row}"> | 44 | <template slot-scope="{row}"> |
45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> | 45 | <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> |
46 | </template> | 46 | </template> |
47 | </el-table-column> | 47 | </el-table-column> |
48 | <el-table-column :label="$t('table.title')" min-width="150px"> | 48 | <el-table-column :label="$t('table.title')" min-width="150px"> |
49 | <template slot-scope="{row}"> | 49 | <template slot-scope="{row}"> |
50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> | 50 | <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span> |
51 | <el-tag>{{ row.type | typeFilter }}</el-tag> | 51 | <el-tag>{{ row.type | typeFilter }}</el-tag> |
52 | </template> | 52 | </template> |
53 | </el-table-column> | 53 | </el-table-column> |
54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> | 54 | <el-table-column :label="$t('table.author')" width="110px" align="center"> |
55 | <template slot-scope="{row}"> | 55 | <template slot-scope="{row}"> |
56 | <span>{{ row.author }}</span> | 56 | <span>{{ row.author }}</span> |
57 | </template> | 57 | </template> |
58 | </el-table-column> | 58 | </el-table-column> |
59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> | 59 | <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center"> |
60 | <template slot-scope="{row}"> | 60 | <template slot-scope="{row}"> |
61 | <span style="color:red;">{{ row.reviewer }}</span> | 61 | <span style="color:red;">{{ row.reviewer }}</span> |
62 | </template> | 62 | </template> |
63 | </el-table-column> | 63 | </el-table-column> |
64 | <el-table-column :label="$t('table.importance')" width="80px"> | 64 | <el-table-column :label="$t('table.importance')" width="80px"> |
65 | <template slot-scope="{row}"> | 65 | <template slot-scope="{row}"> |
66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> | 66 | <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" /> |
67 | </template> | 67 | </template> |
68 | </el-table-column> | 68 | </el-table-column> |
69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> | 69 | <el-table-column :label="$t('table.readings')" align="center" width="95"> |
70 | <template slot-scope="{row}"> | 70 | <template slot-scope="{row}"> |
71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> | 71 | <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span> |
72 | <span v-else>0</span> | 72 | <span v-else>0</span> |
73 | </template> | 73 | </template> |
74 | </el-table-column> | 74 | </el-table-column> |
75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> | 75 | <el-table-column :label="$t('table.status')" class-name="status-col" width="100"> |
76 | <template slot-scope="{row}"> | 76 | <template slot-scope="{row}"> |
77 | <el-tag :type="row.status | statusFilter"> | 77 | <el-tag :type="row.status | statusFilter"> |
78 | {{ row.status }} | 78 | {{ row.status }} |
79 | </el-tag> | 79 | </el-tag> |
80 | </template> | 80 | </template> |
81 | </el-table-column> | 81 | </el-table-column> |
82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> | 82 | <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width"> |
83 | <template slot-scope="{row,$index}"> | 83 | <template slot-scope="{row,$index}"> |
84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> | 84 | <el-button type="primary" size="mini" @click="handleUpdate(row)"> |
85 | {{ $t('table.edit') }} | 85 | {{ $t('table.edit') }} |
86 | </el-button> | 86 | </el-button> |
87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> | 87 | <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')"> |
88 | {{ $t('table.publish') }} | 88 | {{ $t('table.publish') }} |
89 | </el-button> | 89 | </el-button> |
90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> | 90 | <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')"> |
91 | {{ $t('table.draft') }} | 91 | {{ $t('table.draft') }} |
92 | </el-button> | 92 | </el-button> |
93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> | 93 | <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)"> |
94 | {{ $t('table.delete') }} | 94 | {{ $t('table.delete') }} |
95 | </el-button> | 95 | </el-button> |
96 | </template> | 96 | </template> |
97 | </el-table-column> | 97 | </el-table-column> |
98 | </el-table> | 98 | </el-table> |
99 | 99 | ||
100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> | 100 | <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> |
101 | 101 | ||
102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> | 102 | <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> |
103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> | 103 | <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> |
104 | <el-form-item :label="$t('table.type')" prop="type"> | 104 | <el-form-item :label="$t('table.type')" prop="type"> |
105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> | 105 | <el-select v-model="temp.type" class="filter-item" placeholder="Please select"> |
106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> | 106 | <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /> |
107 | </el-select> | 107 | </el-select> |
108 | </el-form-item> | 108 | </el-form-item> |
109 | <el-form-item :label="$t('table.date')" prop="timestamp"> | 109 | <el-form-item :label="$t('table.date')" prop="timestamp"> |
110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> | 110 | <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" /> |
111 | </el-form-item> | 111 | </el-form-item> |
112 | <el-form-item :label="$t('table.title')" prop="title"> | 112 | <el-form-item :label="$t('table.title')" prop="title"> |
113 | <el-input v-model="temp.title" /> | 113 | <el-input v-model="temp.title" /> |
114 | </el-form-item> | 114 | </el-form-item> |
115 | <el-form-item :label="$t('table.status')"> | 115 | <el-form-item :label="$t('table.status')"> |
116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> | 116 | <el-select v-model="temp.status" class="filter-item" placeholder="Please select"> |
117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> | 117 | <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" /> |
118 | </el-select> | 118 | </el-select> |
119 | </el-form-item> | 119 | </el-form-item> |
120 | <el-form-item :label="$t('table.importance')"> | 120 | <el-form-item :label="$t('table.importance')"> |
121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> | 121 | <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" /> |
122 | </el-form-item> | 122 | </el-form-item> |
123 | <el-form-item :label="$t('table.remark')"> | 123 | <el-form-item :label="$t('table.remark')"> |
124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> | 124 | <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" /> |
125 | </el-form-item> | 125 | </el-form-item> |
126 | </el-form> | 126 | </el-form> |
127 | <div slot="footer" class="dialog-footer"> | 127 | <div slot="footer" class="dialog-footer"> |
128 | <el-button @click="dialogFormVisible = false"> | 128 | <el-button @click="dialogFormVisible = false"> |
129 | {{ $t('table.cancel') }} | 129 | {{ $t('table.cancel') }} |
130 | </el-button> | 130 | </el-button> |
131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> | 131 | <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()"> |
132 | {{ $t('table.confirm') }} | 132 | {{ $t('table.confirm') }} |
133 | </el-button> | 133 | </el-button> |
134 | </div> | 134 | </div> |
135 | </el-dialog> | 135 | </el-dialog> |
136 | 136 | ||
137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> | 137 | <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics"> |
138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> | 138 | <el-table :data="pvData" border fit highlight-current-row style="width: 100%"> |
139 | <el-table-column prop="key" label="Channel" /> | 139 | <el-table-column prop="key" label="Channel" /> |
140 | <el-table-column prop="pv" label="Pv" /> | 140 | <el-table-column prop="pv" label="Pv" /> |
141 | </el-table> | 141 | </el-table> |
142 | <span slot="footer" class="dialog-footer"> | 142 | <span slot="footer" class="dialog-footer"> |
143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> | 143 | <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button> |
144 | </span> | 144 | </span> |
145 | </el-dialog> | 145 | </el-dialog> |
146 | </div> | 146 | </div> |
147 | </template> | 147 | </template> |
148 | 148 | ||
149 | <script> | 149 | <script> |
150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' | 150 | import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article' |
151 | import waves from '@/directive/waves' // waves directive | 151 | import waves from '@/directive/waves' // waves directive |
152 | import { parseTime } from '@/utils' | 152 | import { parseTime } from '@/utils' |
153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination | 153 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination |
154 | 154 | ||
155 | const calendarTypeOptions = [ | 155 | const calendarTypeOptions = [ |
156 | { key: 'CN', display_name: 'China' }, | 156 | { key: 'CN', display_name: 'China' }, |
157 | { key: 'US', display_name: 'USA' }, | 157 | { key: 'US', display_name: 'USA' }, |
158 | { key: 'JP', display_name: 'Japan' }, | 158 | { key: 'JP', display_name: 'Japan' }, |
159 | { key: 'EU', display_name: 'Eurozone' } | 159 | { key: 'EU', display_name: 'Eurozone' } |
160 | ] | 160 | ] |
161 | 161 | ||
162 | // arr to obj, such as { CN : "China", US : "USA" } | 162 | // arr to obj, such as { CN : "China", US : "USA" } |
163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { | 163 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { |
164 | acc[cur.key] = cur.display_name | 164 | acc[cur.key] = cur.display_name |
165 | return acc | 165 | return acc |
166 | }, {}) | 166 | }, {}) |
167 | 167 | ||
168 | export default { | 168 | export default { |
169 | name: 'ComplexTable', | 169 | name: 'ComplexTable', |
170 | components: { Pagination }, | 170 | components: { Pagination }, |
171 | directives: { waves }, | 171 | directives: { waves }, |
172 | filters: { | 172 | filters: { |
173 | statusFilter(status) { | 173 | statusFilter(status) { |
174 | const statusMap = { | 174 | const statusMap = { |
175 | published: 'success', | 175 | published: 'success', |
176 | draft: 'info', | 176 | draft: 'info', |
177 | deleted: 'danger' | 177 | deleted: 'danger' |
178 | } | 178 | } |
179 | return statusMap[status] | 179 | return statusMap[status] |
180 | }, | 180 | }, |
181 | typeFilter(type) { | 181 | typeFilter(type) { |
182 | return calendarTypeKeyValue[type] | 182 | return calendarTypeKeyValue[type] |
183 | } | 183 | } |
184 | }, | 184 | }, |
185 | data() { | 185 | data() { |
186 | return { | 186 | return { |
187 | tableKey: 0, | 187 | tableKey: 0, |
188 | list: null, | 188 | list: null, |
189 | total: 0, | 189 | total: 0, |
190 | listLoading: true, | 190 | listLoading: true, |
191 | listQuery: { | 191 | listQuery: { |
192 | page: 1, | 192 | page: 1, |
193 | limit: 20, | 193 | limit: 20, |
194 | importance: undefined, | 194 | importance: undefined, |
195 | title: undefined, | 195 | title: undefined, |
196 | type: undefined, | 196 | type: undefined, |
197 | sort: '+id' | 197 | sort: '+id' |
198 | }, | 198 | }, |
199 | importanceOptions: [1, 2, 3], | 199 | importanceOptions: [1, 2, 3], |
200 | calendarTypeOptions, | 200 | calendarTypeOptions, |
201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], | 201 | sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }], |
202 | statusOptions: ['published', 'draft', 'deleted'], | 202 | statusOptions: ['published', 'draft', 'deleted'], |
203 | showReviewer: false, | 203 | showReviewer: false, |
204 | temp: { | 204 | temp: { |
205 | id: undefined, | 205 | id: undefined, |
206 | importance: 1, | 206 | importance: 1, |
207 | remark: '', | 207 | remark: '', |
208 | timestamp: new Date(), | 208 | timestamp: new Date(), |
209 | title: '', | 209 | title: '', |
210 | type: '', | 210 | type: '', |
211 | status: 'published' | 211 | status: 'published' |
212 | }, | 212 | }, |
213 | dialogFormVisible: false, | 213 | dialogFormVisible: false, |
214 | dialogStatus: '', | 214 | dialogStatus: '', |
215 | textMap: { | 215 | textMap: { |
216 | update: 'Edit', | 216 | update: 'Edit', |
217 | create: 'Create' | 217 | create: 'Create' |
218 | }, | 218 | }, |
219 | dialogPvVisible: false, | 219 | dialogPvVisible: false, |
220 | pvData: [], | 220 | pvData: [], |
221 | rules: { | 221 | rules: { |
222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], | 222 | type: [{ required: true, message: 'type is required', trigger: 'change' }], |
223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], | 223 | timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }], |
224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] | 224 | title: [{ required: true, message: 'title is required', trigger: 'blur' }] |
225 | }, | 225 | }, |
226 | downloadLoading: false | 226 | downloadLoading: false |
227 | } | 227 | } |
228 | }, | 228 | }, |
229 | created() { | 229 | created() { |
230 | this.getList() | 230 | this.getList() |
231 | }, | 231 | }, |
232 | methods: { | 232 | methods: { |
233 | getList() { | 233 | getList() { |
234 | this.listLoading = true | 234 | this.listLoading = true |
235 | fetchList(this.listQuery).then(response => { | 235 | fetchList(this.listQuery).then(response => { |
236 | this.list = response.data.items | 236 | this.list = response.data.items |
237 | this.total = response.data.total | 237 | this.total = response.data.total |
238 | 238 | ||
239 | // Just to simulate the time of the request | 239 | // Just to simulate the time of the request |
240 | setTimeout(() => { | 240 | setTimeout(() => { |
241 | this.listLoading = false | 241 | this.listLoading = false |
242 | }, 1.5 * 1000) | 242 | }, 1.5 * 1000) |
243 | }) | 243 | }) |
244 | }, | 244 | }, |
245 | handleFilter() { | 245 | handleFilter() { |
246 | this.listQuery.page = 1 | 246 | this.listQuery.page = 1 |
247 | this.getList() | 247 | this.getList() |
248 | }, | 248 | }, |
249 | handleModifyStatus(row, status) { | 249 | handleModifyStatus(row, status) { |
250 | this.$message({ | 250 | this.$message({ |
251 | message: '操作成功', | 251 | message: '操作成功', |
252 | type: 'success' | 252 | type: 'success' |
253 | }) | 253 | }) |
254 | row.status = status | 254 | row.status = status |
255 | }, | 255 | }, |
256 | sortChange(data) { | 256 | sortChange(data) { |
257 | const { prop, order } = data | 257 | const { prop, order } = data |
258 | if (prop === 'id') { | 258 | if (prop === 'id') { |
259 | this.sortByID(order) | 259 | this.sortByID(order) |
260 | } | 260 | } |
261 | }, | 261 | }, |
262 | sortByID(order) { | 262 | sortByID(order) { |
263 | if (order === 'ascending') { | 263 | if (order === 'ascending') { |
264 | this.listQuery.sort = '+id' | 264 | this.listQuery.sort = '+id' |
265 | } else { | 265 | } else { |
266 | this.listQuery.sort = '-id' | 266 | this.listQuery.sort = '-id' |
267 | } | 267 | } |
268 | this.handleFilter() | 268 | this.handleFilter() |
269 | }, | 269 | }, |
270 | resetTemp() { | 270 | resetTemp() { |
271 | this.temp = { | 271 | this.temp = { |
272 | id: undefined, | 272 | id: undefined, |
273 | importance: 1, | 273 | importance: 1, |
274 | remark: '', | 274 | remark: '', |
275 | timestamp: new Date(), | 275 | timestamp: new Date(), |
276 | title: '', | 276 | title: '', |
277 | status: 'published', | 277 | status: 'published', |
278 | type: '' | 278 | type: '' |
279 | } | 279 | } |
280 | }, | 280 | }, |
281 | handleCreate() { | 281 | handleCreate() { |
282 | this.resetTemp() | 282 | this.resetTemp() |
283 | this.dialogStatus = 'create' | 283 | this.dialogStatus = 'create' |
284 | this.dialogFormVisible = true | 284 | this.dialogFormVisible = true |
285 | this.$nextTick(() => { | 285 | this.$nextTick(() => { |
286 | this.$refs['dataForm'].clearValidate() | 286 | this.$refs['dataForm'].clearValidate() |
287 | }) | 287 | }) |
288 | }, | 288 | }, |
289 | createData() { | 289 | createData() { |
290 | this.$refs['dataForm'].validate((valid) => { | 290 | this.$refs['dataForm'].validate((valid) => { |
291 | if (valid) { | 291 | if (valid) { |
292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id | 292 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id |
293 | this.temp.author = 'vue-element-admin' | 293 | this.temp.author = '秀野堂主' |
294 | createArticle(this.temp).then(() => { | 294 | createArticle(this.temp).then(() => { |
295 | this.list.unshift(this.temp) | 295 | this.list.unshift(this.temp) |
296 | this.dialogFormVisible = false | 296 | this.dialogFormVisible = false |
297 | this.$notify({ | 297 | this.$notify({ |
298 | title: '成功', | 298 | title: '成功', |
299 | message: '创建成功', | 299 | message: '创建成功', |
300 | type: 'success', | 300 | type: 'success', |
301 | duration: 2000 | 301 | duration: 2000 |
302 | }) | 302 | }) |
303 | }) | 303 | }) |
304 | } | 304 | } |
305 | }) | 305 | }) |
306 | }, | 306 | }, |
307 | handleUpdate(row) { | 307 | handleUpdate(row) { |
308 | this.temp = Object.assign({}, row) // copy obj | 308 | this.temp = Object.assign({}, row) // copy obj |
309 | this.temp.timestamp = new Date(this.temp.timestamp) | 309 | this.temp.timestamp = new Date(this.temp.timestamp) |
310 | this.dialogStatus = 'update' | 310 | this.dialogStatus = 'update' |
311 | this.dialogFormVisible = true | 311 | this.dialogFormVisible = true |
312 | this.$nextTick(() => { | 312 | this.$nextTick(() => { |
313 | this.$refs['dataForm'].clearValidate() | 313 | this.$refs['dataForm'].clearValidate() |
314 | }) | 314 | }) |
315 | }, | 315 | }, |
316 | updateData() { | 316 | updateData() { |
317 | this.$refs['dataForm'].validate((valid) => { | 317 | this.$refs['dataForm'].validate((valid) => { |
318 | if (valid) { | 318 | if (valid) { |
319 | const tempData = Object.assign({}, this.temp) | 319 | const tempData = Object.assign({}, this.temp) |
320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 | 320 | tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 |
321 | updateArticle(tempData).then(() => { | 321 | updateArticle(tempData).then(() => { |
322 | const index = this.list.findIndex(v => v.id === this.temp.id) | 322 | const index = this.list.findIndex(v => v.id === this.temp.id) |
323 | this.list.splice(index, 1, this.temp) | 323 | this.list.splice(index, 1, this.temp) |
324 | this.dialogFormVisible = false | 324 | this.dialogFormVisible = false |
325 | this.$notify({ | 325 | this.$notify({ |
326 | title: '成功', | 326 | title: '成功', |
327 | message: '更新成功', | 327 | message: '更新成功', |
328 | type: 'success', | 328 | type: 'success', |
329 | duration: 2000 | 329 | duration: 2000 |
330 | }) | 330 | }) |
331 | }) | 331 | }) |
332 | } | 332 | } |
333 | }) | 333 | }) |
334 | }, | 334 | }, |
335 | handleDelete(row, index) { | 335 | handleDelete(row, index) { |
336 | this.$notify({ | 336 | this.$notify({ |
337 | title: '成功', | 337 | title: '成功', |
338 | message: '删除成功', | 338 | message: '删除成功', |
339 | type: 'success', | 339 | type: 'success', |
340 | duration: 2000 | 340 | duration: 2000 |
341 | }) | 341 | }) |
342 | this.list.splice(index, 1) | 342 | this.list.splice(index, 1) |
343 | }, | 343 | }, |
344 | handleFetchPv(pv) { | 344 | handleFetchPv(pv) { |
345 | fetchPv(pv).then(response => { | 345 | fetchPv(pv).then(response => { |
346 | this.pvData = response.data.pvData | 346 | this.pvData = response.data.pvData |
347 | this.dialogPvVisible = true | 347 | this.dialogPvVisible = true |
348 | }) | 348 | }) |
349 | }, | 349 | }, |
350 | handleDownload() { | 350 | handleDownload() { |
351 | this.downloadLoading = true | 351 | this.downloadLoading = true |
352 | import('@/vendor/Export2Excel').then(excel => { | 352 | import('@/vendor/Export2Excel').then(excel => { |
353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] | 353 | const tHeader = ['timestamp', 'title', 'type', 'importance', 'status'] |
354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] | 354 | const filterVal = ['timestamp', 'title', 'type', 'importance', 'status'] |
355 | const data = this.formatJson(filterVal) | 355 | const data = this.formatJson(filterVal) |
356 | excel.export_json_to_excel({ | 356 | excel.export_json_to_excel({ |
357 | header: tHeader, | 357 | header: tHeader, |
358 | data, | 358 | data, |
359 | filename: 'table-list' | 359 | filename: 'table-list' |
360 | }) | 360 | }) |
361 | this.downloadLoading = false | 361 | this.downloadLoading = false |
362 | }) | 362 | }) |
363 | }, | 363 | }, |
364 | formatJson(filterVal) { | 364 | formatJson(filterVal) { |
365 | return this.list.map(v => filterVal.map(j => { | 365 | return this.list.map(v => filterVal.map(j => { |
366 | if (j === 'timestamp') { | 366 | if (j === 'timestamp') { |
367 | return parseTime(v[j]) | 367 | return parseTime(v[j]) |
368 | } else { | 368 | } else { |
369 | return v[j] | 369 | return v[j] |
370 | } | 370 | } |
371 | })) | 371 | })) |
372 | }, | 372 | }, |
373 | getSortClass: function(key) { | 373 | getSortClass: function(key) { |
374 | const sort = this.listQuery.sort | 374 | const sort = this.listQuery.sort |
375 | return sort === `+${key}` ? 'ascending' : 'descending' | 375 | return sort === `+${key}` ? 'ascending' : 'descending' |
376 | } | 376 | } |
377 | } | 377 | } |
378 | } | 378 | } |
379 | </script> | 379 | </script> |
380 | 380 |
src/views/users/list.vue
File was created | 1 | <template> | |
2 | <div class="app-container"> | ||
3 | <div class="filter-container"> | ||
4 | <el-input | ||
5 | v-model="listQuery.title" | ||
6 | :placeholder="$t('table.title')" | ||
7 | style="width: 200px;" | ||
8 | class="filter-item" | ||
9 | @keyup.enter.native="handleFilter" | ||
10 | /> | ||
11 | <el-select | ||
12 | v-model="listQuery.importance" | ||
13 | :placeholder="$t('table.importance')" | ||
14 | clearable | ||
15 | style="width: 90px" | ||
16 | class="filter-item" | ||
17 | > | ||
18 | <el-option | ||
19 | v-for="item in importanceOptions" | ||
20 | :key="item" | ||
21 | :label="item" | ||
22 | :value="item" | ||
23 | /> | ||
24 | </el-select> | ||
25 | <el-select | ||
26 | v-model="listQuery.type" | ||
27 | :placeholder="$t('table.type')" | ||
28 | clearable | ||
29 | class="filter-item" | ||
30 | style="width: 130px" | ||
31 | > | ||
32 | <el-option | ||
33 | v-for="item in calendarTypeOptions" | ||
34 | :key="item.key" | ||
35 | :label="item.display_name+'('+item.key+')'" | ||
36 | :value="item.key" | ||
37 | /> | ||
38 | </el-select> | ||
39 | <el-select | ||
40 | v-model="listQuery.sort" | ||
41 | style="width: 140px" | ||
42 | class="filter-item" | ||
43 | @change="handleFilter" | ||
44 | > | ||
45 | <el-option | ||
46 | v-for="item in sortOptions" | ||
47 | :key="item.key" | ||
48 | :label="item.label" | ||
49 | :value="item.key" | ||
50 | /> | ||
51 | </el-select> | ||
52 | <el-button | ||
53 | v-waves | ||
54 | class="filter-item" | ||
55 | type="primary" | ||
56 | icon="el-icon-search" | ||
57 | @click="handleFilter" | ||
58 | > | ||
59 | {{ $t('table.search') }} | ||
60 | </el-button> | ||
61 | <el-button | ||
62 | class="filter-item" | ||
63 | style="margin-left: 10px;" | ||
64 | type="primary" | ||
65 | icon="el-icon-edit" | ||
66 | @click="handleCreate" | ||
67 | > | ||
68 | {{ $t('table.add') }} | ||
69 | </el-button> | ||
70 | <el-button | ||
71 | v-waves | ||
72 | :loading="downloadLoading" | ||
73 | class="filter-item" | ||
74 | type="primary" | ||
75 | icon="el-icon-download" | ||
76 | @click="handleDownload" | ||
77 | > | ||
78 | {{ $t('table.export') }} | ||
79 | </el-button> | ||
80 | <el-checkbox | ||
81 | v-model="showReviewer" | ||
82 | class="filter-item" | ||
83 | style="margin-left:15px;" | ||
84 | @change="tableKey=tableKey+1" | ||
85 | > | ||
86 | {{ $t('table.reviewer') }} | ||
87 | </el-checkbox> | ||
88 | </div> | ||
89 | |||
90 | <el-table | ||
91 | :key="tableKey" | ||
92 | v-loading="listLoading" | ||
93 | :data="list" | ||
94 | border | ||
95 | fit | ||
96 | highlight-current-row | ||
97 | style="width: 100%;" | ||
98 | @sort-change="sortChange" | ||
99 | > | ||
100 | <el-table-column | ||
101 | :label="$t('table.uid')" | ||
102 | prop="id" | ||
103 | sortable="custom" | ||
104 | align="center" | ||
105 | width="80" | ||
106 | :class-name="getSortClass('id')" | ||
107 | > | ||
108 | <template slot-scope="{row}"> | ||
109 | <span>{{ row.uid }}</span> | ||
110 | </template> | ||
111 | </el-table-column> | ||
112 | <el-table-column | ||
113 | :label="$t('table.create_time')" | ||
114 | width="150px" | ||
115 | align="center" | ||
116 | > | ||
117 | <template slot-scope="{row}"> | ||
118 | <span>{{ row.create_time | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> | ||
119 | </template> | ||
120 | </el-table-column> | ||
121 | <el-table-column | ||
122 | :label="$t('table.openid')" | ||
123 | min-width="150px" | ||
124 | > | ||
125 | <template slot-scope="{row}"> | ||
126 | <span | ||
127 | class="link-type" | ||
128 | @click="handleUpdate(row)" | ||
129 | >{{ row.title }}</span> | ||
130 | </template> | ||
131 | </el-table-column> | ||
132 | <el-table-column | ||
133 | :label="$t('table.nickname')" | ||
134 | width="110px" | ||
135 | align="center" | ||
136 | > | ||
137 | <template slot-scope="{row}"> | ||
138 | <span>{{ row.nickname }}</span> | ||
139 | <el-tag>{{ row.type | typeFilter }}</el-tag> | ||
140 | </template> | ||
141 | </el-table-column> | ||
142 | <el-table-column | ||
143 | v-if="showReviewer" | ||
144 | :label="$t('table.reviewer')" | ||
145 | width="110px" | ||
146 | align="center" | ||
147 | > | ||
148 | <template slot-scope="{row}"> | ||
149 | <span style="color:red;">{{ row.reviewer }}</span> | ||
150 | </template> | ||
151 | </el-table-column> | ||
152 | <el-table-column | ||
153 | :label="$t('table.importance')" | ||
154 | width="80px" | ||
155 | > | ||
156 | <template slot-scope="{row}"> | ||
157 | <svg-icon | ||
158 | v-for="n in +row.importance" | ||
159 | :key="n" | ||
160 | icon-class="star" | ||
161 | class="meta-item__icon" | ||
162 | /> | ||
163 | </template> | ||
164 | </el-table-column> | ||
165 | <el-table-column | ||
166 | :label="$t('table.son_of_adv')" | ||
167 | align="center" | ||
168 | width="95" | ||
169 | > | ||
170 | <template slot-scope="{row}"> | ||
171 | <span | ||
172 | v-if="row.son_of_adv" | ||
173 | class="link-type" | ||
174 | @click="handleFetchPv(row.son_of_adv)" | ||
175 | >{{ row.son_of_adv }}</span> | ||
176 | <span v-else>0</span> | ||
177 | </template> | ||
178 | </el-table-column> | ||
179 | <el-table-column | ||
180 | :label="$t('table.status')" | ||
181 | class-name="status-col" | ||
182 | width="100" | ||
183 | > | ||
184 | <template slot-scope="{row}"> | ||
185 | <el-tag :type="row.status | statusFilter">{{ row.status }}</el-tag> | ||
186 | </template> | ||
187 | </el-table-column> | ||
188 | <el-table-column | ||
189 | :label="$t('table.actions')" | ||
190 | align="center" | ||
191 | width="230" | ||
192 | class-name="small-padding fixed-width" | ||
193 | > | ||
194 | <template slot-scope="{row,$index}"> | ||
195 | <el-button | ||
196 | type="primary" | ||
197 | size="mini" | ||
198 | @click="handleUpdate(row)" | ||
199 | >{{ $t('table.edit') }}</el-button> | ||
200 | <el-button | ||
201 | v-if="row.status!='deleted'" | ||
202 | size="mini" | ||
203 | type="danger" | ||
204 | @click="handleDelete(row,$index)" | ||
205 | >{{ $t('table.delete') }}</el-button> | ||
206 | </template> | ||
207 | </el-table-column> | ||
208 | </el-table> | ||
209 | |||
210 | <pagination | ||
211 | v-show="total>0" | ||
212 | :total="total" | ||
213 | :page.sync="listQuery.page" | ||
214 | :limit.sync="listQuery.limit" | ||
215 | @pagination="getList" | ||
216 | /> | ||
217 | <el-dialog | ||
218 | :title="textMap[dialogStatus]" | ||
219 | :visible.sync="dialogFormVisible" | ||
220 | > | ||
221 | <el-form | ||
222 | ref="dataForm" | ||
223 | :rules="rules" | ||
224 | :model="temp" | ||
225 | label-position="left" | ||
226 | label-width="70px" | ||
227 | style="width: 400px; margin-left:50px;" | ||
228 | > | ||
229 | <el-form-item | ||
230 | :label="$t('table.type')" | ||
231 | prop="type" | ||
232 | > | ||
233 | <el-select | ||
234 | v-model="temp.type" | ||
235 | class="filter-item" | ||
236 | placeholder="Please select" | ||
237 | > | ||
238 | <el-option | ||
239 | v-for="item in calendarTypeOptions" | ||
240 | :key="item.key" | ||
241 | :label="item.display_name" | ||
242 | :value="item.key" | ||
243 | /> | ||
244 | </el-select> | ||
245 | </el-form-item> | ||
246 | <el-form-item | ||
247 | :label="$t('table.create_time')" | ||
248 | prop="create_time" | ||
249 | > | ||
250 | <el-date-picker | ||
251 | v-model="temp.create_time" | ||
252 | type="datetime" | ||
253 | placeholder="Please pick a date" | ||
254 | /> | ||
255 | </el-form-item> | ||
256 | <el-form-item | ||
257 | :label="$t('table.业务记录')" | ||
258 | prop="title" | ||
259 | > | ||
260 | <el-input v-model="temp.title" /> | ||
261 | </el-form-item> | ||
262 | <el-form-item :label="$t('table.status')"> | ||
263 | <el-select | ||
264 | v-model="temp.status" | ||
265 | class="filter-item" | ||
266 | placeholder="Please select" | ||
267 | > | ||
268 | <el-option | ||
269 | v-for="item in statusOptions" | ||
270 | :key="item" | ||
271 | :label="item" | ||
272 | :value="item" | ||
273 | /> | ||
274 | </el-select> | ||
275 | </el-form-item> | ||
276 | <el-form-item :label="$t('table.importance')"> | ||
277 | <el-rate | ||
278 | v-model="temp.importance" | ||
279 | :colors="['#99A9BF', '#F7BA2A', '#FF9900']" | ||
280 | :max="3" | ||
281 | style="margin-top:8px;" | ||
282 | /> | ||
283 | </el-form-item> | ||
284 | <el-form-item :label="$t('table.remark')"> | ||
285 | <el-input | ||
286 | v-model="temp.remark" | ||
287 | :autosize="{ minRows: 2, maxRows: 4}" | ||
288 | type="textarea" | ||
289 | placeholder="Please input" | ||
290 | /> | ||
291 | </el-form-item> | ||
292 | </el-form> | ||
293 | <div | ||
294 | slot="footer" | ||
295 | class="dialog-footer" | ||
296 | > | ||
297 | <el-button @click="dialogFormVisible = false">{{ $t('table.cancel') }}</el-button> | ||
298 | <el-button | ||
299 | type="primary" | ||
300 | @click="dialogStatus==='create'?createData():updateData()" | ||
301 | >{{ $t('table.confirm') }}</el-button> | ||
302 | </div> | ||
303 | </el-dialog> | ||
304 | |||
305 | <el-dialog | ||
306 | :visible.sync="dialogPvVisible" | ||
307 | title="Reading statistics" | ||
308 | > | ||
309 | <el-table | ||
310 | :data="pvData" | ||
311 | border | ||
312 | fit | ||
313 | highlight-current-row | ||
314 | style="width: 100%" | ||
315 | > | ||
316 | <el-table-column | ||
317 | prop="key" | ||
318 | label="Channel" | ||
319 | /> | ||
320 | <el-table-column | ||
321 | prop="pv" | ||
322 | label="Pv" | ||
323 | /> | ||
324 | </el-table> | ||
325 | <span | ||
326 | slot="footer" | ||
327 | class="dialog-footer" | ||
328 | > | ||
329 | <el-button | ||
330 | type="primary" | ||
331 | @click="dialogPvVisible = false" | ||
332 | >{{ $t('table.confirm') }}</el-button> | ||
333 | </span> | ||
334 | </el-dialog> | ||
335 | </div> | ||
336 | </template> | ||
337 | |||
338 | <script> | ||
339 | import { | ||
340 | fetchList, | ||
341 | fetchPv, | ||
342 | createUser, | ||
343 | updateUser, | ||
344 | delUser | ||
345 | } from '@/api/user' | ||
346 | import waves from '@/directive/waves' // waves directive | ||
347 | import { parseTime } from '@/utils' | ||
348 | import Pagination from '@/components/Pagination' // secondary package based on el-pagination | ||
349 | |||
350 | const calendarTypeOptions = [ | ||
351 | { key: 'CN', display_name: 'China' }, | ||
352 | { key: 'US', display_name: 'USA' }, | ||
353 | { key: 'JP', display_name: 'Japan' }, | ||
354 | { key: 'EU', display_name: 'Eurozone' } | ||
355 | ] | ||
356 | |||
357 | // arr to obj, such as { CN : "China", US : "USA" } | ||
358 | const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { | ||
359 | acc[cur.key] = cur.display_name | ||
360 | return acc | ||
361 | }, {}) | ||
362 | |||
363 | export default { | ||
364 | name: 'ComplexTable', | ||
365 | components: { Pagination }, | ||
366 | directives: { waves }, | ||
367 | filters: { | ||
368 | statusFilter(status) { | ||
369 | const statusMap = { | ||
370 | published: 'success', | ||
371 | draft: 'info', | ||
372 | deleted: 'danger' | ||
373 | } | ||
374 | return statusMap[status] | ||
375 | }, | ||
376 | typeFilter(type) { | ||
377 | return calendarTypeKeyValue[type] | ||
378 | } | ||
379 | }, | ||
380 | data() { | ||
381 | return { | ||
382 | tableKey: 0, | ||
383 | list: null, | ||
384 | total: 0, | ||
385 | listLoading: true, | ||
386 | listQuery: { | ||
387 | page: 1, | ||
388 | limit: 20, | ||
389 | importance: undefined, | ||
390 | title: undefined, | ||
391 | type: undefined, | ||
392 | sort: '+id' | ||
393 | }, | ||
394 | importanceOptions: [1, 2, 3], | ||
395 | calendarTypeOptions, | ||
396 | sortOptions: [ | ||
397 | { label: 'ID Ascending', key: '+id' }, | ||
398 | { label: 'ID Descending', key: '-id' } | ||
399 | ], | ||
400 | statusOptions: ['published', 'draft', 'deleted'], | ||
401 | showReviewer: false, | ||
402 | temp: { | ||
403 | id: undefined, | ||
404 | importance: 1, | ||
405 | remark: '', | ||
406 | create_time: new Date(), | ||
407 | title: '', | ||
408 | type: '', | ||
409 | status: 'published' | ||
410 | }, | ||
411 | dialogFormVisible: false, | ||
412 | dialogStatus: '', | ||
413 | textMap: { | ||
414 | update: 'Edit', | ||
415 | create: 'Create' | ||
416 | }, | ||
417 | dialogPvVisible: false, | ||
418 | pvData: [], | ||
419 | rules: { | ||
420 | type: [ | ||
421 | { required: true, message: 'type is required', trigger: 'change' } | ||
422 | ], | ||
423 | create_time: [ | ||
424 | { | ||
425 | type: 'date', | ||
426 | required: true, | ||
427 | message: 'create_time is required', | ||
428 | trigger: 'change' | ||
429 | } | ||
430 | ], | ||
431 | title: [ | ||
432 | { required: true, message: 'title is required', trigger: 'blur' } | ||
433 | ] | ||
434 | }, | ||
435 | downloadLoading: false | ||
436 | } | ||
437 | }, | ||
438 | created: async function() { | ||
439 | const params = { | ||
440 | card_no: '111' | ||
441 | } | ||
442 | const res = await this.getList(params) | ||
443 | console.log('resresresres', res) | ||
444 | }, | ||
445 | methods: { | ||
446 | getList() { | ||
447 | this.listLoading = true | ||
448 | fetchList(this.listQuery).then(response => { | ||
449 | this.list = response.data.items | ||
450 | this.total = response.data.total | ||
451 | |||
452 | // Just to simulate the time of the request | ||
453 | setTimeout(() => { | ||
454 | this.listLoading = false | ||
455 | }, 1.5 * 1000) | ||
456 | }) | ||
457 | }, | ||
458 | handleFilter() { | ||
459 | this.listQuery.page = 1 | ||
460 | this.getList() | ||
461 | }, | ||
462 | handleModifyStatus(row, status) { | ||
463 | this.$message({ | ||
464 | message: '操作成功', | ||
465 | type: 'success' | ||
466 | }) | ||
467 | row.status = status | ||
468 | }, | ||
469 | sortChange(data) { | ||
470 | const { prop, order } = data | ||
471 | if (prop === 'id') { | ||
472 | this.sortByID(order) | ||
473 | } | ||
474 | }, | ||
475 | sortByID(order) { | ||
476 | if (order === 'ascending') { | ||
477 | this.listQuery.sort = '+id' | ||
478 | } else { | ||
479 | this.listQuery.sort = '-id' | ||
480 | } | ||
481 | this.handleFilter() | ||
482 | }, | ||
483 | resetTemp() { | ||
484 | this.temp = { | ||
485 | id: undefined, | ||
486 | importance: 1, | ||
487 | remark: '', | ||
488 | create_time: new Date(), | ||
489 | title: '', | ||
490 | status: 'published', | ||
491 | type: '' | ||
492 | } | ||
493 | }, | ||
494 | handleCreate() { | ||
495 | this.resetTemp() | ||
496 | this.dialogStatus = 'create' | ||
497 | this.dialogFormVisible = true | ||
498 | this.$nextTick(() => { | ||
499 | this.$refs['dataForm'].clearValidate() | ||
500 | }) | ||
501 | // const data = [] | ||
502 | // createUser(data).then(() => { | ||
503 | // this.$notify({ | ||
504 | // title: "成功", | ||
505 | // message: "添加成功", | ||
506 | // type: "success", | ||
507 | // duration: 2000 | ||
508 | // }); | ||
509 | // }); | ||
510 | }, | ||
511 | createData() { | ||
512 | this.$refs['dataForm'].validate(valid => { | ||
513 | if (valid) { | ||
514 | this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id | ||
515 | this.temp.author = '秀野堂主' | ||
516 | createUser(this.temp).then(() => { | ||
517 | this.list.unshift(this.temp) | ||
518 | this.dialogFormVisible = false | ||
519 | this.$notify({ | ||
520 | title: '成功', | ||
521 | message: '创建成功', | ||
522 | type: 'success', | ||
523 | duration: 2000 | ||
524 | }) | ||
525 | }) | ||
526 | } | ||
527 | }) | ||
528 | }, | ||
529 | handleUpdate(row) { | ||
530 | this.temp = Object.assign({}, row) // copy obj | ||
531 | this.temp.create_time = new Date(this.temp.create_time) | ||
532 | this.dialogStatus = 'update' | ||
533 | this.dialogFormVisible = true | ||
534 | this.$nextTick(() => { | ||
535 | this.$refs['dataForm'].clearValidate() | ||
536 | }) | ||
537 | }, | ||
538 | updateData() { | ||
539 | this.$refs['dataForm'].validate(valid => { | ||
540 | if (valid) { | ||
541 | const tempData = Object.assign({}, this.temp) | ||
542 | tempData.create_time = +new Date(tempData.create_time) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464 | ||
543 | updateUser(tempData).then(() => { | ||
544 | const index = this.list.findIndex(v => v.id === this.temp.id) | ||
545 | this.list.splice(index, 1, this.temp) | ||
546 | this.dialogFormVisible = false | ||
547 | this.$notify({ | ||
548 | title: '成功', | ||
549 | message: '更新成功', | ||
550 | type: 'success', | ||
551 | duration: 2000 | ||
552 | }) | ||
553 | }) | ||
554 | } | ||
555 | }) | ||
556 | }, | ||
557 | handleDelete(row, index) { | ||
558 | const data = [] | ||
559 | delUser(data).then(() => { | ||
560 | this.list.splice(index, 1) | ||
561 | this.$notify({ | ||
562 | title: '成功', | ||
563 | message: '删除成功', | ||
564 | type: 'success', | ||
565 | duration: 2000 | ||
566 | }) | ||
567 | }) | ||
568 | }, | ||
569 | handleFetchPv(pv) { | ||
570 | fetchPv(pv).then(response => { | ||
571 | this.pvData = response.data.pvData | ||
572 | this.dialogPvVisible = true | ||
573 | }) | ||
574 | }, | ||
575 | handleDownload() { | ||
576 | this.downloadLoading = true | ||
577 | import('@/vendor/Export2Excel').then(excel => { | ||
578 | const tHeader = [ | ||
579 | 'create_time', | ||
580 | 'title', | ||
581 | 'type', | ||
582 | 'importance', | ||
583 | 'status' | ||
584 | ] | ||
585 | const filterVal = [ | ||
586 | 'create_time', | ||
587 | 'title', | ||
588 | 'type', | ||
589 | 'importance', | ||
590 | 'status' | ||
591 | ] | ||
592 | const data = this.formatJson(filterVal) | ||
593 | excel.export_json_to_excel({ | ||
594 | header: tHeader, | ||
595 | data, | ||
596 | filename: 'table-list' | ||
597 | }) | ||
598 | this.downloadLoading = false | ||
599 | }) | ||
600 | }, | ||
601 | formatJson(filterVal) { | ||
602 | return this.list.map(v => | ||
603 | filterVal.map(j => { | ||
604 | if (j === 'create_time') { | ||
605 | return parseTime(v[j]) | ||
606 | } else { | ||
607 | return v[j] | ||
608 | } | ||
609 | }) | ||
610 | ) | ||
611 | }, | ||
612 | getSortClass: function(key) { | ||
613 | const sort = this.listQuery.sort | ||
614 | return sort === `+${key}` ? 'ascending' : 'descending' | ||
615 | } | ||
616 | } | ||
617 | } | ||
618 | </script> | ||
619 |
tests/unit/utils/validate.spec.js
1 | import { validUsername, validURL, validLowerCase, validUpperCase, validAlphabets } from '@/utils/validate.js' | 1 | import { validUsername, validURL, validLowerCase, validUpperCase, validAlphabets } from '@/utils/validate.js' |
2 | describe('Utils:validate', () => { | 2 | describe('Utils:validate', () => { |
3 | it('validUsername', () => { | 3 | it('validUsername', () => { |
4 | expect(validUsername('admin')).toBe(true) | 4 | expect(validUsername('admin')).toBe(true) |
5 | expect(validUsername('assistant')).toBe(true) | ||
5 | expect(validUsername('runner')).toBe(true) | 6 | expect(validUsername('runner')).toBe(true) |
7 | expect(validUsername('shoper')).toBe(true) | ||
6 | // expect(validUsername('xxxx')).toBe(false) | 8 | // expect(validUsername('xxxx')).toBe(false) |
7 | // expect(validUsername('xxxx')).toBe(false) | 9 | // expect(validUsername('xxxx')).toBe(false) |
8 | // expect(validUsername('xxxx')).toBe(false) | 10 | // expect(validUsername('xxxx')).toBe(false) |
9 | }) | 11 | }) |
10 | it('validURL', () => { | 12 | it('validURL', () => { |
11 | // expect(validURL('https://github.com/PanJiaChen/vue-element-admin')).toBe(true) | 13 | // expect(validURL('https://github.com/PanJiaChen/vue-element-admin')).toBe(true) |
12 | // expect(validURL('http://github.com/PanJiaChen/vue-element-admin')).toBe(true) | 14 | // expect(validURL('http://github.com/PanJiaChen/vue-element-admin')).toBe(true) |
13 | // expect(validURL('github.com/PanJiaChen/vue-element-admin')).toBe(false) | 15 | // expect(validURL('github.com/PanJiaChen/vue-element-admin')).toBe(false) |
14 | }) | 16 | }) |
15 | it('validLowerCase', () => { | 17 | it('validLowerCase', () => { |
16 | expect(validLowerCase('abc')).toBe(true) | 18 | expect(validLowerCase('abc')).toBe(true) |
17 | expect(validLowerCase('Abc')).toBe(false) | 19 | expect(validLowerCase('Abc')).toBe(false) |
18 | expect(validLowerCase('123abc')).toBe(false) | 20 | expect(validLowerCase('123abc')).toBe(false) |
19 | }) | 21 | }) |
20 | it('validUpperCase', () => { | 22 | it('validUpperCase', () => { |
21 | expect(validUpperCase('ABC')).toBe(true) | 23 | expect(validUpperCase('ABC')).toBe(true) |
22 | expect(validUpperCase('Abc')).toBe(false) | 24 | expect(validUpperCase('Abc')).toBe(false) |
23 | expect(validUpperCase('123ABC')).toBe(false) | 25 | expect(validUpperCase('123ABC')).toBe(false) |
24 | }) | 26 | }) |
25 | it('validAlphabets', () => { | 27 | it('validAlphabets', () => { |
26 | expect(validAlphabets('ABC')).toBe(true) | 28 | expect(validAlphabets('ABC')).toBe(true) |
27 | expect(validAlphabets('Abc')).toBe(true) | 29 | expect(validAlphabets('Abc')).toBe(true) |
28 | expect(validAlphabets('123aBC')).toBe(false) | 30 | expect(validAlphabets('123aBC')).toBe(false) |
29 | }) | 31 | }) |
30 | }) | 32 | }) |
31 | 33 |