|
- <template>
- <div class="page flex justify-around">
- <!-- 遮罩层 -->
- <div class="mask" v-show="showChooseModel"></div>
- <!-- 左侧栏 -->
- <div class="left">
- <!-- 字幕框 -->
- <div v-show="videoType == 2" class="subtitlesBoxTop">
- <!-- 开关 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>{{ $t("createVideo.subtitlesSwitch") }}</p>
- <el-switch
- v-model="Subtitles.SubtitlesSwitch"
- style="--el-switch-on-color: #000"
- />
- </div>
- </div>
- <!-- 字体系列 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `字体` : `Font Family` }}
- </p>
- <el-select
- v-model="Subtitles.SubtitlesFontFamily"
- style="width: 100px"
- placeholder=" "
- size="default"
- >
- <el-option
- v-for="item in Subtitles.fontFamilyList"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </div>
- </div>
- <!-- y轴 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `纵坐标` : `Y-axis` }}
- </p>
- <el-input-number
- :precision="0"
- v-model="Subtitles.SubtitlesTop"
- size="large"
- controls-position="right"
- />
- </div>
- </div>
- <!-- 字号大小 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }}
- </p>
- <el-select
- v-model="Subtitles.SubtitlesSize"
- style="width: 100px"
- placeholder=" "
- size="default"
- >
- <el-option
- v-for="item in Subtitles.fontSizeList"
- :key="item"
- :label="item"
- :value="item"
- :style="{
- height: item + 'px',
- lineHeight: item + 'px',
- }"
- >
- <span :style="{ fontSize: item + 'px', padding: '5px' }">{{
- item
- }}</span>
- </el-option>
- </el-select>
- </div>
- </div>
- <!-- 字色 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `字体颜色` : `Font Color` }}
- </p>
- <div
- @click="handleSubtitlesColorShow"
- class="myColorBox"
- :style="{ backgroundColor: Subtitles.SubtitlesColor }"
- >
- <div v-show="SubtitlesColorShow" class="selectColor">
- <div
- v-for="item in Subtitles.colorList"
- :style="{ backgroundColor: item }"
- class="selectColor-item"
- @click="Subtitles.SubtitlesColor = item"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div v-show="videoType == 1" class="subtitlesBoxLeft">
- <!-- 开关 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>{{ $t("createVideo.subtitlesSwitch") }}</p>
- <el-switch
- v-model="Subtitles.SubtitlesSwitch"
- style="--el-switch-on-color: #000"
- />
- </div>
- </div>
- <!-- 字体系列 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `字体` : `Font Family` }}
- </p>
- <el-select
- v-model="Subtitles.SubtitlesFontFamily"
- style="width: 100px"
- placeholder=" "
- size="default"
- >
- <el-option
- v-for="item in Subtitles.fontFamilyList"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </div>
- </div>
- <!-- y轴 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `纵坐标` : `Y-axis` }}
- </p>
- <el-input-number
- :precision="0"
- v-model="Subtitles.SubtitlesTop"
- size="large"
- controls-position="right"
- />
- </div>
- </div>
- <!-- 字号大小 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }}
- </p>
- <el-select
- v-model="Subtitles.SubtitlesSize"
- style="width: 100px"
- placeholder=" "
- size="default"
- >
- <el-option
- v-for="item in Subtitles.fontSizeList"
- :key="item"
- :label="item"
- :value="item"
- :style="{
- height: item + 'px',
- lineHeight: item + 'px',
- }"
- >
- <span :style="{ fontSize: item + 'px', padding: '5px' }">{{
- item
- }}</span>
- </el-option>
- </el-select>
- </div>
- </div>
- <!-- 字色 -->
- <div class="tab4Item">
- <div v-if="materialList.BGI.material" class="SubtitlesSwitch">
- <p>
- {{ lanChange == "zh-cn" ? `字体颜色` : `Font Color` }}
- </p>
- <div
- @click="handleSubtitlesColorShow"
- class="myColorBox"
- :style="{ backgroundColor: Subtitles.SubtitlesColor }"
- >
- <div v-show="SubtitlesColorShow" class="selectColor">
- <div
- v-for="item in Subtitles.colorList"
- :style="{ backgroundColor: item }"
- class="selectColor-item"
- @click="Subtitles.SubtitlesColor = item"
- ></div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 选择模版弹出框 -->
- <div class="chooseModelBox" :class="showChooseModel ? '' : 'noModel'">
- <!-- 伸缩按钮 -->
- <div
- v-if="showChooseModel && videoType"
- class="shrinkBtn"
- @click="showChooseModel = false"
- >
- >
- </div>
- <div
- v-if="!showChooseModel"
- class="shrinkBtn"
- @click="showChooseModel = true"
- >
- <
- </div>
- <!-- tab栏 -->
- <p>{{ $t("createVideo.sex") }}</p>
- <div class="tab" v-show="showChooseModel">
- <div
- class="tabItem"
- :class="modelTabItemActive == -1 ? 'tabItemActive' : ''"
- @click="changeTabSex(-1)"
- >
- {{ $t("createVideo.all") }}
- </div>
- <div
- class="tabItem"
- :class="modelTabItemActive == 1 ? 'tabItemActive' : ''"
- @click="changeTabSex(1)"
- >
- {{ $t("createVideo.male") }}
- </div>
- <div
- class="tabItem"
- :class="modelTabItemActive == 2 ? 'tabItemActive' : ''"
- @click="changeTabSex(2)"
- >
- {{ $t("createVideo.female") }}
- </div>
- </div>
- <p>{{ $t("createVideo.videoRatio") }}</p>
- <div class="tab" v-show="showChooseModel">
- <div
- class="tabItem"
- :class="modelTabItemActive2 == -1 ? 'tabItemActive' : ''"
- @click="changeTabVideoType(-1)"
- >
- {{ $t("createVideo.all") }}
- </div>
- <div
- class="tabItem"
- :class="modelTabItemActive2 == 2 ? 'tabItemActive' : ''"
- @click="changeTabVideoType(2)"
- >
- {{ $t("createVideo.landscape") }}
- </div>
- <div
- class="tabItem"
- :class="modelTabItemActive2 == 1 ? 'tabItemActive' : ''"
- @click="changeTabVideoType(1)"
- >
- {{ $t("createVideo.portrait") }}
- </div>
- </div>
- <!-- 模版列表 -->
- <div
- class="modeListBox"
- v-show="showChooseModel"
- v-infinite-scroll="loadMoreModel"
- :infinite-scroll-disabled="overLoadModel"
- >
- <div
- :class="modelId == item.id ? 'modeListBoxItmeActive' : ''"
- class="modeListBoxItme"
- v-for="item in modeList"
- :key="item.id"
- @click="clickModelItem(item)"
- >
- <img class="boxCentreImg" :src="item.coverImg" alt="" />
- </div>
- </div>
- </div>
- <!-- 展示区 -->
- <div class="showModelImgBox">
- <!-- <img :src="modelImg" alt="" /> -->
- <!-- 编辑图片位置组件 -->
- <div
- :class="videoType == 1 ? 'EditPositionBox1' : 'EditPositionBox2'"
- class=""
- >
- <EditPosition
- ref="EditPositionDom"
- id="editPosition"
- :materialList="materialList"
- :videoType="videoType"
- :proportion="proportion"
- :showImgInfo="showImgInfo"
- :Subtitles="Subtitles"
- >
- </EditPosition>
- </div>
- <!-- 控制台 -->
- <div v-if="showImgInfo.data" class="showImgInfoBox">
- <!-- <div class="infoItem">
- </div> -->
- <div class="ItemName">{{ $t("createVideo.abscissa") }}</div>
- <div class="ItemValue">
- <el-input-number
- :precision="0"
- v-model="showImgInfo.data.x"
- size="large"
- controls-position="right"
- />
- </div>
- <div class="ItemName">{{ $t("createVideo.ordinate") }}</div>
- <div class="ItemValue">
- <el-input-number
- :precision="0"
- v-model="showImgInfo.data.y"
- size="large"
- controls-position="right"
- />
- </div>
- <div class="ItemName">{{ $t("createVideo.hierarchy") }}</div>
- <div class="ItemValue">
- <el-input-number
- v-model="showImgInfo.data.z"
- :min="1"
- :max="10"
- size="large"
- controls-position="right"
- />
- </div>
- <div class="ItemName">{{ $t("createVideo.ratio") }}</div>
- <div class="ItemValue">
- <el-input-number
- :precision="2"
- v-model="showImgInfo.data.w"
- :min="0.4"
- :max="1.3"
- size="large"
- controls-position="right"
- />
- </div>
- </div>
- <!-- 保存视频和生成视频 -->
- <div class="btnBox" v-show="!showChooseModel">
- <div
- @click="saveOrUpdate('isSave')"
- class="customBtn"
- style="margin-right: 15px"
- >
- <MyLoadingIcon :isLoading="saveLoading"></MyLoadingIcon>
- <div v-if="!saveLoading">
- {{ $t("createVideo.saveVideo") }}
- </div>
- </div>
- <div @click="createVideo" class="customBtn">
- <MyLoadingIcon :isLoading="createLoading"></MyLoadingIcon>
- <div v-if="!createLoading">
- {{ $t("createVideo.generateVideo") }}
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 右侧栏 -->
- <div class="right">
- <!-- tab栏 -->
- <div class="tab">
- <div
- id="tab-0"
- class="tabItem"
- :class="tabItemActive == 1 ? 'tabItemActive' : ''"
- @click="tabItemActive = 1"
- >
- {{ $t("createVideo.copywriting") }}
- </div>
- <div
- class="tabItem"
- :class="tabItemActive == 2 ? 'tabItemActive' : ''"
- @click="tabItemActive = 2"
- >
- {{ $t("createVideo.BackgroundImage") }}
- </div>
- <div
- class="tabItem"
- :class="tabItemActive == 3 ? 'tabItemActive' : ''"
- @click="tabItemActive = 3"
- >
- {{ $t("createVideo.material") }}
- </div>
- <div
- class="tabItem"
- :class="tabItemActive == 4 ? 'tabItemActive' : ''"
- @click="tabItemActive = 4"
- >
- {{ $t("createVideo.subtitles") }}
- </div>
- <!-- <div
- class="tabItem"
- :class="tabItemActive == 5 ? 'tabItemActive' : ''"
- @click="tabItemActive = 5"
- >
- {{ $t("createVideo.AItext") }}
- </div> -->
- </div>
- <!-- 文案 只能使用v-if,不能使用v-show-->
- <div v-if="tabItemActive == 1" class="tabContent tab1">
- <!-- 标题 -->
- <div class="title">
- <el-input
- style="width: 90%"
- maxlength="15"
- v-model="title"
- :placeholder="$t('createVideo.typeTitle')"
- />
- <el-icon class="icon-edit"><i-ep-edit /></el-icon>
- </div>
- <!-- 文本域 -->
- <div class="text">
- <!-- 文本域 -->
- <el-input
- maxlength="1000"
- id="textInputId"
- v-model="textareaContent"
- :rows="15"
- type="textarea"
- :placeholder="$t('createVideo.aiText')"
- />
-
- <span
- style="margin-right: 10px; font-size: 20px"
- class="pointer"
- @click="insertIcon"
- >
- <el-tooltip
- class="box-item"
- effect="dark"
- :content="$t('createVideo.tooltip2')"
- placement="bottom"
- >
- 🕗
- </el-tooltip>
- </span>
- <i style="float: right; font-size: 14px; padding-top: 5px"
- >{{ $t("createVideo.entered") }} {{ textareaContent.length }} /
- 1000</i
- >
- </div>
- <p>{{ $t("createVideo.languages") }}</p>
- <!-- 语言 -->
- <el-select
- @change="chooseType"
- v-model="language"
- :placeholder="$t('createVideo.select')"
- style="width: 100%"
- >
- <el-option
- v-for="item in languageOptions"
- :key="item.value"
- :label="lanChange == 'zh-cn' ? item.chineseName : item.name"
- :value="item.id"
- >
- <img
- :src="item.img"
- alt=""
- style="width: 20px; margin-right: 10px; vertical-align: text-top"
- />
- <span style="line-height: 20px">{{
- lanChange == "zh-cn" ? item.chineseName : item.name
- }}</span>
- </el-option>
- </el-select>
- <p>{{ $t("createVideo.voices") }}</p>
- <!-- 声音 -->
- <el-select
- @change="chooseStyle"
- :disabled="language ? false : true"
- v-model="sound"
- :placeholder="$t('createVideo.select')"
- style="width: 100%"
- >
- <el-option
- v-for="item in soundOptions"
- :key="item.value"
- :label="
- (lanChange == 'zh-cn'
- ? item.displayName + ` (${item.sex == 1 ? '男' : '女'})`
- : item.localName +
- ` (${item.sex == 1 ? 'male' : 'female'})`) +
- returnAge(item.ageType)
- "
- :value="item.id"
- />
- </el-select>
- <p>{{ $t("createVideo.styles") }}</p>
- <!-- 风格 -->
- <el-select
- :disabled="soundStyleOptions ? false : true"
- v-model="soundStyle"
- :placeholder="$t('createVideo.select')"
- style="width: 100%"
- >
- <el-option
- v-for="item in soundStyleOptions"
- :key="item.name"
- :label="lanChange == 'zh-cn' ? item.name : item.engName"
- :value="item.name"
- >
- <div style="padding: 0 20px">
- {{ lanChange == "zh-cn" ? item.name : item.engName }}
- <span
- style="float: right; cursor: pointer"
- @click.stop="ListenVoices(item.url)"
- >🔊</span
- >
- </div>
- </el-option>
- </el-select>
- </div>
- <!-- 背景 -->
- <div v-if="tabItemActive == 2" class="tabContent tab2">
- <div class="tab">
- <div
- class="tabItem"
- :class="bjTabItemActive == 1 ? 'tabItemActive' : ''"
- @click="changeBjTabItemActive(1)"
- >
- {{ $t("createVideo.systemBGI") }}
- </div>
- <div
- class="tabItem"
- :class="bjTabItemActive == 2 ? 'tabItemActive' : ''"
- @click="changeBjTabItemActive(2)"
- >
- {{ $t("createVideo.personBGI") }}
- </div>
- </div>
- <!-- 系统背景图片展示 -->
- <div
- v-if="bjTabItemActive == 1"
- class="bjSystemBox"
- v-infinite-scroll="loadMoreSystemBGI"
- :infinite-scroll-disabled="overLoadSystemBG"
- >
- <div
- class="bjSystemBoxItem"
- v-for="item in systemBGIList"
- :key="item.id"
- :class="bjImgActive == item.id ? 'ImgBorderActive' : ''"
- @click="selectBjImg(item)"
- >
- <img class="boxCentreImg" :src="item.material" alt="" />
- </div>
- </div>
- <!-- 个人背景图片展示 -->
- <div
- v-if="bjTabItemActive == 2"
- class="bjSystemBox"
- v-infinite-scroll="loadMorePersonBGI"
- :infinite-scroll-disabled="overLoadpersonBG"
- >
- <!-- 上传个人背景 -->
- <div class="bjSystemBoxItem">
- <img
- class="boxCentreImg"
- src="../../assets/img/uploadImg.png"
- alt=""
- />
- <cutImg
- @reGetpersonBGIList="reGetpersonBGIList"
- :type="4"
- :videoType="videoType"
- style="width: 100%; height: 100%"
- ></cutImg>
- </div>
- <div
- class="bjSystemBoxItem"
- v-for="item in personBGIList"
- :key="item.id"
- :class="bjImgActive == item.id ? 'ImgBorderActive' : ''"
- @click="selectBjImg(item)"
- >
- <div
- v-show="bjImgActive == item.id"
- class="delIcon"
- @click="delImg(item.id)"
- >
- <img src="../../assets/img/delete.png" alt="" />
- </div>
- <img class="boxCentreImg" :src="item.material" alt="" />
- </div>
- </div>
- </div>
- <!-- 素材 -->
- <div v-if="tabItemActive == 3" class="tabContent tab3">
- <div class="tab">
- <div
- class="tabItem"
- :class="scTabItemActive == 1 ? 'tabItemActive' : ''"
- @click="changeScTabItemActive(1)"
- >
- {{ $t("createVideo.systemMaterial") }}
- </div>
- <div
- class="tabItem"
- :class="scTabItemActive == 2 ? 'tabItemActive' : ''"
- @click="changeScTabItemActive(2)"
- >
- {{ $t("createVideo.personMaterial") }}
- </div>
- </div>
- <!-- 系统素材图片展示 -->
- <div
- v-if="scTabItemActive == 1"
- class="bjSystemBox"
- v-infinite-scroll="loadMoreSystemSCI"
- :infinite-scroll-disabled="overLoadSystemSC"
- >
- <div
- class="bjSystemBoxItem"
- v-for="item in systemSCIList"
- :key="item.id"
- :class="scImgActive == item.id ? 'ImgBorderActive' : ''"
- @click="selectScImg(item)"
- >
- <img class="boxCentreImg" :src="item.material" alt="" />
- </div>
- </div>
- <!-- 个人素材图片展示 -->
- <div
- v-if="scTabItemActive == 2"
- class="bjSystemBox"
- v-infinite-scroll="loadMorePersonSCI"
- :infinite-scroll-disabled="overLoadpersonSC"
- >
- <div class="bjSystemBoxItem">
- <img
- class="boxCentreImg"
- src="../../assets/img/uploadImg.png"
- alt=""
- />
- <cutImg
- @reGetpersonSCIList="reGetpersonSCIList"
- :type="5"
- :videoType="videoType"
- style="width: 100%; height: 100%"
- ></cutImg>
- </div>
- <div
- class="bjSystemBoxItem"
- v-for="item in personSCIList"
- :key="item.id"
- :class="scImgActive == item.id ? 'ImgBorderActive' : ''"
- @click="selectScImg(item)"
- >
- <div
- v-show="scImgActive == item.id"
- class="delIcon"
- @click="delImg(item.id)"
- >
- <img src="../../assets/img/delete.png" alt="" />
- </div>
- <img class="boxCentreImg" :src="item.material" alt="" />
- </div>
- </div>
- </div>
- <!-- 智能文案 -->
- <div v-if="tabItemActive == 4" class="tabContent tab4">
- <div class="card4">
- <!-- 语言 -->
- <div class="text">
- <!-- 文本域 -->
- <el-input
- maxlength="200"
- id="textInputId"
- v-model="problemContent"
- :rows="5"
- type="textarea"
- :placeholder="$t('createVideo.inputRequirement')"
- />
- </div>
- <el-button
- type="primary"
- :disabled="sendLoading"
- @click="sendRequirement"
- color="#000"
- >
- <my-Loading-Icon2 v-if="sendLoading"></my-Loading-Icon2>
- <span v-if="!sendLoading">
- {{ $t("createVideo.GeneratedText") }}
- </span>
- </el-button>
-
- <p>{{ $t("createVideo.SmartText") }}</p>
- <!-- 语言 -->
- <div class="text" style="cursor: text">
- <!-- 文本域 -->
- <el-input
- maxlength="500"
- id="textInputId"
- v-model="answerContent"
- :rows="15"
- type="textarea"
- disabled=""
- />
- <i
- >{{ $t("createVideo.entered") }} {{ answerContent.length }} /
- 500</i
- >
- </div>
- <el-button color="#000" @click="copyAnswerContent">
- {{ $t("createVideo.copy") }}
- </el-button>
- </div>
- </div>
- </div>
- <!-- 试听的mp3 -->
- <div style="opacity: 0; width: 0">
- <audio autoplay :src="previewAudioUrl" id="audio"></audio>
- </div>
- </div>
- </template>
-
- <!-- videoType==1为竖,==2为横 -->
- <script setup>
- //#region 导入
- import { getCurrentInstance } from "vue";
- import {
- modeListApi,
- voiceTotalApi,
- chooseTypeApi,
- previewAudioApi,
- systemBGIListApi,
- personBGIListApi,
- systemSCIListApi,
- personSCIListApi,
- delImgApi,
- personPatchApi,
- saveOrUpdateApi,
- createVideoApi,
- getModelDetailByIdApi,
- } from "@/apis/createVideo";
- import { useI18n } from "vue-i18n";
- import Recorder from "js-audio-recorder"; //mp3插件
- import imageCompression from "browser-image-compression"; //压缩图片插件
- import { useRoute, useRouter } from "vue-router";
- import cutImg from "@/components/cutImg.vue";
- //#endregion -----------------------------------
-
- const route = useRoute();
- const router = useRouter();
- const { locale } = useI18n();
- const lanChange = ref(locale);
- const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录
-
- // ElMessage.error(
- // lanChange.value == "zh-cn"
- // ? `您还没有输入文案`
- // : `You have not entered the copy yet`
- // );
-
- //#region 选择模版弹出框
- const videoType = ref(null); //判断横屏2还是竖屏1,初始为没有,控制按钮显隐
- const showChooseModel = ref(true); // 控制弹窗显示隐藏
- const modeList = ref([]); //模版列表
- const modelImg = ref(null); //模版回显图
- const modelTabItemActive = ref(-1); //模版tab栏 性别
- const modelTabItemActive2 = ref(-1); //模版tab栏 比例
- const modelPageNum = ref(1);
- const modelPageSize = ref(20);
- const overLoadModel = ref(true); //禁用模版加载更多
- const modelId = ref(null); // 选中模版的id
- // 获取模版列表
- async function getModeList(sex, pageNum, pageSize, videoType) {
- try {
- const res = await modeListApi(sex, pageNum, pageSize, videoType);
- modeList.value = res.data.list;
- overLoadModel.value = false;
- } catch (error) {
- // ElMessage.success(msg);
- }
- }
- // 点击模版
- function clickModelItem(item) {
- modelImg.value = item.coverImg;
- showChooseModel.value = false;
- videoType.value = item.videoType;
- modelId.value = item.id;
- }
- // tab栏切换 性别
- // tab栏切换 横竖比例 videoType==1为竖,==2为横,==-1为全部
- const tabSex = ref(-1);
- const tabVideoType = ref(-1);
- function changeTabSex(index) {
- modeList.value = [];
- modelPageNum.value = 1;
- modelTabItemActive.value = index;
- tabSex.value = false;
- tabSex.value = index;
- getModeList(
- index,
- modelPageNum.value,
- modelPageSize.value,
- tabVideoType.value
- );
- }
- function changeTabVideoType(index) {
- modeList.value = [];
- modelPageNum.value = 1;
- modelTabItemActive2.value = index;
- overLoadModel.value = false;
- tabVideoType.value = index;
- getModeList(
- tabSex.value,
- modelPageNum.value,
- modelPageSize.value,
- tabVideoType.value
- );
- }
- // watch(tabSex, (newVal, oldVal) => {
- // if (newVal == 0) {
- // getModeList("", modelPageNum.value, modelPageSize.value);
- // } else {
- // }
- // });
-
- // function changeTabSex(index) {
- // modeList.value = [];
- // modelPageNum.value = 1;
- // modelTabItemActive.value = index;
- // overLoadModel.value = false;
- // if (index == 0) {
- // getModeList("", modelPageNum.value, modelPageSize.value);
- // } else {
- // getModeList(index, modelPageNum.value, modelPageSize.value);
- // }
- // }
- // 触底刷新
- async function loadMoreModel(params) {
- modelPageNum.value += 1;
- const res = await modeListApi(
- tabSex.value,
- modelPageNum.value,
- modelPageSize.value,
- tabVideoType.value
- );
- modeList.value.push(...res.data.list);
- if (res.data.list.length == 0) {
- overLoadModel.value = true;
- modelPageNum.value = modelPageNum.value - 1;
- }
- }
- //#endregion ----------------------------
-
- //#region 右侧tab栏切换
- const tabItemActive = ref(1);
- //#endregion ----------------------------
-
- //#region 文案及其音频
- const title =
- lanChange.value == "zh-cn" ? ref("未定义标题") : ref("Undefined Title");
- const textareaContent = ref("");
- function insertIcon() {
- const textarea = document.getElementById("textInputId");
- const icon = "🕗"; // 这里使用了一个星星作为示例图标,你可以替换为你自己的图标
- // 获取光标位置
- const startPos = textarea.selectionStart;
- const endPos = textarea.selectionEnd;
- // 在光标位置插入图标
- textareaContent.value =
- textareaContent.value.substring(0, startPos) +
- icon +
- textareaContent.value.substring(endPos, textareaContent.value.length);
-
- // 设置光标位置为插入图标后的位置
- const newCursorPos = startPos + icon.length;
- textarea.setSelectionRange(newCursorPos, newCursorPos);
- textarea.focus();
- }
- const language = ref(""); //选择的语言
- const sound = ref(""); // 选择的声音
- const soundStyle = ref(""); //选择的风格
- // 语言下拉框内容
- const languageOptions = ref([]);
- async function voiceTotal() {
- const res = await voiceTotalApi();
- languageOptions.value = res.data;
- }
- // 声音下拉框内容
- const soundOptions = ref([]);
- async function chooseType() {
- const res = await chooseTypeApi(language.value);
- soundOptions.value = res.data;
- sound.value = null;
- }
- // 风格下拉框内容
- const soundStyleOptions = ref(null);
- async function chooseStyle() {
- const item = soundOptions.value.find((element) => element.id == sound.value);
- soundStyle.value = null;
- if (item) {
- soundStyleOptions.value = item.style;
- }
- }
-
- // 试听
- const previewAudioUrl = ref(null);
- async function getPreviewAudio() {
- if (!textareaContent.value) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `您还没有输入文案`
- : `You have not entered the copy yet`
- );
- return;
- }
- if (!sound.value) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `您还没有选择声音`
- : `You have not selected the sound`
- );
- return;
- }
-
- try {
- const res = await previewAudioApi(
- textareaContent.value,
- sound.value,
- soundStyle.value
- );
- if (!res.data.data) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `暂时无法试听,请稍后重试`
- : `Unable to listen, please try again later`
- );
- }
- previewAudioUrl.value = res.data.data;
- document.getElementById("audio").play();
- } catch (error) {
- ElMessage.error(error);
- }
- }
- // 根据ageType返回年龄
- function returnAge(ageType) {
- if (!ageType) {
- return "";
- } else if (ageType == 1) {
- if (lanChange.value == "zh-cn") {
- return " 儿童";
- } else {
- return "Child";
- }
- } else if (ageType == 2) {
- if (lanChange.value == "zh-cn") {
- return " 少年";
- } else {
- return "Teen";
- }
- } else if (ageType == 3) {
- if (lanChange.value == "zh-cn") {
- return " 年轻";
- } else {
- return "YoungAdult";
- }
- } else if (ageType == 4) {
- if (lanChange.value == "zh-cn") {
- return " 中年";
- } else {
- return "OlderAdult";
- }
- } else if (ageType == 5) {
- if (lanChange.value == "zh-cn") {
- return " 老年";
- } else {
- return "Senior";
- }
- }
- }
- // 新的试听
- function ListenVoices(url) {
- previewAudioUrl.value = url;
- let audioA = document.getElementById("audio");
- audioA.addEventListener("loadedmetadata", async () => {
- audioA.muted = false; // 将 muted 属性设置为 false
- await audioA.play();
- });
- }
- //#endregion ----------------------------
-
- //#region 背景
- const bjTabItemActive = ref(1); //系统或个人tab高亮
- const systemBGIList = ref([]); //系统背景列表
- const systemBGPageNum = ref(1); //系统背景页数
- const overLoadSystemBG = ref(true); //禁止系统背景触底刷新
- // tab栏切换
- function changeBjTabItemActive(type) {
- bjTabItemActive.value = type;
- if (type == 2 && !AccessToken) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `登录过期,请重新登录!`
- : `Login expired, please login again`
- );
- router.push("login");
- }
- }
- async function getSystemBGIList() {
- const res = await systemBGIListApi(
- systemBGPageNum.value,
- 20,
- videoType.value
- );
- systemBGIList.value = res.data.list;
- overLoadSystemBG.value = false;
- }
- // 加载更多系统背景图
- async function loadMoreSystemBGI() {
- systemBGPageNum.value += 1;
- const res = await systemBGIListApi(
- systemBGPageNum.value,
- 20,
- videoType.value
- );
- systemBGIList.value.push(...res.data.list);
- if (res.data.list.length == 0) {
- overLoadSystemBG.value = true;
- systemBGPageNum.value = modelPageNum.value - 1;
- }
- }
-
- // 个人背景
- const personBGIList = ref([]); //个人背景列表
- const personBGPageNum = ref(1); //个人背景页数
- const overLoadpersonBG = ref(true); //禁止个人背景触底刷新
- async function getpersonBGIList() {
- const res = await personBGIListApi(
- personBGPageNum.value,
- 20,
- videoType.value
- );
- personBGIList.value = res.data.list;
- overLoadpersonBG.value = false;
- }
- // 加载更多个人背景图
- async function loadMorePersonBGI() {
- personBGPageNum.value += 1;
- const res = await personBGIListApi(
- personBGPageNum.value,
- 20,
- videoType.value
- );
- personBGIList.value.push(...res.data.list);
- if (res.data.list.length == 0) {
- overLoadpersonBG.value = true;
- personBGPageNum.value = modelPageNum.value - 1;
- }
- }
- // 当横屏竖屏改变时,重新获取背景列表,且还原页数和禁止刷新状态
- watch(
- () => videoType,
- async (newValue, oldValue) => {
- systemBGPageNum.value = 1;
- personBGPageNum.value = 1;
- overLoadSystemBG.value = true;
- overLoadpersonBG.value = true;
- await getSystemBGIList();
- if (AccessToken) {
- await getpersonBGIList();
- }
- },
- { deep: true }
- );
- // 重新获取个人仓库背景图片
- async function reGetpersonBGIList() {
- personBGPageNum.value = 1;
- overLoadpersonBG.value = true;
- await getpersonBGIList();
- }
- // 点击列表中的背景图
- const bjImgActive = ref(null);
- function selectBjImg(img) {
- bjImgActive.value = img.id;
- materialList.BGI.material = img.material;
- materialList.BGI.id = img.id;
- }
- //#endregion ----------------------------
-
- //#region 素材
- const scTabItemActive = ref(1); //系统或个人tab高亮
- const systemSCIList = ref([]); //系统素材列表
- const systemSCPageNum = ref(1); //系统素材页数
- const overLoadSystemSC = ref(true); //禁止系统素材触底刷新
- // tab栏切换
- function changeScTabItemActive(type) {
- scTabItemActive.value = type;
- if (type == 2 && !AccessToken) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `登录过期,请重新登录!`
- : `Login expired, please login again`
- );
- router.push("login");
- }
- }
- async function getSystemSCIList() {
- const res = await systemSCIListApi(
- systemSCPageNum.value,
- 20,
- videoType.value
- );
- systemSCIList.value = res.data.list;
- overLoadSystemSC.value = false;
- }
- // 加载更多系统素材图
- async function loadMoreSystemSCI() {
- systemSCPageNum.value += 1;
- const res = await systemSCIListApi(
- systemSCPageNum.value,
- 20,
- videoType.value
- );
- systemSCIList.value.push(...res.data.list);
- if (res.data.list.length == 0) {
- overLoadSystemSC.value = true;
- systemSCPageNum.value = modelPageNum.value - 1;
- }
- }
-
- // 个人素材
- const personSCIList = ref([]); //个人素材列表
- const personSCPageNum = ref(1); //个人素材页数
- const overLoadpersonSC = ref(true); //禁止个人素材触底刷新
- async function getpersonSCIList() {
- const res = await personSCIListApi(
- personSCPageNum.value,
- 20,
- videoType.value
- );
- personSCIList.value = res.data.list;
- overLoadpersonSC.value = false;
- }
- // 加载更多个人素材图
- async function loadMorePersonSCI() {
- personSCPageNum.value += 1;
- const res = await personSCIListApi(
- personSCPageNum.value,
- 20,
- videoType.value
- );
- personSCIList.value.push(...res.data.list);
- if (res.data.list.length == 0) {
- overLoadpersonSC.value = true;
- personSCPageNum.value = modelPageNum.value - 1;
- }
- }
- // 重新获取个人仓库背景图片
- async function reGetpersonSCIList() {
- personSCPageNum.value = 1;
- overLoadpersonSC.value = true;
- await getpersonSCIList();
- }
- // 点击列表中的素材图
- const scImgActive = ref(null);
- function selectScImg(img) {
- scImgActive.value = img.id;
- materialList.scList.push({ ...img, x: 0, y: 0, z: 0, w: 1, h: 1 });
- }
- // 删除上传的背景或素材
- function delImg(id) {
- const msg =
- lanChange.value == "zh-cn"
- ? "确定删除图片吗?"
- : "Are you sure to delete the picture?";
- const notice = lanChange.value == "zh-cn" ? "提示" : "Notice";
- const confirm = lanChange.value == "zh-cn" ? "确定" : "Confirm";
- const cancel = lanChange.value == "zh-cn" ? "取消" : "Cancel";
- ElMessageBox.confirm(msg, notice, {
- confirmButtonText: confirm,
- cancelButtonText: cancel,
- }).then(async () => {
- try {
- const res = await delImgApi(id);
- reGetpersonSCIList();
- reGetpersonBGIList();
- ElMessage.success(
- lanChange.value == "zh-cn" ? "删除成功!" : "Deleted successfully!"
- );
- } catch (error) {}
- });
- }
- //#endregion ----------------------------
-
- //#region 字幕
- const SubtitlesColorShow = ref(false); // 字色调色板开关
- const Subtitles = reactive({
- SubtitlesSwitch: false, //开关
- SubtitlesFontFamily: "仿宋", //字体系列
- SubtitlesTop: 400, //Y轴
- SubtitlesSize: 30, //字号大小
- SubtitlesWeight: 500, //字粗
- SubtitlesColor: "#FFFFFF", //字色
- SubtitlesWidth: 500, //宽度
- colorList: [
- "#FFFFFF",
- "#FF8080",
- "#000000",
- "#FF80FF",
- "#FF0000",
- "#00FF80",
- "#FF00FF",
- "#0080FF",
- "#00FF00",
- "#0000FF",
- "#000080",
- "#FFFF00",
- "#FF0080",
- "#FF8000",
- "#80FF00",
- "#00FFFF",
- ],
- fontFamilyList: [
- { label: "仿宋", value: "仿宋" },
- { label: "微软雅黑", value: "微软雅黑" },
- { label: "新宋体", value: "新宋体" },
- { label: "黑体", value: "黑体" },
- { label: "楷体", value: "楷体" },
- { label: "等线", value: "等线" },
- { label: "Corbel", value: "Corbel" },
- { label: "Terminal", value: "Terminal" },
- { label: "Times New Roman", value: "Times New Roman" },
- { label: "Verdana", value: "Verdana" },
- ],
- fontSizeList: [12, 16, 20, 30, 44, 60, 80, 100],
- fontWeightList: [100, 500, 900],
- });
- const handleSubtitlesColorShow = (e) => {
- e.stopPropagation(); // 阻止事件冒泡
- SubtitlesColorShow.value = true;
- // SubtitlesBgcShow.value = false;
- };
- const handleClickOutside = () => {
- if (SubtitlesColorShow.value == true) {
- }
- SubtitlesColorShow.value = false;
- };
- onMounted(() => {
- document.addEventListener("click", handleClickOutside);
- });
- function rgbaToBgra(hexColor) {
- // 去除颜色前缀
- hexColor = hexColor.replace("#", "");
- // 分割颜色分量
- const red = hexColor.substring(0, 2);
- const green = hexColor.substring(2, 4);
- const blue = hexColor.substring(4, 6);
- // 组合为新的颜色字符串
- const convertedColor = `&H${blue}${green}${red}`;
- return convertedColor;
- }
- function BgraToRgba(hexColor) {
- // 去除颜色前缀
- hexColor = hexColor.replace("&H", "");
- // 分割颜色分量
- const blue = hexColor.substring(0, 2);
- const green = hexColor.substring(2, 4);
- const red = hexColor.substring(4, 6);
- // 组合为新的颜色字符串
- const convertedColor = `#${red}${green}${blue}`;
- return convertedColor;
- }
- //#endregion ----------------------------
-
- //#region 编辑区域
- const proportion = ref(1); //比例
- const elementWidth = ref(null);
- onMounted(() => {
- elementWidth.value = document.getElementById("editPosition").clientWidth;
- });
- const EditPositionDom = ref(null);
- watch(
- () => videoType.value,
- async (newValue, oldValue) => {
- // 根据横竖屏来确定比例 1竖2横
- await nextTick();
- elementWidth.value = document.getElementById("editPosition").clientWidth;
-
- if (videoType.value == 1) {
- proportion.value = Number(1080 / elementWidth.value).toFixed(2);
- } else if (videoType.value == 2) {
- proportion.value = Number(1920 / elementWidth.value).toFixed(2);
- }
- console.log("设置比例");
- Subtitles.SubtitlesWidth = elementWidth.value * 0.7 * proportion.value;
- console.log(proportion.value, "比例");
- },
- { deep: true }
- );
- const materialList = reactive({
- BGI: {},
- scList: [],
- virtual: {},
- });
- // 根据模版id获取信息
- async function getPersonPatch() {
- try {
- const res = await personPatchApi(modelId.value);
- materialList.BGI.material = res.data.backgroundMaterial;
- materialList.BGI.id = res.data.backgroundId + "";
- materialList.virtual.material = res.data.material;
- materialList.virtual.id = res.data.id;
- // if (!materialList.virtual.w) {
- materialList.virtual = {
- ...materialList.virtual,
- x: 50,
- y: 10,
- z: 0,
- w: 0.55,
- h: 1,
- };
- // }
- } catch (error) {}
- }
- watch(
- () => modelId.value,
- async (newValue, oldValue) => {
- await getPersonPatch();
- },
- { deep: true }
- );
- //#endregion ----------------------------
-
- //#region 编辑区域控制台
- const showImgInfo = ref({
- id: null,
- data: null,
- }); //显示素材or数字人的id
- // const showImgInfoData = ref(null);
- watch(
- () => showImgInfo,
- (newValue, oldValue) => {
- if (materialList.virtual.id == showImgInfo.value.id) {
- showImgInfo.value.data = materialList.virtual;
- } else {
- showImgInfo.value.data = materialList.scList.find(
- (item) => item.id == showImgInfo.value.id
- );
- }
- },
- { deep: true }
- );
- //#endregion ----------------------------
-
- //#region 保存视频和生成草稿
- const workId = ref(null); //保存作品完成后会有一个id,用于生成视频
- const saveLoading = ref(false);
- const createLoading = ref(false);
- async function saveOrUpdate(isCreate) {
- // 单纯的保存视频
- if (isCreate == "isSave") {
- if (saveLoading.value == true) {
- ElMessage.error(lanChange.value == "zh-cn" ? `正在保存` : `Be saving`);
- return;
- }
- if (createLoading.value == true) {
- ElMessage.error(
- lanChange.value == "zh-cn" ? `正在生成` : `Be generating`
- );
- return;
- }
- try {
- saveLoading.value = true;
- // 处理数字人
- const shuziren = {
- id: materialList.virtual.id,
- type: 1,
- material: materialList.virtual.material,
- x: materialList.virtual.x,
- y: materialList.virtual.y,
- z: materialList.virtual.z,
- w: materialList.virtual.w,
- h: materialList.virtual.h,
- };
- // 处理素材
- const scList = materialList.scList.map((item) => {
- return {
- id: item.id,
- type: 5,
- material: item.material,
- x: item.x,
- y: item.y,
- z: item.z,
- w: item.w,
- h: item.h,
- };
- });
- // 处理上传数据
- const data = {
- id: workId.value,
- videoType: videoType.value, //横屏竖屏
- personMouldId: materialList.virtual.id, //数字人id
- speakTypeStr: soundStyle.value, //声音风格
- voiceMouldId: sound.value, //声音id
- // voiceMouldIds: [soundStyle.value ? soundStyle.value : sound.value], //声音id
- title: title.value, //标题
- paperwork: textareaContent.value, //语音内容
- backgroundId: materialList.BGI.id + "", //背景id
- personJson: JSON.stringify(shuziren), // 数字人
- materialAllJson: JSON.stringify([...scList]), // 素材
- subtitleEnabled: Subtitles.SubtitlesSwitch ? 1 : 0, //字幕开关
- subtitleParams: JSON.stringify({
- Fontname: Subtitles.SubtitlesFontFamily, //字体名字
- Fontsize: Subtitles.SubtitlesSize * proportion.value, //字体大小
- Marginv: Subtitles.SubtitlesTop, //上边距
- PrimaryColour: rgbaToBgra(Subtitles.SubtitlesColor), //字色
- Alignment: 6,
- }),
- };
- const res = await saveOrUpdateApi(data);
- workId.value = res.data.id;
- saveLoading.value = false;
- ElMessage.success(
- lanChange.value == "zh-cn"
- ? `保存草稿成功!`
- : `Save draft successfully!`
- );
- router.push("/myCreating");
- } catch (error) {
- ElMessage.error(error);
- saveLoading.value = false;
- }
- }
- // 生成视频时触发的保存
- else if (isCreate == "isCreate") {
- try {
- if (!textareaContent.value) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `您还没有输入文案`
- : `You have not entered the copy yet`
- );
- saveLoading.value = false;
- return;
- }
- if (!sound.value && !soundStyle.value) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `您还没有选择声音`
- : `You have not selected a sound`
- );
- saveLoading.value = false;
- return;
- }
-
- // 处理数字人
- const shuziren = {
- id: materialList.virtual.id,
- type: 1,
- material: materialList.virtual.material,
- x: materialList.virtual.x,
- y: materialList.virtual.y,
- z: materialList.virtual.z,
- w: materialList.virtual.w,
- h: materialList.virtual.h,
- };
- // 处理素材
- const scList = materialList.scList.map((item) => {
- return {
- id: item.id,
- type: 5,
- material: item.material,
- x: item.x,
- y: item.y,
- z: item.z,
- w: item.w,
- h: item.h,
- };
- });
- // 处理上传数据
- const data = {
- id: workId.value,
- videoType: videoType.value, //横屏竖屏
- personMouldId: materialList.virtual.id, //数字人id
- speakTypeStr: soundStyle.value, //声音风格
- voiceMouldId: sound.value, //声音id
- title: title.value, //标题
- paperwork: textareaContent.value, //语音内容
- backgroundId: materialList.BGI.id + "", //背景id
- personJson: JSON.stringify(shuziren), // 数字人
- materialAllJson: JSON.stringify([...scList]), // 素材
- subtitleEnabled: Subtitles.SubtitlesSwitch ? 1 : 0, //字幕开关
- subtitleParams: JSON.stringify({
- Fontname: Subtitles.SubtitlesFontFamily, //字体名字
- Fontsize: Subtitles.SubtitlesSize * proportion.value, //字体大小
- Marginv: Subtitles.SubtitlesTop, //上边距
- PrimaryColour: rgbaToBgra(Subtitles.SubtitlesColor), //字色
- Alignment: 6,
- }),
- };
-
- const res = await saveOrUpdateApi(data);
- workId.value = res.data.id;
- saveLoading.value = false;
- } catch (error) {
- ElMessage.error(error);
- saveLoading.value = false;
- }
- }
- }
- async function createVideo() {
- if (saveLoading.value == true) {
- ElMessage.error(lanChange.value == "zh-cn" ? `正在保存` : `Be saving`);
- return;
- }
- if (createLoading.value == true) {
- ElMessage.error(lanChange.value == "zh-cn" ? `正在生成` : `Be generating`);
- return;
- }
- try {
- createLoading.value = true;
- if (!textareaContent.value) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `您还没有输入文案`
- : `You have not entered the copy yet`
- );
- createLoading.value = false;
- return;
- }
- if (!sound.value && !soundStyle.value) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `您还没有选择声音`
- : `You have not selected a sound`
- );
- createLoading.value = false;
- return;
- }
- // 获取预估时长
- const res4 = await previewAudioApi(
- textareaContent.value,
- sound.value,
- soundStyle.value
- );
- if (res4.data.code != 200) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `视频时长预估失败,无法生成视频,您可以换个声音试试`
- : `Video duration estimation failed, can not generate video, you can try to change the sound`
- );
- createLoading.value = false;
- saveLoading.value = false;
- return;
- }
- if (res4.data.data > 300) {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `预计生成的视频时长约为${formatTime(
- res4.data.data
- )},免费用户生成视频时长为300秒,无法生成视频`
- : `The video generated is expected to be about ${formatTime(
- res4.data.data
- )} long, and the free user-generated video is 300 seconds long and cannot be generated`
- );
- createLoading.value = false;
- saveLoading.value = false;
- return;
- }
- ElMessage.success(
- lanChange.value == "zh-cn"
- ? `预计生成的视频时长约为${formatTime(res4.data.data)}`
- : `The video generated is expected to be approximately${formatTime(
- res4.data.data
- )} in length`
- );
- await saveOrUpdate("isCreate");
- const res2 = await createVideoApi(workId.value);
- ElMessage.success(
- lanChange.value == "zh-cn"
- ? `视频生成中,请稍后!`
- : `Video generation, please wait!`
- );
- createLoading.value = false;
- router.push("/myCreating");
- } catch (error) {
- ElMessage.error(error);
- createLoading.value = false;
- }
- }
- // 预估时长时把秒转为分
- function formatTime(seconds) {
- const minutes = Math.floor(Math.floor(seconds) / 60);
- const remainingSeconds = Math.floor(seconds) % 60;
- const formattedMinutes = String(minutes).padStart(2, "0");
- const formattedSeconds = String(remainingSeconds).padStart(2, "0");
- return `${formattedMinutes}:${formattedSeconds}`;
- }
- //#endregion ----------------------------
-
- //#region 草稿回显
- const subtitleParamsToObj = ref(null);
- async function getModelDetailById() {
- const res = await getModelDetailByIdApi(route.query.id);
- videoType.value = res.data.videoType;
- language.value = res.data.voiceInfo ? res.data.voiceInfo.languageId : null;
- if (language.value) {
- await chooseType(language.value);
- }
- workId.value = res.data.id;
- title.value = res.data.title; //标题
- textareaContent.value = res.data.paperwork; //语音内容
- materialList.BGI.id = res.data.backgroundId + ""; //背景id
- // sound.value = res.data.voiceMouldId;
- // soundStyle.value = JSON.parse(res.data.voiceMouldSm).speakTypeStr;
- sound.value = res.data.voiceMouldId; //声音id
- chooseStyle();
- soundStyle.value = res.data.speakTypeStr; //选择风格
- materialList.BGI.material = JSON.parse(res.data.backgroundSm).material;
- materialList.virtual = JSON.parse(res.data.personJson);
- materialList.virtual.id = res.data.personMouldId; //数字人id
- materialList.scList = res.data.materialAllJson
- ? JSON.parse(res.data.materialAllJson)
- : [];
- showChooseModel.value = false;
- // 字幕回显 需要延时,不然proportion缩放比例不准确
- setTimeout(() => {
- Subtitles.SubtitlesSwitch = res.data.subtitleEnabled == 1 ? true : false;
- subtitleParamsToObj.value = JSON.parse(res.data.subtitleParams);
- Subtitles.SubtitlesFontFamily = subtitleParamsToObj.value.Fontname;
- Subtitles.SubtitlesSize =
- subtitleParamsToObj.value.Fontsize / proportion.value;
- Subtitles.SubtitlesTop = subtitleParamsToObj.value.Marginv;
- Subtitles.SubtitlesColor = BgraToRgba(
- subtitleParamsToObj.value.PrimaryColour
- );
- }, 100);
- }
- //#endregion ----------------------------
-
- //#region 公共方法
- function NumToFixed(num1, num2) {
- return Number(num1).toFixed(num2);
- }
- //#endregion ----------------------------
-
- //#region AI文案
- // 创建websocket
- let mySocket = null; //websocket对象
- const sendLoading = ref(false); //发送状态
- function createWS() {
- mySocket = new WebSocket("wss://gptsocket.malls.iformall.com:8010");
- mySocket.onopen = () => {
- console.log("WebSocket 连接成功1");
- sendRequirement();
- };
- mySocket.onmessage = (event) => {
- // console.log("接收到 WebSocket 消息2:", event.data);
- if (!event.data) {
- return;
- }
- if (event.data == "___talk_end___") {
- sendLoading.value = false;
- mySocket.close();
- return;
- }
- answerContent.value = answerContent.value + event.data;
- };
- mySocket.onclose = () => {
- console.log(
- "WebSocket 连接关闭3,关闭代码:",
- event.code,
- "关闭原因:",
- event.reason
- );
- console.log(mySocket.readyState, "链接状态3");
- };
-
- mySocket.onerror = (error) => {
- ElMessage.error(
- lanChange.value == "zh-cn"
- ? `GPT服务器连接失败,请稍后重试!`
- : `GPT Server connection failed, please try again later`
- );
- sendLoading.value = false;
- mySocket.close();
- console.error("WebSocket 错误4:", error);
- };
- }
- const problemContent = ref(""); //问题输入框内容
- const answerContent = ref(""); //回答输入框内容
- // 点击发送需求
- async function sendRequirement() {
- // loading
- sendLoading.value = true;
-
- // 无需求时
- if (!problemContent.value) {
- sendLoading.value = false;
- mySocket.close();
- return;
- }
- const sendMessage = [
- {
- role: "user",
- content: problemContent.value,
- },
- ];
- // 如果处于链接状态
-
- if (mySocket.readyState != WebSocket.OPEN) {
- createWS();
- } else {
- answerContent.value = "";
- mySocket.send(JSON.stringify(sendMessage));
- }
- }
- // 复制到文案
- function copyAnswerContent() {
- textareaContent.value = answerContent.value;
- document.getElementById("tab-0").click();
- }
- //#endregion ----------------------------
-
- //#region
-
- //#endregion ----------------------------
- // $t在script中的使用
- const {
- appContext: {
- config: { globalProperties },
- },
- } = getCurrentInstance();
-
- const string = "createVideo.typeScript";
- const t = globalProperties.$t(string);
-
- onMounted(async () => {
- voiceTotal(); //获取声音列表
- // getSystemSCIList();
- // getpersonBGIList();
- await getModeList(tabSex.value, 1, 20, tabVideoType.value); //获取模版列表
- if (AccessToken) {
- getpersonSCIList();
- }
- getSystemSCIList();
- if (route.query.id) {
- getModelDetailById();
- }
- createWS();
- });
- </script>
-
- <style lang="scss" scoped>
- .page {
- height: calc(100vh - 80px);
- // height: calc(100vh - 80px);
- background-color: #fff;
- border-radius: 30px 0 0 0;
- overflow: hidden;
- }
- .mask {
- position: absolute;
- width: 100%;
- height: 100%;
- z-index: 4;
- background-color: rgba(0, 0, 0, 0.5);
- }
- .left {
- position: relative;
- width: 68%;
- height: 100%;
- padding: 20px;
- // 字幕盒子
- .subtitlesBoxTop {
- z-index: 3;
- position: absolute;
- top: 50px;
- left: 225px;
- width: 700px;
- // height: 50px;
- background-color: #e9ecf1;
- border-radius: 20px;
- padding: 10px;
- box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
- display: flex;
- justify-content: flex-start;
- align-content: flex-start;
- flex-wrap: wrap;
- .tab4Item {
- display: flex;
- justify-content: space-between;
- width: 130px;
- background-color: rgba(71, 105, 218, 0.1);
- text-align: center;
- padding: 10px;
- height: 80px;
- border-radius: 10px;
- margin: auto;
- // margin-bottom: 10px;
- p {
- padding-bottom: 5px;
- }
- }
- .SubtitlesSwitch {
- width: 100%;
- .el-input-number--large {
- width: 100px;
- }
- .el-input-number__increase {
- width: none;
- }
- }
- .myColorBox {
- position: relative;
- width: 25px;
- height: 25px;
- margin: auto;
- border: #000 solid 2px;
- cursor: pointer;
- .selectColor {
- position: absolute;
- top: 150%;
- left: 50%;
- transform: translateX(-50%);
- display: flex;
- justify-content: flex-start;
- flex-wrap: wrap;
- width: 142px;
- background-color: #ffffff;
- z-index: 99;
- box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px 5px;
- &::before {
- content: "";
- display: block;
- position: absolute;
- top: -10%;
- left: 50%;
- transform: translateX(-50%);
- width: 0;
- height: 0;
- border-left: 15px solid transparent;
- border-right: 15px solid transparent;
- border-bottom: 15px solid white;
- }
- &-item {
- width: 25px;
- height: 25px;
- margin: 5px 5px;
- border: #000 solid 2px;
- border-radius: 5px;
- cursor: pointer;
- }
- }
- }
- }
- .subtitlesBoxLeft {
- z-index: 3;
- position: absolute;
- top: 150px;
- left: 150px;
- width: 150px;
- // height: 50px;
- background-color: #e9ecf1;
- border-radius: 20px;
- padding: 10px;
- box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
- display: flex;
- justify-content: flex-start;
- align-content: flex-start;
- flex-wrap: wrap;
- .tab4Item {
- display: flex;
- justify-content: space-between;
- width: 130px;
- background-color: rgba(71, 105, 218, 0.1);
- text-align: center;
- padding: 10px;
- height: 80px;
- border-radius: 10px;
- margin: auto;
- margin-bottom: 10px;
- p {
- padding-bottom: 5px;
- }
- }
- .SubtitlesSwitch {
- width: 100%;
- .el-input-number--large {
- width: 100px;
- }
- .el-input-number__increase {
- width: none;
- }
- }
- .myColorBox {
- position: relative;
- width: 25px;
- height: 25px;
- margin: auto;
- border: #000 solid 2px;
- cursor: pointer;
- .selectColor {
- position: absolute;
- top: 150%;
- left: 50%;
- transform: translateX(-50%);
- display: flex;
- justify-content: flex-start;
- flex-wrap: wrap;
- width: 142px;
- background-color: #ffffff;
- z-index: 99;
- box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px 5px;
- &::before {
- content: "";
- display: block;
- position: absolute;
- top: -10%;
- left: 50%;
- transform: translateX(-50%);
- width: 0;
- height: 0;
- border-left: 15px solid transparent;
- border-right: 15px solid transparent;
- border-bottom: 15px solid white;
- }
- &-item {
- width: 25px;
- height: 25px;
- margin: 5px 5px;
- border: #000 solid 2px;
- border-radius: 5px;
- cursor: pointer;
- }
- }
- }
- }
- // 选择模版弹出框
- .chooseModelBox {
- position: absolute;
- top: 0px;
- left: 0px;
- width: 50%;
- height: 100%;
- padding: 30px 30px 10px 30px;
- transition: all 0.3s;
- // background-color: #f1f2f6;
- background-color: #454545;
- z-index: 9;
-
- // 伸缩按钮
- .shrinkBtn {
- position: absolute;
- top: 350px;
- right: -40px;
- width: 40px;
- height: 100px;
- line-height: 80px;
- padding: 10px;
- font-size: 30px;
- background-color: #454545;
- color: #fff;
- &::before {
- position: absolute;
- top: -40px;
- left: -0px;
- content: "";
- width: 0;
- height: 0px;
- border-top: 20px solid transparent;
- border-right: 20px solid transparent;
- border-bottom: 20px solid #454545;
- border-left: 20px solid #454545;
- }
- &::after {
- position: absolute;
- bottom: -40px;
- left: -0px;
- content: "";
- width: 0;
- height: 0px;
- border-top: 20px solid #454545;
- border-right: 20px solid transparent;
- border-bottom: 20px solid transparent;
- border-left: 20px solid #454545;
- }
- }
-
- // tab栏
- p {
- color: #fff;
- font-size: 16px;
- padding: 0 20px;
- }
- .tab {
- margin: auto;
- margin-top: 10px;
- display: flex;
- justify-content: space-between;
- width: 100%;
- height: 40px;
- // background-color: #fff;
- margin-bottom: 10px;
- border-radius: 25px;
- color: #b9b9b9;
- .tabItem {
- // flex: 1;
- width: 30%;
- font-size: 14px;
- text-align: center;
- line-height: 40px;
- border-radius: 15px;
- transition: all 0.3s;
- cursor: pointer;
- // margin: 0 10px;
- // padding: 0 5px;
- background-color: #000;
- user-select: none;
- }
- .tabItemActive {
- background-color: #fff;
- color: #000;
- }
- }
- // 模版列表
- .modeListBox {
- display: flex;
- flex-wrap: wrap;
- justify-content: flex-start;
- width: 100%;
- max-height: calc(100% - 180px);
- padding: 20px;
- border-radius: 20px;
- // background-color: #fff;
- overflow: hidden;
- overflow-y: scroll;
- .modeListBoxItme {
- position: relative;
- padding: 20px;
- width: 45%;
- height: 190px;
- margin: 0 20px 20px 0;
- border-radius: 15px;
- // padding: 20px;
- // background: rgba(0, 0, 0, 0.1);
- background-color: #fff;
- z-index: 2;
- cursor: pointer;
- img {
- max-width: 100%;
- max-height: 100%;
- // max-width: 200px;
- // max-height: 200px;
- }
- }
- .modeListBoxItmeActive {
- border: 3px solid #7264f5;
- }
- }
- }
- .noModel {
- width: 0;
- padding: 0;
- // opacity: 0;
- }
- // 展示区
- .showModelImgBox {
- position: relative;
- width: 100%;
- height: 100%;
- padding: 50px;
- z-index: 1;
- img {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- max-width: 800px;
- max-height: 800px;
- }
- .EditPositionBox1 {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- height: 768px;
- width: 432px;
- border-radius: 20px;
- overflow: hidden;
- }
- .EditPositionBox2 {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- height: 432px;
- width: 768px;
- border-radius: 20px;
- overflow: hidden;
- }
- .showImgInfoBox {
- position: absolute;
- top: 200px;
- right: 0px;
- width: 120px;
- background-color: #e9ecf1;
- border-radius: 20px;
- padding: 10px;
- box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
- .ItemName {
- width: 100%;
- height: 40px;
- text-align: center;
- line-height: 40px;
- background-color: #fff;
- border-radius: 10px;
- }
- .ItemValue {
- margin-bottom: 10px;
- width: 100%;
- height: 40px;
- text-align: center;
- line-height: 40px;
- background-color: #f5f7fa;
- border-radius: 10px;
- .el-input-number--large {
- width: 100px;
- }
- .el-input-number__increase {
- width: none;
- }
- }
- }
- .btnBox {
- position: absolute;
- display: flex;
- bottom: 10px;
- right: 10px;
- width: 250px;
- .customBtn {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: 45%;
- height: 50px;
- user-select: none;
- > div {
- width: 100%;
- text-align: center;
- cursor: pointer;
- }
- }
- }
- }
- }
-
- .right {
- width: 32%;
- height: 100%;
- padding: 30px 30px 20px 30px;
- background-color: #f1f2f6;
- border-radius: 30px 0 0 0;
- position: relative;
- .tab {
- display: flex;
- width: 100%;
- height: 50px;
- background-color: #fff;
- margin-bottom: 10px;
- border-radius: 25px;
- .tabItem {
- flex: 1;
- text-align: center;
- line-height: 50px;
- border-radius: 25px;
- transition: all 0.3s;
- cursor: pointer;
- user-select: none;
- }
- .tabItemActive {
- background-color: #000;
- color: #fff;
- }
- }
- .tabContent {
- padding: 20px;
- width: 100%;
- height: calc(100% - 60px);
- background-color: #fff;
- border-radius: 30px;
- .tab {
- background-color: #f1f2f6;
- }
- }
- .tab1 {
- .title {
- :deep(.el-textarea) {
- padding: 10px;
- overflow: hidden;
- }
- :deep(.el-textarea__inner) {
- border-radius: 15px;
- }
- :deep(.el-input) {
- padding-left: 10px;
- margin-bottom: 10px;
- }
- :deep(.el-input__wrapper) {
- border: none;
- border-bottom: 2px solid #000;
- border-radius: 0;
- box-shadow: none;
- }
- .el-icon.icon-edit {
- width: 35px;
- height: 35px;
- font-size: 35px;
- color: #8c939d;
- text-align: center;
- vertical-align: middle;
- }
- }
- .text {
- padding: 10px;
- border: 1px solid #c4c8d0;
- border-radius: 15px;
- .el-button {
- float: right;
- margin-top: 10px;
- }
-
- :deep(.el-textarea__inner) {
- resize: none;
- box-shadow: none;
- }
- }
- p {
- margin: 7px 0;
- }
- }
- .tab2,
- .tab3 {
- .bjSystemBox {
- display: flex;
- flex-wrap: wrap;
- max-height: calc(100% - 60px);
- overflow-y: scroll;
- // background-color: pink;
- .bjSystemBoxItem {
- position: relative;
- margin-right: 3%;
- margin-bottom: 10px;
- width: 30%;
- height: 200px;
- background-color: #e5e5e5;
- border-radius: 10px;
- cursor: pointer;
- border: rgba(0, 0, 0, 0) 2px solid;
- > img {
- padding: 10px;
- max-width: 100%;
- max-height: 100%;
- }
- .delIcon {
- position: absolute;
- right: 5px;
- top: 5px;
- width: 20px;
- height: 20px;
- border-radius: 10px;
- z-index: 999;
- cursor: pointer;
- img {
- max-width: 100%;
- max-height: 100%;
- }
- }
- }
- .ImgBorderActive {
- border: #7264f5 2px solid;
- }
- }
- }
- .tab4 {
- // display: flex;
- // justify-content: flex-start;
- // align-content: flex-start;
- // flex-wrap: wrap;
- .card4 {
- .text {
- padding: 10 px;
- border: 1px solid #c0c4cc;
- .el-button {
- float: right;
- margin-top: 10px;
- }
- :deep(.el-textarea__inner) {
- cursor: text;
- }
- :deep(.el-textarea__inner) {
- resize: none;
- box-shadow: none;
- }
- i {
- font-size: 14px;
- float: right;
- }
- }
-
- p {
- margin: 7px 0;
- }
- .card4Btn {
- margin-top: 10px;
- border-radius: 5px;
- height: 50px;
- width: 100%;
- color: #fff;
- background-color: #000;
- text-align: center;
- line-height: 50px;
- cursor: pointer;
- }
- .el-button {
- width: 100%;
- height: 50px;
- margin-top: 10px;
- }
- }
- :deep(.el-tabs__item.is-active) {
- color: #909393;
- background-color: #000;
- }
-
- :deep(.el-tabs__nav) {
- width: 100%;
- }
-
- :deep(.el-tabs__item) {
- width: 26%;
- }
-
- :deep(.el-tabs__item:hover) {
- color: #909393;
- }
-
- :deep(.el-tabs__content) {
- height: calc(100% - 60px);
- padding: 0;
- }
- .tab4Item {
- display: flex;
- justify-content: space-between;
- width: 30%;
- background-color: rgba(71, 105, 218, 0.1);
- text-align: center;
- padding: 10px;
- height: 80px;
- border-radius: 10px;
- margin: auto;
- margin-bottom: 10px;
- p {
- padding-bottom: 5px;
- }
- }
- .SubtitlesSwitch {
- width: 100%;
- .el-input-number--large {
- width: 100px;
- }
- .el-input-number__increase {
- width: none;
- }
- }
- .myColorBox {
- position: relative;
- width: 25px;
- height: 25px;
- margin: auto;
- border: #000 solid 2px;
- cursor: pointer;
- .selectColor {
- position: absolute;
- top: 150%;
- left: 50%;
- transform: translateX(-50%);
- display: flex;
- justify-content: flex-start;
- flex-wrap: wrap;
- width: 142px;
- background-color: #ffffff;
- z-index: 99;
- box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px 5px;
- &::before {
- content: "";
- display: block;
- position: absolute;
- top: -10%;
- left: 50%;
- transform: translateX(-50%);
- width: 0;
- height: 0;
- border-left: 15px solid transparent;
- border-right: 15px solid transparent;
- border-bottom: 15px solid white;
- }
- &-item {
- width: 25px;
- height: 25px;
- margin: 5px 5px;
- border: #000 solid 2px;
- border-radius: 5px;
- cursor: pointer;
- }
- }
- }
- }
- }
- </style>
|