|
@ -1,6 +1,6 @@ |
|
|
<script setup> |
|
|
<script setup> |
|
|
import { ref, onMounted, watch, nextTick, reactive, onUnmounted } from "vue"; |
|
|
import { ref, onMounted, watch, nextTick, reactive, onUnmounted } from "vue"; |
|
|
import { ElDialog } from "element-plus"; |
|
|
|
|
|
|
|
|
import { ElDialog, ElMessage } from "element-plus"; |
|
|
import { |
|
|
import { |
|
|
getReplyStreamAPI, |
|
|
getReplyStreamAPI, |
|
|
getReplyAPI, |
|
|
getReplyAPI, |
|
@ -37,21 +37,301 @@ const chatStore = useChatStore(); |
|
|
const audioStore = useAudioStore(); |
|
|
const audioStore = useAudioStore(); |
|
|
const dataStore = useDataStore(); |
|
|
const dataStore = useDataStore(); |
|
|
|
|
|
|
|
|
|
|
|
// 将这些变量移到全局作用域 |
|
|
|
|
|
const audioQueue = ref([]); |
|
|
|
|
|
const isPlayingAudio = ref(false); |
|
|
|
|
|
let currentPlayIndex = 0; |
|
|
|
|
|
let isCallingPlayNext = false; |
|
|
|
|
|
|
|
|
|
|
|
// 音频预加载状态 |
|
|
|
|
|
const audioPreloadStatus = { |
|
|
|
|
|
one: { loaded: false, url: null }, |
|
|
|
|
|
two: { loaded: false, url: null }, |
|
|
|
|
|
three: { loaded: false, url: null }, |
|
|
|
|
|
four: { loaded: false, url: null }, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 音频队列顺序管理 |
|
|
|
|
|
const audioQueueOrder = { |
|
|
|
|
|
"API1-第一个": 1, |
|
|
|
|
|
"API2-第二个": 2, |
|
|
|
|
|
"API3-第三个": 3, |
|
|
|
|
|
"API4-第四个": 4, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 播放下一个音频的函数 |
|
|
|
|
|
const playNextAudio = () => { |
|
|
|
|
|
if (isCallingPlayNext) { |
|
|
|
|
|
console.log("playNextAudio已在执行中,跳过重复调用"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (currentPlayIndex >= audioQueue.value.length) { |
|
|
|
|
|
console.log("所有音频播放完成,重置到第一个音频"); |
|
|
|
|
|
// 播放完成后重置到第一个音频,但不自动播放 |
|
|
|
|
|
currentPlayIndex = 0; |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
audioStore.playbackPosition = 0; |
|
|
|
|
|
// 清除音频实例,确保下次点击从头开始 |
|
|
|
|
|
audioStore.soundInstance = null; |
|
|
|
|
|
audioStore.nowSound = null; |
|
|
|
|
|
if (audioQueue.value.length > 0) { |
|
|
|
|
|
audioStore.setCurrentAudioUrl(audioQueue.value[0]); |
|
|
|
|
|
} |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
// if (currentPlayIndex >= audioQueue.value.length) { |
|
|
|
|
|
// console.log("所有音频播放完成"); |
|
|
|
|
|
// isPlayingAudio.value = false; |
|
|
|
|
|
// return; |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
isCallingPlayNext = true; |
|
|
|
|
|
const audioInfo = audioQueue.value[currentPlayIndex]; |
|
|
|
|
|
|
|
|
|
|
|
if (!audioInfo || !audioInfo.url) { |
|
|
|
|
|
console.warn(`音频信息无效,跳过索引 ${currentPlayIndex}`); |
|
|
|
|
|
currentPlayIndex++; |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log(`开始播放 ${audioInfo.name},索引: ${currentPlayIndex}`); |
|
|
|
|
|
|
|
|
|
|
|
const audio = new Howl({ |
|
|
|
|
|
src: [audioInfo.url], |
|
|
|
|
|
html5: true, |
|
|
|
|
|
format: ["mp3", "acc"], |
|
|
|
|
|
rate: 1.2, |
|
|
|
|
|
retryCount: 0, |
|
|
|
|
|
onplay: () => { |
|
|
|
|
|
audioStore.isPlaying = true; |
|
|
|
|
|
isPlayingAudio.value = true; |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
console.log(`${audioInfo.name}音频开始播放`); |
|
|
|
|
|
}, |
|
|
|
|
|
onpause: () => { |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = true; |
|
|
|
|
|
audioStore.playbackPosition = audio.seek() || 0; |
|
|
|
|
|
console.log(`${audioInfo.name}音频已暂停`); |
|
|
|
|
|
}, |
|
|
|
|
|
onresume: () => { |
|
|
|
|
|
audioStore.isPlaying = true; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
console.log(`${audioInfo.name}音频继续播放`); |
|
|
|
|
|
}, |
|
|
|
|
|
onend: () => { |
|
|
|
|
|
console.log(`${audioInfo.name}音频播放完成,准备播放下一个`); |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
audioStore.playbackPosition = 0; |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
|
|
|
|
|
|
currentPlayIndex++; |
|
|
|
|
|
|
|
|
|
|
|
console.log( |
|
|
|
|
|
"currentPlayIndex", |
|
|
|
|
|
currentPlayIndex, |
|
|
|
|
|
"audioQueue.value.length", |
|
|
|
|
|
audioQueue.value.length |
|
|
|
|
|
); |
|
|
|
|
|
if (currentPlayIndex < audioQueue.value.length) { |
|
|
|
|
|
console.log( |
|
|
|
|
|
`队列中还有音频,500ms后播放下一个 (索引:${currentPlayIndex})` |
|
|
|
|
|
); |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
}, 500); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("🎉 所有音频播放完成,清除音频实例"); |
|
|
|
|
|
chatStore.messages[chatStore.currentUserIndex].audioStatus = false; |
|
|
|
|
|
audioStore.nowSound = null; |
|
|
|
|
|
audioStore.soundInstance = null; |
|
|
|
|
|
// currentPlayIndex = 0; |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
|
|
|
|
|
|
// setTimeout(() => { |
|
|
|
|
|
// isCallingPlayNext = false; |
|
|
|
|
|
// playNextAudio(); |
|
|
|
|
|
// }, 500); // 间隔500ms播放下一个 |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
onstop: () => { |
|
|
|
|
|
console.log(`${audioInfo.name}音频被停止`); |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
audioStore.playbackPosition = 0; |
|
|
|
|
|
}, |
|
|
|
|
|
onloaderror: (id, err) => { |
|
|
|
|
|
console.error(`${audioInfo.name}音频播放失败:`, err); |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
audioStore.setCurrentAudioUrl(audioInfo.url); |
|
|
|
|
|
audioStore.nowSound = audio; |
|
|
|
|
|
audioStore.setAudioInstance(audio); |
|
|
|
|
|
|
|
|
|
|
|
console.log(`尝试播放${audioInfo.name}音频`); |
|
|
|
|
|
audio.play(); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 添加音频到播放队列(确保顺序) |
|
|
|
|
|
const addToAudioQueue = (url, name) => { |
|
|
|
|
|
console.log(`=== 添加音频到队列 ===`); |
|
|
|
|
|
console.log("URL:", url); |
|
|
|
|
|
console.log("Name:", name); |
|
|
|
|
|
console.log("音频启用状态:", audioStore.isVoiceEnabled); |
|
|
|
|
|
|
|
|
|
|
|
if (url && audioStore.isVoiceEnabled) { |
|
|
|
|
|
const audioItem = { |
|
|
|
|
|
url, |
|
|
|
|
|
name, |
|
|
|
|
|
order: audioQueueOrder[name] || 999, |
|
|
|
|
|
}; |
|
|
|
|
|
audioQueue.value.push(audioItem); |
|
|
|
|
|
|
|
|
|
|
|
// 按顺序排序队列 |
|
|
|
|
|
audioQueue.value.sort((a, b) => a.order - b.order); |
|
|
|
|
|
|
|
|
|
|
|
console.log(`音频${name}已添加到播放队列,顺序:${audioItem.order}`); |
|
|
|
|
|
console.log( |
|
|
|
|
|
"当前队列顺序:", |
|
|
|
|
|
audioQueue.value.map((item) => `${item.name}(${item.order})`) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// 只有在确实没有音频在播放且这是第一个音频时才开始播放 |
|
|
|
|
|
if ( |
|
|
|
|
|
!isPlayingAudio.value && |
|
|
|
|
|
!audioStore.isPlaying && |
|
|
|
|
|
audioQueue.value.length === 1 |
|
|
|
|
|
) { |
|
|
|
|
|
console.log("✅ 条件满足:没有音频在播放且这是第一个音频,立即开始播放", { |
|
|
|
|
|
isPlayingAudio: isPlayingAudio.value, |
|
|
|
|
|
audioStoreIsPlaying: audioStore.isPlaying, |
|
|
|
|
|
queueLength: audioQueue.value.length, |
|
|
|
|
|
}); |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("⏳ 等待条件:", { |
|
|
|
|
|
isPlayingAudio: isPlayingAudio.value, |
|
|
|
|
|
audioStoreIsPlaying: audioStore.isPlaying, |
|
|
|
|
|
queueLength: audioQueue.value.length, |
|
|
|
|
|
reason: |
|
|
|
|
|
audioQueue.value.length > 1 ? "队列中已有其他音频" : "有音频正在播放", |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("❌ 跳过添加音频:", { |
|
|
|
|
|
hasUrl: !!url, |
|
|
|
|
|
voiceEnabled: audioStore.isVoiceEnabled, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
console.log(`=== 添加音频完成 ===`); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// 语音播放控制函数 |
|
|
// 语音播放控制函数 |
|
|
const toggleVoiceForUser = () => { |
|
|
|
|
|
|
|
|
const toggleVoiceForUser = (index) => { |
|
|
|
|
|
console.log( |
|
|
|
|
|
"上一个按钮坐标", |
|
|
|
|
|
chatStore.currentUserIndex, |
|
|
|
|
|
"当前按钮坐标", |
|
|
|
|
|
index |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
!chatStore.messages[index].audioArray[0] || |
|
|
|
|
|
!chatStore.messages[index].audioArray[1] || |
|
|
|
|
|
!chatStore.messages[index].audioArray[2] || |
|
|
|
|
|
!chatStore.messages[index].audioArray[3] |
|
|
|
|
|
) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 先把当前按钮状态修改 |
|
|
|
|
|
chatStore.messages[index].audioStatus = |
|
|
|
|
|
!chatStore.messages[index].audioStatus; |
|
|
|
|
|
// 如果当前按钮和之前的按钮不是同一个则再修改之前的按钮的状态 |
|
|
|
|
|
if (chatStore.currentUserIndex != index) { |
|
|
|
|
|
if (chatStore.currentUserIndex != null) { |
|
|
|
|
|
if (audioStore.isPlaying) { |
|
|
|
|
|
audioStore.togglePlayPause(); |
|
|
|
|
|
} |
|
|
|
|
|
chatStore.messages[chatStore.currentUserIndex].audioStatus = false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
audioPreloadStatus.one = { loaded: false, url: null }; |
|
|
|
|
|
audioPreloadStatus.two = { loaded: false, url: null }; |
|
|
|
|
|
audioPreloadStatus.three = { loaded: false, url: null }; |
|
|
|
|
|
audioPreloadStatus.four = { loaded: false, url: null }; |
|
|
|
|
|
if (chatStore.messages[index].audioArray[0]) { |
|
|
|
|
|
audioPreloadStatus.one.loaded = true; |
|
|
|
|
|
audioPreloadStatus.one.url = chatStore.messages[index].audioArray[0]; |
|
|
|
|
|
} |
|
|
|
|
|
if (chatStore.messages[index].audioArray[1]) { |
|
|
|
|
|
audioPreloadStatus.two.loaded = true; |
|
|
|
|
|
audioPreloadStatus.two.url = chatStore.messages[index].audioArray[1]; |
|
|
|
|
|
} |
|
|
|
|
|
if (chatStore.messages[index].audioArray[2]) { |
|
|
|
|
|
audioPreloadStatus.three.loaded = true; |
|
|
|
|
|
audioPreloadStatus.three.url = chatStore.messages[index].audioArray[2]; |
|
|
|
|
|
} |
|
|
|
|
|
if (chatStore.messages[index].audioArray[3]) { |
|
|
|
|
|
audioPreloadStatus.four.loaded = true; |
|
|
|
|
|
audioPreloadStatus.four.url = chatStore.messages[index].audioArray[3]; |
|
|
|
|
|
} |
|
|
|
|
|
chatStore.currentUserIndex = index; |
|
|
|
|
|
audioQueue.value = []; |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
audioStore.soundInstance = null; |
|
|
|
|
|
currentPlayIndex = 0; |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
addToAudioQueue(chatStore.messages[index].audioArray[0], "API1-第一个"); |
|
|
|
|
|
addToAudioQueue(chatStore.messages[index].audioArray[1], "API2-第二个"); |
|
|
|
|
|
addToAudioQueue(chatStore.messages[index].audioArray[2], "API3-第三个"); |
|
|
|
|
|
addToAudioQueue(chatStore.messages[index].audioArray[3], "API4-第四个"); |
|
|
|
|
|
|
|
|
if (!audioStore.isVoiceEnabled) { |
|
|
if (!audioStore.isVoiceEnabled) { |
|
|
// 如果语音功能关闭,先开启语音功能 |
|
|
|
|
|
audioStore.toggleVoice(); |
|
|
audioStore.toggleVoice(); |
|
|
} else { |
|
|
} else { |
|
|
// 如果语音功能开启,则切换播放/暂停状态 |
|
|
|
|
|
if (audioStore.currentAudioUrl || audioStore.ttsUrl) { |
|
|
if (audioStore.currentAudioUrl || audioStore.ttsUrl) { |
|
|
// 有音频时切换播放/暂停 |
|
|
|
|
|
audioStore.togglePlayPause(); |
|
|
audioStore.togglePlayPause(); |
|
|
} else { |
|
|
} else { |
|
|
// 没有音频时关闭语音功能 |
|
|
|
|
|
audioStore.toggleVoice(); |
|
|
audioStore.toggleVoice(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
if (!audioStore.isVoiceEnabled) { |
|
|
|
|
|
console.log("1111"); |
|
|
|
|
|
audioStore.toggleVoice(); |
|
|
|
|
|
} else { |
|
|
|
|
|
if (currentPlayIndex >= audioQueue.value.length) { |
|
|
|
|
|
console.log("重新开始播放音频序列"); |
|
|
|
|
|
currentPlayIndex = 0; |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
isCallingPlayNext = false; |
|
|
|
|
|
audioStore.soundInstance = null; |
|
|
|
|
|
// 重新开始播放 |
|
|
|
|
|
if (audioQueue.value.length > 0) { |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
} |
|
|
|
|
|
} else if (audioStore.currentAudioUrl || audioStore.ttsUrl) { |
|
|
|
|
|
console.log("2222"); |
|
|
|
|
|
audioStore.togglePlayPause(); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("3333"); |
|
|
|
|
|
audioStore.toggleVoice(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// 计算属性:判断语音是否启用 |
|
|
// 计算属性:判断语音是否启用 |
|
@ -82,11 +362,6 @@ const playAudio = (url) => { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const handlePlay = () => { |
|
|
const handlePlay = () => { |
|
|
// if (audioStore.soundInstance) { |
|
|
|
|
|
// Howler.unload(); // 添加清理旧实例 |
|
|
|
|
|
// // audioStore.soundInstance.stop() |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
if (audioStore.isNewInstance) { |
|
|
if (audioStore.isNewInstance) { |
|
|
const newSound = new Howl({ |
|
|
const newSound = new Howl({ |
|
|
src: [url], |
|
|
src: [url], |
|
@ -142,22 +417,9 @@ const playAudio = (url) => { |
|
|
// 新增暂停方法 |
|
|
// 新增暂停方法 |
|
|
const pauseAudio = () => { |
|
|
const pauseAudio = () => { |
|
|
if (audioStore.soundInstance) { |
|
|
if (audioStore.soundInstance) { |
|
|
// 添加移动端特殊处理 |
|
|
|
|
|
// if (/iPhone|iPad|iPod/.test(navigator.userAgent)) { |
|
|
|
|
|
// Howler.pause(); // iOS需要强制停止音频上下文 |
|
|
|
|
|
// } else { |
|
|
|
|
|
// audioStore.soundInstance.pause(); |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
audioStore.soundInstance.pause(); |
|
|
audioStore.soundInstance.pause(); |
|
|
|
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
|
|
|
// // 添加状态同步 |
|
|
|
|
|
// nextTick(() => { |
|
|
|
|
|
// Howler.unload(); |
|
|
|
|
|
// audioStore.soundInstance = null; |
|
|
|
|
|
// }); |
|
|
|
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -331,7 +593,7 @@ const playAudioSequence = (audioUrls) => { |
|
|
// 重写togglePlayPause方法以支持音频序列控制 |
|
|
// 重写togglePlayPause方法以支持音频序列控制 |
|
|
const originalTogglePlayPause = audioStore.togglePlayPause; |
|
|
const originalTogglePlayPause = audioStore.togglePlayPause; |
|
|
audioStore.togglePlayPause = () => { |
|
|
audioStore.togglePlayPause = () => { |
|
|
console.log("音频控制按钮被点击"); |
|
|
|
|
|
|
|
|
console.log("音频控制按钮被点击 11111111111"); |
|
|
console.log("当前播放状态:", audioStore.isPlaying); |
|
|
console.log("当前播放状态:", audioStore.isPlaying); |
|
|
console.log("当前暂停状态:", audioStore.isPaused); |
|
|
console.log("当前暂停状态:", audioStore.isPaused); |
|
|
console.log("当前音频实例:", audioStore.soundInstance); |
|
|
console.log("当前音频实例:", audioStore.soundInstance); |
|
@ -486,6 +748,8 @@ const createTypingEffect = (message, content, speed) => { |
|
|
if (message.end) { |
|
|
if (message.end) { |
|
|
chatStore.getUserCount(); |
|
|
chatStore.getUserCount(); |
|
|
chatStore.isLoading = false; |
|
|
chatStore.isLoading = false; |
|
|
|
|
|
chatStore.searchRecord = true; |
|
|
|
|
|
console.log("打印完毕,接触输入框禁用状态"); |
|
|
emit("enableInput"); |
|
|
emit("enableInput"); |
|
|
} |
|
|
} |
|
|
message.isTyping = false; |
|
|
message.isTyping = false; |
|
@ -794,10 +1058,6 @@ const previousMessagesLength = ref(0); |
|
|
watch( |
|
|
watch( |
|
|
() => props.messages, |
|
|
() => props.messages, |
|
|
async (newVal, oldVal) => { |
|
|
async (newVal, oldVal) => { |
|
|
// console.log(newVal, 'newVal') |
|
|
|
|
|
// console.log(oldVal, 'oldVal') |
|
|
|
|
|
// console.log(previousMessagesLength.value, 'previousMessagesLength') |
|
|
|
|
|
// console.log(newVal.length, 'newVal.length') |
|
|
|
|
|
// // 添加空值判断 |
|
|
// // 添加空值判断 |
|
|
if (!newVal?.length || newVal === previousMessagesLength.value) return; |
|
|
if (!newVal?.length || newVal === previousMessagesLength.value) return; |
|
|
|
|
|
|
|
@ -805,10 +1065,13 @@ watch( |
|
|
if (newVal.length > 0) { |
|
|
if (newVal.length > 0) { |
|
|
console.log("消息列表已更新,最新消息:", newVal[newVal.length - 1]); |
|
|
console.log("消息列表已更新,最新消息:", newVal[newVal.length - 1]); |
|
|
chatStore.messages.push(newVal[newVal.length - 1]); |
|
|
chatStore.messages.push(newVal[newVal.length - 1]); |
|
|
|
|
|
|
|
|
console.log("消息列表已更新,最新消息:", chatMsg[chatMsg.length - 1]); |
|
|
|
|
|
|
|
|
|
|
|
console.log("token", localStorage.getItem("localToken")); |
|
|
|
|
|
|
|
|
chatStore.currentUserIndex = chatStore.messages.length - 1; |
|
|
|
|
|
console.log( |
|
|
|
|
|
"消息列表已更新,最新消息:", |
|
|
|
|
|
chatStore.messages[chatStore.messages.length - 1], |
|
|
|
|
|
"最新用户坐标", |
|
|
|
|
|
chatStore.currentUserIndex |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
// 获取权限 |
|
|
// 获取权限 |
|
|
const userStore = useUserStore(); |
|
|
const userStore = useUserStore(); |
|
@ -1010,265 +1273,12 @@ watch( |
|
|
}, |
|
|
}, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// 音频预加载状态跟踪 |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
// 播放音频队列 |
|
|
|
|
|
// 防止重复调用的标志 |
|
|
|
|
|
let isCallingPlayNext = false; |
|
|
|
|
|
// 当前播放索引 |
|
|
|
|
|
let currentPlayIndex = 0; |
|
|
|
|
|
|
|
|
|
|
|
const playNextAudio = () => { |
|
|
|
|
|
console.log("=== playNextAudio 被调用 ==="); |
|
|
|
|
|
console.log("当前队列状态:", { |
|
|
|
|
|
queueLength: audioQueue.value.length, |
|
|
|
|
|
queueItems: audioQueue.value.map((item) => item.name), |
|
|
|
|
|
currentPlayIndex: currentPlayIndex, |
|
|
|
|
|
isPlayingAudio: isPlayingAudio.value, |
|
|
|
|
|
isCallingPlayNext: isCallingPlayNext, |
|
|
|
|
|
audioStoreIsPlaying: audioStore.isPlaying, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
audioQueue.value.length === 0 || |
|
|
|
|
|
isPlayingAudio.value || |
|
|
|
|
|
isCallingPlayNext |
|
|
|
|
|
) { |
|
|
|
|
|
console.log( |
|
|
|
|
|
"❌ 播放条件不满足 - 队列长度:", |
|
|
|
|
|
audioQueue.value.length, |
|
|
|
|
|
"正在播放:", |
|
|
|
|
|
isPlayingAudio.value, |
|
|
|
|
|
"正在调用:", |
|
|
|
|
|
isCallingPlayNext |
|
|
|
|
|
); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否已播放完所有音频(仅在队列不为空时重置) |
|
|
|
|
|
if ( |
|
|
|
|
|
currentPlayIndex >= audioQueue.value.length && |
|
|
|
|
|
audioQueue.value.length > 0 |
|
|
|
|
|
) { |
|
|
|
|
|
console.log("🔄 所有音频播放完成,重置索引从第一个开始"); |
|
|
|
|
|
currentPlayIndex = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
isCallingPlayNext = true; |
|
|
|
|
|
isPlayingAudio.value = true; |
|
|
|
|
|
const audioInfo = audioQueue.value[currentPlayIndex]; |
|
|
|
|
|
|
|
|
|
|
|
console.log( |
|
|
|
|
|
`✅ 开始播放${audioInfo.name}音频 (索引:${currentPlayIndex}),队列总长度:`, |
|
|
|
|
|
audioQueue.value.length |
|
|
|
|
|
); |
|
|
|
|
|
console.log( |
|
|
|
|
|
"完整队列内容:", |
|
|
|
|
|
audioQueue.value.map( |
|
|
|
|
|
(item, index) => |
|
|
|
|
|
`${index === currentPlayIndex ? "▶️" : "⏸️"} ${item.name}` |
|
|
|
|
|
) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// 只有在确实需要停止时才停止之前的音频 |
|
|
|
|
|
if ( |
|
|
|
|
|
audioStore.nowSound && |
|
|
|
|
|
(audioStore.nowSound.playing() || |
|
|
|
|
|
audioStore.nowSound.state() === "loading") |
|
|
|
|
|
) { |
|
|
|
|
|
console.log("停止之前的音频实例"); |
|
|
|
|
|
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; |
|
|
|
|
|
isPlayingAudio.value = true; // 确保状态同步 |
|
|
|
|
|
isCallingPlayNext = false; // 重置调用标志 |
|
|
|
|
|
console.log( |
|
|
|
|
|
`${audioInfo.name}音频开始播放,时长:`, |
|
|
|
|
|
audio.duration() |
|
|
|
|
|
); |
|
|
|
|
|
console.log( |
|
|
|
|
|
"音频播放状态确认 - isPlayingAudio:", |
|
|
|
|
|
isPlayingAudio.value, |
|
|
|
|
|
"audioStore.isPlaying:", |
|
|
|
|
|
audioStore.isPlaying |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
onpause: () => { |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = true; |
|
|
|
|
|
audioStore.playbackPosition = audio.seek() || 0; |
|
|
|
|
|
console.log( |
|
|
|
|
|
`${audioInfo.name}音频已暂停,位置:`, |
|
|
|
|
|
audioStore.playbackPosition |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
onresume: () => { |
|
|
|
|
|
audioStore.isPlaying = true; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
console.log(`${audioInfo.name}音频继续播放`); |
|
|
|
|
|
}, |
|
|
|
|
|
onend: () => { |
|
|
|
|
|
console.log(`${audioInfo.name}音频播放完成,准备播放下一个`); |
|
|
|
|
|
console.log( |
|
|
|
|
|
"播放完成时的状态 - 当前索引:", |
|
|
|
|
|
currentPlayIndex, |
|
|
|
|
|
"队列长度:", |
|
|
|
|
|
audioQueue.value.length, |
|
|
|
|
|
"isPlayingAudio:", |
|
|
|
|
|
isPlayingAudio.value |
|
|
|
|
|
); |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
audioStore.playbackPosition = 0; |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
|
|
|
|
|
|
// 移动到下一个音频索引 |
|
|
|
|
|
currentPlayIndex++; |
|
|
|
|
|
|
|
|
|
|
|
// 确保只有在音频真正播放完成时才播放下一个 |
|
|
|
|
|
if (currentPlayIndex < audioQueue.value.length) { |
|
|
|
|
|
console.log( |
|
|
|
|
|
`队列中还有音频,500ms后播放下一个 (索引:${currentPlayIndex}),当前队列:`, |
|
|
|
|
|
audioQueue.value.map( |
|
|
|
|
|
(item, index) => |
|
|
|
|
|
`${index === currentPlayIndex ? "▶️" : "⏸️"} ${ |
|
|
|
|
|
item.name |
|
|
|
|
|
}` |
|
|
|
|
|
) |
|
|
|
|
|
); |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
isCallingPlayNext = false; // 在调用前重置标志 |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
}, 500); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log( |
|
|
|
|
|
"🎉 所有音频播放完成,清除音频实例,队列保持完整,下次播放将从第一个开始" |
|
|
|
|
|
); |
|
|
|
|
|
// 清除音频实例,确保重新播放时不会使用旧实例 |
|
|
|
|
|
audioStore.nowSound = null; |
|
|
|
|
|
audioStore.soundInstance = null; |
|
|
|
|
|
isCallingPlayNext = false; // 重置调用标志 |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
onstop: () => { |
|
|
|
|
|
console.log(`${audioInfo.name}音频被停止`); |
|
|
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
audioStore.isPaused = false; |
|
|
|
|
|
audioStore.playbackPosition = 0; |
|
|
|
|
|
// 注意:不要在onstop中设置isPlayingAudio.value = false,因为这可能是正常的音频切换 |
|
|
|
|
|
}, |
|
|
|
|
|
onloaderror: (id, err) => { |
|
|
|
|
|
console.error(`${audioInfo.name}音频播放失败:`, err); |
|
|
|
|
|
isPlayingAudio.value = false; |
|
|
|
|
|
isCallingPlayNext = false; // 重置调用标志 |
|
|
|
|
|
// 播放下一个音频 |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 设置当前音频URL到store |
|
|
|
|
|
audioStore.setCurrentAudioUrl(audioInfo.url); |
|
|
|
|
|
audioStore.nowSound = audio; |
|
|
|
|
|
audioStore.setAudioInstance(audio); |
|
|
|
|
|
|
|
|
|
|
|
console.log(`尝试播放${audioInfo.name}音频`); |
|
|
|
|
|
audio.play(); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 音频队列顺序管理 |
|
|
|
|
|
const audioQueueOrder = { |
|
|
|
|
|
"API1-第一个": 1, |
|
|
|
|
|
"API2-第二个": 2, |
|
|
|
|
|
"API3-第三个": 3, |
|
|
|
|
|
"API4-第四个": 4, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 添加音频到播放队列(确保顺序) |
|
|
|
|
|
const addToAudioQueue = (url, name) => { |
|
|
|
|
|
console.log(`=== 添加音频到队列 ===`); |
|
|
|
|
|
console.log("URL:", url); |
|
|
|
|
|
console.log("Name:", name); |
|
|
|
|
|
console.log("音频启用状态:", audioStore.isVoiceEnabled); |
|
|
|
|
|
|
|
|
|
|
|
if (url && audioStore.isVoiceEnabled) { |
|
|
|
|
|
const audioItem = { |
|
|
|
|
|
url, |
|
|
|
|
|
name, |
|
|
|
|
|
order: audioQueueOrder[name] || 999, |
|
|
|
|
|
}; |
|
|
|
|
|
audioQueue.value.push(audioItem); |
|
|
|
|
|
|
|
|
|
|
|
// 按顺序排序队列 |
|
|
|
|
|
audioQueue.value.sort((a, b) => a.order - b.order); |
|
|
|
|
|
|
|
|
|
|
|
console.log( |
|
|
|
|
|
`音频${name}已添加到播放队列,顺序:${audioItem.order}` |
|
|
|
|
|
); |
|
|
|
|
|
console.log( |
|
|
|
|
|
"当前队列顺序:", |
|
|
|
|
|
audioQueue.value.map((item) => `${item.name}(${item.order})`) |
|
|
|
|
|
); |
|
|
|
|
|
console.log("当前播放状态详情:"); |
|
|
|
|
|
console.log(" - isPlayingAudio:", isPlayingAudio.value); |
|
|
|
|
|
console.log(" - audioStore.isPlaying:", audioStore.isPlaying); |
|
|
|
|
|
console.log(" - audioStore.nowSound:", audioStore.nowSound); |
|
|
|
|
|
console.log(" - isCallingPlayNext:", isCallingPlayNext); |
|
|
|
|
|
console.log(" - 队列长度:", audioQueue.value.length); |
|
|
|
|
|
|
|
|
|
|
|
// 只有在确实没有音频在播放且这是第一个音频时才开始播放 |
|
|
|
|
|
if ( |
|
|
|
|
|
!isPlayingAudio.value && |
|
|
|
|
|
!audioStore.isPlaying && |
|
|
|
|
|
audioQueue.value.length === 1 |
|
|
|
|
|
) { |
|
|
|
|
|
console.log( |
|
|
|
|
|
"✅ 条件满足:没有音频在播放且这是第一个音频,立即开始播放" |
|
|
|
|
|
); |
|
|
|
|
|
playNextAudio(); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("⏳ 等待条件:", { |
|
|
|
|
|
isPlayingAudio: isPlayingAudio.value, |
|
|
|
|
|
audioStoreIsPlaying: audioStore.isPlaying, |
|
|
|
|
|
queueLength: audioQueue.value.length, |
|
|
|
|
|
reason: |
|
|
|
|
|
audioQueue.value.length > 1 |
|
|
|
|
|
? "队列中已有其他音频" |
|
|
|
|
|
: "有音频正在播放", |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("❌ 跳过添加音频:", { |
|
|
|
|
|
hasUrl: !!url, |
|
|
|
|
|
voiceEnabled: audioStore.isVoiceEnabled, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
console.log(`=== 添加音频完成 ===`); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// 音频播放队列管理已移到全局作用域 |
|
|
|
|
|
|
|
|
// 重写audioStore的togglePlayPause方法以支持队列播放控制 |
|
|
// 重写audioStore的togglePlayPause方法以支持队列播放控制 |
|
|
const originalTogglePlayPause = audioStore.togglePlayPause; |
|
|
const originalTogglePlayPause = audioStore.togglePlayPause; |
|
|
audioStore.togglePlayPause = () => { |
|
|
audioStore.togglePlayPause = () => { |
|
|
console.log("主页音频控制按钮被点击"); |
|
|
|
|
|
|
|
|
console.log("主页音频控制按钮被点击22222222222222"); |
|
|
console.log( |
|
|
console.log( |
|
|
"当前音频状态 - isPlaying:", |
|
|
"当前音频状态 - isPlaying:", |
|
|
audioStore.isPlaying, |
|
|
audioStore.isPlaying, |
|
@ -1484,6 +1494,9 @@ watch( |
|
|
|
|
|
|
|
|
// 将第一个音频添加到播放队列(确保顺序:API1) |
|
|
// 将第一个音频添加到播放队列(确保顺序:API1) |
|
|
if (audioPreloadStatus.one.url) { |
|
|
if (audioPreloadStatus.one.url) { |
|
|
|
|
|
chatStore.messages[ |
|
|
|
|
|
chatStore.currentUserIndex |
|
|
|
|
|
].audioArray.push(audioPreloadStatus.one.url); |
|
|
addToAudioQueue(audioPreloadStatus.one.url, "API1-第一个"); |
|
|
addToAudioQueue(audioPreloadStatus.one.url, "API1-第一个"); |
|
|
console.log( |
|
|
console.log( |
|
|
"音频队列:添加API1音频,当前队列长度:", |
|
|
"音频队列:添加API1音频,当前队列长度:", |
|
@ -1754,6 +1767,9 @@ watch( |
|
|
|
|
|
|
|
|
// 将第二个音频添加到播放队列(确保顺序:API2) |
|
|
// 将第二个音频添加到播放队列(确保顺序:API2) |
|
|
if (audioPreloadStatus.two.url) { |
|
|
if (audioPreloadStatus.two.url) { |
|
|
|
|
|
chatStore.messages[ |
|
|
|
|
|
chatStore.currentUserIndex |
|
|
|
|
|
].audioArray.push(audioPreloadStatus.two.url); |
|
|
addToAudioQueue(audioPreloadStatus.two.url, "API2-第二个"); |
|
|
addToAudioQueue(audioPreloadStatus.two.url, "API2-第二个"); |
|
|
console.log( |
|
|
console.log( |
|
|
"音频队列:添加API2音频,当前队列长度:", |
|
|
"音频队列:添加API2音频,当前队列长度:", |
|
@ -1855,6 +1871,9 @@ watch( |
|
|
|
|
|
|
|
|
// 将第三个音频添加到播放队列(确保顺序:API3) |
|
|
// 将第三个音频添加到播放队列(确保顺序:API3) |
|
|
if (audioPreloadStatus.three.url) { |
|
|
if (audioPreloadStatus.three.url) { |
|
|
|
|
|
chatStore.messages[ |
|
|
|
|
|
chatStore.currentUserIndex |
|
|
|
|
|
].audioArray.push(audioPreloadStatus.three.url); |
|
|
addToAudioQueue(audioPreloadStatus.three.url, "API3-第三个"); |
|
|
addToAudioQueue(audioPreloadStatus.three.url, "API3-第三个"); |
|
|
console.log( |
|
|
console.log( |
|
|
"音频队列:添加API3音频,当前队列长度:", |
|
|
"音频队列:添加API3音频,当前队列长度:", |
|
@ -2041,6 +2060,9 @@ watch( |
|
|
|
|
|
|
|
|
// 将第四个音频添加到播放队列(确保顺序:API4) |
|
|
// 将第四个音频添加到播放队列(确保顺序:API4) |
|
|
if (audioPreloadStatus.four.url) { |
|
|
if (audioPreloadStatus.four.url) { |
|
|
|
|
|
chatStore.messages[ |
|
|
|
|
|
chatStore.currentUserIndex |
|
|
|
|
|
].audioArray.push(audioPreloadStatus.four.url); |
|
|
addToAudioQueue(audioPreloadStatus.four.url, "API4-第四个"); |
|
|
addToAudioQueue(audioPreloadStatus.four.url, "API4-第四个"); |
|
|
console.log( |
|
|
console.log( |
|
|
"音频队列:添加API4音频,当前队列长度:", |
|
|
"音频队列:添加API4音频,当前队列长度:", |
|
@ -2366,7 +2388,7 @@ watch( |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
{ deep: true } |
|
|
|
|
|
|
|
|
{ deep: false } |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
// 点击历史记录 |
|
|
// 点击历史记录 |
|
@ -2386,7 +2408,15 @@ watch( |
|
|
chatStore.dbqbClickRecord = {}; |
|
|
chatStore.dbqbClickRecord = {}; |
|
|
console.log("dbqbClickRecord 已清空"); |
|
|
console.log("dbqbClickRecord 已清空"); |
|
|
}, 0); |
|
|
}, 0); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
!clickRecord.value.wokeFlowData.One || |
|
|
|
|
|
!clickRecord.value.wokeFlowData.Two || |
|
|
|
|
|
!clickRecord.value.wokeFlowData.Three || |
|
|
|
|
|
!clickRecord.value.wokeFlowData.Four |
|
|
|
|
|
) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
try { |
|
|
// 清空聊天框内容 |
|
|
// 清空聊天框内容 |
|
|
chatStore.messages = []; |
|
|
chatStore.messages = []; |
|
|
|
|
|
|
|
@ -2394,6 +2424,13 @@ watch( |
|
|
sender: "user", |
|
|
sender: "user", |
|
|
timestamp: clickRecord.value.createdTime, |
|
|
timestamp: clickRecord.value.createdTime, |
|
|
content: clickRecord.value.keyword, |
|
|
content: clickRecord.value.keyword, |
|
|
|
|
|
audioArray: [ |
|
|
|
|
|
clickRecord.value.wokeFlowData.One.url, |
|
|
|
|
|
clickRecord.value.wokeFlowData.Two.url, |
|
|
|
|
|
clickRecord.value.wokeFlowData.Three.url, |
|
|
|
|
|
clickRecord.value.wokeFlowData.Four.url, |
|
|
|
|
|
], |
|
|
|
|
|
audioStatus: true, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
chatStore.messages.push({ |
|
|
chatStore.messages.push({ |
|
@ -2630,6 +2667,10 @@ watch( |
|
|
content: "该内容由AI生成,请注意甄别", |
|
|
content: "该内容由AI生成,请注意甄别", |
|
|
end: true, |
|
|
end: true, |
|
|
}); |
|
|
}); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
ElMessage.error("历史数据获取出错!"); |
|
|
|
|
|
console.error("e", e); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
deep: true, // 深度监听对象内部属性的变化 |
|
|
deep: true, // 深度监听对象内部属性的变化 |
|
@ -2643,11 +2684,11 @@ function KlineCanvsEcharts(containerId) { |
|
|
return (window.innerWidth * vw) / 100; |
|
|
return (window.innerWidth * vw) / 100; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
console.log("KLine渲染: 开始处理数据, 容器ID:", containerId); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 开始处理数据, 容器ID:", containerId); |
|
|
|
|
|
|
|
|
// 从 chatStore 中获取数据 |
|
|
// 从 chatStore 中获取数据 |
|
|
const messages = chatStore.messages; |
|
|
const messages = chatStore.messages; |
|
|
console.log("KLine渲染: 获取到的消息:", messages); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 获取到的消息:", messages); |
|
|
let klineMessageIndex = -1; |
|
|
let klineMessageIndex = -1; |
|
|
let klineData = null; |
|
|
let klineData = null; |
|
|
|
|
|
|
|
@ -2663,7 +2704,7 @@ function KlineCanvsEcharts(containerId) { |
|
|
// } |
|
|
// } |
|
|
// } |
|
|
// } |
|
|
klineMessageIndex = containerId.split("-")[2]; |
|
|
klineMessageIndex = containerId.split("-")[2]; |
|
|
console.log("KLine渲染: 找到K线消息索引:", klineMessageIndex); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 找到K线消息索引:", klineMessageIndex); |
|
|
if ( |
|
|
if ( |
|
|
messages[klineMessageIndex].kline && |
|
|
messages[klineMessageIndex].kline && |
|
|
messages[klineMessageIndex].chartData |
|
|
messages[klineMessageIndex].chartData |
|
@ -2683,33 +2724,33 @@ function KlineCanvsEcharts(containerId) { |
|
|
|
|
|
|
|
|
if (messages[klineMessageIndex].klineType == 1) { |
|
|
if (messages[klineMessageIndex].klineType == 1) { |
|
|
if (!klineData) { |
|
|
if (!klineData) { |
|
|
console.warn("六色罗盘渲染: 数据无效 - 在chatStore中找不到有效的K线数据"); |
|
|
|
|
|
|
|
|
// console.warn("六色罗盘渲染: 数据无效 - 在chatStore中找不到有效的K线数据"); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取容器元素 |
|
|
// 获取容器元素 |
|
|
const container = document.getElementById(containerId); |
|
|
const container = document.getElementById(containerId); |
|
|
if (!container) { |
|
|
if (!container) { |
|
|
console.error("六色罗盘渲染: 找不到容器元素:", containerId); |
|
|
|
|
|
|
|
|
// console.error("六色罗盘渲染: 找不到容器元素:", containerId); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 创建图表实例 |
|
|
// 创建图表实例 |
|
|
console.log("六色罗盘渲染: 创建图表实例"); |
|
|
|
|
|
|
|
|
// console.log("六色罗盘渲染: 创建图表实例"); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
// 如果已有实例,先销毁 |
|
|
// 如果已有实例,先销毁 |
|
|
if (chartInstancesMap[containerId]) { |
|
|
if (chartInstancesMap[containerId]) { |
|
|
console.log("六色罗盘渲染: 销毁已有图表实例"); |
|
|
|
|
|
|
|
|
// console.log("六色罗盘渲染: 销毁已有图表实例"); |
|
|
chartInstancesMap[containerId].dispose(); |
|
|
chartInstancesMap[containerId].dispose(); |
|
|
delete chartInstancesMap[containerId]; |
|
|
delete chartInstancesMap[containerId]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 使用普通变量存储实例 |
|
|
// 使用普通变量存储实例 |
|
|
chartInstancesMap[containerId] = echarts.init(container); |
|
|
chartInstancesMap[containerId] = echarts.init(container); |
|
|
console.log("六色罗盘渲染: 图表实例创建成功"); |
|
|
|
|
|
|
|
|
// console.log("六色罗盘渲染: 图表实例创建成功"); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("六色罗盘渲染: 图表实例创建失败:", error); |
|
|
|
|
|
|
|
|
// console.error("六色罗盘渲染: 图表实例创建失败:", error); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -2812,54 +2853,54 @@ function KlineCanvsEcharts(containerId) { |
|
|
}; |
|
|
}; |
|
|
} else if (messages[klineMessageIndex].klineType == 2) { |
|
|
} else if (messages[klineMessageIndex].klineType == 2) { |
|
|
if (!klineData || !klineData.Kline) { |
|
|
if (!klineData || !klineData.Kline) { |
|
|
console.warn("KLine渲染: 数据无效 - 在chatStore中找不到有效的K线数据"); |
|
|
|
|
|
|
|
|
// console.warn("KLine渲染: 数据无效 - 在chatStore中找不到有效的K线数据"); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取容器元素 |
|
|
// 获取容器元素 |
|
|
const container = document.getElementById(containerId); |
|
|
const container = document.getElementById(containerId); |
|
|
if (!container) { |
|
|
if (!container) { |
|
|
console.error("KLine渲染: 找不到容器元素:", containerId); |
|
|
|
|
|
|
|
|
// console.error("KLine渲染: 找不到容器元素:", containerId); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 创建图表实例 |
|
|
// 创建图表实例 |
|
|
console.log("KLine渲染: 创建图表实例"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 创建图表实例"); |
|
|
try { |
|
|
try { |
|
|
// 如果已有实例,先销毁 |
|
|
// 如果已有实例,先销毁 |
|
|
if (chartInstancesMap[containerId]) { |
|
|
if (chartInstancesMap[containerId]) { |
|
|
console.log("KLine渲染: 销毁已有图表实例"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 销毁已有图表实例"); |
|
|
chartInstancesMap[containerId].dispose(); |
|
|
chartInstancesMap[containerId].dispose(); |
|
|
delete chartInstancesMap[containerId]; |
|
|
delete chartInstancesMap[containerId]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 使用普通变量存储实例 |
|
|
// 使用普通变量存储实例 |
|
|
chartInstancesMap[containerId] = echarts.init(container); |
|
|
chartInstancesMap[containerId] = echarts.init(container); |
|
|
console.log("KLine渲染: 图表实例创建成功"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 图表实例创建成功"); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("KLine渲染: 图表实例创建失败:", error); |
|
|
|
|
|
|
|
|
// console.error("KLine渲染: 图表实例创建失败:", error); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const data = klineData.Kline; |
|
|
const data = klineData.Kline; |
|
|
console.log("KLine渲染: Kline数据", data); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: Kline数据", data); |
|
|
|
|
|
|
|
|
// 切割数据方法 |
|
|
// 切割数据方法 |
|
|
const splitData = (a) => { |
|
|
const splitData = (a) => { |
|
|
console.log("KLine渲染: 开始数据切割"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 开始数据切割"); |
|
|
const categoryData = []; |
|
|
const categoryData = []; |
|
|
let values = []; |
|
|
let values = []; |
|
|
for (let i = 0; i < a.length; i++) { |
|
|
for (let i = 0; i < a.length; i++) { |
|
|
categoryData.push(a[i][0]); |
|
|
categoryData.push(a[i][0]); |
|
|
values.push([a[i][1], a[i][2], a[i][3], a[i][4]]); |
|
|
values.push([a[i][1], a[i][2], a[i][3], a[i][4]]); |
|
|
} |
|
|
} |
|
|
console.log("KLine渲染: 日期数据点数量", categoryData.length); |
|
|
|
|
|
console.log("KLine渲染: 值数据点数量", values.length); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 日期数据点数量", categoryData.length); |
|
|
|
|
|
// console.log("KLine渲染: 值数据点数量", values.length); |
|
|
return { categoryData, values }; |
|
|
return { categoryData, values }; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// 给配置项 |
|
|
// 给配置项 |
|
|
console.log("KLine渲染: 开始配置图表选项"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 开始配置图表选项"); |
|
|
|
|
|
|
|
|
const arr1 = []; |
|
|
const arr1 = []; |
|
|
const arr2 = []; |
|
|
const arr2 = []; |
|
@ -4109,13 +4150,13 @@ function KlineCanvsEcharts(containerId) { |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
console.log("KLine渲染: 图表配置完成"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 图表配置完成"); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
// 应用配置 |
|
|
// 应用配置 |
|
|
console.log("KLine渲染: 开始设置图表选项"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 开始设置图表选项"); |
|
|
chartInstancesMap[containerId].setOption(KlineOption); |
|
|
chartInstancesMap[containerId].setOption(KlineOption); |
|
|
console.log("KLine渲染: 图表选项设置成功"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 图表选项设置成功"); |
|
|
|
|
|
|
|
|
// 窗口大小变化时重新渲染图表 |
|
|
// 窗口大小变化时重新渲染图表 |
|
|
const resizeFunc = _.throttle( |
|
|
const resizeFunc = _.throttle( |
|
@ -4150,9 +4191,9 @@ function KlineCanvsEcharts(containerId) { |
|
|
window.removeEventListener("resize", window[`resize_${containerId}`]); |
|
|
window.removeEventListener("resize", window[`resize_${containerId}`]); |
|
|
window.addEventListener("resize", window[`resize_${containerId}`]); |
|
|
window.addEventListener("resize", window[`resize_${containerId}`]); |
|
|
|
|
|
|
|
|
console.log("KLine渲染: 图表渲染完成"); |
|
|
|
|
|
|
|
|
// console.log("KLine渲染: 图表渲染完成"); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("KLine渲染: 图表渲染出错", error); |
|
|
|
|
|
|
|
|
// console.error("KLine渲染: 图表渲染出错", error); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -4180,13 +4221,6 @@ watch( |
|
|
} else { |
|
|
} else { |
|
|
console.log("关闭语音播放"); |
|
|
console.log("关闭语音播放"); |
|
|
pauseAudio(); |
|
|
pauseAudio(); |
|
|
// 强制停止并释放资源 |
|
|
|
|
|
// Howler.stop(); |
|
|
|
|
|
// Howler.unload(); |
|
|
|
|
|
// if (audioStore.soundInstance) { |
|
|
|
|
|
// audioStore.soundInstance.off(); // 移除所有事件监听 |
|
|
|
|
|
// audioStore.soundInstance = null; |
|
|
|
|
|
// } |
|
|
|
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
{ immediate: true } |
|
|
{ immediate: true } |
|
@ -4247,6 +4281,12 @@ onMounted(() => { |
|
|
renderAllKlineCharts(); |
|
|
renderAllKlineCharts(); |
|
|
console.log("组件挂载完成"); |
|
|
console.log("组件挂载完成"); |
|
|
|
|
|
|
|
|
|
|
|
chatStore.messages.forEach((item) => { |
|
|
|
|
|
if (item.sender == "user") { |
|
|
|
|
|
item.audioStatus = false; |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
// 添加页面可见性变化监听器 |
|
|
// 添加页面可见性变化监听器 |
|
|
document.addEventListener("visibilitychange", handleVisibilityChange); |
|
|
document.addEventListener("visibilitychange", handleVisibilityChange); |
|
|
|
|
|
|
|
@ -4337,12 +4377,12 @@ onUnmounted(() => { |
|
|
<!-- 用户消息容器,包含喇叭按钮 --> |
|
|
<!-- 用户消息容器,包含喇叭按钮 --> |
|
|
<div v-if="msg.sender === 'user'" class="user-message-container"> |
|
|
<div v-if="msg.sender === 'user'" class="user-message-container"> |
|
|
<img |
|
|
<img |
|
|
:src="isVoice && audioStore.isPlaying ? voiceNoActive : voice" |
|
|
|
|
|
|
|
|
:src="msg.audioStatus ? voice : voiceNoActive" |
|
|
class="user-message-speaker" |
|
|
class="user-message-speaker" |
|
|
:class="{ |
|
|
:class="{ |
|
|
'speaker-active': isVoice && audioStore.isPlaying, |
|
|
|
|
|
|
|
|
'speaker-active': msg.audioStatus, |
|
|
}" |
|
|
}" |
|
|
@click="toggleVoiceForUser" |
|
|
|
|
|
|
|
|
@click="toggleVoiceForUser(index)" |
|
|
alt="喇叭" |
|
|
alt="喇叭" |
|
|
/> |
|
|
/> |
|
|
<div |
|
|
<div |
|
|