vue2-client 1.18.66 → 1.18.67

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.
@@ -12,8 +12,8 @@
12
12
  </a-button>
13
13
  </div>
14
14
 
15
- <!-- 当有 layout 配置时使用 a-descriptions -->
16
- <template v-if="config && config.layout && !wrapperClassObject['xhdesc-medical-history']">
15
+ <!-- layout 为数字时使用 a-descriptions -->
16
+ <template v-if="config && config.layout && typeof config.layout === 'number' && !wrapperClassObject['xhdesc-medical-history']">
17
17
  <a-descriptions
18
18
  :colon="getGlobalColon()"
19
19
  :column="config.layout"
@@ -115,6 +115,85 @@
115
115
  </a-descriptions>
116
116
  </template>
117
117
 
118
+ <!-- 当 layout 为数组时使用自定义 Grid 布局 -->
119
+ <template v-else-if="config && config.layout && Array.isArray(config.layout) && !wrapperClassObject['xhdesc-medical-history']">
120
+ <div class="grid-descriptions">
121
+ <template v-if="data">
122
+ <!-- 按行分组显示项目 -->
123
+ <div
124
+ v-for="(rowItems, rowIndex) in gridRows"
125
+ :key="rowIndex"
126
+ class="grid-row"
127
+ :style="{ gridTemplateColumns: getGridTemplateColumns(config.layout[rowIndex]) }"
128
+ >
129
+ <div
130
+ v-for="(item, itemIndex) in rowItems"
131
+ :key="item.field || `item-${itemIndex}`"
132
+ :class="[
133
+ 'grid-item',
134
+ wrapperClassObject['xhdesc-grid-formatted'] && 'grid-formatted',
135
+ { 'with-divider': item.isLine, 'placeholder-item': (!item.field || item.field === '') }
136
+ ]"
137
+ >
138
+ <!-- 占位符项目:只显示空的容器 -->
139
+ <div v-if="!item.field || item.field === ''" class="grid-item-content placeholder-content"></div>
140
+
141
+ <!-- 普通项目 -->
142
+ <div v-else class="grid-item-content">
143
+ <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
144
+ <div v-if="item.showAvatar" class="gender-icon">
145
+ <img :src="maleIcon" alt="male" class="gender-img" />
146
+ </div>
147
+ <span class="label-text">{{ item.label }}</span>
148
+ <span v-if="getItemColon(item)" class="colon">:</span>
149
+ </div>
150
+ <a-tooltip
151
+ v-if="isContentOverflow(data[item.field])"
152
+ :title="data[item.field]"
153
+ placement="topLeft"
154
+ :overlay-style="{ maxWidth: '400px' }"
155
+ >
156
+ <div
157
+ class="content-wrapper ellipsis"
158
+ :data-full-text="data[item.field]"
159
+ >
160
+ <template v-if="wrapperClassObject['xhdesc-report-mode']">
161
+ <div class="report-value">
162
+ {{ data[item.field] }}
163
+ </div>
164
+ <div class="report-unit">
165
+ {{ item.unit }}
166
+ </div>
167
+ </template>
168
+ <template v-else>
169
+ {{ data[item.field] }}
170
+ </template>
171
+ </div>
172
+ </a-tooltip>
173
+ <div
174
+ v-else
175
+ class="content-wrapper"
176
+ :data-full-text="data[item.field]"
177
+ >
178
+ <template v-if="wrapperClassObject['xhdesc-report-mode']">
179
+ <div class="report-value">
180
+ {{ data[item.field] }}
181
+ </div>
182
+ <div class="report-unit">
183
+ {{ item.unit }}
184
+ </div>
185
+ </template>
186
+ <template v-else>
187
+ {{ data[item.field] }}
188
+ </template>
189
+ </div>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </template>
194
+ </div>
195
+ </template>
196
+
118
197
  <!-- 医疗病史模式:使用自定义HTML结构实现文本环绕 -->
119
198
  <template v-else-if="config && config.layout && wrapperClassObject['xhdesc-medical-history']">
120
199
  <div class="medical-history-descriptions">
@@ -393,7 +472,8 @@ export default {
393
472
  'padding-left15',
394
473
  'line-height30',
395
474
  'report-mode',
396
- 'border1'
475
+ 'border1',
476
+ 'grid-formatted'
397
477
  ]
