vue2-client 1.16.80 → 1.16.81

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.
Files changed (26) hide show
  1. package/package.json +112 -112
  2. package/src/assets/svg/female.svg +1 -1
  3. package/src/assets/svg/male.svg +1 -1
  4. package/src/base-client/components/common/HIS/HFormGroup/index.js +3 -3
  5. package/src/base-client/components/common/HIS/HFormTable/HFormTable.vue +379 -379
  6. package/src/base-client/components/common/HIS/HTab/HTab.vue +418 -413
  7. package/src/base-client/components/common/XCollapse/XCollapse.vue +833 -833
  8. package/src/base-client/components/common/XInput/XInput.vue +194 -170
  9. package/src/base-client/components/common/XTable/XTable.vue +1610 -1610
  10. package/src/base-client/components/common/XTimeline/XTimeline.vue +454 -454
  11. package/src/base-client/components/his/XHDescriptions/XHDescriptions.vue +1022 -944
  12. package/src/base-client/components/his/XHisEditor/XHisEditor.vue +705 -705
  13. package/src/base-client/components/his/XList/XList.vue +829 -829
  14. package/src/base-client/components/his/XRadio/XRadio.vue +17 -1
  15. package/src/base-client/components/his/XSidebar/XSidebar.vue +15 -14
  16. package/src/base-client/components/his/XSimpleTable/XSimpleTable.vue +159 -159
  17. package/src/base-client/components/his/XTimeSelect/XTimeSelect.vue +72 -3
  18. package/src/base-client/components/his/XTitle/XTitle.vue +255 -233
  19. package/src/base-client/components/his/XTreeRows/XTreeRows.vue +341 -341
  20. package/src/base-client/components/his/threeTestOrders/editor.vue +113 -113
  21. package/src/pages/userInfoDetailManage/ExceptionRecordQuery/index.vue +45 -45
  22. package/src/router/async/router.map.js +1 -2
  23. package/src-base-client/components/common/XCollapse/XCollapse.vue +0 -0
  24. package/.npmignore +0 -21
  25. package/.serena/.npmignore +0 -1
  26. package/yarn.lock +0 -11468
