| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- <template>
- <view class="chat-input-bar-container">
- <reply-message-container
- ref="replyMessageContainerComps"
- v-show="isShowReplyMessageContainer"
- @onShowReplyMessageContainer="onShowReplyMessageContainer"
- :checkedPopupMsgBody="checkedPopupMsgBody"
- />
- <edit-message-container
- v-show="isShowEditMessageContainer"
- @onShowEditMessageContainer="onShowEditMessageContainer"
- />
- <view class="chat-input-bar">
- <!-- <template v-if="!isShowEditMessageContainer">
- <image
- class="chat-audio-icon-container"
- @click="onShowAudioMessageContainer"
- src="/static/images/new_ui/inputbar/audio_click_icon.png"
- ></image>
- </template> -->
- <!-- 文本输入input -->
- <view class="chat-input-container">
- <input
- class="chat-input"
- v-model="msgContent"
- :cursor-spacing="cursorSpacing"
- confirm-type="send"
- type="text"
- :always-embed="true"
- :adjust-position="false"
- @focus="onInputFocus"
- @blur="onInputBlur"
- @confirm="sendTextMessage"
- @input="onInput"
- />
- </view>
- <template v-if="isShowEditMessageContainer">
- <image
- class="chat-emoji-icon-container"
- @click="actionModifyMessage"
- src="/static/images/new_ui/message/send_edit_msg_icon.png"
- ></image>
- </template>
- </view>
- <!-- 输入框底部功能栏 -->
- <view class="chat-input-bottom-bar">
- <!-- 语音 -->
- <!-- <view class="input-bottom-bar-icon" @click="onShowAudioMessageContainer">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/mic_stroke@2x.png"
- ></image>
- </view> -->
- <!-- 图库 -->
- <view class="input-bottom-bar-icon" @click="openPhotoAlbum('album')">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/img@2x.png"
- ></image>
- </view>
- <!-- 拍照 -->
- <view class="input-bottom-bar-icon" @click="openPhotoAlbum('camera')">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/camera@2x.png"
- ></image>
- </view>
- <!-- 文件 -->
- <!-- <view class="input-bottom-bar-icon">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/folder@2x.png"
- ></image>
- </view> -->
- <!-- <SendFileMessage
- ref="fileComps"
- @onCloseAllShowContainer="onCloseAllShowContainer"
- >
- <view class="input-bottom-bar-icon">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/folder@2x.png"
- ></image>
- </view>
- </SendFileMessage> -->
- <!-- emoji -->
- <view class="input-bottom-bar-icon" @click="onShowEmojiIconContainer">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/face@2x.png"
- ></image>
- </view>
- <!-- 更多 -->
- <!-- <view class="input-bottom-bar-icon" @click="onShowMoreFuncContainer">
- <image
- src="/static/images/new_ui/inputbar/tofeipeng/icons/plus_in_circle@2x.png"
- ></image>
- </view> -->
- </view>
- <!-- 音频发送板块 -->
- <view v-if="isShowAudioMessageContainer" class="chat-audio-container">
- <RecordAudioContainer
- @changeRecordAudioContainer="
- () => (isShowAudioMessageContainer = false)
- "
- />
- </view>
- <!-- Emoji Icon选择板块 -->
- <view v-if="isShowEmojiIconContainer" class="chat-emoji-picker-container">
- <EmojiPickerContainer @appendEmojiIcon="appendEmojiIcon" />
- </view>
- <!-- 更多功能选择板块 -->
- <view v-if="isShowMoreFuncContainer" class="chat-more-icon-container">
- <MoreFuncContainer @onCloseAllShowContainer="onCloseAllShowContainer" />
- </view>
- <!-- 发送图片 -->
- <SendImageMessage
- ref="imageComps"
- @onCloseAllShowContainer="onCloseAllShowContainer"
- />
- <!-- 软键盘弹起占位容器 -->
- <view
- class="softkeyword-placeholder"
- :style="{ height: softkeyboardHeight + 'px' }"
- ></view>
- <!-- #ifdef H5 || APP-PLUS -->
- <!-- 小程序的宿主一般自带底部安全区 -->
- <view class="chat-input-bar-bottom-placeholder"></view>
- <!-- #endif -->
- </view>
- </template>
- <script>
- import { EMClient } from '@/EaseIM';
- import { CHAT_TYPE } from '@/EaseIM/constant';
- import { emMessages } from '@/EaseIM/emApis';
- import RecordAudioContainer from './recordAudioContainer';
- import EmojiPickerContainer from './emojiPickerContainer';
- import MoreFuncContainer from './moreFuncContainer';
- import ReplyMessageContainer from './replyMessageContainer';
- import EditMessageContainer from './editMessageContainer';
- import SendImageMessage from './inputMessages/sendImageMessage';
- import SendFileMessage from './inputMessages/sendFileMessage';
- import { MESSAGE_TYPE } from '../../../EaseIM/constant';
- const { sendDisplayMessages, sendCommandMessages, modifyDisplayMessages } =
- emMessages();
- export default {
- name: 'chat-input-bar',
- components: {
- RecordAudioContainer,
- EmojiPickerContainer,
- MoreFuncContainer,
- ReplyMessageContainer,
- EditMessageContainer,
- SendImageMessage,
- SendFileMessage,
- },
- props: {
- checkedPopupMsgBody: {
- type: Object,
- default: () => ({}),
- },
- },
- data() {
- return {
- msgContent: '',
- cursorSpacing: 20,
- softkeyboardHeight: 0,
- isShowAudioMessageContainer: false,
- isShowEmojiIconContainer: false,
- isShowMoreFuncContainer: false,
- isShowReplyMessageContainer: false,
- isShowEditMessageContainer: false,
- isOpenedTypingBeginStatus: false,
- };
- },
- mounted() {
- // #ifndef APP-NVUE
- const query = uni.createSelectorQuery().in(this);
- query
- .select('.chat-input-bar-bottom-placeholder')
- .boundingClientRect((data) => {
- if (data && data.height) {
- this.cursorSpacing = data.height + 20;
- }
- })
- .exec();
- // #endif
- this.getLocalInputingStatus();
- //监听键盘高度变化
- //监听键盘抬起事件
- uni.onKeyboardHeightChange &&
- uni.onKeyboardHeightChange(this.listenerKeyboardHeight);
- },
- computed: {
- chattingId() {
- return this.$store.getters.chattingId;
- },
- chattingChatType() {
- return this.$store.getters.chattingChatType;
- },
- },
- methods: {
- onInputFocus() {
- // input focus的时候重新设置一下input内容以修复在微信小程序&QQ小程序中input focus后位置偏移的bug
- // #ifdef MP-WEIXIN || MP-QQ
- // this.msgContent += ' ';
- // this.$nextTick(() => {
- // this.msgContent = this.msgContent.slice(0, -1);
- // });
- // #endif
- this.onCloseAllShowContainer();
- },
- listenerKeyboardHeight(e) {
- if (e.height > 0) {
- this.softkeyboardHeight = e.height;
- } else {
- this.softkeyboardHeight = 0;
- }
- },
- onInputBlur() {
- this.onCloseAllShowContainer();
- },
- onInput() {
- if (
- this.isShowEditMessageContainer === false &&
- this.isOpenedTypingBeginStatus
- ) {
- //节流正在输入中信令发送调用 10s发送一次。
- uni.$u.throttle(this.sendTypingBeginMessage, 10000, true);
- }
- },
- //发送文本消息
- async sendTextMessage() {
- if (this.msgContent.match(/^\s*$/)) {
- uni.showToast({
- title: '请输入内容',
- icon: 'none',
- });
- return;
- }
- let params = {
- // 消息类型。
- type: 'txt',
- // 消息内容。
- msg: this.msgContent,
- // 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。
- to: this.chattingId,
- // 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`。
- chatType: this.chattingChatType,
- ext: {},
- };
- //如果此时为编辑模式则直接return 并调用编辑消息
- if (this.isShowEditMessageContainer) {
- this.actionModifyMessage();
- return;
- }
- //检测是否存在引用消息
- if (this.isShowReplyMessageContainer) {
- params.ext.msgQuote = {};
- params.ext.msgQuote =
- this.$refs.replyMessageContainerComps.extractMessageBodyValue();
- console.log('>>>存在引用', params);
- }
- try {
- const res = await sendDisplayMessages({ ...params });
- console.log('>>>>>文本消息发送成功', res);
- } catch (error) {
- console.log('>>>>>文本消息发送失败', error);
- if (error.type === 508) {
- uni.showToast({
- title: '发送内容不合规',
- icon: 'none',
- });
- } else {
- uni.showToast({
- title: '消息发送失败',
- icon: 'none',
- });
- }
- } finally {
- this.msgContent = '';
- this.onCloseAllShowContainer();
- this.isShowReplyMessageContainer &&
- (this.isShowReplyMessageContainer = false);
- }
- },
- //编辑修改已发送文本消息
- async actionModifyMessage() {
- const editMessageContent = {
- msg: this.msgContent,
- to: this.checkedPopupMsgBody.to,
- id: this.checkedPopupMsgBody.id,
- chatType: CHAT_TYPE.SINGLE_CHAT,
- };
- try {
- const res = await modifyDisplayMessages(editMessageContent);
- console.log('>>>>>>消息修改成功', res);
- } catch (error) {
- console.log('>>>>>>修改消息失败', error);
- if (error?.type === 50) {
- uni.showToast({
- icon: 'none',
- title: '该消息可编辑次数已达上限',
- });
- } else {
- uni.showToast({
- icon: 'none',
- title: '消息编辑失败请稍后重试',
- });
- }
- } finally {
- this.isShowEditMessageContainer = false;
- this.msgContent = '';
- }
- },
- //获取当前键入中开启状态
- getLocalInputingStatus() {
- const res = uni.getStorageSync(`EM_${EMClient.user}_GENNERAL_CONFIG`);
- const { isShowInputingStatus } = res || {};
- this.isOpenedTypingBeginStatus = isShowInputingStatus;
- },
- //发送正在键入command
- async sendTypingBeginMessage() {
- const params = {
- type: MESSAGE_TYPE.CMD,
- // 消息类型。
- action: 'TypingBegin',
- // 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。
- to: this.chattingId,
- // 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`。
- chatType: this.chattingChatType,
- };
- try {
- await sendCommandMessages(params);
- } catch (error) {
- console.log('>>>>>发送失败', error);
- }
- },
- onShowAudioMessageContainer() {
- this.isShowAudioMessageContainer = !this.isShowAudioMessageContainer;
- this.isShowEmojiIconContainer && (this.isShowEmojiIconContainer = false);
- this.isShowMoreFuncContainer && (this.isShowMoreFuncContainer = false);
- this.$emit('resetScrollHeight', 200);
- },
- onShowEmojiIconContainer() {
- this.isShowEmojiIconContainer = !this.isShowEmojiIconContainer;
- this.isShowAudioMessageContainer &&
- (this.isShowAudioMessageContainer = false);
- this.isShowMoreFuncContainer && (this.isShowMoreFuncContainer = false);
- },
- onShowMoreFuncContainer() {
- this.isShowMoreFuncContainer = !this.isShowMoreFuncContainer;
- this.isShowAudioMessageContainer &&
- (this.isShowAudioMessageContainer = false);
- this.isShowEmojiIconContainer && (this.isShowEmojiIconContainer = false);
- },
- onShowReplyMessageContainer() {
- this.isShowReplyMessageContainer = !this.isShowReplyMessageContainer;
- this.isShowEditMessageContainer &&
- (this.isShowEditMessageContainer = false);
- this.onCloseAllShowContainer();
- },
- onShowEditMessageContainer() {
- if (this.isShowEditMessageContainer === false) {
- this.msgContent = this.checkedPopupMsgBody.msg;
- }
- this.isShowEditMessageContainer = !this.isShowEditMessageContainer;
- this.isShowReplyMessageContainer &&
- (this.isShowReplyMessageContainer = false);
- this.onCloseAllShowContainer();
- },
- onCloseAllShowContainer() {
- this.isShowAudioMessageContainer = false;
- this.isShowEmojiIconContainer = false;
- this.isShowMoreFuncContainer = false;
- },
- appendEmojiIcon(emoji) {
- this.msgContent += emoji;
- },
- appendReEditTextMessage(content) {
- if (this.msgContent !== '') {
- this.msgContent += content;
- } else {
- this.msgContent = content;
- }
- },
- openPhotoAlbum(type) {
- if (type === 'camera') {
- this.$refs.imageComps.openCamera();
- } else if (type === 'album') {
- this.$refs.imageComps.openPhotoAlbum();
- }
- },
- },
- beforeDestroy() {
- uni.offKeyboardHeightChange &&
- uni.offKeyboardHeightChange(this.listenerKeyboardHeight);
- },
- };
- </script>
- <style scoped>
- .chat-input-bar {
- display: flex;
- flex-direction: row;
- align-items: center;
- border-top: solid 1px #f5f5f5;
- background-color: #f8f8f8;
- padding: 10rpx 15rpx;
- }
- .chat-input-bar-bottom-placeholder {
- background-color: #f8f8f8;
- /* #ifndef APP-PLUS */
- height: env(safe-area-inset-bottom);
- /* #endif */
- }
- .softkeyword-placeholder {
- width: 100%;
- background-color: white;
- }
- .chat-input-container {
- flex: 1;
- display: flex;
- /* #ifndef APP-NVUE */
- padding: 15rpx;
- /* #endif */
- /* #ifdef APP-NVUE */
- padding: 10rpx;
- /* #endif */
- background-color: white;
- border-radius: 10rpx;
- }
- .chat-input-bottom-bar {
- width: 100%;
- height: 100rpx;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- padding: 0 50rpx;
- box-sizing: border-box;
- background-color: white;
- }
- .input-bottom-bar-icon {
- width: 60rpx;
- height: 60rpx;
- }
- .input-bottom-bar-icon image {
- width: 100%;
- height: 100%;
- }
- .chat-input {
- flex: 1;
- font-size: 28rpx;
- }
- .chat-input-send {
- background-color: #007aff;
- margin: 10rpx 10rpx 10rpx 20rpx;
- border-radius: 10rpx;
- padding: 10rpx 30rpx;
- }
- .chat-input-send-text {
- color: white;
- font-size: 26rpx;
- }
- .chat-audio-icon-container,
- .chat-emoji-icon-container,
- .chat-cancel-icon-container {
- width: 30px;
- height: 30px;
- }
- .chat-audio-container {
- width: 100%;
- height: 200px;
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-around;
- background: #fff;
- }
- .chat-emoji-picker-container {
- width: 100%;
- /* height: 300px; */
- background: #fff;
- }
- </style>
|