vue2-client 1.16.31 → 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.
@@ -211,7 +211,16 @@
211
211
  <ellipsis :length="item.slotValue" tooltip>{{ text === '' ? '--' : text }}</ellipsis>
212
212
  </span>
213
213
  <span v-else-if="item.slotType === 'progress'" :key="'progress-' + c_index">
214
- <a-progress :percent="text" status="active" style="padding-right: 20px;" />
214
+ <!-- websocket-id (配置名称-字段名称-用户id-页码-数据行id) -->
215
+ <x-web-socket-progress
216
+ v-if="item.webSocket"
217
+ :key="`${tableContext.requestParameters?.pageNo || 1}-${item.dataIndex}-${record[tableContext.rowKey] || index}`"
218
+ :websocket-id="`${queryParamsName}-${item.dataIndex}-${currUser.id}-${tableContext.requestParameters?.pageNo || 1}-${record[tableContext.rowKey] || index}`"
219
+ :initial-value="text || 0"
220
+ @progress-updated="(data) => handleProgressUpdated(data, record, item.dataIndex)"
221
+ />
222
+ <!-- 表格进度组件 -->
223
+ <a-progress v-else :percent="text" status="active" style="padding-right: 20px;" />
215
224
  </span>
216
225
  <span v-else-if="item.slotType === 'badge'" :key="'badge-' + c_index">
217
226
  <x-badge
@@ -277,7 +286,9 @@ import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormIte
277
286
  import CustomFuncCel from '@vue2-client/base-client/components/common/XTable/CustomFuncCel.vue'
278
287
  import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
279
288
  import XRate from '@vue2-client/base-client/components/common/XRate/index.vue'
289
+ import XWebSocketProgress from '@vue2-client/base-client/components/common/XWebSocketProgress'
280
290
  import VueDraggableResizable from 'vue-draggable-resizable'
291
+ import { mapState } from 'vuex'
281
292
 
282
293
  export default {
283
294
  name: 'XTableWrapper',
@@ -288,6 +299,7 @@ export default {
288
299
  XFormItem,
289
300
  XRate,
290
301
  CustomFuncCel,
302
+ XWebSocketProgress,
291
303
  VueDraggableResizable
292
304
  },
293
305
  data () {
@@ -298,6 +310,7 @@ export default {
298
310
  }
299
311
  },
300
312
  computed: {
313
+ ...mapState('account', { currUser: 'user' }),
301
314
  localDataSource () {
302
315
  return this.activeTable?.localDataSource
303
316
  },
@@ -426,6 +439,13 @@ export default {
426
439
  }
427
440
  },
428
441
  props: {
442
+ // 查询配置文件名
443
+ queryParamsName: {
444
+ type: String,
445
+ default: () => {
446
+ return ''
447
+ }
448
+ },
429
449
  loadSelectedData: {
430
450
  type: Boolean,
431
451
  required: false,
@@ -547,7 +567,20 @@ export default {
547
567
  },
548
568
  handleResizeColumn (w, col) {
549
569
  col.width = w
550
- }
570
+ },
571
+
572
+ /**
573
+ * 处理进度更新事件
574
+ * @param {Object} data 进度数据
575
+ * @param {Object} record 行数据
576
+ * @param {String} dataIndex 列字段名
577
+ */
578
+ handleProgressUpdated (data, record, dataIndex) {
579
+ // 更新行数据中的进度值
580
+ if (record && dataIndex) {
581
+ this.$set(record, dataIndex, data.value)
582
+ }
583
+ },
551
584
  }
552
585
  }
553
586
  </script>
