吉媒互动平台前端
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

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
}, [[]])
}