Ver código fonte

Merge branch 'dev' into wk-dev

wenkai 2 semanas atrás
pai
commit
5d68ace30f

+ 14 - 4
src/api/system/gameEventConfigType/types.ts

@@ -1,4 +1,9 @@
 export interface GameEventConfigTypeVO {
+  /**
+   * 主键
+   */
+  typeId: string | number;
+
   /**
    * 类型编码
    */
@@ -37,6 +42,11 @@ export interface GameEventConfigTypeVO {
 }
 
 export interface GameEventConfigTypeForm extends BaseEntity {
+  /**
+   * 主键
+   */
+  typeId?: string | number;
+
   /**
    * 类型编码
    */
@@ -106,10 +116,10 @@ export interface GameEventConfigTypeQuery extends PageQuery {
    */
   status?: string;
 
-    /**
-     * 日期范围参数
-     */
-    params?: any;
+  /**
+   * 日期范围参数
+   */
+  params?: any;
 }
 
 

+ 2 - 2
src/components/ImageOrUrlInput/index.vue

@@ -37,7 +37,7 @@
         </div>
       </el-tab-pane>
       
-             <el-tab-pane label="输入链接" name="url">
+      <el-tab-pane label="输入链接" name="url">
          <div class="url-container">
            <el-input
              v-model="urlValue"
@@ -52,7 +52,7 @@
              <el-alert title="请输入有效的链接地址" type="warning" :closable="false" />
            </div>
          </div>
-       </el-tab-pane>
+      </el-tab-pane>
     </el-tabs>
 
     <el-dialog v-model="dialogVisible" title="预览" width="800px" append-to-body>

+ 10 - 3
src/components/ImageUploadCropper/index.vue

@@ -253,8 +253,15 @@ watch(
       if (Array.isArray(val)) {
         list = val as OssVO[];
       } else {
-        const res = await listByIds(val);
-        list = res.data;
+        // 判断是否为URL路径(包含http/https协议或相对路径)
+        if (typeof val === 'string' && (val.startsWith('http') || val.startsWith('/'))) {
+          // 直接使用URL路径作为图片显示
+          list = [{ url: val } as OssVO];
+        } else {
+          // 原有逻辑,调用API获取信息
+          const res = await listByIds(val);
+          list = res.data;
+        }
       }
       // 然后将数组转为对象数组
       fileList.value = list.map((item) => {
@@ -264,7 +271,7 @@ watch(
           itemData = { name: item, url: item };
         } else {
           // 此处name使用ossId 防止删除出现重名
-          itemData = { name: item.ossId, url: item.url, ossId: item.ossId };
+          itemData = { name: item.ossId || item.url, url: item.url, ossId: item.ossId };
         }
         return itemData;
       });

+ 15 - 8
src/views/system/gameEvent/edit.vue

@@ -189,7 +189,7 @@
                   <el-input v-model="scope.row.siteLink" placeholder="请输入链接" />
                 </template>
               </el-table-column>
-              <el-table-column label="排序" prop="orderNum" width="100">
+              <el-table-column label="排序" prop="orderNum" width="180">
                 <template #default="scope">
                   <el-input-number v-model="scope.row.orderNum" :min="1" :max="999" />
                 </template>
@@ -212,12 +212,16 @@
             </div>
 
             <el-table :data="projectItems" border style="width: 100%">
-              <el-table-column label="类型" prop="projectType" width="100">
+              <el-table-column label="項目类型" prop="projectType" width="180">
                 <template #default="scope">
-                  <el-radio-group v-model="scope.row.projectType">
-                    <el-radio value="0">个人</el-radio>
-                    <el-radio value="1">团体</el-radio>
-                  </el-radio-group>
+                  <el-select v-model="scope.row.projectType" placeholder="请选择項目类型" style="width: 100%">
+                    <el-option
+                      v-for="dict in game_project_type"
+                      :key="dict.value"
+                      :label="dict.label"
+                      :value="dict.value"
+                    />
+                  </el-select>
                 </template>
               </el-table-column>
               <el-table-column label="项目名称" prop="projectName" width="200">
@@ -400,8 +404,8 @@ import { GameEventProjectForm, GameEventProjectVO } from '@/api/system/gameEvent
 const route = useRoute();
 const router = useRouter();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { game_event_type, game_event_purpose, game_event_status, sys_yes_no } = toRefs<any>(
-  proxy?.useDict('game_event_type', 'game_event_purpose', 'game_event_status', 'sys_yes_no')
+const { game_event_type, game_event_purpose, game_event_status, sys_yes_no,game_project_type } = toRefs<any>(
+  proxy?.useDict('game_event_type', 'game_event_purpose', 'game_event_status', 'sys_yes_no','game_project_type')
 );
 
 // 页面状态
@@ -964,6 +968,9 @@ const saveEvent = async () => {
     await saveProjectData(savedEventId);
     
     proxy?.$modal.msgSuccess('保存成功');
+    
+    // 保存成功后,设置一个标识,表示需要刷新列表数据
+    sessionStorage.setItem('needRefreshGameEventList', 'true');
     goBack();
 
   } catch (error) {

+ 13 - 89
src/views/system/gameEvent/index.vue

@@ -160,95 +160,6 @@
 
       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
-    <!-- 添加或修改赛事基本信息对话框 -->
-    <!-- <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-      <el-form ref="gameEventFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="赛事编号" prop="eventCode">
-          <el-input v-model="form.eventCode" placeholder="请输入赛事编号" />
-        </el-form-item>
-        <el-form-item label="赛事名称" prop="eventName">
-          <el-input v-model="form.eventName" placeholder="请输入赛事名称" />
-        </el-form-item>
-        <el-form-item label="赛事类型" prop="eventType">
-          <el-select v-model="form.eventType" placeholder="请选择赛事类型">
-            <el-option
-                v-for="dict in game_event_type"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="举办地点" prop="location">
-          <el-input v-model="form.location" placeholder="请输入举办地点" />
-        </el-form-item>
-        <el-form-item label="用途" prop="purpose">
-          <el-select v-model="form.purpose" placeholder="请选择用途">
-            <el-option
-                v-for="dict in game_event_purpose"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="开始时间" prop="startTime">
-          <el-date-picker clearable
-            v-model="form.startTime"
-            type="datetime"
-            value-format="YYYY-MM-DD HH:mm:ss"
-            placeholder="请选择开始时间">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="结束时间" prop="endTime">
-          <el-date-picker clearable
-            v-model="form.endTime"
-            type="datetime"
-            value-format="YYYY-MM-DD HH:mm:ss"
-            placeholder="请选择结束时间">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="赛事链接" prop="eventUrl">
-          <image-upload v-model="form.eventUrl"/>
-        </el-form-item>
-        <el-form-item label="裁判码" prop="refereeUrl">
-          <image-upload v-model="form.refereeUrl"/>
-        </el-form-item>
-        <el-form-item label="签到码" prop="registerUrl">
-          <image-upload v-model="form.registerUrl"/>
-        </el-form-item>
-        <el-form-item label="举办单位" prop="unit">
-          <el-input v-model="form.unit" placeholder="请输入举办单位" />
-        </el-form-item>
-        <el-form-item label="是否默认赛事" prop="isDefault">
-          <el-radio-group v-model="form.isDefault">
-            <el-radio
-              v-for="dict in sys_yes_no"
-              :key="dict.value"
-              :value="dict.value"
-            >{{dict.label}}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="状态" prop="status">
-          <el-radio-group v-model="form.status">
-            <el-radio
-              v-for="dict in game_event_status"
-              :key="dict.value"
-              :value="dict.value"
-            >{{dict.label}}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-            <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog> -->
     <!-- 注册 RefereeForm 组件 -->
     <RefereeForm ref="refereeFormRef" />
     <!-- 排行榜对话框 -->
@@ -555,4 +466,17 @@ const openRankingBoard = (eventId: string) => {
 onMounted(() => {
   getList();
 });
+
+// 监听路由变化,当从编辑页返回时检查是否需要刷新列表
+onActivated(() => {
+  // 检查是否有需要刷新的标识
+  const needRefresh = sessionStorage.getItem('needRefreshGameEventList');
+  if (needRefresh === 'true') {
+    // 清除标识
+    sessionStorage.removeItem('needRefreshGameEventList');
+    // 刷新列表数据
+    getList();
+  }
+});
+
 </script>

+ 12 - 6
src/views/system/gameEventConfig/index.vue

@@ -15,7 +15,7 @@
             </el-form-item>
             <el-form-item label="是否启用" prop="isEnabled">
               <el-select v-model="queryParams.isEnabled" placeholder="请选择是否启用" clearable >
-                <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value"/>
+                <el-option v-for="dict in game_yes_no" :key="dict.value" :label="dict.label" :value="dict.value"/>
               </el-select>
             </el-form-item>
             <el-form-item label="状态" prop="status">
@@ -61,7 +61,7 @@
         <el-table-column label="配置描述" align="center" prop="configDesc" />
         <el-table-column label="是否启用" align="center" prop="isEnabled">
           <template #default="scope">
-            <dict-tag :options="sys_yes_no" :value="scope.row.isEnabled"/>
+            <dict-tag :options="game_yes_no" :value="scope.row.isEnabled"/>
           </template>
         </el-table-column>
         <el-table-column label="状态" align="center" prop="status">
@@ -102,7 +102,7 @@
         <el-form-item label="是否启用" prop="isEnabled">
           <el-radio-group v-model="form.isEnabled">
             <el-radio
-              v-for="dict in sys_yes_no"
+              v-for="dict in game_yes_no"
               :key="dict.value"
               :value="dict.value"
             >{{dict.label}}</el-radio>
@@ -136,7 +136,7 @@ import { listGameEventConfig, getGameEventConfig, delGameEventConfig, addGameEve
 import { GameEventConfigVO, GameEventConfigQuery, GameEventConfigForm } from '@/api/system/gameEventConfig/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { game_event_status, sys_yes_no } = toRefs<any>(proxy?.useDict('game_event_status', 'sys_yes_no'));
+const { game_event_status, game_yes_no } = toRefs<any>(proxy?.useDict('game_event_status', 'game_yes_no'));
 
 const gameEventConfigList = ref<GameEventConfigVO[]>([]);
 const buttonLoading = ref(false);
@@ -180,9 +180,15 @@ const data = reactive<PageData<GameEventConfigForm, GameEventConfigQuery>>({
     }
   },
   rules: {
-    configValue: [
-      { required: true, message: "配置值不能为空", trigger: "blur" }
+    eventId: [
+      { required: true, message: "赛事ID不能为空", trigger: "blur" }
     ],
+    configKey: [
+      { required: true, message: "配置键不能为空", trigger: "blur" }
+    ],
+    // configValue: [
+    //   { required: true, message: "配置值不能为空", trigger: "blur" }
+    // ],
     configDesc: [
       { required: true, message: "配置描述不能为空", trigger: "blur" }
     ],

+ 5 - 5
src/views/system/gameEventConfigType/index.vue

@@ -18,7 +18,7 @@
             </el-form-item>
             <el-form-item label="是否启用" prop="isEnabled">
               <el-select v-model="queryParams.isEnabled" placeholder="请选择是否启用" clearable >
-                <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value"/>
+                <el-option v-for="dict in game_yes_no" :key="dict.value" :label="dict.label" :value="dict.value"/>
               </el-select>
             </el-form-item>
             <el-form-item>
@@ -58,10 +58,9 @@
         <el-table-column label="排序字段" align="center" prop="sortField" />
         <el-table-column label="是否启用" align="center" prop="isEnabled">
           <template #default="scope">
-            <dict-tag :options="sys_yes_no" :value="scope.row.isEnabled"/>
+            <dict-tag :options="game_yes_no" :value="scope.row.isEnabled"/>
           </template>
         </el-table-column>
-        <el-table-column label="状态" align="center" prop="status" />
         <el-table-column label="备注" align="center" prop="remark" />
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
@@ -95,7 +94,7 @@
         <el-form-item label="是否启用" prop="isEnabled">
           <el-radio-group v-model="form.isEnabled">
             <el-radio
-              v-for="dict in sys_yes_no"
+              v-for="dict in game_yes_no"
               :key="dict.value"
               :value="dict.value"
             >{{dict.label}}</el-radio>
@@ -120,7 +119,7 @@ import { listGameEventConfigType, getGameEventConfigType, delGameEventConfigType
 import { GameEventConfigTypeVO, GameEventConfigTypeQuery, GameEventConfigTypeForm } from '@/api/system/gameEventConfigType/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_yes_no } = toRefs<any>(proxy?.useDict('sys_yes_no'));
+const { game_yes_no } = toRefs<any>(proxy?.useDict('game_yes_no'));
 
 const gameEventConfigTypeList = ref<GameEventConfigTypeVO[]>([]);
 const buttonLoading = ref(false);
@@ -140,6 +139,7 @@ const dialog = reactive<DialogOption>({
 });
 
 const initFormData: GameEventConfigTypeForm = {
+  typeId: undefined,
   typeCode: undefined,
   typeName: undefined,
   typeDesc: undefined,

+ 87 - 10
src/views/system/gameEventSchedule/index.vue

@@ -49,15 +49,15 @@
           <el-tab-pane
             v-for="group in projectGroups"
             :key="group.type"
-            :label="`${group.type}项目 (${group.projects.length})`"
+            :label="`${group.type} (${group.projects.length})`"
             :name="group.type"
           >
             <el-table :data="group.projects" border class="mb-4">
               <el-table-column label="项目名称" prop="projectName" width="150" />
-              <el-table-column label="项目组别" prop="groupType" width="120" />
+              <!-- <el-table-column label="项目组别" prop="groupType" width="120" /> -->
               <el-table-column label="项目类型" width="100">
                 <template #default="scope">
-                  {{ scope.row.projectType === '0' ? '个人' : '团体' }}
+                  <dict-tag :options="game_project_type" :value="scope.row.projectType || ''" />
                 </template>
               </el-table-column>
               <el-table-column label="比赛日期" width="180">
@@ -99,7 +99,7 @@
                   <el-input v-model="scope.row.location" placeholder="输入比赛场地" />
                 </template>
               </el-table-column>
-              <el-table-column label="分组数" width="100">
+              <el-table-column label="分组数" width="150">
                 <template #default="scope">
                   <el-input-number
                     v-model="scope.row.groupNum"
@@ -110,7 +110,7 @@
                   />
                 </template>
               </el-table-column>
-              <el-table-column label="每组人数" width="100">
+              <el-table-column label="每组人数" width="150">
                 <template #default="scope">
                   <el-input-number
                     v-model="scope.row.participateNum"
@@ -146,13 +146,25 @@
           <el-table-column label="项目名称" prop="projectName" width="150" />
           <el-table-column label="项目类型" width="100">
             <template #default="scope">
-              {{ scope.row.projectType === '0' ? '个人' : '团体' }}
+              <dict-tag :options="game_project_type" :value="scope.row.projectType || ''" />
             </template>
           </el-table-column>
-          <el-table-column label="项目组别" prop="groupType" width="120" />
+          <!-- <el-table-column label="项目组别" prop="groupType" width="120" /> -->
           <el-table-column label="比赛场地" prop="location" width="120" />
           <el-table-column label="分组数" prop="groupNum" width="80" />
           <el-table-column label="每组人数" prop="participateNum" width="100" />
+          <el-table-column label="操作" width="100">
+            <template #default="scope">
+              <el-button 
+                type="danger" 
+                size="small" 
+                @click="deleteSchedule(scope.row)"
+                v-hasPermi="['system:gameeventproject:remove']"
+              >
+                删除
+              </el-button>
+            </template>
+          </el-table-column>
         </el-table>
       </el-card>
     </el-card>
@@ -167,6 +179,10 @@ import { GameEventVO } from '@/api/system/gameEvent/types'
 import { GameEventProjectVO } from '@/api/system/gameEventProject/types'
 import { parseTime } from '@/utils/ruoyi'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import DictTag from '@/components/DictTag/index.vue'
+
+const { proxy } = getCurrentInstance() as any
+const { game_project_type } = toRefs<any>(proxy?.useDict('game_project_type'));
 
 // 赛事列表
 const eventList = ref<GameEventVO[]>([])
@@ -189,6 +205,13 @@ const loadEventList = async () => {
       pageSize: 1000
     })
     eventList.value = res.rows
+    
+    // 如果赛事列表不为空,默认选择第一条赛事
+    if (eventList.value.length > 0 && !selectedEventId.value) {
+      selectedEventId.value = eventList.value[0].eventId
+      // 自动加载第一条赛事的数据
+      await loadEventData(selectedEventId.value)
+    }
   } catch (error) {
     ElMessage.error('加载赛事列表失败')
   }
@@ -202,8 +225,8 @@ const loadEventData = async (eventId: string | number) => {
     // 获取赛事基本信息
     const eventRes = await listGameEvent({
       eventId: eventId,
-      pageNum: 0,
-      pageSize: 0
+      pageNum: 1,
+      pageSize: 1000
     })
     currentEvent.value = eventRes.rows[0] || ({} as GameEventVO)
     
@@ -217,7 +240,9 @@ const loadEventData = async (eventId: string | number) => {
     // 按项目类型分组
     const groups: { [key: string]: GameEventProjectVO[] } = {}
     projectRes.rows.forEach(project => {
-      const type = project.projectType === '0' ? '个人' : '团体'
+      // 使用字典标签作为分组键
+      const projectTypeDict = game_project_type.value.find((dict: any) => dict.value === project.projectType)
+      const type = projectTypeDict ? projectTypeDict.label : '未知类型'
       if (!groups[type]) {
         groups[type] = []
       }
@@ -321,6 +346,58 @@ const saveSchedule = async () => {
   }
 }
 
+// 删除日程安排
+const deleteSchedule = async (project: GameEventProjectVO) => {
+  try {
+    await ElMessageBox.confirm(
+      `确定要删除项目 "${project.projectName}" 的日程安排吗?`,
+      '删除确认',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }
+    )
+    
+    // 清除该项目的时间安排
+    await updateGameEventProject({
+      projectId: project.projectId,
+      startTime: null,
+      endTime: null,
+      location: project.location,
+      groupNum: project.groupNum,
+      participateNum: project.participateNum,
+      //其他字段
+      eventId: selectedEventId.value,
+      projectName: project.projectName,
+      projectType: project.projectType,
+      groupType: project.groupType,
+    } as any)
+    
+    // 更新本地数据
+    const group = projectGroups.value.find(g => {
+      const projectTypeDict = game_project_type.value.find((dict: any) => dict.value === project.projectType)
+      const type = projectTypeDict ? projectTypeDict.label : '未知类型'
+      return g.type === type
+    })
+    if (group) {
+      const projectItem = group.projects.find(p => p.projectId === project.projectId)
+      if (projectItem) {
+        projectItem.scheduleDate = ''
+        projectItem.startTime = ''
+        projectItem.endTime = ''
+      }
+    }
+    
+    ElMessage.success('日程安排删除成功')
+    updateScheduleData()
+  } catch (error) {
+    if (error !== 'cancel') {
+      ElMessage.error('删除日程安排失败')
+    }
+  }
+}
+
 // 导出日程表
 const exportSchedule = () => {
   if (scheduleData.value.length === 0) {