You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
3.4 KiB
Vue

4 months ago
<template>
<view class="chat">
<view
v-for="m in messages"
:key="m.id"
:id="'msg-' + m.id"
:class="['msg', m.role]"
>
<view v-if="m.role === 'user'" class="bubble user-bubble">
<text v-if="m.inputType === 'text'">{{ m.content }}</text>
<view
class="text-voice"
v-if="m.inputType === 'voice'"
@tap="playVoice(m)"
>
<text>{{ m.duration }}</text>
<image
class="voice-play"
src="@/static/voice-play.png"
mode="widthFix"
></image>
</view>
</view>
<view v-else class="bubble ai-bubble">
<view v-if="m.type === 'card'" class="ai-card">
<view class="ai-card-title">{{ m.title }}</view>
<view class="ai-card-body">{{ m.content }}</view>
</view>
<view v-else-if="m.loading" class="ai-loading">
<view class="loading-dot"></view>
<view class="loading-dot"></view>
<view class="loading-dot"></view>
</view>
<view v-else>
<text>{{
m.displayText !== undefined ? m.displayText : m.content
}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
messages: {
type: Array,
default() {
return [];
},
},
},
methods: {
playVoice(voicePath) {
console.log('voicePath',voicePath);
// if (!voicePath) {
// uni.showToast({
// title: "无可播放的语音",
// icon: "none",
// });
// return;
// }
// if (!this.innerAudioContext) {
// this.innerAudioContext = uni.createInnerAudioContext();
// this.innerAudioContext.autoplay = false;
// this.innerAudioContext.onError(() => {
// uni.showToast({
// title: "播放失败",
// icon: "none",
// });
// });
// }
// try {
// this.innerAudioContext.stop();
// } catch (e) {}
// this.innerAudioContext.src = voicePath;
// this.innerAudioContext.play();
},
},
};
</script>
<style scoped>
.chat {
margin: 6px 0 12px;
}
.msg {
/* margin: 10px 0; */
display: flex;
margin-bottom: 10px;
padding-bottom: 10px;
}
.msg.user {
justify-content: flex-end;
}
.bubble {
max-width: 80%;
padding: 10px 12px;
border-radius: 14px;
font-size: 14px;
line-height: 1.5;
}
.user-bubble {
background: #4e7bff;
color: #fff;
border-bottom-right-radius: 4px;
margin-right: 6px;
}
.ai-bubble {
background: #fff;
color: #333;
border-bottom-left-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.listen-btn {
margin-left: 8px;
color: #6b7280;
font-size: 14px;
}
.ai-card-title {
color: #5f6fff;
font-weight: 600;
margin-bottom: 6px;
}
.ai-card-body {
color: #666;
}
/* loading animation */
.ai-loading {
display: flex;
align-items: center;
gap: 6px;
padding: 4px 0;
}
.loading-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #9ca3af;
animation: loading-bounce 1.5s ease-in-out infinite both;
}
.loading-dot:nth-child(1) {
animation-delay: -0.32s;
}
.loading-dot:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes loading-bounce {
0%,
80%,
100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1.2);
opacity: 1;
}
}
.text-voice {
display: flex;
align-items: center;
}
.voice-play {
width: 20px;
margin-left: 5px;
}
</style>