| @@ -7,6 +7,7 @@ | |||
| <!-- <meta name="viewport" content="width=device-width,initial-scale=1.0"> --> | |||
| <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |||
| <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.13.2/skins/default/aliplayer-min.css"> | |||
| <script src="http://g.alicdn.com/de/prismplayer/{version}/aliplayer-h5-min.js"></script> | |||
| <script charset="utf-8" type="text/javascript" src="https://g.alicdn.com/de/prismplayer/2.13.2/aliplayer-min.js"> | |||
| </script> | |||
| <title> | |||
| @@ -173,18 +173,14 @@ export default { | |||
| material: res.data.data.url | |||
| }) | |||
| // 重新获取列表 | |||
| await Promise.all([ | |||
| that.$emit('getMyBGIListApi'), | |||
| that.$emit('getMyScListApi') | |||
| ]) | |||
| await that.$parent.$parent.getMyBGIListApi() | |||
| await that.$parent.$parent.getMyScListApi() | |||
| if (this.type == 4) { | |||
| that.$parent.$parent.changeShowBGIList(0) | |||
| that.$parent.$parent.changeShowBGIList(1) | |||
| } | |||
| if (this.type == 5) { | |||
| that.$parent.$parent.changeShowBGIList(2) | |||
| that.$parent.$parent.changeShowBGIList(3) | |||
| } | |||
| that.loadingShow = false | |||
| that.showCropper = false | |||
| Toast.success('上传成功') | |||
| @@ -102,25 +102,13 @@ export default { | |||
| characters: (state) => state.publicObj.characters, | |||
| //动态计算样式 | |||
| bgStyle() { | |||
| if (this.videoType == 1) { | |||
| return { | |||
| // width: '1080px', | |||
| // height: '1920px', | |||
| // transform: 'scale(0.2)', | |||
| backgroundImage: `url(${this.materialList.BGI.material})`, | |||
| backgroundSize: 'cover', | |||
| backgroundPosition: 'center' | |||
| } | |||
| } | |||
| if (this.videoType == 2) { | |||
| return { | |||
| // width: '1920px', | |||
| // height: '1080px', | |||
| // transform: 'scale(0.2)', | |||
| backgroundImage: `url(${this.materialList.BGI.material})`, | |||
| backgroundSize: 'cover', | |||
| backgroundPosition: 'center' | |||
| } | |||
| return { | |||
| // width: '1080px', | |||
| // height: '1920px', | |||
| // transform: 'scale(0.2)', | |||
| backgroundImage: `url(${this.materialList.BGI.material})`, | |||
| backgroundSize: 'cover', | |||
| backgroundPosition: 'center' | |||
| } | |||
| } | |||
| }) | |||
| @@ -181,23 +169,23 @@ export default { | |||
| // 限制X轴 | |||
| // console.log(fatherRect) | |||
| // console.log(sonRect) | |||
| if (this.materialList.scList[index].x < -sonRect.width) { | |||
| this.materialList.scList[index].x = 0 | |||
| this.exceed() | |||
| } | |||
| if (this.materialList.scList[index].x > fatherRect.width) { | |||
| this.materialList.scList[index].x = 0 | |||
| this.exceed() | |||
| } | |||
| // 限制Y轴 | |||
| if (this.materialList.scList[index].y < -sonRect.height) { | |||
| this.materialList.scList[index].y = 0 | |||
| this.exceed() | |||
| } | |||
| if (this.materialList.scList[index].y > fatherRect.height) { | |||
| this.materialList.scList[index].y = 0 | |||
| this.exceed() | |||
| } | |||
| // if (this.materialList.scList[index].x < -sonRect.width) { | |||
| // this.materialList.scList[index].x = 0 | |||
| // this.exceed() | |||
| // } | |||
| // if (this.materialList.scList[index].x > fatherRect.width) { | |||
| // this.materialList.scList[index].x = 0 | |||
| // this.exceed() | |||
| // } | |||
| // // 限制Y轴 | |||
| // if (this.materialList.scList[index].y < -sonRect.height) { | |||
| // this.materialList.scList[index].y = 0 | |||
| // this.exceed() | |||
| // } | |||
| // if (this.materialList.scList[index].y > fatherRect.height) { | |||
| // this.materialList.scList[index].y = 0 | |||
| // this.exceed() | |||
| // } | |||
| }, | |||
| // 数字人的处理 | |||
| @@ -20,6 +20,7 @@ Vue.use(waterfall)// 瀑布流插件 | |||
| Vue.use(ElementUI); | |||
| Vue.use(Vant) | |||
| Vue.config.productionTip = false | |||
| Vue.prototype.$axios = axios | |||
| new Vue({ | |||
| @@ -36,6 +36,5 @@ p { | |||
| .displayFlex { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| } | |||
| @@ -32,7 +32,7 @@ | |||
| <div class="addText-title">添加文案</div> | |||
| <div class="desalinate"> | |||
| <span>已录入{{ textareaContent.length }}字</span> | |||
| <span>视频时长: 00:16</span> | |||
| <!-- <span>视频时长: 00:16</span> --> | |||
| </div> | |||
| </div> | |||
| <!-- 标题框 --> | |||
| @@ -59,10 +59,14 @@ | |||
| <div class="addText-title"> | |||
| 播报声音<span class="redWord">(必选)</span> | |||
| </div> | |||
| <div>{{ soundChoose.subTitle }}</div> | |||
| <div v-if="soundChoose2.speakTypeStr"> | |||
| {{ soundChoose.subTitle }}-{{ soundChoose.title }}-{{ | |||
| soundChoose.ageTypeStr | |||
| }}-{{ soundChoose2.speakTypeStr }} | |||
| </div> | |||
| </div> | |||
| <!-- 合成按钮 --> | |||
| <div class="makeVideo" @click="submit">立即制作</div> | |||
| <div class="makeVideo" @click="submit(1)">立即制作</div> | |||
| <!-- 上移下移 --> | |||
| <div class="upAndBottomBtn"> | |||
| <div class="moveLayer" :class="videoType == 2 ? 'moveLayer1' : ''"> | |||
| @@ -107,26 +111,33 @@ | |||
| <img src="../../assets/icon/icon-material.png" /> | |||
| </template> | |||
| </van-tabbar-item> | |||
| <van-tabbar-item @click="clickBottomTab(4)"> | |||
| <!-- <van-tabbar-item @click="clickBottomTab(4)" disabled> | |||
| <span v-show="showSubtitle">取消字幕</span> | |||
| <span v-show="!showSubtitle">添加字幕</span> | |||
| <template #icon="props"> | |||
| <img src="../../assets/icon/icon-subtitle.png" /> | |||
| </template> | |||
| </van-tabbar-item> | |||
| </van-tabbar-item> --> | |||
| </van-tabbar> | |||
| </div> | |||
| <!-- 合成视频进度条 --> | |||
| <div v-if="showSynthesisDialog" class="synthesisDialog"> | |||
| <div class="synthesisDialog-in"> | |||
| <el-progress | |||
| <van-progress | |||
| :percentage="percentageData" | |||
| color="#7264F5" | |||
| define-back-color="#f0effe" | |||
| stroke-width="12" | |||
| class="progress" | |||
| /> | |||
| <!-- <el-progress | |||
| color="#7264F5" | |||
| define-back-color="#f0effe" | |||
| stroke-width="12" | |||
| class="progress" | |||
| :percentage="26" | |||
| ></el-progress> | |||
| ></el-progress> --> | |||
| <div class="synthesisDialog-text">正在生成视频,请耐心等待!</div> | |||
| </div> | |||
| </div> | |||
| @@ -204,6 +215,13 @@ | |||
| position="bottom" | |||
| :style="{ width: '100%' }" | |||
| > | |||
| <div | |||
| class="SoundList2-title" | |||
| @click="showSoundList2 = !showSoundList2" | |||
| > | |||
| <div> </div> | |||
| <img class="yesImg" src="../../assets/icon/icon-yes.png" alt="" /> | |||
| </div> | |||
| <div class="list"> | |||
| <div v-if="soundItemList2.length == 0">暂无数据</div> | |||
| <template v-if="soundItemList.length != 0"> | |||
| @@ -425,6 +443,9 @@ export default { | |||
| }, | |||
| data() { | |||
| return { | |||
| id: null, | |||
| timeOuter: null, | |||
| percentageData: 1, // 进度条的值 | |||
| pageNum: 1, | |||
| pageSize: 20, | |||
| proportion: null, //编辑页面的比例 | |||
| @@ -456,6 +477,7 @@ export default { | |||
| soundItemListAction: -1, // 声音展示列表高亮 | |||
| soundItemListAction2: -1, // 声音展示列表高亮二级 | |||
| soundChoose: {}, //选中的音频 | |||
| soundChoose2: {}, //选中的音频二级 | |||
| //编辑 | |||
| bjAction: 0, // 背景:素材库和上传高亮 | |||
| bjImgAction: -1, // 选中背景图高亮 | |||
| @@ -528,8 +550,6 @@ export default { | |||
| delete obj.data.subVoiceMould | |||
| let list2 = [{ ...obj.data }, ...list] | |||
| console.log(list2) | |||
| this.soundItemList2 = list2 || [] | |||
| // console.log(this.soundItemList2) | |||
| @@ -543,19 +563,20 @@ export default { | |||
| async clickSoundItem2(index, item) { | |||
| if (this.soundItemListAction2 != index) { | |||
| this.soundItemListAction2 = index //高亮 | |||
| this.soundChoose = item | |||
| this.soundChoose2 = item | |||
| // 得到试听文件 | |||
| const res = await videoDetial(item.exampleVideoId) | |||
| this.audioUrl = res.data.videoUrl | |||
| } else { | |||
| this.soundItemListAction2 = -1 | |||
| this.soundChoose = {} | |||
| this.soundChoose2 = {} | |||
| } | |||
| }, | |||
| // 提交合成视频 | |||
| submit() { | |||
| submit(type) { | |||
| // type代表时保存还是点击生成视频按钮 | |||
| // 组装参数 | |||
| console.log(this.soundChoose.id) | |||
| // 素材列表处理 | |||
| @@ -583,7 +604,7 @@ export default { | |||
| h: this.materialList.virtual.h | |||
| } | |||
| const data = { | |||
| id: this.$route.query.id, | |||
| id: this.id, | |||
| videoType: this.videoType, //横屏竖屏 | |||
| personMouldId: this.materialList.virtual.id, //数字人id | |||
| voiceMouldIds: [this.soundChoose.id], //声音id | |||
| @@ -594,33 +615,37 @@ export default { | |||
| materialAllJson: JSON.stringify([...scList]) // 素材 | |||
| } | |||
| console.log(data, '最终提交的参数') | |||
| // 当没有选择声音参数时 | |||
| if (!this.soundChoose.id) { | |||
| Toast.fail('请选择声音!') | |||
| return | |||
| } | |||
| if (!this.inputTitle) { | |||
| Toast.fail('请输入文案标题!') | |||
| return | |||
| } | |||
| if (!this.textareaContent) { | |||
| Toast.fail('请输入文案内容!') | |||
| return | |||
| if (type == 1) { | |||
| // 当没有选择声音参数时 | |||
| if (!this.soundChoose.id) { | |||
| Toast.fail('请选择声音!') | |||
| return | |||
| } | |||
| if (!this.inputTitle) { | |||
| Toast.fail('请输入文案标题!') | |||
| return | |||
| } | |||
| if (!this.textareaContent) { | |||
| Toast.fail('请输入文案内容!') | |||
| return | |||
| } | |||
| } | |||
| // 先保存草稿,里面再调生成视频的接口 | |||
| this.saveOrUpdate(data) | |||
| this.saveOrUpdate(data, type) | |||
| }, | |||
| /** | |||
| * @description:保存或修改用户作品 | |||
| */ | |||
| async saveOrUpdate(data) { | |||
| async saveOrUpdate(data, type) { | |||
| console.log(data) | |||
| try { | |||
| const res = await saveOrUpdateUserVideo(data) | |||
| console.log(res, '保存或修改用户作品') | |||
| // this.createVideo({ id: this.saveID }) | |||
| this.createVideo({ id: this.$route.query.id }) | |||
| if (type == 1) { | |||
| this.createVideo({ id: this.$route.query.id }) | |||
| } | |||
| } catch (error) { | |||
| console.log(error, 'error') | |||
| Toast.fail(error.message) | |||
| @@ -636,10 +661,16 @@ export default { | |||
| console.log(res, '生成视频') | |||
| Toast.success('提交成功!') | |||
| // *#06# | |||
| that.showSynthesisDialog = true //显示进度条 | |||
| this.timeOuter = setTimeout(() => { | |||
| this.isShowCover = true | |||
| }, 2000) | |||
| const timer = setInterval(() => { | |||
| if (that.percentageData < 98) { | |||
| that.percentageData += 1 | |||
| } else { | |||
| that.percentageData == 98 | |||
| } | |||
| // 重复调取此接口直到videoStatus == 2 || 3 | |||
| this.getVideo(that.$route.query.id) | |||
| if (this.timerOver) { | |||
| @@ -660,6 +691,8 @@ export default { | |||
| const res = await doFindVideoById(id) | |||
| console.log(res, '通过id获取视频') | |||
| if (res.data.videoStatus == 2) { | |||
| this.percentageData == 99 | |||
| this.showSynthesisDialog = false //隐藏进度条 | |||
| this.isShowCover = false | |||
| clearTimeout(this.timeOuter) | |||
| Toast.success('视频生成成功!') | |||
| @@ -710,6 +743,7 @@ export default { | |||
| } | |||
| this.videoType = res.data.videoType | |||
| this.id = res.data.id | |||
| // this.imgUrl = res.data.personMould.coverImg | |||
| this.personMouldId = res.data.personMouldId | |||
| this.mouldSmId = res.data.personMouldSmId | |||
| @@ -717,8 +751,9 @@ export default { | |||
| this.textareaContent = res.data.paperwork || '' | |||
| this.soundChoose.id = res.data.voiceMouldId | |||
| this.soundChoose.mouldSmId = res.data.voiceMouldSmId | |||
| await this.loadVoice() // 获取音频列表 | |||
| if (this.textareaContent.length != 0) { | |||
| await this.loadVoice() // 获取音频列表 | |||
| } | |||
| this.soundItemListAction = this.soundItemList.findIndex((item) => { | |||
| return item.id == this.soundChoose.id | |||
| }) //高亮处理 | |||
| @@ -752,67 +787,67 @@ export default { | |||
| let that = this | |||
| // 背景 | |||
| if (this.bottomTabActive == 2 && this.bjImgAction != -1) { | |||
| Dialog.confirm({ | |||
| // title: '退出登录', | |||
| message: '您确定要用这张背景图吗?' | |||
| }) | |||
| .then(() => { | |||
| if (that.bjAction == 0) { | |||
| that.materialList.BGI = that.systemBGIList.find((item, index) => { | |||
| return index == that.bjImgAction | |||
| }) | |||
| } else if (that.bjAction == 1) { | |||
| that.materialList.BGI = that.myBGIList.find((item, index) => { | |||
| return index == that.bjImgAction | |||
| }) | |||
| } | |||
| this.showTabSheet = false | |||
| // Dialog.confirm({ | |||
| // // title: '退出登录', | |||
| // message: '您确定要用这张背景图吗?' | |||
| // }) | |||
| // .then(() => { | |||
| if (that.bjAction == 0) { | |||
| that.materialList.BGI = that.systemBGIList.find((item, index) => { | |||
| return index == that.bjImgAction | |||
| }) | |||
| .catch(() => { | |||
| console.log('false') | |||
| this.showTabSheet = false | |||
| return | |||
| } else if (that.bjAction == 1) { | |||
| that.materialList.BGI = that.myBGIList.find((item, index) => { | |||
| return index == that.bjImgAction | |||
| }) | |||
| } | |||
| this.showTabSheet = false | |||
| // }) | |||
| // .catch(() => { | |||
| // console.log('false') | |||
| // this.showTabSheet = false | |||
| // return | |||
| // }) | |||
| } | |||
| // 素材 | |||
| else if (this.bottomTabActive == 3 && this.scImgAction != -1) { | |||
| Dialog.confirm({ | |||
| // title: '退出登录', | |||
| message: '您确定要用这张素材图吗?' | |||
| }) | |||
| .then(() => { | |||
| if (that.scAction == 0) { | |||
| let scItem = that.systemScList.find((item, index) => { | |||
| return index == that.scImgAction | |||
| }) | |||
| that.materialList.scList.push({ | |||
| ...scItem, | |||
| x: 0, | |||
| y: 0, | |||
| z: 0, | |||
| w: 1, | |||
| h: 1 | |||
| }) | |||
| } else if (that.scAction == 1) { | |||
| let scItem = that.myScList.find((item, index) => { | |||
| return index == that.scImgAction | |||
| }) | |||
| that.materialList.scList.push({ | |||
| ...scItem, | |||
| x: 0, | |||
| y: 0, | |||
| z: 0, | |||
| w: 1, | |||
| h: 1 | |||
| }) | |||
| } | |||
| this.showTabSheet = false | |||
| // Dialog.confirm({ | |||
| // // title: '退出登录', | |||
| // message: '您确定要用这张素材图吗?' | |||
| // }) | |||
| // .then(() => { | |||
| if (that.scAction == 0) { | |||
| let scItem = that.systemScList.find((item, index) => { | |||
| return index == that.scImgAction | |||
| }) | |||
| that.materialList.scList.push({ | |||
| ...scItem, | |||
| x: 0, | |||
| y: 0, | |||
| z: 0, | |||
| w: 1, | |||
| h: 1 | |||
| }) | |||
| .catch(() => { | |||
| console.log('false') | |||
| this.showTabSheet = false | |||
| return | |||
| } else if (that.scAction == 1) { | |||
| let scItem = that.myScList.find((item, index) => { | |||
| return index == that.scImgAction | |||
| }) | |||
| that.materialList.scList.push({ | |||
| ...scItem, | |||
| x: 0, | |||
| y: 0, | |||
| z: 0, | |||
| w: 1, | |||
| h: 1 | |||
| }) | |||
| } | |||
| this.showTabSheet = false | |||
| // }) | |||
| // .catch(() => { | |||
| // console.log('false') | |||
| // this.showTabSheet = false | |||
| // return | |||
| // }) | |||
| } | |||
| // 啥没选 | |||
| else { | |||
| @@ -890,12 +925,12 @@ export default { | |||
| .then(async () => { | |||
| const res = await delImgApi(id) | |||
| if (this.bottomTabActive == 2) { | |||
| this.getMyBGIListApi() | |||
| this.changeShowBGIList(0) | |||
| await this.getMyBGIListApi() | |||
| this.changeShowBGIList(1) | |||
| } | |||
| if (this.bottomTabActive == 3) { | |||
| this.getMyScListApi() | |||
| this.changeShowBGIList(2) | |||
| await this.getMyScListApi() | |||
| this.changeShowBGIList(3) | |||
| } | |||
| }) | |||
| .catch(() => {}) | |||
| @@ -926,21 +961,12 @@ export default { | |||
| this.proportion = 1920 / elementWidth | |||
| console.log(this.proportion) | |||
| } | |||
| }, | |||
| async beforeDestroy() { | |||
| this.timeOuter = null // 清除定时器 | |||
| await this.submit(2) // 保存草稿 | |||
| console.log('保存了') | |||
| } | |||
| // beforeRouteLeave(to, from, next) { | |||
| // let that = this | |||
| // Dialog.confirm({ | |||
| // // title: '退出登录', | |||
| // message: '您还未编辑完成,需要保存为草稿吗?' | |||
| // }) | |||
| // .then(async () => { | |||
| // const res = await that.submit() | |||
| // next() | |||
| // }) | |||
| // .catch(() => { | |||
| // next() | |||
| // }) | |||
| // } | |||
| } | |||
| </script> | |||
| @@ -984,6 +1010,7 @@ export default { | |||
| .content { | |||
| position: relative; | |||
| margin-top: 10px; | |||
| padding: 0 10px; | |||
| padding-bottom: 50px; | |||
| @@ -1146,12 +1173,16 @@ export default { | |||
| position: fixed; | |||
| top: 0; | |||
| left: 0; | |||
| width: 100vw; | |||
| height: 110vh; | |||
| // width: 100vw; | |||
| // height: 110vh; | |||
| width: 100%; | |||
| height: 100%; | |||
| z-index: 99999; | |||
| color: #333; | |||
| background: rgba(0, 0, 0, 0.5); | |||
| overflow: hidden; | |||
| ::v-deep .el-progress-bar { | |||
| } | |||
| &-in { | |||
| position: absolute; | |||
| top: 40%; | |||
| @@ -1165,7 +1196,7 @@ export default { | |||
| border-radius: 12px; | |||
| .progress { | |||
| width: 300px; | |||
| width: 280px; | |||
| ::v-deep .el-progress__text { | |||
| margin-left: 15px; | |||
| @@ -1264,10 +1295,30 @@ export default { | |||
| } | |||
| .SoundList2 { | |||
| overflow: hidden; | |||
| height: 280px; | |||
| padding: 10px 10px 10px; | |||
| &-title { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| margin-bottom: 10px; | |||
| width: 100%; | |||
| .img { | |||
| float: right; | |||
| margin-top: -3px; | |||
| margin-right: 3px; | |||
| width: 16px; | |||
| height: 16px; | |||
| } | |||
| .yesImg { | |||
| margin-top: -3px; | |||
| width: 24px; | |||
| height: 16px; | |||
| } | |||
| } | |||
| .list { | |||
| height: 280px; | |||
| height: 240px; | |||
| margin-top: 0px; | |||
| } | |||
| .list::-webkit-scrollbar { | |||
| @@ -55,6 +55,7 @@ | |||
| <!-- 具体内容 --> | |||
| <!-- 列表样式--大图 --> | |||
| <div v-if="videoList.length == 0">暂无数据</div> | |||
| <!-- <div v-if="videoList.length != 0 && !showLoading">数据加载中</div> --> | |||
| <!-- 新 修改v-if--> | |||
| <div v-if="waterfallBug"> | |||
| @@ -73,7 +74,13 @@ | |||
| > | |||
| <div class="waterFall-item-paddding"> | |||
| <img | |||
| :src="item.videoType == 2 ? defaultImg : defaultImg1" | |||
| :src=" | |||
| item.coverImg | |||
| ? item.coverImg | |||
| : item.videoType == 2 | |||
| ? defaultImg | |||
| : defaultImg1 | |||
| " | |||
| alt="" | |||
| /> | |||
| <!-- 渐变遮罩层 --> | |||
| @@ -220,8 +227,9 @@ export default { | |||
| }, | |||
| data() { | |||
| return { | |||
| showLoading: true, // 加载处理 | |||
| waterfallBug: true, // 解决瀑布流不显示bug | |||
| videoType: 1, //1竖屏2横屏 | |||
| videoType: -1, //-1全部1竖屏2横屏 | |||
| showPopup: false, // 编辑和删除显示隐藏 | |||
| clickItem: -1, // 弹出层显示隐藏 | |||
| showTrue: true, // 弹出层显示隐藏 | |||
| @@ -249,7 +257,7 @@ export default { | |||
| // 草稿箱切换 | |||
| draftChange(type) { | |||
| this.listActive = type | |||
| this.videoType = 1 | |||
| this.videoType = -1 | |||
| this.loadVideoList(1, this.pageSize, this.videoType) | |||
| }, | |||
| // 横屏竖屏列表 | |||
| @@ -355,12 +363,14 @@ export default { | |||
| message: '您确定要删除该作品吗?' | |||
| }) | |||
| .then(async () => { | |||
| this.showLoading = true | |||
| await this.deleteVideoById(id) | |||
| await this.loadVideoList( | |||
| this.currentPage, | |||
| this.pageSize, | |||
| this.videoType | |||
| ) | |||
| this.showLoading = false | |||
| }) | |||
| .catch(() => { | |||
| return | |||
| @@ -5,48 +5,8 @@ | |||
| <div class="content"> | |||
| <!-- 视频 --> | |||
| <div class="videoBox" v-if="videoSrc"> | |||
| <video | |||
| download | |||
| ref="video" | |||
| :src="videoSrc" | |||
| @loadedmetadata="onVideoLoaded" | |||
| @click.prevent="() => {}" | |||
| @play="playing = true" | |||
| @pause="playing = false" | |||
| @timeupdate="onTimeUpdate" | |||
| ></video> | |||
| <!-- 控制框 --> | |||
| <div class="videoBox-controls"> | |||
| <!-- 前进后退 --> | |||
| <div class="videoBox-controls-left"> | |||
| <div @click="seek(-10)"> | |||
| <i class="el-icon-refresh-left"></i> | |||
| </div> | |||
| <div @click="togglePlay"> | |||
| <i v-show="!this.playing" class="el-icon-video-play"></i> | |||
| <i v-show="this.playing" class="el-icon-video-pause"></i> | |||
| </div> | |||
| <div @click="seek(10)"> | |||
| <i class="el-icon-refresh-right"></i> | |||
| </div> | |||
| </div> | |||
| <!-- 进度条 --> | |||
| <div class="videoBox-controls-middle"> | |||
| <div class="time">{{ formatTime(currentTime) }}</div> | |||
| <van-slider | |||
| active-color="#aa91a5" | |||
| v-model="progress" | |||
| :max="totalTime" | |||
| :value="currentTime" | |||
| @change="onProgressChange" | |||
| ></van-slider> | |||
| <div class="time">{{ formatTime(totalTime) }}</div> | |||
| </div> | |||
| <!-- 全屏 --> | |||
| <div class="videoBox-controls-right" @click="toggleScreen"> | |||
| <van-icon name="enlarge" /> | |||
| </div> | |||
| </div> | |||
| <div id="player-container" /> | |||
| <!-- 下载按钮 --> | |||
| <!-- <a :href="videoSrc" download class="videoBox-download"> | |||
| <img src="../../assets/icon/icon-download.png" alt="" /> | |||
| @@ -65,7 +25,7 @@ import { Toast } from 'vant' | |||
| import { mapState, mapActions } from 'vuex' | |||
| import HeadTop from './../../components/common/head.vue' | |||
| // 工具 | |||
| import { scrollToID } from '../../utils' | |||
| import { scrollToID, getDeviceType } from '../../utils' | |||
| import { saveAs } from 'file-saver' | |||
| // 接口 | |||
| @@ -81,15 +41,9 @@ export default { | |||
| inPage: false, | |||
| // videoSrc: | |||
| // 'https://wenlian.wenzhou.gov.cn:8001//upload/video/%E3%80%8A%E7%93%AF%E8%B6%8A%E4%B9%8B%E5%8D%8E%E3%80%8B%E7%89%87%E8%8A%B11.mp4', | |||
| videoSrc: null, | |||
| showControls: false, // 控制台显示隐藏 | |||
| playing: false, // 播放 | |||
| isLandscape: false, | |||
| progress: 0, | |||
| currentTime: 0, | |||
| totalTime: 0, | |||
| progressChanging: false, | |||
| title: null | |||
| videoSrc: null, //播放地址路径 | |||
| title: null, // 视频名称 | |||
| coverUrl: null //封面图 | |||
| } | |||
| }, | |||
| computed: { | |||
| @@ -97,32 +51,66 @@ export default { | |||
| characters: (state) => state.publicObj.characters | |||
| }) | |||
| }, | |||
| created() { | |||
| // console.log(this.$route) | |||
| // this.videoSrc = this.$route.query.videoUrl | |||
| }, | |||
| mounted() { | |||
| created() {}, | |||
| async mounted() { | |||
| this.inPage = true | |||
| scrollToID('top') | |||
| //初始化数据 | |||
| this.getVideoInfo() | |||
| this.$refs.video.addEventListener('timeupdate', this.onTimeUpdate) | |||
| this.$refs.video.addEventListener('ended', this.onVideoEnded) | |||
| screen.orientation.addEventListener('change', this.onOrientationChange) | |||
| }, | |||
| destroyed() { | |||
| this.$refs.video.removeEventListener('timeupdate', this.onTimeUpdate) | |||
| this.$refs.video.removeEventListener('ended', this.onVideoEnded) | |||
| screen.orientation.removeEventListener('change', this.onOrientationChange) | |||
| await this.getVideoInfo() | |||
| this.open() | |||
| }, | |||
| destroyed() {}, | |||
| methods: { | |||
| // 创建阿里云播放器 | |||
| open() { | |||
| // 检测设备类型 | |||
| const deviceType = getDeviceType() | |||
| let isAndroid = false | |||
| if (!deviceType) { | |||
| // 设备类型为pc | |||
| isAndroid = false | |||
| } else { | |||
| if (deviceType[0] == 'Android') { | |||
| // 设备类型为安卓 | |||
| isAndroid = true | |||
| } else { | |||
| // 其他设备 | |||
| isAndroid = false | |||
| } | |||
| } | |||
| new Aliplayer( | |||
| { | |||
| id: 'player-container', | |||
| cover: this.coverUrl, | |||
| source: this.videoSrc, | |||
| // 安卓设备尺寸比其他设备小一半,需适配 | |||
| // width: isAndroid ? '260px' : '480px', | |||
| // height: isAndroid ? '427px' : '854px', | |||
| width: '100%', | |||
| height: '100%', | |||
| // 以下可选设置 | |||
| playsinline: true, // 禁止内置播放 | |||
| isLive: false, // 直播 | |||
| rePlay: false, // 循环播放 | |||
| preload: true, //播放器自动加载 | |||
| autoplay: false, // 自动播放 | |||
| diagnosisButtonVisible: false, //是否显示检测按钮 | |||
| keyShortCuts: true, //是否启用快捷键 | |||
| keyFastForwardStep: 3, //快进快退的时间长度 | |||
| controlBarVisibility: 'always' // 控制条的显示方式 | |||
| }, | |||
| function (player) { | |||
| player.play() | |||
| } | |||
| ) | |||
| }, | |||
| // 下载视频 | |||
| downloadVideo() { | |||
| // 视频地址 | |||
| const videoUrl = this.videoSrc | |||
| // 下载视频 | |||
| saveAs(videoUrl, this.title) | |||
| saveAs(videoUrl, this.title + '.mp4') | |||
| }, | |||
| // 获取视频信息 | |||
| async getVideoInfo() { | |||
| @@ -131,57 +119,14 @@ export default { | |||
| const { data: res2 } = await doGetVideoDetialById(res.videoId) | |||
| this.videoSrc = res2.videoUrl | |||
| this.title = res2.title | |||
| this.coverUrl = res2.coverURL | |||
| return | |||
| } | |||
| this.videoSrc = res.videoPathUri + res.videoPath | |||
| this.title = res.title | |||
| this.coverUrl = res.coverURL | |||
| }, | |||
| onVideoLoaded() { | |||
| this.totalTime = this.$refs.video.duration | |||
| }, | |||
| onVideoEnded() { | |||
| this.playing = false | |||
| }, | |||
| // 播放&暂停 | |||
| togglePlay() { | |||
| this.playing = !this.playing | |||
| if (this.playing) { | |||
| this.$refs.video.play() | |||
| } else { | |||
| this.$refs.video.pause() | |||
| } | |||
| }, | |||
| // 横屏 | |||
| toggleScreen() { | |||
| if (this.isLandscape) { | |||
| screen.orientation.unlock() | |||
| } else { | |||
| screen.orientation.lock('landscape') | |||
| } | |||
| this.isLandscape = !this.isLandscape | |||
| }, | |||
| onOrientationChange() { | |||
| this.fullScreen = screen.orientation.type.includes('landscape') | |||
| }, | |||
| // 控制快进后退 | |||
| seek(seconds) { | |||
| const newTime = Math.max( | |||
| 0, | |||
| Math.min(this.totalTime, this.currentTime + seconds) | |||
| ) | |||
| this.$refs.video.currentTime = newTime | |||
| this.currentTime = newTime | |||
| }, | |||
| // 拖动滚动条 | |||
| onProgressChange() { | |||
| this.progressChanging = true | |||
| this.$refs.video.currentTime = this.progress | |||
| }, | |||
| //实时更新时间 | |||
| onTimeUpdate() { | |||
| this.currentTime = this.$refs.video.currentTime | |||
| this.progress = this.currentTime | |||
| }, | |||
| // 处理时间 | |||
| formatTime(time) { | |||
| const minutes = Math.floor(time / 60) | |||
| @@ -198,10 +143,15 @@ export default { | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| #player-container { | |||
| width: 100%; | |||
| height: calc(100vh - 40px); | |||
| overflow: hidden; | |||
| } | |||
| .page { | |||
| // width: 375px; | |||
| // height: 100vh; | |||
| overflow-y: hidden; | |||
| overflow: hidden; | |||
| } | |||
| .content { | |||
| width: 100%; | |||
| @@ -211,55 +161,9 @@ export default { | |||
| .videoBox { | |||
| position: relative; | |||
| width: 100%; | |||
| height: 627px; | |||
| height: calc(100vh - 40px); | |||
| background-color: #f8f9f9; | |||
| video { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| &-controls { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| padding: 6px 11px; | |||
| position: absolute; | |||
| left: 50%; | |||
| bottom: 27px; | |||
| transform: translateX(-50%); | |||
| width: calc(100% - 20px); | |||
| height: 26px; | |||
| background: rgba(67, 68, 71, 0.7); | |||
| border-radius: 9px; | |||
| color: #fff; | |||
| &-left { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| div { | |||
| padding: 0 8px; | |||
| } | |||
| i { | |||
| display: block; | |||
| width: 11px; | |||
| height: 11px; | |||
| color: #fff; | |||
| } | |||
| } | |||
| &-middle { | |||
| flex: 1; | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| .time { | |||
| padding: 0 8px; | |||
| } | |||
| ::v-deep .van-slider__button { | |||
| width: 5px; | |||
| height: 5px; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| } | |||
| &-download { | |||
| position: absolute; | |||
| right: 15px; | |||
| @@ -267,6 +171,11 @@ export default { | |||
| display: inline-block; | |||
| width: 24px; | |||
| height: 24px; | |||
| z-index: 99; | |||
| img { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||