mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-11-04 20:28:45 +08:00 
			
		
		
		
	fix: 修复 SkuList TODO 优化相关算法
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-table
 | 
			
		||||
    :data="isBatch ? SkuData : formData.skus"
 | 
			
		||||
    :data="isBatch ? skuList : formData.skus"
 | 
			
		||||
    border
 | 
			
		||||
    class="tabNumWidth"
 | 
			
		||||
    max-height="500"
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
    <template v-if="formData.specType && !isBatch">
 | 
			
		||||
      <!--  根据商品属性动态添加  -->
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        v-for="(item, index) in tableHeaderList"
 | 
			
		||||
        v-for="(item, index) in tableHeaders"
 | 
			
		||||
        :key="index"
 | 
			
		||||
        :label="item.label"
 | 
			
		||||
        align="center"
 | 
			
		||||
@@ -32,65 +32,45 @@
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <!-- TODO @puhui999:用户输入的时候,是按照元;分主要是我们自己用; -->
 | 
			
		||||
    <el-table-column align="center" label="销售价(分)" min-width="168">
 | 
			
		||||
    <el-table-column align="center" label="销售价(元)" min-width="168">
 | 
			
		||||
      <template #default="{ row }">
 | 
			
		||||
        <el-input-number v-model="row.price" :min="0" class="w-100%" controls-position="right" />
 | 
			
		||||
        <el-input-number v-model="row.price" :min="0" class="w-100%" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column align="center" label="市场价(分)" min-width="168">
 | 
			
		||||
    <el-table-column align="center" label="市场价(元)" min-width="168">
 | 
			
		||||
      <template #default="{ row }">
 | 
			
		||||
        <el-input-number
 | 
			
		||||
          v-model="row.marketPrice"
 | 
			
		||||
          :min="0"
 | 
			
		||||
          class="w-100%"
 | 
			
		||||
          controls-position="right"
 | 
			
		||||
        />
 | 
			
		||||
        <el-input-number v-model="row.marketPrice" :min="0" class="w-100%" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column align="center" label="成本价(分)" min-width="168">
 | 
			
		||||
    <el-table-column align="center" label="成本价(元)" min-width="168">
 | 
			
		||||
      <template #default="{ row }">
 | 
			
		||||
        <el-input-number
 | 
			
		||||
          v-model="row.costPrice"
 | 
			
		||||
          :min="0"
 | 
			
		||||
          class="w-100%"
 | 
			
		||||
          controls-position="right"
 | 
			
		||||
        />
 | 
			
		||||
        <el-input-number v-model="row.costPrice" :min="0" class="w-100%" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column align="center" label="库存" min-width="168">
 | 
			
		||||
      <template #default="{ row }">
 | 
			
		||||
        <el-input-number v-model="row.stock" :min="0" class="w-100%" controls-position="right" />
 | 
			
		||||
        <el-input-number v-model="row.stock" :min="0" class="w-100%" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column align="center" label="重量(kg)" min-width="168">
 | 
			
		||||
      <template #default="{ row }">
 | 
			
		||||
        <el-input-number v-model="row.weight" :min="0" class="w-100%" controls-position="right" />
 | 
			
		||||
        <el-input-number v-model="row.weight" :min="0" class="w-100%" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column align="center" label="体积(m^3)" min-width="168">
 | 
			
		||||
      <template #default="{ row }">
 | 
			
		||||
        <el-input-number v-model="row.volume" :min="0" class="w-100%" controls-position="right" />
 | 
			
		||||
        <el-input-number v-model="row.volume" :min="0" class="w-100%" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <template v-if="formData.subCommissionType">
 | 
			
		||||
      <el-table-column align="center" label="一级返佣(分)" min-width="168">
 | 
			
		||||
      <el-table-column align="center" label="一级返佣(元)" min-width="168">
 | 
			
		||||
        <template #default="{ row }">
 | 
			
		||||
          <el-input-number
 | 
			
		||||
            v-model="row.subCommissionFirstPrice"
 | 
			
		||||
            :min="0"
 | 
			
		||||
            class="w-100%"
 | 
			
		||||
            controls-position="right"
 | 
			
		||||
          />
 | 
			
		||||
          <el-input-number v-model="row.subCommissionFirstPrice" :min="0" class="w-100%" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column align="center" label="二级返佣(分)" min-width="168">
 | 
			
		||||
      <el-table-column align="center" label="二级返佣(元)" min-width="168">
 | 
			
		||||
        <template #default="{ row }">
 | 
			
		||||
          <el-input-number
 | 
			
		||||
            v-model="row.subCommissionSecondPrice"
 | 
			
		||||
            :min="0"
 | 
			
		||||
            class="w-100%"
 | 
			
		||||
            controls-position="right"
 | 
			
		||||
          />
 | 
			
		||||
          <el-input-number v-model="row.subCommissionSecondPrice" :min="0" class="w-100%" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </template>
 | 
			
		||||
