参赛记录查看证书
This commit is contained in:
parent
e284d2153c
commit
0e9d03e71e
@ -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 ?? '-',
|
||||
|
||||
@ -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 ?? '-',
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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出错问题
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user