vue2-client 1.12.55 → 1.12.56

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.
@@ -1,186 +1,186 @@
1
- // print.js
2
-
3
- export function printElement (elementToPrint) {
4
- // 创建一个新的浏览器窗口
5
- const printWindow = window.open('', '_blank', 'height=1024,width=768')
6
- // 设置新窗口的文档内容
7
- printWindow.document.write(`
8
- <html>
9
- <head>
10
- <title>Print</title>
11
- <style>
12
- @page {
13
- size: auto;
14
- margin: 0mm;
15
- }
16
- html, body {
17
- margin: 0;
18
- padding: 0;
19
- width: 100%;
20
- height: 100%;
21
- }
22
- #print-container {
23
- display: none
24
- }
25
- .img{
26
- width: 95%;
27
- height: 180px;
28
- object-fit: cover;
29
- }
30
- .reportMain {
31
- text-align: center;
32
- margin: 0 auto;
33
- font-size: 16px;
34
- color: #000;
35
- background-color: #fff;
36
- padding: 15px;
37
- border-radius: 8px;
38
-
39
- .reportTitle {
40
- font-weight: bold;
41
- }
42
-
43
- .subTitle {
44
- display: flex;
45
- justify-content: space-between;
46
- margin-bottom: 1%;
47
-
48
- .subTitleItems {
49
- max-width: 30%;
50
- }
51
- }
52
-
53
- .inputsDiv {
54
- display: flex;
55
- justify-content: space-between;
56
- .inputsDivItem {
57
- display: flex;
58
- align-items: center;
59
- padding: 0 4px;
60
- white-space: nowrap;
61
- .inputsDivItemLabel {
62
- padding: 0 4px;
63
- }
64
- }
65
- }
66
-
67
- .reportTable {
68
- width: 100%;
69
- border-collapse: collapse;
70
- table-layout:fixed;
71
- word-break:break-all;
72
- text-align: center;
73
- }
74
- }
75
- .reportMainForDisplay {
76
- text-align: center;
77
- margin: 10% auto;
78
- font-size: 16px;
79
- color: #000;
80
- background-color: #fff;
81
- padding: 15px;
82
- border-radius: 8px;
83
-
84
- .reportTitle {
85
- font-weight: bold;
86
- }
87
-
88
- .subTitle {
89
- display: flex;
90
- justify-content: space-between;
91
-
92
- .subTitleItems {
93
- max-width: 30%;
94
- }
95
- }
96
-
97
- .inputsDiv {
98
- display: flex;
99
- justify-content: space-around;
100
- .inputsDivItem {
101
- display: flex;
102
- align-items: center;
103
- padding: 0 4px;
104
- white-space: nowrap;
105
- .inputsDivItemLabel {
106
- padding: 0 4px;
107
- }
108
- }
109
- }
110
-
111
- .reportTable {
112
- width: 100%;
113
- border-collapse: collapse;
114
- table-layout:fixed;
115
- word-break:break-all;
116
- }
117
- }
118
- .reportMainNoPadding {
119
- text-align: center;
120
- margin: 0 auto;
121
- font-size: 16px;
122
- color: #000;
123
- background-color: #fff;
124
- border-radius: 8px;
125
-
126
- .reportTitle {
127
- font-weight: bold;
128
- }
129
-
130
- .subTitle {
131
- display: flex;
132
- justify-content: space-between;
133
-
134
- .subTitleItems {
135
- max-width: 30%;
136
- }
137
- }
138
-
139
- .inputsDiv {
140
- display: flex;
141
- justify-content: space-between;
142
- .inputsDivItem {
143
- display: flex;
144
- align-items: center;
145
- padding: 0 4px;
146
- white-space: nowrap;
147
- .inputsDivItemLabel {
148
- padding: 0 4px;
149
- }
150
- }
151
- }
152
-
153
- .reportTable {
154
- width: 100%;
155
- border-collapse: collapse;
156
- table-layout:fixed;
157
- word-break:break-all;
158
- }
159
- }
160
- .tools{
161
- position: fixed;
162
- right: 2%;
163
- text-align: right;
164
- width: 60%;
165
- cursor: pointer;
166
- .toolsItem{
167
- width: 15%;
168
- margin-right: 3%;
169
- display: inline-block;
170
- }
171
- }
172
- </style>
173
- </head>
174
- <body>
175
- <!-- 将需要打印的元素内容复制到新窗口中 -->
176
- ${elementToPrint.innerHTML}
177
- </body>
178
- </html>
179
- `)
180
- // 延迟执行打印,以确保新窗口的内容已加载完成
181
- printWindow.document.close() // 关闭文档流,确保内容完全加载
182
- setTimeout(() => {
183
- printWindow.print() // 调用打印方法
184
- printWindow.close()
185
- }, 500) // 延迟500毫秒后执行打印
186
- }
1
+ // print.js
2
+
3
+ export function printElement (elementToPrint) {
4
+ // 创建一个新的浏览器窗口
5
+ const printWindow = window.open('', '_blank', 'height=1024,width=768')
6
+ // 设置新窗口的文档内容
7
+ printWindow.document.write(`
8
+ <html>
9
+ <head>
10
+ <title>Print</title>
11
+ <style>
12
+ @page {
13
+ size: auto;
14
+ margin: 0mm;
15
+ }
16
+ html, body {
17
+ margin: 0;
18
+ padding: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ }
22
+ #print-container {
23
+ display: none
24
+ }
25
+ .img{
26
+ width: 95%;
27
+ height: 180px;
28
+ object-fit: cover;
29
+ }
30
+ .reportMain {
31
+ text-align: center;
32
+ margin: 0 auto;
33
+ font-size: 16px;
34
+ color: #000;
35
+ background-color: #fff;
36
+ padding: 15px;
37
+ border-radius: 8px;
38
+
39
+ .reportTitle {
40
+ font-weight: bold;
41
+ }
42
+
43
+ .subTitle {
44
+ display: flex;
45
+ justify-content: space-between;
46
+ margin-bottom: 1%;
47
+
48
+ .subTitleItems {
49
+ max-width: 30%;
50
+ }
51
+ }
52
+
53
+ .inputsDiv {
54
+ display: flex;
55
+ justify-content: space-between;
56
+ .inputsDivItem {
57
+ display: flex;
58
+ align-items: center;
59
+ padding: 0 4px;
60
+ white-space: nowrap;
61
+ .inputsDivItemLabel {
62
+ padding: 0 4px;
63
+ }
64
+ }
65
+ }
66
+
67
+ .reportTable {
68
+ width: 100%;
69
+ border-collapse: collapse;
70
+ table-layout:fixed;
71
+ word-break:break-all;
72
+ text-align: center;
73
+ }
74
+ }
75
+ .reportMainForDisplay {
76
+ text-align: center;
77
+ margin: 10% auto;
78
+ font-size: 16px;
79
+ color: #000;
80
+ background-color: #fff;
81
+ padding: 15px;
82
+ border-radius: 8px;
83
+
84
+ .reportTitle {
85
+ font-weight: bold;
86
+ }
87
+
88
+ .subTitle {
89
+ display: flex;
90
+ justify-content: space-between;
91
+
92
+ .subTitleItems {
93
+ max-width: 30%;
94
+ }
95
+ }
96
+
97
+ .inputsDiv {
98
+ display: flex;
99
+ justify-content: space-around;
100
+ .inputsDivItem {
101
+ display: flex;
102
+ align-items: center;
103
+ padding: 0 4px;
104
+ white-space: nowrap;
105
+ .inputsDivItemLabel {
106
+ padding: 0 4px;
107
+ }
108
+ }
109
+ }
110
+
111
+ .reportTable {
112
+ width: 100%;
113
+ border-collapse: collapse;
114
+ table-layout:fixed;
115
+ word-break:break-all;
116
+ }
117
+ }
118
+ .reportMainNoPadding {
119
+ text-align: center;
120
+ margin: 0 auto;
121
+ font-size: 16px;
122
+ color: #000;
123
+ background-color: #fff;
124
+ border-radius: 8px;
125
+
126
+ .reportTitle {
127
+ font-weight: bold;
128
+ }
129
+
130
+ .subTitle {
131
+ display: flex;
132
+ justify-content: space-between;
133
+
134
+ .subTitleItems {
135
+ max-width: 30%;
136
+ }
137
+ }
138
+
139
+ .inputsDiv {
140
+ display: flex;
141
+ justify-content: space-between;
142
+ .inputsDivItem {
143
+ display: flex;
144
+ align-items: center;
145
+ padding: 0 4px;
146
+ white-space: nowrap;
147
+ .inputsDivItemLabel {
148
+ padding: 0 4px;
149
+ }
150
+ }
151
+ }
152
+
153
+ .reportTable {
154
+ width: 100%;
155
+ border-collapse: collapse;
156
+ table-layout:fixed;
157
+ word-break:break-all;
158
+ }
159
+ }
160
+ .tools{
161
+ position: fixed;
162
+ right: 2%;
163
+ text-align: right;
164
+ width: 60%;
165
+ cursor: pointer;
166
+ .toolsItem{
167
+ width: 15%;
168
+ margin-right: 3%;
169
+ display: inline-block;
170
+ }
171
+ }
172
+ </style>
173
+ </head>
174
+ <body>
175
+ <!-- 将需要打印的元素内容复制到新窗口中 -->
176
+ ${elementToPrint.innerHTML}
177
+ </body>
178
+ </html>
179
+ `)
180
+ // 延迟执行打印,以确保新窗口的内容已加载完成
181
+ printWindow.document.close() // 关闭文档流,确保内容完全加载
182
+ setTimeout(() => {
183
+ printWindow.print() // 调用打印方法
184
+ printWindow.close()
185
+ }, 500) // 延迟500毫秒后执行打印
186
+ }
@@ -5,7 +5,8 @@
5
5
  name="trGroup"
