2 Commits 52785edc2a ... c3e1156362

Author SHA1 Message Date
  wenkai c3e1156362 Merge branch 'dev' into wk-dev 2 days ago
  zhou f67be534b3 refactor(system): 重构游戏得分模块并优化二进制数据处理 2 days ago
2 changed files with 41 additions and 122 deletions
  1. 1 1
      src/utils/request.ts
  2. 40 121
      src/views/system/gameScore/index.vue

+ 1 - 1
src/utils/request.ts

@@ -125,7 +125,7 @@ service.interceptors.response.use(
     const msg = errorCode[code] || res.data.msg || errorCode['default'];
     // 二进制数据则直接返回
     if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer' || res.config.responseType === 'blob' || res.config.responseType === 'arraybuffer') {
-      return res;
+      return res.data;
     }
     if (code === 401) {
       // prettier-ignore

+ 40 - 121
src/views/system/gameScore/index.vue

@@ -6,7 +6,11 @@
           <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>
@@ -52,12 +56,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' ? '个人项目' : '团体项目' }}
@@ -92,16 +96,8 @@
 </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 } 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';
@@ -110,7 +106,7 @@ import { GameEventVO, GameEventQuery } from '@/api/system/gameEvent/types';
 import { GameEventProjectVO, GameEventProjectQuery } from '@/api/system/gameEventProject/types';
 import { GameTeamVO } from '@/api/system/gameTeam/types';
 import { GameAthleteVO } from '@/api/system/gameAthlete/types';
-import { ElLoading, ElMessage } from 'element-plus';
+import { ElMessage } from 'element-plus';
 import { useGameEventStore } from '@/store/modules/gameEvent';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -138,7 +134,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 },
 ]);
 
 // 下拉框数据
@@ -163,9 +159,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,
@@ -190,7 +186,7 @@ const getList = async () => {
   gameScoreList.value = res.rows;
   total.value = res.total;
   loading.value = false;
-};
+}
 
 /**
  * 刷新数据
@@ -212,7 +208,9 @@ const printScores = async () => {
 
     // 如果有选择项目,则打印选中的项目
     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 {
@@ -248,7 +246,7 @@ const printScores = async () => {
 
           // 按积分排序,取前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名
 
@@ -394,7 +392,7 @@ const buildPrintHtml = (projects: any[]) => {
   `;
 
   // 为每个项目添加成绩表格
-  projects.forEach((project) => {
+  projects.forEach(project => {
     const scores = project.scores || [];
 
     html += `
@@ -478,103 +476,24 @@ const getProjectTypeName = (type: string) => {
   return typeMap[type] || '未知';
 };
 
-const exportScoresNames = async () => {
-  try {
-    // 显示加载状态
-    const loadingInstance = ElLoading.service({
-      lock: true,
-      text: '正在导出成绩汇总表...',
-      background: 'rgba(0, 0, 0, 0.7)'
-    });
-
-    // 获取默认赛事ID
-    const event = gameEventStore.defaultEventInfo;
-    const eventId = event?.eventId;
-
-    if (!eventId) {
-      proxy?.$modal.msgWarning('未指定赛事,无法导出');
-      loadingInstance.close();
-      return;
-    }
-
-    // 调用导出接口
-    const response = await exportScoresSummary(eventId);
-
-    // 校验响应是否为有效的二进制数据
-    if (!response || !response.data || !(response.data instanceof Blob)) {
-      proxy?.$modal.msgError('导出失败:服务器返回数据异常');
-      loadingInstance.close();
-      return;
-    }
-
-    // 创建Blob时,明确指定类型
-    const blob = new Blob([response.data], {
-      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
-    });
+const exportScoresNames = () => {
+  // 获取默认赛事ID
+  const event = gameEventStore.defaultEventInfo;
+  const eventId = event?.eventId;
 
-    // 验证Blob大小是否合理(防止空文件)
-    if (blob.size === 0) {
-      proxy?.$modal.msgError('导出失败:生成的文件为空');
-      loadingInstance.close();
-      return;
-    }
-
-    const url = window.URL.createObjectURL(blob);
-    const link = document.createElement('a');
-    link.href = url;
-    link.download = `成绩汇总表_${new Date().toLocaleDateString()}.xlsx`;
-    document.body.appendChild(link);
-    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') {
-      errorMessage = error;
-    } 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;
-      if (response && response.data) {
-        try {
-          if (response.data instanceof Blob) {
-            // 如果是blob,尝试读取错误信息
-            const reader = new FileReader();
-            reader.onload = function (e) {
-              try {
-                const text = e.target?.result as string;
-                const errorObj = JSON.parse(text);
-                if (errorObj.msg) {
-                  errorMessage = errorObj.msg;
-                }
-              } catch (parseError) {
-                console.warn('无法解析错误响应:', parseError);
-              }
-            };
-            reader.readAsText(response.data);
-          } else if (typeof response.data === 'string') {
-            errorMessage = response.data;
-          } else if (response.data.msg) {
-            errorMessage = response.data.msg;
-          }
-        } catch (parseError) {
-          console.warn('解析错误响应失败:', parseError);
-        }
-      }
-    }
-
-    proxy?.$modal.msgError('导出失败:' + errorMessage);
+  if (!eventId) {
+    proxy?.$modal.msgWarning('未指定赛事,无法导出');
+    return;
   }
+
+  // 使用 proxy?.download 方式导出
+  proxy?.download(
+    'system/gameScore/exportScoresSummary',
+    {
+      eventId: eventId
+    },
+    `成绩汇总表_${new Date().toLocaleDateString()}.xlsx`
+  );
 };
 
 /**
@@ -582,7 +501,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;
@@ -603,10 +522,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;
@@ -622,8 +541,8 @@ const navigateToEditPage = (row: GameEventProjectVO) => {
 
 onMounted(() => {
   // getDefaultEventInfo().then(() => {
-  getList();
-  refreshData();
+    getList();
+    refreshData();
   // });
 });
 </script>