import type { Ref } from 'vue'; import type { PointMallProductCardViewModel, PointMallProductEditorForm, } from '#/views/member/points-mall/types'; import { message } from 'ant-design-vue'; import { getMemberCouponPickerApi } from '#/api/member'; import { getMemberPointMallProductDetailApi, saveMemberPointMallProductApi, } from '#/api/member/points-mall'; import { mapProductEditorFormToSavePayload, mapProductToEditorForm, resetProductEditorForm, } from './helpers'; interface CouponOption { label: string; value: string; } interface CreateDrawerActionsOptions { canManage: Ref; couponOptions: Ref; drawerMode: Ref<'create' | 'edit'>; form: PointMallProductEditorForm; isDrawerLoading: Ref; isDrawerOpen: Ref; isDrawerSubmitting: Ref; loadProductList: () => Promise; openPicker: (currentProductId?: string) => Promise; selectedStoreId: Ref; } export function createDrawerActions(options: CreateDrawerActionsOptions) { async function loadCouponOptions(keyword?: string) { if (!options.selectedStoreId.value) { options.couponOptions.value = []; return; } try { const rows = await getMemberCouponPickerApi({ storeId: options.selectedStoreId.value, keyword: keyword?.trim() || undefined, }); options.couponOptions.value = rows.map((item) => ({ label: item.displayText || item.name, value: item.couponTemplateId, })); } catch (error) { console.error(error); options.couponOptions.value = []; message.error('加载优惠券失败'); } } async function openCreateDrawer() { if (!options.selectedStoreId.value) { message.warning('请先选择门店'); return; } options.drawerMode.value = 'create'; resetProductEditorForm(options.form); options.isDrawerLoading.value = false; options.isDrawerOpen.value = true; await loadCouponOptions(); } async function openEditDrawer(item: PointMallProductCardViewModel) { if (!options.selectedStoreId.value) { message.warning('请先选择门店'); return; } options.drawerMode.value = 'edit'; options.isDrawerLoading.value = true; options.isDrawerOpen.value = true; try { const detail = await getMemberPointMallProductDetailApi({ storeId: options.selectedStoreId.value, pointMallProductId: item.pointMallProductId, }); const mapped = mapProductToEditorForm(detail); options.form.pointMallProductId = mapped.pointMallProductId; options.form.redeemType = mapped.redeemType; options.form.productId = mapped.productId; options.form.productName = mapped.productName; options.form.couponTemplateId = mapped.couponTemplateId; options.form.couponTemplateName = mapped.couponTemplateName; options.form.physicalName = mapped.physicalName; options.form.pickupMethod = mapped.pickupMethod; options.form.name = mapped.name; options.form.imageUrl = mapped.imageUrl; options.form.exchangeType = mapped.exchangeType; options.form.requiredPoints = mapped.requiredPoints; options.form.cashAmount = mapped.cashAmount; options.form.stockTotal = mapped.stockTotal; options.form.perMemberLimit = mapped.perMemberLimit; options.form.description = mapped.description; options.form.notifyChannels = [...mapped.notifyChannels]; options.form.status = mapped.status; if (detail.redeemType === 'coupon') { await loadCouponOptions(); const selected = options.couponOptions.value.find( (row) => row.value === detail.couponTemplateId, ); options.form.couponTemplateName = selected?.label ?? ''; } } catch (error) { console.error(error); message.error('加载兑换商品详情失败'); options.isDrawerOpen.value = false; } finally { options.isDrawerLoading.value = false; } } function setDrawerOpen(value: boolean) { options.isDrawerOpen.value = value; if (!value) { options.isDrawerLoading.value = false; options.isDrawerSubmitting.value = false; } } function setFormName(value: string) { options.form.name = value; } function setFormImageUrl(value: string) { options.form.imageUrl = value; } function setFormRedeemType(value: PointMallProductEditorForm['redeemType']) { options.form.redeemType = value; if (value !== 'product') { options.form.productId = ''; options.form.productName = ''; } if (value !== 'coupon') { options.form.couponTemplateId = ''; options.form.couponTemplateName = ''; } if (value !== 'physical') { options.form.physicalName = ''; options.form.pickupMethod = 'store_pickup'; } if (value === 'physical') { options.form.notifyChannels = ['in_app', 'sms']; return; } if (!options.form.notifyChannels.includes('in_app')) { options.form.notifyChannels = ['in_app']; } } function setFormProduct(value: { id: string; name: string }) { options.form.productId = value.id; options.form.productName = value.name; } function setFormCouponTemplateId(value: string) { options.form.couponTemplateId = value; const selected = options.couponOptions.value.find( (item) => item.value === value, ); options.form.couponTemplateName = selected?.label ?? ''; } function setFormPhysicalName(value: string) { options.form.physicalName = value; } function setFormPickupMethod( value: PointMallProductEditorForm['pickupMethod'], ) { options.form.pickupMethod = value; } function setFormDescription(value: string) { options.form.description = value; } function setFormExchangeType( value: PointMallProductEditorForm['exchangeType'], ) { options.form.exchangeType = value; if (value === 'points') { options.form.cashAmount = null; } } function setFormRequiredPoints(value: null | number) { options.form.requiredPoints = value; } function setFormCashAmount(value: null | number) { options.form.cashAmount = value; } function setFormStockTotal(value: null | number) { options.form.stockTotal = value; } function setFormPerMemberLimit(value: null | number) { options.form.perMemberLimit = value; } function setFormStatus(value: PointMallProductEditorForm['status']) { options.form.status = value; } function toggleNotifyChannel(value: 'in_app' | 'sms') { if (options.form.notifyChannels.includes(value)) { if (options.form.notifyChannels.length === 1) { return; } options.form.notifyChannels = options.form.notifyChannels.filter( (item) => item !== value, ); return; } options.form.notifyChannels = [...options.form.notifyChannels, value]; } async function openProductPicker() { await options.openPicker(options.form.productId || undefined); } function validateForm() { if (!options.form.name.trim()) { message.warning('请填写展示名称'); return false; } if (!options.form.requiredPoints || options.form.requiredPoints <= 0) { message.warning('所需积分必须大于 0'); return false; } if (options.form.stockTotal === null || options.form.stockTotal < 0) { message.warning('库存数量不能小于 0'); return false; } if (options.form.redeemType === 'product' && !options.form.productId) { message.warning('请选择关联商品'); return false; } if ( options.form.redeemType === 'coupon' && !options.form.couponTemplateId.trim() ) { message.warning('请选择关联优惠券'); return false; } if ( options.form.redeemType === 'physical' && !options.form.physicalName.trim() ) { message.warning('请填写实物名称'); return false; } if ( options.form.exchangeType === 'mixed' && (!options.form.cashAmount || options.form.cashAmount <= 0) ) { message.warning('积分+现金模式下,现金部分必须大于 0'); return false; } if (options.form.notifyChannels.length === 0) { message.warning('请至少选择一种通知方式'); return false; } return true; } async function submitDrawer() { if (!options.canManage.value) { return; } if (!options.selectedStoreId.value) { message.warning('请先选择门店'); return; } if (!validateForm()) { return; } options.isDrawerSubmitting.value = true; try { await saveMemberPointMallProductApi( mapProductEditorFormToSavePayload( options.form, options.selectedStoreId.value, ), ); message.success( options.drawerMode.value === 'create' ? '添加成功' : '保存成功', ); options.isDrawerOpen.value = false; await options.loadProductList(); } catch (error) { console.error(error); message.error('保存失败'); } finally { options.isDrawerSubmitting.value = false; } } return { loadCouponOptions, openCreateDrawer, openEditDrawer, openProductPicker, setDrawerOpen, setFormCashAmount, setFormCouponTemplateId, setFormDescription, setFormExchangeType, setFormImageUrl, setFormName, setFormPerMemberLimit, setFormPhysicalName, setFormPickupMethod, setFormProduct, setFormRedeemType, setFormRequiredPoints, setFormStatus, setFormStockTotal, submitDrawer, toggleNotifyChannel, }; }