From 762483d07d90fd5127e0f5ada3eb5a436715b67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Tue, 7 Apr 2026 09:05:06 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B5=9B=E4=BA=8B=E7=AE=A1=E7=90=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../match/manage/Steps/Step1BasicInfo.vue | 17 ++- .../match/manage/Steps/Step4FeeConfig.vue | 122 ++++++++++++++---- src/views/match/manage/dialog.vue | 28 +++- src/views/match/manage/index.vue | 26 ++-- src/views/user/registration/index.vue | 22 +++- 5 files changed, 161 insertions(+), 54 deletions(-) diff --git a/src/views/match/manage/Steps/Step1BasicInfo.vue b/src/views/match/manage/Steps/Step1BasicInfo.vue index f54d3a8..a1fdabe 100644 --- a/src/views/match/manage/Steps/Step1BasicInfo.vue +++ b/src/views/match/manage/Steps/Step1BasicInfo.vue @@ -124,7 +124,7 @@ const localFormData = ref({ // init from parent watch( () => props.modelValue, - (v) => { + async (v) => { console.log('init from parent', v); if (!v) return; Object.keys(localFormData.value).forEach((k) => { @@ -137,6 +137,21 @@ watch( } }); console.log('after init', localFormData.value); + + // 如果有省份数据,重新加载对应的城市和区县数据 + if(localFormData.value.regionIds[0]) { + try { + const cityRes = await regionCitiesbyprovinceGet({ provincecode: localFormData.value.regionIds[0] }); + cities.value = cityRes?.data ?? []; + if(localFormData.value.regionIds[1]) { + const districtRes = await regionDistrictsbycityGet({ citycode: localFormData.value.regionIds[1] }); + districts.value = districtRes?.data ?? []; + } + } catch { + cities.value = []; + districts.value = []; + } + } }, { deep: true, immediate: true } ); diff --git a/src/views/match/manage/Steps/Step4FeeConfig.vue b/src/views/match/manage/Steps/Step4FeeConfig.vue index 2cb5353..d1b0208 100644 --- a/src/views/match/manage/Steps/Step4FeeConfig.vue +++ b/src/views/match/manage/Steps/Step4FeeConfig.vue @@ -47,7 +47,7 @@
- +
@@ -149,15 +149,67 @@ const localFormData = ref({ creditCode: '', bankName: '', accountNumber: '', + businessLicenseUrl: '', }); +const merchantOptions = ref([]); +const isInitialized = ref(false); + +const syncMerchantInfo = () => { + const id = localFormData.value.merchantId; + + // 如果已经有商户信息(merchantName 不为空),即使没有 merchantId 也正常显示 + if (localFormData.value.merchantName) { + return; + } + + // 如果没有 id,不强制清空,保留已有数据 + if (!id) { + return; + } + + // 尝试从 merchantOptions 中查找商户 + const m = (merchantOptions.value ?? []).find((x) => x?.value == id); + if (m) { + // 只在 localFormData 中的值为空时才从 merchantOptions 中获取 + if (!localFormData.value.merchantName) { + localFormData.value.merchantName = m.merchantName ?? ''; + } + if (!localFormData.value.creditCode) { + localFormData.value.creditCode = m.creditCode ?? ''; + } + if (!localFormData.value.bankName) { + localFormData.value.bankName = m.bankName ?? ''; + } + if (!localFormData.value.accountNumber) { + localFormData.value.accountNumber = m.accountNumber ?? ''; + } + // 只在营业执照 URL 为空时才从 merchantOptions 中获取 + if (!localFormData.value.businessLicenseUrl) { + localFormData.value.businessLicenseUrl = m.businessLicenseUrl ?? ''; + } + } +}; + watch( () => props.modelValue, (v) => { if (!v) return; - Object.keys(localFormData.value).forEach((k) => { - if (v[k] !== undefined) localFormData.value[k] = v[k]; - }); + + // 直接复制所有属性,强制覆盖 + localFormData.value.chargeMode = v.chargeMode ?? 0; + localFormData.value.price = v.price ?? 0; + localFormData.value.merchantId = v.merchantId; + localFormData.value.merchantName = v.merchantName ?? ''; + localFormData.value.creditCode = v.creditCode ?? ''; + localFormData.value.bankName = v.bankName ?? ''; + localFormData.value.accountNumber = v.accountNumber ?? ''; + localFormData.value.businessLicenseUrl = v.businessLicenseUrl ?? ''; + + // 如果已经初始化完成,调用 syncMerchantInfo + if (isInitialized.value) { + syncMerchantInfo(); + } }, { deep: true, immediate: true } ); @@ -167,8 +219,7 @@ watch( (v) => emit('update:modelValue', { ...props.modelValue, ...v }), { deep: true } ); -const businessLicenseUrl = ref(''); -const merchantOptions = ref([]); + onMounted(async () => { try { const res = await merchantPageGet({ PageNo: 1, PageSize: 200 }); @@ -185,27 +236,11 @@ onMounted(async () => { } catch { merchantOptions.value = []; } + + isInitialized.value = true; syncMerchantInfo(); }); -const syncMerchantInfo = () => { - const id = localFormData.value.merchantId; - if (!id) { - localFormData.value.merchantName = ''; - localFormData.value.creditCode = ''; - localFormData.value.bankName = ''; - localFormData.value.accountNumber = ''; - businessLicenseUrl.value = ''; - return; - } - const m = (merchantOptions.value ?? []).find((x) => x?.value == id); - localFormData.value.merchantName = m?.merchantName ?? ''; - localFormData.value.creditCode = m?.creditCode ?? ''; - localFormData.value.bankName = m?.bankName ?? ''; - localFormData.value.accountNumber = m?.accountNumber ?? ''; - businessLicenseUrl.value = m?.businessLicenseUrl ?? ''; -}; - // 商户选择弹窗相关 const merchantDialogVisible = ref(false); const merchantList = ref([]); @@ -256,16 +291,47 @@ const selectMerchant = (row) => { localFormData.value.creditCode = row.creditCode ?? ''; localFormData.value.bankName = row.bankName ?? ''; localFormData.value.accountNumber = row.accountNumber ?? ''; - businessLicenseUrl.value = row.businessLicenseUrl ?? ''; + localFormData.value.businessLicenseUrl = row.businessLicenseUrl ?? ''; merchantDialogVisible.value = false; }; -watch(merchantOptions, syncMerchantInfo, { deep: true }); +watch(merchantOptions, () => { + if (isInitialized.value) { + syncMerchantInfo(); + } +}, { deep: true }); + +const validatePrice = (rule, value, callback) => { + // 当收费模式为定价(赛事)或单价(赛事)时,价格必填 + if (localFormData.value.chargeMode === 1 || localFormData.value.chargeMode === 2) { + if (value === '' || value === null || value === undefined || value <= 0) { + callback(new Error('请输入价格,且价格必须大于0')); + return; + } + } + callback(); +}; + +const validateMerchantId = (rule, value, callback) => { + // 当收费模式为非免费时,收款商户必填 + if (localFormData.value.chargeMode !== 0) { + // 如果有 merchantName,说明数据已经从后端回填了,即使没有 merchantId 也通过 + if (!value && !localFormData.value.merchantName) { + callback(new Error('请选择收款商户')); + return; + } + } + callback(); +}; const rules = { chargeMode: [{ required: true, message: '请选择收费模式', trigger: 'change' }], - price: [{ required: false, message: '请输入价格', trigger: 'change' }], - merchantId: [{ required: true, message: '请选择收款商户', trigger: 'change' }], + price: [ + { validator: validatePrice, trigger: 'change' } + ], + merchantId: [ + { validator: validateMerchantId, trigger: 'change' } + ], bankName: [{ required: false, message: '请输入开户银行', trigger: 'blur' }], accountNumber: [{ required: false, message: '请输入银行账号', trigger: 'blur' }], }; diff --git a/src/views/match/manage/dialog.vue b/src/views/match/manage/dialog.vue index 34785c6..c3bfc77 100644 --- a/src/views/match/manage/dialog.vue +++ b/src/views/match/manage/dialog.vue @@ -12,9 +12,7 @@
- - - +
@@ -160,13 +158,14 @@ const formData = ref({ }, // 步骤4:费用与账户配置 feeConfig: { - chargeMode: 'Free', + chargeMode: 0, // 0=免费,1=定价(赛事),2=单价(赛事),3=单价(项目) price: 0, merchantId: undefined, merchantName: '', creditCode: '', bankName: '', accountNumber: '', + businessLicenseUrl: '', }, }); @@ -191,6 +190,10 @@ const openDialog = async (id) => { console.log('openDialog called with id:', id); dialog.isShowDialog = true; dialog.loading = true; + + // 先重置表单,清除前一个赛事的数据残留 + handleReset(); + if (id) { dialog.title = '编辑赛事'; dialog.submitTxt = '保 存'; @@ -223,14 +226,24 @@ const openDialog = async (id) => { projects: d.projects ?? [], registrationLimit: d.registrationLimit ?? { individualProjectLimit: 1, teamProjectLimit: 1 }, }; - formData.value.feeConfig = { ...formData.value.feeConfig, ...(d.feeConfig ?? {}) }; - console.log('formData.value', formData.value); + // 完全覆盖 feeConfig,不要保留旧数据 + if (d.feeConfig) { + formData.value.feeConfig = { + chargeMode: d.feeConfig.chargeMode ?? 0, + price: d.feeConfig.price ?? 0, + merchantId: d.feeConfig.merchantId, + merchantName: d.feeConfig.merchantName ?? '', + creditCode: d.feeConfig.creditCode ?? '', + bankName: d.feeConfig.bankName ?? '', + accountNumber: d.feeConfig.accountNumber ?? '', + businessLicenseUrl: d.feeConfig.businessLicenseUrl ?? '', + }; + } } } catch (e) { ElMessage.error('加载赛事详情失败'); } } else { - handleReset(); dialog.title = '新增赛事'; dialog.submitTxt = '新 增'; } @@ -360,6 +373,7 @@ const handleReset = () => { creditCode: '', bankName: '', accountNumber: '', + businessLicenseUrl: '', }; // 重置步骤 diff --git a/src/views/match/manage/index.vue b/src/views/match/manage/index.vue index ce74f36..c9f5c25 100644 --- a/src/views/match/manage/index.vue +++ b/src/views/match/manage/index.vue @@ -80,13 +80,13 @@ const refreshTable = () =>{ } const columns = reactive([ { - width: '120px', + width: '80px', prop: 'index', label: '序号', align: 'center', }, { - width: '120px', + width: '200px', prop: 'eventName', label: '赛事名称', align: 'center', @@ -99,10 +99,9 @@ const columns = reactive([ prop: 'coverImage', label: '封面', align: 'center', - width: '120px', }, { - width: '120px', + width: '100px', prop: 'eventType', label: '赛事类型', search: { @@ -115,7 +114,7 @@ const columns = reactive([ ], }, { - width: '120px', + width: '130px', prop: 'registrationType', label: '报名方式', enum: [ @@ -125,7 +124,7 @@ const columns = reactive([ ], }, { - width: '120px', + width: '130px', prop: 'chargeMode', label: '收费模式', search: { @@ -139,10 +138,9 @@ const columns = reactive([ { label: '单价(项目)', value: 3 }, ], }, - - { prop: 'merchantName', label: '收款账户',width: '120px', }, + { prop: 'merchantName', label: '收款账户', width: '150px', }, { - width: '120px', + width: '100px', prop: 'eventStatus', label: '赛事状态', search: { @@ -157,7 +155,7 @@ const columns = reactive([ ], }, { - width: '120px', + width: '160px', prop: 'registrationStartTime', label: '报名开始时间', search: { @@ -168,7 +166,7 @@ const columns = reactive([ }, }, { - width: '120px', + width: '160px', prop: 'registrationEndTime', label: '报名结束时间', search: { @@ -179,7 +177,7 @@ const columns = reactive([ }, }, { - width: '120px', + width: '160px', prop: 'matchStartTime', label: '比赛开始时间', search: { @@ -190,7 +188,7 @@ const columns = reactive([ }, }, { - width: '120px', + width: '160px', prop: 'matchEndTime', label: '比赛结束时间', search: { @@ -200,7 +198,7 @@ const columns = reactive([ }, }, }, - { prop: 'action', label: '操作', align: 'center', width: 160, fixed: 'right', isShow: auths(['event:edit', 'event:delete']) }, + { prop: 'action', label: '操作', align: 'center', width: 200, fixed: 'right', isShow: auths(['event:edit', 'event:delete']) }, ]); const exportableColumns = computed(() => diff --git a/src/views/user/registration/index.vue b/src/views/user/registration/index.vue index ff71a3c..5d72a08 100644 --- a/src/views/user/registration/index.vue +++ b/src/views/user/registration/index.vue @@ -420,7 +420,7 @@