vue2-client 1.16.32 → 1.16.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +112 -112
- package/src/base-client/components/common/XFormTable/demo.vue +7 -45
- package/src/base-client/components/common/XReport/print.js +186 -186
- package/src/base-client/components/common/XTable/README.md +243 -0
- package/src/base-client/components/common/XTable/XTable.vue +1 -0
- package/src/base-client/components/common/XTable/XTableWrapper.vue +35 -2
- package/src/base-client/components/common/XWebSocketProgress/README.md +14 -0
- package/src/base-client/components/common/XWebSocketProgress/index.vue +252 -0
- package/src/base-client/components/his/XHisEditor/XHisEditor.vue +705 -700
- package/src/base-client/components/his/threeTestOrders/editor.vue +113 -113
- package/src/router/async/router.map.js +129 -129
- package/src/utils/map-utils.js +47 -47
- package/src/utils/websocket/README.md +224 -0
- package/src/utils/websocket/websocket.js +241 -0
- package/vue.config.js +6 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
# WebSocket 工具类
|
2
|
+
|
3
|
+
一个通用的 WebSocket 连接管理工具,提供连接、重连、消息发送等功能。
|
4
|
+
|
5
|
+
## 功能特性
|
6
|
+
|
7
|
+
- 🔌 **自动连接管理**: 自动处理连接、断开、重连
|
8
|
+
- 🔄 **智能重连**: 支持自动重连,可配置重连次数和间隔
|
9
|
+
- 📡 **事件系统**: 完整的事件监听机制
|
10
|
+
- 🎯 **Vue 2 兼容**: 提供组合式 API 风格的 Hook
|
11
|
+
|
12
|
+
## 基本用法
|
13
|
+
|
14
|
+
### 1. 直接使用 WebSocketManager 类
|
15
|
+
|
16
|
+
```javascript
|
17
|
+
import { WebSocketManager } from '@vue2-client/utils/websocket/websocket'
|
18
|
+
|
19
|
+
// 创建实例
|
20
|
+
const wsManager = new WebSocketManager({
|
21
|
+
autoReconnect: true,
|
22
|
+
reconnectInterval: 3000,
|
23
|
+
maxReconnectAttempts: 5
|
24
|
+
})
|
25
|
+
|
26
|
+
// 连接 WebSocket
|
27
|
+
wsManager.connect('ws://localhost:8080/websocket')
|
28
|
+
|
29
|
+
// 监听事件
|
30
|
+
wsManager.on('connected', (data) => {
|
31
|
+
console.log('连接成功', data)
|
32
|
+
})
|
33
|
+
|
34
|
+
wsManager.on('message', (data) => {
|
35
|
+
console.log('收到消息', data.data)
|
36
|
+
})
|
37
|
+
|
38
|
+
// 发送消息
|
39
|
+
wsManager.send({ type: 'ping', data: 'hello' })
|
40
|
+
|
41
|
+
// 断开连接
|
42
|
+
wsManager.disconnect()
|
43
|
+
```
|
44
|
+
|
45
|
+
### 2. 在 Vue 组件中使用 useWebSocket Hook
|
46
|
+
|
47
|
+
```vue
|
48
|
+
<template>
|
49
|
+
<div>
|
50
|
+
<div>连接状态: {{ connectionState.isConnected ? '已连接' : '未连接' }}</div>
|
51
|
+
<div>重连次数: {{ connectionState.reconnectAttempts }}</div>
|
52
|
+
<button @click="sendMessage">发送消息</button>
|
53
|
+
<button @click="reconnect">重连</button>
|
54
|
+
</div>
|
55
|
+
</template>
|
56
|
+
|
57
|
+
<script>
|
58
|
+
import { useWebSocket } from '@vue2-client/utils/websocket/websocket'
|
59
|
+
|
60
|
+
export default {
|
61
|
+
setup() {
|
62
|
+
const {
|
63
|
+
connect,
|
64
|
+
disconnect,
|
65
|
+
reconnect,
|
66
|
+
send,
|
67
|
+
on,
|
68
|
+
off,
|
69
|
+
getConnectionState
|
70
|
+
} = useWebSocket({
|
71
|
+
autoReconnect: true,
|
72
|
+
reconnectInterval: 3000,
|
73
|
+
maxReconnectAttempts: 5
|
74
|
+
})
|
75
|
+
|
76
|
+
// 连接状态
|
77
|
+
const connectionState = getConnectionState()
|
78
|
+
|
79
|
+
// 连接 WebSocket
|
80
|
+
connect('ws://localhost:8080/websocket')
|
81
|
+
|
82
|
+
// 监听消息
|
83
|
+
on('message', (data) => {
|
84
|
+
console.log('收到消息:', data.data)
|
85
|
+
})
|
86
|
+
|
87
|
+
// 发送消息
|
88
|
+
const sendMessage = () => {
|
89
|
+
send({ type: 'ping', data: 'hello' })
|
90
|
+
}
|
91
|
+
|
92
|
+
// 重连
|
93
|
+
const reconnectWebSocket = () => {
|
94
|
+
reconnect('ws://localhost:8080/websocket')
|
95
|
+
}
|
96
|
+
|
97
|
+
return {
|
98
|
+
connectionState,
|
99
|
+
sendMessage,
|
100
|
+
reconnect: reconnectWebSocket
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
</script>
|
105
|
+
```
|
106
|
+
|
107
|
+
## API 参考
|
108
|
+
|
109
|
+
### WebSocketManager 类
|
110
|
+
|
111
|
+
#### 构造函数选项
|
112
|
+
|
113
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
114
|
+
|------|------|--------|------|
|
115
|
+
| autoReconnect | Boolean | true | 是否自动重连 |
|
116
|
+
| reconnectInterval | Number | 3000 | 重连间隔(毫秒) |
|
117
|
+
| maxReconnectAttempts | Number | 5 | 最大重连次数 |
|
118
|
+
|
119
|
+
#### 方法
|
120
|
+
|
121
|
+
##### connect(url, options)
|
122
|
+
连接 WebSocket
|
123
|
+
- `url`: WebSocket 连接地址
|
124
|
+
- `options`: 连接选项(可选)
|
125
|
+
|
126
|
+
##### disconnect()
|
127
|
+
断开 WebSocket 连接
|
128
|
+
|
129
|
+
##### send(message)
|
130
|
+
发送消息
|
131
|
+
- `message`: 要发送的消息(字符串或对象)
|
132
|
+
|
133
|
+
##### reconnect(url, options)
|
134
|
+
手动重连
|
135
|
+
- `url`: WebSocket 连接地址
|
136
|
+
- `options`: 连接选项(可选)
|
137
|
+
|
138
|
+
##### on(event, callback)
|
139
|
+
添加事件监听器
|
140
|
+
- `event`: 事件名称
|
141
|
+
- `callback`: 回调函数
|
142
|
+
|
143
|
+
##### off(event, callback)
|
144
|
+
移除事件监听器
|
145
|
+
- `event`: 事件名称
|
146
|
+
- `callback`: 回调函数
|
147
|
+
|
148
|
+
##### getConnectionState()
|
149
|
+
获取连接状态
|
150
|
+
- 返回: `{ isConnected, reconnectAttempts, readyState }`
|
151
|
+
|
152
|
+
### 事件列表
|
153
|
+
|
154
|
+
| 事件名称 | 说明 | 数据 |
|
155
|
+
|----------|------|------|
|
156
|
+
| connecting | 正在连接 | `{ url }` |
|
157
|
+
| connected | 连接成功 | `{ event }` |
|
158
|
+
| message | 收到消息 | `{ data, event }` |
|
159
|
+
| closed | 连接关闭 | `{ event }` |
|
160
|
+
| error | 连接错误 | `{ event }` |
|
161
|
+
| reconnecting | 重连中 | `{ attempts }` |
|
162
|
+
| reconnect-failed | 重连失败 | `{ attempts }` |
|
163
|
+
| disconnected | 已断开连接 | `{}` |
|
164
|
+
|
165
|
+
## 使用示例
|
166
|
+
|
167
|
+
### 实时聊天应用
|
168
|
+
|
169
|
+
```javascript
|
170
|
+
import { useWebSocket } from '@vue2-client/utils/websocket/websocket'
|
171
|
+
|
172
|
+
export default {
|
173
|
+
setup() {
|
174
|
+
const { connect, send, on, off } = useWebSocket({
|
175
|
+
autoReconnect: true,
|
176
|
+
reconnectInterval: 2000,
|
177
|
+
maxReconnectAttempts: 10
|
178
|
+
})
|
179
|
+
|
180
|
+
const messages = ref([])
|
181
|
+
const isConnected = ref(false)
|
182
|
+
|
183
|
+
// 连接聊天服务器
|
184
|
+
connect('ws://localhost:8080/chat')
|
185
|
+
|
186
|
+
// 监听连接状态
|
187
|
+
on('connected', () => {
|
188
|
+
isConnected.value = true
|
189
|
+
})
|
190
|
+
|
191
|
+
on('disconnected', () => {
|
192
|
+
isConnected.value = false
|
193
|
+
})
|
194
|
+
|
195
|
+
// 监听消息
|
196
|
+
on('message', (data) => {
|
197
|
+
messages.value.push(data.data)
|
198
|
+
})
|
199
|
+
|
200
|
+
// 发送消息
|
201
|
+
const sendChatMessage = (message) => {
|
202
|
+
send({
|
203
|
+
type: 'chat',
|
204
|
+
message: message,
|
205
|
+
timestamp: Date.now()
|
206
|
+
})
|
207
|
+
}
|
208
|
+
|
209
|
+
return {
|
210
|
+
messages,
|
211
|
+
isConnected,
|
212
|
+
sendChatMessage
|
213
|
+
}
|
214
|
+
}
|
215
|
+
}
|
216
|
+
```
|
217
|
+
|
218
|
+
## 注意事项
|
219
|
+
|
220
|
+
1. **内存泄漏**: 组件销毁时记得调用 `disconnect()` 方法
|
221
|
+
2. **错误处理**: 建议监听 `error` 和 `reconnect-failed` 事件
|
222
|
+
3. **消息格式**: 支持字符串和 JSON 对象格式的消息
|
223
|
+
4. **重连策略**: 可以根据业务需求调整重连参数
|
224
|
+
5. **浏览器兼容性**: 需要现代浏览器支持 WebSocket API
|
@@ -0,0 +1,241 @@
|
|
1
|
+
/**
|
2
|
+
* WebSocket 工具类
|
3
|
+
* 提供通用的 WebSocket 连接管理功能
|
4
|
+
*/
|
5
|
+
export class WebSocketManager {
|
6
|
+
constructor (options = {}) {
|
7
|
+
this.options = {
|
8
|
+
autoReconnect: true,
|
9
|
+
reconnectInterval: 3000,
|
10
|
+
maxReconnectAttempts: 5,
|
11
|
+
...options
|
12
|
+
}
|
13
|
+
|
14
|
+
this.websocket = null
|
15
|
+
this.reconnectAttempts = 0
|
16
|
+
this.isConnected = false
|
17
|
+
this.reconnectTimer = null
|
18
|
+
this.listeners = new Map()
|
19
|
+
// 标记是否为手动断开,手动断开时不触发自动重连
|
20
|
+
this.manualClose = false
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* 连接 WebSocket
|
25
|
+
* @param {string} url WebSocket 连接地址
|
26
|
+
* @param {Object} options 连接选项
|
27
|
+
*/
|
28
|
+
connect (url, options = {}) {
|
29
|
+
const connectOptions = { ...this.options, ...options }
|
30
|
+
|
31
|
+
try {
|
32
|
+
// 重置手动断开标记
|
33
|
+
this.manualClose = false
|
34
|
+
this.websocket = new WebSocket(url)
|
35
|
+
|
36
|
+
this.websocket.onopen = (event) => this.handleOpen(event, connectOptions)
|
37
|
+
this.websocket.onmessage = (event) => this.handleMessage(event, connectOptions)
|
38
|
+
this.websocket.onclose = (event) => this.handleClose(event, connectOptions)
|
39
|
+
this.websocket.onerror = (event) => this.handleError(event, connectOptions)
|
40
|
+
|
41
|
+
this.emit('connecting', { url })
|
42
|
+
} catch (error) {
|
43
|
+
console.error('>>>> WebSocket连接失败:', error, url)
|
44
|
+
this.emit('error', { error })
|
45
|
+
if (connectOptions.autoReconnect) {
|
46
|
+
this.handleReconnect(url, connectOptions)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* 处理连接成功
|
53
|
+
*/
|
54
|
+
handleOpen (event, options) {
|
55
|
+
this.isConnected = true
|
56
|
+
this.reconnectAttempts = 0
|
57
|
+
this.emit('connected', { event })
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* 处理消息接收
|
62
|
+
*/
|
63
|
+
handleMessage (event, options) {
|
64
|
+
try {
|
65
|
+
const data = JSON.parse(event.data)
|
66
|
+
this.emit('message', { data, event })
|
67
|
+
} catch (error) {
|
68
|
+
// 如果不是JSON格式,直接处理原始数据
|
69
|
+
this.emit('message', { data: { message: event.data }, event })
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* 处理连接关闭
|
75
|
+
*/
|
76
|
+
handleClose (event, options) {
|
77
|
+
this.isConnected = false
|
78
|
+
this.emit('closed', { event })
|
79
|
+
|
80
|
+
// 手动断开时不进行重连
|
81
|
+
if (!this.manualClose && options.autoReconnect && this.reconnectAttempts < options.maxReconnectAttempts) {
|
82
|
+
this.handleReconnect(options.url, options)
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* 处理连接错误
|
88
|
+
*/
|
89
|
+
handleError (event, options) {
|
90
|
+
console.error('WebSocket连接错误:', event)
|
91
|
+
this.isConnected = false
|
92
|
+
this.emit('error', { event })
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
* 处理重连
|
97
|
+
*/
|
98
|
+
handleReconnect (url, options) {
|
99
|
+
if (this.reconnectAttempts >= options.maxReconnectAttempts) {
|
100
|
+
console.log('达到最大重连次数,停止重连')
|
101
|
+
this.emit('reconnect-failed', { attempts: this.reconnectAttempts })
|
102
|
+
return
|
103
|
+
}
|
104
|
+
|
105
|
+
this.reconnectAttempts++
|
106
|
+
|
107
|
+
this.reconnectTimer = setTimeout(() => {
|
108
|
+
console.log(`尝试重连 WebSocket (${this.reconnectAttempts}/${options.maxReconnectAttempts})`)
|
109
|
+
this.connect(url, options)
|
110
|
+
}, options.reconnectInterval)
|
111
|
+
|
112
|
+
this.emit('reconnecting', { attempts: this.reconnectAttempts })
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* 断开连接
|
117
|
+
*/
|
118
|
+
disconnect () {
|
119
|
+
// 设置手动关闭标记,阻止自动重连
|
120
|
+
this.manualClose = true
|
121
|
+
if (this.reconnectTimer) {
|
122
|
+
clearTimeout(this.reconnectTimer)
|
123
|
+
this.reconnectTimer = null
|
124
|
+
}
|
125
|
+
|
126
|
+
if (this.websocket) {
|
127
|
+
this.websocket.close()
|
128
|
+
this.websocket = null
|
129
|
+
}
|
130
|
+
|
131
|
+
this.isConnected = false
|
132
|
+
this.emit('disconnected')
|
133
|
+
}
|
134
|
+
|
135
|
+
/**
|
136
|
+
* 发送消息
|
137
|
+
* @param {string|Object} message 要发送的消息
|
138
|
+
*/
|
139
|
+
send (message) {
|
140
|
+
if (this.websocket && this.isConnected) {
|
141
|
+
const data = typeof message === 'string' ? message : JSON.stringify(message)
|
142
|
+
this.websocket.send(data)
|
143
|
+
return true
|
144
|
+
}
|
145
|
+
return false
|
146
|
+
}
|
147
|
+
|
148
|
+
/**
|
149
|
+
* 手动重连
|
150
|
+
*/
|
151
|
+
reconnect (url, options = {}) {
|
152
|
+
this.disconnect()
|
153
|
+
this.reconnectAttempts = 0
|
154
|
+
this.connect(url, options)
|
155
|
+
}
|
156
|
+
|
157
|
+
/**
|
158
|
+
* 添加事件监听器
|
159
|
+
* @param {string} event 事件名称
|
160
|
+
* @param {Function} callback 回调函数
|
161
|
+
*/
|
162
|
+
on (event, callback) {
|
163
|
+
if (!this.listeners.has(event)) {
|
164
|
+
this.listeners.set(event, [])
|
165
|
+
}
|
166
|
+
this.listeners.get(event).push(callback)
|
167
|
+
}
|
168
|
+
|
169
|
+
/**
|
170
|
+
* 移除事件监听器
|
171
|
+
* @param {string} event 事件名称
|
172
|
+
* @param {Function} callback 回调函数
|
173
|
+
*/
|
174
|
+
off (event, callback) {
|
175
|
+
if (this.listeners.has(event)) {
|
176
|
+
const callbacks = this.listeners.get(event)
|
177
|
+
const index = callbacks.indexOf(callback)
|
178
|
+
if (index > -1) {
|
179
|
+
callbacks.splice(index, 1)
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
/**
|
185
|
+
* 触发事件
|
186
|
+
* @param {string} event 事件名称
|
187
|
+
* @param {Object} data 事件数据
|
188
|
+
*/
|
189
|
+
emit (event, data) {
|
190
|
+
if (this.listeners.has(event)) {
|
191
|
+
this.listeners.get(event).forEach(callback => {
|
192
|
+
try {
|
193
|
+
callback(data)
|
194
|
+
} catch (error) {
|
195
|
+
console.error(`WebSocket事件监听器错误 (${event}):`, error)
|
196
|
+
}
|
197
|
+
})
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
/**
|
202
|
+
* 获取连接状态
|
203
|
+
*/
|
204
|
+
getConnectionState () {
|
205
|
+
return {
|
206
|
+
isConnected: this.isConnected,
|
207
|
+
reconnectAttempts: this.reconnectAttempts,
|
208
|
+
readyState: this.websocket ? this.websocket.readyState : WebSocket.CLOSED
|
209
|
+
}
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* Vue 2 组合式 API 风格的 WebSocket Hook
|
215
|
+
* @param {Object} options 配置选项
|
216
|
+
*/
|
217
|
+
export function useWebSocket (options = {}) {
|
218
|
+
const wsManager = new WebSocketManager(options)
|
219
|
+
|
220
|
+
return {
|
221
|
+
// 连接方法
|
222
|
+
connect: (url, connectOptions) => wsManager.connect(url, connectOptions),
|
223
|
+
disconnect: () => wsManager.disconnect(),
|
224
|
+
reconnect: (url, connectOptions) => wsManager.reconnect(url, connectOptions),
|
225
|
+
|
226
|
+
// 消息方法
|
227
|
+
send: (message) => wsManager.send(message),
|
228
|
+
|
229
|
+
// 事件监听
|
230
|
+
on: (event, callback) => wsManager.on(event, callback),
|
231
|
+
off: (event, callback) => wsManager.off(event, callback),
|
232
|
+
|
233
|
+
// 状态
|
234
|
+
getConnectionState: () => wsManager.getConnectionState(),
|
235
|
+
|
236
|
+
// 原始管理器实例(用于高级用法)
|
237
|
+
manager: wsManager
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
export default WebSocketManager
|
package/vue.config.js
CHANGED
@@ -42,6 +42,12 @@ module.exports = {
|
|
42
42
|
ws: false,
|
43
43
|
changeOrigin: true
|
44
44
|
},
|
45
|
+
'/socket/af-system': {
|
46
|
+
target: 'http://127.0.0.1:9002',
|
47
|
+
ws: true,
|
48
|
+
changeOrigin: true,
|
49
|
+
pathRewrite: { '^/socket/af-system': '/concept-websocket' },
|
50
|
+
},
|
45
51
|
'/revenue-web/api/af-revenue': {
|
46
52
|
pathRewrite: { '^/revenue-web/': '/' },
|
47
53
|
target: v3Server,
|