commit
cf0a567876
@ -16,7 +16,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^1.6.5",
|
"ant-design-vue": "^1.6.5",
|
||||||
"artplayer": "5.1.1",
|
|
||||||
"clipboard": "^2.0.6",
|
"clipboard": "^2.0.6",
|
||||||
"cropperjs": "^1.5.6",
|
"cropperjs": "^1.5.6",
|
||||||
"e-vue-contextmenu": "^0.1.3",
|
"e-vue-contextmenu": "^0.1.3",
|
||||||
|
|||||||
8
public/resource/artplayer@5.1.6.js
Normal file
8
public/resource/artplayer@5.1.6.js
Normal file
File diff suppressed because one or more lines are too long
@ -85,6 +85,14 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 获取office配置
|
// 获取office配置
|
||||||
|
getPublicOfficeConfig: function(params) {
|
||||||
|
return request({
|
||||||
|
url: 'public/office/config',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取office配置
|
||||||
getOfficeConfig: function() {
|
getOfficeConfig: function() {
|
||||||
return request({
|
return request({
|
||||||
url: '/office/config',
|
url: '/office/config',
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
import { loadScript } from '@/utils/load-script'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ModelPreview",
|
name: "ModelPreview",
|
||||||
components: {},
|
components: {},
|
||||||
@ -44,23 +46,9 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const modelViewerJsUrl = window.location.origin + '/resource/model-viewer.min.js';
|
const modelViewerJsUrl = window.location.origin + '/resource/model-viewer.min.js';
|
||||||
|
loadScript(modelViewerJsUrl, 'module').then(() => {
|
||||||
// 检查是否已经加载了相同的脚本
|
this.onRead();
|
||||||
const existingScript = Array.from(document.head.getElementsByTagName('script')).find(
|
})
|
||||||
script => script.src === modelViewerJsUrl
|
|
||||||
)
|
|
||||||
|
|
||||||
if (existingScript) {
|
|
||||||
this.onRead()
|
|
||||||
} else {
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.src = modelViewerJsUrl;
|
|
||||||
script.type = 'module';
|
|
||||||
script.onload = () => {
|
|
||||||
this.onRead()
|
|
||||||
};
|
|
||||||
document.head.appendChild(script);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="artRef"></div>
|
<div ref="artRef"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Artplayer from 'artplayer';
|
|
||||||
|
import { loadScript } from '@/utils/load-script'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Artplayer',
|
name: 'Artplayer',
|
||||||
@ -19,19 +19,26 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.instance = new Artplayer({
|
const artPlayerJsUrl = window.location.origin + '/resource/artplayer@5.1.6.js';
|
||||||
...this.option,
|
loadScript(artPlayerJsUrl, undefined).then(() => {
|
||||||
container: this.$refs.artRef,
|
this.onRead();
|
||||||
});
|
})
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$emit('get-instance', this.instance);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.instance && this.instance.destroy) {
|
if (this.instance && this.instance.destroy) {
|
||||||
this.instance.destroy(false);
|
this.instance.destroy(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
onRead() {
|
||||||
|
this.instance = new Artplayer({
|
||||||
|
...this.option,
|
||||||
|
container: this.$refs.artRef,
|
||||||
|
})
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$emit('get-instance', this.instance);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import fileConfig from '@/utils/file-config'
|
import fileConfig from '@/utils/file-config'
|
||||||
import Artplayer from "@/components/preview/Artplayer.vue";
|
import Artplayer from "@/components/preview/Artplayer.vue";
|
||||||
|
import artplayerPluginVttThumbnail from './artplayer-plugin-vtt-thumbnail';
|
||||||
import Hls from "hls.js";
|
import Hls from "hls.js";
|
||||||
import FlvJs from "flv.js";
|
import FlvJs from "flv.js";
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ export default {
|
|||||||
},
|
},
|
||||||
click: () => this.copyToClipboard(this.videoLink),
|
click: () => this.copyToClipboard(this.videoLink),
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
videoLink: '',
|
videoLink: '',
|
||||||
style: {
|
style: {
|
||||||
@ -163,6 +164,11 @@ export default {
|
|||||||
this.option.customType = {
|
this.option.customType = {
|
||||||
m3u8: this.playM3u8
|
m3u8: this.playM3u8
|
||||||
}
|
}
|
||||||
|
this.option.plugins = [
|
||||||
|
artplayerPluginVttThumbnail({
|
||||||
|
vtt: videoUrl.replace(/m3u8/g, 'vtt'),
|
||||||
|
})
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.file.contentType.indexOf('flv') > -1) {
|
if (this.file.contentType.indexOf('flv') > -1) {
|
||||||
|
|||||||
@ -0,0 +1,68 @@
|
|||||||
|
function padEnd(str, targetLength, padString) {
|
||||||
|
if (str.length > targetLength) {
|
||||||
|
return String(str);
|
||||||
|
} else {
|
||||||
|
targetLength = targetLength - str.length;
|
||||||
|
if (targetLength > padString.length) {
|
||||||
|
padString += padString.repeat(targetLength / padString.length);
|
||||||
|
}
|
||||||
|
return String(str) + padString.slice(0, targetLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function t2d(time) {
|
||||||
|
var arr = time.split('.');
|
||||||
|
var left = arr[0].split(':') || [];
|
||||||
|
var right = padEnd(arr[1] || '0', 3, '0');
|
||||||
|
var ms = Number(right) / 1000;
|
||||||
|
|
||||||
|
var h = Number(left[left.length - 3] || 0) * 3600;
|
||||||
|
var m = Number(left[left.length - 2] || 0) * 60;
|
||||||
|
var s = Number(left[left.length - 1] || 0);
|
||||||
|
return h + m + s + ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function getVttArray(vttUrl = '') {
|
||||||
|
const vttString = await (await fetch(vttUrl)).text();
|
||||||
|
const lines = vttString.split(/[\n\r]/gm).filter((item) => item.trim());
|
||||||
|
const vttArray = [];
|
||||||
|
|
||||||
|
for (let i = 1; i < lines.length; i += 2) {
|
||||||
|
const time = lines[i];
|
||||||
|
const text = lines[i + 1];
|
||||||
|
|
||||||
|
if (!text.trim()) continue;
|
||||||
|
|
||||||
|
const timeReg =
|
||||||
|
/((?:[0-9]{2}:)?(?:[0-9]{2}:)?[0-9]{2}(?:.[0-9]{3})?)(?: ?--> ?)((?:[0-9]{2}:)?(?:[0-9]{2}:)?[0-9]{2}(?:.[0-9]{3})?)/;
|
||||||
|
const timeMatch = time.match(timeReg);
|
||||||
|
|
||||||
|
const textReg = /(.*)#(\w{4})=(.*)/i;
|
||||||
|
const textMatch = text.match(textReg);
|
||||||
|
|
||||||
|
const start = Math.floor(t2d(timeMatch[1]));
|
||||||
|
const end = Math.floor(t2d(timeMatch[2]));
|
||||||
|
|
||||||
|
let url = textMatch[1];
|
||||||
|
const isAbsoluteUrl = /^\/|((https?|ftp|file):\/\/)/i.test(url);
|
||||||
|
if (!isAbsoluteUrl) {
|
||||||
|
const urlArr = vttUrl.split('/');
|
||||||
|
urlArr.pop();
|
||||||
|
urlArr.push(url);
|
||||||
|
url = urlArr.join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = { start, end, url };
|
||||||
|
|
||||||
|
const keys = textMatch[2].split('');
|
||||||
|
const values = textMatch[3].split(',');
|
||||||
|
|
||||||
|
for (let j = 0; j < keys.length; j++) {
|
||||||
|
result[keys[j]] = values[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
vttArray.push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vttArray;
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
import getVttArray from './getVttArray';
|
||||||
|
|
||||||
|
export default function artplayerPluginVttThumbnail(option) {
|
||||||
|
return async (art) => {
|
||||||
|
const {
|
||||||
|
constructor: {
|
||||||
|
utils: { setStyle, isMobile },
|
||||||
|
},
|
||||||
|
template: { $progress },
|
||||||
|
} = art;
|
||||||
|
|
||||||
|
let timer = null;
|
||||||
|
const thumbnails = await getVttArray(option.vtt);
|
||||||
|
function showThumbnails($control, find, width) {
|
||||||
|
setStyle($control, 'backgroundImage', `url(${find.url})`);
|
||||||
|
setStyle($control, 'height', `${find.h}px`);
|
||||||
|
setStyle($control, 'width', `${find.w}px`);
|
||||||
|
setStyle($control, 'backgroundPosition', `-${find.x}px -${find.y}px`);
|
||||||
|
if (width <= find.w / 2) {
|
||||||
|
setStyle($control, 'left', 0);
|
||||||
|
} else if (width > $progress.clientWidth - find.w / 2) {
|
||||||
|
setStyle($control, 'left', `${$progress.clientWidth - find.w}px`);
|
||||||
|
} else {
|
||||||
|
setStyle($control, 'left', `${width - find.w / 2}px`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
art.controls.add({
|
||||||
|
name: 'thumbnails',
|
||||||
|
position: 'top',
|
||||||
|
index: 20,
|
||||||
|
style: option.style || {},
|
||||||
|
mounted($control) {
|
||||||
|
art.on('setBar', async (type, percentage, event) => {
|
||||||
|
const isMobileDroging = type === 'played' && event && isMobile;
|
||||||
|
|
||||||
|
if (type === 'hover' || isMobileDroging) {
|
||||||
|
const width = $progress.clientWidth * percentage;
|
||||||
|
const second = percentage * art.duration;
|
||||||
|
setStyle($control, 'display', 'flex');
|
||||||
|
|
||||||
|
const find = thumbnails.find((item) => second >= item.start && second <= item.end);
|
||||||
|
if (!find) return setStyle($control, 'display', 'none');
|
||||||
|
|
||||||
|
if (width > 0 && width < $progress.clientWidth) {
|
||||||
|
showThumbnails($control, find, width);
|
||||||
|
} else {
|
||||||
|
if (!isMobile) {
|
||||||
|
setStyle($control, 'display', 'none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMobileDroging) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
setStyle($control, 'display', 'none');
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'artplayerPluginVttThumbnail',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window['artplayerPluginVttThumbnail'] = artplayerPluginVttThumbnail;
|
||||||
|
}
|
||||||
25
src/utils/load-script.js
Normal file
25
src/utils/load-script.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// loadScript.js
|
||||||
|
export function loadScript(scriptUrl, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// 检查是否已经加载了相同的脚本
|
||||||
|
const existingScript = Array.from(document.head.getElementsByTagName('script')).find(
|
||||||
|
script => script.src === scriptUrl
|
||||||
|
)
|
||||||
|
if (existingScript) {
|
||||||
|
resolve()
|
||||||
|
} else {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = scriptUrl;
|
||||||
|
if (type) {
|
||||||
|
script.type = type
|
||||||
|
}
|
||||||
|
script.onload = () => {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
script.onerror = () => {
|
||||||
|
reject(new Error(`Failed to load script with URL ${scriptUrl}`));
|
||||||
|
}
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user