feat:【mall 商城】商品发布 - 库存价格【antd】80%: 完善 sku form 逻辑

pull/235/head
puhui999 2025-10-21 16:10:49 +08:00
parent 6ea2082e4b
commit 93149876e5
4 changed files with 97 additions and 53 deletions

View File

@ -1,7 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import { h } from 'vue';
import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants'; import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks'; import { getDictOptions } from '@vben/hooks';
import { handleTree } from '@vben/utils'; import { handleTree } from '@vben/utils';
@ -11,8 +9,6 @@ import { getSimpleBrandList } from '#/api/mall/product/brand';
import { getCategoryList } from '#/api/mall/product/category'; import { getCategoryList } from '#/api/mall/product/category';
import { getSimpleTemplateList } from '#/api/mall/trade/delivery/expressTemplate'; import { getSimpleTemplateList } from '#/api/mall/trade/delivery/expressTemplate';
import SkuList from './sku-list.vue';
/** 基础设置的表单 */ /** 基础设置的表单 */
export function useInfoFormSchema(): VbenFormSchema[] { export function useInfoFormSchema(): VbenFormSchema[] {
return [ return [
@ -110,7 +106,6 @@ export function useInfoFormSchema(): VbenFormSchema[] {
/** 价格库存的表单 */ /** 价格库存的表单 */
export function useSkuFormSchema( export function useSkuFormSchema(
propertyList: any[] = [], propertyList: any[] = [],
ruleConfig: any[] = [],
isDetail: boolean = false, isDetail: boolean = false,
): VbenFormSchema[] { ): VbenFormSchema[] {
return [ return [
@ -164,11 +159,8 @@ export function useSkuFormSchema(
{ {
fieldName: 'singleSkuList', fieldName: 'singleSkuList',
label: '', label: '',
component: h(SkuList), component: 'Input',
componentProps: { componentProps: {},
propertyList,
ruleConfig,
},
dependencies: { dependencies: {
triggerFields: ['specType'], triggerFields: ['specType'],
// 当 specType 为 false单规格时显示 // 当 specType 为 false单规格时显示
@ -191,11 +183,8 @@ export function useSkuFormSchema(
{ {
fieldName: 'batchSkuList', fieldName: 'batchSkuList',
label: '批量设置', label: '批量设置',
component: h(SkuList), component: 'Input',
componentProps: { componentProps: {},
isBatch: true,
propertyList,
},
dependencies: { dependencies: {
triggerFields: ['specType'], triggerFields: ['specType'],
// 当 specType 为 true多规格且 propertyList 有数据时显示,且非详情模式 // 当 specType 为 true多规格且 propertyList 有数据时显示,且非详情模式
@ -207,12 +196,8 @@ export function useSkuFormSchema(
{ {
fieldName: 'multiSkuList', fieldName: 'multiSkuList',
label: '规格列表', label: '规格列表',
component: h(SkuList), component: 'Input',
componentProps: { componentProps: {},
propertyList,
ruleConfig,
isDetail,
},
dependencies: { dependencies: {
triggerFields: ['specType'], triggerFields: ['specType'],
// 当 specType 为 true多规格且 propertyList 有数据时显示 // 当 specType 为 true多规格且 propertyList 有数据时显示

View File

@ -3,7 +3,7 @@ import type { PropertyAndValues, RuleConfig } from './index';
import type { MallSpuApi } from '#/api/mall/product/spu'; import type { MallSpuApi } from '#/api/mall/product/spu';
import { computed, onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { ContentWrap, Page, useVbenModal } from '@vben/common-ui'; import { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
@ -24,6 +24,7 @@ import {
import { getPropertyList } from './index'; import { getPropertyList } from './index';
import ProductAttributes from './product-attributes.vue'; import ProductAttributes from './product-attributes.vue';
import ProductPropertyAddForm from './product-property-add-form.vue'; import ProductPropertyAddForm from './product-property-add-form.vue';
import SkuList from './sku-list.vue';
const spuId = ref<number>(); const spuId = ref<number>();
const { params, name } = useRoute(); const { params, name } = useRoute();
@ -63,6 +64,7 @@ const formData = ref<MallSpuApi.Spu>({
const propertyList = ref<PropertyAndValues[]>([]); // const propertyList = ref<PropertyAndValues[]>([]); //
const formLoading = ref(false); // 12 const formLoading = ref(false); // 12
const isDetail = ref(false); // const isDetail = ref(false); //
const skuListRef = ref(); // Ref
// sku // sku
const ruleConfig: RuleConfig[] = [ const ruleConfig: RuleConfig[] = [
@ -88,15 +90,6 @@ const ruleConfig: RuleConfig[] = [
}, },
]; ];
// sku form schema
const skuFormSchema = computed(() => {
return useSkuFormSchema(
propertyList.value,
ruleConfig,
isDetail.value || false,
);
});
const [InfoForm, infoFormApi] = useVbenForm({ const [InfoForm, infoFormApi] = useVbenForm({
commonConfig: { commonConfig: {
componentProps: { componentProps: {
@ -119,8 +112,18 @@ const [SkuForm, skuFormApi] = useVbenForm({
labelWidth: 120, labelWidth: 120,
}, },
layout: 'horizontal', layout: 'horizontal',
schema: skuFormSchema.value, schema: useSkuFormSchema(propertyList.value, isDetail.value),
showDefaultActions: false, showDefaultActions: false,
handleValuesChange: (values, fieldsChanged) => {
if (fieldsChanged.includes('subCommissionType')) {
formData.value.subCommissionType = values.subCommissionType;
changeSubCommissionType();
}
if (fieldsChanged.includes('specType')) {
formData.value.specType = values.specType;
onChangeSpec();
}
},
}); });
const [ProductPropertyAddFormModal, productPropertyAddFormApi] = useVbenModal({ const [ProductPropertyAddFormModal, productPropertyAddFormApi] = useVbenModal({
@ -227,11 +230,8 @@ const getDetail = async () => {
} }
}); });
formData.value = res; formData.value = res;
// SKU PropertyAndValues
propertyList.value = getPropertyList(res);
// //
infoFormApi.setValues(res); infoFormApi.setValues(res);
// SpuSkuFormData
skuFormApi.setValues(res); skuFormApi.setValues(res);
deliveryFormApi.setValues(res); deliveryFormApi.setValues(res);
descriptionFormApi.setValues(res); descriptionFormApi.setValues(res);
@ -240,18 +240,58 @@ const getDetail = async () => {
formLoading.value = false; formLoading.value = false;
} }
} }
// SKU PropertyAndValues
propertyList.value = getPropertyList(formData.value);
}; };
// =========== sku form ===========
function openPropertyAddForm() {
productPropertyAddFormApi.open();
}
/** 调用 SkuList generateTableData 方法*/ /** 调用 SkuList generateTableData 方法*/
const generateSkus = (propertyList: any[]) => { const generateSkus = (propertyList: any[]) => {
// skuListRef.value.generateTableData(propertyList) skuListRef.value.generateTableData(propertyList);
};
/** 分销类型 */
const changeSubCommissionType = () => {
//
for (const item of formData.value.skus!) {
item.firstBrokeragePrice = 0;
item.secondBrokeragePrice = 0;
}
};
/** 选择规格 */
const onChangeSpec = () => {
//
propertyList.value = [];
// sku
formData.value.skus = [
{
price: 0,
marketPrice: 0,
costPrice: 0,
barCode: '',
picUrl: '',
stock: 0,
weight: 0,
volume: 0,
firstBrokeragePrice: 0,
secondBrokeragePrice: 0,
},
];
}; };
// sku form schema // sku form schema
watch( watch(
skuFormSchema, propertyList,
(newSchema) => { () => {
skuFormApi.updateSchema(newSchema); skuFormApi.updateSchema(
useSkuFormSchema(propertyList.value, isDetail.value),
);
}, },
{ deep: true }, { deep: true },
); );
@ -266,7 +306,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<ProductPropertyAddFormModal /> <ProductPropertyAddFormModal :property-list="propertyList" />
<Page auto-content-height> <Page auto-content-height>
<ContentWrap class="h-full w-full pb-8"> <ContentWrap class="h-full w-full pb-8">
@ -278,13 +318,18 @@ onMounted(async () => {
<InfoForm class="w-3/5" /> <InfoForm class="w-3/5" />
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane tab="价格库存" key="sku"> <Tabs.TabPane tab="价格库存" key="sku">
<SkuForm class="w-3/5"> <SkuForm class="w-full">
<template #singleSkuList>
<SkuList
ref="skuListRef"
:prop-form-data="formData"
:property-list="propertyList"
:rule-config="ruleConfig"
/>
</template>
<template #productAttributes> <template #productAttributes>
<div> <div>
<Button <Button class="mb-10px mr-15px" @click="openPropertyAddForm">
class="mb-10px mr-15px"
@click="productPropertyAddFormApi.open"
>
添加属性 添加属性
</Button> </Button>
<ProductAttributes <ProductAttributes
@ -294,6 +339,22 @@ onMounted(async () => {
/> />
</div> </div>
</template> </template>
<template #batchSkuList>
<SkuList
:is-batch="true"
:prop-form-data="formData"
:property-list="propertyList"
/>
</template>
<template #multiSkuList>
<SkuList
ref="skuListRef"
:is-detail="isDetail"
:prop-form-data="formData"
:property-list="propertyList"
:rule-config="ruleConfig"
/>
</template>
</SkuForm> </SkuForm>
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane tab="物流设置" key="delivery"> <Tabs.TabPane tab="物流设置" key="delivery">

View File

@ -87,6 +87,7 @@ const [Form, formApi] = useVbenForm({
// //
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({
destroyOnClose: true, //
async onConfirm() { async onConfirm() {
const { valid } = await formApi.validate(); const { valid } = await formApi.validate();
if (!valid) return; if (!valid) return;
@ -118,7 +119,6 @@ const [Modal, modalApi] = useVbenModal({
} }
// //
modalApi.lock();
try { try {
const data = { name } as MallPropertyApi.Property; const data = { name } as MallPropertyApi.Property;
const propertyId = await createProperty(data); const propertyId = await createProperty(data);
@ -131,8 +131,9 @@ const [Modal, modalApi] = useVbenModal({
message.success($t('common.createSuccess')); message.success($t('common.createSuccess'));
await modalApi.close(); await modalApi.close();
emit('success'); emit('success');
} finally { } catch (error) {
modalApi.unlock(); //
console.error('添加属性失败:', error);
} }
}, },
async onOpenChange(isOpen: boolean) { async onOpenChange(isOpen: boolean) {

View File

@ -214,11 +214,8 @@ const validateData = (propertyList: PropertyAndValues[]): boolean => {
sku.properties sku.properties
?.map((property: MallSpuApi.Property) => property.propertyId) ?.map((property: MallSpuApi.Property) => property.propertyId)
?.forEach((propertyId?: number) => { ?.forEach((propertyId?: number) => {
if ( if (!skuPropertyIds.includes(propertyId!)) {
propertyId !== undefined && skuPropertyIds.push(propertyId!);
!skuPropertyIds.indexOf(propertyId) === -1
) {
skuPropertyIds.push(propertyId);
} }
}), }),
); );