@@ -0,0 +1,14 @@
1
+ 发生sendMessage请求
2
+ ```json
3
+ {
4
+ "event": "16", // 进度数据, 取值 0~100
5
+ "userList": [
6
+ "ceshiCRUD-t_f_operator_id-419879409793761282-1-18",// 数据webSocket 唯一标识 (配置名称-字段名称-用户id-页码-数据行id)
7
+ "ceshiCRUD-t_f_type-419879409793761282-1-18",
8
+ "ceshiCRUD-t_f_type-419879409793761282-1-19",
9
+ "ceshiCRUD-t_f_type-419879409793761282-1-20",
10
+ "ceshiCRUD-t_f_operator_id-419879409793761282-1-21",
11
+ "ceshiCRUD-t_f_operator_id-419879409793761282-1-22"
12
+ ]
13
+ }
14
+ ```
@@ -0,0 +1,252 @@
1
+ <template>
2
+ <div class="websocket-progress">
3
+ <a-progress
4
+ :percent="progressValue"
5
+ status="active"
6
+ style="padding-right: 20px;" />
7
+
8
+ <!-- 连接状态指示 -->
9
+ <div class="connection-status">
10
+ <a-tooltip :title="connectionStatusText">
11
+ <a-badge
12
+ :status="connectionBadgeStatus"
13
+ :text="connectionStatusText"
14
+ />
15
+ </a-tooltip>
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ import { useWebSocket } from '@vue2-client/utils/websocket/websocket'
22
+
23
+ export default {
24
+ name: 'XWebSocketProgress',
25
+ components: {
26
+ },
27
+ props: {
28
+ // WebSocket 唯一标识
29
+ websocketId: {
30
+ type: String,
31
+ required: true,
32
+ },
33
+ // 初始进度值
34
+ initialValue: {
35
+ type: Number,
36
+ default: 0
37
+ },
38
+ // 自动重连
39
+ autoReconnect: {
40
+ type: Boolean,
41
+ default: true
42
+ },
43
+ // 重连间隔(毫秒)
44
+ reconnectInterval: {
45
+ type: Number,
46
+ default: 3000
47
+ },
48
+ // 最大重连次数
49
+ maxReconnectAttempts: {
50
+ type: Number,
51
+ default: 1
52
+ },
53
+ },
54
+ data () {
55
+ return {
56
+ progressValue: this.initialValue,
57
+ connectionState: {
58
+ isConnected: false,
59
+ reconnectAttempts: 0
60
+ },
61
+ websocketUrl: '',
62
+ }
63
+ },
64
+ computed: {
65
+ // 连接状态文本
66
+ connectionStatusText () {
67
+ if (this.connectionState.isConnected) {
68
+ return '已连接'
69
+ } else if (this.connectionState.reconnectAttempts > 0) {
70
+ return `重连中 (${this.connectionState.reconnectAttempts})`
71
+ } else {
72
+ return '未连接'
73
+ }
74
+ },
75
+
76
+ // 连接状态徽章状态
77
+ connectionBadgeStatus () {
78
+ if (this.connectionState.isConnected) {
79
+ return 'success'
80
+ } else if (this.connectionState.reconnectAttempts > 0) {
81
+ return 'processing'
82
+ } else {
83
+ return 'default'
84
+ }
85
+ }
86
+ },
87
+ mounted () {
88
+ this.initWebSocket()
89
+ },
90
+ beforeDestroy () {
91
+ this.cleanup()
92
+ },
93
+ watch: {
94
+ // 初始值变更时重置当前进度显示
95
+ initialValue (val) {
96
+ const num = parseFloat(val)
97
+ this.progressValue = isNaN(num) ? 0 : Math.max(0, Math.min(100, num))
98
+ },
99
+ // 标识变更时,断开旧连接并按新标识重连
100
+ websocketId (newId, oldId) {
101
+ if (newId === oldId) return
102
+ this.cleanup()
103
+ // 重置进度为新的初始值,确保界面先渲染初始值
104
+ const num = parseFloat(this.initialValue)
105
+ this.progressValue = isNaN(num) ? 0 : Math.max(0, Math.min(100, num))
106
+ // 重新建立连接
107
+ this.$nextTick(() => {
108
+ this.initWebSocket()
109
+ })
110
+ }
111
+ },
112
+ methods: {
113
+ /**
114
+ * 初始化 WebSocket
115
+ */
116
+ initWebSocket () {
117
+ if (!this.websocketId) {
118
+ return
119
+ }
120
+
121
+ this.websocketUrl = `ws:${window.location.host}/socket/af-system/sendMessage?userId=${this.websocketId}`
122
+
123
+ const wsOptions = {
124
+ autoReconnect: this.autoReconnect,
125
+ reconnectInterval: this.reconnectInterval,
126
+ maxReconnectAttempts: this.maxReconnectAttempts
127
+ }
128
+
129
+ // 使用 WebSocket 工具
130
+ const wsManager = useWebSocket(wsOptions)
131
+
132
+ // 保存方法引用
133
+ this.wsConnect = wsManager.connect
134
+ this.wsDisconnect = wsManager.disconnect
135
+ this.wsOn = wsManager.on
136
+ // 绑定事件监听器
137
+ this.setupEventListeners()
138
+
139
+ // 开始连接
140
+ this.wsConnect(this.websocketUrl, wsOptions)
141
+ },
142
+ /**
143
+ * 手动重置为初始值(供父组件可选调用)
144
+ */
145
+ resetToInitial () {
146
+ const num = parseFloat(this.initialValue)
147
+ this.progressValue = isNaN(num) ? 0 : Math.max(0, Math.min(100, num))
148
+ },
149
+
150
+ /**
151
+ * 设置事件监听器
152
+ */
153
+ setupEventListeners () {
154
+ // 连接成功
155
+ this.wsOn('connected', (data) => {
156
+ this.connectionState.isConnected = true
157
+ this.connectionState.reconnectAttempts = 0
158
+ this.$emit('websocket-connected', data)
159
+ })
160
+
161
+ // 连接中
162
+ this.wsOn('connecting', (data) => {
163
+ this.$emit('websocket-connecting', data)
164
+ })
165
+
166
+ // 消息接收
167
+ this.wsOn('message', (data) => {
168
+ this.handleWebSocketMessage(data)
169
+ this.$emit('websocket-message', data)
170
+ })
171
+
172
+ // 连接关闭
173
+ this.wsOn('closed', (data) => {
174
+ this.connectionState.isConnected = false
175
+ this.$emit('websocket-closed', data)
176
+ })
177
+
178
+ // 连接错误
179
+ this.wsOn('error', (data) => {
180
+ this.connectionState.isConnected = false
181
+ this.$emit('websocket-error', data)
182
+ })
183
+
184
+ // 重连中
185
+ this.wsOn('reconnecting', (data) => {
186
+ this.connectionState.reconnectAttempts = data.attempts
187
+ this.$emit('websocket-reconnecting', data)
188
+ })
189
+
190
+ // 重连失败
191
+ this.wsOn('reconnect-failed', (data) => {
192
+ this.connectionState.reconnectAttempts = data.attempts
193
+ this.$emit('websocket-reconnect-failed', data)
194
+ })
195
+
196
+ // 断开连接
197
+ this.wsOn('disconnected', (data) => {
198
+ this.connectionState.isConnected = false
199
+ this.connectionState.reconnectAttempts = 0
200
+ this.$emit('websocket-disconnected', data)
201
+ })
202
+ },
203
+
204
+ /**
205
+ * 处理 WebSocket 消息
206
+ * @param {Object} data 消息数据
207
+ */
208
+ handleWebSocketMessage (data) {
209
+ const messageData = data.data
210
+
211
+ // 更新进度值
212
+ this.updateProgress(parseFloat(messageData))
213
+ },
214
+
215
+ /**
216
+ * 更新进度值
217
+ * @param {number} value 进度值
218
+ */
219
+ updateProgress (value) {
220
+ const numValue = parseFloat(value)
221
+ if (!isNaN(numValue)) {
222
+ this.progressValue = Math.max(0, Math.min(100, numValue))
223
+ this.$emit('progress-updated', {
224
+ value: this.progressValue,
225
+ originalValue: value
226
+ })
227
+ }
228
+ },
229
+
230
+ /**
231
+ * 清理资源
232
+ */
233
+ cleanup () {
234
+ if (this.wsDisconnect) {
235
+ this.wsDisconnect()
236
+ }
237
+ }
238
+ }
239
+ }
240
+ </script>
241
+
242
+ <style scoped lang="less">
243
+ .websocket-progress {
244
+ display: flex;
245
+ align-items: center;
246
+ gap: 8px;
247
+
248
+ .connection-status {
249
+ flex-shrink: 0;
250
+ }
251
+ }
252
+ </style>
@@ -19,6 +19,7 @@
19
19
  <!-- </template>-->
