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