6
6
  v-if="Array.isArray(cell) || !cell.dontShowRow"
7
7
  :key="cellIndex"
8
- :style="isWidget ? {padding: '0px 2px'} : (Array.isArray(cell) ? {} : determineCellStyle(cell))"
8
+ :ref="`trGroup_${ cell.slotRef || cellIndex}`"
9
+ @hook:mounted="(h)=>applyAllStyles(cell,cellIndex)"
9
10
  :span="calculateColSpan(cell)">
10
11
  <div id="report_widget" v-if="isWidget">
11
12
  <!-- 插槽渲染 -->
@@ -41,7 +42,7 @@
41
42
  </template>
42
43
  </template>
43
44
  </div>
44
- <a-card v-else class="flexItem" :bordered="false" :body-style="flexItemBodyState">
45
+ <a-card v-else class="flexItem" :bordered="false">
45
46
  <!-- 插槽渲染 -->
46
47
  <template v-if="Array.isArray(cell)">
47
48
  <!-- 处理 cell 是数组的情况 -->
@@ -207,6 +208,14 @@ export default {
207
208
  ? cell[0][0]?.colSpan * 2
208
209
  : (cell?.colSpan ?? cell?.def?.colSpan ?? 1) * 2
209
210
  },
211
+ applyAllStyles (cell, cellIndex) {
212
+ // 应用组件样式
213
+ const component = this.$refs[`trGroup_${ cell.slotRef || cellIndex}`][0]
214
+ // 确保组件已经完全挂载
215
+ this.$nextTick(() => {
216
+ this.applyComponentStyles(component, cell, cellIndex)
217
+ })
218
+ },
210
219
  onComponentMounted (h, cell, cellIndex) {
211
220
  this.slotRendered += 1
212
221
  if (this.slotRendered >= this.allSlotSum) {
@@ -410,7 +419,215 @@ export default {
410
419
  }
411
420
  }
412
421
  })
