فهرست منبع

Merge remote-tracking branch 'origin/master'

xgb 6 روز پیش
والد
کامیت
e08b4232ef
4فایلهای تغییر یافته به همراه200 افزوده شده و 61 حذف شده
  1. 1 1
      package.json
  2. 190 55
      src/components/VideoUpload/index.vue
  3. 1 0
      src/utils/hsy.js
  4. 8 5
      vue.config.js

+ 1 - 1
package.json

@@ -6,7 +6,7 @@
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {
     "dev": "vue-cli-service serve",
     "dev": "vue-cli-service serve",
-    "build:prod": "vue-cli-service build",
+    "build:prod": "node --max-old-space-size=4096 ./node_modules/@vue/cli-service/bin/vue-cli-service.js build",
     "build:stage": "vue-cli-service build --mode staging",
     "build:stage": "vue-cli-service build --mode staging",
     "preview": "node build/index.js --preview",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src"
     "lint": "eslint --ext .js,.vue src"

+ 190 - 55
src/components/VideoUpload/index.vue

@@ -2,49 +2,67 @@
   <div>
   <div>
     <el-form-item label="视频上传">
     <el-form-item label="视频上传">
       <div class="upload_video" id="upload_video">
       <div class="upload_video" id="upload_video">
-        <el-upload
-          class="upload-demo"
-          ref="upload"
-          action="#"
-          :http-request="uploadVideoToTxPcdn"
-          accept=".mp4"
-          :limit="1"
-          :on-remove="handleRemove"
-          :on-change="handleChange"
-          :auto-upload="false"
-          :key="uploadKey"
-        >
-          <el-button slot="trigger" size="small" type="primary" >选取视频</el-button>
-          <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">点击上传</el-button>
-          <!-- 仅当showControl为true时显示视频库选取按钮 -->
-          <el-button v-if="showControl" style="margin-left: 10px;" size="small" type="success" @click="openVideoLibrary">视频库选取</el-button>
-          <!-- 线路一 -->
-          <div class="progress-container">
+        <div class="upload-toolbar">
+          <el-upload
+            class="upload-picker"
+            ref="upload"
+            action="#"
+            accept=".mp4"
+            :limit="1"
+            :show-file-list="false"
+            :on-remove="handleRemove"
+            :on-change="handleChange"
+            :auto-upload="false"
+            :key="uploadKey"
+          >
+            <el-button slot="trigger" size="small" type="primary">选取视频</el-button>
+          </el-upload>
+          <el-button
+            size="small"
+            type="success"
+            :loading="uploadLoading"
+            :disabled="!hasLocalFile"
+            @click="submitUpload"
+          >点击上传</el-button>
+          <el-button
+            v-if="showControl"
+            size="small"
+            type="success"
+            plain
+            @click="openVideoLibrary"
+          >视频库选取</el-button>
+        </div>
+        <p class="upload-tip">只能上传mp4文件,且不超过500M</p>
+        <div v-if="displayFileName" class="upload-file-info">
+          <i class="el-icon-document" />
+          <span class="upload-file-name" :title="displayFileName">{{ displayFileName }}</span>
+        </div>
+        <div class="progress-container">
+          <div class="progress-row">
             <span class="progress-label">线路一</span>
             <span class="progress-label">线路一</span>
-            <el-progress
-              style="margin-top: 5px;"
-              class="progress"
-              :text-inside="true"
-              :stroke-width="18"
-              :percentage="txProgress"
-              status="success">
-            </el-progress>
+            <span class="progress-percent">{{ txProgress }}%</span>
           </div>
           </div>
-
-          <!-- 线路二 -->
-          <div class="progress-container">
+          <el-progress
+            class="progress-bar"
+            :percentage="txProgress"
+            :stroke-width="18"
+            :show-text="false"
+            :status="txProgress >= 100 ? 'success' : undefined"
+          />
+        </div>
+        <div class="progress-container">
+          <div class="progress-row">
             <span class="progress-label">线路二</span>
             <span class="progress-label">线路二</span>
-            <el-progress
-              style="margin-top: 5px;"
-              class="progress"
-              :text-inside="true"
-              :stroke-width="18"
-              :percentage="hwProgress"
-              status="success">
-            </el-progress>
+            <span class="progress-percent">{{ hwProgress }}%</span>
           </div>
           </div>
-          <div slot="tip" class="el-upload__tip">只能上传mp4文件,且不超过500M</div>
-        </el-upload>
+          <el-progress
+            class="progress-bar"
+            :percentage="hwProgress"
+            :stroke-width="18"
+            :show-text="false"
+            :status="hwProgress >= 100 ? 'success' : undefined"
+          />
+        </div>
       </div>
       </div>
     </el-form-item>
     </el-form-item>
     <el-form-item label="视频播放">
     <el-form-item label="视频播放">
@@ -216,6 +234,17 @@ export default {
       }
       }
     };
     };
   },
   },
