This commit is contained in:
pengxiaolong
2025-05-13 19:39:53 +08:00
parent 37da6765b8
commit c006a8e63d
1232 changed files with 96963 additions and 883 deletions

View File

@@ -0,0 +1,101 @@
<template>
<div class="message-convert-container">
<div
v-if="convertFinished"
:class="{
'convert-content': true,
'occur': true,
}"
>
{{ convertText }}
</div>
<div
:class="{
'loading': true,
'loading-end': convertFinished
}"
>
{{ TUITranslateService.t('TUIChat.转换中') }}...
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from '../../../../../adapter-vue';
import {
IMessageModel,
TUITranslateService,
} from '@tencentcloud/chat-uikit-engine';
import { convertor } from '../../../utils/convertVoiceToText';
interface IProps {
message: IMessageModel;
contentVisible: boolean;
}
interface IEmits {
(e: 'toggleErrorStatus', status: boolean): void;
}
const emits = defineEmits<IEmits>();
const props = withDefaults(defineProps<IProps>(), {
message: () => ({} as IMessageModel),
isSingleConvert: false,
});
const convertFinished = ref<boolean>(false);
const convertText = ref<string>('');
watch(() => props.contentVisible, (newVal: boolean) => {
if (newVal) {
convertor.get(props.message)
.then((text) => {
convertFinished.value = true;
convertText.value = text;
})
.catch((err) => {
convertFinished.value = true;
emits('toggleErrorStatus', true);
convertText.value = err.message;
});
}
}, {
immediate: true,
});
</script>
<style lang="scss" scoped>
.message-convert-container {
min-height: 20px;
min-width: 80px;
position: relative;
transition: width 0.15s ease-out, height 0.15s ease-out, ;
font-size: 14px;
.loading {
position: absolute;
top: 0;
left: 0;
opacity: 1;
transition: opacity 0.3s ease-out;
&.loading-end {
opacity: 0;
}
}
.convert-content {
opacity: 0;
&.occur {
animation: occur 0.3s ease-out 0.45s forwards;
@keyframes occur {
100% {
opacity: 1;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div
v-if="convertVisible"
ref="convertWrapperRef"
:class="{
'message-convert': true,
'reverse': props.message.flow === 'out',
'error': hasConvertError,
}"
>
<ConvertContent
:message="props.message"
:contentVisible="convertVisible"
:isSingleConvert="isSingleConvert"
:convertWrapperRef="convertWrapperRef"
@toggleErrorStatus="toggleErrorStatus"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted } from '../../../../../adapter-vue';
import {
TUIStore,
StoreName,
IMessageModel,
} from '@tencentcloud/chat-uikit-engine';
import ConvertContent from './convert-content.vue';
import { IConvertInfo } from '../../../../../interface';
interface IProps {
message: IMessageModel;
}
const props = withDefaults(defineProps<IProps>(), {
message: () => ({} as IMessageModel),
});
const convertVisible = ref<boolean>(false);
const hasConvertError = ref<boolean>(false);
const convertWrapperRef = ref<HTMLDivElement>();
let isSingleConvert = true;
onMounted(() => {
TUIStore.watch(StoreName.CHAT, {
voiceToTextInfo: onMessageConvertUpdated,
});
});
onUnmounted(() => {
TUIStore.unwatch(StoreName.CHAT, {
voiceToTextInfo: onMessageConvertUpdated,
});
});
function toggleErrorStatus(hasError: boolean) {
hasConvertError.value = hasError;
}
function onMessageConvertUpdated(info: Map<string, IConvertInfo[]>) {
if (info === undefined) return;
isSingleConvert = false;
const convertInfoList = info.get(props.message.conversationID) || [];
for (let i = 0; i < convertInfoList.length; ++i) {
const { messageID, visible } = convertInfoList[i];
if (messageID === props.message.ID && visible !== undefined) {
if (convertInfoList.length === 1 && visible) {
isSingleConvert = true;
}
hasConvertError.value = false;
convertVisible.value = visible;
break;
}
}
}
</script>
<style lang="scss" scoped>
.message-convert {
margin-top: 4px;
margin-left: 44px;
padding: 10px;
background-color: #f2f7ff;
border-radius: 10px;
display: flex;
flex-direction: column !important;
transition: background-color 0.15s ease-out;
&.error {
background-color: #ffdfdf;
}
}
.message-convert.reverse {
margin-right: 44px;
margin-left: auto;
}
</style>