Browse Source

feat(gameEvent): 完善裁判管理功能并优化赛事详情页面

- 注释掉通知页面中的“前往gitee”按钮
- 修改排行榜页面的倒计时逻辑,注释掉重复调用的停止函数
- 调整裁判表单组件,增加裁判姓名字段及项目选择控件样式
- 引入计算属性处理项目列表的数据类型转换
- 支持裁判信息的新增与编辑功能,并完善表单验证规则
- 优化赛事详情页数据结构,增加limitApplication字段
- 更新赛事列表页面按钮文字,将“下载模板”改为“下载报名表”
- 移除赛事详情中不再使用的组件引用(RankingBoard、Editor)
zhou 6 days ago
parent
commit
3d65650fae

+ 1 - 1
src/layout/components/notice/index.vue

@@ -19,7 +19,7 @@
       </template>
       <el-empty v-else :description="'消息为空'"></el-empty>
     </div>
-    <div v-if="newsList.length > 0" class="foot-box" @click="onGoToGiteeClick">前往gitee</div>
+    <!-- <div v-if="newsList.length > 0" class="foot-box" @click="onGoToGiteeClick">前往gitee</div> -->
   </div>
 </template>
 

+ 2 - 4
src/views/system/gameEvent/RankingBoardPage.vue

@@ -255,7 +255,7 @@ const countdownInterval = ref<NodeJS.Timeout | null>(null); // 倒计时定时
 
 // 启动倒计时
 const startCountdown = () => {
-  stopCountdown();
+  // stopCountdown();
   countdownSeconds.value = autoRefreshSeconds.value;
   
   countdownInterval.value = setInterval(() => {
@@ -636,8 +636,8 @@ onUnmounted(() => {
 
 onMounted(async () => {
   try{
-    // refreshAllData();
     startAutoRefresh();
+    await gameEventStore.fetchDefaultEvent();
     const res = await listScoreRanking(defaultEventInfo.value.eventId.toString());
     // 按照totalScore字段降序排序(分数高的在前面)
     athleteScoreList.value = res.data.sort((a, b) => b.totalScore - a.totalScore);
@@ -650,8 +650,6 @@ onMounted(async () => {
       // 加载项目进度信息
       loadProjectProgress()
     ]);
-    // // 开启自动刷新
-    // startAutoRefresh();
   } catch (error) {
     console.error('加载数据失败:', error);
   }

+ 76 - 24
src/views/system/gameEvent/RefereeForm.vue

@@ -1,19 +1,23 @@
 <template>
   <el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
     <el-form ref="refereeFormRef" :model="form" :rules="rules" label-width="80px">
+      <el-form-item label="裁判姓名" prop="name">
+        <el-input v-model="form.name" placeholder="请输入裁判姓名" />
+      </el-form-item>
       <el-form-item label="账号" prop="account">
         <el-input v-model="form.account" placeholder="请输入账号" />
       </el-form-item>
       <el-form-item label="密码" prop="password">
         <el-input type="password" v-model="form.password" placeholder="请输入密码" show-password />
       </el-form-item>
-      <el-form-item label="赛事项目" prop="projectIds">
+      <el-form-item label="赛事项目" prop="projectList2">
         <!-- 合并为一个 el-transfer -->
         <el-transfer
-          v-model="form.projectIds"
+          v-model="projectList2Str"
           :data="allProjects"
           :titles="['可选项目', '已选项目']"
           :button-texts="['移除', '添加']"
+          style="width: 100%"
         />
       </el-form-item>
     </el-form>
@@ -27,10 +31,10 @@
 </template>
 
 <script setup name="RefereeForm" lang="ts">
-import { reactive, ref } from 'vue';
+import { reactive, ref, computed } from 'vue';
 import { ElMessage } from 'element-plus';
-import { listGameEventProject, updateGameEventProject,getGameEventProject } from '@/api/system/gameEventProject';
-import { addGameReferee } from '@/api/system/gameReferee';
+import { listGameEventProject, updateGameEventProject, getGameEventProject } from '@/api/system/gameEventProject';
+import { addGameReferee, updateGameReferee, getGameReferee } from '@/api/system/gameReferee';
 
 const dialog = reactive({
   visible: false,
@@ -38,12 +42,18 @@ const dialog = reactive({
 });
 
 const form = reactive({
+  refereeId: undefined as string | number | undefined,
+  eventId: undefined as string | number | undefined,
+  name: undefined,
   account: undefined,
   password: undefined,
-  projectIds: [] as string[]
+  projectList2: [] as number[]
 });
 
 const rules = {
+  name: [
+    { required: true, message: '请输入裁判姓名', trigger: 'blur' }
+  ],
   account: [
     { required: true, message: '请输入账号', trigger: 'blur' }
   ],
@@ -56,6 +66,14 @@ const refereeFormRef = ref<any>(null);
 const allProjects = ref<{key: string, label: string }[]>([]);
 const eventId = ref<string>(''); // 新增:用于存储赛事ID
 
+// 添加一个计算属性用于处理projectList2的类型转换
+const projectList2Str = computed({
+  get: () => form.projectList2.map(id => String(id)),
+  set: (value) => {
+    form.projectList2 = value.map(id => Number(id));
+  }
+});
+
 const loadProjects = async () => {
   try {
     const res = await listGameEventProject({
@@ -77,7 +95,7 @@ const loadProjects = async () => {
   }
 };
 
-const openDialog = async (eventIdParam: string) => {
+const openDialog = async (eventIdParam: string, refereeId?: string | number) => {
   try {
     
     if (!eventIdParam) {
@@ -88,9 +106,24 @@ const openDialog = async (eventIdParam: string) => {
     eventId.value = eventIdParam; // 接收并设置赛事ID
     
     // 重置表单数据
-    form.account = '';
-    form.password = '';
-    form.projectIds = [];
+    reset();
+    
+    // 如果是编辑模式,加载裁判数据
+    if (refereeId) {
+      const res = await getGameReferee(refereeId);
+      Object.assign(form, res.data);
+      
+      // 处理项目列表数据格式
+      if (Array.isArray(res.data.projectList2)) {
+        form.projectList2 = res.data.projectList2.map(id => id);
+      } else {
+        form.projectList2 = [];
+      }
+      
+      dialog.title = '修改裁判';
+    } else {
+      dialog.title = '添加裁判';
+    }
     
     await loadProjects();
     dialog.visible = true;
@@ -100,24 +133,42 @@ const openDialog = async (eventIdParam: string) => {
   }
 };
 
+const reset = () => {
+  Object.assign(form, {
+    refereeId: undefined,
+    eventId: undefined,
+    name: undefined,
+    account: undefined,
+    password: undefined,
+    projectList2: []
+  });
+  refereeFormRef.value?.resetFields();
+};
+
 const cancel = () => {
   dialog.visible = false;
 };
 
-const submitForm = () => {
-  refereeFormRef.value.validate(async (valid: boolean) => {
-    if (valid) {
-      try {
-        // 在 form 中添加 eventId
-        const formData = { ...form, eventId: eventId.value };
-        const refereeResult = await addGameReferee(formData);
+const submitForm = async () => {
+  const valid = await refereeFormRef.value?.validate();
+  if (valid) {
+    try {
+      const submitForm: any = { ...form, eventId: eventId.value };
+      
+      if (form.refereeId) {
+        // 编辑模式
+        await updateGameReferee(submitForm);
+        ElMessage.success('修改成功');
+      } else {
+        // 添加模式
+        const refereeResult = await addGameReferee(submitForm);
         
         // 获取新添加的裁判ID
         const newRefereeId = refereeResult.data?.refereeId || null;
         
         // 更新所选项目的裁判组字段
-        if (newRefereeId && form.projectIds.length > 0) {
-          for (const projectId of form.projectIds) {
+        if (newRefereeId && form.projectList2.length > 0) {
+          for (const projectId of form.projectList2) {
             // 获取当前项目信息
             const projectRes = await getGameEventProject(projectId);
             
@@ -140,13 +191,14 @@ const submitForm = () => {
         }
         
         ElMessage.success('添加成功');
-        dialog.visible = false;
-      } catch (error) {
-        console.error('添加裁判失败:', error);
-        ElMessage.error('添加失败');
       }
+      
+      dialog.visible = false;
+    } catch (error) {
+      console.error('操作失败:', error);
+      ElMessage.error('操作失败');
     }
-  });
+  }
 };
 
 defineExpose({ openDialog });

+ 2 - 1
src/views/system/gameEvent/detail.vue

@@ -125,7 +125,8 @@ const eventData = ref<GameEventVO>({
   unit: '',
   isDefault: '',
   status: '',
-  remark: ''
+  remark: '',
+  limitApplication: 0
 });
 
 // 项目数据

+ 1 - 3
src/views/system/gameEvent/index.vue

@@ -52,7 +52,7 @@
           <!-- 新增的操作按钮,基于默认赛事 -->
           <el-col :span="1.5">
             <el-button type="warning" plain icon="Download" @click="handleDownloadTemplateDefault" v-hasPermi="['system:gameEvent:download']"
-              >下载模板
+              >下载报名表
             </el-button>
           </el-col>
           <el-col :span="1.5">
@@ -404,8 +404,6 @@ import { useRouter } from 'vue-router';
 import { ref } from 'vue';
 import RefereeForm from '@/views/system/gameEvent/RefereeForm.vue';
 import BibViewerDialog from '@/views/system/gameEvent/components/bibViewerDialog.vue';
-import RankingBoard from './RankingBoard.vue';
-import Editor from '@/components/Editor/index.vue';
 import { useTagsViewStore } from '@/store/modules/tagsView';
 import { globalHeaders } from '@/utils/request';
 import { useGameEventStore } from '@/store/modules/gameEvent';