Merge branch 'main' of http://8.153.108.90:3000/YD/YD_Event.Web
This commit is contained in:
commit
778830c147
@ -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}`);
|
||||
};
|
||||
@ -13,6 +13,36 @@
|
||||
<div style="height:100px;"></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="报名管理" name="second">
|
||||
<!-- 统计区块 -->
|
||||
<div class="registration-stats-container">
|
||||
<div class="stats-card" v-loading="statsLoading">
|
||||
<div class="stats-row">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">报名总人数</div>
|
||||
<div class="stat-value">{{ animatedCounts.totalParticipants }}<span class="stat-unit">人</span></div>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">个人项目</div>
|
||||
<div class="stat-value">{{ animatedCounts.individualParticipants }}<span class="stat-unit">人</span></div>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">团队项目</div>
|
||||
<div class="stat-value">
|
||||
<span>{{ animatedCounts.teamCount }}<span class="stat-unit">队</span></span>
|
||||
<span style="margin: 0 8px;">/</span>
|
||||
<span>{{ animatedCounts.teamParticipants }}<span class="stat-unit">人</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">待审核</div>
|
||||
<div class="stat-value" style="color: #e6a23c;">{{ animatedCounts.pendingReview }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ProTable ref="tableRef" :request-api="eventregistrationPagePost" :columns="columns" :pagination="true"
|
||||
:tool-button="false" :initParam="initParam" toolButton preserve-expanded-content
|
||||
@selectionChange="selection">
|
||||
@ -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({
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.registration-stats-container {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
padding: 24px 32px;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
flex: 1;
|
||||
min-width: 180px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.stat-unit {
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.stat-divider {
|
||||
width: 1px;
|
||||
height: 60px;
|
||||
background: #ebeef5;
|
||||
}
|
||||
|
||||
/* 响应式样式 */
|
||||
@media (max-width: 768px) {
|
||||
.stats-card {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
width: 100%;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.stat-divider {
|
||||
width: 60%;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.arrangement-container {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user