@@ -1,944 +1,1022 @@
1
- <template>
2
- <div class="patient-info-descriptions" :class="wrapperClassObject">
3
- <div class="descriptions-container">
4
- <!-- 详情/收起按钮 -->
5
- <div v-if="hasMoreItems" class="detail-button-wrapper">
6
- <a-button
7
- :type="(config && config.detailsConfig && config.detailsConfig.buttonType) || 'link'"
8
- @click="toggleDetails"
9
- >
10
- <a-icon :type="showAllItems ? 'up' : 'down'" />
11
- {{ showAllItems ? '收起' : ((config && config.detailsConfig && config.detailsConfig.buttonText) || '详情') }}
12
- </a-button>
13
- </div>
14
-
15
- <!-- 当有 layout 配置时使用 a-descriptions -->
16
- <template v-if="config && config.layout && !wrapperClassObject['xhdesc-medical-history']">
17
- <a-descriptions
18
- :column="config.layout"
19
- :size="(config && config.style && config.style.size)"
20
- :bordered="(config && config.style && config.style.bordered)"
21
- layout="horizontal">
22
- <template v-if="data">
23
- <!-- 显示前N个标签 -->
24
- <a-descriptions-item
25
- v-for="(item) in visibleItemsFiltered"
26
- :key="item.field"
27
- :colon="item.colon !== false"
28
- :class="{ 'with-divider': item.isLine }">
29
- <template #label>
30
- <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
31
- <a-avatar
32
- v-if="item.showAvatar"
33
- :size="item.avatar.size"
34
- :icon="item.avatar.icon"
35
- :style="{ background: item.avatar.background }"
36
- />
37
- <span class="label-text">{{ item.label }}</span>
38
- </div>
39
- </template>
40
- <a-tooltip
41
- v-if="isContentOverflow(data[item.field])"
42
- :title="data[item.field]"
43
- placement="topLeft"
44
- :overlay-style="{ maxWidth: '400px' }"
45
- >
46
- <div
47
- class="content-wrapper ellipsis"
48
- :data-full-text="data[item.field]"
49
- >
50
- {{ data[item.field] }}
51
- </div>
52
- </a-tooltip>
53
- <div
54
- v-else
55
- class="content-wrapper"
56
- :data-full-text="data[item.field]"
57
- >
58
- {{ data[item.field] }}
59
- </div>
60
- </a-descriptions-item>
61
-
62
- <!-- 展开后显示剩余标签 -->
63
- <template v-if="showAllItems">
64
- <a-descriptions-item
65
- v-for="item in hiddenItemsFiltered"
66
- :key="item.field"
67
- :colon="item.colon !== false">
68
- <template #label>
69
- <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
70
- <a-avatar
71
- v-if="item.showAvatar"
72
- :size="item.avatar.size"
73
- :icon="item.avatar.icon"
74
- :style="{ background: item.avatar.background }"
75
- />
76
- <span class="label-text">{{ item.label }}</span>
77
- </div>
78
- </template>
79
- <div
80
- class="content-wrapper"
81
- :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
82
- :data-full-text="data[item.field]"
83
- >
84
- {{ data[item.field] }}
85
- </div>
86
- </a-descriptions-item>
87
- </template>
88
- </template>
89
- </a-descriptions>
90
- </template>
91
-
92
- <!-- 医疗病史模式:使用自定义HTML结构实现文本环绕 -->
93
- <template v-else-if="config && config.layout && wrapperClassObject['xhdesc-medical-history']">
94
- <div class="medical-history-descriptions">
95
- <template v-if="data">
96
- <!-- 显示前N个标签 -->
97
- <div
98
- v-for="(item) in visibleItemsFiltered"
99
- :key="item.field"
100
- :class="['medical-history-item', { 'with-divider': item.isLine }]"
101
- >
102
- <div class="medical-history-content">
103
- <a-tooltip
104
- v-if="isContentOverflow(data[item.field])"
105
- :title="data[item.field]"
106
- placement="topLeft"
107
- :overlay-style="{ maxWidth: '400px' }"
108
- >
109
- <div class="medical-history-text ellipsis">
110
- <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
111
- </div>
112
- </a-tooltip>
113
- <div
114
- v-else
115
- class="medical-history-text"
116
- >
117
- <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
118
- </div>
119
- </div>
120
- </div>
121
-
122
- <!-- 展开后显示剩余标签 -->
123
- <template v-if="showAllItems">
124
- <div
125
- v-for="item in hiddenItemsFiltered"
126
- :key="item.field"
127
- class="medical-history-item"
128
- >
129
- <div class="medical-history-content">
130
- <a-tooltip
131
- v-if="isContentOverflow(data[item.field])"
132
- :title="data[item.field]"
133
- placement="topLeft"
134
- :overlay-style="{ maxWidth: '400px' }"
135
- >
136
- <div class="medical-history-text ellipsis">
137
- <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
138
- </div>
139
- </a-tooltip>
140
- <div
141
- v-else
142
- class="medical-history-text"
143
- >
144
- <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
145
- </div>
146
- </div>
147
- </div>
148
- </template>
149
- </template>
150
- </div>
151
- </template>
152
-
153
- <!-- 当没有 layout 配置时使用自适应布局 -->
154
- <template v-else>
155
- <div class="flex-descriptions">
156
- <template v-if="data">
157
- <!-- 显示可见的标签 -->
158
- <div
159
- v-for="(item) in visibleItemsFiltered"
160
- :key="item.field"
161
- :class="['description-item', { 'with-divider': item.isLine }]"
162
- >
163
- <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
164
- <a-avatar
165
- v-if="item.showAvatar"
166
- :size="item.avatar.size"
167
- :icon="item.avatar.icon"
168
- :style="{ background: item.avatar.background }"
169
- />
170
- <span class="label-text">{{ item.label }}:</span>
171
- </div>
172
- <a-tooltip
173
- v-if="isContentOverflow(data[item.field])"
174
- :title="data[item.field]"
175
- placement="topLeft"
176
- :overlay-style="{ maxWidth: '400px' }"
177
- >
178
- <div
179
- class="content-wrapper ellipsis"
180
- :data-full-text="data[item.field]"
181
- >
182
- {{ data[item.field] }}
183
- </div>
184
- </a-tooltip>
185
- <div
186
- v-else
187
- class="content-wrapper"
188
- :data-full-text="data[item.field]"
189
- >
190
- {{ data[item.field] }}
191
- </div>
192
- </div>
193
-
194
- <!-- 展开后显示的内容 -->
195
- <template v-if="showAllItems">
196
- <div
197
- v-for="item in hiddenItemsFiltered"
198
- :key="item.field"
199
- class="description-item"
200
- >
201
- <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
202
- <a-avatar
203
- v-if="item.showAvatar"
204
- :size="item.avatar.size"
205
- :icon="item.avatar.icon"
206
- :style="{ background: item.avatar.background }"
207
- />
208
- <span class="label-text">{{ item.label }}:</span>
209
- </div>
210
- <div
211
- class="content-wrapper"
212
- :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
213
- :data-full-text="data[item.field]"
214
- >
215
- {{ data[item.field] }}
216
- </div>
217
- </div>
218
- </template>
219
- </template>
220
- </div>
221
- </template>
222
-
223
- <!-- 可选:底部区域(分割线 + 三列内容) -->
224
- <div v-if="config && config.footer && Array.isArray(config.footer.items) && data" class="xhdesc-footer">
225
- <div class="xhdesc-divider" />
226
- <!-- 医疗病史模式下的footer结构 -->
227
- <div v-if="wrapperClassObject['xhdesc-medical-history']" class="medical-history-footer">
228
- <div
229
- v-for="(item, idx) in config.footer.items"
230
- :key="item.field || idx"
231
- class="medical-history-item">
232
- <div class="medical-history-content">
233
- <a-tooltip
234
- v-if="isContentOverflow(data[item.field])"
235
- :title="data[item.field]"
236
- placement="topLeft"
237
- :overlay-style="{ maxWidth: '400px' }"
238
- >
239
- <div class="medical-history-text ellipsis">
240
- <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
241
- </div>
242
- </a-tooltip>
243
- <div
244
- v-else
245
- class="medical-history-text"
246
- >
247
- <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
248
- </div>
249
- </div>
250
- </div>
251
- <!-- 右侧信息:换到下一行并靠右对齐(如 医生 / 医嘱日期) -->
252
- <div
253
- v-if="Array.isArray(config.footer.rightItems) && config.footer.rightItems.length"
254
- class="footer-right">
255
- <div
256
- v-for="(item, ridx) in config.footer.rightItems"
257
- :key="item.field || ridx"
258
- class="footer-right-item">
259
- <div class="label-wrapper"><span class="label-text">{{ item.label }}:</span></div>
260
- <div
261
- class="content-wrapper"
262
- :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
263
- :data-full-text="data[item.field]"
264
- >{{ data[item.field] }}
265
- </div>
266
- </div>
267
- </div>
268
- </div>
269
- <!-- 非医疗病史模式下的footer结构 -->
270
- <div v-else class="footer-grid">
271
- <div
272
- v-for="(item, idx) in config.footer.items"
273
- :key="item.field || idx"
274
- class="description-item">
275
- <div class="label-wrapper"><span class="label-text">{{ item.label }}:</span></div>
276
- <div
277
- class="content-wrapper"
278
- :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
279
- :data-full-text="data[item.field]"
280
- >{{ data[item.field] }}
281
- </div>
282
- </div>
283
- </div>
284
- <!-- 右侧信息:换到下一行并靠右对齐(如 医生 / 医嘱日期) -->
285
- <div
286
- v-if="!wrapperClassObject['xhdesc-medical-history'] && Array.isArray(config.footer.rightItems) && config.footer.rightItems.length"
287
- class="footer-right">
288
- <div
289
- v-for="(item, ridx) in config.footer.rightItems"
290
- :key="item.field || ridx"
291
- class="footer-right-item">
292
- <div class="label-wrapper"><span class="label-text">{{ item.label }}:</span></div>
293
- <div
294
- class="content-wrapper"
295
- :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
296
- :data-full-text="data[item.field]"
297
- >{{ data[item.field] }}
298
- </div>
299
- </div>
300
- </div>
301
- </div>
302
- </div>
303
- </div>
304
- </template>
305
-
306
- <script>
307
- import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
308
-
309
- export default {
310
- name: 'XHDescriptions',
311
- data () {
312
- return {
313
- // 隐藏配置 当数据结果 = -1^ 该数据字段会被delete
314
- hiddenConfig: '-1^',
315
- data: null,
316
- config: null,
317
- showAllItems: false // 控制是否显示所有标签
318
- }
319
- },
320
- props: {
321
- queryParamsName: {
322
- type: String,
323
- default: ''
324
- },
325
- parameter: {
326
- type: Object,
327
- default: () => {
328
- return {}
329
- }
330
- }
331
- },
332
- computed: {
333
- // 动态样式开关(与 HForm 思路一致):布尔开关 + size 派生类
334
- wrapperClassObject () {
335
- const attrs = this.$attrs || {}
336
- const classes = {}
337
-
338
- const booleanStyleKeys = [
339
- 'description',
340
- 'no-padding',
341
- 'medical-history',
342
- 'margin-top-12',
343
- 'padding-left15',
344
- 'line-height30'
345
- ]
346
- booleanStyleKeys.forEach(key => {
347
- const val = attrs[key]
348
- const truthy = val === true || val === '' || val === 'true'
349
- if (truthy) classes[`xhdesc-${key}`] = true
350
- })
351
- const size = attrs.size
352
- if (size && typeof size === 'string') classes[`xhdesc-size-${size}`] = true
353
- return classes
354
- },
355
- // 获取详情按钮应该显示在第几个标签后
356
- detailsAfterIndex () {
357
- return (this.config && this.config.detailsConfig && this.config.detailsConfig.showAfterIndex) || 999
358
- },
359
- // 判断是否有更多标签需要显示
360
- hasMoreItems () {
361
- if (!(this.config && this.config.detailsConfig)) return false
362
- if (!this.data || !(this.config && this.config.items) || !Array.isArray(this.config.items)) return false
363
- const hiddenStartIndex = this.detailsAfterIndex || 0
364
- if (hiddenStartIndex >= this.config.items.length) return false
365
- for (let i = hiddenStartIndex; i < this.config.items.length; i++) {
366
- const item = this.config.items[i]
367
- if (item && item.field && this.data[item.field] !== null && this.data[item.field] !== undefined) {
368
- return true
369
- }
370
- }
371
- return false
372
- },
373
- // 获取应该显示的标签
374
- visibleItems () {
375
- if (!(this.config && this.config.items)) return []
376
- if (!(this.config && this.config.detailsConfig)) return this.config.items
377
- if (this.showAllItems) return this.config.items.slice(0, this.detailsAfterIndex)
378
- return this.config.items.slice(0, this.detailsAfterIndex)
379
- },
380
- // 获取隐藏的标签(保持原有逻辑)
381
- hiddenItems () {
382
- if (!(this.config && this.config.items)) return []
383
- if (!(this.config && this.config.detailsConfig)) return []
384
- return this.config.items.slice(this.detailsAfterIndex)
385
- },
386
- // 过滤后可直接渲染的可见项
387
- visibleItemsFiltered () {
388
- const list = this.visibleItems || []
389
- if (!this.data) return []
390
- const res = list.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined)
391
- if (!this.showAllItems) return res
392
- const hiddenFields = new Set((this.hiddenItems || []).map(i => i.field))
393
- return res.filter(item => !hiddenFields.has(item.field))
394
- },
395
- // 过滤后可直接渲染的隐藏项(仅展开时使用)
396
- hiddenItemsFiltered () {
397
- const list = this.hiddenItems || []
398
- if (!this.data) return []
399
- return list.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined)
400
- }
401
- },
402
- created () {
403
- this.getData(this.queryParamsName, {})
404
- },
405
- methods: {
406
- async getData (data, parameterData) {
407
- this.data = null
408
- this.showAllItems = false
409
- getConfigByName(data, 'af-his', res => {
410
- this.config = res
411
- const hiddenConfig = (this.config && this.config.hiddenConfig) || (0 === 1)
412
- const parameter = { ...res.parameter, ...this.parameter, ...parameterData }
413
- runLogic(res.logicName, parameter, 'af-his').then(result => {
414
- if (hiddenConfig) {
415
- for (const key in result) {
416
- if (Object.prototype.hasOwnProperty.call(result, key) && result[key] === this.hiddenConfig) {
417
- delete result[key]
418
- }
419
- }
420
- }
421
- this.data = result
422
- })
423
- })
424
- },
425
- toggleDetails () {
426
- this.showAllItems = !this.showAllItems
427
- },
428
- // 判断内容是否超过三行
429
- isContentOverflow (content) {
430
- if (!content || typeof content !== 'string') return false
431
- return content.length > 150
432
- }
433
- },
434
- watch: {
435
- queryParamsName: {
436
- handler (newValue) {
437
- console.log(newValue)
438
- this.getData(newValue, {})
439
- },
440
- deep: true
441
- },
442
- parameter: {
443
- handler (newValue, oldValue) {
444
- console.log('监听事件触发:', { old: oldValue, new: newValue })
445
- // 当 parameter 变化时重新获取数据
446
- this.getData(this.queryParamsName, {})
447
- },
448
- deep: true // 深度监听对象内部变化
449
- }
450
- }
451
- }
452
- </script>
453
-
454
- <style scoped lang="less">
455
- .patient-info-descriptions {
456
- background: #fff;
457
- padding: 12px;
458
- border-radius: 4px;
459
- width: 100%;
460
- }
461
-
462
- .descriptions-container {
463
- position: relative;
464
- width: 100%;
465
- padding-right: 80px; /* 为按钮预留空间 */
466
- }
467
-
468
- /* 自适应布局样式 */
469
- .flex-descriptions {
470
- display: flex;
471
- flex-wrap: wrap;
472
- gap: 8px 24px;
473
- width: 100%;
474
- }
475
-
476
- .description-item {
477
- display: inline-flex;
478
- align-items: center;
479
- padding: 4px 8px;
480
- border-radius: 4px;
481
- transition: background-color 0.3s;
482
- white-space: nowrap;
483
- flex: 0 1 auto;
484
- }
485
-
486
- .description-item:hover {
487
- background-color: rgba(0, 0, 0, 0.02);
488
- }
489
-
490
- /* 共用样式 */
491
- .label-wrapper {
492
- display: flex;
493
- align-items: center;
494
- gap: 8px;
495
- color: rgba(0, 0, 0, 0.65);
496
- font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
497
- white-space: nowrap;
498
- }
499
-
500
- .label-text {
501
- white-space: nowrap;
502
- color: #313131; // 统一深灰
503
- text-decoration: none !important; // 移除下划线
504
- }
505
-
506
- .content-wrapper {
507
- display: inline-flex;
508
- align-items: center;
509
- margin-left: 4px;
510
- font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
511
- color: rgba(0, 0, 0, 0.85);
512
- text-decoration: none !important; // 移除可能的下划线
513
- max-width: 300px;
514
- overflow: hidden;
515
- text-overflow: ellipsis;
516
- white-space: nowrap;
517
- }
518
-
519
- /* 强制移除任何链接样式(如接口返回含 <a>) */
520
- ::v-deep a {
521
- color: #313131 !important;
522
- text-decoration: none !important;
523
- }
524
-
525
- .detail-button-wrapper {
526
- position: absolute;
527
- right: 0;
528
- top: 0;
529
- z-index: 10;
530
- padding: 4px 8px;
531
- white-space: nowrap;
532
- background-color: #fff;
533
- }
534
-
535
- /* 底部区域:分割线 + 三列内容 */
536
- .xhdesc-footer {
537
- margin-top: 12px;
538
- }
539
-
540
- .xhdesc-divider {
541
- width: calc(100% + 24px); /* 扩展到左右内边距之外 */
542
- height: 0;
543
- border-bottom: 1px solid #E5E9F0;
544
- margin: 10px -12px 14px; /* 抵消左右 12px 内边距 */
545
- overflow: hidden;
546
- }
547
- /* medical-history 模式:左 padding 11px,右 12px(由外层设置),做精确抵消 */
548
- .patient-info-descriptions.xhdesc-medical-history .xhdesc-divider {
549
- width: calc(100% + 23px);
550
- margin-left: -11px;
551
- margin-right: -12px;
552
- }
553
-
554
- .footer-grid {
555
- display: grid;
556
- grid-template-columns: 1fr; // 单列
557
- gap: 8px 24px; // 与上方描述项间距保持一致
558
- align-items: start; // 左上对齐
559
- }
560
-
561
- /* footer 区域的每项直接沿用通用 .description-item/.label-wrapper/.content-wrapper 样式 */
562
-
563
- .footer-right {
564
- margin-top: 8px;
565
- display: flex;
566
- justify-content: flex-end;
567
- align-items: center;
568
- gap: 16px;
569
- }
570
-
571
- .footer-right-item {
572
- display: inline-flex;
573
- align-items: center;
574
- }
575
-
576
- /* Ant Design 描述列表样式覆盖 */
577
- ::v-deep(.ant-descriptions-row) {
578
- display: flex;
579
- flex-direction: row;
580
- align-items: flex-start;
581
- }
582
-
583
- ::v-deep(.ant-descriptions-item) {
584
- padding: 0 !important;
585
- display: flex !important;
586
- align-items: flex-start !important;
587
- flex-direction: row !important;
588
- margin-right: 24px;
589
- width: fit-content !important;
590
- margin-bottom: 16px;
591
- }
592
-
593
- ::v-deep(.ant-descriptions-item-container) {
594
- display: flex !important;
595
- flex-direction: row !important;
596
- align-items: flex-start !important;
597
- position: relative;
598
- gap: 0 !important;
599
- width: 100% !important;
600
- }
601
-
602
- ::v-deep(.ant-descriptions-item-label) {
603
- color: rgba(0, 0, 0, 0.65);
604
- padding: 0 !important;
605
- margin: 0 !important;
606
- font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
607
- display: inline-flex !important;
608
- align-items: center !important;
609
- white-space: nowrap !important;
610
- min-width: v-bind('(config && config.style && config.style.labelWidth) || "80px"');
611
- justify-content: flex-start;
612
- padding-right: 2px !important;
613
- }
614
-
615
- ::v-deep(.ant-descriptions-item-content) {
616
- font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
617
- display: inline-flex !important;
618
- align-items: center !important;
619
- padding: 0 !important;
620
- margin: 0 !important;
621
- margin-left: 0px !important;
622
- }
623
-
624
- ::v-deep(.ant-descriptions-item-colon) {
625
- position: static !important;
626
- display: inline-flex !important;
627
- align-items: center !important;
628
- margin: 0 !important;
629
- padding: 0 !important;
630
- margin-right: 2px !important;
631
- }
632
-
633
- ::v-deep(.ant-descriptions-item-container:hover) {
634
- background-color: rgba(0, 0, 0, 0.02);
635
- border-radius: 4px;
636
- }
637
-
638
- ::v-deep(.ant-btn-link) {
639
- padding: 0;
640
- height: auto;
641
- line-height: 1;
642
- }
643
-
644
- ::v-deep(.ant-btn-link:hover) {
645
- color: #1890ff;
646
- background: transparent;
647
- }
648
-
649
- /* 响应式调整 */
650
- @media screen and (max-width: 768px) {
651
- .content-wrapper {
652
- max-width: 200px;
653
- }
654
- }
655
-
656
- @media screen and (max-width: 576px) {
657
- .content-wrapper {
658
- max-width: 150px;
659
- }
660
- .flex-descriptions {
661
- gap: 4px 12px;
662
- }
663
- }
664
-
665
- /* 添加虚线样式 */
666
- .with-divider {
667
- position: relative;
668
- margin-bottom: 16px !important;
669
- }
670
-
671
- .with-divider::after {
672
- content: '';
673
- position: absolute;
674
- left: 0;
675
- bottom: -8px;
676
- width: 100%;
677
- height: 0;
678
- border-bottom: 1px dashed rgba(0, 0, 0, 0.15);
679
- }
680
-
681
- /* 对于 Ant Design 描述列表的特殊处理 */
682
- ::v-deep(.ant-descriptions-item.with-divider) {
683
- position: relative;
684
- margin-bottom: 16px !important;
685
- }
686
-
687
- ::v-deep(.ant-descriptions-item.with-divider::after) {
688
- content: '';
689
- position: absolute;
690
- left: 0;
691
- bottom: -8px;
692
- width: 100%;
693
- height: 0;
694
- border-bottom: 1px dashed rgba(0, 0, 0, 0.15);
695
- }
696
-
697
- /* 加边框 */
698
- .xhdesc-description {
699
- padding: 4px 4px 4px 4px;
700
-
701
- /* 作用域内 *patient-info-descriptions */
702
- &.patient-info-descriptions,
703
- .patient-info-descriptions {
704
- border: 1px solid #E5E9F0;
705
- border-radius: 6px;
706
- padding: 6.5px 12px;
707
-
708
- /* *ant-btn-link */
709
- ::v-deep .ant-btn-link {
710
- border: none;
711
- }
712
-
713
- /* *ant-descriptions-item-content */
714
- ::v-deep .ant-descriptions-item-content {
715
- font-weight: bold;
716
- }
717
- }
718
- }
719
- // 去除住院收费页面两个描述列表之间的间距
720
- .xhdesc-margin-top-12 {
721
- margin-top: -12px;
722
- }
723
- .xhdesc-no-padding {
724
- padding: 0px;
725
- &.patient-info-descriptions,
726
- .patient-info-descriptions {
727
- /* *ant-descriptions-item-content */
728
- ::v-deep .descriptions-container {
729
- padding: 0px;
730
- }
731
- ::v-deep .content-wrapper {
732
- margin: 0px;
733
- }
734
- }
735
- }
736
- // 库存管理左侧边距
737
- .xhdesc-padding-left15{
738
- padding-left: 15px;
739
- }
740
- // 库存管理左侧字体样式
741
- .xhdesc-line-height30{
742
- &.patient-info-descriptions,
743
- .patient-info-descriptions{
744
- ::v-deep .ant-descriptions-item{
745
- margin-bottom: 0px
746
- }
747
- ::v-deep .content-wrapper{
748
- line-height: 30px;
749
- }
750
- ::v-deep .ant-descriptions-item-label{
751
- line-height: 30px;
752
- }
753
- ::v-deep .content-wrapper{
754
- color: #0057FE;
755
- font-weight: 700
756
- }
757
- }
758
- }
759
- /* 医疗病史模式:自定义HTML结构样式 */
760
- .medical-history-descriptions {
761
- width: 100%;
762
- }
763
-
764
- .medical-history-item {
765
- margin: 0;
766
- width: 100%;
767
- }
768
-
769
- .medical-history-item.with-divider {
770
- position: relative;
771
- padding-bottom: 4px; /* 分割线与上方间距 4px */
772
- margin-bottom: 4px; /* 分割线与下方间距 4px */
773
- }
774
-
775
- .medical-history-item.with-divider::after {
776
- content: '';
777
- position: absolute;
778
- left: 0;
779
- bottom: 0; /* 贴合容器底部 */
780
- width: 100%;
781
- height: 0;
782
- border-bottom: 1px solid rgba(0, 0, 0, 0.15);
783
- }
784
-
785
- .medical-history-content {
786
- font-family: "Source Han Sans";
787
- font-size: 18px;
788
- line-height: 24px;
789
- letter-spacing: 0em;
790
- text-align: left;
791
- word-break: break-word;
792
- white-space: normal;
793
- text-indent: 0;
794
- padding-left: 0;
795
- margin-left: 0;
796
- /* 使用float实现真正的文本环绕 */
797
- overflow: hidden;
798
- /* 确保容器能够正确清除浮动 */
799
- position: relative;
800
- }
801
-
802
- .medical-history-label {
803
- font-family: "Source Han Sans";
804
- font-size: 16px;
805
- font-weight: 700;
806
- color: #313131;
807
- white-space: nowrap;
808
- float: left;
809
- margin-right: 0px;
810
- /* 确保标签不会影响文本流 */
811
- position: relative;
812
- z-index: 1;
813
- }
814
-
815
- .medical-history-text {
816
- font-family: "Source Han Sans";
817
- font-size: 16px;
818
- font-weight: 400;
819
- color: #313131;
820
- display: block;
821
- overflow: hidden;
822
- text-indent: 0;
823
- padding-left: 0;
824
- margin-left: 0;
825
- word-break: break-word;
826
- white-space: normal;
827
- text-align: left;
828
- line-height: 24px;
829
- /* 确保文本能够正确环绕浮动元素 */
830
- margin-top: 0;
831
- margin-bottom: 0;
832
- }
833
-
834
- .medical-history-text.ellipsis {
835
- display: -webkit-box;
836
- -webkit-box-orient: vertical;
837
- -webkit-line-clamp: 3;
838
- line-clamp: 3;
839
- overflow: hidden;
840
- cursor: pointer;
841
- position: relative;
842
- word-break: break-word;
843
- white-space: normal;
844
- line-height: 24px;
845
- text-indent: 0;
846
- padding-left: 0;
847
- margin-left: 0;
848
- text-align: left;
849
- -webkit-box-pack: start;
850
- -webkit-box-align: start;
851
- }
852
-
853
- /* 使用-webkit-line-clamp时不需要手动添加省略号 */
854
- .medical-history-text.ellipsis::after {
855
- display: none;
856
- }
857
-
858
- /* 针对多行文本的特殊处理:确保换行文本与首行对齐 */
859
- .medical-history-text.ellipsis::first-line {
860
- text-indent: 0;
861
- }
862
-
863
- /* 为不支持-webkit-line-clamp的浏览器提供后备方案 */
864
- @supports not (-webkit-line-clamp: 3) {
865
- .medical-history-text.ellipsis {
866
- display: block;
867
- max-height: 72px; /* 3行 * 24px行高 */
868
- overflow: hidden;
869
- position: relative;
870
- }
871
-
872
- .medical-history-text.ellipsis::after {
873
- content: '...';
874
- position: absolute;
875
- right: 0;
876
- bottom: 0;
877
- background: #fff;
878
- padding-left: 4px;
879
- display: block;
880
- }
881
- }
882
-
883
- /* 医疗病史样式开关:通过 wrapperClassObject 添加类 xhdesc-medical-history */
884
- .patient-info-descriptions.xhdesc-medical-history {
885
- padding: 9px 12px 10px 11px !important;
886
- /* 移除右侧空白(本模式不需要详情按钮预留空间) */
887
- .descriptions-container {
888
- padding-right: 0;
889
- padding-left: 0px;
890
- }
891
- /* 医疗病史模式下:footer 区域使用与上方相同的医疗病史样式 */
892
- .medical-history-footer {
893
- width: 100%;
894
- }
895
- .medical-history-footer .footer-right {
896
- margin-top: 8px;
897
- display: flex;
898
- justify-content: flex-end;
899
- align-items: flex-start;
900
- gap: 16px;
901
- width: 100%;
902
- }
903
- /* 右侧(医生/医嘱日期)标签与值的字体要求 */
904
- .medical-history-footer .footer-right .label-wrapper .label-text {
905
- font-family: "Source Han Sans";
906
- font-size: 16px;
907
- font-weight: 700;
908
- color: #313131;
909
- line-height: 22px;
910
- }
911
- .medical-history-footer .footer-right .content-wrapper {
912
- font-family: "Source Han Sans";
913
- font-size: 16px;
914
- font-weight: 400;
915
- line-height: 22px;
916
- color: #313131;
917
- }
918
-
919
- .medical-history-footer .footer-right .medical-history-item {
920
- display: inline-block;
921
- text-align: right;
922
- }
923
-
924
- .medical-history-footer .footer-right .medical-history-content {
925
- text-align: right;
926
- }
927
-
928
- .medical-history-footer .footer-right .medical-history-label {
929
- float: none;
930
- display: inline;
931
- margin-right: 0px;
932
- }
933
-
934
- .medical-history-footer .footer-right .medical-history-text {
935
- display: inline;
936
- text-align: right;
937
- }
938
-
939
- .medical-history-footer .footer-right .medical-history-text.ellipsis {
940
- display: inline;
941
- text-align: right;
942
- }
943
- }
944
- </style>
1
+ <template>
2
+ <div class="patient-info-descriptions" :class="wrapperClassObject">
3
+ <div class="descriptions-container">
4
+ <!-- 详情/收起按钮 -->
5
+ <div v-if="hasMoreItems" class="detail-button-wrapper">
6
+ <a-button
7
+ :type="(config && config.detailsConfig && config.detailsConfig.buttonType) || 'link'"
8
+ @click="toggleDetails"
9
+ >
10
+ {{ showAllItems ? '收起' : ((config && config.detailsConfig && config.detailsConfig.buttonText) || '详情') }}
11
+ <a-icon :type="showAllItems ? 'up' : 'down'" />
12
+ </a-button>
13
+ </div>
14
+
15
+ <!-- 当有 layout 配置时使用 a-descriptions -->
16
+ <template v-if="config && config.layout && !wrapperClassObject['xhdesc-medical-history']">
17
+ <a-descriptions
18
+ :column="config.layout"
19
+ :size="(config && config.style && config.style.size)"
20
+ :bordered="(config && config.style && config.style.bordered)"
21
+ layout="horizontal">
22
+ <template v-if="data">
23
+ <!-- 显示前N个标签 -->
24
+ <a-descriptions-item
25
+ v-for="(item) in visibleItemsFiltered"
26
+ :key="item.field"
27
+ :colon="item.colon !== false"
28
+ :class="{ 'with-divider': item.isLine }">
29
+ <template #label>
30
+ <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
31
+ <div v-if="item.showAvatar" class="gender-icon">
32
+ <img :src="maleIcon" alt="male" class="gender-img" />
33
+ </div>
34
+ <span class="label-text">{{ item.label }}</span>
35
+ </div>
36
+ </template>
37
+ <a-tooltip
38
+ v-if="isContentOverflow(data[item.field])"
39
+ :title="data[item.field]"
40
+ placement="topLeft"
41
+ :overlay-style="{ maxWidth: '400px' }"
42
+ >
43
+ <div
44
+ class="content-wrapper ellipsis"
45
+ :data-full-text="data[item.field]"
46
+ >
47
+ {{ data[item.field] }}
48
+ </div>
49
+ </a-tooltip>
50
+ <div
51
+ v-else
52
+ class="content-wrapper"
53
+ :data-full-text="data[item.field]"
54
+ >
55
+ {{ data[item.field] }}
56
+ </div>
57
+ </a-descriptions-item>
58
+
59
+ <!-- 展开后显示剩余标签 -->
60
+ <template v-if="showAllItems">
61
+ <a-descriptions-item
62
+ v-for="item in hiddenItemsFiltered"
63
+ :key="item.field"
64
+ :colon="item.colon !== false">
65
+ <template #label>
66
+ <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
67
+ <div v-if="item.showAvatar" class="gender-icon">
68
+ <img :src="maleIcon" alt="male" class="gender-img" />
69
+ </div>
70
+ <span class="label-text">{{ item.label }}</span>
71
+ </div>
72
+ </template>
73
+ <div
74
+ class="content-wrapper"
75
+ :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
76
+ :data-full-text="data[item.field]"
77
+ >
78
+ {{ data[item.field] }}
79
+ </div>
80
+ </a-descriptions-item>
81
+ </template>
82
+ </template>
83
+ </a-descriptions>
84
+ </template>
85
+
86
+ <!-- 医疗病史模式:使用自定义HTML结构实现文本环绕 -->
87
+ <template v-else-if="config && config.layout && wrapperClassObject['xhdesc-medical-history']">
88
+ <div class="medical-history-descriptions">
89
+ <template v-if="data">
90
+ <!-- 显示前N个标签 -->
91
+ <div
92
+ v-for="(item) in visibleItemsFiltered"
93
+ :key="item.field"
94
+ :class="['medical-history-item', { 'with-divider': item.isLine }]"
95
+ >
96
+ <div class="medical-history-content">
97
+ <a-tooltip
98
+ v-if="isContentOverflow(data[item.field])"
99
+ :title="data[item.field]"
100
+ placement="topLeft"
101
+ :overlay-style="{ maxWidth: '400px' }"
102
+ >
103
+ <div class="medical-history-text ellipsis">
104
+ <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
105
+ </div>
106
+ </a-tooltip>
107
+ <div
108
+ v-else
109
+ class="medical-history-text"
110
+ >
111
+ <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <!-- 展开后显示剩余标签 -->
117
+ <template v-if="showAllItems">
118
+ <div
119
+ v-for="item in hiddenItemsFiltered"
120
+ :key="item.field"
121
+ class="medical-history-item"
122
+ >
123
+ <div class="medical-history-content">
124
+ <a-tooltip
125
+ v-if="isContentOverflow(data[item.field])"
126
+ :title="data[item.field]"
127
+ placement="topLeft"
128
+ :overlay-style="{ maxWidth: '400px' }"
129
+ >
130
+ <div class="medical-history-text ellipsis">
131
+ <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
132
+ </div>
133
+ </a-tooltip>
134
+ <div
135
+ v-else
136
+ class="medical-history-text"
137
+ >
138
+ <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </template>
143
+ </template>
144
+ </div>
145
+ </template>
146
+
147
+ <!-- 当没有 layout 配置时使用自适应布局 -->
148
+ <template v-else>
149
+ <div class="flex-descriptions">
150
+ <template v-if="data">
151
+ <!-- 显示可见的标签 -->
152
+ <div
153
+ v-for="(item) in visibleItemsFiltered"
154
+ :key="item.field"
155
+ :class="['description-item', { 'with-divider': item.isLine }]"
156
+ >
157
+ <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
158
+ <div v-if="item.showAvatar" class="gender-icon">
159
+ <img :src="maleIcon" alt="male" class="gender-img" />
160
+ </div>
161
+ <span class="label-text">{{ item.label }}:</span>
162
+ </div>
163
+ <a-tooltip
164
+ v-if="isContentOverflow(data[item.field])"
165
+ :title="data[item.field]"
166
+ placement="topLeft"
167
+ :overlay-style="{ maxWidth: '400px' }"
168
+ >
169
+ <div
170
+ class="content-wrapper ellipsis"
171
+ :data-full-text="data[item.field]"
172
+ >
173
+ {{ data[item.field] }}
174
+ </div>
175
+ </a-tooltip>
176
+ <div
177
+ v-else
178
+ class="content-wrapper"
179
+ :data-full-text="data[item.field]"
180
+ >
181
+ {{ data[item.field] }}
182
+ </div>
183
+ </div>
184
+
185
+ <!-- 展开后显示的内容 -->
186
+ <template v-if="showAllItems">
187
+ <div
188
+ v-for="item in hiddenItemsFiltered"
189
+ :key="item.field"
190
+ class="description-item"
191
+ >
192
+ <div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
193
+ <div v-if="item.showAvatar" class="gender-icon">
194
+ <img :src="maleIcon" alt="male" class="gender-img" />
195
+ </div>
196
+ <span class="label-text">{{ item.label }}:</span>
197
+ </div>
198
+ <div
199
+ class="content-wrapper"
200
+ :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
201
+ :data-full-text="data[item.field]"
202
+ >
203
+ {{ data[item.field] }}
204
+ </div>
205
+ </div>
206
+ </template>
207
+ </template>
208
+ </div>
209
+ </template>
210
+
211
+ <!-- 可选:底部区域(分割线 + 三列内容) -->
212
+ <div v-if="config && config.footer && Array.isArray(config.footer.items) && data" class="xhdesc-footer">
213
+ <div class="xhdesc-divider" />
214
+ <!-- 医疗病史模式下的footer结构 -->
215
+ <div v-if="wrapperClassObject['xhdesc-medical-history']" class="medical-history-footer">
216
+ <div
217
+ v-for="(item, idx) in config.footer.items"
218
+ :key="item.field || idx"
219
+ class="medical-history-item">
220
+ <div class="medical-history-content">
221
+ <a-tooltip
222
+ v-if="isContentOverflow(data[item.field])"
223
+ :title="data[item.field]"
224
+ placement="topLeft"
225
+ :overlay-style="{ maxWidth: '400px' }"
226
+ >
227
+ <div class="medical-history-text ellipsis">
228
+ <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
229
+ </div>
230
+ </a-tooltip>
231
+ <div
232
+ v-else
233
+ class="medical-history-text"
234
+ >
235
+ <span class="medical-history-label">{{ item.label }}:</span>{{ data[item.field] }}
236
+ </div>
237
+ </div>
238
+ </div>
239
+ <!-- 右侧信息:换到下一行并靠右对齐(如 医生 / 医嘱日期) -->
240
+ <div
241
+ v-if="Array.isArray(config.footer.rightItems) && config.footer.rightItems.length"
242
+ class="footer-right">
243
+ <div
244
+ v-for="(item, ridx) in config.footer.rightItems"
245
+ :key="item.field || ridx"
246
+ class="footer-right-item">
247
+ <div class="label-wrapper"><span class="label-text">{{ item.label }}:</span></div>
248
+ <div
249
+ class="content-wrapper"
250
+ :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
251
+ :data-full-text="data[item.field]"
252
+ >{{ data[item.field] }}
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ <!-- 非医疗病史模式下的footer结构 -->
258
+ <div v-else class="footer-grid">
259
+ <div
260
+ v-for="(item, idx) in config.footer.items"
261
+ :key="item.field || idx"
262
+ class="description-item">
263
+ <div class="label-wrapper"><span class="label-text">{{ item.label }}:</span></div>
264
+ <div
265
+ class="content-wrapper"
266
+ :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
267
+ :data-full-text="data[item.field]"
268
+ >{{ data[item.field] }}
269
+ </div>
270
+ </div>
271
+ </div>
272
+ <!-- 右侧信息:换到下一行并靠右对齐(如 医生 / 医嘱日期) -->
273
+ <div
274
+ v-if="!wrapperClassObject['xhdesc-medical-history'] && Array.isArray(config.footer.rightItems) && config.footer.rightItems.length"
275
+ class="footer-right">
276
+ <div
277
+ v-for="(item, ridx) in config.footer.rightItems"
278
+ :key="item.field || ridx"
279
+ class="footer-right-item">
280
+ <div class="label-wrapper"><span class="label-text">{{ item.label }}:</span></div>
281
+ <div
282
+ class="content-wrapper"
283
+ :class="{ 'ellipsis': isContentOverflow(data[item.field]) }"
284
+ :data-full-text="data[item.field]"
285
+ >{{ data[item.field] }}
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+ </div>
291
+ </div>
292
+ </template>
293
+
294
+ <script>
295
+ import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
296
+
297
+ export default {
298
+ name: 'XHDescriptions',
299
+ data () {
300
+ return {
301
+ // 隐藏配置 当数据结果 = -1^ 该数据字段会被delete
302
+ hiddenConfig: '-1^',
303
+ data: null,
304
+ config: null,
305
+ showAllItems: false, // 控制是否显示所有标签
306
+ maleIcon: require('@vue2-client/assets/svg/male.svg')
307
+ }
308
+ },
309
+ props: {
310
+ queryParamsName: {
311
+ type: String,
312
+ default: ''
313
+ },
314
+ parameter: {
315
+ type: Object,
316
+ default: () => {
317
+ return {}
318
+ }
319
+ }
320
+ },
321
+ computed: {
322
+ // 动态样式开关(与 HForm 思路一致):布尔开关 + size 派生类
323
+ wrapperClassObject () {
324
+ const attrs = this.$attrs || {}
325
+ const classes = {}
326
+
327
+ const booleanStyleKeys = [
328
+ 'description',
329
+ 'no-padding',
330
+ 'medical-history',
331
+ 'patient-style',
332
+ 'margin-top-12',
333
+ 'padding-left15',
334
+ 'line-height30'
335
+ ]
336
+ booleanStyleKeys.forEach(key => {
337
+ const val = attrs[key]
338
+ const truthy = val === true || val === '' || val === 'true'
339
+ if (truthy) classes[`xhdesc-${key}`] = true
340
+ })
341
+ const size = attrs.size
342
+ if (size && typeof size === 'string') classes[`xhdesc-size-${size}`] = true
343
+ // 展开态样式开关(用于 patient-style 动态高度)
344
+ if (this.showAllItems && this.config && this.config.detailsConfig) classes['xhdesc-open'] = true
345
+ return classes
346
+ },
347
+ // 获取详情按钮应该显示在第几个标签后
348
+ detailsAfterIndex () {
349
+ return (this.config && this.config.detailsConfig && this.config.detailsConfig.showAfterIndex) || 999
350
+ },
351
+ // 判断是否有更多标签需要显示
352
+ hasMoreItems () {
353
+ if (!(this.config && this.config.detailsConfig)) return false
354
+ if (!this.data || !(this.config && this.config.items) || !Array.isArray(this.config.items)) return false
355
+ const hiddenStartIndex = this.detailsAfterIndex || 0
356
+ if (hiddenStartIndex >= this.config.items.length) return false
357
+ for (let i = hiddenStartIndex; i < this.config.items.length; i++) {
358
+ const item = this.config.items[i]
359
+ if (item && item.field && this.data[item.field] !== null && this.data[item.field] !== undefined) {
360
+ return true
361
+ }
362
+ }
363
+ return false
364
+ },
365
+ // 获取应该显示的标签
366
+ visibleItems () {
367
+ if (!(this.config && this.config.items)) return []
368
+ if (!(this.config && this.config.detailsConfig)) return this.config.items
369
+ if (this.showAllItems) return this.config.items.slice(0, this.detailsAfterIndex)
370
+ return this.config.items.slice(0, this.detailsAfterIndex)
371
+ },
372
+ // 获取隐藏的标签(保持原有逻辑)
373
+ hiddenItems () {
374
+ if (!(this.config && this.config.items)) return []
375
+ if (!(this.config && this.config.detailsConfig)) return []
376
+ return this.config.items.slice(this.detailsAfterIndex)
377
+ },
378
+ // 过滤后可直接渲染的可见项
379
+ visibleItemsFiltered () {
380
+ const list = this.visibleItems || []
381
+ if (!this.data) return []
382
+ const res = list.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined)
383
+ if (!this.showAllItems) return res
384
+ const hiddenFields = new Set((this.hiddenItems || []).map(i => i.field))
385
+ return res.filter(item => !hiddenFields.has(item.field))
386
+ },
387
+ // 过滤后可直接渲染的隐藏项(仅展开时使用)
388
+ hiddenItemsFiltered () {
389
+ const list = this.hiddenItems || []
390
+ if (!this.data) return []
391
+ return list.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined)
392
+ }
393
+ },
394
+ created () {
395
+ this.getData(this.queryParamsName, {})
396
+ },
397
+ methods: {
398
+ async getData (data, parameterData) {
399
+ this.data = null
400
+ this.showAllItems = false
401
+ getConfigByName(data, 'af-his', res => {
402
+ this.config = res
403
+ const hiddenConfig = (this.config && this.config.hiddenConfig) || (0 === 1)
404
+ const parameter = { ...res.parameter, ...this.parameter, ...parameterData }
405
+ runLogic(res.logicName, parameter, 'af-his').then(result => {
406
+ if (hiddenConfig) {
407
+ for (const key in result) {
408
+ if (Object.prototype.hasOwnProperty.call(result, key) && result[key] === this.hiddenConfig) {
409
+ delete result[key]
410
+ }
411
+ }
412
+ }
413
+ this.data = result
414
+ })
415
+ })
416
+ },
417
+ toggleDetails () {
418
+ this.showAllItems = !this.showAllItems
419
+ },
420
+ // 判断内容是否超过三行
421
+ isContentOverflow (content) {
422
+ if (!content || typeof content !== 'string') return false
423
+ return content.length > 150
424
+ }
425
+ },
426
+ watch: {
427
+ queryParamsName: {
428
+ handler (newValue) {
429
+ console.log(newValue)
430
+ this.getData(newValue, {})
431
+ },
432
+ deep: true
433
+ },
434
+ parameter: {
435
+ handler (newValue, oldValue) {
436
+ console.log('监听事件触发:', { old: oldValue, new: newValue })
437
+ // 当 parameter 变化时重新获取数据
438
+ this.getData(this.queryParamsName, {})
439
+ },
440
+ deep: true // 深度监听对象内部变化
441
+ }
442
+ }
443
+ }
444
+ </script>
445
+
446
+ <style scoped lang="less">
447
+ .patient-info-descriptions {
448
+ background: #fff;
449
+ border-radius: 4px;
450
+ width: 100%;
451
+ }
452
+
453
+ .descriptions-container {
454
+ position: relative;
455
+ width: 100%;
456
+ padding-right: 80px; /* 为按钮预留空间 */
457
+ }
458
+
459
+ /* 自适应布局样式 */
460
+ .flex-descriptions {
461
+ display: flex;
462
+ flex-wrap: wrap;
463
+ gap: 8px 24px;
464
+ width: 100%;
465
+ }
466
+
467
+ .description-item {
468
+ display: inline-flex;
469
+ align-items: center;
470
+ padding: 4px 8px;
471
+ border-radius: 4px;
472
+ transition: background-color 0.3s;
473
+ white-space: nowrap;
474
+ flex: 0 1 auto;
475
+ }
476
+
477
+ .description-item:hover {
478
+ background-color: rgba(0, 0, 0, 0.02);
479
+ }
480
+
481
+ /* 共用样式 */
482
+ .label-wrapper {
483
+ display: flex;
484
+ align-items: center;
485
+ gap: 8px;
486
+ color: rgba(0, 0, 0, 0.65);
487
+ font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
488
+ white-space: nowrap;
489
+ }
490
+
491
+ .label-text {
492
+ white-space: nowrap;
493
+ color: #313131; // 统一深灰
494
+ text-decoration: none !important; // 移除下划线
495
+ }
496
+
497
+ .content-wrapper {
498
+ display: inline-flex;
499
+ align-items: center;
500
+ margin-left: 4px;
501
+ font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
502
+ color: rgba(0, 0, 0, 0.85);
503
+ text-decoration: none !important; // 移除可能的下划线
504
+ max-width: 300px;
505
+ overflow: hidden;
506
+ text-overflow: ellipsis;
507
+ white-space: nowrap;
508
+ }
509
+
510
+ /* 强制移除任何链接样式(如接口返回含 <a>) */
511
+ ::v-deep a {
512
+ color: #313131 !important;
513
+ text-decoration: none !important;
514
+ }
515
+
516
+ .detail-button-wrapper {
517
+ position: absolute;
518
+ right: 0;
519
+ top: 0;
520
+ z-index: 10;
521
+ padding: 4px 8px;
522
+ white-space: nowrap;
523
+ background-color: #fff;
524
+ }
525
+
526
+ /* 底部区域:分割线 + 三列内容 */
527
+ .xhdesc-footer {
528
+ margin-top: 12px;
529
+ }
530
+
531
+ .xhdesc-divider {
532
+ width: calc(100% + 24px); /* 扩展到左右内边距之外 */
533
+ height: 0;
534
+ border-bottom: 1px solid #E5E9F0;
535
+ margin: 10px -12px 14px; /* 抵消左右 12px 内边距 */
536
+ overflow: hidden;
537
+ }
538
+ /* medical-history 模式:左 padding 11px,右 12px(由外层设置),做精确抵消 */
539
+ .patient-info-descriptions.xhdesc-medical-history .xhdesc-divider {
540
+ width: calc(100% + 23px);
541
+ margin-left: -11px;
542
+ margin-right: -12px;
543
+ }
544
+
545
+ .footer-grid {
546
+ display: grid;
547
+ grid-template-columns: 1fr; // 单列
548
+ gap: 8px 24px; // 与上方描述项间距保持一致
549
+ align-items: start; // 左上对齐
550
+ }
551
+
552
+ /* footer 区域的每项直接沿用通用 .description-item/.label-wrapper/.content-wrapper 样式 */
553
+
554
+ .footer-right {
555
+ margin-top: 8px;
556
+ display: flex;
557
+ justify-content: flex-end;
558
+ align-items: center;
559
+ gap: 16px;
560
+ }
561
+
562
+ .footer-right-item {
563
+ display: inline-flex;
564
+ align-items: center;
565
+ }
566
+
567
+ /* Ant Design 描述列表样式覆盖 */
568
+ ::v-deep(.ant-descriptions-row) {
569
+ display: flex;
570
+ flex-direction: row;
571
+ align-items: flex-start;
572
+ }
573
+
574
+ ::v-deep(.ant-descriptions-item) {
575
+ padding: 0 !important;
576
+ display: flex !important;
577
+ align-items: flex-start !important;
578
+ flex-direction: row !important;
579
+ margin-right: 24px;
580
+ width: fit-content !important;
581
+ margin-bottom: 16px;
582
+ }
583
+
584
+ ::v-deep(.ant-descriptions-item-container) {
585
+ display: flex !important;
586
+ flex-direction: row !important;
587
+ align-items: flex-start !important;
588
+ position: relative;
589
+ gap: 0 !important;
590
+ width: 100% !important;
591
+ }
592
+
593
+ ::v-deep(.ant-descriptions-item-label) {
594
+ color: rgba(0, 0, 0, 0.65);
595
+ padding: 0 !important;
596
+ margin: 0 !important;
597
+ font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
598
+ display: inline-flex !important;
599
+ align-items: center !important;
600
+ white-space: nowrap !important;
601
+ min-width: v-bind('(config && config.style && config.style.labelWidth) || "80px"');
602
+ justify-content: flex-start;
603
+ padding-right: 2px !important;
604
+ }
605
+
606
+ ::v-deep(.ant-descriptions-item-content) {
607
+ font-size: v-bind('(config && config.style && config.style.fontSize) || "14px"');
608
+ display: inline-flex !important;
609
+ align-items: center !important;
610
+ padding: 0 !important;
611
+ margin: 0 !important;
612
+ margin-left: 0px !important;
613
+ }
614
+
615
+ ::v-deep(.ant-descriptions-item-colon) {
616
+ position: static !important;
617
+ display: inline-flex !important;
618
+ align-items: center !important;
619
+ margin: 0 !important;
620
+ padding: 0 !important;
621
+ margin-right: 2px !important;
622
+ }
623
+
624
+ ::v-deep(.ant-descriptions-item-container:hover) {
625
+ background-color: rgba(0, 0, 0, 0.02);
626
+ border-radius: 4px;
627
+ }
628
+
629
+ ::v-deep(.ant-btn-link) {
630
+ padding: 0;
631
+ height: auto;
632
+ line-height: 1;
633
+ }
634
+
635
+ ::v-deep(.ant-btn-link:hover) {
636
+ color: #1890ff;
637
+ background: transparent;
638
+ }
639
+
640
+ /* 响应式调整 */
641
+ @media screen and (max-width: 768px) {
642
+ .content-wrapper {
643
+ max-width: 200px;
644
+ }
645
+ }
646
+
647
+ @media screen and (max-width: 576px) {
648
+ .content-wrapper {
649
+ max-width: 150px;
650
+ }
651
+ .flex-descriptions {
652
+ gap: 4px 12px;
653
+ }
654
+ }
655
+
656
+ /* 添加虚线样式 */
657
+ .with-divider {
658
+ position: relative;
659
+ margin-bottom: 16px !important;
660
+ }
661
+
662
+ .with-divider::after {
663
+ content: '';
664
+ position: absolute;
665
+ left: 0;
666
+ bottom: -8px;
667
+ width: 100%;
668
+ height: 0;
669
+ border-bottom: 1px dashed rgba(0, 0, 0, 0.15);
670
+ }
671
+
672
+ /* 对于 Ant Design 描述列表的特殊处理 */
673
+ ::v-deep(.ant-descriptions-item.with-divider) {
674
+ position: relative;
675
+ margin-bottom: 16px !important;
676
+ }
677
+
678
+ ::v-deep(.ant-descriptions-item.with-divider::after) {
679
+ content: '';
680
+ position: absolute;
681
+ left: 0;
682
+ bottom: -8px;
683
+ width: 100%;
684
+ height: 0;
685
+ border-bottom: 1px dashed rgba(0, 0, 0, 0.15);
686
+ }
687
+
688
+ /* 加边框 */
689
+ .xhdesc-description {
690
+ padding: 4px 4px 4px 4px;
691
+
692
+ /* 作用域内 *patient-info-descriptions */
693
+ &.patient-info-descriptions,
694
+ .patient-info-descriptions {
695
+ border: 1px solid #E5E9F0;
696
+ border-radius: 6px;
697
+ padding: 6.5px 12px;
698
+
699
+ /* *ant-btn-link */
700
+ ::v-deep .ant-btn-link {
701
+ border: none;
702
+ }
703
+
704
+ /* *ant-descriptions-item-content */
705
+ ::v-deep .ant-descriptions-item-content {
706
+ font-weight: bold;
707
+ }
708
+ }
709
+ }
710
+ /* 病患信息样式开关:patient-style */
711
+ .xhdesc-patient-style {
712
+ height: 41px;
713
+ border-radius: 6px;
714
+ opacity: 1;
715
+ background: #FFFFFF;
716
+ box-sizing: border-box;
717
+ border: 0px solid #E5E9F0;
718
+ padding-bottom: 0px !important;
719
+ width: 100%;
720
+ &.patient-info-descriptions,
721
+ .patient-info-descriptions {
722
+ border: 0px solid #E5E9F0;
723
+ border-radius: 6px;
724
+ background: #FFFFFF;
725
+ height: 41px;
726
+ display: flex;
727
+ align-items: center;
728
+
729
+ /* 标签字体(label):统一 16px,与值一致 */
730
+ ::v-deep .label-wrapper .label-text {
731
+ font-family: "Source Han Sans";
732
+ font-size: 16px !important;
733
+ font-weight: 400 !important; /* 确保不加粗 */
734
+ line-height: 23px !important;
735
+ letter-spacing: 0em;
736
+ font-feature-settings: "kern" on;
737
+ color: #5D5C5C;
738
+ }
739
+
740
+ /* 头像与标签的间距 9px */
741
+ ::v-deep .label-wrapper.with-avatar {
742
+ gap: 9px;
743
+ }
744
+
745
+ /* 性别图标样式 */
746
+ .gender-icon {
747
+ margin-top: 2px;
748
+ }
749
+ .gender-img {
750
+ width: 20px;
751
+ height: 20px;
752
+ opacity: 1;
753
+ display: inline-block;
754
+ }
755
+
756
+ /* 详情箭头在文字右侧:颜色、间距、方向(不旋转) */
757
+ ::v-deep .detail-button-wrapper .ant-btn .anticon {
758
+ margin-left: 4px;
759
+ color: #94979E;
760
+ opacity: 1;
761
+ }
762
+
763
+ /* 详情按钮文字字体规范 */
764
+ ::v-deep .detail-button-wrapper .ant-btn,
765
+ ::v-deep .detail-button-wrapper .ant-btn span {
766
+ font-family: "Source Han Sans";
767
+ font-size: 16px;
768
+ color: #5D5C5C;
769
+ }
770
+
771
+ /* 值字体(content) */
772
+ ::v-deep .ant-descriptions-item-content,
773
+ ::v-deep .content-wrapper,
774
+ .medical-history-text {
775
+ font-family: "Source Han Sans";
776
+ font-size: 16px !important;
777
+ font-weight: 700;
778
+ line-height: 23px !important;
779
+ letter-spacing: 0em;
780
+ font-feature-settings: "kern" on;
781
+ color: #5D5C5C;
782
+ }
783
+ }
784
+ }
785
+
786
+ /* 展开态:patient-style 自适应高度与顶部对齐,防止布局错乱 */
787
+ .xhdesc-patient-style.xhdesc-open,
788
+ .xhdesc-open .patient-info-descriptions.xhdesc-patient-style,
789
+ .xhdesc-open .xhdesc-patient-style .patient-info-descriptions {
790
+ height: auto;
791
+ }
792
+ .xhdesc-patient-style.xhdesc-open .patient-info-descriptions,
793
+ .xhdesc-open .patient-info-descriptions.xhdesc-patient-style,
794
+ .xhdesc-open .xhdesc-patient-style .patient-info-descriptions {
795
+ align-items: flex-start;
796
+ }
797
+ // 去除住院收费页面两个描述列表之间的间距
798
+ .xhdesc-margin-top-12 {
799
+ margin-top: -12px;
800
+ }
801
+ .xhdesc-no-padding {
802
+ padding: 0px;
803
+ &.patient-info-descriptions,
804
+ .patient-info-descriptions {
805
+ /* *ant-descriptions-item-content */
806
+ ::v-deep .descriptions-container {
807
+ padding: 0px;
808
+ }
809
+ ::v-deep .content-wrapper {
810
+ margin: 0px;
811
+ }
812
+ }
813
+ }
814
+ // 库存管理左侧边距
815
+ .xhdesc-padding-left15{
816
+ padding-left: 15px;
817
+ }
818
+ // 库存管理左侧字体样式
819
+ .xhdesc-line-height30{
820
+ &.patient-info-descriptions,
821
+ .patient-info-descriptions{
822
+ ::v-deep .ant-descriptions-item{
823
+ margin-bottom: 0px
824
+ }
825
+ ::v-deep .content-wrapper{
826
+ line-height: 30px;
827
+ }
828
+ ::v-deep .ant-descriptions-item-label{
829
+ line-height: 30px;
830
+ }
831
+ ::v-deep .content-wrapper{
832
+ color: #0057FE;
833
+ font-weight: 700
834
+ }
835
+ }
836
+ }
837
+ /* 医疗病史模式:自定义HTML结构样式 */
838
+ .medical-history-descriptions {
839
+ width: 100%;
840
+ }
841
+
842
+ .medical-history-item {
843
+ margin: 0;
844
+ width: 100%;
845
+ }
846
+
847
+ .medical-history-item.with-divider {
848
+ position: relative;
849
+ padding-bottom: 4px; /* 分割线与上方间距 4px */
850
+ margin-bottom: 4px; /* 分割线与下方间距 4px */
851
+ }
852
+
853
+ .medical-history-item.with-divider::after {
854
+ content: '';
855
+ position: absolute;
856
+ left: 0;
857
+ bottom: 0; /* 贴合容器底部 */
858
+ width: 100%;
859
+ height: 0;
860
+ border-bottom: 1px solid rgba(0, 0, 0, 0.15);
861
+ }
862
+
863
+ .medical-history-content {
864
+ font-family: "Source Han Sans";
865
+ font-size: 18px;
866
+ line-height: 24px;
867
+ letter-spacing: 0em;
868
+ text-align: left;
869
+ word-break: break-word;
870
+ white-space: normal;
871
+ text-indent: 0;
872
+ padding-left: 0;
873
+ margin-left: 0;
874
+ /* 使用float实现真正的文本环绕 */
875
+ overflow: hidden;
876
+ /* 确保容器能够正确清除浮动 */
877
+ position: relative;
878
+ }
879
+
880
+ .medical-history-label {
881
+ font-family: "Source Han Sans";
882
+ font-size: 16px;
883
+ font-weight: 700;
884
+ color: #313131;
885
+ white-space: nowrap;
886
+ float: left;
887
+ margin-right: 0px;
888
+ /* 确保标签不会影响文本流 */
889
+ position: relative;
890
+ z-index: 1;
891
+ }
892
+
893
+ .medical-history-text {
894
+ font-family: "Source Han Sans";
895
+ font-size: 16px;
896
+ font-weight: 400;
897
+ color: #313131;
898
+ display: block;
899
+ overflow: hidden;
900
+ text-indent: 0;
901
+ padding-left: 0;
902
+ margin-left: 0;
903
+ word-break: break-word;
904
+ white-space: normal;
905
+ text-align: left;
906
+ line-height: 24px;
907
+ /* 确保文本能够正确环绕浮动元素 */
908
+ margin-top: 0;
909
+ margin-bottom: 0;
910
+ }
911
+
912
+ .medical-history-text.ellipsis {
913
+ display: -webkit-box;
914
+ -webkit-box-orient: vertical;
915
+ -webkit-line-clamp: 3;
916
+ line-clamp: 3;
917
+ overflow: hidden;
918
+ cursor: pointer;
919
+ position: relative;
920
+ word-break: break-word;
921
+ white-space: normal;
922
+ line-height: 24px;
923
+ text-indent: 0;
924
+ padding-left: 0;
925
+ margin-left: 0;
926
+ text-align: left;
927
+ -webkit-box-pack: start;
928
+ -webkit-box-align: start;
929
+ }
930
+
931
+ /* 使用-webkit-line-clamp时不需要手动添加省略号 */
932
+ .medical-history-text.ellipsis::after {
933
+ display: none;
934
+ }
935
+
936
+ /* 针对多行文本的特殊处理:确保换行文本与首行对齐 */
937
+ .medical-history-text.ellipsis::first-line {
938
+ text-indent: 0;
939
+ }
940
+
941
+ /* 为不支持-webkit-line-clamp的浏览器提供后备方案 */
942
+ @supports not (-webkit-line-clamp: 3) {
943
+ .medical-history-text.ellipsis {
944
+ display: block;
945
+ max-height: 72px; /* 3行 * 24px行高 */
946
+ overflow: hidden;
947
+ position: relative;
948
+ }
949
+
950
+ .medical-history-text.ellipsis::after {
951
+ content: '...';
952
+ position: absolute;
953
+ right: 0;
954
+ bottom: 0;
955
+ background: #fff;
956
+ padding-left: 4px;
957
+ display: block;
958
+ }
959
+ }
960
+
961
+ /* 医疗病史样式开关:通过 wrapperClassObject 添加类 xhdesc-medical-history */
962
+ .patient-info-descriptions.xhdesc-medical-history {
963
+ padding: 9px 12px 10px 11px !important;
964
+ /* 移除右侧空白(本模式不需要详情按钮预留空间) */
965
+ .descriptions-container {
966
+ padding-right: 0;
967
+ padding-left: 0px;
968
+ }
969
+ /* 医疗病史模式下:footer 区域使用与上方相同的医疗病史样式 */
970
+ .medical-history-footer {
971
+ width: 100%;
972
+ }
973
+ .medical-history-footer .footer-right {
974
+ margin-top: 8px;
975
+ display: flex;
976
+ justify-content: flex-end;
977
+ align-items: flex-start;
978
+ gap: 16px;
979
+ width: 100%;
980
+ }
981
+ /* 右侧(医生/医嘱日期)标签与值的字体要求 */
982
+ .medical-history-footer .footer-right .label-wrapper .label-text {
983
+ font-family: "Source Han Sans";
984
+ font-size: 16px;
985
+ font-weight: 700;
986
+ color: #313131;
987
+ line-height: 22px;
988
+ }
989
+ .medical-history-footer .footer-right .content-wrapper {
990
+ font-family: "Source Han Sans";
991
+ font-size: 16px;
992
+ font-weight: 400;
993
+ line-height: 22px;
994
+ color: #313131;
995
+ }
996
+
997
+ .medical-history-footer .footer-right .medical-history-item {
998
+ display: inline-block;
999
+ text-align: right;
1000
+ }
1001
+
1002
+ .medical-history-footer .footer-right .medical-history-content {
1003
+ text-align: right;
1004
+ }
1005
+
1006
+ .medical-history-footer .footer-right .medical-history-label {
1007
+ float: none;
1008
+ display: inline;
1009
+ margin-right: 0px;
1010
+ }
1011
+
1012
+ .medical-history-footer .footer-right .medical-history-text {
1013
+ display: inline;
1014
+ text-align: right;
1015
+ }
1016
+
1017
+ .medical-history-footer .footer-right .medical-history-text.ellipsis {
1018
+ display: inline;
1019
+ text-align: right;
1020
+ }
1021
+ }
1022
+ </style>