diff --git a/kinit-admin/src/components/Chat/index.ts b/kinit-admin/src/components/Chat/index.ts new file mode 100644 index 0000000..68e1d60 --- /dev/null +++ b/kinit-admin/src/components/Chat/index.ts @@ -0,0 +1,3 @@ +import Chat from './src/Chat.vue' + +export { Chat } diff --git a/kinit-admin/src/components/Chat/src/Chat.vue b/kinit-admin/src/components/Chat/src/Chat.vue new file mode 100644 index 0000000..7229bf5 --- /dev/null +++ b/kinit-admin/src/components/Chat/src/Chat.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/kinit-admin/src/layout/components/ToolHeader.vue b/kinit-admin/src/layout/components/ToolHeader.vue index 6b2479c..8bd05d5 100644 --- a/kinit-admin/src/layout/components/ToolHeader.vue +++ b/kinit-admin/src/layout/components/ToolHeader.vue @@ -5,6 +5,7 @@ import { LocaleDropdown } from '@/components/LocaleDropdown' import { SizeDropdown } from '@/components/SizeDropdown' import { UserInfo } from '@/components/UserInfo' import { Screenfull } from '@/components/Screenfull' +import { Chat } from '@/components/Chat' import { Breadcrumb } from '@/components/Breadcrumb' import { useAppStore } from '@/store/modules/app' import { useDesign } from '@/hooks/web/useDesign' @@ -54,6 +55,7 @@ export default defineComponent({ ) : undefined}
+ {screenfull.value ? ( diff --git a/kinit-admin/src/store/modules/chat.ts b/kinit-admin/src/store/modules/chat.ts new file mode 100644 index 0000000..b98cd3b --- /dev/null +++ b/kinit-admin/src/store/modules/chat.ts @@ -0,0 +1,100 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import { ref } from 'vue' +import { ElMessage } from 'element-plus' + +interface ChatState { + socket: any + messageQueue: string[] + socketMessage: string +} + +export const useChatStore = defineStore('chat', { + state: (): ChatState => { + return { + socket: null, + messageQueue: [], + socketMessage: '1' + } + }, + getters: {}, + actions: { + SET_SOCKET(socket: any) { + this.socket = socket + }, + SET_SOCKET_MESSAGE(socketMessage: any) { + this.socketMessage = socketMessage + }, + connectWebSocket() { + if (typeof WebSocket === 'undefined') { + ElMessage.error('您的浏览器不支持Websocket通信协议,请使用Chrome或者其他高版本的浏览器!') + return + } + if (this.socket != null && this.socket.readyState === WebSocket.OPEN) { + return this.socket + } + + const HOST_ADDRESS = 'ws://127.0.0.1:8000/api/v1/ws/chat/' + const PING_INTERVAL = 5000 // 心跳间隔,单位为毫秒 + const heartbeatMessage = { type: 0, msg: 'ping' } // 心跳消息 + const heartbeatMessage2 = { type: 0, msg: 'pong', data: ['在线设备'] } // 发送消息 + + const socket = ref(new WebSocket(HOST_ADDRESS)) + let checkTask: any = null + // 监听连接事件 + socket.value.onopen = () => { + // 启动心跳检测 确保连接存活 客户端每隔5秒向服务端发送一次心跳消息 + checkTask = setInterval(() => { + socket.value.send(JSON.stringify(heartbeatMessage)) + }, PING_INTERVAL) + } + + // 当WebSocket接收到服务器发送的消息时,这个函数将被调用。 + socket.value.onmessage = (event) => { + console.log('接收到服务端发送过来的消息', event.data) + const message = JSON.parse(event.data) + console.log(message.type) + if (message.type == WebSocket.CONNECTING) { + socket.value.send(JSON.stringify(heartbeatMessage2)) + return + } else { + if (this.messageQueue.length > 2 << 16) { + this.messageQueue = [] + } + console.log('WebSocket消息: ', message) + this.SET_SOCKET_MESSAGE(message) + } + } + + // 监听关闭事件 断线重连 + socket.value.onclose = () => { + if (this.socket.readyState === WebSocket.CLOSED) { + this.messageQueue.forEach((message) => { + this.sendMessage(message) + }) + this.messageQueue = [] + } + // 清除心跳计时器 + checkTask && clearInterval(checkTask) + // 断线重连 + setTimeout(() => { + this.connectWebSocket() + }, 3000) + } + + // 连接错误 + socket.value.onerror = (event) => { + console.log('WebSocket error:', event) + } + }, + // 发送消息方法 + sendMessage(message: string) { + this.socket.send(message) + } + }, + persist: true +}) + +export const useChatStoreWithOut = () => { + return useChatStore(store) +} diff --git a/kinit-api/application/settings.py b/kinit-api/application/settings.py index 7c23647..6642c12 100644 --- a/kinit-api/application/settings.py +++ b/kinit-api/application/settings.py @@ -11,7 +11,7 @@ from fastapi.security import OAuth2PasswordBearer """ 系统版本 """ -VERSION = "3.9.0" +VERSION = "3.8.2" """安全警告: 不要在生产中打开调试运行!""" DEBUG = False