javacodeadmin/ruoyi-ui/src/components/ShopSku/sku.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>