wengan01 1 mês atrás
pai
commit
30a881e62d

+ 80 - 10
src/views/system/physical/participants/index.vue

@@ -233,11 +233,61 @@ const { queryParams, form, rules } = toRefs(data);
 
 /** 查询线下用户报名列表 */
 const getList = async () => {
+  console.log('=== getList 开始 ===');
+  console.log('当前 loading:', loading.value);
+  console.log('查询参数:', queryParams.value);
+  
   loading.value = true;
-  const res = await listParticipants(queryParams.value);
-  participantsList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
+  console.log('设置 loading 为 true:', loading.value);
+  
+  try {
+    console.log('准备调用 API...');
+    const res = await listParticipants(queryParams.value);
+    console.log('API 返回成功');
+    console.log('完整 API 响应:', res);
+    console.log('响应码:', res.code);
+    console.log('数据:', res.data);
+    
+    // 检查响应结构
+    if (res.code === 200) {
+      // 如果 data 是数组,直接使用;如果是对象且有 rows 属性,使用 rows
+      if (Array.isArray(res.data)) {
+        participantsList.value = res.data;
+        total.value = res.total || res.data.length;
+        console.log('使用 Array.isArray(res.data),列表长度:', res.data.length);
+      } else if (res.data && res.data.rows) {
+        participantsList.value = res.data.rows;
+        total.value = res.data.total || 0;
+        console.log('使用 res.data.rows,列表长度:', res.data.rows.length);
+      } else if (res.rows) {
+        // 兼容旧格式
+        participantsList.value = res.rows;
+        total.value = res.total || 0;
+        console.log('使用 res.rows,列表长度:', res.rows.length);
+      } else {
+        console.warn('未知的数据结构:', res);
+        participantsList.value = [];
+        total.value = 0;
+      }
+    } else {
+      console.error('响应码不是 200:', res.code, res.msg);
+      proxy?.$modal.msgError(res.msg || '获取数据失败');
+      participantsList.value = [];
+      total.value = 0;
+    }
+  } catch (error: any) {
+    console.error('捕获到异常:', error);
+    console.error('错误信息:', error.message);
+    console.error('错误堆栈:', error.stack);
+    proxy?.$modal.msgError(error.message || '获取数据失败,请检查网络连接或权限');
+    participantsList.value = [];
+    total.value = 0;
+  } finally {
+    console.log('进入 finally 块');
+    loading.value = false;
+    console.log('设置 loading 为 false:', loading.value);
+    console.log('=== getList 结束 ===');
+  }
 };
 
 /** 取消按钮 */
