From 4909e9b67b761a5f1cf846c9c58aeb9825b9c51b Mon Sep 17 00:00:00 2001 From: wuyy Date: Thu, 2 Apr 2026 18:01:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=8D=B0=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SelectTable/index.vue | 2 +- src/layout/components/AppMain.vue | 8 +- src/plugins/download.ts | 17 +- src/store/modules/user.ts | 3 + src/utils/permission.ts | 27 +++- src/utils/printHelper.ts | 7 +- src/utils/webSocket.ts | 103 ++++++++++++ src/views/liswork/Issueorder/index.vue | 66 ++++++-- src/views/login.vue | 148 +++++++----------- src/views/regional/circulation/bbcx/index.vue | 50 ++++-- src/views/regional/circulation/sjdj/index.vue | 2 + .../inspectionReport/report/index.vue | 38 +++-- 12 files changed, 331 insertions(+), 140 deletions(-) create mode 100644 src/utils/webSocket.ts diff --git a/src/components/SelectTable/index.vue b/src/components/SelectTable/index.vue index 6286e25..eb3bdfe 100644 --- a/src/components/SelectTable/index.vue +++ b/src/components/SelectTable/index.vue @@ -348,9 +348,9 @@ const setLabel = (val: any) => { const clearHandle = () => { selectShowValue.value = ''; currentRow.value = null; - tableRef.value.clearCurrentRow(); emits("update:data", null); emits('getDataValue', null); + tableRef.value?.clearCurrentRow(); }; diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue index 7ed6129..70ac4be 100644 --- a/src/layout/components/AppMain.vue +++ b/src/layout/components/AppMain.vue @@ -2,11 +2,11 @@
- - + + - - + + diff --git a/src/plugins/download.ts b/src/plugins/download.ts index 5da58a8..37ccca8 100644 --- a/src/plugins/download.ts +++ b/src/plugins/download.ts @@ -15,7 +15,22 @@ export default { method: 'get', url: url, responseType: 'blob', - headers: { 'Authorization': 'Bearer ' + getToken() } + headers: { 'Authorization': 'Bearer ' + getToken() }, + onDownloadProgress: (progressEvent) => { + // console.log(progressEvent) + //progressEvent.loaded 下载文件的当前大小 + //progressEvent.total 下载文件的总大小 如果后端没有返回 请让他加上 + let progressPercent = Math.round((progressEvent.loaded / progressEvent.total) * 100); + let loading = ElLoading.service({ + lock: true, + text: `下载中,请稍候${progressPercent}%`, + background: 'rgba(0, 0, 0, 0.7)', + }) + loading.setText(`下载中,请稍候${progressPercent}%`) + if (progressPercent == 100) { + loading.close() + } + } }).then((res: any) => { const isBlob = blobValidate(res.data) if (isBlob) { diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 5561f69..b23d037 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -20,6 +20,7 @@ interface UserState { roles: string[] permissions: string[] sysLoginParam: Object + deptParam: Object } const useUserStore = defineStore( @@ -35,6 +36,7 @@ const useUserStore = defineStore( roles: [], permissions: [], sysLoginParam: {}, // 登录参数 + deptParam: {} // 部门参数 }), actions: { // 单点登录 @@ -79,6 +81,7 @@ const useUserStore = defineStore( const user = res.user let avatar = user.avatar || '' this.sysLoginParam = user.sysLoginParam + this.deptParam = user.dept if (!isHttp(avatar)) { avatar = (isEmpty(avatar)) ? defAva : import.meta.env.VITE_APP_BASE_API + avatar } diff --git a/src/utils/permission.ts b/src/utils/permission.ts index cd6ea95..5327c59 100644 --- a/src/utils/permission.ts +++ b/src/utils/permission.ts @@ -48,4 +48,29 @@ export function checkRole(value: string[]): boolean { }) return hasRole -} \ No newline at end of file +} + + +/** + * 管理员、检测机构权限校验 + * @param value 校验值 + * @returns {Boolean} + */ +export function checkDeptRole(value: string[]): boolean { + if (!value || !(value instanceof Array) || value.length === 0) { + console.error(`need roles! Like checkRole="['admin','editor']"`) + return false + } + + const userStore = useUserStore() + const roles = userStore.roles + const permissionRoles = value + const deptParam = userStore.deptParam + // 取出 roleKey 进行判断 + const hasRole = roles.some((role: any) => { + const roleKey = role.roleKey || '' + // 是超级管理员 admin 或者 包含指定角色 、 检测机构人员权限 203 + return roleKey === 'admin' || permissionRoles.includes(roleKey) || deptParam.parentId == 203 + }) + return hasRole +} diff --git a/src/utils/printHelper.ts b/src/utils/printHelper.ts index f47802e..048e279 100644 --- a/src/utils/printHelper.ts +++ b/src/utils/printHelper.ts @@ -7,15 +7,14 @@ import { ElMessageBox, ElMessage } from 'element-plus' import { printcheck } from '@/api/checkCode/index' import Download from '@/plugins/download' - +import { getWebSocketState } from '@/utils/webSocket'; export const checkPrintService = async (): Promise => { //连接成功返回true,失败返回false try { - const res = await printcheck() - if (res.code == 0) { + if (getWebSocketState() == 1) { // 1表示WebSocket已连接 return true } else { - await showPrintServiceError(res.msg) + await showPrintServiceError('打印服务未连接') return false } } catch (error) { diff --git a/src/utils/webSocket.ts b/src/utils/webSocket.ts new file mode 100644 index 0000000..f19309b --- /dev/null +++ b/src/utils/webSocket.ts @@ -0,0 +1,103 @@ +// WebSocket连接配置 +type WebSocketOptions = { + fullUrl: string; + onMessage?: (data: string) => void; + onOpen?: () => void; + onError?: (error: Event) => void; + onClose?: () => void; + reconnectInterval?: number; +}; + +let websocket: WebSocket | null = null; +let reconnectTimer: any = null; +let isManualClose = false; + +// 初始化WebSocket连接 +export function initWebSocket(options: WebSocketOptions) { + const { + fullUrl, + onMessage, + onOpen, + onError, + onClose, + reconnectInterval = 3000 + } = options; + + // 关闭旧连接 + if (websocket) { + websocket.close(); + } + + // 检查浏览器支持性 + if (!('WebSocket' in window)) { + console.error('当前浏览器不支持WebSocket'); + return; + } + + // 创建WebSocket连接 + try { + websocket = new WebSocket(fullUrl); + + // 连接成功回调 + websocket.onopen = () => { + clearTimeout(reconnectTimer!); + isManualClose = false; + onOpen?.(); + }; + + // 接收消息回调 + websocket.onmessage = (event) => { + onMessage?.(event.data); + }; + + // 错误回调 + websocket.onerror = (error) => { + onError?.(error); + startReconnect(() => initWebSocket(options), reconnectInterval); + }; + + // 关闭回调 + websocket.onclose = () => { + onClose?.(); + if (!isManualClose) { + startReconnect(() => initWebSocket(options), reconnectInterval); + } + }; + } catch (error) { + console.error('WebSocket连接创建失败:', error); + startReconnect(() => initWebSocket(options), reconnectInterval); + } +} + +// 发送消息 +export function sendWebSocketMessage(message: any): boolean { + if (websocket && websocket.readyState === WebSocket.OPEN) { + websocket.send(JSON.stringify(message)); + return true; + } + console.error('WebSocket未连接,无法发送消息'); + return false; +} + +// 手动关闭WebSocket +export function closeWebSocket(): void { + isManualClose = true; + if (reconnectTimer) { + clearTimeout(reconnectTimer); + } + websocket?.close(); + websocket = null; +} + +// 启动重连 +function startReconnect(connectCallback: () => void, interval: number): void { + if (reconnectTimer) { + clearTimeout(reconnectTimer); + } + reconnectTimer = setTimeout(connectCallback, interval); +} + +// 获取当前连接状态 +export function getWebSocketState(): number | null { + return websocket?.readyState || null; +} \ No newline at end of file diff --git a/src/views/liswork/Issueorder/index.vue b/src/views/liswork/Issueorder/index.vue index 09c4421..9e61f83 100644 --- a/src/views/liswork/Issueorder/index.vue +++ b/src/views/liswork/Issueorder/index.vue @@ -11,10 +11,10 @@
- 保存 - 新增 - 打印 - 作废 + 保存 + 新增 + 打印 + 作废
@@ -72,12 +72,12 @@
-
- + 所有 {{ item.label }} @@ -86,7 +86,7 @@
- + 近3天 近7天 此日 @@ -96,8 +96,8 @@   - 刷新 + :size="aotuSize" @change="dateHandle" />   + 刷新
@@ -130,6 +130,9 @@ import { listitemclass } from "@/api/regional/dict/itemclass.ts"; import { classCom } from '@/utils/classCom'; import { useGroupTableData } from '@/utils/groupHelper' const { proxy } = getCurrentInstance(); +import { initWebSocket, sendWebSocketMessage, closeWebSocket, getWebSocketState } from '@/utils/webSocket'; +const aotuSize = classCom.useAutoSize(); + const labpat = ref({ ageUnit: '1' }) @@ -383,6 +386,7 @@ const printHandle = () => { printLoading.value = true reqPrint(uniqueData).then(res => { if (res.code == 0) { + sendWebSocketMessage(res.data) handleRowClick({ row: rowInfo.value }) ElMessage.success('正在打印中...') handleQuery() @@ -420,11 +424,17 @@ const xmcellStyle = ({ row, column }) => { const searchList = ref([]) const handleTabClick = (tab) => { - const currentTab = xmdlList.value.find(item => item.dictCode === tab.paneName) - if (currentTab) { - searchList.value = processedTableData.value.filter(item => item.classid === currentTab.dictCode) + if (tab.paneName) { + const currentTab = xmdlList.value.find(item => item.dictCode === tab.paneName) + if (currentTab) { + searchList.value = processedTableData.value.filter(item => item.classid === currentTab.dictCode) + filterData.value = [...searchList.value] + } + } else { + searchList.value = [...processedTableData.value] filterData.value = [...searchList.value] } + } const processedTableData = ref([]) @@ -582,6 +592,7 @@ const getXmList = () => { listregdict({ dictType: 'CLASS' }).then(response => { xmdlList.value = response.rows; + xmdlList.value.unshift({ dictCode: '', dictName: '全部' }) activeName.value = xmdlList.value.length > 0 ? xmdlList.value[0].dictCode : ''; handleTabClick({ paneName: activeName.value }); }); @@ -589,7 +600,24 @@ const getXmList = () => { } const itemclassList = ref([]) // 容器类别 - +const initSocket = () => { + initWebSocket({ + fullUrl: `ws://localhost:9801`, + onOpen: () => { + console.log('WebSocket连接成功'); + }, + onMessage: (data) => { + console.log(`收到消息: `, JSON.parse(data)); + }, + onError: (error) => { + console.log(`连接错误: ${error.type}`); + }, + onClose: () => { + console.log('WebSocket连接已关闭'); + }, + reconnectInterval: 3000 // 重连间隔(毫秒) + }); +} onMounted(() => { getXmList() @@ -602,7 +630,13 @@ onMounted(() => { // 初始化初始值 updateInitialData() + initSocket() }) + +// 页面卸载时清理 +onUnmounted(() => { + closeWebSocket(); +});