From 0e9d03e71edb9814e901530923f0efa3e0f246d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Thu, 7 May 2026 08:32:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=82=E8=B5=9B=E8=AE=B0=E5=BD=95=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E8=AF=81=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/marchant/order/index.vue | 33 ++- src/views/match/order/index.vue | 39 ++- src/views/match/user/general/index.vue | 339 +++++++++++++++---------- src/views/match/user/unit/index.vue | 244 +++++++++++++----- vite.config.ts | 4 +- 5 files changed, 450 insertions(+), 209 deletions(-) diff --git a/src/views/marchant/order/index.vue b/src/views/marchant/order/index.vue index 5625233..6e93664 100644 --- a/src/views/marchant/order/index.vue +++ b/src/views/marchant/order/index.vue @@ -43,7 +43,7 @@ - + @@ -131,17 +131,38 @@ const normalizeNames = (value) => { return ''; }; +const shouldShowFee = computed(() => { + return formData.value?.chargeMode === 3; +}); + const detailTableData = computed(() => { const items = formData.value?.items ?? []; const persons = formData.value?.persons ?? []; return items.map((item) => { - const personNamesByItem = persons - .filter((p) => p?.itemId === item?.id || p?.projectId === item?.projectId) + let personNamesByItem = persons + .filter((p) => String(p?.registrationItemId) === String(item?.id)) .map((p) => p?.name) .filter(Boolean); - const participantNames = normalizeNames( - item?.participantNames ?? item?.personNames ?? item?.memberNames ?? personNamesByItem - ) || '-'; + + if (personNamesByItem.length === 0) { + personNamesByItem = persons + .filter((p) => String(p?.projectId) === String(item?.projectId)) + .map((p) => p?.name) + .filter(Boolean); + } + + if (personNamesByItem.length === 0) { + personNamesByItem = [...new Set( + persons + .filter((p) => p?.groupName === item?.groupName) + .map((p) => p?.name) + .filter(Boolean) + )]; + } + + const participantNames = personNamesByItem.length > 0 + ? personNamesByItem.join('、') + : '-'; const fee = item?.fee ?? item?.subtotal ?? ((Number(item?.unitPrice) || 0) * (Number(item?.personCount) || 0)); return { projectName: item?.projectName ?? '-', diff --git a/src/views/match/order/index.vue b/src/views/match/order/index.vue index 89a85f8..40bb50c 100644 --- a/src/views/match/order/index.vue +++ b/src/views/match/order/index.vue @@ -61,7 +61,7 @@ - + @@ -156,17 +156,44 @@ const normalizeNames = (value) => { return ''; }; +// ChargeMode 枚举值:0=免费,1=定价(赛事),2=单价(赛事),3=单价(项目) +// 只有单价(项目)时才显示费用列 +const shouldShowFee = computed(() => { + return formData.value?.chargeMode === 3; +}); + const detailTableData = computed(() => { const items = formData.value?.items ?? []; const persons = formData.value?.persons ?? []; + return items.map((item) => { - const personNamesByItem = persons - .filter((p) => p?.itemId === item?.id || p?.projectId === item?.projectId) + // 方案1: 使用 registrationItemId 进行精确匹配(强一致) + let personNamesByItem = persons + .filter((p) => String(p?.registrationItemId) === String(item?.id)) .map((p) => p?.name) .filter(Boolean); - const participantNames = normalizeNames( - item?.participantNames ?? item?.personNames ?? item?.memberNames ?? personNamesByItem - ) || '-'; + + // 方案2: 使用项目ID匹配 + if (personNamesByItem.length === 0) { + personNamesByItem = persons + .filter((p) => String(p?.projectId) === String(item?.projectId)) + .map((p) => p?.name) + .filter(Boolean); + } + + // 方案3: 最后保底,用项目名和组名去重匹配 + if (personNamesByItem.length === 0) { + personNamesByItem = [...new Set( + persons + .filter((p) => p?.groupName === item?.groupName) + .map((p) => p?.name) + .filter(Boolean) + )]; + } + + const participantNames = personNamesByItem.length > 0 + ? personNamesByItem.join('、') + : '-'; const fee = item?.fee ?? item?.subtotal ?? ((Number(item?.unitPrice) || 0) * (Number(item?.personCount) || 0)); return { projectName: item?.projectName ?? '-', diff --git a/src/views/match/user/general/index.vue b/src/views/match/user/general/index.vue index 50735e7..b8501b7 100644 --- a/src/views/match/user/general/index.vue +++ b/src/views/match/user/general/index.vue @@ -25,7 +25,7 @@ - + @@ -36,12 +36,20 @@ - + @@ -57,9 +65,7 @@ - + - - -
- - - - - - - - + + +
+
+
{{ certGroup.certificateType }}
+
{{ certGroup.names }}
+ 查看证书 +
-
暂无证书
@@ -97,11 +96,11 @@ + diff --git a/src/views/match/user/unit/index.vue b/src/views/match/user/unit/index.vue index 8d3b249..2360db5 100644 --- a/src/views/match/user/unit/index.vue +++ b/src/views/match/user/unit/index.vue @@ -30,7 +30,7 @@ - + @@ -41,12 +41,20 @@ - + @@ -62,9 +70,7 @@ - + - - -
- - - - - - - - + + +
+
+
{{ certGroup.certificateType }}
+
{{ certGroup.names }}
+ 查看证书 +
-
暂无证书
@@ -126,6 +125,7 @@ import { ElMessage, ElForm } from 'element-plus'; import { auths } from '/@/utils/authFunction'; import ProTable from '/@/components/ProTable/index.vue'; import { eventrecordPageGet, eventrecordCertificatesGet } from '/@/api/match/eventRecord'; +import { eventscoreGetCertificateDetailGet } from '/@/api/match/eventscore'; import { merchantcertificationPageGet, merchantcertificationAuditPost } from '/@/api/match/merchantcertification'; import PreviewImage from '/@/components/PreviewImage/index.vue'; @@ -236,6 +236,8 @@ const columnsUser = ref([ const isShowDialog = ref(false); const table = ref(); const certificates = ref([]); +const isShowTeamCertificateList = ref(false); +const certificateList = ref([]); const onOpenMenu = (row) => { console.log(row); @@ -259,25 +261,142 @@ const onOpenMenu = (row) => { initParamUser.value.refresh = Date.now(); }; -const onCancelB = () => { - isShowBook.value = false; -}; - -// 查看证书 -const isShowBook = ref(false); -const lookBook = async (row, item) => { - console.log('查看证书', row, item); - const registrationIds = row.registrationIds || []; - if (registrationIds.length === 0) { - ElMessage.warning('暂无报名记录'); +// 查看证书 - 根据项目类型处理 +const viewCertificates = async (item) => { + console.log('查看证书', item); + const members = item.members || []; + if (members.length === 0) { + ElMessage.warning('暂无证书'); return; } - const { succeeded, data } = await eventrecordCertificatesGet(registrationIds); - if (succeeded) { - certificates.value = data || []; - isShowBook.value = true; + + if (item.isIndividualProject) { + // 个人项目:直接打开证书详情 + const memberId = members[0].id; + try { + const { succeeded, data, errors } = await eventscoreGetCertificateDetailGet(memberId); + if (succeeded && data) { + const imageUrl = data.certificateUrl || data.url || data.Url; + if (imageUrl) { + openCertificate(imageUrl); + } else { + ElMessage.warning('暂无证书'); + } + } else { + ElMessage.warning('暂无证书'); + } + } catch (error) { + console.error('获取证书失败', error); + ElMessage.warning('暂无证书'); + } } else { - ElMessage.error(data); + // 团队项目:弹出证书列表弹窗 + await loadTeamCertificates(members); + } +}; + +// 加载团队证书列表 +const loadTeamCertificates = async (members) => { + const certData = { + athlete: { names: [], memberIds: [], hasCertificate: false, imageUrls: [] }, + coach: { names: [], memberIds: [], hasCertificate: false, imageUrls: [] }, + leader: { names: [], memberIds: [], hasCertificate: false, imageUrls: [] } + }; + + for (const member of members) { + try { + const { succeeded, data } = await eventscoreGetCertificateDetailGet(member.id); + if (succeeded && data) { + const imageUrl = data.certificateUrl || data.url || data.Url; + const name = member.name || data.name || '未知'; + + // 根据后端返回的 personType 判断类型,而不是证书类型 + let typeKey = 'athlete'; + if (member.personType === 2) { + typeKey = 'coach'; + } else if (member.personType === 3) { + typeKey = 'leader'; + } + + if (imageUrl) { + certData[typeKey].hasCertificate = true; + certData[typeKey].imageUrls.push(imageUrl); + } + certData[typeKey].names.push(name); + certData[typeKey].memberIds.push(member.id); + } else { + // 即使没有证书,也要添加姓名到列表 + const name = member.name || '未知'; + let typeKey = 'athlete'; + if (member.personType === 2) { + typeKey = 'coach'; + } else if (member.personType === 3) { + typeKey = 'leader'; + } + certData[typeKey].names.push(name); + certData[typeKey].memberIds.push(member.id); + } + } catch (error) { + console.error('获取证书失败', error); + // 即使获取证书失败,也添加姓名到列表中 + const name = member.name || '未知'; + let typeKey = 'athlete'; + if (member.personType === 2) { + typeKey = 'coach'; + } else if (member.personType === 3) { + typeKey = 'leader'; + } + certData[typeKey].names.push(name); + certData[typeKey].memberIds.push(member.id); + } + } + + // 构建显示列表 + certificateList.value = []; + if (certData.athlete.names.length > 0) { + certificateList.value.push({ + certificateType: '运动员证书', + names: certData.athlete.names.join('、'), + hasCertificate: certData.athlete.hasCertificate, + imageUrls: certData.athlete.imageUrls, + memberIds: certData.athlete.memberIds + }); + } + if (certData.coach.names.length > 0) { + certificateList.value.push({ + certificateType: '教练证书', + names: certData.coach.names.join('、'), + hasCertificate: certData.coach.hasCertificate, + imageUrls: certData.coach.imageUrls, + memberIds: certData.coach.memberIds + }); + } + if (certData.leader.names.length > 0) { + certificateList.value.push({ + certificateType: '领队证书', + names: certData.leader.names.join('、'), + hasCertificate: certData.leader.hasCertificate, + imageUrls: certData.leader.imageUrls, + memberIds: certData.leader.memberIds + }); + } + + if (certificateList.value.length === 0) { + ElMessage.warning('暂无证书'); + } else { + isShowTeamCertificateList.value = true; + } +}; + +// 打开证书组 +const openCertificateGroup = (certGroup) => { + if (certGroup.imageUrls && certGroup.imageUrls.length > 0) { + // 打开第一个证书,或者如果有多个,可以考虑弹窗选择 + for (const url of certGroup.imageUrls) { + if (url) { + openCertificate(url); + } + } } }; @@ -290,6 +409,11 @@ const openCertificate = (url) => { } }; +// 关闭团队证书列表弹窗 +const onTeamCertificateListClose = () => { + certificateList.value = []; +}; + // 审核弹窗相关 const isShowAuditDialog = ref(false); const auditForm = reactive({ @@ -338,29 +462,35 @@ const onCancel = () => { isShowDialog.value = false; }; + diff --git a/vite.config.ts b/vite.config.ts index e3b664a..b9a165f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -30,8 +30,8 @@ const viteConfig = defineConfig((mode: ConfigEnv) => { hmr: true, proxy: { '/api': { - // target: 'http://localhost:9996', - target: 'http://8.153.108.90:9996', + target: 'http://localhost:9996', + // target: 'http://8.153.108.90:9996', ws: true, changeOrigin: true, secure: false, //解决target使用https出错问题