review:【antd】【mall】商品发布的迁移

This commit is contained in:
YunaiV
2025-11-26 10:21:19 +08:00
parent 58e8a71936
commit 2401559fa5
9 changed files with 30 additions and 49 deletions

View File

@@ -16,7 +16,6 @@ export function useFormSchema(): VbenFormSchema[] {
show: () => false,
},
},
// TODO @puhui999商品的选择
{
fieldName: 'spuId',
label: '商品',
@@ -24,11 +23,9 @@ export function useFormSchema(): VbenFormSchema[] {
componentProps: {
placeholder: '请选择商品',
},
renderComponentContent: () => ({
default: () => null,
}),
rules: 'required',
},
// TODO @puhui999商品的选择上面 spuId 可以选择了,下面的 skuId 打开后,没商品。
{
fieldName: 'skuId',
label: '商品规格',
@@ -40,9 +37,6 @@ export function useFormSchema(): VbenFormSchema[] {
triggerFields: ['spuId'],
show: (values) => !!values.spuId,
},
renderComponentContent: () => ({
default: () => null,
}),
rules: 'required',
},
{

View File

@@ -48,6 +48,7 @@ const [Form, formApi] = useVbenForm({
const skuTableSelectRef = ref<InstanceType<typeof SkuTableSelect>>();
const selectedSku = ref<MallSpuApi.Sku>();
/** 处理商品的选择变化 */
async function handleSpuChange(spu?: MallSpuApi.Spu | null) {
// 处理商品选择:如果 spu 为 null 或 id 为 0表示清空选择
const spuId = spu?.id && spu.id ? spu.id : undefined;
@@ -59,6 +60,7 @@ async function handleSpuChange(spu?: MallSpuApi.Spu | null) {
await formApi.setFieldValue('skuId', undefined);
}
/** 打开商品规格的选择弹框 */
async function openSkuSelect() {
const currentValues =
(await formApi.getValues()) as Partial<MallCommentApi.Comment>;
@@ -70,6 +72,7 @@ async function openSkuSelect() {
skuTableSelectRef.value?.open({ spuId: currentSpuId });
}
/** 处理商品规格的选择 */
async function handleSkuSelected(sku: MallSpuApi.Sku) {
selectedSku.value = sku;
formData.value.skuId = sku.id;
@@ -98,6 +101,7 @@ const [Modal, modalApi] = useVbenModal({
async onOpenChange(isOpen: boolean) {
if (!isOpen) {
// 重置表单数据
// TODO @puhui999105 到 108 的代码,不需要的呀?(可以测试下)
formData.value = {
descriptionScores: 5,
benefitScores: 5,
@@ -108,6 +112,7 @@ const [Modal, modalApi] = useVbenModal({
// 加载数据
const data = modalApi.getData<MallCommentApi.Comment>();
if (!data || !data.id) {
// TODO @puhui999115 到 121 的代码,不需要的呀?(可以测试下)
// 新建模式:重置表单
formData.value = {
descriptionScores: 5,
@@ -123,7 +128,7 @@ const [Modal, modalApi] = useVbenModal({
formData.value = await getComment(data.id);
// 设置到 values
await formApi.setValues(formData.value);
// 回显已选规格
// 回显已选的商品规格
if (formData.value?.spuId && formData.value?.skuId) {
const spu = await getSpu(formData.value.spuId);
const sku = spu.skus?.find((item) => item.id === formData.value!.skuId);
@@ -166,9 +171,8 @@ const [Modal, modalApi] = useVbenModal({
selectedSku.properties.length > 0
"
>
已选:{{
selectedSku.properties.map((p: any) => p.valueName).join('/')
}}
已选:
{{ selectedSku.properties.map((p: any) => p.valueName).join('/') }}
</span>
<span v-else-if="selectedSku">已选:{{ selectedSku.id }}</span>
</div>

View File

@@ -2,7 +2,7 @@
import type { MallSpuApi } from '#/api/mall/product/spu';
import type { PropertyAndValues } from '#/views/mall/product/spu/components/type';
/** 获得商品的规格列表 - 商品相关的公共函数(被其模块如 promotion 使用) */
/** 获得商品的规格列表 - 商品相关的公共函数(被其模块如 promotion 使用) */
const getPropertyList = (spu: MallSpuApi.Spu): PropertyAndValues[] => {
// 直接拿返回的 skus 属性逆向生成出 propertyList
const properties: PropertyAndValues[] = [];

View File

@@ -78,6 +78,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
enabled: false,
},
proxyConfig: {
// TODO @puhui999看看注释的部分后续要不要删除
// autoLoad: false, // 禁用自动加载,手动触发查询
ajax: {
query: async () => {
@@ -121,6 +122,7 @@ async function openModal(data?: SpuData) {
}
spuId.value = data.spuId;
visible.value = true;
// TODO @puhui999看看注释的部分后续要不要删除
// // 等待弹窗和 Grid 组件完全渲染后再查询数据
// await nextTick();
// if (gridApi.grid) {

View File

@@ -45,6 +45,7 @@ const expandRowKeys = ref<string[]>([]); // 控制展开行需要设置 row-key
function getSkuConfigs(extendedAttribute: string) {
// 验证 SKU 数据(如果有 ref 的话)
if (skuListRef.value) {
// TODO @puhui999这里有个 linter 错误;
try {
skuListRef.value.validateSku();
} catch (error) {
@@ -64,8 +65,7 @@ function getSkuConfigs(extendedAttribute: string) {
return seckillProducts;
}
// 暴露出给表单提交时使用
defineExpose({ getSkuConfigs });
defineExpose({ getSkuConfigs }); // 暴露出给表单提交时使用
/** 多选时可以删除 SPU */
async function deleteSpu(spuId: number) {
@@ -77,9 +77,7 @@ async function deleteSpu(spuId: number) {
}
}
/**
* 将传进来的值赋值给 spuData
*/
/** 将传进来的值赋值给 spuData */
watch(
() => props.spuList,
(data) => {
@@ -92,9 +90,7 @@ watch(
},
);
/**
* 将传进来的值赋值给 spuPropertyList
*/
/** 将传进来的值赋值给 spuPropertyList */
watch(
() => props.spuPropertyListP,
(data) => {

View File

@@ -6,13 +6,9 @@ import type { MallCategoryApi } from '#/api/mall/product/category';
import { computed } from 'vue';
import { formatToFraction } from '@vben/utils';
import { getRangePickerDefaultProps } from '#/utils';
/**
* @description: 列表的搜索表单
*/
/** 列表的搜索表单 */
export function useGridFormSchema(
categoryTreeList: Ref<MallCategoryApi.Category[] | unknown[]>,
): VbenFormSchema[] {
@@ -55,9 +51,7 @@ export function useGridFormSchema(
];
}
/**
* @description: 列表的字段
*/
/** 列表的字段 */
export function useGridColumns(
isSelectSku: boolean,
): VxeTableGridOptions['columns'] {
@@ -95,10 +89,7 @@ export function useGridColumns(
title: '商品售价',
minWidth: 90,
align: 'center',
formatter: ({ cellValue }) => {
// 格式化价格显示(价格以分为单位存储)
return formatToFraction(cellValue);
},
formatter: 'formatAmount2',
},
{
field: 'salesCount',

View File

@@ -104,7 +104,7 @@ async function expandChange(
expandedRows?: MallSpuApi.Spu[],
) {
// 判断需要展开的 spuId === 选择的 spuId。如果选择了 A 就展开 A 的 skuList。如果选择了 A 手动展开 B 则阻断
// 目的防止误选 sku
// 目的防止误选 sku
if (selectedSpuId.value !== 0) {
if (row.id !== selectedSpuId.value) {
message.warning('你已选择商品请先取消');
@@ -138,8 +138,6 @@ async function expandChange(
return;
}
const res = (await getSpu(row.id)) as MallSpuApi.Spu;
// 注意API 返回的价格应该已经是分为单位,无需转换
// 如果 API 返回的是元,则需要转换为分:
res.skus?.forEach((item) => {
if (typeof item.price === 'number') {
item.price = Math.round(item.price * 100);
@@ -162,10 +160,7 @@ async function expandChange(
isExpand.value = true;
}
/** 搜索表单 Schema */
const formSchema = computed(() => useGridFormSchema(categoryTreeList));
/** 表格列配置 */
const formSchema = computed(() => useGridFormSchema(categoryTreeList)); // 搜索表单 Schema
const gridColumns = computed<VxeTableGridOptions['columns']>(() => {
const columns = useGridColumns(props.isSelectSku);
// 将 checkbox 替换为 radio
@@ -175,9 +170,8 @@ const gridColumns = computed<VxeTableGridOptions['columns']>(() => {
}
return col;
});
});
}); // 表格列配置
/** 初始化列表 */
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: formSchema.value,
@@ -196,6 +190,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
keyField: 'id',
isHover: true,
},
// TODO @puhui999貌似直接 { trigger: 'row', reserve: true } 就可以了?不会影响 radio 的哈。(可以测试下。)
expandConfig: props.isSelectSku
? {
trigger: 'row',
@@ -240,8 +235,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
},
});
/** 弹窗显示状态 */
const visible = ref(false);
const visible = ref(false); // 弹窗显示状态
/** 打开弹窗 */
async function openModal() {

View File

@@ -215,10 +215,9 @@ function handleConfirm() {
closeModal();
}
/** 对外暴露的方法 */
defineExpose({
open: openModal,
});
}); // 对外暴露的方法
/** 初始化分类数据 */
onMounted(async () => {

View File

@@ -132,14 +132,13 @@ async function getSpuDetails(
});
res.skus = selectSkus;
// 构建 SPU 属性列表
const spuProperties: SpuProperty<MallSpuApi.Spu>[] = [
{
spuId: res.id!,
spuDetail: res,
propertyList: getPropertyList(res),
},
];
]; // 构建 SPU 属性列表
// 直接赋值,因为每次只选择一个 SPU
spuList.value = [res];
@@ -187,13 +186,15 @@ const [Modal, modalApi] = useVbenModal({
return;
}
// 重置表单数据(新增和编辑模式都需要)
// TODO @puhui999这里的重置是不是在 183 到 185 已经处理了呀。
formData.value = undefined;
spuList.value = [];
spuPropertyList.value = [];
// 加载数据(仅编辑模式)
// 加载数据
const data = modalApi.getData<MallPointActivityApi.PointActivity>();
if (!data || !data.id) {
// 新增模式:重置表单字段
// TODO @puhui999197 到 201 这块的 setValues 的设置,是不是必要哈。可以看看。
await formApi.setValues({
sort: 0,
remark: '',
@@ -201,7 +202,7 @@ const [Modal, modalApi] = useVbenModal({
});
return;
}
// 编辑模式:加载数据
// 加载数据
modalApi.lock();
try {
formData.value = await getPointActivity(data.id);