feat:【antd】【mall】spu 优化
This commit is contained in:
@@ -62,13 +62,6 @@ export namespace MallSpuApi {
|
|||||||
valueName?: string; // 属性值名称
|
valueName?: string; // 属性值名称
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:这个还要么?
|
|
||||||
/** 优惠券模板 */
|
|
||||||
export interface GiveCouponTemplate {
|
|
||||||
id?: number; // 优惠券编号
|
|
||||||
name?: string; // 优惠券名称
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 商品状态更新请求 */
|
/** 商品状态更新请求 */
|
||||||
export interface SpuStatusUpdateReqVO {
|
export interface SpuStatusUpdateReqVO {
|
||||||
id: number; // 商品编号
|
id: number; // 商品编号
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MallBargainActivityApi {
|
export namespace MallBargainActivityApi {
|
||||||
@@ -32,17 +30,6 @@ export namespace MallBargainActivityApi {
|
|||||||
bargainMinPrice: number; // 砍价底价
|
bargainMinPrice: number; // 砍价底价
|
||||||
stock: number; // 活动库存
|
stock: number; // 活动库存
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:要不要删除?
|
|
||||||
/** 扩展 SKU 配置 */
|
|
||||||
export type SkuExtension = {
|
|
||||||
productConfig: BargainProduct; // 砍价活动配置
|
|
||||||
} & MallSpuApi.Sku;
|
|
||||||
|
|
||||||
/** 扩展 SPU 配置 */
|
|
||||||
export interface SpuExtension extends MallSpuApi.Spu {
|
|
||||||
skus: SkuExtension[]; // SKU 列表
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询砍价活动列表 */
|
/** 查询砍价活动列表 */
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MallCombinationActivityApi {
|
export namespace MallCombinationActivityApi {
|
||||||
@@ -25,23 +23,12 @@ export namespace MallCombinationActivityApi {
|
|||||||
products: CombinationProduct[]; // 商品列表
|
products: CombinationProduct[]; // 商品列表
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:要不要删除?
|
|
||||||
/** 拼团活动所需属性 */
|
/** 拼团活动所需属性 */
|
||||||
export interface CombinationProduct {
|
export interface CombinationProduct {
|
||||||
spuId: number; // 商品 SPU 编号
|
spuId: number; // 商品 SPU 编号
|
||||||
skuId: number; // 商品 SKU 编号
|
skuId: number; // 商品 SKU 编号
|
||||||
combinationPrice: number; // 拼团价格
|
combinationPrice: number; // 拼团价格
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 扩展 SKU 配置 */
|
|
||||||
export type SkuExtension = {
|
|
||||||
productConfig: CombinationProduct; // 拼团活动配置
|
|
||||||
} & MallSpuApi.Sku;
|
|
||||||
|
|
||||||
/** 扩展 SPU 配置 */
|
|
||||||
export interface SpuExtension extends MallSpuApi.Spu {
|
|
||||||
skus: SkuExtension[]; // SKU 列表
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询拼团活动列表 */
|
/** 查询拼团活动列表 */
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MallDiscountActivityApi {
|
export namespace MallDiscountActivityApi {
|
||||||
@@ -25,17 +23,6 @@ export namespace MallDiscountActivityApi {
|
|||||||
endTime?: Date; // 结束时间
|
endTime?: Date; // 结束时间
|
||||||
products?: DiscountProduct[]; // 商品列表
|
products?: DiscountProduct[]; // 商品列表
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:要不要删除?
|
|
||||||
/** 扩展 SKU 配置 */
|
|
||||||
export type SkuExtension = {
|
|
||||||
productConfig: DiscountProduct; // 限时折扣配置
|
|
||||||
} & MallSpuApi.Sku;
|
|
||||||
|
|
||||||
/** 扩展 SPU 配置 */
|
|
||||||
export interface SpuExtension extends MallSpuApi.Spu {
|
|
||||||
skus: SkuExtension[]; // SKU 列表
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询限时折扣活动列表 */
|
/** 查询限时折扣活动列表 */
|
||||||
|
|||||||
@@ -36,17 +36,6 @@ export namespace MallPointActivityApi {
|
|||||||
price: number; // 兑换金额,单位:分
|
price: number; // 兑换金额,单位:分
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:这些还需要么?
|
|
||||||
/** 扩展 SKU 配置 */
|
|
||||||
export type SkuExtension = {
|
|
||||||
productConfig: PointProduct; // 积分商城商品配置
|
|
||||||
} & MallSpuApi.Sku;
|
|
||||||
|
|
||||||
/** 扩展 SPU 配置 */
|
|
||||||
export interface SpuExtension extends MallSpuApi.Spu {
|
|
||||||
skus: SkuExtension[]; // SKU 列表
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 扩展 SPU 配置(带积分信息) */
|
/** 扩展 SPU 配置(带积分信息) */
|
||||||
export interface SpuExtensionWithPoint extends MallSpuApi.Spu {
|
export interface SpuExtensionWithPoint extends MallSpuApi.Spu {
|
||||||
pointStock: number; // 积分商城活动库存
|
pointStock: number; // 积分商城活动库存
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MallSeckillActivityApi {
|
export namespace MallSeckillActivityApi {
|
||||||
@@ -34,17 +32,6 @@ export namespace MallSeckillActivityApi {
|
|||||||
seckillPrice?: number; // 秒杀价格
|
seckillPrice?: number; // 秒杀价格
|
||||||
products?: SeckillProduct[]; // 秒杀商品列表
|
products?: SeckillProduct[]; // 秒杀商品列表
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:这些还需要么?
|
|
||||||
/** 扩展 SKU 配置 */
|
|
||||||
export type SkuExtension = {
|
|
||||||
productConfig: SeckillProduct; // 秒杀商品配置
|
|
||||||
} & MallSpuApi.Sku;
|
|
||||||
|
|
||||||
/** 扩展 SPU 配置 */
|
|
||||||
export interface SpuExtension extends MallSpuApi.Spu {
|
|
||||||
skus: SkuExtension[]; // SKU 列表
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询秒杀活动列表 */
|
/** 查询秒杀活动列表 */
|
||||||
|
|||||||
@@ -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 SkuTableSelect } from './sku-table-select.vue';
|
||||||
export { default as SpuShowcase } from './spu-showcase.vue';
|
export { default as SpuShowcase } from './spu-showcase.vue';
|
||||||
export { default as SpuTableSelect } from './spu-table-select.vue';
|
export { default as SpuTableSelect } from './spu-table-select.vue';
|
||||||
|
export * from './type';
|
||||||
|
|||||||
@@ -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 };
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
import type { PropertyAndValues, RuleConfig } from '../index';
|
|
||||||
|
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
|
import type {
|
||||||
|
PropertyAndValues,
|
||||||
|
RuleConfig,
|
||||||
|
} from '#/views/mall/product/spu/components';
|
||||||
|
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
22
apps/web-antd/src/views/mall/product/spu/components/type.ts
Normal file
22
apps/web-antd/src/views/mall/product/spu/components/type.ts
Normal 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;
|
||||||
|
}
|
||||||
@@ -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';
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropertyAndValues, RuleConfig } from './index';
|
|
||||||
|
|
||||||
import type { MallSpuApi } from '#/api/mall/product/spu';
|
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 { onMounted, ref, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
@@ -14,6 +16,7 @@ import { Button, Card, message } from 'ant-design-vue';
|
|||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { createSpu, getSpu, updateSpu } from '#/api/mall/product/spu';
|
import { createSpu, getSpu, updateSpu } from '#/api/mall/product/spu';
|
||||||
|
import { getPropertyList, SkuList } from '#/views/mall/product/spu/components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useDeliveryFormSchema,
|
useDeliveryFormSchema,
|
||||||
@@ -22,10 +25,8 @@ import {
|
|||||||
useOtherFormSchema,
|
useOtherFormSchema,
|
||||||
useSkuFormSchema,
|
useSkuFormSchema,
|
||||||
} from './data';
|
} from './data';
|
||||||
import { getPropertyList } from './index';
|
|
||||||
import ProductAttributes from './modules/product-attributes.vue';
|
import ProductAttributes from './modules/product-attributes.vue';
|
||||||
import ProductPropertyAddForm from './modules/product-property-add-form.vue';
|
import ProductPropertyAddForm from './modules/product-property-add-form.vue';
|
||||||
import SkuList from './modules/sku-list.vue';
|
|
||||||
|
|
||||||
const spuId = ref<number>();
|
const spuId = ref<number>();
|
||||||
const { params, name } = useRoute();
|
const { params, name } = useRoute();
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<!-- 商品发布 - 库存价格 - 属性列表 -->
|
<!-- 商品发布 - 库存价格 - 属性列表 -->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropertyAndValues } from '../index';
|
|
||||||
|
|
||||||
import type { MallPropertyApi } from '#/api/mall/product/property';
|
import type { MallPropertyApi } from '#/api/mall/product/property';
|
||||||
|
import type { PropertyAndValues } from '#/views/mall/product/spu/components';
|
||||||
|
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MallPointActivityApi } from '#/api/mall/promotion/point';
|
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:有问题
|
// TODO @puhui999:有问题
|
||||||
// import type { SpuProperty } from '#/views/mall/promotion/components/types';
|
// import type { SpuProperty } from '#/views/mall/promotion/components/types';
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
updatePointActivity,
|
updatePointActivity,
|
||||||
} from '#/api/mall/promotion/point';
|
} from '#/api/mall/promotion/point';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
import { getPropertyList } from '#/views/mall/product/spu/form';
|
import { getPropertyList } from '#/views/mall/product/spu/components';
|
||||||
|
|
||||||
// TODO @puhui999:有问题
|
// TODO @puhui999:有问题
|
||||||
// import { SpuAndSkuList, SpuSkuSelect } from '../../../components';
|
// import { SpuAndSkuList, SpuSkuSelect } from '../../../components';
|
||||||
|
|||||||
Reference in New Issue
Block a user