|
|
@ -1,7 +1,7 @@ |
|
|
|
<script setup> |
|
|
|
import { ref, onMounted, watch, nextTick } from "vue"; |
|
|
|
import { ElDialog } from "element-plus"; |
|
|
|
import { getReplyStreamAPI, getReplyAPI, TTSAPI, getQuestionAPI } from "../api/AIxiaocaishen"; |
|
|
|
import { getReplyStreamAPI, getReplyAPI, TTSAPI, getQuestionAPI, qsArpAamClickAPI } from "../api/AIxiaocaishen"; |
|
|
|
import { useUserStore } from '../store/userPessionCode' |
|
|
|
import { useChatStore } from '../store/chat' |
|
|
|
import { useAudioStore } from '../store/audio' |
|
|
@ -31,7 +31,14 @@ const emit = defineEmits(["updateMessage", "sendMessage"]); |
|
|
|
// 弹窗控制 |
|
|
|
const dialogVisible = ref(false); |
|
|
|
const currentQuestions = ref(""); |
|
|
|
const showQuestions = (questions) => { |
|
|
|
const showQuestions = async (questions) => { |
|
|
|
|
|
|
|
const click = await qsArpAamClickAPI({ |
|
|
|
token: localStorage.getItem('localToken'), |
|
|
|
id: questions.id |
|
|
|
}) |
|
|
|
console.log(click); |
|
|
|
|
|
|
|
currentQuestions.value = questions; |
|
|
|
// 触发自定义事件 |
|
|
|
emit("updateMessage", questions.title); |
|
|
@ -40,37 +47,75 @@ const showQuestions = (questions) => { |
|
|
|
|
|
|
|
// 音频播放方法 |
|
|
|
const playAudio = (url) => { |
|
|
|
if (audioStore.soundInstance) { |
|
|
|
audioStore.soundInstance.stop() |
|
|
|
|
|
|
|
// 添加空值校验 |
|
|
|
if (!url) { |
|
|
|
console.warn('音频URL为空,跳过播放'); |
|
|
|
audioStore.isPlaying = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const newSound = new Howl({ |
|
|
|
src: [url], |
|
|
|
html5: true, // 强制HTML5 Audio解决iOS兼容问题 |
|
|
|
format: ['mp3', 'wav'], |
|
|
|
onplay: () => { |
|
|
|
audioStore.isPlaying = true // 改为更新store状态 |
|
|
|
newSound.volume(1) // 添加音量设置 |
|
|
|
}, |
|
|
|
onend: () => audioStore.isPlaying = false, |
|
|
|
onstop: () => audioStore.isPlaying = false, |
|
|
|
onloaderror: (id, err) => { |
|
|
|
console.error('音频加载失败:', err); |
|
|
|
ElMessage.error('音频播放失败,请检查网络连接'); |
|
|
|
|
|
|
|
const handlePlay = () => { |
|
|
|
if (audioStore.soundInstance) { |
|
|
|
Howler.unload(); // 添加清理旧实例 |
|
|
|
// audioStore.soundInstance.stop() |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 添加立即播放逻辑 |
|
|
|
newSound.play() |
|
|
|
audioStore.setAudioInstance(newSound); |
|
|
|
const newSound = new Howl({ |
|
|
|
src: [url], |
|
|
|
html5: true, // 强制HTML5 Audio解决iOS兼容问题 |
|
|
|
format: ['mp3', 'acc'], |
|
|
|
onplay: () => { |
|
|
|
audioStore.isPlaying = true // 改为更新store状态 |
|
|
|
newSound.volume(1) // 添加音量设置 |
|
|
|
}, |
|
|
|
onend: () => audioStore.isPlaying = false, |
|
|
|
onstop: () => audioStore.isPlaying = false, |
|
|
|
onloaderror: (id, err) => { |
|
|
|
console.error('音频加载失败:', err); |
|
|
|
ElMessage.error('音频播放失败,请检查网络连接'); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
// 添加立即播放逻辑 |
|
|
|
newSound.play() |
|
|
|
|
|
|
|
// 处理浏览器自动播放策略 |
|
|
|
if (Howler.autoUnlock) { |
|
|
|
Howler.autoUnlock(); |
|
|
|
audioStore.setAudioInstance(newSound); |
|
|
|
Howler._howls.push(newSound); // 强制注册到全局管理 |
|
|
|
// // 处理浏览器自动播放策略 |
|
|
|
// if (Howler.autoUnlock) { |
|
|
|
// Howler.autoUnlock(); |
|
|
|
// } |
|
|
|
} |
|
|
|
|
|
|
|
Howler.volume(1.0) // 添加全局音量设置 |
|
|
|
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) { |
|
|
|
document.addEventListener('touchstart', handlePlay, { once: true }); |
|
|
|
ElMessage.info('请轻触屏幕以启用音频播放'); |
|
|
|
} else { |
|
|
|
handlePlay(); |
|
|
|
} |
|
|
|
|
|
|
|
// Howler.volume(1.0) // 添加全局音量设置 |
|
|
|
|
|
|
|
}; |
|
|
|
// 新增暂停方法 |
|
|
|
const pauseAudio = () => { |
|
|
|
if (audioStore.soundInstance) { |
|
|
|
// 添加移动端特殊处理 |
|
|
|
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) { |
|
|
|
Howler.stop(); // iOS需要强制停止音频上下文 |
|
|
|
} else { |
|
|
|
audioStore.soundInstance.pause(); |
|
|
|
} |
|
|
|
audioStore.isPlaying = false; |
|
|
|
|
|
|
|
// 添加状态同步 |
|
|
|
nextTick(() => { |
|
|
|
Howler.unload(); |
|
|
|
audioStore.soundInstance = null; |
|
|
|
}); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 获取消息 |
|
|
@ -180,9 +225,15 @@ watch( |
|
|
|
|
|
|
|
const AIcontent = ref(""); |
|
|
|
// 处理不同的 answer 字段 |
|
|
|
const status = JSON.parse(ans.value.resp); |
|
|
|
|
|
|
|
var status; |
|
|
|
if (ans.value.resp !== "") { |
|
|
|
status = JSON.parse(ans.value.resp); |
|
|
|
} else { |
|
|
|
status = null; |
|
|
|
} |
|
|
|
console.log(status, "status") |
|
|
|
if (status.code == 200) { |
|
|
|
if (status === null || status.code == 200) { |
|
|
|
if (ans.value.answerG !== "") { |
|
|
|
AIcontent.value = ans.value.answerG; |
|
|
|
const code = ans.value.code; |
|
|
@ -268,8 +319,10 @@ watch( |
|
|
|
|
|
|
|
const ttsUrl = ref(); |
|
|
|
if (tts.value.tts_cn !== null) { |
|
|
|
audioStore.ttsUrl = tts.value.tts_cn.url; |
|
|
|
ttsUrl.value = tts.value.tts_cn.url; |
|
|
|
} else if (tts.value.tts_en !== null) { |
|
|
|
audioStore.ttsUrl = tts.value.tts_en.url; |
|
|
|
ttsUrl.value = tts.value.tts_en.url; |
|
|
|
} |
|
|
|
|
|
|
@ -322,6 +375,7 @@ watch( |
|
|
|
sender: "ai", |
|
|
|
content: status.msg |
|
|
|
}); |
|
|
|
|
|
|
|
chatStore.setLoading(false); |
|
|
|
} |
|
|
|
|
|
|
@ -329,6 +383,7 @@ watch( |
|
|
|
} |
|
|
|
catch (e) { |
|
|
|
console.error('请求失败:', e); |
|
|
|
chatStore.messages.pop(); |
|
|
|
chatStore.messages.push({ |
|
|
|
sender: "ai", |
|
|
|
content: "AI思考失败,请稍后再试... ", |
|
|
@ -362,7 +417,40 @@ watch( |
|
|
|
|
|
|
|
// }) |
|
|
|
// } |
|
|
|
|
|
|
|
watch( |
|
|
|
() => audioStore.isVoiceEnabled, |
|
|
|
(newVal) => { |
|
|
|
// 添加状态锁定逻辑 |
|
|
|
if (newVal === audioStore.lastVoiceState) return; |
|
|
|
audioStore.lastVoiceState = newVal; |
|
|
|
|
|
|
|
if (newVal) { |
|
|
|
console.log("开启语音播放"); |
|
|
|
// 添加重试机制 |
|
|
|
const tryPlay = () => { |
|
|
|
if (!audioStore.ttsUrl) return; // 新增空值判断 |
|
|
|
if (audioStore.soundInstance?.playing()) return; |
|
|
|
playAudio(audioStore.ttsUrl); |
|
|
|
setTimeout(() => { |
|
|
|
if (!audioStore.soundInstance?.playing()) { |
|
|
|
Howler.unload(); |
|
|
|
} |
|
|
|
}, 1000); |
|
|
|
}; |
|
|
|
tryPlay(); |
|
|
|
} else { |
|
|
|
console.log("关闭语音播放"); |
|
|
|
// 强制停止并释放资源 |
|
|
|
Howler.stop(); |
|
|
|
Howler.unload(); |
|
|
|
if (audioStore.soundInstance) { |
|
|
|
audioStore.soundInstance.off(); // 移除所有事件监听 |
|
|
|
audioStore.soundInstance = null; |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
{ immediate: true } |
|
|
|
) |
|
|
|
|
|
|
|
// 初始化随机GIF |
|
|
|
onMounted(() => { |
|
|
@ -429,7 +517,7 @@ onMounted(() => { |
|
|
|
.chat-container { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
overflow-x: hidden; |
|
|
|
overflow: hidden; |
|
|
|
} |
|
|
|
|
|
|
|
.gif-area { |
|
|
|