Procházet zdrojové kódy

refactor(video): 优化视频内容组件代码结构和功能实现

- 调整按钮标签的HTML结构以改善代码可读性
- 优化表格列中视频时长显示的条件渲染逻辑
- 修复操作下拉菜单样式属性的语法问题
- 改进视频预览和封面上传组件的布局结构
- 简化表单项提示文本的显示方式
- 移除多余的分号和括号以优化导入语句
- 修复视频数据有效性检查中的类型转换问题
- 简化数组映射函数的箭头函数语法
- 优化确认对话框的参数传递方式
- 改进错误消息处理的条件判断逻辑
- 修复服务标签选项加载的数据结构处理
- 添加服务标签名称字段到视频内容类型定义
fugui před 5 dny
rodič
revize
e34c4ea951

+ 1 - 1
src/api/system/physical/videoContent/types.ts

@@ -78,7 +78,7 @@ export interface VideoContentForm extends BaseEntity {
    * 视频文件名
    */
   videoFileName?: string;
-
+  serviceTagName?: string;
   /**
    * 视频标题
    */

+ 62 - 48
src/views/system/physical/videoContent/index.vue

@@ -29,13 +29,19 @@
             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['physical:videoContent:add']">新增</el-button>
           </el-col>
           <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['physical:videoContent:edit']">修改</el-button>
+            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['physical:videoContent:edit']"
+              >修改</el-button
+            >
           </el-col>
           <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['physical:videoContent:remove']">删除</el-button>
+            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['physical:videoContent:remove']"
+              >删除</el-button
+            >
           </el-col>
           <el-col :span="3">
-            <el-button type="warning" plain icon="Wrench" @click="handleFixAll" v-hasPermi="['physical:videoContent:edit']" :loading="isFixing">修复所有数据</el-button>
+            <el-button type="warning" plain icon="Wrench" @click="handleFixAll" v-hasPermi="['physical:videoContent:edit']" :loading="isFixing"
+              >修复所有数据</el-button
+            >
           </el-col>
           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
         </el-row>
@@ -68,10 +74,18 @@
         <el-table-column label="所属标签" align="center" prop="serviceTagName" />
         <el-table-column label="视频时长(秒)" align="center">
           <template #default="{ row }">
-            <span :class="{ 'text-danger': !isDurationValid(row.durationSeconds) && row.durationSeconds !== null && row.durationSeconds !== undefined }">
+            <span
+              :class="{ 'text-danger': !isDurationValid(row.durationSeconds) && row.durationSeconds !== null && row.durationSeconds !== undefined }"
+            >
               {{ row.durationSeconds ?? '待更新' }}
-              <span v-if="!isDurationValid(row.durationSeconds) && row.durationSeconds !== null && row.durationSeconds !== undefined" style="font-size: 12px; color: #f56c6c;">(异常)</span>
-              <span v-if="row.durationSeconds === null || row.durationSeconds === undefined" style="font-size: 12px; color: #909399;">(待异步更新)</span>
+              <span
+                v-if="!isDurationValid(row.durationSeconds) && row.durationSeconds !== null && row.durationSeconds !== undefined"
+                style="font-size: 12px; color: #f56c6c"
+                >(异常)</span
+              >
+              <span v-if="row.durationSeconds === null || row.durationSeconds === undefined" style="font-size: 12px; color: #909399"
+                >(待异步更新)</span
+              >
             </span>
           </template>
         </el-table-column>
@@ -99,11 +113,11 @@
         <el-table-column label="操作" align="center" width="80">
           <template #default="scope">
             <el-dropdown trigger="click" placement="bottom">
-              <span style="color: #303133; cursor: pointer; font-size: 14px; font-weight: 500;">
-                操作 <span style="font-size: 14px; margin-left: 2px;">▼</span>
+              <span style="color: #303133; cursor: pointer; font-size: 14px; font-weight: 500">
+                操作 <span style="font-size: 14px; margin-left: 2px">▼</span>
               </span>
               <template #dropdown>
-                <el-dropdown-menu style="min-width: 100px; padding: 4px 0;">
+                <el-dropdown-menu style="min-width: 100px; padding: 4px 0">
                   <el-dropdown-item @click="handleUpdate(scope.row)" v-hasPermi="['physical:videoContent:edit']">修改</el-dropdown-item>
                   <el-dropdown-item @click="handleDelete(scope.row)" v-hasPermi="['physical:videoContent:remove']">删除</el-dropdown-item>
                   <el-dropdown-item @click="matchFromBackup(scope.row)" v-hasPermi="['physical:videoContent:edit']">异步获取</el-dropdown-item>
@@ -162,8 +176,9 @@
                         size="small"
                         icon="Delete"
                         @click.stop="handleVideoCoverUrlRemove"
-                        style="position: absolute; top: 5px; right: -50px;"
-                      >删除</el-button>
+                        style="position: absolute; top: 5px; right: -50px"
+                        >删除</el-button
+                      >
                     </div>
                     <div v-else style="margin-top: 10px; color: #999">无图片</div>
                   </template>
@@ -206,27 +221,42 @@
                       </div>
                       <el-progress :percentage="100" :stroke-width="20" status="success" />
                     </div>
-                    <video v-if="ossVideoUrlPreviewUrl" :src="ossVideoUrlPreviewUrl" controls style="max-width: 300px; max-height: 200px; margin-top: 10px" />
+                    <video
+                      v-if="ossVideoUrlPreviewUrl"
+                      :src="ossVideoUrlPreviewUrl"
+                      controls
+                      style="max-width: 300px; max-height: 200px; margin-top: 10px"
+                    />
                   </template>
                   <template v-else>
                     <!-- ✅ 使用 videoTempUrl 作为视频源 -->
-                    <video v-if="ossVideoUrlPreviewUrl" :src="ossVideoUrlPreviewUrl" controls style="max-width: 300px; max-height: 200px; margin-top: 10px" @error="handleVideoError" />
+                    <video
+                      v-if="ossVideoUrlPreviewUrl"
+                      :src="ossVideoUrlPreviewUrl"
+                      controls
+                      style="max-width: 300px; max-height: 200px; margin-top: 10px"
+                      @error="handleVideoError"
+                    />
                     <div v-else style="margin-top: 10px; color: #999">暂无视频</div>
-                    <el-button v-if="ossVideoUrlPreviewUrl || form.ossVideoUrl" type="danger" size="small" icon="Delete" @click="handleOssVideoUrlRemove" style="margin-top: 10px">删除视频</el-button>
+                    <el-button
+                      v-if="ossVideoUrlPreviewUrl || form.ossVideoUrl"
+                      type="danger"
+                      size="small"
+                      icon="Delete"
+                      @click="handleOssVideoUrlRemove"
+                      style="margin-top: 10px"
+                      >删除视频</el-button
+                    >
                   </template>
                 </div>
                 <!-- ✅ 数据状态显示 -->
-                <div v-if="dataStatus" style="margin-top: 10px;">
+                <div v-if="dataStatus" style="margin-top: 10px">
                   <span :class="['status-badge', dataStatus === '正常' ? 'status-normal' : 'status-abnormal']">
                     {{ dataStatus || '异常' }}
                   </span>
-                  <el-button
-                    v-if="dataStatus === '异常'"
-                    type="primary"
-                    size="small"
-                    @click="handleMatchFromBackup"
-                    style="margin-left: 10px;"
-                  >异步获取</el-button>
+                  <el-button v-if="dataStatus === '异常'" type="primary" size="small" @click="handleMatchFromBackup" style="margin-left: 10px"
+                    >异步获取</el-button
+                  >
                 </div>
               </template>
             </el-upload>
@@ -241,9 +271,7 @@
         <el-form-item label="试看时长 (秒)" prop="previewDurationSeconds">
           <div>
             <el-input v-model="form.previewDurationSeconds" placeholder="请输入试看时长 (秒)" style="width: 100%" />
-            <div style="margin-top: 4px; font-size: 12px; color: #999">
-              温馨提示:输入 -1 表示免费观看
-            </div>
+            <div style="margin-top: 4px; font-size: 12px; color: #999">温馨提示:输入 -1 表示免费观看</div>
           </div>
         </el-form-item>
         <el-form-item label="订阅时效(天)" prop="subscriptionValidHours">
@@ -262,9 +290,7 @@
         </el-form-item>
         <el-form-item label="视频时长(秒)" prop="durationSeconds">
           <el-input v-model="form.durationSeconds" placeholder="视频时长(秒)- 由系统自动获取" readonly />
-          <div style="margin-top: 4px; font-size: 12px; color: #909399;">
-            视频时长由系统自动获取
-          </div>
+          <div style="margin-top: 4px; font-size: 12px; color: #909399">视频时长由系统自动获取</div>
         </el-form-item>
       </el-form>
       <template #footer>
@@ -278,9 +304,7 @@
 </template>
 
 <script setup name="VideoContent" lang="ts">
-import { ref, reactive, onMounted, getCurrentInstance, type ComponentInternalInstance, onUnmounted } from 'vue';
-import { ElFormInstance } from 'element-plus';
-import { InfoFilled, Wrench, Refresh, ChevronDown } from '@element-plus/icons-vue';
+import { ref, reactive, onMounted, getCurrentInstance, type ComponentInternalInstance, onUnmounted, toRefs } from 'vue';import { ElFormInstance } from 'element-plus';
 import { ElMessageBox } from 'element-plus';
 import request from '@/utils/request';
 
@@ -385,12 +409,11 @@ const isDurationValid = (duration?: number): boolean => {
 };
 
 const isVideoDataValid = (row: VideoContentVO): boolean => {
-  const hasValidOssId = row.ossId && row.ossId > 0;
+  const hasValidOssId = row.ossId && Number(row.ossId) > 0;
   const hasValidUrl = row.ossVideoUrl && String(row.ossVideoUrl).startsWith('http');
   const hasValidDuration = isDurationValid(row.durationSeconds);
   return hasValidOssId && hasValidUrl && hasValidDuration;
 };
-
 // ============ 轮询功能 ============
 // ✅ 启动轮询
 const startPolling = (videoId: number | string) => {
@@ -471,7 +494,7 @@ const resetQuery = () => {
 };
 
 const handleSelectionChange = (selection: VideoContentVO[]) => {
-  ids.value = selection.map(item => item.id);
+  ids.value = selection.map((item) => item.id);
   single.value = selection.length !== 1;
   multiple.value = !selection.length;
 };
@@ -642,15 +665,7 @@ const matchFromBackup = async (row: VideoContentVO) => {
 
 const handleFixAll = async () => {
   try {
-    await proxy?.$modal.confirm(
-      '确定要批量修复所有缺失URL、时长或oss_id的视频数据吗?',
-      '批量修复',
-      {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }
-    );
+    await proxy?.$modal.confirm('确定要批量修复所有缺失URL、时长或oss_id的视频数据吗?');
 
     isFixing.value = true;
 
@@ -681,7 +696,6 @@ const handleFixAll = async () => {
     isFixing.value = false;
   }
 };
-
 // ============ 文件上传 ============
 const handleOssVideoUrlChange = async (file: any) => {
   ossVideoUrlPreviewUrl.value = '';
@@ -795,9 +809,9 @@ const handleOssVideoUrlChange = async (file: any) => {
     ossVideoUrlPreviewUrl.value = localPreviewUrl;
     URL.revokeObjectURL(localPreviewUrl);
 
-    proxy?.$modal.msgError(error.code === 'ECONNABORTED'
-      ? '视频上传超时,请尝试上传更小的文件或联系管理员'
-      : '视频上传失败:' + (error.message || '未知错误'));
+    proxy?.$modal.msgError(
+      error.code === 'ECONNABORTED' ? '视频上传超时,请尝试上传更小的文件或联系管理员' : '视频上传失败:' + (error.message || '未知错误')
+    );
 
     form.value.ossVideoUrl = '';
     form.value.ossId = undefined;
@@ -908,7 +922,7 @@ onUnmounted(() => {
 const loadServiceTabOptions = async () => {
   try {
     const res = await selectEnabledTabsByCategoryList('video');
-    serviceTabOptions.value = Array.isArray(res.data) ? res.data : (Array.isArray(res) ? res : []);
+    serviceTabOptions.value = Array.isArray(res.data) ? res.data : Array.isArray(res) ? res : [];
   } catch (error) {
     console.error('加载页签列表失败:', error);
     proxy?.$modal.msgError('加载页签列表失败');