Browse Source

fix:合并冲突

master
prr 7 months ago
parent
commit
e395736202
  1. 4
      frontend/auto-imports.d.ts
  2. 153
      frontend/components.d.ts
  3. 134
      frontend/src/components/chat/Chat.vue
  4. 57
      frontend/src/components/chat/ChatBox.vue
  5. 151
      frontend/src/components/chat/ChatMessage.vue
  6. 42
      frontend/src/components/chat/ChatMsgList.vue
  7. 11
      frontend/src/components/chat/ChatUserList.vue
  8. 6
      frontend/src/components/chat/chatUserInfo.vue
  9. 606
      frontend/src/stores/chat.ts
  10. 42
      frontend/src/stores/db.ts
  11. 2
      frontend/src/stores/notify.ts
  12. 22
      frontend/src/stores/upgrade.ts
  13. 1
      frontend/src/system/index.ts
  14. 5
      frontend/src/util/sharePath.ts
  15. 6
      godo/files/os.go

4
frontend/auto-imports.d.ts

@ -3,9 +3,11 @@
// @ts-nocheck // @ts-nocheck
// noinspection JSUnusedGlobalSymbols // noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import // Generated by unplugin-auto-import
// biome-ignore lint: disable
export {} export {}
declare global { declare global {
const EffectScope: typeof import('vue')['EffectScope'] const EffectScope: typeof import('vue')['EffectScope']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const computed: typeof import('vue')['computed'] const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp'] const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef'] const customRef: typeof import('vue')['customRef']
@ -70,6 +72,6 @@ declare global {
// for type re-export // for type re-export
declare global { declare global {
// @ts-ignore // @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue') import('vue')
} }

153
frontend/components.d.ts

@ -0,0 +1,153 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
Ad: typeof import('./src/components/desktop/Ad.vue')['default']
AddApp: typeof import('./src/components/store/AddApp.vue')['default']
AppIcon: typeof import('./src/components/taskbar/AppIcon.vue')['default']
AppIconGroup: typeof import('./src/components/taskbar/AppIconGroup.vue')['default']
AppItem: typeof import('./src/components/store/AppItem.vue')['default']
Battery: typeof import('./src/components/taskbar/Battery.vue')['default']
BatteryPop: typeof import('./src/components/taskbar/BatteryPop.vue')['default']
Browser: typeof import('./src/components/builtin/Browser.vue')['default']
Calendar: typeof import('./src/components/builtin/Calendar.vue')['default']
Chat: typeof import('./src/components/chat/Chat.vue')['default']
ChatBox: typeof import('./src/components/chat/ChatBox.vue')['default']
ChatContent: typeof import('./src/components/localchat/ChatContent.vue')['default']
ChatDomain: typeof import('./src/components/localchat/ChatDomain.vue')['default']
ChatEditor: typeof import('./src/components/localchat/ChatEditor.vue')['default']
ChatFoot: typeof import('./src/components/localchat/ChatFoot.vue')['default']
ChatMenu: typeof import('./src/components/chat/ChatMenu.vue')['default']
ChatMessage: typeof import('./src/components/chat/ChatMessage.vue')['default']
ChatMsgList: typeof import('./src/components/chat/ChatMsgList.vue')['default']
ChatNav: typeof import('./src/components/localchat/ChatNav.vue')['default']
ChatUserInfo: typeof import('./src/components/chat/chatUserInfo.vue')['default']
ChatUserList: typeof import('./src/components/chat/ChatUserList.vue')['default']
ChatUserSetting: typeof import('./src/components/chat/ChatUserSetting.vue')['default']
ChatWorkList: typeof import('./src/components/chat/ChatWorkList.vue')['default']
CloseButton: typeof import('./src/components/ui/CloseButton.vue')['default']
CloseDesktop: typeof import('./src/components/desktop/CloseDesktop.vue')['default']
ColorPicker: typeof import('./src/components/setting/ColorPicker.vue')['default']
Computer: typeof import('./src/components/computer/Computer.vue')['default']
ComputerNavBar: typeof import('./src/components/computer/ComputerNavBar.vue')['default']
ContextMenu: typeof import('./src/components/builtin/ContextMenu.vue')['default']
CreateUrl: typeof import('./src/components/builtin/CreateUrl.vue')['default']
CustomIcon: typeof import('./src/components/taskbar/CustomIcon.vue')['default']
DateNote: typeof import('./src/components/builtin/DateNote.vue')['default']
DateTime: typeof import('./src/components/taskbar/DateTime.vue')['default']
DateTimePop: typeof import('./src/components/taskbar/DateTimePop.vue')['default']
DeskItem: typeof import('./src/components/desktop/DeskItem.vue')['default']
Desktop: typeof import('./src/components/desktop/Desktop.vue')['default']
DesktopBackground: typeof import('./src/components/desktop/DesktopBackground.vue')['default']
DialogProcess: typeof import('./src/components/window/DialogProcess.vue')['default']
DialogTemp: typeof import('./src/components/window/DialogTemp.vue')['default']
EditFileName: typeof import('./src/components/builtin/EditFileName.vue')['default']
EditType: typeof import('./src/components/builtin/EditType.vue')['default']
ElAside: typeof import('element-plus/es')['ElAside']
ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCol: typeof import('element-plus/es')['ElCol']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElFooter: typeof import('element-plus/es')['ElFooter']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElMain: typeof import('element-plus/es')['ElMain']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTransfer: typeof import('element-plus/es')['ElTransfer']
ElTree: typeof import('element-plus/es')['ElTree']
Error: typeof import('./src/components/taskbar/Error.vue')['default']
FileIcon: typeof import('./src/components/builtin/FileIcon.vue')['default']
FileIconImg: typeof import('./src/components/builtin/FileIconImg.vue')['default']
FileIconIs: typeof import('./src/components/builtin/FileIconIs.vue')['default']
FileList: typeof import('./src/components/builtin/FileList.vue')['default']
FileProps: typeof import('./src/components/builtin/FileProps.vue')['default']
FileTree: typeof import('./src/components/builtin/FileTree.vue')['default']
FileViewer: typeof import('./src/components/builtin/FileViewer.vue')['default']
IframeFile: typeof import('./src/components/window/IframeFile.vue')['default']
ImageViewer: typeof import('./src/components/builtin/ImageViewer.vue')['default']
Install: typeof import('./src/components/install/Install.vue')['default']
InstallCompony: typeof import('./src/components/install/InstallCompony.vue')['default']
InstallMember: typeof import('./src/components/install/InstallMember.vue')['default']
InstallPerson: typeof import('./src/components/install/InstallPerson.vue')['default']
LocalChat: typeof import('./src/components/localchat/LocalChat.vue')['default']
LockDesktop: typeof import('./src/components/desktop/LockDesktop.vue')['default']
Magnet: typeof import('./src/components/taskbar/Magnet.vue')['default']
MarkDown: typeof import('./src/components/builtin/MarkDown.vue')['default']
MenuBar: typeof import('./src/components/window/MenuBar.vue')['default']
MenuList: typeof import('./src/components/taskbar/MenuList.vue')['default']
MessageCenterPop: typeof import('./src/components/taskbar/MessageCenterPop.vue')['default']
MessageIcon: typeof import('./src/components/taskbar/MessageIcon.vue')['default']
MusicStore: typeof import('./src/components/builtin/MusicStore.vue')['default']
MusicViewer: typeof import('./src/components/builtin/MusicViewer.vue')['default']
NetWork: typeof import('./src/components/taskbar/NetWork.vue')['default']
NetworkPop: typeof import('./src/components/taskbar/NetworkPop.vue')['default']
NotFound: typeof import('./src/components/window/NotFound.vue')['default']
Notice: typeof import('./src/components/desktop/Notice.vue')['default']
NotifyGroup: typeof import('./src/components/builtin/NotifyGroup.vue')['default']
OpeningDesktop: typeof import('./src/components/desktop/OpeningDesktop.vue')['default']
OpenWiteDialog: typeof import('./src/components/builtin/OpenWiteDialog.vue')['default']
OsImage: typeof import('./src/components/builtin/OsImage.vue')['default']
PdfViewer: typeof import('./src/components/builtin/PdfViewer.vue')['default']
PictureStore: typeof import('./src/components/builtin/PictureStore.vue')['default']
PlanTasks: typeof import('./src/components/oa/PlanTasks.vue')['default']
ProcessManager: typeof import('./src/components/setting/ProcessManager.vue')['default']
QuickLink: typeof import('./src/components/computer/QuickLink.vue')['default']
RectChosen: typeof import('./src/components/builtin/RectChosen.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Screen: typeof import('./src/components/desktop/Screen.vue')['default']
ScreenContent: typeof import('./src/components/desktop/ScreenContent.vue')['default']
ScreenRecorder: typeof import('./src/components/taskbar/ScreenRecorder.vue')['default']
Screenshort: typeof import('./src/components/taskbar/Screenshort.vue')['default']
SetAccount: typeof import('./src/components/setting/SetAccount.vue')['default']
SetCustom: typeof import('./src/components/setting/SetCustom.vue')['default']
SetFilePwd: typeof import('./src/components/setting/SetFilePwd.vue')['default']
SetLang: typeof import('./src/components/setting/SetLang.vue')['default']
SetSystem: typeof import('./src/components/setting/SetSystem.vue')['default']
Setting: typeof import('./src/components/setting/Setting.vue')['default']
SetUpdate: typeof import('./src/components/setting/SetUpdate.vue')['default']
ShareFiles: typeof import('./src/components/oa/ShareFiles.vue')['default']
ShowNews: typeof import('./src/components/taskbar/ShowNews.vue')['default']
StartMenu: typeof import('./src/components/taskbar/StartMenu.vue')['default']
StartOption: typeof import('./src/components/taskbar/StartOption.vue')['default']
StateIcon: typeof import('./src/components/taskbar/StateIcon.vue')['default']
Store: typeof import('./src/components/store/Store.vue')['default']
Taskbar: typeof import('./src/components/taskbar/Taskbar.vue')['default']
Upgrade: typeof import('./src/components/desktop/Upgrade.vue')['default']
UpPopover: typeof import('./src/components/computer/UpPopover.vue')['default']
UrlBrowser: typeof import('./src/components/builtin/UrlBrowser.vue')['default']
Version: typeof import('./src/components/builtin/Version.vue')['default']
VideoViewer: typeof import('./src/components/builtin/VideoViewer.vue')['default']
WinButton: typeof import('./src/components/ui/WinButton.vue')['default']
WinCheckBox: typeof import('./src/components/ui/WinCheckBox.vue')['default']
WindowGroup: typeof import('./src/components/window/WindowGroup.vue')['default']
WindowInner: typeof import('./src/components/window/WindowInner.vue')['default']
WindowNode: typeof import('./src/components/window/WindowNode.vue')['default']
WindowTemplate: typeof import('./src/components/window/WindowTemplate.vue')['default']
WinInput: typeof import('./src/components/ui/WinInput.vue')['default']
WinLoading: typeof import('./src/components/ui/WinLoading.vue')['default']
WinLogo: typeof import('./src/components/ui/WinLogo.vue')['default']
WinProcess: typeof import('./src/components/ui/WinProcess.vue')['default']
WinSelect: typeof import('./src/components/ui/WinSelect.vue')['default']
WinUpButtonGroup: typeof import('./src/components/ui/WinUpButtonGroup.vue')['default']
}
}

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

@ -18,13 +18,27 @@
}; };
const data = ref(generateData()); const data = ref(generateData());
const users = ref([]); // users any[]
const users = ref<any[]>([]);
watchEffect(() => { watchEffect(() => {
if (store.allUserList.length > 0) { if (store.allUserList.length > 0) {
data.value = generateData(); data.value = generateData();
} }
}); });
function toggleSelectItem(item: any) {
const index = users.value.indexOf(item.key);
if (index === -1) {
users.value.push(item.key);
} else {
users.value.splice(index, 1);
}
}
function removeItem(userId:string) {
users.value = users.value.filter((user) => user !== userId);
}
</script> </script>
<template> <template>
<el-container class="container"> <el-container class="container">
@ -89,6 +103,7 @@
v-model="store.groupChatInvitedDialogVisible" v-model="store.groupChatInvitedDialogVisible"
title="发起群聊" title="发起群聊"
width="80%" width="80%"
align-center
> >
<div class="dialog-body"> <div class="dialog-body">
<!-- 添加输入部门名的输入框 --> <!-- 添加输入部门名的输入框 -->
@ -96,22 +111,57 @@
v-model="store.departmentName" v-model="store.departmentName"
placeholder="请输入群聊名称" placeholder="请输入群聊名称"
></el-input> ></el-input>
<el-transfer <div class="transfer-container">
v-model="users" <!-- 自定义穿梭框组件 -->
:data="data" <div class="transfer-box">
<div class="list-box">
<h3>可选项</h3>
<ul>
<li
v-for="item in data"
:key="item.key"
@click="toggleSelectItem(item)"
:class="{ selected: users.includes(item.key) }"
> >
<!-- 义穿梭框 -->
<template #default="{ option }">
<div class="user-item">
<el-avatar <el-avatar
:size="20" :size="10"
:src="option.avatar" :src="item.avatar"
class="avatar" class="avatar"
/> />
<span>{{ option.label }}</span> <input
type="checkbox"
:checked="users.includes(item.key)"
/>
<span>{{ item.label }}</span>
<span
v-if="users.includes(item.key)"
class="remove-icon"
@click.stop="removeItem(item.key)"
></span
>
</li>
</ul>
</div>
<div class="list-box">
<h3>已选项</h3>
<ul>
<li
v-for="user in users"
:key="user"
>
<span>{{
data.find((item: any) => item.key === user)?.label
}}</span>
<span
class="remove-icon"
@click="removeItem(user)"
></span
>
</li>
</ul>
</div>
</div>
</div> </div>
</template>
</el-transfer>
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
@ -200,19 +250,16 @@
.dialog-body { .dialog-body {
width: 100%; width: 100%;
} }
.transfer-container >>> .el-transfer-panel {
width: 300px;
}
.el-transfer { .el-transfer {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
/* .el-transfer >>> .el-transfer-panel >>> .el-transfer__buttons {
width: 50px;
} */
/* .el-transfer__button {
width: 20px;;
} */
.chat-box { .chat-box {
flex: 3; flex: 3;
/* 占据剩余宽度的三倍 */ /* 占据剩余宽度的三倍 */
@ -240,4 +287,53 @@
font-size: 14px; font-size: 14px;
justify-content: center; justify-content: center;
} }
.transfer-box {
display: flex;
gap: 0;
}
.list-box {
width: 50%;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
}
.list-box ul {
list-style: none;
padding: 0;
margin: 0;
}
.list-box li {
display: flex;
align-items: center;
padding: 5px 0;
cursor: pointer;
transition: background-color 0.2s;
}
.list-box li:hover {
background-color: #f0f8ff;
}
.list-box li.selected {
background-color: #e6f7ff;
}
input[type="checkbox"] {
margin-right: 8px;
}
.remove-icon {
margin-left: auto;
color: #d32f2f;
cursor: pointer;
font-size: 14px;
}
.remove-icon:hover {
color: #ff5a5a;
}
</style> </style>

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

@ -6,12 +6,42 @@
<!--聊天顶部区--> <!--聊天顶部区-->
<el-header class="chat-header"> <el-header class="chat-header">
<div class="header-title"> <div class="header-title">
<span v-if="store.targetUserInfo.displayName">{{ <span
store.targetUserInfo.displayName v-if="store.targetUserInfo.displayName"
}}</span> class="header-title-name"
<span v-else-if="store.targetGroupInfo.displayName">{{ >{{ store.targetUserInfo.displayName }}</span
store.targetGroupInfo.displayName >
}}</span> <span
v-else-if="store.targetGroupInfo.displayName"
class="header-title-name"
>{{ store.targetGroupInfo.displayName }}</span
>
<!-- 更多 -->
<el-dropdown
placement="bottom"
v-if="
store.targetGroupInfo &&
Object.keys(store.targetGroupInfo).length > 0
"
>
<!-- 设置 -->
<el-icon><More /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="store.inviteFriend"
>邀请好友</el-dropdown-item
>
<el-dropdown-item
@click="
store.quitGroup(
store.targetGroupInfo.chatId
)
"
>退出群聊</el-dropdown-item
>
</el-dropdown-menu>
</template>
</el-dropdown>
</div> </div>
</el-header> </el-header>
@ -103,6 +133,7 @@
choose.select("选择图片", imgExt); choose.select("选择图片", imgExt);
} }
function selectFile() { function selectFile() {
console.log("selectFile")
choosetype.value = "applyfile"; choosetype.value = "applyfile";
choose.select("选择文件", "*"); choose.select("选择文件", "*");
} }
@ -115,6 +146,7 @@
if (paths.length > 0) { if (paths.length > 0) {
store.sendInfo = paths; store.sendInfo = paths;
choose.path = []; choose.path = [];
console.log(choosetype.value);
store.sendMessage(choosetype.value); store.sendMessage(choosetype.value);
} }
}, },
@ -137,10 +169,17 @@
-webkit-app-region: drag; -webkit-app-region: drag;
} }
header-title { .header-title {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0px 10px;
}
.header-title-name {
height: 50px;
line-height: 50px;
font-size: 20px; font-size: 20px;
text-align: left;
margin-left: 15px;
} }
.msg-main { .msg-main {

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

@ -2,10 +2,10 @@
<div <div
v-if="store.chatHistory && store.chatHistory.length > 0" v-if="store.chatHistory && store.chatHistory.length > 0"
v-for="item in store.chatHistory" v-for="item in store.chatHistory"
:key="item.time" :key="item.chatId"
> >
<div <div
v-if="item.userId == store.userInfo.id" v-if="item.isMe"
class="chat-item" class="chat-item"
> >
<el-row> <el-row>
@ -14,20 +14,55 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<div class="chat-name-me"> <div class="chat-name-me">
{{ item.userInfo.nickname }} {{ store.userInfo.nickname }}
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div <div
class="bubble-me" class="bubble-me"
@contextmenu.prevent=" @contextmenu.prevent="
store.showContextMenu($event, item.userId) store.showContextMenu($event, item.chatId)
" "
> >
<div class="chat-font"> <!-- 文本消息展示 -->
<div
v-if="item.content_type == 'text'"
class="chat-font"
>
{{ item.message }}
</div>
<!-- 文件消息展示 -->
<div
v-else-if="item.content_type == 'file'"
:class="['chat-item-file', 'file-me']"
>
<!-- 文件图标 -->
<div class="chat-item-file-icon">
<el-icon
size="30"
color="#303133"
><Document
/></el-icon>
</div>
<!-- 文件名 -->
<div class="chat-item-file-name">
{{ item.message }} {{ item.message }}
</div> </div>
</div> </div>
<!-- 图片消息展示 -->
<div
v-else-if="item.content_type == 'image'"
class="chat-item-image"
>
<el-image
fit="cover"
loading="lazy"
:src="item.message"
/>
</div>
</div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="chat-avatar"> <div class="chat-avatar">
@ -36,7 +71,7 @@
style="margin: 0; float: left" style="margin: 0; float: left"
:size="32" :size="32"
class="userAvatar" class="userAvatar"
:src="item.userInfo.avatar" :src="item.avatar"
/> />
</div> </div>
</el-col> </el-col>
@ -54,7 +89,7 @@
style="margin: 0; float: right" style="margin: 0; float: right"
:size="32" :size="32"
class="userAvatar" class="userAvatar"
:src="item.userInfo.avatar" :src="item.avatar"
/> />
</div> </div>
</el-col> </el-col>
@ -62,15 +97,50 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<div class="chat-name-other"> <div class="chat-name-other">
{{ item.userInfo.nickname }} {{ item.displayName }}
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div class="bubble-other"> <div class="bubble-other">
<div class="chat-font"> <!-- 文本消息展示 -->
<div
v-if="item.content_type == 'text'"
class="chat-font"
>
{{ item.message }}
</div>
<!-- 文件消息展示 -->
<div
v-else-if="item.content_type == 'file'"
:class="['chat-item-file', 'file-other']"
>
<!-- 文件图标 -->
<div class="chat-item-file-icon">
<el-icon
size="30"
color="#303133"
><Document
/></el-icon>
</div>
<!-- 文件名 -->
<div class="chat-item-file-name">
{{ item.message }} {{ item.message }}
</div> </div>
</div> </div>
<!-- 图片消息展示 -->
<div
v-else-if="item.content_type == 'image'"
class="chat-item-image"
>
<el-image
fit="cover"
loading="lazy"
:src="item.message"
/>
</div>
</div>
</el-col> </el-col>
<el-col :span="8" /> <el-col :span="8" />
</el-row> </el-row>
@ -107,22 +177,22 @@
</script> </script>
<style scoped> <style scoped>
.bubble-me { .bubble-me,
background-color: #95ec69;
float: right;
border-radius: 4px;
margin-right: 5px;
margin-top: 5px;
padding: 5px;
}
.bubble-other { .bubble-other {
display: flex;
align-items: center;
background-color: #ffffff; background-color: #ffffff;
float: left; float: left;
border-radius: 4px; border-radius: 4px;
margin-left: 5px; margin-left: 5px;
margin-top: 5px; margin-bottom: 20px;
padding: 5px; }
.bubble-me {
background-color: #95ec69;
float: right;
margin-right: 5px;
margin-left: 0;
} }
.chat-name-me, .chat-name-me,
@ -131,12 +201,51 @@
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
line-height: 1.5; line-height: 1.5;
color: #b2b2b2; color: #b2b2b2;
margin-bottom: 2px;
margin-left: 2px;
}
.chat-name-me {
text-align: right; /* 右对齐昵称 */
margin-right: 2px;
} }
.chat-font { .chat-font {
margin: 8px;
font-size: 15px; font-size: 15px;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
line-height: 1.5; line-height: 1.5;
margin: 10px;
}
.chat-item-file {
border-radius: 4px;
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px;
}
.file-me {
flex-direction: row; /* 图标在左边 */
}
.file-other {
flex-direction: row-reverse; /* 图标在右边 */
}
.chat-item-file-icon {
width: 40px;
}
.chat-item-file-name {
font-size: 14px;
font-family: Arial, sans-serif;
line-height: 1.5;
color: #409eff;
}
.chat-item-image {
width: 180px;
height: 180px;
margin: 10px;
} }
</style> </style>

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

