Browse Source

输入框提示语修改;修改输入非法内容后的逻辑;修改了音频存储文件,主页加入音频控制。

hongxilin/hotfix-20250625101643-手机输入法弹出输入框上浮
宋杰 1 week ago
parent
commit
c16e8870fa
  1. 55
      src/store/audio.js
  2. 43
      src/views/AiEmotion.vue
  3. 32
      src/views/homePage.vue

55
src/store/audio.js

@ -9,7 +9,10 @@ export const useAudioStore = defineStore('audio', {
lastVoiceState: null, lastVoiceState: null,
ttsUrl:'', ttsUrl:'',
isNewInstance: false, // 新增是否是新实例的标志 isNewInstance: false, // 新增是否是新实例的标志
nowSound:''
nowSound:'',
currentAudioUrl: '', // 当前音频URL
isPaused: false, // 是否处于暂停状态
duration: 0 // 音频总时长
}), }),
actions: { actions: {
// 设置音频实例 // 设置音频实例
@ -19,19 +22,67 @@ export const useAudioStore = defineStore('audio', {
// 播放控制 // 播放控制
play() { play() {
if (this.soundInstance) { if (this.soundInstance) {
if (this.isPaused && this.playbackPosition > 0) {
// 从暂停位置继续播放
this.soundInstance.seek(this.playbackPosition)
}
this.soundInstance.play() this.soundInstance.play()
this.isPlaying = true this.isPlaying = true
this.isPaused = false
} }
}, },
// 暂停控制 // 暂停控制
pause() { pause() {
if (this.soundInstance) {
if (this.soundInstance && this.isPlaying) {
// 保存当前播放位置
this.playbackPosition = this.soundInstance.seek() || 0
this.soundInstance.pause() this.soundInstance.pause()
this.isPlaying = false this.isPlaying = false
this.isPaused = true
}
},
// 停止播放
stop() {
if (this.soundInstance) {
this.soundInstance.stop()
this.isPlaying = false
this.isPaused = false
this.playbackPosition = 0
} }
}, },
// 切换播放/暂停
togglePlayPause() {
if (this.isPlaying) {
this.pause()
} else {
this.play()
}
},
// 设置当前音频URL
setCurrentAudioUrl(url) {
if (this.currentAudioUrl !== url) {
// 如果是新的音频,重置播放状态
this.stop()
this.currentAudioUrl = url
this.playbackPosition = 0
this.isPaused = false
}
},
// 语音开关控制
toggleVoice() { toggleVoice() {
this.isVoiceEnabled = !this.isVoiceEnabled this.isVoiceEnabled = !this.isVoiceEnabled
if (!this.isVoiceEnabled) {
// 关闭语音时停止当前播放
this.stop()
}
},
// 重置音频状态
resetAudioState() {
this.stop()
this.currentAudioUrl = ''
this.ttsUrl = ''
this.soundInstance = null
this.nowSound = ''
} }
} }
}) })

43
src/views/AiEmotion.vue

