From a25aa103c05348214df4eea6b091fac654dfa20d Mon Sep 17 00:00:00 2001
From: shenrongliang <1328040932@qq.com>
Date: 星期三, 16 四月 2025 17:18:52 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 easegen-front/src/views/myCourse/index.vue                      |  465 +++++++++++++++++++++++++++++++++++----------------
 easegen-front/src/views/digitalcourse/template/TemplateForm.vue |    4 
 easegen-front/src/api/pptTemplate/index.ts                      |    8 
 easegen-front/src/views/Login/Login.vue                         |    4 
 easegen-front/src/assets/imgs/bei.png                           |    0 
 5 files changed, 331 insertions(+), 150 deletions(-)

diff --git a/easegen-front/src/api/pptTemplate/index.ts b/easegen-front/src/api/pptTemplate/index.ts
index 8b2d2da..08ed5d2 100644
--- a/easegen-front/src/api/pptTemplate/index.ts
+++ b/easegen-front/src/api/pptTemplate/index.ts
@@ -102,3 +102,11 @@
 export const videoMeger = async(data) => {
   return await request.post({ url: '/digitalcourse/course-media/createSubtitlesVideo', data })
 }
+//鍚堟垚鐗囧ご鐗囧熬
+export const createVideo = async(data) => {
+  return await request.post({ url: '/digitalcourse/course-media/createTrailer', data })
+}
+//鍚堟垚瑙嗛
+export const createVideoMeger = async(data) => {
+  return await request.post({ url: '/digitalcourse/course-media/createCompositeVideo', data })
+}
diff --git a/easegen-front/src/assets/imgs/bei.png b/easegen-front/src/assets/imgs/bei.png
index d8f788c..30ec5dc 100644
--- a/easegen-front/src/assets/imgs/bei.png
+++ b/easegen-front/src/assets/imgs/bei.png
Binary files differ
diff --git a/easegen-front/src/views/Login/Login.vue b/easegen-front/src/views/Login/Login.vue
index f2497c3..fcf78da 100644
--- a/easegen-front/src/views/Login/Login.vue
+++ b/easegen-front/src/views/Login/Login.vue
@@ -55,7 +55,7 @@
   width: 100%;
   height: 100%;
   background-image: url('@/assets/imgs/bei.png');
-  background-size: 100% 100%;
+  background-size: 100%;
 }
 .form-box{
   width: 25%;
@@ -63,7 +63,7 @@
   box-sizing: border-box;
   background: #fff;
   float: right;
-  margin-top: 25vh;
+  margin-top: 30vh;
   margin-right: 10vw;
 }
 </style>
diff --git a/easegen-front/src/views/digitalcourse/template/TemplateForm.vue b/easegen-front/src/views/digitalcourse/template/TemplateForm.vue
index 6020d9b..31463a2 100644
--- a/easegen-front/src/views/digitalcourse/template/TemplateForm.vue
+++ b/easegen-front/src/views/digitalcourse/template/TemplateForm.vue
@@ -85,12 +85,12 @@
       </el-row>
       <el-row>
         <el-col :span="12">
-          <el-form-item :label="t('template.topPositionPPT')" prop="pptX">
+          <el-form-item :label="t('template.leftPositionPPT')" prop="pptX">
             <el-input type="number" v-model="formData.pptX" :placeholder="t('common.inputText') + t('template.topPositionPPT')" />
           </el-form-item>
         </el-col>
         <el-col :span="12">
-          <el-form-item :label="t('template.leftPositionPPT')" prop="pptY">
+          <el-form-item  :label="t('template.topPositionPPT')"  prop="pptY">
             <el-input type="number" v-model="formData.pptY" :placeholder="t('common.inputText') + t('template.leftPositionPPT')" />
           </el-form-item>
         </el-col>
diff --git a/easegen-front/src/views/myCourse/index.vue b/easegen-front/src/views/myCourse/index.vue
index b23cc8c..03ad81a 100644
--- a/easegen-front/src/views/myCourse/index.vue
+++ b/easegen-front/src/views/myCourse/index.vue
@@ -1,5 +1,5 @@
 <template>