+  computed: {
+    hasLocalFile() {
+      return this.fileList.length > 0;
+    },
+    displayFileName() {
+      if (this.fileList.length > 0) {
+        return this.fileList[0].name;
+      }
+      return this.fileName || "";
+    }
+  },
   watch: {
   watch: {
     localUploadType(newType) {
     localUploadType(newType) {
       this.$emit("update:uploadType", newType);
       this.$emit("update:uploadType", newType);
@@ -226,6 +255,16 @@ export default {
     },
     },
   },
   },
   methods: {
   methods: {
+    normalizeProgress(value) {
+      const num = Number(value);
+      if (!Number.isFinite(num)) {
+        return 0;
+      }
+      if (num <= 1) {
+        return Math.min(100, Math.max(0, Math.round(num * 100)));
+      }
+      return Math.min(100, Math.max(0, Math.round(num)));
+    },
     // 打开视频库对话框
     // 打开视频库对话框
     openVideoLibrary() {
     openVideoLibrary() {
       this.libraryOpen = true;
       this.libraryOpen = true;
@@ -253,11 +292,17 @@ export default {
       if (this.fileList.length < 1) {
       if (this.fileList.length < 1) {
         return this.$message.error("请先选取视频,再进行上传");
         return this.$message.error("请先选取视频,再进行上传");
       }
       }
-      await this.getFirstThumbnail();
-      //同时上传个线路
-      await this.uploadVideoToTxPcdn();
-      await this.uploadVideoToHsy();
-      this.$emit("update:fileName", this.fileList[0].name);
+      this.uploadLoading = true;
+      this.txProgress = 0;
+      this.hwProgress = 0;
+      try {
+        await this.getFirstThumbnail();
+        await this.uploadVideoToTxPcdn();
+        await this.uploadVideoToHsy();
+        this.$emit("update:fileName", this.fileList[0].name);
+      } finally {
+        this.uploadLoading = false;
+      }
     },
     },
     //获取第一帧封面
     //获取第一帧封面
     async getFirstThumbnail(){
     async getFirstThumbnail(){
@@ -269,15 +314,19 @@ export default {
     },
     },
     // 更新火山云线路进度条
     // 更新火山云线路进度条
     updateHwProgress(progress) {
     updateHwProgress(progress) {
-      if (typeof progress === 'number') {
-        this.hwProgress = progress
-      } else if (progress && typeof progress.percent === 'number') {
-        this.hwProgress = Math.floor(progress.percent * 100)
+      if (typeof progress === "number") {
+        this.hwProgress = this.normalizeProgress(progress);
+        return;
+      }
+      if (progress && typeof progress.percent === "number") {
+        this.hwProgress = this.normalizeProgress(progress.percent);
       }
       }
     },
     },
-    //更新腾讯线路进度条
+    // 更新腾讯线路进度条
     updateTxProgress(progressData) {
     updateTxProgress(progressData) {
-      this.txProgress = Math.round(progressData.percent * 100);
+      if (progressData && typeof progressData.percent === "number") {
+        this.txProgress = this.normalizeProgress(progressData.percent);
+      }
     },
     },
     //上传腾讯云Pcdn
     //上传腾讯云Pcdn
     async uploadVideoToTxPcdn() {
     async uploadVideoToTxPcdn() {
@@ -290,8 +339,10 @@ export default {
         this.$emit("update:fileKey", urlPathWithoutFirstSlash);
         this.$emit("update:fileKey", urlPathWithoutFirstSlash);
         this.$emit("update:videoUrl", line_1);
         this.$emit("update:videoUrl", line_1);
         this.$emit("update:line_1", line_1);
         this.$emit("update:line_1", line_1);
+        this.txProgress = 100;
         this.$message.success("线路一上传成功");
         this.$message.success("线路一上传成功");
       } catch (error) {
       } catch (error) {
+        this.txProgress = 0;
         console.error('线路一上传失败', error);
         console.error('线路一上传失败', error);
         this.$message.error(error?.message || "线路一上传失败");
         this.$message.error(error?.message || "线路一上传失败");
       }
       }
@@ -307,8 +358,10 @@ export default {
         }
         }
         const line_2 = `${videoBase}/${data.SourceInfo.FileName}`;
         const line_2 = `${videoBase}/${data.SourceInfo.FileName}`;
         this.$emit("update:line_2", line_2);
         this.$emit("update:line_2", line_2);
+        this.hwProgress = 100;
         this.$message.success("线路二上传成功");
         this.$message.success("线路二上传成功");
       } catch (error) {
       } catch (error) {
+        this.hwProgress = 0;
         console.error('线路二上传失败', error);
         console.error('线路二上传失败', error);
         const msg = error?.message || error?.extra?.message || "线路二上传失败";
         const msg = error?.message || error?.extra?.message || "线路二上传失败";
         this.$message.error(msg);
         this.$message.error(msg);
@@ -396,19 +449,101 @@ export default {
 };
 };
 </script>
 </script>
 
 
-<style>
+<style scoped>
+.upload_video {
+  width: 100%;
+  max-width: 560px;
+}
+
+.upload-toolbar {
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  gap: 10px;
+}
+
+.upload_video ::v-deep .upload-picker {
+  display: inline-block;
+  line-height: normal;
+}
+
+.upload_video ::v-deep .upload-picker .el-upload {
+  display: inline-block;
+  margin: 0;
+  border: none;
+}
+
+.upload-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.5;
+  color: #909399;
+}
+
+.upload-file-info {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  margin-top: 8px;
+  padding: 8px 10px;
+  font-size: 13px;
+  line-height: 1.4;
+  color: #606266;
+  background: #f5f7fa;
+  border: 1px solid #e4e7ed;
+  border-radius: 4px;
+}
+
+.upload-file-info .el-icon-document {
+  flex-shrink: 0;
+  font-size: 16px;
+  color: #409eff;
+}
+
+.upload-file-name {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
 .progress-container {
 .progress-container {
-  margin-bottom: 5px; /* 进度条之间的间距 */
+  width: 100%;
+  margin-top: 12px;
+}
+
+.progress-row {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 6px;
 }
 }
 
 
 .progress-label {
 .progress-label {
-  display: block;
   font-weight: bold;
   font-weight: bold;
   font-size: 13px;
   font-size: 13px;
-  color: #303331; /* 标签颜色,可以根据需要调整 */
+  color: #303133;
+}
+
+.progress-percent {
+  font-size: 12px;
+  color: #606266;
+}
+
+.progress-bar {
+  width: 100%;
 }
 }
 
 
-/* 视频库选择对话框样式 */
+.progress-bar ::v-deep .el-progress-bar__outer {
+  background-color: #ebeef5;
+}
+
+.progress-bar ::v-deep .el-progress-bar__inner {
+  transition: width 0.3s ease;
+}
+</style>
+
+<style>
+/* 视频库弹窗表格行可点击(弹窗 append-to-body,不宜 scoped) */
 .library-search {
 .library-search {
   margin-bottom: 15px;
   margin-bottom: 15px;
 }
 }

+ 1 - 0
src/utils/hsy.js

@@ -61,6 +61,7 @@ export const uploadToHSY = async (file, onProgress, type, callBackUp) => {
 
 
       // 上传完成
       // 上传完成
       uploader.on('complete', (info) => {
       uploader.on('complete', (info) => {
+        onProgress && onProgress({ percent: 1 })
         resolve({
         resolve({
           ...info.uploadResult,
           ...info.uploadResult,
           fileKey,
           fileKey,

+ 8 - 5
vue.config.js

@@ -133,11 +133,14 @@ module.exports = {
                 }
                 }
               }
               }
             })
             })
-          config.optimization.runtimeChunk('single'),
-          {
-             from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件
-             to: './' //到根目录下
-          }
+          config.optimization.runtimeChunk('single')
+          // Windows 下 terser 多进程压缩易触发 write UNKNOWN,改为单进程
+          config.optimization.minimizer('terser').tap((args) => {
+            const opts = args[0] || {}
+            opts.parallel = false
+            args[0] = opts
+            return args
+          })
         }
         }
       )
       )
   }
   }