You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
421 lines
10 KiB
421 lines
10 KiB
|
|
import _ from 'lodash'
|
|
import { debounce, isEmpty } from '@/utils/util'
|
|
|
|
// 默认的sku字段属性
|
|
const defaultColumns = [
|
|
{
|
|
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: '套餐内容',
|
|
dataIndex: 'content',
|
|
width: 310,
|
|
scopedSlots: { customRender: 'content' }
|
|
},
|
|
]
|
|
|
|
// 默认的sku记录值
|
|
const defaultSkuItemData = {
|
|
image_id: 0,
|
|
image: {},
|
|
// imageList: [],
|
|
goods_price: '',
|
|
line_price: '',
|
|
stock_num: '',
|
|
vname:'',
|
|
content: [
|
|
],
|
|
}
|
|
|
|
// 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,ggtj) {
|
|
console.log(ggtj)
|
|
const specGroupItem = this.multiSpecData.specList[groupIndex]
|
|
const specValueList = specGroupItem.valueList
|
|
specValueList.push({
|
|
key: specValueList.length || 0,
|
|
groupKey: specGroupItem.key,
|
|
spec_value: ggtj
|
|
})
|
|
|
|
this.getData(this.multiSpecData.specList,this.multiSpecData.skuList)
|
|
}
|
|
|
|
// 删除规格组
|
|
handleDeleteSpecGroup (groupIndex) {
|
|
this.multiSpecData.specList.splice(groupIndex, 1)
|
|
this.onUpdate(false)
|
|
}
|
|
|
|
// 删除规格值
|
|
handleDeleteSpecValue (groupIndex, valueIndex) {
|
|
this.multiSpecData.specList[groupIndex].valueList.splice(valueIndex, 1)
|
|
this.onUpdate(false)
|
|
}
|
|
|
|
// 批量设置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: '商品重量' },
|
|
{ field: 'content', 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) {
|
|
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
|
|
}, [[]])
|
|
}
|