【web】 完成站内信功能

dev
Wangxin 8 months ago
parent e066bca3db
commit e6d5b85785
  1. 19
      ALOps_sys_fe/alops-ui/src/router/index.js
  2. 89
      ALOps_sys_fe/alops-ui/src/utils/websocket.js

@ -37,12 +37,25 @@ export const constantRoutes = [
children: [ children: [
{ {
path: 'index_admin', path: 'index_admin',
component: () => import('@/views/index_1'), component: () => import('@/views/index'),
name: 'IndexAdmin', name: 'Index',
meta: { title: '管理员首页', icon: 'dashboard', affix: true, fullscreen: true } meta: { title: '首页', icon: 'dashboard', affix: true, roles: ['common'] }
} }
] ]
}, },
// {
// path: '',
// component: Layout,
// redirect: 'index',
// children: [
// {
// path: 'index_admin',
// component: () => import('@/views/index_1'),
// name: 'IndexAdmin',
// meta: { title: '管理员首页', icon: 'dashboard', affix: true, fullscreen: true }
// }
// ]
// },
{ {
path: '/redirect', path: '/redirect',
component: Layout, component: Layout,

@ -10,6 +10,26 @@ class WebSocketClient {
this.maxReconnectAttempts = 5 this.maxReconnectAttempts = 5
this.reconnectInterval = 3000 this.reconnectInterval = 3000
this.connected = false this.connected = false
// token传递方式: 'url'(默认,URL参数), 'header'(请求头), 'message'(首次消息)
this.tokenMode = 'url'
}
// 设置token传递方式
setTokenMode(mode) {
const validModes = ['url', 'header', 'message']
if (validModes.includes(mode)) {
this.tokenMode = mode
console.log(`WebSocket token传递方式已设置为: ${mode}`)
// 特别说明header模式的限制
if (mode === 'header') {
console.warn('注意: header模式使用WebSocket子协议传递token,受浏览器API限制,实际token将通过Sec-WebSocket-Protocol头传递')
console.warn('后端需要从Sec-WebSocket-Protocol请求头中提取token信息')
}
return true
}
console.error('无效的token传递方式,可选值: url, header, message')
return false
} }
// 初始化WebSocket连接 // 初始化WebSocket连接
@ -24,7 +44,6 @@ class WebSocketClient {
} }
// 获取token并检查登录状态 // 获取token并检查登录状态
// 检查token有效性
const token = getToken() const token = getToken()
if (!token) { if (!token) {
console.warn('WebSocket初始化失败: 未获取到token,请先登录') console.warn('WebSocket初始化失败: 未获取到token,请先登录')
@ -47,8 +66,14 @@ class WebSocketClient {
let wsProtocol = baseURL.includes('https') ? 'wss' : 'ws' let wsProtocol = baseURL.includes('https') ? 'wss' : 'ws'
let wsBaseURL = baseURL.replace(/^https?:\/\//, '') let wsBaseURL = baseURL.replace(/^https?:\/\//, '')
// 将token添加到URL查询参数 // 根据token传递方式构建URL
this.url = `${wsProtocol}://${wsBaseURL}/ws/onlineMessage?userId=${userId}&token=${token}` if (this.tokenMode === 'url') {
// 在token前面加上'token-'前缀
this.url = `${wsProtocol}://${wsBaseURL}/ws/onlineMessage?token=token-${token}`
} else {
// header或message模式下,URL不包含token
this.url = `${wsProtocol}://${wsBaseURL}/ws/onlineMessage`
}
// 输出环境变量和配置信息以调试 // 输出环境变量和配置信息以调试
console.log('WebSocket配置:', { console.log('WebSocket配置:', {
@ -56,7 +81,8 @@ class WebSocketClient {
userId, userId,
wsProtocol, wsProtocol,
wsBaseURL, wsBaseURL,
hasToken: !!token hasToken: !!token,
tokenMode: this.tokenMode
}) })
console.log('尝试连接WebSocket URL:', this.url) console.log('尝试连接WebSocket URL:', this.url)
@ -94,8 +120,27 @@ class WebSocketClient {
} }
try { try {
console.log(`正在建立WebSocket连接 (尝试 ${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`) console.log(`正在建立WebSocket连接${this.tokenMode} (尝试 ${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`)
this.ws = new WebSocket(this.url)
// 根据token模式创建WebSocket连接
if (this.tokenMode === 'header') {
// header模式: 使用WebSocket子协议传递token
// 注意:JavaScript WebSocket API要求子协议名必须是有效的字符串,不能包含特殊字符
// 后端应从Sec-WebSocket-Protocol请求头中获取token信息
const token = getToken()
if (token) {
// 在token前面加上'token-'前缀
// 使用简洁的子协议名称,让后端从请求头中解析完整token
this.ws = new WebSocket(this.url, ['auth-token'])
console.log('WebSocket连接将通过Sec-WebSocket-Protocol头传递token')
} else {
console.error('无法获取token,使用普通连接')
this.ws = new WebSocket(this.url)
}
} else {
// url或message模式: 直接创建连接
this.ws = new WebSocket(this.url)
}
// 设置事件监听 // 设置事件监听
this.ws.onopen = this.onOpen.bind(this) this.ws.onopen = this.onOpen.bind(this)
@ -114,6 +159,20 @@ class WebSocketClient {
console.log('WebSocket连接已建立') console.log('WebSocket连接已建立')
this.connected = true this.connected = true
this.reconnectAttempts = 0 this.reconnectAttempts = 0
// message模式: 连接成功后发送token
if (this.tokenMode === 'message') {
const token = getToken()
if (token) {
const authMessage = {
type: 'auth',
token: `token-${token}`, // 在token前面加上'token-'前缀
userId: this.userId
}
this.send(authMessage)
console.log('已发送认证消息:', authMessage)
}
}
} }
// 接收消息回调 // 接收消息回调
@ -135,7 +194,7 @@ class WebSocketClient {
title: message.title || '系统通知', title: message.title || '系统通知',
message: message.content, message: message.content,
type: 'info', type: 'info',
duration: 10000, // 10秒后自动关闭 duration: 1000000, // 10秒后自动关闭
showClose: true, showClose: true,
onClick: () => { onClick: () => {
// 可以在这里添加点击通知后的处理逻辑 // 可以在这里添加点击通知后的处理逻辑
@ -188,10 +247,18 @@ class WebSocketClient {
console.log(`WebSocket将在 ${Math.round(currentInterval/1000)} 秒后进行第${this.reconnectAttempts}次重连...`) console.log(`WebSocket将在 ${Math.round(currentInterval/1000)} 秒后进行第${this.reconnectAttempts}次重连...`)
setTimeout(() => { setTimeout(() => {
// 重连前刷新token参数 // 根据不同token模式更新认证信息
if (this.url && this.userId) { if (this.tokenMode === 'url' && this.url) {
this.url = this.url.replace(/token=[^&]*/, `token=${token}`) // URL模式: 更新URL中的token参数
} // 在token前面加上'token-'前缀
this.url = this.url.replace(/token=[^&]*/, `token=token-${token}`)
} else if (this.tokenMode === 'header') {
// Header模式: 重连时会自动从getToken()获取最新token
console.log('Header模式下重连,将使用最新token')
} else if (this.tokenMode === 'message') {
// Message模式: 重连成功后会自动发送认证消息
console.log('Message模式下重连,将在连接建立后发送认证消息')
}
this.connect() this.connect()
}, currentInterval) }, currentInterval)
} else { } else {

Loading…
Cancel
Save