20
20
  </template>
21
21
  <a-radio-group
22
+ class="custom-radio-group"
22
23
  v-show="showModeChoose"
23
24
  button-style="solid"
24
25
  @change="changeMode"
@@ -29,7 +30,7 @@
29
30
  </a-radio-group>
30
31
  </a-space>
31
32
  </a-col>
32
- <a-col class="editor-action">
33
+ <a-col class="editor-action-button">
33
34
  <a-space>
34
35
  <template v-if="this.modeType !== 'readonly'">
35
36
  <!-- <a-button-->
@@ -649,6 +650,11 @@ export default {
649
650
  .editor-action-container {
650
651
  height: 40px;
651
652
  }
653
+ .editor-action-button {
654
+ .ant-btn-primary {
655
+ background-color: rgb(0, 87, 254) !important;
656
+ }
657
+ }
652
658
  :deep(.ant-divider-horizontal) {
653
659
  margin: 4px 0;
654
660
  }
@@ -691,4 +697,9 @@ export default {
691
697
  font-size: 12px;
692
698
  margin: 0 !important;
693
699
  }
700
+ .custom-radio-group {
701
+ .ant-radio-button-wrapper-checked {
702
+ background-color: rgb(0, 87, 254) !important;
703
+ }
704
+ }
694
705
  </style>
@@ -87,6 +87,8 @@ const onIframeLoad = (e) => {
87
87
  console.error('无法访问 iframe 内容')
88
88
  return
89
89
  }
90
+ // 关闭文书工具栏
91
+ iframe.contentWindow.editor.option.toolbar = false
90
92
  startEditorCheck(frameWindow, iframe)
91
93
  }