@@ -107,9 +87,8 @@
 | 
			
		||||
<script lang="ts" name="SkuList" setup>
 | 
			
		||||
import { UploadImg } from '@/components/UploadFile'
 | 
			
		||||
import { PropType } from 'vue'
 | 
			
		||||
import { SpuType } from '@/api/mall/product/management/type/spuType'
 | 
			
		||||
import type { Property, SkuType, SpuType } from '@/api/mall/product/spu'
 | 
			
		||||
import { propTypes } from '@/utils/propTypes'
 | 
			
		||||
import { SkuType } from '@/api/mall/product/management/type/skuType'
 | 
			
		||||
import { copyValueToTarget } from '@/utils'
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
@@ -121,66 +100,35 @@ const props = defineProps({
 | 
			
		||||
    type: Array,
 | 
			
		||||
    default: () => []
 | 
			
		||||
  },
 | 
			
		||||
  isBatch: propTypes.bool.def(false) // 是否批量操作
 | 
			
		||||
  isBatch: propTypes.bool.def(false) // 是否作为批量操作组件
 | 
			
		||||
})
 | 
			
		||||
const formData = ref<SpuType>() // 表单数据
 | 
			
		||||
// 批量添加时的零时数据 TODO @puhui999:小写开头哈;然后变量都尾注释
 | 
			
		||||
const SkuData = ref<SkuType[]>([
 | 
			
		||||
const skuList = ref<SkuType[]>([
 | 
			
		||||
  {
 | 
			
		||||
    /**
 | 
			
		||||
     * 商品价格,单位:分
 | 
			
		||||
     */
 | 
			
		||||
    price: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 市场价,单位:分
 | 
			
		||||
     */
 | 
			
		||||
    marketPrice: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 成本价,单位:分
 | 
			
		||||
     */
 | 
			
		||||
    costPrice: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 商品条码
 | 
			
		||||
     */
 | 
			
		||||
    barCode: '',
 | 
			
		||||
    /**
 | 
			
		||||
     * 图片地址
 | 
			
		||||
     */
 | 
			
		||||
    picUrl: '',
 | 
			
		||||
    /**
 | 
			
		||||
     * 库存
 | 
			
		||||
     */
 | 
			
		||||
    stock: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 商品重量,单位:kg 千克
 | 
			
		||||
     */
 | 
			
		||||
    weight: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 商品体积,单位:m^3 平米
 | 
			
		||||
     */
 | 
			
		||||
    volume: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 一级分销的佣金,单位:分
 | 
			
		||||
     */
 | 
			
		||||
    subCommissionFirstPrice: 0,
 | 
			
		||||
    /**
 | 
			
		||||
     * 二级分销的佣金,单位:分
 | 
			
		||||
     */
 | 
			
		||||
    subCommissionSecondPrice: 0
 | 
			
		||||
    price: 0, // 商品价格
 | 
			
		||||
    marketPrice: 0, // 市场价
 | 
			
		||||
    costPrice: 0, // 成本价
 | 
			
		||||
    barCode: '', // 商品条码
 | 
			
		||||
    picUrl: '', // 图片地址
 | 
			
		||||
    stock: 0, // 库存
 | 
			
		||||
    weight: 0, // 商品重量
 | 
			
		||||
    volume: 0, // 商品体积
 | 
			
		||||
    subCommissionFirstPrice: 0, // 一级分销的佣金
 | 
			
		||||
    subCommissionSecondPrice: 0 // 二级分销的佣金
 | 
			
		||||
  }
 | 
			
		||||
])
 | 
			
		||||
]) // 批量添加时的临时数据
 | 
			
		||||
 | 
			
		||||
