IM聊天功能优化
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<a-list item-layout="horizontal" :data-source="unreadList" :locale="locale">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item class="im-chat-msg-item" @click="handleOpenChat(item)">
|
||||
<template #actions>
|
||||
<span class="im-chat-msg-time">{{ formatTime(item.lastTime) }}</span>
|
||||
</template>
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<div class="im-chat-msg-title">
|
||||
<span class="im-chat-msg-name">{{ item.realname || item.username }}</span>
|
||||
<a-badge :count="item.unreadCount" :overflow-count="99" />
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="im-chat-msg-preview">{{ formatPreview(item.lastContent) }}</div>
|
||||
</template>
|
||||
<template #avatar>
|
||||
<a-badge dot :offset="[-2, 2]">
|
||||
<a-avatar :src="getAvatarUrl(item.avatar)">
|
||||
{{ (item.realname || item.username || '?').slice(0, 1) }}
|
||||
</a-avatar>
|
||||
</a-badge>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-spin>
|
||||
|
||||
<ImChatModal @register="registerImChatModal" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
||||
import { fetchDeptMembers } from '/@/views/system/im/im.api';
|
||||
import { formatImMessagePreview } from '/@/views/system/im/imMessageUtil';
|
||||
import { syncImUnreadFromMembers } from '/@/views/system/im/useImUnread';
|
||||
import ImChatModal from '/@/views/system/im/ImChatModal.vue';
|
||||
import { openImChat } from '/@/views/system/im/imSession';
|
||||
|
||||
defineOptions({ name: 'SysImChatMessageList' });
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'closeModal'): void;
|
||||
}>();
|
||||
|
||||
interface ChatMemberItem {
|
||||
id: string;
|
||||
username: string;
|
||||
realname?: string;
|
||||
avatar?: string;
|
||||
conversationId?: string;
|
||||
lastContent?: string;
|
||||
lastTime?: string;
|
||||
unreadCount?: number;
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
const members = ref<ChatMemberItem[]>([]);
|
||||
const [registerImChatModal, { openModal: openImChatModal }] = useModal();
|
||||
|
||||
const unreadList = computed(() =>
|
||||
members.value
|
||||
.filter((item) => (item.unreadCount || 0) > 0)
|
||||
.sort((a, b) => dayjs(b.lastTime || 0).valueOf() - dayjs(a.lastTime || 0).valueOf()),
|
||||
);
|
||||
|
||||
const locale = computed(() => ({
|
||||
emptyText: loading.value ? ' ' : '暂无未读聊天消息',
|
||||
}));
|
||||
|
||||
function getAvatarUrl(avatar?: string) {
|
||||
return avatar ? getFileAccessHttpUrl(avatar) : '';
|
||||
}
|
||||
|
||||
function formatPreview(content?: string) {
|
||||
return formatImMessagePreview(content) || '发来一条新消息';
|
||||
}
|
||||
|
||||
function formatTime(value?: string) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const d = dayjs(value);
|
||||
if (!d.isValid()) {
|
||||
return '';
|
||||
}
|
||||
if (d.isSame(dayjs(), 'day')) {
|
||||
return d.format('HH:mm');
|
||||
}
|
||||
return d.format('MM-DD HH:mm');
|
||||
}
|
||||
|
||||
async function reload(silent = false) {
|
||||
//update-begin---author:cursor ---date:20250528 for:【IM聊天-OA】聊天消息列表静默刷新,避免 spin 遮罩闪烁-----------
|
||||
const showLoading = !silent && members.value.length === 0;
|
||||
if (showLoading) {
|
||||
loading.value = true;
|
||||
}
|
||||
try {
|
||||
members.value = ((await fetchDeptMembers()) || []) as ChatMemberItem[];
|
||||
syncImUnreadFromMembers(members.value);
|
||||
} catch {
|
||||
if (!silent) {
|
||||
members.value = [];
|
||||
}
|
||||
} finally {
|
||||
if (showLoading) {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20250528 for:【IM聊天-OA】聊天消息列表静默刷新,避免 spin 遮罩闪烁-----------
|
||||
}
|
||||
|
||||
async function handleOpenChat(item: ChatMemberItem) {
|
||||
//update-begin---author:xsl ---date:20260528 for:【IM聊天-OA】统一 IM 打开入口,全页优先-----------
|
||||
const mode = await openImChat({ targetUserId: item.id, pageContext: null });
|
||||
if (mode === 'modal') {
|
||||
openImChatModal(true, { targetUserId: item.id, pageContext: null });
|
||||
}
|
||||
//update-end---author:xsl ---date:20260528 for:【IM聊天-OA】统一 IM 打开入口,全页优先-----------
|
||||
emit('closeModal');
|
||||
}
|
||||
|
||||
defineExpose({ reload });
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.im-chat-msg-item {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s;
|
||||
|
||||
&:hover {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
}
|
||||
|
||||
.im-chat-msg-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.im-chat-msg-name {
|
||||
font-weight: 500;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
}
|
||||
|
||||
.im-chat-msg-preview {
|
||||
color: #666;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 520px;
|
||||
}
|
||||
|
||||
.im-chat-msg-time {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user