vue2-client 1.17.38 → 1.17.39
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.
- package/.env +20 -20
- package/package.json +1 -1
- package/src/assets/svg/female.svg +1 -1
- package/src/assets/svg/male.svg +1 -1
- package/src/base-client/components/common/HIS/HButtons/HButtons.vue +491 -491
- package/src/base-client/components/common/HIS/HFormGroup/index.js +3 -3
- package/src/base-client/components/common/HIS/HTab/HTab.vue +443 -443
- package/src/base-client/components/common/XCollapse/XCollapse.vue +830 -833
- package/src/base-client/components/common/XForm/XTreeSelect.vue +276 -276
- package/src/base-client/components/common/XFormTable/XFormTable.vue +112 -0
- package/src/base-client/components/common/XFormTable/demo.vue +89 -89
- package/src/base-client/components/common/XTable/XTableWrapper.vue +0 -5
- package/src/base-client/components/common/XTimeline/XTimeline.vue +477 -477
- package/src/base-client/components/his/XHDescriptions/XHDescriptions.vue +41 -2
- package/src/base-client/components/his/XHisEditor/XHisEditor.vue +705 -705
- package/src/base-client/components/his/XList/XList.vue +938 -938
- package/src/base-client/components/his/XTimeSelect/XTimeSelect.vue +354 -354
- package/src/base-client/components/his/XTitle/XTitle.vue +314 -314
- package/src/base-client/components/his/XTreeRows/XTreeRows.vue +341 -341
- package/src/base-client/components/his/threeTestOrders/editor.vue +113 -113
- package/src/components/STable/index.js +94 -55
- package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowBaseInformation.vue +417 -417
- package/src/pages/userInfoDetailManage/ExceptionRecordQuery/index.vue +45 -45
- package/src/router/async/router.map.js +133 -133
- package/src/services/api/restTools.js +215 -215
- package/src/theme/global.less +144 -112
- package/src-base-client/components/common/HIS/HForm/HForm.vue +347 -0
- package/src-base-client/components/common/XCollapse/XCollapse.vue +0 -0
- package/src/pages/WorkflowDetail/WorkFlowDemo4.vue +0 -127
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<!-- 根据实际部署环境修改 editor.html 的路径 -->
|
|
3
|
-
<iframe
|
|
4
|
-
src="/his/editor/editor.html"
|
|
5
|
-
width="100%"
|
|
6
|
-
height="800"
|
|
7
|
-
frameborder="0"
|
|
8
|
-
@load="onIframeLoad"
|
|
9
|
-
ref="editorIframe">
|
|
10
|
-
</iframe>
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<script setup>
|
|
14
|
-
|
|
15
|
-
import { ref, onBeforeUnmount } from 'vue'
|
|
16
|
-
|
|
17
|
-
const editorIframe = ref(null)
|
|
18
|
-
const checkEditorTimer = ref(null)
|
|
19
|
-
const checkCount = ref(0)
|
|
20
|
-
const editor = ref(null)
|
|
21
|
-
const iframeWindow = ref(null)
|
|
22
|
-
// 对外暴露的获取editor方法
|
|
23
|
-
const getEditor = () => {
|
|
24
|
-
if (editor.value) {
|
|
25
|
-
return editor.value
|
|
26
|
-
}
|
|
27
|
-
if (iframeWindow.value && iframeWindow.value.editor) {
|
|
28
|
-
editor.value = iframeWindow.value.editor
|
|
29
|
-
return editor.value
|
|
30
|
-
}
|
|
31
|
-
if (editorIframe.value && editorIframe.value.contentWindow && editorIframe.value.contentWindow.editor) {
|
|
32
|
-
editor.value = editorIframe.value.contentWindow.editor
|
|
33
|
-
return editor.value
|
|
34
|
-
}
|
|
35
|
-
return null
|
|
36
|
-
}
|
|
37
|
-
// 创建体温单方法
|
|
38
|
-
const createVitalSigns = (data) => {
|
|
39
|
-
const editorObj = getEditor()
|
|
40
|
-
if (!editorObj) {
|
|
41
|
-
throw new Error('editor对象未初始化,无法创建体温单')
|
|
42
|
-
}
|
|
43
|
-
if (typeof editorObj.createVitalSigns === 'function') {
|
|
44
|
-
return editorObj.createVitalSigns(data)
|
|
45
|
-
} else {
|
|
46
|
-
throw new Error('editor对象未包含createVitalSigns方法')
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// 检查editor对象是否已初始化
|
|
51
|
-
const startEditorCheck = (frameWindow, iframe) => {
|
|
52
|
-
if (checkEditorTimer.value) {
|
|
53
|
-
clearInterval(checkEditorTimer.value)
|
|
54
|
-
}
|
|
55
|
-
checkCount.value = 0
|
|
56
|
-
checkEditorTimer.value = setInterval(() => {
|
|
57
|
-
checkCount.value++
|
|
58
|
-
try {
|
|
59
|
-
const editorObj = frameWindow.editor
|
|
60
|
-
if (editorObj && typeof editorObj.createVitalSigns === 'function') {
|
|
61
|
-
clearInterval(checkEditorTimer.value)
|
|
62
|
-
editor.value = editorObj
|
|
63
|
-
// 将editor对象暴露到全局
|
|
64
|
-
window.iframeEditor = editorObj
|
|
65
|
-
window.iframeWindow = frameWindow
|
|
66
|
-
// 触发事件
|
|
67
|
-
emit('editor-ready', editorObj)
|
|
68
|
-
emit('load', { target: iframe, editor: editorObj })
|
|
69
|
-
// 发送消息通知
|
|
70
|
-
window.parent.postMessage({ type: 'editorReady' }, '*')
|
|
71
|
-
}
|
|
72
|
-
} catch (err) {
|
|
73
|
-
console.error('检查editor对象时出错:', err)
|
|
74
|
-
}
|
|
75
|
-
if (checkCount.value >= 20) {
|
|
76
|
-
clearInterval(checkEditorTimer.value)
|
|
77
|
-
console.error('Editor 对象加载失败')
|
|
78
|
-
}
|
|
79
|
-
}, 500)
|
|
80
|
-
}
|
|
81
|
-
// iframe加载完成的处理
|
|
82
|
-
const onIframeLoad = (e) => {
|
|
83
|
-
const iframe = e.target
|
|
84
|
-
const frameWindow = iframe.contentWindow
|
|
85
|
-
iframeWindow.value = frameWindow
|
|
86
|
-
if (!frameWindow) {
|
|
87
|
-
console.error('无法访问 iframe 内容')
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
// 关闭文书工具栏
|
|
91
|
-
iframe.contentWindow.editor.option.toolbar = false
|
|
92
|
-
startEditorCheck(frameWindow, iframe)
|
|
93
|
-
}
|
|
94
|
-
// 组件销毁前清理
|
|
95
|
-
onBeforeUnmount(() => {
|
|
96
|
-
if (checkEditorTimer.value) {
|
|
97
|
-
clearInterval(checkEditorTimer.value)
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
// 暴露方法给父组件
|
|
101
|
-
defineExpose({ getEditor, createVitalSigns })
|
|
102
|
-
|
|
103
|
-
// 定义事件
|
|
104
|
-
const emit = defineEmits(['editor-ready', 'load'])
|
|
105
|
-
</script>
|
|
106
|
-
|
|
107
|
-
<style scoped>
|
|
108
|
-
iframe {
|
|
109
|
-
border: none;
|
|
110
|
-
width: 100%;
|
|
111
|
-
min-height: 800px;
|
|
112
|
-
}
|
|
113
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 根据实际部署环境修改 editor.html 的路径 -->
|
|
3
|
+
<iframe
|
|
4
|
+
src="/his/editor/editor.html"
|
|
5
|
+
width="100%"
|
|
6
|
+
height="800"
|
|
7
|
+
frameborder="0"
|
|
8
|
+
@load="onIframeLoad"
|
|
9
|
+
ref="editorIframe">
|
|
10
|
+
</iframe>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup>
|
|
14
|
+
|
|
15
|
+
import { ref, onBeforeUnmount } from 'vue'
|
|
16
|
+
|
|
17
|
+
const editorIframe = ref(null)
|
|
18
|
+
const checkEditorTimer = ref(null)
|
|
19
|
+
const checkCount = ref(0)
|
|
20
|
+
const editor = ref(null)
|
|
21
|
+
const iframeWindow = ref(null)
|
|
22
|
+
// 对外暴露的获取editor方法
|
|
23
|
+
const getEditor = () => {
|
|
24
|
+
if (editor.value) {
|
|
25
|
+
return editor.value
|
|
26
|
+
}
|
|
27
|
+
if (iframeWindow.value && iframeWindow.value.editor) {
|
|
28
|
+
editor.value = iframeWindow.value.editor
|
|
29
|
+
return editor.value
|
|
30
|
+
}
|
|
31
|
+
if (editorIframe.value && editorIframe.value.contentWindow && editorIframe.value.contentWindow.editor) {
|
|
32
|
+
editor.value = editorIframe.value.contentWindow.editor
|
|
33
|
+
return editor.value
|
|
34
|
+
}
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
// 创建体温单方法
|
|
38
|
+
const createVitalSigns = (data) => {
|
|
39
|
+
const editorObj = getEditor()
|
|
40
|
+
if (!editorObj) {
|
|
41
|
+
throw new Error('editor对象未初始化,无法创建体温单')
|
|
42
|
+
}
|
|
43
|
+
if (typeof editorObj.createVitalSigns === 'function') {
|
|
44
|
+
return editorObj.createVitalSigns(data)
|
|
45
|
+
} else {
|
|
46
|
+
throw new Error('editor对象未包含createVitalSigns方法')
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 检查editor对象是否已初始化
|
|
51
|
+
const startEditorCheck = (frameWindow, iframe) => {
|
|
52
|
+
if (checkEditorTimer.value) {
|
|
53
|
+
clearInterval(checkEditorTimer.value)
|
|
54
|
+
}
|
|
55
|
+
checkCount.value = 0
|
|
56
|
+
checkEditorTimer.value = setInterval(() => {
|
|
57
|
+
checkCount.value++
|
|
58
|
+
try {
|
|
59
|
+
const editorObj = frameWindow.editor
|
|
60
|
+
if (editorObj && typeof editorObj.createVitalSigns === 'function') {
|
|
61
|
+
clearInterval(checkEditorTimer.value)
|
|
62
|
+
editor.value = editorObj
|
|
63
|
+
// 将editor对象暴露到全局
|
|
64
|
+
window.iframeEditor = editorObj
|
|
65
|
+
window.iframeWindow = frameWindow
|
|
66
|
+
// 触发事件
|
|
67
|
+
emit('editor-ready', editorObj)
|
|
68
|
+
emit('load', { target: iframe, editor: editorObj })
|
|
69
|
+
// 发送消息通知
|
|
70
|
+
window.parent.postMessage({ type: 'editorReady' }, '*')
|
|
71
|
+
}
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error('检查editor对象时出错:', err)
|
|
74
|
+
}
|
|
75
|
+
if (checkCount.value >= 20) {
|
|
76
|
+
clearInterval(checkEditorTimer.value)
|
|
77
|
+
console.error('Editor 对象加载失败')
|
|
78
|
+
}
|
|
79
|
+
}, 500)
|
|
80
|
+
}
|
|
81
|
+
// iframe加载完成的处理
|
|
82
|
+
const onIframeLoad = (e) => {
|
|
83
|
+
const iframe = e.target
|
|
84
|
+
const frameWindow = iframe.contentWindow
|
|
85
|
+
iframeWindow.value = frameWindow
|
|
86
|
+
if (!frameWindow) {
|
|
87
|
+
console.error('无法访问 iframe 内容')
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
// 关闭文书工具栏
|
|
91
|
+
iframe.contentWindow.editor.option.toolbar = false
|
|
92
|
+
startEditorCheck(frameWindow, iframe)
|
|
93
|
+
}
|
|
94
|
+
// 组件销毁前清理
|
|
95
|
+
onBeforeUnmount(() => {
|
|
96
|
+
if (checkEditorTimer.value) {
|
|
97
|
+
clearInterval(checkEditorTimer.value)
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
// 暴露方法给父组件
|
|
101
|
+
defineExpose({ getEditor, createVitalSigns })
|
|
102
|
+
|
|
103
|
+
// 定义事件
|
|
104
|
+
const emit = defineEmits(['editor-ready', 'load'])
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style scoped>
|
|
108
|
+
iframe {
|
|
109
|
+
border: none;
|
|
110
|
+
width: 100%;
|
|
111
|
+
min-height: 800px;
|
|
112
|
+
}
|
|
113
|
+
</style>
|
|
@@ -7,6 +7,7 @@ export default {
|
|
|
7
7
|
data () {
|
|
8
8
|
return {
|
|
9
9
|
clickedRowKey: null,
|
|
10
|
+
hoveredRowKey: null, // 跟踪鼠标悬浮的行
|
|
10
11
|
needTotalList: [],
|
|
11
12
|
|
|
12
13
|
selectedRows: [],
|
|
@@ -274,6 +275,8 @@ export default {
|
|
|
274
275
|
}
|
|
275
276
|
this.localDataSource = r.data // 返回结果中的数组数据
|
|
276
277
|
this.localLoading = false
|
|
278
|
+
// 清除选中行状态(翻页或重新查询时)
|
|
279
|
+
this.clickedRowKey = null
|
|
277
280
|
this.setScrollYHeight({ type: 'default' })
|
|
278
281
|
}, () => {
|
|
279
282
|
this.localLoading = false
|
|
@@ -369,12 +372,29 @@ export default {
|
|
|
369
372
|
this.$emit('expand', expanded, record)
|
|
370
373
|
},
|
|
371
374
|
handleRowClick (record, index) {
|
|
375
|
+
const isRowKeySequence = this.rowKey === '序号'
|
|
376
|
+
const currentRowKey = isRowKeySequence ? index : record[this.rowKey]
|
|
377
|
+
|
|
378
|
+
// 如果点击的是已选中的行,则取消选中;否则选中该行
|
|
379
|
+
if (this.clickedRowKey === currentRowKey) {
|
|
380
|
+
this.clickedRowKey = null
|
|
381
|
+
this.$emit('rowClick', null) // 传递 null 表示取消选中
|
|
382
|
+
} else {
|
|
383
|
+
this.clickedRowKey = currentRowKey
|
|
384
|
+
this.$emit('rowClick', record)
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
handleRowMouseEnter (record, index) {
|
|
372
388
|
if (this.rowKey === '序号') {
|
|
373
|
-
this.
|
|
389
|
+
this.hoveredRowKey = index
|
|
374
390
|
} else {
|
|
375
|
-
this.
|
|
391
|
+
this.hoveredRowKey = record[this.rowKey]
|
|
376
392
|
}
|
|
377
|
-
this.$emit('
|
|
393
|
+
this.$emit('rowMouseEnter', record, index)
|
|
394
|
+
},
|
|
395
|
+
handleRowMouseLeave (record, index) {
|
|
396
|
+
this.hoveredRowKey = null
|
|
397
|
+
this.$emit('rowMouseLeave', record, index)
|
|
378
398
|
},
|
|
379
399
|
hexToRgba (hex, alpha = 1) {
|
|
380
400
|
try {
|
|
@@ -405,24 +425,56 @@ export default {
|
|
|
405
425
|
}
|
|
406
426
|
return 'info'
|
|
407
427
|
},
|
|
408
|
-
//
|
|
428
|
+
// 根据行样式类型和是否激活获取背景色
|
|
429
|
+
// isActive: 是否处于 hover 或 selected 状态
|
|
430
|
+
getRowBgColor (styleType, isActive = false) {
|
|
431
|
+
const colorMap = {
|
|
432
|
+
success: {
|
|
433
|
+
normal: 'rgba(82, 196, 26, 0.2)',
|
|
434
|
+
active: 'rgba(82, 196, 26, 0.2)'
|
|
435
|
+
},
|
|
436
|
+
warning: {
|
|
437
|
+
normal: 'rgba(250, 173, 20, 0.1)',
|
|
438
|
+
active: 'rgba(250, 173, 20, 0.2)'
|
|
439
|
+
},
|
|
440
|
+
error: {
|
|
441
|
+
normal: 'rgba(245, 34, 47, 0.1)',
|
|
442
|
+
active: 'rgba(245, 34, 47, 0.2)'
|
|
443
|
+
},
|
|
444
|
+
danger: {
|
|
445
|
+
normal: 'rgba(245, 34, 47, 0.1)',
|
|
446
|
+
active: 'rgba(245, 34, 47, 0.2)'
|
|
447
|
+
},
|
|
448
|
+
magic: {
|
|
449
|
+
normal: 'rgba(114, 46, 209, 0.1)',
|
|
450
|
+
active: 'rgba(114, 46, 209, 0.2)'
|
|
451
|
+
},
|
|
452
|
+
warn: {
|
|
453
|
+
normal: 'rgba(250, 173, 20, 0.1)',
|
|
454
|
+
active: 'rgba(250, 173, 20, 0.2)'
|
|
455
|
+
},
|
|
456
|
+
info: {
|
|
457
|
+
normal: '',
|
|
458
|
+
active: 'rgba(24, 144, 255, 0.2)'
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const colors = colorMap[styleType] || colorMap.info
|
|
463
|
+
return isActive ? colors.active : colors.normal
|
|
464
|
+
},
|
|
465
|
+
// 获取行样式颜色(根据当前行的 hover 和 selected 状态)
|
|
409
466
|
getRowStyleClass (record, index) {
|
|
467
|
+
const isRowKeySequence = this.rowKey === '序号'
|
|
468
|
+
const currentRowKey = isRowKeySequence ? index : record[this.rowKey]
|
|
469
|
+
|
|
470
|
+
// 判断是否是选中行或悬浮行
|
|
471
|
+
const isActive = this.clickedRowKey === currentRowKey || this.hoveredRowKey === currentRowKey
|
|
472
|
+
|
|
473
|
+
// 获取行样式类型
|
|
410
474
|
const styleType = this.getRowStyleType(record, index)
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
case 'warn':
|
|
415
|
-
case 'warning':
|
|
416
|
-
return 'ant-table-row-warning'
|
|
417
|
-
case 'error':
|
|
418
|
-
case 'danger':
|
|
419
|
-
return 'ant-table-row-error'
|
|
420
|
-
case 'magic':
|
|
421
|
-
return 'ant-table-row-magic'
|
|
422
|
-
case 'info':
|
|
423
|
-
default:
|
|
424
|
-
return ''
|
|
425
|
-
}
|
|
475
|
+
|
|
476
|
+
// 返回对应颜色
|
|
477
|
+
return this.getRowBgColor(styleType, isActive)
|
|
426
478
|
},
|
|
427
479
|
},
|
|
428
480
|
|
|
@@ -461,47 +513,34 @@ export default {
|
|
|
461
513
|
})
|
|
462
514
|
// 取消原有的分页组件 产品设计分页组件和汇总在一行 重新分页逻辑
|
|
463
515
|
props.pagination = false
|
|
464
|
-
|
|
465
|
-
|
|
516
|
+
|
|
517
|
+
// 使用 rowClassName 实现响应式行样式
|
|
518
|
+
props.rowClassName = (record, index) => {
|
|
466
519
|
const isRowKeySequence = this.rowKey === '序号'
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if (isCurrentRow && rowStyleClass) {
|
|
475
|
-
// 如果有行样式类,使用对应的深色
|
|
476
|
-
switch (rowStyleClass) {
|
|
477
|
-
case 'ant-table-row-success':
|
|
478
|
-
selectedBgColor = '#b8e6a0'
|
|
479
|
-
break
|
|
480
|
-
case 'ant-table-row-warning':
|
|
481
|
-
selectedBgColor = '#ffe066'
|
|
482
|
-
break
|
|
483
|
-
case 'ant-table-row-error':
|
|
484
|
-
selectedBgColor = '#ffb3b3'
|
|
485
|
-
break
|
|
486
|
-
case 'ant-table-row-magic':
|
|
487
|
-
selectedBgColor = '#d9b3ff'
|
|
488
|
-
break
|
|
489
|
-
default:
|
|
490
|
-
selectedBgColor = this.clickedRowColor
|
|
491
|
-
}
|
|
492
|
-
} else if (isCurrentRow) {
|
|
493
|
-
// 没有行样式类时使用默认选中颜色
|
|
494
|
-
selectedBgColor = this.clickedRowColor
|
|
520
|
+
const currentRowKey = isRowKeySequence ? index : record[this.rowKey]
|
|
521
|
+
|
|
522
|
+
const classes = []
|
|
523
|
+
|
|
524
|
+
// 判断是否是选中行(点击状态)
|
|
525
|
+
if (this.clickedRowKey === currentRowKey) {
|
|
526
|
+
classes.push('row-clicked')
|
|
495
527
|
}
|
|
496
528
|
|
|
529
|
+
// 添加行样式类型(用于不同的颜色主题)
|
|
530
|
+
const styleType = this.getRowStyleType(record, index)
|
|
531
|
+
classes.push(`row-style-${styleType}`)
|
|
532
|
+
|
|
533
|
+
return classes.join(' ')
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// 在 props 中添加自定义行事件
|
|
537
|
+
props.customRow = (record, index) => {
|
|
497
538
|
return {
|
|
498
539
|
on: {
|
|
499
|
-
click: () => this.handleRowClick(record, index)
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
},
|
|
504
|
-
class: rowStyleClass
|
|
540
|
+
click: () => this.handleRowClick(record, index),
|
|
541
|
+
mouseenter: () => this.handleRowMouseEnter(record, index),
|
|
542
|
+
mouseleave: () => this.handleRowMouseLeave(record, index)
|
|
543
|
+
}
|
|
505
544
|
}
|
|
506
545
|
}
|
|
507
546
|
// 自定义底部汇总插槽组件
|