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
1 change: 1 addition & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ declare module '@vue/runtime-core' {
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
9 changes: 6 additions & 3 deletions src/components/RenderMessage/emoji.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue'
import type { EmojiBody } from '@/services/types'
import { useUserStore } from '@/stores/user'

defineProps<{ body: EmojiBody }>()
defineProps<{ body: EmojiBody; id: number }>()

const userStore = useUserStore()

const hasLoadError = ref(false)
const isLoading = ref(true)
Expand All @@ -14,13 +17,13 @@ const handleError = () => {
</script>

<template>
<div class="image emoji">
<div class="image emoji" :draggable="userStore.isSign ? 'true' : 'false'" :data-message-id="id">
<div v-if="hasLoadError" class="image-slot">
<Icon icon="dazed" :size="36" colorful />
加载失败
</div>
<template v-else>
<img v-if="body?.url" :src="body?.url" @error="handleError" />
<img v-if="body?.url" :src="body?.url" @error="handleError" :alt="body.url" />
</template>
</div>
</template>
17 changes: 11 additions & 6 deletions src/components/RenderMessage/file.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<script setup lang="ts">
import { computed } from 'vue'
import { Close } from '@element-plus/icons-vue'
import { getFileSuffix, formatBytes } from '@/utils'
import { formatBytes, getFileSuffix } from '@/utils'
import type { FileBody } from '@/services/types'
import useDownloadQuenuStore from '@/stores/downloadQuenu'
import { useUserStore } from '@/stores/user'

const { downloadObjMap, download, quenu, cancelDownload } = useDownloadQuenuStore()

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

const userStore = useUserStore()

// 下载文件
const downloadFile = () => {
Expand Down Expand Up @@ -35,15 +38,17 @@ const isQuenu = computed(() => {
</script>

<template>
<div class="file">
<div class="file" :draggable="userStore.isSign ? 'true' : 'false'" :data-message-id="id">
<Icon :icon="getFileSuffix(body?.fileName)" :size="32" colorful />
<div class="file-desc">
<span class="file-name">{{ body?.fileName || '未知文件' }}</span>
<span class="file-size">{{ formatBytes(body?.size) }}</span>
</div>
<el-text v-if="isQuenu" class="mx-1" size="small" type="warning" @click="cancelDownloadFile"
>等待下载
<el-icon><Close /></el-icon>
<el-text v-if="isQuenu" class="mx-1" size="small" type="warning" @click="cancelDownloadFile">
等待下载
<el-icon>
<Close />
</el-icon>
</el-text>
<Icon v-else-if="!isDownloading" icon="xiazai" :size="22" @click="downloadFile" />
<el-progress
Expand Down
17 changes: 13 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,11 @@ const handleError = () => {
<img
v-if="body?.url"
:src="body?.url"
@click="imageStore.show(body?.url)"
:draggable="userStore.isSign ? 'true' : 'false'"
:data-message-id="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>
15 changes: 11 additions & 4 deletions src/components/RenderMessage/video.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
import type { VideoBody } from '@/services/types'
import { useVideoPreviewStore } from '@/stores/preview'
import { formatImage } from '@/utils'
import { useUserStore } from '@/stores/user'

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

const videoStore = useVideoPreviewStore()

const userStore = useUserStore()
const getImageHeight = () => {
const width = props.body.thumbWidth || 0
const height = props.body.thumbHeight || 0
Expand All @@ -15,8 +16,14 @@ const getImageHeight = () => {
</script>

<template>
<div class="video" :style="`height:${getImageHeight()}px`" @click="videoStore.open(body?.url)">
<div
class="video"
:style="`height:${getImageHeight()}px`"
@click="videoStore.open(body?.url)"
:draggable="userStore.isSign ? 'true' : 'false'"
:data-message-id="id"
>
<Icon icon="bofang" :size="30" />
<img :src="body.thumbUrl" />
<img :src="body.thumbUrl" :alt="body.thumbUrl" />
</div>
</template>
11 changes: 9 additions & 2 deletions src/components/RenderMessage/voice.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@
import { computed } from 'vue'
import type { VoiceBody } from '@/services/types'
import { useVoicePreviewStore } from '@/stores/preview'
import { useUserStore } from '@/stores/user'

const props = defineProps<{ body: VoiceBody }>()
const props = defineProps<{ body: VoiceBody; id: number }>()
const voiceStore = useVoicePreviewStore()
const userStore = useUserStore()

// 判断当前这个消息组件是否正在播放
const isPlay = computed(() => voiceStore.previewUrl === props.body.url && voiceStore.isPlaying)
</script>

<template>
<div class="voice" @click="voiceStore.open(body.url)">
<div
class="voice"
@click="voiceStore.open(body.url)"
:draggable="userStore.isSign ? 'true' : 'false'"
:data-message-id="id"
>
<div class="saying">
<span :class="['shelter', { play: isPlay }]" />
<Icon icon="saying" :size="18" />
Expand Down
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
16 changes: 10 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,11 @@ export const useChatStore = defineStore('chat', () => {
return unreadCount
}

// 根据消息id获取消息体
const getMessage = (messageId: number) => {
return currentMessageMap.value?.get(messageId)
}

return {
getMsgIndex,
chatMessageList,
Expand Down Expand Up @@ -454,5 +457,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
Loading