413
- }
422
+ },
423
+ // 获取组件样式配置
424
+ async getComponentStyleConfig (componentType) {
425
+ try {
426
+ // 从配置中获取样式定义
427
+ const styleConfig = this.$appdata.getStylesByKey(componentType)
428
+ return styleConfig || {}
429
+ } catch (error) {
430
+ console.error('获取组件样式配置失败:', error)
431
+ return {}
432
+ }
433
+ },
434
+
435
+ // 解析组件样式配置
436
+ async parseComponentStyles (cell) {
437
+ if (!cell.class) return { rootStyles: {}, childStyles: {} }
438
+
439
+ const styleConfig = await this.getComponentStyleConfig(cell.slotType)
440
+ if (!styleConfig) return { rootStyles: {}, childStyles: {} }
441
+
442
+ const rootStyles = {}
443
+ const childStyles = new Map()
444
+
445
+ // 处理每个class配置
446
+ cell.class.split(' ').forEach(className => {
447
+ const classConfig = styleConfig[className]
448
+ if (!classConfig) return
449
+
450
+ // 处理根节点样式
451
+ Object.entries(classConfig).forEach(([key, value]) => {
452
+ if (!key.startsWith('*') && typeof key !== 'object') {
453
+ rootStyles[key] = value
454
+ }
455
+ })
456
+
457
+ // 处理子节点样式
458
+ this.parseNestedStyles(classConfig, childStyles)
459
+ })
460
+
461
+ console.warn('样式配置', rootStyles, childStyles)
462
+ return {
463
+ rootStyles,
464
+ childStyles
465
+ }
466
+ },
467
+
468
+ // 递归解析嵌套的样式配置
469
+ parseNestedStyles (config, styleMap, parentKey = '') {
470
+ Object.entries(config).forEach(([key, value]) => {
471
+ if (!key.startsWith('*')) return
472
+
473
+ const className = key.replace('*', '.')
474
+
475
+ // 如果值是对象,检查是否包含样式和子节点
476
+ if (typeof value === 'object') {
477
+ const { style = {}, children = {} } = this.separateStyleAndChildren(value)
478
+
479
+ // 创建或获取当前节点的样式配置
480
+ if (!styleMap.has(className)) {
481
+ styleMap.set(className, {
482
+ styles: {},
483
+ children: new Map()
484
+ })
485
+ }
486
+
487
+ const nodeData = styleMap.get(className)
488
+
489
+ // 合并样式
490
+ Object.assign(nodeData.styles, style)
491
+
492
+ // 递归处理子节点
493
+ this.parseNestedStyles(children, nodeData.children, className)
494
+ }
495
+ })
496
+ },
497
+
498
+ // 分离样式属性和子节点配置
499
+ separateStyleAndChildren (obj) {
500
+ const style = {}
501
+ const children = {}
502
+
503
+ Object.entries(obj).forEach(([key, value]) => {
504
+ if (key.startsWith('*')) {
505
+ // 子节点配置
506
+ children[key] = value
507
+ } else {
508
+ // 样式属性
509
+ style[key] = value
510
+ }
511
+ })
512
+
513
+ return { style, children }
514
+ },
515
+
516
+ // 应用组件样式
517
+ async applyComponentStyles (component, cell, cellIndex) {
518
+ if (!component || !component.$el) return
519
+
520
+ const { rootStyles, childStyles } = await this.parseComponentStyles(cell)
521
+
522
+ // 应用根节点样式
523
+ if (Object.keys(rootStyles).length > 0) {
524
+ Object.entries(rootStyles).forEach(([property, value]) => {
525
+ component.$el.style.setProperty(property, value, 'important')
526
+ })
527
+ }
528
+
529
+ // 如果没有子节点样式,直接返回
530
+ if (childStyles.size === 0) return
531
+
532
+ let retryCount = 0
533
+ const maxRetries = 5
534
+ const retryInterval = 100 // 100ms
535
+
536
+ const applyStyles = () => {
537
+ this.applyChildStylesOptimized(component.$el, childStyles)
538
+ }
539
+
540
+ // 首次应用样式
541
+ applyStyles()
542
+
543
+ // 创建重试机制
544
+ const retryApplyStyles = () => {
545
+ if (retryCount >= maxRetries) return
546
+
547
+ setTimeout(() => {
548
+ applyStyles()
549
+ retryCount++
550
+ retryApplyStyles()
551
+ }, retryInterval)
552
+ }
553
+
554
+ // 开始重试
555
+ retryApplyStyles()
556
+
557
+ // 创建 MutationObserver 用于动态内容
558
+ const observer = new MutationObserver((mutations) => {
559
+ // 检查是否有新增节点
560
+ const hasNewNodes = mutations.some(mutation =>
561
+ mutation.type === 'childList' && mutation.addedNodes.length > 0
562
+ )
563
+
564
+ if (hasNewNodes) {
565
+ applyStyles()
566
+ }
567
+ })
568
+
569
+ // 配置 observer
570
+ observer.observe(component.$el, {
571
+ childList: true,
572
+ subtree: true,
573
+ attributes: false
574
+ })
575
+
576
+ // 3秒后停止观察
577
+ setTimeout(() => {
578
+ observer.disconnect()
579
+ }, 3000)
580
+
581
+ // 组件销毁时清理
582
+ this.$once('hook:beforeDestroy', () => {
583
+ observer.disconnect()
584
+ })
585
+ },
586
+
587
+ // 优化后的子节点样式应用方法
588
+ applyChildStylesOptimized (rootElement, styleMap, parentSelector = '') {
589
+ if (!rootElement) return
590
+
591
+ // 处理样式映射
592
+ for (const [selector, data] of styleMap.entries()) {
593
+ const currentSelector = parentSelector ? `${parentSelector} ${selector}` : selector
594
+
595
+ try {
596
+ // 查找匹配的元素
597
+ const elements = Array.from(rootElement.querySelectorAll(currentSelector))
598
+
599
+ if (!elements.length) continue
600
+
601
+ // 应用当前层级样式
602
+ if (data.styles) {
603
+ elements.forEach(element => {
604
+ if (!element) return
605
+
606
+ // 应用每个样式属性
607
+ Object.entries(data.styles).forEach(([property, value]) => {
608
+ try {
609
+ element.style.setProperty(property, value, 'important')
610
+ } catch (err) {
611
+ console.warn(`设置样式失败: ${property}=${value}`, err)
612
+ }
613
+ })
614
+ })
615
+ }
616
+
617
+ // 处理子层级
618
+ if (data.children && data.children.size > 0) {
619
+ elements.forEach(element => {
620
+ if (element) {
621
+ this.applyChildStylesOptimized(element, data.children, currentSelector)
622
+ }
623
+ })
624
+ }
625
+ } catch (err) {
626
+ console.warn(`处理选择器失败: ${currentSelector}`, err)
627
+ continue
628
+ }
629
+ }
630
+ },
414
631
  },
