From 54ba432847164210e854d07c177aaee1b4e58a44 Mon Sep 17 00:00:00 2001
From: Flex <q1406482700@163.com>
Date: 星期一, 09 六月 2025 17:10:16 +0800
Subject: [PATCH] 修改登录页样式

---
 yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceUtil.java                                     |   87 ++++++-
 easegen-front/src/views/chooseTemplate/index.vue                                                                                                                                        |  287 +++++++++++++++--------
 yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursescenevoices/vo/AppCourseSceneVoicesMegerReqVO.java |    3 
 yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/voices/AuditionVO.java                                     |    1 
 yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java                           |    1 
 easegen-front/src/views/Login/Login.vue                                                                                                                                                 |  190 ++++++++------
 easegen-front/src/views/Login/components/LoginForm.vue                                                                                                                                  |    6 
 easegen-front/src/views/Login/components/LoginFormTitle.vue                                                                                                                             |    3 
 yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java                                     |  142 +++++++++-
 9 files changed, 487 insertions(+), 233 deletions(-)

diff --git a/easegen-front/src/views/Login/Login.vue b/easegen-front/src/views/Login/Login.vue
index d57f808..ebca7cb 100644
--- a/easegen-front/src/views/Login/Login.vue
+++ b/easegen-front/src/views/Login/Login.vue
@@ -1,28 +1,28 @@
 <template>
   <div class="bei">
-      <div class="BeiArea">
-        <!-- 宸︿晶鍥剧墖 -->
-         <div class="Left-img">
-            <div class="TitleText" >
-              <text> 鏁板瓧浜� </text>鏅鸿兘浜や簰骞冲彴
-            </div>
-         </div>
-        <!-- 鍙宠竟鐨勭櫥褰曠晫闈� -->
-        <Transition appear enter-active-class="animate__animated animate__bounceInRight">
-          <div class="form-box">
-            <!-- 璐﹀彿鐧诲綍 -->
-            <LoginForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
-            <!-- 鎵嬫満鐧诲綍 -->
-            <MobileForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
-            <!-- 浜岀淮鐮佺櫥褰� -->
-            <QrCodeForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
-            <!-- 娉ㄥ唽 -->
-            <RegisterForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
-            <!-- 涓夋柟鐧诲綍 -->
-            <SSOLoginVue class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
-          </div>
-        </Transition>
+    <div class="BeiArea">
+      <!-- 宸︿晶鍥剧墖 -->
+      <div class="Left-Area">
+        <div class="TitleText">
+          <h1>鏁板瓧浜烘櫤鑳戒氦浜掑钩鍙�</h1>
+        </div>
       </div>
+      <!-- 鍙宠竟鐨勭櫥褰曠晫闈� -->
+      <Transition appear enter-active-class="animate__animated animate__bounceInRight">
+        <div class="form-box">
+          <!-- 璐﹀彿鐧诲綍 -->
+          <LoginForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
+          <!-- 鎵嬫満鐧诲綍 -->
+          <MobileForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
+          <!-- 浜岀淮鐮佺櫥褰� -->
+          <QrCodeForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
+          <!-- 娉ㄥ唽 -->
+          <RegisterForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
+          <!-- 涓夋柟鐧诲綍 -->
+          <SSOLoginVue class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white) bai" />
+        </div>
+      </Transition>
+    </div>
   </div>
 </template>
 <script lang="ts" setup>
@@ -33,7 +33,7 @@
 import { LocaleDropdown } from '@/layout/components/LocaleDropdown'
 
 import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components'
-import * as ConfigApi from "@/api/infra/config";
+import * as ConfigApi from '@/api/infra/config'
 
 defineOptions({ name: 'Login' })
 
@@ -43,89 +43,113 @@
 const prefixCls = getPrefixCls('login')
 const passwordLoginSwitch = ref(undefined)
 
