update:查看证书

This commit is contained in:
ltx 2026-05-08 17:49:19 +08:00
parent 52bc6297d4
commit dab13a989f
2 changed files with 125 additions and 60 deletions

2
.env
View File

@ -8,4 +8,4 @@ VITE_OPEN = true
VITE_OPEN_CDN = false
# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
VITE_PUBLIC_PATH = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/event_web/202604211000/'
VITE_PUBLIC_PATH = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/event_web/202605081710/'

View File

@ -61,8 +61,8 @@
<el-button type="primary" size="small" text @click="openVoucherDialog(scope.row)">上传凭证</el-button>
<el-button size="small" text type="primary" @click="onOpenMenu(scope.row)">
查看详情
<el-button size="small" text type="primary" @click="openCertificateDialogByRow(scope.row)">
查看证书
</el-button>
<el-button size="small" text type="primary" @click="openViewChangeMembersDialog(scope.row)">
@ -210,64 +210,38 @@
</el-dialog>
<!-- 证书查看 -->
<el-dialog title="查看证书" v-model="isShowCertDialog" width="60%" :close-on-click-modal="false">
<el-skeleton :rows="10" animated v-if="certLoading" />
<el-dialog title="查看证书" v-model="isShowCertDialog" width="70%" :close-on-click-modal="false">
<el-skeleton :rows="8" animated v-if="certLoading" />
<div v-else>
<!-- 证书列表 -->
<div class="certificate-list-container" style="max-height: 50vh; overflow-y: auto;">
<div v-if="certificateDisplayList.length === 0" style="text-align: center; padding: 40px;">
<el-empty description="暂无证书" />
</div>
<div v-else>
<!-- 按项目分组展示 -->
<div class="project-section" v-for="(projectData, projectIndex) in certificateDisplayList" :key="projectIndex">
<div class="project-title">
{{ projectData.projectName }} - {{ projectData.groupName }} - {{ projectData.projectTypeName }}
</div>
<!-- 个人项目运动员证书 -->
<div v-if="projectData.athleteCertificateGroups.length > 0" class="certificate-type-section">
<div class="section-title">运动员证书</div>
<div
v-for="group in projectData.athleteCertificateGroups"
:key="`${projectData.registrationItemId}_${group.participantName}`"
class="certificate-member-row"
>
<div class="names-list">{{ group.participantName }}</div>
<el-button size="small" text type="primary" @click="openCertificates(group.certificates)">查看证书</el-button>
</div>
</div>
<!-- 项目证书 -->
<div v-if="projectData.projectCertificates.length > 0" class="certificate-type-section">
<div class="section-title">项目证书</div>
<div class="names-list">{{ projectData.projectCertificates.map(c => c.participantName).join('、') }}</div>
<el-button size="small" text type="primary" @click="openCertificates(projectData.projectCertificates)">查看证书</el-button>
</div>
<!-- 运动员证书 -->
<div v-if="projectData.athleteCertificateGroups.length === 0 && projectData.athleteCertificates.length > 0" class="certificate-type-section">
<div class="section-title">运动员证书</div>
<div class="names-list">{{ projectData.athleteCertificates.map(c => c.participantName).join('、') }}</div>
<el-button size="small" text type="primary" @click="openCertificates(projectData.athleteCertificates)">查看证书</el-button>
</div>
<!-- 教练证书 -->
<div v-if="projectData.coachCertificates.length > 0" class="certificate-type-section">
<div class="section-title">教练证书</div>
<div class="names-list">{{ projectData.coachCertificates.map(c => c.participantName).join('、') }}</div>
<el-button size="small" text type="primary" @click="openCertificates(projectData.coachCertificates)">查看证书</el-button>
</div>
<!-- 领队证书 -->
<div v-if="projectData.leaderCertificates.length > 0" class="certificate-type-section">
<div class="section-title">领队证书</div>
<div class="names-list">{{ projectData.leaderCertificates.map(c => c.participantName).join('、') }}</div>
<el-button size="small" text type="primary" @click="openCertificates(projectData.leaderCertificates)">查看证书</el-button>
</div>
</div>
</div>
</div>
<el-empty v-if="flatCertList.length === 0" description="暂无证书" />
<el-table v-else :data="flatCertList" border size="small" style="width: 100%;">
<el-table-column prop="project" label="项目" min-width="200" show-overflow-tooltip />
<el-table-column prop="participantName" label="持有人" min-width="100" align="center" />
<el-table-column prop="certType" label="证书类型" width="110" align="center">
<template #default="scope">
<el-tag size="small" :type="scope.row.certType === '教练证书' ? 'warning' : scope.row.certType === '领队证书' ? 'danger' : scope.row.certType === '团队证书' ? 'success' : 'primary'">
{{ scope.row.certType }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="score" label="成绩" width="120" align="center">
<template #default="scope">
<span>{{ scope.row.score ?? '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="rank" label="名次" width="80" align="center">
<template #default="scope">
<span>{{ scope.row.rank != null ? scope.row.rank + '名' : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template #default="scope">
<el-button size="small" text type="primary" :disabled="!scope.row.certificateUrl" @click="openSingleCertificate(scope.row.certificateUrl)">
查看
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<template #footer>
@ -1389,6 +1363,11 @@ const buildAthleteCertificateGroups = (item, certificates) => {
return groups;
};
const openCertificateDialogByRow = (row) => {
currentRow.value = row;
openCertificateDialog();
};
const openCertificateDialog = async () => {
if (!currentRow.value?.registrationId) return;
isShowCertDialog.value = true;
@ -1527,6 +1506,92 @@ const openCertificates = (certificates) => {
}
};
// 单个证书查看
const openSingleCertificate = (url) => {
if (!url) {
ElMessage.warning('暂无证书链接');
return;
}
let cleanUrl = url.trim().replace(/^[`\s]+|[`\s]+$/g, '');
if (cleanUrl) {
window.open(cleanUrl, '_blank');
}
};
// 将证书列表展平为表格行
const flatCertList = computed(() => {
const rows = [];
for (const project of certificateDisplayList.value) {
const projectLabel = [project.projectName, project.groupName, project.projectTypeName].filter(Boolean).join(' / ');
// 根据项目类型判断是个人还是团队证书
const isIndividual = !project.projectTypeName || project.projectTypeName.includes('个人');
const athleteCertType = isIndividual ? '个人证书' : '团队证书';
// 个人分组运动员证书(始终为个人证书)
for (const group of project.athleteCertificateGroups) {
for (const cert of group.certificates) {
rows.push({
project: projectLabel,
certType: '个人证书',
participantName: group.participantName,
score: cert.score ?? null,
rank: cert.rank ?? null,
certificateUrl: cert.certificateUrl,
certificateId: cert.certificateId,
});
}
}
// 运动员证书(根据项目类型决定个人/团队)
for (const cert of project.athleteCertificates) {
rows.push({
project: projectLabel,
certType: athleteCertType,
participantName: cert.participantName,
score: cert.score ?? null,
rank: cert.rank ?? null,
certificateUrl: cert.certificateUrl,
certificateId: cert.certificateId,
});
}
// 项目证书(团队)
for (const cert of project.projectCertificates) {
rows.push({
project: projectLabel,
certType: '团队证书',
participantName: cert.participantName,
score: cert.score ?? null,
rank: cert.rank ?? null,
certificateUrl: cert.certificateUrl,
certificateId: cert.certificateId,
});
}
// 教练证书
for (const cert of project.coachCertificates) {
rows.push({
project: projectLabel,
certType: '教练证书',
participantName: cert.participantName,
score: cert.score ?? null,
rank: cert.rank ?? null,
certificateUrl: cert.certificateUrl,
certificateId: cert.certificateId,
});
}
// 领队证书
for (const cert of project.leaderCertificates) {
rows.push({
project: projectLabel,
certType: '领队证书',
participantName: cert.participantName,
score: cert.score ?? null,
rank: cert.rank ?? null,
certificateUrl: cert.certificateUrl,
certificateId: cert.certificateId,
});
}
}
return rows;
});
// 取消报名
const isShowCancelDialog = ref(false);
const cancelLoading = ref(false);