fixed 优化商品sku(未完成,计划端午完成)
This commit is contained in:
parent
3170e8b9dd
commit
515b6afe62
@ -156,69 +156,7 @@
|
||||
<el-row v-if="formData.goodsSpecType == 2">
|
||||
<el-col :lg="24">
|
||||
|
||||
<el-form-item :label-width="labelWidth" label="商品规格">
|
||||
<div style="display: block;width: 100%;">
|
||||
<!-- <el-input-number v-model.number="formData.goodsSpec" controls-position="right" :min="0.01"
|
||||
:precision="2" /> -->
|
||||
<div class="input-intro">最多添加3个商品规格组,生成的SKU数量不能超出50个</div>
|
||||
|
||||
<!-- 规格样式 -->
|
||||
<div class="sepc-big-box" v-for="(item, index) in goodsSpecList">
|
||||
<div class="sepc-title-box">
|
||||
<el-input v-model="item.specName" @change="handleChangeSepc(item, index)" class="spec-input"
|
||||
placeholder="规格组名称" clearable />
|
||||
<el-link type="primary" @click="handleDelSpec(item)">删除规格组</el-link>
|
||||
</div>
|
||||
<div class="spec-value-box">
|
||||
<div class="spec-value-input-big-box">
|
||||
<div class="spec-value-input-box" v-for="specValue in item.props">
|
||||
<div class="spec-value-input-del" @click="handleDelSpecValue(item,specValue)"><el-icon>
|
||||
<Close />
|
||||
</el-icon></div>
|
||||
<el-input v-model="specValue.specValueName" @change="handleChangeSepcValue(item,specValue)"
|
||||
class="spec-value-input" placeholder="规格值名称" clearable />
|
||||
</div>
|
||||
</div>
|
||||
<el-link type="primary" v-if="isAddSpecValueMax" @click="handleAddSpecValue(item)">添加规格值</el-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button v-if="isAddSpecMax" class="mt-5" @click="handleAddSpec">
|
||||
<el-icon class="avatar-uploader-icon">
|
||||
<plus />
|
||||
</el-icon>
|
||||
添加规格组
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<!-- Sku列表 -->
|
||||
<el-form-item :label-width="labelWidth" label="Sku列表">
|
||||
|
||||
<!-- sku列表 -->
|
||||
<el-table :data="skuList" border style="width: 100%" :span-method="objectSpanMethod">
|
||||
<!-- 动态列 -->
|
||||
<el-table-column v-for="column in skuColumns" :prop="column.prop" :label="column.label"
|
||||
:key="column.key" :width="column.width">
|
||||
</el-table-column>
|
||||
|
||||
<!-- <el-table-column prop="goodsSkuPrice" label="预览图">
|
||||
<template #default="scope">
|
||||
<UploadImage ref="uploadRef" v-model="scope.row.goodsSkuImg" :data=imgData :limit="1"
|
||||
:fileSize="5" :drag="true" :isShowTip="false" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
|
||||
<el-table-column prop="goodsSkuPrice" label="商品价格">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model.number="scope.row.goodsSkuPrice" controls-position="right" :min="0"
|
||||
:precision="2" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<MultiSpec></MultiSpec>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -388,6 +326,7 @@ import { shopGoodsCategoryTreeList } from '@/api/business/GoodsManager/ShopGoods
|
||||
import { deliveryList } from '@/api/business/LogisticsManage/Deliverys/delivery.js'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import ChooseShopDialog from './ChooseShopDialog.vue';
|
||||
import MultiSpec from './MultiSpec/MultiSpec.vue';
|
||||
|
||||
|
||||
// 打开弹窗时回调
|
||||
|
@ -1,286 +0,0 @@
|
||||
<template>
|
||||
<el-form-item :label-width="labelWidth" label="商品规格">
|
||||
<div style="display: block;width: 100%;">
|
||||
<div class="input-intro">最多添加3个商品规格组,生成的SKU数量不能超出50个</div>
|
||||
|
||||
<!-- 规格样式 -->
|
||||
<div class="sepc-big-box" v-for="(item, index) in multiSpecData.specList">
|
||||
<div class="sepc-title-box">
|
||||
<el-input v-model="item.spec_name" @change="onChangeSpecGroupIpt" class="spec-input" placeholder="规格组名称"
|
||||
clearable />
|
||||
<el-link type="primary" @click="handleDeleteSpecGroup(index)">删除规格组</el-link>
|
||||
</div>
|
||||
<div class="spec-value-box">
|
||||
<div class="spec-value-input-big-box">
|
||||
<div class="spec-value-input-box" v-for="(itm, idx) in item.valueList" :key="idx">
|
||||
<div class="spec-value-input-del" @click="handleDeleteSpecValue(index, idx)"><el-icon>
|
||||
<Close />
|
||||
</el-icon></div>
|
||||
<el-input v-model="specValue.specValueName" @change="onChangeSpecValueIpt"
|
||||
class="spec-value-input" placeholder="规格值名称" clearable />
|
||||
</div>
|
||||
</div>
|
||||
<el-link type="primary" v-if="!isSpecLocked" @click="handleAddSpecValue(index)">添加规格值</el-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button v-if="!isSpecLocked && multiSpecData.specList.length < 3" class="mt-5" @click="handleAddSpecGroup">
|
||||
<el-icon class="avatar-uploader-icon">
|
||||
<plus />
|
||||
</el-icon>
|
||||
添加规格组
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<!-- Sku列表 -->
|
||||
<el-form-item :label-width="labelWidth" label="Sku列表">
|
||||
|
||||
<!-- sku列表 -->
|
||||
<el-table :data="skuList" border style="width: 100%" :span-method="objectSpanMethod">
|
||||
<!-- 动态列 -->
|
||||
<el-table-column v-for="column in skuColumns" :prop="column.prop" :label="column.label" :key="column.key"
|
||||
:width="column.width">
|
||||
</el-table-column>
|
||||
|
||||
<!-- <el-table-column prop="goodsSkuPrice" label="预览图">
|
||||
<template #default="scope">
|
||||
<UploadImage ref="uploadRef" v-model="scope.row.goodsSkuImg" :data=imgData :limit="1"
|
||||
:fileSize="5" :drag="true" :isShowTip="false" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
|
||||
<el-table-column prop="goodsSkuPrice" label="商品价格">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model.number="scope.row.goodsSkuPrice" controls-position="right" :min="0" :precision="2" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PropTypes from 'ant-design-vue/es/_util/vue-types'
|
||||
import MultiSpecModel from '@/common/model/goods/MultiSpec'
|
||||
import { SelectImage } from '@/components'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SelectImage
|
||||
},
|
||||
props: {
|
||||
// 默认的规格列表
|
||||
defaultSpecList: PropTypes.array.def([]),
|
||||
// 默认的SKU列表
|
||||
defaultSkuList: PropTypes.array.def([]),
|
||||
// 商品规格是否锁定(锁定状态下不允许编辑规格)
|
||||
isSpecLocked: PropTypes.bool.def(false)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 标签布局属性
|
||||
labelCol: { span: 3 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 21 },
|
||||
// 商品多规格模型
|
||||
MultiSpecModel: new MultiSpecModel(),
|
||||
// MultiSpecModel: Object,
|
||||
multiSpecData: {
|
||||
// 规格列表
|
||||
specList: [],
|
||||
// SKU列表
|
||||
skuList: []
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultSpecList(val) {
|
||||
if (val.length && this.MultiSpecModel.isEmpty()) {
|
||||
this.getData()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 初始化数据
|
||||
created() {
|
||||
// 获取规格及SKU信息
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 获取规格及SKU信息(展示)
|
||||
getData() {
|
||||
const { defaultSpecList, defaultSkuList } = this
|
||||
this.multiSpecData = this.MultiSpecModel.getData(defaultSpecList, defaultSkuList)
|
||||
},
|
||||
|
||||
// 获取规格及SKU信息(表单提交)
|
||||
getFromSpecData() {
|
||||
return this.MultiSpecModel.getFromSpecData()
|
||||
},
|
||||
|
||||
// 添加规格组
|
||||
handleAddSpecGroup() {
|
||||
if (this.checkSkuMaxNum()) {
|
||||
this.MultiSpecModel.handleAddSpecGroup()
|
||||
}
|
||||
},
|
||||
|
||||
// 删除规格组
|
||||
handleDeleteSpecGroup(groupIndex) {
|
||||
const app = this
|
||||
const modal = this.$confirm({
|
||||
title: '您确定要删除该规格组吗?',
|
||||
content: '删除后不可恢复',
|
||||
onOk() {
|
||||
// 删除元素
|
||||
app.MultiSpecModel.handleDeleteSpecGroup(groupIndex)
|
||||
// 关闭对话框
|
||||
modal.destroy()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 新增规格值
|
||||
handleAddSpecValue(groupIndex) {
|
||||
if (this.checkSkuMaxNum()) {
|
||||
this.MultiSpecModel.handleAddSpecValue(groupIndex)
|
||||
}
|
||||
},
|
||||
|
||||
// 删除规格值
|
||||
handleDeleteSpecValue(groupIndex, valueIndex) {
|
||||
const app = this
|
||||
const modal = this.$confirm({
|
||||
title: '您确定要删除该规格值吗?',
|
||||
content: '删除后不可恢复',
|
||||
onOk() {
|
||||
// 删除元素
|
||||
app.MultiSpecModel.handleDeleteSpecValue(groupIndex, valueIndex)
|
||||
// 关闭对话框
|
||||
modal.destroy()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 规格组输入框change事件
|
||||
onChangeSpecGroupIpt() {
|
||||
// 更新skuList
|
||||
this.MultiSpecModel.onUpdate(true)
|
||||
},
|
||||
|
||||
// 规格值输入框change事件
|
||||
onChangeSpecValueIpt(event, itm) {
|
||||
// 更新skuList
|
||||
this.MultiSpecModel.onUpdate(true)
|
||||
},
|
||||
|
||||
// 验证最大sku数量
|
||||
checkSkuMaxNum() {
|
||||
const skuList = this.multiSpecData.skuList
|
||||
if (skuList.length >= 50) {
|
||||
this.$message.error(`生成的sku列表数量不能大于50个,当前数量:${skuList.length}个`, 2.5)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
|
||||
// 批量设置sku事件
|
||||
handleSkuBatch() {
|
||||
this.MultiSpecModel.handleSkuBatch()
|
||||
},
|
||||
|
||||
// 验证多规格表单
|
||||
verifyForm() {
|
||||
if (!this.MultiSpecModel.verifyForm()) {
|
||||
this.$message.error(this.MultiSpecModel.getError(), 2)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" scoped>
|
||||
.divider-title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.input-intro {
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
.sepc-big-box {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sepc-title-box {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #f4f4f5;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.spec-value-box {
|
||||
width: 100%;
|
||||
padding: 20px 20px 20px 40px;
|
||||
background-color: #fbfbfb;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.spec-value-input-big-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.spec-value-input-box {
|
||||
width: 250px;
|
||||
position: relative;
|
||||
margin-right: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.spec-value-input-del {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
z-index: 99;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: grey;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.spec-input {
|
||||
width: 250px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.el-input-number {
|
||||
width: 140px;
|
||||
}
|
||||
</style>
|
@ -1,446 +0,0 @@
|
||||
|
||||
import _ from 'lodash'
|
||||
import { debounce, isEmpty } from '@/utils/util'
|
||||
|
||||
// 默认的sku字段属性
|
||||
const defaultColumns = [
|
||||
{
|
||||
title: '预览图',
|
||||
dataIndex: 'image',
|
||||
width: 90,
|
||||
scopedSlots: { customRender: 'image' }
|
||||
},
|
||||
{
|
||||
title: '商品价格',
|
||||
dataIndex: 'goods_price',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'goods_price' }
|
||||
},
|
||||
{
|
||||
title: '划线价格',
|
||||
dataIndex: 'line_price',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'line_price' }
|
||||
},
|
||||
{
|
||||
title: '库存数量',
|
||||
dataIndex: 'stock_num',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'stock_num' }
|
||||
},
|
||||
{
|
||||
title: '商品重量 (KG)',
|
||||
dataIndex: 'goods_weight',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'goods_weight' }
|
||||
},
|
||||
{
|
||||
title: 'SKU编码',
|
||||
dataIndex: 'goods_sku_no',
|
||||
width: 140,
|
||||
scopedSlots: { customRender: 'goods_sku_no' }
|
||||
}
|
||||
]
|
||||
|
||||
// 默认的sku记录值
|
||||
const defaultSkuItemData = {
|
||||
image_id: 0,
|
||||
image: {},
|
||||
// imageList: [],
|
||||
goods_price: '',
|
||||
line_price: '',
|
||||
stock_num: '',
|
||||
goods_weight: '',
|
||||
goods_sku_no: ''
|
||||
}
|
||||
|
||||
// const demoSpecList = [
|
||||
// {
|
||||
// key: 0,
|
||||
// spec_name: '颜色',
|
||||
// valueList: [
|
||||
// { key: 0, groupKey: 0, /* spec_value_id: 10001, */ spec_value: '红色' },
|
||||
// { key: 1, groupKey: 0, spec_value: '白色' },
|
||||
// { key: 2, groupKey: 0, spec_value: '蓝色' }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// key: 1,
|
||||
// spec_name: '尺码',
|
||||
// valueList: [
|
||||
// { key: 0, groupKey: 1, spec_value: 'XXL' },
|
||||
// { key: 1, groupKey: 1, spec_value: 'XL' }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
|
||||
/**
|
||||
* 商品 model类
|
||||
* GoodsModel
|
||||
*/
|
||||
export default class MultiSpec {
|
||||
// 商品多规格数据
|
||||
multiSpecData = {}
|
||||
|
||||
// 错误信息
|
||||
error = '';
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @param {array} specList 规格列表
|
||||
* @param {array} skuList SKU列表
|
||||
*/
|
||||
constructor () {
|
||||
this.multiSpecData = {
|
||||
// 规格列表
|
||||
specList: [],
|
||||
// SKU列表
|
||||
skuList: [],
|
||||
// SKU字段
|
||||
skuColumns: _.cloneDeep(defaultColumns),
|
||||
// 批量设置sku
|
||||
skuBatchForm: _.cloneDeep(defaultSkuItemData)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成并获取多规格数据
|
||||
getData (specList = [], skuList = []) {
|
||||
if (specList.length) {
|
||||
this.multiSpecData.specList = _.cloneDeep(specList)
|
||||
this.multiSpecData.skuList = _.cloneDeep(skuList)
|
||||
}
|
||||
// 整理所有的规格组
|
||||
const specGroupArr = this.specGroupArr()
|
||||
// sku记录的规格属性集(生成笛卡尔积)
|
||||
const cartesianList = cartesianProductOf(specGroupArr)
|
||||
// 合并单元格
|
||||
const rowSpanArr = this.rowSpanArr(specGroupArr, cartesianList)
|
||||
// 生成sku字段名
|
||||
this.buildSkuColumns(rowSpanArr)
|
||||
// 生成sku列表数据
|
||||
this.buildSkuList(cartesianList)
|
||||
// 返回多规格数据
|
||||
return this.multiSpecData
|
||||
}
|
||||
|
||||
// 数据是否为空
|
||||
isEmpty () {
|
||||
return this.multiSpecData.specList.length === 0
|
||||
}
|
||||
|
||||
// 返回错误信息
|
||||
getError () {
|
||||
return this.error
|
||||
}
|
||||
|
||||
// 整理所有的规格
|
||||
specGroupArr () {
|
||||
const specGroupArr = []
|
||||
this.multiSpecData.specList.forEach(specGroup => {
|
||||
const itemArr = []
|
||||
specGroup.valueList.forEach(value => {
|
||||
itemArr.push(value)
|
||||
})
|
||||
specGroupArr.push(itemArr)
|
||||
})
|
||||
return specGroupArr
|
||||
}
|
||||
|
||||
// 合并单元格
|
||||
rowSpanArr (specGroupArr, cartesianList) {
|
||||
const rowSpanArr = []
|
||||
var rowSpan = cartesianList.length
|
||||
for (let i = 0; i < specGroupArr.length; i++) {
|
||||
rowSpanArr[i] = parseInt(rowSpan / specGroupArr[i].length)
|
||||
rowSpan = rowSpanArr[i]
|
||||
}
|
||||
return rowSpanArr
|
||||
}
|
||||
|
||||
// 生成skuList
|
||||
buildSkuList (cartesianList) {
|
||||
// 生成新的skuList
|
||||
const newSkuList = []
|
||||
for (let i = 0; i < cartesianList.length; i++) {
|
||||
const newSkuItem = {
|
||||
...defaultSkuItemData,
|
||||
key: i,
|
||||
// skuKey用于合并旧记录
|
||||
skuKey: cartesianList[i].map(item => item.key).join('_'),
|
||||
// skuKeys用于传参给后端
|
||||
skuKeys: cartesianList[i].map(item => {
|
||||
return {
|
||||
groupKey: item.groupKey,
|
||||
valueKey: item.key
|
||||
}
|
||||
})
|
||||
}
|
||||
cartesianList[i].forEach((val, idx) => {
|
||||
newSkuItem[`spec_value_${idx}`] = val.spec_value
|
||||
})
|
||||
newSkuList.push(newSkuItem)
|
||||
}
|
||||
// 兼容旧的sku数据
|
||||
this.multiSpecData.skuList = this.oldSkuList(newSkuList)
|
||||
}
|
||||
|
||||
// 合并已存在的sku数据
|
||||
oldSkuList (newSkuList) {
|
||||
// const oldSkuList = _.cloneDeep(this.multiSpecData.skuList)
|
||||
const oldSkuList = this.multiSpecData.skuList.concat()
|
||||
if (!oldSkuList.length || !newSkuList.length) {
|
||||
return newSkuList
|
||||
}
|
||||
for (const index in newSkuList) {
|
||||
// 查找符合的旧记录
|
||||
let oldSkuItem = {}
|
||||
if (oldSkuList.length === newSkuList.length) {
|
||||
oldSkuItem = _.cloneDeep(oldSkuList[index])
|
||||
} else {
|
||||
oldSkuItem = oldSkuList.find(item => {
|
||||
return item.skuKey === newSkuList[index].skuKey
|
||||
})
|
||||
}
|
||||
// 写入新纪录
|
||||
if (oldSkuItem) {
|
||||
newSkuList[index] = {
|
||||
...newSkuList[index],
|
||||
..._.pick(oldSkuItem, Object.keys(defaultSkuItemData))
|
||||
}
|
||||
// console.log(newSkuList[index].image)
|
||||
}
|
||||
}
|
||||
return newSkuList
|
||||
}
|
||||
|
||||
// 生成sku表格字段名
|
||||
buildSkuColumns (rowSpanArr) {
|
||||
const specList = this.multiSpecData.specList
|
||||
const newColumns = defaultColumns.concat()
|
||||
// 渲染字段的rowSpan
|
||||
const customRender = (specIndex, value, row, index) => {
|
||||
const obj = {
|
||||
children: value,
|
||||
attrs: {}
|
||||
}
|
||||
const rowSpan = rowSpanArr[specIndex - 1]
|
||||
if ((index % rowSpan) === 0) {
|
||||
obj.attrs.rowSpan = rowSpan
|
||||
} else {
|
||||
obj.attrs.rowSpan = 0
|
||||
}
|
||||
return obj
|
||||
}
|
||||
// 遍历规格组整理字段
|
||||
for (let specIndex = specList.length; specIndex > 0; specIndex--) {
|
||||
const specGroupItem = specList[specIndex - 1]
|
||||
newColumns.unshift({
|
||||
title: specGroupItem.spec_name,
|
||||
dataIndex: `spec_value_${specIndex - 1}`,
|
||||
customRender: (value, row, index) => customRender(specIndex, value, row, index)
|
||||
})
|
||||
}
|
||||
this.multiSpecData.skuColumns = newColumns
|
||||
}
|
||||
|
||||
// 添加规格组
|
||||
handleAddSpecGroup () {
|
||||
const specList = this.multiSpecData.specList
|
||||
specList.push({
|
||||
key: specList.length || 0,
|
||||
spec_name: '',
|
||||
valueList: []
|
||||
})
|
||||
// 默认规格值
|
||||
const groupIndex = specList.length - 1
|
||||
this.handleAddSpecValue(groupIndex)
|
||||
}
|
||||
|
||||
// 添加规格值
|
||||
handleAddSpecValue (groupIndex) {
|
||||
const specGroupItem = this.multiSpecData.specList[groupIndex]
|
||||
const specValueList = specGroupItem.valueList
|
||||
specValueList.push({
|
||||
key: specValueList.length || 0,
|
||||
groupKey: specGroupItem.key,
|
||||
spec_value: ''
|
||||
})
|
||||
// 刷新规格值的key
|
||||
this.onRefreshSpecValueKey(groupIndex)
|
||||
}
|
||||
|
||||
// 删除规格组
|
||||
handleDeleteSpecGroup (groupIndex) {
|
||||
this.multiSpecData.specList.splice(groupIndex, 1)
|
||||
this.onUpdate(false)
|
||||
}
|
||||
|
||||
// 删除规格值
|
||||
handleDeleteSpecValue (groupIndex, valueIndex) {
|
||||
// 将规格值移出
|
||||
this.multiSpecData.specList[groupIndex].valueList.splice(valueIndex, 1)
|
||||
// 刷新规格值的key
|
||||
this.onRefreshSpecValueKey(groupIndex)
|
||||
this.onUpdate(false)
|
||||
}
|
||||
|
||||
// 刷新规格值的key
|
||||
onRefreshSpecValueKey (groupIndex) {
|
||||
const specGroupItem = this.multiSpecData.specList[groupIndex]
|
||||
const specValueList = specGroupItem.valueList
|
||||
specValueList.forEach((item, index) => {
|
||||
specValueList[index].key = index
|
||||
})
|
||||
}
|
||||
|
||||
// 批量设置sku事件
|
||||
handleSkuBatch () {
|
||||
const skuBatchForm = this.getFilterObject(this.multiSpecData.skuBatchForm)
|
||||
const skuList = this.multiSpecData.skuList
|
||||
// if (!skuBatchForm.image_id) {
|
||||
// delete skuBatchForm.image
|
||||
// }
|
||||
console.log('skuBatchForm', skuBatchForm)
|
||||
for (const index in skuList) {
|
||||
skuList[index] = { ...skuList[index], ...skuBatchForm }
|
||||
}
|
||||
this.onUpdate(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤对象的空元素
|
||||
* (仅支持一维对象)
|
||||
* @param {object} object 源对象
|
||||
* @returns {object}
|
||||
*/
|
||||
getFilterObject (object) {
|
||||
const newObj = {}
|
||||
for (const key in object) {
|
||||
const value = object[key]
|
||||
// value === 0 可以不过滤image_id为0的情况
|
||||
// if (!isEmpty(value) || value === 0) {
|
||||
// newObj[key] = value
|
||||
// }
|
||||
if (!isEmpty(value)) {
|
||||
newObj[key] = value
|
||||
}
|
||||
}
|
||||
return newObj
|
||||
}
|
||||
|
||||
// 表单验证
|
||||
verifyForm () {
|
||||
// 验证规格
|
||||
if (!this.verifySpec()) {
|
||||
return false
|
||||
}
|
||||
// 验证sku
|
||||
if (!this.verifySkuList()) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 验证sku
|
||||
verifySkuList () {
|
||||
const columns = [
|
||||
{ field: 'goods_price', name: '商品价格' },
|
||||
{ field: 'stock_num', name: '库存数量' },
|
||||
{ field: 'goods_weight', name: '商品重量' }
|
||||
]
|
||||
const skuList = this.multiSpecData.skuList
|
||||
for (const skuIndex in skuList) {
|
||||
const skuItem = skuList[skuIndex]
|
||||
for (const colIndex in columns) {
|
||||
const value = skuItem[columns[colIndex].field]
|
||||
if (value === '' || value === null) {
|
||||
this.error = `${columns[colIndex].name}不能为空`
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 验证规格
|
||||
verifySpec () {
|
||||
const specList = this.multiSpecData.specList
|
||||
if (!specList.length) {
|
||||
this.error = '亲,还没有添加规格组~'
|
||||
return false
|
||||
}
|
||||
for (const index in specList) {
|
||||
// 验证规格组
|
||||
const specGroup = specList[index]
|
||||
if (isEmpty(specGroup.spec_name)) {
|
||||
this.error = '规格组名称不能为空~'
|
||||
return false
|
||||
}
|
||||
// 验证规格值
|
||||
const valueList = specGroup.valueList
|
||||
if (!valueList.length) {
|
||||
this.error = '还没有添加规格值~'
|
||||
return false
|
||||
}
|
||||
for (const i in valueList) {
|
||||
if (isEmpty(valueList[i].spec_value)) {
|
||||
this.error = '规格值不能为空~'
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 获取规格及SKU信息(表单提交)
|
||||
getFromSpecData () {
|
||||
const { multiSpecData: { specList, skuList } } = this
|
||||
const specData = {
|
||||
specList: _.cloneDeep(specList),
|
||||
skuList: _.cloneDeep(skuList)
|
||||
}
|
||||
for (const skuIndex in specData.skuList) {
|
||||
const skuItem = specData.skuList[skuIndex]
|
||||
delete skuItem.image
|
||||
// delete skuItem.imageList
|
||||
delete skuItem.key
|
||||
}
|
||||
return specData
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用防抖节流方式刷新sku列表
|
||||
* @param {boolean} isDebounce 如果true则使用防抖函数
|
||||
*/
|
||||
onUpdate (isDebounce = true) {
|
||||
if (isDebounce) {
|
||||
debounce(getDataForDebounce, 200)(this)
|
||||
} else {
|
||||
getDataForDebounce(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// onUpdate调用的逻辑方法
|
||||
const getDataForDebounce = MultiSpecModel => {
|
||||
return MultiSpecModel.getData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成笛卡尔积数据
|
||||
* cartesianProductOf([arr1, arr2, arr3 ...])
|
||||
*/
|
||||
const cartesianProductOf = arrays => {
|
||||
if (!arrays.length) {
|
||||
return []
|
||||
}
|
||||
return Array.prototype.reduce.call(arrays, (arr1, arr2) => {
|
||||
var ret = []
|
||||
arr1.forEach(v1 => {
|
||||
arr2.forEach(v2 => {
|
||||
ret.push(v1.concat([v2]))
|
||||
})
|
||||
})
|
||||
return ret
|
||||
}, [[]])
|
||||
}
|
@ -1,407 +1,518 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-item label="商品规格" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<div v-if="true" class="form-item-help" style="line-height: 36px">
|
||||
<small>最多添加3个商品规格组,生成的SKU数量不能超出50个</small>
|
||||
<el-form-item :label-width="labelWidth" label="商品规格">
|
||||
<div style="display: block;width: 100%;">
|
||||
<!-- <el-input-number v-model.number="formData.goodsSpec" controls-position="right" :min="0.01"
|
||||
:precision="2" /> -->
|
||||
<div class="input-intro">最多添加3个商品规格组,生成的SKU数量不能超出50个</div>
|
||||
|
||||
<!-- 规格样式 -->
|
||||
<div class="sepc-big-box" v-for="(item, index) in goodsSpecList">
|
||||
<div class="sepc-title-box">
|
||||
<el-input v-model="item.specName" @change="handleChangeSepc(item, index)" class="spec-input" placeholder="规格组名称"
|
||||
clearable />
|
||||
<el-link type="primary" @click="handleDelSpec(item)">删除规格组</el-link>
|
||||
</div>
|
||||
<!-- 规格组 -->
|
||||
<div class="spec-group" v-for="(item, index) in multiSpecData.specList" :key="index">
|
||||
<div class="spec-group-item clearfix">
|
||||
<a-input
|
||||
class="group-item-input"
|
||||
v-model="item.spec_name"
|
||||
:readOnly="isSpecLocked"
|
||||
placeholder="请输入规格名称"
|
||||
@change="onChangeSpecGroupIpt"
|
||||
/>
|
||||
<a
|
||||
v-if="!isSpecLocked"
|
||||
class="group-item-delete"
|
||||
href="javascript:;"
|
||||
@click="handleDeleteSpecGroup(index)"
|
||||
>删除规格组</a>
|
||||
</div>
|
||||
<div class="spec-value clearfix">
|
||||
<div class="spec-value-item" v-for="(itm, idx) in item.valueList" :key="idx">
|
||||
<a-input
|
||||
class="value-item-input"
|
||||
v-model="itm.spec_value"
|
||||
:readOnly="isSpecLocked"
|
||||
placeholder="请输入规格值"
|
||||
@change="onChangeSpecValueIpt"
|
||||
/>
|
||||
<a-icon
|
||||
v-if="!isSpecLocked"
|
||||
class="icon-close"
|
||||
theme="filled"
|
||||
type="close-circle"
|
||||
@click="handleDeleteSpecValue(index, idx)"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="!isSpecLocked" class="spec-value-add">
|
||||
<a
|
||||
class="group-item-delete"
|
||||
href="javascript:;"
|
||||
@click="handleAddSpecValue(index)"
|
||||
>新增规格值</a>
|
||||
<div class="spec-value-box">
|
||||
<div class="spec-value-input-big-box">
|
||||
<div class="spec-value-input-box" v-for="specValue in item.props">
|
||||
<div class="spec-value-input-del" @click="handleDelSpecValue(item, specValue)"><el-icon>
|
||||
<Close />
|
||||
</el-icon></div>
|
||||
<el-input v-model="specValue.specValueName" @change="handleChangeSepcValue(item, specValue)"
|
||||
class="spec-value-input" placeholder="规格值名称" clearable />
|
||||
</div>
|
||||
</div>
|
||||
<el-link type="primary" v-if="isAddSpecValueMax" @click="handleAddSpecValue(item)">添加规格值</el-link>
|
||||
</div>
|
||||
<!-- 添加规格按钮 -->
|
||||
<a-button
|
||||
v-if="!isSpecLocked && multiSpecData.specList.length < 3"
|
||||
class="spec-group-add-btn"
|
||||
icon="plus"
|
||||
@click="handleAddSpecGroup"
|
||||
>添加规格组</a-button>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-show="multiSpecData.skuList.length"
|
||||
label="SKU列表"
|
||||
:labelCol="labelCol"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<!-- 批量设置 -->
|
||||
<div v-if="multiSpecData.skuList.length > 1" class="sku-batch">
|
||||
<span class="title">批量设置:</span>
|
||||
<a-input-number
|
||||
v-model="multiSpecData.skuBatchForm.goods_price"
|
||||
placeholder="商品价格"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
/>
|
||||
<a-input-number
|
||||
v-model="multiSpecData.skuBatchForm.line_price"
|
||||
placeholder="划线价格"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
<a-input-number
|
||||
v-model="multiSpecData.skuBatchForm.stock_num"
|
||||
placeholder="库存数量"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
/>
|
||||
<a-input-number
|
||||
v-model="multiSpecData.skuBatchForm.goods_weight"
|
||||
placeholder="商品重量"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
<a-input v-model="multiSpecData.skuBatchForm.goods_sku_no" placeholder="sku编码" />
|
||||
<a-button @click="handleSkuBatch">立即设置</a-button>
|
||||
</div>
|
||||
<!-- sku列表table -->
|
||||
<a-table
|
||||
class="sku-list"
|
||||
:columns="multiSpecData.skuColumns"
|
||||
:dataSource="multiSpecData.skuList"
|
||||
:scroll="{ x: true }"
|
||||
:pagination="false"
|
||||
bordered
|
||||
>
|
||||
<!-- 预览图 -->
|
||||
<template slot="image" slot-scope="text, item">
|
||||
<SelectImage
|
||||
v-model="item.image_id"
|
||||
:defaultList="(item.image_id > 0 && item.image) ? [item.image] : []"
|
||||
:width="50"
|
||||
/>
|
||||
|
||||
<el-button v-if="isAddSpecMax" class="mt-5" @click="handleAddSpec">
|
||||
<el-icon class="avatar-uploader-icon">
|
||||
<plus />
|
||||
</el-icon>
|
||||
添加规格组
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<!-- Sku列表 -->
|
||||
<el-form-item :label-width="labelWidth" label="Sku列表">
|
||||
|
||||
<!-- sku列表 -->
|
||||
<el-table :data="skuList" border style="width: 100%" :span-method="objectSpanMethod">
|
||||
<!-- 动态列 -->
|
||||
<el-table-column v-for="column in skuColumns" :prop="column.prop" :label="column.label" :key="column.key"
|
||||
:width="column.width">
|
||||
</el-table-column>
|
||||
|
||||
<!-- <el-table-column prop="goodsSkuPrice" label="预览图">
|
||||
<template #default="scope">
|
||||
<UploadImage ref="uploadRef" v-model="scope.row.goodsSkuImg" :data=imgData :limit="1"
|
||||
:fileSize="5" :drag="true" :isShowTip="false" />
|
||||
</template>
|
||||
<!-- 商品价格 -->
|
||||
<template slot="goods_price" slot-scope="text, item">
|
||||
<a-input-number v-model="item.goods_price" size="small" :min="0.01" :precision="2" />
|
||||
</el-table-column> -->
|
||||
|
||||
<el-table-column prop="goodsSkuPrice" label="商品价格">
|
||||
<template #default="scope">
|
||||
<el-input-number v-model.number="scope.row.goodsSkuPrice" controls-position="right" :min="0" :precision="2" />
|
||||
</template>
|
||||
<!-- 划线价格 -->
|
||||
<template slot="line_price" slot-scope="text, item">
|
||||
<a-input-number v-model="item.line_price" size="small" :min="0" :precision="2" />
|
||||
</template>
|
||||
<!-- 库存数量 -->
|
||||
<template slot="stock_num" slot-scope="text, item">
|
||||
<a-input-number v-model="item.stock_num" size="small" :min="0" :precision="0" />
|
||||
</template>
|
||||
<!-- 商品重量 -->
|
||||
<template slot="goods_weight" slot-scope="text, item">
|
||||
<a-input-number v-model="item.goods_weight" size="small" :min="0" :precision="2" />
|
||||
</template>
|
||||
<!-- sku编码 -->
|
||||
<template slot="goods_sku_no" slot-scope="text, item">
|
||||
<a-input v-model="item.goods_sku_no" size="small" />
|
||||
</template>
|
||||
</a-table>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PropTypes from 'ant-design-vue/es/_util/vue-types'
|
||||
import MultiSpecModel from '@/common/model/goods/MultiSpec'
|
||||
import { SelectImage } from '@/components'
|
||||
<script setup>
|
||||
import descartes from "./dikaerji";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SelectImage
|
||||
},
|
||||
props: {
|
||||
// 默认的规格列表
|
||||
defaultSpecList: PropTypes.array.def([]),
|
||||
// 默认的SKU列表
|
||||
defaultSkuList: PropTypes.array.def([]),
|
||||
// 商品规格是否锁定(锁定状态下不允许编辑规格)
|
||||
isSpecLocked: PropTypes.bool.def(false)
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 标签布局属性
|
||||
labelCol: { span: 3 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 21 },
|
||||
// 商品多规格模型
|
||||
MultiSpecModel: new MultiSpecModel(),
|
||||
// MultiSpecModel: Object,
|
||||
multiSpecData: {
|
||||
// 规格列表
|
||||
specList: [],
|
||||
// SKU列表
|
||||
skuList: []
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultSpecList (val) {
|
||||
if (val.length && this.MultiSpecModel.isEmpty()) {
|
||||
this.getData()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 初始化数据
|
||||
created () {
|
||||
// 获取规格及SKU信息
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 获取规格及SKU信息(展示)
|
||||
getData () {
|
||||
const { defaultSpecList, defaultSkuList } = this
|
||||
this.multiSpecData = this.MultiSpecModel.getData(defaultSpecList, defaultSkuList)
|
||||
},
|
||||
/** 商品规格 业务参数 */
|
||||
|
||||
// 获取规格及SKU信息(表单提交)
|
||||
getFromSpecData () {
|
||||
return this.MultiSpecModel.getFromSpecData()
|
||||
},
|
||||
// 添加商品规格按钮状态
|
||||
const isAddSpecMax = ref(true)
|
||||
const isAddSpecValueMax = ref(true)
|
||||
|
||||
// 添加规格组
|
||||
handleAddSpecGroup () {
|
||||
if (this.checkSkuMaxNum()) {
|
||||
this.MultiSpecModel.handleAddSpecGroup()
|
||||
}
|
||||
},
|
||||
// 动态表头
|
||||
const skuColumns = ref([
|
||||
// {
|
||||
// prop: 'specValue',
|
||||
// label: '颜色',
|
||||
// width: '100'
|
||||
// },
|
||||
// {
|
||||
// prop: 'specSecondValue',
|
||||
// label: '内存',
|
||||
// width: '100'
|
||||
// },
|
||||
// {
|
||||
// prop: 'specThirdValue',
|
||||
// label: '版本',
|
||||
// width: '100'
|
||||
// },
|
||||
])
|
||||
|
||||
// 删除规格组
|
||||
handleDeleteSpecGroup (groupIndex) {
|
||||
const app = this
|
||||
const modal = this.$confirm({
|
||||
title: '您确定要删除该规格组吗?',
|
||||
content: '删除后不可恢复',
|
||||
onOk () {
|
||||
// 删除元素
|
||||
app.MultiSpecModel.handleDeleteSpecGroup(groupIndex)
|
||||
// 关闭对话框
|
||||
modal.destroy()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 新增规格值
|
||||
handleAddSpecValue (groupIndex) {
|
||||
if (this.checkSkuMaxNum()) {
|
||||
this.MultiSpecModel.handleAddSpecValue(groupIndex)
|
||||
}
|
||||
},
|
||||
|
||||
// 删除规格值
|
||||
handleDeleteSpecValue (groupIndex, valueIndex) {
|
||||
const app = this
|
||||
const modal = this.$confirm({
|
||||
title: '您确定要删除该规格值吗?',
|
||||
content: '删除后不可恢复',
|
||||
onOk () {
|
||||
// 删除元素
|
||||
app.MultiSpecModel.handleDeleteSpecValue(groupIndex, valueIndex)
|
||||
// 关闭对话框
|
||||
modal.destroy()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 规格组输入框change事件
|
||||
onChangeSpecGroupIpt () {
|
||||
// 更新skuList
|
||||
this.MultiSpecModel.onUpdate(true)
|
||||
},
|
||||
|
||||
// 规格值输入框change事件
|
||||
onChangeSpecValueIpt (event, itm) {
|
||||
// 更新skuList
|
||||
this.MultiSpecModel.onUpdate(true)
|
||||
},
|
||||
|
||||
// 验证最大sku数量
|
||||
checkSkuMaxNum () {
|
||||
const skuList = this.multiSpecData.skuList
|
||||
if (skuList.length >= 50) {
|
||||
this.$message.error(`生成的sku列表数量不能大于50个,当前数量:${skuList.length}个`, 2.5)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
|
||||
// 批量设置sku事件
|
||||
handleSkuBatch () {
|
||||
this.MultiSpecModel.handleSkuBatch()
|
||||
},
|
||||
|
||||
// 验证多规格表单
|
||||
verifyForm () {
|
||||
if (!this.MultiSpecModel.verifyForm()) {
|
||||
this.$message.error(this.MultiSpecModel.getError(), 2)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// 商品多规格
|
||||
.spec-group {
|
||||
width: 895px;
|
||||
margin-bottom: 15px;
|
||||
line-height: normal;
|
||||
|
||||
.ant-input {
|
||||
height: 28px;
|
||||
padding: 4px 11px;
|
||||
font-size: @font-size-base;
|
||||
line-height: 1.5;
|
||||
|
||||
&::placeholder {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-help {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.spec-group-item {
|
||||
background: #f4f5f9;
|
||||
padding: 7px 12px;
|
||||
line-height: 28px;
|
||||
|
||||
.group-item-input {
|
||||
float: left;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.group-item-delete {
|
||||
font-size: 12px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.spec-value {
|
||||
background: #fbfbfb;
|
||||
padding: 8px 35px;
|
||||
|
||||
.spec-value-add,
|
||||
.spec-value-item {
|
||||
float: left;
|
||||
margin-bottom: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.spec-value-add {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
|
||||
a {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.spec-value-item {
|
||||
position: relative;
|
||||
margin-right: 20px;
|
||||
|
||||
.value-item-input {
|
||||
width: 186px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon-close {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-close {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #7d7d7d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加规格按钮
|
||||
.spec-group-add-btn {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
// 批量设置sku
|
||||
.sku-batch {
|
||||
line-height: 40px;
|
||||
margin-bottom: 12px;
|
||||
.title {
|
||||
line-height: 28px;
|
||||
margin-right: 15px;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
/deep/.ant-input,
|
||||
/deep/.ant-input-number {
|
||||
width: 120px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
/deep/.ant-input {
|
||||
width: 140px;
|
||||
}
|
||||
}
|
||||
// 规格组
|
||||
const goodsSpecList = ref([
|
||||
// 规格值Json属性
|
||||
// {
|
||||
// specId: 0,
|
||||
// specName: "",
|
||||
// props: [
|
||||
// {
|
||||
// specValueId: 0,
|
||||
// specValueName: "",
|
||||
// specValue: "",
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
])
|
||||
|
||||
// sku列表
|
||||
.sku-list {
|
||||
width: 895px;
|
||||
/deep/.ant-table-thead > tr > th,
|
||||
/deep/.ant-table-tbody > tr > td {
|
||||
white-space: nowrap;
|
||||
const skuList = ref([
|
||||
])
|
||||
|
||||
|
||||
/** sku列表参数 */
|
||||
const newList = ref([])
|
||||
const newData = ref([])
|
||||
const tableData7 = ref([])
|
||||
const spanArr = ref([])
|
||||
const spanArr1 = ref([])
|
||||
const pos = ref("")
|
||||
const pos1 = ref("")
|
||||
|
||||
|
||||
|
||||
/** sku列表方法 */
|
||||
|
||||
|
||||
//处理数据(拆分规格组里的规格值为数组)
|
||||
const processing = () => {
|
||||
newData.value = [];
|
||||
for (let i = 0; i < goodsSpecList.value.length; i++) {
|
||||
var newlist = [];
|
||||
for (
|
||||
let index = 0;
|
||||
index < goodsSpecList.value[i].props.length;
|
||||
index++
|
||||
) {
|
||||
newlist.push(goodsSpecList.value[i].props[index].specValueName);
|
||||
}
|
||||
/deep/.ant-table-tbody > tr > td {
|
||||
padding: 12px 18px;
|
||||
this.newData.push(newlist);
|
||||
}
|
||||
console.log(this.newData, '各规格组中的规格值');
|
||||
getList();
|
||||
}
|
||||
|
||||
/deep/.ant-input-sm,
|
||||
/deep/.ant-input-number-sm {
|
||||
height: 28px;
|
||||
|
||||
//转换数据
|
||||
const getList = () => {
|
||||
tableData7.value = [];
|
||||
newList.value = this.descartes(newData.value);
|
||||
console.log(newList.value, '笛卡尔积处理过后的数据');
|
||||
for (let index = 0; index < newList.value.length; index++) {
|
||||
this.tableData7.push({
|
||||
specValue: newList.value[index][0],
|
||||
specSecondValue: newList.value[index][1],
|
||||
specThirdValue: newList.value[index][2],
|
||||
goodsGuid: 0,
|
||||
specValueName: "",
|
||||
goodsSkuImg: "",
|
||||
goodsSkuSkuCode: 0,
|
||||
goodsSkuPrice: 0,
|
||||
goodsSkuLinePrice: 0,
|
||||
goodsSkuStockNum: 0,
|
||||
goodsSkuWeight: 0,
|
||||
goodsSkuProps: ""
|
||||
});
|
||||
}
|
||||
/deep/.ant-input-number-sm input {
|
||||
height: 26px;
|
||||
|
||||
getSpanArr(this.tableData7);
|
||||
console.log(this.tableData7, '表格中的数据');
|
||||
}
|
||||
|
||||
|
||||
//计算位置的方法
|
||||
const getSpanArr = (data) => {
|
||||
spanArr.value = [];
|
||||
pos.value = "";
|
||||
spanArr1.value = [];
|
||||
pos1.value = "";
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (i === 0) {
|
||||
spanArr.value.push(1);
|
||||
pos.value = 0;
|
||||
} else {
|
||||
// 判断当前元素与上一个元素是否相同
|
||||
if (data[i].specValue === data[i - 1].specValue) {
|
||||
spanArr.value[pos.value] += 1;
|
||||
spanArr.value.push(0);
|
||||
} else {
|
||||
spanArr.value.push(1);
|
||||
pos.value = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (i === 0) {
|
||||
spanArr1.value.push(1);
|
||||
pos1.value = 0;
|
||||
} else {
|
||||
//如果笛卡尔积一直递增下去的话 这是一个很蠢的方法 由于我的要求层数是已知的 这里偷懒了 不然应该用for循环
|
||||
if (data[i].specSecondValue === data[i - 1].specSecondValue) {
|
||||
spanArr1.value[pos1.value] += 1;
|
||||
spanArr1.value.push(0);
|
||||
} else {
|
||||
spanArr1.value.push(1);
|
||||
pos1.value = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(this.spanArr, '排序Arr');
|
||||
}
|
||||
|
||||
|
||||
// 合并行数
|
||||
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
||||
// columnIndex === 0 找到第一列,实现合并随机出现的行数
|
||||
if (columnIndex === 0) {
|
||||
const _row = spanArr.value[rowIndex];
|
||||
const _col = _row > 0 ? 1 : 0;
|
||||
return {
|
||||
rowspan: _row,
|
||||
colspan: _col
|
||||
};
|
||||
// columnIndex === 1 找到第二列,合并他的列数
|
||||
} else if (columnIndex === 1) {
|
||||
const _row = spanArr1.value[rowIndex];
|
||||
const _col = _row > 0 ? 1 : 0;
|
||||
return {
|
||||
rowspan: _row,
|
||||
colspan: _col
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 合并列表
|
||||
// const objectSpanMethod = ({
|
||||
// row,
|
||||
// column,
|
||||
// rowIndex,
|
||||
// columnIndex,
|
||||
// }) => {
|
||||
// // if (columnIndex === 0) {
|
||||
// // if (rowIndex % firstLen === 0) {
|
||||
// // return {
|
||||
// // rowspan: firstLen,
|
||||
// // colspan: 1,
|
||||
// // }
|
||||
// // } else {
|
||||
// // return {
|
||||
// // rowspan: 0,
|
||||
// // colspan: 0,
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // if (columnIndex === 1) {
|
||||
// // if (rowIndex % secondLen === 0) {
|
||||
// // return {
|
||||
// // rowspan: secondLen,
|
||||
// // colspan: 1,
|
||||
// // }
|
||||
// // } else {
|
||||
// // return {
|
||||
// // rowspan: 0,
|
||||
// // colspan: 0,
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// }
|
||||
|
||||
// let firstLen = 0
|
||||
// let secondLen = 0
|
||||
// skuList.value.map((item, idx) => {
|
||||
// let firstVal = skuList?.value[0].specValue
|
||||
// if (item.specValue === firstVal) {
|
||||
// firstLen += 1
|
||||
// firstVal = item.specValue
|
||||
// }
|
||||
|
||||
// // let secondVal = skuList?.value[0].specSecondValue
|
||||
// // if (item.specSecondValue === secondVal) {
|
||||
// // secondLen += 1
|
||||
// // secondVal = item.specSecondValue
|
||||
// // }
|
||||
// })
|
||||
// console.log(secondLen, '第二列');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** 商品规格 业务方法 */
|
||||
|
||||
// 添加规格组
|
||||
function handleAddSpec() {
|
||||
let data = {
|
||||
specId: 0,
|
||||
specName: "",
|
||||
key: 0,
|
||||
props: [
|
||||
|
||||
]
|
||||
}
|
||||
goodsSpecList.value.push(data)
|
||||
|
||||
if (goodsSpecList.value.length == 3) {
|
||||
isAddSpecMax.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 修改规格组
|
||||
function handleChangeSepc(item, idx) {
|
||||
|
||||
item.key = idx
|
||||
let foundMatch = false;
|
||||
skuColumns.value.map((i, index) => {
|
||||
if (i.key == idx) {
|
||||
i.label = item.specName
|
||||
foundMatch = true
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
if (foundMatch) {
|
||||
return; // 停止执行后续代码
|
||||
}
|
||||
|
||||
// 添加动态表头
|
||||
let column = {
|
||||
prop: 'specValue',
|
||||
label: item.specName,
|
||||
width: '100',
|
||||
key: idx
|
||||
}
|
||||
skuColumns.value.push(column)
|
||||
|
||||
}
|
||||
|
||||
// 删除规格组
|
||||
function handleDelSpec(item) {
|
||||
const index = goodsSpecList.value.indexOf(item);
|
||||
if (index > -1) {
|
||||
goodsSpecList.value.splice(index, 1);
|
||||
}
|
||||
|
||||
if (goodsSpecList.value.length < 3) {
|
||||
isAddSpecMax.value = true
|
||||
}
|
||||
|
||||
|
||||
// 输出对应的表头
|
||||
skuColumns.value = skuColumns.value.filter(column => column.label !== item.specName);
|
||||
|
||||
// 删除对应的sku
|
||||
// skuColumns.value = skuColumns.value.filter(column => column.specName !== item.specName);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 添加规格值
|
||||
function handleAddSpecValue(item) {
|
||||
let data = {
|
||||
specId: 0,
|
||||
specValueId: 0,
|
||||
specValueName: "",
|
||||
}
|
||||
item.props.push(data)
|
||||
|
||||
if (item.props.length == 50) {
|
||||
isAddSpecValueMax.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 修改规格值
|
||||
function handleChangeSepcValue(item, specValue) {
|
||||
|
||||
let firstSpecValue = ""
|
||||
let secondSpecValue = ""
|
||||
let thirdSpecValue = ""
|
||||
|
||||
console.log(item, 'item喵喵喵喵喵喵');
|
||||
// goodsSpecList.value.map((item,index) => {
|
||||
// if(item.key === 0){
|
||||
// firstSpecValue = specValue.specValueName
|
||||
// }
|
||||
// if(item.key === 1){
|
||||
// secondSpecValue = specValue.specValueName
|
||||
// }
|
||||
// if(item.key === 2){
|
||||
// thirdSpecValue = specValue.specValueName
|
||||
// }
|
||||
// })
|
||||
|
||||
// 添加sku
|
||||
let sku = {
|
||||
specValue: firstSpecValue,
|
||||
specSecondValue: secondSpecValue,
|
||||
specThirdValue: thirdSpecValue,
|
||||
goodsGuid: 0,
|
||||
specValueName: "",
|
||||
goodsSkuImg: "",
|
||||
goodsSkuSkuCode: 0,
|
||||
goodsSkuPrice: 0,
|
||||
goodsSkuLinePrice: 0,
|
||||
goodsSkuStockNum: 0,
|
||||
goodsSkuWeight: 0,
|
||||
goodsSkuProps: ""
|
||||
}
|
||||
skuList.value.push(sku)
|
||||
|
||||
console.log(skuList.value, 'asdasd-------------');
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 删除规格值
|
||||
function handleDelSpecValue(item, specValue) {
|
||||
const index = item.props.indexOf(specValue);
|
||||
if (index > -1) {
|
||||
item.props.splice(index, 1);
|
||||
}
|
||||
|
||||
if (item.props.length < 50) {
|
||||
isAddSpecValueMax.value = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.divider-title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.input-intro {
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
.sepc-big-box {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sepc-title-box {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #f4f4f5;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.spec-value-box {
|
||||
width: 100%;
|
||||
padding: 20px 20px 20px 40px;
|
||||
background-color: #fbfbfb;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.spec-value-input-big-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.spec-value-input-box {
|
||||
width: 250px;
|
||||
position: relative;
|
||||
margin-right: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.spec-value-input-del {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
z-index: 99;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: grey;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.spec-input {
|
||||
width: 250px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.el-input-number {
|
||||
width: 140px;
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,226 @@
|
||||
// const skuList = ref([
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "4+128G",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "4+128G",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "8+256G",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "8+256G",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "12+1T",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "12+1T",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "1000G",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "蓝色",
|
||||
// specSecondValue: "1000G",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "4+128G",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "4+128G",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "8+256G",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "8+256G",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "12+1T",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "12+1T",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "1000G",
|
||||
// specThirdValue: "5G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// {
|
||||
// specValue: "黑色",
|
||||
// specSecondValue: "1000G",
|
||||
// specThirdValue: "4G",
|
||||
// goodsGuid: 0,
|
||||
// specValueName: "",
|
||||
// goodsSkuImg: "",
|
||||
// goodsSkuSkuCode: 0,
|
||||
// goodsSkuPrice: 10,
|
||||
// goodsSkuLinePrice: 0,
|
||||
// goodsSkuStockNum: 0,
|
||||
// goodsSkuWeight: 0,
|
||||
// goodsSkuProps: ""
|
||||
// },
|
||||
// ])
|
@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
//笛卡尔积算法
|
||||
function descartes(array){
|
||||
|
||||
if( array.length < 2 ) return array[0] || [];
|
||||
return [].reduce.call(array, function(col, set) {
|
||||
var res = [];
|
||||
col.forEach(function(c) {
|
||||
set.forEach(function(s) {
|
||||
var t = [].concat( Array.isArray(c) ? c : [c] );
|
||||
t.push(s);
|
||||
res.push(t);
|
||||
})});
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
export default descartes
|
Loading…
Reference in New Issue
Block a user