@ -1,10 +1,15 @@
<template> <template>
<div v-if="store.chatList.length > 0" v-for="item in store.chatList" :key="item.id"> <div
v-if="store.chatList.length > 0"
v-for="item in store.chatList"
:key="item.id"
>
<div <div
class="list-item" class="list-item"
@click="store.changeChatList(item.chatId,item.type)" @click="store.getSessionInfo(item.chatId, item.type)"
:style="{ :style="{
backgroundColor: item.userId == store.targetChatId ? '#bae7ff' : '', backgroundColor:
item.chatId == store.targetChatId ? '#bae7ff' : '',
}" }"
> >
<el-row> <el-row>
@ -16,16 +21,26 @@
:src="item.avatar" :src="item.avatar"
/> />
</el-col> </el-col>
<el-col :span="18" class="preview"> <el-col
:span="18"
class="preview"
>
<el-row class="preview-content"> <el-row class="preview-content">
<el-col :span="18" class="preview-left"> <el-col
<div class="previewName">{{ item.displayName }}</div> :span="18"
class="preview-left"
>
<div class="previewName">
{{ item.displayName }}
</div>
<div class="previewChat"> <div class="previewChat">
<span>{{ item.previewMessage }}</span> <span>{{ item.previewMessage }}</span>
</div> </div>
</el-col> </el-col>
<el-col :span="6" class="preview-right"> <el-col
:span="6"
class="preview-right"
>
<div class="previewTime"> <div class="previewTime">
{{ item.previewTimeFormat }} {{ item.previewTimeFormat }}
</div> </div>
@ -35,8 +50,14 @@
</el-row> </el-row>
</div> </div>
</div> </div>
<div v-else class="emptyChat"> <div
<el-icon :size="60" class="chat-icon"> v-else
class="emptyChat"
>
<el-icon
:size="60"
class="chat-icon"
>
<ChatSquare /> <ChatSquare />
</el-icon> </el-icon>
<p class="empty-message">暂无数据</p> <p class="empty-message">暂无数据</p>
@ -49,7 +70,6 @@ import { ref } from "vue";
const store = useChatStore(); const store = useChatStore();
const id = ref("1"); const id = ref("1");
</script> </script>
<style scoped> <style scoped>

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

