fix:【antd】【mall】业务弹窗选择组件的 Modal 改成使用 antd 自己的。原因是 vben modal 嵌套关闭一个会全都关闭。

This commit is contained in:
puhui999
2025-11-25 19:02:56 +08:00
parent 58e958fd87
commit c1fa433348
2 changed files with 123 additions and 114 deletions

View File

@@ -7,10 +7,9 @@ import type { MallSpuApi } from '#/api/mall/product/spu';
import { computed, nextTick, onMounted, ref } from 'vue'; import { computed, nextTick, onMounted, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { handleTree } from '@vben/utils'; import { handleTree } from '@vben/utils';
import { message } from 'ant-design-vue'; import { message, Modal } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getCategoryList } from '#/api/mall/product/category'; import { getCategoryList } from '#/api/mall/product/category';
@@ -28,7 +27,7 @@ const props = withDefaults(defineProps<SpuSelectProps>(), {
}); });
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'confirm', spuId: number, skuIds?: number[]): void; (e: 'select', spuId: number, skuIds?: number[]): void;
}>(); }>();
interface SpuSelectProps { interface SpuSelectProps {
@@ -97,11 +96,6 @@ function selectSpu(row: MallSpuApi.Spu) {
if (selectedSkuIds.value.length > 0) { if (selectedSkuIds.value.length > 0) {
selectedSkuIds.value = []; selectedSkuIds.value = [];
} }
// 自动展开选中的 SPU
if (props.isSelectSku) {
expandChange(row, [row]);
}
} }
/** 处理行展开变化 */ /** 处理行展开变化 */
@@ -222,8 +216,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
}, },
}, },
gridEvents: { gridEvents: {
radioChange: ({ row }: { row: MallSpuApi.Spu }) => { radioChange: ({ row, $grid }: { $grid: any; row: MallSpuApi.Spu }) => {
selectSpu(row); selectSpu(row);
if (props.isSelectSku) {
$grid.clearRowExpand();
$grid.setRowExpand(row, true);
expandChange(row, [row]);
}
}, },
toggleRowExpand: ({ toggleRowExpand: ({
row, row,
@@ -241,50 +240,51 @@ const [Grid, gridApi] = useVbenVxeGrid({
}, },
}); });
/** 初始化弹窗 */ /** 弹窗显示状态 */
const [Modal, modalApi] = useVbenModal({ const visible = ref(false);
destroyOnClose: true,
onConfirm: () => {
if (selectedSpuId.value === 0) {
message.warning('没有选择任何商品');
return;
}
if (props.isSelectSku && selectedSkuIds.value.length === 0) {
message.warning('没有选择任何商品属性');
return;
}
// 返回各自 id 列表
props.isSelectSku
? emit('confirm', selectedSpuId.value, selectedSkuIds.value)
: emit('confirm', selectedSpuId.value);
// 重置选中状态 /** 打开弹窗 */
selectedSpuId.value = 0; async function openModal() {
selectedSkuIds.value = []; visible.value = true;
modalApi.close(); // 等待 Grid 组件完全初始化后再查询数据
}, await nextTick();
async onOpenChange(isOpen: boolean) { if (gridApi.grid) {
if (!isOpen) { await gridApi.query();
selectedSpuId.value = 0; }
selectedSkuIds.value = []; }
spuData.value = undefined;
propertyList.value = []; /** 关闭弹窗 */
isExpand.value = false; function closeModal() {
return; visible.value = false;
} selectedSpuId.value = 0;
// 等待 Grid 组件完全初始化后再查询数据 selectedSkuIds.value = [];
await nextTick(); spuData.value = undefined;
if (gridApi.grid) { propertyList.value = [];
await gridApi.query(); isExpand.value = false;
} }
},
}); /** 确认选择 */
function handleConfirm() {
if (selectedSpuId.value === 0) {
message.warning('没有选择任何商品');
return;
}
if (props.isSelectSku && selectedSkuIds.value.length === 0) {
message.warning('没有选择任何商品属性');
return;
}
// 返回各自 id 列表
props.isSelectSku
? emit('select', selectedSpuId.value, selectedSkuIds.value)
: emit('select', selectedSpuId.value);
// 重置选中状态
closeModal();
}
/** 对外暴露的方法 */ /** 对外暴露的方法 */
defineExpose({ defineExpose({
open: () => { open: openModal,
modalApi.open();
},
}); });
/** 初始化分类数据 */ /** 初始化分类数据 */
@@ -299,7 +299,14 @@ onMounted(async () => {
</script> </script>
<template> <template>
<Modal title="商品选择" class="w-[70%]"> <Modal
v-model:open="visible"
title="商品选择"
width="70%"
:destroy-on-close="true"
@ok="handleConfirm"
@cancel="closeModal"
>
<Grid> <Grid>
<!-- 展开列内容SKU 列表 --> <!-- 展开列内容SKU 列表 -->
<template v-if="isSelectSku" #expand_content="{ row }"> <template v-if="isSelectSku" #expand_content="{ row }">

View File

@@ -220,75 +220,77 @@ const [Modal, modalApi] = useVbenModal({
</script> </script>
<template> <template>
<Modal :title="getTitle" class="w-[70%]"> <div>
<Form class="mx-4"> <Modal :title="getTitle" class="w-[70%]">
<!-- 商品选择 --> <Form class="mx-4">
<template #spuId> <!-- 商品选择 -->
<div class="w-full"> <template #spuId>
<Button v-if="!formData?.id" type="primary" @click="openSpuSelect"> <div class="w-full">
选择商品 <Button v-if="!formData?.id" type="primary" @click="openSpuSelect">
</Button> 选择商品
</Button>
<!-- SPU SKU 列表展示 --> <!-- SPU SKU 列表展示 -->
<SpuAndSkuList <SpuAndSkuList
ref="spuAndSkuListRef" ref="spuAndSkuListRef"
:rule-config="ruleConfig" :rule-config="ruleConfig"
:spu-list="spuList" :spu-list="spuList"
:spu-property-list-p="spuPropertyList" :spu-property-list-p="spuPropertyList"
class="mt-4" class="mt-4"
> >
<!-- 扩展列积分商城特有配置 --> <!-- 扩展列积分商城特有配置 -->
<template #default> <template #default>
<VxeColumn align="center" min-width="168" title="可兑换库存"> <VxeColumn align="center" min-width="168" title="可兑换库存">
<template #default="{ row: sku }"> <template #default="{ row: sku }">
<InputNumber <InputNumber
v-model:value="sku.productConfig.stock" v-model:value="sku.productConfig.stock"
:max="sku.stock" :max="sku.stock"
:min="0" :min="0"
class="w-full" class="w-full"
/> />
</template> </template>
</VxeColumn> </VxeColumn>
<VxeColumn align="center" min-width="168" title="可兑换次数"> <VxeColumn align="center" min-width="168" title="可兑换次数">
<template #default="{ row: sku }"> <template #default="{ row: sku }">
<InputNumber <InputNumber
v-model:value="sku.productConfig.count" v-model:value="sku.productConfig.count"
:min="0" :min="0"
class="w-full" class="w-full"
/> />
</template> </template>
</VxeColumn> </VxeColumn>
<VxeColumn align="center" min-width="168" title="所需积分"> <VxeColumn align="center" min-width="168" title="所需积分">
<template #default="{ row: sku }"> <template #default="{ row: sku }">
<InputNumber <InputNumber
v-model:value="sku.productConfig.point" v-model:value="sku.productConfig.point"
:min="0" :min="0"
class="w-full" class="w-full"
/> />
</template> </template>
</VxeColumn> </VxeColumn>
<VxeColumn align="center" min-width="168" title="所需金额(元)"> <VxeColumn align="center" min-width="168" title="所需金额(元)">
<template #default="{ row: sku }"> <template #default="{ row: sku }">
<InputNumber <InputNumber
v-model:value="sku.productConfig.price" v-model:value="sku.productConfig.price"
:min="0" :min="0"
:precision="2" :precision="2"
:step="0.1" :step="0.1"
class="w-full" class="w-full"
/> />
</template> </template>
</VxeColumn> </VxeColumn>
</template> </template>
</SpuAndSkuList> </SpuAndSkuList>
</div> </div>
</template> </template>
</Form> </Form>
</Modal>
<!-- 商品选择器弹窗 --> <!-- 商品选择器弹窗 -->
<SpuSkuSelect <SpuSkuSelect
ref="spuSkuSelectRef" ref="spuSkuSelectRef"
:is-select-sku="true" :is-select-sku="true"
@confirm="handleSpuSelected" @select="handleSpuSelected"
/> />
</Modal> </div>
</template> </template>