92
94
  // 组件销毁前清理
@@ -1,47 +1,47 @@
1
- import AMapLoader from '@amap/amap-jsapi-loader'
2
- let Amap
3
- async function GetGDMap (secretKey, key) {
4
- if (!Amap) {
5
- window._AMapSecurityConfig = {
6
- securityJsCode: secretKey
7
- }
8
- // 解决高德地图加载报错 ---> 禁止多种API加载方式混用
9
- AMapLoader.reset()
10
- Amap = await AMapLoader.load({
11
- key: key, // 申请好的Web端开发者Key,首次调用 load 时必填
12
- version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
13
- plugins: ['AMap.IndexCluster', 'AMP.MarkerCluster', 'AMap.InfoWindow', 'AMap.HeatMap', 'AMap.HawkEye', 'AMap.DistrictSearch',
14
- 'AMap.ToolBar', 'AMap.Geolocation', 'AMap.MouseTool',
15
- 'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.AutoComplete', 'AMap.Scale'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
16
- AMapUI: {
17
- version: '1.1', // AMapUI 缺省 1.1
18
- plugins: ['misc/PositionPicker'] // 需要加载的 AMapUI ui插件
19
- }
20
- })
21
- }
22
- return Amap
23
- }
24
-
25
- async function getGDMap (address) {
26
- new (await GetGDMap()).Geocoder({
27
- radius: 500 // 范围,默认:500
28
- }).getLocation(address, function (status, result) {
29
- if (status === 'complete' && result.geocodes.length) {
30
- return ({ lng: result.geocodes[0].location.lng, lat: result.geocodes[0].location.lat })
31
- } else {
32
- // eslint-disable-next-line prefer-promise-reject-errors
33
- throw new Error('根据经纬度查询地址失败')
34
- }
35
- })
36
- }
37
-
38
- async function GetLocation (address) {
39
- return new Promise((resolve, reject) => {
40
- try {
41
- resolve(getGDMap(address))
42
- } catch (e) {
43
- reject(e)
44
- }
45
- })
46
- }
47
- export { GetGDMap, GetLocation }
1
+ import AMapLoader from '@amap/amap-jsapi-loader'
2
+ let Amap
3
+ async function GetGDMap (secretKey, key) {
4
+ if (!Amap) {
5
+ window._AMapSecurityConfig = {
6
+ securityJsCode: secretKey
7
+ }
8
+ // 解决高德地图加载报错 ---> 禁止多种API加载方式混用
9
+ AMapLoader.reset()
10
+ Amap = await AMapLoader.load({
11
+ key: key, // 申请好的Web端开发者Key,首次调用 load 时必填
12
+ version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
13
+ plugins: ['AMap.IndexCluster', 'AMP.MarkerCluster', 'AMap.InfoWindow', 'AMap.HeatMap', 'AMap.HawkEye', 'AMap.DistrictSearch',
14
+ 'AMap.ToolBar', 'AMap.Geolocation', 'AMap.MouseTool',
15
+ 'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.AutoComplete', 'AMap.Scale'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
16
+ AMapUI: {
17
+ version: '1.1', // AMapUI 缺省 1.1
18
+ plugins: ['misc/PositionPicker'] // 需要加载的 AMapUI ui插件
19
+ }
20
+ })
21
+ }
22
+ return Amap
23
+ }
24
+
25
+ async function getGDMap (address) {
26
+ new (await GetGDMap()).Geocoder({
27
+ radius: 500 // 范围,默认:500
28
+ }).getLocation(address, function (status, result) {
29
+ if (status === 'complete' && result.geocodes.length) {
30
+ return ({ lng: result.geocodes[0].location.lng, lat: result.geocodes[0].location.lat })
31
+ } else {
32
+ // eslint-disable-next-line prefer-promise-reject-errors
33
+ throw new Error('根据经纬度查询地址失败')
34
+ }
35
+ })
36
+ }
37
+
38
+ async function GetLocation (address) {
39
+ return new Promise((resolve, reject) => {
40
+ try {
41
+ resolve(getGDMap(address))
42
+ } catch (e) {
43
+ reject(e)
44
+ }
45
+ })
46
+ }
47
+ export { GetGDMap, GetLocation }