参赛记录查看证书

This commit is contained in:
马梓彭 2026-05-07 08:32:55 +08:00
parent e284d2153c
commit 0e9d03e71e
5 changed files with 450 additions and 209 deletions

View File

@ -43,7 +43,7 @@
<el-table-column prop="projectName" label="项目" align="center" />
<el-table-column prop="groupName" label="组别" align="center" />
<el-table-column prop="participantNames" label="参赛队员" align="center" show-overflow-tooltip />
<el-table-column prop="fee" label="费用(元)" align="center" width="120">
<el-table-column v-if="shouldShowFee" prop="fee" label="费用(元)" align="center" width="120">
<template #default="scope">
{{ formatAmount(scope.row.fee) }}
</template>
@ -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 ?? '-',

View File

@ -61,7 +61,7 @@
<el-table-column prop="projectName" label="项目" align="center" />
<el-table-column prop="groupName" label="组别" align="center" />
<el-table-column prop="participantNames" label="参赛队员" align="center" show-overflow-tooltip />
<el-table-column prop="fee" label="费用(元)" align="center" width="120">
<el-table-column v-if="shouldShowFee" prop="fee" label="费用(元)" align="center" width="120">
<template #default="scope">
{{ formatAmount(scope.row.fee) }}
</template>
@ -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 ?? '-',

View File

