vue2-client 1.20.79 → 1.20.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.
- package/package.json +1 -1
- package/src/base-client/components/common/HIS/HButtons/HButtons.vue +205 -6
- package/src/base-client/components/common/HIS/HForm/HForm.vue +1 -1
- package/src/base-client/components/common/HIS/HFormGroup/HFormGroup.vue +1 -1
- package/src/base-client/components/common/HIS/HTab/HTab.vue +89 -7
- package/src/base-client/components/common/XFormTable/demo.vue +1 -1
- package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +6 -3
- package/src/base-client/components/his/XTransfer/XTransfer.vue +904 -0
- package/src/base-client/components/his/XTransfer/index.md +327 -0
- package/src/pages/userInfoDetailManage/InstructHistoryRecordQuery/index.vue +1 -1
- package/vue.config.js +1 -1
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script setup
|
|
1
|
+
<script setup >
|
|
2
2
|
import XButtons from '@vue2-client/base-client/components/common/XButtons/XButtons.vue'
|
|
3
|
-
import { ref, computed, useAttrs } from 'vue'
|
|
3
|
+
import { ref, computed, useAttrs, nextTick, onMounted } from 'vue'
|
|
4
4
|
|
|
5
|
-
defineProps({
|
|
5
|
+
const props = defineProps({
|
|
6
6
|
// HButtons特有的属性
|
|
7
7
|
buttonStyle: {
|
|
8
8
|
type: String,
|
|
@@ -10,11 +10,22 @@ defineProps({
|
|
|
10
10
|
}
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
+
const emit = defineEmits(['update:activeIndex', 'activeChange', 'configEnd'])
|
|
14
|
+
|
|
13
15
|
// 内部 XButtons 实例引用
|
|
14
16
|
const xButtonsRef = ref()
|
|
15
17
|
|
|
18
|
+
// useStyle10模式下激活按钮的索引(从0开始)
|
|
19
|
+
const activeIndex = ref(0)
|
|
20
|
+
|
|
16
21
|
// 兼容多种样式配置
|
|
17
22
|
const attrs = useAttrs()
|
|
23
|
+
|
|
24
|
+
// 判断是否使用 useStyle10 模式
|
|
25
|
+
const isUseStyle10 = computed(() => {
|
|
26
|
+
return props.buttonStyle === 'useStyle10' || attrs.useStyle10 === true || attrs.useStyle10 === '' || attrs.useStyle10 === 'true'
|
|
27
|
+
})
|
|
28
|
+
|
|
18
29
|
const wrapperClassObject = computed(() => {
|
|
19
30
|
const a = attrs
|
|
20
31
|
const classes = {}
|
|
@@ -28,7 +39,8 @@ const wrapperClassObject = computed(() => {
|
|
|
28
39
|
'fill-container',
|
|
29
40
|
'no-boder-style',
|
|
30
41
|
'form-inline',
|
|
31
|
-
'one-button-style' // 一个按钮样式,占满整个宽度
|
|
42
|
+
'one-button-style', // 一个按钮样式,占满整个宽度
|
|
43
|
+
'useStyle10' // 左侧蓝色圆点指示器样式
|
|
32
44
|
]
|
|
33
45
|
for (const key of booleanStyleKeys) {
|
|
34
46
|
const val = a[key]
|
|
@@ -38,11 +50,128 @@ const wrapperClassObject = computed(() => {
|
|
|
38
50
|
return classes
|
|
39
51
|
})
|
|
40
52
|
|
|
53
|
+
// 获取内部按钮元素列表
|
|
54
|
+
const getButtonElements = () => {
|
|
55
|
+
const xEl = xButtonsRef.value?.$el
|
|
56
|
+
if (!xEl) return []
|
|
57
|
+
return Array.from(xEl.querySelectorAll('.ant-btn'))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 设置按钮激活状态
|
|
61
|
+
const setActiveState = (btn, isActive) => {
|
|
62
|
+
if (!btn) return
|
|
63
|
+
if (isActive) {
|
|
64
|
+
btn.classList.add('h-btn-active')
|
|
65
|
+
// 使用内联样式确保颜色生效
|
|
66
|
+
btn.style.color = '#0057FE'
|
|
67
|
+
} else {
|
|
68
|
+
btn.classList.remove('h-btn-active')
|
|
69
|
+
// 清除内联样式
|
|
70
|
+
btn.style.color = ''
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 清除所有按钮的激活样式
|
|
75
|
+
const clearAllActiveStyles = () => {
|
|
76
|
+
const buttons = getButtonElements()
|
|
77
|
+
buttons.forEach(btn => {
|
|
78
|
+
setActiveState(btn, false)
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 设置指定索引按钮为激活状态
|
|
83
|
+
const setActiveButton = (index) => {
|
|
84
|
+
const buttons = getButtonElements()
|
|
85
|
+
clearAllActiveStyles()
|
|
86
|
+
|
|
87
|
+
if (buttons[index]) {
|
|
88
|
+
setActiveState(buttons[index], true)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 事件委托:处理按钮点击
|
|
93
|
+
const handleButtonClick = (event) => {
|
|
94
|
+
if (!isUseStyle10.value) return
|
|
95
|
+
|
|
96
|
+
// 查找被点击的按钮元素
|
|
97
|
+
const target = event.target.closest('.ant-btn')
|
|
98
|
+
if (!target) return
|
|
99
|
+
|
|
100
|
+
const buttons = getButtonElements()
|
|
101
|
+
const index = buttons.indexOf(target)
|
|
102
|
+
|
|
103
|
+
if (index === -1) return
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
// 更新激活索引
|
|
107
|
+
activeIndex.value = index
|
|
108
|
+
emit('update:activeIndex', index)
|
|
109
|
+
emit('activeChange', index)
|
|
110
|
+
|
|
111
|
+
// 更新按钮样式
|
|
112
|
+
clearAllActiveStyles()
|
|
113
|
+
setActiveState(buttons[index], true)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 初始化 useStyle10 样式(带重试机制)
|
|
117
|
+
const initUseStyle10 = (retryCount = 0) => {
|
|
118
|
+
|
|
119
|
+
if (!isUseStyle10.value) {
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const buttons = getButtonElements()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
// 如果没有找到按钮,重试最多10次
|
|
127
|
+
if (buttons.length === 0 && retryCount < 10) {
|
|
128
|
+
setTimeout(() => {
|
|
129
|
+
initUseStyle10(retryCount + 1)
|
|
130
|
+
}, 100)
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (buttons.length === 0) {
|
|
135
|
+
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 设置第一个按钮为激活状态
|
|
140
|
+
clearAllActiveStyles()
|
|
141
|
+
setActiveState(buttons[0], true)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 监听 XButtons 配置结束,初始化激活状态
|
|
145
|
+
const handleConfigEnd = async () => {
|
|
146
|
+
await nextTick()
|
|
147
|
+
initUseStyle10()
|
|
148
|
+
emit('configEnd')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 在挂载时也尝试初始化(作为备用方案)
|
|
152
|
+
onMounted(() => {
|
|
153
|
+
setTimeout(() => {
|
|
154
|
+
initUseStyle10()
|
|
155
|
+
}, 300)
|
|
156
|
+
})
|
|
157
|
+
|
|
41
158
|
// 暴露方法:获取内部 XButtons 实例
|
|
42
159
|
defineExpose({
|
|
43
160
|
getXButtonsInstance: function () { return xButtonsRef.value },
|
|
44
161
|
/** 等待配置结束的异步方法,委托给内部 XButtons */
|
|
45
|
-
waitConfigEnd: () => xButtonsRef.value?.waitConfigEnd?.() ?? Promise.resolve()
|
|
162
|
+
waitConfigEnd: () => xButtonsRef.value?.waitConfigEnd?.() ?? Promise.resolve(),
|
|
163
|
+
/** 获取当前激活按钮索引 */
|
|
164
|
+
getActiveIndex: () => activeIndex.value,
|
|
165
|
+
/** 设置激活按钮索引 */
|
|
166
|
+
setActiveIndex: (index) => {
|
|
167
|
+
activeIndex.value = index
|
|
168
|
+
setActiveButton(index)
|
|
169
|
+
},
|
|
170
|
+
/** 获取当前激活按钮元素 */
|
|
171
|
+
getActiveButton: () => {
|
|
172
|
+
const buttons = getButtonElements()
|
|
173
|
+
return buttons[activeIndex.value]
|
|
174
|
+
}
|
|
46
175
|
})
|
|
47
176
|
</script>
|
|
48
177
|
|
|
@@ -53,12 +182,13 @@ defineExpose({
|
|
|
53
182
|
`h-buttons-${buttonStyle}`,
|
|
54
183
|
wrapperClassObject
|
|
55
184
|
]"
|
|
185
|
+
@click="handleButtonClick"
|
|
56
186
|
>
|
|
57
187
|
<x-buttons
|
|
58
188
|
ref="xButtonsRef"
|
|
59
189
|
v-bind="$attrs"
|
|
60
|
-
@configEnd="$emit('configEnd')"
|
|
61
190
|
v-on="$listeners"
|
|
191
|
+
@configEnd="handleConfigEnd"
|
|
62
192
|
>
|
|
63
193
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
64
194
|
<slot :name="name" v-bind="slotData" />
|
|
@@ -491,5 +621,74 @@ defineExpose({
|
|
|
491
621
|
}
|
|
492
622
|
}
|
|
493
623
|
}
|
|
624
|
+
// useStyle10样式 - 左侧蓝色圆点指示器样式,与HTab useStyle10效果一致
|
|
625
|
+
&.h-buttons-useStyle10 {
|
|
626
|
+
:deep(.ant-btn-group) {
|
|
627
|
+
display: flex;
|
|
628
|
+
flex-wrap: wrap;
|
|
629
|
+
gap: 8px;
|
|
630
|
+
margin-left: 0 !important;
|
|
631
|
+
padding: 0 !important;
|
|
632
|
+
|
|
633
|
+
.ant-btn {
|
|
634
|
+
position: relative;
|
|
635
|
+
background-color: transparent !important;
|
|
636
|
+
border: none !important;
|
|
637
|
+
border-radius: 0 !important;
|
|
638
|
+
color: #313131;
|
|
639
|
+
font-family: "Source Han Sans";
|
|
640
|
+
font-size: 16px;
|
|
641
|
+
font-weight: bold;
|
|
642
|
+
line-height: normal;
|
|
643
|
+
letter-spacing: 0em;
|
|
644
|
+
font-feature-settings: "kern" on;
|
|
645
|
+
font-variation-settings: "opsz" auto;
|
|
646
|
+
width: auto;
|
|
647
|
+
height: 40px;
|
|
648
|
+
padding: 0 12px 6px 18px;
|
|
649
|
+
text-align: center;
|
|
650
|
+
margin-right: 0 !important;
|
|
651
|
+
box-shadow: none !important;
|
|
652
|
+
display: inline-flex;
|
|
653
|
+
align-items: center;
|
|
654
|
+
vertical-align: top;
|
|
655
|
+
outline: none !important;
|
|
656
|
+
background: transparent !important;
|
|
657
|
+
background-image: none !important;
|
|
658
|
+
border-color: transparent !important;
|
|
659
|
+
border-width: 0 !important;
|
|
660
|
+
|
|
661
|
+
&::before {
|
|
662
|
+
content: "" !important;
|
|
663
|
+
position: absolute !important;
|
|
664
|
+
left: 5px !important;
|
|
665
|
+
top: 50% !important;
|
|
666
|
+
transform: translateY(-50%) !important;
|
|
667
|
+
width: 8px !important;
|
|
668
|
+
height: 8px !important;
|
|
669
|
+
background-color: #1890ff !important;
|
|
670
|
+
background-image: none !important;
|
|
671
|
+
border-radius: 50% !important;
|
|
672
|
+
display: block !important;
|
|
673
|
+
z-index: 10 !important;
|
|
674
|
+
pointer-events: none !important;
|
|
675
|
+
opacity: 1 !important;
|
|
676
|
+
mix-blend-mode: normal !important;
|
|
677
|
+
box-shadow: none !important;
|
|
678
|
+
filter: none !important;
|
|
679
|
+
-webkit-filter: none !important;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
.anticon {
|
|
683
|
+
display: none !important;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// 激活状态:通过 h-btn-active 类控制
|
|
688
|
+
.ant-btn.h-btn-active {
|
|
689
|
+
color: #0057FE !important;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
494
693
|
}
|
|
495
694
|
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script setup
|
|
1
|
+
<script setup >
|
|
2
2
|
import XFormGroup from '@vue2-client/base-client/components/common/XFormGroup/XFormGroup.vue'
|
|
3
3
|
import { ref, onMounted, getCurrentInstance, watch } from 'vue'
|
|
4
4
|
import { getConfigByNameAsync } from '@vue2-client/services/api/common'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import XTab from '@vue2-client/base-client/components/common/XTab/XTab.vue'
|
|
3
|
-
import { ref, computed, useAttrs, useSlots,
|
|
3
|
+
import { ref, computed, useAttrs, useSlots, onMounted } from 'vue'
|
|
4
4
|
import { getConfigByName } from '@vue2-client/services/api/common'
|
|
5
5
|
|
|
6
6
|
const props = defineProps({
|
|
@@ -22,10 +22,10 @@ const wrapperClassObject = computed(() => {
|
|
|
22
22
|
const a = attrs
|
|
23
23
|
const classes = {}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
// 通用布尔样式开关(以存在/空字符串/'true' 为真)
|
|
26
|
+
const booleanStyleKeys = [
|
|
27
|
+
'hasTopMargin', 'useStyle7', 'useCycle', 'useStyle8', 'out-tab', 'no-underline', 'useStyle9', 'useStyle10'
|
|
28
|
+
]
|
|
29
29
|
for (const key of booleanStyleKeys) {
|
|
30
30
|
const val = a[key]
|
|
31
31
|
const truthy = val === true || val === '' || val === 'true'
|
|
@@ -78,8 +78,9 @@ const loadExtraConfig = (configName) => {
|
|
|
78
78
|
}, env.value === 'dev')
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
onMounted(() =>
|
|
82
|
-
|
|
81
|
+
onMounted(() => {
|
|
82
|
+
loadExtraConfig(props.tabBarExtraConfig)
|
|
83
|
+
})
|
|
83
84
|
|
|
84
85
|
// 暴露方法给父组件使用
|
|
85
86
|
defineExpose({
|
|
@@ -126,6 +127,7 @@ defineExpose({
|
|
|
126
127
|
|
|
127
128
|
<style scoped lang="less">
|
|
128
129
|
.h-tab-wrapper {
|
|
130
|
+
width: 100%;
|
|
129
131
|
overflow: visible !important;
|
|
130
132
|
|
|
131
133
|
// 基础样式
|
|
@@ -578,5 +580,85 @@ defineExpose({
|
|
|
578
580
|
display: none;
|
|
579
581
|
}
|
|
580
582
|
}
|
|
583
|
+
// 样式10:无下划线、左侧绿色圆点、字体样式切换
|
|
584
|
+
&.h-tab-useStyle10 {
|
|
585
|
+
:deep(.ant-tabs-tab-next),
|
|
586
|
+
:deep(.ant-tabs-tab-prev-icon-target),
|
|
587
|
+
:deep(.ant-tabs-tab-next-icon) { display: none; }
|
|
588
|
+
|
|
589
|
+
:deep(.ant-tabs-bar) {
|
|
590
|
+
border-bottom: none !important;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
:deep(.ant-tabs-ink-bar) {
|
|
594
|
+
display: none !important;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
:deep(.ant-tabs-nav-wrap) {
|
|
598
|
+
margin-top: 0;
|
|
599
|
+
padding-left: 0 !important;
|
|
600
|
+
padding-right: 0 !important;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
:deep(.ant-tabs-nav-container) {
|
|
604
|
+
padding-left: 0 !important;
|
|
605
|
+
padding-right: 0 !important;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
:deep(.ant-tabs-nav) {
|
|
609
|
+
display: flex;
|
|
610
|
+
flex-wrap: wrap;
|
|
611
|
+
gap: 8px;
|
|
612
|
+
.ant-tabs-tab {
|
|
613
|
+
position: relative;
|
|
614
|
+
background-color: transparent;
|
|
615
|
+
border-radius: 0;
|
|
616
|
+
color: #313131;
|
|
617
|
+
font-family: "Source Han Sans";
|
|
618
|
+
font-size: 16px;
|
|
619
|
+
font-weight: bold;
|
|
620
|
+
line-height: normal;
|
|
621
|
+
letter-spacing: 0em;
|
|
622
|
+
font-feature-settings: "kern" on;
|
|
623
|
+
font-variation-settings: "opsz" auto;
|
|
624
|
+
width: auto;
|
|
625
|
+
padding: 0 12px 6px;
|
|
626
|
+
padding-left: 18px !important;
|
|
627
|
+
transition: all 0.3s;
|
|
628
|
+
height: 40px;
|
|
629
|
+
text-align: center;
|
|
630
|
+
margin-right: 0px !important;
|
|
631
|
+
display: inline-flex !important;
|
|
632
|
+
align-items: center;
|
|
633
|
+
vertical-align: top;
|
|
634
|
+
}
|
|
635
|
+
.ant-tabs-tab::before {
|
|
636
|
+
content: "" !important;
|
|
637
|
+
position: absolute !important;
|
|
638
|
+
left: 0 !important;
|
|
639
|
+
top: 50% !important;
|
|
640
|
+
transform: translateY(-50%) !important;
|
|
641
|
+
width: 8px !important;
|
|
642
|
+
height: 8px !important;
|
|
643
|
+
background: #0057FE !important;
|
|
644
|
+
border-radius: 50% !important;
|
|
645
|
+
display: block !important;
|
|
646
|
+
z-index: 1 !important;
|
|
647
|
+
}
|
|
648
|
+
.ant-tabs-tab-active {
|
|
649
|
+
background-color: transparent;
|
|
650
|
+
color: #0057FE;
|
|
651
|
+
font-weight: bold;
|
|
652
|
+
width: auto;
|
|
653
|
+
padding: 0 12px 6px;
|
|
654
|
+
padding-left: 18px !important;
|
|
655
|
+
height: 40px;
|
|
656
|
+
text-align: center;
|
|
657
|
+
}
|
|
658
|
+
.ant-tabs-tab-active::before {
|
|
659
|
+
background: #0057FE !important;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
581
663
|
}
|
|
582
664
|
</style>
|
|
@@ -68,7 +68,8 @@
|
|
|
68
68
|
'x-workflow-progress',
|
|
69
69
|
'h-ai',
|
|
70
70
|
'x-markdown',
|
|
71
|
-
'x-markdown-section'
|
|
71
|
+
'x-markdown-section',
|
|
72
|
+
'x-transfer'
|
|
72
73
|
].includes(cell.slotType)">
|
|
73
74
|
<component
|
|
74
75
|
:is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
|
|
@@ -152,7 +153,8 @@
|
|
|
152
153
|
'x-workflow-progress',
|
|
153
154
|
'h-ai',
|
|
154
155
|
'x-markdown',
|
|
155
|
-
'x-markdown-section'
|
|
156
|
+
'x-markdown-section',
|
|
157
|
+
'x-transfer'
|
|
156
158
|
].includes(cell.slotType)">
|
|
157
159
|
<component
|
|
158
160
|
:is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
|
|
@@ -235,7 +237,8 @@ export default {
|
|
|
235
237
|
XWorkflowProgress: () => import('@vue2-client/base-client/components/his/XWorkflowProgress/XWorkflowProgress.vue'),
|
|
236
238
|
HAi: () => import('@vue2-client/base-client/components/his/HAi/HAi.vue'),
|
|
237
239
|
XMarkdown: () => import('@vue2-client/base-client/components/common/XMarkdownViewer/XMarkdownViewer.vue'),
|
|
238
|
-
XMarkdownSection: () => import('@vue2-client/base-client/components/common/XMarkdownSectionExtractor/XMarkdownSectionExtractor.vue')
|
|
240
|
+
XMarkdownSection: () => import('@vue2-client/base-client/components/common/XMarkdownSectionExtractor/XMarkdownSectionExtractor.vue'),
|
|
241
|
+
XTransfer: () => import('@vue2-client/base-client/components/his/XTransfer/XTransfer.vue')
|
|
239
242
|
},
|
|
240
243
|
props: {
|
|
241
244
|
// 每一行的配置
|