123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- <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 config from "@/request/config";
- import { ref, watch, onMounted, onUnmounted } from "../../../adapter-vue";
- import { TUIStore, StoreName, IConversationModel } from "@tencentcloud/chat-uikit-engine";
- import { TUIGlobal } from "@tencentcloud/universal-api";
- import { transformEmojiValueToKey } from "../utils/emojiList";
- 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,
- },
- jobInfoData: {
- type: Object,
- 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>();
- onMounted(() => {
- TUIStore.watch(StoreName.CONV, {
- currentConversation: onCurrentConversationUpdated,
- });
- uni.$on("insert-emoji", (data) => {
- inputText.value += data?.emoji?.name;
- });
- uni.$on("send-message-in-emoji-picker", () => {
- handleSendMessage();
- });
- });
- onUnmounted(() => {
- uni.$off("insertEmoji");
- uni.$off("send-message-in-emoji-picker");
- TUIStore.unwatch(StoreName.CONV, {
- currentConversation: onCurrentConversationUpdated,
- });
- });
- const handleSendMessage = () => {
- const messageList = getEditorContent();
- resetEditor();
- // sendMessages(messageList as any, currentConversation.value!); // im官方发送消息通信方法
- // 发送消息后本地存储文本
- let url = config.baseUrl + "/recruit/recruitCommunicate";
- const header = {
- "Content-Type": "application/json",
- Authorization: uni.getStorageSync("token")
- ? uni.getStorageSync("token")
- : uni.getStorageSync("unitoken"),
- };
- let data = {
- companyUserId: props.jobInfoData.companyUserId,
- msgContent: {
- text: {
- text: messageList[0].payload.text,
- },
- },
- msgType: "TIMTextElem",
- postId: props.jobInfoData.postId,
- recruitUserId: props.jobInfoData.recruitUserId,
- sendType: 0,
- status: props.jobInfoData.status,
- };
- let loginType = uni.getStorageSync("loginType");
- if (loginType == 1) {
- data.sendType = 1;
- }
- uni.request({
- url: url,
- method: "POST",
- header: header,
- data: data,
- success: function (res) {
- console.log(res.data);
- },
- });
- };
- 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 = transformEmojiValueToKey(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) => {
- // uniapp 识别 @ 消息
- 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) {
- currentConversation.value = conversation;
- }
- defineExpose({
- insertAt,
- resetEditor,
- setEditorContent,
- getEditorContent,
- });
- </script>
- <style lang="scss" scoped>
- @import "../../../assets/styles/common";
- .message-input-container {
- display: flex;
- flex-direction: column;
- flex: 1;
- height: calc(100% - 13px);
- width: calc(100% - 20px);
- padding: 3px 10px 10px;
- overflow: hidden;
- &-h5 {
- flex: 1;
- height: auto;
- background: #fff;
- border-radius: 9.4px;
- 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;
- display: flex;
- overflow-y: scroll;
- min-height: 20px;
- }
- }
- </style>
|