Skip to content

Commit

Permalink
feat: 显示小卡片功能 (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kkuil authored Nov 14, 2023
1 parent 4e0d78f commit c5b8466
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 14 deletions.
12 changes: 12 additions & 0 deletions src/constant/message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { MsgEnum } from '@/enums'

// 消息回复映射表
export const MSG_REPLY_TEXT_MAP: Record<number, string> = {
[MsgEnum.UNKNOWN]: '[未知]',
[MsgEnum.RECALL]: '[撤回消息]',
[MsgEnum.IMAGE]: '[图片]',
[MsgEnum.FILE]: '[文件]',
[MsgEnum.VOICE]: '[语音]',
[MsgEnum.VIDEO]: '[音频]',
[MsgEnum.EMOJI]: '[表情]',
}
13 changes: 13 additions & 0 deletions src/stores/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ export const useChatStore = defineStore('chat', () => {
sortAndUniqueSessionList()
}

// 通过房间ID获取会话信息
const getSession = (roomId: number): SessionItem => {
return sessionList.find((item) => item.roomId === roomId) as SessionItem
}

const pushMsg = async (msg: MessageType) => {
const current = messageMap.get(msg.message.roomId)
current?.set(msg.message.id, msg)
Expand Down Expand Up @@ -430,6 +435,12 @@ export const useChatStore = defineStore('chat', () => {
return currentMessageMap.value?.get(messageId)
}

// 删除会话
const removeContact = (roomId: number) => {
const index = sessionList.findIndex((session) => session.roomId === roomId)
sessionList.splice(index, 1)
}

return {
getMsgIndex,
chatMessageList,
Expand All @@ -455,8 +466,10 @@ export const useChatStore = defineStore('chat', () => {
updateSession,
updateSessionLastActiveTime,
markSessionRead,
getSession,
isGroup,
currentSessionInfo,
getMessage,
removeContact,
}
})
9 changes: 8 additions & 1 deletion src/stores/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import apis from '@/services/apis'
import { defineStore } from 'pinia'
import { useGlobalStore } from '@/stores/global'
import type { GroupDetailReq, UserItem } from '@/services/types'
import { pageSize } from './chat'
import { pageSize, useChatStore } from './chat'
import cloneDeep from 'lodash/cloneDeep'
import { OnlineEnum, RoleEnum } from '@/enums'
import { uniqueUserList } from '@/utils/unique'
Expand All @@ -28,6 +28,7 @@ export const useGroupStore = defineStore('group', () => {
const cachedStore = useCachedStore()
const globalStore = useGlobalStore()
const userStore = useUserStore()
const chatStore = useChatStore()
// 消息列表
const userList = ref<UserItem[]>([])
const userListOptions = reactive({ isLast: false, loading: true, cursor: '' })
Expand Down Expand Up @@ -184,6 +185,12 @@ export const useGroupStore = defineStore('group', () => {
// 更新群成员列表
const index = userList.value.findIndex((user) => user.uid === userStore.userInfo.uid)
userList.value.splice(index, 1)

// 更新会话列表
chatStore.removeContact(currentRoomId.value)

// 切换为第一个会话
globalStore.currentSession.roomId = chatStore.sessionList[0].roomId
}

return {
Expand Down
11 changes: 6 additions & 5 deletions src/utils/renderReplyContent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MsgEnum } from '@/enums'
import { MSG_REPLY_TEXT_MAP } from '@/constant/message'

// 计算展示的回复消息的内容
const renderReplyContent = (name?: string, type?: MsgEnum, content?: string) => {
Expand All @@ -8,19 +9,19 @@ const renderReplyContent = (name?: string, type?: MsgEnum, content?: string) =>
return `${name}:${content}`
}
case MsgEnum.IMAGE: {
return `${name}: [图片]`
return `${name}: ${MSG_REPLY_TEXT_MAP[MsgEnum.IMAGE]}`
}
case MsgEnum.FILE: {
return `${name}: [文件]`
return `${name}: ${MSG_REPLY_TEXT_MAP[MsgEnum.FILE]}`
}
case MsgEnum.VOICE: {
return `${name}: [语音]`
return `${name}: ${MSG_REPLY_TEXT_MAP[MsgEnum.VOICE]}`
}
case MsgEnum.VIDEO: {
return `${name}: [视频]`
return `${name}: ${MSG_REPLY_TEXT_MAP[MsgEnum.VIDEO]}`
}
case MsgEnum.EMOJI: {
return `${name}: [表情]`
return `${name}: ${MSG_REPLY_TEXT_MAP[MsgEnum.EMOJI]}`
}
default: {
return ''
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import type { CacheUserItem } from '@/services/types'
import apis from '@/services/apis'
import { RoomTypeEnum } from '@/enums'
import { useChatStore } from '@/stores/chat'
import { useGlobalStore } from '@/stores/global'
import { useCachedStore } from '@/stores/cached'
import { useUserStore } from '@/stores/user'
const chatStore = useChatStore()
const globalStore = useGlobalStore()
const cacheStore = useCachedStore()
const userStore = useUserStore()
const props = defineProps<{
user: CacheUserItem
}>()
const userCard = ref<HTMLDivElement>()
const sendMsg = async () => {
const result = await apis.sessionDetailWithFriends({ uid: props.user.uid }).send()
globalStore.currentSession.roomId = result.roomId
globalStore.currentSession.type = RoomTypeEnum.Single
chatStore.updateSessionLastActiveTime(result.roomId, result)
}
onMounted(() => {
cacheStore.getBatchBadgeInfo(props.user.itemIds)
})
</script>

<template>
<div ref="userCard" class="user-card">
<div class="user-card_top">
<div class="user-card_top-avatar">
<el-avatar shape="square" :size="55" :src="user.avatar" />
</div>
<div class="user-card_top-info">
<el-tooltip effect="dark" :content="user.name" placement="top-start">
<div class="user-card_top-info_name">昵称:{{ user.name }}</div>
</el-tooltip>
<div class="user-card_top-info_id">uid:{{ user.uid }}</div>
<div class="user-card_top-info_place">地区:{{ user.locPlace }}</div>
</div>
</div>
<div class="user-card_badge" v-if="user.itemIds?.length">
<div class="user-card_badge-item" v-for="itemId in user.itemIds" :key="itemId">
<el-badge v-if="user.wearingItemId === itemId" is-dot>
<img
class="user-card_badge-item"
:src="cacheStore.badgeCachedList[itemId]?.img"
:alt="cacheStore.badgeCachedList[itemId]?.describe"
:title="cacheStore.badgeCachedList[itemId]?.describe"
/>
</el-badge>
<img
v-else
class="user-card_badge-item"
:src="cacheStore.badgeCachedList[itemId]?.img"
:alt="cacheStore.badgeCachedList[itemId]?.describe"
:title="cacheStore.badgeCachedList[itemId]?.describe"
/>
</div>
</div>
<div class="user-card_other">
<div
class="user-card_other-item user-card_other_send"
@click="sendMsg"
v-if="userStore.isSign"
>
<Icon class="tool-icon" icon="chat" :size="28" />
<span>发消息</span>
</div>
</div>
</div>
</template>

<style scoped lang="scss" src="./styles.scss"></style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.user-card {
position: absolute;
top: 0;
left: 0;
width: 200px;
padding: 10px;
background-color: var(--background-wrapper);
border-radius: 8px;
box-shadow: 1px 1px 5px 1px var(--background-2);

&_top {
display: flex;
padding-bottom: 10px;
border-bottom: 1px solid var(--background-secondary);

&-avatar {
width: 35%;
}

&-info {
width: 65%;
font-size: 13px;

&_name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}

&_badge {
display: flex;
justify-content: space-between;
padding: 5px 0;

&-item {
width: 25px;
height: 25px;
}
}

&_other {
display: flex;
align-items: center;

&-item {
display: flex;
flex-direction: column;
align-items: center;
min-height: 60px;
font-size: 10px;
cursor: pointer;

&:hover {
color: var(--hover-primary);
}
}
}
}
15 changes: 12 additions & 3 deletions src/views/Home/Chat/components/ChatList/MsgItem/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useUserStore } from '@/stores/user'
import { pageSize, useChatStore } from '@/stores/chat'
import { formatTimestamp } from '@/utils/computedTime'
import { useBadgeInfo, useUserInfo } from '@/hooks/useCached'
import type { MessageType, MsgType } from '@/services/types'
import type { CacheUserItem, MessageType, MsgType } from '@/services/types'
import { useElementVisibility } from '@vueuse/core'
import type { TooltipTriggerType } from 'element-plus/es/components/tooltip/src/trigger'
import { useLikeToggle } from '@/hooks/useLikeToggle'
Expand All @@ -15,6 +15,7 @@ import { useGlobalStore } from '@/stores/global'
import MsgOption from '../MsgOption/index.vue'
import ContextMenu from '../ContextMenu/index.vue'
import UserContextMenu from '../UserContextMenu/index.vue'
import UserCard from '@/views/Home/Chat/components/ChatList/MsgItem/components/UserCard/UserCard.vue'
const props = withDefaults(
defineProps<{
Expand Down Expand Up @@ -185,8 +186,16 @@ const currentReadList = (msgId: number) => {
<div ref="msgVisibleEl">
<transition name="remove">
<div :class="chatCls" v-if="!isRecall">
<!-- 用户头像 -->
<Avatar :src="userInfo.avatar" @contextmenu.prevent.stop="handleUserRightClick($event)" />
<el-popover placement="right" trigger="hover">
<template #reference>
<!-- 用户头像 -->
<Avatar
:src="userInfo.avatar"
@contextmenu.prevent.stop="handleUserRightClick($event)"
/>
</template>
<UserCard :user="userInfo as CacheUserItem" />
</el-popover>
<div class="chat-item-box" ref="boxRef">
<div class="chat-item-user-info">
<!-- 用户徽章悬浮说明 -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,17 @@ const exitGroup = async () => {
<span>退出群聊</span>
</h5>
<div class="flex-center">
<el-button type="danger" size="small" @click="exitGroup">退出群聊</el-button>
<el-popconfirm
title="是否退出该群聊?"
confirm-button-text="确认"
cancel-button-text="取消"
width="200"
@confirm="exitGroup"
>
<template #reference>
<el-button type="danger" size="small">退出群聊</el-button>
</template>
</el-popconfirm>
</div>
</div>
</template>
Expand Down
28 changes: 28 additions & 0 deletions src/views/Home/components/PostCard/PostCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script setup lang="ts">
import { MSG_REPLY_TEXT_MAP } from '@/constant/message'
import type { MessageType, SessionItem } from '@/services/types'
defineProps<{
session: SessionItem
message: MessageType
}>()
</script>

<template>
<div class="post-confirm_box">
<div class="contact-info">
<img
:src="session.avatar"
alt="${session.avatar}"
:title="session.name"
class="session-avatar"
/>
<span>{{ session.name }}</span>
</div>
<div class="msg-body">
{{ MSG_REPLY_TEXT_MAP[message.message.type] ?? message.message.body?.content }}
</div>
</div>
</template>

<style scoped lang="scss" src="./styles.scss"></style>
29 changes: 29 additions & 0 deletions src/views/Home/components/PostCard/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.post-confirm_box {
padding: 0 10px 10px;

.contact-info {
display: flex;
align-items: center;

.session-avatar {
width: 40px;
height: 40px;
margin-right: 10px;
border-radius: 10px;
}
}

.msg-body {
display: -webkit-box;
width: 100%;
height: 70px;
padding: 5px 10px;
margin-top: 10px;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
background-color: var(--background-dark);
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
}
Loading

0 comments on commit c5b8466

Please sign in to comment.