From e1e0554aca0fc626987fe33cf48e53d8e0b56c65 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 20 Dec 2025 09:13:38 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90ele=E3=80=91=E3=80=90mall?= =?UTF-8?q?=E3=80=91spu=20=E4=BB=A3=E7=A0=81=E5=AF=B9=E9=BD=90=20antd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spu/components/sku-table-select.vue | 29 +++-- .../product/spu/components/spu-select.vue | 6 +- .../product/spu/components/spu-showcase.vue | 7 +- .../spu/components/spu-table-select.vue | 81 ++++++------ .../src/views/mall/product/spu/form/index.vue | 119 ++++++++---------- .../spu/form/modules/product-attributes.vue | 7 +- .../modules/product-property-add-form.vue | 2 +- 7 files changed, 119 insertions(+), 132 deletions(-) diff --git a/apps/web-ele/src/views/mall/product/spu/components/sku-table-select.vue b/apps/web-ele/src/views/mall/product/spu/components/sku-table-select.vue index 015345392..c4e23a314 100644 --- a/apps/web-ele/src/views/mall/product/spu/components/sku-table-select.vue +++ b/apps/web-ele/src/views/mall/product/spu/components/sku-table-select.vue @@ -22,16 +22,6 @@ const emit = defineEmits<{ const visible = ref(false); const spuId = ref(); -/** 处理选中 */ -function handleRadioChange() { - const selectedRow = gridApi.grid.getRadioRecord() as MallSpuApi.Sku; - if (selectedRow) { - emit('change', selectedRow); - closeModal(); - } -} - -// TODO @puhui999:这里的代码风格,对齐 antd 的;可以使用 idea 对比两个文件哈; const [Grid, gridApi] = useVbenVxeGrid({ gridOptions: { columns: useSkuGridColumns(), @@ -39,20 +29,33 @@ const [Grid, gridApi] = useVbenVxeGrid({ border: true, radioConfig: { reserve: true, + highlight: true, + }, + rowConfig: { + keyField: 'id', + isHover: true, }, pagerConfig: { enabled: false, }, }, gridEvents: { - radioChange: handleRadioChange, + radioChange: () => { + const selectedRow = gridApi.grid.getRadioRecord() as MallSpuApi.Sku; + if (selectedRow) { + emit('change', selectedRow); + // 关闭弹窗 + visible.value = false; + gridApi.grid.clearRadioRow(); + spuId.value = undefined; + } + }, }, }); /** 关闭弹窗 */ function closeModal() { visible.value = false; - gridApi.grid.clearRadioRow(); spuId.value = undefined; } @@ -63,6 +66,8 @@ async function openModal(data?: SpuData) { } spuId.value = data.spuId; visible.value = true; + // 注意:useVbenVxeGrid 关闭分页(pagerConfig.enabled=false)后,proxyConfig.ajax.query 的结果不会传递到 vxe-table + // 需要手动调用 reloadData 设置表格数据 if (!spuId.value) { gridApi.grid?.reloadData([]); return; diff --git a/apps/web-ele/src/views/mall/product/spu/components/spu-select.vue b/apps/web-ele/src/views/mall/product/spu/components/spu-select.vue index e49b31cfd..0b32a9639 100644 --- a/apps/web-ele/src/views/mall/product/spu/components/spu-select.vue +++ b/apps/web-ele/src/views/mall/product/spu/components/spu-select.vue @@ -312,8 +312,10 @@ onMounted(async () => { diff --git a/apps/web-ele/src/views/mall/product/spu/components/spu-showcase.vue b/apps/web-ele/src/views/mall/product/spu/components/spu-showcase.vue index 468d763de..940ad3d81 100644 --- a/apps/web-ele/src/views/mall/product/spu/components/spu-showcase.vue +++ b/apps/web-ele/src/views/mall/product/spu/components/spu-showcase.vue @@ -108,14 +108,12 @@ function emitSpuChange() { - @@ -129,8 +127,7 @@ function emitSpuChange() { class="flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-lg border-2 border-dashed transition-colors hover:border-primary hover:bg-primary/5" @click="handleOpenSpuSelect" > - - + diff --git a/apps/web-ele/src/views/mall/product/spu/components/spu-table-select.vue b/apps/web-ele/src/views/mall/product/spu/components/spu-table-select.vue index d2d165562..2d337b47d 100644 --- a/apps/web-ele/src/views/mall/product/spu/components/spu-table-select.vue +++ b/apps/web-ele/src/views/mall/product/spu/components/spu-table-select.vue @@ -52,19 +52,23 @@ const formSchema = computed(() => [ component: 'Input', componentProps: { placeholder: '请输入商品名称', - clearable: true, + allowClear: true, }, }, { fieldName: 'categoryId', label: '商品分类', - component: 'ApiTreeSelect', + component: 'TreeSelect', componentProps: { - options: categoryTreeList, - props: { label: 'name', children: 'children' }, - nodeKey: 'id', + data: categoryTreeList, + props: { + label: 'name', + value: 'id', + }, + checkStrictly: true, placeholder: '请选择商品分类', clearable: true, + filterable: true, }, }, { @@ -73,7 +77,7 @@ const formSchema = computed(() => [ component: 'RangePicker', componentProps: { ...getRangePickerDefaultProps(), - clearable: true, + allowClear: true, }, }, ]); @@ -162,40 +166,35 @@ const [Grid, gridApi] = useVbenVxeGrid({ async function openModal(data?: MallSpuApi.Spu | MallSpuApi.Spu[]) { initData.value = data; visible.value = true; + // 等待 Grid 组件完全初始化后再查询数据 await nextTick(); - // 1. 查询数据 - await gridApi.query(); - // 2. 设置已选中行 - const tableData = gridApi.grid.getTableData().fullData; - if ( - props.multiple && - Array.isArray(initData.value) && - initData.value.length > 0 - ) { - setTimeout(() => { - (initData.value as unknown as MallSpuApi.Spu[])!.forEach((spu) => { + if (gridApi.grid) { + // 1. 先查询数据 + await gridApi.query(); + // 2. 设置已选中行 + if (props.multiple && Array.isArray(data) && data.length > 0) { + setTimeout(() => { + const tableData = gridApi.grid.getTableData().fullData; + data.forEach((spu) => { + const row = tableData.find( + (item: MallSpuApi.Spu) => item.id === spu.id, + ); + if (row) { + gridApi.grid.setCheckboxRow(row, true); + } + }); + }, 300); + } else if (!props.multiple && data && !Array.isArray(data)) { + setTimeout(() => { + const tableData = gridApi.grid.getTableData().fullData; const row = tableData.find( - (item: MallSpuApi.Spu) => item.id === spu.id, + (item: MallSpuApi.Spu) => item.id === data.id, ); if (row) { - gridApi.grid.setCheckboxRow(row, true); + gridApi.grid.setRadioRow(row); } - }); - }, 300); - } else if ( - !props.multiple && - initData.value && - !Array.isArray(initData.value) - ) { - setTimeout(() => { - const row = tableData.find( - (item: MallSpuApi.Spu) => - item.id === (initData.value as MallSpuApi.Spu).id, - ); - if (row) { - gridApi.grid.setRadioRow(row); - } - }, 300); + }, 300); + } } } @@ -214,10 +213,9 @@ function handleConfirm() { closeModal(); } -/** 对外暴露的方法 */ defineExpose({ open: openModal, -}); +}); // 对外暴露的方法 /** 初始化分类数据 */ onMounted(async () => { @@ -232,13 +230,14 @@ onMounted(async () => { title="选择商品" width="950px" :destroy-on-close="true" - :append-to-body="true" @close="closeModal" > - diff --git a/apps/web-ele/src/views/mall/product/spu/form/index.vue b/apps/web-ele/src/views/mall/product/spu/form/index.vue index 4b2fe8088..5f584c9a8 100644 --- a/apps/web-ele/src/views/mall/product/spu/form/index.vue +++ b/apps/web-ele/src/views/mall/product/spu/form/index.vue @@ -32,7 +32,6 @@ const spuId = ref(); const { params, name } = useRoute(); const { closeCurrentTab } = useTabs(); const activeTabName = ref('info'); - const formLoading = ref(false); // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const isDetail = ref(name === 'ProductSpuDetail'); // 是否查看详情 const skuListRef = ref(); // 商品属性列表 Ref @@ -70,7 +69,6 @@ const formData = ref({ }); // spu 表单数据 const propertyList = ref([]); // 商品属性列表 const ruleConfig: RuleConfig[] = [ - // TODO @puhui999:ele 这里都有 :number,antd 要不要加? { name: 'stock', rule: (arg: number) => arg >= 0, @@ -200,7 +198,7 @@ async function handleSubmit() { item.secondBrokeragePrice = convertToInteger(item.secondBrokeragePrice); }); } - // 处理轮播图列表 TODO @puhui999:这个是必须的哇? + // 处理轮播图列表:上传组件可能返回对象或字符串,统一处理成字符串数组 const newSliderPicUrls: any[] = []; values.sliderPicUrls!.forEach((item: any) => { // 如果是前端选的图 @@ -319,13 +317,10 @@ onMounted(async () => { - + -
- - - + + + + + +
- diff --git a/apps/web-ele/src/views/mall/product/spu/form/modules/product-attributes.vue b/apps/web-ele/src/views/mall/product/spu/form/modules/product-attributes.vue index a81137fd0..e92e00237 100644 --- a/apps/web-ele/src/views/mall/product/spu/form/modules/product-attributes.vue +++ b/apps/web-ele/src/views/mall/product/spu/form/modules/product-attributes.vue @@ -215,18 +215,17 @@ async function getAttributeOptions(propertyId: number) {
- + 添加
diff --git a/apps/web-ele/src/views/mall/product/spu/form/modules/product-property-add-form.vue b/apps/web-ele/src/views/mall/product/spu/form/modules/product-property-add-form.vue index b45bd92c9..789ecd139 100644 --- a/apps/web-ele/src/views/mall/product/spu/form/modules/product-property-add-form.vue +++ b/apps/web-ele/src/views/mall/product/spu/form/modules/product-property-add-form.vue @@ -61,9 +61,9 @@ const formSchema: VbenFormSchema[] = [ })); }, filterable: true, + allowCreate: true, placeholder: '请选择属性名称。如果不存在,可手动输入选择', multiple: true, - allowCreate: true, clearable: true, }, rules: 'required',