-  <!-- 鎼滅储 -->
+  <!-- 鎼滅储鍖哄煙 -->
   <ContentWrap>
     <el-form
       class="-mb-15px"
@@ -18,7 +18,7 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery">
+        <el-button @click="handleQuery" type="primary">
           <Icon icon="ep:search" class="mr-5px" />
           {{t('table.search')}}
         </el-button>
@@ -30,30 +30,25 @@
     </el-form>
   </ContentWrap>
 
-  <!-- 鍒楄〃 -->
+  <!-- 瑙嗛鍒楄〃 -->
   <ContentWrap>
-    <el-table v-loading="loading" :data="list">
-      <el-table-column :label="t('myCourse.videoCode')" align="center" prop="id" />
-      <el-table-column :label="t('myCourse.videoName')" align="center" prop="name" />
-<!--      <el-table-column :label="t('myCourse.duration')" align="center" prop="duration">-->
-<!--        <template #default="scope">-->
-<!--          {{ formatDuration(scope.row.duration) }}-->
-<!--        </template>-->
-<!--      </el-table-column>-->
-      <el-table-column label="鎺掗槦涓暟" align="center" prop="pos" >
+    <el-table v-loading="loading" :data="list" style="width: 100%">
+      <el-table-column :label="t('myCourse.videoCode')" align="center" prop="id" width="100" />
+      <el-table-column :label="t('myCourse.videoName')" align="center" prop="name" min-width="150" />
+      <el-table-column label="鎺掗槦涓暟" align="center" prop="pos" width="100">
         <template #default="scope">
