|
@ -612,28 +612,142 @@ watch( |
|
|
four: { completed: false, result: null, error: null }, |
|
|
four: { completed: false, result: null, error: null }, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 音频预加载状态跟踪 |
|
|
|
|
|
const audioPreloadStatus = { |
|
|
|
|
|
one: { loaded: false, url: null }, |
|
|
|
|
|
two: { loaded: false, url: null }, |
|
|
|
|
|
three: { loaded: false, url: null }, |
|
|
|
|
|
four: { loaded: false, url: null } |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 音频播放队列管理 |
|
|
|
|
|
const audioQueue = ref([]); |
|
|
|
|
|
const isPlayingAudio = ref(false); |
|
|
|
|
|
|
|
|
|
|
|
// 播放音频队列 |
|
|
|
|
|
const playNextAudio = () => { |
|
|
|
|
|
if (audioQueue.value.length === 0 || isPlayingAudio.value) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
isPlayingAudio.value = true; |
|
|
|
|
|
const audioInfo = audioQueue.value.shift(); |
|
|
|
|
|
|
|
|
|
|
|
console.log(`开始播放${audioInfo.name}音频`); |
|
|
|
|
|
|
|
|
|
|
|
if (audioStore.nowSound) { |
|
|
|
|
|
audioStore.nowSound.stop(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const audio = new Howl({ |
|
|
|
|
|
src: [audioInfo.url], |
|
|
|
|
|
html5: true, |
|
|
|
|
|
format: ["mp3", "acc"], |
|
|
|
|
|
rate: 1.2, |
|
|
|
|
|
onplay: () => { |
|
|
|
|
|
audioStore.isPlaying = true; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
console.log(`${audioInfo.name}音频开始播放`); |
|
|
|
|
|
}, |
|
|
|
|
|
onend: () => { |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
console.log(`${audioInfo.name}音频播放完成`); |
|
|
|
|
|
// 播放下一个音频 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
}, |
|
|
|
|
|
onloaderror: (id, err) => { |
|
|
|
|
|
console.error(`${audioInfo.name}音频播放失败:`, err); |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
// 播放下一个音频 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
audioStore.nowSound = audio; |
|
|
|
|
|
audioStore.setAudioInstance(audio); |
|
|
|
|
|
audio.play(); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 添加音频到播放队列 |
|
|
|
|
|
const addToAudioQueue = (url, name) => { |
|
|
|
|
|
if (url && audioStore.isVoiceEnabled) { |
|
|
|
|
|
audioQueue.value.push({ url, name }); |
|
|
|
|
|
console.log(`音频${name}已添加到播放队列`); |
|
|
|
|
|
// 如果当前没有播放音频,立即开始播放 |
|
|
|
|
|
if (!isPlayingAudio.value) { |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 预加载音频函数 |
|
|
|
|
|
const preloadAudio = (url, apiKey) => { |
|
|
|
|
|
if (!url || !audioStore.isVoiceEnabled) { |
|
|
|
|
|
audioPreloadStatus[apiKey].loaded = true; |
|
|
|
|
|
return Promise.resolve(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve) => { |
|
|
|
|
|
const audio = new Howl({ |
|
|
|
|
|
src: [url], |
|
|
|
|
|
html5: true, |
|
|
|
|
|
format: ["mp3", "acc"], |
|
|
|
|
|
rate: 1.2, |
|
|
|
|
|
preload: true, |
|
|
|
|
|
onload: () => { |
|
|
|
|
|
console.log(`音频${apiKey}预加载完成:`, url); |
|
|
|
|
|
audioPreloadStatus[apiKey].loaded = true; |
|
|
|
|
|
audioPreloadStatus[apiKey].url = url; |
|
|
|
|
|
resolve(); |
|
|
|
|
|
}, |
|
|
|
|
|
onloaderror: (id, err) => { |
|
|
|
|
|
console.error(`音频${apiKey}预加载失败:`, err); |
|
|
|
|
|
audioPreloadStatus[apiKey].loaded = true; // 标记为已处理,避免阻塞 |
|
|
|
|
|
resolve(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 检查第一个接口是否可以开始输出(文本和音频都准备好) |
|
|
|
|
|
const canStartFirstOutput = () => { |
|
|
|
|
|
return apiStatus.one.completed && audioPreloadStatus.one.loaded; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// 检查并按顺序执行代码的函数 |
|
|
// 检查并按顺序执行代码的函数 |
|
|
const checkAndExecuteInOrder = () => { |
|
|
const checkAndExecuteInOrder = () => { |
|
|
// 检查OneAPI |
|
|
|
|
|
if (apiStatus.one.completed && !apiStatus.one.executed) { |
|
|
|
|
|
apiStatus.one.executed = true; |
|
|
|
|
|
if (apiStatus.one.result) { |
|
|
|
|
|
console.log("执行OneAPI代码:", apiStatus.one.result); |
|
|
|
|
|
// 在这里添加OneAPI成功后需要执行的代码 |
|
|
|
|
|
// 删除正在为您生成信息 |
|
|
|
|
|
chatStore.messages.pop(); |
|
|
|
|
|
// 添加报告头和时间 |
|
|
|
|
|
addTypingTask( |
|
|
|
|
|
{ |
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "title1", |
|
|
|
|
|
type: "title1", |
|
|
|
|
|
content: codeData.value.name + "全景作战报告", |
|
|
|
|
|
date: moment().format("MM/DD/YYYY"), |
|
|
|
|
|
}, |
|
|
|
|
|
"", |
|
|
|
|
|
50 |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
// 检查OneAPI - 只有当文本和音频都准备好时才开始输出 |
|
|
|
|
|
if (canStartFirstOutput() && !apiStatus.one.executed) { |
|
|
|
|
|
apiStatus.one.executed = true; |
|
|
|
|
|
if (apiStatus.one.result) { |
|
|
|
|
|
console.log("执行OneAPI代码(文本和音频同步开始):", apiStatus.one.result); |
|
|
|
|
|
|
|
|
|
|
|
// 将第一个音频添加到播放队列 |
|
|
|
|
|
if (audioPreloadStatus.one.url) { |
|
|
|
|
|
addToAudioQueue(audioPreloadStatus.one.url, "第一个"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 在这里添加OneAPI成功后需要执行的代码 |
|
|
|
|
|
// 删除正在为您生成信息 |
|
|
|
|
|
chatStore.messages.pop(); |
|
|
|
|
|
// 添加报告头和时间 |
|
|
|
|
|
addTypingTask( |
|
|
|
|
|
{ |
|
|
|
|
|
sender: "ai", |
|
|
|
|
|
class: "title1", |
|
|
|
|
|
type: "title1", |
|
|
|
|
|
content: codeData.value.name + "全景作战报告", |
|
|
|
|
|
date: moment().format("MM/DD/YYYY"), |
|
|
|
|
|
}, |
|
|
|
|
|
"", |
|
|
|
|
|
50 |
|
|
|
|
|
); |
|
|
// chatStore.messages.push({ |
|
|
// chatStore.messages.push({ |
|
|
// sender: "ai", |
|
|
// sender: "ai", |
|
|
// class: "title1", |
|
|
// class: "title1", |
|
@ -858,6 +972,12 @@ watch( |
|
|
apiStatus.two.executed = true; |
|
|
apiStatus.two.executed = true; |
|
|
if (apiStatus.two.result) { |
|
|
if (apiStatus.two.result) { |
|
|
console.log("执行TwoAPI代码:", apiStatus.two.result); |
|
|
console.log("执行TwoAPI代码:", apiStatus.two.result); |
|
|
|
|
|
|
|
|
|
|
|
// 将第二个音频添加到播放队列 |
|
|
|
|
|
if (audioPreloadStatus.two.url) { |
|
|
|
|
|
addToAudioQueue(audioPreloadStatus.two.url, "第二个"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 在这里添加TwoAPI成功后需要执行的代码 |
|
|
// 在这里添加TwoAPI成功后需要执行的代码 |
|
|
// 添加标题2 |
|
|
// 添加标题2 |
|
|
addTypingTask( |
|
|
addTypingTask( |
|
@ -930,6 +1050,12 @@ watch( |
|
|
apiStatus.three.executed = true; |
|
|
apiStatus.three.executed = true; |
|
|
if (apiStatus.three.result) { |
|
|
if (apiStatus.three.result) { |
|
|
console.log("执行ThreeAPI代码:", apiStatus.three.result); |
|
|
console.log("执行ThreeAPI代码:", apiStatus.three.result); |
|
|
|
|
|
|
|
|
|
|
|
// 将第三个音频添加到播放队列 |
|
|
|
|
|
if (audioPreloadStatus.three.url) { |
|
|
|
|
|
addToAudioQueue(audioPreloadStatus.three.url, "第三个"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 在这里添加ThreeAPI成功后需要执行的代码 |
|
|
// 在这里添加ThreeAPI成功后需要执行的代码 |
|
|
// 添加标题3-2 |
|
|
// 添加标题3-2 |
|
|
addTypingTask( |
|
|
addTypingTask( |
|
@ -1073,6 +1199,12 @@ watch( |
|
|
apiStatus.four.executed = true; |
|
|
apiStatus.four.executed = true; |
|
|
if (apiStatus.four.result) { |
|
|
if (apiStatus.four.result) { |
|
|
console.log("执行FourAPI代码:", apiStatus.four.result); |
|
|
console.log("执行FourAPI代码:", apiStatus.four.result); |
|
|
|
|
|
|
|
|
|
|
|
// 将第四个音频添加到播放队列 |
|
|
|
|
|
if (audioPreloadStatus.four.url) { |
|
|
|
|
|
addToAudioQueue(audioPreloadStatus.four.url, "第四个"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 在这里添加FourAPI成功后需要执行的代码 |
|
|
// 在这里添加FourAPI成功后需要执行的代码 |
|
|
// 添加标题3-4 |
|
|
// 添加标题3-4 |
|
|
addTypingTask( |
|
|
addTypingTask( |
|
@ -1177,47 +1309,34 @@ watch( |
|
|
apiStatus.four.completed && |
|
|
apiStatus.four.completed && |
|
|
apiStatus.four.executed |
|
|
apiStatus.four.executed |
|
|
) { |
|
|
) { |
|
|
console.log("所有API已完成,开始收集音频URL"); |
|
|
|
|
|
// 收集所有音频URL |
|
|
|
|
|
|
|
|
console.log("所有API已完成,开始收集预加载的音频URL"); |
|
|
|
|
|
// 收集所有预加载的音频URL |
|
|
const audioUrls = []; |
|
|
const audioUrls = []; |
|
|
console.log("API返回结果检查:"); |
|
|
|
|
|
console.log("result21:", result21); |
|
|
|
|
|
console.log("result22:", result22); |
|
|
|
|
|
console.log("result23:", result23); |
|
|
|
|
|
console.log("result24:", result24); |
|
|
|
|
|
|
|
|
console.log("预加载音频状态检查:"); |
|
|
|
|
|
console.log("audioPreloadStatus:", audioPreloadStatus); |
|
|
|
|
|
|
|
|
if (result21?.data?.url) { |
|
|
|
|
|
console.log("添加result21音频URL:", result21.data.url); |
|
|
|
|
|
audioUrls.push(result21.data.url.trim()); |
|
|
|
|
|
|
|
|
if (audioPreloadStatus.one.url) { |
|
|
|
|
|
console.log("添加预加载音频URL one:", audioPreloadStatus.one.url); |
|
|
|
|
|
audioUrls.push(audioPreloadStatus.one.url); |
|
|
} |
|
|
} |
|
|
if (result22?.data?.url) { |
|
|
|
|
|
console.log("添加result22音频URL:", result22.data.url); |
|
|
|
|
|
audioUrls.push(result22.data.url.trim()); |
|
|
|
|
|
|
|
|
if (audioPreloadStatus.two.url) { |
|
|
|
|
|
console.log("添加预加载音频URL two:", audioPreloadStatus.two.url); |
|
|
|
|
|
audioUrls.push(audioPreloadStatus.two.url); |
|
|
} |
|
|
} |
|
|
if (result23?.data?.url) { |
|
|
|
|
|
console.log("添加result23音频URL:", result23.data.url); |
|
|
|
|
|
audioUrls.push(result23.data.url.trim()); |
|
|
|
|
|
|
|
|
if (audioPreloadStatus.three.url) { |
|
|
|
|
|
console.log("添加预加载音频URL three:", audioPreloadStatus.three.url); |
|
|
|
|
|
audioUrls.push(audioPreloadStatus.three.url); |
|
|
} |
|
|
} |
|
|
if (result24?.data?.url) { |
|
|
|
|
|
console.log("添加result24音频URL:", result24.data.url); |
|
|
|
|
|
audioUrls.push(result24.data.url.trim()); |
|
|
|
|
|
|
|
|
if (audioPreloadStatus.four.url) { |
|
|
|
|
|
console.log("添加预加载音频URL four:", audioPreloadStatus.four.url); |
|
|
|
|
|
audioUrls.push(audioPreloadStatus.four.url); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
console.log("收集到的音频URLs:", audioUrls); |
|
|
|
|
|
|
|
|
console.log("收集到的预加载音频URLs:", audioUrls); |
|
|
console.log("语音是否启用:", audioStore.isVoiceEnabled); |
|
|
console.log("语音是否启用:", audioStore.isVoiceEnabled); |
|
|
|
|
|
|
|
|
// 开始轮流播放音频 |
|
|
|
|
|
if (audioUrls.length > 0 && audioStore.isVoiceEnabled) { |
|
|
|
|
|
console.log("开始播放音频序列"); |
|
|
|
|
|
playAudioSequence(audioUrls); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log( |
|
|
|
|
|
"跳过音频播放 - audioUrls长度:", |
|
|
|
|
|
audioUrls.length, |
|
|
|
|
|
"语音启用状态:", |
|
|
|
|
|
audioStore.isVoiceEnabled |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 音频播放逻辑已移至各个接口的执行代码中 |
|
|
|
|
|
console.log("所有接口执行完成,音频已在各接口中单独播放"); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -1229,12 +1348,20 @@ watch( |
|
|
apiStatus.one.completed = true; |
|
|
apiStatus.one.completed = true; |
|
|
apiStatus.one.result = result21; |
|
|
apiStatus.one.result = result21; |
|
|
|
|
|
|
|
|
|
|
|
// 预加载第一个接口的音频 |
|
|
|
|
|
if (result21?.data?.url) { |
|
|
|
|
|
await preloadAudio(result21.data.url.trim(), 'one'); |
|
|
|
|
|
} else { |
|
|
|
|
|
audioPreloadStatus.one.loaded = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 检查是否可以执行 |
|
|
// 检查是否可以执行 |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("OneAPI失败:", error); |
|
|
console.error("OneAPI失败:", error); |
|
|
apiStatus.one.completed = true; |
|
|
apiStatus.one.completed = true; |
|
|
apiStatus.one.error = error; |
|
|
apiStatus.one.error = error; |
|
|
|
|
|
audioPreloadStatus.one.loaded = true; // 失败时也标记为已处理 |
|
|
// 即使失败也要检查后续执行 |
|
|
// 即使失败也要检查后续执行 |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} |
|
|
} |
|
@ -1248,12 +1375,20 @@ watch( |
|
|
apiStatus.two.completed = true; |
|
|
apiStatus.two.completed = true; |
|
|
apiStatus.two.result = result22; |
|
|
apiStatus.two.result = result22; |
|
|
|
|
|
|
|
|
|
|
|
// 预加载第二个接口的音频 |
|
|
|
|
|
if (result22?.data?.url) { |
|
|
|
|
|
await preloadAudio(result22.data.url.trim(), 'two'); |
|
|
|
|
|
} else { |
|
|
|
|
|
audioPreloadStatus.two.loaded = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 检查是否可以执行 |
|
|
// 检查是否可以执行 |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("TwoAPI失败:", error); |
|
|
console.error("TwoAPI失败:", error); |
|
|
apiStatus.two.completed = true; |
|
|
apiStatus.two.completed = true; |
|
|
apiStatus.two.error = error; |
|
|
apiStatus.two.error = error; |
|
|
|
|
|
audioPreloadStatus.two.loaded = true; |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
@ -1266,12 +1401,20 @@ watch( |
|
|
apiStatus.three.completed = true; |
|
|
apiStatus.three.completed = true; |
|
|
apiStatus.three.result = result23; |
|
|
apiStatus.three.result = result23; |
|
|
|
|
|
|
|
|
|
|
|
// 预加载第三个接口的音频 |
|
|
|
|
|
if (result23?.data?.url) { |
|
|
|
|
|
await preloadAudio(result23.data.url.trim(), 'three'); |
|
|
|
|
|
} else { |
|
|
|
|
|
audioPreloadStatus.three.loaded = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 检查是否可以执行 |
|
|
// 检查是否可以执行 |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("ThreeAPI失败:", error); |
|
|
console.error("ThreeAPI失败:", error); |
|
|
apiStatus.three.completed = true; |
|
|
apiStatus.three.completed = true; |
|
|
apiStatus.three.error = error; |
|
|
apiStatus.three.error = error; |
|
|
|
|
|
audioPreloadStatus.three.loaded = true; |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
@ -1284,12 +1427,20 @@ watch( |
|
|
apiStatus.four.completed = true; |
|
|
apiStatus.four.completed = true; |
|
|
apiStatus.four.result = result24; |
|
|
apiStatus.four.result = result24; |
|
|
|
|
|
|
|
|
|
|
|
// 预加载第四个接口的音频 |
|
|
|
|
|
if (result24?.data?.url) { |
|
|
|
|
|
await preloadAudio(result24.data.url.trim(), 'four'); |
|
|
|
|
|
} else { |
|
|
|
|
|
audioPreloadStatus.four.loaded = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 检查是否可以执行 |
|
|
// 检查是否可以执行 |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("FourAPI失败:", error); |
|
|
console.error("FourAPI失败:", error); |
|
|
apiStatus.four.completed = true; |
|
|
apiStatus.four.completed = true; |
|
|
apiStatus.four.error = error; |
|
|
apiStatus.four.error = error; |
|
|
|
|
|
audioPreloadStatus.four.loaded = true; |
|
|
checkAndExecuteInOrder(); |
|
|
checkAndExecuteInOrder(); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|