Authored by htoooth

fix

@@ -17,19 +17,21 @@ @@ -17,19 +17,21 @@
17 </Row> 17 </Row>
18 18
19 <Row> 19 <Row>
20 - <Col span="8">  
21 - <Form-item label="品牌"> 20 + <div class="ivu-form-item ivu-form-item-required">
  21 + <label class="ivu-form-item-label" style="width: 70px;">品牌</label>
  22 + <div style="float: left; line-height: 1; padding: 10px 12px 10px 0; box-sizing: border-box;">
22 <span>{{product.brandName}}</span> 23 <span>{{product.brandName}}</span>
23 - </Form-item>  
24 - </Col> 24 + </div>
  25 + </div>
25 </Row> 26 </Row>
26 27
27 <Row> 28 <Row>
28 - <Col span="8">  
29 - <Form-item label="类目"> 29 + <div class="ivu-form-item ivu-form-item-required">
  30 + <label class="ivu-form-item-label" style="width: 70px;">类目</label>
  31 + <span style="float: left; line-height: 1; padding: 10px 12px 10px 0; box-sizing: border-box;">
30 <span>{{sortName}}</span> 32 <span>{{sortName}}</span>
31 - </Form-item>  
32 - </Col> 33 + </span>
  34 + </div>
33 </Row> 35 </Row>
34 36
35 <Row> 37 <Row>
@@ -103,30 +105,38 @@ @@ -103,30 +105,38 @@
103 </Row> 105 </Row>
104 106
105 <Row> 107 <Row>
106 - <Form-item label="颜色">  
107 - <span class='squre'  
108 - v-for="color in colors"  
109 - @click="clickColor(color)"  
110 - :class="{  
111 - 'squre-selected': color.selected,  
112 - 'squre-disabled': color.disabled  
113 - }">  
114 - <span class="squre-color"  
115 - :style="{ 'background-color': '#' + color.colorCode}"> 108 + <div class="ivu-form-item ivu-form-item-required">
  109 + <label class="ivu-form-item-label" style="width: 70px;"> 颜色</label>
  110 + <div :class="{'product-table-error' : table.showValidateColor}" style="margin-left: 70px;">
  111 + <span class='squre'
  112 + v-for="color in colors"
  113 + @click="clickColor(color)"
  114 + :class="{
  115 + 'squre-selected': color.selected,
  116 + 'squre-disabled': color.disabled
  117 + }">
  118 + <span class="squre-color"
  119 + :style="{ 'background-color': '#' + color.colorCode}">
  120 + </span>
  121 + <span class="squre-name">{{color.colorName}}</span>
116 </span> 122 </span>
117 - <span class="squre-name">{{color.colorName}}</span>  
118 - </span>  
119 - </Form-item> 123 + </div>
  124 + <div class="product-table-tip" v-if="table.showValidateColor">颜色必须选择</div>
  125 + </div>
120 </Row> 126 </Row>
121 127
122 <Row> 128 <Row>
123 - <Form-item label="尺寸">  
124 - <Checkbox-group v-model='table.selectedSizes'>  
125 - <Checkbox v-for="size in sizes" :key="size" :label="size.id" >  
126 - <span>{{size.sizeName}}</span>  
127 - </Checkbox>  
128 - </Checkbox-group>  
129 - </Form-item> 129 + <div class="ivu-form-item ivu-form-item-required">
  130 + <label class="ivu-form-item-label" style="width: 70px;">尺寸</label>
  131 + <div :class="{'product-table-error': table.showValidateSize}" style="margin-left: 70px;">
  132 + <Checkbox-group v-model='table.selectedSizes'>
  133 + <Checkbox v-for="size in sizes" :key="size" :label="size.id" >
  134 + <span>{{size.sizeName}}</span>
  135 + </Checkbox>
  136 + </Checkbox-group>
  137 + </div>
  138 + <div class="product-table-tip" v-if="table.showValidateSize">尺码必须选择</div>
  139 + </div>
