Commit f3ec4dd955193ce14f27df0ebc15c1a078b2f546

Authored by Adam
1 parent 96898eae45
Exists in master

auto commit the code by alias command

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' 15 import systemRouter from './modules/system'
16 import prodRouter from './modules/prod' 16 import prodRouter from './modules/prod'
17 import orderRouter from './modules/order'
17 import metaRouter from './modules/meta' 18 import metaRouter from './modules/meta'
18 import sitesRouter from './modules/sites' 19 import sitesRouter from './modules/sites'
19 20
20 /** 21 /**
21 * Note: sub-menu only appear when route children.length >= 1 22 * Note: sub-menu only appear when route children.length >= 1
22 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html 23 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
23 * 24 *
24 * hidden: true if set true, item will not show in the sidebar(default is false) 25 * hidden: true if set true, item will not show in the sidebar(default is false)
25 * alwaysShow: true if set true, will always show the root menu 26 * alwaysShow: true if set true, will always show the root menu
26 * if not set alwaysShow, when item has more than one children route, 27 * if not set alwaysShow, when item has more than one children route,
27 * it will becomes nested mode, otherwise not show the root menu 28 * it will becomes nested mode, otherwise not show the root menu
28 * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb 29 * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
29 * name:'router-name' the name is used by <keep-alive> (must set!!!) 30 * name:'router-name' the name is used by <keep-alive> (must set!!!)
30 * meta : { 31 * meta : {
31 roles: ['admin','assistant','runner', 'shoper'] control the page roles (you can set multiple roles) 32 roles: ['admin','assistant','runner', 'shoper'] control the page roles (you can set multiple roles)
32 title: 'title' the name show in sidebar and breadcrumb (recommend set) 33 title: 'title' the name show in sidebar and breadcrumb (recommend set)
33 icon: 'svg-name' the icon show in the sidebar 34 icon: 'svg-name' the icon show in the sidebar
34 noCache: true if set true, the page will no be cached(default is false) 35 noCache: true if set true, the page will no be cached(default is false)
35 affix: true if set true, the tag will affix in the tags-view 36 affix: true if set true, the tag will affix in the tags-view
36 breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) 37 breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
37 activeMenu: '/example/list' if set path, the sidebar will highlight the path you set 38 activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
38 } 39 }
39 */ 40 */
40 41
41 /** 42 /**
42 * constantRoutes 43 * constantRoutes
43 * a base page that does not have permission requirements 44 * a base page that does not have permission requirements
44 * all roles can be accessed 45 * all roles can be accessed
45 */ 46 */
46 export const constantRoutes = [{ 47 export const constantRoutes = [{
47 path: '/redirect', 48 path: '/redirect',
48 component: Layout, 49 component: Layout,
49 hidden: true, 50 hidden: true,
50 children: [{ 51 children: [{
51 path: '/redirect/:path*', 52 path: '/redirect/:path*',
52 component: () => import('@/views/redirect/index') 53 component: () => import('@/views/redirect/index')
53 }] 54 }]
54 }, 55 },
55 { 56 {
56 path: '/login', 57 path: '/login',
57 component: () => import('@/views/login/index'), 58 component: () => import('@/views/login/index'),
58 hidden: true 59 hidden: true
59 }, 60 },
60 { 61 {
61 path: '/auth-redirect', 62 path: '/auth-redirect',
62 component: () => import('@/views/login/auth-redirect'), 63 component: () => import('@/views/login/auth-redirect'),
63 hidden: true 64 hidden: true
64 }, 65 },
65 { 66 {
66 path: '/404', 67 path: '/404',
67 component: () => import('@/views/error-page/404'), 68 component: () => import('@/views/error-page/404'),
68 hidden: true 69 hidden: true
69 }, 70 },
70 { 71 {
71 path: '/500', 72 path: '/500',
72 component: () => import('@/views/error-page/500'), 73 component: () => import('@/views/error-page/500'),
73 hidden: true 74 hidden: true
74 }, 75 },
75 { 76 {
76 path: '/401', 77 path: '/401',
77 component: () => import('@/views/error-page/401'), 78 component: () => import('@/views/error-page/401'),
78 hidden: true 79 hidden: true
79 }, 80 },
80 { 81 {
81 path: '/', 82 path: '/',
82 component: Layout, 83 component: Layout,
83 redirect: '/dashboard', 84 redirect: '/dashboard',
84 children: [{ 85 children: [{
85 path: 'dashboard', 86 path: 'dashboard',
86 component: () => import('@/views/dashboard/index'), 87 component: () => import('@/views/dashboard/index'),
87 name: 'Dashboard', 88 name: 'Dashboard',
88 meta: { 89 meta: {
89 title: 'dashboard', 90 title: 'dashboard',
90 icon: 'dashboard', 91 icon: 'dashboard',
91 affix: true 92 affix: true
92 } 93 }
93 }] 94 }]
94 }, 95 },
95 // { 96 // {
96 // path: '/documentation', 97 // path: '/documentation',
97 // component: Layout, 98 // component: Layout,
98 // children: [ 99 // children: [
99 // { 100 // {
100 // path: 'index', 101 // path: 'index',
101 // component: () => import('@/views/documentation/index'), 102 // component: () => import('@/views/documentation/index'),
102 // name: 'Documentation', 103 // name: 'Documentation',
103 // meta: { title: 'documentation', icon: 'documentation', affix: true } 104 // meta: { title: 'documentation', icon: 'documentation', affix: true }
104 // } 105 // }
105 // ] 106 // ]
106 // }, 107 // },
107 { 108 {
108 path: '/guide', 109 path: '/guide',
109 component: Layout, 110 component: Layout,
110 redirect: '/guide/index', 111 redirect: '/guide/index',
111 children: [{ 112 children: [{
112 path: 'index', 113 path: 'index',
113 component: () => import('@/views/guide/index'), 114 component: () => import('@/views/guide/index'),
114 name: 'Guide', 115 name: 'Guide',
115 meta: { 116 meta: {
116 title: 'guide', 117 title: 'guide',
117 icon: 'guide', 118 icon: 'guide',
118 noCache: true 119 noCache: true
119 } 120 }
120 }] 121 }]
121 } 122 }
122 // { 123 // {
123 // path: '/profile', 124 // path: '/profile',
124 // component: Layout, 125 // component: Layout,
125 // redirect: '/profile/index', 126 // redirect: '/profile/index',
126 // hidden: true, 127 // hidden: true,
127 // children: [ 128 // children: [
128 // { 129 // {
129 // path: 'index', 130 // path: 'index',
130 // component: () => import('@/views/profile/index'), 131 // component: () => import('@/views/profile/index'),
131 // name: 'Profile', 132 // name: 'Profile',
132 // meta: { title: 'profile', icon: 'user', noCache: true } 133 // meta: { title: 'profile', icon: 'user', noCache: true }
133 // } 134 // }
134 // ] 135 // ]
135 // } 136 // }
136 ] 137 ]
137 138
138 /** 139 /**
139 * asyncRoutes 140 * asyncRoutes
140 * the routes that need to be dynamically loaded based on user roles 141 * the routes that need to be dynamically loaded based on user roles
141 */ 142 */
142 export const asyncRoutes = [ 143 export const asyncRoutes = [
143 // { 144 // {
144 // path: '/permission', 145 // path: '/permission',
145 // component: Layout, 146 // component: Layout,
146 // redirect: '/permission/page', 147 // redirect: '/permission/page',
147 // alwaysShow: true, // will always show the root menu 148 // alwaysShow: true, // will always show the root menu
148 // name: 'Permission', 149 // name: 'Permission',
149 // meta: { 150 // meta: {
150 // title: 'permission', 151 // title: 'permission',
151 // icon: 'lock', 152 // icon: 'lock',
152 // roles: ['admin', 'assistant'] // you can set roles in root nav 153 // roles: ['admin', 'assistant'] // you can set roles in root nav
153 // }, 154 // },
154 // children: [ 155 // children: [
155 // { 156 // {
156 // path: 'page', 157 // path: 'page',
157 // component: () => import('@/views/permission/page'), 158 // component: () => import('@/views/permission/page'),
158 // name: 'PagePermission', 159 // name: 'PagePermission',
159 // meta: { 160 // meta: {
160 // title: 'pagePermission', 161 // title: 'pagePermission',
161 // roles: ['admin','assistant'] // or you can only set roles in sub nav 162 // roles: ['admin','assistant'] // or you can only set roles in sub nav
162 // } 163 // }
163 // }, 164 // },
164 // { 165 // {
165 // path: 'directive', 166 // path: 'directive',
166 // component: () => import('@/views/permission/directive'), 167 // component: () => import('@/views/permission/directive'),
167 // name: 'DirectivePermission', 168 // name: 'DirectivePermission',
168 // meta: { 169 // meta: {
169 // title: 'directivePermission', 170 // title: 'directivePermission',
170 // roles: ['admin', 'shoper'] 171 // roles: ['admin', 'shoper']
171 // // if do not set roles, means: this page does not require permission 172 // // if do not set roles, means: this page does not require permission
172 // } 173 // }
173 // }, 174 // },
174 // { 175 // {
175 // path: 'role', 176 // path: 'role',
176 // component: () => import('@/views/permission/role'), 177 // component: () => import('@/views/permission/role'),
177 // name: 'RolePermission', 178 // name: 'RolePermission',
178 // meta: { 179 // meta: {
179 // title: 'rolePermission', 180 // title: 'rolePermission',
180 // roles: ['admin', 'runner'] 181 // roles: ['admin', 'runner']
181 // } 182 // }
182 // } 183 // }
183 // ] 184 // ]
184 // }, 185 // },
185 // tableRouter, 186 // tableRouter,
186 metaRouter, 187 metaRouter,
187 userRouter, 188 userRouter,
188 prodRouter, 189 prodRouter,
189 { 190 orderRouter,
190 path: '/orders',
191 component: Layout,
192 redirect: '/order/page',
193 alwaysShow: true, // will always show the root menu
194 name: 'Order',
195 meta: {
196 title: 'orders',
197 icon: 'shopping',
198 roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav
199 },
200 children: [{
201 path: 'page',
202 component: () => import('@/views/permission/page'),
203 name: 'OrderList',
204 meta: {
205 title: 'OrderList',
206 roles: ['admin', 'assistant', 'runner', 'shoper'] // or you can only set roles in sub nav
207 }
208 },
209 {
210 path: 'defined',
211 component: () => import('@/views/permission/directive'),
212 name: 'OrderDefiend',
213 meta: {
214 title: 'OrderDefiend',
215 roles: ['admin', 'assistant', 'runner', 'shoper']
216 // if do not set roles, means: this page does not require permission
217 }
218 }
219 ]
220 },
221 sitesRouter, 191 sitesRouter,
222 192
223 // { 193 // {
224 // path: '/icon', 194 // path: '/icon',
225 // component: Layout, 195 // component: Layout,
226 // children: [ 196 // children: [
227 // { 197 // {
228 // path: 'index', 198 // path: 'index',
229 // component: () => import('@/views/icons/index'), 199 // component: () => import('@/views/icons/index'),
230 // name: 'Icons', 200 // name: 'Icons',
231 // meta: { title: 'icons', icon: 'icon', noCache: true } 201 // meta: { title: 'icons', icon: 'icon', noCache: true }
232 // } 202 // }
233 // ] 203 // ]
234 // }, 204 // },
235 systemRouter, 205 systemRouter,
236 /** when your routing map is too long, you can split it into small modules **/ 206 /** when your routing map is too long, you can split it into small modules **/
237 // componentsRouter, 207 // componentsRouter,
238 // chartsRouter, 208 // chartsRouter,
239 // nestedRouter, 209 // nestedRouter,
240 // tableRouter, 210 // tableRouter,
241 211
242 // { 212 // {
243 // path: '/example', 213 // path: '/example',
244 // component: Layout, 214 // component: Layout,
245 // redirect: '/example/list', 215 // redirect: '/example/list',
246 // name: 'Example', 216 // name: 'Example',
247 // meta: { 217 // meta: {
248 // title: 'example', 218 // title: 'example',
249 // icon: 'example' 219 // icon: 'example'
250 // }, 220 // },
251 // children: [ 221 // children: [
252 // { 222 // {
253 // path: 'create', 223 // path: 'create',
254 // component: () => import('@/views/example/create'), 224 // component: () => import('@/views/example/create'),
255 // name: 'CreateArticle', 225 // name: 'CreateArticle',
256 // meta: { title: 'createArticle', icon: 'edit' } 226 // meta: { title: 'createArticle', icon: 'edit' }
257 // }, 227 // },
258 // { 228 // {
259 // path: 'edit/:id(\\d+)', 229 // path: 'edit/:id(\\d+)',
260 // component: () => import('@/views/example/edit'), 230 // component: () => import('@/views/example/edit'),
261 // name: 'EditArticle', 231 // name: 'EditArticle',
262 // meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' }, 232 // meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' },
263 // hidden: true 233 // hidden: true
264 // }, 234 // },
265 // { 235 // {
266 // path: 'list', 236 // path: 'list',
267 // component: () => import('@/views/example/list'), 237 // component: () => import('@/views/example/list'),
268 // name: 'ArticleList', 238 // name: 'ArticleList',
269 // meta: { title: 'articleList', icon: 'list' } 239 // meta: { title: 'articleList', icon: 'list' }
270 // } 240 // }
271 // ] 241 // ]
272 // }, 242 // },
273 243
274 // { 244 // {
275 // path: '/tab', 245 // path: '/tab',
276 // component: Layout, 246 // component: Layout,
277 // children: [ 247 // children: [
278 // { 248 // {
279 // path: 'index', 249 // path: 'index',
280 // component: () => import('@/views/tab/index'), 250 // component: () => import('@/views/tab/index'),
281 // name: 'Tab', 251 // name: 'Tab',
282 // meta: { title: 'tab', icon: 'tab' } 252 // meta: { title: 'tab', icon: 'tab' }
283 // } 253 // }
284 // ] 254 // ]
285 // }, 255 // },
286 256
287 // { 257 // {
288 // path: '/error', 258 // path: '/error',
289 // component: Layout, 259 // component: Layout,
290 // redirect: 'noRedirect', 260 // redirect: 'noRedirect',
291 // name: 'ErrorPages', 261 // name: 'ErrorPages',
292 // meta: { 262 // meta: {
293 // title: 'errorPages', 263 // title: 'errorPages',
294 // icon: '404' 264 // icon: '404'
295 // }, 265 // },
296 // children: [ 266 // children: [
297 // { 267 // {
298 // path: '401', 268 // path: '401',
299 // component: () => import('@/views/error-page/401'), 269 // component: () => import('@/views/error-page/401'),
300 // name: 'Page401', 270 // name: 'Page401',
301 // meta: { title: 'page401', noCache: true } 271 // meta: { title: 'page401', noCache: true }
302 // }, 272 // },
303 // { 273 // {
304 // path: '404', 274 // path: '404',
305 // component: () => import('@/views/error-page/404'), 275 // component: () => import('@/views/error-page/404'),
306 // name: 'Page404', 276 // name: 'Page404',
307 // meta: { title: 'page404', noCache: true } 277 // meta: { title: 'page404', noCache: true }
308 // } 278 // }
309 // ] 279 // ]
310 // }, 280 // },
311 281
312 // { 282 // {
313 // path: '/error-log', 283 // path: '/error-log',
314 // component: Layout, 284 // component: Layout,
315 // children: [ 285 // children: [
316 // { 286 // {
317 // path: 'log', 287 // path: 'log',
318 // component: () => import('@/views/error-log/index'), 288 // component: () => import('@/views/error-log/index'),
319 // name: 'ErrorLog', 289 // name: 'ErrorLog',
320 // meta: { title: 'errorLog', icon: 'bug' } 290 // meta: { title: 'errorLog', icon: 'bug' }
321 // } 291 // }
322 // ] 292 // ]
323 // }, 293 // },
324 294
325 // { 295 // {
326 // path: '/excel', 296 // path: '/excel',
327 // component: Layout, 297 // component: Layout,
328 // redirect: '/excel/export-excel', 298 // redirect: '/excel/export-excel',
329 // name: 'Excel', 299 // name: 'Excel',
330 // meta: { 300 // meta: {
331 // title: 'excel', 301 // title: 'excel',
332 // icon: 'excel' 302 // icon: 'excel'
333 // }, 303 // },
334 // children: [ 304 // children: [
335 // { 305 // {
336 // path: 'export-excel', 306 // path: 'export-excel',
337 // component: () => import('@/views/excel/export-excel'), 307 // component: () => import('@/views/excel/export-excel'),
338 // name: 'ExportExcel', 308 // name: 'ExportExcel',
339 // meta: { title: 'exportExcel' } 309 // meta: { title: 'exportExcel' }
340 // }, 310 // },
341 // { 311 // {
342 // path: 'export-selected-excel', 312 // path: 'export-selected-excel',
343 // component: () => import('@/views/excel/select-excel'), 313 // component: () => import('@/views/excel/select-excel'),
344 // name: 'SelectExcel', 314 // name: 'SelectExcel',
345 // meta: { title: 'selectExcel' } 315 // meta: { title: 'selectExcel' }
346 // }, 316 // },
347 // { 317 // {
348 // path: 'export-merge-header', 318 // path: 'export-merge-header',
349 // component: () => import('@/views/excel/merge-header'), 319 // component: () => import('@/views/excel/merge-header'),
350 // name: 'MergeHeader', 320 // name: 'MergeHeader',
351 // meta: { title: 'mergeHeader' } 321 // meta: { title: 'mergeHeader' }
352 // }, 322 // },
353 // { 323 // {
354 // path: 'upload-excel', 324 // path: 'upload-excel',
355 // component: () => import('@/views/excel/upload-excel'), 325 // component: () => import('@/views/excel/upload-excel'),
356 // name: 'UploadExcel', 326 // name: 'UploadExcel',
357 // meta: { title: 'uploadExcel' } 327 // meta: { title: 'uploadExcel' }
358 // } 328 // }
359 // ] 329 // ]
360 // }, 330 // },
361 331
362 // { 332 // {
363 // path: '/zip', 333 // path: '/zip',
364 // component: Layout, 334 // component: Layout,
365 // redirect: '/zip/download', 335 // redirect: '/zip/download',
366 // alwaysShow: true, 336 // alwaysShow: true,
367 // name: 'Zip', 337 // name: 'Zip',
368 // meta: { title: 'zip', icon: 'zip' }, 338 // meta: { title: 'zip', icon: 'zip' },
369 // children: [ 339 // children: [
370 // { 340 // {
371 // path: 'download', 341 // path: 'download',
372 // component: () => import('@/views/zip/index'), 342 // component: () => import('@/views/zip/index'),
373 // name: 'ExportZip', 343 // name: 'ExportZip',
374 // meta: { title: 'exportZip' } 344 // meta: { title: 'exportZip' }
375 // } 345 // }
376 // ] 346 // ]
377 // }, 347 // },
378 348
379 // { 349 // {
380 // path: '/pdf', 350 // path: '/pdf',
381 // component: Layout, 351 // component: Layout,
382 // redirect: '/pdf/index', 352 // redirect: '/pdf/index',
383 // children: [ 353 // children: [
384 // { 354 // {
385 // path: 'index', 355 // path: 'index',
386 // component: () => import('@/views/pdf/index'), 356 // component: () => import('@/views/pdf/index'),
387 // name: 'PDF', 357 // name: 'PDF',
388 // meta: { title: 'pdf', icon: 'pdf' } 358 // meta: { title: 'pdf', icon: 'pdf' }
389 // } 359 // }
390 // ] 360 // ]
391 // }, 361 // },
392 // { 362 // {
393 // path: '/pdf/download', 363 // path: '/pdf/download',
394 // component: () => import('@/views/pdf/download'), 364 // component: () => import('@/views/pdf/download'),
395 // hidden: true 365 // hidden: true
396 // }, 366 // },
397 367
398 // { 368 // {
399 // path: '/theme', 369 // path: '/theme',
400 // component: Layout, 370 // component: Layout,
401 // children: [ 371 // children: [
402 // { 372 // {
403 // path: 'index', 373 // path: 'index',
404 // component: () => import('@/views/theme/index'), 374 // component: () => import('@/views/theme/index'),
405 // name: 'Theme', 375 // name: 'Theme',
406 // meta: { title: 'theme', icon: 'theme' } 376 // meta: { title: 'theme', icon: 'theme' }
407 // } 377 // }
408 // ] 378 // ]
409 // }, 379 // },
410 380
411 // { 381 // {
412 // path: '/clipboard', 382 // path: '/clipboard',
413 // component: Layout, 383 // component: Layout,
414 // children: [ 384 // children: [
415 // { 385 // {
416 // path: 'index', 386 // path: 'index',
417 // component: () => import('@/views/clipboard/index'), 387 // component: () => import('@/views/clipboard/index'),
418 // name: 'ClipboardDemo', 388 // name: 'ClipboardDemo',
419 // meta: { title: 'clipboardDemo', icon: 'clipboard' } 389 // meta: { title: 'clipboardDemo', icon: 'clipboard' }
420 // } 390 // }
421 // ] 391 // ]
422 // }, 392 // },
423 393
424 // { 394 // {
425 // path: '/i18n', 395 // path: '/i18n',
426 // component: Layout, 396 // component: Layout,
427 // children: [ 397 // children: [
428 // { 398 // {
429 // path: 'index', 399 // path: 'index',
430 // component: () => import('@/views/i18n-demo/index'), 400 // component: () => import('@/views/i18n-demo/index'),
431 // name: 'I18n', 401 // name: 'I18n',
432 // meta: { title: 'i18n', icon: 'international' } 402 // meta: { title: 'i18n', icon: 'international' }
433 // } 403 // }
434 // ] 404 // ]
435 // }, 405 // },
436 406
437 // { 407 // {
438 // path: 'external-link', 408 // path: 'external-link',
439 // component: Layout, 409 // component: Layout,
440 // children: [ 410 // children: [
441 // { 411 // {
442 // path: 'https://github.com/PanJiaChen/vue-element-admin', 412 // path: 'https://github.com/PanJiaChen/vue-element-admin',
443 // meta: { title: 'externalLink', icon: 'link' } 413 // meta: { title: 'externalLink', icon: 'link' }
444 // } 414 // }
445 // ] 415 // ]
446 // }, 416 // },
447 417
448 // 404 page must be placed at the end !!! 418 // 404 page must be placed at the end !!!
449 { 419 {
450 path: '*', 420 path: '*',
451 redirect: '/404', 421 redirect: '/404',
452 hidden: true 422 hidden: true
453 } 423 }
454 ] 424 ]
455 425
456 const createRouter = () => new Router({ 426 const createRouter = () => new Router({
457 // mode: 'history', // require service support 427 // mode: 'history', // require service support
458 scrollBehavior: () => ({ 428 scrollBehavior: () => ({
459 y: 0 429 y: 0
460 }), 430 }),
461 routes: constantRoutes 431 routes: constantRoutes
462 }) 432 })
463 433
464 const router = createRouter() 434 const router = createRouter()
465 435
466 // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465 436 // Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
467 export function resetRouter() { 437 export function resetRouter() {
468 const newRouter = createRouter() 438 const newRouter = createRouter()
469 router.matcher = newRouter.matcher // reset router 439 router.matcher = newRouter.matcher // reset router
470 } 440 }
471 441
472 export default router 442 export default router
src/router/modules/prod.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 prodRouter = { 5 const prodRouter = {
6 path: '/prods', 6 path: '/prods',
7 component: Layout, 7 component: Layout,
8 redirect: '/prod/page', 8 redirect: '/prod/page',
9 alwaysShow: true, // will always show the root menu 9 alwaysShow: true, // will always show the root menu
10 name: 'Prod', 10 name: 'Prod',
11 meta: { 11 meta: {
12 title: 'prods', // 会自动被i18n替换 12 title: 'prods', // 会自动被i18n替换
13 icon: 'star', 13 icon: 'star',
14 roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav 14 roles: ['admin', 'assistant', 'runner', 'shoper'] // you can set roles in root nav
15 }, 15 },
16 children: [{ 16 children: [{
17 path: 'page', 17 path: 'page',
18 component: () => import('@/views/permission/page'), 18 component: () => import('@/views/permission/page'),
19 name: 'ProdList', 19 name: 'ProdList',
20 meta: { 20 meta: {
21 title: 'ProdList', 21 title: 'ProdList',
22 roles: ['admin', 'assistant', 'runner', 'shoper'] // or you can only set roles in sub nav 22 roles: ['admin', 'assistant', 'runner', 'shoper']
23 } 23 }
24 }, 24 },
25 { 25 {
26 path: 'defined', 26 path: 'defined',
27 component: () => import('@/views/permission/directive'), 27 component: () => import('@/views/permission/directive'),
28 name: 'ProdDefiend', 28 name: 'ProdDefiend',
29 meta: { 29 meta: {
30 title: 'ProdDefiend', 30 title: 'ProdDefiend',
31 roles: ['admin', 'assistant', 'shoper'] 31 roles: ['admin', 'assistant', 'shoper']
32 // if do not set roles, means: this page does not require permission 32 }
33 }, {
34 path: 'defined2',
35 component: () => import('@/views/prod/list'),
36 name: 'prod...',
37 meta: {
38 title: '产品列表',
39 roles: ['admin', 'assistant', 'shoper']
33 } 40 }
34 } 41 }
35 ] 42 ]
36 } 43 }
37 44
38 export default prodRouter 45 export default prodRouter
39 46
src/views/order/complex-table.vue
1 <template> File was deleted
2 <div class="app-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" />
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" />
7 </el-select>
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" />
10 </el-select>
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" />
13 </el-select>
14 <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
15 {{ $t('table.search') }}
16 </el-button>
17 <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
18 {{ $t('table.add') }}
19 </el-button>
20 <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
21 {{ $t('table.export') }}
22 </el-button>
23 <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
24 {{ $t('table.reviewer') }}
25 </el-checkbox>
26 </div>
27
28 <el-table
29 :key="tableKey"
30 v-loading="listLoading"
31 :data="list"
32 border
33 fit
34 highlight-current-row
35 style="width: 100%;"
36 @sort-change="sortChange"
37 >
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}">
40 <span>{{ row.id }}</span>
41 </template>
42 </el-table-column>
43 <el-table-column :label="$t('table.date')" width="150px" align="center">
44 <template slot-scope="{row}">
45 <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
46 </template>
47 </el-table-column>
48 <el-table-column :label="$t('table.title')" min-width="150px">
49 <template slot-scope="{row}">
50 <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span>
51 <el-tag>{{ row.type | typeFilter }}</el-tag>
52 </template>
53 </el-table-column>
54 <el-table-column :label="$t('table.author')" width="110px" align="center">
55 <template slot-scope="{row}">
56 <span>{{ row.author }}</span>
57 </template>
58 </el-table-column>
59 <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center">
60 <template slot-scope="{row}">
61 <span style="color:red;">{{ row.reviewer }}</span>
62 </template>
63 </el-table-column>
64 <el-table-column :label="$t('table.importance')" width="80px">
65 <template slot-scope="{row}">
66 <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" />
67 </template>
68 </el-table-column>
69 <el-table-column :label="$t('table.readings')" align="center" width="95">
70 <template slot-scope="{row}">
71 <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span>
72 <span v-else>0</span>
73 </template>
74 </el-table-column>
75 <el-table-column :label="$t('table.status')" class-name="status-col" width="100">
76 <template slot-scope="{row}">
77 <el-tag :type="row.status | statusFilter">
78 {{ row.status }}
79 </el-tag>
80 </template>
81 </el-table-column>
82 <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width">
83 <template slot-scope="{row,$index}">
84 <el-button type="primary" size="mini" @click="handleUpdate(row)">
85 {{ $t('table.edit') }}
86 </el-button>
87 <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')">
88 {{ $t('table.publish') }}
89 </el-button>
90 <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')">
91 {{ $t('table.draft') }}
92 </el-button>
93 <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)">
94 {{ $t('table.delete') }}
95 </el-button>
96 </template>
97 </el-table-column>
98 </el-table>
99
100 <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
101
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;">
104 <el-form-item :label="$t('table.type')" prop="type">
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" />
107 </el-select>
108 </el-form-item>
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" />
111 </el-form-item>
112 <el-form-item :label="$t('table.title')" prop="title">
113 <el-input v-model="temp.title" />
114 </el-form-item>
115 <el-form-item :label="$t('table.status')">
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" />
118 </el-select>
119 </el-form-item>
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;" />
122 </el-form-item>
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" />
125 </el-form-item>
126 </el-form>
127 <div slot="footer" class="dialog-footer">
128 <el-button @click="dialogFormVisible = false">
129 {{ $t('table.cancel') }}
130 </el-button>
131 <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
132 {{ $t('table.confirm') }}
133 </el-button>
134 </div>
135 </el-dialog>
136
137 <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
138 <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
139 <el-table-column prop="key" label="Channel" />
140 <el-table-column prop="pv" label="Pv" />
141 </el-table>
142 <span slot="footer" class="dialog-footer">
143 <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button>
144 </span>
145 </el-dialog>
146 </div>
147 </template>
148
149 <script>
150 import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
151 import waves from '@/directive/waves' // waves directive
152 import { parseTime } from '@/utils'
153 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
154
155 const calendarTypeOptions = [
156 { key: 'CN', display_name: 'China' },
157 { key: 'US', display_name: 'USA' },
158 { key: 'JP', display_name: 'Japan' },
159 { key: 'EU', display_name: 'Eurozone' }
160 ]
161
162 // arr to obj, such as { CN : "China", US : "USA" }
163 const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
164 acc[cur.key] = cur.display_name
165 return acc
166 }, {})
167
168 export default {
169 name: 'ComplexTable',
170 components: { Pagination },
171 directives: { waves },
172 filters: {
173 statusFilter(status) {
174 const statusMap = {
175 published: 'success',
176 draft: 'info',
177 deleted: 'danger'
178 }
179 return statusMap[status]
180 },
181 typeFilter(type) {
182 return calendarTypeKeyValue[type]
183 }
184 },
185 data() {
186 return {
187 tableKey: 0,
188 list: null,
189 total: 0,
190 listLoading: true,
191 listQuery: {
192 page: 1,
193 limit: 20,
194 importance: undefined,
195 title: undefined,
196 type: undefined,
197 sort: '+id'
198 },
199 importanceOptions: [1, 2, 3],
200 calendarTypeOptions,
201 sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
202 statusOptions: ['published', 'draft', 'deleted'],
203 showReviewer: false,
204 temp: {
205 id: undefined,
206 importance: 1,
207 remark: '',
208 timestamp: new Date(),
209 title: '',
210 type: '',
211 status: 'published'
212 },
213 dialogFormVisible: false,
214 dialogStatus: '',
215 textMap: {
216 update: 'Edit',
217 create: 'Create'
218 },
219 dialogPvVisible: false,
220 pvData: [],
221 rules: {
222 type: [{ required: true, message: 'type 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' }]
225 },
226 downloadLoading: false
227 }
228 },
229 created() {
230 this.getList()
231 },
232 methods: {
233 getList() {
234 this.listLoading = true
235 fetchList(this.listQuery).then(response => {
236 this.list = response.data.items
237 this.total = response.data.total
238
239 // Just to simulate the time of the request
240 setTimeout(() => {
241 this.listLoading = false
242 }, 1.5 * 1000)
243 })
244 },
245 handleFilter() {
246 this.listQuery.page = 1
247 this.getList()
248 },
249 handleModifyStatus(row, status) {
250 this.$message({
251 message: '操作成功',
252 type: 'success'
253 })
254 row.status = status
255 },
256 sortChange(data) {
257 const { prop, order } = data
258 if (prop === 'id') {
259 this.sortByID(order)
260 }
261 },
262 sortByID(order) {
263 if (order === 'ascending') {
264 this.listQuery.sort = '+id'
265 } else {
266 this.listQuery.sort = '-id'
267 }
268 this.handleFilter()
269 },
270 resetTemp() {
271 this.temp = {
272 id: undefined,
273 importance: 1,
274 remark: '',
275 timestamp: new Date(),
276 title: '',
277 status: 'published',
278 type: ''
279 }
280 },
281 handleCreate() {
282 this.resetTemp()
283 this.dialogStatus = 'create'
284 this.dialogFormVisible = true
285 this.$nextTick(() => {
286 this.$refs['dataForm'].clearValidate()
287 })
288 },
289 createData() {
290 this.$refs['dataForm'].validate((valid) => {
291 if (valid) {
292 this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
293 this.temp.author = '秀野堂主'
294 createArticle(this.temp).then(() => {
295 this.list.unshift(this.temp)
296 this.dialogFormVisible = false
297 this.$notify({
298 title: '成功',
299 message: '创建成功',
300 type: 'success',
301 duration: 2000
302 })
303 })
304 }
305 })
306 },
307 handleUpdate(row) {
308 this.temp = Object.assign({}, row) // copy obj
309 this.temp.timestamp = new Date(this.temp.timestamp)
310 this.dialogStatus = 'update'
311 this.dialogFormVisible = true
312 this.$nextTick(() => {
313 this.$refs['dataForm'].clearValidate()
314 })
315 },
316 updateData() {
317 this.$refs['dataForm'].validate((valid) => {
318 if (valid) {
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
321 updateArticle(tempData).then(() => {
322 const index = this.list.findIndex(v => v.id === this.temp.id)
323 this.list.splice(index, 1, this.temp)
324 this.dialogFormVisible = false
325 this.$notify({
326 title: '成功',
327 message: '更新成功',
328 type: 'success',
329 duration: 2000
330 })
331 })
332 }
333 })
334 },
335 handleDelete(row, index) {
336 this.$notify({
337 title: '成功',
338 message: '删除成功',
339 type: 'success',
340 duration: 2000
341 })
342 this.list.splice(index, 1)
343 },
344 handleFetchPv(pv) {
345 fetchPv(pv).then(response => {
346 this.pvData = response.data.pvData
347 this.dialogPvVisible = true
348 })
349 },
350 handleDownload() {
351 this.downloadLoading = true
352 import('@/vendor/Export2Excel').then(excel => {
353 const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
354 const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
355 const data = this.formatJson(filterVal)
356 excel.export_json_to_excel({
357 header: tHeader,
358 data,
359 filename: 'table-list'
360 })
361 this.downloadLoading = false
362 })
363 },
364 formatJson(filterVal) {
365 return this.list.map(v => filterVal.map(j => {
366 if (j === 'timestamp') {
367 return parseTime(v[j])
368 } else {
369 return v[j]
370 }
371 }))
372 },
373 getSortClass: function(key) {
374 const sort = this.listQuery.sort
375 return sort === `+${key}` ? 'ascending' : 'descending'
376 }
377 }
378 }
379 </script>
380 1 <template>
src/views/prod/complex-table.vue
1 <template> File was deleted
2 <div class="app-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" />
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" />
7 </el-select>
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" />
10 </el-select>
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" />
13 </el-select>
14 <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
15 {{ $t('table.search') }}
16 </el-button>
17 <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
18 {{ $t('table.add') }}
19 </el-button>
20 <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
21 {{ $t('table.export') }}
22 </el-button>
23 <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
24 {{ $t('table.reviewer') }}
25 </el-checkbox>
26 </div>
27
28 <el-table
29 :key="tableKey"
30 v-loading="listLoading"
31 :data="list"
32 border
33 fit
34 highlight-current-row
35 style="width: 100%;"
36 @sort-change="sortChange"
37 >
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}">
40 <span>{{ row.id }}</span>
41 </template>
42 </el-table-column>
43 <el-table-column :label="$t('table.date')" width="150px" align="center">
44 <template slot-scope="{row}">
45 <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
46 </template>
47 </el-table-column>
48 <el-table-column :label="$t('table.title')" min-width="150px">
49 <template slot-scope="{row}">
50 <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span>
51 <el-tag>{{ row.type | typeFilter }}</el-tag>
52 </template>
53 </el-table-column>
54 <el-table-column :label="$t('table.author')" width="110px" align="center">
55 <template slot-scope="{row}">
56 <span>{{ row.author }}</span>
57 </template>
58 </el-table-column>
59 <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center">
60 <template slot-scope="{row}">
61 <span style="color:red;">{{ row.reviewer }}</span>
62 </template>
63 </el-table-column>
64 <el-table-column :label="$t('table.importance')" width="80px">
65 <template slot-scope="{row}">
66 <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" />
67 </template>
68 </el-table-column>
69 <el-table-column :label="$t('table.readings')" align="center" width="95">
70 <template slot-scope="{row}">
71 <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span>
72 <span v-else>0</span>
73 </template>
74 </el-table-column>
75 <el-table-column :label="$t('table.status')" class-name="status-col" width="100">
76 <template slot-scope="{row}">
77 <el-tag :type="row.status | statusFilter">
78 {{ row.status }}
79 </el-tag>
80 </template>
81 </el-table-column>
82 <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width">
83 <template slot-scope="{row,$index}">
84 <el-button type="primary" size="mini" @click="handleUpdate(row)">
85 {{ $t('table.edit') }}
86 </el-button>
87 <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')">
88 {{ $t('table.publish') }}
89 </el-button>
90 <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')">
91 {{ $t('table.draft') }}
92 </el-button>
93 <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)">
94 {{ $t('table.delete') }}
95 </el-button>
96 </template>
97 </el-table-column>
98 </el-table>
99
100 <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
101
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;">
104 <el-form-item :label="$t('table.type')" prop="type">
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" />
107 </el-select>
108 </el-form-item>
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" />
111 </el-form-item>
112 <el-form-item :label="$t('table.title')" prop="title">
113 <el-input v-model="temp.title" />
114 </el-form-item>
115 <el-form-item :label="$t('table.status')">
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" />
118 </el-select>
119 </el-form-item>
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;" />
122 </el-form-item>
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" />
125 </el-form-item>
126 </el-form>
127 <div slot="footer" class="dialog-footer">
128 <el-button @click="dialogFormVisible = false">
129 {{ $t('table.cancel') }}
130 </el-button>
131 <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
132 {{ $t('table.confirm') }}
133 </el-button>
134 </div>
135 </el-dialog>
136
137 <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
138 <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
139 <el-table-column prop="key" label="Channel" />
140 <el-table-column prop="pv" label="Pv" />
141 </el-table>
142 <span slot="footer" class="dialog-footer">
143 <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button>
144 </span>
145 </el-dialog>
146 </div>
147 </template>
148
149 <script>
150 import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
151 import waves from '@/directive/waves' // waves directive
152 import { parseTime } from '@/utils'
153 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
154
155 const calendarTypeOptions = [
156 { key: 'CN', display_name: 'China' },
157 { key: 'US', display_name: 'USA' },
158 { key: 'JP', display_name: 'Japan' },
159 { key: 'EU', display_name: 'Eurozone' }
160 ]
161
162 // arr to obj, such as { CN : "China", US : "USA" }
163 const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
164 acc[cur.key] = cur.display_name
165 return acc
166 }, {})
167
168 export default {
169 name: 'ComplexTable',
170 components: { Pagination },
171 directives: { waves },
172 filters: {
173 statusFilter(status) {
174 const statusMap = {
175 published: 'success',
176 draft: 'info',
177 deleted: 'danger'
178 }
179 return statusMap[status]
180 },
181 typeFilter(type) {
182 return calendarTypeKeyValue[type]
183 }
184 },
185 data() {
186 return {
187 tableKey: 0,
188 list: null,
189 total: 0,
190 listLoading: true,
191 listQuery: {
192 page: 1,
193 limit: 20,
194 importance: undefined,
195 title: undefined,
196 type: undefined,
197 sort: '+id'
198 },
199 importanceOptions: [1, 2, 3],
200 calendarTypeOptions,
201 sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
202 statusOptions: ['published', 'draft', 'deleted'],
203 showReviewer: false,
204 temp: {
205 id: undefined,
206 importance: 1,
207 remark: '',
208 timestamp: new Date(),
209 title: '',
210 type: '',
211 status: 'published'
212 },
213 dialogFormVisible: false,
214 dialogStatus: '',
215 textMap: {
216 update: 'Edit',
217 create: 'Create'
218 },
219 dialogPvVisible: false,
220 pvData: [],
221 rules: {
222 type: [{ required: true, message: 'type 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' }]
225 },
226 downloadLoading: false
227 }
228 },
229 created() {
230 this.getList()
231 },
232 methods: {
233 getList() {
234 this.listLoading = true
235 fetchList(this.listQuery).then(response => {
236 this.list = response.data.items
237 this.total = response.data.total
238
239 // Just to simulate the time of the request
240 setTimeout(() => {
241 this.listLoading = false
242 }, 1.5 * 1000)
243 })
244 },
245 handleFilter() {
246 this.listQuery.page = 1
247 this.getList()
248 },
249 handleModifyStatus(row, status) {
250 this.$message({
251 message: '操作成功',
252 type: 'success'
253 })
254 row.status = status
255 },
256 sortChange(data) {
257 const { prop, order } = data
258 if (prop === 'id') {
259 this.sortByID(order)
260 }
261 },
262 sortByID(order) {
263 if (order === 'ascending') {
264 this.listQuery.sort = '+id'
265 } else {
266 this.listQuery.sort = '-id'
267 }
268 this.handleFilter()
269 },
270 resetTemp() {
271 this.temp = {
272 id: undefined,
273 importance: 1,
274 remark: '',
275 timestamp: new Date(),
276 title: '',
277 status: 'published',
278 type: ''
279 }
280 },
281 handleCreate() {
282 this.resetTemp()
283 this.dialogStatus = 'create'
284 this.dialogFormVisible = true
285 this.$nextTick(() => {
286 this.$refs['dataForm'].clearValidate()
287 })
288 },
289 createData() {
290 this.$refs['dataForm'].validate((valid) => {
291 if (valid) {
292 this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
293 this.temp.author = '秀野堂主'
294 createArticle(this.temp).then(() => {
295 this.list.unshift(this.temp)
296 this.dialogFormVisible = false
297 this.$notify({
298 title: '成功',
299 message: '创建成功',
300 type: 'success',
301 duration: 2000
302 })
303 })
304 }
305 })
306 },
307 handleUpdate(row) {
308 this.temp = Object.assign({}, row) // copy obj
309 this.temp.timestamp = new Date(this.temp.timestamp)
310 this.dialogStatus = 'update'
311 this.dialogFormVisible = true
312 this.$nextTick(() => {
313 this.$refs['dataForm'].clearValidate()
314 })
315 },
316 updateData() {
317 this.$refs['dataForm'].validate((valid) => {
318 if (valid) {
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
321 updateArticle(tempData).then(() => {
322 const index = this.list.findIndex(v => v.id === this.temp.id)
323 this.list.splice(index, 1, this.temp)
324 this.dialogFormVisible = false
325 this.$notify({
326 title: '成功',
327 message: '更新成功',
328 type: 'success',
329 duration: 2000
330 })
331 })
332 }
333 })
334 },
335 handleDelete(row, index) {
336 this.$notify({
337 title: '成功',
338 message: '删除成功',
339 type: 'success',
340 duration: 2000
341 })
342 this.list.splice(index, 1)
343 },
344 handleFetchPv(pv) {
345 fetchPv(pv).then(response => {
346 this.pvData = response.data.pvData
347 this.dialogPvVisible = true
348 })
349 },
350 handleDownload() {
351 this.downloadLoading = true
352 import('@/vendor/Export2Excel').then(excel => {
353 const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
354 const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
355 const data = this.formatJson(filterVal)
356 excel.export_json_to_excel({
357 header: tHeader,
358 data,
359 filename: 'table-list'
360 })
361 this.downloadLoading = false
362 })
363 },
364 formatJson(filterVal) {
365 return this.list.map(v => filterVal.map(j => {
366 if (j === 'timestamp') {
367 return parseTime(v[j])
368 } else {
369 return v[j]
370 }
371 }))
372 },
373 getSortClass: function(key) {
374 const sort = this.listQuery.sort
375 return sort === `+${key}` ? 'ascending' : 'descending'
376 }
377 }
378 }
379 </script>
380 1 <template>