客服聊天列表使用scroll-view原生组件,移除 z-paging 组件
parent
f6e74b12cb
commit
dd71ba7d9e
|
|
@ -19,13 +19,13 @@
|
||||||
class="sicon-edit"
|
class="sicon-edit"
|
||||||
:class="{ 'is-active': toolsMode === 'tools' }"
|
:class="{ 'is-active': toolsMode === 'tools' }"
|
||||||
@tap.stop="onTools('tools')"
|
@tap.stop="onTools('tools')"
|
||||||
></text>
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="message"
|
v-if="message"
|
||||||
class="ss-reset-button send-btn"
|
class="ss-reset-button send-btn"
|
||||||
@tap="sendMessage"
|
@tap="sendMessage"
|
||||||
:disabled="isDisabled || sending"
|
:disabled="isDisabled || sending"
|
||||||
:class="{ 'disabled': isDisabled || sending }"
|
:class="{ disabled: isDisabled || sending }"
|
||||||
>
|
>
|
||||||
<text v-if="sending">发送中</text>
|
<text v-if="sending">发送中</text>
|
||||||
<text v-else>发送</text>
|
<text v-else>发送</text>
|
||||||
|
|
@ -52,18 +52,18 @@
|
||||||
// 是否自动获取焦点
|
// 是否自动获取焦点
|
||||||
autoFocus: {
|
autoFocus: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
// 最大字数限制
|
// 最大字数限制
|
||||||
maxLength: {
|
maxLength: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 500
|
default: 500,
|
||||||
},
|
},
|
||||||
// 是否显示字数统计
|
// 是否显示字数统计
|
||||||
showCharCount: {
|
showCharCount: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits(['update:modelValue', 'onTools', 'sendMessage']);
|
const emits = defineEmits(['update:modelValue', 'onTools', 'sendMessage']);
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
},
|
},
|
||||||
set(newValue) {
|
set(newValue) {
|
||||||
emits(`update:modelValue`, newValue);
|
emits(`update:modelValue`, newValue);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 控制发送状态
|
// 控制发送状态
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 聊天列表使用scroll-view原生组件,整体倒置 -->
|
<!-- 聊天列表使用scroll-view原生组件,整体倒置 -->
|
||||||
<scroll-view :scroll-top="scroll.top" class="chat-scroll-view" scroll-y :refresher-enabled="false"
|
<scroll-view
|
||||||
@scroll="onScroll" @scrolltolower="loadMoreHistory" style="transform: scaleY(-1);">
|
:scroll-top="scroll.top"
|
||||||
|
class="chat-scroll-view"
|
||||||
|
scroll-y
|
||||||
|
:refresher-enabled="false"
|
||||||
|
@scroll="onScroll"
|
||||||
|
@scrolltolower="loadMoreHistory"
|
||||||
|
style="transform: scaleY(-1)"
|
||||||
|
>
|
||||||
<!-- 消息列表容器 -->
|
<!-- 消息列表容器 -->
|
||||||
<view class="message-container">
|
<view class="message-container">
|
||||||
<!-- 加载更多提示 -->
|
<!-- 加载更多提示 -->
|
||||||
<view v-if="isLoading" class="loading-more" style="transform: scaleY(-1);">
|
<view v-if="isLoading" class="loading-more" style="transform: scaleY(-1)">
|
||||||
<text>加载中...</text>
|
<text>加载中...</text>
|
||||||
</view>
|
</view>
|
||||||
<!-- 消息列表 -->
|
<!-- 消息列表 -->
|
||||||
<view class="message-list">
|
<view class="message-list">
|
||||||
<view v-for="(item, index) in messageList" :key="item.id" class="message-item"
|
<view
|
||||||
style="transform: scaleY(-1);">
|
v-for="(item, index) in messageList"
|
||||||
|
:key="item.id"
|
||||||
|
class="message-item"
|
||||||
|
style="transform: scaleY(-1)"
|
||||||
|
>
|
||||||
<!-- 消息渲染 -->
|
<!-- 消息渲染 -->
|
||||||
<MessageListItem :message="item" :message-index="index" :message-list="messageList"></MessageListItem>
|
<MessageListItem
|
||||||
|
:message="item"
|
||||||
|
:message-index="index"
|
||||||
|
:message-list="messageList"
|
||||||
|
></MessageListItem>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -22,7 +37,9 @@
|
||||||
<!-- 底部聊天输入框 -->
|
<!-- 底部聊天输入框 -->
|
||||||
<su-fixed bottom>
|
<su-fixed bottom>
|
||||||
<view v-if="showTip" class="back-top ss-flex ss-row-center ss-m-b-10" @tap="scrollToTop">
|
<view v-if="showTip" class="back-top ss-flex ss-row-center ss-m-b-10" @tap="scrollToTop">
|
||||||
<text class="back-top-item ss-flex ss-row-center">{{ showNewMessageTip ? '有新消息' : '回到底部' }}</text>
|
<text class="back-top-item ss-flex ss-row-center">
|
||||||
|
{{ showNewMessageTip ? '有新消息' : '回到底部' }}
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<slot name="bottom"></slot>
|
<slot name="bottom"></slot>
|
||||||
</su-fixed>
|
</su-fixed>
|
||||||
|
|
@ -33,7 +50,7 @@
|
||||||
import { onMounted, reactive, ref, computed } from 'vue';
|
import { onMounted, reactive, ref, computed } from 'vue';
|
||||||
import KeFuApi from '@/sheep/api/promotion/kefu';
|
import KeFuApi from '@/sheep/api/promotion/kefu';
|
||||||
import { isEmpty } from '@/sheep/helper/utils';
|
import { isEmpty } from '@/sheep/helper/utils';
|
||||||
import { formatDate } from '@/sheep/util';
|
import { formatDate } from '@/sheep/helper/utils';
|
||||||
import sheep from '@/sheep';
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
const { safeAreaInsets } = sheep.$platform.device;
|
const { safeAreaInsets } = sheep.$platform.device;
|
||||||
|
|
@ -95,8 +112,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤掉已存在的消息
|
// 过滤掉已存在的消息
|
||||||
const historyMessages = data.filter(msg =>
|
const historyMessages = data.filter(
|
||||||
!messageList.value.some(existing => existing.id === msg.id),
|
(msg) => !messageList.value.some((existing) => existing.id === msg.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (historyMessages.length > 0) {
|
if (historyMessages.length > 0) {
|
||||||
|
|
@ -187,10 +204,16 @@
|
||||||
// H5环境
|
// H5环境
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
// 窗口大小变化可能是由键盘引起的
|
// 窗口大小变化可能是由键盘引起的
|
||||||
if (document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA')) {
|
if (
|
||||||
|
document.activeElement &&
|
||||||
|
(document.activeElement.tagName === 'INPUT' ||
|
||||||
|
document.activeElement.tagName === 'TEXTAREA')
|
||||||
|
) {
|
||||||
// 估算键盘高度,实际上是窗口高度变化
|
// 估算键盘高度,实际上是窗口高度变化
|
||||||
const currentHeight = window.innerHeight;
|
const currentHeight = window.innerHeight;
|
||||||
const viewportHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
|
const viewportHeight = window.visualViewport
|
||||||
|
? window.visualViewport.height
|
||||||
|
: window.innerHeight;
|
||||||
const keyboardHeight = currentHeight - viewportHeight;
|
const keyboardHeight = currentHeight - viewportHeight;
|
||||||
setKeyboardHeight(keyboardHeight > 0 ? keyboardHeight : 0);
|
setKeyboardHeight(keyboardHeight > 0 ? keyboardHeight : 0);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -213,7 +236,7 @@
|
||||||
scroll.value = {
|
scroll.value = {
|
||||||
top: 0,
|
top: 0,
|
||||||
oldTop: 0,
|
oldTop: 0,
|
||||||
}
|
};
|
||||||
getMessageList();
|
getMessageList();
|
||||||
setupKeyboardListeners();
|
setupKeyboardListeners();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
"
|
"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
lazy-load
|
lazy-load
|
||||||
></image>
|
/>
|
||||||
<!-- 内容 -->
|
<!-- 内容 -->
|
||||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
|
<template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
|
||||||
<view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
|
<view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
:height="200"
|
:height="200"
|
||||||
:width="200"
|
:width="200"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></su-image>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
|
<template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
// 缓存表情映射
|
// 缓存表情映射
|
||||||
const emojiMap = computed(() => {
|
const emojiMap = computed(() => {
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
emojiList.forEach(emoji => {
|
emojiList.forEach((emoji) => {
|
||||||
map.set(emoji.name, emoji.file);
|
map.set(emoji.name, emoji.file);
|
||||||
});
|
});
|
||||||
return map;
|
return map;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue