471 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="system-menu-container layout-padding">
<ProTable
ref="tableRef"
:request-api="merchantcertificationPageGet"
@selection-change="handleSelectionChange"
:columns="columns"
:pagination="true"
:tool-button="false"
:initParams="initParam"
row-key="id"
>
<template #tools>
<el-button v-auth="'user:general:audit'" size="small" type="primary" @click="showAuditDialog"> 批量审核 </el-button>
</template>
<template #index="scope">
{{ scope.$index + 1 }}
</template>
<template #auditStatus="scope">
<el-tag :type="getAuditStatusType(scope.row.auditStatus)">
{{ getAuditStatusText(scope.row.auditStatus) }}
</el-tag>
</template>
<template #businessLicenseUrl="scope">
<PreviewImage v-if="scope.row.businessLicenseUrl" :src="scope.row.businessLicenseUrl" width="100px" height="100px" fit="cover" radius="4px" :show-zoom-icon="true" />
<span v-else>-</span>
</template>
<template #action="scope">
<el-button v-auth="'user:general:record'" size="small" text type="primary" @click="onOpenMenu(scope.row)"> 参赛记录 </el-button>
</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>
<!-- 展开列 -->
<el-table-column type="expand">
<template #default="scope">
<div class="expand-content">
<el-table :data="scope.row.items || []" border style="width: 100%; margin-top: 10px;">
<el-table-column label="项目名称" prop="projectName" min-width="150" />
<el-table-column label="角色" prop="role" width="120" />
<el-table-column label="参赛组别" prop="groupName" width="120" />
<el-table-column label="姓名" prop="participantName" 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
v-if="item.row.certificateUrl"
size="small"
text
type="primary"
@click="viewCertificates(item.row)"
>
查看证书
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<template #index="scope">
{{ scope.$index + 1 }}
</template>
<template #eventType="scope">
<el-tag :type="scope.row.eventType === 'Online' ? 'primary' : 'success'">
{{ scope.row.eventType === 'Online' ? '线上' : '线下' }}
</el-tag>
</template>
<template #startTime="scope"> {{ scope.row.startTime }} -- {{ scope.row.endTime }} </template>
</ProTable>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onCancel">确定</el-button>
</span>
</template>
</el-dialog>
<!-- 团队项目证书列表弹窗 -->
<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>
<template #footer>
<span class="dialog-footer">
<el-button @click="isShowTeamCertificateList = false">关闭</el-button>
</span>
</template>
</el-dialog>
<!-- 审核弹窗 -->
<el-dialog title="批量审核" v-model="isShowAuditDialog" width="500px">
<el-form :model="auditForm" label-width="100px">
<el-form-item label="审核状态">
<el-radio-group v-model="auditForm.status">
<el-radio :value="2">审核通过</el-radio>
<el-radio :value="3">审核拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="审核备注">
<el-input v-model="auditForm.remark" type="textarea" :rows="3" placeholder="请输入审核备注"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="isShowAuditDialog = false">取消</el-button>
<el-button type="primary" @click="onSubmitAudit">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="unit">
import { defineAsyncComponent, ref, reactive } from 'vue';
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 { merchantcertificationPageGet, merchantcertificationAuditPost } from '/@/api/match/merchantcertification';
import PreviewImage from '/@/components/PreviewImage/index.vue';
const initParam = ref({
refresh: true,
});
const selectedListIds = ref([]);
const initParamUser = ref({
sysUserId: null,
});
const statusList = ['info', 'warning', 'success', 'danger'];
const getAuditStatusText = (status) => {
switch (status) {
case 0:
return '待提交';
case 1:
return '待审核';
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';
}
};
const columns = ref([
{ prop: 'ss', type: 'selection' },
{ prop: 'index', label: '序号', align: 'center' },
{ prop: 'merchantName', label: '单位名称', search: { el: 'input' } },
{ prop: 'address', label: '地址' },
{ prop: 'contactPhone', label: '联系电话', search: { el: 'input' } },
{ prop: 'businessLicenseUrl', label: '营业执照', width: '130px' },
{
prop: 'auditStatus',
label: '审核状态',
search: {
el: 'select',
},
enum: [
{ label: '全部', value: '' },
{ label: '审核拒绝', value: 3 },
{ label: '审核通过', value: 2 },
{ label: '待审核', value: 1 },
{ label: '待提交', value: 0 },
{ label: '已取消', value: 4 },
],
},
{
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();
const handleSelectionChange = (val) => {
console.log(val);
selectedListIds.value = val.map((item) => item.id);
};
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: '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.userId) {
ElMessage.warning('用户信息无效,无法查看参赛记录');
return;
}
if (typeof row.userId !== 'number' || row.userId <= 0) {
ElMessage.warning('用户ID无效,请刷新页面后重试');
return;
}
// 设置用户ID参数 - 单位用户使用 sysUserId
initParamUser.value.sysUserId = row.userId;
isShowDialog.value = true;
// 下次打开对话框时强制刷新数据
initParamUser.value.refresh = Date.now();
};
// 查看证书
const viewCertificates = (item) => {
if (item.certificateUrl) {
openCertificate(item.certificateUrl);
} else {
ElMessage.warning('暂无证书');
}
};
// 加载团队证书列表
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);
}
}
}
};
// 打开证书图片
const openCertificate = (url) => {
if (url) {
window.open(url, '_blank');
} else {
ElMessage.warning('证书链接无效');
}
};
// 关闭团队证书列表弹窗
const onTeamCertificateListClose = () => {
certificateList.value = [];
};
// 审核弹窗相关
const isShowAuditDialog = ref(false);
const auditForm = reactive({
status: 2, // 默认审核通过
remark: '',
});
const showAuditDialog = () => {
if (selectedListIds.value.length === 0) {
ElMessage.warning('请先选择要审核的记录');
return;
}
auditForm.status = 2;
auditForm.remark = '';
isShowAuditDialog.value = true;
};
const onSubmitAudit = async () => {
console.log(selectedListIds.value);
const { succeeded, data } = await merchantcertificationAuditPost({
ids: selectedListIds.value,
status: auditForm.status,
remark: auditForm.remark,
});
if (succeeded) {
ElMessage.success('操作成功');
isShowAuditDialog.value = false;
tableRef.value.clearSelection();
tableRef.value.getTableList();
} else {
ElMessage.error(data);
}
};
// 对话框关闭时清理
const onDialogClose = () => {
// 清理参数,避免下次查询时使用旧参数
initParamUser.value = {
sysUserId: null,
refresh: Date.now(),
};
};
// 取消
const onCancel = () => {
isShowDialog.value = false;
};
</script>
<style scoped lang="scss">
.dialog-footer {
margin-top: 80px;
}
.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>