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

View File

@ -3,7 +3,7 @@ import type { PropertyAndValues, RuleConfig } from './index';
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 { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
@ -24,6 +24,7 @@ import {
import { getPropertyList } from './index';
import ProductAttributes from './product-attributes.vue';
import ProductPropertyAddForm from './product-property-add-form.vue';
import SkuList from './sku-list.vue';
const spuId = ref<number>();
const { params, name } = useRoute();
@ -63,6 +64,7 @@ const formData = ref<MallSpuApi.Spu>({
const propertyList = ref<PropertyAndValues[]>([]); //
const formLoading = ref(false); // 12
const isDetail = ref(false); //
const skuListRef = ref(); // Ref
// sku
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({
commonConfig: {
componentProps: {
@ -119,8 +112,18 @@ const [SkuForm, skuFormApi] = useVbenForm({
labelWidth: 120,
},
layout: 'horizontal',
schema: skuFormSchema.value,
schema: useSkuFormSchema(propertyList.value, isDetail.value),
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({
@ -227,11 +230,8 @@ const getDetail = async () => {
}
});
formData.value = res;
// SKU PropertyAndValues
propertyList.value = getPropertyList(res);
//
infoFormApi.setValues(res);
// SpuSkuFormData
skuFormApi.setValues(res);
deliveryFormApi.setValues(res);
descriptionFormApi.setValues(res);
@ -240,18 +240,58 @@ const getDetail = async () => {
formLoading.value = false;
}
}
// SKU PropertyAndValues
propertyList.value = getPropertyList(formData.value);
};
// =========== sku form ===========
function openPropertyAddForm() {
productPropertyAddFormApi.open();
}
/** 调用 SkuList generateTableData 方法*/
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
watch(
skuFormSchema,
(newSchema) => {
skuFormApi.updateSchema(newSchema);
propertyList,
() => {
skuFormApi.updateSchema(
useSkuFormSchema(propertyList.value, isDetail.value),
);
},
{ deep: true },
);
@ -266,7 +306,7 @@ onMounted(async () => {
</script>
<template>
<ProductPropertyAddFormModal />
<ProductPropertyAddFormModal :property-list="propertyList" />
<Page auto-content-height>
<ContentWrap class="h-full w-full pb-8">
@ -278,13 +318,18 @@ onMounted(async () => {
<InfoForm class="w-3/5" />
</Tabs.TabPane>
<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>
<div>
<Button
class="mb-10px mr-15px"
@click="productPropertyAddFormApi.open"
>
<Button class="mb-10px mr-15px" @click="openPropertyAddForm">
添加属性
</Button>
<ProductAttributes
@ -294,6 +339,22 @@ onMounted(async () => {
/>
</div>
</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>
</Tabs.TabPane>
<Tabs.TabPane tab="物流设置" key="delivery">

View File

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

View File

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