-         <span v-if="scope.row.pos==0">瑙嗛姝e湪鍚堟垚...</span>
+          <span v-if="scope.row.pos==0">瑙嗛姝e湪鍚堟垚...</span>
           <span v-else>{{ scope.row.pos }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="杩涘害" align="center" prop="progressVideo">
+      <el-table-column label="杩涘害" align="center" prop="progressVideo" width="100">
         <template #default="scope">
           <span v-if="scope.row.status==2">100%</span>
           <span v-else>{{ calculateProgress(scope.row.progressVideo) }}%</span>
         </template>
       </el-table-column>
 
-      <el-table-column :label="t('myCourse.courseName')" align="center" prop="courseName">
+      <el-table-column :label="t('myCourse.courseName')" align="center" prop="courseName" min-width="150">
         <template #default="scope">
           <el-link type="primary" @click="goDetail(scope.row.courseId)">{{ scope.row.courseName }}</el-link>
         </template>
@@ -62,94 +57,119 @@
         :label="t('table.createTime')"
         align="center"
         prop="createTime"
-        width="120"
+        width="160"
         :formatter="dateFormatter"
       />
       <el-table-column
         :label="t('myCourse.finishTime')"
         align="center"
         prop="finishTime"
-        width="120"
+        width="160"
         :formatter="dateFormatter"
       />
-      <el-table-column :label="t('myCourse.SynthesisTime')" align="center">
+      <el-table-column :label="t('myCourse.SynthesisTime')" align="center" width="120">
         <template #default="scope">
           {{ calculateDuration(scope.row.createTime, scope.row.finishTime) }}
         </template>
       </el-table-column>
-      <el-table-column :label="t('myCourse.errorReason')" align="center" prop="errorReason">
+      <el-table-column :label="t('myCourse.errorReason')" align="center" prop="errorReason" width="150">
         <template #default="scope">
           <el-tooltip :content="scope.row.errorReason || '--'" placement="top">
             <span>
-              {{ scope.row.errorReason ? (scope.row.errorReason.length > 20 ? scope.row.errorReason.slice(0, 20) + '...' : scope.row.errorReason) : '--' }}
+              {{ scope.row.errorReason ? (scope.row.errorReason.length > 10 ? scope.row.errorReason.slice(0, 10) + '...' : scope.row.errorReason) : '--' }}
             </span>
           </el-tooltip>
         </template>
       </el-table-column>
-      <el-table-column :label="t('myCourse.status')" align="center" prop="status">
+      <el-table-column :label="t('myCourse.status')" align="center" prop="status" width="120">
         <template #default="scope">
           <dict-tag v-if="scope.row.status==2 && scope.row.subtitlesAddStatus!=null" :type="DICT_TYPE.video_zi" :value="scope.row.subtitlesAddStatus" />
           <dict-tag v-else :type="DICT_TYPE.VIDEO_STATUS" :value="scope.row.status" />
         </template>
       </el-table-column>
-      <el-table-column :label="t('table.action')" align="center" min-width="110" fixed="right">
+      <el-table-column :label="t('table.action')" align="center" width="230" fixed="right">
         <template #default="scope">
-          <template v-if="scope.row.status == 2">
-            <el-button
-              link
-              type="primary"
-              @click="openPreview(scope.row)"
-            >
-              {{t('myCourse.preview')}}
-            </el-button>
-            <el-button
-              link
-              type="primary"
-              @click="handleDownload(scope.row.previewUrl,scope.row.courseName)"
-            >
-              {{t('myCourse.downloadVideo')}}
-            </el-button>
-
-          </template>
-          <template v-if=" scope.row.status == 3">
-            <el-button
-              link
-              type="warning"
-              @click="reMegerMedia(scope.row.id)"
-            >
-              {{t('myCourse.resynthesize')}}
-            </el-button>
-          </template>
-          <template v-if="scope.row.status == 2">
-            <el-button
-              link
-              type="primary"
-              @click="openSubtitleDialog(scope.row.id)"
-            >
-              瀛楀箷
-            </el-button>
-          </template>
-          <template v-if="scope.row.subtitlesAddStatus == 2">
-            <el-button
-              link
-              type="primary"
-              @click="handleDownload(scope.row.videoUrl,scope.row.courseName)"
-            >
-             涓嬭浇瀛楀箷鍚堟垚瑙嗛
-            </el-button>
-          </template>
-        <template v-if="scope.row.status == 2 || scope.row.status==3">
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-          >
-            {{ t('action.del') }}
-          </el-button>
-        </template>
+          <el-button-group>
+            <template v-if="scope.row.status == 2">
+              <el-button
+                type="text"
+                @click="openPreview(scope.row)"
+                plain
+              >
+                {{t('myCourse.preview')}}
+              </el-button>
+              <el-button
+                type="text"
+                @click="handleHeaderFooter(scope.row)"
+                plain
+              >
+                鐗囧ご鐗囧熬
+              </el-button>
+              <template v-if="scope.row.status == 2 || scope.row.status==3">
+                <el-button
+                  type="text"
+                  @click="handleDelete(scope.row.id)"
+                  plain
+                >
+                  {{ t('action.del') }}
+                </el-button>
+              </template>
+              <template v-if="scope.row.status == 3">
+                <el-button
+                  type="text"
+                  @click="reMegerMedia(scope.row.id)"
+                  plain
+                >
+                  {{t('myCourse.resynthesize')}}
+                </el-button>
+              </template>
+              <template v-if="scope.row.status == 2">
+                <el-button
+                  type="text"
+                  @click="openSubtitleDialog(scope.row.id)"
+                  plain
+                >
+                  瀛楀箷
+                </el-button>
+              </template>
+            </template>
+            <el-dropdown>
+              <el-button type="text" plain>
+                鏇村<el-icon class="el-icon--right"><arrow-down /></el-icon>
+              </el-button>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item
+                    v-if="scope.row.subtitlesAddStatus == 2"
+                    @click="handleDownload(scope.row.videoUrl, scope.row.courseName + '_瀛楀箷鍚堟垚瑙嗛')"
+                  >
+                    <Icon class="mr-2" />涓嬭浇瀛楀箷鍚堟垚瑙嗛
+                  </el-dropdown-item>
+                  <el-dropdown-item
+                    @click="handleDownload(scope.row.previewUrl, scope.row.courseName + '_瑙嗛')"
+                  >
+                    <Icon class="mr-2" />涓嬭浇瑙嗛
+                  </el-dropdown-item>
+                  <el-dropdown-item
+                    v-if="scope.row.compositeVideo!=null"
+                    @click="handleDownload(scope.row.compositeVideo, scope.row.courseName + '_鐗囧ご鐗囧熬瑙嗛')"
+                  >
+                    <Icon class="mr-2" />涓嬭浇鐗囧ご鐗囧熬瑙嗛
+                  </el-dropdown-item>
+                  <el-dropdown-item
+                    v-if="scope.row.titles!=null && scope.row.trailer!=null"
+                    @click="mergeHeaderFooter(scope.row.id)"
+                  >
+                    <Icon class="mr-2" />鍚堟垚鐗囧ご鐗囧熬瑙嗛
+                  </el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </el-button-group>
         </template>
       </el-table-column>
     </el-table>
+
     <!-- 鍒嗛〉 -->
     <Pagination
       :total="total"
@@ -210,7 +230,6 @@
                 @change="handleFileUpload"
               />
             </el-button>
-            <!-- 褰撴煡鐪嬪瓧骞曟寜閽浆鍦堟椂锛屽瓧骞曡棰戝悎鎴愪篃杞湀 -->
             <el-button
               type="primary"
               @click="downloadSubtitles"
@@ -250,9 +269,7 @@
           >
             淇濆瓨瀛楀箷
           </el-button>
-
         </div>
-
       </el-form-item>
       <el-form-item label="棰勮瑙嗛" v-if="subtitleForm.subtitlesAddStatus==2">
         <div style="width: 100%;">
@@ -268,15 +285,56 @@
       </el-form-item>
     </el-form>
 
-
     <template #footer>
       <div class="dialog-footer">
         <el-button @click="subtitleDialogVisible = false">鍏� 闂�</el-button>
+      </div>
+    </template>
+  </el-dialog>
 
+  <!-- 鐗囧ご鐗囧熬璁剧疆寮规 -->
+  <el-dialog
+    v-model="headerFooterDialogVisible"
+    title="鐗囧ご鐗囧熬璁剧疆"
+    width="50%"
+  >
+    <el-form :model="headerFooterForm" label-width="120px">
+      <el-form-item label="鐗囧ご瑙嗛">
+        <UploadFile v-model="headerFooterForm.titles" :fileType="['mp4']" :limit="1" @on-success="handleFileSuccess('audition', $event)"/>
+      </el-form-item>
+      <el-form-item label="鐗囧熬瑙嗛">
+        <UploadFile v-model="headerFooterForm.trailer" :fileType="['mp4']" :limit="1" @on-success="handleFileSuccess1('audition', $event)"/>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="headerFooterDialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="applyHeaderFooter" :loading="applyingHeaderFooter">搴旂敤</el-button>
+      </div>
+    </template>
+  </el-dialog>
+  <el-dialog
+    v-model="dialogVisible"
+    title="瑙嗛鍚堟垚涓�"
+    width="50%"
+  >
+    <el-form :model="formData1" label-width="120px">
+      <el-form-item  label="瑙嗛鏍煎紡">
+        <el-select v-model="formData1.isvideo">
+          <el-option :disabled="formData1.videoUrl==null" label="瀛楀箷瑙嗛" :value="1" />
+          <el-option label="鍘熻棰�" :value="2" />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="hecheng" :loading="applyingHeaderFooter">鍚堟垚</el-button>
       </div>
     </template>
   </el-dialog>
 </template>
+
 <script lang="ts" setup>
 import { DICT_TYPE } from '@/utils/dict'
 import { dateFormatter } from '@/utils/formatTime'
@@ -287,13 +345,20 @@
 import { getAccessToken, getTenantId } from "@/utils/auth"
 import axios from 'axios'
 import { config } from '@/config/axios/config'
-import {videoMeger} from "@/api/pptTemplate";
+import {createVideo, createVideoMeger, videoMeger} from "@/api/pptTemplate";
+import { ArrowDown } from '@element-plus/icons-vue'
+
 const router = useRouter()
 const message = useMessage()
 const { t } = useI18n()
 const polling = ref(false)
 let pollingTimer: number | null = null
-
+//鍚堟垚鐗囧ご鐗囧熬瑙嗛
+const dialogVisible = ref(false)
+const formData1 = reactive({
+  isvideo: 2,
+  id: null as number | null
+})
 // 瑙嗛鍒楄〃鐩稿叧鏁版嵁
 const loading = ref(true)
 const total = ref(0)
@@ -316,11 +381,34 @@
   videoId: null as number | null,
   timeThreshold: '0.05',
   language: 'zh',
-  content: ''
+  content: '',
+  subtitlesUrl: '',
+  videoUrl: '',
+  courseName: '',
+  subtitlesAddStatus: null
 })
 const generating = ref(false)
 const saving = ref(false)
 
