Merge branch 'release/1.0' of git.yoho.cn:fe/yoho-shop-manage into release/1.0
Showing
20 changed files
with
515 additions
and
471 deletions
1 | <template> | 1 | <template> |
2 | <Row class="layout-header"> | 2 | <Row class="layout-header"> |
3 | <Col :span="12" class="brand-title"> | 3 | <Col :span="12" class="brand-title"> |
4 | - <i class="fa fa-bars" aria-hidden="true" @click="$emit('menu-trigger')"></i> | 4 | + <i class="iconfont icon-alignjustify" aria-hidden="true" @click="$emit('menu-trigger')"></i> |
5 | {{userInfo.name}} | 5 | {{userInfo.name}} |
6 | </Col> | 6 | </Col> |
7 | <Col :span="12" class="shop-info"> | 7 | <Col :span="12" class="shop-info"> |
8 | - <span class="name">{{userInfo.currentShop.shopName}}</span> | 8 | + <span v-if="!showLoading" class="name">{{userInfo.currentShop.shopName}}</span> |
9 | + <span v-if="showLoading" class="loading">切换中...</span> | ||
9 | <span>|</span> | 10 | <span>|</span> |
10 | <Dropdown @on-click="switchShop" trigger="click"> | 11 | <Dropdown @on-click="switchShop" trigger="click"> |
11 | <a class="swtich-shop" href="javascript:void(0)"> | 12 | <a class="swtich-shop" href="javascript:void(0)"> |
@@ -22,12 +23,14 @@ | @@ -22,12 +23,14 @@ | ||
22 | 23 | ||
23 | <script> | 24 | <script> |
24 | import Vue from 'vue'; | 25 | import Vue from 'vue'; |
26 | +import userService from 'user-service'; | ||
25 | 27 | ||
26 | export default { | 28 | export default { |
27 | name: 'UserInfo', | 29 | name: 'UserInfo', |
28 | data() { | 30 | data() { |
29 | return { | 31 | return { |
30 | - userInfo: this.$user | 32 | + userInfo: this.$user, |
33 | + showLoading: false | ||
31 | }; | 34 | }; |
32 | }, | 35 | }, |
33 | methods: { | 36 | methods: { |
@@ -36,9 +39,18 @@ export default { | @@ -36,9 +39,18 @@ export default { | ||
36 | }, | 39 | }, |
37 | switchShop(id) { | 40 | switchShop(id) { |
38 | if (this.userInfo.currentShop.shopsId !== id) { | 41 | if (this.userInfo.currentShop.shopsId !== id) { |
39 | - this.userInfo.currentShop = this.userInfo.shops.find(shop => shop.shopsId === id); | ||
40 | - Vue.switchShop(id); | ||
41 | - this.$emit('shop-change', this.userInfo.currentShop); | 42 | + this.showLoading = true; |
43 | + userService.switchShop(id).then(res => { | ||
44 | + this.showLoading = false; | ||
45 | + if (res.code === 200) { | ||
46 | + this.userInfo.currentShop = this.userInfo.shops.find(shop => shop.shopsId === id); | ||
47 | + Vue.switchShop(id); | ||
48 | + this.$emit('shop-change', this.userInfo.currentShop); | ||
49 | + this.$Message.success(`当前店铺切换为:${this.userInfo.currentShop.shopName}`); | ||
50 | + } else { | ||
51 | + this.$Message.error(`切换失败:${res.message}`); | ||
52 | + } | ||
53 | + }); | ||
42 | } | 54 | } |
43 | } | 55 | } |
44 | } | 56 | } |
@@ -49,15 +61,15 @@ export default { | @@ -49,15 +61,15 @@ export default { | ||
49 | .layout-header { | 61 | .layout-header { |
50 | height: 50px !important; | 62 | height: 50px !important; |
51 | background: #fff; | 63 | background: #fff; |
52 | - box-shadow: 0 1px 1px rgba(0, 0, 0, .1); | 64 | + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); |
53 | font-size: 14px; | 65 | font-size: 14px; |
54 | line-height: 20px; | 66 | line-height: 20px; |
55 | padding: 15px; | 67 | padding: 15px; |
56 | position: relative; | 68 | position: relative; |
57 | 69 | ||
58 | &.user-collapse { | 70 | &.user-collapse { |
59 | - height: 0px !important; | ||
60 | - padding: 0px !important; | 71 | + height: 0 !important; |
72 | + padding: 0 !important; | ||
61 | overflow: hidden; | 73 | overflow: hidden; |
62 | 74 | ||
63 | .fa-bars { | 75 | .fa-bars { |
@@ -67,7 +79,8 @@ export default { | @@ -67,7 +79,8 @@ export default { | ||
67 | } | 79 | } |
68 | 80 | ||
69 | &.print-hide { | 81 | &.print-hide { |
70 | - display: none; } | 82 | + display: none; |
83 | + } | ||
71 | 84 | ||
72 | .fa { | 85 | .fa { |
73 | font-size: 20px; | 86 | font-size: 20px; |
@@ -75,7 +88,7 @@ export default { | @@ -75,7 +88,7 @@ export default { | ||
75 | margin-right: 10px; | 88 | margin-right: 10px; |
76 | cursor: pointer; | 89 | cursor: pointer; |
77 | } | 90 | } |
78 | - | 91 | + |
79 | .shop-info { | 92 | .shop-info { |
80 | text-align: right; | 93 | text-align: right; |
81 | padding-right: 20px; | 94 | padding-right: 20px; |
@@ -84,6 +97,10 @@ export default { | @@ -84,6 +97,10 @@ export default { | ||
84 | margin-right: 5px; | 97 | margin-right: 5px; |
85 | } | 98 | } |
86 | 99 | ||
100 | + .loading { | ||
101 | + color: #ccc; | ||
102 | + } | ||
103 | + | ||
87 | .swtich-shop { | 104 | .swtich-shop { |
88 | margin-left: 5px; | 105 | margin-left: 5px; |
89 | font-size: 12px; | 106 | font-size: 12px; |
@@ -91,7 +108,7 @@ export default { | @@ -91,7 +108,7 @@ export default { | ||
91 | } | 108 | } |
92 | 109 | ||
93 | .logout { | 110 | .logout { |
94 | - color: #F44545; | 111 | + color: #f44545; |
95 | font-size: 12px; | 112 | font-size: 12px; |
96 | margin-left: 5px; | 113 | margin-left: 5px; |
97 | } | 114 | } |
1 | <template> | 1 | <template> |
2 | - <Select :value="handleValue" @on-change="updateValue" :disabled="disable" placeholder="请选择" style="width: 350px;"> | 2 | + <Select :value="handleValue" @on-change="updateValue" :disabled="disable" placeholder="请选择" style="width: 400px;"> |
3 | <Option :value="season.id" v-for="season in seasonList" :key="season.id">{{season.label}}</Option> | 3 | <Option :value="season.id" v-for="season in seasonList" :key="season.id">{{season.label}}</Option> |
4 | </Select> | 4 | </Select> |
5 | </template> | 5 | </template> |
1 | +<template> | ||
2 | + <Table ref="sellerGoods" :context="self" :data="table.data" :columns="table.columns" stripe border></Table> | ||
3 | +</template> | ||
4 | + | ||
5 | +<script> | ||
6 | + import {ExamplePop} from 'components/pop'; | ||
7 | + | ||
8 | + export default { | ||
9 | + name: 'TableCreateGoodSize', | ||
10 | + props: { | ||
11 | + value: { | ||
12 | + type: Array, | ||
13 | + default() { | ||
14 | + return []; | ||
15 | + } | ||
16 | + } | ||
17 | + }, | ||
18 | + data() { | ||
19 | + return { | ||
20 | + self: this, | ||
21 | + table: { | ||
22 | + columns: [ | ||
23 | + { | ||
24 | + title: '色系名称', | ||
25 | + key: 'goodsName', | ||
26 | + render(row, col, index) { | ||
27 | + return `<div v-if="isExist(${index})"> | ||
28 | + <p>{{table.data[${index}].goodsName.name}}</p> | ||
29 | + <Radio :value="table.data[${index}].goodsName.isDefault" | ||
30 | + @on-change="clickDefault(${index})">主推</Radio> | ||
31 | + </div>`; | ||
32 | + } | ||
33 | + }, | ||
34 | + { | ||
35 | + title: '颜色展示名称', | ||
36 | + key: 'factoryGoodsName', | ||
37 | + render(row, col, index) { | ||
38 | + return `<div v-if="isExist(${index})"> | ||
39 | + <i-input | ||
40 | + v-model="row.factoryGoodsName" | ||
41 | + :placeholder="row.goodsName.name"> | ||
42 | + </i-input> | ||
43 | + </div>`; | ||
44 | + } | ||
45 | + }, | ||
46 | + { | ||
47 | + title: '色卡图片', | ||
48 | + key: 'goodsColorImage', | ||
49 | + width: 170, | ||
50 | + render(row, col, index) { | ||
51 | + return `<div | ||
52 | + :class="{'table-upload-item': true , | ||
53 | + 'table-upload-item-error': | ||
54 | + row.goodsColorImage.showValidate && row.goodsColorImage.validate}" | ||
55 | + > | ||
56 | + <div class="table-upload-item-img"> | ||
57 | + <img v-if="row.goodsColorImage.value" | ||
58 | + :src="row.goodsColorImage.value" alt="" width="84px" height="112px"> | ||
59 | + </div> | ||
60 | + <div> | ||
61 | + <file-upload :id="{index: ${index}}" | ||
62 | + @on-success="uploadSuccess" | ||
63 | + @on-error="uploadError"></file-upload> | ||
64 | + <example-pop></example-pop> | ||
65 | + </div> | ||
66 | + <div v-if="row.goodsColorImage.showValidate && row.goodsColorImage.validate" | ||
67 | + class="table-upload-item-tip"> | ||
68 | + 必须上传图片 | ||
69 | + </div> | ||
70 | + </div>`; | ||
71 | + }, | ||
72 | + renderHeader(col, index) { | ||
73 | + return `<span class="table-header">${col.title}</span>`; | ||
74 | + } | ||
75 | + }, | ||
76 | + { | ||
77 | + title: '款型编码', | ||
78 | + key: 'factoryCode', | ||
79 | + render(row, col, index) { | ||
80 | + return `<div v-if="isExist(${index})"> | ||
81 | + <i-input | ||
82 | + v-model="row.factoryCode" | ||
83 | + placeholder="请输入..." > | ||
84 | + </i-input> | ||
85 | + </div>`; | ||
86 | + } | ||
87 | + }, | ||
88 | + { | ||
89 | + title: '尺码', | ||
90 | + key: 'sizeId', | ||
91 | + width: 80, | ||
92 | + render(row, col, index) { | ||
93 | + return `<div class="size-id"> | ||
94 | + <div v-for="size in row.sizeId" class="row-span"> | ||
95 | + {{size.name}} | ||
96 | + </div> | ||
97 | + </div>`; | ||
98 | + } | ||
99 | + }, | ||
100 | + { | ||
101 | + title: '商品条码', | ||
102 | + key: 'sizeCode', | ||
103 | + render(row, col, index) { | ||
104 | + return `<div class='size-code'> | ||
105 | + <div v-for="size,i in row.sizeCode" class="row-span"> | ||
106 | + <div style="position: relative"> | ||
107 | + <div :class="{'size-code-error': size.validate && !size.name}"> | ||
108 | + <i-input | ||
109 | + v-model="size.name" | ||
110 | + :disabled="!row.operator[i].value" | ||
111 | + placeholder="请输入..." | ||
112 | + /> | ||
113 | + </div> | ||
114 | + <div class="size-code-tip" v-if="size.validate && !size.name"> | ||
115 | + 不能为空 | ||
116 | + </div> | ||
117 | + </div> | ||
118 | + </div> | ||
119 | + </div>`; | ||
120 | + }, | ||
121 | + renderHeader(col, index) { | ||
122 | + return `<span class="table-header">${col.title}</span>`; | ||
123 | + } | ||
124 | + }, | ||
125 | + { | ||
126 | + title: '操作', | ||
127 | + key: 'operator', | ||
128 | + width: 100, | ||
129 | + render(row, col, index) { | ||
130 | + return `<template v-if="isExist(${index})"> | ||
131 | + <div class="size-operator"> | ||
132 | + <div v-for="op,i in row.operator" class="row-span"> | ||
133 | + <i-button v-if="row.operator[i].value" | ||
134 | + type="warning" | ||
135 | + @click="clickOperator(row, i)">禁用</i-button> | ||
136 | + <i-button v-else type="primary" | ||
137 | + @click="clickOperator(row, i)">启用</i-button> | ||
138 | + </div> | ||
139 | + </div> | ||
140 | + </template>`; | ||
141 | + } | ||
142 | + } | ||
143 | + ], | ||
144 | + data: this.value | ||
145 | + } | ||
146 | + }; | ||
147 | + }, | ||
148 | + methods: { | ||
149 | + isExist(index) { | ||
150 | + let row = this.table.data[index]; | ||
151 | + | ||
152 | + if (row) { | ||
153 | + return true; | ||
154 | + } | ||
155 | + | ||
156 | + return false; | ||
157 | + }, | ||
158 | + refreshTable() { | ||
159 | + this.table.data = this.$refs.sellerGoods.rebuildData; | ||
160 | + }, | ||
161 | + syncData() { | ||
162 | + this.$emit('input', this.$refs.sellerGoods.rebuildData); | ||
163 | + }, | ||
164 | + clickDefault(index) { | ||
165 | + this.refreshTable(); | ||
166 | + let color = this.table.data[index]; | ||
167 | + | ||
168 | + | ||
169 | + color.goodsName.isDefault = true; | ||
170 | + this.table.data.forEach((c) => { | ||
171 | + if (c.colorId !== color.colorId) { | ||
172 | + c.goodsName.isDefault = false; | ||
173 | + } | ||
174 | + }); | ||
175 | + }, | ||
176 | + clickOperator(row, itemIndex) { | ||
177 | + this.refreshTable(); | ||
178 | + row.operator[itemIndex].value = row.operator[itemIndex].value ? false : true; | ||
179 | + | ||
180 | + if (row.operator[itemIndex].value) { | ||
181 | + row.sizeCode[itemIndex].name = ''; | ||
182 | + row.sizeCode[itemIndex].validate = true; | ||
183 | + } else { | ||
184 | + row.sizeCode[itemIndex].name = ''; | ||
185 | + row.sizeCode[itemIndex].validate = false; | ||
186 | + } | ||
187 | + | ||
188 | + }, | ||
189 | + uploadSuccess: function(attach, files) { | ||
190 | + this.refreshTable(); | ||
191 | + this.table.data[attach.index].goodsColorImage.value = files[0]; | ||
192 | + | ||
193 | + this.table.data[attach.index].goodsColorImage.validate = true; | ||
194 | + if (this.table.data[attach.index].goodsColorImage.value) { | ||
195 | + this.table.data[attach.index].goodsColorImage.showValidate = false; | ||
196 | + } else { | ||
197 | + this.table.data[attach.index].goodsColorImage.showValidate = true; | ||
198 | + } | ||
199 | + }, | ||
200 | + uploadError: function(attach, err) { | ||
201 | + }, | ||
202 | + }, | ||
203 | + watch: { | ||
204 | + value(newValue) { | ||
205 | + this.table.data = newValue; | ||
206 | + } | ||
207 | + }, | ||
208 | + components: { | ||
209 | + ExamplePop | ||
210 | + } | ||
211 | + }; | ||
212 | + | ||
213 | +</script> | ||
214 | + | ||
215 | +<style lang="scss"> | ||
216 | + | ||
217 | + @mixin row-span{ | ||
218 | + min-height: 30px; | ||
219 | + | ||
220 | + .row-span { | ||
221 | + min-height: 30px; | ||
222 | + border-bottom: 1px solid #e3e8ee; | ||
223 | + padding-top: 20px ; | ||
224 | + padding-bottom: 20px ; | ||
225 | + margin-left: -18px; | ||
226 | + margin-right: -18px; | ||
227 | + padding-left: 18px ; | ||
228 | + padding-right: 18px ; | ||
229 | + | ||
230 | + &:last-child { | ||
231 | + border-bottom: none; | ||
232 | + } | ||
233 | + } | ||
234 | + } | ||
235 | + | ||
236 | + .size-code { | ||
237 | + @include row-span; | ||
238 | + | ||
239 | + &-error { | ||
240 | + border: 1px solid #f30; | ||
241 | + } | ||
242 | + | ||
243 | + &-tip { | ||
244 | + position: absolute; | ||
245 | + line-height: 1; | ||
246 | + padding-top: 6px; | ||
247 | + color: #f30; | ||
248 | + } | ||
249 | + } | ||
250 | + | ||
251 | + .size-id { | ||
252 | + @include row-span; | ||
253 | + text-align: center; | ||
254 | + } | ||
255 | + | ||
256 | + .size-operator { | ||
257 | + @include row-span; | ||
258 | + text-align: center; | ||
259 | + } | ||
260 | + | ||
261 | + .table-upload-item { | ||
262 | + display: inline-block; | ||
263 | + height: 220px; | ||
264 | + width: 130px; | ||
265 | + text-align: center; | ||
266 | + margin: 30px 0; | ||
267 | + } | ||
268 | + | ||
269 | + .table-upload-item-error { | ||
270 | + border: 1px solid #f30; | ||
271 | + } | ||
272 | + | ||
273 | + .table-upload-item-tip { | ||
274 | + padding-top: 6px; | ||
275 | + color: #f30; | ||
276 | + top: 100%; | ||
277 | + } | ||
278 | + | ||
279 | + .table-upload-item-img { | ||
280 | + display: inline-block; | ||
281 | + height: 116px; | ||
282 | + width: 88px; | ||
283 | + border: 2px solid #e8e8e8; | ||
284 | + box-sizing: border-box; | ||
285 | + } | ||
286 | + | ||
287 | + .table-header { | ||
288 | + &:after { | ||
289 | + content: '*'; | ||
290 | + display: inline-block; | ||
291 | + margin-left: 4px; | ||
292 | + line-height: 1; | ||
293 | + font-family: SimSun; | ||
294 | + font-size: 12px; | ||
295 | + color: #f30; | ||
296 | + } | ||
297 | + } | ||
298 | + | ||
299 | +</style> |
@@ -50,16 +50,16 @@ export default { | @@ -50,16 +50,16 @@ export default { | ||
50 | { | 50 | { |
51 | title: '色卡图片', | 51 | title: '色卡图片', |
52 | key: 'goodsColorImage', | 52 | key: 'goodsColorImage', |
53 | - width: 250, | 53 | + width: 180, |
54 | render(row, col, index) { | 54 | render(row, col, index) { |
55 | return `<div | 55 | return `<div |
56 | - :class="{'upload-item': true , | ||
57 | - 'upload-item-error': | 56 | + :class="{'table-upload-item': true , |
57 | + 'table-upload-item-error': | ||
58 | row.goodsColorImage.showValidate && row.goodsColorImage.validate}"> | 58 | row.goodsColorImage.showValidate && row.goodsColorImage.validate}"> |
59 | - <div class="upload-item-img"> | 59 | + <div class="table-upload-item-img"> |
60 | <img v-if="row.goodsColorImage.value" | 60 | <img v-if="row.goodsColorImage.value" |
61 | :src="row.goodsColorImage.value" | 61 | :src="row.goodsColorImage.value" |
62 | - alt="" width="120px" height="122px"> | 62 | + alt="" width="84px" height="112px"> |
63 | </div> | 63 | </div> |
64 | 64 | ||
65 | <div> | 65 | <div> |
@@ -69,7 +69,7 @@ export default { | @@ -69,7 +69,7 @@ export default { | ||
69 | <example-pop></example-pop> | 69 | <example-pop></example-pop> |
70 | </div> | 70 | </div> |
71 | <div v-if="row.goodsColorImage.showValidate && row.goodsColorImage.validate" | 71 | <div v-if="row.goodsColorImage.showValidate && row.goodsColorImage.validate" |
72 | - class="upload-item-tip"> | 72 | + class="table-upload-item-tip"> |
73 | 必须上传图片 | 73 | 必须上传图片 |
74 | </div> | 74 | </div> |
75 | </div>`; | 75 | </div>`; |
@@ -297,11 +297,11 @@ export default { | @@ -297,11 +297,11 @@ export default { | ||
297 | } | 297 | } |
298 | } | 298 | } |
299 | 299 | ||
300 | -.upload-item-error { | 300 | +.table-upload-item-error { |
301 | border: 1px solid #f30; | 301 | border: 1px solid #f30; |
302 | } | 302 | } |
303 | 303 | ||
304 | -.upload-item-tip { | 304 | +.table-upload-item-tip { |
305 | padding-top: 6px; | 305 | padding-top: 6px; |
306 | color: #f30; | 306 | color: #f30; |
307 | top: 100%; | 307 | top: 100%; |
@@ -50,7 +50,7 @@ export default { | @@ -50,7 +50,7 @@ export default { | ||
50 | let mid = value[1]; | 50 | let mid = value[1]; |
51 | let min = value[2]; | 51 | let min = value[2]; |
52 | 52 | ||
53 | - if (!max.value) { | 53 | + if (!max || !max.value) { |
54 | return callback(new Error('一级类目不能为空')); | 54 | return callback(new Error('一级类目不能为空')); |
55 | } else if (!mid.value) { | 55 | } else if (!mid.value) { |
56 | 56 | ||
@@ -84,6 +84,8 @@ export default { | @@ -84,6 +84,8 @@ export default { | ||
84 | this.$refs.formData.validate((valid) => { | 84 | this.$refs.formData.validate((valid) => { |
85 | if (valid) { | 85 | if (valid) { |
86 | this.goNext(); | 86 | this.goNext(); |
87 | + } else { | ||
88 | + this.$Message.error('请填写必填项!'); | ||
87 | } | 89 | } |
88 | }); | 90 | }); |
89 | }, | 91 | }, |
1 | <template> | 1 | <template> |
2 | <div> | 2 | <div> |
3 | <Form ref="product" :model="product" :label-width="70" :rules="ruleValidate"> | 3 | <Form ref="product" :model="product" :label-width="70" :rules="ruleValidate"> |
4 | - | ||
5 | <Row> | 4 | <Row> |
6 | <div class="create-group"> | 5 | <div class="create-group"> |
7 | <span class="create-group-indicator"></span> | 6 | <span class="create-group-indicator"></span> |
@@ -10,78 +9,36 @@ | @@ -10,78 +9,36 @@ | ||
10 | </div> | 9 | </div> |
11 | </Row> | 10 | </Row> |
12 | 11 | ||
13 | - <Row> | ||
14 | - <Col> | ||
15 | - <div class="create-item-title">商品基本信息</div> | ||
16 | - </Col> | ||
17 | - </Row> | 12 | + <Row> <div class="create-item-title">商品基本信息</div> </Row> |
18 | 13 | ||
19 | - <Row> | ||
20 | - <div class="ivu-form-item ivu-form-item-required"> | ||
21 | - <label class="ivu-form-item-label" style="width: 100px;">品牌</label> | ||
22 | - <div style="float: left; line-height: 1; padding: 10px 12px 10px 0; box-sizing: border-box;"> | ||
23 | - <span>{{product.brandName}}</span> | ||
24 | - </div> | ||
25 | - </div> | ||
26 | - </Row> | 14 | + <Form-item label="品牌"> <span>{{product.brandName}}</span> </Form-item> |
27 | 15 | ||
28 | - <Row> | ||
29 | - <div class="ivu-form-item ivu-form-item-required"> | ||
30 | - <label class="ivu-form-item-label" style="width: 100px;">类目</label> | ||
31 | - <span style="float: left; line-height: 1; padding: 10px 12px 10px 0; box-sizing: border-box;"> | ||
32 | - <span>{{sortName}}</span> | ||
33 | - </span> | ||
34 | - </div> | ||
35 | - </Row> | 16 | + <Form-item label="类目"> <span>{{sortName}}</span> </Form-item> |
36 | 17 | ||
37 | - <Row> | ||
38 | - <Col span="8"> | ||
39 | - <Form-item label="商品名称" prop="productName"> | ||
40 | - <Input v-model="product.productName" placeholder="请输入..."/> | ||
41 | - </Form-item> | ||
42 | - </Col> | ||
43 | - </Row> | 18 | + <Form-item label="商品名称" prop="productName"> |
19 | + <Input v-model="product.productName" placeholder="请输入..." style="width: 400px;"/> | ||
20 | + </Form-item> | ||
44 | 21 | ||
45 | - <Row> | ||
46 | - <Col span="8"> | ||
47 | - <Form-item label="商品卖点"> | ||
48 | - <Input v-model="product.phrase" type="textarea" :rows="4" placeholder="请输入..."/> | ||
49 | - </Form-item> | ||
50 | - </Col> | ||
51 | - </Row> | 22 | + <Form-item label="商品卖点"> |
23 | + <Input v-model="product.phrase" type="textarea" :rows="4" placeholder="请输入..." style="width: 400px;"/> | ||
24 | + </Form-item> | ||
52 | 25 | ||
53 | - <Row> | ||
54 | - <Col span="8"> | ||
55 | - <Form-item label="商家商品编码" prop="factoryCode"> | ||
56 | - <Input v-model="product.factoryCode" placeholder="请输入..."/> | ||
57 | - </Form-item> | ||
58 | - </Col> | ||
59 | - </Row> | 26 | + <Form-item label="商家商品编码" prop="factoryCode"> |
27 | + <Input v-model="product.factoryCode" placeholder="请输入..." style="width: 400px;"/> | ||
28 | + </Form-item> | ||
60 | 29 | ||
61 | - <Row> | ||
62 | - <Col span="8"> | ||
63 | - <Form-item label="货品年" prop="goodsYears"> | ||
64 | - <Date-picker :value="product.goodsYears" @on-change="clickGoodsYear" type="year" placeholder="选择年" style="width: 200px"> | ||
65 | - </Date-picker> | ||
66 | - </Form-item> | ||
67 | - </Col> | ||
68 | - </Row> | 30 | + <Form-item label="货品年" prop="goodsYears"> |
31 | + <Date-picker :value="product.goodsYears" @on-change="clickGoodsYear" type="year" placeholder="选择年" style="width: 400px"> | ||
32 | + </Date-picker> | ||
33 | + </Form-item> | ||
69 | 34 | ||
70 | - <Row> | ||
71 | - <Col span="8"> | ||
72 | - <Form-item label="货品季" prop="goodsSeason"> | ||
73 | - <SelectSeason v-model="product.goodsSeason"></SelectSeason> | ||
74 | - </Form-item> | ||
75 | - </Col> | ||
76 | - </Row> | 35 | + <Form-item label="货品季" prop="goodsSeason"> |
36 | + <SelectSeason v-model="product.goodsSeason"></SelectSeason> | ||
37 | + </Form-item> | ||
77 | 38 | ||
78 | - <Row> | ||
79 | - <Col span="8"> | ||
80 | - <Form-item label="上市日期" prop="expectSaleTimeStr"> | ||
81 | - <Date-picker :value="product.expectSaleTimeStr" @on-change="clickSaleDate" type="date" placeholder="选择日期" style="width: 200px"></Date-picker> | ||
82 | - </Form-item> | ||
83 | - </Col> | ||
84 | - </Row> | 39 | + <Form-item label="上市日期" prop="expectSaleTimeStr"> |
40 | + <Date-picker :value="product.expectSaleTimeStr" @on-change="clickSaleDate" type="date" placeholder="选择日期" style="width: 400px"></Date-picker> | ||
41 | + </Form-item> | ||
85 | 42 | ||
86 | <Form-item label="性别" prop="gender"> | 43 | <Form-item label="性别" prop="gender"> |
87 | <RadioGender v-model="product.gender"></RadioGender> | 44 | <RadioGender v-model="product.gender"></RadioGender> |
@@ -91,20 +48,16 @@ | @@ -91,20 +48,16 @@ | ||
91 | <RadioSeason v-model="product.seasons"></RadioSeason> | 48 | <RadioSeason v-model="product.seasons"></RadioSeason> |
92 | </Form-item> | 49 | </Form-item> |
93 | 50 | ||
94 | - | ||
95 | <Form-item label="年龄层" prop="ageLevel"> | 51 | <Form-item label="年龄层" prop="ageLevel"> |
96 | <CheckboxAge v-model="product.ageLevel"></CheckboxAge> | 52 | <CheckboxAge v-model="product.ageLevel"></CheckboxAge> |
97 | </Form-item> | 53 | </Form-item> |
98 | 54 | ||
99 | <Row> | 55 | <Row> |
100 | - <Col> | ||
101 | - <div class="create-item-title">商品规格 | ||
102 | - <span class="create-group-sub-title">(颜色名称只能填写中文,最多5个汉字。款型编码和条码只能填写英文和数字,不区分大小写)</span> | ||
103 | - </div> | ||
104 | - </Col> | 56 | + <div class="create-item-title">商品规格 |
57 | + <span class="create-group-sub-title">(颜色名称只能填写中文,最多5个汉字。款型编码和条码只能填写英文和数字,不区分大小写)</span> | ||
58 | + </div> | ||
105 | </Row> | 59 | </Row> |
106 | 60 | ||
107 | - | ||
108 | <Form-item label="颜色" prop="selectColor"> | 61 | <Form-item label="颜色" prop="selectColor"> |
109 | <CheckboxColor v-model="product.selectColor" @on-add="addColor" @on-remove="removeColor"></CheckboxColor> | 62 | <CheckboxColor v-model="product.selectColor" @on-add="addColor" @on-remove="removeColor"></CheckboxColor> |
110 | </Form-item> | 63 | </Form-item> |
@@ -113,45 +66,25 @@ | @@ -113,45 +66,25 @@ | ||
113 | <CheckboxSize v-model="product.selectSize" :sort-id="product.smallSortId" @on-add="addSize" @on-remove="removeSize"></CheckboxSize> | 66 | <CheckboxSize v-model="product.selectSize" :sort-id="product.smallSortId" @on-add="addSize" @on-remove="removeSize"></CheckboxSize> |
114 | </Form-item> | 67 | </Form-item> |
115 | 68 | ||
116 | - <Row> | ||
117 | - <Form-item > | ||
118 | - <Table ref="sellerGoods" :context="self" :data="table.data" :columns="table.columns" stripe border></Table> | ||
119 | - </Form-item> | ||
120 | - </Row> | ||
121 | - | ||
122 | - <Row> | ||
123 | - <Col> | ||
124 | - <div class="create-item-title">商品价格</div> | ||
125 | - </Col> | ||
126 | - </Row> | ||
127 | - | ||
128 | - <Row> | ||
129 | - <Col span="8"> | ||
130 | - <Form-item label="吊牌价" prop="retailPrice"> | ||
131 | - <Input v-model="product.retailPrice" :number="true" placeholder="请输入..."/> | ||
132 | - </Form-item> | ||
133 | - </Col> | ||
134 | - </Row> | 69 | + <Form-item > |
70 | + <TableCreateGoodSize ref="sellerGoods" v-model="table.data"></TableCreateGoodSize> | ||
71 | + </Form-item> | ||
135 | 72 | ||
73 | + <Row> <div class="create-item-title">商品价格</div> </Row> | ||
136 | 74 | ||
137 | - <Row> | ||
138 | - <Col span="8"> | ||
139 | - <Form-item label="销售价" prop="salesPrice"> | ||
140 | - <Input v-model="product.salesPrice" :number="true" placeholder="请输入..."/> | ||
141 | - </Form-item> | ||
142 | - </Col> | ||
143 | - </Row> | 75 | + <Form-item label="吊牌价" prop="retailPrice"> |
76 | + <Input v-model="product.retailPrice" :number="true" placeholder="请输入..." style="width: 400px;"/> | ||
77 | + </Form-item> | ||
144 | 78 | ||
79 | + <Form-item label="销售价" prop="salesPrice"> | ||
80 | + <Input v-model="product.salesPrice" :number="true" placeholder="请输入..." style="width: 400px;"/> | ||
81 | + </Form-item> | ||
145 | </Form> | 82 | </Form> |
146 | 83 | ||
147 | - <Row> | ||
148 | - <Col> | ||
149 | - <div style="text-align: center"> | ||
150 | - <Button type="primary" @click="nextStep(1)" size="large">下一步</Button> | ||
151 | - <Button type="primary" @click="nextStep(0)" size="large">保存并退出</Button> | ||
152 | - </div> | ||
153 | - </Col> | ||
154 | - </Row> | 84 | + <div style="text-align: center"> |
85 | + <Button type="primary" @click="nextStep(1)" size="large">下一步</Button> | ||
86 | + <Button type="primary" @click="nextStep(0)" size="large">保存并退出</Button> | ||
87 | + </div> | ||
155 | </div> | 88 | </div> |
156 | </template> | 89 | </template> |
157 | 90 | ||
@@ -163,6 +96,7 @@ import {CheckboxAge, CheckboxColor, CheckboxSize} from 'components/checkbox'; | @@ -163,6 +96,7 @@ import {CheckboxAge, CheckboxColor, CheckboxSize} from 'components/checkbox'; | ||
163 | import {RadioSeason, RadioGender} from 'components/radio'; | 96 | import {RadioSeason, RadioGender} from 'components/radio'; |
164 | import {SelectSeason} from 'components/select'; | 97 | import {SelectSeason} from 'components/select'; |
165 | import {ExamplePop} from 'components/pop'; | 98 | import {ExamplePop} from 'components/pop'; |
99 | +import {TableCreateGoodSize} from 'components/table'; | ||
166 | 100 | ||
167 | const makeColor = () => { | 101 | const makeColor = () => { |
168 | return { | 102 | return { |
@@ -238,128 +172,6 @@ export default { | @@ -238,128 +172,6 @@ export default { | ||
238 | self: this, | 172 | self: this, |
239 | colors: [], | 173 | colors: [], |
240 | table: { | 174 | table: { |
241 | - columns: [ | ||
242 | - { | ||
243 | - title: '色系名称', | ||
244 | - key: 'goodsName', | ||
245 | - render(row, col, index) { | ||
246 | - return `<div v-if="isExist(${index})"> | ||
247 | - <p>{{table.data[${index}].goodsName.name}}</p> | ||
248 | - <Radio :value="table.data[${index}].goodsName.isDefault" | ||
249 | - @on-change="clickDefault(${index})">主推</Radio> | ||
250 | - </div>`; | ||
251 | - } | ||
252 | - }, | ||
253 | - { | ||
254 | - title: '颜色展示名称', | ||
255 | - key: 'factoryGoodsName', | ||
256 | - render(row, col, index) { | ||
257 | - return `<div v-if="isExist(${index})"> | ||
258 | - <i-input | ||
259 | - v-model="row.factoryGoodsName" | ||
260 | - :placeholder="row.goodsName.name"> | ||
261 | - </i-input> | ||
262 | - </div>`; | ||
263 | - } | ||
264 | - }, | ||
265 | - { | ||
266 | - title: '色卡图片', | ||
267 | - key: 'goodsColorImage', | ||
268 | - width: 170, | ||
269 | - render(row, col, index) { | ||
270 | - return `<div | ||
271 | - :class="{'upload-item': true , | ||
272 | - 'upload-item-error': | ||
273 | - row.goodsColorImage.showValidate && row.goodsColorImage.validate}" | ||
274 | - > | ||
275 | - <div class="upload-item-img"> | ||
276 | - <img v-if="row.goodsColorImage.value" | ||
277 | - :src="row.goodsColorImage.value" alt="" width="120px" height="122px"> | ||
278 | - </div> | ||
279 | - <div> | ||
280 | - <file-upload :id="{index: ${index}}" | ||
281 | - @on-success="uploadSuccess" | ||
282 | - @on-error="uploadError"></file-upload> | ||
283 | - <example-pop></example-pop> | ||
284 | - </div> | ||
285 | - <div v-if="row.goodsColorImage.showValidate && row.goodsColorImage.validate" | ||
286 | - class="upload-item-tip"> | ||
287 | - 必须上传图片 | ||
288 | - </div> | ||
289 | - </div>`; | ||
290 | - }, | ||
291 | - renderHeader(col, index) { | ||
292 | - return `<span class="table-header">${col.title}</span>`; | ||
293 | - } | ||
294 | - }, | ||
295 | - { | ||
296 | - title: '款型编码', | ||
297 | - key: 'factoryCode', | ||
298 | - render(row, col, index) { | ||
299 | - return `<div v-if="isExist(${index})"> | ||
300 | - <i-input | ||
301 | - v-model="row.factoryCode" | ||
302 | - placeholder="请输入..." > | ||
303 | - </i-input> | ||
304 | - </div>`; | ||
305 | - } | ||
306 | - }, | ||
307 | - { | ||
308 | - title: '尺码', | ||
309 | - key: 'sizeId', | ||
310 | - width: 80, | ||
311 | - render(row, col, index) { | ||
312 | - return `<div class="size-id"> | ||
313 | - <div v-for="size in row.sizeId" class="row-span"> | ||
314 | - {{size.name}} | ||
315 | - </div> | ||
316 | - </div>`; | ||
317 | - } | ||
318 | - }, | ||
319 | - { | ||
320 | - title: '商品条码', | ||
321 | - key: 'sizeCode', | ||
322 | - render(row, col, index) { | ||
323 | - return `<div class='size-code'> | ||
324 | - <div v-for="size,i in row.sizeCode" class="row-span"> | ||
325 | - <div style="position: relative"> | ||
326 | - <div :class="{'size-code-error': size.validate && !size.name}"> | ||
327 | - <i-input | ||
328 | - v-model="size.name" | ||
329 | - :disabled="!row.operator[i].value" | ||
330 | - placeholder="请输入..." | ||
331 | - /> | ||
332 | - </div> | ||
333 | - <div class="size-code-tip" v-if="size.validate && !size.name"> | ||
334 | - 不能为空 | ||
335 | - </div> | ||
336 | - </div> | ||
337 | - </div> | ||
338 | - </div>`; | ||
339 | - }, | ||
340 | - renderHeader(col, index) { | ||
341 | - return `<span class="table-header">${col.title}</span>`; | ||
342 | - } | ||
343 | - }, | ||
344 | - { | ||
345 | - title: '操作', | ||
346 | - key: 'operator', | ||
347 | - width: 100, | ||
348 | - render(row, col, index) { | ||
349 | - return `<template v-if="isExist(${index})"> | ||
350 | - <div class="size-operator"> | ||
351 | - <div v-for="op,i in row.operator" class="row-span"> | ||
352 | - <i-button v-if="row.operator[i].value" | ||
353 | - type="warning" | ||
354 | - @click="clickOperator(row, i)">禁用</i-button> | ||
355 | - <i-button v-else type="primary" | ||
356 | - @click="clickOperator(row, i)">启用</i-button> | ||
357 | - </div> | ||
358 | - </div> | ||
359 | - </template>`; | ||
360 | - } | ||
361 | - } | ||
362 | - ], | ||
363 | data: [], | 175 | data: [], |
364 | selectedSizes: [], | 176 | selectedSizes: [], |
365 | selectedColors: [], | 177 | selectedColors: [], |
@@ -449,7 +261,7 @@ export default { | @@ -449,7 +261,7 @@ export default { | ||
449 | this.beforeSubmit(); | 261 | this.beforeSubmit(); |
450 | return api.saveBaseProductInfo(this.product); | 262 | return api.saveBaseProductInfo(this.product); |
451 | }, () => { | 263 | }, () => { |
452 | - this.$Message.error('表单验证失败!'); | 264 | + this.$Message.error('请填写必填项!'); |
453 | }); | 265 | }); |
454 | }, | 266 | }, |
455 | nextStep: function(go) { | 267 | nextStep: function(go) { |
@@ -489,31 +301,6 @@ export default { | @@ -489,31 +301,6 @@ export default { | ||
489 | saveAndQuit: function() { | 301 | saveAndQuit: function() { |
490 | this.$router.push({name: 'product.offsale'}); | 302 | this.$router.push({name: 'product.offsale'}); |
491 | }, | 303 | }, |
492 | - clickDefault: function(index) { | ||
493 | - this.refreshTable(); | ||
494 | - let color = this.table.data[index]; | ||
495 | - | ||
496 | - | ||
497 | - color.goodsName.isDefault = true; | ||
498 | - this.table.data.forEach((c) => { | ||
499 | - if (c.colorId !== color.colorId) { | ||
500 | - c.goodsName.isDefault = false; | ||
501 | - } | ||
502 | - }); | ||
503 | - }, | ||
504 | - clickOperator: function(row, itemIndex) { | ||
505 | - this.refreshTable(); | ||
506 | - row.operator[itemIndex].value = row.operator[itemIndex].value ? false : true; | ||
507 | - | ||
508 | - if (row.operator[itemIndex].value) { | ||
509 | - row.sizeCode[itemIndex].name = ''; | ||
510 | - row.sizeCode[itemIndex].validate = true; | ||
511 | - } else { | ||
512 | - row.sizeCode[itemIndex].name = ''; | ||
513 | - row.sizeCode[itemIndex].validate = false; | ||
514 | - } | ||
515 | - | ||
516 | - }, | ||
517 | clickGoodsYear: function(value) { | 304 | clickGoodsYear: function(value) { |
518 | this.product.goodsYears = value; | 305 | this.product.goodsYears = value; |
519 | }, | 306 | }, |
@@ -535,22 +322,6 @@ export default { | @@ -535,22 +322,6 @@ export default { | ||
535 | 322 | ||
536 | _.first(this.table.data).goodsName.isDefault = true; | 323 | _.first(this.table.data).goodsName.isDefault = true; |
537 | }, | 324 | }, |
538 | - changeFactoryGoodsName: function(row, index) { | ||
539 | - this.table.data[index].factoryGoodsName = row.factoryGoodsName; | ||
540 | - }, | ||
541 | - changeFactoryCode: function(row, index) { | ||
542 | - this.table.data[index].factoryCode = row.factoryCode; | ||
543 | - }, | ||
544 | - changeSizeCode: function(row, rowIndex, sizeIndex) { | ||
545 | - this.table.data[rowIndex].sizeCode[sizeIndex].name = row.sizeCode[sizeIndex].name; | ||
546 | - | ||
547 | - this.table.data[rowIndex].sizeCode[sizeIndex].validate = true; | ||
548 | - if (this.table.data[rowIndex].sizeCode[sizeIndex].name) { | ||
549 | - this.table.data[rowIndex].sizeCode[sizeIndex].showValidate = false; | ||
550 | - } else { | ||
551 | - this.table.data[rowIndex].sizeCode[sizeIndex].showValidate = true; | ||
552 | - } | ||
553 | - }, | ||
554 | addColor: function(color) { | 325 | addColor: function(color) { |
555 | this.refreshTable(); | 326 | this.refreshTable(); |
556 | this.addColorData(color); | 327 | this.addColorData(color); |
@@ -646,33 +417,11 @@ export default { | @@ -646,33 +417,11 @@ export default { | ||
646 | }); | 417 | }); |
647 | 418 | ||
648 | color.operator.push({ | 419 | color.operator.push({ |
649 | - value: true | 420 | + value: false |
650 | }); | 421 | }); |
651 | }, | 422 | }, |
652 | - isExist: function(index) { | ||
653 | - let row = this.table.data[index]; | ||
654 | - | ||
655 | - if (row) { | ||
656 | - return true; | ||
657 | - } | ||
658 | - | ||
659 | - return false; | ||
660 | - }, | ||
661 | - uploadSuccess: function(attach, files) { | ||
662 | - this.refreshTable(); | ||
663 | - this.table.data[attach.index].goodsColorImage.value = files[0]; | ||
664 | - | ||
665 | - this.table.data[attach.index].goodsColorImage.validate = true; | ||
666 | - if (this.table.data[attach.index].goodsColorImage.value) { | ||
667 | - this.table.data[attach.index].goodsColorImage.showValidate = false; | ||
668 | - } else { | ||
669 | - this.table.data[attach.index].goodsColorImage.showValidate = true; | ||
670 | - } | ||
671 | - }, | ||
672 | refreshTable() { | 423 | refreshTable() { |
673 | - this.table.data = this.$refs.sellerGoods.rebuildData; | ||
674 | - }, | ||
675 | - uploadError: function(attach, err) { | 424 | + this.$refs.sellerGoods.syncData(); |
676 | }, | 425 | }, |
677 | validateOtherProps: function() { | 426 | validateOtherProps: function() { |
678 | return new Promise((resolve, reject) => { | 427 | return new Promise((resolve, reject) => { |
@@ -782,124 +531,12 @@ export default { | @@ -782,124 +531,12 @@ export default { | ||
782 | SelectSeason, | 531 | SelectSeason, |
783 | CheckboxColor, | 532 | CheckboxColor, |
784 | CheckboxSize, | 533 | CheckboxSize, |
785 | - ExamplePop | 534 | + ExamplePop, |
535 | + TableCreateGoodSize | ||
786 | } | 536 | } |
787 | }; | 537 | }; |
788 | </script> | 538 | </script> |
789 | 539 | ||
790 | <style lang="scss"> | 540 | <style lang="scss"> |
791 | -@mixin row-span{ | ||
792 | - min-height: 30px; | ||
793 | - | ||
794 | - .row-span { | ||
795 | - min-height: 30px; | ||
796 | - border-bottom: 1px solid #e3e8ee; | ||
797 | - padding-top: 20px ; | ||
798 | - padding-bottom: 20px ; | ||
799 | - margin-left: -18px; | ||
800 | - margin-right: -18px; | ||
801 | - padding-left: 18px ; | ||
802 | - padding-right: 18px ; | ||
803 | - | ||
804 | - &:last-child { | ||
805 | - border-bottom: none; | ||
806 | - } | ||
807 | - } | ||
808 | -} | ||
809 | - | ||
810 | -.squre { | ||
811 | - display: inline-block; | ||
812 | - height: 30px; | ||
813 | - margin-right: 10px; | ||
814 | - cursor: pointer; | ||
815 | - border: 1px solid white; | ||
816 | -} | ||
817 | - | ||
818 | -.squre-selected { | ||
819 | - border: 1px solid black; | ||
820 | -} | ||
821 | - | ||
822 | -.squre-disabled { | ||
823 | - color: gray; | ||
824 | - opacity: 0.5; | ||
825 | - cursor: not-allowed; | ||
826 | - border: 1px solid gray; | ||
827 | -} | ||
828 | - | ||
829 | -.squre-color { | ||
830 | - display: inline-block; | ||
831 | - height: 28px; | ||
832 | - width: 28px; | ||
833 | -} | ||
834 | - | ||
835 | -.squre-name { | ||
836 | - display: inline-block; | ||
837 | - height: 30px; | ||
838 | - line-height: 30px; | ||
839 | - vertical-align: top; | ||
840 | -} | ||
841 | - | ||
842 | -.size-code { | ||
843 | - @include row-span; | ||
844 | - | ||
845 | - &-error { | ||
846 | - border: 1px solid #f30; | ||
847 | - } | ||
848 | - | ||
849 | - &-tip { | ||
850 | - position: absolute; | ||
851 | - line-height: 1; | ||
852 | - padding-top: 6px; | ||
853 | - color: #f30; | ||
854 | - } | ||
855 | -} | ||
856 | - | ||
857 | -.size-id { | ||
858 | - @include row-span; | ||
859 | - text-align: center; | ||
860 | -} | ||
861 | - | ||
862 | -.size-operator { | ||
863 | - @include row-span; | ||
864 | - text-align: center; | ||
865 | -} | ||
866 | - | ||
867 | -.upload-item { | ||
868 | - display: inline-block; | ||
869 | - height: 220px; | ||
870 | - width: 130px; | ||
871 | - text-align: center; | ||
872 | - margin: 30px 0; | ||
873 | -} | ||
874 | - | ||
875 | -.upload-item-error { | ||
876 | - border: 1px solid #f30; | ||
877 | -} | ||
878 | - | ||
879 | -.upload-item-tip { | ||
880 | - padding-top: 6px; | ||
881 | - color: #f30; | ||
882 | - top: 100%; | ||
883 | -} | ||
884 | - | ||
885 | -.upload-item-img { | ||
886 | - display: inline-block; | ||
887 | - height: 126px; | ||
888 | - width: 124px; | ||
889 | - border: 2px solid #e8e8e8; | ||
890 | - box-sizing: border-box; | ||
891 | -} | ||
892 | - | ||
893 | -.table-header { | ||
894 | - &:after { | ||
895 | - content: '*'; | ||
896 | - display: inline-block; | ||
897 | - margin-left: 4px; | ||
898 | - line-height: 1; | ||
899 | - font-family: SimSun; | ||
900 | - font-size: 12px; | ||
901 | - color: #f30; | ||
902 | - } | ||
903 | -} | ||
904 | 541 | ||
905 | </style> | 542 | </style> |
@@ -129,6 +129,14 @@ import api from 'product-create/api'; | @@ -129,6 +129,14 @@ import api from 'product-create/api'; | ||
129 | import serial from 'product-create/serialize'; | 129 | import serial from 'product-create/serialize'; |
130 | 130 | ||
131 | export default { | 131 | export default { |
132 | + props: { | ||
133 | + from: { | ||
134 | + type: String, | ||
135 | + default() { | ||
136 | + return 'product.offsale'; | ||
137 | + } | ||
138 | + } | ||
139 | + }, | ||
132 | data() { | 140 | data() { |
133 | return { | 141 | return { |
134 | showLoading: true, | 142 | showLoading: true, |
@@ -159,6 +167,8 @@ export default { | @@ -159,6 +167,8 @@ export default { | ||
159 | }; | 167 | }; |
160 | }, | 168 | }, |
161 | created() { | 169 | created() { |
170 | + this.from = this.$route.query.from || this.from; | ||
171 | + | ||
162 | service.getProduct(this.$route.params.id).then((result) => { | 172 | service.getProduct(this.$route.params.id).then((result) => { |
163 | _.update(result, 'goodsSeason', (s) => `${s}`); | 173 | _.update(result, 'goodsSeason', (s) => `${s}`); |
164 | if (!_.has(result, 'materialList')) { | 174 | if (!_.has(result, 'materialList')) { |
@@ -493,7 +503,7 @@ export default { | @@ -493,7 +503,7 @@ export default { | ||
493 | desc: '该商品保存成功!' | 503 | desc: '该商品保存成功!' |
494 | }); | 504 | }); |
495 | 505 | ||
496 | - this.$router.push({ name: 'product.offsale' }); | 506 | + this.go(this.from); |
497 | } else { | 507 | } else { |
498 | this.$Notice.error({ | 508 | this.$Notice.error({ |
499 | title: '保存错误', | 509 | title: '保存错误', |
@@ -503,13 +513,16 @@ export default { | @@ -503,13 +513,16 @@ export default { | ||
503 | } | 513 | } |
504 | }); | 514 | }); |
505 | }, | 515 | }, |
516 | + go(from) { | ||
517 | + this.$router.push({ name: from }); | ||
518 | + }, | ||
506 | submit() { | 519 | submit() { |
507 | this.validate() | 520 | this.validate() |
508 | .then(([r1, r2]) => { | 521 | .then(([r1, r2]) => { |
509 | if (r1 & r2) { | 522 | if (r1 & r2) { |
510 | return Promise.resolve(); | 523 | return Promise.resolve(); |
511 | } else { | 524 | } else { |
512 | - this.$Message.error('验证未通过'); | 525 | + this.$Message.error('请填写必填项'); |
513 | return Promise.reject(); | 526 | return Promise.reject(); |
514 | } | 527 | } |
515 | }) | 528 | }) |
@@ -103,7 +103,7 @@ | @@ -103,7 +103,7 @@ | ||
103 | return service.getCategoryList(this.pageData.current, this.pageData.pageSize).then((result) => { | 103 | return service.getCategoryList(this.pageData.current, this.pageData.pageSize).then((result) => { |
104 | if (result.code === 200) { | 104 | if (result.code === 200) { |
105 | this.pageData.total = result.data.total; | 105 | this.pageData.total = result.data.total; |
106 | - this.pageData.current = result.data.currentPage; | 106 | + this.pageData.current = result.data.currentPage || 1; |
107 | this.tableData = result.data.rows; | 107 | this.tableData = result.data.rows; |
108 | } | 108 | } |
109 | }); | 109 | }); |
@@ -19,9 +19,7 @@ const plugin = { | @@ -19,9 +19,7 @@ const plugin = { | ||
19 | checkPurview() { | 19 | checkPurview() { |
20 | return Promise.resolve(); | 20 | return Promise.resolve(); |
21 | 21 | ||
22 | - // let pUrl = `/${_.split(to.name, '.').join('/')}`; | ||
23 | - | ||
24 | - // let pur = _.find(purviews, p => p.menu_url === pUrl); | 22 | + // let pur = _.find(Vue.$purviews, p => p.menu_url === to.path); |
25 | 23 | ||
26 | // if (pur) { | 24 | // if (pur) { |
27 | // return Promise.resolve(); | 25 | // return Promise.resolve(); |
@@ -42,6 +40,8 @@ const plugin = { | @@ -42,6 +40,8 @@ const plugin = { | ||
42 | user = Rsa.decrypt(user, Object); | 40 | user = Rsa.decrypt(user, Object); |
43 | return this.initPurview(Vue, user).then(() => { | 41 | return this.initPurview(Vue, user).then(() => { |
44 | next(); | 42 | next(); |
43 | + }, () => { | ||
44 | + next(); | ||
45 | }); | 45 | }); |
46 | } | 46 | } |
47 | next(); | 47 | next(); |
@@ -65,7 +65,7 @@ const plugin = { | @@ -65,7 +65,7 @@ const plugin = { | ||
65 | return next('/login.html'); | 65 | return next('/login.html'); |
66 | } | 66 | } |
67 | 67 | ||
68 | - return this.checkPurview(Vue.$purviews, to).then(() => { | 68 | + return this.checkPurview(Vue, to).then(() => { |
69 | return next(); | 69 | return next(); |
70 | }, () => { | 70 | }, () => { |
71 | return next('/401.html'); | 71 | return next('/401.html'); |
@@ -31,6 +31,13 @@ const userService = { | @@ -31,6 +31,13 @@ const userService = { | ||
31 | } | 31 | } |
32 | }); | 32 | }); |
33 | return purs; | 33 | return purs; |
34 | + }, | ||
35 | + switchShop(shopId) { | ||
36 | + return axios.post('/switchShop', { | ||
37 | + shopId | ||
38 | + }).then(res => { | ||
39 | + return res.data; | ||
40 | + }); | ||
34 | } | 41 | } |
35 | }; | 42 | }; |
36 | 43 |
@@ -55,7 +55,8 @@ let domainApis = { | @@ -55,7 +55,8 @@ let domainApis = { | ||
55 | getRemoteImageUrlBySku: '/product/getRemoteImageUrlBySku' | 55 | getRemoteImageUrlBySku: '/product/getRemoteImageUrlBySku' |
56 | }, | 56 | }, |
57 | shop: { | 57 | shop: { |
58 | - login: '/loginInter' | 58 | + login: '/loginInter', |
59 | + switchShop: '/index/ajaxshop' | ||
59 | } | 60 | } |
60 | }; | 61 | }; |
61 | 62 |
@@ -83,7 +83,8 @@ class Api extends Context { | @@ -83,7 +83,8 @@ class Api extends Context { | ||
83 | logger.error(`api call ${err.statusCode} [${err.options.method}] | 83 | logger.error(`api call ${err.statusCode} [${err.options.method}] |
84 | ${err.options.url} ${err.response.body || ''}`); | 84 | ${err.options.url} ${err.response.body || ''}`); |
85 | } else { | 85 | } else { |
86 | - logger.error(`api call ${err}`); | 86 | + logger.error(`api call [${options.method || 'get'}] ${options.url} |
87 | + ${JSON.stringify(options.qs || options.body)} ${err}`); | ||
87 | } | 88 | } |
88 | return Promise.reject(API_INTERNAL_ERROR); | 89 | return Promise.reject(API_INTERNAL_ERROR); |
89 | }); | 90 | }); |
@@ -10,6 +10,8 @@ const Express = require('express'); | @@ -10,6 +10,8 @@ const Express = require('express'); | ||
10 | const UserController = require('./user-controller'); | 10 | const UserController = require('./user-controller'); |
11 | const FileController = require('./file-controller'); | 11 | const FileController = require('./file-controller'); |
12 | const middleware = require('../framework/middleware'); | 12 | const middleware = require('../framework/middleware'); |
13 | +const before = require('../middleware/before'); | ||
14 | +const auth = require('../middleware/auth'); | ||
13 | const multipart = require('connect-multiparty'); | 15 | const multipart = require('connect-multiparty'); |
14 | const multipartMiddleware = multipart(); | 16 | const multipartMiddleware = multipart(); |
15 | 17 | ||
@@ -17,7 +19,8 @@ let router = Express.Router(); // eslint-disable-line | @@ -17,7 +19,8 @@ let router = Express.Router(); // eslint-disable-line | ||
17 | 19 | ||
18 | router.post('/login', middleware(UserController, 'login')); | 20 | router.post('/login', middleware(UserController, 'login')); |
19 | router.post('/logout', middleware(UserController, 'logout')); | 21 | router.post('/logout', middleware(UserController, 'logout')); |
20 | -router.post('/upload/image', multipartMiddleware, middleware(FileController, 'uploadImage')); | ||
21 | -router.post('/upload/xlsx', multipartMiddleware, middleware(FileController, 'uploadXlsx')); | 22 | +router.post('/switchShop', before, auth, middleware(UserController, 'switchShop')); |
23 | +router.post('/upload/image', before, auth, multipartMiddleware, middleware(FileController, 'uploadImage')); | ||
24 | +router.post('/upload/xlsx', before, auth, multipartMiddleware, middleware(FileController, 'uploadXlsx')); | ||
22 | 25 | ||
23 | module.exports = router; | 26 | module.exports = router; |
@@ -26,9 +26,8 @@ class UserController extends Context { | @@ -26,9 +26,8 @@ class UserController extends Context { | ||
26 | let currentShop = _.first(result.data); | 26 | let currentShop = _.first(result.data); |
27 | 27 | ||
28 | this.syncSession({req, res}, Object.assign(user, { | 28 | this.syncSession({req, res}, Object.assign(user, { |
29 | - shops: result.data, | ||
30 | - currentShop: currentShop | ||
31 | - }), sess); | 29 | + shops: result.data |
30 | + }), sess, currentShop); | ||
32 | 31 | ||
33 | return res.json({ | 32 | return res.json({ |
34 | code: 200, | 33 | code: 200, |
@@ -68,26 +67,62 @@ class UserController extends Context { | @@ -68,26 +67,62 @@ class UserController extends Context { | ||
68 | data: '登出成功' | 67 | data: '登出成功' |
69 | }); | 68 | }); |
70 | } | 69 | } |
70 | + switchShop(req, res) { | ||
71 | + let shopId = req.body.shopId; | ||
71 | 72 | ||
72 | - syncSession(context, user, sess) { | 73 | + if (!shopId) { |
74 | + return res.json({ | ||
75 | + code: 400, | ||
76 | + message: '参数错误' | ||
77 | + }); | ||
78 | + } | ||
79 | + let shop = _.find(req.session.USER.shops, s => s.shopsId === shopId); | ||
80 | + | ||
81 | + if (!shop) { | ||
82 | + return res.json({ | ||
83 | + code: 400, | ||
84 | + message: '不存在的店铺' | ||
85 | + }); | ||
86 | + } | ||
87 | + this.userService.switchShop({ | ||
88 | + shopId, | ||
89 | + cookies: { | ||
90 | + PHPSESSID: encodeURIComponent(req.cookies.PHPSESSID), | ||
91 | + 'connect.sid': encodeURIComponent(req.cookies['connect.sid']) | ||
92 | + } | ||
93 | + }).then(response => { | ||
94 | + this.syncShopSession({ | ||
95 | + req, | ||
96 | + res | ||
97 | + }, response); | ||
98 | + return res.json({ | ||
99 | + code: 200 | ||
100 | + }); | ||
101 | + }); | ||
102 | + } | ||
103 | + | ||
104 | + syncSession(context, user, sess, currentShop) { | ||
73 | context.req.session.USER = user; | 105 | context.req.session.USER = user; |
74 | context.req.session.LOGIN_UID = user.pid; // pid 为用户名 | 106 | context.req.session.LOGIN_UID = user.pid; // pid 为用户名 |
75 | 107 | ||
108 | + this.syncShopSession(context, sess); | ||
109 | + context.res.cookie('_isLogin', true, { | ||
110 | + path: '/' | ||
111 | + }); | ||
112 | + context.res.cookie('_sign', currentShop.shopsId, { | ||
113 | + path: '/' | ||
114 | + }); | ||
115 | + } | ||
116 | + | ||
117 | + syncShopSession(context, sess) { | ||
76 | _.each(sess, (v, k) => { | 118 | _.each(sess, (v, k) => { |
77 | context.res.cookie(k, v, { | 119 | context.res.cookie(k, v, { |
78 | path: '/', | 120 | path: '/', |
79 | domain: '.yohobuy.com', | 121 | domain: '.yohobuy.com', |
80 | httpOnly: true, | 122 | httpOnly: true, |
81 | - overwrite: false, | ||
82 | encode: val => val | 123 | encode: val => val |
83 | }); | 124 | }); |
84 | }); | 125 | }); |
85 | - context.res.cookie('_isLogin', true, { | ||
86 | - path: '/' | ||
87 | - }); | ||
88 | - context.res.cookie('_sign', user.currentShop.shopsId, { | ||
89 | - path: '/' | ||
90 | - }); | ||
91 | } | 126 | } |
92 | } | 127 | } |
93 | 128 |
@@ -39,24 +39,28 @@ class UserService extends Context { | @@ -39,24 +39,28 @@ class UserService extends Context { | ||
39 | password: password | 39 | password: password |
40 | } | 40 | } |
41 | }).then(response => { | 41 | }).then(response => { |
42 | - let sessId = '', sid = ''; | 42 | + return this._getShopsSession(response.rawHeaders); |
43 | + }); | ||
44 | + } | ||
45 | + | ||
46 | + _getShopsSession(rawHeaders) { | ||
47 | + let sessId = '', sid = ''; | ||
43 | 48 | ||
44 | - _.each(response.rawHeaders, header => { | ||
45 | - let sessIdMatched = header.match(new RegExp(regSession.replace('${0}', 'PHPSESSID'))); | ||
46 | - let sidMatched = header.match(new RegExp(regSession.replace('${0}', 'connect\.sid'))); | 49 | + _.each(rawHeaders, header => { |
50 | + let sessIdMatched = header.match(new RegExp(regSession.replace('${0}', 'PHPSESSID'))); | ||
51 | + let sidMatched = header.match(new RegExp(regSession.replace('${0}', 'connect\.sid'))); | ||
47 | 52 | ||
48 | - if (sessIdMatched) { | ||
49 | - sessId = sessIdMatched[1]; | ||
50 | - } | ||
51 | - if (sidMatched) { | ||
52 | - sid = sidMatched[1]; | ||
53 | - } | ||
54 | - }); | ||
55 | - return { | ||
56 | - PHPSESSID: sessId, | ||
57 | - 'connect.sid': sid | ||
58 | - }; | 53 | + if (sessIdMatched) { |
54 | + sessId = sessIdMatched[1]; | ||
55 | + } | ||
56 | + if (sidMatched) { | ||
57 | + sid = sidMatched[1]; | ||
58 | + } | ||
59 | }); | 59 | }); |
60 | + return { | ||
61 | + PHPSESSID: sessId, | ||
62 | + 'connect.sid': sid | ||
63 | + }; | ||
60 | } | 64 | } |
61 | 65 | ||
62 | getShops(pid) { | 66 | getShops(pid) { |
@@ -68,6 +72,22 @@ class UserService extends Context { | @@ -68,6 +72,22 @@ class UserService extends Context { | ||
68 | }); | 72 | }); |
69 | } | 73 | } |
70 | 74 | ||
75 | + switchShop(opts) { | ||
76 | + let options = { | ||
77 | + url: `${config.apiDomain.shop.switchShop}?shops_id=${opts.shopId}`, | ||
78 | + resolveWithFullResponse: true, | ||
79 | + }; | ||
80 | + let jar = rp.jar(); | ||
81 | + | ||
82 | + _.each(opts.cookies, (val, key) => { | ||
83 | + jar.setCookie(rp.cookie(`${key}=${val}`), options.url); | ||
84 | + }); | ||
85 | + options.jar = jar; | ||
86 | + return rp.get(options).then(response => { | ||
87 | + return this._getShopsSession(response.rawHeaders); | ||
88 | + }); | ||
89 | + } | ||
90 | + | ||
71 | profile(pid) { | 91 | profile(pid) { |
72 | return this.instance(Api).get(config.apiDomain.shop.profile.url, {userId: pid}); | 92 | return this.instance(Api).get(config.apiDomain.shop.profile.url, {userId: pid}); |
73 | } | 93 | } |
-
Please register or login to post a comment