From f00cf6db396120b8cd8e587b3059368f39375415 Mon Sep 17 00:00:00 2001 From: yxh Date: Tue, 2 Jan 2024 17:51:46 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E7=AB=99=E5=86=85=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E3=80=81=E7=A7=81=E4=BF=A1=E3=80=81websocket=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/system/notice/sysNotice.ts | 80 ++++ src/api/system/notice/sysNoticeRead.ts | 52 +++ src/layout/navBars/breadcrumb/user.vue | 45 +- src/layout/navBars/breadcrumb/userNews.vue | 399 +++++++++++++----- src/main.ts | 11 + src/stores/interface/index.ts | 10 + src/stores/noticeStore.ts | 19 + src/utils/websocket.ts | 169 ++++++++ .../list/component/NoticeMessageEdit.vue | 300 +++++++++++++ .../system/sysNotice/list/component/model.ts | 61 +++ src/views/system/sysNotice/list/index.vue | 375 ++++++++++++++++ src/views/system/sysNotice/show/index.vue | 259 ++++++++++++ 12 files changed, 1672 insertions(+), 108 deletions(-) create mode 100644 src/api/system/notice/sysNotice.ts create mode 100644 src/api/system/notice/sysNoticeRead.ts create mode 100644 src/stores/noticeStore.ts create mode 100644 src/utils/websocket.ts create mode 100644 src/views/system/sysNotice/list/component/NoticeMessageEdit.vue create mode 100644 src/views/system/sysNotice/list/component/model.ts create mode 100644 src/views/system/sysNotice/list/index.vue create mode 100644 src/views/system/sysNotice/show/index.vue diff --git a/src/api/system/notice/sysNotice.ts b/src/api/system/notice/sysNotice.ts new file mode 100644 index 0000000..39adb08 --- /dev/null +++ b/src/api/system/notice/sysNotice.ts @@ -0,0 +1,80 @@ +import request from '/@/utils/request' +// 查询通知私信列表 +export function listSysNotice(query:object) { + return request({ + url: '/api/v1/system/sysNotice/list', + method: 'get', + params: query + }) +} + +export function listShowNotice(query:object) { + return request({ + url: '/api/v1/system/sysNotice/listShow', + method: 'get', + params: query + }) +} +// 查询通知私信详细 +export function getSysNotice(id:number) { + return request({ + url: '/api/v1/system/sysNotice/get', + method: 'get', + params: { + id: id.toString() + } + }) +} +// 新增通知私信 +export function addSysNotice(data:object) { + return request({ + url: '/api/v1/system/sysNotice/add', + method: 'post', + data: data + }) +} +// 修改通知私信 +export function updateSysNotice(data:object) { + return request({ + url: '/api/v1/system/sysNotice/edit', + method: 'put', + data: data + }) +} +// 删除通知私信 +export function delSysNotice(ids:number[]) { + return request({ + url: '/api/v1/system/sysNotice/delete', + method: 'delete', + data:{ + ids:ids + } + }) +} + + +export function getIndexData(){ + return request( + { + url:'/api/v1/system/sysNotice/getIndexData', + method:'get' + } + ) +} + +//获取维度通知私信公告信息 +export function unReadCount(){ + return request({ + url:'/api/v1/system/sysNotice/unReadCount', + method:'get' + }) +} + +//获取私信待选择的用户 +export function getUserList(query:string){ + return request({ + url:'/api/v1/system/sysNotice/userList', + method:'get', + params:{userNickname:query} + }) +} diff --git a/src/api/system/notice/sysNoticeRead.ts b/src/api/system/notice/sysNoticeRead.ts new file mode 100644 index 0000000..c2576f2 --- /dev/null +++ b/src/api/system/notice/sysNoticeRead.ts @@ -0,0 +1,52 @@ +import request from '/@/utils/request' +// 查询已读记录列表 +export function listSysNoticeRead(query:object) { + return request({ + url: '/api/v1/system/sysNoticeRead/list', + method: 'get', + params: query + }) +} +// 查询已读记录详细 +export function getSysNoticeRead(id:number) { + return request({ + url: '/api/v1/system/sysNoticeRead/get', + method: 'get', + params: { + id: id.toString() + } + }) +} +// 新增已读记录 +export function addSysNoticeRead(data:object) { + return request({ + url: '/api/v1/system/sysNoticeRead/add', + method: 'post', + data: data + }) +} +export function readNotice(data:object) { + return request({ + url: '/api/v1/system/sysNoticeRead/readNotice', + method: 'post', + data: data + }) +} +// 修改已读记录 +export function updateSysNoticeRead(data:object) { + return request({ + url: '/api/v1/system/sysNoticeRead/edit', + method: 'put', + data: data + }) +} +// 删除已读记录 +export function delSysNoticeRead(ids:number[]) { + return request({ + url: '/api/v1/system/sysNoticeRead/delete', + method: 'delete', + data:{ + ids:ids + } + }) +} diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue index c8a38a1..9d68707 100644 --- a/src/layout/navBars/breadcrumb/user.vue +++ b/src/layout/navBars/breadcrumb/user.vue @@ -36,7 +36,7 @@
- +
@@ -80,9 +80,9 @@ diff --git a/src/main.ts b/src/main.ts index 6561639..a241a45 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,6 +13,7 @@ import '/@/theme/index.scss'; import mitt from 'mitt'; import VueGridLayout from 'vue-grid-layout'; import {getUpFileUrl, handleTree, parseTime, selectDictLabel} from '/@/utils/gfast'; +import Websocket from '/@/utils/websocket'; import {useDict} from '/@/api/system/dict/data'; import {getItems, setItems, getOptionValue, isEmpty} from '/@/api/items' // 分页组件 @@ -27,6 +28,16 @@ import VueUeditorWrap from 'vue-ueditor-wrap'; const app = createApp(App); +// 全局websocket +const onMessageList: Array = []; +app.provide('onMessageList', onMessageList); +const onMessage = (event: any) => { + onMessageList.forEach((f) => { + f.call(null, event); + }); +}; +Websocket(onMessage); + directive(app); other.elSvg(app); diff --git a/src/stores/interface/index.ts b/src/stores/interface/index.ts index 336b021..a0d99d0 100644 --- a/src/stores/interface/index.ts +++ b/src/stores/interface/index.ts @@ -95,3 +95,13 @@ export interface ThemeConfigStates { export interface bigUploadStates { panelShow : boolean } + +export interface NoticeMessage{ + id:number; + title:string; + tag:number; + type:number; +} +export interface NoticeStates{ + message:NoticeMessage; +} diff --git a/src/stores/noticeStore.ts b/src/stores/noticeStore.ts new file mode 100644 index 0000000..0f01209 --- /dev/null +++ b/src/stores/noticeStore.ts @@ -0,0 +1,19 @@ +import { defineStore } from 'pinia'; +import {NoticeMessage, NoticeStates} from "/@/stores/interface"; + +export const noticeStore = defineStore({ + id: 'noticeStore', + state: (): NoticeStates => ({ + message: {} + }), + getters: { + getMessages(): NoticeMessage { + return this.message; + }, + }, + actions: { + setMessages(messages:NoticeMessage) { + this.message = messages; + }, + }, +}); diff --git a/src/utils/websocket.ts b/src/utils/websocket.ts new file mode 100644 index 0000000..7d0ac03 --- /dev/null +++ b/src/utils/websocket.ts @@ -0,0 +1,169 @@ +import {getToken} from "/@/utils/gfast" +import {noticeStore} from "/@/stores/noticeStore"; +const noticeStoreAct = noticeStore() +const webSocketURL = import.meta.env.VITE_WEBSOCKET_URL +let socket: WebSocket; +let isActive: boolean; + +export function getSocket(): WebSocket { + if (socket === undefined) { + location.reload(); + } + return socket; +} + +export function getActive(): boolean { + return isActive; +} + +export function sendMsg(event: string, data = null, isRetry = true) { + if (socket === undefined || !isActive) { + if (!isRetry) { + console.log('socket连接异常,发送失败!'); + return; + } + console.log('socket连接异常,等待重试..'); + setTimeout(function () { + sendMsg(event, data); + }, 200); + return; + } + + try { + socket.send( + JSON.stringify({ + event: event, + data: data, + }) + ); + } catch (err) { + // @ts-ignore + console.log('ws发送消息失败,等待重试,err:' + err.message); + if (!isRetry) { + return; + } + setTimeout(function () { + sendMsg(event, data); + }, 100); + } +} + +export function addOnMessage(onMessageList: any, func: Function) { + let exist = false; + for (let i = 0; i < onMessageList.length; i++) { + if (onMessageList[i].name == func.name) { + onMessageList[i] = func; + exist = true; + } + } + if (!exist) { + onMessageList.push(func); + } +} + +export default (onMessage: Function) => { + const heartCheck = { + timeout: 10000, + timeoutObj: setTimeout(() => {}), + serverTimeoutObj: setInterval(() => {}), + reset: function () { + clearTimeout(this.timeoutObj); + clearTimeout(this.serverTimeoutObj); + return this; + }, + start: function () { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = this; + clearTimeout(this.timeoutObj); + clearTimeout(this.serverTimeoutObj); + this.timeoutObj = setTimeout(function () { + socket.send( + JSON.stringify({ + event: 'ping', + }) + ); + self.serverTimeoutObj = setTimeout(function () { + console.log('关闭服务'); + socket.close(); + }, self.timeout); + }, this.timeout); + }, + }; + + + let lockReconnect = false; + let timer: ReturnType; + const createSocket = () => { + console.log('createSocket...'); + try { + if (getToken() === '') { + throw new Error('用户未登录,稍后重试...'); + } + socket = new WebSocket(webSocketURL+'/api/v1/websocket?token='+encodeURIComponent(getToken())); + init(); + } catch (e) { + console.log('createSocket err:' + e); + reconnect(); + } + if (lockReconnect) { + lockReconnect = false; + } + }; + const reconnect = () => { + console.log('lockReconnect:' + lockReconnect); + if (lockReconnect) return; + lockReconnect = true; + clearTimeout(timer); + timer = setTimeout(() => { + createSocket(); + }, 30000); + }; + + const init = () => { + socket.onopen = function (_) { + console.log('WebSocket:已连接'); + heartCheck.reset().start(); + isActive = true; + }; + + socket.onmessage = function (event) { + isActive = true; + // console.log('WebSocket:收到一条消息', event.data); + let isHeart = false; + const message = JSON.parse(event.data); + if (message.event === 'ping') { + isHeart = true; + } + // 通知私信 + if (message.event === 'notice') { + noticeStoreAct.setMessages(message.data) + return; + } + if (onMessage && !isHeart) { + onMessage.call(null, event); + } + heartCheck.reset().start(); + }; + + socket.onerror = function (_) { + console.log('WebSocket:发生错误'); + reconnect(); + isActive = false; + }; + + socket.onclose = function (_) { + console.log('WebSocket:已关闭'); + heartCheck.reset(); + reconnect(); + isActive = false; + }; + + window.onbeforeunload = function () { + socket.close(); + isActive = false; + }; + }; + + createSocket(); +}; + diff --git a/src/views/system/sysNotice/list/component/NoticeMessageEdit.vue b/src/views/system/sysNotice/list/component/NoticeMessageEdit.vue new file mode 100644 index 0000000..48cd0e0 --- /dev/null +++ b/src/views/system/sysNotice/list/component/NoticeMessageEdit.vue @@ -0,0 +1,300 @@ + + + diff --git a/src/views/system/sysNotice/list/component/model.ts b/src/views/system/sysNotice/list/component/model.ts new file mode 100644 index 0000000..072eb1e --- /dev/null +++ b/src/views/system/sysNotice/list/component/model.ts @@ -0,0 +1,61 @@ +export interface SysNoticeTableColumns { + id:number; // ID + title:string; // 标题 + type:number; // 类型 + tag:number; // 标签 + content:string; // 内容 + remark:string; // 备注 + sort:number; // 排序 + status:number; // 状态 + createdBy:string; // 发送人 + createdAt:string; // 创建时间 +} + + +export interface SysNoticeInfoData { + id:number|undefined; // ID + receiver:number[]|undefined;//用户id + title:string|undefined; // 标题 + type:number|undefined; // 类型 + tag:number|undefined; // 标签 + content:string|undefined; // 内容 + remark:string|undefined; // 备注 + sort:number|undefined; // 排序 + status:number; // 状态 + createdBy:number|undefined; // 发送人 + updatedBy:number|undefined; // 修改人 + createdAt:string|undefined; // 创建时间 + updatedAt:string|undefined; // 更新时间 + deletedAt:string|undefined; // 删除时间 +} + + +export interface SysNoticeTableDataState { + ids:any[]; + tableData: { + data: Array; + total: number; + loading: boolean; + param: { + pageNum: number; + pageSize: number; + id: number|undefined; + title: string|undefined; + type: number|undefined; + tag: number|undefined; + status: number|undefined; + createdAt: string|undefined; + dateRange: string[]; + }; + }; +} + + +export interface SysNoticeEditState{ + loading:boolean; + isShowDialog: boolean; + userListOptions:object[]; + title:string; + formData:SysNoticeInfoData; + rules: object; +} diff --git a/src/views/system/sysNotice/list/index.vue b/src/views/system/sysNotice/list/index.vue new file mode 100644 index 0000000..f571318 --- /dev/null +++ b/src/views/system/sysNotice/list/index.vue @@ -0,0 +1,375 @@ + + + diff --git a/src/views/system/sysNotice/show/index.vue b/src/views/system/sysNotice/show/index.vue new file mode 100644 index 0000000..61e1533 --- /dev/null +++ b/src/views/system/sysNotice/show/index.vue @@ -0,0 +1,259 @@ + + +