|
@@ -14,13 +14,20 @@
|
|
<el-main>
|
|
<el-main>
|
|
<div style="margin-bottom: 20px; display: flex; align-items: center; gap: 20px; flex-wrap: nowrap;">
|
|
<div style="margin-bottom: 20px; display: flex; align-items: center; gap: 20px; flex-wrap: nowrap;">
|
|
<el-button @click="getRandomVideo" type="primary">随机播放</el-button>
|
|
<el-button @click="getRandomVideo" type="primary">随机播放</el-button>
|
|
- <el-switch v-model="loopMode" active-text="自动连播" inactive-text="单次播放"></el-switch>
|
|
|
|
- <el-switch v-model="infiniteLoop" active-text="无限循环" inactive-text="正常模式"
|
|
|
|
- @change="toggleInfiniteLoop" style="flex-shrink: 0;">
|
|
|
|
|
|
+ <el-radio-group v-model="selectedFileType" size="mini" style="margin-left: 10px;">
|
|
|
|
+ <el-radio-button label="video">视频</el-radio-button>
|
|
|
|
+ <el-radio-button label="audio">音频</el-radio-button>
|
|
|
|
+ <el-radio-button label="all">全部</el-radio-button>
|
|
|
|
+ </el-radio-group>
|
|
|
|
+ <el-switch v-model="loopMode" active-text="连播" active-color="#13ce66" inactive-color="#ff4949"
|
|
|
|
+ style="margin-left: 15px;"></el-switch>
|
|
|
|
+
|
|
|
|
+ <el-switch v-model="infiniteLoop" active-text="循环播放" @change="toggleInfiniteLoop"
|
|
|
|
+ style="flex-shrink: 0;">
|
|
</el-switch>
|
|
</el-switch>
|
|
<div v-if="currentFile" style="display: flex; align-items: center; flex-shrink: 0;">
|
|
<div v-if="currentFile" style="display: flex; align-items: center; flex-shrink: 0;">
|
|
<span style="margin-right: 10px;">当前播放:</span>
|
|
<span style="margin-right: 10px;">当前播放:</span>
|
|
- <el-tag type="info">{{ currentFile.filename }}</el-tag>
|
|
|
|
|
|
+ <div style="font-weight: bold;">{{ currentFile.filename }}</div>
|
|
<span style="margin-left: 15px; margin-right: 10px;">权重:</span>
|
|
<span style="margin-left: 15px; margin-right: 10px;">权重:</span>
|
|
<el-input-number v-model="currentFile.weight" :min="0" :max="10" size="mini"
|
|
<el-input-number v-model="currentFile.weight" :min="0" :max="10" size="mini"
|
|
@change="updateWeight(currentFile)" style="width: 100px;">
|
|
@change="updateWeight(currentFile)" style="width: 100px;">
|
|
@@ -36,7 +43,7 @@
|
|
<!-- 视频列表 -->
|
|
<!-- 视频列表 -->
|
|
<el-aside width="450px" style="background: #f5f5f5; height: 100vh;">
|
|
<el-aside width="450px" style="background: #f5f5f5; height: 100vh;">
|
|
<h3 style="margin-bottom: 15px;">视频列表(双击播放)</h3>
|
|
<h3 style="margin-bottom: 15px;">视频列表(双击播放)</h3>
|
|
- <el-table :data="files" stripe height="calc(100vh - 60px)" @row-dblclick="playSelected">
|
|
|
|
|
|
+ <el-table :data="filteredFiles" stripe height="calc(100vh - 60px)" @row-dblclick="playSelected">
|
|
<el-table-column prop="filename" label="文件名"></el-table-column>
|
|
<el-table-column prop="filename" label="文件名"></el-table-column>
|
|
<el-table-column label="权重" width="150">
|
|
<el-table-column label="权重" width="150">
|
|
<template slot-scope="{row}">
|
|
<template slot-scope="{row}">
|
|
@@ -64,6 +71,8 @@
|
|
currentVideoMD5: '',
|
|
currentVideoMD5: '',
|
|
loopMode: true,
|
|
loopMode: true,
|
|
infiniteLoop: false
|
|
infiniteLoop: false
|
|
|
|
+ ,
|
|
|
|
+ selectedFileType: 'video'
|
|
}
|
|
}
|
|
},
|
|
},
|
|
mounted() {
|
|
mounted() {
|
|
@@ -72,10 +81,32 @@
|
|
computed: {
|
|
computed: {
|
|
currentFile() {
|
|
currentFile() {
|
|
return this.files.find(file => file.md5 === this.currentVideoMD5)
|
|
return this.files.find(file => file.md5 === this.currentVideoMD5)
|
|
- }
|
|
|
|
|
|
+ },
|
|
|
|
+ filteredFiles() {
|
|
|
|
+ const videoExts = ['mp4', 'avi', 'mov', 'mkv'];
|
|
|
|
+ const audioExts = ['aac', 'mp3', 'flac'];
|
|
|
|
+
|
|
|
|
+ return this.files.filter(file => {
|
|
|
|
+ const ext = file.filename.split('.').pop().toLowerCase();
|
|
|
|
+ if (this.selectedFileType === 'video') return videoExts.includes(ext);
|
|
|
|
+ if (this.selectedFileType === 'audio') return audioExts.includes(ext);
|
|
|
|
+ return true;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
- async fetchFiles() {
|
|
|
|
|
|
+ // 加权随机选择方法
|
|
|
|
+ getWeightedRandom(files) {
|
|
|
|
+ const totalWeight = files.reduce((sum, file) => sum + (file.weight || 1), 0);
|
|
|
|
+ const random = Math.random() * totalWeight;
|
|
|
|
+ let currentSum = 0;
|
|
|
|
+
|
|
|
|
+ for (const file of files) {
|
|
|
|
+ currentSum += file.weight || 1;
|
|
|
|
+ if (random <= currentSum) return file;
|
|
|
|
+ }
|
|
|
|
+ return files[Math.floor(Math.random() * files.length)];
|
|
|
|
+ }, async fetchFiles() {
|
|
const res = await axios.get('/files')
|
|
const res = await axios.get('/files')
|
|
this.files = res.data
|
|
this.files = res.data
|
|
},
|
|
},
|
|
@@ -117,9 +148,9 @@
|
|
return this.playCurrent()
|
|
return this.playCurrent()
|
|
}
|
|
}
|
|
|
|
|
|
- const res = await axios.get('/random')
|
|
|
|
- this.currentVideoMD5 = res.data.md5
|
|
|
|
- this.currentVideo = `/play/${res.data.md5}`
|
|
|
|
|
|
+ const res = this.getWeightedRandom(this.filteredFiles);
|
|
|
|
+ this.currentVideoMD5 = res.md5
|
|
|
|
+ this.currentVideo = `/play/${res.md5}`
|
|
|
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
const player = this.$refs.videoPlayer
|
|
const player = this.$refs.videoPlayer
|