Commit a86b16bba66bd2283ef0acc24ff86ac1ef8adb67

Authored by Adam
1 parent 0bd81688e7
Exists in master

auto commit the code by alias command

1 # just a flag 1 # just a flag
2 ENV = 'production' 2 ENV = 'production'
3 3
4 # base api 4 # base api
5 VUE_APP_BASE_API = '/prod-api' 5 #VUE_APP_BASE_API = '/prod-api'
6 6 VUE_APP_BASE_API = 'https://api.glass.xiuyetang.com/'
7 7
1 import Mock from 'mockjs' 1 import Mock from 'mockjs'
2 import { param2Obj } from '../src/utils' 2 import {
3 param2Obj
4 } from '../src/utils'
3 5
4 import user from './user' 6 import user from './user'
5 import role from './role' 7 import role from './role'
8 import prod from './prod'
6 import article from './article' 9 import article from './article'
7 import search from './remote-search' 10 import search from './remote-search'
8 11 //因为没有Mock上,所以会请求不到数据。报404
9 const mocks = [ 12 const mocks = [
10 ...user, 13 ...user,
11 ...role, 14 ...role,
12 ...article, 15 ...article,
16 ...prod,
13 ...search 17 ...search
14 ] 18 ]
15 19
16 // for front mock 20 // for front mock
17 // please use it cautiously, it will redefine XMLHttpRequest, 21 // please use it cautiously, it will redefine XMLHttpRequest,
18 // which will cause many of your third-party libraries to be invalidated(like progress event). 22 // which will cause many of your third-party libraries to be invalidated(like progress event).
19 export function mockXHR() { 23 export function mockXHR() {
20 // mock patch 24 // mock patch
21 // https://github.com/nuysoft/Mock/issues/300 25 // https://github.com/nuysoft/Mock/issues/300
22 Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send 26 Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
23 Mock.XHR.prototype.send = function() { 27 Mock.XHR.prototype.send = function () {
24 if (this.custom.xhr) { 28 if (this.custom.xhr) {
25 this.custom.xhr.withCredentials = this.withCredentials || false 29 this.custom.xhr.withCredentials = this.withCredentials || false
26 30
27 if (this.responseType) { 31 if (this.responseType) {
28 this.custom.xhr.responseType = this.responseType 32 this.custom.xhr.responseType = this.responseType
29 } 33 }
30 } 34 }
31 this.proxy_send(...arguments) 35 this.proxy_send(...arguments)
32 } 36 }
33 37
34 function XHR2ExpressReqWrap(respond) { 38 function XHR2ExpressReqWrap(respond) {
35 return function(options) { 39 return function (options) {
36 let result = null 40 let result = null
37 if (respond instanceof Function) { 41 if (respond instanceof Function) {
38 const { body, type, url } = options 42 const {
43 body,
44 type,
45 url
46 } = options
39 // https://expressjs.com/en/4x/api.html#req 47 // https://expressjs.com/en/4x/api.html#req
40 result = respond({ 48 result = respond({
41 method: type, 49 method: type,
42 body: JSON.parse(body), 50 body: JSON.parse(body),
43 query: param2Obj(url) 51 query: param2Obj(url)
44 }) 52 })
45 } else { 53 } else {
46 result = respond 54 result = respond
47 } 55 }
48 return Mock.mock(result) 56 return Mock.mock(result)
49 } 57 }
50 } 58 }
51 59
52 for (const i of mocks) { 60 for (const i of mocks) {
53 Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) 61 Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
54 } 62 }
55 } 63 }
56 64
57 // for mock server 65 // for mock server
58 const responseFake = (url, type, respond) => { 66 const responseFake = (url, type, respond) => {
59 return { 67 return {
60 url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`), 68 url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
61 type: type || 'get', 69 type: type || 'get',
62 response(req, res) { 70 response(req, res) {
63 console.log('request invoke:' + req.path) 71 console.log('request invoke:' + req.path)
64 res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) 72 res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
65 } 73 }
66 } 74 }
67 } 75 }
68 76
69 export default mocks.map(route => { 77 export default mocks.map(route => {
70 return responseFake(route.url, route.type, route.response) 78 return responseFake(route.url, route.type, route.response)
71 }) 79 })
72 80
1 import Mock from 'mockjs' 1 import Mock from 'mockjs'
2 // import logoPath from "~@/assets/img/yp_logo.jpeg" 2 // import logoPath from "~@/assets/img/yp_logo.jpeg"
3 3
4 const List = [] 4 const List = []
5 const count = 20 5 const count = 20
6 6
7 const baseContent = '<p>I am testing data, I am testing data.</p><p></p>' 7 const baseContent = '<p>I am testing data, I am testing data.</p><p></p>'
8 // const image_uri = logoPath 8 // const image_uri = logoPath
9 const image_uri = 'https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif' 9 const image_uri = 'https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif'
10 10
11 for (let i = 0; i < count; i++) { 11 for (let i = 0; i < count; i++) {
12 List.push(Mock.mock({ 12 List.push(Mock.mock({
13 pid: '@increment', 13 pid: '@increment', //产品id
14 pname: '@title(5,10)', 14 pname: '01-8701志平防蓝光-防辐射电脑网课眼镜,TR90弹性漆,近视镜,青春潮流', //产品名移交
15 timestamp: +Mock.Random.date('T'), 15 timestamp: +Mock.Random.date('T'), //产品时间
16 shoper: '@first', //所属工厂 16 shoper: '@first', //所属工厂
17 salescount: '@first', //购买次数 17 salescount: '@first', //购买次数
18 importance: '@integer(1, 3)', //排序权重 18 importance: '@integer(1, 3)', //排序-权重
19 prod_info_weight: '@integer(1, 3)', //重量 19 prod_info_weight: '@integer(1, 3)', //参数--->重量
20 prod_info_leg_long: '@integer(1, 3)', //腿长 20 prod_info_leg_long: '@integer(1, 3)', //参数--->腿长
21 prod_info_glass_width: '@integer(1, 3)', //镜宽 21 prod_info_glass_width: '@integer(1, 3)', //参数--->镜宽
22 prod_info_glass_height: '@integer(1, 3)', //镜高 22 prod_info_glass_height: '@integer(1, 3)', //参数--->镜高
23 prod_info_frame_width: '@integer(1, 3)', //框宽 23 prod_info_frame_width: '@integer(1, 3)', //参数--->框宽
24 prod_info_frame_height: '@integer(1, 3)', //框高 24 prod_info_frame_height: '@integer(1, 3)', //参数--->框高
25 prod_info_norse_width: '@integer(1, 3)', //鼻宽 25 prod_info_norse_width: '@integer(1, 3)', //参数--->鼻宽
26 prod_info_window_pic: [], //鼻宽 26 prod_info_window_pic: [], //鼻宽
27 image_uri: image_uri 27 image_uri: image_uri,
28 prod_memo: '',
29 // 'type|1': ['CN', 'US', 'JP', 'EU'],
30 // 'status|1': ['published', 'draft'],
31 'type|1': ['CN', 'US', 'JP', 'EU'], //本产品销售区域
32 'prod_status|1': ['published', 'draft'], //状态,上线-下线
33 judge_list: [], //评论管理
34 sku_list: [], //sku清单
35 sku_attr: [], //sku属性
28 })) 36 }))
29 } 37 }
30 38
31 export default [{ 39 export default [{
32 url: '/yp/prod/list', 40 url: '/yp/prod/list',
33 type: 'post', 41 type: 'post',
34 response: config => { 42 response: config => {
35 const { 43 const {
36 importance, 44 importance,
37 type, 45 type,
38 title, 46 pname,
39 page = 1, 47 page = 1,
40 limit = 20, 48 limit = 20,
41 sort 49 // sort
42 } = config.query 50 } = config.query
43 51
44 let mockList = List.filter(item => { 52 let mockList = List.filter(item => {
45 if (importance && item.importance !== +importance) return false 53 if (importance && item.importance !== +importance) return false
46 if (type && item.type !== type) return false 54 if (type && item.type !== type) return false
47 if (title && item.title.indexOf(title) < 0) return false 55 if (pname && item.pname.indexOf(pname) < 0) return false
48 return true 56 return true
49 }) 57 })
50 58
51 if (sort === '-id') { 59 // if (sort === '-pid') {
52 mockList = mockList.reverse() 60 // mockList = mockList.reverse()
53 } 61 // }
54
55 const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1)) 62 const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
56 63
57 return { 64 return {
58 code: 20000, 65 code: 20000,
59 data: { 66 data: {
60 total: mockList.length, 67 total: mockList.length,
61 items: pageList 68 items: pageList
62 } 69 }
63 } 70 }
64 } 71 }
65 }, 72 },
66
67 { 73 {
68 url: '/yp/prod/detail', 74 url: '/yp/prod/detail',
69 type: 'get', 75 type: 'get',
70 response: config => { 76 response: config => {
71 const { 77 const {
72 id 78 pid
73 } = config.query 79 } = config.query
74 for (const prod of List) { 80 for (const prod of List) {
75 if (prod.id === +id) { 81 if (prod.pid === +pid) {
76 return { 82 return {
77 code: 20000, 83 code: 20000,
78 data: prod 84 data: prod
79 } 85 }
80 } 86 }
81 } 87 }
82 } 88 }
83 }, 89 },
84 90
85 { 91 // {
86 url: '/yp/prod/pv', 92 // url: '/yp/prod/pv',
87 type: 'get', 93 // type: 'get',
88 response: _ => { 94 // response: _ => {
89 return { 95 // return {
90 code: 20000, 96 // code: 20000,
91 data: { 97 // data: {
92 pvData: [{ 98 // pvData: [{
93 key: 'PC', 99 // key: 'PC',
94 pv: 1024 100 // pv: 1024
95 }, 101 // },
96 { 102 // {
97 key: 'mobile', 103 // key: 'mobile',
98 pv: 1024 104 // pv: 1024
99 }, 105 // },
100 { 106 // {
101 key: 'ios', 107 // key: 'ios',
102 pv: 1024 108 // pv: 1024
103 }, 109 // },
104 { 110 // {
105 key: 'android', 111 // key: 'android',
106 pv: 1024 112 // pv: 1024
107 } 113 // }
108 ] 114 // ]
109 } 115 // }
110 } 116 // }
111 } 117 // }
112 }, 118 // },
113 119
114 { 120 {
115 url: '/yp/prod/create', 121 url: '/yp/prod/create',
116 type: 'post', 122 type: 'post',
117 response: _ => { 123 response: _ => {
118 return { 124 return {
119 code: 20000, 125 code: 20000,
120 data: 'success' 126 data: 'success'
121 } 127 }
122 } 128 }
123 }, 129 },
124 130
125 { 131 {
126 url: '/yp/prod/update', 132 url: '/yp/prod/update',
127 type: 'post', 133 type: 'post',
128 response: _ => { 134 response: _ => {
129 return { 135 return {
130 code: 20000, 136 code: 20000,
131 data: 'success' 137 data: 'success'
132 } 138 }
133 } 139 }
134 } 140 }
1 import request from '@/utils/request' 1 import request from '@/utils/request'
2 2
3 // export const getPersonInfo = data => { 3 // export const getPersonInfo = data => {
4 // return service({ 4 // return service({
5 // url: '/person_pay/getpersoninfo', 5 // url: '/person_pay/getpersoninfo',
6 // method: 'post', 6 // method: 'post',
7 // data 7 // data
8 // }) 8 // })
9 // } 9 // }
10 10
11 export function fetchList(query) { 11 export function fetchList(query) {
12 return request({ 12 return request({
13 url: '/yp/prod/list', 13 url: '/yp/prod/list',
14 method: 'post', 14 method: 'post',
15 params: query 15 data: query
16 }) 16 })
17 } 17 }
18 18
19 export function fetchArticle(id) { 19 export function fetchProd(pid) {
20 return request({ 20 return request({
21 url: '/yp/prod/detail', 21 url: '/yp/prod/detail',
22 method: 'get', 22 method: 'get',
23 params: { 23 params: {
24 id 24 pid
25 } 25 }
26 }) 26 })
27 } 27 }
28 28
29 export function fetchPv(pv) { 29 export function fetchPv(pv) {
30 return request({ 30 return request({
31 url: '/yp/prod/pv', 31 url: '/yp/prod/pv',
32 method: 'get', 32 method: 'get',
33 params: { 33 params: {
34 pv 34 pv
35 } 35 }
36 }) 36 })
37 } 37 }
38 38
39 export function createArticle(data) { 39 export function createArticle(data) {
40 return request({ 40 return request({
41 url: '/yp/prod/create', 41 url: '/yp/prod/create',
42 method: 'post', 42 method: 'post',
43 data 43 data
44 }) 44 })
45 } 45 }
46 46
47 export function updateArticle(data) { 47 export function updateArticle(data) {
48 return request({ 48 return request({
49 url: '/yp/prod/update', 49 url: '/yp/prod/update',
50 method: 'post', 50 method: 'post',
51 data 51 data
52 }) 52 })
53 } 53 }
54 54
src/components/Pagination/index.vue
1 <template> 1 <template>
2 <div :class="{'hidden':hidden}" class="pagination-container"> 2 <div
3 :class="{'hidden':hidden}"
4 class="pagination-container"
5 >
3 <el-pagination 6 <el-pagination
4 :background="background" 7 :background="background"
5 :current-page.sync="currentPage" 8 :current-page.sync="currentPage"
6 :page-size.sync="pageSize" 9 :page-size.sync="pageSize"
7 :layout="layout" 10 :layout="layout"
8 :page-sizes="pageSizes" 11 :page-sizes="pageSizes"
9 :total="total" 12 :total="total"
10 v-bind="$attrs" 13 v-bind="$attrs"
11 @size-change="handleSizeChange" 14 @size-change="handleSizeChange"
12 @current-change="handleCurrentChange" 15 @current-change="handleCurrentChange"
13 /> 16 />
14 </div> 17 </div>
15 </template> 18 </template>
16 19
17 <script> 20 <script>
18 import { scrollTo } from '@/utils/scroll-to' 21 import { scrollTo } from '@/utils/scroll-to'
19 22
20 export default { 23 export default {
21 name: 'Pagination', 24 name: 'Pagination',
22 props: { 25 props: {
23 total: { 26 total: {
24 required: true, 27 required: true,
25 type: Number 28 type: Number
26 }, 29 },
27 page: { 30 page: {
28 type: Number, 31 type: Number,
29 default: 1 32 default: 1
30 }, 33 },
31 limit: { 34 limit: {
32 type: Number, 35 type: Number,
33 default: 20 36 default: 20
34 }, 37 },
35 pageSizes: { 38 pageSizes: {
36 type: Array, 39 type: Array,
37 default() { 40 default() {
38 return [10, 20, 30, 50] 41 return [10, 20, 30, 50]
39 } 42 }
40 }, 43 },
41 layout: { 44 layout: {
42 type: String, 45 type: String,
43 default: 'total, sizes, prev, pager, next, jumper' 46 default: 'total, sizes, prev, pager, next, jumper'
44 }, 47 },
45 background: { 48 background: {
46 type: Boolean, 49 type: Boolean,
47 default: true 50 default: true
48 }, 51 },
49 autoScroll: { 52 autoScroll: {
50 type: Boolean, 53 type: Boolean,
51 default: true 54 default: true
52 }, 55 },
53 hidden: { 56 hidden: {
54 type: Boolean, 57 type: Boolean,
55 default: false 58 default: false
56 } 59 }
57 }, 60 },
58 computed: { 61 computed: {
59 currentPage: { 62 currentPage: {
60 get() { 63 get() {
61 return this.page 64 return this.page
62 }, 65 },
63 set(val) { 66 set(val) {
64 this.$emit('update:page', val) 67 this.$emit('update:page', val)
65 } 68 }
66 }, 69 },
67 pageSize: { 70 pageSize: {
68 get() { 71 get() {
69 return this.limit 72 return this.limit
70 }, 73 },
71 set(val) { 74 set(val) {
72 this.$emit('update:limit', val) 75 this.$emit('update:limit', val)
73 } 76 }
74 } 77 }
75 }, 78 },
76 methods: { 79 methods: {
77 handleSizeChange(val) { 80 handleSizeChange(val) {
78 this.$emit('pagination', { page: this.currentPage, limit: val }) 81 this.$emit('pagination', { page: this.currentPage, limit: val })
79 if (this.autoScroll) { 82 if (this.autoScroll) {
80 scrollTo(0, 800) 83 scrollTo(0, 800)
81 } 84 }
82 }, 85 },
83 handleCurrentChange(val) { 86 handleCurrentChange(val) {
84 this.$emit('pagination', { page: val, limit: this.pageSize }) 87 this.$emit('pagination', { page: val, limit: this.pageSize })
85 if (this.autoScroll) { 88 if (this.autoScroll) {
86 scrollTo(0, 800) 89 scrollTo(0, 800)
87 } 90 }
88 } 91 }
89 } 92 }
90 } 93 }
91 </script> 94 </script>
92 95
93 <style scoped> 96 <style scoped>
94 .pagination-container { 97 .pagination-container {
95 background: #fff; 98 background: #fff;
96 padding: 32px 16px; 99 padding: 32px 16px;
97 } 100 }
98 .pagination-container.hidden { 101 .pagination-container.hidden {
99 display: none; 102 display: none;
100 } 103 }
101 </style> 104 </style>
102 105
1 export default { 1 export default {
2 // 添加的新词条------start 2 // 添加的新词条------start
3 prod: { 3 prod: {
4 menu_title: 'products', 4 menu_title: 'products',
5 sku_modle_pic: '模型图', 5 sku_modle_pic: '模型图',
6 sku_buy_pic: '购买效果图', 6 sku_buy_pic: '购买效果图',
7 window_pic: '橱窗图', 7 window_pic: '橱窗图',
8 detail_pic: '详情图' 8 detail_pic: '详情图'
9 }, 9 },
10 order: { 10 order: {
11 refunding: '退款中', 11 refunding: '退款中',
12 refunded: '退款完成', 12 refunded: '退款完成',
13 13
14 pay_pending: '待支付', 14 pay_pending: '待支付',
15 pay_finished: '支付完成', 15 pay_finished: '支付完成',
16 16
17 deliver_pre: '准备配送', 17 deliver_pre: '准备配送',
18 deliver_ing: '配送中', 18 deliver_ing: '配送中',
19 deliver_finished: '物流完成' 19 deliver_finished: '物流完成'
20 }, 20 },
21 users: { 21 users: {
22 table: { 22 table: {
23 uid: '用户id', 23 uid: '用户id',
24 username: '用户名', 24 username: '用户名',
25 password: '密码', 25 password: '密码',
26 create_at: '注册时间', 26 create_at: '注册时间',
27 nickname: '昵称', 27 nickname: '昵称',
28 roles: '角色', 28 roles: '角色',
29 openid: 'openid', 29 openid: 'openid',
30 son_of_adv: '下线', 30 son_of_adv: '下线',
31 status: '当前状态', 31 status: '当前状态',
32 level: '等级', 32 level: '等级',
33 oper: '操作', 33 oper: '操作',
34 souceof: '上线', 34 souceof: '上线',
35 revernew: '收益', 35 revernew: '收益',
36 buyvalue: '消费价值', 36 buyvalue: '消费价值',
37 buywill: '消费潜力', 37 buywill: '消费潜力',
38 score: '积分', 38 score: '积分',
39 weixin: '微信', 39 weixin: '微信',
40 facebook: 'facebook', 40 facebook: 'facebook',
41 comefromperson: '来自人', 41 comefromperson: '来自人',
42 comefromplatform: '来自平台', 42 comefromplatform: '来自平台',
43 benifit: '提成', 43 benifit: '提成',
44 coupon: '优惠券', 44 coupon: '优惠券',
45 remark: '备注', 45 remark: '备注',
46 importance: '重要度', 46 importance: '重要度',
47 num: '数量' 47 num: '数量'
48 }, 48 },
49 add: '添加', 49 add: '添加',
50 search: '搜索', 50 search: '搜索',
51 del: '删除', 51 del: '删除',
52 update: '修改', 52 update: '修改',
53 edit: '修改', 53 edit: '修改',
54 selectall: '全选' 54 selectall: '全选'
55 }, 55 },
56 site: { 56 site: {
57 // seo:'seo', 57 // seo:'seo',
58 58
59 }, 59 },
60 meta: { 60 meta: {
61 metadefine: '元定义' 61 metadefine: '元定义'
62 }, 62 },
63 system: { 63 system: {
64 memu: '系统' 64 memu: '系统'
65 }, 65 },
66 route: { 66 route: {
67 users: { 67 users: {
68 people: '用户', 68 people: '用户',
69 user: '普通用户', 69 user: '普通用户',
70 list: '列表', 70 list: '列表',
71 shoper: '厂商', 71 shoper: '厂商',
72 runner: '运营官', 72 runner: '运营官',
73 assistant: '操作员', 73 assistant: '操作员',
74 admin: '超级管理员' 74 admin: '超级管理员'
75 }, 75 },
76 shopers: '厂商', 76 shopers: '厂商',
77 prods: { 77 prods: {
78 prod_menu: '产品', 78 prod_menu: '产品',
79 prodlist: '产品列表' 79 prodlist: '产品列表'
80 }, 80 },
81 orders: '订单', 81 orders: '订单',
82 sites: '站点', 82 sites: {
83 sites: '站点',
84 siteList: '站点列表'
85 },
83 metas: { 86 metas: {
84 metas: '元', 87 metas: '元',
85 list: '树' 88 list: '树'
86 }, 89 },
87 systems: { 90 systems: {
88 systems: '系统设置', 91 systems: '系统设置',
89 sites: '站点设置', 92 sites: '站点设置',
90 money: '货币设置', 93 money: '货币设置',
91 industry: '行业设置', 94 industry: '行业设置',
92 template: '模版设置' 95 template: '模版设置'
93 }, 96 },
94 // 添加的新词条------end 97 // 添加的新词条------end
95 dashboard: '首页', 98 dashboard: '首页',
96 documentation: '文档', 99 documentation: '文档',
97 guide: '引导页', 100 guide: '引导页',
98 permission: '权限测试页', 101 permission: '权限测试页',
99 rolePermission: '角色权限', 102 rolePermission: '角色权限',
100 pagePermission: '页面权限', 103 pagePermission: '页面权限',
101 directivePermission: '指令权限', 104 directivePermission: '指令权限',
102 icons: '图标', 105 icons: '图标',
103 components: '组件', 106 components: '组件',
104 tinymce: '富文本编辑器', 107 tinymce: '富文本编辑器',
105 markdown: 'Markdown', 108 markdown: 'Markdown',
106 jsonEditor: 'JSON 编辑器', 109 jsonEditor: 'JSON 编辑器',
107 dndList: '列表拖拽', 110 dndList: '列表拖拽',
108 splitPane: 'Splitpane', 111 splitPane: 'Splitpane',
109 avatarUpload: '头像上传', 112 avatarUpload: '头像上传',
110 dropzone: 'Dropzone', 113 dropzone: 'Dropzone',
111 sticky: 'Sticky', 114 sticky: 'Sticky',
112 countTo: 'Count To', 115 countTo: 'Count To',
113 componentMixin: '小组件', 116 componentMixin: '小组件',
114 backToTop: '返回顶部', 117 backToTop: '返回顶部',
115 dragDialog: '拖拽 Dialog', 118 dragDialog: '拖拽 Dialog',
116 dragSelect: '拖拽 Select', 119 dragSelect: '拖拽 Select',
117 dragKanban: '可拖拽看板', 120 dragKanban: '可拖拽看板',
118 charts: '图表', 121 charts: '图表',
119 keyboardChart: '键盘图表', 122 keyboardChart: '键盘图表',
120 lineChart: '折线图', 123 lineChart: '折线图',
121 mixChart: '混合图表', 124 mixChart: '混合图表',
122 example: '综合实例', 125 example: '综合实例',
123 nested: '路由嵌套', 126 nested: '路由嵌套',
124 menu1: '菜单1', 127 menu1: '菜单1',
125 'menu1-1': '菜单 1-1', 128 'menu1-1': '菜单 1-1',
126 'menu1-2': '菜单 1-2', 129 'menu1-2': '菜单 1-2',
127 'menu1-2-1': '菜单 1-2-1', 130 'menu1-2-1': '菜单 1-2-1',
128 'menu1-2-2': '菜单 1-2-2', 131 'menu1-2-2': '菜单 1-2-2',
129 'menu1-3': '菜单 1-3', 132 'menu1-3': '菜单 1-3',
130 menu2: '菜单 2', 133 menu2: '菜单 2',
131 Table: 'Table', 134 Table: 'Table',
132 dynamicTable: '动态 Table', 135 dynamicTable: '动态 Table',
133 dragTable: '拖拽 Table', 136 dragTable: '拖拽 Table',
134 inlineEditTable: 'Table 内编辑', 137 inlineEditTable: 'Table 内编辑',
135 complexTable: '综合 Table', 138 complexTable: '综合 Table',
136 tab: 'Tab', 139 tab: 'Tab',
137 form: '表单', 140 form: '表单',
138 createArticle: '创建文章', 141 createArticle: '创建文章',
139 editArticle: '编辑文章', 142 editArticle: '编辑文章',
140 articleList: '文章列表', 143 articleList: '文章列表',
141 errorPages: '错误页面', 144 errorPages: '错误页面',
142 page401: '401', 145 page401: '401',
143 page404: '404', 146 page404: '404',
144 errorLog: '错误日志', 147 errorLog: '错误日志',
145 excel: 'Excel', 148 excel: 'Excel',
146 exportExcel: '导出 Excel', 149 exportExcel: '导出 Excel',
147 selectExcel: '导出 已选择项', 150 selectExcel: '导出 已选择项',
148 mergeHeader: '导出 多级表头', 151 mergeHeader: '导出 多级表头',
149 uploadExcel: '上传 Excel', 152 uploadExcel: '上传 Excel',
150 zip: 'Zip', 153 zip: 'Zip',
151 pdf: 'PDF', 154 pdf: 'PDF',
152 exportZip: 'Export Zip', 155 exportZip: 'Export Zip',
153 theme: '换肤', 156 theme: '换肤',
154 clipboardDemo: 'Clipboard', 157 clipboardDemo: 'Clipboard',
155 i18n: '国际化', 158 i18n: '国际化',
156 externalLink: '外链', 159 externalLink: '外链',
157 profile: '个人中心' 160 profile: '个人中心'
158 }, 161 },
159 navbar: { 162 navbar: {
160 dashboard: '首页', 163 dashboard: '首页',
161 github: '项目地址', 164 github: '项目地址',
162 logOut: '退出登录', 165 logOut: '退出登录',
163 profile: '个人中心', 166 profile: '个人中心',
164 theme: '换肤', 167 theme: '换肤',
165 size: '布局大小' 168 size: '布局大小'
166 }, 169 },
167 login: { 170 login: {
168 runner: '运营官', 171 runner: '运营官',
169 shoper: '商家', 172 shoper: '商家',
170 assistant: '操作员', 173 assistant: '操作员',
171 signup: '注册', 174 signup: '注册',
172 forgetpassword: '忘记密码', 175 forgetpassword: '忘记密码',
173 rememberpassword: 'remember password', 176 rememberpassword: 'remember password',
174 177
175 title: '鱼皮出海--让我们荡起双浆', 178 title: '鱼皮出海--让我们荡起双浆',
176 logIn: '登录', 179 logIn: '登录',
177 username: '账号', 180 username: '账号',
178 password: '密码', 181 password: '密码',
179 any: '随便填', 182 any: '随便填',
180 thirdparty: '第三方登录', 183 thirdparty: '第三方登录',
181 thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!' 184 thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!'
182 }, 185 },
183 documentation: { 186 documentation: {
184 documentation: '文档', 187 documentation: '文档',
185 github: 'Github 地址' 188 github: 'Github 地址'
186 }, 189 },
187 permission: { 190 permission: {
188 addRole: '新增角色', 191 addRole: '新增角色',
189 editPermission: '编辑权限', 192 editPermission: '编辑权限',
190 roles: '你的权限', 193 roles: '你的权限',
191 switchRoles: '切换权限', 194 switchRoles: '切换权限',
192 tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。', 195 tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
193 delete: '删除', 196 delete: '删除',
194 confirm: '确定', 197 confirm: '确定',
195 cancel: '取消' 198 cancel: '取消'
196 }, 199 },
197 guide: { 200 guide: {
198 description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于', 201 description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于',
199 button: '打开引导' 202 button: '打开引导'
200 }, 203 },
201 components: { 204 components: {
202 documentation: '文档', 205 documentation: '文档',
203 tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见', 206 tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见',
204 dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone', 207 dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone',
205 stickyTips: '当页面滚动到预设的位置会吸附在顶部', 208 stickyTips: '当页面滚动到预设的位置会吸附在顶部',
206 backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮', 209 backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮',
207 backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素', 210 backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素',
208 imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。' 211 imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。'
209 }, 212 },
210 table: { 213 table: {
211 dynamicTips1: '固定表头, 按照表头顺序排序', 214 dynamicTips1: '固定表头, 按照表头顺序排序',
212 dynamicTips2: '不固定表头, 按照点击顺序排序', 215 dynamicTips2: '不固定表头, 按照点击顺序排序',
213 dragTips1: '默认顺序', 216 dragTips1: '默认顺序',
214 dragTips2: '拖拽后顺序', 217 dragTips2: '拖拽后顺序',
215 title: '标题', 218 title: '标题',
216 importance: '重要性', 219 importance: '重要性',
217 type: '类型', 220 type: '类型',
218 remark: '点评', 221 remark: '点评',
219 search: '搜索', 222 search: '搜索',
220 add: '添加', 223 add: '添加',
221 export: '导出', 224 export: '导出',
222 reviewer: '审核人', 225 reviewer: '审核人',
223 id: '序号', 226 id: '序号',
224 date: '时间', 227 date: '时间',
225 author: '作者', 228 author: '作者',
226 readings: '阅读数', 229 readings: '阅读数',
227 status: '状态', 230 status: '状态',
228 actions: '操作', 231 actions: '操作',
229 edit: '编辑', 232 edit: '编辑',
230 publish: '发布', 233 publish: '发布',
231 draft: '草稿', 234 draft: '草稿',
232 delete: '删除', 235 delete: '删除',
233 cancel: '取 消', 236 cancel: '取 消',
234 confirm: '确 定' 237 confirm: '确 定'
235 }, 238 },
236 example: { 239 example: {
237 warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见' 240 warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见'
238 }, 241 },
239 errorLog: { 242 errorLog: {
240 tips: '请点击右上角bug小图标', 243 tips: '请点击右上角bug小图标',
241 description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。', 244 description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。',
242 documentation: '文档介绍' 245 documentation: '文档介绍'
243 }, 246 },
244 excel: { 247 excel: {
245 export: '导出', 248 export: '导出',
246 selectedExport: '导出已选择项', 249 selectedExport: '导出已选择项',
247 placeholder: '请输入文件名(默认excel-list)' 250 placeholder: '请输入文件名(默认excel-list)'
248 }, 251 },
249 zip: { 252 zip: {
250 export: '导出', 253 export: '导出',
251 placeholder: '请输入文件名(默认file)' 254 placeholder: '请输入文件名(默认file)'
252 }, 255 },
253 pdf: { 256 pdf: {
254 tips: '这里使用 window.print() 来实现下载pdf的功能' 257 tips: '这里使用 window.print() 来实现下载pdf的功能'
255 }, 258 },
256 theme: { 259 theme: {
257 change: '换肤', 260 change: '换肤',
258 documentation: '换肤文档', 261 documentation: '换肤文档',
259 tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。' 262 tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。'
260 }, 263 },
261 tagsView: { 264 tagsView: {
262 refresh: '刷新', 265 refresh: '刷新',
263 close: '关闭', 266 close: '关闭',
264 closeOthers: '关闭其它', 267 closeOthers: '关闭其它',
265 closeAll: '关闭所有' 268 closeAll: '关闭所有'
266 }, 269 },
267 settings: { 270 settings: {
268 title: '系统布局配置', 271 title: '系统布局配置',
269 theme: '主题色', 272 theme: '主题色',
270 tagsView: '开启 Tags-View', 273 tagsView: '开启 Tags-View',
271 fixedHeader: '固定 Header', 274 fixedHeader: '固定 Header',
272 sidebarLogo: '侧边栏 Logo' 275 sidebarLogo: '侧边栏 Logo'
273 } 276 }
274 } 277 }
275 278
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: '/prod', 6 path: '/prod',
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.prod_menu', // 会自动被i18n替换 12 title: 'prods.prod_menu', // 会自动被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: 'list', 17 path: 'list',
18 component: () => import('@/views/prod/list'), 18 component: () => import('@/views/prod/list'),
19 name: 'prodList', 19 name: 'ProdList',
20 meta: { 20 meta: {
21 title: 'prods.prodlist', 21 title: 'prods.prodlist',
22 roles: ['admin', 'assistant', 'shoper', 'runner'] 22 roles: ['admin', 'assistant', 'shoper', 'runner']
23 } 23 }
24 }, {
25 path: 'edit/:pid(\\d+)',
26 component: () => import('@/views/prod/edit'),
27 name: 'ProdEdit',
28 meta: {
29 title: 'prods.prodedit',
30 noCache: true,
31 activeMenu: '/prod/list'
32 },
33 hidden: true
34 }, {
35 path: 'create/:fid(\\d+)',
36 component: () => import('@/views/prod/create'),
37 name: 'ProdCreate',
38 meta: {
39 title: 'prods.prodcreate',
40 noCache: true,
41 activeMenu: '/prod/list'
42 },
43 hidden: true
24 }] 44 }]
25 } 45 }
26 46
27 export default prodRouter 47 export default prodRouter
28 48
src/router/modules/sites.js
1 import Layout from '@/layout' 1 import Layout from '@/layout'
2 2
3 const sitesRouter = { 3 const sitesRouter = {
4 path: '/sites', 4 path: '/sites',
5 component: Layout, 5 component: Layout,
6 redirect: '/site/page', 6 redirect: '/site/page',
7 alwaysShow: true, // will always show the root menu 7 alwaysShow: true, // will always show the root menu
8 name: 'Site', 8 name: 'Site',
9 meta: { 9 meta: {
10 title: 'sites', 10 title: 'sites.sites',
11 icon: 'people', 11 icon: 'people',
12 roles: ['admin', 'assistant', 'runner'] // you can set roles in root nav 12 roles: ['admin', 'assistant', 'runner'] // you can set roles in root nav
13 }, 13 },
14 children: [{ 14 children: [{
15 path: 'sitepage', 15 path: 'sitepage',
16 component: () => import('@/views/site/list'), 16 component: () => import('@/views/site/list'),
17 name: 'SiteList', 17 name: 'SiteList',
18 meta: { 18 meta: {
19 title: '站点列表', 19 title: 'sites.siteList',
20 roles: ['admin', 'runner'] 20 roles: ['admin', 'runner']
21 21
22 } 22 }
23 }] 23 }]
24 } 24 }
25 25
26 export default sitesRouter 26 export default sitesRouter
27 27
src/store/modules/settings.js
1 import variables from '@/styles/element-variables.scss' 1 import variables from '@/styles/element-variables.scss'
2 import defaultSettings from '@/settings' 2 import defaultSettings from '@/settings'
3 3
4 const { showSettings, tagsView, fixedHeader, sidebarLogo, supportPinyinSearch } = defaultSettings 4 const {
5 showSettings,
6 tagsView,
7 fixedHeader,
8 sidebarLogo,
9 supportPinyinSearch
10 } = defaultSettings
5 11
6 const state = { 12 const state = {
7 theme: variables.theme, 13 theme: variables.theme,
8 showSettings, 14 showSettings,
9 tagsView, 15 tagsView,
10 fixedHeader, 16 fixedHeader,
11 sidebarLogo, 17 sidebarLogo,
12 supportPinyinSearch 18 supportPinyinSearch
13 } 19 }
14 20
15 const mutations = { 21 const mutations = {
16 CHANGE_SETTING: (state, { key, value }) => { 22 CHANGE_SETTING: (state, {
23 key,
24 value
25 }) => {
17 if (state.hasOwnProperty(key)) { 26 if (state.hasOwnProperty(key)) {
18 state[key] = value 27 state[key] = value
19 } 28 }
20 } 29 }
21 } 30 }
22 31
23 const actions = { 32 const actions = {
24 changeSetting({ commit }, data) { 33 changeSetting({
34 commit
35 }, data) {
25 commit('CHANGE_SETTING', data) 36 commit('CHANGE_SETTING', data)
26 } 37 }
27 } 38 }
28 39
29 export default { 40 export default {
30 namespaced: true, 41 namespaced: true,
31 state, 42 state,
32 mutations, 43 mutations,
33 actions 44 actions
34 } 45 }
35
src/utils/request.js
1 import axios from 'axios' 1 import axios from 'axios'
2 import qs from 'qs' 2 import qs from 'qs'
3 import { 3 import {
4 MessageBox, 4 MessageBox,
5 Message, 5 Message,
6 // Loading, 6 // Loading,
7 Notification 7 Notification
8 } from 'element-ui' 8 } from 'element-ui'
9 import store from '@/store' 9 import store from '@/store'
10 import { 10 import {
11 getToken 11 getToken
12 } from '@/utils/auth' 12 } from '@/utils/auth'
13 13
14 // const baseUrl = 'http://localhost/sys-glass/api'; 14 // const baseUrl = 'http://localhost/sys-glass/api';
15 // const baseUrl = 'http://localhost:8087'; 15 // const baseUrl = 'http://localhost:8087';
16 const baseUrl = '/dev-api' 16 const baseUrl = '/dev-api'
17 // const baseUrl = process.env.VUE_APP_BASE_API // url = base url + request url 17 // const baseUrl = process.env.VUE_APP_BASE_API // url = base url + request url
18 // create an axios instance 18 // create an axios instance
19 const service = axios.create({ 19 const service = axios.create({
20 // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url 20 // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
21 baseURL: baseUrl, // url = base url + request url 21 baseURL: baseUrl, // url = base url + request url
22 withCredentials: true, // send cookies when cross-domain requests 22 withCredentials: true, // send cookies when cross-domain requests
23 timeout: 3000 // request timeout 23 timeout: 3000 // request timeout
24 }) 24 })
25 // let loadingInstance 25 // let loadingInstance
26 // request interceptor 26 // request interceptor
27 service.interceptors.request.use( 27 service.interceptors.request.use(
28 config => { 28 config => {
29 const token = sessionStorage.getItem('access_token') 29 const token = sessionStorage.getItem('access_token')
30 // const csrf = store.getters.csrf 30 // const csrf = store.getters.csrf
31 if (token) { 31 if (token) {
32 config.headers = { 32 config.headers = {
33 'access-token': token, 33 'access-token': token,
34 'Content-Type': 'application/x-www-form-urlencoded' 34 'Content-Type': 'application/x-www-form-urlencoded'
35 } 35 }
36 } 36 }
37 if (config.url === 'refresh') { 37 if (config.url === 'refresh') {
38 config.headers = { 38 config.headers = {
39 'refresh-token': sessionStorage.getItem('refresh_token'), 39 'refresh-token': sessionStorage.getItem('refresh_token'),
40 'Content-Type': 'application/x-www-form-urlencoded' 40 'Content-Type': 'application/x-www-form-urlencoded'
41 } 41 }
42 } 42 }
43 // let options = { 43 // Notification({
44 // lock: true, 44 // type: 'success',
45 // fullscreen: false, 45 // message: baseUrl + config.url,
46 // text: '数据加载中……', 46 // title: 'request axios ',
47 // // background: '#FFCC00', 47 // showClose: true,
48 // spinner: 'el-icon-loading' 48 // duration: 3000
49 // }; 49 // })
50 const options = {
51 type: 'success',
52 message: baseUrl + config.url,
53 title: 'request axios ',
54 showClose: true,
55 duration: 3000
56 }
57 Notification(options)
58 // loadingInstance = Loading.service(options); 50 // loadingInstance = Loading.service(options);
59 config.method === 'post' 51 config.method === 'post'
60 ? config.data = qs.stringify({ 52 ? config.data = qs.stringify({
61 ...config.data 53 ...config.data
62 }) 54 })
63 : config.params = { 55 : config.params = {
64 ...config.params 56 ...config.params
65 } 57 }
66 if (store.getters.token) { 58 if (store.getters.token) {
67 // let each request carry token 59 // let each request carry token
68 // ['X-Token'] is a custom headers key 60 // ['X-Token'] is a custom headers key
69 // please modify it according to the actual situation 61 // please modify it according to the actual situation
70 config.headers['X-Token'] = getToken() 62 config.headers['X-Token'] = getToken()
71 } 63 }
72 config.headers['Content-Type'] = 'application/x-www-form-urlencoded' 64 config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
73 65
74 return config 66 return config
75 // do something before request is sent 67 // do something before request is sent
76 }, 68 },
77 error => { 69 error => {
78 // do something with request error
79 Message({ 70 Message({
80 message: error || 'Error', 71 message: error || 'Error',
81 type: 'error', 72 type: 'error',
82 duration: 5 * 1000 73 duration: 5 * 1000
83 }) 74 })
84 console.log(error) // for debug 75 console.log(error) // for debug
85 return Promise.reject(error) 76 return Promise.reject(error)
86 } 77 }
87 ) 78 )
88 79
89 // response interceptor 80 // response interceptor
90 service.interceptors.response.use( 81 service.interceptors.response.use(
91 /** 82 /**
92 * If you want to get http information such as headers or status 83 * If you want to get http information such as headers or status
93 * Please return response => response 84 * Please return response => response
94 */ 85 */
95 86
96 /** 87 /**
97 * Determine the request status by custom code 88 * Determine the request status by custom code
98 * Here is just an example 89 * Here is just an example
99 * You can also judge the status by HTTP Status Code 90 * You can also judge the status by HTTP Status Code
100 */ 91 */
101 response => { 92 response => {
102 const options = { 93 const options = {
103 type: 'error', 94 type: response.status == 200 ? 'success' : 'error',
104 message: response.status, 95 message: response.status,
105 title: 'response status value ', 96 title: 'response status value ',
106 showClose: true, 97 showClose: true,
107 duration: 1000 98 duration: 1000
108 } 99 }
109 Notification(options) 100 Notification(options)
110 // Notification.close() 101 // Notification.close()
111 102
112 // 这里根据后端提供的数据进行对应的处理 103 // 这里根据后端提供的数据进行对应的处理
113 console.log('response===>', response) 104 console.log('response===>', response)
114 // 定时刷新access-token 105 // 定时刷新access-token
115 // if (!response.data.value && response.data.data.message === 'token invalid') { 106 // if (!response.data.value && response.data.data.message === 'token invalid') {
116 // // 刷新token 107 // // 刷新token
117 // store.dispatch('refresh').then(response => { 108 // store.dispatch('refresh').then(response => {
118 // sessionStorage.setItem('access_token', response.data) 109 // sessionStorage.setItem('access_token', response.data)
119 // }).catch(error => { 110 // }).catch(error => {
120 // throw new Error('token刷新' + error) 111 // throw new Error('token刷新' + error)
121 // }) 112 // })
122 // } 113 // }
123 114
124 const res = response.data 115 const res = response.data
125 116
126 // if the custom code is not 20000, it is judged as an error. 117 // if the custom code is not 20000, it is judged as an error.
127 if (res.code !== 20000) { 118 if (res.code !== 20000) {
128 Message({ 119 Message({
129 message: res.message || 'Error', 120 message: res.message || 'Error',
130 type: 'error', 121 type: 'error',
131 duration: 5 * 1000 122 duration: 5 * 1000
132 }) 123 })
133 124
134 // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; 125 // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
135 if (res.code === 50008 || res.code === 50012 || res.code === 50014) { 126 if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
136 // to re-login 127 // to re-login
137 MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { 128 MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
138 confirmButtonText: 'Re-Login', 129 confirmButtonText: 'Re-Login',
139 cancelButtonText: 'Cancel', 130 cancelButtonText: 'Cancel',
140 type: 'warning' 131 type: 'warning'
141 }).then(() => { 132 }).then(() => {
142 store.dispatch('user/resetToken').then(() => { 133 store.dispatch('user/resetToken').then(() => {
143 location.reload() 134 location.reload()
144 }) 135 })
145 }) 136 })
146 } 137 }
147 return Promise.reject(new Error(res.message || 'Error')) 138 return Promise.reject(new Error(res.message || 'Error'))
148 } else { 139 } else {
149 return res 140 return res
150 } 141 }
151 }, 142 },
152 error => { 143 error => {
153 console.log('error', error) 144 console.log('error', error)
154 // console.log(JSON.stringify(error)); 145 // console.log(JSON.stringify(error));
155 // 500的状态也应该处理一下 146 // 500的状态也应该处理一下
156 // 401-403的状态也应该处理一下 147 // 401-403的状态也应该处理一下
157 const text = JSON.parse(JSON.stringify(error)).response.status === 404 148 const text = JSON.parse(JSON.stringify(error)).response.status === 404
158 ? '404' 149 ? '404'
159 : '网络异常,请重试' 150 : '网络异常,请重试'
160 Message({ 151 Message({
161 message: text || 'Error', 152 message: text || 'Error',
162 type: 'error', 153 type: 'error',
163 duration: 5 * 1000 154 duration: 5 * 1000
164 }) 155 })
165 156
166 return Promise.reject(error) 157 return Promise.reject(error)
167 } 158 }
168 ) 159 )
169 160
170 // 假设你想移除拦截器 161 // 假设你想移除拦截器
171 // axios.interceptors.request.eject(service); 162 // axios.interceptors.request.eject(service);
172 163
173 export default service 164 export default service
174 165
src/views/example/list.vue
1 <template> 1 <template>
2 <div class="app-container"> 2 <div class="app-container">
3 <el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%"> 3 <el-table
4 <el-table-column align="center" label="ID" width="80"> 4 v-loading="listLoading"
5 :data="list"
6 border
7 fit
8 highlight-current-row
9 style="width: 100%"
10 >
11 <el-table-column
12 align="center"
13 label="ID"
14 width="80"
15 >
5 <template slot-scope="scope"> 16 <template slot-scope="scope">
6 <span>{{ scope.row.id }}</span> 17 <span>{{ scope.row.id }}</span>
7 </template> 18 </template>
8 </el-table-column> 19 </el-table-column>
9 20
10 <el-table-column width="180px" align="center" label="Date"> 21 <el-table-column
22 width="180px"
23 align="center"
24 label="Date"
25 >
11 <template slot-scope="scope"> 26 <template slot-scope="scope">
12 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> 27 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
13 </template> 28 </template>
14 </el-table-column> 29 </el-table-column>
15 30
16 <el-table-column width="120px" align="center" label="Author"> 31 <el-table-column
32 width="120px"
33 align="center"
34 label="Author"
35 >
17 <template slot-scope="scope"> 36 <template slot-scope="scope">
18 <span>{{ scope.row.author }}</span> 37 <span>{{ scope.row.author }}</span>
19 </template> 38 </template>
20 </el-table-column> 39 </el-table-column>
21 40
22 <el-table-column width="100px" label="Importance"> 41 <el-table-column
42 width="100px"
43 label="Importance"
44 >
23 <template slot-scope="scope"> 45 <template slot-scope="scope">
24 <svg-icon v-for="n in +scope.row.importance" :key="n" icon-class="star" class="meta-item__icon" /> 46 <svg-icon
47 v-for="n in +scope.row.importance"
48 :key="n"
49 icon-class="star"
50 class="meta-item__icon"
51 />
25 </template> 52 </template>
26 </el-table-column> 53 </el-table-column>
27 54
28 <el-table-column class-name="status-col" label="Status" width="110"> 55 <el-table-column
56 class-name="status-col"
57 label="Status"
58 width="110"
59 >
29 <template slot-scope="{row}"> 60 <template slot-scope="{row}">
30 <el-tag :type="row.status | statusFilter"> 61 <el-tag :type="row.status | statusFilter">
31 {{ row.status }} 62 {{ row.status }}
32 </el-tag> 63 </el-tag>
33 </template> 64 </template>
34 </el-table-column> 65 </el-table-column>
35 66
36 <el-table-column min-width="300px" label="Title"> 67 <el-table-column
68 min-width="300px"
69 label="Title"
70 >
37 <template slot-scope="{row}"> 71 <template slot-scope="{row}">
38 <router-link :to="'/example/edit/'+row.id" class="link-type"> 72 <router-link
73 :to="'/example/edit/'+row.id"
74 class="link-type"
75 >
39 <span>{{ row.title }}</span> 76 <span>{{ row.title }}</span>
40 </router-link> 77 </router-link>
41 </template> 78 </template>
42 </el-table-column> 79 </el-table-column>
43 80
44 <el-table-column align="center" label="Actions" width="120"> 81 <el-table-column
82 align="center"
83 label="Actions"
84 width="120"
85 >
45 <template slot-scope="scope"> 86 <template slot-scope="scope">
46 <router-link :to="'/example/edit/'+scope.row.id"> 87 <router-link :to="'/example/edit/'+scope.row.id">
47 <el-button type="primary" size="small" icon="el-icon-edit"> 88 <el-button
89 type="primary"
90 size="small"
91 icon="el-icon-edit"
92 >
48 Edit 93 Edit
49 </el-button> 94 </el-button>
50 </router-link> 95 </router-link>
51 </template> 96 </template>
52 </el-table-column> 97 </el-table-column>
53 </el-table> 98 </el-table>
54 99
55 <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" /> 100 <pagination
101 v-show="total>0"
102 :total="total"
103 :page.sync="listQuery.page"
104 :limit.sync="listQuery.limit"
105 @pagination="getList"
106 />
56 </div> 107 </div>
57 </template> 108 </template>
58 109
59 <script> 110 <script>
60 import { fetchList } from '@/api/article' 111 import { fetchList } from '@/api/article'
61 import Pagination from '@/components/Pagination' // Secondary package based on el-pagination 112 import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
62 113
63 export default { 114 export default {
64 name: 'ArticleList', 115 name: 'ArticleList',
65 components: { Pagination }, 116 components: { Pagination },
66 filters: { 117 filters: {
67 statusFilter(status) { 118 statusFilter(status) {
68 const statusMap = { 119 const statusMap = {
69 published: 'success', 120 published: 'success',
70 draft: 'info', 121 draft: 'info',
71 deleted: 'danger' 122 deleted: 'danger'
72 } 123 }
73 return statusMap[status] 124 return statusMap[status]
74 } 125 }
75 }, 126 },
76 data() { 127 data() {
77 return { 128 return {
78 list: null, 129 list: null,
79 total: 0, 130 total: 0,
80 listLoading: true, 131 listLoading: true,
81 listQuery: { 132 listQuery: {
82 page: 1, 133 page: 1,
83 limit: 20 134 limit: 20
84 } 135 }
85 } 136 }
86 }, 137 },
87 created() { 138 created() {
88 this.getList() 139 this.getList()
89 }, 140 },
90 methods: { 141 methods: {
91 getList() { 142 getList() {
92 this.listLoading = true 143 this.listLoading = true
93 fetchList(this.listQuery).then(response => { 144 fetchList(this.listQuery).then(response => {
94 this.list = response.data.items 145 this.list = response.data.items
95 this.total = response.data.total 146 this.total = response.data.total
96 this.listLoading = false 147 this.listLoading = false
97 }) 148 })
98 } 149 }
99 } 150 }
100 } 151 }
101 </script> 152 </script>
102 153
103 <style scoped> 154 <style scoped>
104 .edit-input { 155 .edit-input {
105 padding-right: 100px; 156 padding-right: 100px;
106 } 157 }
107 .cancel-btn { 158 .cancel-btn {
108 position: absolute; 159 position: absolute;
109 right: 15px; 160 right: 15px;
110 top: 10px; 161 top: 10px;
111 } 162 }
112 </style> 163 </style>
113 164
src/views/prod/components/Dropdown/Comment.vue
File was created 1 <template>
2 <el-dropdown :show-timeout="100" trigger="click">
3 <el-button plain>
4 {{ !comment_disabled?'Comment: opened':'Comment: closed' }}
5 <i class="el-icon-caret-bottom el-icon--right" />
6 </el-button>
7 <el-dropdown-menu slot="dropdown" class="no-padding">
8 <el-dropdown-item>
9 <el-radio-group v-model="comment_disabled" style="padding: 10px;">
10 <el-radio :label="true">
11 Close comment
12 </el-radio>
13 <el-radio :label="false">
14 Open comment
15 </el-radio>
16 </el-radio-group>
17 </el-dropdown-item>
18 </el-dropdown-menu>
19 </el-dropdown>
20 </template>
21
22 <script>
23 export default {
24 props: {
25 value: {
26 type: Boolean,
27 default: false
28 }
29 },
30 computed: {
31 comment_disabled: {
32 get() {
33 return this.value
34 },
35 set(val) {
36 this.$emit('input', val)
37 }
38 }
39 }
40 }
41 </script>
42
src/views/prod/components/Dropdown/Platform.vue
File was created 1 <template>
2 <el-dropdown :hide-on-click="false" :show-timeout="100" trigger="click">
3 <el-button plain>
4 Platfroms({{ platforms.length }})
5 <i class="el-icon-caret-bottom el-icon--right" />
6 </el-button>
7 <el-dropdown-menu slot="dropdown" class="no-border">
8 <el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
9 <el-checkbox v-for="item in platformsOptions" :key="item.key" :label="item.key">
10 {{ item.name }}
11 </el-checkbox>
12 </el-checkbox-group>
13 </el-dropdown-menu>
14 </el-dropdown>
15 </template>
16
17 <script>
18 export default {
19 props: {
20 value: {
21 required: true,
22 default: () => [],
23 type: Array
24 }
25 },
26 data() {
27 return {
28 platformsOptions: [
29 { key: 'a-platform', name: 'a-platform' },
30 { key: 'b-platform', name: 'b-platform' },
31 { key: 'c-platform', name: 'c-platform' }
32 ]
33 }
34 },
35 computed: {
36 platforms: {
37 get() {
38 return this.value
39 },
40 set(val) {
41 this.$emit('input', val)
42 }
43 }
44 }
45 }
46 </script>
47
src/views/prod/components/Dropdown/SourceUrl.vue
File was created 1 <template>
2 <el-dropdown :show-timeout="100" trigger="click">
3 <el-button plain>
4 Link
5 <i class="el-icon-caret-bottom el-icon--right" />
6 </el-button>
7 <el-dropdown-menu slot="dropdown" class="no-padding no-border" style="width:400px">
8 <el-form-item label-width="0px" style="margin-bottom: 0px" prop="source_uri">
9 <el-input v-model="source_uri" placeholder="Please enter the content">
10 <template slot="prepend">
11 URL
12 </template>
13 </el-input>
14 </el-form-item>
15 </el-dropdown-menu>
16 </el-dropdown>
17 </template>
18
19 <script>
20 export default {
21 props: {
22 value: {
23 type: String,
24 default: ''
25 }
26 },
27 computed: {
28 source_uri: {
29 get() {
30 return this.value
31 },
32 set(val) {
33 this.$emit('input', val)
34 }
35 }
36 }
37 }
38 </script>
39
src/views/prod/components/Dropdown/index.js
File was created 1 export { default as CommentDropdown } from './Comment'
2 export { default as PlatformDropdown } from './Platform'
3 export { default as SourceUrlDropdown } from './SourceUrl'
4
src/views/prod/components/ProdDetail.vue
File was created 1 <template>
2 <div class="createPost-container">
3 <el-form
4 ref="postForm"
5 :model="postForm"
6 :rules="rules"
7 class="form-container"
8 >
9 <sticky
10 :z-index="10"
11 :class-name="'sub-navbar '+postForm.status"
12 >
13 <CommentDropdown v-model="postForm.comment_disabled" />
14 <PlatformDropdown v-model="postForm.platforms" />
15 <SourceUrlDropdown v-model="postForm.source_uri" />
16 <el-button
17 v-loading="loading"
18 style="margin-left: 10px;"
19 type="success"
20 @click="submitForm"
21 >
22 Publish
23 </el-button>
24 <el-button
25 v-loading="loading"
26 type="warning"
27 @click="draftForm"
28 >
29 Draft
30 </el-button>
31 </sticky>
32
33 <div class="createPost-main-container">
34 <el-row>
35 <!-- <Warning /> -->
36 <el-col :span="24">
37 <el-form-item
38 style="margin-bottom: 40px;"
39 prop="title"
40 >
41 <MDinput
42 v-model="postForm.title"
43 :maxlength="100"
44 name="name"
45 required
46 >
47 Title
48 </MDinput>
49 </el-form-item>
50
51 <div class="postInfo-container">
52 <el-row>
53 <el-col :span="8">
54 <el-form-item
55 label-width="60px"
56 label="shoper:"
57 class="postInfo-container-item"
58 >
59 <el-select
60 v-model="postForm.shoper"
61 :remote-method="getRemoteUserList"
62 filterable
63 default-first-option
64 remote
65 placeholder="Search user"
66 >
67 <el-option
68 v-for="(item,index) in userListOptions"
69 :key="item+index"
70 :label="item"
71 :value="item"
72 />
73 </el-select>
74 </el-form-item>
75 </el-col>
76
77 <el-col :span="10">
78 <el-form-item
79 label-width="120px"
80 label="Publish Time:"
81 class="postInfo-container-item"
82 >
83 <el-date-picker
84 v-model="displayTime"
85 type="datetime"
86 format="yyyy-MM-dd HH:mm:ss"
87 placeholder="Select date and time"
88 />
89 </el-form-item>
90 </el-col>
91
92 <el-col :span="6">
93 <el-form-item
94 label-width="90px"
95 label="Importance:"
96 class="postInfo-container-item"
97 >
98 <el-rate
99 v-model="postForm.importance"
100 :max="3"
101 :colors="['#99A9BF', '#F7BA2A', '#FF9900']"
102 :low-threshold="1"
103 :high-threshold="3"
104 style="display:inline-block"
105 />
106 </el-form-item>
107 </el-col>
108 </el-row>
109 </div>
110 </el-col>
111 </el-row>
112
113 <el-form-item
114 style="margin-bottom: 40px;"
115 label-width="70px"
116 label="Summary:"
117 >
118 <el-input
119 v-model="postForm.content_short"
120 :rows="1"
121 type="textarea"
122 class="article-textarea"
123 autosize
124 placeholder="Please enter the content"
125 />
126 <span
127 v-show="contentShortLength"
128 class="word-counter"
129 >{{ contentShortLength }}words</span>
130 </el-form-item>
131
132 <el-form-item
133 prop="content"
134 style="margin-bottom: 30px;"
135 >
136 <Tinymce
137 ref="editor"
138 v-model="postForm.content"
139 :height="400"
140 />
141 </el-form-item>
142
143 <el-form-item
144 prop="image_uri"
145 style="margin-bottom: 30px;"
146 >
147 <Upload v-model="postForm.image_uri" />
148 </el-form-item>
149 </div>
150 </el-form>
151 </div>
152 </template>
153
154 <script>
155 import Tinymce from '@/components/Tinymce'
156 import Upload from '@/components/Upload/SingleImage3'
157 import MDinput from '@/components/MDinput'
158 import Sticky from '@/components/Sticky' // 粘性header组件
159 import { validURL } from '@/utils/validate'
160 import { fetchProd } from '@/api/prod'
161 import { searchUser } from '@/api/remote-search'
162 // import Warning from './Warning'
163 import {
164 CommentDropdown,
165 PlatformDropdown,
166 SourceUrlDropdown
167 } from './Dropdown'
168
169 const defaultForm = {
170 status: 'draft',
171 title: '', // 文章题目
172 content: '', // 文章内容
173 content_short: '', // 文章摘要
174 source_uri: '', // 文章外链
175 image_uri: '', // 文章图片
176 display_time: undefined, // 前台展示时间
177 id: undefined,
178 platforms: ['a-platform'],
179 comment_disabled: false,
180 importance: 0
181 }
182
183 export default {
184 name: 'ProdDetail',
185 components: {
186 Tinymce,
187 MDinput,
188 Upload,
189 Sticky,
190 // Warning,
191 CommentDropdown,
192 PlatformDropdown,
193 SourceUrlDropdown
194 },
195 props: {
196 isEdit: {
197 type: Boolean,
198 default: false
199 }
200 },
201 data() {
202 const validateRequire = (rule, value, callback) => {
203 if (value === '') {
204 this.$message({
205 message: rule.field + '为必传项',
206 type: 'error'
207 })
208 callback(new Error(rule.field + '为必传项'))
209 } else {
210 callback()
211 }
212 }
213 const validateSourceUri = (rule, value, callback) => {
214 if (value) {
215 if (validURL(value)) {
216 callback()
217 } else {
218 this.$message({
219 message: '外链url填写不正确',
220 type: 'error'
221 })
222 callback(new Error('外链url填写不正确'))
223 }
224 } else {
225 callback()
226 }
227 }
228 return {
229 postForm: Object.assign({}, defaultForm),
230 loading: false,
231 userListOptions: [],
232 rules: {
233 image_uri: [{ validator: validateRequire }],
234 title: [{ validator: validateRequire }],
235 content: [{ validator: validateRequire }],
236 source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
237 },
238 tempRoute: {}
239 }
240 },
241 computed: {
242 contentShortLength() {
243 return this.postForm.content_short.length
244 },
245 lang() {
246 return this.$store.getters.language
247 },
248 displayTime: {
249 // set and get is useful when the data
250 // returned by the back end api is different from the front end
251 // back end return => "2013-06-25 06:59:25"
252 // front end need timestamp => 1372114765000
253 get() {
254 return +new Date(this.postForm.display_time)
255 },
256 set(val) {
257 this.postForm.display_time = new Date(val)
258 }
259 }
260 },
261 created() {
262 if (this.isEdit) {
263 const pid = this.$route.params && this.$route.params.pid
264 this.fetchData(pid)
265 }
266
267 // Why need to make a copy of this.$route here?
268 // Because if you enter this page and quickly switch tag, may be in the execution of the setTagsViewTitle function, this.$route is no longer pointing to the current page
269 // https://github.com/PanJiaChen/vue-element-admin/issues/1221
270 this.tempRoute = Object.assign({}, this.$route)
271 },
272 methods: {
273 fetchData(pid) {
274 fetchProd(pid)
275 .then(response => {
276 this.postForm = response.data
277
278 // just for test
279 this.postForm.title += ` prod pId:${this.postForm.pid}`
280 this.postForm.content_short += ` prod Id:${this.postForm.pid}`
281
282 // set tagsview title
283 this.setTagsViewTitle()
284
285 // set page title
286 this.setPageTitle()
287 })
288 .catch(err => {
289 console.log(err)
290 })
291 },
292 setTagsViewTitle() {
293 const title = this.lang === 'zh' ? '编辑文章' : 'Edit Article'
294 const route = Object.assign({}, this.tempRoute, {
295 title: `${title}-${this.postForm.pid}`
296 })
297 this.$store.dispatch('tagsView/updateVisitedView', route)
298 },
299 setPageTitle() {
300 const title = 'Edit Article'
301 document.title = `${title} - ${this.postForm.pid}`
302 },
303 submitForm() {
304 console.log('this.postForm', this.postForm)
305 this.$refs.postForm.validate(valid => {
306 if (valid) {
307 this.loading = true
308 this.$notify({
309 title: '成功',
310 message: '发布文章成功',
311 type: 'success',
312 duration: 2000
313 })
314 this.postForm.status = 'published'
315 this.loading = false
316 } else {
317 console.log('error submit!!')
318 return false
319 }
320 })
321 },
322 draftForm() {
323 if (
324 this.postForm.content.length === 0 ||
325 this.postForm.title.length === 0
326 ) {
327 this.$message({
328 message: '请填写必要的标题和内容',
329 type: 'warning'
330 })
331 return
332 }
333 this.$message({
334 message: '保存成功',
335 type: 'success',
336 showClose: true,
337 duration: 1000
338 })
339 this.postForm.status = 'draft'
340 },
341 getRemoteUserList(query) {
342 searchUser(query).then(response => {
343 if (!response.data.items) return
344 this.userListOptions = response.data.items.map(v => v.name)
345 })
346 }
347 }
348 }
349 </script>
350
351 <style lang="scss" scoped>
352 @import "~@/styles/mixin.scss";
353
354 .createPost-container {
355 position: relative;
356
357 .createPost-main-container {
358 padding: 40px 45px 20px 50px;
359
360 .postInfo-container {
361 position: relative;
362 @include clearfix;
363 margin-bottom: 10px;
364
365 .postInfo-container-item {
366 float: left;
367 }
368 }
369 }
370
371 .word-counter {
372 width: 40px;
373 position: absolute;
374 right: 10px;
375 top: 0px;
376 }
377 }
378
379 .article-textarea /deep/ {
380 textarea {
381 padding-right: 40px;
382 resize: none;
383 border: none;
384 border-radius: 0px;
385 border-bottom: 1px solid #bfcbd9;
386 }
387 }
388 </style>
389
src/views/prod/components/Warning.vue
File was created 1 <template>
2 <aside>
3 {{ $t('example.warning') }}
4 <a
5 href="https://panjiachen.github.io/vue-element-admin-site/guide/essentials/tags-view.html"
6 target="_blank"
7 >Document</a>
8 </aside>
9 </template>
10
11
src/views/prod/create.vue
File was created 1 <template>
2 <prod-detail :is-edit="false" />
3 </template>
4
5 <script>
6 import ProdDetail from './components/ProdDetail'
7 // HTML 中的标签名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。
8 // 这意味着当你使用 DOM 中的模板时,
9 // 使用驼峰命名法 的 prop 名需要使用其等价的短横线分隔命名方法或者全部使用小写。
10 // 否者就会报上述错误。
11 export default {
12 name: 'CreateForm',
13 components: { ProdDetail }
14 }
15 </script>
16
17
src/views/prod/edit.vue
File was created 1 <template>
2 <prod-detail :is-edit="true" />
3 </template>
4
5 <script>
6 import ProdDetail from './components/ProdDetail'
7
8 export default {
9 name: 'EditForm',
10 components: { ProdDetail }
11 }
12 </script>
13
14
src/views/prod/list.vue
1 <template> 1 <template>
2 <div class="app-container"> 2 <div class="app-container">
3 <!-- <el-header>
4
5 </el-header> -->
6 <template>
7 <router-link :to="'/prod/create/1111'">
8 <el-button
9 type="primary"
10 size="small"
11 icon="el-icon-edit"
12 >
13 create
14 </el-button>
15 </router-link>
16 </template>
3 <el-table 17 <el-table
4 v-loading="listLoading" 18 v-loading="listLoading"
5 :data="list" 19 :data="list"
6 border 20 border
7 fit 21 fit
8 highlight-current-row 22 highlight-current-row
9 style="width: 100%" 23 style="width: 100%"
10 > 24 >
11 <el-table-column 25 <el-table-column
12 align="center" 26 align="center"
13 label="ID" 27 label="pid"
14 width="80"
15 > 28 >
16 <template slot-scope="scope"> 29 <template slot-scope="scope">
17 <span>{{ scope.row.id }}</span> 30 <span>{{ scope.row.pid }}</span>
18 </template> 31 </template>
19 </el-table-column> 32 </el-table-column>
20
21 <el-table-column 33 <el-table-column
22 width="180px"
23 align="center" 34 align="center"
24 label="Date" 35 label="pname"
25 > 36 >
26 <template slot-scope="scope"> 37 <template slot-scope="scope">
27 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> 38 <span>{{ scope.row.pname }}</span>
28 </template> 39 </template>
29 </el-table-column> 40 </el-table-column>
30
31 <el-table-column 41 <el-table-column
32 width="120px"
33 align="center" 42 align="center"
34 label="Author" 43 label="参数信息"
35 > 44 >
36 <template slot-scope="scope"> 45 <template slot-scope="scope">
37 <span>{{ scope.row.author }}</span> 46 <span>框宽{{ scope.row.prod_info_frame_width }}mm</span><br>
47 <span>腿长{{ scope.row.prod_info_leg_long }}mm</span><br>
48 <span>镜宽{{ scope.row.prod_info_glass_width }}mm</span><br>
49 <span>镜高{{ scope.row.prod_info_glass_height }}mm</span><br>
50 <span>鼻宽{{ scope.row.prod_info_norse_width }}mm</span><br>
51 <span>重量{{ scope.row.prod_info_weight }}g</span>
38 </template> 52 </template>
39 </el-table-column> 53 </el-table-column>
40 54
41 <el-table-column 55 <el-table-column
42 width="100px" 56 align="center"
43 label="Importance" 57 label="Date"
44 > 58 >
45 <template slot-scope="scope"> 59 <template slot-scope="scope">
60 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
61 </template>
62 </el-table-column>
63
64 <el-table-column label="Importance">
65 <template slot-scope="scope">
46 <svg-icon 66 <svg-icon
47 v-for="n in +scope.row.importance" 67 v-for="n in +scope.row.importance"
48 :key="n" 68 :key="n"
49 icon-class="star" 69 icon-class="star"
50 class="meta-item__icon" 70 class="meta-item__icon"
51 /> 71 />
52 </template> 72 </template>
53 </el-table-column> 73 </el-table-column>
54 74
55 <el-table-column 75 <el-table-column
56 class-name="status-col" 76 class-name="status-col"
57 label="Status" 77 label="prod_status"
58 width="110"
59 > 78 >
60 <template slot-scope="{row}"> 79 <template slot-scope="{row}">
61 <el-tag :type="row.status | statusFilter"> 80 <el-tag :type="row.prod_status | statusFilter">
62 {{ row.status }} 81 {{ row.prod_status }}
63 </el-tag> 82 </el-tag>
64 </template> 83 </template>
65 </el-table-column> 84 </el-table-column>
66 85
67 <el-table-column 86 <el-table-column
68 min-width="300px"
69 label="Title"
70 >
71 <template slot-scope="{row}">
72 <router-link
73 :to="'/example/edit/'+row.id"
74 class="link-type"
75 >
76 <span>{{ row.title }}</span>
77 </router-link>
78 </template>
79 </el-table-column>
80
81 <el-table-column
82 align="center" 87 align="center"
83 label="Actions" 88 label="Actions"
84 width="120"
85 > 89 >
86 <template slot-scope="scope"> 90 <template slot-scope="{row}">
87 <router-link :to="'/example/edit/'+scope.row.id"> 91 <router-link :to="'/prod/edit/'+row.pid">
92 <el-button
93 type="primary"
94 size="small"
95 icon="el-icon-edit"
96 >
97 Edit1
98 </el-button>
99 </router-link>
100 <router-link :to="'/prod/del/'+row.pid">
88 <el-button 101 <el-button
89 type="primary" 102 type="primary"
90 size="small" 103 size="small"
91 icon="el-icon-edit" 104 icon="el-icon-edit"
92 > 105 >
93 Edit 106 Edit2
94 </el-button> 107 </el-button>
95 </router-link> 108 </router-link>
96 </template> 109 </template>
97 </el-table-column> 110 </el-table-column>
98 </el-table> 111 </el-table>
99 112
100 <pagination 113 <pagination
101 v-show="total>0" 114 v-show="total>0"
102 :total="total" 115 :total="total"
103 :page.sync="listQuery.page" 116 :page.sync="listQuery.page"
104 :limit.sync="listQuery.limit" 117 :limit.sync="listQuery.limit"
105 @pagination="getList" 118 @pagination="getList"
106 /> 119 />
107 </div> 120 </div>
108 </template> 121 </template>
109 122
110 <script> 123 <script>
111 import { fetchList } from '@/api/article' 124 import { fetchList } from '@/api/prod'
125 // import { Pagination } from "@/components/Pagination"; // Secondary package based on el-pagination
112 import Pagination from '@/components/Pagination' // Secondary package based on el-pagination 126 import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
113
114 export default { 127 export default {
115 name: 'ArticleList', 128 name: 'ProdList',
116 components: { Pagination }, 129 components: { Pagination },
117 filters: { 130 filters: {
118 statusFilter(status) { 131 statusFilter(prod_status) {
119 const statusMap = { 132 const statusMap = {
120 published: 'success', 133 published: 'success',
121 draft: 'info', 134 draft: 'info',
122 deleted: 'danger' 135 deleted: 'danger'
123 } 136 }
124 return statusMap[status] 137 return statusMap[prod_status]
125 } 138 }
126 }, 139 },
127 data() { 140 data() {
128 return { 141 return {
129 list: null, 142 list: null,
130 total: 0, 143 total: 0,
131 listLoading: true, 144 listLoading: true,
132 listQuery: { 145 listQuery: {
133 page: 1, 146 page: 1,
134 limit: 20 147 limit: 20
135 } 148 }
136 } 149 }
137 }, 150 },
138 created() { 151 created() {
139 this.getList() 152 this.getList()
140 }, 153 },
141 methods: { 154 methods: {
142 getList() { 155 getList() {
143 this.listLoading = true 156 this.listLoading = true