+// 鐗囧ご鐗囧熬寮规鐩稿叧
+const headerFooterDialogVisible = ref(false)
+const headerFooterForm = reactive({
+  id: null as number | null,
+  titles: '',
+  trailer: '',
+})
+
+const applyingHeaderFooter = ref(false)
+const handleFileSuccess = (fileType,response) => {
+  if (fileType === 'audition') {
+    headerFooterForm.titles = response.data
+  }
+};
+const handleFileSuccess1 = (fileType,response) => {
+  if (fileType === 'audition') {
+    headerFooterForm.trailer = response.data
+  }
+};
 // 鑾峰彇瑙嗛鍒楄〃
 const getList = async () => {
   loading.value = true
@@ -363,15 +451,15 @@
 }
 
 // 涓嬭浇鏂囦欢
-const handleDownload = (url, courseName) => {
+const handleDownload = (url, filename) => {
   if (!url) {
     message.warning("鏈壘鍒拌祫婧愭枃浠讹紒")
     return
   }
-  // window.open(url, '_blank');
+
   const link = document.createElement('a')
   link.href = url
-  link.download = courseName
+  link.download = filename || 'download'
   link.target = '_blank'
   document.body.appendChild(link)
   link.click()
@@ -393,16 +481,8 @@
   })
 }
 
