vue2-client 1.15.127 → 1.15.129

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.
@@ -0,0 +1,14 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "WebSearch",
5
+ "WebFetch(domain:context7.com)",
6
+ "Bash(npm run lint)",
7
+ "mcp__context7__resolve-library-id",
8
+ "mcp__context7__get-library-docs"
9
+ ],
10
+ "deny": [],
11
+ "ask": [],
12
+ "defaultMode": "acceptEdits"
13
+ }
14
+ }
package/.env.revenue CHANGED
@@ -1,4 +1,4 @@
1
- VUE_APP_PUBLIC_PATH=/
1
+ VUE_APP_PUBLIC_PATH=/revenue-web
2
2
  VUE_APP_NAME=Admin
3
3
  VUE_APP_ROUTES_KEY=admin.routes
4
4
  VUE_APP_PERMISSIONS_KEY=admin.permissions
@@ -16,4 +16,4 @@ VUE_APP_WEB_CONFIG_KEY=admin.webconfig
16
16
  VUE_APP_API_BASE_URL=http://123.60.214.109:8405
17
17
  VUE_APP_SYSTEM_NAME=af-revenue
18
18
  VUE_APP_LOGIN_VERSION=V4
19
-
19
+ VUE_APP_SINGLE_PAPER=TRUE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-client",
3
- "version": "1.15.127",
3
+ "version": "1.15.129",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
package/public/index.html CHANGED
@@ -15,7 +15,7 @@
15
15
  <noscript>
16
16
  <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
17
17
  </noscript>
18
- <div id="popContainer" class="beauty-scroll" style="height: 100%; overflow-y: auto">
18
+ <div id="popContainer" class="beauty-scroll">
19
19
  <div id="app"></div>
20
20
  </div>
21
21
  <!-- require cdn assets js -->
@@ -1,14 +1,108 @@
1
1
  <script setup lang="ts">
2
2
  import XButtons from '@vue2-client/base-client/components/common/XButtons/XButtons.vue'
3
+ import { ref, onMounted, onUpdated, getCurrentInstance, watch, nextTick } from 'vue'
3
4
 
4
- // 只定义HButtons特有的属性
5
5
  defineProps({
6
- // HButtons特有的属性
7
6
  buttonStyle: {
8
7
  type: String,
9
- default: 'button24' // 可选值: button24, right-button, button24-top-0, button24-top10, button21, button20, button23, table-height-button23, button22, out-button, button-watermark-icon, button, default, button1, button4, button25, button14, button13, button5, button2, button16, button3, button15, button8, 0padding-button, button10, button9, button6, button31, button12, button7, center, button11, button18, button17, button19, left53px, charges-button, button30
8
+ default: 'button24'
10
9
  }
11
10
  })
11
+
12
+ const xButtonsRef = ref(null)
13
+ const instance = getCurrentInstance()
14
+
15
+ // 防抖控制
16
+ let syncTimeout = null
17
+ function debounceSync (callback, delay = 100) {
18
+ if (syncTimeout) clearTimeout(syncTimeout)
19
+ syncTimeout = setTimeout(callback, delay)
20
+ }
21
+
22
+ // 方法缓存,避免重复挂载
23
+ const syncedMethods = new WeakMap()
24
+
25
+ function syncChildRefs () {
26
+ if (!instance || !instance.proxy || !xButtonsRef.value) return
27
+ const proxy = instance.proxy
28
+ const target = proxy.$refs
29
+ const childRefs = xButtonsRef.value.$refs
30
+ if (!childRefs) return
31
+
32
+ Object.entries(childRefs).forEach(([key, value]) => {
33
+ const v = Array.isArray(value) ? value[0] : value
34
+ if (target[key] !== v) target[key] = v
35
+ })
36
+ if (target.xButtonsRef !== xButtonsRef.value) target.xButtonsRef = xButtonsRef.value
37
+ }
38
+
39
+ function getAllFunctionNames (obj) {
40
+ if (!obj) return []
41
+ const names = new Set()
42
+ let current = obj
43
+ while (current && current !== Object.prototype) {
44
+ Object.getOwnPropertyNames(current).forEach(name => {
45
+ if (typeof obj[name] === 'function' && name !== 'constructor') names.add(name)
46
+ })
47
+ current = Object.getPrototypeOf(current)
48
+ }
49
+ return Array.from(names)
50
+ }
51
+
52
+ function syncChildMethods () {
53
+ if (!instance || !instance.proxy || !xButtonsRef.value) return
54
+ const proxy = instance.proxy
55
+ const inner = xButtonsRef.value
56
+ const cached = syncedMethods.get(inner) || new Set()
57
+
58
+ getAllFunctionNames(inner).forEach(name => {
59
+ if (cached.has(name) || proxy[name]) return
60
+ proxy[name] = function () {
61
+ if (xButtonsRef.value && typeof xButtonsRef.value[name] === 'function') {
62
+ return xButtonsRef.value[name].apply(xButtonsRef.value, arguments)
63
+ }
64
+ }
65
+ cached.add(name)
66
+ })
67
+ syncedMethods.set(inner, cached)
68
+ }
69
+
70
+ function syncAll () {
71
+ syncChildRefs()
72
+ syncChildMethods()
73
+ }
74
+
75
+ // 子组件生命周期事件回调,确保及时同步
76
+ function onInnerMounted () { nextTick(function () { debounceSync(syncAll) }) }
77
+ function onInnerUpdated () { nextTick(function () { debounceSync(syncChildRefs) }) }
78
+
79
+ // 生命周期与监听
80
+ onMounted(() => nextTick(() => debounceSync(syncAll)))
81
+ onUpdated(() => nextTick(() => debounceSync(syncAll)))
82
+
83
+ watch(() => xButtonsRef.value && xButtonsRef.value.$refs, () => nextTick(() => debounceSync(syncChildRefs)), { deep: true, flush: 'post' })
84
+ watch(() => xButtonsRef.value, () => nextTick(() => debounceSync(syncChildMethods)), { flush: 'post' })
85
+
86
+ // 常用方法显式代理(API更清晰)
87
+ function createMethodProxy (methodName) {
88
+ return function () {
89
+ const inst = xButtonsRef.value
90
+ if (inst && typeof inst[methodName] === 'function') return inst[methodName].apply(inst, arguments)
91
+ }
92
+ }
93
+
94
+ const COMMON_METHODS = [
95
+ 'clickByKey', 'setButtons', 'disableButton', 'enableButton'
96
+ ]
97
+
98
+ defineExpose({
99
+ getXButtonsInstance: () => xButtonsRef.value,
100
+ // 显式常用方法
101
+ ...COMMON_METHODS.reduce((acc, m) => {
102
+ acc[m] = createMethodProxy(m)
103
+ return acc
104
+ }, {})
105
+ })
12
106
  </script>
