|
@@ -38,6 +38,11 @@
|
|
|
<el-col :span="1.5">
|
|
|
<el-button type="primary" @click="exportScoresNames">导出成绩(全部)</el-button>
|
|
|
</el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="warning" @click="openBonusDialog" :loading="bonusLoading">
|
|
|
+ <el-icon><Edit /></el-icon> 加分
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
|
|
|
</el-row>
|
|
|
</template>
|
|
@@ -91,11 +96,86 @@
|
|
|
|
|
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
|
|
</el-card>
|
|
|
+
|
|
|
+ <!-- 加分编辑弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ title="加分编辑"
|
|
|
+ v-model="bonusDialog.visible"
|
|
|
+ width="90%"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ append-to-body>
|
|
|
+ <div class="mb-4">
|
|
|
+ <el-button type="primary" @click="saveBonusChanges" :loading="saveLoading">
|
|
|
+ <el-icon><Check /></el-icon> 保存修改
|
|
|
+ </el-button>
|
|
|
+ <el-button type="success" @click="exportBonusData" :loading="exportLoading">
|
|
|
+ <el-icon><Download /></el-icon> 导出Excel
|
|
|
+ </el-button>
|
|
|
+ <el-button @click="refreshBonusData">
|
|
|
+ <el-icon><Refresh /></el-icon> 刷新数据
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ v-loading="bonusLoading"
|
|
|
+ border
|
|
|
+ :data="bonusDataList"
|
|
|
+ max-height="600"
|
|
|
+ @selection-change="handleBonusSelectionChange">
|
|
|
+ <el-table-column type="selection" width="55" align="center" />
|
|
|
+ <el-table-column label="序号" align="center" width="80">
|
|
|
+ <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
|
|
|
+ v-for="project in bonusProjectList"
|
|
|
+ :key="project.projectId"
|
|
|
+ :label="project.projectName"
|
|
|
+ align="center"
|
|
|
+ width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.projectScores[project.projectName] || 0 }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <!-- 领导加分列 - 可编辑 -->
|
|
|
+ <el-table-column label="领导加分" align="center" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.leaderPoint"
|
|
|
+ type="number"
|
|
|
+ step="0.01"
|
|
|
+ size="small"
|
|
|
+ @input="calculateTotalScore(scope.row)"
|
|
|
+ @blur="calculateTotalScore(scope.row)" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <!-- 额外加分列 - 可编辑 -->
|
|
|
+ <el-table-column label="额外加分" align="center" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input
|
|
|
+ v-model="scope.row.extraPoint"
|
|
|
+ type="number"
|
|
|
+ step="0.01"
|
|
|
+ size="small"
|
|
|
+ @input="calculateTotalScore(scope.row)"
|
|
|
+ @blur="calculateTotalScore(scope.row)" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup name="GameScore" lang="ts">
|
|
|
-import { listGameScore, getGameScore, delGameScore, addGameScore, updateGameScore, getProjectScoreData } from '@/api/system/gameScore';
|
|
|
+import { listGameScore, getGameScore, delGameScore, addGameScore, updateGameScore, getProjectScoreData, getBonusData, updateBonusData, exportBonusExcel } from '@/api/system/gameScore';
|
|
|
import { listGameEventProject } from '@/api/system/gameEventProject';
|
|
|
import { getGameTeam } from '@/api/system/gameTeam';
|
|
|
import { getGameAthlete } from '@/api/system/gameAthlete';
|
|
@@ -120,6 +200,19 @@ const single = ref(true);
|
|
|
const multiple = ref(true);
|
|
|
const total = ref(0);
|
|
|
|
|
|
+// 加分弹窗相关数据
|
|
|
+const bonusLoading = ref(false);
|
|
|
+const saveLoading = ref(false);
|
|
|
+const exportLoading = ref(false);
|
|
|
+const bonusDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ title: '加分编辑'
|
|
|
+});
|
|
|
+
|
|
|
+const bonusDataList = ref<any[]>([]);
|
|
|
+const bonusProjectList = ref<any[]>([]);
|
|
|
+const selectedBonusRows = ref<any[]>([]);
|
|
|
+
|
|
|
// 列显隐数据
|
|
|
const columns = ref<FieldOption[]>([
|
|
|
{ key: 0, label: 'ID', visible: false },
|
|
@@ -148,8 +241,8 @@ const initFormData: GameScoreForm = {
|
|
|
scoreRank: undefined,
|
|
|
scorePoint: undefined,
|
|
|
award: undefined,
|
|
|
- extraScore1: undefined,
|
|
|
- extraScore2: undefined,
|
|
|
+ leaderPoint: undefined,
|
|
|
+ extraPoint: undefined,
|
|
|
statusFlag: undefined,
|
|
|
status: undefined,
|
|
|
remark: undefined
|
|
@@ -168,13 +261,176 @@ const data = reactive<PageData<GameScoreForm, GameScoreQuery>>({
|
|
|
|
|
|
const { queryParams, form, rules } = toRefs(data);
|
|
|
|
|
|
+// 加分相关方法
|
|
|
+// 打开加分弹窗
|
|
|
+const openBonusDialog = async () => {
|
|
|
+ try {
|
|
|
+ bonusLoading.value = true;
|
|
|
+ bonusDialog.visible = true;
|
|
|
+
|
|
|
+ // 获取默认赛事ID
|
|
|
+ const event = gameEventStore.defaultEventInfo;
|
|
|
+ const eventId = event?.eventId;
|
|
|
+
|
|
|
+ if (!eventId) {
|
|
|
+ proxy?.$modal.msgWarning('未指定赛事,无法进行加分操作');
|
|
|
+ bonusDialog.visible = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取加分数据
|
|
|
+ await loadBonusData(eventId);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("打开加分弹窗失败:", error);
|
|
|
+ proxy?.$modal.msgError("加载加分数据失败");
|
|
|
+ } finally {
|
|
|
+ bonusLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 加载加分数据
|
|
|
+const loadBonusData = async (eventId: string | number) => {
|
|
|
+ try {
|
|
|
+ const response = await getBonusData({
|
|
|
+ eventId: eventId
|
|
|
+ });
|
|
|
+
|
|
|
+ bonusDataList.value = response.data.rows || [];
|
|
|
+ bonusProjectList.value = response.data.projects || [];
|
|
|
+
|
|
|
+ // 初始化加分字段
|
|
|
+ bonusDataList.value.forEach((row: any) => {
|
|
|
+ if (!row.leaderPoint) row.leaderPoint = 0;
|
|
|
+ if (!row.extraPoint) row.extraPoint = 0;
|
|
|
+ calculateTotalScore(row);
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.error("加载加分数据失败:", error);
|
|
|
+ proxy?.$modal.msgError("加载加分数据失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 计算总分
|
|
|
+const calculateTotalScore = (row: any) => {
|
|
|
+ let totalScore = 0;
|
|
|
+
|
|
|
+ // 累加各项目积分
|
|
|
+ Object.values(row.projectScores || {}).forEach((score: any) => {
|
|
|
+ totalScore += Number(score) || 0;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 加上领导加分和额外加分
|
|
|
+ totalScore += Number(row.leaderPoint) || 0;
|
|
|
+ totalScore += Number(row.extraPoint) || 0;
|
|
|
+
|
|
|
+ row.totalScore = totalScore;
|
|
|
+
|
|
|
+ // 重新计算排名
|
|
|
+ calculateBonusRankings();
|
|
|
+};
|
|
|
+
|
|
|
+// 计算excel表排名
|
|
|
+const calculateBonusRankings = () => {
|
|
|
+ // 按总分排序
|
|
|
+ const sortedData = [...bonusDataList.value].sort((a, b) => b.totalScore - a.totalScore);
|
|
|
+
|
|
|
+ // 更新排名
|
|
|
+ sortedData.forEach((row, index) => {
|
|
|
+ row.rank = index + 1;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新原数组
|
|
|
+ bonusDataList.value = sortedData;
|
|
|
+};
|
|
|
+
|
|
|
+// 选择变化处理
|
|
|
+const handleBonusSelectionChange = (selection: any[]) => {
|
|
|
+ selectedBonusRows.value = selection;
|
|
|
+};
|
|
|
+
|
|
|
+// 保存加分修改
|
|
|
+const saveBonusChanges = async () => {
|
|
|
+ try {
|
|
|
+ saveLoading.value = true;
|
|
|
+
|
|
|
+ const event = gameEventStore.defaultEventInfo;
|
|
|
+ const eventId = event?.eventId;
|
|
|
+
|
|
|
+ if (!eventId) {
|
|
|
+ proxy?.$modal.msgWarning('未指定赛事,无法保存');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateData = bonusDataList.value.map(row => ({
|
|
|
+ teamId: row.teamId,
|
|
|
+ leaderPoint: Number(row.leaderPoint) || 0,
|
|
|
+ extraPoint: Number(row.extraPoint) || 0,
|
|
|
+ totalScore: row.totalScore,
|
|
|
+ rank: row.rank
|
|
|
+ }));
|
|
|
+
|
|
|
+ await updateBonusData({
|
|
|
+ eventId: eventId,
|
|
|
+ data: updateData
|
|
|
+ });
|
|
|
+
|
|
|
+ proxy?.$modal.msgSuccess("保存成功");
|
|
|
+
|
|
|
+ // 刷新主页面数据
|
|
|
+ // await refreshData();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("保存失败:", error);
|
|
|
+ proxy?.$modal.msgError("保存失败,请稍后再试");
|
|
|
+ } finally {
|
|
|
+ saveLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 导出加分数据方法
|
|
|
+const exportBonusData = async () => {
|
|
|
+ try {
|
|
|
+ exportLoading.value = true;
|
|
|
+
|
|
|
+ const event = gameEventStore.defaultEventInfo;
|
|
|
+ const eventId = event?.eventId;
|
|
|
+
|
|
|
+ if (!eventId) {
|
|
|
+ proxy?.$modal.msgWarning('未指定默认赛事,无法导出');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用 proxy?.download 方法,传递JSON字符串参数
|
|
|
+ proxy?.download(
|
|
|
+ '/system/gameScore/exportBonusExcel',
|
|
|
+ {
|
|
|
+ eventId: eventId,
|
|
|
+ data: JSON.stringify(bonusDataList.value),
|
|
|
+ projects: JSON.stringify(bonusProjectList.value)
|
|
|
+ },
|
|
|
+ `总成绩排名表_${new Date().toLocaleDateString()}.xlsx`
|
|
|
+ );
|
|
|
+
|
|
|
+ proxy?.$modal.msgSuccess("导出成功");
|
|
|
+ } catch (error) {
|
|
|
+ console.error("导出失败:", error);
|
|
|
+ proxy?.$modal.msgError("导出失败,请稍后再试");
|
|
|
+ } finally {
|
|
|
+ exportLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 刷新加分数据
|
|
|
+const refreshBonusData = async () => {
|
|
|
+ const event = gameEventStore.defaultEventInfo;
|
|
|
+ const eventId = event?.eventId;
|
|
|
+
|
|
|
+ if (eventId) {
|
|
|
+ await loadBonusData(eventId);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
/** 查询成绩列表 */
|
|
|
const getList = async () => {
|
|
|
- // if (!queryParams.value.eventId) {
|
|
|
- // proxy?.$modal.msgWarning('未指定默认赛事');
|
|
|
- // loading.value = false;
|
|
|
- // return;
|
|
|
- // }
|
|
|
loading.value = true;
|
|
|
const res = await listGameScore(queryParams.value);
|
|
|
gameScoreList.value = res.rows;
|