-// 鏍煎紡鍖栬棰戞椂闀�
-const formatDuration = (milliseconds: number) => {
-  const seconds = Math.floor(milliseconds / 1000)
-  const hrs = Math.floor(seconds / 3600)
-  const mins = Math.floor((seconds % 3600) / 60)
-  const secs = seconds % 60
-  return `${hrs > 0 ? `${hrs}鏃禶 : ''}${mins > 0 ? `${mins}鍒哷 : ''}${secs}绉抈
-}
 // 璁$畻杩涘害
-const calculateProgress = (progressStr: number) => {
+const calculateProgress = (progressStr) => {
   if (!progressStr || typeof progressStr !== 'string') return 0;
 
   const parts = progressStr.split('/');
@@ -433,7 +513,7 @@
 }
 
 // 璁$畻鍚堟垚鑰楁椂
-const calculateDuration = (createTime: string, finishTime: string) => {
+const calculateDuration = (createTime, finishTime) => {
   if (!createTime || !finishTime) return '鏈畬鎴�'
 
   const start = new Date(createTime).getTime()
@@ -450,36 +530,38 @@
 // 鎵撳紑瀛楀箷寮规
 const openSubtitleDialog = async (videoId: number) => {
   try {
-
     subtitleDialogVisible.value = true
     subtitleForm.videoId = videoId
     const videoDetail = await pptTemplateApi.myCourseDetail(videoId)
-    // 绔嬪嵆鑾峰彇瑙嗛璇︽儏妫�鏌ュ瓧骞曠姸鎬�
-    subtitleForm.subtitlesAddStatus=videoDetail.subtitlesAddStatus
-    console.log('瑙嗛璇︽儏:', videoDetail)
+
+    subtitleForm.subtitlesAddStatus = videoDetail.subtitlesAddStatus
+    subtitleForm.courseName = videoDetail.courseName
+
     if (videoDetail.subtitlesAddStatus === 2) {
       subtitleForm.videoUrl = videoDetail.videoUrl || ''
-      generating.value=false
-      polling.value=false
-    }else if (videoDetail.subtitlesAddStatus === 1) {
+      generating.value = false
+      polling.value = false
+    } else if (videoDetail.subtitlesAddStatus === 1) {
       subtitleForm.videoUrl = ''
-      generating.value=true
-      polling.value=true
+      generating.value = true
+      polling.value = true
+    }else {
+      subtitleForm.videoUrl = videoDetail.videoUrl || ''
+      generating.value = false
+      polling.value = false
     }
-    if (videoDetail.subtitlesStatus === 2) { // 2 琛ㄧず瀛楀箷宸茬敓鎴�
+
+    if (videoDetail.subtitlesStatus === 2) {
+      generating.value = false
+      polling.value = false
       if (videoDetail.subtitlesUrl) {
         subtitleForm.subtitlesUrl = videoDetail.subtitlesUrl
-        subtitleForm.courseName=videoDetail.courseName
-        generating.value=false
-        polling.value=false
         try {
-          // 灏濊瘯浠嶶RL鑾峰彇瀛楀箷鍐呭
           const response = await fetch(videoDetail.subtitlesUrl)
           if (response.ok) {
             const srtContent = await response.text()
             subtitleForm.content = srtContent
           } else {
-            // 濡傛灉URL涓嶅彲鐢紝妫�鏌ユ槸鍚︽湁鐩存帴鐨勫瓧骞曞唴瀹�
             subtitleForm.content = videoDetail.subtitlesContent || ''
           }
         } catch (error) {
@@ -487,30 +569,25 @@
           subtitleForm.content = videoDetail.subtitlesContent || ''
         }
       } else if (videoDetail.subtitlesContent) {
-        // 鐩存帴浣跨敤瀛楀箷鍐呭
         subtitleForm.content = videoDetail.subtitlesContent
       }
     } else if (videoDetail.subtitlesStatus === 3) {
-      // 瀛楀箷鏈敓鎴愭垨鐢熸垚澶辫触锛屾竻绌哄唴瀹�
+      generating.value = false
+      polling.value = false
       subtitleForm.content = ''
-    }else if (videoDetail.subtitlesStatus === 1) {
-      generating.value=true
-      polling.value=true
+    } else if (videoDetail.subtitlesStatus === 1) {
+      generating.value = true
+      polling.value = true
       subtitleForm.content = ''
+    }else{
+      generating.value = false
+      polling.value = false
     }
   } catch (error) {
     console.error('鑾峰彇瑙嗛璇︽儏澶辫触:', error)
     message.error('鑾峰彇瑙嗛璇︽儏澶辫触锛岃閲嶈瘯')
     subtitleDialogVisible.value = false
   }
-  console.log('瑙嗛璇︽儏:', generating)
-}
-
-// 閲嶇疆瀛楀箷琛ㄥ崟
-const resetSubtitleForm = () => {
-  subtitleFormRef.value?.resetFields()
-  subtitleForm.videoId = null
-  subtitleForm.content = ''
 }
 
 // 瑙﹀彂鏂囦欢涓婁紶
@@ -555,7 +632,7 @@
 const generateSubtitles = async () => {
   try {
     await subtitleFormRef.value.validateField(['timeThreshold', 'language'])
-    console.log(subtitleForm)
+
     if (!subtitleForm.videoId) {
       message.warning('瑙嗛ID涓嶈兘涓虹┖')
       return
@@ -568,8 +645,10 @@
       sentenceGap: parseFloat(subtitleForm.timeThreshold),
       lang: subtitleForm.language
     }
+
     await pptTemplateApi.generateSubtitles(params)
     message.success(subtitleForm.courseName+' '+'瀛楀箷鐢熸垚浠诲姟宸插紑濮�')
+
     const maxAttempts = 20000
     const interval = 3000
     let attempts = 0
@@ -580,7 +659,7 @@
 
       try {
         const videoDetail = await pptTemplateApi.myCourseDetail(subtitleForm.videoId!)
-        console.log('杞缁撴灉:', videoDetail)
+
         if (videoDetail.subtitlesStatus === 2) {
           if (videoDetail.subtitlesUrl) {
             try {
@@ -598,7 +677,6 @@
           message.success(subtitleForm.courseName+' '+'瀛楀箷鐢熸垚鎴愬姛')
           stopPolling()
         } else if (videoDetail.subtitlesStatus === 3) {
-          // message.error(`瀛楀箷鐢熸垚澶辫触: ${videoDetail.errorReason || '鏈煡鍘熷洜'}`)
           stopPolling()
         } else if (attempts >= maxAttempts) {
           message.warning(subtitleForm.courseName+' '+'瀛楀箷鐢熸垚瓒呮椂锛岃绋嶅悗鎵嬪姩妫�鏌�')
@@ -620,13 +698,13 @@
     poll()
   } catch (error) {
     console.error(subtitleForm.courseName+' '+'鐢熸垚瀛楀箷鍑洪敊:', error)
-    // message.error(`鐢熸垚瀛楀箷澶辫触: ${error.message || '鏈煡閿欒'}`)
     stopPolling()
   } finally {
     generating.value = false
   }
 }
 
+// 淇濆瓨瀛楀箷
 const saveSubtitles = async () => {
   try {
     saving.value = true
@@ -642,7 +720,7 @@
     const formData = new FormData()
     formData.append('file', file)
 
-    // 4. 涓婁紶鏂囦欢 - 浣跨敤 axios 鏇夸唬 request
+    // 4. 涓婁紶鏂囦欢
     const uploadResponse = await axios({
       url: config.base_url+'/infra/file/upload',
       method: 'post',
@@ -673,6 +751,7 @@
     saving.value = false
   }
 }
+
 // 灏嗘枃鏈唴瀹规牸寮忓寲涓篠RT鏍煎紡
 const formatToSrt = (content: string): string => {
   if (content.trim().match(/^\d+\s+\d{2}:\d{2}:\d{2},\d{3}\s-->\s\d{2}:\d{2}:\d{2},\d{3}/)) {
@@ -691,18 +770,9 @@
   return srtContent
 }
 
-// 鍋滄杞
-const stopPolling = () => {
-  if (pollingTimer) {
-    clearTimeout(pollingTimer)
-    pollingTimer = null
-  }
-  polling.value = false
-}
-//瀛楀箷瑙嗛鍚堟垚
+// 瀛楀箷瑙嗛鍚堟垚
 const downloadSubtitles = async () => {
   try {
-    // 鍒ゆ柇瀛楀箷鍐呭鏄惁涓虹┖
     if (!subtitleForm.content.trim()) {
       message.warning('璇峰厛鐢熸垚鎴栦笂浼犲瓧骞曞唴瀹�')
       return
@@ -725,15 +795,14 @@
 
       try {
         const videoDetail = await pptTemplateApi.myCourseDetail(subtitleForm.videoId!)
-        console.log('杞瀛楀箷瑙嗛鍚堟垚缁撴灉:', videoDetail)
 
         if (videoDetail.subtitlesAddStatus === 2) {
           message.success(subtitleForm.courseName+' '+'瀛楀箷瑙嗛鍚堟垚鎴愬姛')
           if (videoDetail.previewUrl) {
-            subtitleForm.content = '' // 娓呯┖褰撳墠瀛楀箷鍐呭
+            subtitleForm.content = ''
             stopPolling()
             subtitleDialogVisible.value = false
-            getList() // 鍒锋柊鍒楄〃
+            getList()
           }
         } else if (videoDetail.subtitlesAddStatus === 3) {
           message.error(subtitleForm.courseName+' '+`瀛楀箷瑙嗛鍚堟垚澶辫触: ${videoDetail.errorReason || '鏈煡鍘熷洜'}`)
@@ -764,6 +833,104 @@
     generating.value = false
   }
 }
+
+// 鍋滄杞
+const stopPolling = () => {
+  if (pollingTimer) {
+    clearTimeout(pollingTimer)
+    pollingTimer = null
+  }
+  polling.value = false
+}
+
+// 澶勭悊鐗囧ご鐗囧熬鎸夐挳鐐瑰嚮
+const handleHeaderFooter =async (row) => {
+  console.log(row)
+  headerFooterForm.id = row.id
+  let details= await pptTemplateApi.myCourseDetail(row.id)
+  console.log(details)
+  headerFooterForm.titles = details.titles || ''
+  headerFooterForm.trailer = details.trailer || ''
+  headerFooterDialogVisible.value = true
+}
+// 搴旂敤鐗囧ご鐗囧熬璁剧疆
+const applyHeaderFooter = async () => {
+  try {
+    console.log('搴旂敤鐗囧ご鐗囧熬璁剧疆:', headerFooterForm)
+    const title = await pptTemplateApi.createVideo(headerFooterForm)
+    console.log('鍒涘缓瑙嗛鏍囬:', title)
+    if (title) {
+      message.success('鐗囧ご鐗囧熬璁剧疆鎴愬姛')
+      headerFooterDialogVisible.value = false
+      getList()
+    }
+  } catch (error) {
+    console.error('鐗囧ご鐗囧熬璁剧疆鍑洪敊:', error)
+    message.error('鐗囧ご鐗囧熬璁剧疆鍑洪敊')
+  } finally {
+    applyingHeaderFooter.value = false
+  }
+}
+//鍚堟垚鐗囧ご鐗囧熬瑙嗛
+const mergeHeaderFooter = async (id: number) => {
+  try {
+    let details= await pptTemplateApi.myCourseDetail(id)
+    formData1.value=details
+    dialogVisible.value = true
+    console.log(formData1.value)
+  }
+  catch (error) {
+    console.error(error)
+  }
+
+}
+//鍚堟垚鐗囧ご鐗囧熬
+const hecheng = async () => {
+  try {
+    console.log(formData1.value)
+    applyingHeaderFooter.value = true
+    let obj={}
+    if (formData1.isvideo=='2'){
+      obj={
+        id:formData1.value.id,
+        titles:formData1.value.titles,
+        trailer:formData1.value.trailer,
+        courseName:formData1.value.courseName,
+        videoUrl:null,
+        previewUrl:formData1.value.previewUrl
+      }
+      const res = await pptTemplateApi.createVideoMeger(obj)
+      if (res) {
+        message.success('瑙嗛鍚堟垚鎴愬姛')
+        applyingHeaderFooter.value = true
+        dialogVisible.value = false
+        getList()
+      }
+    }else if (formData1.isvideo=='1'){
+      obj={
+        id:formData1.value.id,
+        titles:formData1.value.titles,
+        trailer:formData1.value.trailer,
+        courseName:formData1.value.courseName,
+        videoUrl:formData1.value.courseName,
+        previewUrl:null
+      }
+      const res = await pptTemplateApi.createVideoMeger(obj)
+      if (res) {
+        message.success('瑙嗛鍚堟垚鎴愬姛')
+        applyingHeaderFooter.value = true
+        dialogVisible.value = false
+        getList()
+      }
+    }
+    // loading.value = true
+    //
+  }
+  catch (error) {
+    console.error(error)
+  }
+}
+
 // 娓呯悊瀹氭椂鍣�
 onBeforeUnmount(() => {
   stopPolling()
@@ -774,6 +941,7 @@
   getList()
 })
 </script>
+
 <style scoped>
 .textarea-wrapper {
   position: relative;
@@ -781,20 +949,15 @@
 }
 
 .scroll-outside {
-  /* 闅愯棌榛樿婊氬姩鏉� */
   overflow: hidden;
 }
 
 .scroll-outside .el-textarea__inner {
-  /* 鏄剧ず鑷畾涔夋粴鍔ㄦ潯 */
   overflow-y: auto;
-  /* 纭繚婊氬姩鏉′笉浼氭尋鍘嬪唴瀹� */
   padding-right: 0;
-  /* 鍙�夛細澧炲姞鍙宠竟璺濅负婊氬姩鏉$暀鍑虹┖闂� */
   margin-right: 16px;
 }
 
-/* 鍙�夛細鑷畾涔夋粴鍔ㄦ潯鏍峰紡 */
 .scroll-outside .el-textarea__inner::-webkit-scrollbar {
   width: 8px;
 }
@@ -803,4 +966,14 @@
   background: #c0c4cc;
   border-radius: 4px;
 }
+
+.el-button-group {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.el-dropdown {
+  margin-left: 0;
+}
 </style>

--
Gitblit v1.9.3