选择发送日期
-
+
@@ -785,18 +789,19 @@ function locateMessage(messageId: number) {
border-radius: 1px;
}
-/* :deep 穿透 el-calendar 子组件 DOM;默认偏大压一压让它能塞进 320 popover */
-.im-message-history__calendar :deep(.el-calendar) {
- 40px: 36px;
-}
-.im-message-history__calendar :deep(.el-calendar__header) {
+/* :deep 穿透 antd Calendar(fullscreen=false 卡片模式)子 DOM,压一压塞进 320 popover */
+.im-message-history__calendar :deep(.ant-picker-calendar-header) {
padding: 4px 8px;
}
-.im-message-history__calendar :deep(.el-calendar-table) {
+.im-message-history__calendar :deep(.ant-picker-content) {
font-size: 12px;
}
-.im-message-history__calendar :deep(.el-calendar-day) {
- height: 36px;
- padding: 4px;
+.im-message-history__calendar :deep(.ant-picker-cell) {
+ padding: 1px 0;
+}
+.im-message-history__calendar :deep(.ant-picker-cell .ant-picker-calendar-date) {
+ height: 28px;
+ margin: 0 2px;
+ padding: 2px 4px 0;
}
diff --git a/apps/web-antd/src/views/im/home/pages/conversation/components/message/message-panel.vue b/apps/web-antd/src/views/im/home/pages/conversation/components/message/message-panel.vue
index cd1abcdab..908de3a92 100644
--- a/apps/web-antd/src/views/im/home/pages/conversation/components/message/message-panel.vue
+++ b/apps/web-antd/src/views/im/home/pages/conversation/components/message/message-panel.vue
@@ -13,7 +13,7 @@ import { getCurrentUserId } from '#/views/im/utils/auth'
import { ImConversationType, ImRtcCallMediaType, ImRtcCallStatus } from '#/views/im/utils/constants'
import { getClientConversationId } from '#/views/im/utils/db'
import { resolveCallEndReasonText } from '#/views/im/utils/message'
-import { getMemberDisplayName, isGroupQuit } from '#/views/im/utils/user'
+import { getGroupDisplayName, getMemberDisplayName, isGroupQuit } from '#/views/im/utils/user'
import { GroupMuteMemberDialog } from '../../../../components/group'
import {
@@ -185,10 +185,11 @@ const groupInfo = computed<
}
const group = groupStore.getGroup(conversation.targetId)
const selfMember = group?.members?.find((member) => member.userId === getCurrentUserId())
+ const showGroupName = group ? getGroupDisplayName(group) : conversation.name
return {
id: conversation.targetId,
name: group?.name || conversation.name,
- showGroupName: group?.name || conversation.name,
+ showGroupName,
showImage: group?.avatar || conversation.avatar,
notice: group?.notice,
remarkNickName: selfMember?.displayUserName,
diff --git a/apps/web-antd/src/views/im/home/pages/conversation/index.vue b/apps/web-antd/src/views/im/home/pages/conversation/index.vue
index 9aa947c73..b18421510 100644
--- a/apps/web-antd/src/views/im/home/pages/conversation/index.vue
+++ b/apps/web-antd/src/views/im/home/pages/conversation/index.vue
@@ -10,6 +10,7 @@ import { Button, Dropdown, Input, Menu } from 'ant-design-vue'
import { ImConversationType } from '../../../utils/constants'
import { filterConversationsByKeyword, getConversationKey } from '../../../utils/conversation'
import { StorageKeys } from '../../../utils/db'
+import { getGroupDisplayName } from '../../../utils/user'
import { ResizableAside } from '../../components'
import { FriendAddDialog } from '../../components/friend'
import { GroupCreateDialog } from '../../components/group'
@@ -124,7 +125,7 @@ function handleGroupCreated(groupId: number) {
conversationStore.openConversation(
groupId,
ImConversationType.GROUP,
- group.name,
+ getGroupDisplayName(group),
group.avatar || '',
{ silent: !!group.silent }
)
diff --git a/apps/web-antd/src/views/im/home/store/groupStore.ts b/apps/web-antd/src/views/im/home/store/groupStore.ts
index 161d21c40..adacf614f 100644
--- a/apps/web-antd/src/views/im/home/store/groupStore.ts
+++ b/apps/web-antd/src/views/im/home/store/groupStore.ts
@@ -223,7 +223,7 @@ export const useGroupStore = defineStore('imGroupStore', {
return
}
const fresh = (list || []).map((group) => convertGroup(group))
- // 合并而非全量替换:silent / groupRemark / 成员缓存这些字段不在 ImGroupApi.GroupRespVO 里,得从旧 group 保留
+ // 合并而非全量替换:成员缓存只在成员列表接口维护,群个人设置以群列表接口为准
const groupMap = new Map(this.groups.map((group) => [group.id, group]))
this.groups = fresh.map((group) => {
const existing = groupMap.get(group.id)
@@ -234,8 +234,6 @@ export const useGroupStore = defineStore('imGroupStore', {
...group,
members: existing.members,
memberCount: existing.memberCount ?? group.memberCount,
- silent: existing.silent ?? group.silent,
- groupRemark: existing.groupRemark,
membersLoaded: existing.membersLoaded,
membersExpired: existing.membersExpired
}
@@ -250,6 +248,24 @@ export const useGroupStore = defineStore('imGroupStore', {
})
}
this.saveGroupList()
+ this.preloadMembersForEmptyAvatarGroups()
+ },
+
+ /** 预加载空群头像的成员列表,供 GroupAvatar 异步合成群头像 */
+ preloadMembersForEmptyAvatarGroups() {
+ for (const group of this.groups) {
+ if (
+ group.avatar ||
+ group.joinStatus === CommonStatusEnum.DISABLE ||
+ (group.membersLoaded && !group.membersExpired && group.members?.length)
+ ) {
+ continue
+ }
+ const force = !!group.membersLoaded && !group.membersExpired && !group.members?.length
+ this.fetchGroupMemberList(group.id, force).catch((error) => {
+ console.warn('[IM groupStore] 预加载群头像成员失败', { groupId: group.id }, error)
+ })
+ }
},
/** 失效全部群成员缓存 */
@@ -908,7 +924,9 @@ function convertGroup(group: ImGroupApi.GroupRespVO): Group {
mutedAll: group.mutedAll,
banned: group.banned,
joinApproval: group.joinApproval,
- joinStatus: group.joinStatus
+ joinStatus: group.joinStatus,
+ groupRemark: group.groupRemark,
+ silent: group.silent
}
}
diff --git a/apps/web-antd/src/views/im/home/store/websocketStore.ts b/apps/web-antd/src/views/im/home/store/websocketStore.ts
index 03e4da9f8..682311ef3 100644
--- a/apps/web-antd/src/views/im/home/store/websocketStore.ts
+++ b/apps/web-antd/src/views/im/home/store/websocketStore.ts
@@ -45,7 +45,7 @@ import {
playAudioTip,
resolveCallEndReasonText
} from '../../utils/message'
-import { getFriendDisplayName } from '../../utils/user'
+import { getFriendDisplayName, getGroupDisplayName } from '../../utils/user'
import { useConversationStore } from './conversationStore'
import { type FriendNotificationPayload, useFriendStore } from './friendStore'
import { useGroupRequestStore } from './groupRequestStore'
@@ -781,7 +781,7 @@ export const useImWebSocketStore = defineStore('imWebSocketStore', {
{
type: ImConversationType.GROUP,
targetId: websocketMessage.groupId,
- name: group?.name || String(websocketMessage.groupId),
+ name: group ? getGroupDisplayName(group) : String(websocketMessage.groupId),
avatar: group?.avatar || '',
silent: group?.silent
},
diff --git a/apps/web-antd/src/views/im/manager/message/data.ts b/apps/web-antd/src/views/im/manager/message/data.ts
index 0129e7ff9..06ab5d01a 100644
--- a/apps/web-antd/src/views/im/manager/message/data.ts
+++ b/apps/web-antd/src/views/im/manager/message/data.ts
@@ -35,7 +35,7 @@ export function usePrivateGridFormSchema(): VbenFormSchema[] {
component: 'Select',
componentProps: {
allowClear: true,
- options: getDictOptions(DICT_TYPE.IM_MESSAGE_TYPE, 'number'),
+ options: getDictOptions(DICT_TYPE.IM_CONTENT_TYPE, 'number'),
placeholder: '请选择内容类型',
},
},
@@ -84,7 +84,7 @@ export function usePrivateGridColumns(showReadColumns: boolean): VxeTableGridOpt
width: 100,
cellRender: {
name: 'CellDict',
- props: { type: DICT_TYPE.IM_MESSAGE_TYPE },
+ props: { type: DICT_TYPE.IM_CONTENT_TYPE },
},
},
{
@@ -101,7 +101,17 @@ export function usePrivateGridColumns(showReadColumns: boolean): VxeTableGridOpt
width: 100,
cellRender: {
name: 'CellDict',
- props: { type: DICT_TYPE.IM_PRIVATE_MESSAGE_STATUS },
+ props: { type: DICT_TYPE.IM_MESSAGE_STATUS },
+ },
+ },
+ {
+ field: 'receiptStatus',
+ title: '回执',
+ width: 110,
+ cellRender: {
+ name: 'CellDict',
+ // 回执状态(私聊 / 群聊共用 im_message_receipt_status),与源端「回执」列对齐
+ props: { type: DICT_TYPE.IM_MESSAGE_RECEIPT_STATUS },
},
},
]
@@ -143,7 +153,7 @@ export function useGroupGridFormSchema(): VbenFormSchema[] {
component: 'Select',
componentProps: {
allowClear: true,
- options: getDictOptions(DICT_TYPE.IM_MESSAGE_TYPE, 'number'),
+ options: getDictOptions(DICT_TYPE.IM_CONTENT_TYPE, 'number'),
placeholder: '请选择内容类型',
},
},
@@ -192,7 +202,7 @@ export function useGroupGridColumns(showReadColumns: boolean): VxeTableGridOptio
width: 100,
cellRender: {
name: 'CellDict',
- props: { type: DICT_TYPE.IM_MESSAGE_TYPE },
+ props: { type: DICT_TYPE.IM_CONTENT_TYPE },
},
},
{
@@ -214,7 +224,7 @@ export function useGroupGridColumns(showReadColumns: boolean): VxeTableGridOptio
width: 100,
cellRender: {
name: 'CellDict',
- props: { type: DICT_TYPE.IM_GROUP_MESSAGE_STATUS },
+ props: { type: DICT_TYPE.IM_MESSAGE_STATUS },
},
},
{
@@ -223,7 +233,7 @@ export function useGroupGridColumns(showReadColumns: boolean): VxeTableGridOptio
width: 110,
cellRender: {
name: 'CellDict',
- props: { type: DICT_TYPE.IM_GROUP_MESSAGE_RECEIPT_STATUS },
+ props: { type: DICT_TYPE.IM_MESSAGE_RECEIPT_STATUS },
},
},
]
diff --git a/apps/web-antd/src/views/im/manager/message/group/modules/detail.vue b/apps/web-antd/src/views/im/manager/message/group/modules/detail.vue
index 57490f346..2b4f01095 100644
--- a/apps/web-antd/src/views/im/manager/message/group/modules/detail.vue
+++ b/apps/web-antd/src/views/im/manager/message/group/modules/detail.vue
@@ -48,14 +48,14 @@ defineExpose({ open });
{{ formatUserLabel(detail.senderNickname, detail.senderId) }}
-
+
-
+
diff --git a/apps/web-antd/src/views/im/manager/message/private/modules/detail.vue b/apps/web-antd/src/views/im/manager/message/private/modules/detail.vue
index 486b9eaca..27e0a0495 100644
--- a/apps/web-antd/src/views/im/manager/message/private/modules/detail.vue
+++ b/apps/web-antd/src/views/im/manager/message/private/modules/detail.vue
@@ -13,6 +13,7 @@ import {
formatJsonText,
formatUserLabel,
} from '#/views/im/manager/utils/format';
+import { MESSAGE_PRIVATE_READ_ENABLED } from '#/views/im/utils/config';
import { MessageContentPreview } from '../..';
@@ -44,10 +45,17 @@ defineExpose({ open });
{{ formatUserLabel(detail.receiverNickname, detail.receiverId) }}
-
+
-
+
+
+
+
+
{{ formatDateTimeText(detail.sendTime) }}
diff --git a/apps/web-antd/src/views/im/manager/statistics/components/distribution-chart.vue b/apps/web-antd/src/views/im/manager/statistics/components/distribution-chart.vue
index b3f391f61..e95a230da 100644
--- a/apps/web-antd/src/views/im/manager/statistics/components/distribution-chart.vue
+++ b/apps/web-antd/src/views/im/manager/statistics/components/distribution-chart.vue
@@ -56,7 +56,7 @@ async function loadData() {
const data = await getMessageTypeDistribution();
const items = data.map((item) => ({
name:
- getDictObj(DICT_TYPE.IM_MESSAGE_TYPE, String(item.type))?.label ||
+ getDictObj(DICT_TYPE.IM_CONTENT_TYPE, String(item.type))?.label ||
`未知(${item.type})`,
value: item.value,
}));
diff --git a/packages/constants/src/dict-enum.ts b/packages/constants/src/dict-enum.ts
index ae431d905..73e0095e3 100644
--- a/packages/constants/src/dict-enum.ts
+++ b/packages/constants/src/dict-enum.ts
@@ -178,17 +178,16 @@ const IOT_DICT = {
/** ========== IM - 即时通讯模块 ========== */
const IM_DICT = {
IM_CHANNEL_MATERIAL_TYPE: 'im_channel_material_type', // IM 频道素材类型
+ IM_CONTENT_TYPE: 'im_content_type', // IM 消息内容类型
IM_FRIEND_ADD_SOURCE: 'im_friend_add_source', // IM 好友添加来源
IM_FRIEND_REQUEST_HANDLE_RESULT: 'im_friend_request_handle_result', // IM 好友申请处理结果
IM_FRIEND_STATUS: 'im_friend_status', // IM 好友状态
IM_GROUP_ADD_SOURCE: 'im_group_add_source', // IM 加群来源
IM_GROUP_MEMBER_ROLE: 'im_group_member_role', // IM 群成员角色
- IM_GROUP_MESSAGE_RECEIPT_STATUS: 'im_group_message_receipt_status', // IM 群消息回执状态
- IM_GROUP_MESSAGE_STATUS: 'im_group_message_status', // IM 群聊消息状态
IM_GROUP_REQUEST_HANDLE_RESULT: 'im_group_request_handle_result', // IM 加群申请处理结果
IM_GROUP_STATUS: 'im_group_status', // IM 群状态
- IM_MESSAGE_TYPE: 'im_message_type', // IM 消息类型
- IM_PRIVATE_MESSAGE_STATUS: 'im_private_message_status', // IM 私聊消息状态
+ IM_MESSAGE_RECEIPT_STATUS: 'im_message_receipt_status', // IM 消息回执状态(私聊 / 群聊共用)
+ IM_MESSAGE_STATUS: 'im_message_status', // IM 消息状态(私聊 / 群聊共用)
IM_RTC_CALL_CONVERSATION_TYPE: 'im_rtc_call_conversation_type', // IM 通话会话类型
IM_RTC_CALL_END_REASON: 'im_rtc_call_end_reason', // IM 通话结束原因
IM_RTC_CALL_MEDIA_TYPE: 'im_rtc_call_media_type', // IM 通话媒体类型