From c65b90aaa3477a90ebc325024927d80227c0c841 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期四, 09 四月 2026 14:09:25 +0800
Subject: [PATCH] 测试完成
---
src/components/AudioPlayer/index.vue | 964 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 964 insertions(+), 0 deletions(-)
diff --git a/src/components/AudioPlayer/index.vue b/src/components/AudioPlayer/index.vue
new file mode 100644
index 0000000..0524c1f
--- /dev/null
+++ b/src/components/AudioPlayer/index.vue
@@ -0,0 +1,964 @@
+<template>
+ <div class="audio-player">
+ <!-- 涓绘挱鏀惧櫒 -->
+ <div class="audio-container" v-if="showDefaultPlayer">
+ <audio
+ ref="audioElement"
+ :src="audioSource"
+ preload="metadata"
+ @timeupdate="updateTime"
+ @loadedmetadata="updateDuration"
+ @play="handlePlay"
+ @pause="handlePause"
+ @ended="handleEnded"
+ @error="handleError"
+ style="display: none"
+ ></audio>
+
+ <!-- 鎾斁鎺у埗 -->
+ <div class="audio-controls">
+ <el-button
+ v-if="!isPlaying"
+ type="text"
+ icon="el-icon-video-play"
+ class="play-btn"
+ @click="playAudio"
+ :loading="loading"
+ ></el-button>
+ <el-button
+ v-else
+ type="text"
+ icon="el-icon-video-pause"
+ class="pause-btn"
+ @click="pauseAudio"
+ ></el-button>
+
+ <!-- 杩涘害鏉� -->
+ <div class="progress-container" @click="seekAudio" @mousemove="updateHoverTime">
+ <div class="progress-background">
+ <!-- 缂撳啿杩涘害 -->
+ <div
+ v-if="buffered.length > 0"
+ class="buffered-progress"
+ :style="{ width: `${bufferedPercent}%` }"
+ ></div>
+
+ <!-- 鎾斁杩涘害 -->
+ <div
+ class="played-progress"
+ :style="{ width: `${progressPercent}%` }"
+ ></div>
+
+ <!-- 鎮仠棰勮 -->
+ <div
+ v-if="showHoverPreview"
+ class="hover-preview"
+ :style="{ left: `${hoverPercent}%` }"
+ >
+ <span class="hover-time">{{ formatTime(hoverTime) }}</span>
+ </div>
+
+ <!-- 鎾斁鐐� -->
+ <div
+ class="playhead"
+ :style="{ left: `${progressPercent}%` }"
+ ></div>
+ </div>
+ </div>
+
+ <!-- 鏃堕棿鏄剧ず -->
+ <div class="time-display">
+ <span class="current-time">{{ formatTime(currentTime) }}</span>
+ <span class="time-separator">/</span>
+ <span class="duration">{{ formatTime(duration) }}</span>
+ </div>
+
+ <!-- 闊抽噺鎺у埗 -->
+ <div class="volume-control" v-if="showVolumeControl">
+ <el-popover
+ placement="top"
+ width="40"
+ trigger="hover"
+ popper-class="volume-popover"
+ >
+ <div class="volume-slider-container" @click.stop>
+ <el-slider
+ v-model="volume"
+ vertical
+ height="100px"
+ :show-tooltip="false"
+ @input="changeVolume"
+ ></el-slider>
+ </div>
+
+ <el-button
+ slot="reference"
+ type="text"
+ :icon="volumeIcon"
+ class="volume-btn"
+ @click.stop
+ ></el-button>
+ </el-popover>
+ </div>
+
+ <!-- 鎾斁閫熷害 -->
+ <el-select
+ v-if="showPlaybackRate"
+ v-model="playbackRate"
+ size="mini"
+ class="playback-rate"
+ @change="changePlaybackRate"
+ >
+ <el-option
+ v-for="rate in playbackRates"
+ :key="rate"
+ :label="`${rate}x`"
+ :value="rate"
+ ></el-option>
+ </el-select>
+
+ <!-- 涓嬭浇鎸夐挳 -->
+ <el-button
+ v-if="showDownload"
+ type="text"
+ icon="el-icon-download"
+ class="download-btn"
+ @click="downloadAudio"
+ title="涓嬭浇闊抽"
+ ></el-button>
+
+ <!-- 鏇村鍔熻兘鎸夐挳 -->
+ <el-dropdown
+ v-if="showMoreOptions"
+ trigger="click"
+ class="more-options"
+ >
+ <el-button type="text" icon="el-icon-more" class="more-btn"></el-button>
+ <el-dropdown-menu slot="dropdown">
+ <el-dropdown-item @click.native="loopAudio = !loopAudio">
+ <i :class="loopAudio ? 'el-icon-refresh' : 'el-icon-refresh-left'"></i>
+ {{ loopAudio ? '鍏抽棴寰幆' : '寮�鍚惊鐜�' }}
+ </el-dropdown-item>
+ <el-dropdown-item @click.native="resetAudio">
+ <i class="el-icon-refresh-right"></i>
+ 閲嶇疆
+ </el-dropdown-item>
+ <el-dropdown-item v-if="showDetails" @click.native="showAudioInfo">
+ <i class="el-icon-info"></i>
+ 闊抽淇℃伅
+ </el-dropdown-item>
+ </el-dropdown-menu>
+ </el-dropdown>
+ </div>
+ </div>
+
+ <!-- 闊抽淇℃伅瀵硅瘽妗� -->
+ <el-dialog
+ v-if="showDetailsDialog"
+ title="闊抽淇℃伅"
+ :visible.sync="showDetailsDialog"
+ width="400px"
+ >
+ <div class="audio-info">
+ <div class="info-item">
+ <span class="label">鏂囦欢澶у皬锛�</span>
+ <span class="value">{{ fileSize }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">闊抽鏃堕暱锛�</span>
+ <span class="value">{{ formatTime(duration) }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">鏂囦欢鏍煎紡锛�</span>
+ <span class="value">{{ audioFormat }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">闊抽鍦板潃锛�</span>
+ <a :href="audioSource" target="_blank" class="audio-url">{{ truncateUrl(audioSource) }}</a>
+ </div>
+ </div>
+ </el-dialog>
+
+ <!-- 绠�鏄撴挱鏀惧櫒锛堜粎鏄剧ず鎾斁鎸夐挳锛� -->
+ <div v-else class="simple-player">
+ <el-button
+ v-if="!isPlaying"
+ type="text"
+ icon="el-icon-video-play"
+ size="small"
+ class="simple-play-btn"
+ @click="playAudio"
+ :loading="loading"
+ >
+ 鎾斁褰曢煶
+ </el-button>
+ <el-button
+ v-else
+ type="text"
+ icon="el-icon-video-pause"
+ size="small"
+ class="simple-pause-btn"
+ @click="pauseAudio"
+ >
+ 鏆傚仠鎾斁
+ </el-button>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'AudioPlayer',
+ props: {
+ // 闊抽婧愬湴鍧�
+ audioSource: {
+ type: String,
+ default: ''
+ },
+
+ // 鏄惁鏄剧ず瀹屾暣鎾斁鍣�
+ showDefaultPlayer: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず闊抽噺鎺у埗
+ showVolumeControl: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず鎾斁閫熷害鎺у埗
+ showPlaybackRate: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず涓嬭浇鎸夐挳
+ showDownload: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず鏇村閫夐」
+ showMoreOptions: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず闊抽淇℃伅
+ showDetails: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鍒濆闊抽噺锛�0-100锛�
+ initialVolume: {
+ type: Number,
+ default: 80,
+ validator: (value) => value >= 0 && value <= 100
+ },
+
+ // 鍒濆鎾斁閫熷害
+ initialPlaybackRate: {
+ type: Number,
+ default: 1.0
+ },
+
+ // 鑷姩鎾斁
+ autoplay: {
+ type: Boolean,
+ default: false
+ },
+
+ // 寰幆鎾斁
+ loop: {
+ type: Boolean,
+ default: false
+ }
+ },
+
+ data() {
+ return {
+ // 鎾斁鐘舵��
+ isPlaying: false,
+ isLoading: false,
+ loading: false,
+ error: false,
+
+ // 鏃堕棿鐩稿叧
+ currentTime: 0,
+ duration: 0,
+ buffered: [],
+
+ // 闊抽噺
+ volume: this.initialVolume,
+ isMuted: false,
+
+ // 鎾斁閫熷害
+ playbackRate: this.initialPlaybackRate,
+ playbackRates: [0.5, 0.75, 1.0, 1.25, 1.5, 2.0],
+
+ // 寰幆鎾斁
+ loopAudio: this.loop,
+
+ // 杩涘害鏉℃偓鍋�
+ hoverTime: 0,
+ hoverPercent: 0,
+ showHoverPreview: false,
+
+ // 闊抽淇℃伅
+ showDetailsDialog: false,
+ fileSize: '鏈煡',
+ audioFormat: '鏈煡',
+
+ // 鐩戝惉鍣ㄥ紩鐢�
+ resizeObserver: null
+ };
+ },
+
+ computed: {
+ // 鎾斁杩涘害鐧惧垎姣�
+ progressPercent() {
+ if (this.duration <= 0) return 0;
+ return (this.currentTime / this.duration) * 100;
+ },
+
+ // 缂撳啿杩涘害鐧惧垎姣�
+ bufferedPercent() {
+ if (this.duration <= 0) return 0;
+ if (this.buffered.length === 0) return 0;
+
+ const bufferedEnd = this.buffered.end(this.buffered.length - 1);
+ return (bufferedEnd / this.duration) * 100;
+ },
+
+ // 闊抽噺鍥炬爣
+ volumeIcon() {
+ if (this.isMuted || this.volume === 0) {
+ return 'el-icon-turn-off-microphone';
+ } else if (this.volume <= 30) {
+ return 'el-icon-microphone';
+ } else if (this.volume <= 70) {
+ return 'el-icon-microphone';
+ } else {
+ return 'el-icon-microphone';
+ }
+ }
+ },
+
+ watch: {
+ // 鐩戝惉闊抽婧愬彉鍖�
+ audioSource(newSource) {
+ if (newSource) {
+ this.resetAudio();
+ this.loadAudio();
+ }
+ },
+
+ // 鐩戝惉鑷姩鎾斁
+ autoplay(newVal) {
+ if (newVal && this.audioSource) {
+ this.playAudio();
+ }
+ },
+
+ // 鐩戝惉寰幆鎾斁
+ loopAudio(newVal) {
+ this.$emit('loop-change', newVal);
+ }
+ },
+
+ mounted() {
+ if (this.audioSource) {
+ this.loadAudio();
+ }
+
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ this.resizeObserver = new ResizeObserver(() => {
+ this.updateBuffered();
+ });
+
+ if (this.$refs.audioElement) {
+ this.resizeObserver.observe(this.$refs.audioElement);
+ }
+ },
+
+ beforeDestroy() {
+ if (this.resizeObserver) {
+ this.resizeObserver.disconnect();
+ }
+
+ // 鍋滄闊抽鎾斁
+ this.pauseAudio();
+ },
+
+ methods: {
+ // 鍔犺浇闊抽
+ async loadAudio() {
+ this.loading = true;
+ this.error = false;
+
+ try {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ // 璁剧疆闊抽噺
+ audio.volume = this.volume / 100;
+ audio.playbackRate = this.playbackRate;
+ audio.loop = this.loopAudio;
+
+ // 灏濊瘯鑾峰彇鏂囦欢淇℃伅
+ this.getAudioInfo();
+
+ // 濡傛灉璁剧疆浜嗚嚜鍔ㄦ挱鏀撅紝寮�濮嬫挱鏀�
+ if (this.autoplay) {
+ await this.playAudio();
+ }
+ } catch (error) {
+ console.error('鍔犺浇闊抽澶辫触:', error);
+ this.error = true;
+ this.$emit('error', error);
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 鎾斁闊抽
+ async playAudio() {
+ try {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ await audio.play();
+ this.isPlaying = true;
+ this.$emit('play');
+ } catch (error) {
+ console.error('鎾斁澶辫触:', error);
+ this.error = true;
+ this.isPlaying = false;
+ this.$emit('error', error);
+
+ // 濡傛灉鏄敤鎴蜂氦浜掑紩璧风殑閿欒锛屾彁绀虹敤鎴�
+ if (error.name === 'NotAllowedError') {
+ this.$message.warning('璇锋墜鍔ㄧ偣鍑绘挱鏀炬寜閽紑濮嬫挱鏀�');
+ }
+ }
+ },
+
+ // 鏆傚仠闊抽
+ pauseAudio() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.pause();
+ this.isPlaying = false;
+ this.$emit('pause');
+ },
+
+ // 璺宠浆鍒版寚瀹氭椂闂�
+ seekAudio(event) {
+ const audio = this.$refs.audioElement;
+ if (!audio || this.duration <= 0) return;
+
+ const progressContainer = event.currentTarget;
+ const rect = progressContainer.getBoundingClientRect();
+ const x = event.clientX - rect.left;
+ const width = rect.width;
+
+ const percent = Math.max(0, Math.min(1, x / width));
+ const time = percent * this.duration;
+
+ audio.currentTime = time;
+ this.currentTime = time;
+ this.$emit('seek', time);
+ },
+
+ // 鏇存柊鎮仠鏃堕棿
+ updateHoverTime(event) {
+ const progressContainer = event.currentTarget;
+ const rect = progressContainer.getBoundingClientRect();
+ const x = event.clientX - rect.left;
+ const width = rect.width;
+
+ const percent = Math.max(0, Math.min(1, x / width));
+ this.hoverPercent = percent * 100;
+ this.hoverTime = percent * this.duration;
+ this.showHoverPreview = true;
+ },
+
+ // 闅愯棌鎮仠棰勮
+ hideHoverPreview() {
+ this.showHoverPreview = false;
+ },
+
+ // 鏇存柊鏃堕棿
+ updateTime() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.currentTime = audio.currentTime;
+ this.$emit('timeupdate', this.currentTime);
+ },
+
+ // 鏇存柊鎬绘椂闀�
+ updateDuration() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.duration = audio.duration;
+ this.updateBuffered();
+ this.$emit('loadedmetadata', this.duration);
+ },
+
+ // 鏇存柊缂撳啿鏁版嵁
+ updateBuffered() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.buffered = audio.buffered;
+ },
+
+ // 澶勭悊鎾斁
+ handlePlay() {
+ this.isPlaying = true;
+ this.$emit('play');
+ },
+
+ // 澶勭悊鏆傚仠
+ handlePause() {
+ this.isPlaying = false;
+ this.$emit('pause');
+ },
+
+ // 澶勭悊鎾斁缁撴潫
+ handleEnded() {
+ this.isPlaying = false;
+ this.currentTime = 0;
+ this.$emit('ended');
+ },
+
+ // 澶勭悊閿欒
+ handleError(event) {
+ console.error('闊抽鎾斁閿欒:', event);
+ this.error = true;
+ this.isPlaying = false;
+ this.$emit('error', event);
+ },
+
+ // 鏀瑰彉闊抽噺
+ changeVolume(value) {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.volume = value / 100;
+ this.volume = value;
+ this.isMuted = value === 0;
+ this.$emit('volume-change', value);
+ },
+
+ // 闈欓煶/鍙栨秷闈欓煶
+ toggleMute() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.isMuted = !this.isMuted;
+ audio.muted = this.isMuted;
+ this.$emit('mute-change', this.isMuted);
+ },
+
+ // 鏀瑰彉鎾斁閫熷害
+ changePlaybackRate(rate) {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.playbackRate = rate;
+ this.playbackRate = rate;
+ this.$emit('playbackrate-change', rate);
+ },
+
+ // 閲嶇疆闊抽
+ resetAudio() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.currentTime = 0;
+ this.currentTime = 0;
+ this.pauseAudio();
+ this.$emit('reset');
+ },
+
+ // 涓嬭浇闊抽
+ downloadAudio() {
+ if (!this.audioSource) {
+ this.$message.warning('闊抽鍦板潃鏃犳晥');
+ return;
+ }
+
+ const link = document.createElement('a');
+ link.href = this.audioSource;
+ link.download = this.getFileNameFromUrl(this.audioSource);
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+
+ this.$emit('download');
+ },
+
+ // 鏄剧ず闊抽淇℃伅
+ async showAudioInfo() {
+ this.showDetailsDialog = true;
+ await this.getAudioInfo();
+ },
+
+ // 鑾峰彇闊抽淇℃伅
+ async getAudioInfo() {
+ if (!this.audioSource) return;
+
+ try {
+ // 鑾峰彇鏂囦欢澶у皬
+ const response = await fetch(this.audioSource, { method: 'HEAD' });
+ const contentLength = response.headers.get('content-length');
+
+ if (contentLength) {
+ this.fileSize = this.formatFileSize(contentLength);
+ }
+
+ // 鑾峰彇鏂囦欢鏍煎紡
+ const url = this.audioSource.toLowerCase();
+ if (url.endsWith('.mp3')) this.audioFormat = 'MP3';
+ else if (url.endsWith('.wav')) this.audioFormat = 'WAV';
+ else if (url.endsWith('.ogg')) this.audioFormat = 'OGG';
+ else if (url.endsWith('.m4a')) this.audioFormat = 'M4A';
+ else if (url.endsWith('.aac')) this.audioFormat = 'AAC';
+ else this.audioFormat = '鏈煡鏍煎紡';
+
+ } catch (error) {
+ console.error('鑾峰彇闊抽淇℃伅澶辫触:', error);
+ this.fileSize = '鏈煡';
+ this.audioFormat = '鏈煡';
+ }
+ },
+
+ // 鏍煎紡鍖栨椂闂�
+ formatTime(time) {
+ if (isNaN(time) || time < 0) return '00:00';
+
+ const hours = Math.floor(time / 3600);
+ const minutes = Math.floor((time % 3600) / 60);
+ const seconds = Math.floor(time % 60);
+
+ if (hours > 0) {
+ return `${hours.toString().padStart(2, '0')}:${minutes
+ .toString()
+ .padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
+ } else {
+ return `${minutes.toString().padStart(2, '0')}:${seconds
+ .toString()
+ .padStart(2, '0')}`;
+ }
+ },
+
+ // 鏍煎紡鍖栨枃浠跺ぇ灏�
+ formatFileSize(bytes) {
+ if (bytes === 0) return '0 B';
+
+ const k = 1024;
+ const sizes = ['B', 'KB', 'MB', 'GB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+ },
+
+ // 鎴柇URL鏄剧ず
+ truncateUrl(url, maxLength = 40) {
+ if (!url) return '';
+ if (url.length <= maxLength) return url;
+
+ const start = url.substring(0, maxLength / 2 - 3);
+ const end = url.substring(url.length - maxLength / 2 + 3);
+ return start + '...' + end;
+ },
+
+ // 浠嶶RL鑾峰彇鏂囦欢鍚�
+ getFileNameFromUrl(url) {
+ if (!url) return 'audio';
+
+ const fileName = url.split('/').pop();
+ return fileName || 'audio';
+ }
+ }
+};
+</script>
+
+<style lang="scss" scoped>
+.audio-player {
+ width: 100%;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+
+ .audio-container {
+ background: #fff;
+ border-radius: 8px;
+ padding: 12px 16px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border: 1px solid #ebeef5;
+
+ .audio-controls {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+
+ .play-btn,
+ .pause-btn {
+ width: 36px;
+ height: 36px;
+ padding: 0;
+ font-size: 20px;
+ color: #409EFF;
+
+ &:hover {
+ color: #66b1ff;
+ }
+
+ &:active {
+ color: #3a8ee6;
+ }
+ }
+
+ .progress-container {
+ flex: 1;
+ height: 36px;
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+
+ .progress-background {
+ position: relative;
+ width: 100%;
+ height: 6px;
+ background: #e4e7ed;
+ border-radius: 3px;
+ overflow: visible;
+
+ .buffered-progress {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background: #c0c4cc;
+ border-radius: 3px;
+ transition: width 0.2s ease;
+ }
+
+ .played-progress {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background: #409EFF;
+ border-radius: 3px;
+ transition: width 0.2s ease;
+ z-index: 2;
+ }
+
+ .hover-preview {
+ position: absolute;
+ top: -30px;
+ width: 1px;
+ height: 20px;
+ background: #909399;
+ transform: translateX(-50%);
+ z-index: 3;
+ pointer-events: none;
+
+ .hover-time {
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ background: rgba(0, 0, 0, 0.8);
+ color: white;
+ padding: 2px 6px;
+ border-radius: 3px;
+ font-size: 12px;
+ white-space: nowrap;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 0;
+ height: 0;
+ border-left: 4px solid transparent;
+ border-right: 4px solid transparent;
+ border-top: 4px solid rgba(0, 0, 0, 0.8);
+ }
+ }
+
+ .playhead {
+ position: absolute;
+ top: 50%;
+ width: 12px;
+ height: 12px;
+ background: #fff;
+ border: 2px solid #409EFF;
+ border-radius: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 4;
+ cursor: pointer;
+ transition: all 0.2s ease;
+
+ &:hover {
+ transform: translate(-50%, -50%) scale(1.2);
+ box-shadow: 0 0 8px rgba(64, 158, 255, 0.5);
+ }
+ }
+ }
+
+ &:hover {
+ .progress-background {
+ height: 8px;
+
+ .playhead {
+ transform: translate(-50%, -50%) scale(1.1);
+ }
+ }
+ }
+ }
+
+ .time-display {
+ min-width: 100px;
+ font-size: 12px;
+ color: #606266;
+ display: flex;
+ align-items: center;
+ gap: 2px;
+
+ .current-time {
+ color: #303133;
+ font-weight: 500;
+ }
+
+ .time-separator {
+ opacity: 0.6;
+ }
+
+ .duration {
+ opacity: 0.8;
+ }
+ }
+
+ .volume-control {
+ .volume-btn {
+ padding: 0;
+ width: 24px;
+ height: 24px;
+ font-size: 16px;
+ color: #606266;
+
+ &:hover {
+ color: #409EFF;
+ }
+ }
+ }
+
+ .playback-rate {
+ width: 60px;
+
+ ::v-deep .el-input__inner {
+ height: 24px;
+ line-height: 24px;
+ padding: 0 5px;
+ font-size: 12px;
+ }
+ }
+
+ .download-btn,
+ .more-btn {
+ padding: 0;
+ width: 24px;
+ height: 24px;
+ font-size: 16px;
+ color: #606266;
+
+ &:hover {
+ color: #409EFF;
+ }
+ }
+ }
+ }
+
+ .simple-player {
+ .simple-play-btn,
+ .simple-pause-btn {
+ padding: 4px 8px;
+ font-size: 12px;
+ color: #409EFF;
+
+ &:hover {
+ color: #66b1ff;
+ }
+ }
+ }
+
+ .audio-info {
+ .info-item {
+ margin-bottom: 12px;
+ display: flex;
+
+ .label {
+ width: 80px;
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .value {
+ flex: 1;
+ color: #606266;
+ }
+
+ .audio-url {
+ color: #409EFF;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+}
+
+// 闊抽噺寮圭獥鏍峰紡
+::v-deep .volume-popover {
+ padding: 10px;
+ min-width: 40px;
+
+ .volume-slider-container {
+ height: 100px;
+ display: flex;
+ justify-content: center;
+
+ .el-slider {
+ height: 100%;
+
+ .el-slider__runway {
+ background: #e4e7ed;
+ }
+
+ .el-slider__bar {
+ background: #409EFF;
+ }
+
+ .el-slider__button {
+ border-color: #409EFF;
+ width: 12px;
+ height: 12px;
+ }
+ }
+ }
+}
+</style>
--
Gitblit v1.9.3