123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- <template>
- <div
- :class="{
- 'message-input-container': true,
- 'message-input-container-h5': !isPC,
- }"
- >
- <div
- v-if="props.isMuted"
- class="message-input-mute"
- >
- {{ props.muteText }}
- </div>
- <input
- id="editor"
- ref="inputRef"
- v-model="inputText"
- :adjust-position="true"
- cursor-spacing="20"
- confirm-type="send"
- :confirm-hold="true"
- maxlength="140"
- type="text"
- placeholder-class="input-placeholder"
- class="message-input-area"
- :placeholder="props.placeholder"
- auto-blur
- @confirm="handleSendMessage"
- @input="onInput"
- @blur="onBlur"
- @focus="onFocus"
- >
- </div>
- </template>
- <script lang="ts" setup>
- import { ref, watch, onMounted, onUnmounted } from '../../../adapter-vue';
- import { TUIStore, StoreName, IConversationModel, IMessageModel } from '@tencentcloud/chat-uikit-engine';
- import { TUIGlobal } from '@tencentcloud/universal-api';
- import DraftManager from '../utils/conversationDraft';
- import { transformTextWithEmojiNamesToKeys } from '../emoji-config';
- import { isPC } from '../../../utils/env';
- import { sendMessages } from '../utils/sendMessage';
- import { ISendMessagePayload } from '../../../interface';
- const props = defineProps({
- placeholder: {
- type: String,
- default: 'this is placeholder',
- },
- replayOrReferenceMessage: {
- type: Object,
- default: () => ({}),
- required: false,
- },
- isMuted: {
- type: Boolean,
- default: true,
- },
- muteText: {
- type: String,
- default: '',
- },
- enableInput: {
- type: Boolean,
- default: true,
- },
- enableAt: {
- type: Boolean,
- default: true,
- },
- enableTyping: {
- type: Boolean,
- default: true,
- },
- isGroup: {
- type: Boolean,
- default: false,
- },
- });
- const emits = defineEmits(['onTyping', 'onFocus', 'onAt']);
- const inputText = ref('');
- const inputRef = ref();
- const inputBlur = ref(true);
- const inputContentEmpty = ref(true);
- const allInsertedAtInfo = new Map();
- const currentConversation = ref<IConversationModel>();
- const currentConversationID = ref<string>('');
- const currentQuoteMessage = ref<{ message: IMessageModel; type: string }>();
- onMounted(() => {
- TUIStore.watch(StoreName.CONV, {
- currentConversation: onCurrentConversationUpdated,
- });
- TUIStore.watch(StoreName.CHAT, {
- quoteMessage: onQuoteMessageUpdated,
- });
- uni.$on('insert-emoji', (data) => {
- inputText.value += data?.emoji?.name;
- });
- uni.$on('send-message-in-emoji-picker', () => {
- handleSendMessage();
- });
- });
- onUnmounted(() => {
- if (currentConversationID.value) {
- DraftManager.setStore(currentConversationID.value, inputText.value, inputText.value, currentQuoteMessage.value);
- }
- uni.$off('insertEmoji');
- uni.$off('send-message-in-emoji-picker');
- TUIStore.unwatch(StoreName.CONV, {
- currentConversation: onCurrentConversationUpdated,
- });
- TUIStore.unwatch(StoreName.CHAT, {
- quoteMessage: onQuoteMessageUpdated,
- });
- reset();
- });
- const handleSendMessage = () => {
- const messageList = getEditorContent();
- resetEditor();
- sendMessages(messageList as any, currentConversation.value!);
- };
- const insertAt = (atInfo: any) => {
- if (!allInsertedAtInfo?.has(atInfo?.id)) {
- allInsertedAtInfo?.set(atInfo?.id, atInfo?.label);
- }
- inputText.value += atInfo?.label;
- };
- const getEditorContent = () => {
- let text = inputText.value;
- text = transformTextWithEmojiNamesToKeys(text);
- const atUserList: string[] = [];
- allInsertedAtInfo?.forEach((value: string, key: string) => {
- if (text?.includes('@' + value)) {
- atUserList.push(key);
- }
- });
- const payload: ISendMessagePayload = {
- text,
- };
- if (atUserList?.length) {
- payload.atUserList = atUserList;
- }
- return [
- {
- type: 'text',
- payload,
- },
- ];
- };
- const resetEditor = () => {
- inputText.value = '';
- inputContentEmpty.value = true;
- allInsertedAtInfo?.clear();
- };
- const setEditorContent = (content: any) => {
- inputText.value = content;
- };
- const onBlur = () => {
- inputBlur.value = true;
- };
- const onFocus = (e: any) => {
- inputBlur.value = false;
- emits('onFocus', e?.detail?.height);
- };
- const isEditorContentEmpty = () => {
- inputContentEmpty.value = inputText?.value?.length ? false : true;
- };
- const onInput = (e: any) => {
- // uni-app recognizes mention messages
- const text = e?.detail?.value;
- isEditorContentEmpty();
- if (props.isGroup && (text.endsWith('@') || text.endsWith('@\n'))) {
- TUIGlobal?.hideKeyboard();
- emits('onAt', true);
- }
- };
- watch(
- () => [inputContentEmpty.value, inputBlur.value],
- (newVal: any, oldVal: any) => {
- if (newVal !== oldVal) {
- emits('onTyping', inputContentEmpty.value, inputBlur.value);
- }
- },
- {
- immediate: true,
- deep: true,
- },
- );
- function onCurrentConversationUpdated(conversation: IConversationModel) {
- const prevConversationID = currentConversationID.value;
- currentConversation.value = conversation;
- currentConversationID.value = conversation?.conversationID;
- if (prevConversationID !== currentConversationID.value) {
- if (prevConversationID) {
- DraftManager.setStore(
- prevConversationID,
- inputText.value,
- inputText.value,
- currentQuoteMessage.value,
- );
- }
- resetEditor();
- if (currentConversationID.value) {
- DraftManager.getStore(currentConversationID.value, setEditorContent);
- }
- }
- }
- function onQuoteMessageUpdated(options?: { message: IMessageModel; type: string }) {
- currentQuoteMessage.value = options;
- }
- function reset() {
- inputBlur.value = true;
- currentConversation.value = null;
- currentConversationID.value = '';
- currentQuoteMessage.value = null;
- resetEditor();
- }
- defineExpose({
- insertAt,
- resetEditor,
- setEditorContent,
- getEditorContent,
- });
- </script>
- <style lang="scss" scoped>
- @import "../../../assets/styles/common";
- .message-input-container {
- display: flex;
- flex-direction: column;
- flex: 1;
- padding: 3px 10px 10px;
- overflow: hidden;
- &-h5 {
- flex: 1;
- height: auto;
- background: #fff;
- border-radius: 10px;
- padding: 7px 0 7px 10px;
- font-size: 16px !important;
- max-height: 86px;
- }
- .message-input-mute {
- flex: 1;
- display: flex;
- color: #999;
- font-size: 14px;
- justify-content: center;
- align-items: center;
- }
- .message-input-area {
- flex: 1;
- overflow-y: scroll;
- min-height: 25px;
- }
- }
- </style>
|