细节修改

This commit is contained in:
kron
2025-12-30 18:10:31 +08:00
parent 44913a6f2e
commit 910530748d
7 changed files with 270 additions and 72 deletions

View File

@@ -128,9 +128,42 @@ class AudioManager {
this.failedLoadKeys = new Set();
// 加载代数,用于 reloadAll 时作废旧的加载循环
this.loadGeneration = 0;
// 本地路径缓存 Map: { url: localPath }
this.localFileCache = uni.getStorageSync("audio_local_files") || {};
// 启动时自动清理过期的缓存文件URL 已不在 audioFils 中的文件)
this.cleanObsoleteCache();
this.initAudios();
}
// 清理不再使用的缓存文件
cleanObsoleteCache() {
const activeUrls = new Set(Object.values(audioFils));
const cachedUrls = Object.keys(this.localFileCache);
let hasChanges = false;
for (const url of cachedUrls) {
if (!activeUrls.has(url)) {
debugLog(`发现废弃音频缓存,正在清理: ${url}`);
const path = this.localFileCache[url];
// 移除物理文件
uni.removeSavedFile({
filePath: path,
complete: () => {
// 忽略移除结果,直接移除记录
},
});
// 移除记录
delete this.localFileCache[url];
hasChanges = true;
}
}
if (hasChanges) {
uni.setStorageSync("audio_local_files", this.localFileCache);
debugLog("废弃缓存清理完成");
}
}
// 初始化音频(两阶段:首轮串行加载全部,次轮仅串行加载失败项一次)
initAudios() {
if (this.isLoading) {
@@ -244,7 +277,7 @@ class AudioManager {
});
}
// 创建单个音频实例(统一在失败时记录,而非立即重试
// 创建单个音频实例(支持本地缓存
createAudio(key, callback) {
this.currentLoadingIndex++;
const src = audioFils[key];
@@ -287,7 +320,7 @@ class AudioManager {
clearTimeout(loadTimeout);
this.readyMap.set(key, true);
this.failedLoadKeys.delete(key);
debugLog(`音频 ${key} 已加载完成`, this.getLoadProgress());
// debugLog(`音频 ${key} 已加载完成`, this.getLoadProgress());
uni.$emit("audioLoaded", key);
const loadedAudioKeys = uni.getStorageSync("loadedAudioKeys") || {};
loadedAudioKeys[key] = true;
@@ -298,11 +331,20 @@ class AudioManager {
audio.onError((res) => {
clearTimeout(loadTimeout);
debugLog(`音频 ${key} 加载失败:`, res.errMsg);
// 如果是本地文件加载失败,可能是文件损坏,清除缓存以便下次重新下载
if (realSrc !== src && this.localFileCache[src] === realSrc) {
debugLog(`本地缓存失效,移除记录: ${key}`);
delete this.localFileCache[src];
uni.setStorageSync("audio_local_files", this.localFileCache);
// 移除文件
uni.removeSavedFile({ filePath: realSrc });
}
this.recordLoadFailure(key);
this.audioMap.delete(key);
audio.destroy();
if (this.readyMap.get(key)) {
this.readyMap.set(key, false);
// 这里不要去除,不然检查进度的时候由于没有重新加载而进度卡住,等播放失败的时候会重新加载
// this.readyMap.set(key, false);
} else {
if (callback) callback();
}
@@ -326,23 +368,72 @@ class AudioManager {
this.audioMap.set(key, audio);
};
// 统一先下载到本地再加载
uni.downloadFile({
url: src,
timeout: 20000,
success: (res) => {
// 成功必须有临时文件路径
if (res.tempFilePath) {
setupAudio(res.tempFilePath);
} else {
this.recordLoadFailure(key);
if (callback) callback();
}
},
fail: () => {
this.recordLoadFailure(key);
if (callback) callback();
},
// 检查是否有可用的本地缓存
this.checkLocalFile(src).then((localPath) => {
if (localPath) {
debugLog(`命中本地缓存: ${key}`);
setupAudio(localPath);
} else {
console.log("download");
// 下载并尝试保存
uni.downloadFile({
url: src,
timeout: 20000,
success: (res) => {
if (res.tempFilePath) {
// 尝试保存文件到本地存储(持久化)
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
const savedPath = saveRes.savedFilePath;
this.localFileCache[src] = savedPath;
uni.setStorageSync("audio_local_files", this.localFileCache);
debugLog(`音频已缓存到本地: ${key}`);
setupAudio(savedPath);
},
fail: (err) => {
debugLog(
`保存音频失败(可能空间不足),使用临时文件: ${key}`,
err
);
setupAudio(res.tempFilePath);
},
});
} else {
this.recordLoadFailure(key);
if (callback) callback();
}
},
fail: () => {
this.recordLoadFailure(key);
if (callback) callback();
},
});
}
});
}
// 检查本地文件是否有效
checkLocalFile(url) {
return new Promise((resolve) => {
const path = this.localFileCache[url];
if (!path) {
resolve(null);
return;
}
// 检查文件是否存在
uni.getFileSystemManager().getFileInfo({
filePath: path,
success: () => {
resolve(path);
},
fail: () => {
// 文件不存在,清理记录
delete this.localFileCache[url];
uni.setStorageSync("audio_local_files", this.localFileCache);
resolve(null);
},
});
});
}
@@ -550,9 +641,28 @@ class AudioManager {
return Number((loaded / total).toFixed(2));
}
// 清理本地音频缓存文件
clearCache() {
debugLog("开始清理本地音频缓存...");
const cache = uni.getStorageSync("audio_local_files") || {};
const paths = Object.values(cache);
for (const path of paths) {
uni.removeSavedFile({
filePath: path,
complete: (res) => {
// 无论成功失败都继续
},
});
}
uni.removeStorageSync("audio_local_files");
this.localFileCache = {};
debugLog("本地音频缓存清理完成");
}
// 手动重置并重新加载所有音频(用于卡住时恢复)
reloadAll() {
debugLog("执行 reloadAll: 重置所有状态并重新加载");
// 1. 停止所有播放
this.stopAll();
@@ -573,6 +683,10 @@ class AudioManager {
this.sequenceIndex = 0;
this.isSequenceRunning = false;
// 清理一下可能损坏的缓存(可选,如果用户因为缓存坏了卡住,这一步很有用)
// 这里选择不自动全清,而是依赖 onError 里的单点清除。如果需要彻底重置,可取消注释:
// this.clearCache();
// 4. 强制重置加载锁
this.isLoading = false;
this.loadingPromise = null;