Authored by 陈峰

重构商品编辑完成

<template>
<Checkbox-group :value="handleValue" @on-change="updateValue" >
<Checkbox-group :value="values" @on-change="updateValue" >
<Checkbox v-for="age in ageList" :key="age.id" :label="age.id" :disabled="disable">
<span>{{age.label}}</span>
</Checkbox>
... ... @@ -34,21 +34,20 @@ export default {
}, {
id: '5',
label: '幼童'
}],
handleValue: this.value.split('|')
}]
};
},
computed: {
values() {
return this.value.split('|');
}
},
methods: {
updateValue(newValue) {
let nValue = newValue.join('|');
this.$emit('input', nValue);
}
},
watch: {
value(newValue) {
this.handleValue = newValue.split('|');
}
}
};
... ...
... ... @@ -38,18 +38,21 @@ export default {
methods: {
render() {
api.getColor().then((result) => {
this.colors = result.data.map(color => {
let selectColor = _.find(this.selectColors, c => c.id === color.id);
this.initColors(result.data);
});
},
initColors(colors) {
this.colors = colors.map(color => {
let selectColor = _.find(this.selectColors, c => c.id === color.id);
if (selectColor) {
color.selected = true;
color.disabled = selectColor.disabled;
} else {
color.selected = false;
color.disabled = false;
}
return color;
});
if (selectColor) {
color.selected = true;
color.disabled = selectColor.disabled;
} else {
color.selected = false;
color.disabled = false;
}
return color;
});
},
selectColor(color) {
... ... @@ -64,7 +67,7 @@ export default {
},
watch: {
selectColors() {
this.render();
this.initColors(this.colors);
}
}
};
... ... @@ -89,7 +92,7 @@ export default {
color: #000;
}
&.disabled {
opacity: 0.5;
opacity: 0.2;
}
.color-border {
vertical-align: middle;
... ...
<template>
<Checkbox-group :value="values" @on-change="selectSize">
<Checkbox v-for="size in sizes" key="size" :label="size.id" :disabled="size.disabled">
<span>{{size.sizeName}}</span>
</Checkbox>
</Checkbox-group>
</template>
<script>
import _ from 'lodash';
import api from 'product-create/api';
export default {
name: 'CheckboxSize',
props: {
sortId: {
type: Number
},
selectSizes: {
type: Array,
default() {
return [];
}
}
},
computed: {
values() {
return _.map(this.selectSizes, size => {
return size.id;
});
}
},
created() {
this.render();
},
data() {
return {
sizes: []
};
},
methods: {
render() {
api.getSize(this.sortId).then((result) => {
this.initSizes(result.data);
});
},
initSizes(sizes) {
this.sizes = sizes.map(size => {
let selectColor = _.find(this.selectSizes, c => c.id === size.id);
if (selectColor) {
size.disabled = selectColor.disabled;
} else {
size.disabled = false;
}
return size;
});
},
selectSize(values) {
let selectSize = this.sizes.filter(size => _.some(values, val => val === size.id));
this.$emit('on-change', selectSize);
}
},
watch: {
selectSizes() {
this.initSizes(this.sizes);
}
}
};
</script>
... ...
import CheckboxAge from './checkbox-age';
import CheckboxColor from './checkbox-color';
import CheckboxSize from './checkbox-size';
export {
CheckboxAge,
CheckboxColor
CheckboxColor,
CheckboxSize
};
... ...
<template>
<div class="good-images">
<Row v-for="(good, goodIndex) in productGoods"
:key="goodIndex">
<Col span="4">
<div class="color-item-title">
<span>{{good.goodsName}}({{good.factoryGoodsName}})</span>
</div>
</Col>
<Col span="4" v-for="(image, imageIndex) in good.goodsImage" :key="imageIndex">
<div class="upload-item">
<div class="upload-item-img">
<img v-if="imageIndex === 0 && image.imageUrl" :src="image.imageUrl"
alt=""
width="120px"
height="122px">
<drag-file-upload v-if="imageIndex > 0"
:default-file="image.imageUrl"
:id="{goodIndex, imageIndex}"
@on-success="uploadImageSuccess"
@on-remove="uploadImageRemove">
</drag-file-upload>
</div>
<div class="upload-item-title">
{{imagesTitles[imageIndex]}}
</div>
</div>
</Col>
</Row>
</div>
</template>
<script>
export default {
props: {
value: {
type: Array,
default() {
return [];
}
}
},
data() {
return {
productGoods: this.value,
imagesTitles: ['商品正面图*', '商品反面图', '模特图', '男生频道封面图', '女生频道封面图']
};
},
methods: {
uploadImageSuccess(data, file) {
this.productGoods[data.goodIndex].goodsImage[data.imageIndex].imageUrl = file.url;
this.$emit('input', this.productGoods);
},
uploadImageRemove(data) {
this.productGoods[data.goodIndex].goodsImage[data.imageIndex].imageUrl = '';
this.$emit('input', this.productGoods);
}
},
watch: {
value: {
handler(val) {
this.productGoods = val;
},
deep: true
}
}
};
</script>
<style>
.upload-item {
display: inline-block;
height: 180px;
width: 130px;
text-align: center;
margin: 10px 0;
}
.color-item-title {
text-align: center;
margin: 50px 0;
}
.upload-item {
display: inline-block;
height: 200px;
width: 130px;
text-align: center;
margin: 30px 0;
}
.upload-item-error {
border: 1px solid #f30;
position: relative;
}
.upload-item-tip {
position: absolute;
line-height: 1;
padding-top: 6px;
color: #f30;
top: 100%;
}
.upload-item-img {
display: inline-block;
height: 126px;
width: 124px;
border: 2px solid #e8e8e8;
box-sizing: border-box;
}
</style>
... ...
import GoodImage from './good-image';
import Material from './material';
import MuliSelect from './muli-select';
import TableGood from './table-good';
export {
GoodImage,
Material,
MuliSelect,
TableGood
};
... ...
... ... @@ -8,6 +8,7 @@
<script>
export default {
name: 'Material',
props: {
value: {
type: Array,
... ...
... ... @@ -23,6 +23,7 @@
<script>
export default {
name: 'MuliSelect',
props: ['value', 'attr'],
data() {
let _this = this;
... ...
... ... @@ -5,8 +5,17 @@
<script>
export default {
name: 'TableGood',
props: {
value: {
type: Array,
default() {
return [];
}
}
},
data() {
return {
self: this,
table: {
columns: [
{
... ... @@ -27,7 +36,8 @@ export default {
return `<div v-if="isExist(${index})">
<i-input
v-model="row.factoryGoodsName"
:placeholder="row.goodsName.name">
:placeholder="row.goodsName.name"
@on-blur="changeFactoryGoodsName(row,${index})">
</i-input>
</div>`;
}
... ... @@ -124,9 +134,122 @@ export default {
}
}
],
data: []
data: this.value
}
};
},
methods: {
clickDefault(index) {
this.refreshTable();
let color = this.table.data[index];
color.goodsName.isDefault = true;
this.table.data.forEach((c) => {
if (c.colorId !== color.colorId) {
c.goodsName.isDefault = false;
}
});
},
changeFactoryGoodsName(row, index) {
this.$emit('on-factory-name', index, row.factoryGoodsName);
},
uploadSuccess(attach, files) {
this.refreshTable();
this.table.data[attach.index].goodsColorImage.value = files[0];
this.onUploadGoodImage(attach, files[0]);
this.table.data[attach.index].goodsColorImage.validate = true;
if (this.table.data[attach.index].goodsColorImage.value) {
this.table.data[attach.index].goodsColorImage.showValidate = false;
} else {
this.table.data[attach.index].goodsColorImage.showValidate = true;
}
},
onUploadGoodImage(attach, file) {
this.$emit('on-upload', attach, file);
},
uploadError() {
},
clickOperator(row, itemIndex) {
this.refreshTable();
row.operator[itemIndex].value = row.operator[itemIndex].value ? false : true;
if (row.operator[itemIndex].value) {
row.sizeCode[itemIndex].name = '';
row.sizeCode[itemIndex].validate = true;
} else {
row.sizeCode[itemIndex].name = '';
row.sizeCode[itemIndex].validate = false;
}
},
refreshTable() {
this.table.data = this.$refs.sellerGoods.rebuildData;
},
isExist(index) {
let row = this.table.data[index];
if (row) {
return true;
}
return false;
},
syncData() {
this.$emit('input', this.$refs.sellerGoods.rebuildData);
}
},
watch: {
value(newVal) {
this.table.data = newVal;
}
}
};
</script>
<style lang="scss">
@mixin row-span {
min-height: 30px;
.row-span {
min-height: 30px;
border-bottom: 1px solid #e3e8ee;
padding-top: 20px;
padding-bottom: 20px;
margin-left: -18px;
margin-right: -18px;
padding-left: 18px;
padding-right: 18px;
&:last-child {
border-bottom: none;
}
}
}
.size-code {
@include row-span;
&-error {
border: 1px solid #f30;
}
&-tip {
position: absolute;
line-height: 1;
padding-top: 6px;
color: #f30;
}
}
.size-id {
@include row-span;
text-align: center;
}
.size-operator {
@include row-span;
text-align: center;
}
</style>
... ...
... ... @@ -44,20 +44,15 @@
<span class="create-group-sub-title">(颜色名称只能填写中文,最多5个汉字。款型编码和条码只能填写英文和数字,不区分大小写)</span>
</div>
<Form-item label="颜色">
<CheckboxColor :select-colors="table.defaultSelectedColors" @on-change="clickColor"></CheckboxColor>
<CheckboxColor :select-colors="table.defaultSelectedColors" @on-change="selectColor"></CheckboxColor>
</Form-item>
<Form-item label="尺寸">
<Checkbox-group v-model='table.selectedSizes'>
<Checkbox v-for="size in sizes"
:key="size"
:label="size.id"
:disabled="size.disabled">
<span>{{size.sizeName}}</span>
</Checkbox>
</Checkbox-group>
<CheckboxSize :sort-id="this.product.smallSortId" :select-sizes="table.defaultSelectedSizes" @on-change="selectSize"></CheckboxSize>
</Form-item>
<Form-item>
<Table ref="sellerGoods" :context="self" :data="table.data" :columns="table.columns" stripe border></Table>
<TableGood ref="tableGood" v-model="table.data"
@on-upload="uploadGoodSzieSuccess"
@on-factory-name="onChangeFactoryCode"></TableGood>
</Form-item>
<div class="create-item-title">商品价格</div>
<Form-item label="吊牌价">
... ... @@ -74,98 +69,7 @@
<div class="create-item-title">商品颜色主图
<span class="create-group-sub-title">(商品正面图默认为用户选择商品颜色和展示使用。用户从不同频道查看商品,优先展示频道封面图)</span>
</div>
<Row v-for="good,goodIndex in product.goods"
:key="good">
<Col span="4">
<div class="color-item-title">
<span>{{good.goodsName}}({{good.factoryGoodsName}})</span>
</div>
</Col>
<Col span="4">
<div class="upload-item">
<div class="upload-item-img">
<img :src="good.goodsImage[0].imageUrl"
alt=""
width="120px"
height="122px"
v-if="good.goodsImage[0].imageUrl">
</div>
<div class="upload-item-title">
商品正面图*
</div>
</div>
</Col>
<Col span="4">
<div class="upload-item">
<div class="upload-item-img">
<drag-file-upload :default-file="good.goodsImage[1].imageUrl"
:id="{goodIndex, imageIndex: 1}"
@on-success="uploadImageSuccess"
@on-remove="uploadImageRemove">
</drag-file-upload>
</div>
<div class="upload-item-title">
商品反面图
</div>
</div>
</Col>
<Col span="4">
<div class="upload-item">
<div class="upload-item-img">
<drag-file-upload :default-file="good.goodsImage[2].imageUrl"
:id="{goodIndex, imageIndex: 2}"
@on-success="uploadImageSuccess"
@on-remove="uploadImageRemove">
</drag-file-upload>
</div>
<div class="upload-item-title">
模特图
</div>
</div>
</Col>
<Col span="4">
<div class="upload-item">
<div class="upload-item-img">
<drag-file-upload :default-file="good.goodsImage[3].imageUrl"
:id="{goodIndex, imageIndex: 3}"
@on-success="uploadImageSuccess"
@on-remove="uploadImageRemove">
</drag-file-upload>
</div>
<div class="upload-item-title">
男生频道封面图
</div>
</div>
</Col>
<Col span="4">
<div class="upload-item">
<div class="upload-item-img">
<drag-file-upload :default-file="good.goodsImage[4].imageUrl"
:id="{goodIndex, imageIndex: 4}"
@on-success="uploadImageSuccess"
@on-remove="uploadImageRemove">
</drag-file-upload>
</div>
<div class="upload-item-title">
女生频道封面图
</div>
</div>
</Col>
</Row>
<GoodImage v-model="product.goods"></GoodImage>
<div class="create-item-title">商品描述(详情页内容)</div>
<editor :content="product.productIntro"
@change="updateProductDesc"></editor>
... ... @@ -173,19 +77,19 @@
<Form-item :label="attr.attributeName"
v-for="attr in render.productStandardRelationStr"
:key="attr">
<multi-select v-model="attr.model" :attr="attr"></multi-select>
<MuliSelect v-model="attr.model" :attr="attr"></MuliSelect>
</Form-item>
<Form-item :label="attr.attributeName"
v-for="attr in render.attributeProValuesOne"
:key="attr">
<multi-select v-model="attr.model" :attr="attr"></multi-select>
<MuliSelect v-model="attr.model" :attr="attr"></MuliSelect>
</Form-item>
<Form-item :label="attr.attributeName" v-for="attr in render.attributeProValuesTwo" :key="attr">
<multi-select v-model="attr.model" :attr="attr"></multi-select>
<MuliSelect v-model="attr.model" :attr="attr"></MuliSelect>
</Form-item>
<Form-item v-if="render.productMaterial" :label="render.productMaterial.attributeName">
<shop-material v-model="product.materialList" :idNameList="render.productMaterial.idNameList">
</shop-material>
<Material v-model="product.materialList" :idNameList="render.productMaterial.idNameList">
</Material>
</Form-item>
<Form-item>
<Button type="primary" @click="submit" size="large">保存</Button>
... ... @@ -194,10 +98,9 @@
</Form>
</template>
<script>
import ShopMaterial from './components/material';
import MuliSelect from './components/muli-select';
import { CheckboxAge, CheckboxColor } from 'components/checkbox';
import _ from 'lodash';
import {Material, MuliSelect, TableGood, GoodImage} from './components';
import { CheckboxAge, CheckboxColor, CheckboxSize } from 'components/checkbox';
import { SelectSeason } from 'components/select';
import { RadioSeason, RadioGender } from 'components/radio';
... ... @@ -205,138 +108,14 @@ import service from 'product-create/service';
import api from 'product-create/api';
import serial from 'product-create/serialize';
const _ = require('lodash');
const Fn = require('lodash/fp');
export default {
data() {
return {
show: true,
product: null,
self: this,
colors: [],
sizes: [],
table: {
columns: [
{
title: '色系名称',
key: 'goodsName',
render(row, col, index) {
return `<div v-if="isExist(${index})">
<p>{{table.data[${index}].goodsName.name}}</p>
<Radio :value="table.data[${index}].goodsName.isDefault"
@on-change="clickDefault(${index})">主推</Radio>
</div>`;
}
},
{
title: '颜色展示名称',
key: 'factoryGoodsName',
render(row, col, index) {
return `<div v-if="isExist(${index})">
<i-input
v-model="row.factoryGoodsName"
:placeholder="row.goodsName.name">
</i-input>
</div>`;
}
},
{
title: '色卡图片*',
key: 'goodsColorImage',
width: 170,
render(row, col, index) {
return `<div
:class="{'upload-item': true ,
'upload-item-error':
row.goodsColorImage.showValidate && row.goodsColorImage.validate}"
>
<div class="upload-item-img">
<img v-if="row.goodsColorImage.value"
:src="row.goodsColorImage.value" alt="" width="120px" height="122px">
</div>
<div>
<file-upload :id="{index: ${index}}"
@on-success="uploadSuccess"
@on-error="uploadError"></file-upload>
</div>
<div v-if="row.goodsColorImage.showValidate && row.goodsColorImage.validate"
class="upload-item-tip">
必须上传图片
</div>
</div>`;
}
},
{
title: '款型编码',
key: 'factoryCode',
render(row, col, index) {
return `<div v-if="isExist(${index})">
<i-input
v-model="row.factoryCode"
placeholder="请输入..."
>
</i-input>
</div>`;
}
},
{
title: '尺码*',
key: 'sizeId',
width: 80,
render() {
return `<div class="size-id">
<div v-for="size in row.sizeId" class="row-span">
{{size.name}}
</div>
</div>`;
}
},
{
title: '商品条码*',
key: 'sizeCode',
render() {
return `<div class='size-code'>
<div v-for="size,i in row.sizeCode" class="row-span">
<div style="position: relative">
<div :class="{'size-code-error': size.validate && !size.name}">
<i-input
v-model="size.name"
:disabled="!row.operator[i].value"
placeholder="请输入..."
/>
</div>
<div class="size-code-tip" v-if="size.validate && !size.name">
不能为空
</div>
</div>
</div>
</div>`;
}
},
{
title: '操作',
key: 'operator',
width: 100,
render(row, col, index) {
return `<template v-if="isExist(${index})">
<div class="size-operator" v-if="table.data[${index}]">
<div v-for="op,i in table.data[${index}].operator" class="row-span">
<i-button v-if="table.data[${index}].operator[i].value"
type="warning"
@click="clickOperator(row, i)">禁用</i-button>
<i-button v-else type="primary"
@click="clickOperator(row, i)">启用</i-button>
</div>
</div>
</template>`;
}
}
],
data: [],
selectedSizes: [],
defaultSelectedSizes: [],
selectedColors: [],
defaultSelectedColors: [],
},
desc: '',
... ... @@ -360,92 +139,113 @@ export default {
created() {
service.getProduct(this.$route.params.id).then((result) => {
_.update(result, 'goodsSeason', (s) => `${s}`);
if (!_.has(result, 'materialList')) {
result.materialList = [];
}
this.product = result;
}).then(() => {
return Promise.all([
this.getSize(),
this.getAllAttr(this.product.smallSortId, this.product.maxSortId)
]);
return this.getAllAttr(this.product.smallSortId, this.product.maxSortId);
}).then(() => {
this.init();
this.show = false;
});
},
methods: {
clickOperator(row, itemIndex) {
this.refreshTable();
row.operator[itemIndex].value = row.operator[itemIndex].value ? false : true;
if (row.operator[itemIndex].value) {
row.sizeCode[itemIndex].name = '';
row.sizeCode[itemIndex].validate = true;
} else {
row.sizeCode[itemIndex].name = '';
row.sizeCode[itemIndex].validate = false;
}
},
clickColor(selectColors, color) {
this.addColor(color);
selectColor(selectColors) {
this.table.defaultSelectedColors = selectColors;
this.refreshGoods();
},
changeSizeCode(row, rowIndex, sizeIndex) {
this.table.data[rowIndex].sizeCode[sizeIndex].name = row.sizeCode[sizeIndex].name;
selectSize(selcetSize) {
this.table.defaultSelectedSizes = selcetSize;
this.refreshGoods();
},
changeFactoryGoodsName(row, index) {
this.table.data[index].factoryGoodsName = row.factoryGoodsName;
this.onChangeFactoryCode(index, row.factoryGoodsName);
},
changeFactoryCode(row, index) {
this.table.data[index].factoryCode = row.factoryCode;
},
uploadSuccess(attach, files) {
this.refreshTable();
this.table.data[attach.index].goodsColorImage.value = files[0];
this.onUploadGoodImage(attach, files[0]);
refreshGoods() {
this.$refs.tableGood.syncData();
this.table.data[attach.index].goodsColorImage.validate = true;
if (this.table.data[attach.index].goodsColorImage.value) {
this.table.data[attach.index].goodsColorImage.showValidate = false;
} else {
this.table.data[attach.index].goodsColorImage.showValidate = true;
}
},
uploadError() {
},
uploadImageSuccess(data, file) {
let colorIndex = data.goodIndex;
let imageIndex = data.imageIndex;
let rmCidIndex = _.map(this.table.data, (goodColor, index) => {
if (_.some(this.table.defaultSelectedColors, color => color.id === goodColor.colorId)) {
return -1;
}
return index;
}).filter(inx => inx >= 0);
_.remove(this.table.data, (good, index) => _.some(rmCidIndex, inx => inx === index));
_.remove(this.product.goods, (good, index) => _.some(rmCidIndex, inx => inx === index));
_.each(this.table.defaultSelectedColors, color => {
let colorGood = _.find(this.table.data, good => good.colorId === color.id);
if (colorGood) {
let rmSidIndexs = _.map(colorGood.sizeId, (goodSize, index) => {
if (_.some(this.table.defaultSelectedSizes, size => size.id === goodSize.id)) {
return -1;
}
return index;
}).filter(inx => inx >= 0);
this.product.goods[colorIndex].goodsImage[imageIndex].imageUrl = file.url;
},
uploadImageRemove(data) {
let colorIndex = data.goodIndex;
let imageIndex = data.imageIndex;
_.remove(colorGood.sizeId, (sid, index) => _.some(rmSidIndexs, inx => inx === index));
_.remove(colorGood.sizeCode, (code, index) => _.some(rmSidIndexs, inx => inx === index));
_.remove(colorGood.operator, (op, index) => _.some(rmSidIndexs, inx => inx === index));
this.product.goods[colorIndex].goodsImage[imageIndex].imageUrl = '';
},
clickDefault(index) {
this.refreshTable();
let color = this.table.data[index];
let addSizeList = this.table.defaultSelectedSizes
.filter(size => !_.some(colorGood.sizeId, goodSize => size.id === goodSize.id));
color.goodsName.isDefault = true;
this.table.data.forEach((c) => {
if (c.colorId !== color.colorId) {
c.goodsName.isDefault = false;
_.each(addSizeList, size => this.addSizeItem(colorGood, size));
} else {
let newGood = {
goodsName: {
name: color.colorName,
isDefault: false,
},
factoryGoodsName: '',
goodsColorImage: {
value: '',
showValidate: false,
validate: false
},
factoryCode: '',
colorId: color.id,
sizeId: [],
sizeCode: [],
operator: []
};
_.each(this.table.defaultSelectedSizes, size => this.addSizeItem(newGood, size));
this.table.data.push(newGood);
this.product.goods.push(service.handleGoods({
goodsName: color.colorName,
productSkn: this.product.productSkn,
factoryGoodsName: ''
}));
}
});
},
getSize() {
return api.getSize(this.product.smallSortId).then((result) => {
if (result.code === 200) {
this.sizes = result.data;
}
addSizeItem(colorGood, size) {
colorGood.sizeId.push({
id: size.id,
name: size.sizeName
});
colorGood.sizeCode.push({
name: '',
showValidate: false,
validate: false
});
colorGood.operator.push({
value: true
});
},
onChangeFactoryCode(index, code) {
let goods = this.product.goods[index];
goods.factoryGoodsName = code;
// 同步图片中的factoryGoodsName 的值
goods.goodsImage.forEach((image) => {
image.factoryGoodsName = code || goods.goodsName;
});
},
uploadGoodSzieSuccess(attach, file) {
this.product.goods[attach.index].goodsImage[0].imageUrl = file;
},
getAllAttr(smallSortId, maxSortId) {
return api.getAllAttr(smallSortId, maxSortId).then((result) => {
this.render.productStandardRelationStr = service.addNoneItem(result[0] || []);
... ... @@ -487,28 +287,28 @@ export default {
this.initDefaultSelectedSize();
this.initTableData();
this.initImage();
this.initAttr();
},
initDefaultSelectedColor() {
this.table.defaultSelectedColors = _.map(this.product.sellerGoodList, good => {
return {
id: good.colorId,
selected: false,
disable: true
disabled: true
};
});
},
initDefaultSelectedSize() {
let goodsSizeList = Fn.props('goodsSizeList');
let uniqSize = Fn.uniqBy((s) => s.sizeId);
let allHandleItem = _.flow(Fn.map(goodsSizeList), _.flattenDeep, uniqSize)(this.product.sellerGoodList);
let selectSize = Fn.filter(s => _.find(allHandleItem, (selectedItem) => selectedItem.sizeId === s.id));
this.table.selectedSizes = selectSize(this.sizes).map((s) => {
s.disabled = true;
return s.id;
});
let goodFirst = _.first(this.product.sellerGoodList);
if (goodFirst) {
this.table.defaultSelectedSizes = _.map(goodFirst.goodsSizeList, size => {
return {
id: size.sizeId,
sizeName: size.sizeName,
disabled: true
};
});
}
},
initTableData() {
let goodsList = this.product.sellerGoodList;
... ... @@ -522,8 +322,6 @@ export default {
initImage() {
this.product.goods = this.product.sellerGoodsImagesList.map(service.handleGoodsImage);
},
initAttr() {
},
handleItem(goods, goodsImage) {
let newGoods = {};
... ... @@ -545,261 +343,38 @@ export default {
newGoods.sizeId = [];
newGoods.sizeCode = [];
newGoods.operator = [];
this.table.selectedSizes.forEach((s) => {
let sizeObj = _.find(this.sizes, { id: s });
if (!sizeObj) {
return;
}
this.table.defaultSelectedSizes.forEach(size => {
newGoods.sizeId.push({
id: sizeObj.id,
name: sizeObj.sizeName,
id: size.id,
name: size.sizeName,
productSku: '',
});
newGoods.sizeCode.push({
name: '',
validate: false,
showValidate: false
});
newGoods.operator.push({
value: false
});
});
goods.goodsSizeList.forEach((s) => {
let index = _.findIndex(newGoods.sizeId, { id: s.sizeId });
if (index === -1) {
return;
}
newGoods.sizeId[index].productSku = s.productSku;
if (s.factoryCode) {
newGoods.sizeCode[index].name = s.factoryCode;
newGoods.operator[index].value = true;
}
});
return newGoods;
},
updateProductDesc(c) {
this.product.productIntro = c;
},
beforeSave() {
let newProduct = {};
this.refreshTable();
newProduct.productSkn = this.product.productSkn;
newProduct.id = this.product.id;
newProduct.productName = this.product.productName;
newProduct.gender = this.product.gender;
newProduct.factoryCode = this.product.factoryCode;
newProduct.goodsYears = this.product.goodsYears;
newProduct.phrase = this.product.phrase;
newProduct.goodsSeason = this.product.goodsSeason;
newProduct.ageLevel = this.product.ageLevel;
newProduct.seasons = this.product.seasons;
newProduct.expectSaleTimeStr = this.product.expectSaleTimeStr;
newProduct.sellerGoodsInfoStr = JSON.stringify(this.handleColor());
newProduct.goodsImagesReqStr = JSON.stringify(this.handleImage());
newProduct.productStandardRelationStr = JSON.stringify(this.handleRelation());
newProduct.attributeProValuesOne = JSON.stringify(this.handleOne());
newProduct.attributeProValuesTwo = JSON.stringify(this.handleTwo());
newProduct.productMaterial = this.product.materialList.map(s => s.id).join(',');
newProduct.productIntro = this.product.productIntro;
return newProduct;
},
save() {
let newProduct = this.beforeSave();
this.$Loading.start();
console.log(JSON.stringify(newProduct));
return;
// return api.updateProductAllInfo(newProduct).then((result) => {
// this.$Loading.finish();
// if (result.code === 200) {
// this.$Notice.success({
// title: '修改成功',
// desc: '该商品保存成功!'
// });
// this.$router.push({ name: 'product.offsale' });
// } else {
// this.$Notice.error({
// title: '保存错误',
// desc: result.message
// });
// }
// });
},
submit() {
this.validate()
.then(([r1, r2]) => {
if (r1 & r2) {
return Promise.resolve();
} else {
this.$Message.error('验证未通过');
return Promise.reject();
}
})
.then(this.save).catch(() => this.$Loading.error());
},
isExist(index) {
let row = this.table.data[index];
if (row) {
return true;
}
return false;
},
addColor(color) {
this.refreshTable();
if (color.disabled) {
return;
}
let findColorIndex = this.table.selectedColors.findIndex((c) => {
return c.id === color.id;
});
if (findColorIndex !== -1) {
this.removeColorData(color);
this.table.selectedColors.splice(findColorIndex, 1);
color.selected = false;
} else {
this.addColorData(color);
this.table.selectedColors.push(color);
color.selected = true;
}
},
addColorData(color) {
let newColor = {
goodsName: {
name: color.colorName,
isDefault: false,
},
factoryGoodsName: '',
goodsColorImage: {
value: '',
showValidate: false,
validate: false
},
factoryCode: '',
colorId: color.id,
sizeId: [],
sizeCode: [],
operator: []
};
if (this.table.selectedSizes.length > 0) {
this.table.selectedSizes.forEach((sizeId) => {
this.addSize(newColor, sizeId);
});
}
this.table.data.push(newColor);
this.onAddColor({ goodsName: color.colorName, productSkn: this.product.productSkn });
},
removeColorData(color) {
let index = this.table.data.findIndex((d) => {
return d.colorId === color.id;
});
this.table.data.splice(index, 1);
this.onRemoveColor(index);
},
addSize(color, sizeId) {
let findSize = this.findSize(sizeId);
if (!findSize) {
return;
}
color.sizeId.push({
id: findSize.id,
name: findSize.sizeName
});
color.sizeCode.push({
name: '',
showValidate: false,
validate: false
});
color.operator.push({
value: true
});
},
findSize(sizeId) {
let index = this.sizes.findIndex((sizeObj) => {
return sizeObj.id === sizeId;
});
if (index !== -1) {
return this.sizes[index];
}
return null;
},
removeSize(color, sizeId) {
let index = color.sizeId.findIndex((s) => {
return s.id === sizeId;
});
if (index !== -1) {
color.sizeId.splice(index, 1);
color.sizeCode.splice(index, 1);
color.operator.splice(index, 1);
}
},
isInColorSize(s) {
let sizeId = (this.table.data[0] || {}).sizeId || [];
let id = sizeId.map(si => si.id);
return _.includes(id, s);
},
onAddColor(newGoods) {
this.product.goods.push(service.handleGoods(newGoods));
},
onRemoveColor(index) {
this.product.goods.splice(index, 1);
},
onUploadGoodImage(attach, file) {
let index = attach.index;
// 注意这里vue 没有办法监听到,手动添加监听
this.$set(this.product, `goods[${index}].goodsImage[0].imageUrl`, file);
this.product.goods[index].goodsImage[0].imageUrl = file;
},
onChangeFactoryCode(index, code) {
// 注意这里vue 没有办法监听到,手动添加监听
this.$set(this.product, `goods[${index}].factoryGoodsName`, code);
let goods = this.product.goods[index];
goods.factoryGoodsName = code;
// 同步图片中的factoryGoodsName 的值
goods.goodsImage.forEach((image) => {
image.factoryGoodsName = code || goods.goodsName;
});
},
validate() {
return Promise.all([this.validateProduct(), this.validateTable()]);
},
... ... @@ -815,7 +390,7 @@ export default {
});
},
validateTable() {
this.refreshTable();
this.$refs.tableGood.syncData();
let errors = [];
this.table.data.forEach((color) => {
... ... @@ -846,36 +421,89 @@ export default {
return Promise.resolve(false);
}
},
refreshTable() {
this.table.data = this.$refs.sellerGoods.rebuildData;
},
handleColor() {
return this.table.data.map(this._handleColor);
beforeSave() {
let newProduct = {};
this.$refs.tableGood.syncData();
newProduct.productSkn = this.product.productSkn;
newProduct.id = this.product.id;
newProduct.productName = this.product.productName;
newProduct.gender = this.product.gender;
newProduct.factoryCode = this.product.factoryCode;
newProduct.goodsYears = this.product.goodsYears;
newProduct.phrase = this.product.phrase;
newProduct.goodsSeason = this.product.goodsSeason;
newProduct.ageLevel = this.product.ageLevel;
newProduct.seasons = this.product.seasons;
newProduct.expectSaleTimeStr = this.product.expectSaleTimeStr;
newProduct.sellerGoodsInfoStr =
JSON.stringify(this.handleColor());
newProduct.goodsImagesReqStr =
JSON.stringify(service.handleEditColorImage(this.product));
newProduct.productStandardRelationStr =
JSON.stringify(serial.handleRelation(this.render.productStandardRelationStr));
newProduct.attributeProValuesOne =
JSON.stringify(serial.handleOne(this.product.productSkn, this.render.attributeProValuesOne));
newProduct.attributeProValuesTwo =
JSON.stringify(serial.handleTwo(this.product.productSkn, this.render.attributeProValuesTwo));
newProduct.productMaterial = this.product.materialList.map(s => s.id).join(',');
newProduct.productIntro = this.product.productIntro;
return newProduct;
},
_handleColor(tableColor) {
let newColor = {
factoryCode: '',
factoryGoodsName: '',
isDefault: '',
goodsColorImage: '',
productSkc: '',
id: '',
goodsName: '',
colorId: '',
goodsSizeList: []
};
save() {
let newProduct = this.beforeSave();
this.$Loading.start();
newColor.factoryCode = tableColor.factoryCode;
newColor.factoryGoodsName = tableColor.factoryGoodsName || tableColor.goodsName.name;
newColor.isDefault = tableColor.goodsName.isDefault ? 'Y' : 'N';
newColor.goodsColorImage = tableColor.goodsColorImage.value;
newColor.productSkc = tableColor.productSkc;
newColor.id = tableColor.id;
newColor.goodsName = tableColor.goodsName.name;
newColor.colorId = tableColor.colorId;
newColor.goodsSizeList = this.handleSize(tableColor);
return api.updateProductAllInfo(newProduct).then((result) => {
this.$Loading.finish();
if (result.code === 200) {
this.$Notice.success({
title: '修改成功',
desc: '该商品保存成功!'
});
this.$router.push({ name: 'product.offsale' });
} else {
this.$Notice.error({
title: '保存错误',
desc: result.message
});
return newColor;
}
});
},
submit() {
this.validate()
.then(([r1, r2]) => {
if (r1 & r2) {
return Promise.resolve();
} else {
this.$Message.error('验证未通过');
return Promise.reject();
}
})
.then(this.save).catch(() => this.$Loading.error());
},
handleColor() {
return this.table.data.map(tableColor => {
return {
factoryCode: tableColor.factoryCode,
factoryGoodsName: tableColor.factoryGoodsName || tableColor.goodsName.name,
isDefault: tableColor.goodsName.isDefault ? 'Y' : 'N',
goodsColorImage: tableColor.goodsColorImage.value,
productSkc: tableColor.productSkc,
id: tableColor.id,
goodsName: tableColor.goodsName.name,
colorId: tableColor.colorId,
goodsSizeList: this.handleSize(tableColor)
};
});
},
handleSize(color) {
return color.sizeId.reduce((total, cur, i) => {
... ... @@ -889,51 +517,19 @@ export default {
return total;
}, []);
},
handleImage() {
return service.handleEditColorImage(this.product);
},
handleRelation() {
return serial.handleRelation(this.render.productStandardRelationStr);
},
handleOne() {
return serial.handleOne(this.product.productSkn, this.render.attributeProValuesOne);
},
handleTwo() {
return serial.handleTwo(this.product.productSkn, this.render.attributeProValuesTwo);
},
}
},
components: {
'shop-material': ShopMaterial,
'multi-select': MuliSelect,
Material,
MuliSelect,
TableGood,
CheckboxAge,
RadioSeason,
RadioGender,
SelectSeason,
CheckboxColor
},
watch: {
'table.selectedSizes'(newVal, oldVal) {
let addSize = _.differenceWith(newVal, oldVal, (left, right) => {
return left === right;
});
let removeSize = _.differenceWith(oldVal, newVal, (left, right) => {
return left === right;
});
addSize = addSize.filter(s => !this.isInColorSize(s));
_.forEach(this.table.data, (color) => {
if (!_.isEmpty(addSize)) {
addSize.forEach(s => this.addSize(color, s));
}
if (!_.isEmpty(removeSize)) {
removeSize.forEach(s => this.removeSize(color, s));
}
});
},
CheckboxColor,
CheckboxSize,
GoodImage
}
};
</script>
... ... @@ -984,90 +580,4 @@ export default {
margin-top: 20px;
}
@mixin row-span {
min-height: 30px;
.row-span {
min-height: 30px;
border-bottom: 1px solid #e3e8ee;
padding-top: 20px;
padding-bottom: 20px;
margin-left: -18px;
margin-right: -18px;
padding-left: 18px;
padding-right: 18px;
&:last-child {
border-bottom: none;
}
}
}
.size-code {
@include row-span;
&-error {
border: 1px solid #f30;
}
&-tip {
position: absolute;
line-height: 1;
padding-top: 6px;
color: #f30;
}
}
.size-id {
@include row-span;
text-align: center;
}
.size-operator {
@include row-span;
text-align: center;
}
.upload-item {
display: inline-block;
height: 180px;
width: 130px;
text-align: center;
margin: 10px 0;
}
.color-item-title {
text-align: center;
margin: 50px 0;
}
.upload-item {
display: inline-block;
height: 200px;
width: 130px;
text-align: center;
margin: 30px 0;
}
.upload-item-error {
border: 1px solid #f30;
position: relative;
}
.upload-item-tip {
position: absolute;
line-height: 1;
padding-top: 6px;
color: #f30;
top: 100%;
}
.upload-item-img {
display: inline-block;
height: 126px;
width: 124px;
border: 2px solid #e8e8e8;
box-sizing: border-box;
}
</style>
... ...
export default [
{
sub: [
{
menu_name: '发布新商品',
menu_url: '/product/create/step1.html',
menu_id: 'product.create',
status: 1,
id: 11
}, {
menu_name: '在售商品',
menu_url: '/product/onsale.html',
menu_id: 'product.onsale',
status: 1,
id: 12
}, {
menu_name: '未上架商品',
menu_url: '/product/offsale.html',
menu_id: 'product.offsale',
status: 1,
id: 13
}, {
menu_name: '批量功能',
menu_url: '/product/output.html',
menu_id: 'product.output',
status: 1,
id: 14
}
],
menu_name: '商品管理',
menu_id: 'product',
status: 1,
id: 1
}, {
sub: [
{
menu_name: '发货入库差异',
menu_url: '/repository/diff.html',
menu_id: 'repository.diff',
status: 1,
id: 31
},
{
menu_name: '可调拨库存(jit)',
menu_url: '/repository/jit.html',
menu_id: 'repository.jit',
status: 1,
id: 32
}
],
menu_name: '库存管理',
menu_id: 'repository',
status: 1,
id: 3
}, {
sub: [
{
menu_name: '店铺基本信息',
menu_url: '/shop/info.html',
status: 1,
id: 21
},
{
menu_name: '店铺装修PC',
menu_url: '/shop/decoration/decor-pc.html',
status: 1,
id: 22
},
{
menu_name: '店铺装修App',
menu_url: '/shop/decoration/decor-app.html',
status: 1,
id: 23
},
{
menu_name: '商品分类',
menu_url: '/shop/category/list.html',
status: 1,
id: 24
},
],
menu_name: '店铺管理',
menu_id: 'shop',
status: 1,
id: 2
}, {
sub: [
{
menu_name: '经营总览',
menu_url: '/statistics/overview.html',
menu_id: 'statistics.overview',
status: 1,
id: 41
},
{
menu_name: '销售统计',
menu_url: '/statistics/sale.html',
menu_id: 'statistics.sale',
status: 1,
id: 42
},
],
menu_name: '数据报表',
menu_id: 'statistics',
status: 1,
id: 4
},
{
sub: [
{
menu_name: '对账单',
menu_url: '/finance/clearing.html',
menu_id: 'finance.clearing',
status: 1,
id: 51
},
{
menu_name: '结算单',
menu_url: '/finance/payment.html',
menu_id: 'finance.payment',
status: 1,
id: 52
}
],
menu_name: '财务管理',
menu_id: 'finance',
status: 1,
id: 5
}
];
import _ from 'lodash';
import axios from 'axios';
import purviewMock from './_purview-mock';
const userService = {
login(username, password) {
... ... @@ -9,34 +8,27 @@ const userService = {
});
},
purviews() {
return new Promise(resolve => {
// 结构扁平化
let deepList = (purviews) => {
let purs = [];
return axios.post('/erp/getPurview').then(res => {
return {ori: res.data.data, deep: this.deepList(res.data.data)};
});
},
deepList(purviews) {
let purs = [];
_.each(purviews, pur => {
let sub = pur.sub;
_.each(purviews, pur => {
let sub = pur.sub;
purs.push(pur);
if (sub && sub.length) {
let subs = deepList(sub);
purs.push(pur);
if (sub && sub.length) {
let subs = this.deepList(sub);
_.each(subs, s => {
s.pMenu = pur;
});
purs = purs.concat(...subs);
}
_.each(subs, s => {
s.pMenu = pur;
});
return purs;
};
return resolve({ori: purviewMock, deep: deepList(purviewMock)});
purs = purs.concat(...subs);
}
});
// return axios.post('/erp/getPurview').then(res => {
// console.log(res);
// return res.data;
// });
return purs;
}
};
... ...
... ... @@ -33,6 +33,10 @@ class UserService extends Context {
}
shopLogin(account, password) {
return Promise.resolve({
PHPSESSID: 1,
'connect.sid': 2
})
return rp.get({
url: apiDomain.shop.login,
resolveWithFullResponse: true,
... ...