|
|
@@ -492,7 +492,7 @@ const printScores = async () => {
|
|
|
|
|
|
// 按积分排序,取前n名(使用用户输入的数量)
|
|
|
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, topCount); // 使用用户输入的数量
|
|
|
|
|
|
@@ -606,107 +606,232 @@ const printScores = async () => {
|
|
|
/**
|
|
|
* 构建打印HTML内容
|
|
|
*/
|
|
|
-const buildPrintHtml = (projects: any[], topCount: number = 3) => {
|
|
|
- const printTime = new Date().toLocaleString('zh-CN');
|
|
|
-
|
|
|
- let html = `
|
|
|
- <!DOCTYPE html>
|
|
|
+const buildPrintHtml = (projects: any[], topCount: number) => {
|
|
|
+ return `
|
|
|
<html>
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
- <title>赛事成绩打印 - 前${topCount}名</title>
|
|
|
+ <title>成绩打印(前${topCount}名)</title>
|
|
|
<style>
|
|
|
- body { font-family: Arial, sans-serif; margin: 20px; }
|
|
|
- .print-header { text-align: center; margin-bottom: 30px; border-bottom: 2px solid #333; padding-bottom: 20px; }
|
|
|
- .print-header h1 { margin: 0 0 10px 0; font-size: 24px; color: #333; }
|
|
|
- .print-header p { margin: 0; color: #666; font-size: 14px; }
|
|
|
- .project-section { margin-bottom: 40px; page-break-inside: avoid; }
|
|
|
- .project-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; padding: 10px; background: #f5f5f5; border-left: 4px solid #409eff; }
|
|
|
- .title-label { color: #f56c6c; font-weight: bold; }
|
|
|
- .score-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
|
|
|
- .score-table th, .score-table td { border: 1px solid #ddd; padding: 8px 12px; text-align: center; }
|
|
|
- .score-table th { background: #f8f9fa; font-weight: bold; color: #333; }
|
|
|
- .score-table td { color: #333; }
|
|
|
- .rank-1 { background-color: #fff7e6; font-weight: bold; }
|
|
|
+ body {
|
|
|
+ font-family: SimSun, 'Times New Roman', serif;
|
|
|
+ padding: 20px;
|
|
|
+ margin: 0;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ .print-header {
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 30px;
|
|
|
+ border-bottom: 2px solid #333;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ }
|
|
|
+ .print-header h1 {
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ font-size: 24px;
|
|
|
+ }
|
|
|
+ .print-header p {
|
|
|
+ margin: 0;
|
|
|
+ color: #666;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ .project-section {
|
|
|
+ margin-bottom: 40px;
|
|
|
+ page-break-inside: avoid;
|
|
|
+ }
|
|
|
+ .project-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ padding: 10px;
|
|
|
+ background: #f5f5f5;
|
|
|
+ border-left: 4px solid #409eff;
|
|
|
+ }
|
|
|
+ .title-label {
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ .score-table {
|
|
|
+ width: 100%;
|
|
|
+ border-collapse: collapse;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ .score-table th,
|
|
|
+ .score-table td {
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ padding: 8px 12px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .score-table th {
|
|
|
+ background: #f8f9fa;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ .rank-1 { background-color: #fff7e6; }
|
|
|
.rank-2 { background-color: #f6ffed; }
|
|
|
.rank-3 { background-color: #f0f9ff; }
|
|
|
- @media print { .project-section { page-break-inside: avoid; } }
|
|
|
+
|
|
|
+ /* 打印样式 - 优化打印预览和实际打印效果一致性 */
|
|
|
+ @media print {
|
|
|
+ * {
|
|
|
+ -webkit-print-color-adjust: exact !important;
|
|
|
+ print-color-adjust: exact !important;
|
|
|
+ background: transparent !important;
|
|
|
+ box-shadow: none !important;
|
|
|
+ text-shadow: none !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ body {
|
|
|
+ font-family: SimSun, "Times New Roman", serif !important;
|
|
|
+ font-size: 12pt !important;
|
|
|
+ line-height: 1.4 !important;
|
|
|
+ color: #000 !important;
|
|
|
+ padding: 0 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .print-container {
|
|
|
+ padding: 0 !important;
|
|
|
+ max-width: 100% !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .print-content {
|
|
|
+ width: 100% !important;
|
|
|
+ max-width: 100% !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .project-section {
|
|
|
+ page-break-inside: avoid !important;
|
|
|
+ page-break-after: auto !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-table {
|
|
|
+ width: 100% !important;
|
|
|
+ border-collapse: collapse !important;
|
|
|
+ font-size: 11pt !important;
|
|
|
+ page-break-inside: avoid !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-table th,
|
|
|
+ .score-table td {
|
|
|
+ border: 1px solid #000 !important;
|
|
|
+ padding: 5pt !important;
|
|
|
+ text-align: center !important;
|
|
|
+ vertical-align: middle !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-table th {
|
|
|
+ background-color: #f8f9fa !important;
|
|
|
+ color: #000 !important;
|
|
|
+ font-weight: bold !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-table thead {
|
|
|
+ display: table-header-group !important; /* 确保表头在每页重复 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-table tbody {
|
|
|
+ display: table-row-group !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 确保排名样式在打印中正确显示 */
|
|
|
+ .rank-1 {
|
|
|
+ background-color: #fff7e6 !important;
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rank-2 {
|
|
|
+ background-color: #f6ffed !important;
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rank-3 {
|
|
|
+ background-color: #f0f9ff !important;
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 设置页面边距 */
|
|
|
+ @page {
|
|
|
+ margin: 20mm !important;
|
|
|
+ size: A4 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 避免第一页顶部和最后一页底部有太多空白 */
|
|
|
+ .print-header {
|
|
|
+ page-break-after: avoid !important;
|
|
|
+ border-bottom: 2px solid #000 !important;
|
|
|
+ margin-bottom: 30pt !important;
|
|
|
+ padding-bottom: 20pt !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 确保字体大小在打印中保持一致 */
|
|
|
+ h1 {
|
|
|
+ font-size: 18pt !important;
|
|
|
+ margin-bottom: 10pt !important;
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .project-title {
|
|
|
+ font-size: 14pt !important;
|
|
|
+ margin-bottom: 10pt !important;
|
|
|
+ padding: 8pt !important;
|
|
|
+ border-left: 4px solid #000 !important;
|
|
|
+ background-color: #f5f5f5 !important;
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .title-label {
|
|
|
+ color: #000 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 确保在IE浏览器中也能正常打印 */
|
|
|
+ @media print and (-ms-high-contrast: none), print and (-ms-high-contrast: active) {
|
|
|
+ * {
|
|
|
+ color-adjust: exact !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
<div class="print-header">
|
|
|
<h1>赛事管理系统 - 成绩打印(前${topCount}名)</h1>
|
|
|
- <p>打印时间: ${printTime}</p>
|
|
|
+ <p>打印时间: ${new Date().toLocaleString('zh-CN')}</p>
|
|
|
</div>
|
|
|
- `;
|
|
|
-
|
|
|
- // 为每个项目添加成绩表格
|
|
|
- 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>
|
|
|
+
|
|
|
+ ${projects.map(project => `
|
|
|
+ <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>
|
|
|
+ </div>
|
|
|
+ <table class="score-table">
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <th class="title-label">类别</th>
|
|
|
+ <th class="title-label">名次</th>
|
|
|
+ <th class="title-label">队伍</th>
|
|
|
+ <th class="title-label">运动员编号</th>
|
|
|
+ <th class="title-label">姓名</th>
|
|
|
+ <th class="title-label">成绩</th>
|
|
|
+ <th class="title-label">积分</th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ ${project.scores.slice(0, topCount).map((score: any, index: number) => `
|
|
|
+ <tr>
|
|
|
+ <td>${score.classification === '0' ? '个人项目' : '团体项目'}</td>
|
|
|
+ <td>第${Number(index) + 1}名</td>
|
|
|
+ <td>${score.teamName || '-'}</td>
|
|
|
+ <td>${score.athleteCode || '-'}</td>
|
|
|
+ <td>${score.athleteName || '-'}</td>
|
|
|
+ <td >${score.classification === '0' ? formatScore(score.individualPerformance) : formatScore(score.teamPerformance)}</td>
|
|
|
+ <td>${score.scorePoint || 0}</td>
|
|
|
+ </tr>
|
|
|
+ `).join('')}
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
</div>
|
|
|
-
|
|
|
- <table class="score-table">
|
|
|
- <thead>
|
|
|
- <tr>
|
|
|
- <th class="title-label">类别</th>
|
|
|
- <th>名次</th>
|
|
|
- <th class="title-label">队伍</th>
|
|
|
- <th class="title-label">运动员编号</th>
|
|
|
- <th class="title-label">姓名</th>
|
|
|
- <th class="title-label">成绩</th>
|
|
|
- <th class="title-label">积分</th>
|
|
|
- </tr>
|
|
|
- </thead>
|
|
|
- <tbody>
|
|
|
- `;
|
|
|
-
|
|
|
- if (scores.length > 0) {
|
|
|
- scores.forEach((score: any, index: number) => {
|
|
|
- // 动态设置排名样式,只对前3名应用特殊样式
|
|
|
- let rankClass = '';
|
|
|
- if (index === 0) rankClass = 'rank-1';
|
|
|
- else if (index === 1) rankClass = 'rank-2';
|
|
|
- else if (index === 2) rankClass = 'rank-3';
|
|
|
-
|
|
|
- html += `
|
|
|
- <tr class="${rankClass}">
|
|
|
- <td>${score.classification === '0' ? '个人项目' : '团体项目'}</td>
|
|
|
- <td>第${index + 1}名</td>
|
|
|
- <td>${score.teamName || '-'}</td>
|
|
|
- <td>${score.athleteCode || '-'}</td>
|
|
|
- <td>${score.athleteName || '-'}</td>
|
|
|
- <td>${formatScore(score.individualPerformance || score.teamPerformance)}</td>
|
|
|
- <td>${score.scorePoint || 0}</td>
|
|
|
- </tr>
|
|
|
- `;
|
|
|
- });
|
|
|
- } else {
|
|
|
- html += `
|
|
|
- <tr>
|
|
|
- <td colspan="7" style="text-align: center; color: #999;">暂无成绩数据</td>
|
|
|
- </tr>
|
|
|
- `;
|
|
|
- }
|
|
|
-
|
|
|
- html += `
|
|
|
- </tbody>
|
|
|
- </table>
|
|
|
- </div>
|
|
|
- `;
|
|
|
- });
|
|
|
-
|
|
|
- html += `
|
|
|
+ `).join('')}
|
|
|
</body>
|
|
|
</html>
|
|
|
`;
|
|
|
-
|
|
|
- return html;
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
@@ -847,12 +972,16 @@ const calculateParticipantCounts = async () => {
|
|
|
|
|
|
// 计算完赛人数(有成绩记录的)
|
|
|
const completedScores = scores.filter(score => {
|
|
|
- const individualScore = parseFloat(score.individualPerformance);
|
|
|
- const teamScore = parseFloat(score.teamPerformance);
|
|
|
-
|
|
|
// 成绩必须存在且大于0
|
|
|
- return (!isNaN(individualScore) && individualScore > 0) ||
|
|
|
- (!isNaN(teamScore) && teamScore > 0);
|
|
|
+ const sc = score.classification === '0' ? score.individualPerformance : score.teamPerformance;
|
|
|
+ if (sc === null || sc === undefined || sc === '' || sc === '00:00:00.000') {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (typeof sc === 'number') {
|
|
|
+ return !isNaN(sc) && sc > 0;
|
|
|
+ }else if(typeof sc === 'string'){
|
|
|
+ return sc !== '0';
|
|
|
+ }
|
|
|
});
|
|
|
console.log('completedScores: ', completedScores);
|
|
|
(project as any).completedParticipants = completedScores.length;
|
|
|
@@ -907,3 +1036,6 @@ onMounted(() => {
|
|
|
loadProjects();
|
|
|
});
|
|
|
</script>
|
|
|
+
|
|
|
+
|
|
|
+
|