From 4615ee99f3a4e28b71d03ff705b8a6b5311a2686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Fri, 15 May 2026 13:45:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=A5=E5=90=8D=E7=AE=A1=E7=90=86=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/match/eventregistration.js | 15 +++ src/views/match/manage/work.vue | 177 ++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 1 deletion(-) diff --git a/src/api/match/eventregistration.js b/src/api/match/eventregistration.js index d0fa4f7..1364f4f 100644 --- a/src/api/match/eventregistration.js +++ b/src/api/match/eventregistration.js @@ -108,4 +108,19 @@ export const eventregistrationDeleteDelete = (data) => { */ export const eventregistrationSetstatusPatch = (data) => { return http.patch('/eventregistration/setstatus', data); +}; + +/** + * 获取报名统计数据 + * @param {number} eventId - 赛事ID + * @returns {Promise<{ + * totalParticipants: number, + * individualParticipants: number, + * teamCount: number, + * teamParticipants: number, + * pendingReview: number + * }>} + */ +export const eventregistrationStatsGet = (eventId) => { + return http.get(`/eventregistration/stats/${eventId}`); }; \ No newline at end of file diff --git a/src/views/match/manage/work.vue b/src/views/match/manage/work.vue index 926a700..1ad0f09 100644 --- a/src/views/match/manage/work.vue +++ b/src/views/match/manage/work.vue @@ -13,6 +13,36 @@
+ +
+
+
+
+
报名总人数
+
{{ animatedCounts.totalParticipants }}人
+
+
+
+
个人项目
+
{{ animatedCounts.individualParticipants }}人
+
+
+
+
团队项目
+
+ {{ animatedCounts.teamCount }}队 + / + {{ animatedCounts.teamParticipants }}人 +
+
+
+
+
待审核
+
{{ animatedCounts.pendingReview }}
+
+
+
+
@@ -290,7 +320,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'; import { Check, View, Download, Rank, Warning } from '@element-plus/icons-vue'; import { eventDetailGet } from '/@/api/match/event'; import { eventarrangementListGet, eventarrangementPut, eventarrangementExportPost, eventarrangementPreviewPost } from '/@/api/match/eventarrangement'; -import { eventregistrationPagePost, eventregistrationBatchauditPost, eventregistrationMaterialurlsPost } from '/@/api/match/eventregistration'; +import { eventregistrationPagePost, eventregistrationBatchauditPost, eventregistrationMaterialurlsPost, eventregistrationStatsGet } from '/@/api/match/eventregistration'; import { eventscorePageathletePost, eventscorePagecoachleaderPost, eventscoreImportscorePost, eventscoreDownloadtemplateGet, eventscoreExportcertificatePost, eventscoreIssuecertificatePost, eventscoreGetCertificateDetailGet, eventscoreIssuepointsPost } from '/@/api/match/eventscore'; import { certificateListGet } from '/@/api/match/certificate'; import Step1BasicInfo from './Steps/Step1BasicInfo.vue'; @@ -326,6 +356,24 @@ const selectedCertificateId = ref(); const issuingCertificate = ref(false); const certificateForm = ref({}); const certificateList = ref([]); + +// 报名统计相关 +const registrationStats = ref({ + totalParticipants: 0, + individualParticipants: 0, + teamCount: 0, + teamParticipants: 0, + pendingReview: 0 +}); +const statsLoading = ref(false); +const animatedCounts = ref({ + totalParticipants: 0, + individualParticipants: 0, + teamCount: 0, + teamParticipants: 0, + pendingReview: 0 +}); + // 表单数据(响应式对象) const formData = ref({ // 步骤1:基本信息 @@ -441,6 +489,9 @@ const openDialog = async (id) => { // 等待对话框渲染完成后刷新表格数据 await nextTick() refreshScoreTable() + + // 获取报名统计数据 + await fetchRegistrationStats(); }; const initSortable = () => { @@ -619,11 +670,58 @@ const columns = reactive([ { prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }, ]); +// 获取报名统计数据 +const fetchRegistrationStats = async () => { + if (!initParam.value.eventId) return; + + statsLoading.value = true; + try { + const res = await eventregistrationStatsGet(initParam.value.eventId); + if (res?.succeeded && res?.data) { + registrationStats.value = res.data; + // 启动数字动画 + animateNumbers(res.data); + } + } catch (error) { + console.error('获取统计数据失败:', error); + } finally { + statsLoading.value = false; + } +}; + +// 数字动画函数 +const animateNumbers = (targetStats) => { + const duration = 1500; // 动画持续时间(毫秒) + const startTime = Date.now(); + + const animate = () => { + const elapsed = Date.now() - startTime; + const progress = Math.min(elapsed / duration, 1); + + // 使用 easeOutQuart 缓动函数 + const easeProgress = 1 - Math.pow(1 - progress, 4); + + animatedCounts.value.totalParticipants = Math.floor(targetStats.totalParticipants * easeProgress); + animatedCounts.value.individualParticipants = Math.floor(targetStats.individualParticipants * easeProgress); + animatedCounts.value.teamCount = Math.floor(targetStats.teamCount * easeProgress); + animatedCounts.value.teamParticipants = Math.floor(targetStats.teamParticipants * easeProgress); + animatedCounts.value.pendingReview = Math.floor(targetStats.pendingReview * easeProgress); + + if (progress < 1) { + requestAnimationFrame(animate); + } + }; + + animate(); +}; + const onSureOrder = async (id) => { const res = await eventregistrationBatchauditPost({ ids: [id], 'paymentStatus': 1 }); if (res.succeeded) { ElMessage.success('操作成功!'); initParam.value.refresh = !initParam.value.refresh; + // 审核完成后刷新统计数据 + await fetchRegistrationStats(); } }; const selectListIds = ref() @@ -800,6 +898,8 @@ const allSure = async () => { if (res.succeeded) { ElMessage.success('操作成功!'); initParam.value.refresh = !initParam.value.refresh; + // 审核完成后刷新统计数据 + await fetchRegistrationStats(); } } @@ -1409,6 +1509,81 @@ defineExpose({