diff --git a/src/audioManager.js b/src/audioManager.js
index 33ba885..f8608a5 100644
--- a/src/audioManager.js
+++ b/src/audioManager.js
@@ -126,6 +126,8 @@ class AudioManager {
this.readyMap = new Map();
// 新增:首轮失败的音频集合与重试阶段标识
this.failedLoadKeys = new Set();
+ // 加载代数,用于 reloadAll 时作废旧的加载循环
+ this.loadGeneration = 0;
this.initAudios();
}
@@ -141,9 +143,15 @@ class AudioManager {
this.currentLoadingIndex = 0;
this.failedLoadKeys.clear();
+ // 增加代数,使得旧的加载循环失效
+ this.loadGeneration = (this.loadGeneration || 0) + 1;
+ const currentGen = this.loadGeneration;
+
this.loadingPromise = new Promise((resolve) => {
const finalize = () => {
+ if (currentGen !== this.loadGeneration) return;
const runRounds = (round) => {
+ if (currentGen !== this.loadGeneration) return;
// 达到最大轮次或没有失败项,收尾
if (this.failedLoadKeys.size === 0 || round > this.maxRetryRounds) {
this.isLoading = false;
@@ -155,30 +163,40 @@ class AudioManager {
this.failedLoadKeys.clear();
debugLog(`开始第 ${round} 轮串行加载,共 ${retryKeys.length} 个`);
- this.loadKeysSequentially(retryKeys, () => {
- // 如仍有失败项,继续下一轮;否则结束
- if (this.failedLoadKeys.size > 0 && round < this.maxRetryRounds) {
- setTimeout(() => runRounds(round + 1), this.retryRoundIntervalMs);
- } else {
- this.isLoading = false;
- resolve();
- }
- });
+ this.loadKeysSequentially(
+ retryKeys,
+ () => {
+ if (currentGen !== this.loadGeneration) return;
+ // 如仍有失败项,继续下一轮;否则结束
+ if (this.failedLoadKeys.size > 0 && round < this.maxRetryRounds) {
+ setTimeout(
+ () => runRounds(round + 1),
+ this.retryRoundIntervalMs
+ );
+ } else {
+ this.isLoading = false;
+ resolve();
+ }
+ },
+ currentGen
+ );
};
// 启动第 1 轮重试(如有失败项)
runRounds(1);
};
- this.loadNextAudio(finalize);
+ this.loadNextAudio(finalize, currentGen);
});
return this.loadingPromise;
}
// 按自定义列表串行加载音频(避免并发过多)
- loadKeysSequentially(keys, onComplete) {
+ loadKeysSequentially(keys, onComplete, gen) {
+ if (gen !== undefined && gen !== this.loadGeneration) return;
let idx = 0;
const list = Array.from(keys);
const next = () => {
+ if (gen !== undefined && gen !== this.loadGeneration) return;
if (idx >= list.length) {
if (onComplete) onComplete();
return;
@@ -206,7 +224,8 @@ class AudioManager {
}
// 串行加载下一个音频(首轮)
- loadNextAudio(onComplete) {
+ loadNextAudio(onComplete, gen) {
+ if (gen !== undefined && gen !== this.loadGeneration) return;
if (this.currentLoadingIndex >= this.audioKeys.length) {
debugLog("首轮加载遍历完成", this.currentLoadingIndex);
if (onComplete) onComplete();
@@ -220,7 +239,7 @@ class AudioManager {
);
this.createAudio(key, () => {
setTimeout(() => {
- this.loadNextAudio(onComplete);
+ this.loadNextAudio(onComplete, gen);
}, 100);
});
}
@@ -530,6 +549,38 @@ class AudioManager {
}
return Number((loaded / total).toFixed(2));
}
+
+
+ // 手动重置并重新加载所有音频(用于卡住时恢复)
+ reloadAll() {
+ // 1. 停止所有播放
+ this.stopAll();
+
+ // 2. 销毁现有音频实例
+ for (const audio of this.audioMap.values()) {
+ try {
+ audio.destroy();
+ } catch (_) {}
+ }
+ this.audioMap.clear();
+
+ // 3. 重置状态
+ this.readyMap.clear();
+ this.failedLoadKeys.clear();
+ this.allowPlayMap.clear();
+ this.currentPlayingKey = null;
+ this.sequenceQueue = [];
+ this.sequenceIndex = 0;
+ this.isSequenceRunning = false;
+
+ // 4. 强制重置加载锁
+ this.isLoading = false;
+ this.loadingPromise = null;
+ this.currentLoadingIndex = 0;
+
+ // 5. 重新初始化 (initAudios 会自增 loadGeneration,从而终止之前的任何异步循环)
+ return this.initAudios();
+ }
}
// 导出单例
diff --git a/src/components/Container.vue b/src/components/Container.vue
index 698eb1a..0221d30 100644
--- a/src/components/Container.vue
+++ b/src/components/Container.vue
@@ -66,9 +66,7 @@ const checkAudioProgress = async () => {
if (audioInitProgress.value === 1) return resolve();
audioTimer.value = setInterval(() => {
const result = AudioManager.getLoadProgress();
- if (result > audioProgress.value) {
- audioProgress.value = result;
- }
+ audioProgress.value = result;
if (audioProgress.value === 1) {
setTimeout(() => {
audioInitProgress.value = 1;
@@ -227,7 +225,12 @@ const goCalibration = async () => {
mode="widthFix"
/>
- 资源加载中...
+
+
+ 若加载时间过长,请
+
@@ -321,11 +324,21 @@ const goCalibration = async () => {
width: 46rpx;
height: 26rpx;
}
-.audio-progress > view:nth-child(2) > text {
- width: 100%;
+.audio-progress > view:nth-child(3) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-top: 20rpx;
+}
+.audio-progress > view:nth-child(3) > text {
font-size: 22rpx;
color: #a2a2a2;
text-align: center;
- margin-top: 10rpx;
+ line-height: 32rpx;
+}
+.audio-progress > view:nth-child(3) > button {
+ font-size: 22rpx;
+ color: #ffe431;
+ line-height: 32rpx;
}
diff --git a/src/components/UserHeader.vue b/src/components/UserHeader.vue
index 7f50fa8..e9196f9 100644
--- a/src/components/UserHeader.vue
+++ b/src/components/UserHeader.vue
@@ -66,7 +66,7 @@ watch(
:onClick="toUserPage"
:size="42"
/>
-
+
{{ user.nickName }}
段位积分
-
text {
text-align: center;
+ word-break: keep-all;
+ width: 83px;
}
.rank-number {
display: block;