!277 feat:【antd】【mall】spu 优化

Merge pull request !277 from puhui999/dev-mall
This commit is contained in:
芋道源码
2025-11-26 01:58:40 +00:00
committed by Gitee
22 changed files with 1038 additions and 312 deletions

View File

@@ -113,6 +113,7 @@ export function useFormSchema(): VbenFormSchema[] {
placeholder: '请输入排序',
class: '!w-full',
},
defaultValue: 0,
rules: 'required',
},
{

View File

@@ -1,13 +1,15 @@
<script lang="ts" setup>
import type { MallSpuApi } from '#/api/mall/product/spu';
import type { MallPointActivityApi } from '#/api/mall/promotion/point';
import type { RuleConfig } from '#/views/mall/product/spu/form';
// TODO @puhui999有问题
// import type { SpuProperty } from '#/views/mall/promotion/components/types';
import type {
RuleConfig,
SpuProperty,
} from '#/views/mall/product/spu/components';
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { convertToInteger, formatToFraction } from '@vben/utils';
import { cloneDeep, convertToInteger, formatToFraction } from '@vben/utils';
import { Button, InputNumber, message } from 'ant-design-vue';
@@ -20,10 +22,12 @@ import {
updatePointActivity,
} from '#/api/mall/promotion/point';
import { $t } from '#/locales';
import { getPropertyList } from '#/views/mall/product/spu/form';
import {
getPropertyList,
SpuAndSkuList,
SpuSkuSelect,
} from '#/views/mall/product/spu/components';
// TODO @puhui999有问题
// import { SpuAndSkuList, SpuSkuSelect } from '../../../components';
import { useFormSchema } from '../data';
const emit = defineEmits(['success']);
@@ -70,15 +74,12 @@ const ruleConfig: RuleConfig[] = [
},
]; // SKU 规则配置
const spuList = ref<any[]>([]); // 选择的 SPU 列表
// TODO @puhui999有问题
// const spuPropertyList = ref<SpuProperty<any>[]>([]); // SPU 属性列表
const spuPropertyList = ref<any[]>([]); // SPU 属性列表
const spuList = ref<MallSpuApi.Spu[]>([]); // 选择的 SPU 列表
const spuPropertyList = ref<SpuProperty<MallSpuApi.Spu>[]>([]); // SPU 属性列表
/** 打开商品选择器 */
// TODO @puhui999spuSkuSelectRef.value.open is not a function
function openSpuSelect() {
spuSkuSelectRef.value.open();
spuSkuSelectRef.value?.open();
}
/** 选择商品后的回调 */
@@ -106,7 +107,7 @@ async function getSpuDetails(
? res.skus
: res.skus?.filter((sku) => skuIds.includes(sku.id!));
// 为每个 SKU 配置积分商城相关的配置
selectSkus?.forEach((sku: any) => {
selectSkus?.forEach((sku) => {
let config: MallPointActivityApi.PointProduct = {
skuId: sku.id!,
stock: 0,
@@ -122,22 +123,26 @@ async function getSpuDetails(
}
config = product || config;
}
sku.productConfig = config;
// 动态添加 productConfig 属性到 SKU
(
sku as MallSpuApi.Sku & {
productConfig: MallPointActivityApi.PointProduct;
}
).productConfig = config;
});
res.skus = selectSkus;
// TODO @puhui999有问题
// const spuProperties: SpuProperty[] = [];
const spuProperties: any[] = [];
spuProperties.push({
spuId: res.id!,
spuDetail: res,
propertyList: getPropertyList(res),
});
// 构建 SPU 属性列表
const spuProperties: SpuProperty<MallSpuApi.Spu>[] = [
{
spuId: res.id!,
spuDetail: res,
propertyList: getPropertyList(res),
},
];
// TODO @puhui999貌似直接 = 下面的,不用 push
spuList.value.push(res);
// TODO @puhui999貌似直接 = 下面的,不用 push
// 直接赋值,因为每次只选择一个 SPU
spuList.value = [res];
spuPropertyList.value = spuProperties;
}
@@ -151,9 +156,10 @@ const [Modal, modalApi] = useVbenModal({
}
modalApi.lock();
try {
// 获取积分商城商品配置
const products: MallPointActivityApi.PointProduct[] =
spuAndSkuListRef.value?.getSkuConfigs('productConfig') || [];
// 获取积分商城商品配置(深拷贝避免直接修改原对象)
const products: MallPointActivityApi.PointProduct[] = cloneDeep(
spuAndSkuListRef.value?.getSkuConfigs('productConfig') || [],
);
// 价格需要转为分
products.forEach((item) => {
item.price = convertToInteger(item.price);
@@ -180,11 +186,22 @@ const [Modal, modalApi] = useVbenModal({
spuPropertyList.value = [];
return;
}
// 加载数据
// 重置表单数据(新增和编辑模式都需要)
formData.value = undefined;
spuList.value = [];
spuPropertyList.value = [];
// 加载数据(仅编辑模式)
const data = modalApi.getData<MallPointActivityApi.PointActivity>();
if (!data || !data.id) {
// 新增模式:重置表单字段
await formApi.setValues({
sort: 0,
remark: '',
spuId: undefined,
});
return;
}
// 编辑模式:加载数据
modalApi.lock();
try {
formData.value = await getPointActivity(data.id);
@@ -203,76 +220,77 @@ const [Modal, modalApi] = useVbenModal({
</script>
<template>
<Modal :title="getTitle" class="w-[70%]">
<Form class="mx-4">
<!-- 商品选择 -->
<template #spuId>
<div class="w-full">
<Button v-if="!formData?.id" type="primary" @click="openSpuSelect">
选择商品
</Button>
<div>
<Modal :title="getTitle" class="w-[70%]">
<Form class="mx-4">
<!-- 商品选择 -->
<template #spuId>
<div class="w-full">
<Button v-if="!formData?.id" type="primary" @click="openSpuSelect">
选择商品
</Button>
<!-- SPU SKU 列表展示 -->
<SpuAndSkuList
v-if="spuList.length > 0"
ref="spuAndSkuListRef"
:rule-config="ruleConfig"
:spu-list="spuList"
:spu-property-list="spuPropertyList"
class="mt-4"
>
<!-- 扩展列积分商城特有配置 -->
<template #default>
<VxeColumn align="center" min-width="168" title="可兑换库存">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.stock"
:max="sku.stock"
:min="0"
class="w-full"
/>
</template>
</VxeColumn>
<VxeColumn align="center" min-width="168" title="可兑换次数">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.count"
:min="0"
class="w-full"
/>
</template>
</VxeColumn>
<VxeColumn align="center" min-width="168" title="所需积分">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.point"
:min="0"
class="w-full"
/>
</template>
</VxeColumn>
<VxeColumn align="center" min-width="168" title="所需金额(元)">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.price"
:min="0"
:precision="2"
:step="0.1"
class="w-full"
/>
</template>
</VxeColumn>
</template>
</SpuAndSkuList>
</div>
</template>
</Form>
<!-- SPU SKU 列表展示 -->
<SpuAndSkuList
ref="spuAndSkuListRef"
:rule-config="ruleConfig"
:spu-list="spuList"
:spu-property-list-p="spuPropertyList"
class="mt-4"
>
<!-- 扩展列积分商城特有配置 -->
<template #default>
<VxeColumn align="center" min-width="168" title="可兑换库存">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.stock"
:max="sku.stock"
:min="0"
class="w-full"
/>
</template>
</VxeColumn>
<VxeColumn align="center" min-width="168" title="可兑换次数">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.count"
:min="0"
class="w-full"
/>
</template>
</VxeColumn>
<VxeColumn align="center" min-width="168" title="所需积分">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.point"
:min="0"
class="w-full"
/>
</template>
</VxeColumn>
<VxeColumn align="center" min-width="168" title="所需金额(元)">
<template #default="{ row: sku }">
<InputNumber
v-model:value="sku.productConfig.price"
:min="0"
:precision="2"
:step="0.1"
class="w-full"
/>
</template>
</VxeColumn>
</template>
</SpuAndSkuList>
</div>
</template>
</Form>
</Modal>
<!-- 商品选择器弹窗 -->
<SpuSkuSelect
ref="spuSkuSelectRef"
:is-select-sku="true"
@confirm="handleSpuSelected"
@select="handleSpuSelected"
/>
</Modal>
</div>
</template>