-
-onMounted(async ()=>{
-    const data = await ConfigApi.getConfigKey('password-login-switch')
-    if (data && data.length > 0) {
-      passwordLoginSwitch.value = data
-    }
+onMounted(async () => {
+  const data = await ConfigApi.getConfigKey('password-login-switch')
+  if (data && data.length > 0) {
+    passwordLoginSwitch.value = data
+  }
 })
 </script>
-<style  scoped>
-*{
+
+<style>
+.bei .BeiArea .form-box > .el-form {
+  height: 100%;
+}
+.bei .BeiArea .form-box > .el-form > div {
+  height: 100%;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+</style>
+
+<style scoped>
+* {
   margin: 0;
   padding: 0;
 }
-.bei{
+
+.bei {
   width: 100%;
-  height: 100%;
-  background-color: #000;
+  min-height: 100%;
   display: flex;
   justify-content: center;
   align-items: center;
 }
-.bei .BeiArea{
-  width: 86%;
-  height: 95%;
+
+.bei .BeiArea {
+  width: auto;
+  max-width: 100%;
+  height: auto;
   display: flex;
   justify-content: center;
   align-items: center;
-  background-color: #000a25;
+  border-radius: 8px;
+  box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
+  overflow: hidden;
 }
-.bei .BeiArea .form-box{
-  /* width: 25%; */
-  width: 400px;
-  margin-top: -36px;
-  padding: 70px 30px;
+
+.bei .BeiArea .Left-Area {
+  width: 500px;
+  height: 450px;
+  display: flex;
+  justify-content: center;
+  align-content: center;
+  background: linear-gradient(to bottom right, #1b6ac2, #57b5f2);
+}
+
+.bei .BeiArea .Left-Area .TitleText {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.bei .BeiArea .Left-Area .TitleText h1 {
+  color: #fff;
+  font-size: 2.6rem;
+}
+
+.bei .BeiArea .form-box {
   box-sizing: border-box;
   background: #fff;
-  margin-left: 300px;
-  box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
-}
-.bei .BeiArea .Left-img{
-  width: 729px;
-  height: 655px;
-  margin-top: 138px;
-  margin-left: -74px;
-  background-image:url( "@/assets/imgs/bei3-1.png" );
-  /* background-size: 100%; */
-  background-size: contain;
-  background-repeat: no-repeat;
-  background-position: center center;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
-.bei .BeiArea .Left-img .TitleText{
-  margin-top: calc( -85% );
-  margin-left: -60px;
-  color: #fff;
-  width: 100%;
-  text-align: left;
-  font-size: 48px;
-  padding-left: 10%;
-  box-sizing: border-box;
-}
-.bei .BeiArea .Left-img .TitleText text{
-  color: #2d84fa;
+  /* width: calc(400px + (100vw - 1900px) * 0.5); */
+  width: 500px;
+  height: 450px;
+  padding: 20px 40px;
 }
 
-@media screen and ( max-width: 1300px )  {
 
-  .form-box{
-    width: 50% !important;
-    margin: 0 auto !important;
+/* @media ( max-width:1300px ) and (min-width:1000px) {
+  .bei .BeiArea .form-box{
+    width: 45%;
+    height: 90vh;
   }
-
-  .Left-img{
-    display: none !important;
+  .bei .BeiArea .Left-Area{
+    width: 45%;
+    height: 90vh;
   }
-  
+} */
+
+/* @media ( max-width:1000px ){
+  .bei .BeiArea .form-box{
+    width: 50%;
+    height: 100vh;
+  }
+  .bei .BeiArea .Left-Area{
+    width: 50%;
+    height: 100vh;
+  }
+} */
+
+@media ( max-width:1550px ){
+  .bei .BeiArea .Left-Area .TitleText h1{
+    font-size: 2.4rem !important;
+  }
 }
 
-@media (max-width:1650px) and ( min-width: 1300px )  {
-  .bei .BeiArea .Left-img{
-    margin-left: 0;
+@media ( max-width:1050px ){
+  .bei .BeiArea .Left-Area .TitleText h1{
+    font-size: 2rem !important;
   }
 }
 
diff --git a/easegen-front/src/views/Login/components/LoginForm.vue b/easegen-front/src/views/Login/components/LoginForm.vue
index 989e379..5c83098 100644
--- a/easegen-front/src/views/Login/components/LoginForm.vue
+++ b/easegen-front/src/views/Login/components/LoginForm.vue
@@ -358,14 +358,11 @@
 .NewClass {
   ::v-deep(.el-input__inner) {
     font-size: 20px;
-    line-height: 40px;
-    height: 60px;
   }
   ::v-deep(.el-button--large) {
     padding: 20px;
     box-sizing: border-box;
     font-size: 20px;
-    height: 60px;
     margin-top: 20px;
   }
 }
@@ -374,8 +371,6 @@
   .NewClass {
     ::v-deep(.el-input__inner) {
       font-size: 20px;
-      line-height: 40px;
-      height: 50px;
     }
     ::v-deep(.el-form-item--large){
       margin-bottom: 40px;
@@ -387,7 +382,6 @@
       padding: 20px;
       box-sizing: border-box;
       font-size: 20px;
-      height: 60px;
       margin-top: 10px;
     }
   }
diff --git a/easegen-front/src/views/Login/components/LoginFormTitle.vue b/easegen-front/src/views/Login/components/LoginFormTitle.vue
index 72c68d2..ae3a2c4 100644
--- a/easegen-front/src/views/Login/components/LoginFormTitle.vue
+++ b/easegen-front/src/views/Login/components/LoginFormTitle.vue
@@ -1,7 +1,8 @@
 
 <style>
 .c717a8a{
-  color: #717a8a
+  color: #717a8a;
+  text-align: center;
 }
 </style>
 
diff --git a/easegen-front/src/views/chooseTemplate/index.vue b/easegen-front/src/views/chooseTemplate/index.vue
index 11996e5..44352d7 100644
--- a/easegen-front/src/views/chooseTemplate/index.vue
+++ b/easegen-front/src/views/chooseTemplate/index.vue
@@ -586,36 +586,44 @@
             </div>
           </div>
           <div class="SoundModelArea" v-loading="soundLoading">
-            <div
-              class="ModealBox"
-              v-for="(item, index) in audioList"
-              :key="index"
-              @click="handleSelect(item)"
-              @mouseenter="handleMouseenter(item)"
-              @mouseleave="handleMouseleave(item)"
-              :class="item.isSelect ? 'slectModel' : ''"
-            >
-              <div class="ImgBox">
-                <img :src="item.avatarUrl" alt="" />
+            <div class="SoundModelAreaBox" v-for="(value, key, index) in audioList" :key="index">
+              <div class="SoundClassTit">
+                <el-divider content-position="center"> {{ languageClass(key) }} </el-divider>
+                <!-- <el-divider content-position="center"> 123 </el-divider> -->
               </div>
-              <div class="TextArea">
-                <p> {{ item.name }} </p>
-                <p> {{ item.introduction }} </p>
+              <div class="SoundClassContent">
+                <div
+                  class="ModealBox"
+                  v-for="(item, index) in value"
+                  :key="index"
+                  @click="handleSelect(key, item)"
+                  @mouseenter="handleMouseenter(key, item)"
+                  @mouseleave="handleMouseleave(key, item)"
+                  :class="item.isSelect ? 'slectModel' : ''"
+                >
+                  <div class="ImgBox">
+                    <img :src="item.avatarUrl" alt="" />
+                  </div>
+                  <div class="TextArea">
+                    <p> {{ item.name }} </p>
+                    <p> {{ item.introduction }} </p>
+                  </div>
+                  <img
+                    class="play-img"
+                    v-if="item.isHover && !item.isPlay"
+                    src="@/assets/imgs/play.png"
+                    alt=""
+                    @click.stop="playAudio(item)"
+                  />
+                  <img
+                    class="play-img"
+                    v-if="item.isHover && item.isPlay"
+                    src="@/assets/imgs/pause.png"
+                    alt=""
+                    @click.stop="SoundpauseAudio(item)"
+                  />
+                </div>
               </div>
-              <img
-                class="play-img"
-                v-if="item.isHover && !item.isPlay"
-                src="@/assets/imgs/play.png"
-                alt=""
-                @click.stop="playAudio(item)"
-              />
-              <img
-                class="play-img"
-                v-if="item.isHover && item.isPlay"
-                src="@/assets/imgs/pause.png"
-                alt=""
-                @click.stop="SoundpauseAudio(item)"
-              />
             </div>
           </div>
           <div class="ButtonArea">
@@ -740,7 +748,6 @@
 import { useEditorHtml } from '@/hooks/web/useEditorHtml'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
-import { measureMemory } from 'vm'
 import { any } from 'vue-types'
 
 const editorHtml = useEditorHtml()
@@ -773,7 +780,6 @@
   hostValue.value = item
   chooseHost1(2)
   // dialogVisible2.value = true
-  
 }
 const chooseHost1 = (index) => {
   if (index == 1) {
@@ -1012,11 +1018,11 @@
       // 鑾峰彇澹伴煶绫诲埆
       getVoiceType()
     }
-    if( selectList.value === undefined ){
+    if (selectList.value === undefined) {
       // 鑾峰彇妯″瀷鍒楄〃
       getSoundModelList()
     }
-    if( ChangeSoundTypeList.value === undefined ){
+    if (ChangeSoundTypeList.value === undefined) {
       // 鑾峰彇鍙�夌殑澹伴煶绫诲瀷鍒楄〃
       GetSoundTypeList()
     }
@@ -1043,7 +1049,7 @@
 const changeAudio = ref<any>()
 //鑾峰彇鎬у埆瀛楀吀
 const getAudioType = () => {
-  const list = getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)
+  let list = getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)
   audioType.value = list
   changeAudio.value = list[0].value
 }
@@ -1088,8 +1094,11 @@
     soundLoading.value = true
     // 璇█绫诲瀷
     soundQueryParams.language = selectLanguage?.value.value ?? ''
+    soundQueryParams.language =
+      soundQueryParams.language === 'all_Language' ? '' : soundQueryParams.language
     // 鎬у埆
     soundQueryParams.gender = changeAudio?.value ?? ''
+    soundQueryParams.gender = Number(soundQueryParams.gender) === 3 ? '' : soundQueryParams.gender
     // 澹伴煶绫诲瀷
     soundQueryParams.voiceType = activeSoundType?.value.value ?? ''
     const data = await pptTemplateApi.videlPageList(soundQueryParams)
@@ -1098,11 +1107,45 @@
       item.isPlay = false
       item.isSelect = false
     })
-    audioList.value = data.list
+    let LanguageArr = {}
+    data.list.forEach((item) => {
+      if (LanguageArr?.[item.language] !== undefined) {
+        LanguageArr[item.language].push(item)
+      } else {
+        LanguageArr = { ...LanguageArr, [item.language]: [{ ...item }] }
+      }
+    })
+    console.log(LanguageArr)
+
+    audioList.value = LanguageArr
     total.value = data.total
+    if (selectList.value !== undefined && selectList.value !== null) {
+      selectList.value = null //鍒濆鍖�
+    }
+    // 鍋滄褰撳墠鎾斁鐨勯煶棰�
+    if (SoundcurrentAudio.value) {
+      SoundcurrentAudio.value.pause()
+      SoundcurrentAudio.value = null
+    }
+
+    // 閲嶇疆褰撳墠鎾斁鐘舵��
+    if (SoundcurrentlyPlaying.value) {
+      SoundcurrentlyPlaying.value.isPlay = false
+      SoundcurrentlyPlaying.value = null
+    }
   } finally {
     soundLoading.value = false
   }
+}
+// 褰撳墠璇鏄剧ず
+const languageClass = (language) => {
+  let text = ''
+  languageList.value.forEach((element) => {
+    if (element.value === language) {
+      text = element.label
+    }
+  })
+  return text
 }
 // 璇閫夋嫨
 const LanguageChange = (event) => {
@@ -1122,15 +1165,30 @@
   SoundTypeList.value.forEach((element) => {
     if (element.value === event) {
       ChangeSoundTypeList.value = { ...element }
+
+      if (selectList.value !== undefined && selectList.value !== null) {
+        selectList.value = null //鍒濆鍖�
+      }
+      // 鍋滄褰撳墠鎾斁鐨勯煶棰�
+      if (SoundcurrentAudio.value) {
+        SoundcurrentAudio.value.pause()
+        SoundcurrentAudio.value = null
+      }
+
+      // 閲嶇疆褰撳墠鎾斁鐘舵��
+      if (SoundcurrentlyPlaying.value) {
+        SoundcurrentlyPlaying.value.isPlay = false
+        SoundcurrentlyPlaying.value = null
+      }
     }
   })
   getSoundModelList()
 }
 //閫夋嫨澹伴煶妯″瀷
 const selectList = ref()
-const handleSelect = (item) => {
+const handleSelect = (key, item) => {
   selectList.value = [item]
-  audioList.value.forEach((child) => {
+  audioList.value[key].forEach((child) => {
     if (child.id == item.id) {
       child.isSelect = true
     } else {
@@ -1147,11 +1205,14 @@
 })
 // 纭畾鎸夐挳鐐瑰嚮澶勭悊鍑芥暟
 const submitForm = () => {
-  console.log(ChangeSoundTypeList.value.value)
+  console.log(selectLanguage.value)
+  if (selectLanguage.value.value === 'all_Language') {
+    message.warning('璇峰皢璇鎸夐挳鐢卞叏閮ㄨ绉嶄慨鏀逛负鎮ㄩ渶瑕佺敓鎴愮殑澹伴煶鐨勬枃鏈殑璇绫诲瀷')
+    return false
+  }
   if (ChangeSoundTypeList.value.value === 2) {
     //姝ゆ椂涓洪�氱敤
-    console.log(selectList.value)
-    if (selectList.value === undefined) {
+    if (selectList.value === undefined || selectList.value === null) {
       message.warning('璇烽�夋嫨澹伴煶妯″瀷')
       return false
     }
@@ -1189,23 +1250,24 @@
     model: selectList.value !== undefined ? selectList.value : '' //澹伴煶妯″瀷
   }
 
-  SoundTool.value = false
-  rightTools.forEach((child) => {
-    if (child.name == '澹伴煶' || child.name == 'sound') {
-      child.isActive = false
-    }
-  })
+  // SoundTool.value = false
+
+  // rightTools.forEach((child) => {
+  //   if (child.name == '澹伴煶' || child.name == 'sound') {
+  //     child.isActive = false
+  //   }
+  // })
 }
 // 榧犳爣绉诲叆涓庣Щ鍑�
-const handleMouseenter = (item) => {
-  audioList.value.forEach((child) => {
+const handleMouseenter = (key, item) => {
+  audioList.value[key].forEach((child) => {
     if (child.id == item.id) {
       child.isHover = true
     }
   })
 }
-const handleMouseleave = (item) => {
-  audioList.value.forEach((child) => {
+const handleMouseleave = (key, item) => {
+  audioList.value[key].forEach((child) => {
     if (child.id == item.id) {
       child.isHover = false
     }
@@ -1431,7 +1493,7 @@
 }
 
 const chooseTemplate = (currTemplate) => {
-  console.log( "currTemplate", currTemplate)
+  console.log('currTemplate', currTemplate)
   selectTemplate.value = cloneDeep(currTemplate)
   templates.value.forEach((item) => {
     item.isActive = false
@@ -2078,6 +2140,13 @@
     language: selectLanguage.value?.value
   }
 
+  if (ChangeSoundTypeList.value.value === 2) {
+    //姝ゆ椂閫夊彇浜嗗0闊虫ā鍨�
+    params.humanId = null
+  } else if (ChangeSoundTypeList.value.value === 1) {
+    params.voiceId = null
+  }
+
   try {
     showAudioPlay1.value = true
     const res = await pptTemplateApi.createAudio(params)
@@ -2142,14 +2211,13 @@
 }
 
 const goBack = () => {
-  if (PPTArr.value.length==0) {
+  if (PPTArr.value.length == 0) {
     pptTemplateApi.coursesDelete(courseInfo.value.id).then((res) => {
       router.go(-1)
     })
-  }else {
+  } else {
     router.go(-1)
   }
-
 }
 
 const editorRef = shallowRef()
@@ -2878,60 +2946,71 @@
     height: 86%;
     margin: 10px 0;
     overflow-y: scroll;
-    display: flex;
-    flex-wrap: wrap;
-    align-content: flex-start;
-    > .ModealBox {
-      width: 47%;
-      margin: 10px 1%;
-      display: flex;
-      justify-content: space-around;
-      align-items: center;
-      position: relative;
-      > .ImgBox {
-        width: 26%;
+
+    .SoundModelAreaBox {
+      width: 100%;
+      .SoundClassTit {
+        width: 80%;
         margin: 0 auto;
-        img {
-          width: 100%;
+      }
+      .SoundClassContent {
+        width: 100%;
+        display: flex;
+        flex-wrap: wrap;
+        align-content: flex-start;
+        > .ModealBox {
+          width: 47%;
+          margin: 10px 1%;
+          display: flex;
+          justify-content: space-around;
+          align-items: center;
+          position: relative;
+          > .ImgBox {
+            width: 26%;
+            margin: 0 auto;
+            img {
+              width: 100%;
+            }
+          }
+          > .TextArea {
+            width: 48%;
+            p {
+              font-size: 12px;
+              margin: 4px 0;
+              padding-left: 6px;
+              box-sizing: border-box;
+              text-align: left;
+              word-wrap: break-word;
+            }
+          }
+          > .play-img {
+            width: 32px;
+            height: 32px;
+            cursor: pointer;
+            position: absolute;
+            top: 0;
+            right: 0;
+            left: 0;
+            bottom: 0;
+            margin: auto;
+            z-index: +10;
+          }
+        }
+        .ModealBox:hover {
+          background-color: #000;
+          opacity: 0.5;
+          border: 2px solid #0183f4;
+          > .TextArea {
+            p {
+              color: #fff;
+            }
+          }
+        }
+        > .slectModel {
+          border: 2px solid #1989fa;
+          border-radius: 6px;
         }
       }
-      > .TextArea {
-        width: 48%;
-        p {
-          font-size: 12px;
-          margin: 4px 0;
-          padding-left: 6px;
-          box-sizing: border-box;
-          text-align: left;
-          word-wrap: break-word;
-        }
-      }
-      > .play-img {
-        width: 32px;
-        height: 32px;
-        cursor: pointer;
-        position: absolute;
-        top: 0;
-        right: 0;
-        left: 0;
-        bottom: 0;
-        margin: auto;
-        z-index: +10;
-      }
-    }
-    .ModealBox:hover {
-      background-color: #000;
-      opacity: 0.5;
-      border: 2px solid #0183f4;
-      > .TextArea {
-        p {
-          color: #fff;
-        }
-      }
-    }
-    > .slectModel {
-      border: 2px solid #1989fa;
-      border-radius: 6px;
     }
   }
   .ButtonArea {
diff --git a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursescenevoices/vo/AppCourseSceneVoicesMegerReqVO.java b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursescenevoices/vo/AppCourseSceneVoicesMegerReqVO.java
index 6bc6dae..1bb345c 100644
--- a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursescenevoices/vo/AppCourseSceneVoicesMegerReqVO.java
+++ b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/controller/admin/coursescenevoices/vo/AppCourseSceneVoicesMegerReqVO.java
@@ -36,4 +36,5 @@
     @Schema(description = "鐘舵��", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private Integer status;
 
-}
\ No newline at end of file
+    private String language;
+}
diff --git a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/voices/AuditionVO.java b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/voices/AuditionVO.java
index 1a03ea0..ab27f9a 100644
--- a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/voices/AuditionVO.java
+++ b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/dal/dataobject/voices/AuditionVO.java
@@ -15,4 +15,5 @@
     //澹伴煶妯″瀷ID
     private String voiceId;
 
+    private String language;
 }
diff --git a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
index cdeb917..c2b1e80 100644
--- a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
+++ b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
@@ -119,6 +119,7 @@
         for (AppCourseScenesMegerReqVO scene : scenes) {
             //TODO 鍏堝垽鏂槸鍚︽湁澶囨敞鍐呭
             auditionVO.setText(scene.getBackground().getPptRemark());
+            auditionVO.setLanguage(scene.getVoice().getLanguage().toLowerCase());
             if (scene.getVoice().getVoiceId() == null){
                 auditionVO.setHumanId(String.valueOf(digitalHumansDO.getId()));
             }else{
diff --git a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java
index 4f677b7..80ccd3d 100644
--- a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java
+++ b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceImpl.java
@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.digitalcourse.service.voices;
 
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.lang.UUID;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpRequest;
@@ -16,11 +17,17 @@
 import cn.iocoder.yudao.module.digitalcourse.dal.mysql.voices.VoicesMapper;
 import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
 import cn.iocoder.yudao.module.infra.api.file.FileApi;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.digitalcourse.enums.ErrorCodeConstants.VOICES_NOT_EXISTS;
@@ -135,47 +142,136 @@
     private DigitalHumansMapper digitalHumansMapper;
     private static final String EASEGEN_URL = "easegen.url";
     private static final String HEYGEM_CORE_URL = "heygem.core.url";
+    private static final String HEYGEM_VOICE_DATA = "heygem.voice.data";
+
+    public static final Set<String> SUPPORTED_LANGUAGES = Set.of(
+            "en", "es", "fr", "de", "it", "pt", "pl", "tr", "ru",
+            "nl", "cs", "ar", "zh-cn", "hu", "ko", "ja", "hi"
+    );
+    // 涓嫳鏂囦笓鐢ㄦā鍨嬫敮鎸佺殑璇█
+    private static final Set<String> CN_EN_LANGUAGES = Set.of("zh-cn", "en");
+
     @Override
     public String audition(AuditionVO auditionVO) {
+        String language = auditionVO.getLanguage().toLowerCase();
+        // 鍒ゆ柇鏄惁鏄敮鎸佺殑璇█
+        if (!SUPPORTED_LANGUAGES.contains(language)) {
+            throw new IllegalArgumentException("涓嶆敮鎸佺殑璇█绫诲瀷: " + language);
+        }
+
+        // 鏋勫缓鍙傛暟
         InvokeVO invokeVO = new InvokeVO();
         invokeVO.setSpeaker(InvokeVO.generateUUID());
         invokeVO.setText(auditionVO.getText());
+
         if (auditionVO.getVoiceId() == null) {
             DigitalHumansDO digitalHumansDO = digitalHumansMapper.selectById(auditionVO.getHumanId());
             invokeVO.setReferenceText(digitalHumansDO.getReferenceAudioText());
             invokeVO.setReferenceAudio(digitalHumansDO.getAsrFormatAudioUrl());
-        }else if (auditionVO.getHumanId() == null){
+        } else if (auditionVO.getHumanId() == null) {
             VoicesDO voicesDO = voicesMapper.selectById(auditionVO.getVoiceId());
             invokeVO.setReferenceText(voicesDO.getReferenceAudioText());
             invokeVO.setReferenceAudio(voicesDO.getAsrFormatAudioUrl());
         }
-        ObjectMapper objectMapper = new ObjectMapper();
-        String jsonString = null;
-        try {
-            jsonString = objectMapper.writeValueAsString(invokeVO);
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException(e);
-        }
-        String configValueByKey = configApi.getConfigValueByKey(HEYGEM_CORE_URL);
-        String url = configValueByKey + "/v1/invoke";
-        HttpResponse execute = HttpRequest.post(url)
-                .body(jsonString)
-                .execute();
-
-        if (execute.getStatus() != 200) {
-            return null;
-        }
 
         String fileName = UUID.randomUUID().toString() + ".wav";
+        byte[] content;
 
-        // 鑾峰彇闊抽鏂囦欢鐨勪簩杩涘埗鏁版嵁
-        byte[] content = execute.bodyBytes();
+        try {
+            if (CN_EN_LANGUAGES.contains(language)) {
+                // 浣跨敤涓嫳鏂囨ā鍨�
+                String jsonString = new ObjectMapper().writeValueAsString(invokeVO);
+                String coreUrl = configApi.getConfigValueByKey(HEYGEM_CORE_URL) + "/v1/invoke";
+                HttpResponse response = HttpRequest.post(coreUrl)
+                        .body(jsonString)
+                        .execute();
 
-        // 浣跨敤 `createFile` 鏂规硶瀛樺偍鏂囦欢锛屽苟鑾峰彇 URL
-        String fileUrl = fileApi.createFile(fileName, null, content);
+                if (response.getStatus() != 200) {
+                    return null;
+                }
+                content = response.bodyBytes();
 
-        return fileUrl;  // 杩斿洖瀛樺偍鐨勬枃浠� URL
-        // 杩斿洖闊抽鏂囦欢璺緞
+            } else {
+                // 浣跨敤鍏朵粬璇█妯″瀷锛屽 http://127.0.0.1:5002/synthesize
+                String referenceAudio = invokeVO.getReferenceAudio();
+                String resultName = "";
+                if (referenceAudio != null) {
+                    if (referenceAudio.startsWith("/code/sessions/") || referenceAudio.startsWith("/code/data/")) {
+                        System.out.println("璺緞灞炰簬 /code/sessions/ 鎴� /code/data/");
+
+                        // 鍙彇绗竴涓矾寰勶紙浠||鍒嗗壊锛�
+                        String firstPath = referenceAudio.split("\\|\\|\\|")[0];
+
+                        // 鍙栨渶鍚庝竴绾ф枃浠跺悕
+                        String fileName1 = firstPath.substring(firstPath.lastIndexOf('/') + 1);
+
+                        String coreName;
+                        if (referenceAudio.startsWith("/code/sessions/")) {
+                            // sessions璺緞鍙兘鏈� _partN锛屽幓闄� _partN 鍙婂悗闈㈤儴鍒�
+                            int partIndex = fileName1.indexOf("_part");
+                            if (partIndex != -1) {
+                                coreName = fileName1.substring(0, partIndex);
+                            } else {
+                                // 娌℃湁_part锛屽幓鎺夋墿灞曞悕
+                                int dotIndex = fileName1.lastIndexOf('.');
+                                coreName = (dotIndex != -1) ? fileName1.substring(0, dotIndex) : fileName1;
+                            }
+                        } else {
+                            // data璺緞鐩存帴鍙栧畬鏁存枃浠跺悕锛堝嵆鏍煎紡鍚�+鍚庣紑锛�
+                            coreName = fileName1.substring(0, fileName1.lastIndexOf('.'));
+                        }
+
+                        // 鑾峰彇鍚庣紑
+                        int dotIndex = fileName1.lastIndexOf('.');
+                        String suffix = (dotIndex != -1) ? fileName1.substring(dotIndex) : "";
+
+                        // 鏈�缁堢粨鏋�
+                        resultName = coreName + suffix;
+
+                        System.out.println("鎻愬彇鐨勬牸寮忓悕锛�" + resultName);
+                    } else {
+                        // 鍏朵粬璺緞
+                        System.out.println("鏈煡璺緞绫诲瀷");
+                        throw new IllegalArgumentException("澹伴煶妯″瀷寮傚父锛岃鑱旂郴绠$悊鍛�");
+                    }
+                }
+                //resultName
+                String resultVoiceUrl = configApi.getConfigValueByKey(HEYGEM_VOICE_DATA)+"/origin_audio/" + resultName;
+                Map<String, Object> params = new HashMap<>();
+                params.put("text", auditionVO.getText());
+                params.put("speaker_wav", resultVoiceUrl);
+                params.put("language", language);
+
+                HttpResponse response = HttpRequest.post("http://127.0.0.1:5002/synthesize")
+                        .contentType("application/json")
+                        .body(new ObjectMapper().writeValueAsString(params))
+                        .execute();
+
+                if (response.getStatus() != 200) {
+                    return null;
+                }
+                String body = response.body();
+                JSONObject json = JSON.parseObject(body);
+
+                Integer code = json.getInteger("code");
+                String message = json.getString("message");
+
+                if (code == null || code != 200) {
+                    throw new RuntimeException("璇煶鍚堟垚澶辫触锛�" + message);
+                }
+
+                JSONObject outputPath = json.getJSONObject("output_path");
+                String diskPath = outputPath.getString("disk_path");
+                String url = outputPath.getString("url");
+
+                // 浣跨敤 diskPath 鍜� url
+                content = FileUtil.readBytes(diskPath);
+            }
+            // 淇濆瓨闊抽鏂囦欢骞惰繑鍥炲湴鍧�
+            return fileApi.createFile(fileName, null, content);
+        } catch (Exception e) {
+            throw new RuntimeException("璇煶鍚堟垚澶辫触", e);
+        }
 
 
     }
diff --git a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceUtil.java b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceUtil.java
index 0ababbb..f9211a8 100644
--- a/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceUtil.java
+++ b/yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/voices/VoicesServiceUtil.java
@@ -26,10 +26,7 @@
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
@@ -60,28 +57,65 @@
     private static final String HEYGEM_CORE_URL = "heygem.core.url";
     @Async
     public void remoteTrain(VoicesTrailVO trailVO){
+        // 鍒涘缓鐩爣鐩綍
         String origin_audio = configApi.getConfigValueByKey(HEYGEM_VOICE_DATA) + "/origin_audio";
-        //璁粌鍓嶆牎楠�
         try {
             Files.createDirectories(Path.of(origin_audio));
         } catch (IOException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("鍒涘缓鐩綍澶辫触: " + origin_audio, e);
         }
-        String extname = trailVO.getFixAuditionUrl().substring(trailVO.getFixAuditionUrl().lastIndexOf("."));
+
+        // 鑾峰彇婧愭枃浠剁殑鎵╁睍鍚嶏紙濡� .mp3 鎴� .wav锛�
+        String fixAuditionUrl = trailVO.getFixAuditionUrl();
+        String extname = fixAuditionUrl.substring(fixAuditionUrl.lastIndexOf("."));
+
+        // 鐢熸垚鐩爣鏂囦欢鍚嶏紙鍒濆涓哄師濮嬫墿灞曞悕锛�
         String modelFileName = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + extname;
-        String modelFilePath = Paths.get(origin_audio, modelFileName).toString();
+        Path modelFilePath = Paths.get(origin_audio, modelFileName);
 
-        String substring = configApi.getConfigValueByKey(EASEGEN_URL)+trailVO.getFixAuditionUrl().substring(trailVO.getFixAuditionUrl().lastIndexOf("/"));
+        // 鑾峰彇鏈湴婧愭枃浠惰矾寰勶紙鎷兼帴 EASEGEN_URL 鍜屾枃浠跺悕锛�
+        String substring = configApi.getConfigValueByKey(EASEGEN_URL) +
+                fixAuditionUrl.substring(fixAuditionUrl.lastIndexOf("/"));
+        Path sourcePath = Path.of(substring);
 
-        try {
-            Files.copy(Path.of(substring), Path.of(modelFilePath), StandardCopyOption.REPLACE_EXISTING);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+        // 濡傛灉涓嶆槸 .wav锛屽氨杞爜
+        if (!substring.toLowerCase(Locale.ROOT).endsWith(".wav")) {
+            // 鏋勯�� wav 璺緞锛堜笌鍘熻矾寰勫悓鐩綍锛�
+            String filename = sourcePath.getFileName().toString();
+            String nameWithoutExt = filename.substring(0, filename.lastIndexOf("."));
+            Path wavPath = sourcePath.resolveSibling(nameWithoutExt + ".wav");
+
+            // 鎵ц FFmpeg 鍛戒护
+            String ffmpegCmd = String.format("ffmpeg -y -i \"%s\" \"%s\"", sourcePath, wavPath);
+            try {
+                Process process = Runtime.getRuntime().exec(ffmpegCmd);
+                int exitCode = process.waitFor();
+                if (exitCode != 0) {
+                    throw new RuntimeException("FFmpeg 杞崲澶辫触锛岃繑鍥炵爜锛�" + exitCode);
+                }
+
+                // 杞崲鎴愬姛鍚庝娇鐢ㄦ柊鐨� .wav 璺緞浣滀负鏈�缁堟枃浠惰矾寰勶紙鐩爣鍚嶄篃鏀逛负 .wav锛�
+                modelFileName = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + ".wav";
+                modelFilePath = Paths.get(origin_audio, modelFileName);
+                Files.copy(wavPath, modelFilePath, StandardCopyOption.REPLACE_EXISTING);
+
+            } catch (IOException | InterruptedException e) {
+                throw new RuntimeException("鎵ц FFmpeg 杞崲澶辫触", e);
+            }
+
+        } else {
+            // 宸叉槸 .wav锛岀洿鎺ュ鍒�
+            try {
+                Files.copy(sourcePath, modelFilePath, StandardCopyOption.REPLACE_EXISTING);
+            } catch (IOException e) {
+                throw new RuntimeException("澶嶅埗 .wav 鏂囦欢澶辫触", e);
+            }
         }
+
 
         String configValueByKey = configApi.getConfigValueByKey(HEYGEM_VOICE_DATA);
         // 璁$畻鐩稿璺緞
-        Path relativeAudioPath = Path.of(configValueByKey).relativize(Path.of(modelFilePath));
+        Path relativeAudioPath = Path.of(configValueByKey).relativize(modelFilePath);
         Map<String, Object> map = Map.of(
                 "format", "wav",
                 "reference_audio", relativeAudioPath.toString().replace("\\", "/"),
@@ -100,6 +134,7 @@
                         .body(JSON.toJSONString(map))
                         .execute();
                 String body = execute.body();
+
 
                 // 妫�鏌ュ搷搴旂姸鎬佺爜鏄惁鎴愬姛
                 if (execute.getStatus() != 200) {
@@ -123,13 +158,35 @@
                 // 澶勭悊涓氬姟閫昏緫閿欒锛屾洿鏂扮姸鎬佸拰閿欒淇℃伅
                 String referenceAudioText = responseJson.getString("reference_audio_text");
                 String asrFormatAudioUrl = responseJson.getString("asr_format_audio_url");
+                if (referenceAudioText == null || asrFormatAudioUrl == null) {
+                    if (body.equals("{\"code\":-1,\"msg\":\"asr failed\"}")) {
+                        String a = origin_audio+"/format_denoise_"+modelFileName;
+                        String b = origin_audio+"/format_"+modelFileName;
+                        Path pathA = Path.of(a);
+                        Path pathB = Path.of(b);
+                        ///code/data/origin_audio/format_denoise_20250609090124273.wav
+                        if (Files.exists(pathA)) {
+                            asrFormatAudioUrl = "/code/data/origin_audio/format_denoise_" + modelFileName;
+                            referenceAudioText = "123";
+                        }else if (Files.exists(pathB)) {
+                            asrFormatAudioUrl = "/code/data/origin_audio/format_" + modelFileName;
+                            referenceAudioText = "123";
+                        }
 
+                    }else{
+                        // 濡傛灉娌℃湁杩斿洖棰勬湡鐨勫瓧娈碉紝璁や负鏄敊璇�
+                        voicesMapper.update(new UpdateWrapper<VoicesDO>().lambda().eq(VoicesDO::getCode, trailVO.getCode()).set(VoicesDO::getStatus, ERROR_STATUS));
+                        log.error("璁粌澶辫触锛�->>>>>>>>> 鏈繑鍥為鏈熺殑瀛楁");
+                        return;
+                    }
+
+                }
 
                 voicesMapper.update(
                         new UpdateWrapper<VoicesDO>()
                                 .lambda()
                                 .eq(VoicesDO::getCode, trailVO.getCode())  // 鏉′欢锛歝ode 绛変簬浼犲叆鐨勫��
-                                .set(VoicesDO::getStatus, 0)  // 鏇存柊瀛楁 status 涓� 0
+                                .set(VoicesDO::getStatus, COMPLETE_STATUS)  // 鏇存柊瀛楁 status 涓� 0
                                 .set(VoicesDO::getAsrFormatAudioUrl,asrFormatAudioUrl)
                                 .set(VoicesDO::getReferenceAudioText,referenceAudioText)
                 );

--
Gitblit v1.9.3