From 1f79df232f122eaecae1a8711fbc7547e100220b Mon Sep 17 00:00:00 2001 From: Kkuil <3024067144@qq.com> Date: Tue, 24 Oct 2023 18:36:37 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=AE=A1=E7=90=86=E5=91=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 4 +- src/components.d.ts | 3 +- src/constant/group.ts | 2 + src/services/apis.ts | 6 ++ src/services/urls.ts | 1 + src/stores/cached.ts | 11 ++- src/stores/chat.ts | 9 ++ src/stores/group.ts | 71 ++++++++++++++- .../components/SettingBox/SettingBox.vue | 90 +++++++++++++++++++ .../components/SettingBox/styles.scss | 24 +++++ .../components/ChatList/RoomName/index.vue | 35 ++++++++ .../components/ChatList/RoomName/styles.scss | 18 ++++ .../Home/Chat/components/ChatList/index.vue | 7 +- .../Home/Chat/components/ChatList/styles.scss | 1 + 14 files changed, 271 insertions(+), 11 deletions(-) create mode 100644 src/constant/group.ts create mode 100644 src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/SettingBox.vue create mode 100644 src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/styles.scss create mode 100644 src/views/Home/Chat/components/ChatList/RoomName/index.vue create mode 100644 src/views/Home/Chat/components/ChatList/RoomName/styles.scss diff --git a/.env.development b/.env.development index 16824dcc..b493aaf6 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,2 @@ -VITE_API_PREFIX=https://api.mallchat.cn -VITE_WS_URL=wss://api.mallchat.cn/websocket \ No newline at end of file +VITE_API_PREFIX=http://127.0.0.1:8080 +VITE_WS_URL=wss://127.0.0.1:8090/websocket \ No newline at end of file diff --git a/src/components.d.ts b/src/components.d.ts index 47dccd26..2d6f2716 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -16,10 +16,9 @@ declare module '@vue/runtime-core' { ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElBadge: typeof import('element-plus/es')['ElBadge'] ElButton: typeof import('element-plus/es')['ElButton'] - ElCollapse: typeof import('element-plus/es')['ElCollapse'] - ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] ElDialog: typeof import('element-plus/es')['ElDialog'] ElDivider: typeof import('element-plus/es')['ElDivider'] + ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] ElInput: typeof import('element-plus/es')['ElInput'] diff --git a/src/constant/group.ts b/src/constant/group.ts new file mode 100644 index 00000000..3ebb7771 --- /dev/null +++ b/src/constant/group.ts @@ -0,0 +1,2 @@ +// 最大管理员数量 +export const MAX_ADMIN_COUNT = 3 diff --git a/src/services/apis.ts b/src/services/apis.ts index d0a0a353..89e65466 100644 --- a/src/services/apis.ts +++ b/src/services/apis.ts @@ -111,4 +111,10 @@ export default { /** 会话详情(联系人列表发消息用) */ sessionDetailWithFriends: (params: { uid: number }) => getRequest(urls.sessionDetailWithFriends, { params }), + /** 添加群管理 */ + addAdmin: ({ roomId, uidList }: { roomId: number; uidList: number[] }) => + putRequest(urls.addAdmin, { + roomId, + uidList, + }), } diff --git a/src/services/urls.ts b/src/services/urls.ts index 7f0ed2d9..adc6fe2f 100644 --- a/src/services/urls.ts +++ b/src/services/urls.ts @@ -32,6 +32,7 @@ export default { createGroup: `${prefix}/capi/room/group`, // 新增群组 getGroupUserList: `${prefix}/capi/room/public/group/member/page`, inviteGroupMember: `${prefix}/capi/room/group/member`, // 邀请群成员 + addAdmin: `${prefix}/capi/room/group/admin`, // 添加管理员 groupDetail: `${prefix}/capi/room/public/group`, // 群组详情 sessionDetail: `${prefix}/capi/chat/public/contact/detail`, // 会话详情 sessionDetailWithFriends: `${prefix}/capi/chat/public/contact/detail/friend`, // 会话详情(联系人列表发消息用) diff --git a/src/stores/cached.ts b/src/stores/cached.ts index e57e4caf..d77b5947 100644 --- a/src/stores/cached.ts +++ b/src/stores/cached.ts @@ -5,7 +5,7 @@ import { useGlobalStore } from '@/stores/global' import type { CacheUserItem, CacheBadgeItem } from '@/services/types' import { isDiffNow10Min } from '@/utils/computedTime' -type BaseUserItem = Pick +export type BaseUserItem = Pick export const useCachedStore = defineStore( 'cached', @@ -110,6 +110,14 @@ export const useCachedStore = defineStore( return currentAtUsersList.value?.filter((item) => item.name?.startsWith(searchKey)) } + /** + * 通过用户ID列表获取用户基本信息 + * @param uidList + */ + const filterUsersByUidList = (uidList: number[]) => { + return currentAtUsersList.value.filter((user) => uidList.includes(user.uid)) + } + return { userCachedList, badgeCachedList, @@ -119,6 +127,7 @@ export const useCachedStore = defineStore( filterUsers, getGroupAtUserBaseInfo, currentAtUsersList, + filterUsersByUidList, } }, { persist: true }, diff --git a/src/stores/chat.ts b/src/stores/chat.ts index 14cdef80..7a8952ef 100644 --- a/src/stores/chat.ts +++ b/src/stores/chat.ts @@ -82,6 +82,13 @@ export const useChatStore = defineStore('chat', () => { replyMapping.set(currentRoomId.value, val as Map) }, }) + const isGroup = computed(() => currentRoomType.value === RoomTypeEnum.Group) + /** + * 获取当前会话信息 + */ + const currentSessionInfo = computed(() => + sessionList.find((session) => session.roomId === globalStore.currentSession.roomId), + ) const chatListToBottomAction = ref<() => void>() // 外部提供消息列表滚动到底部事件 @@ -445,5 +452,7 @@ export const useChatStore = defineStore('chat', () => { updateSession, updateSessionLastActiveTime, markSessionRead, + isGroup, + currentSessionInfo, } }) diff --git a/src/stores/group.ts b/src/stores/group.ts index d5914b75..3b872a67 100644 --- a/src/stores/group.ts +++ b/src/stores/group.ts @@ -1,13 +1,13 @@ -import { ref, reactive, computed } from 'vue' +import { computed, reactive, ref } from 'vue' import apis from '@/services/apis' import { defineStore } from 'pinia' -import { useCachedStore } from '@/stores/cached' import { useGlobalStore } from '@/stores/global' -import type { UserItem, GroupDetailReq } from '@/services/types' +import type { GroupDetailReq, UserItem } from '@/services/types' import { pageSize } from './chat' import cloneDeep from 'lodash/cloneDeep' -import { OnlineEnum } from '@/enums' +import { OnlineEnum, RoleEnum } from '@/enums' import { uniqueUserList } from '@/utils/unique' +import { useCachedStore } from '@/stores/cached' const sorAction = (pre: UserItem, next: UserItem) => { if (pre.activeStatus === OnlineEnum.ONLINE && next.activeStatus === OnlineEnum.ONLINE) { @@ -30,6 +30,50 @@ export const useGroupStore = defineStore('group', () => { const userList = ref([]) const userListOptions = reactive({ isLast: false, loading: true, cursor: '' }) const currentRoomId = computed(() => globalStore.currentSession.roomId) + /** + * 获取当前群主ID + */ + const currentLordId = computed(() => { + const list = userList.value.filter((member) => member.roleId === RoleEnum.LORD) + if (list.length) { + return list[0]?.uid + } + return -99 + }) + /** + * 获取当前管理员ID列表 + */ + const adminUidList = computed(() => { + return userList.value + .filter((member) => member.roleId === RoleEnum.ADMIN) + .map((member) => member.uid) + }) + /** + * 获取管理员基本信息列表 + */ + const adminList = computed(() => { + return cachedStore.filterUsersByUidList(adminUidList.value) + }) + /** + * 获取管理员基本信息列表 + */ + const memberList = computed(() => { + const memberInfoList = cachedStore.filterUsersByUidList(userList.value.map((item) => item.uid)) + return memberInfoList.map((member) => { + if (adminUidList.value.includes(member.uid)) { + return { + ...member, + roleId: RoleEnum.ADMIN, + } + } else if (member.uid === currentLordId.value) { + return { + ...member, + roleId: RoleEnum.LORD, + } + } + return member + }) + }) const countInfo = ref({ avatar: '', groupName: '', @@ -99,15 +143,34 @@ export const useGroupStore = defineStore('group', () => { userList.value = userList.value.filter((item) => item.uid !== uid) } + /** + * 添加管理员 + * @param uidList + */ + const addAdmin = async (uidList: number[]) => { + await apis.addAdmin({ roomId: currentRoomId.value, uidList }).send() + + // 更新群成员列表 + userList.value.forEach((user) => { + if (uidList.includes(user.uid)) { + user.roleId = RoleEnum.ADMIN + } + }) + } + return { userList, userListOptions, loadMore, getGroupUserList, getCountStatistic, + currentLordId, countInfo, batchUpdateUserStatus, showGroupList, filterUser, + adminList, + memberList, + addAdmin, } }) diff --git a/src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/SettingBox.vue b/src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/SettingBox.vue new file mode 100644 index 00000000..bf6d8d44 --- /dev/null +++ b/src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/SettingBox.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/styles.scss b/src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/styles.scss new file mode 100644 index 00000000..1840dc77 --- /dev/null +++ b/src/views/Home/Chat/components/ChatList/RoomName/components/SettingBox/styles.scss @@ -0,0 +1,24 @@ +.setting-box { + .advanced { + width: 100%; + padding: 10px; + border: 1px solid #777; + border-radius: 5px; + + .set-admin { + display: flex; + align-items: center; + justify-content: space-between; + + .admin-avatar { + margin: 0 3px; + } + + .add-admin-transfer { + .add-admin-btn { + margin-top: 5px; + } + } + } + } +} diff --git a/src/views/Home/Chat/components/ChatList/RoomName/index.vue b/src/views/Home/Chat/components/ChatList/RoomName/index.vue new file mode 100644 index 00000000..13cf6de1 --- /dev/null +++ b/src/views/Home/Chat/components/ChatList/RoomName/index.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/views/Home/Chat/components/ChatList/RoomName/styles.scss b/src/views/Home/Chat/components/ChatList/RoomName/styles.scss new file mode 100644 index 00000000..09d154ac --- /dev/null +++ b/src/views/Home/Chat/components/ChatList/RoomName/styles.scss @@ -0,0 +1,18 @@ +.room-name { + display: flex; + align-items: center; + justify-content: space-between; + height: 50px; + padding: 0 10px; + background: var(--background-mask); + border-radius: 8px 8px 0 0; + + .setting { + font-size: 13px; + cursor: pointer; + + &:hover { + color: var(--hover-primary); + } + } +} diff --git a/src/views/Home/Chat/components/ChatList/index.vue b/src/views/Home/Chat/components/ChatList/index.vue index 19cebaab..16ba6412 100644 --- a/src/views/Home/Chat/components/ChatList/index.vue +++ b/src/views/Home/Chat/components/ChatList/index.vue @@ -1,10 +1,11 @@