Browse Source

add:新增部门列表数据展示

master
qiutianhong 8 months ago
parent
commit
1eefbe5df7
  1. 3
      frontend/components.d.ts
  2. 2
      frontend/src/components/chat/Chat.vue
  3. 121
      frontend/src/components/chat/ChatUserList.vue
  4. 118
      frontend/src/stores/chat.ts
  5. 2
      frontend/src/stores/db.ts
  6. 3
      frontend/src/stores/upgrade.ts

3
frontend/components.d.ts

@ -57,6 +57,8 @@ declare module 'vue' {
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem'] ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCol: typeof import('element-plus/es')['ElCol'] ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
ElContainer: typeof import('element-plus/es')['ElContainer'] ElContainer: typeof import('element-plus/es')['ElContainer']
ElDialog: typeof import('element-plus/es')['ElDialog'] ElDialog: typeof import('element-plus/es')['ElDialog']
@ -85,6 +87,7 @@ declare module 'vue' {
ElText: typeof import('element-plus/es')['ElText'] ElText: typeof import('element-plus/es')['ElText']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTransfer: typeof import('element-plus/es')['ElTransfer'] ElTransfer: typeof import('element-plus/es')['ElTransfer']
ElTree: typeof import('element-plus/es')['ElTree']
Error: typeof import('./src/components/taskbar/Error.vue')['default'] Error: typeof import('./src/components/taskbar/Error.vue')['default']
FileIcon: typeof import('./src/components/builtin/FileIcon.vue')['default'] FileIcon: typeof import('./src/components/builtin/FileIcon.vue')['default']
FileIconImg: typeof import('./src/components/builtin/FileIconImg.vue')['default'] FileIconImg: typeof import('./src/components/builtin/FileIconImg.vue')['default']

2
frontend/src/components/chat/Chat.vue

@ -126,7 +126,7 @@
<el-button @click="store.groupChatInvitedDialogVisible = false" <el-button @click="store.groupChatInvitedDialogVisible = false"
>取消</el-button >取消</el-button
> >
<el-button @click="store.setGroupInfoDrawerVisible(true)" <el-button @click="store.createGroupChats(true)"
>确定</el-button >确定</el-button
> >
</span> </span>

121
frontend/src/components/chat/ChatUserList.vue

@ -8,6 +8,40 @@
ElRow, ElRow,
} from "element-plus"; } from "element-plus";
const store = useChatStore(); const store = useChatStore();
const handleNodeClick = (data) => {
console.log(data);
};
const defaultProps = {
children: "children",
label: "label",
};
//
function transformData(data) {
return data.map((dept) => ({
label: dept.dept_name,
children: transformUsers(dept.users).concat(
transformSubDepts(dept.sub_depts)
),
}));
}
function transformUsers(users) {
if (!users) return [];
return users.map((user) => ({
label: `${user.user_name} (${user.user_id})`,
children: [],
}));
}
function transformSubDepts(sub_depts) {
if (!sub_depts) return [];
return transformData(sub_depts);
}
const data = transformData(store.departmentList);
console.log(data);
</script> </script>
<template> <template>
@ -17,12 +51,12 @@
<span <span
v-if="store.userList.length > 0" v-if="store.userList.length > 0"
class="title" class="title"
>同事{{ store.userList.length }}</span >在线{{ store.userList.length }}</span
> >
<span <span
v-else v-else
class="title" class="title"
>同事</span >在线</span
> >
</template> </template>
<div v-if="store.userList.length > 0"> <div v-if="store.userList.length > 0">
@ -81,53 +115,60 @@
<el-collapse-item name="2"> <el-collapse-item name="2">
<template #title> <template #title>
<span <span
v-if="store.groupList.length > 0" v-if="store.departmentList.length > 0"
class="title" class="title"
>部门{{ store.groupList.length }}</span
> >
部门{{ store.departmentList.length }}
</span>
<span <span
v-else v-else
class="title" class="title"
>部门</span >部门</span
> >
</template> </template>
<div v-if="store.groupList.length > 0">
<div <div
v-for="group in store.groupList" class="tree-container"
:key="group.id" v-if="data.length > 0"
>
<el-tree
:data="data"
node-key="dept_id"
:props="{ label: 'label', children: 'children' }"
@node-click="handleNodeClick"
:default-expand-all="false"
> >
<div <!-- <template #default="{ node, data }">
class="list-item" <div
@click="store.changeGroupList(group)" class="list-item"
:style="{ @click="store.changeGroupList(data)"
backgroundColor: :style="{
group.id === store.targetGroupId backgroundColor:
? '#C4C4C4' data.dept_id === store.targetGroupId
: '', ? '#C4C4C4'
}" : '',
> }"
<el-row> >
<el-col :span="6"> <el-row>
<el-avatar <el-col :span="6">
shape="square" <el-avatar
:size="40" shape="square"
class="avatar" :size="40"
:src="group.avatar" class="avatar"
/> :src="data.avatar || ''"
</el-col> />
<el-col :span="18"> </el-col>
<el-row> <el-col :span="18">
<el-col :span="18"> <div class="preview-name">
<div class="previewName"> {{ data.dept_name }}
{{ group.name }} </div>
</div> </el-col>
</el-col> </el-row>
</el-row> </div>
</el-col> </template> -->
</el-row> </el-tree>
</div>
</div>
</div> </div>
<div v-else> <div v-else>
<p class="no-data">暂无数据</p> <p class="no-data">暂无数据</p>
</div> </div>
@ -149,7 +190,7 @@
} }
.list-item:hover { .list-item:hover {
background-color: #bae7ff; /* background-color: #bae7ff; */
} }
.avatar { .avatar {

118
frontend/src/stores/chat.ts

@ -1,5 +1,5 @@
import emojiList from "@/assets/emoji.json"; import emojiList from "@/assets/emoji.json";
import { fetchPost, getSystemConfig } from '@/system/config'; import { fetchGet, fetchPost, getSystemConfig } from '@/system/config';
import { notifyError } from "@/util/msg"; import { notifyError } from "@/util/msg";
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { db } from "./db"; import { db } from "./db";
@ -10,8 +10,9 @@ import { db } from "./db";
export const useChatStore = defineStore('chatStore', () => { export const useChatStore = defineStore('chatStore', () => {
interface ChatMessage { interface ChatMessage {
type: string; // 消息类型,0表示文字消息,1表示图片消息,2表示文件消息 id?: any;
time: number; // 消息发送时间 type: any; // 消息类型,0表示文字消息,1表示图片消息,2表示文件消息
time: any; // 消息发送时间
message: any; // 消息内容 message: any; // 消息内容
userId: any; // 发送者id userId: any; // 发送者id
toUserId: any; // 接收者id toUserId: any; // 接收者id
@ -31,6 +32,11 @@ export const useChatStore = defineStore('chatStore', () => {
groupChatInvitedDialogVisible.value = visible; groupChatInvitedDialogVisible.value = visible;
}; };
// 创建群聊
const createGroupChats = () => {
console.log('createGroupChats')
}
// 设置群信息抽屉状态 // 设置群信息抽屉状态
const setGroupInfoDrawerVisible = (visible: boolean) => { const setGroupInfoDrawerVisible = (visible: boolean) => {
groupInfoSettingDrawerVisible.value = visible groupInfoSettingDrawerVisible.value = visible
@ -61,30 +67,7 @@ export const useChatStore = defineStore('chatStore', () => {
// 群组数据 // 群组数据
const groupList: any = ref([ const groupList: any = ref([
{
id: 1,
name: '群组1',
avatar: '/logo.png',
previewTimeFormat: "今天",
previewType: 0,
previewMessage: "这是一个示例消息。",
},
{
id: 2,
name: '群组2',
avatar: '/logo.png',
previewTimeFormat: "今天",
previewType: 0,
previewMessage: "这是一个示例消息。",
},
{
id: 3,
name: '群组3',
avatar: '/logo.png',
previewTimeFormat: "今天",
previewType: 0,
previewMessage: "这是一个示例消息。",
}
]); ]);
const activeNames = ref([]); const activeNames = ref([]);
@ -100,6 +83,11 @@ export const useChatStore = defineStore('chatStore', () => {
const targetUserInfo: any = ref({}); const targetUserInfo: any = ref({});
const targetUserId = ref(); const targetUserId = ref();
const search = ref(''); const search = ref('');
// 部门列表
const departmentList = ref([
])
const contextMenu = ref({ const contextMenu = ref({
visible: false, visible: false,
@ -112,18 +100,29 @@ export const useChatStore = defineStore('chatStore', () => {
y: 0 y: 0
}); });
const initChat = () => { const initChat = () => {
if (config.userInfo.avatar == '') { if (config.userInfo.avatar == '') {
config.userInfo.avatar = '/logo.png'; config.userInfo.avatar = '/logo.png';
} }
userInfo.value = config.userInfo; userInfo.value = config.userInfo;
getUserList() getUserList()
// initUserList() getDepartmentList()
initUserList()
initChatList() initChatList()
// initOnlineUserList() // initOnlineUserList()
console.log(userList.value); console.log(userList.value);
}; };
// 获取部门列表
const getDepartmentList = async () => {
const res = await fetchGet(userInfo.value.url+"/chat/user/list")
console.log(res);
if (res.ok) {
const data = await res.json();
departmentList.value = data.data.users;
}
}
// 初始化用户列表 // 初始化用户列表
const initChatList = async () => { const initChatList = async () => {
chatList.value = await db.getAll('conversationList'); chatList.value = await db.getAll('conversationList');
@ -137,21 +136,24 @@ export const useChatStore = defineStore('chatStore', () => {
const sendMessage = async () => { const sendMessage = async () => {
const chatSendUrl = config.userInfo.url + '/chat/send'; const chatSendUrl = config.userInfo.url + '/chat/send';
// 封装成消息历史记录 // 封装成消息历史记录
console.log(chatSendUrl);
const messageHistory: ChatMessage = { const messageHistory: ChatMessage = {
type: 'user', type: 'user',
time: Date.now(), time: null,
message: message.value, message: message.value,
userId: userInfo.value.userId, userId: userInfo.value.id,
toUserId: targetUserId.value, toUserId: targetUserId.value,
// receiver: targetUserId.value,
userInfo: { userInfo: {
}, },
}; };
// 发送消息 console.log(messageHistory);
const res = await fetchPost(chatSendUrl, messageHistory);
console.log(res); // 创建没有 `id` 属性的副本
const { id, ...messageHistoryWithoutId } = messageHistory;
console.log(messageHistoryWithoutId);
// 发送消息
const res = await fetchPost(chatSendUrl, JSON.stringify(messageHistoryWithoutId));
if (res.ok) { if (res.ok) {
// 本地存储一份聊天记录 // 本地存储一份聊天记录
await db.addOne('chatRecord', messageHistory); await db.addOne('chatRecord', messageHistory);
@ -159,10 +161,8 @@ export const useChatStore = defineStore('chatStore', () => {
// 更新聊天历史 // 更新聊天历史
chatHistory.value.push(messageHistory); chatHistory.value.push(messageHistory);
console.log(chatHistory.value);
// 更新 chatList 和 conversationList // 更新 chatList 和 conversationList
// await changeChatListAndGetChatHistory(targetUserId.value, messageHistory); // await changeChatListAndGetChatHistory(userInfo.value.userId);
// 清空输入框 // 清空输入框
clearMessage(); clearMessage();
@ -240,8 +240,8 @@ export const useChatStore = defineStore('chatStore', () => {
// 检查 userId 是否在 map 中 // 检查 userId 是否在 map 中
if (chatListMap.has(userId)) { if (chatListMap.has(userId)) {
// 如果存在获取聊天记录添加到historyList // 如果存在获取聊天记录添加到historyList
const data = await db.getByField("chatRecord", "userId", userId) // console.log(getHistory(userId, userInfo.value.id))
chatHistory.value = data chatHistory.value = await getHistory(userId, userInfo.value.id)
return; return;
} else { } else {
// 如果不在chatlist中表示没有聊天记录。那么去用户表中获取该用户的基本信息 // 如果不在chatlist中表示没有聊天记录。那么去用户表中获取该用户的基本信息
@ -320,6 +320,7 @@ export const useChatStore = defineStore('chatStore', () => {
// 更新聊天记录表 // 更新聊天记录表
// 更新会话列表数据库 // 更新会话列表数据库
// 更新chatlist // 更新chatlist
console.log(data)
const isPresence = await db.getByField('workbenchusers', 'id', data.userId) const isPresence = await db.getByField('workbenchusers', 'id', data.userId)
if (isPresence[0].id !== data.userId) { if (isPresence[0].id !== data.userId) {
return return
@ -458,7 +459,6 @@ export const useChatStore = defineStore('chatStore', () => {
try { try {
// 从数据库中获取所有用户信息 // 从数据库中获取所有用户信息
const list = await db.getAll("workbenchusers"); const list = await db.getAll("workbenchusers");
console.log(list);
// 创建一个 Map,用于存储每个用户的唯一 ID 地址 // 创建一个 Map,用于存储每个用户的唯一 ID 地址
let uniqueIdMap = new Map<string, any>(); let uniqueIdMap = new Map<string, any>();
@ -481,8 +481,6 @@ export const useChatStore = defineStore('chatStore', () => {
// 初始化统一用户列表状态 // 初始化统一用户列表状态
const initUserList = async () => { const initUserList = async () => {
console.log("初始化用户列表状态");
console.log(userList.value);
if (!userList.value.length) return; if (!userList.value.length) return;
// 获取需要更新的用户数据(只选取在线的用户并设为离线状态) // 获取需要更新的用户数据(只选取在线的用户并设为离线状态)
const updates = userList.value.reduce((acc: any[], user: any) => { const updates = userList.value.reduce((acc: any[], user: any) => {
@ -541,30 +539,23 @@ export const useChatStore = defineStore('chatStore', () => {
targetUserId.value = userId; targetUserId.value = userId;
// 获取当前用户和目标用户的聊天记录 // 获取当前用户和目标用户的聊天记录
const messagesList = await db.getByField('chatRecord', 'userId', userId);
// // 表示与该用户没有聊天记录,但是也需要初始化一些信息
// if (messagesList.length == 0) {
// const userData:any = await db.getOne("workbenchusers", userId)
// console.log(userData)
// const data: any = {
// userId: userData.id,
// userInfo: {
// id: userData.id,
// avatar: userData.avatar,
// nickname: userData.nickname,
// }
// }
// chatHistory.value.push(data)
// } else {
chatHistory.value = messagesList;
// }
const history = await getHistory(userId, userInfo.value.id)
chatHistory.value = history;
// 设置目标用户的信息 // 设置目标用户的信息
await setTargetUserInfo(userId); await setTargetUserInfo(userId);
}; };
const getHistory = async (userId: any, toUserId: any) => {
const messagesList = await db.filter('chatRecord', (record: any) => {
return (
(record.userId === userId && record.toUserId === toUserId) ||
(record.toUserId === userId && record.userId === toUserId)
);
});
return messagesList
}
const setTargetUserInfo = async (id: number) => { const setTargetUserInfo = async (id: number) => {
@ -605,6 +596,7 @@ export const useChatStore = defineStore('chatStore', () => {
groupChatInvitedDialogVisible, groupChatInvitedDialogVisible,
groupInfoSettingDrawerVisible, groupInfoSettingDrawerVisible,
targetNickname, targetNickname,
departmentList,
initChat, initChat,
showContextMenu, showContextMenu,
setCurrentNavId, setCurrentNavId,
@ -618,6 +610,8 @@ export const useChatStore = defineStore('chatStore', () => {
setGroupInfoDrawerVisible, setGroupInfoDrawerVisible,
createGroupChat, createGroupChat,
userChatMessage, userChatMessage,
initOnlineUserList initOnlineUserList,
getDepartmentList,
createGroupChats
}; };
}); });

2
frontend/src/stores/db.ts

@ -5,7 +5,7 @@ export type ChatTable = 'chatuser' | 'chatmsg' | 'chatmessage' | 'groupmessage'
export const dbInit: any = new Dexie('GodoOSDatabase'); export const dbInit: any = new Dexie('GodoOSDatabase');
dbInit.version(1).stores({ dbInit.version(1).stores({
// 用户列表 // 用户列表
workbenchusers: '++id,ip,userName,avatar,mobile,nickName,isOnline,updatedAt,createdAt', workbenchusers: '++id,ip,userName,avatar,mobile,phone,nickName,isOnline,updatedAt,createdAt',
// 聊天记录 // 聊天记录
chatRecord: '++id,toUserId,messages,time,createdAt,userInfo', chatRecord: '++id,toUserId,messages,time,createdAt,userInfo',
// 会话列表 // 会话列表

3
frontend/src/stores/upgrade.ts

@ -94,7 +94,8 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
chatChatStore.handleUserData(message.data) chatChatStore.handleUserData(message.data)
break; break;
case 'user': case 'user':
chatChatStore.userChatMessage console.log(message.data)
chatChatStore.userChatMessage(message.data)
break break
default: default:
console.warn('Unknown message type:', message.type); console.warn('Unknown message type:', message.type);

Loading…
Cancel
Save