fix(GoodsStock.vue): 笛卡尔积生成动态sku表格时合并单元格span-method方法TypeScript编译不通过问题,此页面暂不使用TS语法。

This commit is contained in:
郝先瑞
2022-01-23 00:38:15 +08:00
parent c816a19172
commit dfcbe3e644

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="components-container"> <div class="component-container">
<div class="components-container__main"> <div class="component-container__main">
<el-card class="box-card"> <el-card class="box-card">
<template #header> <template #header>
<span>商品规格</span> <span>商品规格</span>
@@ -73,7 +73,7 @@
</div> </div>
<el-input <el-input
v-if="tagInputs[scope.$index].visible" v-if="tagInputs.length>0 &&tagInputs[scope.$index].visible"
v-model="tagInputs[scope.$index].value" v-model="tagInputs[scope.$index].value"
@keyup.enter.native="handleSpecValueInput(scope.$index)" @keyup.enter.native="handleSpecValueInput(scope.$index)"
@blur="handleSpecValueInput(scope.$index)" @blur="handleSpecValueInput(scope.$index)"
@@ -118,11 +118,11 @@
:inline="true" :inline="true"
> >
<el-table <el-table
:data="skuForm.skuList" :data="skuForm.skuList"
:span-method="handleCellMerge" :span-method="objectSpanMethod"
highlight-current-row highlight-current-row
size="mini" size="mini"
fit
border border
> >
@@ -161,30 +161,33 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-form> </el-form>
</el-card> </el-card>
</div> </div>
<div class="components-container__footer"> <div class="component-container__footer">
<el-button @click="handlePrev">上一步设置商品属性</el-button> <el-button @click="handlePrev">上一步设置商品属性</el-button>
<el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup>
import {listAttributes} from "@/api/pms/attribute"; import {listAttributes} from "@/api/pms/attribute";
import SingleUpload from '@/components/Upload/SingleUpload.vue' import SingleUpload from '@/components/Upload/SingleUpload.vue'
import Sortable from 'sortablejs' // import Sortable from 'sortablejs'
import {addGoods, updateGoods} from "@/api/pms/goods"; import {addGoods, updateGoods} from "@/api/pms/goods";
import {computed, getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs, unref, watch} from "vue"; import {computed, getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs, unref, watch} from "vue";
import {ElMessage, ElTable, ElForm} from "element-plus" import {ElNotification,ElMessage, ElTable, ElForm} from "element-plus"
import {Plus, Minus} from '@element-plus/icons' import {Plus, Minus} from '@element-plus/icons'
import SvgIcon from '@/components/SvgIcon/index.vue' import SvgIcon from '@/components/SvgIcon/index.vue'
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
const emit = defineEmits(['prev', 'next']) const emit = defineEmits(['prev', 'next'])
const proxy = getCurrentInstance() as any const proxy = getCurrentInstance()
const router = useRouter() const router = useRouter()
const specTableRef = ref(ElTable) const specTableRef = ref(ElTable)
@@ -202,7 +205,7 @@ const categoryId = computed(() => props.modelValue.categoryId);
const state = reactive({ const state = reactive({
specForm: { specForm: {
specList: [{}] as Array<any>, specList: []
}, },
skuForm: { skuForm: {
skuList: [] skuList: []
@@ -233,12 +236,13 @@ watch(categoryId, (newVal, oldVal) => {
listAttributes({categoryId: newVal, type: 1}).then(response => { listAttributes({categoryId: newVal, type: 1}).then(response => {
const specList = response.data const specList = response.data
if (specList && specList.length > 0) { if (specList && specList.length > 0) {
specList.forEach((item: any) => { specList.forEach((item) => {
state.specForm.specList.push({ state.specForm.specList.push({
name: item.name, name: item.name,
values: [] values: []
}) })
}) })
loadData()
} }
}) })
} }
@@ -252,44 +256,42 @@ watch(categoryId, (newVal, oldVal) => {
function loadData() { function loadData() {
const goodsId = props.modelValue.id const goodsId = props.modelValue.id
// 编辑数据加载
if (goodsId) {
props.modelValue.specList.forEach((specItem: any) => {
const specIndex = state.specForm.specList.findIndex(item => item.name == specItem.name)
if (specIndex > -1) {
state.specForm.specList[specIndex].values.push({
id: specItem.id,
value: specItem.value,
picUrl: specItem.picUrl
})
} else {
state.specForm.specList.push({
name: specItem.name,
values: [{id: specItem.id, value: specItem.value, picUrl: specItem.picUrl}]
})
}
})
// 每个规格项追加一个添加规格值按钮 props.modelValue.specList.forEach((specItem) => {
for (let i = 0; i < state.specForm.specList.length; i++) { const specIndex = state.specForm.specList.findIndex(item => item.name == specItem.name)
state.tagInputs.push({'value': undefined, 'visible': false}) if (specIndex > -1) {
state.specForm.specList[specIndex].values.push({
id: specItem.id,
value: specItem.value,
picUrl: specItem.picUrl
})
} else {
state.specForm.specList.push({
name: specItem.name,
values: [{id: specItem.id, value: specItem.value, picUrl: specItem.picUrl}]
})
} }
})
// SKU规格ID拼接字符串处理 // 每个规格项追加一个添加规格值按钮
props.modelValue.skuList.forEach((sku: any) => { for (let i = 0; i < state.specForm.specList.length; i++) {
sku.specIdArr = sku.specIds.split('_') state.tagInputs.push({'value': undefined, 'visible': false})
})
generateSkuList()
handleSpecChange()
handleSpecReorder()
nextTick(() => {
registerSpecDragSortEvent()
})
} }
// SKU规格ID拼接字符串处理
props.modelValue.skuList.forEach((sku) => {
sku.specIdArr = sku.specIds.split('_')
})
generateSkuList()
handleSpecChange()
handleSpecReorder()
nextTick(() => {
// registerSpecDragSortEvent()
})
} }
/** /**
@@ -297,7 +299,7 @@ function loadData() {
*/ */
function handleSpecChange() { function handleSpecChange() {
const specList = JSON.parse(JSON.stringify(state.specForm.specList)) const specList = JSON.parse(JSON.stringify(state.specForm.specList))
state.specTitles = specList.map((item: any) => item.name) state.specTitles = specList.map((item) => item.name)
} }
/** /**
@@ -312,7 +314,7 @@ function handleSpecReorder() {
/** /**
* 注册拖拽排序事件 * 注册拖拽排序事件
*/ */
function registerSpecDragSortEvent() { /*function registerSpecDragSortEvent() {
const el = specTableRef.value.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0] const el = specTableRef.value.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
Sortable.create(el, { Sortable.create(el, {
ghostClass: 'sortable-ghost', // Class name for the drop placeholder, ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
@@ -329,7 +331,7 @@ function registerSpecDragSortEvent() {
handleSpecReorder() handleSpecReorder()
} }
}) })
} }*/
/** /**
* 根据商品规格笛卡尔积生成SKU列表 * 根据商品规格笛卡尔积生成SKU列表
@@ -342,11 +344,11 @@ function registerSpecDragSortEvent() {
*/ */
function generateSkuList() { function generateSkuList() {
const specList = JSON.parse(JSON.stringify(state.specForm.specList.filter(item => item.values.length > 0))) // 深拷贝取有属性的规格项否则笛卡尔积运算得到的SKU列表值为空 const specList = JSON.parse(JSON.stringify(state.specForm.specList.filter(item => item.values.length > 0))) // 深拷贝取有属性的规格项否则笛卡尔积运算得到的SKU列表值为空
const skuList = specList.reduce((acc: any, curr: any) => { const skuList = specList.reduce((acc, curr) => {
let result = [] as any let result = []
acc.forEach((item: any) => { acc.forEach((item) => {
// curr => { 'id':1,'name':'颜色','values':[{id:1,value:'白色'},{id:2,value:'黑色'},{id:3,value:'蓝色'}] } // curr => { 'id':1,'name':'颜色','values':[{id:1,value:'白色'},{id:2,value:'黑色'},{id:3,value:'蓝色'}] }
curr.values.forEach((v: any) => { // v=>{id:1,value:'白色'} curr.values.forEach((v) => { // v=>{id:1,value:'白色'}
let temp = Object.assign({}, item) let temp = Object.assign({}, item)
temp.specValues += v.value + '_' // 规格值拼接 temp.specValues += v.value + '_' // 规格值拼接
temp.specIds += v.id + '|' // 规格ID拼接 temp.specIds += v.id + '|' // 规格ID拼接
@@ -356,14 +358,14 @@ function generateSkuList() {
return result return result
}, [{specValues: '', specIds: ''}]) }, [{specValues: '', specIds: ''}])
skuList.forEach((item: any) => { skuList.forEach((item) => {
item.specIds = item.specIds.substring(0, item.specIds.length - 1) item.specIds = item.specIds.substring(0, item.specIds.length - 1)
item.name = item.specValues.substring(0, item.specIds.length - 1).replaceAll('_', ' ') item.name = item.specValues.substring(0, item.specIds.length - 1).replaceAll('_', ' ')
const specIdArr = item.specIds.split('|') const specIdArr = item.specIds.split('|')
const skus = props.modelValue.skuList.filter((sku: any) => const skus = props.modelValue.skuList.filter((sku) =>
sku.specIdArr.length === specIdArr.length && sku.specIdArr.length === specIdArr.length &&
sku.specIdArr.every((a: number) => specIdArr.some((b: number) => a === b)) && sku.specIdArr.every((a) => specIdArr.some((b) => a === b)) &&
specIdArr.every((x: number) => sku.specIdArr.some((y: number) => x === y)) specIdArr.every((x) => sku.specIdArr.some((y) => x === y))
) // 数据库的SKU列表 ) // 数据库的SKU列表
if (skus && skus.length > 0) { if (skus && skus.length > 0) {
@@ -374,11 +376,11 @@ function generateSkuList() {
item.stock = sku.stock item.stock = sku.stock
} }
const specValueArr = item.specValues.substring(0, item.specValues.length - 1).split('_') // ['黑','6+128G','官方标配'] const specValueArr = item.specValues.substring(0, item.specValues.length - 1).split('_') // ['黑','6+128G','官方标配']
specValueArr.forEach((v: any, i: any) => { specValueArr.forEach((v, i) => {
const key = 'specValue' + (i + 1) const key = 'specValue' + (i + 1)
item[key] = v item[key] = v
if (i == 0 && state.specForm.specList.length > 0) { if (i == 0 && state.specForm.specList.length > 0) {
const valueIndex = state.specForm.specList[0].values.findIndex((specValue: any) => specValue.value == v) const valueIndex = state.specForm.specList[0].values.findIndex((specValue) => specValue.value == v)
if (valueIndex > -1) { if (valueIndex > -1) {
item.picUrl = state.specForm.specList[0].values[valueIndex].picUrl item.picUrl = state.specForm.specList[0].values[valueIndex].picUrl
} }
@@ -405,7 +407,7 @@ function handleSpecAdd() {
* 删除规格 * 删除规格
* @param index * @param index
*/ */
function handleSpecRemove(index: number) { function handleSpecRemove(index) {
state.specForm.specList.splice(index, 1) state.specForm.specList.splice(index, 1)
state.tagInputs.splice(index, 1) state.tagInputs.splice(index, 1)
generateSkuList() generateSkuList()
@@ -418,7 +420,7 @@ function handleSpecRemove(index: number) {
* *
* @param specIndex * @param specIndex
*/ */
function handleSpecValueAdd(specIndex: number) { function handleSpecValueAdd(specIndex) {
state.tagInputs[specIndex].visible = true state.tagInputs[specIndex].visible = true
} }
@@ -428,11 +430,12 @@ function handleSpecValueAdd(specIndex: number) {
* @param rowIndex * @param rowIndex
* @param specValueId * @param specValueId
*/ */
function handleSpecValueRemove(rowIndex: number, specValueId: number) { function handleSpecValueRemove(rowIndex, specValueId) {
const specList = JSON.parse(JSON.stringify(state.specForm.specList)) const specList = JSON.parse(JSON.stringify(state.specForm.specList))
const removeIndex = specList[rowIndex].values.map((item: any) => item.id).indexOf(specValueId) const removeIndex = specList[rowIndex].values.map((item) => item.id).indexOf(specValueId)
specList[rowIndex].values.splice(removeIndex, 1) specList[rowIndex].values.splice(removeIndex, 1)
state.specForm.specList = specList state.specForm.specList = specList
generateSkuList()
handleSpecChange() handleSpecChange()
handleSpecReorder() handleSpecReorder()
} }
@@ -440,17 +443,17 @@ function handleSpecValueRemove(rowIndex: number, specValueId: number) {
/** /**
* 规格值输入 * 规格值输入
*/ */
function handleSpecValueInput(rowIndex: number) { function handleSpecValueInput(rowIndex) {
const currSpecValue = state.tagInputs[rowIndex].value const currSpecValue = state.tagInputs[rowIndex].value
const specValues = state.specForm.specList[rowIndex].values const specValues = state.specForm.specList[rowIndex].values
if (specValues && specValues.length > 0 && specValues.map((item: any) => item.value).includes(currSpecValue)) { if (specValues && specValues.length > 0 && specValues.map((item) => item.value).includes(currSpecValue)) {
ElMessage.warning("规格值重复,请重新输入") ElMessage.warning("规格值重复,请重新输入")
return false return false
} }
if (currSpecValue) { if (currSpecValue) {
if (specValues && specValues.length > 0) { if (specValues && specValues.length > 0) {
// 临时规格值ID tid_1_1 // 临时规格值ID tid_1_1
let maxSpecValueIndex = specValues.filter((item: any) => item.id.includes('tid_')).map((item: any) => item.id.split('_')[2]).reduce((acc: any, curr: any) => { let maxSpecValueIndex = specValues.filter((item) => item.id.includes('tid_')).map((item) => item.id.split('_')[2]).reduce((acc, curr) => {
return acc > curr ? acc : curr return acc > curr ? acc : curr
}, 0) }, 0)
console.log('maxSpecValueIndex', maxSpecValueIndex) console.log('maxSpecValueIndex', maxSpecValueIndex)
@@ -467,13 +470,20 @@ function handleSpecValueInput(rowIndex: number) {
generateSkuList() generateSkuList()
} }
/** /**
* 合并规格单元格 * 合并规格单元格
* *
* @param cellObj 单元格对象 * @param cellObj 单元格对象
*/ */
function handleCellMerge(cellObj: any) {
const {rowIndex, columnIndex} = cellObj const objectSpanMethod = ({
row,
column,
rowIndex,
columnIndex,
}) => {
let mergeRows = [1, 1, 1] // 分别对应规格1、规格2、规格3列合并的行数 let mergeRows = [1, 1, 1] // 分别对应规格1、规格2、规格3列合并的行数
const specLen = state.specForm.specList.filter(item => item.values && item.values.length > 0).length const specLen = state.specForm.specList.filter(item => item.values && item.values.length > 0).length
if (specLen == 2) { if (specLen == 2) {
@@ -500,24 +510,25 @@ function handleCellMerge(cellObj: any) {
} }
} }
/** /**
* 商品表单提交 * 商品表单提交
*/ */
function submitForm() { function submitForm() {
const specForm = unref(specFormRef) const specForm = unref(specFormRef)
specForm.validate((specValid: boolean) => { specForm.validate((specValid) => {
if (specValid) { if (specValid) {
const skuForm = unref(skuFormRef) const skuForm = unref(skuFormRef)
skuForm.validate((skuValid: boolean) => { skuForm.validate((skuValid) => {
if (skuValid) { if (skuValid) {
openFullScreen() // openFullScreen()
let submitsData = Object.assign({}, props.modelValue) let submitsData = Object.assign({}, props.modelValue)
delete submitsData.specList delete submitsData.specList
delete submitsData.skuList delete submitsData.skuList
let specList = [] as Array<any> let specList = []
state.specForm.specList.forEach(item => { state.specForm.specList.forEach(item => {
item.values.forEach((value: any) => { item.values.forEach((value) => {
value.name = item.name value.name = item.name
}) })
specList = specList.concat(item.values) specList = specList.concat(item.values)
@@ -528,7 +539,7 @@ function submitForm() {
submitsData.originPrice *= 100 submitsData.originPrice *= 100
let skuList = JSON.parse(JSON.stringify(state.skuForm.skuList)) let skuList = JSON.parse(JSON.stringify(state.skuForm.skuList))
skuList.map((item: any) => { skuList.map((item) => {
item.price *= 100 item.price *= 100
return item return item
}) })
@@ -537,20 +548,28 @@ function submitForm() {
const goodsId = props.modelValue.id const goodsId = props.modelValue.id
if (goodsId) { // 编辑商品提交 if (goodsId) { // 编辑商品提交
updateGoods(goodsId, submitsData).then((res) => { updateGoods(goodsId, submitsData).then((res) => {
router.push({path: '/pms/good'}) router.push({path: '/pms/goods'})
proxy.$notify.success('修改商品成功') ElNotification({
closeFullScreen() title: 'Success',
message: '新增商品成功',
type: 'success',
})
//closeFullScreen()
}, (err) => { }, (err) => {
closeFullScreen() //closeFullScreen()
} }
) )
} else { // 新增商品提交 } else { // 新增商品提交
addGoods(submitsData).then(response => { addGoods(submitsData).then(response => {
router.push({path: '/pms/good'}) router.push({path: '/pms/goods'})
proxy.$notify.success('新增商品成功') ElNotification({
closeFullScreen() title: 'Success',
message: '新增商品成功',
type: 'success',
})
// closeFullScreen()
}, (err) => { }, (err) => {
closeFullScreen() // closeFullScreen()
}) })
} }
} }
@@ -570,7 +589,7 @@ function openFullScreen() {
function closeFullScreen() { function closeFullScreen() {
if (state.loading) { if (state.loading) {
(state.loading as any).close() state.loading.close()
} }
} }
@@ -590,7 +609,7 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.components-container { .component-container {
&__main { &__main {
margin: 20px auto margin: 20px auto
} }