|
@@ -79,6 +79,10 @@
|
|
|
|
|
|
|
|
<!-- 底部操作 -->
|
|
<!-- 底部操作 -->
|
|
|
<view class="bottom-actions">
|
|
<view class="bottom-actions">
|
|
|
|
|
+ <button class="action-btn" @click="showTimerPicker = true">
|
|
|
|
|
+ <text class="action-icon">⏰</text>
|
|
|
|
|
+ <text class="action-text">{{ timerRemaining > 0 ? formatTimer(timerRemaining) : '定时' }}</text>
|
|
|
|
|
+ </button>
|
|
|
<button class="action-btn" @click="handleDownload">
|
|
<button class="action-btn" @click="handleDownload">
|
|
|
<text class="action-icon">⬇</text>
|
|
<text class="action-icon">⬇</text>
|
|
|
<text class="action-text">下载</text>
|
|
<text class="action-text">下载</text>
|
|
@@ -89,6 +93,24 @@
|
|
|
</button>
|
|
</button>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
|
|
+ <!-- 定时关闭选择器 -->
|
|
|
|
|
+ <view v-if="showTimerPicker" class="rate-picker" @click="showTimerPicker = false">
|
|
|
|
|
+ <view class="rate-content" @click.stop>
|
|
|
|
|
+ <text class="rate-title">定时关闭</text>
|
|
|
|
|
+ <view class="rate-options">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="option in timerOptions"
|
|
|
|
|
+ :key="option.value"
|
|
|
|
|
+ class="rate-item"
|
|
|
|
|
+ :class="{ active: timerDuration === option.value }"
|
|
|
|
|
+ @click="handleSetTimer(option.value)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <text>{{ option.label }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
<!-- 播放速度选择器 -->
|
|
<!-- 播放速度选择器 -->
|
|
|
<view v-if="showRatePicker" class="rate-picker" @click="showRatePicker = false">
|
|
<view v-if="showRatePicker" class="rate-picker" @click="showRatePicker = false">
|
|
|
<view class="rate-content" @click.stop>
|
|
<view class="rate-content" @click.stop>
|
|
@@ -122,9 +144,22 @@ const audioStore = useAudioStore();
|
|
|
const audioId = ref('');
|
|
const audioId = ref('');
|
|
|
const audio = ref<AudioItem | null>(null);
|
|
const audio = ref<AudioItem | null>(null);
|
|
|
const showRatePicker = ref(false);
|
|
const showRatePicker = ref(false);
|
|
|
|
|
+const showTimerPicker = ref(false);
|
|
|
const savedProgress = ref(0); // 保存的历史进度
|
|
const savedProgress = ref(0); // 保存的历史进度
|
|
|
const showResumePrompt = ref(false); // 显示继续播放提示
|
|
const showResumePrompt = ref(false); // 显示继续播放提示
|
|
|
|
|
|
|
|
|
|
+// 定时关闭状态
|
|
|
|
|
+const timerDuration = ref(0); // 定时时长(秒),0表示未设置
|
|
|
|
|
+const timerRemaining = ref(0); // 剩余时间(秒)
|
|
|
|
|
+const timerOptions = [
|
|
|
|
|
+ { label: '15分钟', value: 15 * 60 },
|
|
|
|
|
+ { label: '30分钟', value: 30 * 60 },
|
|
|
|
|
+ { label: '45分钟', value: 45 * 60 },
|
|
|
|
|
+ { label: '60分钟', value: 60 * 60 },
|
|
|
|
|
+ { label: '关闭定时', value: 0 },
|
|
|
|
|
+];
|
|
|
|
|
+let timerInterval: number | null = null;
|
|
|
|
|
+
|
|
|
// 从 store 获取状态
|
|
// 从 store 获取状态
|
|
|
const isPlaying = computed(() => audioStore.isPlaying);
|
|
const isPlaying = computed(() => audioStore.isPlaying);
|
|
|
const currentTime = computed(() => audioStore.currentTime);
|
|
const currentTime = computed(() => audioStore.currentTime);
|
|
@@ -178,6 +213,10 @@ onUnmounted(() => {
|
|
|
if (progressSaveTimer) {
|
|
if (progressSaveTimer) {
|
|
|
clearInterval(progressSaveTimer);
|
|
clearInterval(progressSaveTimer);
|
|
|
}
|
|
}
|
|
|
|
|
+ // 清除定时关闭
|
|
|
|
|
+ if (timerInterval) {
|
|
|
|
|
+ clearInterval(timerInterval);
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 监听播放进度变化
|
|
// 监听播放进度变化
|
|
@@ -326,6 +365,43 @@ function handleSetRate(rate: number) {
|
|
|
showRatePicker.value = false;
|
|
showRatePicker.value = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 设置定时关闭
|
|
|
|
|
+function handleSetTimer(seconds: number) {
|
|
|
|
|
+ timerDuration.value = seconds;
|
|
|
|
|
+ timerRemaining.value = seconds;
|
|
|
|
|
+ showTimerPicker.value = false;
|
|
|
|
|
+
|
|
|
|
|
+ // 清除之前的定时器
|
|
|
|
|
+ if (timerInterval) {
|
|
|
|
|
+ clearInterval(timerInterval);
|
|
|
|
|
+ timerInterval = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (seconds > 0) {
|
|
|
|
|
+ // 启动倒计时
|
|
|
|
|
+ timerInterval = setInterval(() => {
|
|
|
|
|
+ if (timerRemaining.value > 0) {
|
|
|
|
|
+ timerRemaining.value--;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 时间到,暂停播放
|
|
|
|
|
+ audioStore.pause();
|
|
|
|
|
+ if (timerInterval) {
|
|
|
|
|
+ clearInterval(timerInterval);
|
|
|
|
|
+ timerInterval = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ uni.showToast({ title: '定时关闭,播放已暂停', icon: 'none' });
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 1000) as unknown as number;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 格式化定时器显示
|
|
|
|
|
+function formatTimer(seconds: number): string {
|
|
|
|
|
+ const mins = Math.floor(seconds / 60);
|
|
|
|
|
+ const secs = seconds % 60;
|
|
|
|
|
+ return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 切换收藏
|
|
// 切换收藏
|
|
|
async function toggleFavorite() {
|
|
async function toggleFavorite() {
|
|
|
if (!audio.value) return;
|
|
if (!audio.value) return;
|