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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-client",
3
- "version": "1.20.79",
3
+ "version": "1.20.81",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
@@ -1,8 +1,8 @@
1
- <script setup lang="ts">
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 lang="ts">
1
+ <script setup>
2
2
  import XAddNativeForm from '@vue2-client/base-client/components/common/XAddNativeForm/XAddNativeForm.vue'
3
3
  import { ref, computed, useAttrs } from 'vue'
4
4
 
@@ -1,4 +1,4 @@
1
- <script setup lang="ts">
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, watch, onMounted } from 'vue'
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
- // 通用布尔样式开关(以存在/空字符串/'true' 为真)
26
- const booleanStyleKeys = [
27
- 'hasTopMargin', 'useStyle7', 'useCycle', 'useStyle8', 'out-tab', 'no-underline', 'useStyle9'
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(() => loadExtraConfig(props.tabBarExtraConfig))
82
- watch(() => props.tabBarExtraConfig, loadExtraConfig)
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>
@@ -30,7 +30,7 @@ export default {
30
30
  data() {
31
31
  return {
32
32
  // 查询配置文件名
33
- queryParamsName: 'MachineHandCRUD_Simple',
33
+ queryParamsName: 'UserFilesListCRUD',
34
34
  // 查询配置左侧tree
35
35
  xTreeConfigName: 'addressType',
36
36
  // 新增表单固定值
@@ -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
  // 每一行的配置