398
478
  booleanStyleKeys.forEach(key => {
399
479
  const val = attrs[key]
@@ -435,7 +515,13 @@ export default {
435
515
  visibleItemsFiltered () {
436
516
  const list = this.visibleItems || []
437
517
  if (!this.data) return []
438
- const res = list.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined)
518
+ // 保留所有配置的字段,包括空字段(用作占位符)
519
+ const res = list.filter(item => {
520
+ // 空字段(占位符)始终显示
521
+ if (!item.field || item.field === '') return true
522
+ // 其他字段只有在有数据时才显示
523
+ return this.data[item.field] !== null && this.data[item.field] !== undefined
524
+ })
439
525
  if (!this.showAllItems) return res
440
526
  const hiddenFields = new Set((this.hiddenItems || []).map(i => i.field))
441
527
  return res.filter(item => !hiddenFields.has(item.field))
@@ -444,6 +530,24 @@ export default {
444
530
  const list = this.hiddenItems || []
445
531
  if (!this.data) return []
446
532
  return list.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined)
533
+ },
534
+ // Grid布局的行分组数据
535
+ gridRows () {
536
+ if (!Array.isArray(this.config?.layout) || !this.visibleItemsFiltered) return []
537
+
538
+ const items = [...this.visibleItemsFiltered]
539
+ const rows = []
540
+ let currentIndex = 0
541
+
542
+ for (let i = 0; i < this.config.layout.length; i++) {
543
+ const columnsInRow = this.config.layout[i]
544
+ const rowItems = items.slice(currentIndex, currentIndex + columnsInRow)
545
+ rows.push(rowItems) // 总是创建行,即使没有项目
546
+ currentIndex += columnsInRow
547
+ if (currentIndex >= items.length) break
548
+ }
549
+
550
+ return rows
447
551
  }
448
552
  },
449
553
  created () {
@@ -490,6 +594,11 @@ export default {
490
594
  return item.colon
491
595
  }
492
596
  return this.getGlobalColon()
597
+ },
598
+ // 生成CSS Grid模板列样式
599
+ getGridTemplateColumns (columns) {
600
+ if (typeof columns !== 'number' || columns <= 0) return 'repeat(auto-fit, minmax(200px, 1fr))'
601
+ return `repeat(${columns}, 1fr)`
493
602
  }
494
603
  },
495
604
  watch: {
@@ -532,6 +641,110 @@ export default {
532
641
  width: 100%;
533
642
  }
534
643
 
644
+ /* Grid布局样式 */
645
+ .grid-descriptions {
646
+ width: 100%;
647
+ }
648
+
649
+ .grid-row {
650
+ display: grid;
651
+ gap: 16px 24px;
652
+ width: 100%;
653
+ margin-bottom: 16px;
654
+ }
655
+
656
+ .grid-row:last-child {
657
+ margin-bottom: 0;
658
+ }
659
+
660
+ .grid-item {
661
+ display: flex;
662
+ align-items: flex-start;
663
+ padding: 8px;
664
+ border-radius: 4px;
665
+ transition: background-color 0.3s;
666
+ min-width: 0; /* 允许内容收缩 */
667
+ min-height: 40px; /* 确保行高一致 */
668
+ }
669
+
670
+ .grid-item:hover {
671
+ background-color: rgba(0, 0, 0, 0.02);
672
+ }
673
+
674
+ /* 占位符项目样式 */
675
+ .placeholder-item {
676
+ background-color: transparent !important;
677
+ }
678
+
679
+ .placeholder-item:hover {
680
+ background-color: transparent !important;
681
+ }
682
+
683
+ /* Grid布局格式化样式:对齐 + 字体 */
684
+ .grid-item.grid-formatted .grid-item-content {
685
+ display: flex;
686
+ align-items: center;
687
+ gap: 16px;
688
+ width: 100%;
689
+ height: 100%;
690
+ }
691
+
692
+ .grid-item.grid-formatted .label-wrapper {
693
+ flex: 0 0 auto;
694
+ min-width: 80px;
695
+ max-width: 120px;
696
+ display: flex;
697
+ align-items: center;
698
+ position: relative;
699
+ }
700
+
701
+ .grid-item.grid-formatted .label-text {
702
+ flex: 1;
703
+ text-align: justify; /* 两端对齐 */
704
+ padding-right: 12px; /* 为冒号留空间 */
705
+ text-justify: inter-word; /* 优化两端对齐 */
706
+ word-break: break-all; /* 允许在任意字符间断行 */
707
+ letter-spacing: 0.5em; /* 适中的字符间距 */
708
+ }
709
+
710
+ .grid-item.grid-formatted .colon {
711
+ position: absolute;
712
+ right: 0;
713
+ top: 50%;
714
+ transform: translateY(-50%);
715
+ }
716
+
717
+ .grid-item.grid-formatted .content-wrapper {
718
+ flex: 1;
719
+ text-align: left;
720
+ min-width: 0; /* 允许收缩 */
721
+ }
722
+
723
+ .grid-item.grid-formatted .label-wrapper .label-text {
724
+ font-family: "Source Han Sans";
725
+ font-size: 16px;
726
+ font-weight: normal;
727
+ line-height: 23px;
728
+ letter-spacing: 0em;
729
+ color: #313131;
730
+ }
731
+
732
+ .grid-item.grid-formatted .content-wrapper {
733
+ font-family: "Source Han Sans";
734
+ font-size: 16px;
735
+ font-weight: bold;
736
+ line-height: 23px;
737
+ letter-spacing: 0em;
738
+ color: #313131;
739
+ }
740
+
741
+ /* Grid布局冒号样式 */
742
+ .grid-item .colon {
743
+ margin: 0 2px;
744
+ color: rgba(0, 0, 0, 0.65);
745
+ font-size: 14px;
746
+ }
747
+
535
748
  .description-item {
536
749
  display: inline-flex;
537
750
  align-items: center;