@@ -335,10 +385,18 @@ const submitForm = () => {
 /** 删除按钮操作 */
 const handleDelete = async (row?: ParticipantsVO) => {
   const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除线下用户报名编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-  await delParticipants(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
+  await proxy?.$modal.confirm('是否确认删除线下用户报名编号为"' + _ids + '"的数据项?');
+  loading.value = true;
+  try {
+    await delParticipants(_ids);
+    proxy?.$modal.msgSuccess('删除成功');
+    await getList();
+  } catch (error) {
+    console.error('删除失败:', error);
+    proxy?.$modal.msgError('删除失败');
+  } finally {
+    loading.value = false;
+  }
 };
 
 /** 导出按钮操作 */
@@ -357,7 +415,7 @@ watch(
   () => route.query,
   (newQuery) => {
     console.log('路由参数变化:', newQuery);
-    if (newQuery.tournamentId) {
+    if (newQuery && newQuery.tournamentId) {
       // 手动重置所有查询参数(不调用 resetQuery,因为它会自动 getList)
       queryParams.value.tournamentId = '';
       queryParams.value.name = '';
@@ -370,6 +428,18 @@ watch(
       getList();
     }
   },
-  { immediate: true }  // 立即执行一次
+  { immediate: false }  // 改为 false,不在组件挂载时立即执行
 );
+
+// 组件挂载时的处理
+onMounted(() => {
+  console.log('组件已挂载');
+  // 检查是否有路由参数
+  if (route.query.tournamentId) {
+    console.log('检测到路由参数 tournamentId:', route.query.tournamentId);
+    queryParams.value.tournamentId = route.query.tournamentId;
+  }
+  // 调用 getList 加载数据
+  getList();
+});
 </script>

+ 67 - 211
src/views/system/physical/tournaments/index.vue

@@ -194,84 +194,30 @@
         </el-form-item>-->
         <!-- 比赛图标 -->
         <el-form-item label="比赛图标" prop="competitionIcon">
-          <div class="upload-container">
-            <el-upload
-              class="upload-icon"
-              action="#"
-              :on-change="handleIconChange"
-              :on-remove="handleIconRemove"
-              :file-list="fileList"
-              :auto-upload="false"
-              :limit="1"
-              accept="image/*"
-              :disabled="dialog.mode === 'view'"
-            >
-              <template #trigger>
-                <el-button type="primary" :disabled="dialog.mode === 'view'">点击选择图标</el-button>
-              </template>
-
-              <!-- 预览图区域 -->
-              <template #default>
-                <div class="preview-area" @click="handlePreviewClick">
-                  <!-- 只有当 iconPreviewUrl 或 competitionIcon 存在时才显示 img -->
-                  <img
-                    v-if="iconPreviewUrl || competitionIcon"
-                    :src="iconPreviewUrl || competitionIcon"
-                    alt="预览图"
-                    style="max-width: 100px; max-height: 100px; margin-top: 10px; cursor: pointer"
-                  />
-                  <!-- 可选:无图时显示提示文字 -->
-                  <div v-else style="margin-top: 10px; color: #999"></div>
-                </div>
-              </template>
-
-              <template #tip>
-                <div class="el-upload__tip">
-                  <span v-if="fileList.length > 0">当前已选文件:{{ fileList[0].name }}</span>
-                </div>
-              </template>
-            </el-upload>
+          <div class="icon-select-container">
+            <el-button type="primary" @click="openIconSelectDialog('icon')" :disabled="dialog.mode === 'view'">点击选择图标</el-button>
+            <div v-if="form.competitionIcon" class="preview-area" @click="handlePreviewIconClick">
+              <img
+                :src="form.competitionIcon"
+                alt="预览图"
+                style="max-width: 100px; max-height: 100px; margin-top: 10px; cursor: pointer; border-radius: 4px"
+              />
+            </div>
+            <div v-else style="margin-top: 10px; color: #999">未选择图标</div>
           </div>
         </el-form-item>
-        <!-- 比赛图标 -->
+        <!-- 比赛背景 -->
         <el-form-item label="比赛背景" prop="competitionBg">
-          <div class="upload-container">
-            <el-upload
-              class="upload-icon"
-              action="#"
-              :on-change="handleIconChange2"
-              :on-remove="handleIconRemove2"
-              :file-list="fileList2"
-              :auto-upload="false"
-              :limit="1"
-              accept="image/*"
-              :disabled="dialog.mode === 'view'"
-            >
-              <template #trigger>
-                <el-button type="primary" :disabled="dialog.mode === 'view'">点击选择背景</el-button>
-              </template>
-
-              <!-- 预览图区域 -->
-              <template #default>
-                <div class="preview-area" @click="handlePreviewClick2">
-                  <!-- 只有当 iconPreviewUrl 或 competitionIcon 存在时才显示 img -->
-                  <img
-                    v-if="iconPreviewUrl2 || competitionBg"
-                    :src="iconPreviewUrl2 || competitionBg"
-                    alt="预览图"
-                    style="max-width: 100px; max-height: 100px; margin-top: 10px; cursor: pointer"
-                  />
-                  <!-- 可选:无图时显示提示文字 -->
-                  <div v-else style="margin-top: 10px; color: #999"></div>
-                </div>
-              </template>
-
-              <template #tip>
-                <div class="el-upload__tip">
-                  <span v-if="fileList2.length > 0">当前已选文件:{{ fileList2[0].name }}</span>
-                </div>
-              </template>
-            </el-upload>
+          <div class="icon-select-container">
+            <el-button type="primary" @click="openIconSelectDialog('background')" :disabled="dialog.mode === 'view'">点击选择背景</el-button>
+            <div v-if="form.competitionBg" class="preview-area" @click="handlePreviewBgClick">
+              <img
+                :src="form.competitionBg"
+                alt="预览图"
+                style="max-width: 100px; max-height: 100px; margin-top: 10px; cursor: pointer; border-radius: 4px"
+              />
+            </div>
+            <div v-else style="margin-top: 10px; color: #999">未选择背景</div>
           </div>
         </el-form-item>
         <el-form-item label="报名时间" prop="startTime">
@@ -485,13 +431,18 @@
       <!-- 使用 component 动态加载目标组件 -->
       <levels-index :blind-structure-id="dialogParams.blindStructureId" :name="dialogParams.name" />
     </el-dialog>
-    <!-- 预览弹窗 -->
-    <el-dialog v-model="dialogVisible" title="图片预览" width="50%">
-      <img :src="previewSrc || iconPreviewUrl || competitionIcon" alt="预览图片" style="max-width: 100%; max-height: 80vh" />
-    </el-dialog>
-    <el-dialog v-model="dialogVisible2" title="图片预览" width="50%">
-      <img :src="previewSrc2 || iconPreviewUrl2 || competitionBg" alt="预览图片" style="max-width: 100%; max-height: 80vh" />
+    <!-- 图片预览弹窗 -->
+    <el-dialog v-model="previewDialogVisible" title="图片预览" width="50%">
+      <img :src="previewDialogSrc" alt="预览图片" style="max-width: 100%; max-height: 80vh" />
     </el-dialog>
+    <!-- 图片库选择组件 -->
+    <TournamentImageSelect
+      v-model="imageSelectVisible"
+      :default-type="imageSelectType"
+      :default-scene="'online'"
+      @confirm="handleImageSelectConfirm"
+      @cancel="handleImageSelectCancel"
+    />
   </div>
 </template>
 
@@ -509,7 +460,6 @@ import { TournamentsVO, TournamentsQuery, TournamentsForm } from '@/api/system/p
 import { selectItemsSelList, selectXianXiaItemsSelList } from '@/api/system/business/items';
 import { selectPhysicalBlingStructuresInfo } from '@/api/system/physical/blindStructures';
 import { selectPhysicalBlindLevelsById } from '@/api/system/physical/blindLevels';
-import { uploadTournament } from '@/api/system/business/tournaments';
 import { selectPhysicalLeagueTournamentSelList } from '@/api/system/physical/leagueTournament';
 import { selectPhysicalJudgeSelList } from '@/api/system/physical/judge';
 import { selectCompetitionZoneSelList } from '@/api/system/physical/competitionZone';
@@ -777,14 +727,6 @@ const getList = async () => {
 const cancel = () => {
   reset();
   resetFormPrize();
-  fileList.value = [];
-  fileList2.value = [];
-  // 清除预览图和临时链接
-  iconPreviewUrl.value = '';
-  competitionIcon.value = ''; // 如果需要清除后台加载的图标,可以在这里设置为空字符串
-
-  iconPreviewUrl2.value = '';
-  competitionBg.value = '';
   dialog.visible = false;
 };
 
@@ -825,14 +767,6 @@ const handleSelectionChange = (selection: TournamentsVO[]) => {
 const handleAdd = () => {
   reset();
   resetFormPrize();
-  fileList.value = [];
-  fileList2.value = [];
-  // 清除预览图和临时链接
-  iconPreviewUrl.value = '';
-  competitionIcon.value = ''; // 如果需要清除后台加载的图标,可以在这里设置为空字符串
-  iconPreviewUrl2.value = '';
-  competitionBg.value = '';
-
   form.value.leagueTournamentId = queryParams.value.leagueTournamentId ? Number(queryParams.value.leagueTournamentId) : undefined;
   dialog.visible = true;
   dialog.title = '创建比赛';
@@ -854,8 +788,7 @@ const handleUpdate = async (row?: TournamentsVO, mode: 'edit' | 'view' = 'edit')
   form.value.gameType = String(res.data.gameType); // 转为字符串
   form.value.gameVariant = String(res.data.gameVariant); // 转为字符串
   form.value.qualifierType = String(res.data.qualifierType);
-  competitionIcon.value = res.data.competitionIcon;
-  competitionBg.value = res.data.competitionBg;
+  // competitionIcon 和 competitionBg 已通过 Object.assign 自动赋值到 form
   // 处理报名条件数据
   const conditionItems = res.data.itemsConditionList || [];
   if (conditionItems.length > 0) {
@@ -1190,122 +1123,46 @@ const removeReward = (index: number) => {
 const getRewardTooltipContent = (rewards: any[]) => {
   return rewards.map((prize) => `第${prize.ranking}名:${prize.quantity} ${prize.itemsName}`).join('\n');
 };
-//预览图标需要
-const iconPreviewUrl = ref('');
-const competitionIcon = ref('');
-const fileList = ref([]);
-const dialogVisible = ref(false);
-const previewSrc = ref('');
-const handleIconChange = async (file) => {
-  const index = fileList.value.findIndex((f) => f.uid === file.uid);
-  fileList.value = [];
-
-  if (file.raw) {
-    iconPreviewUrl.value = URL.createObjectURL(file.raw);
-  }
-
-  if (index === -1) {
-    // 如果文件不在列表中,则添加进去
-    fileList.value.push(file);
-  }
-
-  try {
-    const rawFile = file.raw;
-    const res = await uploadTournament(rawFile);
-    if (res.code === 200) {
-      // 更新文件状态为成功
-      fileList.value[index] = {
-        ...file,
-        status: 'success',
-        response: res.data.url
-      };
-      data.form.competitionIcon = fileList.value[index].response;
-      iconPreviewUrl.value = fileList.value[index].response;
-      ElMessage.success('上传成功');
-    } else {
-      throw new Error(res.msg);
-    }
-  } catch (error) {
-    // 更新文件状态为失败
-    fileList.value[index] = {
-      ...file,
-      status: 'fail',
-      error: '上传失败'
-    };
-    ElMessage.error('上传失败,请重试');
-  }
-};
-// 删除文件处理函数
-const handleIconRemove = (file, updatedFileList) => {
-  fileList.value = updatedFileList;
-  // 清除预览图和临时链接
-  iconPreviewUrl.value = '';
-  competitionIcon.value = ''; // 如果需要清除后台加载的图标,可以在这里设置为空字符串
+// 图片库选择相关变量
+const imageSelectVisible = ref(false);
+const imageSelectType = ref<'icon' | 'background'>('icon');
+const previewDialogVisible = ref(false);
+const previewDialogSrc = ref('');
+
+// 打开图片选择对话框
+const openIconSelectDialog = (type: 'icon' | 'background') => {
+  imageSelectType.value = type;
+  imageSelectVisible.value = true;
 };
-// 点击预览图触发放大
-const handlePreviewClick = () => {
-  const currentSrc = iconPreviewUrl.value || competitionIcon.value;
-  if (currentSrc) {
-    dialogVisible.value = true;
+
+// 图片选择确认回调
+const handleImageSelectConfirm = (url: string) => {
+  if (imageSelectType.value === 'icon') {
+    form.value.competitionIcon = url;
+  } else {
+    form.value.competitionBg = url;
   }
+  imageSelectVisible.value = false;
 };
-//预览图标需要
-const iconPreviewUrl2 = ref('');
-const competitionBg = ref('');
-const fileList2 = ref([]);
-const dialogVisible2 = ref(false);
-const previewSrc2 = ref('');
-const handleIconChange2 = async (file) => {
-  const index = fileList2.value.findIndex((f) => f.uid === file.uid);
-  fileList2.value = [];
-
-  if (file.raw) {
-    iconPreviewUrl2.value = URL.createObjectURL(file.raw);
-  }
 
-  if (index === -1) {
-    // 如果文件不在列表中,则添加进去
-    fileList2.value.push(file);
-  }
+// 图片选择取消回调
+const handleImageSelectCancel = () => {
+  imageSelectVisible.value = false;
+};
 
-  try {
-    const rawFile = file.raw;
-    const res = await uploadTournament(rawFile);
-    if (res.code === 200) {
-      // 更新文件状态为成功
-      fileList2.value[index] = {
-        ...file,
-        status: 'success',
-        response: res.data.url
-      };
-      data.form.competitionBg = fileList2.value[index].response;
-      iconPreviewUrl2.value = fileList2.value[index].response;
-      ElMessage.success('上传成功');
-    } else {
-      throw new Error(res.msg);
-    }
-  } catch (error) {
-    // 更新文件状态为失败
-    fileList2.value[index] = {
-      ...file,
-      status: 'fail',
-      error: '上传失败'
-    };
-    ElMessage.error('上传失败,请重试');
+// 预览图标点击
+const handlePreviewIconClick = () => {
+  if (form.value.competitionIcon) {
+    previewDialogSrc.value = form.value.competitionIcon;
+    previewDialogVisible.value = true;
   }
 };
-// 删除文件处理函数
-const handleIconRemove2 = (file, updatedFileList) => {
-  fileList2.value = updatedFileList;
-  // 清除预览图和临时链接
-  iconPreviewUrl2.value = '';
-  competitionBg.value = ''; // 如果需要清除后台加载的图标,可以在这里设置为空字符串
-};
-// 点击预览图触发放大
-const handlePreviewClick2 = () => {
-  const currentSrc = iconPreviewUrl2.value || competitionBg.value;
-  if (currentSrc) {
-    dialogVisible2.value = true;
+
+// 预览背景点击
+const handlePreviewBgClick = () => {
+  if (form.value.competitionBg) {
+    previewDialogSrc.value = form.value.competitionBg;
+    previewDialogVisible.value = true;
   }
 };
 /** 修改按钮操作 */
@@ -1326,8 +1183,7 @@ const handleCopy = async (row?: TournamentsVO) => {
   form.value.delayCardNum = res.data.delayCardNum;
 
   form.value.gameVariant = String(res.data.gameVariant); // 转为字符串
-  competitionIcon.value = res.data.competitionIcon;
-  competitionBg.value = res.data.competitionBg;
+  // competitionIcon 和 competitionBg 已通过 Object.assign 自动赋值到 form
   // 处理报名条件数据
   const conditionItems = res.data.itemsConditionList || [];
   if (conditionItems.length > 0) {

+ 1 - 2
src/views/system/physical/videoContent/index.vue

@@ -508,8 +508,7 @@ const handleUpdate = async (row?: VideoContentVO) => {
   const _id = row?.id || ids.value[0];
   const res = await getVideoContent(_id);
   Object.assign(form.value, res.data);
-  // ✅ 核心原则1:修改页面打开时设置视频URL
-  ossVideoUrlPreviewUrl.value = String(res.data?.videoTempUrl || res.data?.ossVideoUrl || '');
+  ossVideoUrlPreviewUrl.value = String(res.data?.ossVideoUrl || '');
 
   if (res.data.videoCoverUrl) {
     videoCoverUrlFileList.value = [{ name: '已上传封面图', url: res.data.videoCoverUrl, status: 'success' }];

+ 1 - 1
vite.config.ts

@@ -24,7 +24,7 @@ export default defineConfig(({ mode, command }) => {
       open: true,
       proxy: {
         [env.VITE_APP_BASE_API]: {
-          target: 'http://localhost:16103',
+          target: 'http://localhost:15103',
           changeOrigin: true,
           ws: true,
           rewrite: (path) => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')