|
|
@@ -1,4 +1,4 @@
|
|
|
-<template>
|
|
|
+<template>
|
|
|
<div class="p-2">
|
|
|
<el-card shadow="never">
|
|
|
<template #header>
|
|
|
@@ -28,7 +28,7 @@
|
|
|
<!-- <span class="countdown-description">数据将自动刷新</span> -->
|
|
|
</div>
|
|
|
</el-col>
|
|
|
- <right-toolbar v-model:showSearch="showSearch" @queryTable="loadBonusData" :columns="columns"></right-toolbar>
|
|
|
+ <!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="loadBonusData" ></right-toolbar> -->
|
|
|
</el-row>
|
|
|
</template>
|
|
|
|
|
|
@@ -36,31 +36,39 @@
|
|
|
v-loading="bonusLoading"
|
|
|
border
|
|
|
:data="bonusDataList"
|
|
|
+ :key="bonusDataList.length + '_' + bonusProjectList.length"
|
|
|
+ max-height="calc(100vh - 200px)"
|
|
|
+ show-summary
|
|
|
+ :summary-method="getSummaries"
|
|
|
@selection-change="handleBonusSelectionChange">
|
|
|
- <el-table-column type="selection" width="55" align="center" />
|
|
|
- <el-table-column label="序号" align="center" width="80">
|
|
|
+ <el-table-column type="selection" width="55" align="center" fixed="left" />
|
|
|
+ <el-table-column label="序号" align="center" width="80" fixed="left">
|
|
|
<template #default="scope">
|
|
|
{{ scope.$index + 1 }}
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="代表队名称" align="center" prop="teamName" width="150" />
|
|
|
- <el-table-column label="排名" align="center" prop="rank" width="80" />
|
|
|
- <el-table-column label="总分" align="center" prop="totalScore" width="100" />
|
|
|
+ <el-table-column label="代表队名称" align="center" prop="teamName" width="150" fixed="left" />
|
|
|
+ <el-table-column label="排名" align="center" prop="rank" width="80" fixed="left" />
|
|
|
+ <el-table-column label="总分" align="center" prop="totalScore" width="100" fixed="left" />
|
|
|
|
|
|
<!-- 动态项目列 -->
|
|
|
<el-table-column
|
|
|
v-for="project in bonusProjectList"
|
|
|
:key="project.projectId"
|
|
|
+ :prop="project.projectId + ''"
|
|
|
align="center"
|
|
|
width="120">
|
|
|
<template #header>
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="primary"
|
|
|
- @click="goToProjectDetail(project)"
|
|
|
- class="project-header-link">
|
|
|
- {{ project.projectName }}
|
|
|
- </el-button>
|
|
|
+ <div class="project-header-container">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="primary"
|
|
|
+ @click="goToProjectDetail(project)"
|
|
|
+ class="project-header-link">
|
|
|
+ {{ project.projectName }}
|
|
|
+ </el-button>
|
|
|
+ <div class="project-total-score">总分: {{ getProjectTotal(project.scoreValue) }}</div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
<template #default="scope">
|
|
|
{{ scope.row.projectScores[project.projectName] || 0 }}
|
|
|
@@ -73,7 +81,8 @@
|
|
|
<el-input
|
|
|
v-model="scope.row.leaderPoint"
|
|
|
type="number"
|
|
|
- step="0.01"
|
|
|
+ :min="0"
|
|
|
+ step="1"
|
|
|
size="small"
|
|
|
@input="calculateTotalScore(scope.row)"
|
|
|
@blur="calculateTotalScore(scope.row)" />
|
|
|
@@ -86,7 +95,8 @@
|
|
|
<el-input
|
|
|
v-model="scope.row.extraPoint"
|
|
|
type="number"
|
|
|
- step="0.01"
|
|
|
+ :min="0"
|
|
|
+ step="1"
|
|
|
size="small"
|
|
|
@input="calculateTotalScore(scope.row)"
|
|
|
@blur="calculateTotalScore(scope.row)" />
|
|
|
@@ -211,6 +221,10 @@ const loadBonusData = async () => {
|
|
|
|
|
|
// 计算总分
|
|
|
const calculateTotalScore = (row: any) => {
|
|
|
+ // 强制修正负数为0
|
|
|
+ if (row.leaderPoint < 0) row.leaderPoint = 0;
|
|
|
+ if (row.extraPoint < 0) row.extraPoint = 0;
|
|
|
+
|
|
|
let totalScore = 0;
|
|
|
|
|
|
// 累加各项目积分
|
|
|
@@ -322,6 +336,62 @@ const refreshBonusData = async () => {
|
|
|
startCountdown();
|
|
|
};
|
|
|
|
|
|
+// 获取项目总分(积分分值之和)
|
|
|
+const getProjectTotal = (scoreValue: string | null | undefined) => {
|
|
|
+ if (!scoreValue) return 0;
|
|
|
+ // 兼容逗号、中文逗号和空格分隔
|
|
|
+ const values = scoreValue.split(/[,,\s]+/);
|
|
|
+ return values.reduce((sum, val) => sum + (Number(val) || 0), 0);
|
|
|
+};
|
|
|
+
|
|
|
+// 表格汇总行计算逻辑
|
|
|
+const getSummaries = (param: any) => {
|
|
|
+ const { columns, data } = param;
|
|
|
+ const sums: string[] = [];
|
|
|
+
|
|
|
+ columns.forEach((column: any, index: number) => {
|
|
|
+ // 根据图片,合计应该显示在第一个单元格(index 1,因为 index 0 是勾选框)
|
|
|
+ if (index === 1) {
|
|
|
+ sums[index] = '合计';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找当前列对应的项目
|
|
|
+ const identifier = column.property;
|
|
|
+ if (!identifier) {
|
|
|
+ sums[index] = '';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const project = bonusProjectList.value.find(p => String(p.projectId) === identifier || p.projectName === identifier);
|
|
|
+ if (project) {
|
|
|
+ const values = data.map((item: any) => Number(item.projectScores[project.projectName] || 0));
|
|
|
+ const total = values.reduce((prev: number, curr: number) => prev + curr, 0);
|
|
|
+ const target = getProjectTotal(project.scoreValue);
|
|
|
+ const isFinished = total >= target;
|
|
|
+
|
|
|
+ sums[index] = total.toString();
|
|
|
+
|
|
|
+ // 暴力美学:异步修改 DOM 样式,绕过 Element Plus 汇总行渲染限制
|
|
|
+ nextTick(() => {
|
|
|
+ const columnId = column.id;
|
|
|
+ const footerCells = document.querySelectorAll(`.el-table__footer-wrapper .${columnId}, .el-table__fixed-footer-wrapper .${columnId}`);
|
|
|
+ footerCells.forEach((cell: any) => {
|
|
|
+ if (cell) {
|
|
|
+ cell.style.color = isFinished ? '#67C23A' : '#F56C6C';
|
|
|
+ cell.style.fontWeight = 'bold';
|
|
|
+ cell.style.fontSize = '14px';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ sums[index] = '';
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return sums;
|
|
|
+};
|
|
|
+
|
|
|
// 跳转到项目详情页
|
|
|
const goToProjectDetail = (project: any) => {
|
|
|
const event = gameEventStore.defaultEventInfo;
|
|
|
@@ -369,7 +439,7 @@ onMounted(async () => {
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
|
/* 倒计时信息区域样式 */
|
|
|
.countdown-info {
|
|
|
@@ -455,6 +525,38 @@ onMounted(async () => {
|
|
|
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2) !important;
|
|
|
}
|
|
|
|
|
|
+.project-header-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 2px;
|
|
|
+}
|
|
|
+
|
|
|
+.project-total-score {
|
|
|
+ font-size: 11px;
|
|
|
+ color: #909399;
|
|
|
+ font-weight: normal;
|
|
|
+}
|
|
|
+
|
|
|
+// 汇总行样式穿透 (包含固定列部分的汇总行)
|
|
|
+:deep(.el-table__footer-wrapper),
|
|
|
+:deep(.el-table__fixed-footer-wrapper) {
|
|
|
+ .summary-finished {
|
|
|
+ color: #67c23a !important;
|
|
|
+ font-weight: bold !important;
|
|
|
+ .cell {
|
|
|
+ color: #67c23a !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .summary-unfinished {
|
|
|
+ color: #f56c6c !important;
|
|
|
+ font-weight: bold !important;
|
|
|
+ .cell {
|
|
|
+ color: #f56c6c !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* 表头样式增强 */
|
|
|
.el-table .el-table__header .project-header-link {
|
|
|
font-weight: 600;
|
|
|
@@ -463,6 +565,32 @@ onMounted(async () => {
|
|
|
min-width: 80px;
|
|
|
}
|
|
|
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+/* 全局样式覆盖,确保汇总行显色 */
|
|
|
+.el-table {
|
|
|
+ .el-table__footer-wrapper,
|
|
|
+ .el-table__fixed-footer-wrapper {
|
|
|
+ .summary-finished {
|
|
|
+ color: #67c23a !important;
|
|
|
+ font-weight: bold !important;
|
|
|
+ .cell {
|
|
|
+ color: #67c23a !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .summary-unfinished {
|
|
|
+ color: #f56c6c !important;
|
|
|
+ font-weight: bold !important;
|
|
|
+ .cell {
|
|
|
+ color: #f56c6c !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
/* 响应式设计 */
|
|
|
@media (max-width: 1200px) {
|
|
|
.countdown-info {
|