diff --git a/src/apis/createVideo.js b/src/apis/createVideo.js index 24c88bc..b62dfbc 100644 --- a/src/apis/createVideo.js +++ b/src/apis/createVideo.js @@ -180,4 +180,16 @@ export function findByIdApi(id) { url: `/api/userPhotoVideo/findById?id=${id}`, method: 'get', }) +} + +/** + * @description 获取音乐列表 + * @params data + * @returns data + */ +export function musicListApi() { + return request({ + url: `api/userPhotoVideo/music`, + method: 'get', + }) } \ No newline at end of file diff --git a/src/assets/img/star.png b/src/assets/img/star.png new file mode 100644 index 0000000..3b0137f Binary files /dev/null and b/src/assets/img/star.png differ diff --git a/src/lang/package/en.ts b/src/lang/package/en.ts index b192b79..d8bfbdf 100644 --- a/src/lang/package/en.ts +++ b/src/lang/package/en.ts @@ -69,6 +69,8 @@ export default { music:'Music', Aipicture:'Ai-generated pictures', AipictureTip:'Please customize your picture', + chooseMusic:'Choose music', + searchMusic:'Search music' }, // 我的视频 diff --git a/src/lang/package/zh-cn.ts b/src/lang/package/zh-cn.ts index f08c51b..ba5e6df 100644 --- a/src/lang/package/zh-cn.ts +++ b/src/lang/package/zh-cn.ts @@ -69,6 +69,8 @@ export default { music:'音乐', Aipicture:'Ai生成图片', AipictureTip:'请自定义您的图片', + chooseMusic:'选择音乐', + searchMusic:'搜索音乐', }, // 我的视频 diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index fe8e71d..22b58ff 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -16,12 +16,15 @@ -
- +
+
{{ $t("shop.title") }}
+
+
+ +
+ API +
@@ -103,7 +109,13 @@ function routerTo(url: RouteLocationRaw) { .pricing { position: absolute; - bottom: 20px; + bottom: 60px; + width: calc(100% - 40px); + text-align: center; + } + .API { + position: absolute; + bottom: 0px; width: calc(100% - 40px); text-align: center; } diff --git a/src/store/modules/userInfo.js b/src/store/modules/userInfo.js index f186337..2beeb57 100644 --- a/src/store/modules/userInfo.js +++ b/src/store/modules/userInfo.js @@ -9,11 +9,16 @@ export const userInfoModules = defineStore("userInfo", () => { function setEmail(params) { email.value = params } + // 登录获取用户信息 async function getUserInfo() { const res = await getUserInfoApi() userInfo.value = res.data } - return { userInfo, setEmail, getUserInfo }; + // 退出清除用户信息 + function loginOut(params) { + userInfo.value = null + } + return { userInfo, setEmail, getUserInfo, loginOut }; }, { persist: true, diff --git a/src/types/components.d.ts b/src/types/components.d.ts index cbeaaba..f5f10bc 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -53,9 +53,11 @@ declare module '@vue/runtime-core' { IEpCloseBold: typeof import('~icons/ep/close-bold')['default'] IEpCollection: typeof import('~icons/ep/collection')['default'] IEpDelete: typeof import('~icons/ep/delete')['default'] + IEpDocumentAdd: typeof import('~icons/ep/document-add')['default'] IEpDownload: typeof import('~icons/ep/download')['default'] IEpEdit: typeof import('~icons/ep/edit')['default'] IEpGoods: typeof import('~icons/ep/goods')['default'] + IEpHeadset: typeof import('~icons/ep/headset')['default'] IEpLoading: typeof import('~icons/ep/loading')['default'] IEpMenu: typeof import('~icons/ep/menu')['default'] IEpMic: typeof import('~icons/ep/mic')['default'] diff --git a/src/views/createVideo/index.vue b/src/views/createVideo/index.vue index 7436c33..db5bafc 100644 --- a/src/views/createVideo/index.vue +++ b/src/views/createVideo/index.vue @@ -159,10 +159,14 @@
+
+ GPT + +
{{ $t("createVideo.Aipicture") }}
@@ -239,6 +243,10 @@
+
+ GPT + +
@@ -348,7 +356,7 @@

- + {{ $t("createVideo.uploadAudio") }}

@@ -415,133 +423,167 @@
-
+ +

+ + {{ $t("createVideo.chooseMusic") }} +

+ +
- - {{ $t("createVideo.confirm") }} - - - - - +
-

{{ $t("createVideo.languages") }}

- +
+
+ {{ item.name }} + {{ handleTime(item.time) }} +
+
+
+ +
+ + - -
-

{{ $t("createVideo.voices") }}

- + {{ + $t("createVideo.saveVideo") + }} - - -

{{ $t("createVideo.styles") }}

- + - - - {{ - $t("createVideo.generateVideo") - }} + + {{ + $t("createVideo.generateVideo") + }} +
-
+
+ - - {{ $t("createVideo.confirm") }} - - - - - + 🔊 + 🕗

{{ $t("createVideo.languages") }}

+ + :label="item.name" + :value="item.id" + > + + {{ item.name }} +

{{ $t("createVideo.voices") }}

+

{{ $t("createVideo.styles") }}

+ - {{ - $t("createVideo.generateVideo") - }} + + + + {{ + $t("createVideo.saveVideo") + }} + + + + {{ + $t("createVideo.generateVideo") + }}
+
@@ -568,6 +610,7 @@ import { createVideoApi, previewAudioApi, findByIdApi, + musicListApi, } from "@/apis/createVideo"; import { useI18n } from "vue-i18n"; import Recorder from "js-audio-recorder"; //mp3插件 @@ -1025,7 +1068,7 @@ async function saveOrUpdate(index, isSaveVideo) { if (createLoading.value == true) { return; } - tabFrom.value = index; + tabFrom.value = index; // 判断是哪一个tab栏内的生成视频按钮 const saveOrUpdateData = { id: id.value, //从草稿或者重新编辑回到创建视频时有id title: title.value, @@ -1035,6 +1078,7 @@ async function saveOrUpdate(index, isSaveVideo) { speakTypeStr: soundStyle.value, //声音风格 voiceMouldId: sound.value, //选择声音id voiceFrom=1 时必传 voiceMaterialId: afterSaveAudioId.value, //上传音频且保存音频后得到的id voiceFrom=2 时必传 + musicId: musicItemAction.value, // 选中音乐的id,voiceFrom=3 时必传 }; if (index == 1) { createLoading.value = true; @@ -1072,6 +1116,35 @@ async function saveOrUpdate(index, isSaveVideo) { createLoading.value = false; } } + if (index == 3) { + try { + const res1 = await saveOrUpdateApi(saveOrUpdateData); // 保存数据 + + // 这个if判断是不是仅仅保存视频 + if (isSaveVideo == "saveVideo") { + ElMessage.success( + lanChange.value == "zh-cn" ? `已保存为草稿` : `Saved as manuscript` + ); + createLoading.value = false; + router.push("/myCreating"); + return; + } + console.log("ceshi"); + const res2 = await createVideoApi({ id: res1.data.id }); // 生成视频 + if (res2.message == "success") { + ElMessage.success( + lanChange.value == "zh-cn" + ? `视频正在生成中,请耐心等待` + : `The video is being generated, please wait patiently` + ); + } + createLoading.value = false; + router.push("/myCreating"); + } catch (error) { + ElMessage.error(error); + createLoading.value = false; + } + } } //#endregion ---------------------------- @@ -1087,14 +1160,56 @@ async function findById(findId) { afterSaveAudioId.value = res.data.voiceMaterialId; //保存音频后得到的id imgUrl.value = res.data.personPhotoUrl; //图片回显 audioUrl.value = res.data.voiceMaterialUrl; // mp3回显 - language.value = res.data.voiceInfo.languageId; - await chooseType(language.value); + musicItemAction.value = res.data.musicId; //音乐id回显 + language.value = res.data.voiceInfo ? res.data.voiceInfo.languageId : null; + if (language.value) { + await chooseType(language.value); + } sound.value = res.data.voiceMouldId; //声音id chooseStyle(); soundStyle.value = res.data.speakTypeStr; //选择风格 } //#endregion ---------------------------- +//#region 音乐tab +const musicList = ref(null); //展示音乐列表 +const audioMusicUrl = ref(null); //选中音乐Url回显 +const musicItemAction = ref(null); //选中高亮 +// 获取音乐列表 +async function getMusicList() { + try { + const res = await musicListApi(); + musicList.value = res.data; + } catch (error) { + console.log(error); + } +} +// 点击选择音乐 +function chooseMusicUrl(url, id) { + audioMusicUrl.value = url; + musicItemAction.value = id; +} +// 转化秒为分秒 +function handleTime(time) { + let m = Math.floor(time / 60); + let s = time % 60; + if (s < 10) { + s = "0" + s; + } + return m + ":" + s; +} +// 搜索功能 +const searchInput = ref(null); +async function searchMusicList() { + // const res = await + console.log("搜索"); +} +//#endregion ---------------------------- + +//#region + +//#endregion ---------------------------- + //#region //#endregion ---------------------------- @@ -1116,8 +1231,15 @@ onMounted(async () => { } await voiceTotal(); if (route.query.id) { - findById(route.query.id); + await findById(route.query.id); } + await getMusicList(); + + musicList.value.forEach((item) => { + if (item.id == musicItemAction.value) { + audioMusicUrl.value = item.url; + } + }); }); @@ -1342,7 +1464,7 @@ onMounted(async () => { padding: 10px; > div { margin-right: 20px; - padding: 5px 10px; + padding: 10px 15px; transition: all 0.3s; border-radius: 5px; &:hover { @@ -1470,6 +1592,38 @@ onMounted(async () => { background-size: 200% 100% !important; } } + .aiPicTab { + position: relative; + z-index: 2; + .subscript { + position: absolute; + top: -20px; + right: -20px; + width: 40px; + height: 40px; + + z-index: 1; + img { + position: absolute; + top: 0; + left: 0px; + width: 100%; + height: 100%; + z-index: 3; + } + span { + position: absolute; + line-height: 45px; + z-index: 4; + padding-left: 0px; + padding-bottom: 5px; + font-size: 16px; + color: #17ceb9; + font-weight: 900; + transform: rotate(45deg); + } + } + } } } @@ -1479,6 +1633,36 @@ onMounted(async () => { padding: 30px 30px 20px 30px; background-color: #f1f2f6; border-radius: 30px 0 0 0; + position: relative; + z-index: 2; + + .subscript { + position: absolute; + top: 30px; + right: 30px; + width: 40px; + height: 40px; + z-index: 3; + img { + position: absolute; + top: 0; + left: 0px; + width: 100%; + height: 100%; + z-index: 3; + } + span { + position: absolute; + line-height: 45px; + z-index: 4; + padding-left: 0px; + padding-bottom: 5px; + font-size: 16px; + color: #17ceb9; + font-weight: 900; + transform: rotate(45deg); + } + } :deep(.el-tabs--border-card) { font-size: 20px; border: none; @@ -1488,6 +1672,7 @@ onMounted(async () => { height: 100%; padding: 20px 20px 0px 20px; border-radius: 20px; + .card1 { .text { padding: 10px; @@ -1607,10 +1792,89 @@ onMounted(async () => { } } .card3 { + width: 100%; + padding: 10px; + .el-icon { + vertical-align: text-top; + } + .musicList { + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + .musicItem { + width: 100%; + height: 30px; + position: relative; + margin-top: 10px; + padding: 0 20px; + border: #000 1px solid; + border-radius: 10px; + overflow: hidden; + transition: all 0.3s; + box-shadow: #00000026 2px 2px 2px 2px; + transition: all 0.3s; + cursor: pointer; + .musicNmae { + display: inline-block; + width: 320px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .musicTime { + display: inline-block; + max-width: 300px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + .musicItemAvtive { + background-color: #000; + color: #fff; + } + } + .AudioBox { + display: flex; + justify-content: space-around; + width: 100%; + padding: 20px; + transition: all 0.3s; + audio { + width: 100%; + } + } + > .el-button { + width: 100%; + height: 50px; + margin-top: 10px; + // background-color: #000; + } + :deep(.el-input__wrapper) { + border: none; + border-bottom: 2px solid #000; + border-radius: 0; + box-shadow: none; + } + + .el-icon.icon-edit { + width: 30px; + height: 30px; + font-size: 30px; + color: #8c939d; + text-align: center; + cursor: pointer; + transition: all 0.3s; + &:hover { + color: #292929; + } + } + } + .card4 { .text { padding: 10px; border: 1px solid #000; - .el-button { float: right; margin-top: 10px; @@ -1623,7 +1887,7 @@ onMounted(async () => { } p { - margin: 10px 0; + margin: 7px 0; } > .el-button { @@ -1631,8 +1895,12 @@ onMounted(async () => { height: 50px; margin-top: 10px; } - } + :deep(.el-input .is-focus) { + // box-shadow: none !important; + // box-shadow: 0 0 0 1px #000 !important; + } + } :deep(.el-tabs__item.is-active) { color: #909393; background-color: #000; @@ -1643,7 +1911,7 @@ onMounted(async () => { } :deep(.el-tabs__item) { - width: 25%; + width: 26%; } :deep(.el-tabs__item:hover) {