2025-12-11 22:33:31 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view>
|
|
|
|
|
|
<view class="video_message_container" @click="clickMediaItem">
|
|
|
|
|
|
<u--image
|
|
|
|
|
|
:showLoading="true"
|
|
|
|
|
|
:src="src"
|
|
|
|
|
|
:width="imgWidth"
|
|
|
|
|
|
:height="maxHeight"
|
|
|
|
|
|
mode="widthFix"
|
|
|
|
|
|
@load="onLoaded"
|
|
|
|
|
|
@click="clickMediaItem">
|
|
|
|
|
|
<template v-slot:loading>
|
|
|
|
|
|
<u-loading-icon color="red"></u-loading-icon>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</u--image>
|
|
|
|
|
|
<!-- 覆盖层:显示封面下载状态/视频下载入口/播放按钮 -->
|
|
|
|
|
|
<view class="download-overlay" @click.stop="onOverlayClick">
|
|
|
|
|
|
<view v-if="videoDownloading" class="progress-box">
|
|
|
|
|
|
<view class="progress-bar">
|
|
|
|
|
|
<view class="progress-fill" :style="{ width: videoDownloadProgress + '%' }"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<text class="progress-text">{{ videoDownloadProgress }}%</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<u-icon v-else-if="videoExists" class="play_icon" name="play-circle" size="48" color="#fff"></u-icon>
|
|
|
|
|
|
<uni-icons v-else class="play_icon" type="cloud-download" size="48" color="#fff"></uni-icons>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<!-- 视频播放器组件 -->
|
|
|
|
|
|
<videoPlayer :previewVideoFlag="previewVideoFlag" :previewVideoSrc="previewVideoSrc" @quitPlay="previewVideoFlag=false"></videoPlayer>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
/*
|
|
|
|
|
|
{
|
|
|
|
|
|
"clientMsgID": "d9a596f3e665e84559821a8aa5fb9f16",
|
|
|
|
|
|
"serverMsgID": "76a56965a5fba40df213da2acb331517",
|
|
|
|
|
|
"createTime": 1765413732786,
|
|
|
|
|
|
"sendTime": 1765413733732,
|
|
|
|
|
|
"sessionType": 1,
|
|
|
|
|
|
"sendID": "100003",
|
|
|
|
|
|
"recvID": "100004",
|
|
|
|
|
|
"msgFrom": 100,
|
|
|
|
|
|
"contentType": 104,
|
|
|
|
|
|
"senderPlatformID": 2,
|
|
|
|
|
|
"senderNickname": "131****2222",
|
|
|
|
|
|
"senderFaceUrl": "/static/img/avatar.png",
|
|
|
|
|
|
"seq": 22,
|
|
|
|
|
|
"isRead": false,
|
|
|
|
|
|
"status": 2,
|
|
|
|
|
|
"videoElem": {
|
|
|
|
|
|
"videoPath": "/storage/emulated/0/Movies/顺网云电脑 2025-10-21 04-26-04-converted.mp4",
|
|
|
|
|
|
"videoUrl": "http://www.axzc.xyz/object/100003/msg_video_d9a596f3e665e84559821a8aa5fb9f16.mp4",
|
|
|
|
|
|
"videoType": "mp4",
|
|
|
|
|
|
"videoSize": 3751005,
|
|
|
|
|
|
"duration": 44,
|
|
|
|
|
|
"snapshotPath": "/storage/emulated/0/Android/data/hk.huisheng.im/apps/__UNI__CA458BA/doc/video_cover_2ea1c8ec.jpg",
|
|
|
|
|
|
"snapshotSize": 36974,
|
|
|
|
|
|
"snapshotUrl": "http://www.axzc.xyz/object/100003/msg_videoSnapshot_d9a596f3e665e84559821a8aa5fb9f16.jpg",
|
|
|
|
|
|
"snapshotWidth": 1087,
|
|
|
|
|
|
"snapshotHeight": 726
|
|
|
|
|
|
},
|
|
|
|
|
|
"attachedInfoElem": {
|
|
|
|
|
|
"groupHasReadInfo": {
|
|
|
|
|
|
"hasReadCount": 0,
|
|
|
|
|
|
"groupMemberCount": 0
|
|
|
|
|
|
},
|
|
|
|
|
|
"isPrivateChat": false,
|
|
|
|
|
|
"burnDuration": 0,
|
|
|
|
|
|
"hasReadTime": 0,
|
|
|
|
|
|
"isEncryption": false,
|
|
|
|
|
|
"inEncryptStatus": false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
const imgWidth = 240;
|
|
|
|
|
|
import md5 from "md5";
|
|
|
|
|
|
import videoPlayer from "@/components/videoPlayer.vue";
|
|
|
|
|
|
import util from "@/util"
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: "VideoMessageContainer",
|
|
|
|
|
|
components: {
|
|
|
|
|
|
videoPlayer,
|
|
|
|
|
|
},
|
|
|
|
|
|
props: {
|
|
|
|
|
|
message: Object,
|
|
|
|
|
|
conversationID:String,
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
loadingWidth: imgWidth+"px",
|
|
|
|
|
|
imgWidth:imgWidth,
|
|
|
|
|
|
isDownloading: false,
|
|
|
|
|
|
downloadProgress: 0,
|
|
|
|
|
|
coverDownloading: false,
|
|
|
|
|
|
coverDownloadProgress: 0,
|
|
|
|
|
|
videoDownloading: false,
|
|
|
|
|
|
videoDownloadProgress: 0,
|
|
|
|
|
|
videoExists: false,
|
|
|
|
|
|
videoCachePath:"",
|
|
|
|
|
|
previewVideoFlag: false,
|
|
|
|
|
|
previewVideoSrc: "",
|
|
|
|
|
|
src:"",
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
maxHeight() {
|
|
|
|
|
|
const imageHeight = this.message.videoElem.snapshotHeight;
|
|
|
|
|
|
const imageWidth = this.message.videoElem.snapshotWidth;
|
|
|
|
|
|
const aspectRatio = imageHeight / imageWidth;
|
|
|
|
|
|
return imgWidth * aspectRatio;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
async created(){
|
|
|
|
|
|
this.init();
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
async init(){
|
|
|
|
|
|
// 如果有远程 snapshotUrl,则下载到 coverCachePath
|
|
|
|
|
|
const snapshotUrl = this.message?.videoElem?.snapshotUrl;
|
|
|
|
|
|
const key = md5(this.message?.videoElem?.videoUrl || '');
|
2025-12-17 08:47:58 +08:00
|
|
|
|
const coverCachePath = `${this.conversationID}/cover_${key}.jpg`;
|
|
|
|
|
|
this.videoCachePath = `${this.conversationID}/${key}.mp4`;
|
|
|
|
|
|
this.videoExists = await util.fileExists(this.videoCachePath);
|
|
|
|
|
|
self.coverDownloading = true;
|
|
|
|
|
|
util.cacheFile(snapshotUrl,coverCachePath,(e)=>{
|
|
|
|
|
|
self.coverDownloading = false;
|
|
|
|
|
|
self.src = coverCachePath;
|
|
|
|
|
|
console.log(e);
|
|
|
|
|
|
},(e)=>{
|
|
|
|
|
|
console.log(e);
|
|
|
|
|
|
},(e)=>{
|
|
|
|
|
|
console.log(e);
|
|
|
|
|
|
});
|
2025-12-11 22:33:31 +08:00
|
|
|
|
},
|
|
|
|
|
|
clickMediaItem() {
|
|
|
|
|
|
uni.previewImage({
|
|
|
|
|
|
current: 0,
|
|
|
|
|
|
urls: [this.message.videoElem?.snapshotUrl],
|
|
|
|
|
|
indicator: "none",
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
async onLoaded() {
|
|
|
|
|
|
this.loadingWidth = "auto";
|
|
|
|
|
|
},
|
|
|
|
|
|
onOverlayClick() {
|
|
|
|
|
|
// 点击覆盖层:如果视频已缓存则直接播放,否则开始下载
|
|
|
|
|
|
if (this.videoExists) {
|
2025-12-17 08:47:58 +08:00
|
|
|
|
this.playVideo("_doc/"+this.videoCachePath);
|
2025-12-11 22:33:31 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const url = this.message?.videoElem?.videoUrl || this.message?.videoElem?.videoPath;
|
|
|
|
|
|
if (!url) {
|
|
|
|
|
|
uni.showToast({ title: '无可下载的视频' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.videoDownloading = true;
|
|
|
|
|
|
this.videoDownloadProgress = 0;
|
|
|
|
|
|
util.downloadFile(url, this.videoCachePath, (localPath) => {
|
|
|
|
|
|
this.videoDownloading = false;
|
|
|
|
|
|
this.videoExists = true;
|
2025-12-17 08:47:58 +08:00
|
|
|
|
this.playVideo("_doc/"+localPath);
|
2025-12-11 22:33:31 +08:00
|
|
|
|
}, (err) => {
|
|
|
|
|
|
this.videoDownloading = false;
|
|
|
|
|
|
uni.showToast({ title: '下载失败' });
|
|
|
|
|
|
}, (prog) => {
|
|
|
|
|
|
this.videoDownloadProgress = prog;
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
playVideo(localPath) {
|
|
|
|
|
|
if (!localPath) return;
|
|
|
|
|
|
this.previewVideoSrc = localPath;
|
|
|
|
|
|
this.previewVideoFlag = true;
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.video_message_container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
|
|
.play_icon {
|
|
|
|
|
|
width: 48px;
|
|
|
|
|
|
height: 48px;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.video_duration {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 12rpx;
|
|
|
|
|
|
right: 24rpx;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.download-overlay {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
background: rgba(0,0,0,0.35);
|
|
|
|
|
|
}
|
|
|
|
|
|
.progress-box {
|
|
|
|
|
|
width: 70%;
|
|
|
|
|
|
max-width: 240px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.progress-bar {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 8px;
|
|
|
|
|
|
background: rgba(255,255,255,0.25);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.progress-fill {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: #4caf50;
|
|
|
|
|
|
width: 0%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.progress-text {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|