Эх сурвалжийг харах

feat(api/system/gameScore): 添加加分数据相关API和界面

- 在`index.ts`中添加了获取、更新加分数据以及导出加分Excel的API。
- 在`types.ts`中更新了`GameScoreVO`和`GameScoreForm`接口,将`extraScore1`和`extraScore2`字段分别改为`leaderPoint`和`extraPoint`。
- 在`gameAthlete/index.vue`中修改了表单项的标签,将“运动员编号”改为“号码”。
- 在`gameScoreEdit.vue`中移除了团队项目显示中的队伍名称和队伍编号列。
- 在`index.vue`中添加了加分编辑弹窗及相关按钮,并实现了加载、保存、导出加分数据的功能。
- 更新了相关方法以支持新的加分功能。
zhou 1 сар өмнө
parent
commit
12e571b2d7

+ 41 - 0
src/api/system/gameScore/index.ts

@@ -146,3 +146,44 @@ export const exportScoresSummary = (eventId: string | number) => {
     responseType: 'blob' // 确保以二进制流形式接收响应
   });
 };
+
+/**
+ * 获取加分数据
+ * @param params 查询参数
+ */
+export const getBonusData = (params: { eventId: string | number }) => {
+  return request({
+    url: '/system/gameScore/getBonusData',
+    method: 'get',
+    params
+  });
+};
+
+/**
+ * 更新加分数据
+ * @param data 加分数据
+ */
+export const updateBonusData = (data: { eventId: string | number; data: any[] }) => {
+  return request({
+    url: '/system/gameScore/updateBonusData',
+    method: 'put',
+    data
+  });
+};
+
+/**
+ * 导出加分Excel
+ * @param data 导出数据
+ */
+export const exportBonusExcel = (data: { 
+  eventId: string | number; 
+  data: any[]; 
+  projects: any[] 
+}) => {
+  return request({
+    url: '/system/gameScore/exportBonusExcel',
+    method: 'post',
+    data,
+    responseType: 'blob' // 确保以二进制流形式接收响应
+  });
+};

+ 8 - 8
src/api/system/gameScore/types.ts

@@ -54,14 +54,14 @@ export interface GameScoreVO {
   award: string;
 
   /**
-   * 附加成绩1
+   * 领导加分
    */
-  extraScore1: string;
+  leaderPoint: number;
 
   /**
-   * 附加成绩2
+   * 额外加分
    */
-  extraScore2: string;
+  extraPoint: number;
 
   /**
    * 成绩状态(0等待处理1处理完毕)
@@ -147,14 +147,14 @@ export interface GameScoreForm extends BaseEntity {
   award?: string;
 
   /**
-   * 附加成绩1
+   * 领导加分
    */
-  extraScore1?: string;
+  leaderPoint?: number;
 
   /**
-   * 附加成绩2
+   * 额外加分
    */
-  extraScore2?: string;
+  extraPoint?: number;
 
   /**
    * 成绩状态(0等待处理1处理完毕)

+ 2 - 2
src/views/system/gameAthlete/index.vue

@@ -7,8 +7,8 @@
             <el-form-item label="队伍名称" prop="teamName">
               <el-input v-model="queryParams.teamName" placeholder="请输入队伍名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="运动员编号" prop="athleteCode">
-              <el-input v-model="queryParams.athleteCode" placeholder="请输入运动员号" clearable @keyup.enter="handleQuery" />
+            <el-form-item label="号" prop="athleteCode">
+              <el-input v-model="queryParams.athleteCode" placeholder="请输入运动员号" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="姓名" prop="name">
               <el-input v-model="queryParams.name" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" />

+ 0 - 2
src/views/system/gameScore/gameScoreEdit.vue

@@ -45,8 +45,6 @@
         
         <!-- 团体项目显示队伍信息 -->
         <template v-else>
-          <!-- <el-table-column label="队伍名称" align="center" prop="teamName" /> -->
-          <!-- <el-table-column label="队伍编号" align="center" prop="teamCode" /> -->
           <el-table-column label="团队成绩" align="center" prop="teamPerformance" />
         </template>
         

+ 264 - 8
src/views/system/gameScore/index.vue

@@ -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;