feat: 商品规格功能调整

This commit is contained in:
duan
2025-02-21 14:41:43 +08:00
parent dc5f664143
commit 43ae9f371d
17 changed files with 954 additions and 140 deletions

View File

@@ -33,8 +33,8 @@
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="商品图片" required prop="coverImg">
<SingleImageUpload v-model="ruleForm.coverImg" />
<el-form-item label="商品图片" required prop="images">
<MultiImageUpload v-model="ruleForm.images" />
</el-form-item>
<el-form-item>
<div style="color: #999;">第一张图为商品封面图图片尺寸为750×750</div>
@@ -48,12 +48,12 @@
</el-checkbox-group>
</el-form-item> -->
<el-form-item label="商品类型">
<el-radio-group v-model="ruleForm.type">
<el-radio-group v-model="ruleForm.type" @change="changeTypeEnum(ruleForm.type)">
<el-radio label="single">单规格商品</el-radio>
<el-radio label="sku">多规格商品</el-radio>
<el-radio label="package">套餐商品</el-radio>
<el-radio label="weight">称重商品</el-radio>
<el-radio label="coupon">团购券</el-radio>
<!-- <el-radio label="coupon">团购券</el-radio> -->
</el-radio-group>
</el-form-item>
<!-- <el-form-item label="规格类型">
@@ -62,52 +62,24 @@
<el-radio label="sku">多规格</el-radio>
</el-radio-group>
</el-form-item> -->
<el-form-item label="套餐类型">
<!-- <el-form-item label="套餐类型">
<el-radio-group v-model="ruleForm.groupType">
<el-radio label="0">固定套餐</el-radio>
<el-radio label="1">可选套餐</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="ruleForm.groupType == 0">
<el-table border :data="item.goods" v-for="(item, index) in ruleForm.proGroupVo" :key="index">
<el-table-column label="名称" prop="proName"></el-table-column>
<el-table-column label="规格" prop="skuName"> </el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
<el-table-column label="数量" prop="number">
<template v-slot="scope">
<el-input-number v-model="scope.row.number" :min="0" />
</template>
</el-table-column>
<el-table-column width="150">
<template slot="header" slot-scope="scope">
<el-button type="primary"
@click="$refs.shopListRef.show([...ruleForm.proGroupVo[index].goods])">添加商品</el-button>
</template>
<template slot-scope="scope">
<el-button type="text" :disabled="scope.row.typeEnum != '多规格'"
@click="showSelectSkuHandle(scope.row, scope.$index, index)">设置规格</el-button>
<el-button type="text" @click="ruleForm.proGroupVo[index].goods.splice(scope.$index, 1)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<template v-if="ruleForm.groupType == 1">
<div class="group_wrap" v-for="(item, index) in form.proGroupVo" :key="index">
<el-form inline :model="item">
<el-form-item label="规格组名">
<el-input v-model="item.title" />
</el-form-item>
<el-form-item :label="`本组菜品${item.goods.length}选`">
<el-input v-model="item.number" />
</el-form-item>
<el-form-item>
<el-button @click="form.proGroupVo.splice(index, 1)">删除</el-button>
</el-form-item>
</el-form>
<div>
<el-table border :data="item.goods">
</el-form-item> -->
<el-form-item label="套餐商品" v-if="ruleForm.type == 'package'">
<div style="display: block;width: 100%;">
<div class="head-container">
<el-radio-group v-model="ruleForm.groupType" @change="typeChange">
<el-radio-button label="0">固定套餐</el-radio-button>
<el-radio-button label="1">可选套餐</el-radio-button>
</el-radio-group>
</div>
<div v-if="ruleForm.groupType == '0'">
<el-table border :data="item.goods" v-for="(item, index) in ruleForm.proGroupVo" :key="index">
<el-table-column label="名称" prop="proName"></el-table-column>
<el-table-column label="规格" prop="skuName"></el-table-column>
<el-table-column label="规格" prop="skuName"> </el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
<el-table-column label="数量" prop="number">
<template v-slot="scope">
@@ -115,23 +87,85 @@
</template>
</el-table-column>
<el-table-column width="150">
<template slot="header" slot-scope="scope">
<el-button type="primary"
@click="$refs.shopListRef.show([...form.proGroupVo[index].goods]); addGroupIndex = index">添加商品</el-button>
<template #header>
<el-button type="primary" @click="addgoods">添加商品</el-button>
</template>
<template slot-scope="scope">
<!-- <template slot="header" v-slot="scope"> -->
<!-- <el-button type="primary" @click="">添加商品</el-button> -->
<!-- </template> -->
<!-- <template v-slot="scope">
<el-button type="text" :disabled="scope.row.typeEnum != '多规格'"
@click="showSelectSkuHandle(scope.row, scope.$index, index)">设置规格</el-button>
<el-button type="text" @click="form.proGroupVo[index].goods.splice(scope.$index, 1)">删除</el-button>
</template>
</template> -->
</el-table-column>
</el-table>
</div>
</div>
<el-button type="primary" @click="$refs.shopListRef.show(); addGroupIndex = false">添加套餐组</el-button>
</template>
<!--
<div v-if="ruleForm.groupType == 1">
<div class="group_wrap" v-for="(item, index) in form.proGroupVo" :key="index">
<el-form inline :model="item">
<el-form-item label="规格组名">
<el-input v-model="item.title" />
</el-form-item>
<el-form-item :label="`本组菜品${item.goods.length}选`">
<el-input v-model="item.number" />
</el-form-item>
<el-form-item>
<el-button @click="form.proGroupVo.splice(index, 1)">删除</el-button>
</el-form-item>
</el-form>
<div>
<el-table border :data="item.goods">
<el-table-column label="名称" prop="proName"></el-table-column>
<el-table-column label="规格" prop="skuName"></el-table-column>
<el-table-column label="价格" prop="price"></el-table-column>
<el-table-column label="数量" prop="number">
<template v-slot="scope">
<el-input-number v-model="scope.row.number" :min="0" />
</template>
</el-table-column>
<el-table-column width="150">
<template slot="header" slot-scope="scope">
<el-button type="primary"
@click="$refs.shopListRef.show([...form.proGroupVo[index].goods]); addGroupIndex = index">添加商品</el-button>
</template>
<template slot-scope="scope">
<el-button type="text" :disabled="scope.row.typeEnum != '多规格'"
@click="showSelectSkuHandle(scope.row, scope.$index, index)">设置规格</el-button>
<el-button type="text" @click="form.proGroupVo[index].goods.splice(scope.$index, 1)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-button type="primary" @click="$refs.shopListRef.show(); addGroupIndex = false">添加套餐组</el-button>
</div> -->
</el-form-item>
<el-form-item label="选择规格" v-if="ruleForm.type == 'sku'">
<el-select v-model="ruleForm.specId" placeholder="请选择规格" style="width: 500px" @change="selectSpecHandle">
<el-option :label="item.name" :value="item.id" v-for="item in datas.specificationsconfig"
:key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="item.name" v-if="datas.selectSpeclist.length" v-for="item in datas.selectSpeclist"
:key="item.name">
<el-checkbox-group v-model="item.selectSpecResult" @change="selectSpecResultChange">
<el-checkbox :value="item.name" v-for="(item, index) in item.children" :key="index">{{ item.name
}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<!-- 规格属性 -->
<SpecificationAttribute></SpecificationAttribute>
<!-- 单规格称重 -->
<SpecificationAttribute v-if="ruleForm.type != 'sku'" :info="ruleForm" :list="list"
ref="specificationAttributeRef">
</SpecificationAttribute>
<SpecificationAttribute v-if="ruleForm.type == 'sku' && list.length" :specTableHeaders="datas.specTableHeaders"
:info="ruleForm" :list="list" ref="specificationAttributeRef"></SpecificationAttribute>
<el-form-item label="重量">
<el-col :span="12">
<div style="display: block;">
@@ -159,7 +193,7 @@
</el-form-item> -->
<el-form-item label="定时上下架">
<el-checkbox-group v-model="ruleForm.days">
<el-checkbox v-for="(item, index) in datas.cycle" :key="item.value" :label="item.value">
<el-checkbox v-for="(item, index) in datas.cycle" :key="item.value" :value="item.value">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
@@ -199,6 +233,8 @@
<el-button @click="resetForm(ruleFormRef)">取消</el-button>
</el-form-item>
</el-form>
<!-- 选择商品 -->
<shopList ref="shopListRef" @success="selectShopRes" />
</div>
</template>
@@ -209,7 +245,23 @@ import type { FormInstance, FormRules } from 'element-plus'
import SpecificationAttribute from './SpecificationAttribute.vue'
import UserAPI from "@/api/product/productclassification";
import UserAPI2 from "@/api/product/commonUnits";
import UserAPI3 from "@/api/product/index";
import UserAPI4 from "@/api/product/specificationsconfig";
import shopList from "@/components/mycomponents/shopList.vue";
import { useRouter } from 'vue-router';
const router = useRouter();
let list = ref<any[]>([{
"originPrice": 0,
"costPrice": 0,
"salePrice": 0,
"memberPrice": 0,
"suitNum": 1,
"coverImg": "",
"weight": 0,
"barCode": "88888888888888888888"
}]);
let datas = reactive({
cycle: [
{ label: "周一", value: "Monday" },
@@ -222,8 +274,23 @@ let datas = reactive({
],
Company: [],
classification: [],
})
// 商品规格
specificationsconfig: [],
selectSpeclist: [],
defaultSku: {
"originPrice": 0,
"costPrice": 0,
"salePrice": 0,
"memberPrice": 0,
"suitNum": 1,
"coverImg": "",
"weight": 0,
"barCode": "88888888888888888888"
},
specTableHeaders: [],
})
let shopListRef = ref(null)
interface RuleForm {
name: string,
shortTitle: string,
@@ -239,6 +306,7 @@ interface RuleForm {
weight: Number,
isAllowTempModifyPrice: Number,
days: string[],
useTime: string[],
startTime: string,
endTime: string,
isSale: string,
@@ -248,6 +316,46 @@ interface RuleForm {
packFee: Number,
sort: Number,
}
// 添加商品
function addgoods() {
shopListRef.value.opens()
}
// 分组选择商品
function selectShopRes(res) {
// let newres = res.map(item => {
// item.proId = item.id
// item.proName = item.name
// item.price = item.lowPrice
// item.skuId = ''
// item.skuName = ''
// item.number = 1
// return item
// })
// if (this.form.groupType == 0) {
// let obj = {
// title: '',
// count: newres.length,
// number: '',
// goods: newres
// }
// this.form.proGroupVo = [{ ...obj }]
// } else {
// if (this.addGroupIndex !== false) {
// this.form.proGroupVo[this.addGroupIndex].count = newres.length
// this.form.proGroupVo[this.addGroupIndex].goods = newres
// } else {
// let arr = [...this.form.proGroupVo]
// arr.push({
// title: '',
// count: newres.length,
// number: '',
// goods: newres
// })
// this.form.proGroupVo = [...arr]
// }
// }
}
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
//商品名称
@@ -265,11 +373,16 @@ const ruleForm = reactive<RuleForm>({
// 商品类型
type: 'single',
// 规格id
specId: 'normal',
specId: '',
// 套餐类型
groupType: '0',
// 套餐入参
proGroupVo: [],
proGroupVo: [{
title: '',
count: '',
number: '',
goods: []
}],
// sku集合
skuList: [],
// 重量
@@ -280,13 +393,13 @@ const ruleForm = reactive<RuleForm>({
days: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
useTime: ['00:00:00', '23:59:59'],
// 开始时间
startTime: '00:00:00',
startTime: '',
// 结束时间
endTime: "23:59:59",
endTime: "",
// 是否上架
isSale: "1",
// 是否开启库存
isStock: "0",
isStock: "1",
// 设为推荐
isHot: "1",
// 库存数量
@@ -314,7 +427,7 @@ const rules = reactive<FormRules<RuleForm>>({
trigger: 'change',
},
],
coverImg: [
images: [
{
required: true,
message: '请选择图片',
@@ -331,18 +444,187 @@ async function getList() {
datas.Company = await UserAPI2.getList()
datas.classification = await UserAPI.getList()
}
const submitForm = async (formEl: FormInstance | undefined) => {
console.log(ruleForm, '提交数据')
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!')
// 选择规格属性
function selectSpecResultChange() {
createSkuHeader();
createSkuBody();
}
// 生成多规格表头
function createSkuHeader() {
const headers = [];
for (let item of datas.selectSpeclist) {
if (item.selectSpecResult.length) {
headers.push({
label: item.name,
value: item.name,
});
}
}
datas.specTableHeaders = headers;
}
// 生成多规格表体
function createSkuBody() {
let bodys = [];
for (let item of datas.selectSpeclist) {
if (item.selectSpecResult.length) {
let arr = [];
for (let val of item.selectSpecResult) {
arr.push({
[item.name]: val,
});
}
bodys.push(arr);
}
}
let arr = cartesian(bodys);
const m = {
coverImg: "",
...datas.defaultSku,
};
let newarr = [];
for (let item of arr) {
if (Array.isArray(item)) {
let obj = {};
let specSnap = [];
for (let v of item) {
for (let key in v) {
obj[`${key}`] = v[key];
specSnap.push(v[key]);
}
}
let specSnapStr = specSnap.join(",");
newarr.push({
specSnap: specSnapStr,
specInfo: specSnapStr,
...m,
...obj,
// barCode: `${dayjs().valueOf()}${RandomNumBoth(1, 9999)}`,
});
} else {
let specSnap = [];
for (let key in item) {
specSnap.push(item[key]);
}
let specSnapStr = specSnap.join(",");
newarr.push({
specSnap: specSnapStr,
specInfo: specSnapStr,
...m,
...item,
// barCode: `${dayjs().valueOf()}${RandomNumBoth(1, 9999)}`,
});
}
}
console.log(newarr, '提交')
list.value = newarr;
}
// 切换类型
function changeTypeEnum(item) {
// single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券
list.value = []
if (item == 'sku') {
tbProductSpecGet();
} else {
ruleForm.specId = ""
datas.selectSpeclist = []
list.value = [datas.defaultSku]
}
}
// 笛卡尔积算法
function cartesian(arr) {
if (arr.length < 2) return arr[0] || [];
return [].reduce.call(arr, (col, set) => {
let res = [];
col.forEach((c) => {
set.forEach((s) => {
let t = [].concat(Array.isArray(c) ? c : [c]);
t.push(s);
res.push(t);
});
});
return res;
});
}
// 套餐类型切换
function typeChange() {
ruleForm.typeEnum = 'normal'
if (ruleForm.groupType == 0) {
// this.$set(this.form.proGroupVo, 0, {
// title: '',
// count: '',
// number: 1,
// goods: []
// })
} else {
// this.form.proGroupVo = []
}
// this.changeTypeEnum()
}
// 获取规格列表
async function tbProductSpecGet() {
datas.specificationsconfig = await UserAPI4.getPage()
}
// 选择规格
function selectSpecHandle(e) {
const selectSpec = JSON.parse(JSON.stringify(datas.specificationsconfig.find((item) => item.id == e).children));
for (let item in selectSpec) {
selectSpec[item].selectSpecResult = [];
}
datas.selectSpeclist = selectSpec;
// this.form.skuList = [ ];
}
const specificationAttributeRef = ref(null)
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid, fields) => {
if (valid) {
// 第一张图片作为封面图
ruleForm.coverImg = ruleForm.images[0]
// 规格id修改
ruleForm.specId = specIdFunction(ruleForm.type)
// 修改时间
ruleForm.startTime = ruleForm.useTime[0]
ruleForm.endTime = ruleForm.useTime[1]
// 拿到sku数据
ruleForm.skuList = specificationAttributeRef.value.getdata()
// 多规格 selectSpecInfo 添加
if (ruleForm.type == 'sku') {
let obj = {}
datas.selectSpeclist.forEach((item: any) => {
obj[item.name] = item.selectSpecResult
})
ruleForm.selectSpecInfo = obj
}
console.log(ruleForm, '提交数据')
let res = await UserAPI3.addunit(ruleForm)
if (res.code == 200) {
ElMessage.success("添加成功");
router.push({ name: 'productIndex' });
}
} else {
ElMessage.error("请填写完整信息");
console.log('error submit!', fields)
}
})
}
// 规格id过滤
const specIdFunction = (type: string) => {
if (type === 'single') {
return null
} else if (type === '2') {
return 2
} else if (type === '3') {
return 3
} else if (type === '4') {
return 4
} else if (type === '5') {
return 5
}
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()