2023-12-01 03:36:04 +00:00
|
|
|
|
<template>
|
2024-05-21 10:32:48 +00:00
|
|
|
|
<div>
|
|
|
|
|
|
<el-text type="info">
|
|
|
|
|
|
<span class="ml-4">{{ datetimeFormat(data.create_time) }}</span>
|
|
|
|
|
|
</el-text>
|
|
|
|
|
|
</div>
|
2023-12-01 03:36:04 +00:00
|
|
|
|
<div>
|
2024-09-13 07:47:05 +00:00
|
|
|
|
<!-- 语音播放 -->
|
|
|
|
|
|
<span v-if="tts">
|
|
|
|
|
|
<el-tooltip effect="dark" content="语音播放" placement="top">
|
|
|
|
|
|
<el-button text :disabled="!data?.write_ed" @click="playAnswerText(data?.answer_text)">
|
|
|
|
|
|
<AppIcon iconName="VideoPlay"></AppIcon>
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
<el-divider direction="vertical" />
|
|
|
|
|
|
</span>
|
2024-05-28 02:41:36 +00:00
|
|
|
|
<el-tooltip effect="dark" content="换个答案" placement="top">
|
2024-05-28 10:24:00 +00:00
|
|
|
|
<el-button :disabled="chat_loading" text @click="regeneration">
|
2024-09-13 07:47:05 +00:00
|
|
|
|
<el-icon><RefreshRight /></el-icon>
|
2023-12-01 03:36:04 +00:00
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
<el-divider direction="vertical" />
|
|
|
|
|
|
<el-tooltip effect="dark" content="复制" placement="top">
|
2023-12-01 10:21:49 +00:00
|
|
|
|
<el-button text @click="copyClick(data?.answer_text)">
|
2023-12-01 03:36:04 +00:00
|
|
|
|
<AppIcon iconName="app-copy"></AppIcon>
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
<el-divider direction="vertical" />
|
2023-12-01 10:21:49 +00:00
|
|
|
|
<el-tooltip
|
|
|
|
|
|
effect="dark"
|
|
|
|
|
|
content="赞同"
|
|
|
|
|
|
placement="top"
|
|
|
|
|
|
v-if="buttonData?.vote_status === '-1'"
|
|
|
|
|
|
>
|
2023-12-04 07:23:09 +00:00
|
|
|
|
<el-button text @click="voteHandle('0')" :disabled="loading">
|
2023-12-01 03:36:04 +00:00
|
|
|
|
<AppIcon iconName="app-like"></AppIcon>
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
2023-12-01 10:21:49 +00:00
|
|
|
|
<el-tooltip
|
|
|
|
|
|
effect="dark"
|
|
|
|
|
|
content="取消赞同"
|
|
|
|
|
|
placement="top"
|
2023-12-04 07:23:09 +00:00
|
|
|
|
v-if="buttonData?.vote_status === '0'"
|
2023-12-01 10:21:49 +00:00
|
|
|
|
>
|
|
|
|
|
|
<el-button text @click="voteHandle('-1')" :disabled="loading">
|
2023-12-01 03:36:04 +00:00
|
|
|
|
<AppIcon iconName="app-like-color"></AppIcon>
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
2023-12-01 10:21:49 +00:00
|
|
|
|
<el-divider direction="vertical" v-if="buttonData?.vote_status === '-1'" />
|
|
|
|
|
|
<el-tooltip
|
|
|
|
|
|
effect="dark"
|
|
|
|
|
|
content="反对"
|
|
|
|
|
|
placement="top"
|
|
|
|
|
|
v-if="buttonData?.vote_status === '-1'"
|
|
|
|
|
|
>
|
2023-12-04 07:23:09 +00:00
|
|
|
|
<el-button text @click="voteHandle('1')" :disabled="loading">
|
2023-12-01 03:36:04 +00:00
|
|
|
|
<AppIcon iconName="app-oppose"></AppIcon>
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
2023-12-01 10:21:49 +00:00
|
|
|
|
<el-tooltip
|
|
|
|
|
|
effect="dark"
|
|
|
|
|
|
content="取消反对"
|
|
|
|
|
|
placement="top"
|
2023-12-04 07:23:09 +00:00
|
|
|
|
v-if="buttonData?.vote_status === '1'"
|
2023-12-01 10:21:49 +00:00
|
|
|
|
>
|
|
|
|
|
|
<el-button text @click="voteHandle('-1')" :disabled="loading">
|
2023-12-01 03:36:04 +00:00
|
|
|
|
<AppIcon iconName="app-oppose-color"></AppIcon>
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
</div>
|
2024-09-13 07:47:05 +00:00
|
|
|
|
<!-- 先渲染,不然不能播放 -->
|
|
|
|
|
|
<audio ref="audioPlayer" controls hidden="hidden"></audio>
|
2023-12-01 03:36:04 +00:00
|
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
2024-05-20 09:50:14 +00:00
|
|
|
|
import { ref } from 'vue'
|
2023-12-01 03:36:04 +00:00
|
|
|
|
import { copyClick } from '@/utils/clipboard'
|
2023-12-01 10:21:49 +00:00
|
|
|
|
import applicationApi from '@/api/application'
|
2024-05-21 10:32:48 +00:00
|
|
|
|
import { datetimeFormat } from '@/utils/time'
|
2023-12-01 10:21:49 +00:00
|
|
|
|
const props = defineProps({
|
2023-12-01 03:36:04 +00:00
|
|
|
|
data: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => {}
|
2023-12-01 10:21:49 +00:00
|
|
|
|
},
|
|
|
|
|
|
applicationId: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: ''
|
|
|
|
|
|
},
|
2024-05-20 09:50:14 +00:00
|
|
|
|
chatId: {
|
2023-12-01 10:21:49 +00:00
|
|
|
|
type: String,
|
|
|
|
|
|
default: ''
|
2023-12-07 11:28:38 +00:00
|
|
|
|
},
|
2024-05-28 10:24:00 +00:00
|
|
|
|
chat_loading: {
|
|
|
|
|
|
type: Boolean
|
|
|
|
|
|
},
|
2024-09-13 07:47:05 +00:00
|
|
|
|
log: Boolean,
|
2024-09-14 06:24:23 +00:00
|
|
|
|
tts: Boolean,
|
|
|
|
|
|
tts_type: String
|
2023-12-01 03:36:04 +00:00
|
|
|
|
})
|
|
|
|
|
|
|
2023-12-01 11:17:58 +00:00
|
|
|
|
const emit = defineEmits(['update:data', 'regeneration'])
|
2023-12-01 03:36:04 +00:00
|
|
|
|
|
2024-09-13 07:47:05 +00:00
|
|
|
|
const audioPlayer = ref<HTMLAudioElement | null>(null)
|
2023-12-01 10:21:49 +00:00
|
|
|
|
const buttonData = ref(props.data)
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
|
2023-12-07 11:28:38 +00:00
|
|
|
|
function regeneration() {
|
2023-12-01 11:17:58 +00:00
|
|
|
|
emit('regeneration')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-01 10:21:49 +00:00
|
|
|
|
function voteHandle(val: string) {
|
|
|
|
|
|
applicationApi
|
2024-05-20 09:50:14 +00:00
|
|
|
|
.putChatVote(props.applicationId, props.chatId, props.data.record_id, val, loading)
|
|
|
|
|
|
.then(() => {
|
2023-12-01 10:21:49 +00:00
|
|
|
|
buttonData.value['vote_status'] = val
|
|
|
|
|
|
emit('update:data', buttonData.value)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2024-09-13 07:47:05 +00:00
|
|
|
|
|
|
|
|
|
|
const playAnswerText = (text: string) => {
|
2024-09-14 06:24:23 +00:00
|
|
|
|
if (props.tts_type === 'BROWSER') {
|
2024-09-13 07:47:05 +00:00
|
|
|
|
// 创建一个新的 SpeechSynthesisUtterance 实例
|
|
|
|
|
|
const utterance = new SpeechSynthesisUtterance(text)
|
|
|
|
|
|
// 调用浏览器的朗读功能
|
|
|
|
|
|
window.speechSynthesis.speak(utterance)
|
|
|
|
|
|
}
|
2024-09-14 06:24:23 +00:00
|
|
|
|
if (props.tts_type === 'TTS') {
|
2024-09-13 07:47:05 +00:00
|
|
|
|
applicationApi
|
2024-09-14 06:24:23 +00:00
|
|
|
|
.postTextToSpeech(props.applicationId as string, { text: text }, loading)
|
2024-09-13 07:47:05 +00:00
|
|
|
|
.then((res: any) => {
|
|
|
|
|
|
// 假设我们有一个 MP3 文件的字节数组
|
|
|
|
|
|
// 创建 Blob 对象
|
|
|
|
|
|
const blob = new Blob([res], { type: 'audio/mp3' })
|
|
|
|
|
|
|
|
|
|
|
|
// 创建对象 URL
|
|
|
|
|
|
const url = URL.createObjectURL(blob)
|
|
|
|
|
|
|
|
|
|
|
|
// 测试blob是否能正常播放
|
|
|
|
|
|
// const link = document.createElement('a')
|
|
|
|
|
|
// link.href = window.URL.createObjectURL(blob)
|
|
|
|
|
|
// link.download = "abc.mp3"
|
|
|
|
|
|
// link.click()
|
|
|
|
|
|
|
|
|
|
|
|
// 检查 audioPlayer 是否已经引用了 DOM 元素
|
|
|
|
|
|
if (audioPlayer.value instanceof HTMLAudioElement) {
|
|
|
|
|
|
audioPlayer.value.src = url
|
|
|
|
|
|
audioPlayer.value.play() // 自动播放音频
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('audioPlayer.value is not an instance of HTMLAudioElement')
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
|
console.log('err: ', err)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-01 03:36:04 +00:00
|
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped></style>
|