赛事证书发放
This commit is contained in:
parent
06cbee57a7
commit
0b8390e64c
@ -89,11 +89,11 @@ export const eventscoreIssuecertificatePost = (data) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看证书
|
* 查看证书
|
||||||
* @param {number} id - 报名人员ID (EventRegistrationPerson的Id) (路径参数)
|
* @param {number} id - 报名人员ID (EventRegistrationPerson的Id)
|
||||||
* @returns {Promise<Object>} 返回证书详情
|
* @returns {Promise<Object>} 返回证书详情
|
||||||
*/
|
*/
|
||||||
export const eventscoreGetCertificateDetailGet = (id) => {
|
export const eventscoreGetCertificateDetailGet = (id) => {
|
||||||
return http.get(`/EventScore/GetCertificateDetail/${id}`);
|
return http.post('/eventscore/getcertificatedetail', { id });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,4 +139,22 @@ export const eventscoreDeleteDelete = (data) => {
|
|||||||
*/
|
*/
|
||||||
export const eventscoreSetstatusPatch = (data) => {
|
export const eventscoreSetstatusPatch = (data) => {
|
||||||
return http.patch('/eventscore/setstatus', data);
|
return http.patch('/eventscore/setstatus', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看证书 URL
|
||||||
|
* @param {Object} params - 查询参数
|
||||||
|
* @param {number} params.id - 报名人员ID
|
||||||
|
*/
|
||||||
|
export const eventscoreViewcertificateGet = (params) => {
|
||||||
|
return http.get('/eventscore/viewcertificate', { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发放积分
|
||||||
|
* @param {Object} data - 发放积分参数
|
||||||
|
* @param {number} data.eventId - 赛事ID
|
||||||
|
*/
|
||||||
|
export const eventscoreIssuepointsPost = (data) => {
|
||||||
|
return http.post('/eventscore/issuePoints', data);
|
||||||
};
|
};
|
||||||
@ -128,35 +128,61 @@
|
|||||||
<el-radio-button value="教练">教练</el-radio-button>
|
<el-radio-button value="教练">教练</el-radio-button>
|
||||||
<el-radio-button value="领队">领队</el-radio-button>
|
<el-radio-button value="领队">领队</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<ProTable v-if="user == '运动员'" ref="tableuu" :request-api="eventscorePageathletePost"
|
|
||||||
:columns="columnsScore" :pagination="true" :tool-button="false" :initParam="initParam" toolButton
|
<div v-if="user == '运动员'" class="score-certificate-container">
|
||||||
preserve-expanded-content @selectionChange="selection">
|
<div class="project-group-panel">
|
||||||
<template #tools>
|
<div class="panel-header">项目-组别列表</div>
|
||||||
<el-button v-auth="'event:add'" type="primary" :loading="importingScore" @click="inScore"> 导入成绩 </el-button>
|
<el-tree
|
||||||
<el-button v-auth="'event:add'" type="primary" @click="downloadTemplate"> 下载模板 </el-button>
|
ref="projectGroupTreeRef"
|
||||||
<el-button v-auth="'event:add'" type="primary" @click="allSure"> 发放证书 </el-button>
|
:data="projectGroupTreeData"
|
||||||
<el-button v-auth="'event:add'" type="primary" @click="exportCertificate"> 导出证书 </el-button>
|
:props="treeProps"
|
||||||
</template>
|
node-key="nodeKey"
|
||||||
<template #index="scope">
|
highlight-current
|
||||||
{{ scope.$index + 1 }}
|
:expand-on-click-node="false"
|
||||||
</template>
|
@node-click="handleTreeNodeClick"
|
||||||
<template #action="scope">
|
default-expand-all
|
||||||
<el-button size="small" text type="primary" @click="onLookBook(scope.row.id)"> 查看证书
|
>
|
||||||
</el-button>
|
<template #default="{ node, data }">
|
||||||
</template>
|
<span class="tree-node-label">
|
||||||
</ProTable>
|
{{ node.label }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="athlete-list-panel">
|
||||||
|
<ProTable ref="tableuu" :request-api="eventscorePageathletePost"
|
||||||
|
:columns="columnsScore" :pagination="true" :tool-button="false" :initParam="scoreQueryParam" toolButton
|
||||||
|
preserve-expanded-content @selectionChange="selection">
|
||||||
|
<template #tools>
|
||||||
|
<el-button v-auth="'event:add'" type="primary" :loading="importingScore" @click="inScore"> 导入成绩 </el-button>
|
||||||
|
<el-button v-auth="'event:add'" type="primary" @click="downloadTemplate"> 下载模板 </el-button>
|
||||||
|
<el-button v-auth="'event:add'" type="primary" @click="openIssueCertificateDialog"> 发放证书 </el-button>
|
||||||
|
<el-button v-auth="'event:add'" type="primary" @click="exportCertificate"> 导出证书 </el-button>
|
||||||
|
<el-button v-auth="'event:add'" type="success" :loading="issuingPoints" @click="handleIssuePoints"> 发放积分 </el-button>
|
||||||
|
</template>
|
||||||
|
<template #index="scope">
|
||||||
|
{{ scope.$index + 1 }}
|
||||||
|
</template>
|
||||||
|
<template #action="scope">
|
||||||
|
<el-button size="small" text type="primary" @click="viewCertificate(scope.row.id)"> 查看证书
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</ProTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ProTable v-if="user == '教练'" ref="tableCoach" :request-api="eventscorePagecoachleaderPost"
|
<ProTable v-if="user == '教练'" ref="tableCoach" :request-api="eventscorePagecoachleaderPost"
|
||||||
:columns="columnsCoach" :pagination="true" :tool-button="false" :initParam="initParamCoach" toolButton
|
:columns="columnsCoach" :pagination="true" :tool-button="false" :initParam="initParamCoach" toolButton
|
||||||
preserve-expanded-content @selectionChange="selection">
|
preserve-expanded-content @selectionChange="selection">
|
||||||
<template #tools>
|
<template #tools>
|
||||||
<el-button v-auth="'event:add'" type="primary" @click="allSure"> 发放证书 </el-button>
|
<el-button v-auth="'event:add'" type="primary" @click="openIssueCertificateDialog"> 发放证书 </el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #index="scope">
|
<template #index="scope">
|
||||||
{{ scope.$index + 1 }}
|
{{ scope.$index + 1 }}
|
||||||
</template>
|
</template>
|
||||||
<template #action="scope">
|
<template #action="scope">
|
||||||
<el-button size="small" text type="primary" @click="onLookBook(scope.row.id)"> 查看证书
|
<el-button size="small" text type="primary" @click="viewCertificate(scope.row.id)"> 查看证书
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</ProTable>
|
</ProTable>
|
||||||
@ -165,16 +191,34 @@
|
|||||||
:columns="columnsLeader" :pagination="true" :tool-button="false" :initParam="initParamLeader" toolButton
|
:columns="columnsLeader" :pagination="true" :tool-button="false" :initParam="initParamLeader" toolButton
|
||||||
preserve-expanded-content @selectionChange="selection">
|
preserve-expanded-content @selectionChange="selection">
|
||||||
<template #tools>
|
<template #tools>
|
||||||
<el-button v-auth="'event:add'" type="primary" @click="allSure"> 发放证书 </el-button>
|
<el-button v-auth="'event:add'" type="primary" @click="openIssueCertificateDialog"> 发放证书 </el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #index="scope">
|
<template #index="scope">
|
||||||
{{ scope.$index + 1 }}
|
{{ scope.$index + 1 }}
|
||||||
</template>
|
</template>
|
||||||
<template #action="scope">
|
<template #action="scope">
|
||||||
<el-button size="small" text type="primary" @click="onLookBook(scope.row.id)"> 查看证书
|
<el-button size="small" text type="primary" @click="viewCertificate(scope.row.id)"> 查看证书
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</ProTable>
|
</ProTable>
|
||||||
|
|
||||||
|
<!-- 发放证书对话框 -->
|
||||||
|
<el-dialog v-model="certificateDialogVisible" title="发放证书" width="500px">
|
||||||
|
<el-form :model="certificateForm" label-width="120px">
|
||||||
|
<el-form-item label="选择证书模板">
|
||||||
|
<el-select v-model="selectedTemplateId" placeholder="请选择证书模板" style="width: 100%;">
|
||||||
|
<el-option label="默认模板" :value="undefined" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="已选人数">
|
||||||
|
<span>{{ selectListIds.value?.length || 0 }} 人</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="certificateDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="issuingCertificate" @click="issueCertificate">确定发放</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
@ -247,7 +291,7 @@ import { Check, View, Download, Rank, Warning } from '@element-plus/icons-vue';
|
|||||||
import { eventDetailGet } from '/@/api/match/event';
|
import { eventDetailGet } from '/@/api/match/event';
|
||||||
import { eventarrangementListGet, eventarrangementPut, eventarrangementExportPost, eventarrangementPreviewPost } from '/@/api/match/eventarrangement';
|
import { eventarrangementListGet, eventarrangementPut, eventarrangementExportPost, eventarrangementPreviewPost } from '/@/api/match/eventarrangement';
|
||||||
import { eventregistrationPagePost, eventregistrationBatchauditPost, eventregistrationMaterialurlsPost } from '/@/api/match/eventregistration';
|
import { eventregistrationPagePost, eventregistrationBatchauditPost, eventregistrationMaterialurlsPost } from '/@/api/match/eventregistration';
|
||||||
import { eventscorePageathletePost, eventscorePagecoachleaderPost,eventscoreImportscorePost, eventscoreDownloadtemplateGet, eventscoreExportcertificatePost } from '/@/api/match/eventscore';
|
import { eventscorePageathletePost, eventscorePagecoachleaderPost,eventscoreImportscorePost, eventscoreDownloadtemplateGet, eventscoreExportcertificatePost, eventscoreIssuecertificatePost, eventscoreGetCertificateDetailGet, eventscoreIssuepointsPost } from '/@/api/match/eventscore';
|
||||||
import Step1BasicInfo from './Steps/Step1BasicInfo.vue';
|
import Step1BasicInfo from './Steps/Step1BasicInfo.vue';
|
||||||
import Step2Units from './Steps/Step2Units.vue';
|
import Step2Units from './Steps/Step2Units.vue';
|
||||||
import Step3ProjectConfig from './Steps/Step3ProjectConfig.vue';
|
import Step3ProjectConfig from './Steps/Step3ProjectConfig.vue';
|
||||||
@ -261,6 +305,7 @@ const isShowDialog = ref(false);
|
|||||||
const activeName = ref('first')
|
const activeName = ref('first')
|
||||||
const eventlist = ref([]);
|
const eventlist = ref([]);
|
||||||
const importingScore = ref(false);
|
const importingScore = ref(false);
|
||||||
|
const issuingPoints = ref(false);
|
||||||
const arrangementContainerRef = ref(null);
|
const arrangementContainerRef = ref(null);
|
||||||
let sortableInstance = null;
|
let sortableInstance = null;
|
||||||
|
|
||||||
@ -272,6 +317,12 @@ const scoreFileInputRef = ref(null);
|
|||||||
const tableuu = ref();
|
const tableuu = ref();
|
||||||
const tableCoach = ref();
|
const tableCoach = ref();
|
||||||
const tableLeader = ref();
|
const tableLeader = ref();
|
||||||
|
|
||||||
|
// 证书发放相关
|
||||||
|
const certificateDialogVisible = ref(false);
|
||||||
|
const selectedTemplateId = ref();
|
||||||
|
const issuingCertificate = ref(false);
|
||||||
|
const certificateForm = ref({});
|
||||||
// 表单数据(响应式对象)
|
// 表单数据(响应式对象)
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
// 步骤1:基本信息
|
// 步骤1:基本信息
|
||||||
@ -353,6 +404,9 @@ const openDialog = async (id) => {
|
|||||||
};
|
};
|
||||||
formData.value.feeConfig = { ...formData.value.feeConfig, ...(d.feeConfig ?? {}) };
|
formData.value.feeConfig = { ...formData.value.feeConfig, ...(d.feeConfig ?? {}) };
|
||||||
console.log('formData.value', formData.value);
|
console.log('formData.value', formData.value);
|
||||||
|
|
||||||
|
projectGroupTreeData.value = buildProjectGroupTree(d.projects)
|
||||||
|
resetSelectedGroup()
|
||||||
}
|
}
|
||||||
|
|
||||||
const res2 = await eventarrangementListGet(id);
|
const res2 = await eventarrangementListGet(id);
|
||||||
@ -541,6 +595,13 @@ const selection = (e) => {
|
|||||||
//预览赛事编排
|
//预览赛事编排
|
||||||
const previewArrangement = async () => {
|
const previewArrangement = async () => {
|
||||||
try {
|
try {
|
||||||
|
// 验证场地数
|
||||||
|
const validation = validateVenueCount();
|
||||||
|
if (!validation.valid) {
|
||||||
|
ElMessage.warning(validation.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const res = await eventarrangementPreviewPost(initParam.value.id);
|
const res = await eventarrangementPreviewPost(initParam.value.id);
|
||||||
if (res.succeeded) {
|
if (res.succeeded) {
|
||||||
previewData.value = res.data || [];
|
previewData.value = res.data || [];
|
||||||
@ -610,6 +671,13 @@ const downloadByBlob = (blob, filename = '赛事编排.xlsx') => {
|
|||||||
|
|
||||||
const getArr = async () => {
|
const getArr = async () => {
|
||||||
try {
|
try {
|
||||||
|
// 验证场地数
|
||||||
|
const validation = validateVenueCount();
|
||||||
|
if (!validation.valid) {
|
||||||
|
ElMessage.warning(validation.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { succeeded, data, errors } = await eventarrangementExportPost(initParam.value.id);
|
const { succeeded, data, errors } = await eventarrangementExportPost(initParam.value.id);
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
ElMessage.error(errors || '导出失败');
|
ElMessage.error(errors || '导出失败');
|
||||||
@ -659,7 +727,8 @@ const columnsScore = ref([
|
|||||||
{ prop: 'index', label: '序号', align: 'center', type: 'selection' },
|
{ prop: 'index', label: '序号', align: 'center', type: 'selection' },
|
||||||
{ prop: 'name', label: '姓名', width: '120px', },
|
{ prop: 'name', label: '姓名', width: '120px', },
|
||||||
{ prop: 'score', label: '成绩', width: '120px', },
|
{ prop: 'score', label: '成绩', width: '120px', },
|
||||||
{ prop: 'rank', label: '名次', },
|
{ prop: 'unitName', label: '单位', width: '180px', },
|
||||||
|
{ prop: 'rankText', label: '名次', width: '120px', },
|
||||||
{
|
{
|
||||||
prop: 'gender',
|
prop: 'gender',
|
||||||
label: '性别',
|
label: '性别',
|
||||||
@ -671,9 +740,67 @@ const columnsScore = ref([
|
|||||||
{ label: '女', value: 1 },
|
{ label: '女', value: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ prop: 'unitName', label: '单位', },
|
|
||||||
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const projectGroupTreeRef = ref()
|
||||||
|
const projectGroupTreeData = ref([])
|
||||||
|
const treeProps = {
|
||||||
|
children: 'children',
|
||||||
|
label: 'label'
|
||||||
|
}
|
||||||
|
const selectedProjectGroup = ref(null)
|
||||||
|
|
||||||
|
const scoreQueryParam = computed(() => ({
|
||||||
|
refresh: initParam.value.refresh,
|
||||||
|
eventId: initParam.value.eventId,
|
||||||
|
projectId: selectedProjectGroup.value?.type === 'project' ? selectedProjectGroup.value?.id : undefined,
|
||||||
|
groupName: selectedProjectGroup.value?.type === 'group' ? selectedProjectGroup.value?.groupName : undefined
|
||||||
|
}))
|
||||||
|
|
||||||
|
const buildProjectGroupTree = (projects) => {
|
||||||
|
const treeData = []
|
||||||
|
if (!projects || !Array.isArray(projects)) return treeData
|
||||||
|
|
||||||
|
projects.forEach(project => {
|
||||||
|
const projectNode = {
|
||||||
|
nodeKey: `project-${project.id}`,
|
||||||
|
id: project.id,
|
||||||
|
type: 'project',
|
||||||
|
label: project.name,
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.groups && Array.isArray(project.groups)) {
|
||||||
|
project.groups.forEach((group, idx) => {
|
||||||
|
projectNode.children.push({
|
||||||
|
nodeKey: `group-${project.id}-${idx}`,
|
||||||
|
id: project.id,
|
||||||
|
type: 'group',
|
||||||
|
groupName: group.groupName,
|
||||||
|
label: group.groupName
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
treeData.push(projectNode)
|
||||||
|
})
|
||||||
|
|
||||||
|
return treeData
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleTreeNodeClick = (data) => {
|
||||||
|
selectedProjectGroup.value = data
|
||||||
|
initParam.value.refresh = !initParam.value.refresh
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetSelectedGroup = () => {
|
||||||
|
selectedProjectGroup.value = null
|
||||||
|
if (projectGroupTreeRef.value) {
|
||||||
|
projectGroupTreeRef.value.setCurrentKey(null)
|
||||||
|
}
|
||||||
|
initParam.value.refresh = !initParam.value.refresh
|
||||||
|
}
|
||||||
const columnsCoach = ref([
|
const columnsCoach = ref([
|
||||||
{ prop: 'index', label: '序号', align: 'center', type: 'selection' },
|
{ prop: 'index', label: '序号', align: 'center', type: 'selection' },
|
||||||
{ prop: 'name', label: '教练姓名', width: '120px', search: { el: 'input' }, },
|
{ prop: 'name', label: '教练姓名', width: '120px', search: { el: 'input' }, },
|
||||||
@ -689,8 +816,8 @@ const columnsCoach = ref([
|
|||||||
{ label: '女', value: 1 },
|
{ label: '女', value: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ prop: 'idCard', label: '身份证号', },
|
{ prop: 'idCardNumber', label: '身份证号', },
|
||||||
{ prop: 'phone', label: '联系电话', search: { el: 'input' }, },
|
{ prop: 'mobile', label: '联系电话', search: { el: 'input' }, },
|
||||||
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
||||||
])
|
])
|
||||||
const columnsLeader = ref([
|
const columnsLeader = ref([
|
||||||
@ -708,8 +835,8 @@ const columnsLeader = ref([
|
|||||||
{ label: '女', value: 1 },
|
{ label: '女', value: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ prop: 'idCard', label: '身份证号', },
|
{ prop: 'idCardNumber', label: '身份证号', },
|
||||||
{ prop: 'phone', label: '联系电话', search: { el: 'input' }, },
|
{ prop: 'mobile', label: '联系电话', search: { el: 'input' }, },
|
||||||
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -810,6 +937,99 @@ const exportCertificate = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 打开发放证书对话框
|
||||||
|
const openIssueCertificateDialog = () => {
|
||||||
|
if (!selectListIds.value || selectListIds.value.length === 0) {
|
||||||
|
ElMessage.warning('请先选择要发放证书的人员');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedTemplateId.value = undefined;
|
||||||
|
certificateDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发放证书
|
||||||
|
const issueCertificate = async () => {
|
||||||
|
if (!selectListIds.value || selectListIds.value.length === 0) {
|
||||||
|
ElMessage.warning('请先选择要发放证书的人员');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
issuingCertificate.value = true;
|
||||||
|
try {
|
||||||
|
const res = await eventscoreIssuecertificatePost({
|
||||||
|
personIds: selectListIds.value,
|
||||||
|
eventId: initParam.value.eventId,
|
||||||
|
templateId: selectedTemplateId.value
|
||||||
|
});
|
||||||
|
if (res?.succeeded) {
|
||||||
|
ElMessage.success(`证书发放成功!成功 ${res.data?.successCount || 0} 条,失败 ${res.data?.failCount || 0} 条`);
|
||||||
|
certificateDialogVisible.value = false;
|
||||||
|
refreshScoreTable();
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.errors || '证书发放失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('发放证书失败:', error);
|
||||||
|
ElMessage.error('发放证书失败');
|
||||||
|
} finally {
|
||||||
|
issuingCertificate.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发放积分
|
||||||
|
const handleIssuePoints = async () => {
|
||||||
|
try {
|
||||||
|
ElMessageBox.confirm('确定要发放积分吗?系统将根据赛事积分规则为符合条件的用户发放积分。', '发放积分确认', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
issuingPoints.value = true;
|
||||||
|
try {
|
||||||
|
const res = await eventscoreIssuepointsPost({
|
||||||
|
eventId: initParam.value.eventId
|
||||||
|
});
|
||||||
|
if (res?.succeeded) {
|
||||||
|
ElMessage.success(res.data?.Message || '积分发放成功');
|
||||||
|
refreshScoreTable();
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.errors || '积分发放失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('发放积分失败:', error);
|
||||||
|
ElMessage.error(error?.message || '积分发放失败');
|
||||||
|
} finally {
|
||||||
|
issuingPoints.value = false;
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// 用户取消
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('发放积分确认失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看证书
|
||||||
|
const viewCertificate = async (id) => {
|
||||||
|
try {
|
||||||
|
const { succeeded, data, errors } = await eventscoreGetCertificateDetailGet(id);
|
||||||
|
if (succeeded) {
|
||||||
|
if (data?.url) {
|
||||||
|
window.open(data.url, '_blank');
|
||||||
|
} else if (data?.Url) {
|
||||||
|
window.open(data.Url, '_blank');
|
||||||
|
} else {
|
||||||
|
ElMessage.warning('该人员暂无证书');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.error(errors || '查看证书失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查看证书失败:', error);
|
||||||
|
ElMessage.error('查看证书失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 获取组别单位显示
|
// 获取组别单位显示
|
||||||
const getGroupUnit = (projectType) => {
|
const getGroupUnit = (projectType) => {
|
||||||
return projectType && projectType.includes('团队') ? '组' : '人';
|
return projectType && projectType.includes('团队') ? '组' : '人';
|
||||||
@ -907,16 +1127,34 @@ const calculateProjectDuration = (item) => {
|
|||||||
return { totalMinutes, totalSeconds, error };
|
return { totalMinutes, totalSeconds, error };
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听 eventlist 变化,实时计算总时长
|
// 验证场地数是否有效
|
||||||
|
const validateVenueCount = () => {
|
||||||
|
if (!eventlist.value || eventlist.value.length === 0) {
|
||||||
|
return { valid: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalidProjects = [];
|
||||||
|
eventlist.value.forEach((item) => {
|
||||||
|
if (item.venueCount === 0 || !item.venueCount) {
|
||||||
|
invalidProjects.push(item.projectName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (invalidProjects.length > 0) {
|
||||||
|
const message = invalidProjects.map(name => `${name}: 场地数不能为0`).join('\n');
|
||||||
|
return { valid: false, message };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { valid: true };
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听 eventlist 变化,实时计算总时长(不显示错误提示)
|
||||||
watch(
|
watch(
|
||||||
eventlist,
|
eventlist,
|
||||||
(newList) => {
|
(newList) => {
|
||||||
if (newList && newList.length > 0) {
|
if (newList && newList.length > 0) {
|
||||||
newList.forEach((item) => {
|
newList.forEach((item) => {
|
||||||
const result = calculateProjectDuration(item);
|
const result = calculateProjectDuration(item);
|
||||||
if (result.error) {
|
|
||||||
ElMessage.warning(`${item.projectName}: ${result.error}`);
|
|
||||||
}
|
|
||||||
item.totalDurationMinutes = result.totalMinutes;
|
item.totalDurationMinutes = result.totalMinutes;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1240,4 +1478,105 @@ defineExpose({
|
|||||||
width: 8%;
|
width: 8%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 成绩与证书页面样式 */
|
||||||
|
.score-certificate-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel {
|
||||||
|
flex: 0 0 280px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-header {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: #409eff;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel :deep(.el-tree) {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel :deep(.el-tree-node__content) {
|
||||||
|
height: 36px;
|
||||||
|
padding-left: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel :deep(.el-tree-node__content:hover) {
|
||||||
|
background: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel :deep(.el-tree-node.is-current > .el-tree-node__content) {
|
||||||
|
background: #ecf5ff;
|
||||||
|
color: #409eff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-label {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.athlete-list-panel {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.athlete-list-panel :deep(.el-card__body) {
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.score-certificate-container {
|
||||||
|
flex-direction: column;
|
||||||
|
height: auto;
|
||||||
|
min-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel {
|
||||||
|
flex: none;
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.athlete-list-panel {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 350px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.score-certificate-container {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-group-panel {
|
||||||
|
flex: none;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-header {
|
||||||
|
padding: 10px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user