@ -693,8 +693,11 @@ function playAudio(url) {
console.log('开始创建音频实例...'); console.log('开始创建音频实例...');
try { try {
// URL
audioStore.setCurrentAudioUrl(url);
// //
if (audioStore.nowSound) {
if (audioStore.nowSound && audioStore.nowSound.playing()) {
audioStore.nowSound.stop(); audioStore.nowSound.stop();
} }
@ -705,19 +708,35 @@ function playAudio(url) {
format: ['mp3', 'wav'], format: ['mp3', 'wav'],
onplay: () => { onplay: () => {
isAudioPlaying.value = true; isAudioPlaying.value = true;
audioStore.isPlaying = true;
console.log('开始播放场景应用语音'); console.log('开始播放场景应用语音');
}, },
onend: () => { onend: () => {
isAudioPlaying.value = false; isAudioPlaying.value = false;
audioStore.isPlaying = false;
audioStore.isPaused = false;
audioStore.playbackPosition = 0;
console.log('场景应用语音播放结束'); console.log('场景应用语音播放结束');
}, },
onstop: () => { onstop: () => {
isAudioPlaying.value = false; isAudioPlaying.value = false;
audioStore.isPlaying = false;
console.log('场景应用语音播放停止'); console.log('场景应用语音播放停止');
}, },
onpause: () => {
isAudioPlaying.value = false;
audioStore.isPlaying = false;
console.log('场景应用语音播放暂停');
},
onerror: (error) => { onerror: (error) => {
isAudioPlaying.value = false; isAudioPlaying.value = false;
audioStore.isPlaying = false;
console.error('音频播放错误:', error); console.error('音频播放错误:', error);
},
onload: () => {
//
audioStore.duration = newSound.duration();
console.log('音频加载完成,时长:', audioStore.duration);
} }
}); });
@ -764,11 +783,6 @@ async function handleSendMessage(input) {
if (input.trim()) { if (input.trim()) {
const userMessage = reactive({ sender: 'user', text: input }); const userMessage = reactive({ sender: 'user', text: input });
messages.value.push(userMessage); messages.value.push(userMessage);
//
isLoading.value = true;
isPageLoaded.value = false;
//
isRotating.value = true;
try { try {
// //
@ -797,6 +811,12 @@ async function handleSendMessage(input) {
if (parsedData && parsedData.market && parsedData.code) { if (parsedData && parsedData.market && parsedData.code) {
console.log("工作流接口返回股票信息:", parsedData); console.log("工作流接口返回股票信息:", parsedData);
//
isLoading.value = true;
isPageLoaded.value = false;
//
isRotating.value = true;
// //
const conclusionParams = { const conclusionParams = {
content: input.trim(), content: input.trim(),
@ -826,16 +846,19 @@ async function handleSendMessage(input) {
emotionStore.updateActiveStockConclusion(conclusionResponse.data); emotionStore.updateActiveStockConclusion(conclusionResponse.data);
} }
} else { } else {
// refuse
ElMessage.error(processRefuseMessage(parsedData.refuse)); ElMessage.error(processRefuseMessage(parsedData.refuse));
return; //
} }
} catch (error) { } catch (error) {
ElMessage.error('请求工作流接口失败,请检查网络连接'); ElMessage.error('请求工作流接口失败,请检查网络连接');
return; //
} finally { } finally {
//
isRotating.value = false;
//
if (isRotating.value) {
isRotating.value = false;
}
} }
} else {
ElMessage.error(processRefuseMessage(parsedData.refuse));
} }
} }

32
src/views/homePage.vue

@ -46,7 +46,19 @@ const chatStore = useChatStore();
const audioStore = useAudioStore(); const audioStore = useAudioStore();
const isVoice = computed(() => audioStore.isVoiceEnabled); const isVoice = computed(() => audioStore.isVoiceEnabled);
const toggleVoice = () => { const toggleVoice = () => {
audioStore.toggleVoice();
if (!audioStore.isVoiceEnabled) {
//
audioStore.toggleVoice();
} else {
// /
if (audioStore.currentAudioUrl || audioStore.ttsUrl) {
// /
audioStore.togglePlayPause();
} else {
//
audioStore.toggleVoice();
}
}
}; };
// sessionStorage 使 'aifindCow'tab // sessionStorage 使 'aifindCow'tab
const activeTab = ref(sessionStorage.getItem("activeTabAI") || "AIchat"); const activeTab = ref(sessionStorage.getItem("activeTabAI") || "AIchat");
@ -570,7 +582,8 @@ onMounted(async () => {
<!-- AI情绪大模型按钮 --> <!-- AI情绪大模型按钮 -->
<img :src="activeTab === 'AiEmotion' ? emotionButton01 : emotionButton02 <img :src="activeTab === 'AiEmotion' ? emotionButton01 : emotionButton02
" @click="setActiveTab('AiEmotion', 1)" class="action-btn model-btn" alt="AI情绪大模型" /> " @click="setActiveTab('AiEmotion', 1)" class="action-btn model-btn" alt="AI情绪大模型" />
<img v-if="isVoice" :src="voice" @click="toggleVoice" class="action-btn" />
<img v-if="audioStore.isVoiceEnabled && !audioStore.isPlaying" :src="voice" @click="toggleVoice" class="action-btn" />
<img v-else-if="audioStore.isVoiceEnabled && audioStore.isPlaying" :src="voice" @click="toggleVoice" class="action-btn" style="opacity: 0.7; animation: pulse 1.5s infinite;" />
<img v-else :src="voiceNoActive" @click="toggleVoice" class="action-btn" /> <img v-else :src="voiceNoActive" @click="toggleVoice" class="action-btn" />
</div> </div>
<img v-if="!chatStore.isLoading" :src="sendBtn" @click="sendMessage" class="action-btn send-btn" /> <img v-if="!chatStore.isLoading" :src="sendBtn" @click="sendMessage" class="action-btn send-btn" />
@ -585,7 +598,7 @@ onMounted(async () => {
<div class="footer-second-line"> <div class="footer-second-line">
<img :src="msgBtn" class="msg-icon" /> <img :src="msgBtn" class="msg-icon" />
<el-input type="textarea" v-model="message" @focus="onFocus" @blur="onBlur" <el-input type="textarea" v-model="message" @focus="onFocus" @blur="onBlur"
:autosize="{ minRows: 1, maxRows: 4 }" placeholder="给AI小财神发消息..." class="msg-input"
:autosize="{ minRows: 1, maxRows: 4 }" placeholder="请输入股票名称或股票代码..." class="msg-input"
@keydown.enter.exact.prevent="isLoading ? null : sendMessage()" resize="none"> @keydown.enter.exact.prevent="isLoading ? null : sendMessage()" resize="none">
</el-input> </el-input>
</div> </div>
@ -949,6 +962,19 @@ body {
margin-right: 5px; margin-right: 5px;
} }
/* 音频播放动画 */
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.footer-second-line { .footer-second-line {
position: relative; position: relative;
display: flex; display: flex;

Loading…
Cancel
Save