♻️ refactor(im): 业务策略数值从 ImCommonConstants 上移到 ImProperties(按 group / message 子模块分组),常量类仅保留 AT_USER_ID_ALL 协议契约值
♻️ refactor(im): 抽出 utils/config.ts 集中数值常量,按业务域统一前缀(GROUP_ / MESSAGE_ / FRIEND_ / CONVERSATION_ / FORWARD_),constants.ts 只留协议枚举与契约值
im
parent
dfd5b39a17
commit
c5b082ca80
|
|
@ -34,7 +34,7 @@ import { ref } from 'vue'
|
|||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
|
||||
import { addGroupAdmin, removeGroupAdmin } from '@/api/im/group'
|
||||
import { GROUP_ADMIN_MAX_COUNT } from '@/views/im/utils/constants'
|
||||
import { GROUP_ADMIN_MAX_COUNT } from '@/views/im/utils/config'
|
||||
import GroupMemberPickerPanel from '../picker/GroupMemberPickerPanel.vue'
|
||||
import type { GroupMemberLite } from './GroupMember.vue'
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,10 @@ import {
|
|||
import {
|
||||
ImConversationType,
|
||||
ImMessageType,
|
||||
PRIVATE_MESSAGE_PULL_SIZE,
|
||||
GROUP_MESSAGE_PULL_SIZE,
|
||||
isFriendChatTip,
|
||||
isFriendNotification
|
||||
} from '../../utils/constants'
|
||||
import { MESSAGE_PRIVATE_PULL_SIZE, MESSAGE_GROUP_PULL_SIZE } from '../../utils/config'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import type { Message } from '../types'
|
||||
|
||||
|
|
@ -109,7 +108,7 @@ export const useMessagePuller = () => {
|
|||
// 私聊 / 群聊各自一套接口和分页大小,按 isPrivate 在循环内分支调度
|
||||
let minId = startMinId || 0
|
||||
const isPrivate = conversationType === ImConversationType.PRIVATE
|
||||
const size = isPrivate ? PRIVATE_MESSAGE_PULL_SIZE : GROUP_MESSAGE_PULL_SIZE
|
||||
const size = isPrivate ? MESSAGE_PRIVATE_PULL_SIZE : MESSAGE_GROUP_PULL_SIZE
|
||||
while (true) {
|
||||
const list = isPrivate
|
||||
? await apiPullPrivateMessages({ minId, size })
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ import Icon from '@/components/Icon/src/Icon.vue'
|
|||
import { formatFileSize } from '@/utils/file'
|
||||
import { formatSeconds } from '@/utils/formatTime'
|
||||
|
||||
import { ImMessageType, MERGE_FORWARD_PREVIEW_LINES } from '@/views/im/utils/constants'
|
||||
import { ImMessageType } from '@/views/im/utils/constants'
|
||||
import { MESSAGE_MERGE_PREVIEW_LINES } from '@/views/im/utils/config'
|
||||
import {
|
||||
parseMessage,
|
||||
parseTextSegments,
|
||||
|
|
@ -259,7 +260,7 @@ const mergePreviewLines = computed(() => {
|
|||
return []
|
||||
}
|
||||
return mergePayload.value.messages
|
||||
.slice(0, MERGE_FORWARD_PREVIEW_LINES)
|
||||
.slice(0, MESSAGE_MERGE_PREVIEW_LINES)
|
||||
.map((item) => `${item.senderNickname}:${summarizeMessageContent(item)}`)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -163,12 +163,12 @@ import {
|
|||
ImConversationType,
|
||||
ImFriendAddSource,
|
||||
ImGroupMemberRole,
|
||||
TIME_TIP_GAP_MS,
|
||||
isFriendChatTip,
|
||||
isGroupNotification,
|
||||
isMediaMessageType,
|
||||
isNormalMessage
|
||||
} from '@/views/im/utils/constants'
|
||||
import { MESSAGE_TIME_TIP_GAP_MS, MESSAGE_RECALL_WINDOW_MS } from '@/views/im/utils/config'
|
||||
import { pinGroupMessage as apiPinGroupMessage, cancelMuteMember } from '@/api/im/group'
|
||||
import { removeGroupMember } from '@/api/im/group/member'
|
||||
import {
|
||||
|
|
@ -254,7 +254,7 @@ const shouldShowTimeTip = computed(() => {
|
|||
if (!props.prevMessage?.sendTime) {
|
||||
return true
|
||||
}
|
||||
return props.message.sendTime - props.prevMessage.sendTime > TIME_TIP_GAP_MS
|
||||
return props.message.sendTime - props.prevMessage.sendTime > MESSAGE_TIME_TIP_GAP_MS
|
||||
})
|
||||
|
||||
/** 仅 MessageItem 自身仍要用到的 type 判定(其它分支已下沉到 MessageBubble) */
|
||||
|
|
@ -477,9 +477,6 @@ const MENU_KEYS = {
|
|||
} as const
|
||||
type MenuKey = (typeof MENU_KEYS)[keyof typeof MENU_KEYS]
|
||||
|
||||
/** 撤回时间窗:自己发送的消息超过这个时长就不能再撤回,菜单回退为「删除」(对齐微信 2 分钟) */
|
||||
const RECALL_WINDOW_MS = 2 * 60 * 1000
|
||||
|
||||
/**
|
||||
* 右键菜单项:
|
||||
* - 引用:已落库(id≠0)+ 未撤回的消息可引用,引用块写入 draftStore.reply
|
||||
|
|
@ -589,7 +586,7 @@ async function handleContextMenu(e: MouseEvent) {
|
|||
props.message.selfSend &&
|
||||
!!props.message.id &&
|
||||
!isRecall.value &&
|
||||
Date.now() - props.message.sendTime <= RECALL_WINDOW_MS
|
||||
Date.now() - props.message.sendTime <= MESSAGE_RECALL_WINDOW_MS
|
||||
if (canRecall) {
|
||||
items.push({
|
||||
key: MENU_KEYS.RECALL,
|
||||
|
|
|
|||
|
|
@ -162,9 +162,9 @@ import {
|
|||
ImConversationType,
|
||||
ImForwardMode,
|
||||
ImMessageType,
|
||||
MERGE_FORWARD_PREVIEW_LINES,
|
||||
type ImForwardModeValue
|
||||
} from '@/views/im/utils/constants'
|
||||
import { MESSAGE_MERGE_PREVIEW_LINES } from '@/views/im/utils/config'
|
||||
import { getConversationKey, summarizeMessageContent } from '@/views/im/utils/conversation'
|
||||
import { buildDefaultGroupName } from '@/views/im/utils/group'
|
||||
import {
|
||||
|
|
@ -271,14 +271,14 @@ const mergePreview = computed(() => {
|
|||
return null
|
||||
}
|
||||
const lines = payload.messages
|
||||
.slice(0, MERGE_FORWARD_PREVIEW_LINES)
|
||||
.slice(0, MESSAGE_MERGE_PREVIEW_LINES)
|
||||
.map((item) => `${item.senderNickname}:${summarizeMessageContent(item)}`)
|
||||
return { title: payload.title, lines }
|
||||
})
|
||||
|
||||
/** 逐条模式预览:取前 N 条摘要 */
|
||||
const singlePreviewLines = computed(() =>
|
||||
state.messages.slice(0, MERGE_FORWARD_PREVIEW_LINES).map((m) => summarizeMessageContent(m))
|
||||
state.messages.slice(0, MESSAGE_MERGE_PREVIEW_LINES).map((m) => summarizeMessageContent(m))
|
||||
)
|
||||
|
||||
/** 待发送的逐条消息:剥离 quote 一次,发送多目标时复用 */
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import {
|
|||
ImMessageType,
|
||||
ImMessageStatus,
|
||||
IM_AT_ALL_USER_ID,
|
||||
RECENT_FORWARD_MAX,
|
||||
isGroupNotification,
|
||||
isMediaMessageType,
|
||||
isNormalMessage
|
||||
} from '../../utils/constants'
|
||||
import { CONVERSATION_RECENT_FORWARD_MAX } from '../../utils/config'
|
||||
import { getCurrentUserId, imStorage, removeQuietly, StorageKeys } from '../../utils/storage'
|
||||
import { parseRecallMessageId, revokeBlobUrlsInContent } from '../../utils/message'
|
||||
import { resolveConversationLastContent } from '../../utils/conversation'
|
||||
|
|
@ -126,7 +126,7 @@ export const useConversationStore = defineStore('imConversationStore', {
|
|||
privateMessageMaxId: 0, // 私聊最大消息 id,作为 pull 的游标
|
||||
groupMessageMaxId: 0, // 群聊最大消息 id,作为 pull 的游标
|
||||
loading: false, // 是否正在批量加载(例如离线消息拉取期间),避免频繁写存储
|
||||
recentForwardConversationKeys: [] as string[] // 最近转发会话 key 列表(按推送顺序倒序,最大 RECENT_FORWARD_MAX 个)
|
||||
recentForwardConversationKeys: [] as string[] // 最近转发会话 key 列表(按推送顺序倒序,最大 CONVERSATION_RECENT_FORWARD_MAX 个)
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
|
@ -188,7 +188,7 @@ export const useConversationStore = defineStore('imConversationStore', {
|
|||
])
|
||||
// 缺数据时显式赋空,避免切账号后沿用上一个用户的内存列表
|
||||
this.recentForwardConversationKeys = Array.isArray(recent)
|
||||
? recent.slice(0, RECENT_FORWARD_MAX)
|
||||
? recent.slice(0, CONVERSATION_RECENT_FORWARD_MAX)
|
||||
: []
|
||||
if (!meta) {
|
||||
return
|
||||
|
|
@ -812,7 +812,7 @@ export const useConversationStore = defineStore('imConversationStore', {
|
|||
// ==================== 最近转发 ====================
|
||||
|
||||
/**
|
||||
* 推送一批会话 key 到最近转发列表:去重 + 推到队首 + 截断 RECENT_FORWARD_MAX
|
||||
* 推送一批会话 key 到最近转发列表:去重 + 推到队首 + 截断 CONVERSATION_RECENT_FORWARD_MAX
|
||||
*
|
||||
* 调用点:RecommendCardDialog / MessageForwardDialog 提交后(含部分成功)把目标 keys 推进来
|
||||
*/
|
||||
|
|
@ -823,7 +823,7 @@ export const useConversationStore = defineStore('imConversationStore', {
|
|||
const merged = [...keys, ...this.recentForwardConversationKeys]
|
||||
this.recentForwardConversationKeys = Array.from(new Set(merged)).slice(
|
||||
0,
|
||||
RECENT_FORWARD_MAX
|
||||
CONVERSATION_RECENT_FORWARD_MAX
|
||||
)
|
||||
this.persistRecentForwardConversationKeys()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,11 +21,8 @@ import {
|
|||
type ImFriendRequestRespVO
|
||||
} from '@/api/im/friend/request'
|
||||
import { useConversationStore } from './conversationStore'
|
||||
import {
|
||||
FRIEND_REQUEST_PAGE_SIZE,
|
||||
ImConversationType,
|
||||
ImFriendRequestHandleResult
|
||||
} from '../../utils/constants'
|
||||
import { ImConversationType, ImFriendRequestHandleResult } from '../../utils/constants'
|
||||
import { FRIEND_REQUEST_PAGE_SIZE } from '../../utils/config'
|
||||
import { getCurrentUserId, imStorage, setQuietly, StorageKeys } from '../../utils/storage'
|
||||
import { getFriendDisplayName } from '../../utils/user'
|
||||
import type { Friend, FriendLite, FriendRequest } from '../types'
|
||||
|
|
|
|||
|
|
@ -128,12 +128,8 @@ import { computed } from 'vue'
|
|||
import Icon from '@/components/Icon/src/Icon.vue'
|
||||
import { formatFileSize } from '@/utils/file'
|
||||
import { formatSeconds } from '@/utils/formatTime'
|
||||
import {
|
||||
ImMessageType,
|
||||
MERGE_FORWARD_PREVIEW_LINES,
|
||||
isFriendChatTip,
|
||||
isGroupNotification
|
||||
} from '@/views/im/utils/constants'
|
||||
import { ImMessageType, isFriendChatTip, isGroupNotification } from '@/views/im/utils/constants'
|
||||
import { MESSAGE_MERGE_PREVIEW_LINES } from '@/views/im/utils/config'
|
||||
import CardLineLabel from '@/views/im/home/components/card/CardLineLabel.vue'
|
||||
import {
|
||||
parseMessage,
|
||||
|
|
@ -207,7 +203,7 @@ const mergePreviewLines = computed(() => {
|
|||
return []
|
||||
}
|
||||
return mergePayload.value.messages
|
||||
.slice(0, MERGE_FORWARD_PREVIEW_LINES)
|
||||
.slice(0, MESSAGE_MERGE_PREVIEW_LINES)
|
||||
.map((item) => `${item.senderNickname}:${summarizeMessageContent(item)}`)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* IM 前端运行参数 / UI 阈值
|
||||
*
|
||||
* 与 constants.ts 的分工:
|
||||
* - constants.ts:协议枚举(与后端 enum 一一对应)+ 协议契约值(如 IM_AT_ALL_USER_ID)
|
||||
* - config.ts:可调节的策略数值,包括镜像后端 ImProperties 的默认值与纯前端 UI 阈值
|
||||
*
|
||||
* 标注「后端镜像」的常量与 yudao.im.* 配置默认值一致;调整后端配置时需同步修改这里
|
||||
*/
|
||||
|
||||
// ==================== 后端镜像(与 ImProperties 默认值对齐) ====================
|
||||
|
||||
/** 群最大成员人数(对齐 yudao.im.group.max-member) */
|
||||
export const GROUP_MAX_MEMBER = 500
|
||||
|
||||
/** 单群管理员人数上限(对齐 yudao.im.group.admin-max-count) */
|
||||
export const GROUP_ADMIN_MAX_COUNT = 3
|
||||
|
||||
/** 单群置顶消息条数上限(对齐 yudao.im.group.pin-max-count) */
|
||||
export const GROUP_PIN_MAX_COUNT = 5
|
||||
|
||||
/** 消息撤回时间限制(分钟,对齐 yudao.im.message.recall-timeout-minutes) */
|
||||
export const MESSAGE_RECALL_TIMEOUT_MINUTES = 5
|
||||
|
||||
/** 私聊离线消息最大拉取天数(对齐 yudao.im.message.private-pull-max-days) */
|
||||
export const MESSAGE_PRIVATE_PULL_MAX_DAYS = 30
|
||||
|
||||
/** 群聊离线消息最大拉取天数(对齐 yudao.im.message.group-pull-max-days) */
|
||||
export const MESSAGE_GROUP_PULL_MAX_DAYS = 30
|
||||
|
||||
// ==================== 前端独有:拉取 / 分页 ====================
|
||||
|
||||
/** 每次拉取私聊消息的最大条数(后端上限 1000,前端取保守值 100) */
|
||||
export const MESSAGE_PRIVATE_PULL_SIZE = 100
|
||||
|
||||
/** 每次拉取群聊消息的最大条数(后端上限 1000,前端取保守值 100) */
|
||||
export const MESSAGE_GROUP_PULL_SIZE = 100
|
||||
|
||||
/** 「我相关」好友申请列表的单次拉取条数(游标分页 page size) */
|
||||
export const FRIEND_REQUEST_PAGE_SIZE = 100
|
||||
|
||||
/** 「我相关」加群申请列表的单次拉取条数 */
|
||||
export const GROUP_REQUEST_PAGE_SIZE = 100
|
||||
|
||||
// ==================== 前端独有:UI 阈值 ====================
|
||||
|
||||
/** 消息之间渲染「时间分隔条」的阈值:10 分钟 */
|
||||
export const MESSAGE_TIME_TIP_GAP_MS = 10 * 60 * 1000
|
||||
|
||||
/**
|
||||
* 撤回菜单可见的时间窗:自己发送的消息超过这个时长就不能再撤回,菜单回退为「删除」
|
||||
*
|
||||
* 比后端 MESSAGE_RECALL_TIMEOUT_MINUTES(5 分钟)严格,对齐微信 PC 的 2 分钟
|
||||
*/
|
||||
export const MESSAGE_RECALL_WINDOW_MS = 2 * 60 * 1000
|
||||
|
||||
/** 合并转发消息(MERGE 类型)气泡内预览的最大行数(对齐微信「聊天记录」气泡) */
|
||||
export const MESSAGE_MERGE_PREVIEW_LINES = 3
|
||||
|
||||
/** 最近转发会话 key 列表的最大保留数量(对齐微信 PC 横向头像区可见容量) */
|
||||
export const CONVERSATION_RECENT_FORWARD_MAX = 12
|
||||
|
|
@ -202,27 +202,6 @@ export const ImFriendRequestHandleResult = {
|
|||
REFUSED: 2 // 拒绝
|
||||
} as const
|
||||
|
||||
/** 群管理员人数上限(对齐后端 GROUP_ADMIN_MAX_COUNT) */
|
||||
export const GROUP_ADMIN_MAX_COUNT = 3
|
||||
|
||||
/** 群置顶消息条数上限(对齐后端 GROUP_PIN_MAX_COUNT) */
|
||||
export const GROUP_PIN_MAX_COUNT = 5
|
||||
|
||||
/** 每次拉取私聊消息的最大条数(后端上限 1000,前端取保守值 100) */
|
||||
export const PRIVATE_MESSAGE_PULL_SIZE = 100
|
||||
|
||||
/** 每次拉取群聊消息的最大条数(后端上限 1000,前端取保守值 100) */
|
||||
export const GROUP_MESSAGE_PULL_SIZE = 100
|
||||
|
||||
/** 「我相关」好友申请列表的单次拉取条数(游标分页 page size,前端控制) */
|
||||
export const FRIEND_REQUEST_PAGE_SIZE = 100
|
||||
|
||||
/** 「我相关」加群申请列表的单次拉取条数 */
|
||||
export const GROUP_REQUEST_PAGE_SIZE = 100
|
||||
|
||||
/** 消息之间渲染「时间分隔条」的阈值:10 分钟 */
|
||||
export const TIME_TIP_GAP_MS = 10 * 60 * 1000
|
||||
|
||||
/**
|
||||
* @全体成员 的特殊 userId 标识:atUserIds 中包含 -1 表示 @ 全体成员
|
||||
*
|
||||
|
|
@ -234,12 +213,6 @@ export const IM_AT_ALL_USER_ID = -1
|
|||
/** @全体成员 的展示名(对齐微信 PC) */
|
||||
export const IM_AT_ALL_NICKNAME = '所有人'
|
||||
|
||||
/** 合并转发气泡内预览的最大行数(对齐微信「聊天记录」气泡) */
|
||||
export const MERGE_FORWARD_PREVIEW_LINES = 3
|
||||
|
||||
/** 最近转发会话 key 列表的最大保留数量(对齐微信 PC 横向头像区可见容量) */
|
||||
export const RECENT_FORWARD_MAX = 12
|
||||
|
||||
/** 转发模式:SINGLE 逐条原样转 / MERGE 打包成 MergeMessage */
|
||||
export const ImForwardMode = {
|
||||
SINGLE: 'single',
|
||||
|
|
|
|||
Loading…
Reference in New Issue