From 1d0d9d24ad3b1566b6e11b8fc19310b99db1b31c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 25 Jun 2023 16:43:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=B0=81=E8=A3=85=20SpuSelect=20SpuAndS?= =?UTF-8?q?kuList=20=E4=B8=BA=E5=95=86=E5=93=81=E6=B4=BB=E5=8A=A8=E5=95=86?= =?UTF-8?q?=E5=93=81=E9=80=89=E6=8B=A9=E5=95=86=E5=93=81=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E9=80=9A=E7=94=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 51e79f29cc70ad1670b93829bab3d5d23751c263) --- src/api/mall/product/spu.ts | 18 ++- .../mall/promotion/seckill/seckillActivity.ts | 6 +- .../product/spu/components/BasicInfoForm.vue | 5 +- .../mall/product/spu/components/SkuList.vue | 45 ++++++-- .../mall/product/spu/components/index.ts | 15 ++- .../components/SpuAndSkuList.vue | 106 ++++++------------ .../SpuSelect.vue} | 63 +++++------ src/views/mall/promotion/components/index.ts | 13 +++ .../seckill/activity/SeckillActivityForm.vue | 80 ++++++++++--- .../seckill/activity/components/index.ts | 4 - .../mall/promotion/seckill/activity/index.vue | 19 +++- .../seckill/activity/seckillActivity.data.ts | 32 +++--- 12 files changed, 229 insertions(+), 177 deletions(-) rename src/views/mall/promotion/{seckill/activity => }/components/SpuAndSkuList.vue (59%) rename src/views/mall/promotion/{seckill/activity/components/SpuAndSkuSelectForm.vue => components/SpuSelect.vue} (83%) create mode 100644 src/views/mall/promotion/components/index.ts delete mode 100644 src/views/mall/promotion/seckill/activity/components/index.ts diff --git a/src/api/mall/product/spu.ts b/src/api/mall/product/spu.ts index 42350218..1556dd11 100644 --- a/src/api/mall/product/spu.ts +++ b/src/api/mall/product/spu.ts @@ -47,17 +47,13 @@ export interface Spu { recommendBest?: boolean // 是否精品 recommendNew?: boolean // 是否新品 recommendGood?: boolean // 是否优品 -} - -// TODO @puhui999: SpuRespVO 合并到 SPU 里?前端少点 VO 类哈; -export interface SpuRespVO extends Spu { - price: number - salesCount: number - marketPrice: number - costPrice: number - stock: number - createTime: Date - status: number + price?: number // 商品价格 + salesCount?: number // 商品销量 + marketPrice?: number // 市场价 + costPrice?: number // 成本价 + stock?: number // 商品库存 + createTime?: Date // 商品创建时间 + status?: number // 商品状态 } // 获得 Spu 列表 diff --git a/src/api/mall/promotion/seckill/seckillActivity.ts b/src/api/mall/promotion/seckill/seckillActivity.ts index 93b128f3..0f1f08d1 100644 --- a/src/api/mall/promotion/seckill/seckillActivity.ts +++ b/src/api/mall/promotion/seckill/seckillActivity.ts @@ -1,5 +1,5 @@ import request from '@/config/axios' -import { Sku, SpuRespVO } from '@/api/mall/product/spu' +import { Sku, Spu } from '@/api/mall/product/spu' export interface SeckillActivityVO { id: number @@ -21,6 +21,7 @@ export interface SeckillActivityVO { products: SeckillProductVO[] } +// 秒杀活动所需属性 export interface SeckillProductVO { spuId: number skuId: number @@ -28,11 +29,12 @@ export interface SeckillProductVO { stock: number } +// 扩展 Sku 配置 type SkuExtension = Sku & { productConfig: SeckillProductVO } -export interface SpuExtension extends SpuRespVO { +export interface SpuExtension extends Spu { skus: SkuExtension[] // 重写类型 } diff --git a/src/views/mall/product/spu/components/BasicInfoForm.vue b/src/views/mall/product/spu/components/BasicInfoForm.vue index c8cc6f57..501295b4 100644 --- a/src/views/mall/product/spu/components/BasicInfoForm.vue +++ b/src/views/mall/product/spu/components/BasicInfoForm.vue @@ -274,10 +274,7 @@ watch( const emit = defineEmits(['update:activeName']) const validate = async () => { // 校验 sku - if (!skuListRef.value.validateSku()) { - message.warning('商品相关价格不能低于 0.01 元!!') - throw new Error('商品相关价格不能低于 0.01 元!!') - } + skuListRef.value.validateSku() // 校验表单 if (!productSpuBasicInfoRef) return return await unref(productSpuBasicInfoRef).validate((valid) => { diff --git a/src/views/mall/product/spu/components/SkuList.vue b/src/views/mall/product/spu/components/SkuList.vue index da263686..e033b233 100644 --- a/src/views/mall/product/spu/components/SkuList.vue +++ b/src/views/mall/product/spu/components/SkuList.vue @@ -259,8 +259,10 @@ import { UploadImg } from '@/components/UploadFile' import type { Property, Sku, Spu } from '@/api/mall/product/spu' import { createImageViewer } from '@/components/ImageViewer' import { RuleConfig } from '@/views/mall/product/spu/components/index' +import { Properties } from './index' defineOptions({ name: 'SkuList' }) +const message = useMessage() // 消息弹窗 const props = defineProps({ propFormData: { @@ -268,7 +270,7 @@ const props = defineProps({ default: () => {} }, propertyList: { - type: Array, + type: Array as PropType, default: () => [] }, ruleConfig: { @@ -323,26 +325,47 @@ const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表 /** * 保存时,每个商品规格的表单要校验下。例如说,销售金额最低是 0.01 这种。 */ -const validateSku = (): boolean => { +const validateSku = () => { const checks = ['price', 'marketPrice', 'costPrice'] + let warningInfo = '请检查商品各行相关属性配置,' let validate = true // 默认通过 - for (const sku of formData.value!.skus) { + for (const sku of formData.value!.skus!) { // 作为活动组件的校验 if (props.isActivityComponent) { for (const rule of props.ruleConfig) { - if (sku[rule.name] < rule.geValue) { + const arg = getValue(sku, rule.name) + if (!rule.rule(arg)) { validate = false // 只要有一个不通过则直接不通过 + warningInfo += rule.message break } } } else { if (checks.some((check) => sku[check] < 0.01)) { validate = false // 只要有一个不通过则直接不通过 + warningInfo = '商品相关价格不能低于 0.01 元!!' break } } + // 只要有一个不通过则结束后续的校验 + if (!validate) { + message.warning(warningInfo) + throw new Error(warningInfo) + } } - return validate +} +const getValue = (obj, arg) => { + const keys = arg.split('.') + let value = obj + for (const key of keys) { + if (value && typeof value === 'object' && key in value) { + value = value[key] + } else { + value = undefined + break + } + } + return value } const emit = defineEmits<{ @@ -417,13 +440,13 @@ const generateTableData = (propertyList: any[]) => { * 生成 skus 前置校验 */ const validateData = (propertyList: any[]) => { - const skuPropertyIds = [] + const skuPropertyIds: number[] = [] formData.value!.skus!.forEach((sku) => sku.properties ?.map((property) => property.propertyId) - .forEach((propertyId) => { - if (skuPropertyIds.indexOf(propertyId) === -1) { - skuPropertyIds.push(propertyId) + ?.forEach((propertyId) => { + if (skuPropertyIds.indexOf(propertyId!) === -1) { + skuPropertyIds.push(propertyId!) } }) ) @@ -457,7 +480,7 @@ const build = (propertyValuesList: Property[][]) => { /** 监听属性列表,生成相关参数和表头 */ watch( () => props.propertyList, - (propertyList) => { + (propertyList: Properties[]) => { // 如果不是多规格则结束 if (!formData.value!.specType) { return @@ -497,7 +520,7 @@ watch( return } // 添加新属性没有属性值也不做处理 - if (propertyList.some((item) => item.values.length === 0)) { + if (propertyList.some((item) => item.values!.length === 0)) { return } // 生成 table 数据,即 sku 列表 diff --git a/src/views/mall/product/spu/components/index.ts b/src/views/mall/product/spu/components/index.ts index 8c269e56..59c031e8 100644 --- a/src/views/mall/product/spu/components/index.ts +++ b/src/views/mall/product/spu/components/index.ts @@ -14,8 +14,19 @@ interface Properties { } interface RuleConfig { - name: string // 需要校验的字段 - geValue: number // TODO 暂定大于一个数字 + // 需要校验的字段 + // 例:name: 'name' 则表示校验 sku.name 的值 + // 例:name: 'productConfig.stock' 则表示校验 sku.productConfig.name 的值,此处 productConfig 表示我在 Sku 上扩展的属性 + name: string + // 校验规格为一个毁掉函数,其中 arg 为需要校验的字段的值。 + // 例:需要校验价格必须大于0.01 + // { + // name:'price', + // rule:(arg) => arg > 0.01 + // } + rule: (arg: any) => boolean + // 校验不通过时的消息提示 + message: string } /** diff --git a/src/views/mall/promotion/seckill/activity/components/SpuAndSkuList.vue b/src/views/mall/promotion/components/SpuAndSkuList.vue similarity index 59% rename from src/views/mall/promotion/seckill/activity/components/SpuAndSkuList.vue rename to src/views/mall/promotion/components/SpuAndSkuList.vue index 63268a35..e239a39a 100644 --- a/src/views/mall/promotion/seckill/activity/components/SpuAndSkuList.vue +++ b/src/views/mall/promotion/components/SpuAndSkuList.vue @@ -1,5 +1,5 @@