/** 批量添加 */
 | 
			
		||||
const batchAdd = () => {
 | 
			
		||||
  formData.value.skus.forEach((item) => {
 | 
			
		||||
    copyValueToTarget(item, SkuData.value[0])
 | 
			
		||||
    copyValueToTarget(item, skuList.value[0])
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const tableHeaderList = ref<{ prop: string; label: string }[]>([])
 | 
			
		||||
const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表头
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 将传进来的值赋值给SkuData
 | 
			
		||||
 * 将传进来的值赋值给skuList
 | 
			
		||||
 */
 | 
			
		||||
watch(
 | 
			
		||||
  () => props.propFormData,
 | 
			
		||||
@@ -197,21 +145,18 @@ watch(
 | 
			
		||||
// TODO @芋艿:看看 chatgpt 可以进一步下面几个方法的实现不
 | 
			
		||||
/** 生成表数据 */
 | 
			
		||||
const generateTableData = (data: any[]) => {
 | 
			
		||||
  // 构建数据结构
 | 
			
		||||
  const propertiesItemList = []
 | 
			
		||||
  for (const item of data) {
 | 
			
		||||
    const objList = []
 | 
			
		||||
    for (const v of item.values) {
 | 
			
		||||
      const obj = { propertyId: 0, valueId: 0, valueName: '' }
 | 
			
		||||
      obj.propertyId = item.id
 | 
			
		||||
      obj.valueId = v.id
 | 
			
		||||
      obj.valueName = v.name
 | 
			
		||||
      objList.push(obj)
 | 
			
		||||
    }
 | 
			
		||||
    propertiesItemList.push(objList)
 | 
			
		||||
  }
 | 
			
		||||
  // 构建数据结构 fix: 使用map替换多重for循环
 | 
			
		||||
  const propertiesItemList = data.map((item) =>
 | 
			
		||||
    item.values.map((v) => ({
 | 
			
		||||
      propertyId: item.id,
 | 
			
		||||
      propertyName: item.name,
 | 
			
		||||
      valueId: v.id,
 | 
			
		||||
      valueName: v.name
 | 
			
		||||
    }))
 | 
			
		||||
  )
 | 
			
		||||
  const buildList = build(propertiesItemList)
 | 
			
		||||
  // 如果构建后的组合数跟sku数量一样的话则不用处理,添加新属性没有属性值也不做处理 (解决编辑表单时或查看详情时数据回显问题)
 | 
			
		||||
  // 如果构建后的组合数跟sku数量一样的话则不用处理,添加新属性没有属性值也不做处理
 | 
			
		||||
  // fix: 解决编辑表单时或查看详情时数据回显问题
 | 
			
		||||
  if (
 | 
			
		||||
    buildList.length === formData.value.skus.length ||
 | 
			
		||||
    data.some((item) => item.values.length === 0)
 | 
			
		||||
@@ -222,7 +167,7 @@ const generateTableData = (data: any[]) => {
 | 
			
		||||
  formData.value!.skus = []
 | 
			
		||||
  buildList.forEach((item) => {
 | 
			
		||||
    const row = {
 | 
			
		||||
      properties: [],
 | 
			
		||||
      properties: Array.isArray(item) ? item : [item],
 | 
			
		||||
      price: 0,
 | 
			
		||||
      marketPrice: 0,
 | 
			
		||||
      costPrice: 0,
 | 
			
		||||
@@ -234,32 +179,25 @@ const generateTableData = (data: any[]) => {
 | 
			
		||||
      subCommissionFirstPrice: 0,
 | 
			
		||||
      subCommissionSecondPrice: 0
 | 
			
		||||
    }
 | 
			
		||||
    // 判断是否是单一属性的情况
 | 
			
		||||
    if (Array.isArray(item)) {
 | 
			
		||||
      row.properties = item
 | 
			
		||||
    } else {
 | 
			
		||||
      row.properties.push(item)
 | 
			
		||||
    }
 | 
			
		||||
    formData.value.skus.push(row)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 构建所有排列组合 */
 | 
			
		||||
const build = (list: any[]) => {
 | 
			
		||||
  if (list.length === 0) {
 | 
			
		||||
const build = (propertyValuesList: Property[][]) => {
 | 
			
		||||
  if (propertyValuesList.length === 0) {
 | 
			
		||||
    return []
 | 
			
		||||
  } else if (list.length === 1) {
 | 
			
		||||
    return list[0]
 | 
			
		||||
  } else if (propertyValuesList.length === 1) {
 | 
			
		||||
    return propertyValuesList[0]
 | 
			
		||||
  } else {
 | 
			
		||||
    const result = []
 | 
			
		||||
    const rest = build(list.slice(1))
 | 
			
		||||
    for (let i = 0; i < list[0].length; i++) {
 | 
			
		||||
    const result: Property[][] = []
 | 
			
		||||
    const rest = build(propertyValuesList.slice(1))
 | 
			
		||||
    for (let i = 0; i < propertyValuesList[0].length; i++) {
 | 
			
		||||
      for (let j = 0; j < rest.length; j++) {
 | 
			
		||||
        // 第一次不是数组结构,后面的都是数组结构
 | 
			
		||||
        if (Array.isArray(rest[j])) {
 | 
			
		||||
          result.push([list[0][i], ...rest[j]])
 | 
			
		||||
          result.push([propertyValuesList[0][i], ...rest[j]])
 | 
			
		||||
        } else {
 | 
			
		||||
          result.push([list[0][i], rest[j]])
 | 
			
		||||
          result.push([propertyValuesList[0][i], rest[j]])
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -270,12 +208,12 @@ const build = (list: any[]) => {
 | 
			
		||||
/** 监听属性列表生成相关参数和表头 */
 | 
			
		||||
watch(
 | 
			
		||||
  () => props.attributeList,
 | 
			
		||||
  (data) => {
 | 
			
		||||
  (attributeList) => {
 | 
			
		||||
    // 如果不是多规格则结束
 | 
			
		||||
    if (!formData.value.specType) return
 | 
			
		||||
    // 如果当前组件作为批量添加数据使用则重置表数据
 | 
			
		||||
    if (props.isBatch) {
 | 
			
		||||
      SkuData.value = [
 | 
			
		||||
      skuList.value = [
 | 
			
		||||
        {
 | 
			
		||||
          price: 0,
 | 
			
		||||
          marketPrice: 0,
 | 
			
		||||
@@ -291,15 +229,15 @@ watch(
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
    // 判断代理对象是否为空
 | 
			
		||||
    if (JSON.stringify(data) === '[]') return
 | 
			
		||||
    if (JSON.stringify(attributeList) === '[]') return
 | 
			
		||||
    // 重置表头
 | 
			
		||||
    tableHeaderList.value = []
 | 
			
		||||
    tableHeaders.value = []
 | 
			
		||||
    // 生成表头
 | 
			
		||||
    data.forEach((item, index) => {
 | 
			
		||||
    attributeList.forEach((item, index) => {
 | 
			
		||||
      // name加属性项index区分属性值
 | 
			
		||||
      tableHeaderList.value.push({ prop: `name${index}`, label: item.name })
 | 
			
		||||
      tableHeaders.value.push({ prop: `name${index}`, label: item.name })
 | 
			
		||||
    })
 | 
			
		||||
    generateTableData(data)
 | 
			
		||||
    generateTableData(attributeList)
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    deep: true,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user