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
186 lines
3.4 KiB
Vue
<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>
|