feat:【antd】【mall】spu 优化

This commit is contained in:
puhui999
2025-11-24 12:00:50 +08:00
parent cc7e8eda4f
commit 0ae62ef7e7
14 changed files with 73 additions and 143 deletions

View File

@@ -62,13 +62,6 @@ export namespace MallSpuApi {
valueName?: string; // 属性值名称
}
// TODO @puhui999这个还要么
/** 优惠券模板 */
export interface GiveCouponTemplate {
id?: number; // 优惠券编号
name?: string; // 优惠券名称
}
/** 商品状态更新请求 */
export interface SpuStatusUpdateReqVO {
id: number; // 商品编号

View File

@@ -1,7 +1,5 @@
import type { PageParam, PageResult } from '@vben/request';
import type { MallSpuApi } from '#/api/mall/product/spu';
import { requestClient } from '#/api/request';
export namespace MallBargainActivityApi {
@@ -32,17 +30,6 @@ export namespace MallBargainActivityApi {
bargainMinPrice: number; // 砍价底价
stock: number; // 活动库存
}
// TODO @puhui999要不要删除
/** 扩展 SKU 配置 */
export type SkuExtension = {
productConfig: BargainProduct; // 砍价活动配置
} & MallSpuApi.Sku;
/** 扩展 SPU 配置 */
export interface SpuExtension extends MallSpuApi.Spu {
skus: SkuExtension[]; // SKU 列表
}
}
/** 查询砍价活动列表 */

View File

@@ -1,7 +1,5 @@
import type { PageParam, PageResult } from '@vben/request';
import type { MallSpuApi } from '#/api/mall/product/spu';
import { requestClient } from '#/api/request';
export namespace MallCombinationActivityApi {
@@ -25,23 +23,12 @@ export namespace MallCombinationActivityApi {
products: CombinationProduct[]; // 商品列表
}
// TODO @puhui999要不要删除
/** 拼团活动所需属性 */
export interface CombinationProduct {
spuId: number; // 商品 SPU 编号
skuId: number; // 商品 SKU 编号
combinationPrice: number; // 拼团价格
}
/** 扩展 SKU 配置 */
export type SkuExtension = {
productConfig: CombinationProduct; // 拼团活动配置
} & MallSpuApi.Sku;
/** 扩展 SPU 配置 */
export interface SpuExtension extends MallSpuApi.Spu {
skus: SkuExtension[]; // SKU 列表
}
}
/** 查询拼团活动列表 */

View File

@@ -1,7 +1,5 @@
import type { PageParam, PageResult } from '@vben/request';
import type { MallSpuApi } from '#/api/mall/product/spu';
import { requestClient } from '#/api/request';
export namespace MallDiscountActivityApi {
@@ -25,17 +23,6 @@ export namespace MallDiscountActivityApi {
endTime?: Date; // 结束时间
products?: DiscountProduct[]; // 商品列表
}
// TODO @puhui999要不要删除
/** 扩展 SKU 配置 */
export type SkuExtension = {
productConfig: DiscountProduct; // 限时折扣配置
} & MallSpuApi.Sku;
/** 扩展 SPU 配置 */
export interface SpuExtension extends MallSpuApi.Spu {
skus: SkuExtension[]; // SKU 列表
}
}
/** 查询限时折扣活动列表 */

View File

@@ -36,17 +36,6 @@ export namespace MallPointActivityApi {
price: number; // 兑换金额,单位:分
}
// TODO @puhui999这些还需要么
/** 扩展 SKU 配置 */
export type SkuExtension = {
productConfig: PointProduct; // 积分商城商品配置
} & MallSpuApi.Sku;
/** 扩展 SPU 配置 */
export interface SpuExtension extends MallSpuApi.Spu {
skus: SkuExtension[]; // SKU 列表
}
/** 扩展 SPU 配置(带积分信息) */
export interface SpuExtensionWithPoint extends MallSpuApi.Spu {
pointStock: number; // 积分商城活动库存

View File

@@ -1,7 +1,5 @@
import type { PageParam, PageResult } from '@vben/request';
import type { MallSpuApi } from '#/api/mall/product/spu';
import { requestClient } from '#/api/request';
export namespace MallSeckillActivityApi {
@@ -34,17 +32,6 @@ export namespace MallSeckillActivityApi {
seckillPrice?: number; // 秒杀价格
products?: SeckillProduct[]; // 秒杀商品列表
}
// TODO @puhui999这些还需要么
/** 扩展 SKU 配置 */
export type SkuExtension = {
productConfig: SeckillProduct; // 秒杀商品配置
} & MallSpuApi.Sku;
/** 扩展 SPU 配置 */
export interface SpuExtension extends MallSpuApi.Spu {
skus: SkuExtension[]; // SKU 列表
}
}
/** 查询秒杀活动列表 */

View File

@@ -1,3 +1,6 @@
export * from './property-util';
export { default as SkuList } from './sku-list.vue';
export { default as SkuTableSelect } from './sku-table-select.vue';
export { default as SpuShowcase } from './spu-showcase.vue';
export { default as SpuTableSelect } from './spu-table-select.vue';
export * from './type';

View File

@@ -0,0 +1,36 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { MallSpuApi } from '#/api/mall/product/spu';
import type { PropertyAndValues } from '#/views/mall/product/spu/components/type';
/** 获得商品的规格列表 - 商品相关的公共函数(被其他模块如 promotion 使用) */
const getPropertyList = (spu: MallSpuApi.Spu): PropertyAndValues[] => {
// 直接拿返回的 skus 属性逆向生成出 propertyList
const properties: PropertyAndValues[] = [];
// 只有是多规格才处理
if (spu.specType) {
spu.skus?.forEach((sku) => {
sku.properties?.forEach(
({ propertyId, propertyName, valueId, valueName }) => {
// 添加属性
if (!properties?.some((item) => item.id === propertyId)) {
properties.push({
id: propertyId!,
name: propertyName!,
values: [],
});
}
// 添加属性值
const index = properties?.findIndex((item) => item.id === propertyId);
if (
!properties[index]?.values?.some((value) => value.id === valueId)
) {
properties[index]?.values?.push({ id: valueId!, name: valueName! });
}
},
);
});
}
return properties;
};
export { getPropertyList };

View File

@@ -1,9 +1,11 @@
<script lang="ts" setup>
import type { Ref } from 'vue';
import type { PropertyAndValues, RuleConfig } from '../index';
import type { MallSpuApi } from '#/api/mall/product/spu';
import type {
PropertyAndValues,
RuleConfig,
} from '#/views/mall/product/spu/components';
import { ref, watch } from 'vue';

View File

@@ -0,0 +1,22 @@
/** 商品属性及其值的树形结构(用于前端展示和操作) */
export interface PropertyAndValues {
id: number;
name: string;
values?: PropertyAndValues[];
}
export interface RuleConfig {
// 需要校验的字段
// 例name: 'name' 则表示校验 sku.name 的值
// 例name: 'productConfig.stock' 则表示校验 sku.productConfig.name 的值,此处 productConfig 表示我在 Sku 上扩展的属性
name: string;
// 校验规格为一个毁掉函数,其中 arg 为需要校验的字段的值。
// 例需要校验价格必须大于0.01
// {
// name:'price',
// rule:(arg: number) => arg > 0.01
// }
rule: (arg: any) => boolean;
// 校验不通过时的消息提示
message: string;
}

View File

@@ -1,63 +0,0 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { MallSpuApi } from '#/api/mall/product/spu';
// TODO @puhui999这个是不是 api 后端有定义类似的?如果是,是不是放到 api 哈?
export interface PropertyAndValues {
id: number;
name: string;
values?: PropertyAndValues[];
}
export interface RuleConfig {
// 需要校验的字段
// 例name: 'name' 则表示校验 sku.name 的值
// 例name: 'productConfig.stock' 则表示校验 sku.productConfig.name 的值,此处 productConfig 表示我在 Sku 上扩展的属性
name: string;
// 校验规格为一个毁掉函数,其中 arg 为需要校验的字段的值。
// 例需要校验价格必须大于0.01
// {
// name:'price',
// rule:(arg: number) => arg > 0.01
// }
rule: (arg: any) => boolean;
// 校验不通过时的消息提示
message: string;
}
// TODO @puhui999这个是只有 index.ts 在用么?还是别的模块也会用
/** 获得商品的规格列表 - 商品相关的公共函数 */
const getPropertyList = (spu: MallSpuApi.Spu): PropertyAndValues[] => {
// 直接拿返回的 skus 属性逆向生成出 propertyList
const properties: PropertyAndValues[] = [];
// 只有是多规格才处理
if (spu.specType) {
spu.skus?.forEach((sku) => {
sku.properties?.forEach(
({ propertyId, propertyName, valueId, valueName }) => {
// 添加属性
if (!properties?.some((item) => item.id === propertyId)) {
properties.push({
id: propertyId!,
name: propertyName!,
values: [],
});
}
// 添加属性值
const index = properties?.findIndex((item) => item.id === propertyId);
if (
!properties[index]?.values?.some((value) => value.id === valueId)
) {
properties[index]?.values?.push({ id: valueId!, name: valueName! });
}
},
);
});
}
return properties;
};
export { getPropertyList };
// 导出组件
// TODO @puhui999如果 sku-list.vue 要对外,可以考虑在 spu 下面,搞个 components 模块目前看别的模块应该会用到哈。modules 是当前模块用到的components 是跨模块要用到的。
export { default as SkuList } from './modules/sku-list.vue';

View File

@@ -1,7 +1,9 @@
<script lang="ts" setup>
import type { PropertyAndValues, RuleConfig } from './index';
import type { MallSpuApi } from '#/api/mall/product/spu';
import type {
PropertyAndValues,
RuleConfig,
} from '#/views/mall/product/spu/components';
import { onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
@@ -14,6 +16,7 @@ import { Button, Card, message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { createSpu, getSpu, updateSpu } from '#/api/mall/product/spu';
import { getPropertyList, SkuList } from '#/views/mall/product/spu/components';
import {
useDeliveryFormSchema,
@@ -22,10 +25,8 @@ import {
useOtherFormSchema,
useSkuFormSchema,
} from './data';
import { getPropertyList } from './index';
import ProductAttributes from './modules/product-attributes.vue';
import ProductPropertyAddForm from './modules/product-property-add-form.vue';
import SkuList from './modules/sku-list.vue';
const spuId = ref<number>();
const { params, name } = useRoute();

View File

@@ -1,8 +1,7 @@
<!-- 商品发布 - 库存价格 - 属性列表 -->
<script lang="ts" setup>
import type { PropertyAndValues } from '../index';
import type { MallPropertyApi } from '#/api/mall/product/property';
import type { PropertyAndValues } from '#/views/mall/product/spu/components';
import { computed, ref, watch } from 'vue';

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
import type { MallPointActivityApi } from '#/api/mall/promotion/point';
import type { RuleConfig } from '#/views/mall/product/spu/form';
import type { RuleConfig } from '#/views/mall/product/spu/components';
// TODO @puhui999有问题
// import type { SpuProperty } from '#/views/mall/promotion/components/types';
@@ -20,7 +20,7 @@ import {
updatePointActivity,
} from '#/api/mall/promotion/point';
import { $t } from '#/locales';
import { getPropertyList } from '#/views/mall/product/spu/form';
import { getPropertyList } from '#/views/mall/product/spu/components';
// TODO @puhui999有问题
// import { SpuAndSkuList, SpuSkuSelect } from '../../../components';