mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-25 20:08:12 +00:00
perf: 优化视频播放
This commit is contained in:
parent
1a36044de2
commit
49203c15a7
@ -2218,7 +2218,7 @@ class Base
|
|||||||
$type = ['jpg', 'jpeg', 'webp', 'gif', 'png'];
|
$type = ['jpg', 'jpeg', 'webp', 'gif', 'png'];
|
||||||
break;
|
break;
|
||||||
case 'video':
|
case 'video':
|
||||||
$type = ['rm', 'rmvb', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4'];
|
$type = ['rm', 'rmvb', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'webm'];
|
||||||
break;
|
break;
|
||||||
case 'audio':
|
case 'audio':
|
||||||
$type = ['mp3', 'wma', 'wav', 'amr'];
|
$type = ['mp3', 'wma', 'wav', 'amr'];
|
||||||
@ -2233,7 +2233,7 @@ class Base
|
|||||||
$type = ['zip'];
|
$type = ['zip'];
|
||||||
break;
|
break;
|
||||||
case 'file':
|
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;
|
break;
|
||||||
case 'firmware':
|
case 'firmware':
|
||||||
$type = ['img', 'tar', 'bin'];
|
$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'])) {
|
if (in_array($extension, ['jpg', 'jpeg', 'webp', 'gif', 'png'])) {
|
||||||
//图片尺寸
|
//图片尺寸
|
||||||
$paramet = getimagesize($array['file']);
|
$paramet = getimagesize($array['file']);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
php:
|
php:
|
||||||
container_name: "dootask-php-${APP_ID}"
|
container_name: "dootask-php-${APP_ID}"
|
||||||
image: "kuaifan/php:swoole-8.0.rc14"
|
image: "kuaifan/php:swoole-8.0.rc15"
|
||||||
shm_size: "2gb"
|
shm_size: "2gb"
|
||||||
ulimits:
|
ulimits:
|
||||||
core:
|
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'"
|
:class-name="viewMode === 'desktop' ? 'common-preview-image-view' : 'common-preview-image-swipe'"
|
||||||
fullscreen>
|
fullscreen>
|
||||||
<template v-if="list.length > 0">
|
<template v-if="list.length > 0">
|
||||||
<PreviewImageView v-if="viewMode === 'desktop'" :initial-index="index" :url-list="list" infinite/>
|
<PreviewVideoView v-if="viewVideo" :item="viewVideo"/>
|
||||||
<PreviewImageSwipe v-if="viewMode === 'mobile'" :initial-index="index" :url-list="list" @on-destroy="show=false"/>
|
<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>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
@ -64,12 +65,13 @@ body {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const PreviewVideoView = () => import('./components/video');
|
||||||
const PreviewImageView = () => import('./components/view');
|
const PreviewImageView = () => import('./components/view');
|
||||||
const PreviewImageSwipe = () => import('./components/swipe');
|
const PreviewImageSwipe = () => import('./components/swipe');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PreviewImage',
|
name: 'PreviewImage',
|
||||||
components: {PreviewImageSwipe, PreviewImageView},
|
components: {PreviewVideoView, PreviewImageSwipe, PreviewImageView},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -104,6 +106,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
viewVideo() {
|
||||||
|
if (this.list.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const item = this.list.find(({src}) => {
|
||||||
|
return /\.mp4$/i.test(src)
|
||||||
|
})
|
||||||
|
return item || false
|
||||||
|
},
|
||||||
viewMode() {
|
viewMode() {
|
||||||
if (this.mode) {
|
if (this.mode) {
|
||||||
return this.mode
|
return this.mode
|
||||||
|
|||||||
@ -57,6 +57,16 @@ export default {
|
|||||||
position = newPaths.findIndex(item => item === paths[position]);
|
position = newPaths.findIndex(item => item === paths[position]);
|
||||||
paths = newPaths;
|
paths = newPaths;
|
||||||
}
|
}
|
||||||
|
const videoPath = paths.find(src => {
|
||||||
|
return /\.mp4$/i.test(src)
|
||||||
|
});
|
||||||
|
if (videoPath) {
|
||||||
|
$A.eeuiAppSendMessage({
|
||||||
|
action: 'videoPreview',
|
||||||
|
path: videoPath
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
$A.eeuiAppSendMessage({
|
$A.eeuiAppSendMessage({
|
||||||
action: 'picturePreview',
|
action: 'picturePreview',
|
||||||
position,
|
position,
|
||||||
|
|||||||
@ -34,6 +34,17 @@
|
|||||||
<div v-else-if="msgData.type === 'file'" :class="`content-file ${msgData.msg.type}`">
|
<div v-else-if="msgData.type === 'file'" :class="`content-file ${msgData.msg.type}`">
|
||||||
<div class="dialog-file">
|
<div class="dialog-file">
|
||||||
<img v-if="msgData.msg.type === 'img'" class="file-img" :style="imageStyle(msgData.msg)" :src="msgData.msg.thumb" @click="viewFile"/>
|
<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">
|
<div v-else class="file-box" @click="downFile">
|
||||||
<img class="file-thumb" :src="msgData.msg.thumb"/>
|
<img class="file-thumb" :src="msgData.msg.thumb"/>
|
||||||
<div class="file-info">
|
<div class="file-info">
|
||||||
@ -565,7 +576,7 @@ export default {
|
|||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
||||||
imageStyle(info) {
|
imageStyle(info, type = 'style') {
|
||||||
const {width, height} = info;
|
const {width, height} = info;
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
let maxW = 220,
|
let maxW = 220,
|
||||||
@ -581,14 +592,30 @@ export default {
|
|||||||
tempH = maxH;
|
tempH = maxH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (type === 'width') {
|
||||||
|
return tempW
|
||||||
|
}
|
||||||
|
if (type === 'height') {
|
||||||
|
return tempH
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
width: tempW + 'px',
|
width: tempW + 'px',
|
||||||
height: tempH + 'px',
|
height: tempH + 'px',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (type === 'width' || type === 'height') {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isVideoFile(msg) {
|
||||||
|
return msg.type === 'file'
|
||||||
|
&& msg.ext === 'mp4'
|
||||||
|
&& msg.width > 0
|
||||||
|
&& msg.height > 0;
|
||||||
|
},
|
||||||
|
|
||||||
playRecord() {
|
playRecord() {
|
||||||
if (this.operateVisible) {
|
if (this.operateVisible) {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -3231,6 +3231,14 @@ export default {
|
|||||||
data = this.operateItem
|
data = this.operateItem
|
||||||
}
|
}
|
||||||
const {msg} = data;
|
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)) {
|
if (['jpg', 'jpeg', 'webp', 'gif', 'png'].includes(msg.ext)) {
|
||||||
this.onViewPicture(msg.path);
|
this.onViewPicture(msg.path);
|
||||||
return
|
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
|
* @param data
|
||||||
*/
|
*/
|
||||||
previewImage({state}, data) {
|
previewImage({state}, data) {
|
||||||
if (!$A.isJson(data)) {
|
if (!$A.isJson(data) || !$A.isArray(data.list)) {
|
||||||
data = {index:0, list: [data]}
|
data = {index:0, list: [data]}
|
||||||
}
|
}
|
||||||
state.previewImageIndex = data.index;
|
state.previewImageIndex = data.index;
|
||||||
|
|||||||
@ -1018,6 +1018,48 @@
|
|||||||
&.file {
|
&.file {
|
||||||
display: inline-block;
|
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 {
|
.file-box {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user