diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/controller/SysImChatController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/controller/SysImChatController.java index 9d636555..a677cacc 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/controller/SysImChatController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/controller/SysImChatController.java @@ -12,10 +12,12 @@ import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.TokenUtils; import org.jeecg.common.util.oConvertUtils; import org.jeecg.modules.im.dto.SysImCreateGroupDTO; +import org.jeecg.modules.im.dto.SysImGroupMembersDTO; import org.jeecg.modules.im.dto.SysImSendMessageDTO; import org.jeecg.modules.im.service.ISysImChatService; import org.jeecg.modules.im.vo.SysImContactVO; import org.jeecg.modules.im.vo.SysImConversationVO; +import org.jeecg.modules.im.vo.SysImGroupDetailVO; import org.jeecg.modules.im.vo.SysImMessageVO; import org.jeecg.modules.system.entity.SysUser; import org.jeecg.modules.system.service.ISysUserService; @@ -155,4 +157,69 @@ public class SysImChatController { return Result.OK(imChatService.createGroupConversation(user.getId(), resolveTenantId(user, request), user.getOrgCode(), dto)); } //update-end---author:xsl ---date:20260528 for:【IM聊天-OA】群聊接口----------- + + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群管理接口----------- + @Operation(summary = "IM聊天-群聊详情") + @RequiresPermissions("sys:im:chat:list") + @GetMapping("/group/detail") + public Result groupDetail(@RequestParam(name = "conversationId") String conversationId) { + LoginUser user = currentUser(); + return Result.OK(imChatService.getGroupDetail(user.getId(), conversationId)); + } + + @Operation(summary = "IM聊天-添加群成员") + @RequiresPermissions("sys:im:chat:list") + @PostMapping("/group/addMembers") + public Result addGroupMembers(@RequestBody SysImGroupMembersDTO dto, HttpServletRequest request) { + LoginUser user = currentUser(); + return Result.OK(imChatService.addGroupMembers(user.getId(), resolveTenantId(user, request), user.getOrgCode(), dto)); + } + + @Operation(summary = "IM聊天-移除群成员") + @RequiresPermissions("sys:im:chat:list") + @PostMapping("/group/removeMember") + public Result removeGroupMember(@RequestParam(name = "conversationId") String conversationId, + @RequestParam(name = "memberUserId") String memberUserId) { + LoginUser user = currentUser(); + imChatService.removeGroupMember(user.getId(), conversationId, memberUserId); + return Result.OK("移除成功"); + } + + @Operation(summary = "IM聊天-修改群名称") + @RequiresPermissions("sys:im:chat:list") + @PostMapping("/group/rename") + public Result renameGroup(@RequestParam(name = "conversationId") String conversationId, + @RequestParam(name = "groupName") String groupName) { + LoginUser user = currentUser(); + return Result.OK(imChatService.renameGroup(user.getId(), conversationId, groupName)); + } + + @Operation(summary = "IM聊天-转让群主") + @RequiresPermissions("sys:im:chat:list") + @PostMapping("/group/transfer") + public Result transferGroupOwner(@RequestParam(name = "conversationId") String conversationId, + @RequestParam(name = "newOwnerId") String newOwnerId) { + LoginUser user = currentUser(); + imChatService.transferGroupOwner(user.getId(), conversationId, newOwnerId); + return Result.OK("转让成功"); + } + + @Operation(summary = "IM聊天-退出群聊") + @RequiresPermissions("sys:im:chat:list") + @PostMapping("/group/quit") + public Result quitGroup(@RequestParam(name = "conversationId") String conversationId) { + LoginUser user = currentUser(); + imChatService.quitGroup(user.getId(), conversationId); + return Result.OK("已退出群聊"); + } + + @Operation(summary = "IM聊天-解散群聊") + @RequiresPermissions("sys:im:chat:list") + @PostMapping("/group/dismiss") + public Result dismissGroup(@RequestParam(name = "conversationId") String conversationId) { + LoginUser user = currentUser(); + imChatService.dismissGroup(user.getId(), conversationId); + return Result.OK("群聊已解散"); + } + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群管理接口----------- } diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/dto/SysImGroupMembersDTO.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/dto/SysImGroupMembersDTO.java new file mode 100644 index 00000000..2804598e --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/dto/SysImGroupMembersDTO.java @@ -0,0 +1,22 @@ +package org.jeecg.modules.im.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * IM 群聊添加成员 + */ +//update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-添加群成员----------- +@Data +@Schema(description = "IM群聊添加成员") +public class SysImGroupMembersDTO { + + @Schema(description = "会话ID") + private String conversationId; + + @Schema(description = "新增成员用户ID") + private List memberUserIds; +} +//update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-添加群成员----------- diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/ISysImChatService.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/ISysImChatService.java index 0e1c5806..0ceebee6 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/ISysImChatService.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/ISysImChatService.java @@ -5,12 +5,15 @@ package org.jeecg.modules.im.service; import com.baomidou.mybatisplus.core.metadata.IPage; import org.jeecg.modules.im.dto.SysImCreateGroupDTO; +import org.jeecg.modules.im.dto.SysImGroupMembersDTO; import org.jeecg.modules.im.dto.SysImSendMessageDTO; import org.jeecg.modules.im.vo.SysImContactVO; import org.jeecg.modules.im.vo.SysImConversationVO; +import org.jeecg.modules.im.vo.SysImGroupDetailVO; + import org.jeecg.modules.im.vo.SysImMessageVO; @@ -53,5 +56,28 @@ public interface ISysImChatService { List listDeptMembers(String userId, Integer tenantId, String orgCode, String keyword); + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群管理接口----------- + /** 群聊详情(含成员列表,区分群主) */ + SysImGroupDetailVO getGroupDetail(String userId, String conversationId); + + /** 添加群成员(所有群成员可操作) */ + SysImConversationVO addGroupMembers(String userId, Integer tenantId, String orgCode, SysImGroupMembersDTO dto); + + /** 移除群成员(仅群主) */ + void removeGroupMember(String userId, String conversationId, String memberUserId); + + /** 修改群名称(仅群主) */ + SysImConversationVO renameGroup(String userId, String conversationId, String groupName); + + /** 转让群主(仅群主) */ + void transferGroupOwner(String userId, String conversationId, String newOwnerId); + + /** 退出群聊(非群主成员) */ + void quitGroup(String userId, String conversationId); + + /** 解散群聊(仅群主) */ + void dismissGroup(String userId, String conversationId); + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群管理接口----------- + } diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/impl/SysImChatServiceImpl.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/impl/SysImChatServiceImpl.java index a7d761fe..bec7fc7d 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/impl/SysImChatServiceImpl.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/impl/SysImChatServiceImpl.java @@ -10,6 +10,7 @@ import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.util.DateUtils; import org.jeecg.common.util.oConvertUtils; import org.jeecg.modules.im.dto.SysImCreateGroupDTO; +import org.jeecg.modules.im.dto.SysImGroupMembersDTO; import org.jeecg.modules.im.dto.SysImSendMessageDTO; import org.jeecg.modules.im.entity.SysImConversation; import org.jeecg.modules.im.entity.SysImConversationMember; @@ -20,6 +21,8 @@ import org.jeecg.modules.im.mapper.SysImMessageMapper; import org.jeecg.modules.im.service.ISysImChatService; import org.jeecg.modules.im.vo.SysImContactVO; import org.jeecg.modules.im.vo.SysImConversationVO; +import org.jeecg.modules.im.vo.SysImGroupDetailVO; +import org.jeecg.modules.im.vo.SysImGroupMemberVO; import org.jeecg.modules.im.vo.SysImMessageVO; import org.jeecg.modules.message.websocket.WebSocket; import org.jeecg.modules.system.entity.SysDepart; @@ -198,6 +201,193 @@ public class SysImChatServiceImpl implements ISysImChatService { } //update-end---author:xsl ---date:20260528 for:【IM聊天-OA】群聊会话列表与创建----------- + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群管理----------- + private static final int GROUP_MEMBER_MAX = 50; + + @Override + public SysImGroupDetailVO getGroupDetail(String userId, String conversationId) { + SysImConversation conversation = assertGroupConversation(userId, conversationId); + List members = memberMapper.selectList(new LambdaQueryWrapper() + .eq(SysImConversationMember::getConversationId, conversationId) + .orderByAsc(SysImConversationMember::getCreateTime)); + List memberUserIds = members.stream() + .map(SysImConversationMember::getUserId) + .filter(oConvertUtils::isNotEmpty) + .distinct() + .collect(Collectors.toList()); + Map userMap = new HashMap<>(memberUserIds.size()); + if (!memberUserIds.isEmpty()) { + List users = userMapper.selectBatchIds(memberUserIds); + if (users != null) { + for (SysUser user : users) { + userMap.put(user.getId(), user); + } + } + } + String ownerId = conversation.getOwnerId(); + List memberVoList = new ArrayList<>(members.size()); + for (SysImConversationMember member : members) { + SysUser user = userMap.get(member.getUserId()); + SysImGroupMemberVO memberVo = new SysImGroupMemberVO(); + memberVo.setUserId(member.getUserId()); + memberVo.setOwner(member.getUserId() != null && member.getUserId().equals(ownerId)); + if (user != null) { + memberVo.setRealname(user.getRealname()); + memberVo.setUsername(user.getUsername()); + memberVo.setAvatar(user.getAvatar()); + } + memberVoList.add(memberVo); + } + // 群主排在最前 + memberVoList.sort(Comparator.comparingInt(item -> Boolean.TRUE.equals(item.getOwner()) ? 0 : 1)); + SysImGroupDetailVO detail = new SysImGroupDetailVO(); + detail.setConversationId(conversation.getId()); + detail.setGroupName(conversation.getGroupName()); + detail.setOwnerId(ownerId); + detail.setMemberCount(memberVoList.size()); + detail.setOwner(userId.equals(ownerId)); + detail.setMembers(memberVoList); + return detail; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public SysImConversationVO addGroupMembers(String userId, Integer tenantId, String orgCode, SysImGroupMembersDTO dto) { + if (dto == null || oConvertUtils.isEmpty(dto.getConversationId())) { + throw new JeecgBootException("会话不存在"); + } + SysImConversation conversation = assertGroupConversation(userId, dto.getConversationId()); + if (dto.getMemberUserIds() == null || dto.getMemberUserIds().isEmpty()) { + throw new JeecgBootException("请选择要添加的成员"); + } + // 已在群成员 + Set existIds = memberMapper.selectList(new LambdaQueryWrapper() + .eq(SysImConversationMember::getConversationId, conversation.getId())) + .stream().map(SysImConversationMember::getUserId).collect(Collectors.toSet()); + // 去重并过滤已存在成员 + List toAdd = new ArrayList<>(); + Set seen = new LinkedHashSet<>(); + for (String memberId : dto.getMemberUserIds()) { + if (oConvertUtils.isEmpty(memberId) || existIds.contains(memberId) || !seen.add(memberId)) { + continue; + } + toAdd.add(memberId); + } + if (toAdd.isEmpty()) { + throw new JeecgBootException("所选成员已在群内"); + } + if (existIds.size() + toAdd.size() > GROUP_MEMBER_MAX) { + throw new JeecgBootException("群成员不能超过" + GROUP_MEMBER_MAX + "人"); + } + // 校验同租户、同部门 + for (String memberId : toAdd) { + validateTenantChat(userId, tenantId, orgCode, memberId); + } + Date now = new Date(); + for (String memberId : toAdd) { + createMember(conversation.getId(), memberId, now); + } + return buildGroupConversationVo(conversation, userId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeGroupMember(String userId, String conversationId, String memberUserId) { + SysImConversation conversation = assertGroupConversation(userId, conversationId); + assertGroupOwner(userId, conversation); + if (oConvertUtils.isEmpty(memberUserId)) { + throw new JeecgBootException("请选择要移除的成员"); + } + if (memberUserId.equals(conversation.getOwnerId())) { + throw new JeecgBootException("群主不能被移除"); + } + memberMapper.delete(new LambdaQueryWrapper() + .eq(SysImConversationMember::getConversationId, conversationId) + .eq(SysImConversationMember::getUserId, memberUserId)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public SysImConversationVO renameGroup(String userId, String conversationId, String groupName) { + SysImConversation conversation = assertGroupConversation(userId, conversationId); + assertGroupOwner(userId, conversation); + if (oConvertUtils.isEmpty(groupName)) { + throw new JeecgBootException("群名称不能为空"); + } + String name = groupName.trim(); + if (name.length() > 30) { + throw new JeecgBootException("群名称不能超过30字"); + } + conversation.setGroupName(name); + conversation.setUpdateBy(userId); + conversation.setUpdateTime(new Date()); + conversationMapper.updateById(conversation); + return buildGroupConversationVo(conversation, userId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void transferGroupOwner(String userId, String conversationId, String newOwnerId) { + SysImConversation conversation = assertGroupConversation(userId, conversationId); + assertGroupOwner(userId, conversation); + if (oConvertUtils.isEmpty(newOwnerId)) { + throw new JeecgBootException("请选择新群主"); + } + if (newOwnerId.equals(userId)) { + throw new JeecgBootException("不能转让给自己"); + } + if (getMember(newOwnerId, conversationId) == null) { + throw new JeecgBootException("新群主必须是群成员"); + } + conversation.setOwnerId(newOwnerId); + conversation.setUpdateBy(userId); + conversation.setUpdateTime(new Date()); + conversationMapper.updateById(conversation); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void quitGroup(String userId, String conversationId) { + SysImConversation conversation = assertGroupConversation(userId, conversationId); + if (userId.equals(conversation.getOwnerId())) { + throw new JeecgBootException("群主不能退出群聊,请先转让群主或解散群聊"); + } + memberMapper.delete(new LambdaQueryWrapper() + .eq(SysImConversationMember::getConversationId, conversationId) + .eq(SysImConversationMember::getUserId, userId)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void dismissGroup(String userId, String conversationId) { + SysImConversation conversation = assertGroupConversation(userId, conversationId); + assertGroupOwner(userId, conversation); + memberMapper.delete(new LambdaQueryWrapper() + .eq(SysImConversationMember::getConversationId, conversationId)); + conversationMapper.deleteById(conversationId); + } + + /** 校验会话存在、为群聊且当前用户是群成员 */ + private SysImConversation assertGroupConversation(String userId, String conversationId) { + if (oConvertUtils.isEmpty(conversationId)) { + throw new JeecgBootException("会话不存在"); + } + SysImConversation conversation = conversationMapper.selectById(conversationId); + if (conversation == null || !CONV_TYPE_GROUP.equals(conversation.getConvType())) { + throw new JeecgBootException("群聊不存在"); + } + assertMember(userId, conversationId); + return conversation; + } + + /** 校验当前用户是群主 */ + private void assertGroupOwner(String userId, SysImConversation conversation) { + if (!userId.equals(conversation.getOwnerId())) { + throw new JeecgBootException("仅群主可执行该操作"); + } + } + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群管理----------- + //update-begin---author:cursor ---date:20260528 for:【IM聊天-OA】消息分页----------- @Override public IPage listMessages(String userId, String conversationId, Integer pageNo, Integer pageSize, String startTime, String beforeTime) { diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/vo/SysImGroupDetailVO.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/vo/SysImGroupDetailVO.java new file mode 100644 index 00000000..c418a7a2 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/vo/SysImGroupDetailVO.java @@ -0,0 +1,29 @@ +package org.jeecg.modules.im.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * IM 群聊详情(群设置) + */ +//update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群详情----------- +@Data +@Schema(description = "IM群聊详情") +public class SysImGroupDetailVO { + + @Schema(description = "会话ID") + private String conversationId; + @Schema(description = "群名称") + private String groupName; + @Schema(description = "群主用户ID") + private String ownerId; + @Schema(description = "群成员数") + private Integer memberCount; + @Schema(description = "当前用户是否群主") + private Boolean owner; + @Schema(description = "群成员列表") + private List members; +} +//update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群详情----------- diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/vo/SysImGroupMemberVO.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/vo/SysImGroupMemberVO.java new file mode 100644 index 00000000..87fd84a0 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/vo/SysImGroupMemberVO.java @@ -0,0 +1,25 @@ +package org.jeecg.modules.im.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * IM 群成员 + */ +//update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群成员展示----------- +@Data +@Schema(description = "IM群成员") +public class SysImGroupMemberVO { + + @Schema(description = "用户ID") + private String userId; + @Schema(description = "姓名") + private String realname; + @Schema(description = "账号") + private String username; + @Schema(description = "头像") + private String avatar; + @Schema(description = "是否群主") + private Boolean owner; +} +//update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置-群成员展示----------- diff --git a/jeecgboot-vue3/src/views/system/im/ImChat.vue b/jeecgboot-vue3/src/views/system/im/ImChat.vue index b4a958a6..f1082c5d 100644 --- a/jeecgboot-vue3/src/views/system/im/ImChat.vue +++ b/jeecgboot-vue3/src/views/system/im/ImChat.vue @@ -131,6 +131,9 @@ @@ -214,6 +217,10 @@ + + + + 图片预览 @@ -243,6 +250,10 @@ import ImPageListPickModal from './ImPageListPickModal.vue'; import ImBizRecordMessageContent from './ImBizRecordMessageContent.vue'; import ImCreateGroupModal from './ImCreateGroupModal.vue'; + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置抽屉----------- + import ImGroupSettingDrawer from './ImGroupSettingDrawer.vue'; + import { useDrawer } from '/@/components/Drawer'; + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置抽屉----------- import { useModal } from '/@/components/Modal'; import { useMessage } from '/@/hooks/web/useMessage'; import { buildImBizRecordPayload, parseImBizRecordPayload, serializeImBizRecordPayload } from './imBizRecordMessage'; @@ -499,6 +510,9 @@ const [registerListPickModal, { openModal: openListPickModal }] = useModal(); const [registerCreateGroupModal, { openModal: openCreateGroupModal }] = useModal(); //update-end---author:xsl ---date:20260528 for:【IM聊天-OA】点击功能名气泡选择列表明细发送----------- + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置抽屉----------- + const [registerGroupSettingDrawer, { openDrawer: openGroupSettingDrawer, closeDrawer: closeGroupSettingDrawer }] = useDrawer(); + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置抽屉----------- const defaultHistoryDays = ref(getImDefaultHistoryDays()); const currentUserId = computed(() => userStore.getUserInfo?.id || ''); const deptLabel = computed(() => { @@ -715,9 +729,60 @@ function handleSettingsMenuClick({ key }: { key: string }) { if (key === 'chatSettings') { openSettingsModal(true, {}); + return; } + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】打开群设置抽屉----------- + if (key === 'groupSettings') { + if (!activeGroup.value?.conversationId) { + return; + } + openGroupSettingDrawer(true, { conversationId: activeGroup.value.conversationId }); + } + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】打开群设置抽屉----------- } + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置变更/退出回调----------- + /** 群信息变更(改名/加人/踢人/转让):同步标题、成员数,并刷新群列表 */ + async function handleGroupSettingChanged(payload: { conversationId: string; groupName?: string; memberCount?: number }) { + if (!payload?.conversationId) { + return; + } + patchGroup(payload.conversationId, { + groupName: payload.groupName, + memberCount: payload.memberCount, + }, { moveToTop: false }); + if (activeGroup.value?.conversationId === payload.conversationId) { + activeGroup.value = { + ...activeGroup.value, + groupName: payload.groupName ?? activeGroup.value.groupName, + memberCount: payload.memberCount ?? activeGroup.value.memberCount, + }; + } + // 后台静默刷新群列表,保证成员数等准确 + await loadGroups(true); + } + + /** 退出或解散群聊:从列表移除,若为当前会话则清空聊天区 */ + async function handleGroupExited(conversationId: string) { + if (!conversationId) { + return; + } + groupList.value = groupList.value.filter((item) => item.conversationId !== conversationId); + resetGroupUnread(conversationId); + syncAllUnread(); + if (activeGroup.value?.conversationId === conversationId) { + activeGroup.value = null; + activeChatType.value = ''; + activeConversationId.value = ''; + setImActiveConversationId(''); + messageList.value = []; + draft.value = ''; + clearImActiveSession(); + } + closeGroupSettingDrawer(); + } + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置变更/退出回调----------- + function onChatSettingsSaved() { defaultHistoryDays.value = getImDefaultHistoryDays(); if (activeConversationId.value) { diff --git a/jeecgboot-vue3/src/views/system/im/ImGroupAddMemberModal.vue b/jeecgboot-vue3/src/views/system/im/ImGroupAddMemberModal.vue new file mode 100644 index 00000000..97ce2771 --- /dev/null +++ b/jeecgboot-vue3/src/views/system/im/ImGroupAddMemberModal.vue @@ -0,0 +1,164 @@ + + + + + + + diff --git a/jeecgboot-vue3/src/views/system/im/ImGroupSettingDrawer.vue b/jeecgboot-vue3/src/views/system/im/ImGroupSettingDrawer.vue new file mode 100644 index 00000000..912fe66e --- /dev/null +++ b/jeecgboot-vue3/src/views/system/im/ImGroupSettingDrawer.vue @@ -0,0 +1,473 @@ + + + + + + + diff --git a/jeecgboot-vue3/src/views/system/im/im.api.ts b/jeecgboot-vue3/src/views/system/im/im.api.ts index d41b4232..fb2cf2c2 100644 --- a/jeecgboot-vue3/src/views/system/im/im.api.ts +++ b/jeecgboot-vue3/src/views/system/im/im.api.ts @@ -8,6 +8,15 @@ enum Api { read = '/sys/im/chat/read', groups = '/sys/im/chat/groups', groupCreate = '/sys/im/chat/group/create', + //update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置接口----------- + groupDetail = '/sys/im/chat/group/detail', + groupAddMembers = '/sys/im/chat/group/addMembers', + groupRemoveMember = '/sys/im/chat/group/removeMember', + groupRename = '/sys/im/chat/group/rename', + groupTransfer = '/sys/im/chat/group/transfer', + groupQuit = '/sys/im/chat/group/quit', + groupDismiss = '/sys/im/chat/group/dismiss', + //update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置接口----------- } export interface ImGroupConversation { @@ -57,3 +66,51 @@ export const fetchGroups = () => defHttp.get({ url: Api.g export const createGroupConversation = (data: { groupName: string; memberUserIds: string[] }) => defHttp.post({ url: Api.groupCreate, data }); + +//update-begin---author:cursor ---date:20260529 for:【IM聊天-OA】群设置接口----------- +export interface ImGroupMember { + userId: string; + realname?: string; + username?: string; + avatar?: string; + owner?: boolean; +} + +export interface ImGroupDetail { + conversationId: string; + groupName?: string; + ownerId?: string; + memberCount?: number; + /** 当前登录用户是否群主 */ + owner?: boolean; + members: ImGroupMember[]; +} + +/** 群聊详情(含成员列表) */ +export const fetchGroupDetail = (conversationId: string) => + defHttp.get({ url: Api.groupDetail, params: { conversationId } }); + +/** 添加群成员 */ +export const addGroupMembers = (data: { conversationId: string; memberUserIds: string[] }) => + defHttp.post({ url: Api.groupAddMembers, data }); + +/** 移除群成员(仅群主) */ +export const removeGroupMember = (conversationId: string, memberUserId: string) => + defHttp.post({ url: Api.groupRemoveMember, params: { conversationId, memberUserId } }, { joinParamsToUrl: true }); + +/** 修改群名称(仅群主) */ +export const renameGroup = (conversationId: string, groupName: string) => + defHttp.post({ url: Api.groupRename, params: { conversationId, groupName } }, { joinParamsToUrl: true }); + +/** 转让群主(仅群主) */ +export const transferGroupOwner = (conversationId: string, newOwnerId: string) => + defHttp.post({ url: Api.groupTransfer, params: { conversationId, newOwnerId } }, { joinParamsToUrl: true }); + +/** 退出群聊(非群主成员) */ +export const quitGroup = (conversationId: string) => + defHttp.post({ url: Api.groupQuit, params: { conversationId } }, { joinParamsToUrl: true }); + +/** 解散群聊(仅群主) */ +export const dismissGroup = (conversationId: string) => + defHttp.post({ url: Api.groupDismiss, params: { conversationId } }, { joinParamsToUrl: true }); +//update-end---author:cursor ---date:20260529 for:【IM聊天-OA】群设置接口-----------