Browse Source

add:新增会话列表消息预览

master
prr 8 months ago
parent
commit
94ac8751c5
  1. 1
      frontend/package.json
  2. 2693
      frontend/pnpm-lock.yaml
  3. 1
      frontend/src/assets/icon/group_avatar.svg
  4. 2
      frontend/src/components/chat/Chat.vue
  5. 3
      frontend/src/components/chat/ChatBox.vue
  6. 2
      frontend/src/components/chat/ChatMessage.vue
  7. 8
      frontend/src/components/chat/ChatMsgList.vue
  8. 697
      frontend/src/components/window/WindowTemplate.vue
  9. 125
      frontend/src/stores/chat.ts
  10. 4
      frontend/src/stores/db.ts
  11. 4
      frontend/src/system/member.ts

1
frontend/package.json

@ -24,6 +24,7 @@
"vue": "^3.4.31", "vue": "^3.4.31",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
"vue-router": "^4.4.0", "vue-router": "^4.4.0",
"vue-svg-icon": "^1.2.9",
"vue-web-screen-shot": "^1.5.3" "vue-web-screen-shot": "^1.5.3"
}, },
"devDependencies": { "devDependencies": {

2693
frontend/pnpm-lock.yaml

File diff suppressed because it is too large

1
frontend/src/assets/icon/group_avatar.svg

@ -0,0 +1 @@
<svg t="1730993827187" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1654" width="200" height="200"><path d="M412.0896 962.2016c-52.8 0-105.5936 0.0064-158.3936 0-61.8176-0.0064-113.1712-41.0304-126.496-101.408-1.8432-8.3648-2.816-17.0816-2.8992-25.6448-0.3136-33.2736-0.6656-66.5664 0.0384-99.8336 1.3248-62.4768 24.5184-115.8208 69.6192-159.136 33.1456-31.8336 72.736-51.4624 118.2016-58.6368 11.6416-1.8368 23.5136-2.9504 35.2896-3.04 43.9424-0.3328 87.8976-0.5952 131.8336 0.0192 98.7392 1.3824 184.0768 66.7456 211.8336 161.5936 6.0224 20.576 8.7872 41.632 8.864 63.0272 0.1152 31.36 0.0576 62.72 0.0256 94.0736-0.064 61.5296-41.7472 113.2928-101.9392 126.0928-8.8896 1.8944-18.1632 2.72-27.264 2.7584-52.9088 0.2624-105.8112 0.1344-158.7136 0.1344z m0.0896-63.8272c53.216 0 106.4384 0.0128 159.6544-0.0256 3.1872 0 6.3872-0.2368 9.5488-0.6208 30.0864-3.6352 54.7584-31.3664 54.7904-61.6128 0.0384-34.1248 0.0384-68.256-0.0256-102.3808-0.0064-4.4672-0.3008-8.9536-0.8192-13.3888-4.1856-35.5136-18.2976-66.528-43.0912-92.3328-31.2576-32.5312-69.5936-49.44-114.8032-49.76-44.0448-0.3072-88.0896-0.096-132.1408-0.032-4.9984 0.0064-10.0288 0.2432-14.9888 0.8192-35.4048 4.1152-66.3488 18.1248-92.1344 42.7776-32.8832 31.4368-49.8112 70.0352-50.1248 115.616-0.224 32.3136-0.0576 64.6272-0.0128 96.9472 0.0064 3.0784 0.224 6.176 0.6272 9.2288 4.0256 30.688 31.424 54.7584 62.2784 54.7648 53.7408 0.0064 107.4944 0 161.2416 0zM412.0832 450.2016c-106.3296-0.608-191.8336-85.5872-191.776-192.0064 0.0576-106.6176 85.8112-191.6672 191.9488-191.744 105.824-0.0768 191.8912 86.0928 191.6736 191.7568-0.2176 106.3936-85.4976 191.392-191.8464 191.9936z m128.096-191.9168c0.4928-69.504-56.2048-126.5856-124.9728-128.1792-71.8464-1.664-129.7792 56.0768-131.3024 125.1392-1.5872 71.9232 56.256 129.7216 125.2224 131.2256 72.6528 1.5808 131.6608-57.7664 131.0528-128.1856z" p-id="1655" fill="#ffffff"></path><path d="M715.7376 962.2784c6.1824-8.576 12.0704-16.7552 17.984-24.9216 8.0704-11.1424 14.016-23.3536 18.0672-36.4672 0.64-2.0608 1.5296-2.624 3.5392-2.5664 10.464 0.3008 20.8256 0.0256 30.8544-3.7376 25.4144-9.536 41.9968-33.1776 41.984-60.2432-0.0192-34.4512 0.5696-68.9152-0.256-103.3472-0.8192-34.2528-12.7296-64.9344-33.9712-91.8208-18.7264-23.7056-42.304-40.8832-70.6752-51.4304-1.28-0.4736-2.5216-1.5424-3.3664-2.6496-10.4896-13.8048-20.2624-28.2112-31.5264-41.344-9.1008-10.6112-19.9744-19.6992-29.92-29.3312-0.3456 0.0896 0.0832-0.1088 0.5184-0.1216 48.2432-1.024 93.0368 10.5216 133.184 37.7024 50.0288 33.8688 81.7152 80.4736 94.8736 139.5392 3.6032 16.1792 5.0112 32.5952 5.0432 49.1328 0.0576 29.9712-0.0896 59.9424 0.0448 89.9136 0.1344 29.6832-7.776 56.7808-25.8432 80.5056-20.7104 27.1936-47.9936 43.8784-81.8304 49.2928-7.8528 1.2544-15.8848 1.6768-23.8528 1.824-14.8096 0.2752-29.6384 0.0704-44.8512 0.0704zM583.616 67.8912c52.064-7.2256 129.5872 11.136 178.3168 81.2736 46.0672 66.2976 45.376 155.0912-1.6576 220.6016-49.5808 69.056-126.5216 85.9456-176.8896 78.8544 1.3696-1.2352 2.4448-2.2144 3.5328-3.1872 19.4624-17.4784 33.8112-38.9952 47.9872-60.6592 0.832-1.2736 2.3296-2.4704 3.7632-2.9248 49.3952-15.7632 81.1968-48.6016 91.0016-99.4944 9.6256-49.9648-6.976-91.9424-46.1888-124.5568-13.2544-11.0272-28.5696-18.3808-45.1392-23.1552-1.3312-0.384-2.6752-1.6448-3.4496-2.8544-12.2816-19.0848-25.152-37.7216-40.992-54.0992-3.232-3.3472-6.7264-6.4192-10.2848-9.7984z" p-id="1656" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

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

@ -223,6 +223,8 @@
.side { .side {
flex: 1; flex: 1;
/* 占据剩余宽度 */ /* 占据剩余宽度 */
max-width: 200px;
min-width: 200px;
max-height: max-content; max-height: max-content;
border-right: 1px solid #e8e8e8; border-right: 1px solid #e8e8e8;
overflow-y: hidden; overflow-y: hidden;

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

@ -550,7 +550,8 @@
} }
.msg-main { .msg-main {
width: 100%; background-color: re;
/* width: 100%; */
/* 占据整个宽度 */ /* 占据整个宽度 */
height: 75%; height: 75%;
padding: 0; padding: 0;

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

@ -146,7 +146,7 @@
<!-- 图片消息展示 --> <!-- 图片消息展示 -->
<div <div
v-else-if="item.content_type == 'image'" v-else-if="item.content_type == 'image'"
class="chat-item-image" class=""
> >
<el-image <el-image
fit="cover" fit="cover"

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

@ -27,14 +27,18 @@
:src="item.avatar" :src="item.avatar"
></el-avatar> ></el-avatar>
<el-avatar <!-- <el-avatar
v-else="item.type == 'group'" v-else="item.type == 'group'"
shape="square" shape="square"
:size="40" :size="40"
class="avatar" class="avatar"
:src="item.avatar" :src="item.avatar"
></el-avatar ></el-avatar
> > -->
<!-- 引入icon -->
<el-icon :size="40">
</el-icon>
</el-col> </el-col>
<!-- 在线状态 --> <!-- 在线状态 -->

697
frontend/src/components/window/WindowTemplate.vue

@ -1,343 +1,368 @@
<template> <template>
<div <div
class="wintmp_outer dragwin" class="wintmp_outer dragwin"
:class="{ :class="{
topwin: istop, topwin: istop,
max: windowInfo.state == WindowStateEnum.maximize, max: windowInfo.state == WindowStateEnum.maximize,
min: windowInfo.state == WindowStateEnum.minimize, min: windowInfo.state == WindowStateEnum.minimize,
fullscreen: windowInfo.state == WindowStateEnum.fullscreen, fullscreen: windowInfo.state == WindowStateEnum.fullscreen,
noframe: !windowInfo.frame, noframe: !windowInfo.frame,
disable: windowInfo.disable, disable: windowInfo.disable,
}" }"
:style="customerStyle" :style="customerStyle"
@touchstart.passive="onFocus" @touchstart.passive="onFocus"
@mousedown="onFocus" @mousedown="onFocus"
ref="$win_outer" ref="$win_outer"
v-dragable v-dragable
> >
<!-- 窗口标题栏 --> <!-- 窗口标题栏 -->
<div class="wintmp_uper" @contextmenu.prevent> <div
<MenuBar :browser-window="browserWindow"></MenuBar> class="wintmp_uper"
</div> @contextmenu.prevent
>
<div <MenuBar :browser-window="browserWindow"></MenuBar>
class="wintmp_main" </div>
:class="{ resizeing: resizemode != 'null' }"
@mousedown.stop="predown" <div
@touchstart.stop.passive="predown" class="wintmp_main"
@contextmenu.stop.prevent :class="{ resizeing: resizemode != 'null' }"
> @mousedown.stop="predown"
<div @touchstart.stop.passive="predown"
class="content-mask" @contextmenu.stop.prevent
v-if="!istop && typeof browserWindow.content === 'string'" >
></div> <div
<WindowInner :win="browserWindow"></WindowInner> class="content-mask"
</div> v-if="!istop && typeof browserWindow.content === 'string'"
<!-- 使用 v-for 生成拖拽边界 --> ></div>
<div <WindowInner :win="browserWindow"></WindowInner>
v-for="border in dragBorders" </div>
:key="border.type" <!-- 使用 v-for 生成拖拽边界 -->
:class="[ <div
border.class, v-for="border in dragBorders"
'win_drag_border', :key="border.type"
{ isChoseMode: resizemode == border.type }, :class="[
border.cursorClass border.class,
]" 'win_drag_border',
v-if="resizable" { isChoseMode: resizemode == border.type },
draggable="false" border.cursorClass,
@mousedown.stop.prevent="startScale($event, border.type)" ]"
@touchstart.stop.passive="startScale($event, border.type)" v-if="resizable"
></div> draggable="false"
</div> @mousedown.stop.prevent="startScale($event, border.type)"
@touchstart.stop.passive="startScale($event, border.type)"
></div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onUnmounted, provide, ref } from "vue"; import { useSystem } from "@/system";
import { onMounted, computed, UnwrapNestedRefs } from "vue"; import { emitEvent } from "@/system/event";
import { WindowStateEnum } from "@/system/window/BrowserWindow"; import {
import { ScaleElement } from "@/system/window/dom/ScaleElement"; BrowserWindow,
import { BrowserWindow } from "@/system/window/BrowserWindow"; WindowStateEnum,
import { emitEvent } from "@/system/event"; } from "@/system/window/BrowserWindow";
import { useSystem } from "@/system"; import { ScaleElement } from "@/system/window/dom/ScaleElement";
import { vDragable } from "@/system/window/MakeDragable"; import { vDragable } from "@/system/window/MakeDragable";
import {
const sys = useSystem(); computed,
const props = defineProps<{ onMounted,
browserWindow: UnwrapNestedRefs<BrowserWindow>; onUnmounted,
}>(); provide,
ref,
const browserWindow = props.browserWindow; UnwrapNestedRefs,
const windowInfo = browserWindow.windowInfo; } from "vue";
provide("browserWindow", browserWindow);
provide("system", sys); const sys = useSystem();
const props = defineProps<{
function predown() { browserWindow: UnwrapNestedRefs<BrowserWindow>;
browserWindow.moveTop(); }>();
emitEvent("window.content.click", browserWindow);
} const browserWindow = props.browserWindow;
const windowInfo = browserWindow.windowInfo;
const customerStyle = ref<NonNullable<unknown>>({}); provide("browserWindow", browserWindow);
provide("system", sys);
function onFocus(e: MouseEvent | TouchEvent): void {
browserWindow?.moveTop(); function predown() {
if (windowInfo.state === WindowStateEnum.maximize) { browserWindow.moveTop();
if (e instanceof MouseEvent) { emitEvent("window.content.click", browserWindow);
e.preventDefault(); }
e.stopPropagation();
} const customerStyle = ref<NonNullable<unknown>>({});
}
} function onFocus(e: MouseEvent | TouchEvent): void {
browserWindow?.moveTop();
const istop = computed(() => windowInfo.istop); if (windowInfo.state === WindowStateEnum.maximize) {
if (e instanceof MouseEvent) {
onMounted(() => { e.preventDefault();
customerStyle.value = { e.stopPropagation();
width: computed(() => windowInfo.width + "px"), }
height: computed(() => windowInfo.height + "px"), }
left: computed(() => windowInfo.x + "px"), }
top: computed(() => windowInfo.y + "px"),
zIndex: computed(() => { const istop = computed(() => windowInfo.istop);
if (windowInfo.alwaysOnTop) {
return 9999; onMounted(() => {
} customerStyle.value = {
return windowInfo.zindex; width: computed(() => windowInfo.width + "px"),
}), height: computed(() => windowInfo.height + "px"),
backgroundColor: computed(() => windowInfo.backgroundColor), left: computed(() => windowInfo.x + "px"),
}; top: computed(() => windowInfo.y + "px"),
}); zIndex: computed(() => {
if (windowInfo.alwaysOnTop) {
const resizable = ref(windowInfo.resizable); return 9999;
const resizemode = ref("null"); }
let scaleAble: ScaleElement; return windowInfo.zindex;
}),
onMounted(() => { backgroundColor: computed(() => windowInfo.backgroundColor),
scaleAble = new ScaleElement( };
resizemode, });
windowInfo.width,
windowInfo.height, const resizable = ref(windowInfo.resizable);
windowInfo.x, const resizemode = ref("null");
windowInfo.y let scaleAble: ScaleElement;
);
scaleAble.onResize((width: number, height: number, x: number, y: number) => { onMounted(() => {
windowInfo.width = width || windowInfo.width; scaleAble = new ScaleElement(
windowInfo.height = height || windowInfo.height; resizemode,
windowInfo.x = x || windowInfo.x; windowInfo.width,
windowInfo.y = y || windowInfo.y; windowInfo.height,
browserWindow.emit("resize", windowInfo.width, windowInfo.height); windowInfo.x,
}); windowInfo.y
}); );
scaleAble.onResize(
function startScale(e: MouseEvent | TouchEvent, dire: string) { (width: number, height: number, x: number, y: number) => {
console.log(e); windowInfo.width = width || windowInfo.width;
if (windowInfo.disable) { windowInfo.height = height || windowInfo.height;
return; windowInfo.x = x || windowInfo.x;
} windowInfo.y = y || windowInfo.y;
scaleAble?.startScale( browserWindow.emit(
e, "resize",
dire, windowInfo.width,
windowInfo.x, windowInfo.height
windowInfo.y, );
windowInfo.width, }
windowInfo.height );
); });
}
function startScale(e: MouseEvent | TouchEvent, dire: string) {
onUnmounted(() => { console.log(e);
scaleAble.unMount(); if (windowInfo.disable) {
}); return;
}
const dragBorders = [ scaleAble?.startScale(
{ type: 'r', class: 'right_border', cursorClass: 'ew-resize' }, e,
{ type: 'b', class: 'bottom_border', cursorClass: 'ns-resize' }, dire,
{ type: 'l', class: 'left_border', cursorClass: 'ew-resize' }, windowInfo.x,
{ type: 't', class: 'top_border', cursorClass: 'ns-resize' }, windowInfo.y,
{ type: 'rb', class: 'right_bottom_border', cursorClass: 'nwse-resize' }, windowInfo.width,
{ type: 'lb', class: 'left_bottom_border', cursorClass: 'nesw-resize' }, windowInfo.height
{ type: 'lt', class: 'left_top_border', cursorClass: 'nwse-resize' }, );
{ type: 'rt', class: 'right_top_border', cursorClass: 'nesw-resize' }, }
];
onUnmounted(() => {
scaleAble.unMount();
});
const dragBorders = [
{ type: "r", class: "right_border", cursorClass: "ew-resize" },
{ type: "b", class: "bottom_border", cursorClass: "ns-resize" },
{ type: "l", class: "left_border", cursorClass: "ew-resize" },
{ type: "t", class: "top_border", cursorClass: "ns-resize" },
{
type: "rb",
class: "right_bottom_border",
cursorClass: "nwse-resize",
},
{ type: "lb", class: "left_bottom_border", cursorClass: "nesw-resize" },
{ type: "lt", class: "left_top_border", cursorClass: "nwse-resize" },
{ type: "rt", class: "right_top_border", cursorClass: "nesw-resize" },
];
</script> </script>
<style> <style>
.dragwin { .dragwin {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
.wintmp_outer { .wintmp_outer {
position: absolute; position: absolute;
padding: 0; padding: 0;
margin: 0; margin: 0;
// left: 0; // left: 0;
// top: 0; // top: 0;
width: max-content; min-width: 950px;
height: max-content; width: max-content;
background-color: #fff; height: max-content;
border: var(--window-border); min-height: 650px;
display: flex; border-radius: 10px;
flex-direction: column; overflow: hidden;
box-shadow: var(--window-box-shadow); background-color: #fff;
border-radius: var(--window-border-radius); // border: var(--window-border);
.wintmp_main { display: flex;
position: relative; flex-direction: column;
width: 100%; // box-shadow: var(--window-box-shadow);
height: 100%; // border-radius: var(--window-border-radius);
// background-color: rgb(255, 255, 255); .wintmp_main {
overflow: hidden; position: relative;
contain: content; width: 100%;
} height: 100%;
} // background-color: rgb(255, 255, 255);
overflow: hidden;
.topwin { contain: content;
border: 1px solid #0078d7; }
box-shadow: var(--window-top-box-shadow); }
}
.topwin {
.icon { // border: 1px solid #0078d7;
width: 12px; // box-shadow: var(--window-top-box-shadow);
height: 12px; }
}
.icon {
.max { width: 12px;
position: absolute; height: 12px;
left: 0 !important; }
top: 0 !important;
width: 100% !important; .max {
height: 100% !important; position: absolute;
transition: left 0.1s ease-in-out, top 0.1s ease-in-out, width 0.1s ease-in-out, left: 0 !important;
height 0.1s ease-in-out; top: 0 !important;
} width: 100% !important;
height: 100% !important;
.disable { transition: left 0.1s ease-in-out, top 0.1s ease-in-out,
.wintmp_uper, width 0.1s ease-in-out, height 0.1s ease-in-out;
.wintmp_main { }
pointer-events: none;
user-select: none; .disable {
box-shadow: none; .wintmp_uper,
} .wintmp_main {
} pointer-events: none;
.min { user-select: none;
visibility: hidden; box-shadow: none;
display: none; }
} }
.min {
.fullscreen { visibility: hidden;
// display: none;
position: fixed; }
left: 0 !important;
top: 0 !important; .fullscreen {
width: 100% !important; //
height: 100% !important; position: fixed;
z-index: 205 !important; left: 0 !important;
border: none; top: 0 !important;
.wintmp_uper { width: 100% !important;
display: none; height: 100% !important;
} z-index: 205 !important;
} border: none;
.wintmp_uper {
.noframe { display: none;
border: none; }
box-shadow: none; }
.wintmp_uper {
display: none; .noframe {
} border: none;
} box-shadow: none;
.wintmp_uper {
.transparent { display: none;
background-color: transparent; }
}
.wintmp_main {
background-color: transparent; .transparent {
} background-color: transparent;
.wintmp_uper { .wintmp_main {
background-color: rgba(255, 255, 255, 0.774); background-color: transparent;
} }
}
.wintmp_uper {
.win_drag_border { background-color: rgba(255, 255, 255, 0.774);
position: absolute; }
background-color: rgba(0, 0, 0, 0); }
}
.win_drag_border {
.right_border { position: absolute;
cursor: ew-resize; background-color: rgba(0, 0, 0, 0);
right: -12px; }
width: 16px;
height: calc(100% - 4px); .right_border {
} cursor: ew-resize;
right: -12px;
.bottom_border { width: 16px;
cursor: ns-resize; height: calc(100% - 4px);
bottom: -12px; }
width: calc(100% - 4px);
height: 16px; .bottom_border {
} cursor: ns-resize;
bottom: -12px;
.left_border { width: calc(100% - 4px);
cursor: ew-resize; height: 16px;
left: -12px; }
width: 16px;
height: calc(100% - 4px); .left_border {
} cursor: ew-resize;
left: -12px;
.top_border { width: 16px;
cursor: ns-resize; height: calc(100% - 4px);
top: -12px; }
width: calc(100% - 4px);
height: 16px; .top_border {
} cursor: ns-resize;
top: -12px;
.left_top_border { width: calc(100% - 4px);
cursor: nwse-resize; height: 16px;
left: -12px; }
top: -12px;
width: 16px; .left_top_border {
height: 16px; cursor: nwse-resize;
} left: -12px;
top: -12px;
.right_top_border { width: 16px;
cursor: nesw-resize; height: 16px;
right: -12px; }
top: -12px;
width: 16px; .right_top_border {
height: 16px; cursor: nesw-resize;
} right: -12px;
top: -12px;
.left_bottom_border { width: 16px;
cursor: nesw-resize; height: 16px;
left: -12px; }
bottom: -12px;
width: 16px; .left_bottom_border {
height: 16px; cursor: nesw-resize;
} left: -12px;
bottom: -12px;
.right_bottom_border { width: 16px;
cursor: nwse-resize; height: 16px;
right: -12px; }
bottom: -12px;
width: 16px; .right_bottom_border {
height: 16px; cursor: nwse-resize;
} right: -12px;
bottom: -12px;
.isChoseMode { width: 16px;
width: 100vw; height: 16px;
height: 100vh; }
position: fixed;
left: 0; .isChoseMode {
top: 0; width: 100vw;
} height: 100vh;
position: fixed;
.resizeing { left: 0;
user-select: none; top: 0;
pointer-events: none; }
}
.resizeing {
.content-mask { user-select: none;
position: absolute; pointer-events: none;
width: 100%; }
height: 100%;
background-color: rgba(0, 0, 0, 0); .content-mask {
z-index: 100; position: absolute;
} width: 100%;
</style> height: 100%;
background-color: rgba(0, 0, 0, 0);
z-index: 100;
}
</style>

125
frontend/src/stores/chat.ts

@ -289,6 +289,7 @@ export const useChatStore = defineStore('chatStore', () => {
// 添加到聊天记录 // 添加到聊天记录
if (Message.type === 'group') { if (Message.type === 'group') {
await db.addOne("workbenchGroupChatRecord", messageHistory); await db.addOne("workbenchGroupChatRecord", messageHistory);
updateGroupSessionList(messageHistory.previewMessage as string)
} else if (Message.type === 'user') { } else if (Message.type === 'user') {
await db.addOne("workbenchChatRecord", messageHistory); await db.addOne("workbenchChatRecord", messageHistory);
updateUserSessionList(messageHistory.previewMessage as string) updateUserSessionList(messageHistory.previewMessage as string)
@ -355,6 +356,7 @@ export const useChatStore = defineStore('chatStore', () => {
// 添加到聊天记录 // 添加到聊天记录
if (Message.type === 'group') { if (Message.type === 'group') {
await db.addOne("workbenchGroupChatRecord", messageHistory); await db.addOne("workbenchGroupChatRecord", messageHistory);
updateGroupSessionList(messageHistory.previewMessage as string)
} else if (Message.type === 'user') { } else if (Message.type === 'user') {
await db.addOne("workbenchChatRecord", messageHistory); await db.addOne("workbenchChatRecord", messageHistory);
updateUserSessionList(messageHistory.previewMessage as string) updateUserSessionList(messageHistory.previewMessage as string)
@ -429,6 +431,9 @@ export const useChatStore = defineStore('chatStore', () => {
} }
await db.addOne("workbenchGroupChatRecord", messageHistory); await db.addOne("workbenchGroupChatRecord", messageHistory);
// 更新groupSessionList
updateGroupSessionList(message.value)
} }
// 更新聊天历史 // 更新聊天历史
@ -440,6 +445,25 @@ export const useChatStore = defineStore('chatStore', () => {
} }
const updateGroupSessionList = async (message: string) => {
const groupSessionList = await db.getByField("groupSessionList", "chatId", targetChatId.value)
await db.update("groupSessionList", groupSessionList[0].id, {
previewMessage: message,
time: Date.now(),
previewTimeFormat: Date.now()
})
// 更新grouplist的预览字段
groupList.value.forEach((item: any) => {
if (item.chatId === targetChatId.value) {
item.previewMessage = message
item.previewTimeFormat = formatTime(Date.now())
}
})
initChatList()
}
const updateUserSessionList = async (message: string) => { const updateUserSessionList = async (message: string) => {
// 更新sessionlist表的字段 // 更新sessionlist表的字段
@ -455,11 +479,14 @@ export const useChatStore = defineStore('chatStore', () => {
// 更新聊天和聊天记录 // 更新聊天和聊天记录
const changeChatListAndChatHistory = async (data: any) => { const changeChatListAndChatHistory = async (data: any, message: string) => {
// 从 conversationList 数据库中查找是否存在对应的会话 // 从 conversationList 数据库中查找是否存在对应的会话
const conversation = await db.getByField("workbenchSessionList", 'chatId', data.userId); const conversation = await db.getByField("workbenchSessionList", 'chatId', data.userId);
console.log("更新的文字", message)
// 准备会话更新数据 // 准备会话更新数据
const updatedConversation = { const updatedConversation = {
userId: data.userId, userId: data.userId,
@ -472,7 +499,7 @@ export const useChatStore = defineStore('chatStore', () => {
displayName: data.userInfo.nickname, displayName: data.userInfo.nickname,
nickname: data.userInfo.nickname, nickname: data.userInfo.nickname,
time: Date.now(), time: Date.now(),
previewMessage: data.previewMessage, previewMessage: message,
previewTimeFormat: formatTime(Date.now()), // 时间格式化函数 previewTimeFormat: formatTime(Date.now()), // 时间格式化函数
createdAt: Date.now(), createdAt: Date.now(),
}; };
@ -489,7 +516,7 @@ export const useChatStore = defineStore('chatStore', () => {
avatar: data.userInfo.avatar, avatar: data.userInfo.avatar,
nickname: data.userInfo.nickname, nickname: data.userInfo.nickname,
displayName: data.userInfo.nickname, displayName: data.userInfo.nickname,
previewMessage: data.message, previewMessage: message,
time: Date.now(), time: Date.now(),
previewTimeFormat: formatTime(Date.now()) previewTimeFormat: formatTime(Date.now())
}); });
@ -504,6 +531,7 @@ export const useChatStore = defineStore('chatStore', () => {
} else { } else {
chatList.value.push(updatedConversation); chatList.value.push(updatedConversation);
} }
initChatList()
} }
}; };
@ -642,10 +670,11 @@ export const useChatStore = defineStore('chatStore', () => {
messages: message.value, messages: message.value,
chatId: group_id, chatId: group_id,
type: "group", type: "group",
time: Date.now(),
displayName: departmentName.value, displayName: departmentName.value,
previewMessage: message.value, previewMessage: "快开始打招呼吧!",
previewTimeFormat: formatTime(Date.now()), previewTimeFormat: Date.now(),
createdAt: new Date() createdAt: Date.now()
} }
groupList.value.push(groupConversation) groupList.value.push(groupConversation)
@ -659,17 +688,25 @@ export const useChatStore = defineStore('chatStore', () => {
content_type: "invite_group_message", content_type: "invite_group_message",
isMe: true, isMe: true,
chatId: group_id, chatId: group_id,
time: Date.now(),
message: `你邀请 ${inviteUserName} 加入群聊`, message: `你邀请 ${inviteUserName} 加入群聊`,
createdAt: Date.now() createdAt: Date.now()
} }
// 添加到数据库 // 添加到数据库
await db.addOne("workbenchGroupChatRecord", groupInviteMessage) await db.addOne("workbenchGroupChatRecord", groupInviteMessage)
// groupConversation添加到groupSessionList
await db.addOne("groupSessionList", groupConversation)
// 更新会话列表 // 更新会话列表
initChatList() initChatList()
// 关闭对话弹窗 // 关闭对话弹窗
setGroupChatInvitedDialogVisible(false) setGroupChatInvitedDialogVisible(false)
// 更新群组列表 // 更新群组列表
await getAllList() // await getAllList()
getGroupList()
notifySuccess('创建群聊成功') notifySuccess('创建群聊成功')
}; };
@ -728,26 +765,10 @@ export const useChatStore = defineStore('chatStore', () => {
await db.addOne("workbenchChatRecord", addMessageHistory) await db.addOne("workbenchChatRecord", addMessageHistory)
// 更新 chatList 和 conversationList表 // 更新 chatList 和 conversationList表
changeChatListAndChatHistory(data) changeChatListAndChatHistory(data, addMessageHistory.previewMessage)
console.log(chatList.value[0].chatId)
console.log(data.toUserId)
// // 找到chatlist中的对应项,更新previewMessage和previewTimeFormat
// const chatListIndex = chatList.value.findIndex((chat: { chatId: string; }) => chat.chatId === data.toUserId);
// console.log(chatListIndex)
// if (chatListIndex !== -1) {
// if (chatListIndex !== -1) {
// chatList.value[chatListIndex].previewMessage = addMessageHistory.previewMessage;
// chatList.value[chatListIndex].previewTimeFormat = addMessageHistory.previewTimeFormat;
// }
// // 更新sessionlist表的字段
// const sessionList = await db.getByField("workbenchSessionList", "chatId", targetUserInfo.value.chatId)
// await db.update("workbenchSessionList", sessionList[0].id, {
// previewMessage: message,
// previewTimeFormat: formatTime(Date.now())
// })
// 更改聊天记录 // 更改聊天记录
chatHistory.value.push(addMessageHistory) chatHistory.value.push(addMessageHistory)
@ -782,19 +803,27 @@ export const useChatStore = defineStore('chatStore', () => {
return false; return false;
} }
const list = await res.json() const list = await res.json()
console.log(list)
if (list.data.groups == null) { if (list.data.groups == null) {
list.data.groups = [] list.data.groups = []
} }
// 封装 list.data.groups
const formattedGroups = list.data.groups.map((group: any) => ({ // 从groupSessionList中获取群信息
group_id: group.id, const groupSessionList = await db.getAll("groupSessionList")
avatar: group.avatar || '', // 使用默认头像
// messages: "", // 合并查找和封装逻辑到一个循环中
displayName: group.name, const formattedGroups = list.data.groups.map((group: any) => {
chatId: group.id, const groupSession = groupSessionList.find((item: { chatId: string; }) => item.chatId === group.id);
type: 'group', return {
})); group_id: group.id,
avatar: group.avatar || '', // 使用默认头像
displayName: group.name,
chatId: group.id,
type: 'group',
time: groupSession ? groupSession.time : "",
previewMessage: groupSession ? groupSession.previewMessage : "", // 如果找到对应的会话则使用其预览消息,否则为空
};
});
groupList.value = formattedGroups; groupList.value = formattedGroups;
// 将群成员添加到数据库 // 将群成员添加到数据库
@ -1032,7 +1061,7 @@ export const useChatStore = defineStore('chatStore', () => {
const groupChatMessage = async (data: any) => { const groupChatMessage = async (data: any) => {
messageReceiveStatus.value = false messageReceiveStatus.value = false
console.log("接受消息", data)
// 构建消息记录 // 构建消息记录
const messageRecord: any = { const messageRecord: any = {
@ -1056,12 +1085,15 @@ export const useChatStore = defineStore('chatStore', () => {
if (data.content_type === 'image') { if (data.content_type === 'image') {
messageRecord.message = await getImageSrc(data.message) messageRecord.message = await getImageSrc(data.message)
messageRecord.previewMessage = "[图片消息]" messageRecord.previewMessage = "[图片消息]"
updateRecipientGroupSessionList(messageRecord.previewMessage, data.to_groupid)
} else if (data.content_type === 'text') { } else if (data.content_type === 'text') {
messageRecord.message = data.message messageRecord.message = data.message
messageRecord.previewMessage = data.message messageRecord.previewMessage = data.message
updateRecipientGroupSessionList(messageRecord.previewMessage, data.to_groupid)
} else if (data.content_type === 'file') { } else if (data.content_type === 'file') {
messageRecord.message = data.message messageRecord.message = data.message
messageRecord.previewMessage = "[文件消息]" messageRecord.previewMessage = "[文件消息]"
updateRecipientGroupSessionList(messageRecord.previewMessage, data.to_groupid)
} }
// 判断接受的消息是否是自己发送的 // 判断接受的消息是否是自己发送的
@ -1080,6 +1112,19 @@ export const useChatStore = defineStore('chatStore', () => {
messageReceiveStatus.value = true messageReceiveStatus.value = true
}; };
// 接受方更新groupSessionList
const updateRecipientGroupSessionList = async (message: string, chatId: string) => {
const group = await db.getByField("groupSessionList", "chatId", chatId)
// 更新groupSessionList
await db.update("groupSessionList", group[0].id, {
previewMessage: message,
time: Date.now(),
previewTimeFormat: Date.now(),
})
await getGroupList()
initChatList()
}
const showContextMenu = (event: any, id: number) => { const showContextMenu = (event: any, id: number) => {
contextMenu.value.visible = true; contextMenu.value.visible = true;
contextMenu.value.chatMessageId = id; contextMenu.value.chatMessageId = id;
@ -1155,10 +1200,13 @@ export const useChatStore = defineStore('chatStore', () => {
message: data.message, message: data.message,
chatId: data.group_id, chatId: data.group_id,
isMe: false, isMe: false,
previewMessage: "快开始打招呼吧!",
content_type: "invite_group_message", content_type: "invite_group_message",
createdAt: Date.now() createdAt: Date.now()
}; };
await db.addOne("workbenchGroupChatRecord", groupInviteMessage) await db.addOne("workbenchGroupChatRecord", groupInviteMessage)
// 添加到groupSessionList
await db.addOne("groupSessionList", groupInviteMessage)
const groupExists = groupList.value.some((group: { group_id: string; }) => group.group_id === data.group_id); const groupExists = groupList.value.some((group: { group_id: string; }) => group.group_id === data.group_id);
@ -1242,7 +1290,6 @@ export const useChatStore = defineStore('chatStore', () => {
inviteFriendDialogVisible, inviteFriendDialogVisible,
drawerVisible, drawerVisible,
addMemberDialogVisible, addMemberDialogVisible,
// groupTitle,
inviteUserList, inviteUserList,
messageSendStatus, messageSendStatus,
messageReceiveStatus, messageReceiveStatus,

4
frontend/src/stores/db.ts

@ -11,7 +11,7 @@ dbInit.version(1).stores({
// 聊天记录 // 聊天记录
workbenchChatRecord: '++id,toUserId,messages,messageType,time,createdAt,userInfo', workbenchChatRecord: '++id,toUserId,messages,messageType,time,createdAt,userInfo',
// 群组会话列表 // 群组会话列表
groupSessionList: '++id,groupId,name,message,previewMessage,avatar,createdAt', groupSessionList: '++id,groupId,chatId,name,message,previewMessage,avatar,createdAt',
// 群组聊天记录 // 群组聊天记录
workbenchGroupChatRecord: '++id,chatId,userId,to_groupid,messageType,userInfo,message,time,type,createdAt', workbenchGroupChatRecord: '++id,chatId,userId,to_groupid,messageType,userInfo,message,time,type,createdAt',
// 群用户列表 // 群用户列表
@ -27,9 +27,11 @@ dbInit.version(1).stores({
workbenchGroupChatRecord: any; workbenchGroupChatRecord: any;
workbenchGroupUserList: any; workbenchGroupUserList: any;
workbenchGroupInviteMessage: any; workbenchGroupInviteMessage: any;
groupSessionList: any;
workbenchChatRecord: { addIndex: (arg0: string, arg1: (obj: { toUserId: any; }) => any) => void; }; workbenchChatRecord: { addIndex: (arg0: string, arg1: (obj: { toUserId: any; }) => any) => void; };
}) => { }) => {
// 手动添加索引 // 手动添加索引
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.workbenchChatUser.addIndex('chatId', (obj: { chatId: any; }) => obj.chatId);

4
frontend/src/system/member.ts

@ -4,8 +4,8 @@ export const memberList = [
appIcon: "chat", appIcon: "chat",
content:"Chat", content:"Chat",
frame: true, frame: true,
width: 800, width: 1050,
height: 600, height: 650,
center: true, center: true,
resizable: true, resizable: true,
isDeskTop: true, isDeskTop: true,

Loading…
Cancel
Save