@ -25,7 +25,7 @@
</template>
</ProTable>
<!-- 弹窗 -->
<!-- 参赛记录弹窗 -->
<el-dialog title="参赛记录" v-model="isShowDialog" width="80%" @close="onDialogClose">
<ProTable v-if="isShowDialog" ref="table" :request-api="eventrecordPageGet" :columns="columnsUser" :pagination="true" :tool-button="false" :initParam="initParamUser" preserve-expanded-content>
<!-- 展开列 -->
@ -36,12 +36,20 @@
<el-table-column label="项目名称" prop="projectName" min-width="150" />
<el-table-column label="项目类型" prop="projectTypeName" width="120" />
<el-table-column label="参赛组别" prop="groupName" width="120" />
<el-table-column label="报名人数" prop="personCount" width="100" align="center" />
<el-table-column label="姓名" prop="memberNames" min-width="200" />
<el-table-column label="成绩" prop="score" width="120" />
<el-table-column label="名次" prop="rank" width="100" />
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="item">
<el-button size="small" text type="primary" @click="lookBook(scope.row, item.row)">查看证书</el-button>
<el-button
v-if="item.row.memberIds && item.row.memberIds.length > 0"
size="small"
text
type="primary"
@click="viewCertificates(item.row)"
>
查看证书
</el-button>
</template>
</el-table-column>
</el-table>
@ -57,9 +65,7 @@
</el-tag>
</template>
<template #startTime="scope"> {{ scope.row.startTime }} -- {{ scope.row.endTime }} </template>
<template #action="scope">
<el-button v-auth="'user:general:record'" size="small" text type="primary" @click="lookBook(scope.row)"> 查看证书 </el-button>
</template>
</ProTable>
<template #footer>
<span class="dialog-footer">
@ -69,25 +75,18 @@
</template>
</el-dialog>
<!-- 弹窗 -->
<el-dialog title="查看证书" v-model="isShowBook" width="80%">
<div v-if="certificates.length > 0">
<el-table :data="certificates" border>
<el-table-column label="证书名称" prop="name" />
<el-table-column label="获奖等级" prop="awardLevel" />
<el-table-column label="证书类型" prop="certificateType" />
<el-table-column label="查看">
<template #default="scope">
<el-button size="small" text type="primary" @click="openCertificate(scope.row.imageUrl)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!-- 团队项目证书列表弹窗 -->
<el-dialog title="团队证书列表" v-model="isShowTeamCertificateList" width="50%" @close="onTeamCertificateListClose">
<div class="certificate-list-container">
<div class="certificate-type-section" v-for="(certGroup, index) in certificateList" :key="index">
<div class="section-title">{{ certGroup.certificateType }}</div>
<div class="names-list">{{ certGroup.names }}</div>
<el-button v-if="certGroup.hasCertificate" size="small" text type="primary" @click="openCertificateGroup(certGroup)">查看证书</el-button>
</div>
</div>
<div v-else>暂无证书</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancelB">取消</el-button>
<el-button type="primary" @click="onCancelB">确定</el-button>
<el-button @click="isShowTeamCertificateList = false">关闭</el-button>
</span>
</template>
</el-dialog>
@ -97,11 +96,11 @@
<script setup name="general">
import { defineAsyncComponent, ref, reactive } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import SysMenuApi from '/@/api/SysMenuApi';
import { auths } from '/@/utils/authFunction';
import ProTable from '/@/components/ProTable/index.vue';
import { appuserPageGet, appuserAuditPost } from '/@/api/match/appuser';
import { eventrecordPageGet, eventrecordCertificatesGet } from '/@/api/match/eventRecord';
import { eventscoreGetCertificateDetailGet } from '/@/api/match/eventscore';
import PreviewImage from '/@/components/PreviewImage/index.vue';
const initParam = ref({
@ -119,31 +118,21 @@ const getAuditStatusText = (status) => {
return '待提交';
case 1:
return '待审核';
case 2:
return '审核通过';
case 3:
return '审核拒绝';
case 4:
return '已取消';
default:
return status;
case 2: return '审核通过';
case 3: return '审核拒绝';
case 4: return '已取消';
default: return status;
}
};
const getAuditStatusType = (status) => {
switch (status) {
case 0:
return 'info';
case 1:
return 'warning';
case 2:
return 'success';
case 3:
return 'danger';
case 4:
return 'info';
default:
return 'info';
case 0: return 'info';
case 1: return 'warning';
case 2: return 'success';
case 3: return 'danger';
case 4: return 'info';
default: return 'info';
}
};
@ -151,43 +140,11 @@ const columns = ref([
{ prop: 'ss', type: 'selection' },
{ prop: 'index', label: '序号', align: 'center' },
{ prop: 'name', label: '姓名', search: { el: 'input' } },
{
prop: 'gender',
label: '性别',
search: {
el: 'select',
},
enum: [
{ label: '全部', value: '' },
{ label: '男', value: 0 },
{ label: '女', value: 1 },
],
},
{ prop: 'gender', label: '性别', search: { el: 'select' }, enum: [{ label: '全部', value: '' }, { label: '男', value: 0 }, { label: '女', value: 1 }] },
{ prop: 'mobile', label: '联系电话', search: { el: 'input' } },
{ prop: 'idCardImageUrl', label: '身份证', width: '130px' },
{
prop: 'auditStatus',
label: '审核状态',
search: {
el: 'select',
},
enum: [
{ label: '全部', value: '' },
{ label: '未提交', value: 0 },
{ label: '未审核', value: 1 },
{ label: '已通过', value: 2 },
{ label: '未通过', value: 3 },
],
},
{
prop: 'createdTime',
label: '生成时间',
search: {
el: 'date-picker',
props: { type: 'daterange' },
},
},
{ prop: 'auditStatus', label: '审核状态', search: { el: 'select' }, enum: [{ label: '全部', value: '' }, { label: '未提交', value: 0 }, { label: '未审核', value: 1 }, { label: '已通过', value: 2 }, { label: '未通过', value: 3 }] },
{ prop: 'createdTime', label: '生成时间', search: { el: 'date-picker', props: { type: 'daterange' } } },
{ prop: 'action', label: '操作', align: 'center', fixed: 'right', isShow: auths(['user:general:record']) },
]);
const tableRef = ref();
@ -196,52 +153,33 @@ const handleSelectionChange = (val) => {
selectedListIds.value = val.map((item) => item.id);
};
const statusNameList = ['未提交', '未审核', '已通过', '未通过'];
const columnsUser = ref([
{ prop: 'index', label: '序号', align: 'center' },
{ prop: 'eventName', label: '赛事名称', search: { el: 'input' } },
{ prop: 'eventType', label: '赛事类型', width: '100' },
{
prop: 'startTime',
label: '起止时间',
search: {
el: 'date-picker',
props: { type: 'daterange' },
},
},
{
prop: 'endTime',
label: '起止时间',
isShow: false,
},
{ prop: 'startTime', label: '起止时间', search: { el: 'date-picker', props: { type: 'daterange' } } },
{ prop: 'endTime', label: '起止时间', isShow: false },
{ prop: 'action', label: '操作', align: 'center', fixed: 'right' },
]);
const isShowDialog = ref(false);
const table = ref();
const certificates = ref([]);
const isShowTeamCertificateList = ref(false);
const certificateList = ref([]);
const onOpenMenu = (row) => {
console.log(row);
// 参数验证
if (!row || !row.id) {
ElMessage.warning('用户信息无效,无法查看参赛记录');
return;
}
if (typeof row.id !== 'number' || row.id <= 0) {
ElMessage.warning('用户ID无效,请刷新页面后重试');
return;
}
// 设置用户ID参数
initParamUser.value.appUserId = row.id;
isShowDialog.value = true;
// 下次打开对话框时强制刷新数据
initParamUser.value.refresh = Date.now();
};
@ -250,7 +188,6 @@ const onBatchAudit = async () => {
const { succeeded, data } = await appuserAuditPost({ ids: selectedListIds.value, status: 2 });
if (succeeded) {
ElMessage.success('操作成功');
// initParam.value.refresh = !initParam.value.refresh;
tableRef.value.clearSelection();
tableRef.value.getTableList();
} else {
@ -258,25 +195,141 @@ const onBatchAudit = async () => {
}
};
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);
}
}
}
};
@ -289,9 +342,13 @@ const openCertificate = (url) => {
}
};
// 关闭团队证书列表弹窗
const onTeamCertificateListClose = () => {
certificateList.value = [];
};
// 对话框关闭时清理
const onDialogClose = () => {
// 清理参数,避免下次查询时使用旧参数
initParamUser.value = {
appUserId: null,
refresh: Date.now(),
@ -303,29 +360,35 @@ const onCancel = () => {
isShowDialog.value = false;
};
</script>
<style scoped lang="scss">
.dialog-footer {
margin-top: 80px;
}
/* 时长组合框样式 */
.duration-row {
display: flex;
align-items: center;
gap: 8px;
}
.duration-row .el-input {
width: 120px;
}
.duration-separator {
color: #606266;
font-size: 14px;
}
.duration-label {
color: #909399;
font-size: 14px;
.certificate-list-container {
max-height: 400px;
overflow-y: auto;
.certificate-type-section {
margin-bottom: 24px;
padding: 16px;
background-color: #f5f7fa;
border-radius: 8px;
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
color: #303133;
}
.names-list {
font-size: 14px;
color: #606266;
margin-bottom: 12px;
line-height: 1.6;
}
}
}
</style>

View File

@ -30,7 +30,7 @@
</template>
</ProTable>
<!-- 弹窗 -->
<!-- 参赛记录弹窗 -->
<el-dialog title="参赛记录" v-model="isShowDialog" width="80%" @close="onDialogClose">
<ProTable v-if="isShowDialog" ref="table" :request-api="eventrecordPageGet" :columns="columnsUser" :pagination="true" :tool-button="false" :initParam="initParamUser" preserve-expanded-content>
<!-- 展开列 -->
@ -41,12 +41,20 @@
<el-table-column label="项目名称" prop="projectName" min-width="150" />
<el-table-column label="项目类型" prop="projectTypeName" width="120" />
<el-table-column label="参赛组别" prop="groupName" width="120" />
<el-table-column label="报名人数" prop="personCount" width="100" align="center" />
<el-table-column label="姓名" prop="memberNames" min-width="200" />
<el-table-column label="成绩" prop="score" width="120" />
<el-table-column label="名次" prop="rank" width="100" />
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="item">
<el-button size="small" text type="primary" @click="lookBook(scope.row, item.row)">查看证书</el-button>
<el-button
v-if="item.row.memberIds && item.row.memberIds.length > 0"
size="small"
text
type="primary"
@click="viewCertificates(item.row)"
>
查看证书
</el-button>
</template>
</el-table-column>
</el-table>
@ -62,9 +70,7 @@
</el-tag>
</template>
<template #startTime="scope"> {{ scope.row.startTime }} -- {{ scope.row.endTime }} </template>
<template #action="scope">
<el-button v-auth="'user:general:record'" size="small" text type="primary" @click="lookBook(scope.row)"> 查看证书 </el-button>
</template>
</ProTable>
<template #footer>
<span class="dialog-footer">
@ -74,25 +80,18 @@
</template>
</el-dialog>
<!-- 弹窗 -->
<el-dialog title="查看证书" v-model="isShowBook" width="80%">
<div v-if="certificates.length > 0">
<el-table :data="certificates" border>
<el-table-column label="证书名称" prop="name" />
<el-table-column label="获奖等级" prop="awardLevel" />
<el-table-column label="证书类型" prop="certificateType" />
<el-table-column label="查看">
<template #default="scope">
<el-button size="small" text type="primary" @click="openCertificate(scope.row.imageUrl)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!-- 团队项目证书列表弹窗 -->
<el-dialog title="团队证书列表" v-model="isShowTeamCertificateList" width="50%" @close="onTeamCertificateListClose">
<div class="certificate-list-container">
<div class="certificate-type-section" v-for="(certGroup, index) in certificateList" :key="index">
<div class="section-title">{{ certGroup.certificateType }}</div>
<div class="names-list">{{ certGroup.names }}</div>
<el-button v-if="certGroup.hasCertificate" size="small" text type="primary" @click="openCertificateGroup(certGroup)">查看证书</el-button>
</div>
</div>
<div v-else>暂无证书</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancelB">取消</el-button>
<el-button type="primary" @click="onCancelB">确定</el-button>
<el-button @click="isShowTeamCertificateList = false">关闭</el-button>
</span>
</template>
</el-dialog>
@ -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;
};
</script>
<style scoped lang="scss">
.dialog-footer {
margin-top: 80px;
}
/* 时长组合框样式 */
.duration-row {
display: flex;
align-items: center;
gap: 8px;
}
.duration-row .el-input {
width: 120px;
}
.duration-separator {
color: #606266;
font-size: 14px;
}
.duration-label {
color: #909399;
font-size: 14px;
.certificate-list-container {
max-height: 400px;
overflow-y: auto;
.certificate-type-section {
margin-bottom: 24px;
padding: 16px;
background-color: #f5f7fa;
border-radius: 8px;
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
color: #303133;
}
.names-list {
font-size: 14px;
color: #606266;
margin-bottom: 12px;
line-height: 1.6;
}
}
}
</style>

View File

@ -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出错问题