13
107
 
14
108
  <template>
@@ -19,8 +113,11 @@ defineProps({
19
113
  ]"
20
114
  >
21
115
  <x-buttons
116
+ ref="xButtonsRef"
22
117
  v-bind="$attrs"
23
118
  v-on="$listeners"
119
+ @hook:mounted="onInnerMounted"
120
+ @hook:updated="onInnerUpdated"
24
121
  >
25
122
  <template v-for="(_, name) in $slots" #[name]="slotData">
26
123
  <slot :name="name" v-bind="slotData" />
@@ -30,720 +127,5 @@ defineProps({
30
127
  </template>
31
128
 
32
129
  <style scoped lang="less">
33
- .h-buttons-wrapper {
34
- // 基础样式
35
- :deep(.ant-btn-group) {
36
- .ant-btn {
37
- border-radius: 6px;
38
- background-color: #FFFFFF;
39
- border: 1px solid #9499A0;
40
- color: #313131;
41
- font-weight: normal;
42
- letter-spacing: 0em;
43
- width: 110px;
44
- font-size: 16px;
45
- font-family: "Source Han Sans";
46
- line-height: normal;
47
- margin-right: 25px;
48
- height: 32px;
49
- }
50
- }
51
-
52
- // button24样式
53
- &.h-buttons-button24 {
54
- :deep(.ant-btn-group) {
55
- .ant-btn {
56
- border: 1px solid #CDCDCD;
57
- color: #5D5C5C;
58
- font-weight: normal;
59
- letter-spacing: 0em;
60
- font-size: 16px;
61
- line-height: normal;
62
- margin-right: 25px;
63
- border-radius: 6px;
64
- background-color: #FFFFFF;
65
- // 这个不合理
66
- // top: -100px;
67
- width: fit-content;
68
- min-width: 110px;
69
- font-family: "Source Han Sans";
70
- height: 32px;
71
- }
72
- }
73
- }
74
-
75
- // right-button样式
76
- &.h-buttons-right-button {
77
- :deep(.ant-btn-group) {
78
- margin-top: -24px;
79
- right: 121px;
80
- position: sticky;
81
- float: right;
82
- z-index: 100;
83
- }
84
- }
85
-
86
- // button24-top-0样式
87
- &.h-buttons-button24-top-0 {
88
- :deep(.ant-btn-group) {
89
- .ant-btn {
90
- border: 1px solid #CDCDCD;
91
- color: #5D5C5C;
92
- font-weight: normal;
93
- letter-spacing: 0em;
94
- font-size: 16px;
95
- line-height: normal;
96
- margin-right: 25px;
97
- border-radius: 6px;
98
- background-color: #FFFFFF;
99
- width: fit-content;
100
- min-width: 110px;
101
- font-family: "Source Han Sans";
102
- height: 32px;
103
- }
104
- }
105
- }
106
-
107
- // button24-top10样式
108
- &.h-buttons-button24-top10 {
109
- :deep(.ant-btn-group) {
110
- .ant-btn {
111
- top: 10px;
112
- }
113
- }
114
- }
115
-
116
- // button21样式
117
- &.h-buttons-button21 {
118
- :deep(.ant-btn-group) {
119
- top: -88px;
120
- display: flex;
121
- .ant-btn {
122
- border-radius: 6px;
123
- background-color: #FFFFFF;
124
- border: 1px solid #9499A0;
125
- color: #313131;
126
- font-weight: normal;
127
- letter-spacing: 0em;
128
- width: 110px;
129
- font-size: 16px;
130
- font-family: "Source Han Sans";
131
- line-height: normal;
132
- margin-right: 25px;
133
- height: 32px;
134
- }
135
- width: 200px;
136
- }
137
- }
138
-
139
- // button20样式
140
- &.h-buttons-button20 {
141
- :deep(.ant-btn-group) {
142
- .ant-btn {
143
- border-radius: 6px;
144
- background-color: #1890FF;
145
- border: none;
146
- color: #FFFFFF;
147
- font-weight: normal;
148
- letter-spacing: 0em;
149
- width: 150px;
150
- font-size: 16px;
151
- font-family: "Source Han Sans";
152
- line-height: normal;
153
- margin-right: 25px;
154
- height: 32px;
155
- }
156
- height: 52px;
157
- }
158
- }
159
-
160
- // button23样式
161
- &.h-buttons-button23 {
162
- :deep(.ant-btn-group) {
163
- .ant-btn {
164
- border: none;
165
- padding: 0 !important;
166
- color: #FFFFFF;
167
- font-weight: normal;
168
- letter-spacing: 0em;
169
- font-size: 16px;
170
- line-height: normal;
171
- border-radius: 50%;
172
- background-color: #1890FF;
173
- margin-left: 10px;
174
- top: -88px;
175
- width: 30px;
176
- font-family: "Source Han Sans";
177
- height: 30px;
178
- }
179
- }
180
- }
181
-
182
- // table-height-button23样式
183
- &.h-buttons-table-height-button23 {
184
- :deep(.ant-btn-group) {
185
- .ant-btn {
186
- border: none;
187
- padding: 0 !important;
188
- color: #FFFFFF;
189
- font-weight: normal;
190
- letter-spacing: 0em;
191
- font-size: 16px;
192
- line-height: normal;
193
- border-radius: 50%;
194
- background-color: #1890FF;
195
- margin-left: 10px;
196
- top: -64px;
197
- width: 30px;
198
- font-family: "Source Han Sans";
199
- height: 30px;
200
- }
201
- }
202
- }
203
-
204
- // button22样式
205
- &.h-buttons-button22 {
206
- :deep(.x-buttons) {
207
- margin: -20px 6px -20px 6px;
208
- .ant-btn-group {
209
- .ant-btn {
210
- border-radius: 6px;
211
- display: inline-block;
212
- }
213
- width: 100%;
214
- }
215
- }
216
- }
217
-
218
- // out-button样式
219
- &.h-buttons-out-button {
220
- :deep(.x-buttons) {
221
- .ant-btn-group {
222
- .ant-btn {
223
- border: 1px solid #9499A0;
224
- color: #313131;
225
- font-weight: normal;
226
- letter-spacing: 0em;
227
- font-size: 16px;
228
- line-height: normal;
229
- box-sizing: border-box;
230
- margin-right: 6px;
231
- border-radius: 6px;
232
- background-color: #FFFFFF;
233
- left: 12px;
234
- width: 110px;
235
- font-family: "Source Han Sans";
236
- height: 32px;
237
- }
238
- }
239
- margin-top: -35px;
240
- }
241
- }
242
-
243
- // button-watermark-icon样式
244
- &.h-buttons-button-watermark-icon {
245
- :deep(.watermark-icon) {
246
- top: 37%;
247
- }
248
- :deep(.x-button) {
249
- display: flex !important;
250
- }
251
- :deep(.ant-btn-group) {
252
- margin: 0 auto;
253
- display: block;
254
- }
255
- }
256
-
257
- // button样式
258
- &.h-buttons-button {
259
- :deep(.ant-btn-group) {
260
- .ant-btn {
261
- border-radius: 6px;
262
- background-color: #FFFFFF;
263
- border: 1px solid #9499A0;
264
- color: #313131;
265
- font-weight: normal;
266
- letter-spacing: 0em;
267
- width: 110px;
268
- font-size: 16px;
269
- font-family: "Source Han Sans";
270
- line-height: normal;
271
- margin-right: 25px;
272
- height: 32px;
273
- }
274
- }
275
- }
276
-
277
- // button1样式
278
- &.h-buttons-button1 {
279
- :deep(.ant-btn-primary) {
280
- background-color: rgb(93, 92, 92);
281
- }
282
- width: 130px;
283
- }
284
-
285
- // button4样式
286
- &.h-buttons-button4 {
287
- :deep(.x-buttons) {
288
- margin: -20px 3px -20px 3px;
289
- .ant-btn-group {
290
- .ant-btn {
291
- border-radius: 6px;
292
- border: 1px solid #9499A0;
293
- font-size: 16px;
294
- height: 32px;
295
- background-color: #FFFFFF;
296
- color: #313131;
297
- }
298
- width: 70%;
299
- justify-content: space-between;
300
- }
301
- }
302
- }
303
-
304
- // button25样式
305
- &.h-buttons-button25 {
306
- :deep(.x-buttons) {
307
- margin: -20px 3px -20px 3px;
308
- .ant-btn-group {
309
- .ant-btn {
310
- border-radius: 6px;
311
- border: 1px solid #9499A0;
312
- font-size: 16px;
313
- height: 32px;
314
- background-color: #FFFFFF;
315
- color: #313131;
316
- width: 173px;
317
- }
318
- width: 173px;
319
- justify-content: space-between;
320
- }
321
- }
322
- }
323
-
324
- // button14样式
325
- &.h-buttons-button14 {
326
- :deep(.x-buttons) {
327
- .ant-btn-group {
328
- display: flex;
329
- gap: 6px;
330
- .ant-btn {
331
- border: 1px solid #9499A0;
332
- color: #313131;
333
- font-weight: normal;
334
- letter-spacing: 0em;
335
- font-size: 16px;
336
- line-height: normal;
337
- box-sizing: border-box;
338
- border-radius: 6px;
339
- background-color: #FFFFFF;
340
- left: 12px;
341
- width: 110px;
342
- font-family: "Source Han Sans";
343
- height: 32px;
344
- }
345
- }
346
- margin-top: -22px;
347
- }
348
- }
349
-
350
- // button13样式
351
- &.h-buttons-button13 {
352
- :deep(.ant-btn-group) {
353
- top: -90px;
354
- }
355
- }
356
-
357
- // button5样式
358
- &.h-buttons-button5 {
359
- :deep(.ant-btn-group) {
360
- .ant-btn {
361
- border-radius: 6px;
362
- background-color: #1890FF;
363
- border: none;
364
- color: #FFFFFF;
365
- font-weight: normal;
366
- letter-spacing: 0em;
367
- width: 110px;
368
- font-size: 16px;
369
- font-family: "Source Han Sans";
370
- line-height: normal;
371
- margin-right: 25px;
372
- height: 32px;
373
- }
374
- height: 52px;
375
- }
376
- }
377
-
378
- // button2样式
379
- &.h-buttons-button2 {
380
- :deep(.x-buttons) {
381
- margin: -20px 6px -20px 6px;
382
- color: #FFFFFF;
383
- .ant-btn-group {
384
- .ant-btn {
385
- border-radius: 6px;
386
- border: none;
387
- width: 46%;
388
- font-size: 16px;
389
- height: 32px;
390
- }
391
- width: 100%;
392
- justify-content: space-between;
393
- }
394
- }
395
- }
396
-
397
- // button16样式
398
- &.h-buttons-button16 {
399
- :deep(.ant-btn-group) {
400
- display: flex;
401
- gap: 6px;
402
- .ant-btn {
403
- border-radius: 6px;
404
- border: none;
405
- font-weight: normal;
406
- letter-spacing: 0em;
407
- width: 110px;
408
- font-size: 16px;
409
- font-family: "Source Han Sans";
410
- line-height: normal;
411
- height: 32px;
412
- }
413
- margin-top: -60px;
414
- }
415
- }
416
-
417
- // button3样式
418
- &.h-buttons-button3 {
419
- :deep(.x-buttons) {
420
- margin: -20px 6px -20px 6px;
421
- .ant-btn-group {
422
- padding: 0 170px;
423
- .ant-btn {
424
- border-radius: 6px;
425
- display: inline-block;
426
- }
427
- width: 100%;
428
- justify-content: space-between;
429
- }
430
- }
431
- }
432
-
433
- // button15样式
434
- &.h-buttons-button15 {
435
- :deep(.x-buttons) {
436
- .ant-btn-group {
437
- flex-direction: column;
438
- display: flex;
439
- gap: 6px;
440
- .ant-btn {
441
- border: none;
442
- color: #FFFFFF;
443
- font-weight: normal;
444
- letter-spacing: 0em;
445
- font-size: 16px;
446
- line-height: normal;
447
- box-sizing: border-box;
448
- border-radius: 6px;
449
- background-color: #5D5C5C;
450
- left: 12px;
451
- width: 280px;
452
- font-family: "Source Han Sans";
453
- height: 32px;
454
- }
455
- }
456
- margin-top: -22px;
457
- }
458
- }
459
-
460
- // button8样式
461
- &.h-buttons-button8 {
462
- :deep(.ant-btn-group) {
463
- top: -8px;
464
- }
465
- }
466
-
467
- // 0padding-button样式
468
- &.h-buttons-0padding-button {
469
- padding: 0px 4px;
470
- }
471
-
472
- // button10样式
473
- &.h-buttons-button10 {
474
- :deep(.ant-btn-group) {
475
- display: flex;
476
- gap: 8px;
477
- .ant-btn {
478
- border-radius: 6px;
479
- border: none;
480
- color: #FFFFFF;
481
- font-weight: normal;
482
- letter-spacing: 0em;
483
- width: 173px;
484
- font-size: 16px;
485
- font-family: "Source Han Sans";
486
- line-height: normal;
487
- height: 32px;
488
- }
489
- justify-content: flex-end;
490
- }
491
- }
492
-
493
- // button9样式
494
- &.h-buttons-button9 {
495
- :deep(.ant-btn-group) {
496
- top: -28px;
497
- display: flex;
498
- .ant-btn {
499
- border-radius: 6px;
500
- background-color: #1890FF;
501
- border: none;
502
- color: #FFFFFF;
503
- font-weight: normal;
504
- letter-spacing: 0em;
505
- width: 110px;
506
- font-size: 16px;
507
- font-family: "Source Han Sans";
508
- line-height: normal;
509
- margin-right: 25px;
510
- height: 32px;
511
- }
512
- justify-content: center;
513
- }
514
- }
515
-
516
- // button6样式
517
- &.h-buttons-button6 {
518
- :deep(.x-buttons) {
519
- margin: -20px 6px -20px 6px;
520
- .ant-btn-group {
521
- .ant-btn {
522
- border-radius: 6px;
523
- border: 1px solid #9499A0;
524
- background-color: #FFFFFF;
525
- color: #5D5C5C;
526
- width: 46%;
527
- font-size: 16px;
528
- height: 32px;
529
- }
530
- width: 100%;
531
- justify-content: space-between;
532
- }
533
- }
534
- }
535
-
536
- // button31样式
537
- &.h-buttons-button31 {
538
- :deep(.x-buttons) {
539
- width: 110%;
540
- margin: -20px 0px -20px 0px;
541
- .ant-btn-group {
542
- .ant-btn {
543
- border-radius: 6px;
544
- border: 1px solid #9499A0;
545
- background-color: #FFFFFF;
546
- color: #5D5C5C;
547
- width: 100%;
548
- font-size: 16px;
549
- height: 32px;
550
- }
551
- width: 100%;
552
- justify-content: space-between;
553
- }
554
- }
555
- }
556
-
557
- // button12样式
558
- &.h-buttons-button12 {
559
- :deep(.ant-btn-group) {
560
- display: flex;
561
- gap: 8px;
562
- .ant-btn {
563
- border-radius: 6px;
564
- border: none;
565
- color: #FFFFFF;
566
- font-weight: normal;
567
- letter-spacing: 0em;
568
- width: 173px;
569
- font-size: 16px;
570
- font-family: "Source Han Sans";
571
- line-height: normal;
572
- height: 32px;
573
- }
574
- justify-content: flex-end;
575
- margin-top: -30px;
576
- }
577
- }
578
-
579
- // button7样式
580
- &.h-buttons-button7 {
581
- :deep(.x-buttons) {
582
- margin: -20px 6px -20px 6px;
583
- .ant-btn-group {
584
- padding: 0 30px;
585
- .ant-btn {
586
- border-radius: 6px;
587
- border: none;
588
- margin: 0 10px;
589
- width: 110px;
590
- font-size: 16px;
591
- height: 32px;
592
- }
593
- width: 100%;
594
- }
595
- }
596
- }
597
-
598
- // center样式
599
- &.h-buttons-center {
600
- :deep(.ant-btn-group) {
601
- display: flex;
602
- .ant-btn {
603
- border-radius: 6px;
604
- background-color: #FFFFFF;
605
- border: 1px solid #9499A0;
606
- color: #5D5C5C;
607
- font-weight: normal;
608
- letter-spacing: 0em;
609
- width: 110px;
610
- font-size: 16px;
611
- font-family: "Source Han Sans";
612
- line-height: normal;
613
- margin-right: 25px;
614
- height: 32px;
615
- }
616
- justify-content: center;
617
- }
618
- }
619
-
620
- // button11样式
621
- &.h-buttons-button11 {
622
- :deep(.ant-btn-group) {
623
- display: flex;
624
- .ant-btn {
625
- border-radius: 6px;
626
- border: none;
627
- color: #FFFFFF;
628
- font-weight: normal;
629
- letter-spacing: 0em;
630
- font-size: 16px;
631
- font-family: "Source Han Sans";
632
- line-height: normal;
633
- height: 32px;
634
- }
635
- justify-content: flex-end;
636
- margin-top: -54px;
637
- }
638
- }
639
-
640
- // button18样式
641
- &.h-buttons-button18 {
642
- :deep(.x-buttons) {
643
- padding-top: 18px !important;
644
- margin: -20px 3px -20px 3px;
645
- .ant-btn-group {
646
- padding-top: 18px !important;
647
- .ant-btn {
648
- border-radius: 6px;
649
- border: none;
650
- font-size: 16px;
651
- margin-top: 15px !important;
652
- height: 32px;
653
- }
654
- width: 70%;
655
- padding-bottom: 39px !important;
656
- justify-content: space-between;
657
- }
658
- padding-bottom: 39px !important;
659
- }
660
- }
661
-
662
- // button17样式
663
- &.h-buttons-button17 {
664
- :deep(.ant-btn-group) {
665
- display: flex;
666
- gap: 6px;
667
- .ant-btn {
668
- border-radius: 6px;
669
- border: none;
670
- font-weight: normal;
671
- letter-spacing: 0em;
672
- width: 110px;
673
- font-size: 16px;
674
- font-family: "Source Han Sans";
675
- line-height: normal;
676
- height: 32px;
677
- }
678
- justify-content: center;
679
- }
680
- :deep(.x-buttons) {
681
- margin-top: -60px;
682
- }
683
- }
684
-
685
- // button19样式
686
- &.h-buttons-button19 {
687
- :deep(.x-buttons) {
688
- margin: -20px 6px -20px 6px;
689
- .ant-btn-group {
690
- padding-top: 30px;
691
- .ant-btn {
692
- border-radius: 6px;
693
- border: none;
694
- margin: 0 2px;
695
- width: 120px;
696
- font-size: 16px;
697
- height: 52px;
698
- }
699
- width: 100%;
700
- padding-bottom: 10px;
701
- }
702
- }
703
- }
704
-
705
- // left53px样式
706
- &.h-buttons-left53px {
707
- padding: 2px;
708
- left: 53px;
709
- position: relative;
710
- }
711
-
712
- // charges-button样式
713
- &.h-buttons-charges-button {
714
- :deep(.ant-btn-group) {
715
- .ant-btn {
716
- border: 1px solid #9499A0;
717
- color: #313131;
718
- font-weight: normal;
719
- display: flex;
720
- letter-spacing: 0em;
721
- font-size: 16px;
722
- line-height: normal;
723
- box-sizing: border-box;
724
- margin-right: 6px;
725
- border-radius: 6px;
726
- background-color: #FFFFFF;
727
- width: 110px;
728
- font-family: "Source Han Sans";
729
- height: 32px;
730
- }
731
- }
732
- :deep(.ant-card-body) {
733
- padding: 0;
734
- }
735
- }
736
-
737
- // button30样式
738
- &.h-buttons-button30 {
739
- :deep(.ant-btn-group) {
740
- .ant-btn {
741
- border-radius: 6px;
742
- display: inline-block;
743
- margin-right: 10px;
744
- }
745
- width: 100%;
746
- }
747
- }
748
- }
130
+ .h-buttons-wrapper { }
749
131
  </style>
@@ -1,14 +1,118 @@
1
1
  <script setup lang="ts">
2
2
  import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'
3
+ import { ref, onMounted, onUpdated, getCurrentInstance, watch, nextTick } from 'vue'
3
4
 
4
- // 只定义HFormTable特有的属性
5
5
  defineProps({
6
- // HFormTable特有的属性
7
6
  tableStyle: {
8
7
  type: String,
9
8
  default: 'formtable-col1'
10
9
  }
11
10
  })
11
+
12
+ const xFormTableRef = ref(null)
13
+ const instance = getCurrentInstance()
14
+
15
+ // 防抖控制
16
+ let syncTimeout = null
17
+ function debounceSync (callback, delay = 100) {
18
+ if (syncTimeout) clearTimeout(syncTimeout)
19
+ syncTimeout = setTimeout(callback, delay)
20
+ }
21
+
22
+ // 方法缓存,避免重复挂载
23
+ const syncedMethods = new WeakMap()
24
+
25
+ function syncChildRefs () {
26
+ if (!instance || !instance.proxy || !xFormTableRef.value) return
27
+ const proxy = instance.proxy
28
+ const target = proxy.$refs
29
+ const childRefs = xFormTableRef.value.$refs
30
+ if (!childRefs) return
31
+
32
+ Object.entries(childRefs).forEach(([key, value]) => {
33
+ const v = Array.isArray(value) ? value[0] : value
34
+ if (target[key] !== v) target[key] = v
35
+ })
36
+ if (target.xFormTableRef !== xFormTableRef.value) target.xFormTableRef = xFormTableRef.value
37
+ }
38
+
39
+ function getAllFunctionNames (obj) {
40
+ if (!obj) return []
41
+ const names = new Set()
42
+ let current = obj
43
+ while (current && current !== Object.prototype) {
44
+ Object.getOwnPropertyNames(current).forEach(name => {
45
+ if (typeof obj[name] === 'function' && name !== 'constructor') names.add(name)
46
+ })
47
+ current = Object.getPrototypeOf(current)
48
+ }
49
+ return Array.from(names)
50
+ }
51
+
52
+ function syncChildMethods () {
53
+ if (!instance || !instance.proxy || !xFormTableRef.value) return
54
+ const proxy = instance.proxy
55
+ const inner = xFormTableRef.value
56
+ const cached = syncedMethods.get(inner) || new Set()
57
+
58
+ getAllFunctionNames(inner).forEach(name => {
59
+ if (cached.has(name) || proxy[name]) return
60
+ proxy[name] = function () {
61
+ if (xFormTableRef.value && typeof xFormTableRef.value[name] === 'function') {
62
+ return xFormTableRef.value[name].apply(xFormTableRef.value, arguments)
63
+ }
64
+ }
65
+ cached.add(name)
66
+ })
67
+ syncedMethods.set(inner, cached)
68
+ }
69
+
70
+ function syncAll () {
71
+ syncChildRefs()
72
+ syncChildMethods()
73
+ }
74
+
75
+ // 子组件生命周期事件回调,确保及时同步
76
+ function onInnerMounted () { nextTick(function () { debounceSync(syncAll) }) }
77
+ function onInnerUpdated () { nextTick(function () { debounceSync(syncChildRefs) }) }
78
+
79
+ // 生命周期与监听
80
+ onMounted(() => nextTick(() => debounceSync(syncAll)))
81
+ onUpdated(() => nextTick(() => debounceSync(syncAll)))
82
+
83
+ watch(() => xFormTableRef.value && xFormTableRef.value.$refs, () => nextTick(() => debounceSync(syncChildRefs)), { deep: true, flush: 'post' })
84
+ watch(() => xFormTableRef.value, () => nextTick(() => debounceSync(syncChildMethods)), { flush: 'post' })
85
+
86
+ // 常用方法显式代理(API更清晰)
87
+ function createMethodProxy (methodName) {
88
+ return function () {
89
+ const inst = xFormTableRef.value
90
+ if (inst && typeof inst[methodName] === 'function') return inst[methodName].apply(inst, arguments)
91
+ }
92
+ }
93
+
94
+ const COMMON_METHODS = [
95
+ 'reload', 'init', 'doSearch', 'resetForm', 'refreshTable',
96
+ 'clearRowKeys', 'update', 'setTableData'
97
+ ]
98
+
99
+ defineExpose({
100
+ getXFormTableInstance: () => xFormTableRef.value,
101
+ // 显式常用方法
102
+ ...COMMON_METHODS.reduce((acc, m) => {
103
+ acc[m] = createMethodProxy(m)
104
+ return acc
105
+ }, {}),
106
+ // 便捷:获取内部表格/表单ref
107
+ getTableRef: () => {
108
+ const refs = xFormTableRef.value && xFormTableRef.value.$refs
109
+ return (refs && (refs.table || refs.xTable)) || undefined
110
+ },
111
+ getFormRef: () => {
112
+ const refs = xFormTableRef.value && xFormTableRef.value.$refs
113
+ return (refs && (refs.form || refs.xForm)) || undefined
114
+ }
115
+ })
12
116
  </script>
13
117
 
14
118
  <template>
@@ -19,8 +123,11 @@ defineProps({
19
123
  ]"
20
124
  >
21
125
  <x-form-table
126
+ ref="xFormTableRef"
22
127
  v-bind="$attrs"
23
128
  v-on="$listeners"
129
+ @hook:mounted="onInnerMounted"
130
+ @hook:updated="onInnerUpdated"
24
131
  >
25
132
  <template v-for="(_, name) in $slots" #[name]="slotData">
26
133
  <slot :name="name" v-bind="slotData" />
@@ -1,51 +1,134 @@
1
1
  <script setup lang="ts">
2
2
  import XTab from '@vue2-client/base-client/components/common/XTab/XTab.vue'
3
- import { ref } from 'vue'
3
+ import { ref, onMounted, onUpdated, getCurrentInstance, watch, nextTick } from 'vue'
4
4
 
5
5
  defineProps({
6
- // HTab特有的属性
7
6
  hasTopMargin: {
8
7
  type: Boolean,
9
8
  default: true
10
9
  }
11
10
  })
12
11
 
13
- // 创建对XTab组件的引用
14
- const xTabRef = ref()
12
+ const emit = defineEmits(['ready'])
15
13
 
16
- // 暴露方法给父组件使用
17
- defineExpose({
18
- // 为了兼容性,保留getXTabInstance方法
19
- getXTabInstance: () => xTabRef.value,
14
+ const xTabRef = ref(null)
15
+ const instance = getCurrentInstance()
20
16
 
21
- // 直接暴露常用方法,方便调用
22
- tabPaneChange: function () {
23
- if (xTabRef.value) {
24
- return xTabRef.value.tabPaneChange.apply(xTabRef.value, arguments)
25
- }
26
- },
27
- initConfig: function () {
28
- if (xTabRef.value) {
29
- return xTabRef.value.initConfig()
30
- }
31
- },
32
- getConfig: function () {
33
- if (xTabRef.value) {
34
- return xTabRef.value.getConfig()
17
+ // 就绪承诺
18
+ let _resolveReady = null
19
+ let _readyPromise = null
20
+ function resetReady () {
21
+ _readyPromise = new Promise(function (resolve) { _resolveReady = resolve })
22
+ }
23
+ resetReady()
24
+ function markReady () {
25
+ if (_resolveReady) { _resolveReady(); _resolveReady = null }
26
+ emit('ready')
27
+ }
28
+
29
+ // 防抖控制
30
+ let syncTimeout = null
31
+ function debounceSync (callback, delay = 100) {
32
+ if (syncTimeout) clearTimeout(syncTimeout)
33
+ syncTimeout = setTimeout(callback, delay)
34
+ }
35
+
36
+ // 方法缓存
37
+ const syncedMethods = new WeakMap()
38
+
39
+ function getAllFunctionNames (obj) {
40
+ if (!obj) return []
41
+ const names = new Set()
42
+ let current = obj
43
+ while (current && current !== Object.prototype) {
44
+ Object.getOwnPropertyNames(current).forEach(name => {
45
+ if (typeof obj[name] === 'function' && name !== 'constructor') names.add(name)
46
+ })
47
+ current = Object.getPrototypeOf(current)
48
+ }
49
+ return Array.from(names)
50
+ }
51
+
52
+ function syncChildMethods () {
53
+ if (!instance || !instance.proxy || !xTabRef.value) return
54
+ const proxy = instance.proxy
55
+ const inner = xTabRef.value
56
+ const cached = syncedMethods.get(inner) || new Set()
57
+ getAllFunctionNames(inner).forEach(name => {
58
+ if (cached.has(name) || proxy[name]) return
59
+ proxy[name] = function () {
60
+ if (xTabRef.value && typeof xTabRef.value[name] === 'function') {
61
+ return xTabRef.value[name].apply(xTabRef.value, arguments)
62
+ }
35
63
  }
36
- },
37
- // 暴露XTab的属性访问方法
38
- getActiveKey: function () {
39
- return xTabRef.value && xTabRef.value.activeKey
40
- },
41
-
42
- getConfigData: function () {
43
- return xTabRef.value && xTabRef.value.config
44
- },
45
-
46
- getShowTabBar: function () {
47
- return xTabRef.value && xTabRef.value.showTabBar
64
+ cached.add(name)
65
+ })
66
+ syncedMethods.set(inner, cached)
67
+ }
68
+
69
+ // 访问时动态合并 $refs:原始 + 子组件(拍平数组)+ xTabRef
70
+ function installRefsGetter () {
71
+ if (!instance || !instance.proxy) return
72
+ const proxy = instance.proxy
73
+ const baseRefs = proxy.$refs
74
+ if (!baseRefs) return
75
+ try {
76
+ Object.defineProperty(proxy, '$refs', {
77
+ configurable: true,
78
+ get () {
79
+ const merged = {}
80
+ // 基础 refs
81
+ if (baseRefs) {
82
+ Object.keys(baseRefs).forEach(function (k) { merged[k] = baseRefs[k] })
83
+ }
84
+ // 子组件 refs
85
+ const child = xTabRef.value && xTabRef.value.$refs
86
+ if (child) {
87
+ Object.keys(child).forEach(function (k) {
88
+ const v = Array.isArray(child[k]) ? child[k][0] : child[k]
89
+ merged[k] = v
90
+ })
91
+ }
92
+ // xTabRef 本身
93
+ merged.xTabRef = xTabRef.value
94
+ return merged
95
+ }
96
+ })
97
+ } catch (e) {
98
+ // 忽略 defineProperty 失败,保持原逻辑
99
+ }
100
+ }
101
+
102
+ function syncAll () {
103
+ syncChildMethods()
104
+ markReady()
105
+ }
106
+
107
+ // 生命周期与监听
108
+ onMounted(() => nextTick(() => {
109
+ installRefsGetter()
110
+ debounceSync(function () { syncAll() })
111
+ }))
112
+ onUpdated(() => nextTick(() => debounceSync(function () { syncAll() })))
113
+ watch(() => xTabRef.value, () => nextTick(() => { resetReady(); debounceSync(function () { syncAll() }) }), { flush: 'post' })
114
+
115
+ // 常用方法显式代理
116
+ function createMethodProxy (methodName) {
117
+ return function () {
118
+ const inst = xTabRef.value
119
+ if (inst && typeof inst[methodName] === 'function') return inst[methodName].apply(inst, arguments)
48
120
  }
121
+ }
122
+
123
+ const COMMON_METHODS = ['tabPaneChange', 'initConfig', 'getConfig']
124
+
125
+ defineExpose({
126
+ getXTabInstance: () => xTabRef.value,
127
+ whenReady: () => _readyPromise,
128
+ ...COMMON_METHODS.reduce((acc, m) => { acc[m] = createMethodProxy(m); return acc }, {}),
129
+ getActiveKey: () => xTabRef.value && xTabRef.value.activeKey,
130
+ getConfigData: () => xTabRef.value && xTabRef.value.config,
131
+ getShowTabBar: () => xTabRef.value && xTabRef.value.showTabBar,
49
132
  })
50
133
  </script>
51
134
 
@@ -65,16 +148,9 @@ defineExpose({
65
148
 
66
149
  <style scoped lang="less">
67
150
  .h-tab-wrapper {
68
- // 基础样式
69
- :deep(.ant-tabs-tab-next) {
70
- display: none;
71
- }
72
-
151
+ :deep(.ant-tabs-tab-next) { display: none; }
73
152
  :deep(.ant-tabs-nav) {
74
- .ant-tabs-tab-next-icon {
75
- display: none;
76
- }
77
-
153
+ .ant-tabs-tab-next-icon { display: none; }
78
154
  .ant-tabs-tab {
79
155
  background-color: transparent;
80
156
  border-radius: 6px 6px 0 0;
@@ -88,7 +164,6 @@ defineExpose({
88
164
  height: 32px;
89
165
  text-align: center;
90
166
  }
91
-
92
167
  .ant-tabs-tab-active {
93
168
  background-color: #0057FE;
94
169
  color: #ffffff;
@@ -98,43 +173,14 @@ defineExpose({
98
173
  text-align: center;
99
174
  }
100
175
  }
101
-
102
- :deep(.ant-tabs-bar) {
103
- border-bottom: 2px solid #0057FE;
104
- }
105
-
106
- :deep(.ant-tabs-tab-arrow-show) {
107
- display: none;
108
- }
109
-
110
- :deep(.ant-tabs-ink-bar) {
111
- background-color: transparent;
112
- bottom: -1px;
113
- display: none;
114
- height: 0;
115
- }
116
-
117
- :deep(.ant-tabs-tab-prev-icon-target) {
118
- display: none;
119
- }
120
-
121
- // 带顶部边距的样式
176
+ :deep(.ant-tabs-bar) { border-bottom: 2px solid #0057FE; }
177
+ :deep(.ant-tabs-tab-arrow-show) { display: none; }
178
+ :deep(.ant-tabs-ink-bar) { background-color: transparent; bottom: -1px; display: none; height: 0; }
179
+ :deep(.ant-tabs-tab-prev-icon-target) { display: none; }
122
180
  &.h-tab-has-top-margin {
123
- :deep(.ant-tabs-nav) {
124
- margin-top: 6px;
125
- }
126
-
127
- :deep(.ant-tabs-bar) {
128
- margin: 0 6px;
129
- }
130
-
131
- :deep(.ant-card-body) {
132
- padding: 6px 0;
133
-
134
- .ant-card-body {
135
- padding: 6px;
136
- }
137
- }
181
+ :deep(.ant-tabs-nav) { margin-top: 6px; }
182
+ :deep(.ant-tabs-bar) { margin: 0 6px; }
183
+ :deep(.ant-card-body) { padding: 6px 0; .ant-card-body { padding: 6px; } }
138
184
  }
139
185
  }
140
186
  </style>
@@ -64,7 +64,26 @@ export default {
64
64
  },
65
65
  // 清除特定页面的缓存
66
66
  clearCache (resultKeys) {
67
+ console.warn('BlankView clearCache 开始执行:', resultKeys)
68
+
69
+ // 1. 清除AKeepAlive缓存
67
70
  this.clearCaches = resultKeys
71
+ // 2. 强制刷新router-view
72
+ this.forceRefreshRouterView()
73
+
74
+ console.warn('BlankView clearCache 执行完成')
75
+ },
76
+
77
+ // 强制刷新router-view
78
+ forceRefreshRouterView () {
79
+ this.refreshing = true
80
+ this.$nextTick(() => {
81
+ // 延长刷新时间,确保缓存完全清理
82
+ setTimeout(() => {
83
+ this.refreshing = false
84
+ console.warn('router-view 刷新完成')
85
+ }, 300)
86
+ })
68
87
  }
69
88
  },
70
89
  watch: {
@@ -1,18 +1,20 @@
1
1
  <template>
2
- <div id="test">
3
- <a-card :bordered="false">
4
- <XReport
5
- ref="main"
6
- v-if="configName"
7
- :use-oss-for-img="false"
8
- :config-name="configName"
9
- :show-img-in-cell="true"
10
- :display-only="true"
11
- :edit-mode="false"
12
- :dont-format="true"/>
13
- <a-empty v-else/>
14
- </a-card>
15
- </div>
2
+ <a-card
3
+ :bordered="false"
4
+ size="small"
5
+ :bodyStyle="{ padding:'12px', borderRadius: '8px' }">
6
+ <XReport
7
+ ref="main"
8
+ v-if="configName"
9
+ :key="`xreport-${configName}`"
10
+ :use-oss-for-img="false"
11
+ :config-name="configName"
12
+ :show-img-in-cell="true"
13
+ :display-only="true"
14
+ :edit-mode="false"
15
+ :dont-format="true"/>
16
+ <a-empty v-else/>
17
+ </a-card>
16
18
  </template>
17
19
 
18
20
  <script>
@@ -17,7 +17,7 @@ routerResource.blank = view.blank
17
17
  // 单页面视图
18
18
  routerResource.singlePage = view.blank
19
19
  // 栅格配置视图
20
- routerResource.gridView = view.gridView
20
+ routerResource.gridView = () => import('@vue2-client/layouts/GridView')
21
21
  // 测试
22
22
  routerResource.businessQuery = view.blank
23
23
  // 业务查询 - 收费查询
@@ -418,9 +418,10 @@ function loadGuards (guards, options) {
418
418
  * @param func
419
419
  */
420
420
  function funcToRouter (func) {
421
+ const parsedfunc = parsefunc(func)
421
422
  return [{
422
423
  router: 'root',
423
- children: positionRouter(parsefunc(func))
424
+ children: window.__MICRO_APP_ENVIRONMENT__ ? positionRouter(flattenTree(parsedfunc)) : positionRouter(parsedfunc)
424
425
  }]
425
426
  }
426
427
 
@@ -483,10 +484,6 @@ function parsefunc (func) {
483
484
  }
484
485
  tree.push(route)
485
486
  }
486
- // 如果是 microapp 作为子应用路由应该是平铺的 树状结构由父项目处理
487
- if (window.__MICRO_APP_ENVIRONMENT__) {
488
- return flattenTree(tree)
489
- }
490
487
  return tree
491
488
  }
492
489
 
package/vue.config.js CHANGED
@@ -11,11 +11,11 @@ const productionGzipExtensions = ['js', 'css']
11
11
  const isProd = process.env.NODE_ENV === 'production'
12
12
 
13
13
  // v4 产品演示
14
- const v3Server = 'http://aote-office.8866.org:31567'
14
+ const v3Server = 'https://yc.aofengcloud.com:31467'
15
15
  // const gateway = 'http://192.168.50.67:31467'
16
16
  // const testUpload = 'http://123.60.214.109:8406'
17
- const OSSServerDev = 'http://192.168.50.67:30351'
18
- const revenue = 'http://aote-office.8866.org:31567'
17
+ const OSSServerDev = 'https://yc.aofengcloud.com:31467'
18
+ const revenue = 'https://yc.aofengcloud.com:31467'
19
19
  // const revenue = 'http://127.0.0.1:31467'
20
20
  // const OSSServerProd = 'http://192.168.50.67:31351'
21
21
  // const testUploadLocal = 'http://127.0.0.1:9001'
@@ -42,6 +42,11 @@ module.exports = {
42
42
  ws: false,
43
43
  changeOrigin: true
44
44
  },
45
+ '/revenue-web/api/af-revenue': {
46
+ pathRewrite: { '^/revenue-web/': '/' },
47
+ target: v3Server,
48
+ changeOrigin: true
49
+ },
45
50
  // '/api/af-system/resource': {
46
51
  // pathRewrite: { '^/api/af-system': '/' },
47
52
  // target: testUpload,