130 </Row> 140 </Row>
131 141
132 <Row> 142 <Row>
@@ -194,6 +204,8 @@ const makeColor = () => { @@ -194,6 +204,8 @@ const makeColor = () => {
194 }; 204 };
195 }; 205 };
196 206
  207 +
  208 +
197 export default { 209 export default {
198 props: ['step', 'product'], 210 props: ['step', 'product'],
199 data() { 211 data() {
@@ -237,7 +249,7 @@ export default { @@ -237,7 +249,7 @@ export default {
237 return { 249 return {
238 self: this, 250 self: this,
239 colors: [], 251 colors: [],
240 - selectedColors: [], 252 +
241 sizes: [], 253 sizes: [],
242 table: { 254 table: {
243 columns: [ 255 columns: [
@@ -259,8 +271,7 @@ export default { @@ -259,8 +271,7 @@ export default {
259 return `<div v-if="isExist(${index})"> 271 return `<div v-if="isExist(${index})">
260 <i-input 272 <i-input
261 v-model="row.factoryGoodsName" 273 v-model="row.factoryGoodsName"
262 - placeholder="请输入..."  
263 - style="width: 100px"> 274 + :placeholder="row.goodsName.name">
264 </i-input> 275 </i-input>
265 </div>`; 276 </div>`;
266 } 277 }
@@ -268,12 +279,26 @@ export default { @@ -268,12 +279,26 @@ export default {
268 { 279 {
269 title: '色卡图片*', 280 title: '色卡图片*',
270 key: 'goodsColorImage', 281 key: 'goodsColorImage',
  282 + width: 170,
271 render(row, col, index) { 283 render(row, col, index) {
272 - return `<img v-if="row.goodsColorImage"  
273 - :src="row.goodsColorImage" alt="" width="120px" height="120px">  
274 - <yoho-upload :id="{index: ${index}}"  
275 - @on-success="uploadSuccess"  
276 - @on-error="uploadError"></yoho-upload>`; 284 + return `<div
  285 + :class="{'upload-item': true ,
  286 + 'upload-item-error': row.goodsColorImage.showValidate && row.goodsColorImage.validate}"
  287 + >
  288 + <div class="upload-item-img">
  289 + <img v-if="row.goodsColorImage.value"
  290 + :src="row.goodsColorImage.value" alt="" width="120px" height="122px">
  291 + </div>
  292 + <div>
  293 + <yoho-upload :id="{index: ${index}}"
  294 + @on-success="uploadSuccess"
  295 + @on-error="uploadError"></yoho-upload>
  296 + </div>
  297 + <div v-if="row.goodsColorImage.showValidate && row.goodsColorImage.validate"
  298 + class="upload-item-tip">
  299 + 必须上传图片
  300 + </div>
  301 + </div>`;
277 } 302 }
278 }, 303 },
279 { 304 {
@@ -283,15 +308,15 @@ export default { @@ -283,15 +308,15 @@ export default {
283 return `<div v-if="isExist(${index})"> 308 return `<div v-if="isExist(${index})">
284 <i-input 309 <i-input
285 v-model="row.factoryCode" 310 v-model="row.factoryCode"
286 - placeholder="请输入..."  
287 - style="width: 100px"> 311 + placeholder="请输入..." >
288 </i-input> 312 </i-input>
289 </div>`; 313 </div>`;
290 } 314 }
291 }, 315 },
292 { 316 {
293 - title: '尺码*', 317 + title: '尺码',
294 key: 'sizeId', 318 key: 'sizeId',
  319 + width: 80,
295 render(row, col, index) { 320 render(row, col, index) {
296 return `<div class="size-id"> 321 return `<div class="size-id">
297 <div v-for="size in row.sizeId" class="row-span"> 322 <div v-for="size in row.sizeId" class="row-span">
@@ -306,11 +331,18 @@ export default { @@ -306,11 +331,18 @@ export default {
306 render(row, col, index) { 331 render(row, col, index) {
307 return `<div class='size-code'> 332 return `<div class='size-code'>
308 <div v-for="size,i in row.sizeCode" class="row-span"> 333 <div v-for="size,i in row.sizeCode" class="row-span">
309 - <i-input  
310 - v-model="size.name"  
311 - :disabled="!row.operator[i].value"  
312 - placeholder="请输入..."  
313 - style="width: 100px"/> 334 + <div style="position: relative">
  335 + <div :class="{'size-code-error': size.validate && !size.name}">
  336 + <i-input
  337 + v-model="size.name"
  338 + :disabled="!row.operator[i].value"
  339 + placeholder="请输入..."
  340 + />
  341 + </div>
  342 + <div class="size-code-tip" v-if="size.validate && !size.name">
  343 + 不能为空
  344 + </div>
  345 + </div>
314 </div> 346 </div>
315 </div>`; 347 </div>`;
316 } 348 }
@@ -318,6 +350,7 @@ export default { @@ -318,6 +350,7 @@ export default {
318 { 350 {
319 title: '操作', 351 title: '操作',
320 key: 'operator', 352 key: 'operator',
  353 + width: 100,
321 render(row, col, index) { 354 render(row, col, index) {
322 return `<template v-if="isExist(${index})"> 355 return `<template v-if="isExist(${index})">
323 <div class="size-operator"> 356 <div class="size-operator">
@@ -335,9 +368,12 @@ export default { @@ -335,9 +368,12 @@ export default {
335 ], 368 ],
336 data: [], 369 data: [],
337 selectedSizes: [], 370 selectedSizes: [],
338 - selectedColors: [] 371 + selectedColors: [],
  372 + showValidateColor: false,
  373 + showValidateSize: false,
  374 + showValidateOtherProp: false,
  375 + showValidateTable: false,
339 }, 376 },
340 - ageLevel: [],  
341 ruleValidate: { 377 ruleValidate: {
342 productName: [ 378 productName: [
343 { required: true, message: '商品名不能为空', trigger: 'blur'} 379 { required: true, message: '商品名不能为空', trigger: 'blur'}
@@ -376,19 +412,49 @@ export default { @@ -376,19 +412,49 @@ export default {
376 }; 412 };
377 }, 413 },
378 mounted: function() { 414 mounted: function() {
379 - this.getColor();  
380 - this.getSize(); 415 + this.getColorAsync();
  416 + this.getSizeAsync();
381 }, 417 },
382 methods: { 418 methods: {
383 - validate: function() {  
384 - return new Promise((resolve, reject) => {  
385 - this.$refs['product'].validate((valid) => {  
386 - if (valid) {  
387 - resolve();  
388 - } else {  
389 - reject(); 419 + beforeSubmit: function() {
  420 + const handleColor = (color) => {
  421 + let newColor = makeColor();
  422 +
  423 + newColor.goodsName = color.goodsName.name;
  424 + newColor.isDefault = color.goodsName.isDefault ? 'Y' : 'N';
  425 +
  426 + newColor.factoryGoodsName = color.factoryGoodsName || color.goodsName.name;
  427 + newColor.factoryCode = color.factoryCode;
  428 +
  429 + newColor.goodsColorImage = color.goodsColorImage.value;
  430 + newColor.colorId = color.colorId;
  431 +
  432 + let goodsSizeList = [];
  433 +
  434 + color.operator.forEach((op, i) => {
  435 + if (!op.value) {
  436 + return;
390 } 437 }
391 - }) 438 +
  439 + let goodsSize = {};
  440 +
  441 + goodsSize.sizeId = color.sizeId[i].id;
  442 + goodsSize.factoryCode = color.sizeCode[i].name;
  443 + goodsSizeList.push(goodsSize);
  444 + });
  445 +
  446 + newColor.goodsSizeList = goodsSizeList;
  447 +
  448 + return newColor;
  449 + };
  450 +
  451 + this.refreshTable();
  452 + this.product.sellerGoodsInfoStr = JSON.stringify(this.table.data.map(handleColor));
  453 + },
  454 + submit: function() {
  455 + return this.validate().then(() => {
  456 + this.beforeSubmit();
  457 + return api.saveBaseProductInfo(this.product);
392 }); 458 });
393 }, 459 },
394 nextStep: function() { 460 nextStep: function() {
@@ -424,14 +490,14 @@ export default { @@ -424,14 +490,14 @@ export default {
424 this.step.value = 0; 490 this.step.value = 0;
425 this.$router.push({name: 'product.create.step1'}); 491 this.$router.push({name: 'product.create.step1'});
426 }, 492 },
427 - getColor: function() { 493 + getColorAsync: function() {
428 return api.getColor().then((result) => { 494 return api.getColor().then((result) => {
429 if (result.code === 200) { 495 if (result.code === 200) {
430 this.colors = result.data; 496 this.colors = result.data;
431 } 497 }
432 }); 498 });
433 }, 499 },
434 - getSize: function() { 500 + getSizeAsync: function() {
435 return api.getSize(this.product.smallSortId).then((result) => { 501 return api.getSize(this.product.smallSortId).then((result) => {
436 if (result.code === 200) { 502 if (result.code === 200) {
437 this.sizes = result.data; 503 this.sizes = result.data;
@@ -441,21 +507,6 @@ export default { @@ -441,21 +507,6 @@ export default {
441 clickColor: function(color) { 507 clickColor: function(color) {
442 this.addColor(color); 508 this.addColor(color);
443 }, 509 },
444 - changeFactoryGoodsName: function(row, index) {  
445 - this.table.data[index].factoryGoodsName = row.factoryGoodsName;  
446 - },  
447 - changeFactoryCode: function(row, index) {  
448 - this.table.data[index].factoryCode = row.factoryCode;  
449 - },  
450 - changeUploadFileSuccess: function(row, index) {  
451 - this.table.data[index].goodsColorImage = row.goodsColorImage;  
452 - },  
453 - changeUploadFileFail: function(row, index) {  
454 -  
455 - },  
456 - changeSizeCode: function(row, rowIndex, sizeIndex) {  
457 - this.table.data[rowIndex].sizeCode[sizeIndex].name = row.sizeCode[sizeIndex].name;  
458 - },  
459 clickDefault: function(index) { 510 clickDefault: function(index) {
460 this.refreshTable(); 511 this.refreshTable();
461 let color = this.table.data[index]; 512 let color = this.table.data[index];
@@ -471,6 +522,15 @@ export default { @@ -471,6 +522,15 @@ export default {
471 clickOperator: function(row, itemIndex) { 522 clickOperator: function(row, itemIndex) {
472 this.refreshTable(); 523 this.refreshTable();
473 row.operator[itemIndex].value = row.operator[itemIndex].value ? false : true; 524 row.operator[itemIndex].value = row.operator[itemIndex].value ? false : true;
  525 +
  526 + if (row.operator[itemIndex].value) {
  527 + row.sizeCode[itemIndex].name = '';
  528 + row.sizeCode[itemIndex].validate = true;
  529 + } else {
  530 + row.sizeCode[itemIndex].name = '';
  531 + row.sizeCode[itemIndex].validate = false;
  532 + }
  533 +
474 }, 534 },
475 clickGoodsYear: function(value) { 535 clickGoodsYear: function(value) {
476 this.product.goodsYears = value; 536 this.product.goodsYears = value;
@@ -493,6 +553,22 @@ export default { @@ -493,6 +553,22 @@ export default {
493 553
494 _.first(this.table.data).goodsName.isDefault = true; 554 _.first(this.table.data).goodsName.isDefault = true;
495 }, 555 },
  556 + changeFactoryGoodsName: function(row, index) {
  557 + this.table.data[index].factoryGoodsName = row.factoryGoodsName;
  558 + },
  559 + changeFactoryCode: function(row, index) {
  560 + this.table.data[index].factoryCode = row.factoryCode;
  561 + },
  562 + changeSizeCode: function(row, rowIndex, sizeIndex) {
  563 + this.table.data[rowIndex].sizeCode[sizeIndex].name = row.sizeCode[sizeIndex].name;
  564 +
  565 + this.table.data[rowIndex].sizeCode[sizeIndex].validate = true;
  566 + if (this.table.data[rowIndex].sizeCode[sizeIndex].name) {
  567 + this.table.data[rowIndex].sizeCode[sizeIndex].showValidate = false;
  568 + } else {
  569 + this.table.data[rowIndex].sizeCode[sizeIndex].showValidate = true;
  570 + }
  571 + },
496 addColor: function(color) { 572 addColor: function(color) {
497 this.refreshTable(); 573 this.refreshTable();
498 let findColorIndex = this.table.selectedColors.findIndex((c) => { 574 let findColorIndex = this.table.selectedColors.findIndex((c) => {
@@ -511,39 +587,6 @@ export default { @@ -511,39 +587,6 @@ export default {
511 587
512 this.initDefault(); 588 this.initDefault();
513 }, 589 },
514 - addSize: function(color, sizeId) {  
515 - this.refreshTable();  
516 - let findSize = this.findSize(sizeId);  
517 -  
518 - if (!findSize) {  
519 - return;  
520 - }  
521 -  
522 - color.sizeId.push({  
523 - id: findSize.id,  
524 - name: findSize.sizeName  
525 - });  
526 -  
527 - color.sizeCode.push({  
528 - name: ''  
529 - });  
530 -  
531 - color.operator.push({  
532 - value: false  
533 - });  
534 - },  
535 - removeSize: function(color, sizeId) {  
536 - this.refreshTable();  
537 - let index = color.sizeId.findIndex((s) => {  
538 - return s.id === sizeId;  
539 - });  
540 -  
541 - if (index !== -1) {  
542 - color.sizeId.splice(index, 1);  
543 - color.sizeCode.splice(index, 1);  
544 - color.operator.splice(index, 1);  
545 - }  
546 - },  
547 addColorData: function(color) { 590 addColorData: function(color) {
548 let newColor = { 591 let newColor = {
549 goodsName: { 592 goodsName: {
@@ -551,7 +594,11 @@ export default { @@ -551,7 +594,11 @@ export default {
551 isDefault: false, 594 isDefault: false,
552 }, 595 },
553 factoryGoodsName: '', 596 factoryGoodsName: '',
554 - goodsColorImage: '', 597 + goodsColorImage: {
  598 + value: '',
  599 + showValidate: false,
  600 + validate: false
  601 + },
555 factoryCode: '', 602 factoryCode: '',
556 colorId: color.id, 603 colorId: color.id,
557 sizeId: [], 604 sizeId: [],
@@ -574,6 +621,41 @@ export default { @@ -574,6 +621,41 @@ export default {
574 621
575 this.table.data.splice(index, 1); 622 this.table.data.splice(index, 1);
576 }, 623 },
  624 + removeSize: function(color, sizeId) {
  625 + this.refreshTable();
  626 + let index = color.sizeId.findIndex((s) => {
  627 + return s.id === sizeId;
  628 + });
  629 +
  630 + if (index !== -1) {
  631 + color.sizeId.splice(index, 1);
  632 + color.sizeCode.splice(index, 1);
  633 + color.operator.splice(index, 1);
  634 + }
  635 + },
  636 + addSize: function(color, sizeId) {
  637 + this.refreshTable();
  638 + let findSize = this.findSize(sizeId);
  639 +
  640 + if (!findSize) {
  641 + return;
  642 + }
  643 +
  644 + color.sizeId.push({
  645 + id: findSize.id,
  646 + name: findSize.sizeName
  647 + });
  648 +
  649 + color.sizeCode.push({
  650 + name: '',
  651 + validate: false,
  652 + showValidate: false
  653 + });
  654 +
  655 + color.operator.push({
  656 + value: true
  657 + });
  658 + },
577 findSize: function(sizeId) { 659 findSize: function(sizeId) {
578 let index = this.sizes.findIndex((sizeObj) => { 660 let index = this.sizes.findIndex((sizeObj) => {
579 return sizeObj.id === sizeId; 661 return sizeObj.id === sizeId;
@@ -594,55 +676,119 @@ export default { @@ -594,55 +676,119 @@ export default {
594 676
595 return false; 677 return false;
596 }, 678 },
597 - submit: function() {  
598 - return this.validate().then(() => {  
599 - this.beforeSubmit();  
600 - return api.saveBaseProductInfo(this.product);  
601 - });  
602 - },  
603 - beforeSubmit: function() {  
604 - const handleColor = (color) => {  
605 - let newColor = makeColor();  
606 -  
607 - newColor.goodsName = color.goodsName.name;  
608 - newColor.isDefault = color.goodsName.isDefault ? 'Y' : 'N';  
609 -  
610 - newColor.factoryGoodsName = color.factoryGoodsName;  
611 - newColor.factoryCode = color.factoryCode;  
612 -  
613 - newColor.goodsColorImage = color.goodsColorImage;  
614 - newColor.colorId = color.colorId; 679 + uploadSuccess: function(attach, files) {
  680 + this.refreshTable();
  681 + this.table.data[attach.index].goodsColorImage.value = files[0];
615 682
616 - let goodsSizeList = []; 683 + this.table.data[attach.index].goodsColorImage.validate = true;
  684 + if (this.table.data[attach.index].goodsColorImage.value) {
  685 + this.table.data[attach.index].goodsColorImage.showValidate = false;
  686 + } else {
  687 + this.table.data[attach.index].goodsColorImage.showValidate = true;
  688 + }
  689 + },
  690 + refreshTable() {
  691 + this.table.data = this.$refs.sellerGoods.rebuildData;
  692 + },
  693 + uploadError: function(attach, err) {
  694 + },
  695 + validateOtherProps: function() {
  696 + return new Promise((resolve, reject) => {
  697 + this.$refs['product'].validate((valid) => {
  698 + if (valid) {
  699 + this.table.showValidateOtherProps = false;
  700 + resolve();
  701 + } else {
  702 + this.table.showValidateOtherProps = true;
  703 + reject();
  704 + }
  705 + })
  706 + }).catch(() => {});
  707 + },
  708 + validateTable: function() {
  709 + let _this = this;
  710 +
  711 + return new Promise(function(resolve, reject) {
  712 + let errors = [];
  713 +
  714 + _this.table.data.forEach((color, i) => {
  715 + let operators = color.operator;
  716 + let sizeCodes = color.sizeCode;
  717 +
  718 + operators.forEach((o, j) => {
  719 + if (o.value) {
  720 + if (!sizeCodes[j].name) {
  721 + sizeCodes[j].showValidate = true;
  722 + sizeCodes[j].validate = true;
  723 + errors.push({row: i, index: j, message: '不能为空'});
  724 + } else {
  725 + sizeCodes[j].showValidate = false;
  726 + }
  727 + }
  728 + });
617 729
618 - color.operator.forEach((op, i) => {  
619 - if (!op.value) {  
620 - return; 730 + if (!color.goodsColorImage.value) {
  731 + color.goodsColorImage.showValidate = true;
  732 + color.goodsColorImage.validate = true;
  733 + errors.push({row: i, message: '商品封面不能为空', field: 'goodsColorImage.name'});
  734 + } else {
  735 + color.goodsColorImage.showValidate = false;
621 } 736 }
  737 + });
622 738
623 - let goodsSize = {}; 739 + if (errors.length !== 0) {
  740 + _this.table.showValidateTable = false;
  741 + return resolve();
  742 + } else {
  743 + _this.table.showValidateTable = true;
  744 + return reject(errors);
  745 + }
624 746
625 - goodsSize.sizeId = color.sizeId[i].id;  
626 - goodsSize.factoryCode = color.sizeCode[i].name;  
627 - goodsSizeList.push(goodsSize);  
628 - }); 747 + }).catch((err) => {
  748 + });
  749 + },
  750 + validateColor: function() {
  751 + let _this = this;
629 752
630 - newColor.goodsSizeList = goodsSizeList; 753 + return new Promise((resolve, reject) => {
  754 + if (_this.table.selectedColors.length === 0) {
  755 + this.table.showValidateColor = true;
  756 + return reject({message: '颜色不能为空'})
  757 + }
631 758
632 - return newColor;  
633 - }; 759 + this.table.showValidateColor = false;
  760 + return resolve();
  761 + }).catch((err) => {
  762 + });
634 763
635 - this.refreshTable();  
636 - this.product.sellerGoodsInfoStr = JSON.stringify(this.table.data.map(handleColor));  
637 }, 764 },
638 - uploadSuccess: function(attach, files) {  
639 - this.refreshTable();  
640 - this.table.data[attach.index].goodsColorImage = files[0];  
641 - },  
642 - refreshTable() {  
643 - this.table.data = this.$refs.sellerGoods.rebuildData; 765 + validateSize: function() {
  766 + return new Promise((resolve, reject) => {
  767 + if (this.table.selectedSizes.length === 0) {
  768 + this.table.showValidateSize = true;
  769 + return reject({message: '尺码不能为空'});
  770 + }
  771 +
  772 + this.table.showValidateSize = false;
  773 + return resolve();
  774 + }).catch(() => {
  775 + });
644 }, 776 },
645 - uploadError: function(attach, err) { 777 + validate: function() {
  778 + return this.validateOtherProps()
  779 + .then(this.validateColor)
  780 + .then(this.validateSize)
  781 + .then(this.validateTable)
  782 + .then(() => {
  783 + if (!this.showValidateColor
  784 + && !this.showValidateSize
  785 + && !this.showValidateOtherProp
  786 + && !this.showValidateTable) {
  787 + return Promise.resolve();
  788 + } else {
  789 + return Promise.reject();
  790 + }
  791 + });
646 } 792 }
647 }, 793 },
648 computed: { 794 computed: {
@@ -670,7 +816,20 @@ export default { @@ -670,7 +816,20 @@ export default {
670 this.removeSize(color, removeSize[0]); 816 this.removeSize(color, removeSize[0]);
671 } 817 }
672 }); 818 });
  819 +
  820 + if (newVal.length === 0) {
  821 + this.table.showValidateSize = true;
  822 + } else {
  823 + this.table.showValidateSize = false;
  824 + }
673 }, 825 },
  826 + 'table.selectedColors': function(newVal) {
  827 + if (newVal.length === 0) {
  828 + this.table.showValidateColor = true;
  829 + } else {
  830 + this.table.showValidateColor = false;
  831 + }
  832 + }
674 }, 833 },
675 components: { 834 components: {
676 'product-age': Age, 835 'product-age': Age,
@@ -735,6 +894,17 @@ export default { @@ -735,6 +894,17 @@ export default {
735 894
736 .size-code { 895 .size-code {
737 @include row-span; 896 @include row-span;
  897 +
  898 + &-error {
  899 + border: 1px solid #f30;
  900 + }
  901 +
  902 + &-tip {
  903 + position: absolute;
  904 + line-height: 1;
  905 + padding-top: 6px;
  906 + color: #f30;
  907 + }
738 } 908 }
739 909
740 .size-id { 910 .size-id {
@@ -747,4 +917,45 @@ export default { @@ -747,4 +917,45 @@ export default {
747 text-align: center; 917 text-align: center;
748 } 918 }
749 919
  920 +.product-table-error {
  921 + border: 1px solid #f30;
  922 +}
  923 +
  924 +.product-table-tip {
  925 + position: absolute;
  926 + line-height: 1;
  927 + padding-top: 6px;
  928 + color: #f30;
  929 + left: 70px;
  930 +}
  931 +
  932 +.upload-item {
  933 + display: inline-block;
  934 + height: 200px;
  935 + width: 130px;
  936 + text-align: center;
  937 + margin: 30px 0;
  938 +}
  939 +
  940 +.upload-item-error {
  941 + border: 1px solid #f30;
  942 + position: relative;
  943 +}
  944 +
  945 +.upload-item-tip {
  946 + position: absolute;
  947 + line-height: 1;
  948 + padding-top: 6px;
  949 + color: #f30;
  950 + top: 100%;
  951 +}
  952 +
  953 +.upload-item-img {
  954 + display: inline-block;
  955 + height: 126px;
  956 + width: 124px;
  957 + border: 2px solid #e8e8e8;
  958 + box-sizing: border-box;
  959 +}
  960 +
750 </style> 961 </style>