diff --git a/src/api/im/group/request/index.ts b/src/api/im/group/request/index.ts index fab05e9af..14aa41a50 100644 --- a/src/api/im/group/request/index.ts +++ b/src/api/im/group/request/index.ts @@ -47,19 +47,6 @@ export const refuseGroupRequest = (id: number | string, handleContent?: string) }) } -// 查询「我相关」的加群申请列表(含我主动申请、我被邀请待审);游标分页 -// TODO @AI:这个 list 接口,改成传递 groupId,查询这个群下,所有的申请。然后,group size 增加一个:「群申请列表」,里面可以看到所有的。 -export const getMyGroupRequestList = (limit: number, lastRequestId?: number) => { - const params: Record = { limit } - if (lastRequestId != null) { - params.lastRequestId = lastRequestId - } - return request.get({ - url: '/im/group-request/list', - params - }) -} - // 查询「我管理的所有群」下的未处理加群申请列表(不分页);前端 store 据此派生横幅红点 + Drawer 列表 export const getUnhandledRequestList = () => { return request.get({ @@ -67,6 +54,14 @@ export const getUnhandledRequestList = () => { }) } +// 查询指定群下的全部加群申请(含已处理);仅群主 / 管理员可查 +export const getGroupRequestListByGroupId = (groupId: number) => { + return request.get({ + url: '/im/group-request/list-by-group', + params: { groupId } + }) +} + // 按 id 单查申请记录(带越权过滤;WebSocket 通知到达后用) export const getMyGroupRequest = (id: number) => { return request.get({ diff --git a/src/views/im/home/components/group/GroupRequestListDialog.vue b/src/views/im/home/components/group/GroupRequestListDialog.vue new file mode 100644 index 000000000..ff058672a --- /dev/null +++ b/src/views/im/home/components/group/GroupRequestListDialog.vue @@ -0,0 +1,391 @@ + + + + + + + diff --git a/src/views/im/home/index.vue b/src/views/im/home/index.vue index dea50961d..e110b11f0 100644 --- a/src/views/im/home/index.vue +++ b/src/views/im/home/index.vue @@ -57,6 +57,13 @@ const { readActive, syncPrivateReadStatus } = useMessageSender() /** 初始化:先吃本地缓存让首屏立即渲染,再远端刷新最新数据,最后建实时通信拉离线消息 */ onMounted(async () => { + // 0.1 系统表情包后台预拉:独立链路与首屏 IDB / 远端拉取并发,消除表情面板首次展开白屏;失败仅记日志,不阻塞主流程 + void faceStore.ensureFacePacks().catch((e) => console.warn('[IM] 后台预拉表情包失败', e)) + // 0.2 我管理的群下未处理加群申请:会话列表全局入口 / 群顶部横幅都从这份 store 派生;后台拉,不阻断 + void groupRequestStore.fetchUnhandledList().catch((e) => + console.warn('[IM] 拉取未处理加群申请失败', e) + ) + // 1.1 整段 loading=true 阻断 saveConversations 抖动写盘 + WebSocket 普通消息进缓冲,避免 connect 到 pullOnce 之间收到的实时消息推进 maxId 导致 pull 跳过断线积压消息 conversationStore.loading = true try { diff --git a/src/views/im/home/pages/conversation/components/conversation/ConversationGroupSide.vue b/src/views/im/home/pages/conversation/components/conversation/ConversationGroupSide.vue index 464213039..c992485de 100644 --- a/src/views/im/home/pages/conversation/components/conversation/ConversationGroupSide.vue +++ b/src/views/im/home/pages/conversation/components/conversation/ConversationGroupSide.vue @@ -272,13 +272,34 @@ 全群禁言 - -
- 进群需要群主 / 群管理确认 - -
+ + + + @@ -402,6 +426,7 @@ import GroupMemberAddDialog from '../../../../components/group/GroupMemberAddDia import GroupMemberSelector, { type GroupMemberFlag } from '../../../../components/group/GroupMemberSelector.vue' +import GroupRequestListDialog from '../../../../components/group/GroupRequestListDialog.vue' import type { Conversation, FriendLite, GroupLite } from '../../../../types' import type { GroupMemberLite } from '../../../../components/group/GroupMember.vue' @@ -445,6 +470,7 @@ const inviteVisible = ref(false) const removeVisible = ref(false) const adminVisible = ref(false) const transferOwnerVisible = ref(false) +const requestListVisible = ref(false) const showAllMembers = ref(false) const namePopoverVisible = ref(false) const noticePopoverVisible = ref(false) diff --git a/src/views/im/home/pages/conversation/components/conversation/ConversationItem.vue b/src/views/im/home/pages/conversation/components/conversation/ConversationItem.vue index 98af78c78..4c10e5cf4 100644 --- a/src/views/im/home/pages/conversation/components/conversation/ConversationItem.vue +++ b/src/views/im/home/pages/conversation/components/conversation/ConversationItem.vue @@ -42,6 +42,10 @@
+ + + {{ requestText }} + {{ atText }} @@ -78,6 +82,7 @@ import { useMessage } from '@/hooks/web/useMessage' import { useConversationStore } from '../../../../store/conversationStore' import { useFriendStore } from '../../../../store/friendStore' import { useGroupStore } from '../../../../store/groupStore' +import { useGroupRequestStore } from '../../../../store/groupRequestStore' import { useImUiStore } from '../../../../store/uiStore' import { useDraftStore } from '../../../../store/draftStore' import { ImConversationType, ImMessageType, isNormalMessage } from '../../../../../utils/constants' @@ -98,6 +103,7 @@ const props = defineProps<{ const conversationStore = useConversationStore() const friendStore = useFriendStore() const groupStore = useGroupStore() +const groupRequestStore = useGroupRequestStore() const uiStore = useImUiStore() const draftStore = useDraftStore() const message = useMessage() @@ -176,6 +182,15 @@ const atText = computed(() => { return '' }) +/** 群聊未处理加群申请红字前缀;store 已经按「我管理的群」过滤过,count > 0 即可显示 */ +const requestText = computed(() => { + if (!isGroup.value) { + return '' + } + const count = groupRequestStore.getUnhandledCountByGroupId(props.conversation.targetId) + return count > 0 ? `[${count}条进群申请]` : '' +}) + /** 点击切会话 */ function handleClick() { conversationStore.setActiveConversation(props.conversation) diff --git a/src/views/im/home/pages/conversation/components/message/ConversationGroupRequestPending.vue b/src/views/im/home/pages/conversation/components/message/ConversationGroupRequestPending.vue index 5c5da5b71..b2486ef44 100644 --- a/src/views/im/home/pages/conversation/components/message/ConversationGroupRequestPending.vue +++ b/src/views/im/home/pages/conversation/components/message/ConversationGroupRequestPending.vue @@ -2,79 +2,38 @@ -
-
+
- - {{ pendingCount }} 条新的入群申请待处理 - + 新进群申请({{ pendingCount }})
- -
-
- -
-
- {{ item.userNickname || `用户 ${item.userId}` }} - - ← {{ item.inviterNickname || `用户 ${item.inviterUserId}` }} 邀请 - -
-
- {{ item.applyContent }} -
-
-
- - 同意 - - - 拒绝 - -
-
-
+ +