Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 新增撤销管理员和退群功能 #107

Merged
merged 15 commits into from
Nov 2, 2023
3 changes: 1 addition & 2 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ 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']
ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElTabPane: typeof import('element-plus/es')['ElTabPane']
Expand Down
18 changes: 14 additions & 4 deletions src/components/RenderMessage/image.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
import { computed, ref } from 'vue'
import type { ImageBody } from '@/services/types'
import { useImgPreviewStore } from '@/stores/preview'
import { formatImage } from '@/utils'
import { useUserStore } from '@/stores/user'

const props = defineProps<{ body: ImageBody }>()
const props = defineProps<{ body: ImageBody; id: number }>()

const imageStore = useImgPreviewStore()
const userStore = useUserStore()
const hasLoadError = ref(false)
const isLoading = ref(true)

Expand All @@ -33,7 +35,11 @@ const handleError = () => {
</script>

<template>
<div class="image" :style="{ height: getImageHeight + 'px' }" @click="imageStore.show(body?.url)">
<div
class="image"
:style="{ height: getImageHeight + 'px' }"
@click="imageStore.show(body?.url as string)"
>
<div v-if="hasLoadError" class="image-slot" :style="getWidthStyle()">
<Icon icon="dazed" :size="36" colorful />
加载失败
Expand All @@ -42,8 +48,12 @@ const handleError = () => {
<img
v-if="body?.url"
:src="body?.url"
@click="imageStore.show(body?.url)"
ref="img"
:draggable="userStore.isSign ? 'true' : 'false'"
:data-messageid="id"
@click="imageStore.show(body?.url as string)"
@error="handleError"
:alt="body?.url"
/>
</template>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/RenderMessage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ defineProps<{ message: MsgType }>()
</script>

<template>
<component :is="componentMap[message.type]" :body="message.body" />
<component :is="componentMap[message.type]" :body="message.body" :id="message.id" />
Kkuil marked this conversation as resolved.
Show resolved Hide resolved
</template>
35 changes: 23 additions & 12 deletions src/services/apis.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import type {
ListResponse,
UserItem,
GroupStatisticType,
MessageType,
MarkMsgReq,
UserInfoType,
BadgeType,
MessageReq,
CacheUserItem,
CacheBadgeItem,
CacheUserReq,
CacheBadgeReq,
CacheUserItem,
CacheUserReq,
ContactItem,
EmojiItem,
GroupDetailReq,
GroupStatisticType,
ListResponse,
MarkMsgReq,
MessageReq,
MessageType,
MsgReadUnReadCountType,
RequestFriendItem,
ContactItem,
SessionItem,
MsgReadUnReadCountType,
GroupDetailReq,
UserInfoType,
UserItem,
} from '@/services/types'
import { alovaIns } from './request'
import urls from './urls'
Expand Down Expand Up @@ -119,4 +119,15 @@ export default {
roomId,
uidList,
}),
/** 撤销群管理 */
revokeAdmin: ({ roomId, uidList }: { roomId: number; uidList: number[] }) =>
deleteRequest<Boolean>(urls.revokeAdmin, {
roomId,
uidList,
}),
/** 退群 */
exitGroup: ({ roomId }: { roomId: number }) =>
deleteRequest<Boolean>(urls.exitGroup, {
roomId,
}),
}
2 changes: 2 additions & 0 deletions src/services/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export default {
createGroup: `${prefix}/capi/room/group`, // 新增群组
getGroupUserList: `${prefix}/capi/room/public/group/member/page`,
inviteGroupMember: `${prefix}/capi/room/group/member`, // 邀请群成员
exitGroup: `${prefix}/capi/room/group/member`, // 退群
addAdmin: `${prefix}/capi/room/group/admin`, // 添加管理员
revokeAdmin: `${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`, // 会话详情(联系人列表发消息用)
Expand Down
20 changes: 14 additions & 6 deletions src/stores/chat.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { ref, reactive, computed, watch } from 'vue'
import { computed, reactive, ref, watch } from 'vue'
import { defineStore } from 'pinia'
import cloneDeep from 'lodash/cloneDeep'
import { useRoute } from 'vue-router'
// import Router from '@/router'
import apis from '@/services/apis'
import type { MessageType, MarkItemType, RevokedMsgType, SessionItem } from '@/services/types'
import { MarkEnum, RoomTypeEnum } from '@/enums'
import type { MarkItemType, MessageType, RevokedMsgType, SessionItem } from '@/services/types'
import { MarkEnum, MsgEnum, RoomTypeEnum } from '@/enums'
import { computedTimeBlock } from '@/utils/computedTime'
import { useCachedStore } from '@/stores/cached'
import { useUserStore } from '@/stores/user'
Expand All @@ -14,7 +13,6 @@ import { useGroupStore } from '@/stores/group'
import { useContactStore } from '@/stores/contacts'
import shakeTitle from '@/utils/shakeTitle'
import notify from '@/utils/notification'
import { MsgEnum } from '@/enums'

export const pageSize = 20
// 标识是否第一次请求
Expand Down Expand Up @@ -286,7 +284,7 @@ export const useChatStore = defineStore('chat', () => {
if (!current) {
result = await apis.sessionDetail({ id: msg.message.roomId }).send()
}
// Router.push('/')
// Router.push('/')
// }
updateSessionLastActiveTime(msg.message.roomId, result)
}
Expand Down Expand Up @@ -427,6 +425,15 @@ export const useChatStore = defineStore('chat', () => {
return unreadCount
}

// 根据消息id获取消息体
const getMessage = (messageId: number) => {
for (const map of messageMap) {
Kkuil marked this conversation as resolved.
Show resolved Hide resolved
if (map[0] === currentRoomId.value) {
return map[1].get(messageId)
}
}
}

return {
getMsgIndex,
chatMessageList,
Expand Down Expand Up @@ -454,5 +461,6 @@ export const useChatStore = defineStore('chat', () => {
markSessionRead,
isGroup,
currentSessionInfo,
getMessage,
}
})
10 changes: 1 addition & 9 deletions src/stores/contacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import { reactive } from 'vue'
import { defineStore } from 'pinia'
import apis from '@/services/apis'
import { useGlobalStore } from '@/stores/global'
import { RequestFriendAgreeStatus } from '@/services/types'
import type { ContactItem, RequestFriendItem } from '@/services/types'
import { RequestFriendAgreeStatus } from '@/services/types'

export const pageSize = 20

export const useContactStore = defineStore('contact', () => {
const globalStore = useGlobalStore()
const contactsList = reactive<ContactItem[]>([])
const requestFriendsList = reactive<RequestFriendItem[]>([])

const contactsOptions = reactive({ isLast: false, isLoading: false, cursor: '' })
const requestFriendsOptions = reactive({ isLast: false, isLoading: false, cursor: '' })

const getContactList = async (isFresh = false) => {
if (!isFresh) {
if (contactsOptions.isLast || contactsOptions.isLoading) return
Expand Down Expand Up @@ -76,11 +73,9 @@ export const useContactStore = defineStore('contact', () => {
requestFriendsOptions.isLast = data.isLast
requestFriendsOptions.isLoading = false
}

// 默认执行一次
// getContactList()
// getRequestFriendsList()

/** 接受好友请求 */
const onAcceptFriend = (applyId: number) => {
// 同意好友申请
Expand All @@ -92,15 +87,13 @@ export const useContactStore = defineStore('contact', () => {
getRequestFriendsList(true)
// 刷新好友列表
getContactList(true)

// 标识为可以发消息的人
if (globalStore.currentSelectedContact) {
// @ts-ignore
globalStore.currentSelectedContact.status = RequestFriendAgreeStatus.Agree
}
})
}

/** 删除好友 */
const onDeleteContact = async (uid: number) => {
if (!uid) return
Expand All @@ -111,7 +104,6 @@ export const useContactStore = defineStore('contact', () => {
// 刷新好友列表
getContactList(true)
}

return {
getContactList,
getRequestFriendsList,
Expand Down
31 changes: 31 additions & 0 deletions src/stores/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import cloneDeep from 'lodash/cloneDeep'
import { OnlineEnum, RoleEnum } from '@/enums'
import { uniqueUserList } from '@/utils/unique'
import { useCachedStore } from '@/stores/cached'
import { useUserStore } from '@/stores/user'

const sorAction = (pre: UserItem, next: UserItem) => {
if (pre.activeStatus === OnlineEnum.ONLINE && next.activeStatus === OnlineEnum.ONLINE) {
Expand All @@ -26,6 +27,7 @@ const sorAction = (pre: UserItem, next: UserItem) => {
export const useGroupStore = defineStore('group', () => {
const cachedStore = useCachedStore()
const globalStore = useGlobalStore()
const userStore = useUserStore()
// 消息列表
const userList = ref<UserItem[]>([])
const userListOptions = reactive({ isLast: false, loading: true, cursor: '' })
Expand Down Expand Up @@ -158,6 +160,32 @@ export const useGroupStore = defineStore('group', () => {
})
}

/**
* 撤销管理员
* @param uidList
*/
const revokeAdmin = async (uidList: number[]) => {
await apis.revokeAdmin({ roomId: currentRoomId.value, uidList }).send()

// 更新群成员列表
userList.value.forEach((user) => {
if (uidList.includes(user.uid)) {
user.roleId = RoleEnum.NORMAL
}
})
}

/**
* 退出群聊
*/
const exitGroup = async () => {
await apis.exitGroup({ roomId: currentRoomId.value }).send()

// 更新群成员列表
const index = userList.value.findIndex((user) => user.uid === userStore.userInfo.uid)
userList.value.splice(index, 1)
}

return {
userList,
userListOptions,
Expand All @@ -169,8 +197,11 @@ export const useGroupStore = defineStore('group', () => {
batchUpdateUserStatus,
showGroupList,
filterUser,
adminUidList,
adminList,
memberList,
addAdmin,
revokeAdmin,
exitGroup,
}
})
10 changes: 6 additions & 4 deletions src/views/Home/Chat/components/ChatList/MsgItem/index.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup lang="ts">
import { computed, nextTick, onMounted, ref, type Ref, inject, watch, reactive } from 'vue'
import { computed, inject, nextTick, onMounted, reactive, ref, type Ref, watch } from 'vue'
import { useUserStore } from '@/stores/user'
import { useChatStore, pageSize } from '@/stores/chat'
import { pageSize, useChatStore } from '@/stores/chat'
import { formatTimestamp } from '@/utils/computedTime'
import { useUserInfo, useBadgeInfo } from '@/hooks/useCached'
import { useBadgeInfo, useUserInfo } from '@/hooks/useCached'
import type { MessageType, MsgType } from '@/services/types'
import { useElementVisibility } from '@vueuse/core'
import type { TooltipTriggerType } from 'element-plus/es/components/tooltip/src/trigger'
Expand Down Expand Up @@ -240,7 +240,9 @@ const currentReadList = (msgId: number) => {
<span class="chat-item-read-count-text" v-if="readCount.unread !== 0">
{{ readCount.read }}
</span>
<el-icon v-else><IEpCheck /></el-icon>
<el-icon v-else>
<IEpCheck />
</el-icon>
</div>
<!-- 消息加载中 -->
<Icon v-if="msg?.loading" icon="loading" :size="20" spin />
Expand Down
Loading