415
632
  beforeMount () {
416
633
  if (this.useOssForImg) {
@@ -116,6 +116,11 @@ const GetAppDataService = {
116
116
  const str = localStorage.getItem(process.env.VUE_APP_WEB_CONFIG_KEY)
117
117
  const object = JSON.parse(str)
118
118
  return object[key]
119
- }
119
+ },
120
+ getStylesByKey (key) {
121
+ const str = localStorage.getItem(process.env.VUE_APP_STYLES_KEY)
122
+ const object = JSON.parse(str)
123
+ return object[key]
124
+ },
120
125
  }
121
126
  export default GetAppDataService
package/src/bootstrap.js CHANGED
@@ -24,6 +24,9 @@ async function bootstrap ({ router, store, i18n, message }) {
24
24
  Vue.$store.commit('setting/setSetting', res?.setting)
25
25
  }
26
26
  })
27
+ await getConfigByName('componentStyles', undefined, res => {
28
+ localStorage.setItem(process.env.VUE_APP_WEB_STYLES_KEY, JSON.stringify(res))
29
+ })
27
30
  }
28
31
  // 设置应用配置
29
32
  setAppOptions({ router, store, i18n })
@@ -4,7 +4,7 @@
4
4
  @updateImg="updateImg"
5
5
  ref="main"
6
6
  :use-oss-for-img="false"
7
- config-name="medicineMouldCover"
7
+ config-name="openPrescriptionCover"
8
8
  server-name="af-his"
9
9
  :show-img-in-cell="true"
10
10
  :display-only="displayOnly"