299 lines
7.8 KiB
Vue
299 lines
7.8 KiB
Vue
<template>
|
|
<div>
|
|
|
|
<el-card class="sku-main-card" shadow="never">
|
|
<SkuForm
|
|
:source-attribute="sourceAttribute"
|
|
:attribute.sync="attribute"
|
|
:sku.sync="sku"
|
|
:structure="structure"
|
|
ref="skuForm"
|
|
:theme="2"
|
|
>
|
|
<template #score="slotProps">
|
|
<div>
|
|
<el-rate v-model="slotProps.row.score" />
|
|
</div>
|
|
</template>
|
|
<template #pic="slotProps">
|
|
|
|
<div class="upimg">
|
|
<div class="imgs"> <image-upload v-model="slotProps.row.pic" :limit="1" :isShowTip="false" /></div>
|
|
</div>
|
|
</template>
|
|
</SkuForm>
|
|
</el-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import SkuForm from './skufrom.vue'
|
|
export default {
|
|
components:{
|
|
SkuForm
|
|
},
|
|
props:{
|
|
info:{
|
|
type:String,
|
|
|
|
}
|
|
},
|
|
|
|
watch:{
|
|
info:{
|
|
handler() {
|
|
this.init();
|
|
}
|
|
}
|
|
},
|
|
mounted(){
|
|
this.init();
|
|
},
|
|
data() {
|
|
return {
|
|
data:{},
|
|
sourceAttribute: [
|
|
|
|
],
|
|
attribute: [
|
|
|
|
],
|
|
sku: [
|
|
|
|
],
|
|
structure:[
|
|
{
|
|
name: 'pic',
|
|
type: 'slot',
|
|
label: '图片',
|
|
batch:false
|
|
|
|
},
|
|
{
|
|
name: 'price',
|
|
type: 'input',
|
|
label: '价格',
|
|
batch:false,
|
|
required: true
|
|
|
|
},
|
|
{
|
|
name: 'stock',
|
|
type: 'input',
|
|
label: '库存',
|
|
batch:false,
|
|
required: true
|
|
|
|
}
|
|
],
|
|
|
|
}
|
|
},
|
|
methods: {
|
|
parseInfoToSkuData(infoStr) {
|
|
let data;
|
|
try {
|
|
data = typeof infoStr === 'string' ? JSON.parse(infoStr) : infoStr;
|
|
} catch {
|
|
return {
|
|
sourceAttribute: [],
|
|
attribute: [],
|
|
sku: []
|
|
};
|
|
}
|
|
const attrs = data.attrs || {};
|
|
const attrArr = Object.keys(attrs).map(name => ({
|
|
name,
|
|
item: attrs[name]
|
|
}));
|
|
// 生成sku字段
|
|
return {
|
|
sourceAttribute: JSON.parse(JSON.stringify(attrArr)),
|
|
attribute: JSON.parse(JSON.stringify(attrArr)),
|
|
sku: Array.isArray(data.sku) ? data.sku.map(item => {
|
|
const specNames = Object.keys(attrs);
|
|
const skuValue = specNames.map(name => item[name]).join(';');
|
|
return {
|
|
sku: skuValue,
|
|
...item
|
|
}
|
|
}) : []
|
|
};
|
|
},
|
|
init(){
|
|
if(this.info){
|
|
this.data=JSON.parse(this.info);
|
|
// 新增:自动转换
|
|
const parsed = this.parseInfoToSkuData(this.info);
|
|
this.sourceAttribute = parsed.sourceAttribute;
|
|
this.attribute = parsed.attribute;
|
|
this.sku = parsed.sku;
|
|
this.$refs.skuForm.init()
|
|
}
|
|
},
|
|
TodoData(){
|
|
// 1. 组装 attrs
|
|
const attrs = {};
|
|
// 取规格名和规格值(数组)
|
|
this.$refs.skuForm.getArray().forEach(attr => {
|
|
if(attr.name && Array.isArray(attr.item)){
|
|
attrs[attr.name] = attr.item.map(r => r.name || r);
|
|
}
|
|
});
|
|
// 2. 组装 sku
|
|
// 取所有规格名
|
|
const specNames = Object.keys(attrs);
|
|
// 每个sku对象包含所有规格名及其值、图片、价格、库存等字段
|
|
|
|
const skuList = (this.sku || []).map(row => {
|
|
const result = {};
|
|
// 规格属性
|
|
const _txt=row.sku.split(';');
|
|
|
|
_txt.forEach((name,index) => {
|
|
result[specNames[index]] = name;
|
|
})
|
|
|
|
// 其他字段
|
|
this.structure.forEach(col => {
|
|
if(row[col.name] !== undefined) result[col.name] = row[col.name];
|
|
});
|
|
return result;
|
|
});
|
|
|
|
return {
|
|
type: 'many',
|
|
attrs,
|
|
sku: skuList
|
|
};
|
|
},
|
|
submit() {
|
|
let _IS=false
|
|
|
|
this.$refs.skuForm.validate(valid => {
|
|
if (valid) {
|
|
|
|
_IS=JSON.stringify(this.TodoData())
|
|
|
|
} else {
|
|
|
|
_IS=false
|
|
}
|
|
})
|
|
return _IS
|
|
},
|
|
add(){
|
|
this.sourceAttribute.push({
|
|
"name": "",
|
|
"item": [],
|
|
"input":""
|
|
})
|
|
this.attribute.push({
|
|
"name": "",
|
|
"item": []
|
|
})
|
|
this.$refs.skuForm.init()
|
|
this.generateSku()
|
|
},
|
|
itemAdd(row){
|
|
if(row.input){
|
|
row.item.push(row.input)
|
|
row.input = ""
|
|
}else{
|
|
this.$message.error("请输入内容")
|
|
}
|
|
},
|
|
generateSku() {
|
|
// 清空之前的SKU数据
|
|
this.sku = [];
|
|
|
|
// 获取所有规格项
|
|
let specs = this.sourceAttribute.map(attr => {
|
|
return {
|
|
name: attr.name,
|
|
items: attr.item
|
|
};
|
|
}).filter(spec => spec.name && spec.items.length > 0);
|
|
|
|
// 如果没有规格项,直接返回
|
|
if (specs.length === 0) {
|
|
return;
|
|
}
|
|
|
|
// 生成规格组合
|
|
const generateCombinations = (specs) => {
|
|
if (specs.length === 0) return [[]];
|
|
|
|
const [first, ...rest] = specs;
|
|
const combinations = generateCombinations(rest);
|
|
|
|
return first.items.flatMap(item =>
|
|
combinations.map(combination => [item, ...combination])
|
|
);
|
|
};
|
|
|
|
// 生成所有可能的组合
|
|
const combinations = generateCombinations(specs);
|
|
|
|
// 构建SKU数据
|
|
this.sku = combinations.map(combination => {
|
|
const skuItem = {
|
|
specs: {},
|
|
price: 0,
|
|
stock: 0,
|
|
imageUrl: ''
|
|
};
|
|
|
|
// 设置规格值
|
|
specs.forEach((spec, index) => {
|
|
skuItem.specs[spec.name] = combination[index];
|
|
});
|
|
|
|
return skuItem;
|
|
});
|
|
|
|
// 更新attribute数据
|
|
this.attribute = specs.map(spec => ({
|
|
name: spec.name,
|
|
item: spec.items
|
|
}));
|
|
},
|
|
itemDelete(row){
|
|
console.log(row)
|
|
this.sourceAttribute.splice(row.vmCount, 1);
|
|
this.attribute.splice(row.vmCount, )
|
|
this.$refs.skuForm.init()
|
|
this.generateSku()
|
|
}
|
|
|
|
}
|
|
}
|
|
</script>
|
|
<style scoped lang="scss">
|
|
.upimg {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
::v-deep .el-upload--picture-card {
|
|
width: 60px !important;
|
|
height: 60px !important;
|
|
line-height: 66px !important;
|
|
}
|
|
::v-deep .el-upload-list--picture-card .el-upload-list__item {
|
|
width: 60px !important;
|
|
height: 60px !important;
|
|
line-height: 60px !important;
|
|
}
|
|
.imgs {
|
|
margin-right: 15px;
|
|
}
|
|
}
|
|
.sku-main-card {
|
|
margin: 24px 0 24px 0;
|
|
background: #f8fafd;
|
|
border-radius: 10px;
|
|
border: 1px solid #e6e8eb;
|
|
box-shadow: 0 2px 8px 0 rgba(0,0,0,0.03);
|
|
|
|
}
|
|
</style>
|