|
@@ -6,11 +6,7 @@
|
|
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
|
|
<el-form-item label="项目" prop="projectId">
|
|
|
<el-select v-model="queryParams.projectId" placeholder="请选择项目" clearable filterable>
|
|
|
- <el-option
|
|
|
- v-for="project in projectList"
|
|
|
- :key="project.projectId"
|
|
|
- :label="project.projectName"
|
|
|
- :value="project.projectId">
|
|
|
+ <el-option v-for="project in projectList" :key="project.projectId" :label="project.projectName" :value="project.projectId">
|
|
|
</el-option>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
@@ -56,12 +52,12 @@
|
|
|
<el-table v-loading="loading" border :data="projectList" @selection-change="handleSelectionChange">
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
|
<el-table-column label="ID" align="center" prop="projectId" v-if="columns[0].visible" />
|
|
|
- <el-table-column label="项目类型" align="center" prop="projectType" v-if="columns[2].visible" >
|
|
|
+ <el-table-column label="项目类型" align="center" prop="projectType" v-if="columns[2].visible">
|
|
|
<template #default="scope">
|
|
|
<dict-tag :options="game_project_type" :value="scope.row.projectType" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="归类" align="center" prop="classification" v-if="columns[3].visible" >
|
|
|
+ <el-table-column label="归类" align="center" prop="classification" v-if="columns[3].visible">
|
|
|
<template #default="scope">
|
|
|
<el-tag :type="scope.row.classification === '0' ? 'success' : 'warning'">
|
|
|
{{ scope.row.classification === '0' ? '个人项目' : '团体项目' }}
|
|
@@ -70,7 +66,7 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="项目" align="center" prop="projectName" v-if="columns[1].visible" />
|
|
|
<!-- <el-table-column label="分组" align="center" prop="groupType" v-if="columns[2].visible" /> -->
|
|
|
-
|
|
|
+
|
|
|
<el-table-column label="状态" align="center" prop="status" v-if="columns[4].visible">
|
|
|
<template #default="scope">
|
|
|
<el-select v-model="scope.row.status" placeholder="请选择状态">
|
|
@@ -96,8 +92,16 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup name="GameScore" lang="ts">
|
|
|
-import { listGameScore, getGameScore, delGameScore, addGameScore, updateGameScore, getProjectScoreData, exportScoresSummary } from '@/api/system/gameScore';
|
|
|
-import { getDefaultEvent } from '@/api/system/gameEvent'
|
|
|
+import {
|
|
|
+ listGameScore,
|
|
|
+ getGameScore,
|
|
|
+ delGameScore,
|
|
|
+ addGameScore,
|
|
|
+ updateGameScore,
|
|
|
+ getProjectScoreData,
|
|
|
+ exportScoresSummary
|
|
|
+} from '@/api/system/gameScore';
|
|
|
+import { getDefaultEvent } from '@/api/system/gameEvent';
|
|
|
import { listGameEventProject } from '@/api/system/gameEventProject';
|
|
|
import { getGameTeam } from '@/api/system/gameTeam';
|
|
|
import { getGameAthlete } from '@/api/system/gameAthlete';
|
|
@@ -134,7 +138,7 @@ const columns = ref<FieldOption[]>([
|
|
|
{ key: 3, label: '归类', visible: true },
|
|
|
{ key: 4, label: '状态', visible: true },
|
|
|
{ key: 5, label: '比赛时间', visible: true },
|
|
|
- { key: 6, label: '更新时间', visible: true },
|
|
|
+ { key: 6, label: '更新时间', visible: true }
|
|
|
]);
|
|
|
|
|
|
// 下拉框数据
|
|
@@ -159,9 +163,9 @@ const initFormData: GameScoreForm = {
|
|
|
statusFlag: undefined,
|
|
|
status: undefined,
|
|
|
remark: undefined
|
|
|
-}
|
|
|
+};
|
|
|
const data = reactive<PageData<GameScoreForm, GameScoreQuery>>({
|
|
|
- form: {...initFormData},
|
|
|
+ form: { ...initFormData },
|
|
|
queryParams: {
|
|
|
pageNum: 1,
|
|
|
pageSize: 10,
|
|
@@ -186,7 +190,7 @@ const getList = async () => {
|
|
|
gameScoreList.value = res.rows;
|
|
|
total.value = res.total;
|
|
|
loading.value = false;
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
/**
|
|
|
* 刷新数据
|
|
@@ -203,14 +207,12 @@ const printScores = async () => {
|
|
|
text: '正在准备打印数据...',
|
|
|
background: 'rgba(0, 0, 0, 0.7)'
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
let projectsToPrint = [];
|
|
|
-
|
|
|
+
|
|
|
// 如果有选择项目,则打印选中的项目
|
|
|
if (ids.value.length > 0) {
|
|
|
- projectsToPrint = projectList.value.filter(project =>
|
|
|
- ids.value.includes(project.projectId)
|
|
|
- );
|
|
|
+ projectsToPrint = projectList.value.filter((project) => ids.value.includes(project.projectId));
|
|
|
} else {
|
|
|
// 如果没有选择项目,提示用户是否打印所有项目
|
|
|
try {
|
|
@@ -238,30 +240,30 @@ const printScores = async () => {
|
|
|
projectId: project.projectId,
|
|
|
classification: project.classification,
|
|
|
pageNum: 1,
|
|
|
- pageSize: 1000
|
|
|
+ pageSize: 1000
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
// 获取成绩数据并补充队伍和运动员信息
|
|
|
const scores = scoreRes.rows || [];
|
|
|
-
|
|
|
+
|
|
|
// 按积分排序,取前3名
|
|
|
const sortedScores = scores
|
|
|
- .filter(score => score.scorePoint && score.scorePoint > 0) // 只显示有积分的成绩
|
|
|
+ .filter((score) => score.scorePoint && score.scorePoint > 0) // 只显示有积分的成绩
|
|
|
.sort((a: any, b: any) => (b.scorePoint || 0) - (a.scorePoint || 0)) // 按积分降序排列
|
|
|
.slice(0, 3); // 只取前3名
|
|
|
-
|
|
|
+
|
|
|
const scoresWithDetails = await Promise.all(
|
|
|
sortedScores.map(async (score: any) => {
|
|
|
let teamName = '-';
|
|
|
let athleteName = '-';
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
// 获取队伍信息
|
|
|
if (score.teamId) {
|
|
|
const teamRes = await getGameTeam(score.teamId);
|
|
|
teamName = teamRes.data.teamName || `队伍${score.teamId}`;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 获取运动员信息
|
|
|
if (score.athleteId) {
|
|
|
const athleteRes = await getGameAthlete(score.athleteId);
|
|
@@ -270,7 +272,7 @@ const printScores = async () => {
|
|
|
} catch (error) {
|
|
|
console.warn('获取队伍或运动员信息失败:', error);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return {
|
|
|
...score,
|
|
|
teamName,
|
|
@@ -278,7 +280,7 @@ const printScores = async () => {
|
|
|
};
|
|
|
})
|
|
|
);
|
|
|
-
|
|
|
+
|
|
|
return {
|
|
|
...project,
|
|
|
scores: scoresWithDetails
|
|
@@ -298,18 +300,18 @@ const printScores = async () => {
|
|
|
|
|
|
// 构建打印HTML内容
|
|
|
const printHtml = buildPrintHtml(projectsWithScores);
|
|
|
-
|
|
|
+
|
|
|
// 使用 Blob 和 URL.createObjectURL 来避免弹窗拦截问题
|
|
|
const blob = new Blob([printHtml], { type: 'text/html' });
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
-
|
|
|
+
|
|
|
// 创建隐藏的 iframe 来处理打印
|
|
|
const iframe = document.createElement('iframe');
|
|
|
iframe.style.position = 'absolute';
|
|
|
iframe.style.top = '-9999px';
|
|
|
iframe.style.left = '-9999px';
|
|
|
document.body.appendChild(iframe);
|
|
|
-
|
|
|
+
|
|
|
iframe.onload = () => {
|
|
|
try {
|
|
|
// 打印完成后清理
|
|
@@ -321,14 +323,14 @@ const printScores = async () => {
|
|
|
console.error('清理打印资源失败:', error);
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
// 在 iframe 中加载并打印
|
|
|
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
|
if (iframeDoc) {
|
|
|
iframeDoc.open();
|
|
|
iframeDoc.write(printHtml);
|
|
|
iframeDoc.close();
|
|
|
-
|
|
|
+
|
|
|
// 等待内容加载后打印
|
|
|
setTimeout(() => {
|
|
|
try {
|
|
@@ -359,7 +361,7 @@ const printScores = async () => {
|
|
|
*/
|
|
|
const buildPrintHtml = (projects: any[]) => {
|
|
|
const printTime = new Date().toLocaleString('zh-CN');
|
|
|
-
|
|
|
+
|
|
|
let html = `
|
|
|
<!DOCTYPE html>
|
|
|
<html>
|
|
@@ -392,16 +394,16 @@ const buildPrintHtml = (projects: any[]) => {
|
|
|
`;
|
|
|
|
|
|
// 为每个项目添加成绩表格
|
|
|
- projects.forEach(project => {
|
|
|
+ projects.forEach((project) => {
|
|
|
const scores = project.scores || [];
|
|
|
-
|
|
|
+
|
|
|
html += `
|
|
|
<div class="project-section">
|
|
|
<div class="project-title">
|
|
|
- <span class="title-label">${project.projectId}</span>
|
|
|
- <span class="title-label">${getProjectTypeName(project.projectType)} ${project.projectName}</span>
|
|
|
+ <span class="title-label">${project.projectId}</span>
|
|
|
+ <span class="title-label">${getProjectTypeName(project.projectType)} ${project.projectName}</span>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<table class="score-table">
|
|
|
<thead>
|
|
|
<tr>
|
|
@@ -469,14 +471,14 @@ const formatScore = (score: number | string) => {
|
|
|
const getProjectTypeName = (type: string) => {
|
|
|
const typeMap: Record<string, string> = {
|
|
|
'1': '田径',
|
|
|
- '2': '游泳',
|
|
|
+ '2': '游泳',
|
|
|
'3': '球类',
|
|
|
'4': '其他'
|
|
|
};
|
|
|
return typeMap[type] || '未知';
|
|
|
};
|
|
|
|
|
|
-const exportScoresNames = async () => {
|
|
|
+const exportScoresNames = async () => {
|
|
|
try {
|
|
|
// 显示加载状态
|
|
|
const loadingInstance = ElLoading.service({
|
|
@@ -488,7 +490,7 @@ const exportScoresNames = async () => {
|
|
|
// 获取默认赛事ID
|
|
|
const event = gameEventStore.defaultEventInfo;
|
|
|
const eventId = event?.eventId;
|
|
|
-
|
|
|
+
|
|
|
if (!eventId) {
|
|
|
proxy?.$modal.msgWarning('未指定赛事,无法导出');
|
|
|
loadingInstance.close();
|
|
@@ -497,7 +499,7 @@ const exportScoresNames = async () => {
|
|
|
|
|
|
// 调用导出接口
|
|
|
const response = await exportScoresSummary(eventId);
|
|
|
-
|
|
|
+
|
|
|
// 校验响应是否为有效的二进制数据
|
|
|
if (!response || !response.data || !(response.data instanceof Blob)) {
|
|
|
proxy?.$modal.msgError('导出失败:服务器返回数据异常');
|
|
@@ -506,10 +508,10 @@ const exportScoresNames = async () => {
|
|
|
}
|
|
|
|
|
|
// 创建Blob时,明确指定类型
|
|
|
- const blob = new Blob([response.data], {
|
|
|
- type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
|
+ const blob = new Blob([response.data], {
|
|
|
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
// 验证Blob大小是否合理(防止空文件)
|
|
|
if (blob.size === 0) {
|
|
|
proxy?.$modal.msgError('导出失败:生成的文件为空');
|
|
@@ -525,14 +527,13 @@ const exportScoresNames = async () => {
|
|
|
link.click();
|
|
|
document.body.removeChild(link);
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
-
|
|
|
+
|
|
|
loadingInstance.close();
|
|
|
proxy?.$modal.msgSuccess('导出成功');
|
|
|
-
|
|
|
} catch (error) {
|
|
|
console.error('导出失败:', error);
|
|
|
let errorMessage = '未知错误';
|
|
|
-
|
|
|
+
|
|
|
if (error instanceof Error) {
|
|
|
errorMessage = error.message;
|
|
|
} else if (typeof error === 'string') {
|
|
@@ -540,7 +541,7 @@ const exportScoresNames = async () => {
|
|
|
} else if (error && typeof error === 'object' && 'message' in error) {
|
|
|
errorMessage = String(error.message);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 尝试获取更详细的错误信息
|
|
|
if (error && typeof error === 'object' && 'response' in error) {
|
|
|
const response = (error as any).response;
|
|
@@ -549,7 +550,7 @@ const exportScoresNames = async () => {
|
|
|
if (response.data instanceof Blob) {
|
|
|
// 如果是blob,尝试读取错误信息
|
|
|
const reader = new FileReader();
|
|
|
- reader.onload = function(e) {
|
|
|
+ reader.onload = function (e) {
|
|
|
try {
|
|
|
const text = e.target?.result as string;
|
|
|
const errorObj = JSON.parse(text);
|
|
@@ -571,7 +572,7 @@ const exportScoresNames = async () => {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
proxy?.$modal.msgError('导出失败:' + errorMessage);
|
|
|
}
|
|
|
};
|
|
@@ -581,7 +582,7 @@ const exportScoresNames = async () => {
|
|
|
*/
|
|
|
const loadProjects = async () => {
|
|
|
loading.value = true;
|
|
|
- console.log('加载项目列表: ',queryParams.value);
|
|
|
+ console.log('加载项目列表: ', queryParams.value);
|
|
|
const res = await listGameEventProject(queryParams.value);
|
|
|
projectList.value = res.rows;
|
|
|
total.value = res.total;
|
|
@@ -602,10 +603,10 @@ const resetQuery = () => {
|
|
|
|
|
|
/** 多选框选中数据 */
|
|
|
const handleSelectionChange = (selection: GameScoreVO[]) => {
|
|
|
- ids.value = selection.map(item => item.projectId); // 使用eventId作为标识
|
|
|
+ ids.value = selection.map((item) => item.projectId); // 使用eventId作为标识
|
|
|
single.value = selection.length != 1;
|
|
|
multiple.value = !selection.length;
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const navigateToEditPage = (row: GameEventProjectVO) => {
|
|
|
const projectId = row.projectId;
|
|
@@ -621,8 +622,8 @@ const navigateToEditPage = (row: GameEventProjectVO) => {
|
|
|
|
|
|
onMounted(() => {
|
|
|
// getDefaultEventInfo().then(() => {
|
|
|
- getList();
|
|
|
- refreshData();
|
|
|
+ getList();
|
|
|
+ refreshData();
|
|
|
// });
|
|
|
});
|
|
|
-</script>
|
|
|
+</script>
|