Browse Source

style:优化群成员样式。

master
qiutianhong 7 months ago
parent
commit
0f8227e09c
  1. 80
      frontend/src/components/chat/ChatBox.vue
  2. 12
      frontend/src/components/chat/ChatMessage.vue
  3. 20
      frontend/src/components/chat/ChatMsgList.vue
  4. 96
      frontend/src/components/chat/chatGroupMember.vue
  5. 12
      frontend/src/components/chat/chatUserInfo.vue
  6. 60
      frontend/src/stores/chat.ts
  7. 7
      frontend/src/stores/db.ts
  8. 2
      frontend/src/system/member.ts

80
frontend/src/components/chat/ChatBox.vue

@ -48,6 +48,8 @@
> >
</div> </div>
</el-dialog> </el-dialog>
<!-- 群成员抽屉 -->
<ChatGroupMember />
<div <div
class="chatbox-main" class="chatbox-main"
v-if="store.targetChatId" v-if="store.targetChatId"
@ -87,6 +89,13 @@
/></el-icon> /></el-icon>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item
@click="
store.groupMemberDrawerVisible = true
"
>群成员</el-dropdown-item
>
<el-dropdown-item <el-dropdown-item
@click="openInviteGroupDialog()" @click="openInviteGroupDialog()"
>邀请群聊</el-dropdown-item >邀请群聊</el-dropdown-item
@ -99,7 +108,10 @@
" "
>退出群聊</el-dropdown-item >退出群聊</el-dropdown-item
> >
<el-dropdown-item>清空记录</el-dropdown-item> <el-dropdown-item
@click="clearMessages('group')"
>清空记录</el-dropdown-item
>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
@ -126,7 +138,7 @@
/></el-icon> /></el-icon>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item @click="store.clearChatRecord()" <el-dropdown-item @click="clearMessages('user')"
>清空记录</el-dropdown-item >清空记录</el-dropdown-item
> >
</el-dropdown-menu> </el-dropdown-menu>
@ -147,14 +159,6 @@
</div> </div>
</el-scrollbar> </el-scrollbar>
</div> </div>
<!-- 群成员滚动区域 -->
<div class="member-container">
<el-scrollbar ref="memberScrollbarRef">
<div ref="memberInnerRef">
<ChatGroupMember />
</div>
</el-scrollbar>
</div>
</el-main> </el-main>
<!--聊天输入区和发送按钮等--> <!--聊天输入区和发送按钮等-->
@ -207,28 +211,14 @@
" "
v-else v-else
> >
<el-icon <el-empty description="请选择一个用户或群聊" />
:size="180"
color="#0078d7"
>
<ChatDotSquare />
</el-icon>
<p
style="
font-size: 18px;
font-weight: 600;
margin-top: 10px;
color: #333;
"
>
欢迎使用GodoOS
</p>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useChatStore } from "@/stores/chat"; import { useChatStore } from "@/stores/chat";
import { useChooseStore } from "@/stores/choose"; import { useChooseStore } from "@/stores/choose";
import { notifyError, notifySuccess } from "@/util/msg";
const store: any = useChatStore(); const store: any = useChatStore();
const choose = useChooseStore(); const choose = useChooseStore();
@ -237,6 +227,27 @@
const scrollbarRef = ref(null); const scrollbarRef = ref(null);
const innerRef = ref(null); const innerRef = ref(null);
//
const clearMessages = (type: string) => {
//
if (type === "user") {
if (store.clearSentMessages()) {
if (store.clearReceivedMessages()) {
notifySuccess("删除成功");
store.getSessionInfo(store.targetChatId, type);
} else {
notifyError("删除失败");
}
} else if (store.clearReceivedMessages()) {
notifySuccess("删除成功");
} else {
notifyError("删除失败");
}
} else if (type === "group") {
store.clearGroupMessages();
}
};
const openInviteGroupDialog = () => { const openInviteGroupDialog = () => {
store.inviteFriendDialogVisible = true; store.inviteFriendDialogVisible = true;
store.getInviteUserList(); store.getInviteUserList();
@ -292,11 +303,6 @@
} }
); );
function openDrawer() {
store.drawerVisible = true;
// store.getGroupMemberList(store.targetGroupInfo.group_id);
}
// store.drawerVisible // store.drawerVisible
watch( watch(
() => store.drawerVisible, () => store.drawerVisible,
@ -348,14 +354,14 @@
/* 聊天消息滚动区域 */ /* 聊天消息滚动区域 */
.msg-container { .msg-container {
width: calc(100% - 150px); width: 100%;
height: 100%; height: 100%;
} }
/* 群成员滚动区域 */ /* 群成员滚动区域 */
.member-container { .member-container {
border-left: 1px solid #edebeb; border-left: 1px solid #edebeb;
width: 140px; width: 140px;
height: 100%; height: calc(100% - 10px);
} }
.input-main { .input-main {
@ -388,14 +394,6 @@
margin-bottom: 10px; /* 每个成员之间的间距 */ margin-bottom: 10px; /* 每个成员之间的间距 */
} }
:deep(.el-drawer__header) {
color: #000000;
}
:deep(.el-drawer__body) {
margin-top: -40px; /* 根据需要调整这个值 */
}
.group-name { .group-name {
font-size: 16px; font-size: 16px;
border-top: 1px solid #edebeb; border-top: 1px solid #edebeb;

12
frontend/src/components/chat/ChatMessage.vue

@ -76,7 +76,7 @@
</div> </div>
<!-- 发送时间展示在消息框外部的下方 --> <!-- 发送时间展示在消息框外部的下方 -->
<div class="chat-time-me-outer"> <div class="chat-time-me-outer">
{{ item.previewTimeFormat }} {{ formatTime(item.createdAt) }}
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
@ -160,7 +160,7 @@
</div> </div>
<!-- 发送时间展示在消息框外部的下方 --> <!-- 发送时间展示在消息框外部的下方 -->
<div class="chat-time-other-outer"> <div class="chat-time-other-outer">
{{ item.previewTimeFormat }} {{ item.time }}
</div> </div>
</el-col> </el-col>
<el-col :span="8" /> <el-col :span="8" />
@ -230,6 +230,14 @@
const currUserId = ref(); const currUserId = ref();
//
function formatTime(timestamp) {
const date = new Date(timestamp);
const month = date.getMonth() + 1; // 0
const day = date.getDate();
return `${month}-${day}`;
}
const showUserInfo = (chatId: string) => { const showUserInfo = (chatId: string) => {
console.log(chatId); console.log(chatId);
currUserId.value = chatId; currUserId.value = chatId;

20
frontend/src/components/chat/ChatMsgList.vue

@ -33,7 +33,7 @@
:size="40" :size="40"
class="avatar" class="avatar"
style=" style="
background-color: #165DFF; background-color: #165dff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -90,7 +90,7 @@
</div> </div>
<div class="previewTime"> <div class="previewTime">
{{ item.previewTimeFormat }} {{ formatTime(item.time) }}
</div> </div>
</div> </div>
@ -129,6 +129,14 @@
const store = useChatStore(); const store = useChatStore();
const id = ref("1"); const id = ref("1");
//
function formatTime(timestamp) {
const date = new Date(timestamp);
const month = date.getMonth() + 1; // 0
const day = date.getDate();
return `${month}-${day}`;
}
// store // store
const filteredMessages = computed(() => { const filteredMessages = computed(() => {
return store.search return store.search
@ -152,11 +160,11 @@
margin-bottom: 5px; margin-bottom: 5px;
overflow: hidden; overflow: hidden;
margin-top: 5px; margin-top: 5px;
background-color: #FFF; background-color: #fff;
} }
.list-item:hover { .list-item:hover {
background-color: #E8F3FF; background-color: #e8f3ff;
} }
.avatar { .avatar {
@ -201,7 +209,7 @@
.previewTime { .previewTime {
font-size: 12px; font-size: 12px;
color: #86909C; color: #86909c;
} }
.preview-left { .preview-left {
@ -218,7 +226,7 @@
margin-left: 10px; margin-left: 10px;
font-size: 12px; font-size: 12px;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
color: #86909C; color: #86909c;
overflow: hidden; /* 隐藏超出部分 */ overflow: hidden; /* 隐藏超出部分 */
text-overflow: ellipsis; /* 显示为省略号 */ text-overflow: ellipsis; /* 显示为省略号 */
white-space: nowrap; /* 不换行 */ white-space: nowrap; /* 不换行 */

96
frontend/src/components/chat/chatGroupMember.vue

@ -1,44 +1,73 @@
<template> <template>
<div class="group-member-container"> <el-drawer
v-model="store.groupMemberDrawerVisible"
direction="rtl"
title="群成员"
:with-header="true"
:show-close="true"
size="250px"
>
<!-- 群成员列表 --> <!-- 群成员列表 -->
<div <div class="group-member-container">
class="member-list" <div
v-for="item in groupMembers" class="member-list"
:key="item.userId" v-for="item in store.groupMembers"
> :key="item.id"
<!-- 头像和昵称 --> >
<div class="member-item"> <div class="member-item">
<div class="avatar-container"> <!-- 头像和昵称 -->
<el-avatar <div class="avatar-container">
style="width: 100%; height: 100%;" <el-avatar
:src="item.avatar" style="width: 100%; height: 100%"
/> :src="item.avatar"
/>
</div>
<span>{{ item.nickname }}</span>
</div> </div>
<span>{{ item.nickname }}</span>
</div> </div>
</div> </div>
</div> </el-drawer>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useChatStore } from "@/stores/chat"; import { useChatStore } from "@/stores/chat";
const store = useChatStore(); const store = useChatStore();
// 使 // true
watch(
() => store.groupMemberDrawerVisible,
(newVal) => {
if (newVal) {
store.getGroupMemberList(store.targetGroupInfo.group_id);
}
}
);
// 使40 //
const groupMembers = ref( watch(
Array.from({ length: 40 }, (v, i) => ({ () => store.drawerVisible,
userId: `${i + 1}`, (newVal) => {
avatar: `path/to/avatar${i + 1}.jpg`, if (newVal) {
nickname: `用户1111111111111111${i + 1}`, store.getGroupMemberList(store.targetGroupInfo.group_id);
})) }
}
); );
</script> </script>
<style scoped> <style scoped>
:deep(.el-drawer__header) {
background-color: red;
padding: 0px 20px;
height: 50px;
color: #000000;
margin-bottom: 0px;
}
:deep(.el-drawer__title) {
font-size: 20px;
}
.group-member-container { .group-member-container {
margin: 10px 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-y: auto; /* 添加滚动条 */
} }
.member-item { .member-item {
@ -48,19 +77,18 @@
} }
.avatar-container { .avatar-container {
width: 25px; width: 30px;
height: 25px; height: 30px;
margin-right: 5px; margin-right: 10px;
} }
.member-item span { .member-item span {
width: 90px; width: 150px;
margin-left: 10px; margin-left: 10px;
font-size: 12px; font-size: 12px;
color: #86909C; color: #86909c;
overflow: hidden; /* 防止内容溢出 */ overflow: hidden;
white-space: nowrap; /* 保持文本在一行 */ white-space: nowrap;
text-overflow: ellipsis; /* 文本溢出显示省略号 */ text-overflow: ellipsis;
max-width: 150px; /* 最大宽度,根据需要调整 */
} }
</style> </style>

12
frontend/src/components/chat/chatUserInfo.vue

@ -74,7 +74,9 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<div v-else>1</div> <div v-else class="empty-container">
<el-empty description="请选择一个用户或群聊" />
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -107,6 +109,14 @@
</script> </script>
<style scoped> <style scoped>
.empty-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.chat-user-info { .chat-user-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

60
frontend/src/stores/chat.ts

@ -99,6 +99,8 @@ export const useChatStore = defineStore('chatStore', () => {
// 定义消息发送、接受的状态用于控制滚动条的滚动 // 定义消息发送、接受的状态用于控制滚动条的滚动
const messageSendStatus = ref(false) const messageSendStatus = ref(false)
const messageReceiveStatus = ref(false) const messageReceiveStatus = ref(false)
// 群成员列表抽屉是否显示
const groupMemberDrawerVisible = ref(false)
// 群成员列表 // 群成员列表
const groupMemberList = ref<any[]>([]) const groupMemberList = ref<any[]>([])
@ -1260,43 +1262,66 @@ export const useChatStore = defineStore('chatStore', () => {
}; };
// 清空聊天记录 // 清空发送的聊天记录
// 清空聊天记录 const clearSentMessages = async () => {
const clearChatRecord = async () => {
// 删除我发送给对方的记录
const whereObjSent = { const whereObjSent = {
toUserId: targetChatId.value, toUserId: targetChatId.value,
userId: userInfo.value.id userId: userInfo.value.id
}; };
const resSent = await db.deleteByWhere("workbenchChatRecord", whereObjSent); const resSent = await db.deleteByWhere("workbenchChatRecord", whereObjSent);
if (resSent >= 0) {
// 更新chatList中的预览消息
chatList.value.forEach((item: any) => {
if (item.chatId === targetChatId.value) {
item.previewMessage = "快开始打招呼吧!";
}
});
return true
} else {
return false
}
};
// 删除对方发送给我的记录 // 清空接收的聊天记录
const clearReceivedMessages = async () => {
const whereObjReceived = { const whereObjReceived = {
userId: targetChatId.value, userId: targetChatId.value,
toUserId: userInfo.value.id toUserId: userInfo.value.id
}; };
const resReceived = await db.deleteByWhere("workbenchChatRecord", whereObjReceived); const resReceived = await db.deleteByWhere("workbenchChatRecord", whereObjReceived);
if (resReceived >= 0) {
// 检查两个删除操作是否都成功 // 更新chatList中的预览消息
if (resSent == 1 && resReceived == 1) { chatList.value.forEach((item: any) => {
// 更新chatHistory,移除相关记录 if (item.chatId === targetChatId.value) {
chatHistory.value = chatHistory.value.filter((item: any) => item.previewMessage = "快开始打招呼吧!";
!(item.toUserId === targetChatId.value && item.userId === userInfo.value.id) && }
!(item.userId === targetChatId.value && item.toUserId === userInfo.value.id) });
); return true
} else {
return false
}
};
// 清空群消息
const clearGroupMessages = async () => {
const res = await db.deleteByField("workbenchGroupChatRecord", "chatId", targetChatId.value);
if (res >= 0) {
// 还需要找到
getSessionInfo(targetChatId.value, "group")
// 更新chatList中的预览消息 // 更新chatList中的预览消息
chatList.value.forEach((item: any) => { chatList.value.forEach((item: any) => {
if (item.chatId === targetChatId.value) { if (item.chatId === targetChatId.value) {
item.previewMessage = "快开始打招呼吧!"; item.previewMessage = "快开始打招呼吧!";
} }
}); });
notifySuccess("清空成功"); notifySuccess("删除成功");
return; } else {
notifyError("删除失败");
} }
notifyError("清空失败");
} }
return { return {
emojiList, emojiList,
groupSystemMessage, groupSystemMessage,
@ -1334,6 +1359,7 @@ export const useChatStore = defineStore('chatStore', () => {
messageSendStatus, messageSendStatus,
messageReceiveStatus, messageReceiveStatus,
groupMembers, groupMembers,
groupMemberDrawerVisible,
initChat, initChat,
showContextMenu, showContextMenu,
setCurrentNavId, setCurrentNavId,
@ -1358,6 +1384,8 @@ export const useChatStore = defineStore('chatStore', () => {
setScrollToBottom, setScrollToBottom,
getGroupMemberList, getGroupMemberList,
getInviteUserList, getInviteUserList,
clearChatRecord, clearReceivedMessages,
clearSentMessages,
clearGroupMessages
}; };
}); });

7
frontend/src/stores/db.ts

@ -9,7 +9,7 @@ dbInit.version(1).stores({
// 会话列表 // 会话列表
workbenchSessionList: '++id,avatar,chatId,username,nickname,userId,toUserId,previewMessage,messages,time,createdAt', workbenchSessionList: '++id,avatar,chatId,username,nickname,userId,toUserId,previewMessage,messages,time,createdAt',
// 聊天记录 // 聊天记录
workbenchChatRecord: '++id,toUserId,messages,messageType,time,createdAt,userInfo', workbenchChatRecord: '++id,[toUserId+userId], [userId+toUserId],toUserId,messages,messageType,time,createdAt,userInfo',
// 群组会话列表 // 群组会话列表
groupSessionList: '++id,groupId,chatId,name,message,previewMessage,avatar,createdAt', groupSessionList: '++id,groupId,chatId,name,message,previewMessage,avatar,createdAt',
// 群组聊天记录 // 群组聊天记录
@ -28,13 +28,14 @@ dbInit.version(1).stores({
workbenchGroupUserList: any; workbenchGroupUserList: any;
workbenchGroupInviteMessage: any; workbenchGroupInviteMessage: any;
groupSessionList: any; groupSessionList: any;
workbenchChatRecord: { addIndex: (arg0: string, arg1: (obj: { toUserId: any; }) => any) => void; }; workbenchChatRecord: any;
}) => { }) => {
// 手动添加索引 // 手动添加索引
tx.groupSessionList.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId); tx.groupSessionList.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId);
tx.workbenchSessionList.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId); tx.workbenchSessionList.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId);
tx.workbenchChatRecord.addIndex('toUserId', (obj: { toUserId: any; }) => obj.toUserId); tx.workbenchChatRecord.addIndex('toUserId', (obj: { toUserId: any; }) => obj.toUserId);
tx.workbenchChatUser.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId); // 添加复合索引
tx.workbenchChatRecord.addIndex('[toUserId+userId]', (obj: { toUserId: any; userId: any; }) => [obj.toUserId, obj.userId]);
tx.workbenchGroupChatRecord.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId); tx.workbenchGroupChatRecord.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId);
tx.workbenchGroupUserList.addIndex('group_id', (obj: { group_id: any; }) => obj.group_id); tx.workbenchGroupUserList.addIndex('group_id', (obj: { group_id: any; }) => obj.group_id);
tx.workbenchGroupInviteMessage.addIndex('group_id', (obj: { group_id: any; }) => obj.group_id); tx.workbenchGroupInviteMessage.addIndex('group_id', (obj: { group_id: any; }) => obj.group_id);

2
frontend/src/system/member.ts

@ -4,7 +4,7 @@ export const memberList = [
appIcon: "chat", appIcon: "chat",
content:"Chat", content:"Chat",
frame: true, frame: true,
width: 1000, width: 900,
height: 650, height: 650,
center: true, center: true,
resizable: true, resizable: true,

Loading…
Cancel
Save