@ -49,9 +49,9 @@
<el-collapse-item name="1"> <el-collapse-item name="1">
<template #title> <template #title>
<span <span
v-if="store.userList.length > 0" v-if="store.onlineUserList.length > 0"
class="title" class="title"
>在线{{ store.userList.length }}</span >在线{{ store.onlineUserList.length }}</span
> >
<span <span
v-else v-else
@ -59,15 +59,14 @@
>在线</span >在线</span
> >
</template> </template>
<div v-if="store.userList.length > 0"> <div v-if="store.onlineUserList.length > 0">
<div <div
v-for="item in store.userList" v-for="item in store.onlineUserList"
:key="item.id" :key="item.id"
> >
<div <div
class="list-item" class="list-item"
@click="store.changeChatList(item.id,'user')" @click="store.getSessionInfo(item.chatId, 'user')"
:style="{ :style="{
backgroundColor: backgroundColor:
item.id === store.targetChatId ? '#bae7ff' : '', item.id === store.targetChatId ? '#bae7ff' : '',

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

@ -16,7 +16,7 @@
class="user-info-container" class="user-info-container"
> >
<div class="user-details"> <div class="user-details">
<p>昵称: {{ store.targetUserInfo.nickname }}</p> <p>昵称: {{ store.targetUserInfo.displayName }}</p>
<p>邮箱: {{ store.targetUserInfo.email }}</p> <p>邮箱: {{ store.targetUserInfo.email }}</p>
<p>电话: {{ store.targetUserInfo.phone }}</p> <p>电话: {{ store.targetUserInfo.phone }}</p>
<p>描述: {{ store.targetUserInfo.desc }}</p> <p>描述: {{ store.targetUserInfo.desc }}</p>
@ -37,9 +37,9 @@
const store = useChatStore(); const store = useChatStore();
const sendMessage = (userId:number) => { const sendMessage = (chatId: string) => {
store.currentNavId = 0; store.currentNavId = 0;
store.changeChatListAndGetChatHistory(userId) store.addChatListAndGetChatHistory(chatId);
}; };
</script> </script>

606
frontend/src/stores/chat.ts

@ -1,30 +1,26 @@
import emojiList from "@/assets/emoji.json"; import emojiList from "@/assets/emoji.json";
import { fetchGet, fetchPost, getSystemConfig } from '@/system/config'; import { fetchGet, fetchPost, getSystemConfig } from '@/system/config';
import { notifyError } from "@/util/msg"; import { notifySuccess } from "@/util/msg";
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { db } from "./db"; import { db } from "./db";
export const useChatStore = defineStore('chatStore', () => { export const useChatStore = defineStore('chatStore', () => {
interface ChatMessage { interface OnlineUserInfoType {
id?: any; id: string;
type: any; ip: string;
time?: any; avatar: string;
message: any; // 消息内容 online: boolean;
userId: any; // 发送者id type: string;
toUserId?: any; // 接收者id chatId: string;
to_groupid?: any; username: string;
groupId?: any; nickname: string;
messageType?: string; // 消息类型,0表示文字消息,1表示图片消息,2表示文件消息
userInfo: { // 发送者信息
} }
};
// 文件消息类型 // 文件消息类型
interface ChatFileMessage { interface ChatMessageType {
type: string; type: string;
content_type: string; content_type: string;
time: Date | null; time: string;
userId: number; userId: number;
toUserId: number; toUserId: number;
message: string; message: string;
@ -33,10 +29,10 @@ export const useChatStore = defineStore('chatStore', () => {
} }
// 文件发送模型 // 文件发送模型
const fileMessage: ChatFileMessage = { const Message: ChatMessageType = {
type: '', type: '',
content_type: '', content_type: '',
time: null, time: new Date().toISOString(),
userId: 0, userId: 0,
toUserId: 0, toUserId: 0,
message: '', message: '',
@ -47,6 +43,9 @@ export const useChatStore = defineStore('chatStore', () => {
// 发起群聊对话框显示 // 发起群聊对话框显示
const groupChatInvitedDialogVisible = ref(false); const groupChatInvitedDialogVisible = ref(false);
const fileSendActive = ref()
// 群信息设置抽屉 // 群信息设置抽屉
const groupInfoSettingDrawerVisible = ref(false); const groupInfoSettingDrawerVisible = ref(false);
// 设置群聊邀请对话框状态 // 设置群聊邀请对话框状态
@ -63,20 +62,8 @@ export const useChatStore = defineStore('chatStore', () => {
const departmentName = ref(''); const departmentName = ref('');
const sendInfo: any = ref() const sendInfo: any = ref()
// 在线用户列表
// 定义用户类型 const onlineUserList = ref<OnlineUserInfoType[]>([]);
type User = {
id: number;
ip: string;
isOnline: boolean;
avatar: string;
nickname: string;
username: string;
updatedAt?: number;
};
// 将 userList 的类型设置为 User[]
const userList = ref<User[]>([]);
// 聊天列表 // 聊天列表
const chatList: any = ref([]); const chatList: any = ref([]);
@ -103,6 +90,9 @@ export const useChatStore = defineStore('chatStore', () => {
const targetChatId = ref(); const targetChatId = ref();
const search = ref(''); const search = ref('');
// 群成员列表
const groupMemberList = ref([])
// 所有用户列表 // 所有用户列表
const allUserList = ref([]) const allUserList = ref([])
@ -123,20 +113,19 @@ export const useChatStore = defineStore('chatStore', () => {
}); });
const initChat = async () => {
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() // 初始化用户列表
getGroupList()
getDepartmentList()
initUserList() initUserList()
// 获取群列表
await getGroupList()
// 初始化聊天列表
initChatList() initChatList()
// initOnlineUserList() // 获取部门列表
console.log(userList.value); getDepartmentList()
}; };
// 获取部门列表 // 获取部门列表
@ -151,10 +140,15 @@ export const useChatStore = defineStore('chatStore', () => {
// 初始化用户列表 // 初始化用户列表
const initChatList = async () => { const initChatList = async () => {
const userchatList = await db.getAll('conversationList'); const userSessionList = await db.getAll("workbenchSessionList");
console.log(userchatList) // 确保groupList已加载
if (groupList.value.length > 0) {
// 合并两个数组 // 合并两个数组
chatList.value = [...userchatList, ...groupList.value]; chatList.value = [...userSessionList, ...groupList.value];
} else {
// 如果groupList为空,只使用userSessionList
chatList.value = [...userSessionList];
}
}; };
const setCurrentNavId = (id: number) => { const setCurrentNavId = (id: number) => {
@ -162,113 +156,195 @@ export const useChatStore = defineStore('chatStore', () => {
}; };
const sendMessage = async (messageType: string) => { const sendMessage = async (messageType: string) => {
console.log("sendMessage:", messageType)
if (messageType == 'text') { if (messageType == 'text') {
sendTextMessage() await sendTextMessage()
}
if (messageType == 'image') {
sendImageMessage()
} }
// if (messageType == 'image') {
// sendImageMessage()
// }
console.log(messageType)
if (messageType == 'applyfile') { if (messageType == 'applyfile') {
fileMessage.type = "user"
fileMessage.content_type = 'file'
fileMessage.time = null
fileMessage.userId = userInfo.value.id
fileMessage.toUserId = targetChatId.value
fileMessage.message = sendInfo.value[0]
fileMessage.to_groupid = targetGroupInfo.value.group_id || ''
try {
await sendFileMessage() await sendFileMessage()
} catch (error) {
notifyError('文件发送失败');
} }
} }
// 发送图片消息
const sendImageMessage = async () => {
// 判断是群聊发送还是单聊发送
if (targetGroupInfo.value && Object.keys(targetGroupInfo.value).length > 0) {
console.log('群聊发送文件');
Message.type = 'group';
Message.content_type = 'image';
Message.userId = userInfo.value.id;
Message.to_groupid = targetGroupInfo.value.group_id;
Message.message = sendInfo.value[0];
Message.userInfo = {};
console.log("群聊发送文件", Message)
} else if (targetUserInfo.value && Object.keys(targetUserInfo.value).length > 0) {
console.log('单聊发送文件');
Message.type = 'user';
Message.content_type = 'image';
Message.userId = userInfo.value.id;
Message.toUserId = targetChatId.value;
Message.message = sendInfo.value[0];
Message.to_groupid = targetGroupInfo.value?.group_id || '';
Message.userInfo = {};
}
console.log(Message)
// 发送文件消息
const res = await fetchPost(config.userInfo.url + '/chat/send/file', JSON.stringify(Message));
if (!res.ok) {
fileSendActive.value = false;
return;
} }
const data = await res.json();
console.log(data);
const sendFileMessage = async () => { // 封装成消息历史记录
const messageHistory = {
...Message,
isMe: true,
chatId: Message.type === 'group' ? targetGroupInfo.value.chatId : targetUserInfo.value.chatId,
avatar: Message.type === 'group' ? targetUserInfo.value.avatar : '',
createdAt: Date.now()
};
console.log(fileMessage) console.log("messageHistory------", messageHistory)
const res = await fetchPost(config.userInfo.url + '/chat/send/file', JSON.stringify(fileMessage)); // 添加到聊天记录
if (res.ok) { await db.addOne("workbenchGroupChatRecord", messageHistory);
const data = await res.json(); chatHistory.value.push(messageHistory);
console.log(data) fileSendActive.value = true;
notifySuccess('文件发送成功');
// 两秒后关闭
setTimeout(() => {
fileSendActive.value = false;
}, 2000);
} }
// 发送文件消息
const sendFileMessage = async () => {
// 判断是群聊发送还是单聊发送
if (targetGroupInfo.value && Object.keys(targetGroupInfo.value).length > 0) {
console.log('群聊发送文件');
Message.type = 'group';
Message.content_type = 'file';
Message.userId = userInfo.value.id;
Message.to_groupid = targetGroupInfo.value.group_id;
Message.message = sendInfo.value[0];
Message.userInfo = {};
console.log("群聊发送文件", Message)
} else if (targetUserInfo.value && Object.keys(targetUserInfo.value).length > 0) {
console.log('单聊发送文件');
Message.type = 'user';
Message.content_type = 'file';
Message.userId = userInfo.value.id;
Message.toUserId = targetChatId.value;
Message.message = sendInfo.value[0];
Message.to_groupid = targetGroupInfo.value?.group_id || '';
Message.userInfo = {};
}
console.log(Message)
// 发送文件消息
const res = await fetchPost(config.userInfo.url + '/chat/send/file', JSON.stringify(Message));
if (!res.ok) {
fileSendActive.value = false;
return;
}
const data = await res.json();
console.log(data);
// 封装成消息历史记录
const messageHistory = {
...Message,
isMe: true,
chatId: Message.type === 'group' ? targetGroupInfo.value.chatId : targetUserInfo.value.chatId,
avatar: Message.type === 'group' ? targetUserInfo.value.avatar : '',
createdAt: Date.now()
};
console.log("messageHistory------", messageHistory)
// 添加到聊天记录
await db.addOne("workbenchGroupChatRecord", messageHistory);
chatHistory.value.push(messageHistory);
fileSendActive.value = true;
notifySuccess('文件发送成功');
// 两秒后关闭
setTimeout(() => {
fileSendActive.value = false;
}, 2000);
} }
// 发送文字消息 // 发送文字消息
const sendTextMessage = async () => { const sendTextMessage = async () => {
let messageHistory: ChatMessage;
// 判断是群聊发送还是单聊发送 // 判断是群聊发送还是单聊发送
if (targetGroupInfo.value && Object.keys(targetGroupInfo.value).length) { if (targetGroupInfo.value && Object.keys(targetGroupInfo.value).length) {
console.log('群聊发送'); console.log('群聊发送');
// 群聊发送消息的逻辑 Message.type = 'group'
messageHistory = { Message.content_type = 'text'
type: 'group', Message.to_groupid = targetGroupInfo.value?.group_id
messageType: 'text', // 明确指定消息类型 Message.message = message.value
time: Date.now(), Message.userId = userInfo.value.id
groupId: targetGroupInfo.value?.group_id, // 使用可选链操作符 Message.userInfo = {}
message: message.value, console.log(Message)
userId: userInfo.value.id,
to_groupid: targetGroupInfo.value?.group_id, // 使用可选链操作符
userInfo: {},
};
} else if (targetUserInfo.value && Object.keys(targetUserInfo.value).length > 0) { } else if (targetUserInfo.value && Object.keys(targetUserInfo.value).length > 0) {
console.log('单聊发送'); console.log('单聊发送');
// 单聊发送消息 Message.type = 'user'
// 封装成消息历史记录 Message.content_type = 'text'
messageHistory = { Message.userId = userInfo.value.id
type: 'user', Message.toUserId = targetChatId.value
messageType: 'text', // 明确指定消息类型 Message.message = message.value
time: Date.now(), Message.content_type = 'text'
message: message.value, Message.to_groupid = targetGroupInfo.value?.group_id || ''
userId: userInfo.value.id, Message.userInfo = {}
toUserId: targetChatId.value,
userInfo: {},
};
} else {
notifyError('请先选择聊天对象');
return;
} }
if (!messageHistory) {
// 这是一个额外的检查,确保 messageHistory 已经被赋值
console.log('消息发送失败')
return;
}
// 创建没有 `id` 属性的副本
const { id, ...messageHistoryWithoutId } = messageHistory;
console.log(messageHistoryWithoutId);
// 发送消息 // 发送消息
const res = await fetchPost(config.userInfo.url + '/chat/send', JSON.stringify(messageHistory)); const res = await fetchPost(config.userInfo.url + '/chat/send', JSON.stringify(Message));
if (res.ok) { if (res.ok) {
// 封装成消息历史记录
var messageHistory
// 本地存储一份聊天记录 // 本地存储一份聊天记录
if (messageHistory.type === 'user') { if (Message.type === 'user') {
await db.addOne('chatRecord', messageHistory); messageHistory = {
// changeChatListAndGetChatHistory(userInfo.value.userId); ...Message,
isMe: true,
displayName: userInfo.value.nickname,
chatId: targetUserInfo.value.chatId.toString(),
avatar: userInfo.value.avatar,
createdAt: Date.now()
}
await db.addOne("workbenchChatRecord", messageHistory);
} else if (messageHistory.type === 'group') { } else if (Message.type === 'group') {
await db.addOne('groupChatRecord', messageHistory); messageHistory = {
...Message,
isMe: true,
chatId: targetGroupInfo.value.chatId.toString(),
createdAt: Date.now()
}
await db.addOne("workbenchGroupChatRecord", messageHistory);
} }
// 更新聊天历史 // 更新聊天历史
chatHistory.value.push(messageHistory); chatHistory.value.push(messageHistory);
console.log(await res.json())
// 更新 chatList 和 conversationList
// changeChatListAndGetChatHistory(userInfo.value.userId);
// 清空输入框 // 清空输入框
clearMessage(); clearMessage();
// 聊天框滚动到底部 // 聊天框滚动到底部
await setScrollToBottom(); await setScrollToBottom();
return;
} }
} }
@ -278,39 +354,39 @@ export const useChatStore = defineStore('chatStore', () => {
const changeChatListAndChatHistory = async (data: any) => { const changeChatListAndChatHistory = async (data: any) => {
// 从 conversationList 数据库中查找是否存在对应的会话 // 从 conversationList 数据库中查找是否存在对应的会话
const conversation = await db.getByField('conversationList', 'userId', data.userId); const conversation = await db.getByField("workbenchSessionList", 'userId', data.userId);
// 准备会话更新数据 // 准备会话更新数据
const updatedConversation = { const updatedConversation = {
userId: data.userId, userId: data.userId,
avatar: data.userInfo.avatar || "logo.png", // 如果没有头像使用默认图片 avatar: data.userInfo.avatar, // 如果没有头像使用默认图片
toUserId: data.toUserId, toUserId: data.toUserId,
chatId: data.userId, chatId: data.userId,
type: data.type, type: data.type,
messages: data.message, messages: data.message,
displayName: data.userInfo.nickname, displayName: data.userInfo.nickname,
nickname: data.userInfo.nickname, nickname: data.userInfo.nickname,
time: data.time || Date.now(), time: Date.now().toString,
previewMessage: data.message, // previewMessage: data.message,
previewTimeFormat: formatTime(Date.now()), // 时间格式化函数 // previewTimeFormat: formatTime(Date.now()), // 时间格式化函数
createdAt: Date.now() createdAt: Date.now()
}; };
if (conversation.length === 0) { if (conversation.length === 0) {
// 如果会话不存在,则添加到数据库和 chatList // 如果会话不存在,则添加到数据库和 chatList
await db.addOne('conversationList', updatedConversation); await db.addOne('workbenchSessionList', updatedConversation);
chatList.value.push(updatedConversation); chatList.value.push(updatedConversation);
} else { } else {
// 如果会话存在,则更新数据库和 chatList // 如果会话存在,则更新数据库和 chatList
// 只更新变化的字段,而非全部覆盖,以减少写入数据的量 // 只更新变化的字段,而非全部覆盖,以减少写入数据的量
await db.update('conversationList', conversation[0].id, { await db.update('workbenchSessionList', conversation[0].id, {
avatar: data.userInfo.avatar || "logo.png", avatar: data.userInfo.avatar,
nickname: data.userInfo.nickname, nickname: data.userInfo.nickname,
displayName: data.userInfo.nickname, displayName: data.userInfo.nickname,
previewMessage: data.message, // previewMessage: data.message,
time: data.time || Date.now(), time: data.time || Date.now().toString,
previewTimeFormat: formatTime(Date.now()) // previewTimeFormat: formatTime(Date.now())
}); });
@ -326,8 +402,8 @@ export const useChatStore = defineStore('chatStore', () => {
} }
}; };
// 点击目标用户时,将其添加到 chatList,并添加到数据库 // 点击目标用户时,将其添加到 chatList,并添加到数据库,以及获取到聊天记录
const changeChatListAndGetChatHistory = async (chatId: number) => { const addChatListAndGetChatHistory = async (chatId: string) => {
const chatIdSet = new Set(chatList.value.map((chat: { chatId: any }) => chat.chatId)); const chatIdSet = new Set(chatList.value.map((chat: { chatId: any }) => chat.chatId));
// 如果会话存在于 chatList,则获取聊天记录并更新 chatHistory // 如果会话存在于 chatList,则获取聊天记录并更新 chatHistory
@ -336,30 +412,24 @@ export const useChatStore = defineStore('chatStore', () => {
chatHistory.value = await getHistory(chatId, userInfo.value.id, "user"); chatHistory.value = await getHistory(chatId, userInfo.value.id, "user");
return; return;
} }
console.log("不存在")
// 如果会话不存在,则从用户表中获取该用户的基本信息 // 如果会话不存在,则从用户表中获取该用户的基本信息
const user = await db.getOne("workbenchusers", chatId); const user = await db.getOne("workbenchChatUser", Number(chatId));
if (!user) {
console.warn("User not found in workbenchusers with userId:", chatId);
return;
}
// 将新用户信息添加到 chatList // 将新用户信息添加到 chatList
const newChat = { const newChat = {
userId: user.id,
type: "user", type: "user",
chatId: user.id, chatId: user.id,
nickname: user.nickname, nickname: user.nickname,
avatar: user.avatar, avatar: user.avatar,
toUserId: userInfo.value.id,
time: Date.now(),
displayName: user.nickname, displayName: user.nickname,
previewTimeFormat: formatTime(Date.now()),
previewMessage: "",
}; };
chatList.value.push(newChat); chatList.value.push(newChat);
// 持久化数据到数据库 // 持久化数据到数据库
await db.addOne("conversationList", { await db.addOne("workbenchSessionList", {
userId: user.id,
type: "user", type: "user",
chatId: user.id, chatId: user.id,
displayName: user.nickname, displayName: user.nickname,
@ -368,9 +438,11 @@ export const useChatStore = defineStore('chatStore', () => {
avatar: user.avatar, avatar: user.avatar,
toUserId: userInfo.value.id, toUserId: userInfo.value.id,
time: Date.now(), time: Date.now(),
previewMessage: "",
createdAt: Date.now(), createdAt: Date.now(),
}); });
// 获取聊天记录
chatHistory.value = await getHistory(chatId, userInfo.value.id, "user");
}; };
@ -402,7 +474,7 @@ export const useChatStore = defineStore('chatStore', () => {
// 获取用户表中所有用户 // 获取用户表中所有用户
const getAllUser = async () => { const getAllUser = async () => {
allUserList.value = await db.getAll("workbenchusers"); allUserList.value = await db.getAll("workbenchChatUser");
console.log(allUserList.value) console.log(allUserList.value)
}; };
@ -423,24 +495,18 @@ export const useChatStore = defineStore('chatStore', () => {
if (!res.ok) { if (!res.ok) {
return false; return false;
} }
// getGroupList()
// initChatList()
const groupData = await res.json(); const groupData = await res.json();
console.log(groupData) console.log(groupData)
// 构建数据入库 // 构建数据入库
// 群数据 // 群数据
const group_id = groupData.data.group_id const group_id = groupData.data.group_id
// 群成员数据
const groupMembers = {
userId: currUserId,
groupId: group_id,
createdAt: new Date()
}
db.addOne("groupMembers", groupMembers)
// 添加到会话列表中 // 添加到会话列表中
const groupConversation = { const groupConversation = {
group_id: group_id, group_id: group_id,
name: departmentName.value,
avatar: "./logo.png", avatar: "./logo.png",
messages: "", messages: "",
chatId: group_id, chatId: group_id,
@ -450,7 +516,8 @@ export const useChatStore = defineStore('chatStore', () => {
previewTimeFormat: formatTime(Date.now()), previewTimeFormat: formatTime(Date.now()),
createdAt: new Date() createdAt: new Date()
} }
chatList.value.push(groupConversation) groupList.value.push(groupConversation)
initChatList()
// 关闭对话弹窗 // 关闭对话弹窗
setGroupChatInvitedDialogVisible(false) setGroupChatInvitedDialogVisible(false)
}; };
@ -462,7 +529,8 @@ export const useChatStore = defineStore('chatStore', () => {
// 更新会话列表数据库 // 更新会话列表数据库
// 更新chatlist // 更新chatlist
// 更新聊天记录 // 更新聊天记录
const isPresence = await db.getByField('workbenchusers', 'id', data.userId) console.log("userChatMessage:", data)
const isPresence = await db.getByField('workbenchChatUser', 'chatId', data.userId)
if (isPresence[0].id !== data.userId) { if (isPresence[0].id !== data.userId) {
return return
} }
@ -474,22 +542,16 @@ export const useChatStore = defineStore('chatStore', () => {
userId: data.userId, userId: data.userId,
message: data.message, message: data.message,
toUserId: data.toUserId, toUserId: data.toUserId,
chatId: data.userId, chatId: data.toUserId,
isMe: false,
content_type: data.content_type,
to_groupid: data.to_groupid,
displayName: data.userInfo.nickname, displayName: data.userInfo.nickname,
avatar: data.userInfo.avatar,
createdAt: Date.now(), createdAt: Date.now(),
// 用户信息
userInfo: {
id: data.userId,
nickname: data.userInfo.nickname || "未知用户",
avatar: data.userInfo.avatar || "logo.png", // 使用默认头像。
email: data.userInfo.email,
phone: data.userInfo.phone,
remark: data.userInfo.remark,
role_id: data.userInfo.role_id,
}
} }
await db.addOne('chatRecord', addMessageHistory) await db.addOne("workbenchChatRecord", addMessageHistory)
console.log("添加成功") console.log("添加成功")
// 更新 chatList 和 conversationList表 // 更新 chatList 和 conversationList表
@ -518,40 +580,60 @@ export const useChatStore = defineStore('chatStore', () => {
}; };
// 获取群列表信息 // 获取群列表信息
const getGroupList = async () => { const getGroupList = async () => {
console.log('获取群列表')
const res = await fetchGet(userInfo.value.url + '/chat/group/list'); const res = await fetchGet(userInfo.value.url + '/chat/group/list');
if (!res.ok) { if (!res.ok) {
console.warn("Error fetching group list:", res); console.warn("Error fetching group list:", res);
return false; return false;
} }
const list = await res.json() const list = await res.json()
console.log(list.data.groups) console.log(list)
if (list.data.groups == null) {
list.data.groups = []
}
// 封装 list.data.groups // 封装 list.data.groups
const formattedGroups = list.data.groups.map((group: any) => ({ const formattedGroups = list.data.groups.map((group: any) => ({
group_id: group.id, group_id: group.id,
name: group.name,
avatar: group.avatar || '', // 使用默认头像 avatar: group.avatar || '', // 使用默认头像
messages: "", // messages: "",
displayName: group.name, displayName: group.name,
chatId: group.id, chatId: group.id,
type: 'group', type: 'group',
previewMessage: "",
previewTimeFormat: formatTime(Date.now()),
createdAt: group.createdAt
})); }));
groupList.value = formattedGroups; groupList.value = formattedGroups;
};
const handleUserData = async (data: any[]) => { // 将群成员添加到数据库
for (const group of list.data.groups) {
// 查询数据库中是否已存在该群组的成员列表
const existingGroup = await db.getByField("workbenchGroupUserList", "group_id", group.id);
if (existingGroup.length > 0) {
// 如果存在,更新userIdArray
await db.update("workbenchGroupUserList", existingGroup[0].id, {
userIdArray: group.members
});
} else {
// 如果不存在,添加新记录
await db.addOne("workbenchGroupUserList", {
group_id: group.id,
userIdArray: group.members
});
}
}
};
const onlineUserData = async (data: OnlineUserInfoType[]) => {
// 创建一个用户数组,将所有在线的用户提取出来 // 创建一个用户数组,将所有在线的用户提取出来
const users: any[] = []; const onlineUsers: OnlineUserInfoType[] = [];
// 遍历每个数据项 // 遍历每个数据项
data.forEach((item: any) => { data.forEach((item: any) => {
if (item.id && item.login_ip) { if (item.id && item.login_ip) {
users.push({ onlineUsers.push({
id: item.id, id: item.id,
ip: item.login_ip, ip: item.login_ip,
type: "user",
chatId: item.id,
online: true,
avatar: item.avatar, avatar: item.avatar,
username: item.username, username: item.username,
nickname: item.nickname nickname: item.nickname
@ -559,22 +641,21 @@ export const useChatStore = defineStore('chatStore', () => {
} }
}); });
// 将提取到的用户数据传递给
// 将提取到的用户数据传递给 setUserList if (onlineUsers.length > 0) {
if (users.length > 0) { await setOnlineUserList(onlineUsers);
await setUserList(users);
} }
}; };
const setUserList = async (data: any[]) => { const setOnlineUserList = async (data: OnlineUserInfoType[]) => {
if (data.length < 1) { if (data.length < 1) {
return; return;
} }
// 从当前用户列表中获取已有用户的 IP 和完整用户映射 // 从当前用户列表中获取已有用户的 IP 和完整用户映射
const existingIps = new Set(userList.value.map((d: any) => d.ip)); const existingIps = new Set(onlineUserList.value.map((d: any) => d.ip));
const userMap = new Map<string, User>( const userMap = new Map<string, OnlineUserInfoType>(
userList.value.map((user: User) => [user.ip, user]) onlineUserList.value.map((user: OnlineUserInfoType) => [user.ip, user])
); );
const updates: any[] = []; const updates: any[] = [];
@ -600,6 +681,8 @@ export const useChatStore = defineStore('chatStore', () => {
newEntries.push({ newEntries.push({
id: d.id, id: d.id,
ip: d.ip, ip: d.ip,
type: "user",
chatId: d.id,
isOnline: true, isOnline: true,
avatar: d.avatar, avatar: d.avatar,
nickname: d.nickname, nickname: d.nickname,
@ -613,20 +696,18 @@ export const useChatStore = defineStore('chatStore', () => {
// 批量更新和添加用户数据 // 批量更新和添加用户数据
if (updates.length > 0) { if (updates.length > 0) {
await db.table('workbenchusers').bulkUpdate(updates); await db.table("workbenchChatUser").bulkUpdate(updates);
} }
if (newEntries.length > 0) { if (newEntries.length > 0) {
await db.table('workbenchusers').bulkPut(newEntries); await db.table("workbenchChatUser").bulkPut(newEntries);
} }
initOnlineUserList()
// 刷新用户列表
await getUserList();
}; };
const getUserList = async () => { const initOnlineUserList = async () => {
try {
// 从数据库中获取所有用户信息 // 从数据库中获取所有用户信息
const list = await db.getAll("workbenchusers"); const list = await db.getAll("workbenchChatUser");
// 创建一个 Map,用于存储每个用户的唯一 ID 地址 // 创建一个 Map,用于存储每个用户的唯一 ID 地址
let uniqueIdMap = new Map<string, any>(); let uniqueIdMap = new Map<string, any>();
@ -637,22 +718,18 @@ export const useChatStore = defineStore('chatStore', () => {
// 将 Map 的值转换为数组(去重后的用户列表) // 将 Map 的值转换为数组(去重后的用户列表)
const uniqueIdList = Array.from(uniqueIdMap.values()); const uniqueIdList = Array.from(uniqueIdMap.values());
// 按照 updatedAt 时间进行升序排序 // 按照 updatedAt 时间进行升序排序
uniqueIdList.sort((a: any, b: any) => a.time - b.time); uniqueIdList.sort((a: any, b: any) => a.time - b.time);
// 更新用户列表 // 更新用户列表
userList.value = uniqueIdList; onlineUserList.value = uniqueIdList;
} catch (error) {
console.error("获取用户列表失败:", error);
}
}; };
// 初始化统一用户列表状态 // 初始化统一用户列表状态
const initUserList = async () => { const initUserList = async () => {
if (!userList.value.length) return; if (!onlineUserList.value.length) return;
// 获取需要更新的用户数据(只选取在线的用户并设为离线状态) // 获取需要更新的用户数据(只选取在线的用户并设为离线状态)
const updates = userList.value.reduce((acc: any[], user: any) => { const updates = onlineUserList.value.reduce((acc: any[], user: any) => {
console.log(user);
if (user.isOnline) { if (user.isOnline) {
console.log(user); console.log(user);
acc.push({ acc.push({
@ -665,63 +742,31 @@ export const useChatStore = defineStore('chatStore', () => {
// 如果有需要更新的用户,批量更新数据库状态 // 如果有需要更新的用户,批量更新数据库状态
if (updates.length) { if (updates.length) {
await db.table('workbenchusers').bulkUpdate(updates); await db.table('workbenchChatUser').bulkUpdate(updates);
} }
}; };
// 设置会话列表
const initOnlineUserList = async () => { const getSessionInfo = async (chatId: string, type: string) => {
const msgAll = await db.getAll('workbenchusers');
const list = msgAll.reduce((acc: any, msg: any) => {
if (!msg.isMe) {
const targetId = msg.targetId;
if (!acc[targetId]) {
acc[targetId] = { chatArr: [], readNum: 0 };
}
acc[targetId].chatArr.push(msg);
// 计算未读消息数量
if (!msg.isRead) {
acc[targetId].readNum++;
}
}
return acc;
}, {});
const res = Object.keys(list).map(targetId => {
const { chatArr, readNum } = list[targetId];
const lastMessage = chatArr[chatArr.length - 1];
if (lastMessage) {
lastMessage.readNum = readNum;
return lastMessage;
}
return null; // 防止返回空值
}).filter(Boolean); // 过滤掉空值
userList.value = res.sort((a, b) => b.createdAt - a.createdAt);
};
const changeChatList = async (chatId: number, type: string) => {
// 设置 targetUserId // 设置 targetUserId
// 根据type去判断 // 根据type去判断
// user会话,查发送和接收发方id // user会话,查发送和接收发方id
// group会话,查群id(chatId)查到所有消息记录 // group会话,查群id(chatId)查到所有消息记录
// 清空聊天记录
chatHistory.value = []
targetChatId.value = chatId targetChatId.value = chatId
if (type === 'user') { if (type === 'user') {
console.log("user") console.log("user")
// 获取当前用户和目标用户的聊天记录 // 获取当前用户和目标用户的聊天记录
console.log(chatId, type)
const history = await getHistory(userInfo.value.id, chatId, type) const history = await getHistory(userInfo.value.id, chatId, type)
console.log(history) console.log(history)
chatHistory.value = history; chatHistory.value = [...history];
// 设置目标用户的信息 // 设置目标用户的信息
await setTargetUserInfo(chatId); await setTargetUserInfo(chatId);
} else if (type === 'group') { } else if (type === 'group') {
console.log('group') console.log('group')
// 获取当前用户和目标用户的聊天记录 // 获取当前用户和目标用户的聊天记录
console.log(userInfo.value.id, chatId, type)
const history = await getHistory(userInfo.value.id, chatId, type) const history = await getHistory(userInfo.value.id, chatId, type)
chatHistory.value = history; chatHistory.value = history;
// 设置目标用户的信息 // 设置目标用户的信息
@ -729,10 +774,10 @@ export const useChatStore = defineStore('chatStore', () => {
} }
}; };
const getHistory = async (sendUserId: number, toUserId: number, type: string) => { const getHistory = async (sendUserId: string, toUserId: string, type: string) => {
var messagesHistory var messagesHistory
if (type === 'user') { if (type === 'user') {
messagesHistory = await db.filter('chatRecord', (record: any) => { messagesHistory = await db.filter("workbenchChatRecord", (record: any) => {
return ( return (
(record.userId === sendUserId && record.toUserId === toUserId) || (record.userId === sendUserId && record.toUserId === toUserId) ||
(record.toUserId === sendUserId && record.userId === toUserId) (record.toUserId === sendUserId && record.userId === toUserId)
@ -740,21 +785,30 @@ export const useChatStore = defineStore('chatStore', () => {
}); });
} else if (type === 'group') { } else if (type === 'group') {
console.log('group') console.log('group')
messagesHistory = await db.getByField('groupChatRecord', "groupId", toUserId); messagesHistory = await db.getByField("workbenchGroupChatRecord", "chatId", toUserId);
console.log("messagesHistory", messagesHistory)
} }
return messagesHistory return messagesHistory
} }
// 设置目标用户的信息 // 设置目标用户的信息
const setTargetUserInfo = async (id: number) => { const setTargetUserInfo = async (id: string) => {
console.log(id) console.log(id)
const userInfoArray = await db.getByField('conversationList', "userId", id); const userInfoArray = await db.getByField("workbenchChatUser", "chatId", id);
targetUserInfo.value = userInfoArray.length > 0 ? userInfoArray[0] : {}; // 封装用户信息
const userInfo = {
type: "user",
avatar: userInfoArray[0].avatar,
displayName: userInfoArray[0].nickname,
toUserId: config.userInfo.id,
chatId: userInfoArray[0].chatId
}
targetUserInfo.value = userInfoArray.length > 0 ? userInfo : {};
targetGroupInfo.value = {} targetGroupInfo.value = {}
}; };
// 设置目标群信息 // 设置目标群信息
const setTargetGrouprInfo = async (id: number) => { const setTargetGrouprInfo = async (id: string) => {
for (const group of groupList.value) { for (const group of groupList.value) {
console.log(group) console.log(group)
if (group.group_id === id) { if (group.group_id === id) {
@ -775,34 +829,31 @@ export const useChatStore = defineStore('chatStore', () => {
const messageRecord = { const messageRecord = {
userId: data.userId, userId: data.userId,
groupId: data.to_groupid, groupId: data.to_groupid,
messageType: data.messageType, content_type: data.content_type,
message: data.message, message: data.message,
time: data.time, time: data.time,
type: data.type, type: data.type,
createdAt: Date.now(), chatId: data.to_groupid,
userInfo: { isMe: false,
id: data.userId, displayName: data.userInfo.nickname,
nickname: data.userInfo.nickname || "未知用户", avatar: data.userInfo.avatar,
avatar: data.userInfo.avatar || "logo.png", // 使用默认头像。
email: data.userInfo.email,
phone: data.userInfo.phone,
remark: data.userInfo.remark,
role_id: data.userInfo.role_id, role_id: data.userInfo.role_id,
} createdAt: Date.now(),
}; };
// 判断当前消息是否是自己发送的
if (messageRecord.userId === userInfo.value.id) {
return;
}
console.log(messageRecord) console.log(messageRecord)
// 将消息记录添加到数据库 // 将消息记录添加到数据库
await db.addOne('groupChatRecord', messageRecord); const res = await db.addOne("workbenchGroupChatRecord", messageRecord);
console.log(res)
// 更改聊天记录 // 更改聊天记录
chatHistory.value.push(messageRecord) chatHistory.value.push(messageRecord)
// // 更新 chatHistory
// chatHistory.value.push(messageRecord);
// // 更新 chatList 和 conversationList表
// changeChatListAndChatHistory(data);
}; };
const showContextMenu = (event: any, id: number) => { const showContextMenu = (event: any, id: number) => {
@ -812,9 +863,36 @@ export const useChatStore = defineStore('chatStore', () => {
contextMenu.value.y = event.y; contextMenu.value.y = event.y;
}; };
// 退出群聊
const quitGroup = async (group_id: string) => {
const url = config.userInfo.url + '/chat/group/leave';
const res = await fetchPost(url, JSON.stringify({ group_id }))
if (!res.ok) {
return false;
}
console.log(await res.json())
// 从groupList中删除
groupList.value = groupList.value.filter((group: any) => group.group_id !== group_id)
const a = await db.deleteByField("workbenchGroupUserList", "group_id", group_id)
console.log(a)
initChatList()
notifySuccess("退出群聊成功")
targetGroupInfo.value = {}
targetChatId.value = ''
// const group = await db.getByField("workbenchGroupUserList", "group_id", group_id);
// if (group.length > 0) {
// // 删除当前用户
// console.log(group[0])
// const updatedUserIdArray = group[0].userIdArray.filter((user: any) => user.id !== userInfo.value.id);
// await db.update("workbenchGroupUserList", group[0].id, { userIdArray: updatedUserIdArray });
// }
}
return { return {
emojiList, emojiList,
userList, onlineUserList,
chatList, chatList,
groupList, groupList,
chatHistory, chatHistory,
@ -838,22 +916,24 @@ export const useChatStore = defineStore('chatStore', () => {
departmentName, departmentName,
targetGroupInfo, targetGroupInfo,
sendInfo, sendInfo,
fileSendActive,
groupMemberList,
initChat, initChat,
showContextMenu, showContextMenu,
setCurrentNavId, setCurrentNavId,
sendMessage, sendMessage,
changeChatList, getSessionInfo,
handleContextMenu, handleContextMenu,
changeChatListAndGetChatHistory, addChatListAndGetChatHistory,
handleUserData,
initUserList, initUserList,
setGroupChatInvitedDialogVisible, setGroupChatInvitedDialogVisible,
setGroupInfoDrawerVisible, setGroupInfoDrawerVisible,
createGroupChat, createGroupChat,
onlineUserData,
groupChatMessage,
userChatMessage, userChatMessage,
initOnlineUserList,
getDepartmentList, getDepartmentList,
getAllUser, getAllUser,
groupChatMessage quitGroup,
}; };
}); });

42
frontend/src/stores/db.ts

@ -1,35 +1,37 @@
import Dexie from 'dexie'; import Dexie from 'dexie';
export type ChatTable = 'chatuser' | 'chatmsg' | 'chatmessage' | 'groupmessage' | 'chatRecord' | 'workbenchusers' | 'conversationList' | 'group' | 'groupMembers' | 'groupChatList' | 'groupChatRecord'; export type ChatTable = 'chatuser' | 'chatmsg' | 'workbenchChatRecord' | 'workbenchChatUser' | 'workbenchSessionList' | 'groupSessionList' | 'workbenchGroupChatRecord' | 'workbenchGroupUserList';
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,phone,nickName,isOnline,updatedAt,createdAt', workbenchChatUser: '++id,ip,userName,chatId,avatar,mobile,phone,nickName,isOnline,updatedAt,createdAt',
// 聊天记录
chatRecord: '++id,toUserId,messages,messageType,time,createdAt,userInfo',
// 会话列表 // 会话列表
conversationList: '++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',
// 群组会话列表
groupSessionList: '++id,groupId,name,message,previewMessage,avatar,createdAt',
// 群组聊天记录
workbenchGroupChatRecord: '++id,chatId,userId,to_groupid,messageType,userInfo,message,time,type,createdAt',
// 群用户列表
workbenchGroupUserList: '++id, group_id, createdAt, userIdArray',
// 用户列表
chatuser: '++id,ip,hostname,userName,avatar,mobile,nickName,isOnline,updatedAt,createdAt', chatuser: '++id,ip,hostname,userName,avatar,mobile,nickName,isOnline,updatedAt,createdAt',
chatmsg: '++id,toUserId,targetIp,senderInfo,reciperInfo,previewMessage,content,type,status,isRead,isMe,readAt,createdAt', chatmsg: '++id,toUserId,targetIp,senderInfo,reciperInfo,previewMessage,content,type,status,isRead,isMe,readAt,createdAt',
chatmessage: '++id,userId,toUserId,senderInfo,isMe,isRead,content,type,readAt,createdAt',
groupChatRecord: '++id,userId,groupId,messageType,userInfo,message,time,type,createdAt',
// 群组表
group: '++id,avatar,name,groupId,creator,createdAt',
// 群成员表
groupMembers: '++id,userId,groupTableId,groupId,createdAt',
// 群会话列表
groupChatList: '++id,groupId,name,message,previewMessage,avatar,createdAt',
}).upgrade((tx: { }).upgrade((tx: {
conversationList: any; workbenchSessionList: any;
group: any; workbenchChatUser: any;
chatRecord: { addIndex: (arg0: string, arg1: (obj: { toUserId: any; }) => any) => void; }; workbenchGroupChatRecord: any;
workbenchGroupUserList: any;
workbenchChatRecord: { addIndex: (arg0: string, arg1: (obj: { toUserId: any; }) => any) => void; };
}) => { }) => {
// 手动添加索引 // 手动添加索引
tx.conversationList.addIndex('userId', (obj: { userId: any; }) => obj.userId); tx.workbenchSessionList.addIndex('userId', (obj: { userId: any; }) => obj.userId);
tx.chatRecord.addIndex('toUserId', (obj: { toUserId: any; }) => obj.toUserId); tx.workbenchChatRecord.addIndex('toUserId', (obj: { toUserId: any; }) => obj.toUserId);
tx.group.addIndex('groupId', (obj: { groupId: any }) => obj.groupId); // 添加索引: 群主 ID tx.workbenchChatUser.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);
}); });
export const db = { export const db = {

2
frontend/src/stores/notify.ts

@ -1,6 +1,6 @@
import { fetchGet, getSystemConfig } from "@/system/config";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
import { getSystemConfig, fetchGet } from "@/system/config";
import { useUpgradeStore } from "./upgrade"; import { useUpgradeStore } from "./upgrade";
export const useNotifyStore = defineStore('notifyStore', () => { export const useNotifyStore = defineStore('notifyStore', () => {
const config = getSystemConfig(); const config = getSystemConfig();

22
frontend/src/stores/upgrade.ts

@ -68,22 +68,9 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
}; };
} }
// 获取用户聊天消息
function userChatMessage() {
const url = getUrl('/chat/message', false)
const source = new EventSource(url);
source.onmessage = function (event) {
const data = JSON.parse(event.data);
handleMessage(data);
};
source.onerror = function (event) {
console.error('EventSource error:', event);
};
}
async function handleMessage(message: any) { async function handleMessage(message: any) {
// console.log(message)
switch (message.type) { switch (message.type) {
case 'update': case 'update':
checkUpdate(message.data) checkUpdate(message.data)
@ -92,7 +79,7 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
localChatStore.handlerMessage(message.data) localChatStore.handlerMessage(message.data)
break; break;
case 'online': case 'online':
chatChatStore.handleUserData(message.data) chatChatStore.onlineUserData(message.data)
break; break;
case 'user': case 'user':
chatChatStore.userChatMessage(message.data) chatChatStore.userChatMessage(message.data)
@ -105,7 +92,7 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
} }
} }
async function checkUpdate(res: any) { async function checkUpdate(res: any) {
//console.log(res) console.log(res)
if (!res) return if (!res) return
const config = getSystemConfig(); const config = getSystemConfig();
if (!config.account.ad) return; if (!config.account.ad) return;
@ -142,7 +129,6 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
list.forEach((item: any) => { list.forEach((item: any) => {
if (item.img && item.img.indexOf('http') == -1) { if (item.img && item.img.indexOf('http') == -1) {
item.img = `https://godoos.com${item.img}` item.img = `https://godoos.com${item.img}`
} }
}); });
return list return list
@ -202,7 +188,7 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
checkUpdate, checkUpdate,
systemMessage, systemMessage,
onlineMessage, onlineMessage,
userChatMessage, // userChatMessage,
update update
} }
}) })

1
frontend/src/system/index.ts

@ -118,6 +118,7 @@ export class System {
// const messageStore = useMessageStore(); // const messageStore = useMessageStore();
// messageStore.systemMessage() // messageStore.systemMessage()
upgradeStore.onlineMessage(); upgradeStore.onlineMessage();
// upgradeStore.userChatMessage();
}, 3000); }, 3000);
} }
setTimeout(() => { setTimeout(() => {

5
frontend/src/util/sharePath.ts

@ -25,3 +25,8 @@ export function turnFilePath(file: OsFileWithoutContent) : string {
const arr = file.path.split('/') const arr = file.path.split('/')
return `/${arr[1]}/${arr[2]}/${arr[arr.length - 1]}` return `/${arr[1]}/${arr[2]}/${arr[arr.length - 1]}`
} }
//返回是我的分享还是接收分享的文件路径
export function getFileRootPath(path: string) : string {
const rootPath = path.indexOf('/F/myshare') === 0 ? '/F/myshare' : '/F/othershare'
return rootPath
}

6
godo/files/os.go

@ -364,7 +364,11 @@ func IsHavePwd(pwd string) bool {
func GetSalt(r *http.Request) (string, error) { func GetSalt(r *http.Request) (string, error) {
data, ishas := libs.GetConfig("salt") data, ishas := libs.GetConfig("salt")
if ishas { if ishas {
return data.(string), nil // 断言成功则返回
if salt, ok := data.(string); ok {
return salt, nil
}
return "", fmt.Errorf("类型断言失败,期望类型为 string")
} }
salt := r.Header.Get("salt") salt := r.Header.Get("salt")
if salt != "" { if salt != "" {

Loading…
Cancel
Save