mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-03 10:21:55 +00:00
perf: 优化视频播放
This commit is contained in:
parent
1a36044de2
commit
49203c15a7
@ -2218,7 +2218,7 @@ class Base
|
||||
$type = ['jpg', 'jpeg', 'webp', 'gif', 'png'];
|
||||
break;
|
||||
case 'video':
|
||||
$type = ['rm', 'rmvb', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4'];
|
||||
$type = ['rm', 'rmvb', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'webm'];
|
||||
break;
|
||||
case 'audio':
|
||||
$type = ['mp3', 'wma', 'wav', 'amr'];
|
||||
@ -2233,7 +2233,7 @@ class Base
|
||||
$type = ['zip'];
|
||||
break;
|
||||
case 'file':
|
||||
$type = ['jpg', 'jpeg', 'webp', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz', 'ai', 'avi', 'bmp', 'cdr', 'eps', 'mov', 'mp3', 'mp4', 'pr', 'psd', 'svg', 'tif'];
|
||||
$type = ['jpg', 'jpeg', 'webp', 'png', 'gif', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'esp', 'pdf', 'rar', 'zip', 'gz', 'ai', 'avi', 'bmp', 'cdr', 'eps', 'mov', 'mp3', 'mp4', 'webm', 'pr', 'psd', 'svg', 'tif'];
|
||||
break;
|
||||
case 'firmware':
|
||||
$type = ['img', 'tar', 'bin'];
|
||||
@ -2320,6 +2320,17 @@ class Base
|
||||
}
|
||||
}
|
||||
//
|
||||
if (in_array($extension, ['mp4', 'webm'])) {
|
||||
// 视频尺寸
|
||||
$thumbFile = $array['file'] . '_thumb.jpg';
|
||||
shell_exec("ffmpeg -i {$array['file']} -ss 1 -vframes 1 {$thumbFile} 2>&1");
|
||||
if (file_exists($thumbFile)) {
|
||||
$paramet = getimagesize($thumbFile);
|
||||
$array['width'] = $paramet[0];
|
||||
$array['height'] = $paramet[1];
|
||||
$array['thumb'] = $array['path'] . '_thumb.jpg';
|
||||
}
|
||||
}
|
||||
if (in_array($extension, ['jpg', 'jpeg', 'webp', 'gif', 'png'])) {
|
||||
//图片尺寸
|
||||
$paramet = getimagesize($array['file']);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
services:
|
||||
php:
|
||||
container_name: "dootask-php-${APP_ID}"
|
||||
image: "kuaifan/php:swoole-8.0.rc14"
|
||||
image: "kuaifan/php:swoole-8.0.rc15"
|
||||
shm_size: "2gb"
|
||||
ulimits:
|
||||
core:
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div ref="view" class="common-preview-video">
|
||||
<video v-if="item.src" :width="videoStyle('width')" :height="videoStyle('height')" controls autoplay>
|
||||
<source :src="item.src" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.common-preview-video {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
> video {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
src: '',
|
||||
width: 0,
|
||||
height: 0,
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
videoStyle(type) {
|
||||
let {width, height} = this.item;
|
||||
const maxWidth = this.windowWidth;
|
||||
const maxHeight = this.windowHeight;
|
||||
if (width > maxWidth) {
|
||||
height = height * maxWidth / width;
|
||||
width = maxWidth;
|
||||
}
|
||||
if (height > maxHeight) {
|
||||
width = width * maxHeight / height;
|
||||
height = maxHeight;
|
||||
}
|
||||
if (type === 'width') return width;
|
||||
if (type === 'height') return height;
|
||||
return {
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -8,8 +8,9 @@
|
||||
:class-name="viewMode === 'desktop' ? 'common-preview-image-view' : 'common-preview-image-swipe'"
|
||||
fullscreen>
|
||||
<template v-if="list.length > 0">
|
||||
<PreviewImageView v-if="viewMode === 'desktop'" :initial-index="index" :url-list="list" infinite/>
|
||||
<PreviewImageSwipe v-if="viewMode === 'mobile'" :initial-index="index" :url-list="list" @on-destroy="show=false"/>
|
||||
<PreviewVideoView v-if="viewVideo" :item="viewVideo"/>
|
||||
<PreviewImageView v-else-if="viewMode === 'desktop'" :initial-index="index" :url-list="list" infinite/>
|
||||
<PreviewImageSwipe v-else-if="viewMode === 'mobile'" :initial-index="index" :url-list="list" @on-destroy="show=false"/>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
@ -64,12 +65,13 @@ body {
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const PreviewVideoView = () => import('./components/video');
|
||||
const PreviewImageView = () => import('./components/view');
|
||||
const PreviewImageSwipe = () => import('./components/swipe');
|
||||
|
||||
export default {
|
||||
name: 'PreviewImage',
|
||||
components: {PreviewImageSwipe, PreviewImageView},
|
||||
components: {PreviewVideoView, PreviewImageSwipe, PreviewImageView},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
@ -104,6 +106,15 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
viewVideo() {
|
||||
if (this.list.length === 0) {
|
||||
return false
|
||||
}
|
||||
const item = this.list.find(({src}) => {
|
||||
return /\.mp4$/i.test(src)
|
||||
})
|
||||
return item || false
|
||||
},
|
||||
viewMode() {
|
||||
if (this.mode) {
|
||||
return this.mode
|
||||
|
||||
@ -57,6 +57,16 @@ export default {
|
||||
position = newPaths.findIndex(item => item === paths[position]);
|
||||
paths = newPaths;
|
||||
}
|
||||
const videoPath = paths.find(src => {
|
||||
return /\.mp4$/i.test(src)
|
||||
});
|
||||
if (videoPath) {
|
||||
$A.eeuiAppSendMessage({
|
||||
action: 'videoPreview',
|
||||
path: videoPath
|
||||
});
|
||||
return
|
||||
}
|
||||
$A.eeuiAppSendMessage({
|
||||
action: 'picturePreview',
|
||||
position,
|
||||
|
||||
@ -34,6 +34,17 @@
|
||||
<div v-else-if="msgData.type === 'file'" :class="`content-file ${msgData.msg.type}`">
|
||||
<div class="dialog-file">
|
||||
<img v-if="msgData.msg.type === 'img'" class="file-img" :style="imageStyle(msgData.msg)" :src="msgData.msg.thumb" @click="viewFile"/>
|
||||
<div v-else-if="isVideoFile(msgData.msg)" class="file-video" :style="imageStyle(msgData.msg)" @click="viewFile">
|
||||
<img v-if="msgData.msg.thumb" :src="msgData.msg.thumb">
|
||||
<video v-else :width="imageStyle(msgData.msg, 'width')" :height="imageStyle(msgData.msg, 'height')">
|
||||
<source :src="msgData.msg.path" type="video/mp4">
|
||||
</video>
|
||||
<div class="file-play">
|
||||
<div class="play-icon">
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="file-box" @click="downFile">
|
||||
<img class="file-thumb" :src="msgData.msg.thumb"/>
|
||||
<div class="file-info">
|
||||
@ -565,7 +576,7 @@ export default {
|
||||
return {};
|
||||
},
|
||||
|
||||
imageStyle(info) {
|
||||
imageStyle(info, type = 'style') {
|
||||
const {width, height} = info;
|
||||
if (width && height) {
|
||||
let maxW = 220,
|
||||
@ -581,14 +592,30 @@ export default {
|
||||
tempH = maxH;
|
||||
}
|
||||
}
|
||||
if (type === 'width') {
|
||||
return tempW
|
||||
}
|
||||
if (type === 'height') {
|
||||
return tempH
|
||||
}
|
||||
return {
|
||||
width: tempW + 'px',
|
||||
height: tempH + 'px',
|
||||
};
|
||||
}
|
||||
if (type === 'width' || type === 'height') {
|
||||
return 0
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
||||
isVideoFile(msg) {
|
||||
return msg.type === 'file'
|
||||
&& msg.ext === 'mp4'
|
||||
&& msg.width > 0
|
||||
&& msg.height > 0;
|
||||
},
|
||||
|
||||
playRecord() {
|
||||
if (this.operateVisible) {
|
||||
return
|
||||
|
||||
@ -3231,6 +3231,14 @@ export default {
|
||||
data = this.operateItem
|
||||
}
|
||||
const {msg} = data;
|
||||
if (msg.ext === 'mp4') {
|
||||
this.$store.dispatch("previewImage", {
|
||||
src: msg.path,
|
||||
width: msg.width,
|
||||
height: msg.height,
|
||||
})
|
||||
return
|
||||
}
|
||||
if (['jpg', 'jpeg', 'webp', 'gif', 'png'].includes(msg.ext)) {
|
||||
this.onViewPicture(msg.path);
|
||||
return
|
||||
|
||||
2
resources/assets/js/store/actions.js
vendored
2
resources/assets/js/store/actions.js
vendored
@ -3439,7 +3439,7 @@ export default {
|
||||
* @param data
|
||||
*/
|
||||
previewImage({state}, data) {
|
||||
if (!$A.isJson(data)) {
|
||||
if (!$A.isJson(data) || !$A.isArray(data.list)) {
|
||||
data = {index:0, list: [data]}
|
||||
}
|
||||
state.previewImageIndex = data.index;
|
||||
|
||||
@ -1018,6 +1018,48 @@
|
||||
&.file {
|
||||
display: inline-block;
|
||||
|
||||
.file-video {
|
||||
display: flex;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
> img,
|
||||
> video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-play {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
|
||||
.play-icon {
|
||||
border: 2px solid #a0a0a0;
|
||||
border-radius: 50%;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
> i {
|
||||
color: #a0a0a0;
|
||||
font-size: 30px;
|
||||
padding-left: 4px;
|
||||
transform: scaleY(0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-box {
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user