| @@ -176,3 +176,15 @@ export function createVideoApi(id) { | |||||
| data: { id } | data: { id } | ||||
| }) | }) | ||||
| } | } | ||||
| /** | |||||
| * @description:根据id获取用户作品详情 | |||||
| * @param {number} id | |||||
| * @return data | |||||
| */ | |||||
| export function getModelDetailByIdApi(id) { | |||||
| return request({ | |||||
| url: `/api/userVideo/findById?id=${id}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| @@ -2,7 +2,7 @@ import request from "@/utils/request.js"; | |||||
| /** | /** | ||||
| * @description 获取我的视频作品 | |||||
| * @description 获取我的视频作品(已改) | |||||
| * @params pageNum, pageSize | * @params pageNum, pageSize | ||||
| * @returns data | * @returns data | ||||
| */ | */ | ||||
| @@ -12,35 +12,47 @@ import request from "@/utils/request.js"; | |||||
| // method: 'get' | // method: 'get' | ||||
| // }) | // }) | ||||
| // } | // } | ||||
| export function userPhotoVideoList(pageNum, pageSize, title) { | |||||
| export function userPhotoVideoListApi(pageNum, pageSize, title) { | |||||
| let videoStatuss = [1, 2, 3, 4, 5, 6] | let videoStatuss = [1, 2, 3, 4, 5, 6] | ||||
| return request({ | return request({ | ||||
| url: `/api/userVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&title=${title}&videoType=-1&videoStatuss=${videoStatuss}`, | |||||
| url: `/api/userVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&title=${title}&videoType=-1`, | |||||
| method: 'get' | method: 'get' | ||||
| }) | }) | ||||
| } | } | ||||
| /** | /** | ||||
| * @description 删除视频作品 | |||||
| * @description 删除视频作品(旧) | |||||
| * @params videoID | * @params videoID | ||||
| * @returns data | * @returns data | ||||
| */ | */ | ||||
| export function delUserPhotoVideoByID(videoID) { | |||||
| export function delUserPhotoVideoByIDApi(videoID) { | |||||
| return request({ | return request({ | ||||
| url: `/api/userPhotoVideo/del?id=${videoID}`, | |||||
| url: `/api/userVideo/del?id=${videoID}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * @description 提升画质(旧) | |||||
| * @params id | |||||
| * @returns data | |||||
| */ | |||||
| export function videoHyApi(id) { | |||||
| return request({ | |||||
| url: `/api/userPhotoVideo/videoHy?id=${id}`, | |||||
| method: 'get' | method: 'get' | ||||
| }) | }) | ||||
| } | } | ||||
| /** | /** | ||||
| * @description 获取作品列表 | |||||
| * @param {number} pageParams (pageNum, pageSize) | |||||
| * @description 查询是否有视频更新(旧) | |||||
| * @params id | |||||
| * @returns data | * @returns data | ||||
| */ | */ | ||||
| export function getVideoList(pageNum, pageSize, videoType, videoStatuss) { | |||||
| export function checkVideoStatusApi(list) { | |||||
| return request({ | return request({ | ||||
| url: `/api/userVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&videoType=${videoType}&videoStatuss=${videoStatuss}`, | |||||
| url: `/api/userPhotoVideo/checkVideoStatus?list=${list}`, | |||||
| method: 'get' | method: 'get' | ||||
| }) | }) | ||||
| } | |||||
| } | |||||
| @@ -1,5 +1,5 @@ | |||||
| <template> | <template> | ||||
| <div class="loadingIcon"> | |||||
| <div v-if="isLoading" class="loadingIcon"> | |||||
| <div> | <div> | ||||
| <el-icon class="is-loading"> | <el-icon class="is-loading"> | ||||
| <svg | <svg | ||||
| @@ -32,8 +32,8 @@ const props = defineProps({ | |||||
| .loadingIcon { | .loadingIcon { | ||||
| position: relative; | position: relative; | ||||
| width: 100%; | width: 100%; | ||||
| height: 80px; | |||||
| line-height: 80px; | |||||
| height: 30px; | |||||
| line-height: 35px; | |||||
| text-align: center; | text-align: center; | ||||
| transform: scale(2); | transform: scale(2); | ||||
| > div { | > div { | ||||
| @@ -92,6 +92,10 @@ export default { | |||||
| personBGI:'Person background diagram', | personBGI:'Person background diagram', | ||||
| systemMaterial:'System Material', | systemMaterial:'System Material', | ||||
| personMaterial:'Person Material', | personMaterial:'Person Material', | ||||
| abscissa:'abscissa', | |||||
| ordinate:'ordinate', | |||||
| hierarchy:'hierarchy', | |||||
| ratio:'ratio', | |||||
| }, | }, | ||||
| // 我的视频 | // 我的视频 | ||||
| @@ -114,7 +118,12 @@ export default { | |||||
| manuscriptText: "Manuscript", | manuscriptText: "Manuscript", | ||||
| generatingText: "The video is generating, Please wait a moment", | generatingText: "The video is generating, Please wait a moment", | ||||
| generationFailedText: "The video generate is failed, Reason:", | generationFailedText: "The video generate is failed, Reason:", | ||||
| edit:'Edit' | |||||
| edit:'Edit', | |||||
| upSharpness:'Upgrade image quality', | |||||
| upSharpnessTips:'If you are satisfied with the preview, you can click here to improve the video sharpness ~', | |||||
| freeUserTip:'Free user-generated videos are limited to 1 minute', | |||||
| hasNewVideo:'You have a new video status!', | |||||
| reset:"reset", | |||||
| }, | }, | ||||
| // 个人账户 | // 个人账户 | ||||
| @@ -94,6 +94,10 @@ export default { | |||||
| personBGI:'个人背景', | personBGI:'个人背景', | ||||
| systemMaterial:'系统素材', | systemMaterial:'系统素材', | ||||
| personMaterial:'个人素材', | personMaterial:'个人素材', | ||||
| abscissa:'横坐标', | |||||
| ordinate:'纵坐标', | |||||
| hierarchy:'层级', | |||||
| ratio:'缩放倍率', | |||||
| }, | }, | ||||
| // 我的视频 | // 我的视频 | ||||
| @@ -116,7 +120,12 @@ export default { | |||||
| manuscriptText: "草稿", | manuscriptText: "草稿", | ||||
| generatingText: "视频正在生成中,请稍等哦", | generatingText: "视频正在生成中,请稍等哦", | ||||
| generationFailedText: "视频生成失败。原因:", | generationFailedText: "视频生成失败。原因:", | ||||
| edit:'编辑' | |||||
| edit:'编辑', | |||||
| upSharpness:'升级画质', | |||||
| upSharpnessTips:'如果对预览效果满意,您可以点击此处来提升视频清晰度~', | |||||
| freeUserTip:'免费用户生成视频时长限制为1分钟', | |||||
| hasNewVideo:'您有新的视频状态!', | |||||
| reset:"重置", | |||||
| }, | }, | ||||
| // 个人账户 | // 个人账户 | ||||
| @@ -17,12 +17,12 @@ | |||||
| </div> | </div> | ||||
| {{ $t("createVideo.title") }} | {{ $t("createVideo.title") }} | ||||
| </div> | </div> | ||||
| <!-- <div class="myRouter-item" @click="router.push('/myCreating')"> | |||||
| <div class="myRouter-item" @click="router.push('/myCreating')"> | |||||
| <div class="icon"> | <div class="icon"> | ||||
| <el-icon><i-ep-edit /></el-icon> | |||||
| <el-icon><i-ep-menu /></el-icon> | |||||
| </div> | </div> | ||||
| {{ $t("myCreating.title") }} | {{ $t("myCreating.title") }} | ||||
| </div> --> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <!-- 右边显示部分 --> | <!-- 右边显示部分 --> | ||||
| @@ -25,6 +25,7 @@ div { | |||||
| text-align: center; | text-align: center; | ||||
| border: 1px solid #000; | border: 1px solid #000; | ||||
| border-radius: 5px; | border-radius: 5px; | ||||
| user-select: none; | |||||
| } | } | ||||
| p { | p { | ||||
| @@ -41,6 +41,7 @@ declare module '@vue/runtime-core' { | |||||
| IEpDownload: typeof import('~icons/ep/download')['default'] | IEpDownload: typeof import('~icons/ep/download')['default'] | ||||
| IEpEdit: typeof import('~icons/ep/edit')['default'] | IEpEdit: typeof import('~icons/ep/edit')['default'] | ||||
| IEpLoading: typeof import('~icons/ep/loading')['default'] | IEpLoading: typeof import('~icons/ep/loading')['default'] | ||||
| IEpMenu: typeof import('~icons/ep/menu')['default'] | |||||
| IEpSearch: typeof import('~icons/ep/search')['default'] | IEpSearch: typeof import('~icons/ep/search')['default'] | ||||
| IEpVideoPlay: typeof import('~icons/ep/video-play')['default'] | IEpVideoPlay: typeof import('~icons/ep/video-play')['default'] | ||||
| LangSelect: typeof import('./../components/LangSelect/index.vue')['default'] | LangSelect: typeof import('./../components/LangSelect/index.vue')['default'] | ||||
| @@ -0,0 +1,67 @@ | |||||
| import axios from 'axios' | |||||
| import router from '@/router/index' | |||||
| import { ElMessage } from 'element-plus' | |||||
| // ElMessage | |||||
| import { userInfoModules } from "@/store/modules/userInfo"; | |||||
| // import stores from '@/store/index' | |||||
| import { store } from '@/store/index'; // 因为不是在setup环境而是js中,必须重新初始化加载store | |||||
| const userInfoPinia = userInfoModules(store); //pinia | |||||
| // 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | |||||
| const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | |||||
| // console.log(process.env.NODE_ENV, 'env') | |||||
| /** | |||||
| * @description:发送Axios请求 | |||||
| */ | |||||
| const request = axios.create({ | |||||
| baseURL: env, | |||||
| timeout: 15000 | |||||
| }) | |||||
| // 请求拦截器 | |||||
| request.interceptors.request.use( | |||||
| function (config) { | |||||
| // 给所有授权的请求提供token | |||||
| const AccessToken = localStorage.getItem("AccessToken") | |||||
| if (AccessToken) { | |||||
| config.headers.token = AccessToken | |||||
| } | |||||
| return config | |||||
| }, | |||||
| function (error) { | |||||
| // 操作 | |||||
| return Promise.reject(error) | |||||
| } | |||||
| ) | |||||
| // 响应拦截器 | |||||
| request.interceptors.response.use( | |||||
| function (response) { | |||||
| let code = response.data.code | |||||
| // 当token无效(过期或损坏)时 1053为未登录 | |||||
| if (code == 1052 || code == 1053) { | |||||
| localStorage.removeItem("AccessToken"); | |||||
| router.push("/login"); | |||||
| ElMessage.error("登录过期,请重新登录!"); | |||||
| return | |||||
| // 弹出错误 | |||||
| } else if (code != 200) { | |||||
| if (code == 500) { | |||||
| ElMessage.error("系统异常,请稍后再试"); | |||||
| // 其他错误 | |||||
| } else { | |||||
| return Promise.reject(response.data) | |||||
| } | |||||
| } else { | |||||
| // 正常返回 | |||||
| return response.data | |||||
| } | |||||
| }, | |||||
| function (error) { | |||||
| } | |||||
| ) | |||||
| export default request | |||||
| @@ -1,15 +1,19 @@ | |||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import router from '@/router/index' | import router from '@/router/index' | ||||
| import { ElMessage } from 'element-plus' | import { ElMessage } from 'element-plus' | ||||
| // ElMessage | // ElMessage | ||||
| import { useAppStore } from '@/store/modules/app'; | |||||
| import { userInfoModules } from "@/store/modules/userInfo"; | import { userInfoModules } from "@/store/modules/userInfo"; | ||||
| // import stores from '@/store/index' | |||||
| import { store } from '@/store/index'; // 因为不是在setup环境而是js中,必须重新初始化加载store | import { store } from '@/store/index'; // 因为不是在setup环境而是js中,必须重新初始化加载store | ||||
| const appStore = useAppStore(store); //pinia | |||||
| const userInfoPinia = userInfoModules(store); //pinia | const userInfoPinia = userInfoModules(store); //pinia | ||||
| // const userInfoPinia = userInfoModules(store); //pinia | |||||
| // 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | // 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | ||||
| const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | ||||
| // console.log(process.env.NODE_ENV, 'env') | |||||
| // const env = process.env.NODE_ENV == 'development' ? "" : "" | |||||
| console.log(env) | |||||
| /** | /** | ||||
| * @description:发送Axios请求 | * @description:发送Axios请求 | ||||
| @@ -21,6 +25,7 @@ const request = axios.create({ | |||||
| // 请求拦截器 | // 请求拦截器 | ||||
| request.interceptors.request.use( | request.interceptors.request.use( | ||||
| function (config) { | function (config) { | ||||
| // 给所有授权的请求提供token | // 给所有授权的请求提供token | ||||
| const AccessToken = localStorage.getItem("AccessToken") | const AccessToken = localStorage.getItem("AccessToken") | ||||
| @@ -30,6 +35,14 @@ request.interceptors.request.use( | |||||
| return config | return config | ||||
| }, | }, | ||||
| function (error) { | function (error) { | ||||
| if (axios.isCancel(error)) { | |||||
| // 请求被取消处理 | |||||
| ElMessage.error( | |||||
| appStore.language == "zh-cn" ? `请求超时,请重试!` : `Request timeout, please try again` | |||||
| ); | |||||
| } | |||||
| // 操作 | // 操作 | ||||
| return Promise.reject(error) | return Promise.reject(error) | ||||
| } | } | ||||
| @@ -38,18 +51,31 @@ request.interceptors.request.use( | |||||
| // 响应拦截器 | // 响应拦截器 | ||||
| request.interceptors.response.use( | request.interceptors.response.use( | ||||
| function (response) { | function (response) { | ||||
| if (!response.data) { | |||||
| // ElMessage.error($t('tips.systemException')); | |||||
| ElMessage.error( | |||||
| appStore.language == "zh-cn" ? `服务器繁忙,请重试!` : `The server is busy, please try again` | |||||
| ); | |||||
| } | |||||
| let code = response.data.code | let code = response.data.code | ||||
| // 当token无效(过期或损坏)时 1053为未登录 | // 当token无效(过期或损坏)时 1053为未登录 | ||||
| if (code == 1052 || code == 1053) { | if (code == 1052 || code == 1053) { | ||||
| localStorage.removeItem("AccessToken"); | localStorage.removeItem("AccessToken"); | ||||
| router.push("/login"); | router.push("/login"); | ||||
| ElMessage.error("登录过期,请重新登录!"); | |||||
| // ElMessage.error("登录过期,请重新登录!"); | |||||
| // ElMessage.error($t('tips.tokenExpired')); | |||||
| ElMessage.error( | |||||
| appStore.language == "zh-cn" ? `登录过期,请重新登录!` : `Login expired, please login again` | |||||
| ); | |||||
| return | return | ||||
| // 弹出错误 | // 弹出错误 | ||||
| } else if (code != 200) { | } else if (code != 200) { | ||||
| if (code == 500) { | if (code == 500) { | ||||
| ElMessage.error("系统异常,请稍后再试"); | |||||
| // ElMessage.error("系统异常,请稍后再试"); | |||||
| // ElMessage.error($t('tips.systemException')); | |||||
| ElMessage.error( | |||||
| appStore.language == "zh-cn" ? `服务器繁忙,请重试!` : `The server is busy, please try again` | |||||
| ); | |||||
| // 其他错误 | // 其他错误 | ||||
| } else { | } else { | ||||
| return Promise.reject(response.data) | return Promise.reject(response.data) | ||||
| @@ -109,7 +109,7 @@ | |||||
| <div v-if="showImgInfo.data" class="showImgInfoBox"> | <div v-if="showImgInfo.data" class="showImgInfoBox"> | ||||
| <!-- <div class="infoItem"> | <!-- <div class="infoItem"> | ||||
| </div> --> | </div> --> | ||||
| <div class="ItemName">横坐标</div> | |||||
| <div class="ItemName">{{ $t("createVideo.abscissa") }}</div> | |||||
| <div class="ItemValue"> | <div class="ItemValue"> | ||||
| <el-input-number | <el-input-number | ||||
| v-model="showImgInfo.data.x" | v-model="showImgInfo.data.x" | ||||
| @@ -117,7 +117,7 @@ | |||||
| controls-position="right" | controls-position="right" | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| <div class="ItemName">纵坐标</div> | |||||
| <div class="ItemName">{{ $t("createVideo.ordinate") }}</div> | |||||
| <div class="ItemValue"> | <div class="ItemValue"> | ||||
| <el-input-number | <el-input-number | ||||
| v-model="showImgInfo.data.y" | v-model="showImgInfo.data.y" | ||||
| @@ -125,7 +125,7 @@ | |||||
| controls-position="right" | controls-position="right" | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| <div class="ItemName">层级</div> | |||||
| <div class="ItemName">{{ $t("createVideo.hierarchy") }}</div> | |||||
| <div class="ItemValue"> | <div class="ItemValue"> | ||||
| <el-input-number | <el-input-number | ||||
| v-model="showImgInfo.data.z" | v-model="showImgInfo.data.z" | ||||
| @@ -135,7 +135,7 @@ | |||||
| controls-position="right" | controls-position="right" | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| <div class="ItemName">缩放倍率</div> | |||||
| <div class="ItemName">{{ $t("createVideo.ratio") }}</div> | |||||
| <div class="ItemValue"> | <div class="ItemValue"> | ||||
| <el-input-number | <el-input-number | ||||
| v-model="showImgInfo.data.w" | v-model="showImgInfo.data.w" | ||||
| @@ -148,11 +148,21 @@ | |||||
| </div> | </div> | ||||
| <!-- 保存视频和生成视频 --> | <!-- 保存视频和生成视频 --> | ||||
| <div class="btnBox" v-show="!showChooseModel"> | <div class="btnBox" v-show="!showChooseModel"> | ||||
| <div class="customBtn" style="margin-right: 15px"> | |||||
| {{ $t("createVideo.saveVideo") }} | |||||
| <div | |||||
| @click="saveOrUpdate('isSave')" | |||||
| class="customBtn" | |||||
| style="margin-right: 15px" | |||||
| > | |||||
| <MyLoadingIcon :isLoading="saveLoading"></MyLoadingIcon> | |||||
| <div v-if="!saveLoading"> | |||||
| {{ $t("createVideo.saveVideo") }} | |||||
| </div> | |||||
| </div> | </div> | ||||
| <div class="customBtn"> | |||||
| {{ $t("createVideo.generateVideo") }} | |||||
| <div @click="createVideo" class="customBtn"> | |||||
| <MyLoadingIcon :isLoading="createLoading"></MyLoadingIcon> | |||||
| <div v-if="!createLoading"> | |||||
| {{ $t("createVideo.generateVideo") }} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -298,14 +308,14 @@ | |||||
| <div | <div | ||||
| class="tabItem" | class="tabItem" | ||||
| :class="bjTabItemActive == 1 ? 'tabItemActive' : ''" | :class="bjTabItemActive == 1 ? 'tabItemActive' : ''" | ||||
| @click="bjTabItemActive = 1" | |||||
| @click="changeBjTabItemActive(1)" | |||||
| > | > | ||||
| {{ $t("createVideo.systemBGI") }} | {{ $t("createVideo.systemBGI") }} | ||||
| </div> | </div> | ||||
| <div | <div | ||||
| class="tabItem" | class="tabItem" | ||||
| :class="bjTabItemActive == 2 ? 'tabItemActive' : ''" | :class="bjTabItemActive == 2 ? 'tabItemActive' : ''" | ||||
| @click="bjTabItemActive = 2" | |||||
| @click="changeBjTabItemActive(2)" | |||||
| > | > | ||||
| {{ $t("createVideo.personBGI") }} | {{ $t("createVideo.personBGI") }} | ||||
| </div> | </div> | ||||
| @@ -372,14 +382,14 @@ | |||||
| <div | <div | ||||
| class="tabItem" | class="tabItem" | ||||
| :class="scTabItemActive == 1 ? 'tabItemActive' : ''" | :class="scTabItemActive == 1 ? 'tabItemActive' : ''" | ||||
| @click="scTabItemActive = 1" | |||||
| @click="changeScTabItemActive(1)" | |||||
| > | > | ||||
| {{ $t("createVideo.systemMaterial") }} | {{ $t("createVideo.systemMaterial") }} | ||||
| </div> | </div> | ||||
| <div | <div | ||||
| class="tabItem" | class="tabItem" | ||||
| :class="scTabItemActive == 2 ? 'tabItemActive' : ''" | :class="scTabItemActive == 2 ? 'tabItemActive' : ''" | ||||
| @click="scTabItemActive = 2" | |||||
| @click="changeScTabItemActive(2)" | |||||
| > | > | ||||
| {{ $t("createVideo.personMaterial") }} | {{ $t("createVideo.personMaterial") }} | ||||
| </div> | </div> | ||||
| @@ -466,6 +476,7 @@ import { | |||||
| personPatchApi, | personPatchApi, | ||||
| saveOrUpdateApi, | saveOrUpdateApi, | ||||
| createVideoApi, | createVideoApi, | ||||
| getModelDetailByIdApi, | |||||
| } from "@/apis/createVideo"; | } from "@/apis/createVideo"; | ||||
| import { useI18n } from "vue-i18n"; | import { useI18n } from "vue-i18n"; | ||||
| import Recorder from "js-audio-recorder"; //mp3插件 | import Recorder from "js-audio-recorder"; //mp3插件 | ||||
| @@ -478,14 +489,14 @@ const route = useRoute(); | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const { locale } = useI18n(); | const { locale } = useI18n(); | ||||
| const lanChange = ref(locale); | const lanChange = ref(locale); | ||||
| const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | |||||
| // ElMessage.error( | // ElMessage.error( | ||||
| // lanChange.value == "zh-cn" | // lanChange.value == "zh-cn" | ||||
| // ? `您还没有输入文案` | // ? `您还没有输入文案` | ||||
| // : `You have not entered the copy yet` | // : `You have not entered the copy yet` | ||||
| // ); | // ); | ||||
| const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | |||||
| //#region 选择模版弹出框 | //#region 选择模版弹出框 | ||||
| const videoType = ref(null); //判断横屏2还是竖屏1,初始为没有,控制按钮显隐 | const videoType = ref(null); //判断横屏2还是竖屏1,初始为没有,控制按钮显隐 | ||||
| const showChooseModel = ref(true); // 控制弹窗显示隐藏 | const showChooseModel = ref(true); // 控制弹窗显示隐藏 | ||||
| @@ -720,6 +731,18 @@ const bjTabItemActive = ref(1); //系统或个人tab高亮 | |||||
| const systemBGIList = ref([]); //系统背景列表 | const systemBGIList = ref([]); //系统背景列表 | ||||
| const systemBGPageNum = ref(1); //系统背景页数 | const systemBGPageNum = ref(1); //系统背景页数 | ||||
| const overLoadSystemBG = ref(true); //禁止系统背景触底刷新 | 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() { | async function getSystemBGIList() { | ||||
| const res = await systemBGIListApi( | const res = await systemBGIListApi( | ||||
| systemBGPageNum.value, | systemBGPageNum.value, | ||||
| @@ -780,7 +803,9 @@ watch( | |||||
| overLoadSystemBG.value = true; | overLoadSystemBG.value = true; | ||||
| overLoadpersonBG.value = true; | overLoadpersonBG.value = true; | ||||
| await getSystemBGIList(); | await getSystemBGIList(); | ||||
| await getpersonBGIList(); | |||||
| if (AccessToken) { | |||||
| await getpersonBGIList(); | |||||
| } | |||||
| }, | }, | ||||
| { deep: true } | { deep: true } | ||||
| ); | ); | ||||
| @@ -804,6 +829,18 @@ const scTabItemActive = ref(1); //系统或个人tab高亮 | |||||
| const systemSCIList = ref([]); //系统素材列表 | const systemSCIList = ref([]); //系统素材列表 | ||||
| const systemSCPageNum = ref(1); //系统素材页数 | const systemSCPageNum = ref(1); //系统素材页数 | ||||
| const overLoadSystemSC = ref(true); //禁止系统素材触底刷新 | 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() { | async function getSystemSCIList() { | ||||
| const res = await systemSCIListApi( | const res = await systemSCIListApi( | ||||
| systemSCPageNum.value, | systemSCPageNum.value, | ||||
| @@ -970,14 +1007,176 @@ watch( | |||||
| //#region 保存视频和生成草稿 | //#region 保存视频和生成草稿 | ||||
| const workId = ref(null); //保存作品完成后会有一个id,用于生成视频 | const workId = ref(null); //保存作品完成后会有一个id,用于生成视频 | ||||
| async function saveOrUpdate() { | |||||
| 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; | |||||
| 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 | |||||
| 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]), // 素材 | |||||
| }; | |||||
| const res = await saveOrUpdateApi(data); | |||||
| workId.value = res.data.id; | |||||
| saveLoading.value = false; | |||||
| ElMessage.success( | |||||
| lanChange.value == "zh-cn" | |||||
| ? `保存草稿成功!` | |||||
| : `Save draft successfully!` | |||||
| ); | |||||
| } 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 | |||||
| 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]), // 素材 | |||||
| }; | |||||
| 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 { | try { | ||||
| createLoading.value = true; | |||||
| if (!textareaContent.value) { | if (!textareaContent.value) { | ||||
| ElMessage.error( | ElMessage.error( | ||||
| lanChange.value == "zh-cn" | lanChange.value == "zh-cn" | ||||
| ? `您还没有输入文案` | ? `您还没有输入文案` | ||||
| : `You have not entered the copy yet` | : `You have not entered the copy yet` | ||||
| ); | ); | ||||
| createLoading.value = false; | |||||
| return; | return; | ||||
| } | } | ||||
| if (!sound.value && !soundStyle.value) { | if (!sound.value && !soundStyle.value) { | ||||
| @@ -986,62 +1185,42 @@ async function saveOrUpdate() { | |||||
| ? `您还没有选择声音` | ? `您还没有选择声音` | ||||
| : `You have not selected a sound` | : `You have not selected a sound` | ||||
| ); | ); | ||||
| createLoading.value = false; | |||||
| return; | 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 | |||||
| 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]), // 素材 | |||||
| }; | |||||
| const res = await saveOrUpdateApi(data); | |||||
| workId.value = res.data.id; | |||||
| } catch (error) { | |||||
| ElMessage.error(error); | |||||
| } | |||||
| } | |||||
| async function createVideo() { | |||||
| try { | |||||
| await saveOrUpdate(); | |||||
| await saveOrUpdate("isCreate"); | |||||
| const res2 = await createVideoApi(workId.value); | const res2 = await createVideoApi(workId.value); | ||||
| ElMessage.success( | |||||
| lanChange.value == "zh-cn" | |||||
| ? `视频生成成功!` | |||||
| : `Video generation is successful!` | |||||
| ); | |||||
| createLoading.value = false; | |||||
| router.push("/myCreating"); | |||||
| } catch (error) { | } catch (error) { | ||||
| ElMessage.error(error); | ElMessage.error(error); | ||||
| createLoading.value = false; | |||||
| } | } | ||||
| } | } | ||||
| //#endregion ---------------------------- | //#endregion ---------------------------- | ||||
| //#region | |||||
| async function getModelDetailById() { | |||||
| const res = await getModelDetailByIdApi(route.query.id); | |||||
| workId.value = res.data.id; | |||||
| videoType.value = res.data.videoType; | |||||
| title.value = res.data.title; //标题 | |||||
| textareaContent.value = res.data.paperwork; //语音内容 | |||||
| materialList.BGI.id = res.data.backgroundId + ""; //背景id | |||||
| 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) | |||||
| : []; | |||||
| } | |||||
| //#endregion ---------------------------- | |||||
| //#region | //#region | ||||
| //#endregion ---------------------------- | //#endregion ---------------------------- | ||||
| @@ -1064,8 +1243,13 @@ onMounted(async () => { | |||||
| // getSystemSCIList(); | // getSystemSCIList(); | ||||
| // getpersonBGIList(); | // getpersonBGIList(); | ||||
| await getModeList(tabSex.value, 1, 20, tabVideoType.value); //获取模版列表 | await getModeList(tabSex.value, 1, 20, tabVideoType.value); //获取模版列表 | ||||
| getpersonSCIList(); | |||||
| if (AccessToken) { | |||||
| getpersonSCIList(); | |||||
| } | |||||
| getSystemSCIList(); | getSystemSCIList(); | ||||
| if (route.query.id) { | |||||
| // getModelDetailById(); | |||||
| } | |||||
| }); | }); | ||||
| </script> | </script> | ||||
| @@ -1169,6 +1353,7 @@ onMounted(async () => { | |||||
| // margin: 0 10px; | // margin: 0 10px; | ||||
| // padding: 0 5px; | // padding: 0 5px; | ||||
| background-color: #000; | background-color: #000; | ||||
| user-select: none; | |||||
| } | } | ||||
| .tabItemActive { | .tabItemActive { | ||||
| background-color: #fff; | background-color: #fff; | ||||
| @@ -1287,7 +1472,17 @@ onMounted(async () => { | |||||
| right: 10px; | right: 10px; | ||||
| width: 250px; | width: 250px; | ||||
| .customBtn { | .customBtn { | ||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| width: 45%; | width: 45%; | ||||
| height: 50px; | |||||
| user-select: none; | |||||
| > div { | |||||
| width: 100%; | |||||
| text-align: center; | |||||
| cursor: pointer; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1314,6 +1509,7 @@ onMounted(async () => { | |||||
| border-radius: 25px; | border-radius: 25px; | ||||
| transition: all 0.3s; | transition: all 0.3s; | ||||
| cursor: pointer; | cursor: pointer; | ||||
| user-select: none; | |||||
| } | } | ||||
| .tabItemActive { | .tabItemActive { | ||||
| background-color: #000; | background-color: #000; | ||||
| @@ -0,0 +1,695 @@ | |||||
| <template> | |||||
| <div class="page"> | |||||
| <!-- 搜索框 --> | |||||
| <div class="top"> | |||||
| <div class="flex justify-between" style="width: 300px"> | |||||
| <el-input | |||||
| v-model="title" | |||||
| :placeholder="$t('myCreating.search')" | |||||
| @keyup.enter="searchVideoList" | |||||
| /> | |||||
| <el-icon class="icon-edit" @click="searchVideoList" | |||||
| ><i-ep-search | |||||
| /></el-icon> | |||||
| </div> | |||||
| </div> | |||||
| <!-- 作品列表 --> | |||||
| <div v-if="!isLoading"> | |||||
| <div v-if="videoList.length > 0" class="workList flex"> | |||||
| <div class="workItem" v-for="item in videoList" :key="item.id"> | |||||
| <div class="workImg"> | |||||
| <img | |||||
| v-if="item.coverImg" | |||||
| class="coverImg inmiddle" | |||||
| :src="item.coverImg" | |||||
| alt="" | |||||
| /> | |||||
| <img | |||||
| v-else | |||||
| class="takePlace inmiddle" | |||||
| src="@/assets/img/left-top-logo.png" | |||||
| alt="" | |||||
| /> | |||||
| </div> | |||||
| <div :class="'statusName ' + item.statusName"> | |||||
| {{ $t("myCreating." + item.statusName) }} | |||||
| </div> | |||||
| <div class="workInfo flex"> | |||||
| <span>{{ item.title }}</span> | |||||
| <span>{{ dayjs(item.createDate).format("YYYY-MM-DD") }}</span> | |||||
| </div> | |||||
| <!-- 更多遮罩层 --> | |||||
| <div | |||||
| class="more" | |||||
| @mouseleave="mouseleave" | |||||
| @click="clickVideoItem(item)" | |||||
| > | |||||
| <el-icon | |||||
| v-if="[0].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-edit | |||||
| /></el-icon> | |||||
| <el-icon | |||||
| v-if="[1, 2, 4, 6].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-loading | |||||
| /></el-icon> | |||||
| <el-icon | |||||
| v-if="[3].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-closeBold | |||||
| /></el-icon> | |||||
| <el-icon | |||||
| v-if="[5].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-videoPlay | |||||
| /></el-icon> | |||||
| <div class="showBtn" @click.stop="mouseenter(item)">...</div> | |||||
| <div class="btns" v-show="showPopup"> | |||||
| <!-- 下载按钮 --> | |||||
| <div | |||||
| class="btns-item" | |||||
| @click.stop="handleDownload(item.videoPlayUrl)" | |||||
| > | |||||
| <div class="btns-item-icon"> | |||||
| <el-icon class="icon-delete"><i-ep-download /></el-icon> | |||||
| </div> | |||||
| <div class="text">{{ $t("myCreating.download") }}</div> | |||||
| </div> | |||||
| <!-- 删除按钮 --> | |||||
| <div | |||||
| class="btns-item" | |||||
| @click.stop="handelDelete(item.id, item.title)" | |||||
| > | |||||
| <div class="btns-item-icon"> | |||||
| <el-icon class="icon-delete"><i-ep-delete /></el-icon> | |||||
| </div> | |||||
| <div class="text">{{ $t("myCreating.delete") }}</div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div v-if="videoList.length == 0" class="noList"> | |||||
| <div class="title"> | |||||
| {{ $t("myCreating.noList") }} | |||||
| </div> | |||||
| <div class="goCreate" @click="goCreate"> | |||||
| {{ $t("myCreating.goCreate") }} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div v-if="isLoading" class="loadingIcon"> | |||||
| <el-icon class="is-loading"> | |||||
| <svg | |||||
| viewBox="0 0 1024 1024" | |||||
| xmlns="http://www.w3.org/2000/svg" | |||||
| data-v-ea893728="" | |||||
| > | |||||
| <path | |||||
| fill="currentColor" | |||||
| d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" | |||||
| ></path> | |||||
| </svg> | |||||
| </el-icon> | |||||
| <span class="loadingText">{{ $t("myCreating.loading") }}</span> | |||||
| </div> | |||||
| <!-- 弹出框预览作品 --> | |||||
| <el-dialog | |||||
| destroy-on-close | |||||
| class="elDialog" | |||||
| v-model="showDialog" | |||||
| :title="presentItem.title" | |||||
| width="40%" | |||||
| center | |||||
| > | |||||
| <div class="videoBox"> | |||||
| <video | |||||
| v-if="presentItem.videoPlayUrl" | |||||
| controls="true" | |||||
| class="" | |||||
| :src="presentItem.videoPlayUrl" | |||||
| ></video> | |||||
| <div v-else class="insteadVideo"> | |||||
| {{ $t("myCreating." + presentItem.statusName + "Text") }} | |||||
| <span v-if="presentItem.videoStatus == 3">{{ | |||||
| presentItem.videoMsg | |||||
| }}</span> | |||||
| </div> | |||||
| <!-- 有视频路径的页脚 --> | |||||
| <div class="footer" v-if="presentItem.videoPlayUrl"> | |||||
| <span class="dialog-footer"> | |||||
| <!-- dialog下载按钮 --> | |||||
| <button | |||||
| class="elBtn" | |||||
| type="primary" | |||||
| @click.stop="handleDownload(presentItem.videoPlayUrl)" | |||||
| > | |||||
| <el-icon class="icon-delete"><i-ep-download /></el-icon | |||||
| >{{ $t("myCreating.download") }} | |||||
| </button> | |||||
| <!-- dialog删除按钮 --> | |||||
| <button | |||||
| class="elBtn" | |||||
| @click.stop="handelDelete(presentItem.id, presentItem.title)" | |||||
| > | |||||
| <el-icon class="icon-delete"><i-ep-delete /></el-icon | |||||
| >{{ $t("myCreating.delete") }} | |||||
| </button> | |||||
| </span> | |||||
| </div> | |||||
| <!-- 无视频路径的页脚 --> | |||||
| <div class="footer" v-if="!presentItem.videoPlayUrl"> | |||||
| <span class="dialog-footer"> | |||||
| <!-- dialog编辑按钮 --> | |||||
| <button | |||||
| class="elBtn" | |||||
| type="primary" | |||||
| @click.stop=" | |||||
| router.push({ | |||||
| path: '/createVideo', | |||||
| query: { id: presentItem.id }, | |||||
| }) | |||||
| " | |||||
| v-if="[0, 3].includes(presentItem.videoStatus)" | |||||
| > | |||||
| {{ $t("myCreating.edit") }} | |||||
| </button> | |||||
| </span> | |||||
| </div> | |||||
| </div> | |||||
| </el-dialog> | |||||
| <!-- 分页 --> | |||||
| <div v-if="!isLoading" class="pagination"> | |||||
| <el-pagination | |||||
| v-model:current-page="pageNum" | |||||
| v-model:page-size="pageSize" | |||||
| :page-sizes="[10, 20, 50, 100, 200]" | |||||
| :small="false" | |||||
| :disabled="false" | |||||
| :background="true" | |||||
| layout="total, sizes, prev, pager, next, jumper" | |||||
| :total="total" | |||||
| @size-change="handleSizeChange" | |||||
| @current-change="handleCurrentChange" | |||||
| /> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script setup> | |||||
| import { userPhotoVideoList, delUserPhotoVideoByID } from "@/apis/myCreating"; | |||||
| import { timestampToTime } from "@/utils/tools"; | |||||
| import { useI18n } from "vue-i18n"; | |||||
| import { getStatus } from "./videoStatus"; | |||||
| import { useRouter } from "vue-router"; | |||||
| import dayjs from "dayjs"; | |||||
| const router = useRouter(); | |||||
| // 当前语言状态与国际化组件 | |||||
| const { locale } = useI18n(); | |||||
| const lanChange = ref(locale); | |||||
| const title = ref(""); | |||||
| const pageNum = ref(1); | |||||
| const pageSize = ref(10); | |||||
| const total = ref(0); | |||||
| // 弹窗显示隐藏 | |||||
| const showDialog = ref(false); | |||||
| const isLoading = ref(true); | |||||
| // 当前作品 | |||||
| const presentItem = ref(""); | |||||
| // 作品列表 | |||||
| const videoList = ref([]); | |||||
| const handleSizeChange = (val) => { | |||||
| pageSize.value = val; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }; | |||||
| const handleCurrentChange = (val) => { | |||||
| pageNum.value = val; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }; | |||||
| // 点击作品 | |||||
| function clickVideoItem(item) { | |||||
| showDialog.value = true; | |||||
| presentItem.value = item; | |||||
| } | |||||
| // 删除框是否显示 | |||||
| let showPopup = ref(false); | |||||
| function mouseleave() { | |||||
| showPopup.value = false; | |||||
| } | |||||
| function mouseenter(item) { | |||||
| presentItem.value = item; | |||||
| showPopup.value = !showPopup.value; | |||||
| } | |||||
| // 下载 | |||||
| function handleDownload(itemVideoPlayUrl) { | |||||
| if (itemVideoPlayUrl) { | |||||
| const link = document.createElement("a"); | |||||
| link.href = itemVideoPlayUrl; | |||||
| document.body.appendChild(link); | |||||
| link.click(); | |||||
| document.body.removeChild(link); | |||||
| } else { | |||||
| ElMessage.error( | |||||
| lanChange.value == "zh-cn" ? `无法下载` : `Unable to download` | |||||
| ); | |||||
| } | |||||
| } | |||||
| function goCreate() { | |||||
| router.push("/createVideo"); | |||||
| } | |||||
| function searchVideoList() { | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value, true); | |||||
| } | |||||
| function handelDelete(id, title) { | |||||
| const msg = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `确定要删除这个作品吗? 作品标题:${title}` | |||||
| : `Are you sure to delete this video ? Title:${title};`; | |||||
| 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(() => { | |||||
| delPhotoVideo(id); | |||||
| }); | |||||
| } | |||||
| /** | |||||
| * @description:获取我的视频作品 | |||||
| * @return: data | |||||
| */ | |||||
| function getPhotoVideoList(pageNum, pageSize, title, searchFlag) { | |||||
| userPhotoVideoList(pageNum, pageSize, title) | |||||
| .then((res) => { | |||||
| console.log(res, "res"); | |||||
| res.data.list.forEach((item) => { | |||||
| // item.createDate = timestampToTime(item.createDate) || ""; | |||||
| // item.updateDate = timestampToTime(item.updateDate) || ""; | |||||
| // item.createVideoDate = timestampToTime(item.createVideoDate) || ""; | |||||
| item.statusName = getStatus(item.videoStatus); | |||||
| }); | |||||
| videoList.value = res.data.list; | |||||
| total.value = res.data.total * 1; | |||||
| if (searchFlag) { | |||||
| const total = res.data.total; | |||||
| const msg1 = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `查询成功!找到${total}条符合条件的视频` | |||||
| : `Found! Match ${total} videos`; | |||||
| const msg2 = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `查询成功!没有符合条件的视频` | |||||
| : `Found! No match videos`; | |||||
| const msg3 = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `查询成功!已加载全部视频` | |||||
| : `Found! Present all videos`; | |||||
| return title | |||||
| ? ElMessage.success(total > 0 ? msg1 : msg2) | |||||
| : ElMessage.success(msg3); | |||||
| } | |||||
| isLoading.value = false; | |||||
| }) | |||||
| .catch((err) => { | |||||
| console.log(err, "err"); | |||||
| }); | |||||
| } | |||||
| /** | |||||
| * @description:删除视频作品 | |||||
| * @param: videoID | |||||
| * @return: data | |||||
| */ | |||||
| function delPhotoVideo(videoID) { | |||||
| delUserPhotoVideoByID(videoID) | |||||
| .then((res) => { | |||||
| console.log(res, "res"); | |||||
| const msg = lanChange.value == "zh-cn" ? `删除成功!` : `Success !`; | |||||
| ElMessage.success(msg); | |||||
| showDialog.value = false; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }) | |||||
| .catch((err) => { | |||||
| console.log(err, "err"); | |||||
| ElMessage.error(err.message); | |||||
| }); | |||||
| } | |||||
| onMounted(() => { | |||||
| isLoading.value = true; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }); | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page { | |||||
| min-height: calc(100vh - 80px); | |||||
| padding: 15px 130px; | |||||
| background-color: #fff; | |||||
| border-radius: 25px 0 0; | |||||
| .top { | |||||
| margin-bottom: 35px; | |||||
| } | |||||
| .loadingIcon { | |||||
| height: 100px; | |||||
| line-height: 100px; | |||||
| text-align: center; | |||||
| transform: scale(2); | |||||
| .loadingText { | |||||
| position: relative; | |||||
| top: -2px; | |||||
| left: 4px; | |||||
| } | |||||
| } | |||||
| .workList { | |||||
| flex-wrap: wrap; | |||||
| justify-content: flex-start; | |||||
| width: 100%; | |||||
| // height: 200px; | |||||
| margin-top: 5px; | |||||
| padding-bottom: 50px; | |||||
| cursor: pointer; | |||||
| .workItem { | |||||
| position: relative; | |||||
| width: 300px; | |||||
| // height: 200px; | |||||
| margin: 0 20px 20px 0; | |||||
| border: 2px solid #c2c2c2; | |||||
| border-radius: 15px; | |||||
| cursor: pointer; | |||||
| overflow: hidden; | |||||
| .workImg { | |||||
| position: relative; | |||||
| width: 100%; | |||||
| height: 170px; | |||||
| cursor: pointer; | |||||
| padding: 10px; | |||||
| overflow: hidden; | |||||
| .coverImg { | |||||
| max-width: 90%; | |||||
| max-height: 170px; | |||||
| cursor: pointer; | |||||
| } | |||||
| .takePlace { | |||||
| position: absolute; | |||||
| top: 40%; | |||||
| width: 80%; | |||||
| } | |||||
| } | |||||
| .more { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 0; | |||||
| width: 100%; | |||||
| height: 170px; | |||||
| background-color: rgb(0 0 0 / 30%); | |||||
| cursor: pointer; | |||||
| opacity: 0; | |||||
| transition: all 0.2s; | |||||
| .icon-videoPlay { | |||||
| position: absolute; | |||||
| top: 50%; | |||||
| left: 50%; | |||||
| width: 50px; | |||||
| height: 50px; | |||||
| font-size: 50px; | |||||
| color: #fff; | |||||
| text-align: center; | |||||
| transform: translate(-50%, -50%); | |||||
| cursor: pointer; | |||||
| } | |||||
| .showBtn { | |||||
| position: absolute; | |||||
| top: 10px; | |||||
| right: 10px; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| font-size: 20px; | |||||
| line-height: 10px; | |||||
| color: #fff; | |||||
| text-align: center; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| border-radius: 2px; | |||||
| &:hover { | |||||
| background-color: #00000056; | |||||
| } | |||||
| } | |||||
| .btns { | |||||
| position: absolute; | |||||
| top: 45px; | |||||
| right: 10px; | |||||
| // width: 70px; | |||||
| // height: 60px; | |||||
| overflow: hidden; | |||||
| border-radius: 10px; | |||||
| cursor: pointer; | |||||
| &-item { | |||||
| // width: 70px; | |||||
| // height: 30px; | |||||
| text-align: center; | |||||
| background-color: #fff; | |||||
| padding: 0 10px; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| &-icon { | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| cursor: pointer; | |||||
| .icon-delete { | |||||
| position: absolute; | |||||
| top: 4px; | |||||
| left: 0; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| font-size: 16px; | |||||
| color: #000; | |||||
| text-align: center; | |||||
| cursor: pointer; | |||||
| } | |||||
| } | |||||
| .text { | |||||
| display: inline-block; | |||||
| height: 30px; | |||||
| padding-left: 5px; | |||||
| margin-top: -5px; | |||||
| line-height: 20px; | |||||
| cursor: pointer; | |||||
| } | |||||
| &:hover { | |||||
| color: #ffffff; | |||||
| background-color: #0000001a; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .workInfo { | |||||
| justify-content: space-between; | |||||
| height: 40px; | |||||
| padding: 0 10px; | |||||
| line-height: 40px; | |||||
| border-top: 1px solid #afafaf; | |||||
| white-space: nowrap; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| font-size: 13px; | |||||
| } | |||||
| .statusName { | |||||
| position: absolute; | |||||
| top: 10%; | |||||
| left: -10%; | |||||
| width: 120px; | |||||
| text-align: center; | |||||
| color: #ffffff; | |||||
| font-size: 14px; | |||||
| transform: rotate(-45deg); | |||||
| &.manuscript { | |||||
| /* 草稿 */ | |||||
| background: linear-gradient(to right, #d7d2cc 0%, #304352 100%); | |||||
| } | |||||
| &.generating { | |||||
| /* 生成中 */ | |||||
| background: linear-gradient(270deg, #4b61dc, #15d1b8); | |||||
| } | |||||
| &.generationFailed { | |||||
| /* 生成失败 */ | |||||
| background: linear-gradient(120deg, #f093fb 0%, #f5576c 100%); | |||||
| } | |||||
| &.generationSucceed { | |||||
| /* 生成成功 */ | |||||
| background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%); | |||||
| } | |||||
| } | |||||
| &:hover { | |||||
| .more { | |||||
| opacity: 1; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .noList { | |||||
| .title { | |||||
| font-size: 30px; | |||||
| text-align: center; | |||||
| margin-top: 100px; | |||||
| background-image: -webkit-linear-gradient( | |||||
| left, | |||||
| #4b61dc, | |||||
| #15d1b8 25%, | |||||
| #4b61dc 50%, | |||||
| #15d1b8 75%, | |||||
| #4b61dc | |||||
| ) !important; | |||||
| -webkit-text-fill-color: transparent !important; | |||||
| -webkit-background-clip: text !important; | |||||
| background-clip: text !important; | |||||
| -webkit-background-size: 200% 100% !important; | |||||
| background-size: 200% 100% !important; | |||||
| } | |||||
| .goCreate { | |||||
| width: 200px; | |||||
| height: 40px; | |||||
| line-height: 40px; | |||||
| text-align: center; | |||||
| color: #ffffff; | |||||
| border-radius: 6px; | |||||
| background: linear-gradient(270deg, #4b61dc, #15d1b8); | |||||
| margin: 30px auto; | |||||
| cursor: pointer; | |||||
| transition: all 0.3s; | |||||
| &:hover { | |||||
| transform: scale(1.1); | |||||
| } | |||||
| } | |||||
| } | |||||
| .pagination { | |||||
| position: fixed; | |||||
| bottom: 20px; | |||||
| left: 50%; | |||||
| transform: translateX(-50%); | |||||
| background-color: #ffffff; | |||||
| padding: 10px 20px; | |||||
| border-radius: 8px; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| &:hover { | |||||
| background-color: #b8b8b873; | |||||
| } | |||||
| } | |||||
| } | |||||
| :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; | |||||
| } | |||||
| } | |||||
| .elDialog { | |||||
| .videoBox { | |||||
| // display: flex; | |||||
| // justify-content: space-between; | |||||
| width: 100%; | |||||
| padding: 20px; | |||||
| video { | |||||
| width: 100%; | |||||
| max-height: 600px; | |||||
| margin: auto; | |||||
| } | |||||
| .insteadVideo { | |||||
| font-size: 20px; | |||||
| font-weight: 600; | |||||
| margin: 20px auto; | |||||
| text-align: center; | |||||
| } | |||||
| } | |||||
| .dialog-footer { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| .elBtn { | |||||
| color: #fff; | |||||
| border-radius: 10px; | |||||
| padding: 5px 10px; | |||||
| cursor: pointer; | |||||
| background-color: #000; | |||||
| transition: all 0.3s; | |||||
| &:hover { | |||||
| background-color: #15d1b8; | |||||
| } | |||||
| } | |||||
| :deep(.el-icon) { | |||||
| margin-right: 5px; | |||||
| font-weight: 700; | |||||
| } | |||||
| } | |||||
| } | |||||
| :deep(.el-dialog) { | |||||
| overflow: hidden; | |||||
| border-radius: 25px; | |||||
| } | |||||
| // :deep(.el-dialog__header) { | |||||
| // } | |||||
| :deep(.el-dialog__title) { | |||||
| background-image: -webkit-linear-gradient( | |||||
| left, | |||||
| #4b61dc, | |||||
| #15d1b8 25%, | |||||
| #4b61dc 50%, | |||||
| #15d1b8 75%, | |||||
| #4b61dc | |||||
| ) !important; | |||||
| -webkit-text-fill-color: transparent !important; | |||||
| -webkit-background-clip: text !important; | |||||
| background-clip: text !important; | |||||
| -webkit-background-size: 200% 100% !important; | |||||
| background-size: 200% 100% !important; | |||||
| } | |||||
| :deep(.el-dialog__body) { | |||||
| padding: 0; | |||||
| } | |||||
| :deep(.dialog__footer) { | |||||
| padding: 0; | |||||
| } | |||||
| </style> | |||||
| @@ -2,8 +2,9 @@ | |||||
| <div class="page"> | <div class="page"> | ||||
| <!-- 搜索框 --> | <!-- 搜索框 --> | ||||
| <div class="top"> | <div class="top"> | ||||
| <div class="flex justify-between" style="width: 300px"> | |||||
| <div class="search"> | |||||
| <el-input | <el-input | ||||
| style="width: 300px" | |||||
| v-model="title" | v-model="title" | ||||
| :placeholder="$t('myCreating.search')" | :placeholder="$t('myCreating.search')" | ||||
| @keyup.enter="searchVideoList" | @keyup.enter="searchVideoList" | ||||
| @@ -11,6 +12,14 @@ | |||||
| <el-icon class="icon-edit" @click="searchVideoList" | <el-icon class="icon-edit" @click="searchVideoList" | ||||
| ><i-ep-search | ><i-ep-search | ||||
| /></el-icon> | /></el-icon> | ||||
| <!-- 重置按钮 --> | |||||
| <div v-show="title" class="resetSearch" @click="resetSearch"> | |||||
| {{ $t("myCreating.reset") }} | |||||
| </div> | |||||
| </div> | |||||
| <!-- 更新视频提示 --> | |||||
| <div class="hasNewVideoTips" :class="hasNewCreate ? '' : 'hasNew'"> | |||||
| {{ $t("myCreating.hasNewVideo") }} | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <!-- 作品列表 --> | <!-- 作品列表 --> | ||||
| @@ -62,7 +71,7 @@ | |||||
| ><i-ep-closeBold | ><i-ep-closeBold | ||||
| /></el-icon> | /></el-icon> | ||||
| <el-icon | <el-icon | ||||
| v-if="[5].includes(item.videoStatus)" | |||||
| v-if="[5, 7, 8, 9, 10, 11, 12].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | class="icon-videoPlay" | ||||
| ><i-ep-videoPlay | ><i-ep-videoPlay | ||||
| /></el-icon> | /></el-icon> | ||||
| @@ -71,7 +80,7 @@ | |||||
| <!-- 下载按钮 --> | <!-- 下载按钮 --> | ||||
| <div | <div | ||||
| class="btns-item" | class="btns-item" | ||||
| @click.stop="handleDownload(item.videoPlayUrl)" | |||||
| @click.stop="handleDownload(item.videoPlayUrl, item.title)" | |||||
| > | > | ||||
| <div class="btns-item-icon"> | <div class="btns-item-icon"> | ||||
| <el-icon class="icon-delete"><i-ep-download /></el-icon> | <el-icon class="icon-delete"><i-ep-download /></el-icon> | ||||
| @@ -126,6 +135,14 @@ | |||||
| center | center | ||||
| > | > | ||||
| <div class="videoBox"> | <div class="videoBox"> | ||||
| <!-- 免费用户1分钟 [5].includes(presentItem.videoStatus)--> | |||||
| <div | |||||
| v-if="presentItem.videoPlayUrl && presentItem.videoTime > 60" | |||||
| class="overtimeTips" | |||||
| > | |||||
| <img src="../../assets/img/tips.png" alt="" /> | |||||
| {{ $t("myCreating.freeUserTip") }} | |||||
| </div> | |||||
| <video | <video | ||||
| v-if="presentItem.videoPlayUrl" | v-if="presentItem.videoPlayUrl" | ||||
| controls="true" | controls="true" | ||||
| @@ -134,29 +151,68 @@ | |||||
| ></video> | ></video> | ||||
| <div v-else class="insteadVideo"> | <div v-else class="insteadVideo"> | ||||
| {{ $t("myCreating." + presentItem.statusName + "Text") }} | {{ $t("myCreating." + presentItem.statusName + "Text") }} | ||||
| <span v-if="presentItem.videoStatus == 3">{{ | |||||
| <p v-if="lanChange == 'zh-cn' && presentItem.videoStatus == 3"> | |||||
| 错误原因: {{ presentItem.videoMsg }} | |||||
| </p> | |||||
| <p v-if="lanChange == 'en' && presentItem.videoStatus == 3"> | |||||
| Error cause: {{ presentItem.videoMsg }} | |||||
| </p> | |||||
| <!-- <span v-if="presentItem.videoStatus == 3">{{ | |||||
| presentItem.videoMsg | presentItem.videoMsg | ||||
| }}</span> | |||||
| }}</span> --> | |||||
| </div> | </div> | ||||
| <!-- 有视频路径的页脚 --> | <!-- 有视频路径的页脚 --> | ||||
| <div class="footer" v-if="presentItem.videoPlayUrl"> | <div class="footer" v-if="presentItem.videoPlayUrl"> | ||||
| <span class="dialog-footer"> | <span class="dialog-footer"> | ||||
| <!-- dialog下载按钮 --> | |||||
| <!-- dialog下载按钮 upGrades--> | |||||
| <button | <button | ||||
| class="elBtn" | class="elBtn" | ||||
| type="primary" | type="primary" | ||||
| @click.stop="handleDownload(presentItem.videoPlayUrl)" | |||||
| @click.stop=" | |||||
| handleDownload(presentItem.videoPlayUrl, presentItem.title) | |||||
| " | |||||
| > | > | ||||
| <el-icon class="icon-delete"><i-ep-download /></el-icon | |||||
| >{{ $t("myCreating.download") }} | |||||
| <!-- <el-icon class="icon-delete"><i-ep-download /></el-icon> --> | |||||
| {{ $t("myCreating.download") }} | |||||
| </button> | </button> | ||||
| <!-- 提升画质 v-if="presentItem.isHy == 0"--> | |||||
| <el-tooltip | |||||
| style="cursor: pointer" | |||||
| v-if="false" | |||||
| class="box-item" | |||||
| effect="light" | |||||
| :content="$t('myCreating.upSharpnessTips')" | |||||
| placement="top" | |||||
| > | |||||
| <button | |||||
| style="cursor: pointer" | |||||
| v-if="presentItem.isHy == 0" | |||||
| class="elBtn upSharpness" | |||||
| @click.stop="upGrades(presentItem.id)" | |||||
| > | |||||
| <div v-if="!upGradesLoading" style="cursor: pointer"> | |||||
| <img src="../../assets//img/Upgrades.png" alt="" /> | |||||
| {{ $t("myCreating.upSharpness") }} | |||||
| </div> | |||||
| <div v-if="upGradesLoading"> | |||||
| <!-- <my-Loading-Icon | |||||
| class="previewAudioLoadingBox" | |||||
| v-if="!upGradesLoading" | |||||
| ></my-Loading-Icon> --> | |||||
| <el-icon class="is-loading" style="font-size: 16px" | |||||
| ><i-ep-Loading | |||||
| /></el-icon> | |||||
| </div> | |||||
| </button> | |||||
| </el-tooltip> | |||||
| <!-- dialog删除按钮 --> | <!-- dialog删除按钮 --> | ||||
| <button | <button | ||||
| class="elBtn" | class="elBtn" | ||||
| @click.stop="handelDelete(presentItem.id, presentItem.title)" | @click.stop="handelDelete(presentItem.id, presentItem.title)" | ||||
| > | > | ||||
| <el-icon class="icon-delete"><i-ep-delete /></el-icon | |||||
| >{{ $t("myCreating.delete") }} | |||||
| <!-- <el-icon class="icon-delete"><i-ep-delete /></el-icon> --> | |||||
| {{ $t("myCreating.delete") }} | |||||
| </button> | </button> | ||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| @@ -186,7 +242,7 @@ | |||||
| <el-pagination | <el-pagination | ||||
| v-model:current-page="pageNum" | v-model:current-page="pageNum" | ||||
| v-model:page-size="pageSize" | v-model:page-size="pageSize" | ||||
| :page-sizes="[10, 20, 50, 100, 200]" | |||||
| :page-sizes="[12, 24, 36]" | |||||
| :small="false" | :small="false" | ||||
| :disabled="false" | :disabled="false" | ||||
| :background="true" | :background="true" | ||||
| @@ -200,12 +256,19 @@ | |||||
| </template> | </template> | ||||
| <script setup> | <script setup> | ||||
| import { userPhotoVideoList, delUserPhotoVideoByID } from "@/apis/myCreating"; | |||||
| //#region 导入 | |||||
| import { | |||||
| userPhotoVideoListApi, | |||||
| delUserPhotoVideoByIDApi, | |||||
| videoHyApi, | |||||
| checkVideoStatusApi, | |||||
| } from "@/apis/myCreating"; | |||||
| import { timestampToTime } from "@/utils/tools"; | import { timestampToTime } from "@/utils/tools"; | ||||
| import { useI18n } from "vue-i18n"; | import { useI18n } from "vue-i18n"; | ||||
| import { getStatus } from "./videoStatus"; | import { getStatus } from "./videoStatus"; | ||||
| import { useRouter } from "vue-router"; | import { useRouter } from "vue-router"; | ||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| //#endregion ---------------------- | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| // 当前语言状态与国际化组件 | // 当前语言状态与国际化组件 | ||||
| const { locale } = useI18n(); | const { locale } = useI18n(); | ||||
| @@ -213,7 +276,7 @@ const lanChange = ref(locale); | |||||
| const title = ref(""); | const title = ref(""); | ||||
| const pageNum = ref(1); | const pageNum = ref(1); | ||||
| const pageSize = ref(10); | |||||
| const pageSize = ref(12); | |||||
| const total = ref(0); | const total = ref(0); | ||||
| // 弹窗显示隐藏 | // 弹窗显示隐藏 | ||||
| const showDialog = ref(false); | const showDialog = ref(false); | ||||
| @@ -250,13 +313,20 @@ function mouseenter(item) { | |||||
| showPopup.value = !showPopup.value; | showPopup.value = !showPopup.value; | ||||
| } | } | ||||
| // 下载 | // 下载 | ||||
| function handleDownload(itemVideoPlayUrl) { | |||||
| function handleDownload(itemVideoPlayUrl, name) { | |||||
| if (itemVideoPlayUrl) { | if (itemVideoPlayUrl) { | ||||
| const link = document.createElement("a"); | |||||
| link.href = itemVideoPlayUrl; | |||||
| document.body.appendChild(link); | |||||
| link.click(); | |||||
| document.body.removeChild(link); | |||||
| console.log(1); | |||||
| let a = document.createElement("a"); | |||||
| a.download = `${name}.mp4`; | |||||
| a.href = itemVideoPlayUrl; | |||||
| // 设置下载文件名 | |||||
| a.style.display = "none"; | |||||
| document.body.appendChild(a); | |||||
| a.click(); | |||||
| a.remove(); | |||||
| ElMessage.success( | |||||
| lanChange.value == "zh-cn" ? `下载成功` : `Download Successfully` | |||||
| ); | |||||
| } else { | } else { | ||||
| ElMessage.error( | ElMessage.error( | ||||
| lanChange.value == "zh-cn" ? `无法下载` : `Unable to download` | lanChange.value == "zh-cn" ? `无法下载` : `Unable to download` | ||||
| @@ -268,10 +338,15 @@ function goCreate() { | |||||
| router.push("/createVideo"); | router.push("/createVideo"); | ||||
| } | } | ||||
| function resetSearch(params) { | |||||
| title.value = ""; | |||||
| searchVideoList(); | |||||
| } | |||||
| // 搜索 | |||||
| function searchVideoList() { | function searchVideoList() { | ||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value, true); | getPhotoVideoList(pageNum.value, pageSize.value, title.value, true); | ||||
| } | } | ||||
| // 删除 | |||||
| function handelDelete(id, title) { | function handelDelete(id, title) { | ||||
| const msg = | const msg = | ||||
| lanChange.value == "zh-cn" | lanChange.value == "zh-cn" | ||||
| @@ -287,15 +362,65 @@ function handelDelete(id, title) { | |||||
| delPhotoVideo(id); | delPhotoVideo(id); | ||||
| }); | }); | ||||
| } | } | ||||
| // 升级画质 | |||||
| const upGradesLoading = ref(false); | |||||
| function upGrades(id) { | |||||
| if (upGradesLoading.value == true) { | |||||
| ElMessage.error( | |||||
| lanChange.value == "zh-cn" | |||||
| ? `正在升级,请稍后~` | |||||
| : `Upgrading, please wait ~` | |||||
| ); | |||||
| return; | |||||
| } | |||||
| const msg = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `确定要升级该作品吗?` | |||||
| : `Are you sure you want to upgrade this work?`; | |||||
| 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 () => { | |||||
| upGradesLoading.value = true; | |||||
| try { | |||||
| const res = await videoHyApi(id); | |||||
| ElMessage.success( | |||||
| lanChange.value == "zh-cn" | |||||
| ? `升级中!请稍等~` | |||||
| : `Upgrading! Please wait a moment` | |||||
| ); | |||||
| showDialog.value = false; | |||||
| upGradesLoading.value = false; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| } catch (error) { | |||||
| ElMessage.error( | |||||
| lanChange.value == "zh-cn" | |||||
| ? `升级失败,请稍后重试` | |||||
| : `Upgrade failed, please try again later` | |||||
| ); | |||||
| upGradesLoading.value = false; | |||||
| } | |||||
| }); | |||||
| } | |||||
| /** | /** | ||||
| * @description:获取我的视频作品 | * @description:获取我的视频作品 | ||||
| * @return: data | * @return: data | ||||
| */ | */ | ||||
| function getPhotoVideoList(pageNum, pageSize, title, searchFlag) { | function getPhotoVideoList(pageNum, pageSize, title, searchFlag) { | ||||
| userPhotoVideoList(pageNum, pageSize, title) | |||||
| userPhotoVideoListApi(pageNum, pageSize, title) | |||||
| .then((res) => { | .then((res) => { | ||||
| console.log(res, "res"); | console.log(res, "res"); | ||||
| notGenerateList.value = []; | |||||
| // 找到数组中未生成的,放入列表,为了刷新 | |||||
| res.data.list.forEach((item) => { | |||||
| if ([1, 2, 4, 6, 7, 8, 10, 12].includes(item.videoStatus)) { | |||||
| notGenerateList.value.push(item.id); | |||||
| } | |||||
| }); | |||||
| res.data.list.forEach((item) => { | res.data.list.forEach((item) => { | ||||
| // item.createDate = timestampToTime(item.createDate) || ""; | // item.createDate = timestampToTime(item.createDate) || ""; | ||||
| // item.updateDate = timestampToTime(item.updateDate) || ""; | // item.updateDate = timestampToTime(item.updateDate) || ""; | ||||
| @@ -335,7 +460,7 @@ function getPhotoVideoList(pageNum, pageSize, title, searchFlag) { | |||||
| * @return: data | * @return: data | ||||
| */ | */ | ||||
| function delPhotoVideo(videoID) { | function delPhotoVideo(videoID) { | ||||
| delUserPhotoVideoByID(videoID) | |||||
| delUserPhotoVideoByIDApi(videoID) | |||||
| .then((res) => { | .then((res) => { | ||||
| console.log(res, "res"); | console.log(res, "res"); | ||||
| const msg = lanChange.value == "zh-cn" ? `删除成功!` : `Success !`; | const msg = lanChange.value == "zh-cn" ? `删除成功!` : `Success !`; | ||||
| @@ -348,27 +473,108 @@ function delPhotoVideo(videoID) { | |||||
| ElMessage.error(err.message); | ElMessage.error(err.message); | ||||
| }); | }); | ||||
| } | } | ||||
| //#region 定时刷新 | |||||
| const hasNewCreate = ref(false); //提示框显示隐藏 | |||||
| const notGenerateList = ref([]); //页面上未生成的视频的id 普通视频 | |||||
| const notGenerateList2 = ref([]); //页面上未生成的视频的id 升级视频 | |||||
| const checkVideoStatus = async () => { | |||||
| // 如果列表中没有生成中的视频,不发送请求 | |||||
| const intervalId = setInterval(async () => { | |||||
| // && notGenerateList2.value.length == 0; | |||||
| if (notGenerateList.value.length == 0) { | |||||
| return; | |||||
| } | |||||
| try { | |||||
| const res = await checkVideoStatusApi(notGenerateList.value); | |||||
| // 如果有新的,则提示且更新列表 | |||||
| if (res.code != 2115) { | |||||
| hasNewCreate.value = true; | |||||
| const changeHasNewCreate = setTimeout(() => { | |||||
| hasNewCreate.value = false; | |||||
| }, 5000); | |||||
| notGenerateList.value = []; | |||||
| // notGenerateList2.value = []; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| } | |||||
| } catch (error) {} | |||||
| }, 3000); | |||||
| onUnmounted(() => { | |||||
| clearInterval(intervalId); | |||||
| }); | |||||
| }; | |||||
| //#endregion --------------------------- | |||||
| //#region 页面初始化 | |||||
| onMounted(() => { | onMounted(() => { | ||||
| isLoading.value = true; | isLoading.value = true; | ||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | getPhotoVideoList(pageNum.value, pageSize.value, title.value); | ||||
| // checkVideoStatus(); | |||||
| }); | }); | ||||
| //#endregion --------------------------- | |||||
| </script> | </script> | ||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||
| .page { | .page { | ||||
| min-height: calc(100vh - 80px); | |||||
| position: relative; | |||||
| height: calc(100vh - 80px); | |||||
| padding: 15px 130px; | padding: 15px 130px; | ||||
| background-color: #fff; | background-color: #fff; | ||||
| border-radius: 25px 0 0; | border-radius: 25px 0 0; | ||||
| width: 100%; | |||||
| overflow: hidden; | |||||
| overflow-y: auto; | |||||
| .top { | .top { | ||||
| position: relative; | |||||
| margin-bottom: 35px; | margin-bottom: 35px; | ||||
| .search { | |||||
| display: flex; | |||||
| justify-content: flex-start; | |||||
| .resetSearch { | |||||
| margin-left: 10px; | |||||
| padding: 0 10px; | |||||
| height: 30px; | |||||
| width: 100px; | |||||
| text-align: center; | |||||
| line-height: 30px; | |||||
| background-color: #000; | |||||
| border: 1px solid #000; | |||||
| border-radius: 15px; | |||||
| cursor: pointer; | |||||
| transition: all 0.3s; | |||||
| color: #fff; | |||||
| &:hover { | |||||
| background-color: #fff; | |||||
| color: #000; | |||||
| } | |||||
| } | |||||
| } | |||||
| .hasNewVideoTips { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 50%; | |||||
| transform: translateX(-50%); | |||||
| width: 400px; | |||||
| padding: 5px 30px; | |||||
| color: #fff; | |||||
| background-color: #000; | |||||
| text-align: center; | |||||
| font-size: 20px; | |||||
| transition: all 0.5s; | |||||
| opacity: 1; | |||||
| border-radius: 15px; | |||||
| } | |||||
| .hasNew { | |||||
| opacity: 0; | |||||
| transition: all 0.5s; | |||||
| } | |||||
| } | } | ||||
| .loadingIcon { | .loadingIcon { | ||||
| height: 100px; | height: 100px; | ||||
| line-height: 100px; | line-height: 100px; | ||||
| text-align: center; | text-align: center; | ||||
| transform: scale(2); | transform: scale(2); | ||||
| .loadingText { | .loadingText { | ||||
| position: relative; | position: relative; | ||||
| top: -2px; | top: -2px; | ||||
| @@ -382,7 +588,6 @@ onMounted(() => { | |||||
| // height: 200px; | // height: 200px; | ||||
| margin-top: 5px; | margin-top: 5px; | ||||
| padding-bottom: 50px; | padding-bottom: 50px; | ||||
| cursor: pointer; | |||||
| .workItem { | .workItem { | ||||
| position: relative; | position: relative; | ||||
| width: 300px; | width: 300px; | ||||
| @@ -495,6 +700,7 @@ onMounted(() => { | |||||
| padding-left: 5px; | padding-left: 5px; | ||||
| margin-top: -5px; | margin-top: -5px; | ||||
| line-height: 20px; | line-height: 20px; | ||||
| font-size: 13px; | |||||
| cursor: pointer; | cursor: pointer; | ||||
| } | } | ||||
| &:hover { | &:hover { | ||||
| @@ -542,6 +748,18 @@ onMounted(() => { | |||||
| /* 生成成功 */ | /* 生成成功 */ | ||||
| background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%); | background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%); | ||||
| } | } | ||||
| &.videoUping { | |||||
| /* 升级中 */ | |||||
| background: linear-gradient(120deg, #4512c7 0%, #4fd334 100%); | |||||
| } | |||||
| &.videoUpFailed { | |||||
| /* HD */ | |||||
| background: linear-gradient(120deg, #ff0019 0%, #ff00c3 100%); | |||||
| } | |||||
| &.videoUpSucceed { | |||||
| /* HD */ | |||||
| background: linear-gradient(120deg, #fdeb71 0%, #d37e1a 100%); | |||||
| } | |||||
| } | } | ||||
| &:hover { | &:hover { | ||||
| .more { | .more { | ||||
| @@ -628,6 +846,23 @@ onMounted(() => { | |||||
| // justify-content: space-between; | // justify-content: space-between; | ||||
| width: 100%; | width: 100%; | ||||
| padding: 20px; | padding: 20px; | ||||
| .overtimeTips { | |||||
| // width: 60%; | |||||
| // display: inline-block; | |||||
| padding: 5px; | |||||
| margin-bottom: 10px; | |||||
| background-color: #ccc; | |||||
| border-radius: 5px; | |||||
| line-height: 20px; | |||||
| color: #000; | |||||
| text-align: center; | |||||
| img { | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| vertical-align: middle; | |||||
| margin-right: 5px; | |||||
| } | |||||
| } | |||||
| video { | video { | ||||
| width: 100%; | width: 100%; | ||||
| max-height: 600px; | max-height: 600px; | ||||
| @@ -635,10 +870,13 @@ onMounted(() => { | |||||
| } | } | ||||
| .insteadVideo { | .insteadVideo { | ||||
| font-size: 20px; | font-size: 20px; | ||||
| font-weight: 600; | |||||
| font-weight: 400; | |||||
| margin: 20px auto; | margin: 20px auto; | ||||
| text-align: center; | text-align: center; | ||||
| } | } | ||||
| p { | |||||
| font-weight: 700; | |||||
| } | |||||
| } | } | ||||
| .dialog-footer { | .dialog-footer { | ||||
| @@ -647,7 +885,7 @@ onMounted(() => { | |||||
| .elBtn { | .elBtn { | ||||
| color: #fff; | color: #fff; | ||||
| border-radius: 10px; | border-radius: 10px; | ||||
| padding: 5px 10px; | |||||
| padding: 10px 15px; | |||||
| cursor: pointer; | cursor: pointer; | ||||
| background-color: #000; | background-color: #000; | ||||
| transition: all 0.3s; | transition: all 0.3s; | ||||
| @@ -655,7 +893,12 @@ onMounted(() => { | |||||
| background-color: #15d1b8; | background-color: #15d1b8; | ||||
| } | } | ||||
| } | } | ||||
| .upSharpness { | |||||
| img { | |||||
| width: 14px; | |||||
| height: 14px; | |||||
| } | |||||
| } | |||||
| :deep(.el-icon) { | :deep(.el-icon) { | ||||
| margin-right: 5px; | margin-right: 5px; | ||||
| font-weight: 700; | font-weight: 700; | ||||