vue2-client 1.22.2 → 1.22.3

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 (170) hide show
  1. package/.claude/settings.local.json +30 -30
  2. package/.env.his +19 -19
  3. package/.eslintrc.js +74 -74
  4. package/.history/.eslintrc_20260521171150.js +74 -0
  5. package/.history/.eslintrc_20260521171213.js +74 -0
  6. package/.history/src/base-client/components/common/HIS/HAddNativeForm/HAddNativeForm_20260601154443.vue +726 -0
  7. package/.history/src/base-client/components/common/HIS/HAddNativeForm/HAddNativeForm_20260601154700.vue +478 -0
  8. package/.history/src/base-client/components/common/HIS/HButtons/HButtons_20260512175435.vue +706 -0
  9. package/.history/src/base-client/components/common/HIS/HButtons/HButtons_20260512175450.vue +694 -0
  10. package/.history/src/base-client/components/common/HIS/HButtons/HButtons_20260611152602.vue +755 -0
  11. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260513145941.vue +524 -0
  12. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260513153133.vue +731 -0
  13. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260513160316.vue +525 -0
  14. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260601144150.vue +1046 -0
  15. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260310142713.vue +512 -0
  16. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260310145118.vue +511 -0
  17. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260311094834.vue +696 -0
  18. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260320143028.vue +693 -0
  19. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260409101450.vue +677 -0
  20. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260508164645.vue +758 -0
  21. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260508164714.vue +693 -0
  22. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260508171651.vue +716 -0
  23. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260509133717.vue +695 -0
  24. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260509171115.vue +664 -0
  25. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513140637.vue +1455 -0
  26. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513140935.vue +1441 -0
  27. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513150818.vue +1441 -0
  28. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513153119.vue +1442 -0
  29. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513153126.vue +1486 -0
  30. package/.history/src/base-client/components/common/XForm/XFormItem_20260513140854.vue +1607 -0
  31. package/.history/src/base-client/components/common/XMarkdownViewer/XMarkdownViewer_20260519140403.vue +643 -0
  32. package/.history/src/base-client/components/common/XMarkdownViewer/XMarkdownViewer_20260519140829.vue +628 -0
  33. package/.history/src/base-client/components/common/XMarkdownViewer/demo_20260519142824.vue +104 -0
  34. package/.history/src/base-client/components/common/XMarkdownViewer/demo_20260519143155.vue +102 -0
  35. package/.history/src/base-client/components/common/XReportGrid/XReport_20260309171231.vue +1241 -0
  36. package/.history/src/base-client/components/common/XReportGrid/XReport_20260309171441.vue +1223 -0
  37. package/.history/src/base-client/components/his/HAi/HAi_20260612174826.vue +472 -0
  38. package/.history/src/base-client/components/his/HAi/HAi_20260612175839.vue +538 -0
  39. package/.history/src/base-client/components/his/HAi/HAi_20260615103331.vue +650 -0
  40. package/.history/src/base-client/components/his/XHDescriptions/XHDescriptions_20260424134504.vue +1469 -0
  41. package/.history/src/base-client/components/his/XSidebar/XSidebar_20260610171133.vue +788 -0
  42. package/.history/src/base-client/components/his/XSidebar/XSidebar_20260610171151.vue +780 -0
  43. package/.history/src/base-client/components/his/XTransfer/XTransfer_20260511170841.vue +585 -0
  44. package/.history/src/base-client/components/his/XTransfer/XTransfer_20260511171138.vue +787 -0
  45. package/.history/src/base-client/components/his/XTransfer/XTransfer_20260512141830.vue +739 -0
  46. package/.history/src/components/STable/index_20260409155138.js +806 -0
  47. package/.history/src/components/STable/index_20260409155218.js +814 -0
  48. package/.history/src/expression/core/Expression_20260305164427.js +1371 -0
  49. package/.history/src/expression/core/Expression_20260305170258.js +1358 -0
  50. package/.history/src/expression/core/Program_20260305111830.js +944 -0
  51. package/.history/src/expression/core/Program_20260305112041.js +931 -0
  52. package/.history/src/logic/LogicRunner_20260304154306.js +170 -0
  53. package/.history/src/logic/LogicRunner_20260304155553.js +112 -0
  54. package/.history/src/logic/LogicRunner_20260305105834.js +112 -0
  55. package/.history/src/logic/LogicRunner_20260305112718.js +129 -0
  56. package/.history/src/logic/LogicRunner_20260305182436.js +133 -0
  57. package/.history/src/logic/LogicRunner_20260306151301.js +213 -0
  58. package/.history/src/logic/LogicRunner_20260306152419.js +213 -0
  59. package/.history/src/logic/plugins/common/DateTools_20260305154159.js +61 -0
  60. package/.history/src/logic/plugins/common/DateTools_20260305154217.js +44 -0
  61. package/.history/src/logic/plugins/common/DateTools_20260305161014.js +44 -0
  62. package/.history/src/logic/plugins/common/HttpTools_20260305164352.js +80 -0
  63. package/.history/src/logic/plugins/common/HttpTools_20260305170258.js +75 -0
  64. package/.history/src/logic/plugins/common/HttpTools_20260305171634.js +75 -0
  65. package/.history/src/logic/plugins/common/HttpTools_20260306152419.js +72 -0
  66. package/.history/src/services/api/restTools_20260427142149.js +245 -0
  67. package/.history/src/services/api/restTools_20260427142853.js +230 -0
  68. package/.history/src/services/api/restTools_20260519135558.js +230 -0
  69. package/.history/src/services/api/restTools_20260519140825.js +230 -0
  70. package/.history/src/services/api/restTools_20260519151223.js +230 -0
  71. package/.history/src/utils/indexedDB_20260306150918.js +593 -0
  72. package/.history/src/utils/indexedDB_20260306151301.js +586 -0
  73. package/.idea/af-vue2-client.iml +9 -0
  74. package/.idea/codeStyles/Project.xml +62 -0
  75. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  76. package/.idea/misc.xml +6 -0
  77. package/.idea/modules.xml +1 -1
  78. package/Components.md +60 -60
  79. package/index.js +31 -31
  80. package/jest-transform-stub.js +8 -8
  81. package/jest.setup.js +7 -7
  82. package/package.json +1 -1
  83. package/preview-input-box.html +180 -0
  84. package/src/assets/img/querySlotDemo.svg +15 -15
  85. package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
  86. package/src/base-client/components/common/CitySelect/index.js +3 -3
  87. package/src/base-client/components/common/CitySelect/index.md +109 -109
  88. package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
  89. package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
  90. package/src/base-client/components/common/HIS/HButtons/HButtons.vue +55 -1
  91. package/src/base-client/components/common/HIS/HForm/HForm.vue +1186 -1186
  92. package/src/base-client/components/common/HIS/HTab/HTab.vue +88 -1
  93. package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
  94. package/src/base-client/components/common/PersonSetting/index.js +3 -3
  95. package/src/base-client/components/common/Tree/index.js +2 -2
  96. package/src/base-client/components/common/Upload/index.js +3 -3
  97. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  98. package/src/base-client/components/common/XAddReport/XAddReport.vue +16 -1
  99. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  100. package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
  101. package/src/base-client/components/common/XDataDrawer/index.js +3 -3
  102. package/src/base-client/components/common/XDataDrawer/index.md +41 -41
  103. package/src/base-client/components/common/XDescriptions/index.js +3 -3
  104. package/src/base-client/components/common/XDescriptions/index.md +382 -382
  105. package/src/base-client/components/common/XForm/index.md +178 -178
  106. package/src/base-client/components/common/XInput/XInput.vue +32 -1
  107. package/src/base-client/components/common/XInspectionDetailDrawer/index.vue +1 -1
  108. package/src/base-client/components/common/XMarkdownViewer/demo.vue +102 -102
  109. package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
  110. package/src/base-client/components/common/XStepView/index.js +3 -3
  111. package/src/base-client/components/common/XStepView/index.md +31 -31
  112. package/src/base-client/components/common/XTable/index.md +255 -255
  113. package/src/base-client/components/his/HAi/HAi.vue +1177 -436
  114. package/src/base-client/components/his/XList/XList.vue +337 -58
  115. package/src/base-client/components/his/XSidebar/XSidebar.vue +36 -12
  116. package/src/base-client/components/his/XTransfer/index.md +327 -327
  117. package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
  118. package/src/base-client/plugins/Config.js +19 -19
  119. package/src/base-client/plugins/tabs-page-plugin.js +39 -39
  120. package/src/components/Charts/Bar.vue +62 -62
  121. package/src/components/Charts/ChartCard.vue +134 -134
  122. package/src/components/Charts/Liquid.vue +67 -67
  123. package/src/components/Charts/MiniArea.vue +39 -39
  124. package/src/components/Charts/MiniBar.vue +39 -39
  125. package/src/components/Charts/MiniProgress.vue +75 -75
  126. package/src/components/Charts/MiniSmoothArea.vue +40 -40
  127. package/src/components/Charts/Radar.vue +68 -68
  128. package/src/components/Charts/RankList.vue +77 -77
  129. package/src/components/Charts/TagCloud.vue +113 -113
  130. package/src/components/Charts/TransferBar.vue +64 -64
  131. package/src/components/Charts/Trend.vue +82 -82
  132. package/src/components/Charts/chart.less +12 -12
  133. package/src/components/Charts/smooth.area.less +13 -13
  134. package/src/components/NumberInfo/NumberInfo.vue +54 -54
  135. package/src/components/NumberInfo/index.js +3 -3
  136. package/src/components/NumberInfo/index.less +54 -54
  137. package/src/components/NumberInfo/index.md +43 -43
  138. package/src/components/STable/index.js +953 -953
  139. package/src/components/card/ChartCard.vue +79 -79
  140. package/src/components/chart/Bar.vue +60 -60
  141. package/src/components/chart/MiniArea.vue +67 -67
  142. package/src/components/chart/MiniBar.vue +59 -59
  143. package/src/components/chart/MiniProgress.vue +57 -57
  144. package/src/components/chart/Radar.vue +80 -80
  145. package/src/components/chart/RankingList.vue +60 -60
  146. package/src/components/chart/Trend.vue +79 -79
  147. package/src/components/chart/index.less +9 -9
  148. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  149. package/src/components/input/IInput.vue +66 -66
  150. package/src/components/menu/SideMenu.vue +75 -75
  151. package/src/components/menu/menu.js +273 -273
  152. package/src/components/tool/AStepItem.vue +60 -60
  153. package/src/layouts/CommonLayout.vue +56 -56
  154. package/src/lib.js +1 -1
  155. package/src/mock/extend/index.js +84 -84
  156. package/src/mock/goods/index.js +108 -108
  157. package/src/pages/dashboard/workplace/WorkPlace.vue +141 -141
  158. package/src/pages/system/dictionary/index.vue +44 -44
  159. package/src/pages/system/monitor/loginInfor/index.vue +37 -37
  160. package/src/pages/system/monitor/operLog/index.vue +37 -37
  161. package/src/services/api/cas.js +79 -79
  162. package/src/store/modules/setting.js +119 -119
  163. package/src/utils/errorCode.js +6 -6
  164. package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
  165. package/.idea/MarsCodeWorkspaceAppSettings.xml +0 -7
  166. package/.idea/google-java-format.xml +0 -6
  167. package/.idea/inspectionProfiles/Project_Default.xml +0 -24
  168. package/.idea/jsLinters/eslint.xml +0 -6
  169. package/.idea/vue2-client.iml +0 -12
  170. package/.vscode/settings.json +0 -28
@@ -0,0 +1,696 @@
1
+ <script setup>
2
+ import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'
3
+ import { ref, computed, useAttrs, nextTick, onMounted, onBeforeUnmount } from 'vue'
4
+
5
+ const props = defineProps({
6
+ // HFormTable特有的属性
7
+ tableStyle: {
8
+ type: String,
9
+ default: 'formtable-col1'
10
+ }
11
+ })
12
+
13
+ // 兼容多种样式配置
14
+ const attrs = useAttrs()
15
+
16
+ const wrapperClassObject = computed(() => {
17
+ const a = attrs
18
+ const classes = {}
19
+
20
+ // 通用布尔样式开关(以存在/空字符串/'true' 为真)
21
+ const booleanStyleKeys = [
22
+ 'button-row-0margin',
23
+ 'top-hidden',
24
+ 'dialog-style',
25
+ 'button-style',
26
+ 'header-center',
27
+ 'expanded-grid-white',
28
+ 'report-mode',
29
+ // listView模式下隐藏“已选择”按钮
30
+ 'listview-hide-selected',
31
+ 'min-height-auto'
32
+ ]
33
+ for (const key of booleanStyleKeys) {
34
+ const val = a[key]
35
+ const truthy = val === true || val === '' || val === 'true'
36
+ if (truthy) classes[`h-form-table-${key}`] = true
37
+ }
38
+
39
+ // 兼容通过 attrs 透传的分页样式:将值映射为当前样式中存在的类名
40
+ const paginationAttr = a && a.paginationStyle
41
+ if (paginationAttr && ['pagination-center', 'custom-pagination'].includes(paginationAttr)) {
42
+ classes[`h-form-table-${paginationAttr}`] = true
43
+ }
44
+ return classes
45
+ })
46
+
47
+ // 从attrs中获取行高度,通过内联样式传递
48
+ const wrapperStyleObject = computed(() => {
49
+ const a = attrs
50
+ const rowHeight = a['row-height'] || a.rowHeight || '37px'
51
+ return {
52
+ '--row-height': rowHeight
53
+ }
54
+ })
55
+
56
+ // 通过暴露的实例访问 $slots,避免直接依赖 Composition API 的 useSlots
57
+ // 在模板中使用 `$slots` 遍历以保持与 Vue2 兼容
58
+ // 创建对XFormTable组件的引用
59
+ const xFormTableRef = ref()
60
+ const wrapperRef = ref()
61
+
62
+ // 使用 MutationObserver 监听行结构/高度变化,实时同步固定列
63
+ let observer = null
64
+ let resizeObserver = null
65
+ let isSyncing = false
66
+ let rafId = 0
67
+ const getWrapperEl = () => wrapperRef.value
68
+ const scheduleSync = () => {
69
+ if (isSyncing) return
70
+ if (rafId) cancelAnimationFrame(rafId)
71
+ rafId = requestAnimationFrame(() => {
72
+ rafId = 0
73
+ syncFixedExpandedHeights()
74
+ })
75
+ }
76
+
77
+ // 翻页/换行时固定列 tbody 可能晚于主表更新,先清空固定列内联高度再延迟同步,避免第二页沿用第一页高度
78
+ const clearAllFixedRowHeights = () => {
79
+ try {
80
+ const wrapper = getWrapperEl()
81
+ if (!wrapper) return
82
+ const fixedRows = wrapper.querySelectorAll(
83
+ '.ant-table-fixed-right .ant-table-tbody > tr, .ant-table-fixed-right .ant-table-body-inner > table > tbody > tr, .ant-table-fixed-right .ant-table-body > table > tbody > tr'
84
+ )
85
+ fixedRows.forEach(f => {
86
+ if (!f) return
87
+ f.removeAttribute('data-synced-height')
88
+ f.style.removeProperty('height')
89
+ f.style.removeProperty('min-height')
90
+ f.style.removeProperty('max-height')
91
+ f.querySelectorAll('td').forEach(td => {
92
+ td.style.removeProperty('height')
93
+ td.style.removeProperty('min-height')
94
+ td.style.removeProperty('max-height')
95
+ td.style.removeProperty('line-height')
96
+ })
97
+ })
98
+ } catch (e) {
99
+ console.warn('[HFormTable] clearAllFixedRowHeights error:', e)
100
+ }
101
+ }
102
+
103
+ const scheduleSyncAfterPageChange = () => {
104
+ clearAllFixedRowHeights()
105
+ if (syncAfterPageChangeTimer) clearTimeout(syncAfterPageChangeTimer)
106
+ syncAfterPageChangeTimer = setTimeout(() => {
107
+ syncAfterPageChangeTimer = 0
108
+ scheduleSync()
109
+ // 再延迟一次,确保固定列已渲染并完成布局
110
+ setTimeout(scheduleSync, 60)
111
+ }, 80)
112
+ }
113
+ let syncAfterPageChangeTimer = 0
114
+
115
+ const setupHeightSync = () => {
116
+ try {
117
+ const wrapper = getWrapperEl()
118
+ if (!wrapper || observer) return
119
+
120
+ observer = new MutationObserver((mutations) => {
121
+ if (isSyncing) return
122
+ const hasChildList = mutations.some(m => m.type === 'childList')
123
+ const hasAttr = mutations.some(m =>
124
+ m.type === 'attributes' &&
125
+ (m.attributeName === 'style' || m.attributeName === 'class')
126
+ )
127
+ if (hasChildList) {
128
+ // 换行/翻页:先清空固定列高度,再延迟同步,避免第二页沿用第一页高度
129
+ scheduleSyncAfterPageChange()
130
+ } else if (hasAttr) {
131
+ scheduleSync()
132
+ }
133
+ })
134
+
135
+ // 监听主表行变化(兼容不同 Ant Table DOM)
136
+ const mainTable =
137
+ wrapper.querySelector('.ant-table-body > table > tbody') ||
138
+ wrapper.querySelector('.ant-table-tbody')
139
+ if (mainTable) {
140
+ observer.observe(mainTable, {
141
+ childList: true,
142
+ subtree: true,
143
+ attributes: true,
144
+ attributeFilter: ['style', 'class']
145
+ })
146
+ }
147
+
148
+ // 同时监听固定列 tbody(有些情况下固定列延后渲染/更新)
149
+ const fixedTbody =
150
+ wrapper.querySelector('.ant-table-fixed-right .ant-table-body-inner > table > tbody') ||
151
+ wrapper.querySelector('.ant-table-fixed-right .ant-table-body > table > tbody') ||
152
+ wrapper.querySelector('.ant-table-fixed-right .ant-table-tbody')
153
+ if (fixedTbody) {
154
+ observer.observe(fixedTbody, {
155
+ childList: true,
156
+ subtree: true,
157
+ attributes: true,
158
+ attributeFilter: ['style', 'class']
159
+ })
160
+ }
161
+
162
+ // 兜底:表体尺寸变化也触发同步(如下拉弹出/收起、滚动条变化)
163
+ const tableBody = wrapper.querySelector('.ant-table-body') || wrapper.querySelector('.ant-table-body-inner')
164
+ if (!resizeObserver && tableBody && typeof ResizeObserver !== 'undefined') {
165
+ resizeObserver = new ResizeObserver(() => scheduleSync())
166
+ resizeObserver.observe(tableBody)
167
+ }
168
+ } catch (e) {
169
+ console.warn('[HFormTable] setupHeightSync error:', e)
170
+ }
171
+ }
172
+
173
+ // 同步固定列行高到主表对应行高,避免错位
174
+ const syncFixedExpandedHeights = () => {
175
+ try {
176
+ const wrapper = getWrapperEl()
177
+ if (!wrapper) return
178
+ if (isSyncing) return
179
+ isSyncing = true
180
+ const mainRows = Array.from(
181
+ wrapper.querySelectorAll('.ant-table-tbody > tr.ant-table-row, .ant-table-body > table > tbody > tr.ant-table-row')
182
+ )
183
+ const fixedRows = Array.from(
184
+ wrapper.querySelectorAll('.ant-table-fixed-right .ant-table-tbody > tr, .ant-table-fixed-right .ant-table-body-inner > table > tbody > tr, .ant-table-fixed-right .ant-table-body > table > tbody > tr')
185
+ )
186
+
187
+ // 用 rowKey 精准匹配,避免固定列/主表 tr 数量不一致时错位
188
+ const getRowKey = (tr) => tr?.getAttribute?.('data-row-key') || tr?.dataset?.rowKey || ''
189
+ const mainHeights = new Map()
190
+ mainRows.forEach(m => {
191
+ const key = getRowKey(m)
192
+ if (!key) return
193
+ const h = Math.round(m.getBoundingClientRect().height)
194
+ if (!h) return
195
+ mainHeights.set(key, h)
196
+ })
197
+
198
+ // 无 key 的占位行:强制压成 0 高,避免底部占位行撑高整表(第二页“下面几行高”)
199
+ const collapsePlaceholderRow = (tr) => {
200
+ if (!tr) return
201
+ tr.removeAttribute('data-synced-height')
202
+ tr.style.setProperty('height', '0', 'important')
203
+ tr.style.setProperty('min-height', '0', 'important')
204
+ tr.style.setProperty('max-height', '0', 'important')
205
+ tr.style.setProperty('line-height', '0', 'important')
206
+ tr.style.setProperty('overflow', 'hidden', 'important')
207
+ tr.querySelectorAll('td').forEach(td => {
208
+ td.style.setProperty('height', '0', 'important')
209
+ td.style.setProperty('min-height', '0', 'important')
210
+ td.style.setProperty('max-height', '0', 'important')
211
+ td.style.setProperty('line-height', '0', 'important')
212
+ td.style.setProperty('padding', '0', 'important')
213
+ td.style.setProperty('border', 'none', 'important')
214
+ td.style.setProperty('overflow', 'hidden', 'important')
215
+ })
216
+ }
217
+
218
+ // 改用「顺序匹配」而非依赖 key 匹配(避免翻页后 key 时间差导致匹配失败)
219
+ // 主表行和固定列行按 DOM 顺序一一对应
220
+ const mainRowsList = mainRows.filter(m => getRowKey(m)) // 只取有 key 的主表行
221
+ const fixedRowsList = fixedRows.filter(f => getRowKey(f)) // 只取有 key 的固定列行
222
+ const count = Math.min(mainRowsList.length, fixedRowsList.length)
223
+
224
+ for (let i = 0; i < count; i++) {
225
+ const m = mainRowsList[i]
226
+ const f = fixedRowsList[i]
227
+ const key = getRowKey(m)
228
+ if (!key) continue
229
+
230
+ const h = Math.round(m.getBoundingClientRect().height)
231
+ if (!h) continue
232
+
233
+ const hs = String(h)
234
+ if (f.dataset.syncedHeight === hs) continue
235
+ f.dataset.syncedHeight = hs
236
+
237
+ // 彻底清理并重新设置高度,确保覆盖 CSS 样式
238
+ f.style.cssText = ''
239
+ f.style.setProperty('height', h + 'px', 'important')
240
+ f.style.setProperty('min-height', h + 'px', 'important')
241
+ f.style.setProperty('max-height', h + 'px', 'important')
242
+ f.style.setProperty('line-height', 'normal', 'important')
243
+ f.querySelectorAll('td').forEach(td => {
244
+ td.style.cssText = ''
245
+ td.style.setProperty('height', h + 'px', 'important')
246
+ td.style.setProperty('min-height', h + 'px', 'important')
247
+ td.style.setProperty('max-height', h + 'px', 'important')
248
+ td.style.setProperty('line-height', 'normal', 'important')
249
+ td.style.setProperty('vertical-align', 'middle', 'important')
250
+ })
251
+ }
252
+
253
+ // 清理所有固定列行中可能残留的旧高度(防止旧数据污染)
254
+ fixedRows.forEach(f => {
255
+ const key = getRowKey(f)
256
+ const mainKey = mainHeights.get(key)
257
+ if (!mainKey && f.dataset.syncedHeight) {
258
+ // 无对应主表 key,清理掉之前同步的高度
259
+ collapsePlaceholderRow(f)
260
+ }
261
+ })
262
+ } catch (e) {
263
+ console.warn('[HFormTable] syncFixedExpandedHeights error:', e)
264
+ } finally {
265
+ isSyncing = false
266
+ }
267
+ }
268
+ const onExpandLog = (expanded, record) => {
269
+ // 等DOM完成再测量
270
+ nextTick(() => {
271
+ // 设置实时监听(如果还没设置)
272
+ if (!observer) {
273
+ setupHeightSync()
274
+ }
275
+
276
+ // 立即同步一次(避免第一次展开时错位)
277
+ syncFixedExpandedHeights()
278
+
279
+ // 短延迟再同步一次(应对异步渲染)
280
+ setTimeout(() => {
281
+ syncFixedExpandedHeights()
282
+ }, 20)
283
+ })
284
+ }
285
+
286
+ onMounted(() => {
287
+ nextTick(() => {
288
+ setupHeightSync()
289
+ syncFixedExpandedHeights()
290
+ })
291
+ })
292
+
293
+ onBeforeUnmount(() => {
294
+ try {
295
+ observer?.disconnect?.()
296
+ resizeObserver?.disconnect?.()
297
+ if (rafId) cancelAnimationFrame(rafId)
298
+ if (syncAfterPageChangeTimer) clearTimeout(syncAfterPageChangeTimer)
299
+ } finally {
300
+ observer = null
301
+ resizeObserver = null
302
+ rafId = 0
303
+ syncAfterPageChangeTimer = 0
304
+ isSyncing = false
305
+ }
306
+ })
307
+
308
+ // 暴露方法给父组件使用
309
+ defineExpose({
310
+ // 为了兼容性,保留getXFormTableInstance方法
311
+ getXFormTableInstance: () => xFormTableRef.value,
312
+ /** 等待配置结束的异步方法,委托给内部 XFormTable */
313
+ waitConfigEnd: () => xFormTableRef.value?.waitConfigEnd?.() ?? Promise.resolve()
314
+ })
315
+
316
+ // 计算是否使用自定义分页(兼容 attrs 透传与 tableStyle 配置)
317
+ const isCustomPagination = computed(() => {
318
+ const a = attrs
319
+ const paginationAttr = (a && a.paginationStyle) || ''
320
+ return props.tableStyle === 'custom-pagination' || paginationAttr === 'custom-pagination'
321
+ })
322
+ // 是否隐藏顶部功能区
323
+ const isHiddenFunctionalArea = computed(() => {
324
+ return attrs.hiddenFunctionalArea === 'true' || attrs.hiddenFunctionalArea === true
325
+ })
326
+
327
+ // 从 attrs 中获取 pageMaxSize,如果存在则作为 defaultPageSize
328
+ const computedDefaultPageSize = computed(() => {
329
+ const pageMaxSize = attrs.pageMaxSize
330
+ // 将字符串转换为数字,如果无效则使用默认值
331
+ const numericPageSize = pageMaxSize ? Number(pageMaxSize) : null
332
+ const defaultSize = (numericPageSize && numericPageSize > 0) ? numericPageSize : 10
333
+
334
+ return defaultSize
335
+ })
336
+ </script>
337
+
338
+ <template>
339
+ <div
340
+ ref="wrapperRef"
341
+ class="h-form-table-wrapper"
342
+ :class="[
343
+ `h-form-table-${tableStyle}`,
344
+ wrapperClassObject
345
+ ]"
346
+ :style="wrapperStyleObject"
347
+ >
348
+ <x-form-table
349
+ ref="xFormTableRef"
350
+ v-bind="$attrs"
351
+ :defaultPageSize="computedDefaultPageSize"
352
+ :customPagination="isCustomPagination"
353
+ :hiddenFunctionalArea="isHiddenFunctionalArea"
354
+ @expand="onExpandLog"
355
+ @configEnd="$emit('configEnd')"
356
+ v-on="$listeners"
357
+ >
358
+ <template v-for="(_, name) in $slots" #[name]="slotData">
359
+ <slot :name="name" v-bind="slotData" />
360
+ </template>
361
+ </x-form-table>
362
+ </div>
363
+ </template>
364
+
365
+ <style scoped lang="less">
366
+ // 表格行高度变量,默认37px
367
+ @row-height: var(--row-height, 37px);
368
+
369
+ .h-form-table-wrapper {
370
+ // 基础样式
371
+ :deep(.table-wrapper) {
372
+ .ant-table {
373
+ .ant-table-row {
374
+ margin: 0 !important;
375
+ height: @row-height !important;
376
+ max-height: @row-height !important;
377
+ line-height: @row-height !important;
378
+
379
+ > td {
380
+ height: @row-height !important;
381
+ min-height: @row-height !important;
382
+ max-height: @row-height !important;
383
+ padding: 0 8px !important;
384
+ box-sizing: border-box !important;
385
+ vertical-align: middle !important;
386
+
387
+ // 去掉内部元素的 margin,防止带下拉框的行被撑高
388
+ .ant-form-item,
389
+ .ant-form-item-control {
390
+ margin-bottom: 0 !important;
391
+ margin-top: 0 !important;
392
+ }
393
+ .ant-select,
394
+ .ant-input,
395
+ .ant-picker {
396
+ margin-bottom: 0 !important;
397
+ margin-top: 0 !important;
398
+ height: @row-height !important;
399
+ max-height: @row-height !important;
400
+ line-height: @row-height !important;
401
+ }
402
+ .ant-select-selection--single {
403
+ height: calc(@row-height - 2px) !important;
404
+ min-height: calc(@row-height - 2px) !important;
405
+ }
406
+ .ant-select-selection__rendered {
407
+ line-height: calc(@row-height - 2px) !important;
408
+ }
409
+ }
410
+ }
411
+ font-size: 16px;
412
+ }
413
+
414
+ .ant-alert-info {
415
+ display: none;
416
+ }
417
+ }
418
+
419
+ :deep(.ant-card) {
420
+ margin: -10px 0px 29px 0px;
421
+ }
422
+ :deep(.ant-space .ant-btn .anticon) {
423
+ display: none;
424
+ }
425
+ :deep(.ant-space .ant-btn) {
426
+ border: 0px;
427
+ box-shadow: none;
428
+ padding: 0px;
429
+ color: #5D5C5C;
430
+ font-weight: bold;
431
+ letter-spacing: 0em;
432
+ font-size: 18px;
433
+ line-height: normal;
434
+ background-color: transparent;
435
+ font-family: "Source Han Sans";
436
+ }
437
+
438
+ :deep(.ant-card-body) {
439
+ padding: 0 6px;
440
+ }
441
+
442
+ :deep(.ant-table-small) {
443
+ border-width: 0;
444
+
445
+ .ant-table-fixed {
446
+ border-radius: 0;
447
+ border-bottom: 1px solid #f0f0f0;
448
+ }
449
+ }
450
+
451
+ // 操作列(固定列)高度与主体一致,行内文字垂直居中
452
+ :deep(.ant-table-fixed-right .ant-table-body-inner) {
453
+ table tbody tr.ant-table-row {
454
+ height: @row-height !important;
455
+ max-height: @row-height !important;
456
+
457
+ > td {
458
+ height: @row-height !important;
459
+ min-height: @row-height !important;
460
+ max-height: @row-height !important;
461
+ padding: 0 8px !important;
462
+ box-sizing: border-box !important;
463
+ vertical-align: middle !important;
464
+ line-height: @row-height !important;
465
+ }
466
+ }
467
+ }
468
+ // 主表行高与固定列一致
469
+ :deep(.table-wrapper .ant-table-body > table > tbody > tr.ant-table-row) {
470
+ height: @row-height !important;
471
+ max-height: @row-height !important;
472
+ }
473
+
474
+ :deep(.ant-table-fixed-right .ant-btn),
475
+ :deep(.ant-table-fixed-right a) {
476
+ line-height: inherit !important;
477
+ vertical-align: middle !important;
478
+ padding: 0 4px;
479
+ }
480
+
481
+ // 表格高度样式
482
+ &.h-form-table-height {
483
+ :deep(.table-wrapper) {
484
+ .ant-select-open ~ .ant-table-content {
485
+ height: 500px !important;
486
+ }
487
+ }
488
+ }
489
+ // 表格最小高度自动
490
+ &.h-form-table-min-height-auto {
491
+ :deep(.table-wrapper) {
492
+ .ant-table:not(.ant-table-empty) {
493
+ .ant-table-content {
494
+ min-height: auto !important;
495
+ .ant-table-body {
496
+ min-height: auto !important;
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+
503
+ // 修复数据量少时下拉框被挡住的问题:为表格内容区域设置最小高度
504
+ // 当表格有数据时,确保表格内容区域有足够高度,避免下拉框被挡住
505
+ // 注意:只在表格有数据时应用,避免空表格时显示问题
506
+ :deep(.table-wrapper) {
507
+ .ant-table:not(.ant-table-empty) {
508
+ .ant-table-content {
509
+ // 设置最小高度,确保即使数据少时也有足够空间显示下拉框
510
+ // 这个高度应该足够显示下拉框选项(通常下拉框高度约200-300px)
511
+ min-height: 300px;
512
+ .ant-table-body {
513
+ // 确保表格体也有最小高度,保证滚动容器有足够空间
514
+ min-height: 250px;
515
+ }
516
+ }
517
+ }
518
+ }
519
+
520
+ // 表格样式
521
+ &.h-form-table-table {
522
+ :deep(.ant-table-small .ant-table-fixed-header) {
523
+ .ant-table-content {
524
+ .ant-table-content {
525
+ .ant-table-body {
526
+ border-radius: 0 0 4px 4px;
527
+ // 修复展开行后固定列与主体错位:保持表体滚动容器为自动滚动
528
+ overflow: auto !important;
529
+ }
530
+ }
531
+ }
532
+ }
533
+ }
534
+ // 移除之前隐藏固定列占位行的样式,保持与主体行数一致
535
+ // 展开行单元格去除额外内边距,避免高度不一致
536
+ :deep(.ant-table-expanded-row > td) {
537
+ padding: 0 !important;
538
+ }
539
+ // 展开内容中的表单/控件去掉外边距,避免撑高
540
+ :deep(.ant-table-expanded-row .ant-form-item) {
541
+ margin-bottom: 0 !important;
542
+ }
543
+
544
+ // 移除之前的隐藏固定列样式,避免展开/合并后操作列消失
545
+ &.h-form-table-dialog-style {
546
+ /* 选择前面的兄弟元素 */
547
+ :global(.ant-col.ant-col-24[name="trGroup"]:has(+ .ant-card .ant-card-body .h-form-table-wrapper.h-form-table-dialog-style)) {
548
+ padding-top: 0px !important;
549
+ padding-left: 0px !important;
550
+ }
551
+
552
+ :global(.ant-card-body:has(.h-form-table-wrapper.h-form-table-dialog-style)) {
553
+ padding-top: 0px !important;
554
+ padding-left: 0px !important;
555
+ }
556
+ }
557
+ // 隐藏按钮区域
558
+ &.h-form-table-button-area-hide {
559
+ :deep(.ant-btn) {
560
+ display: none;
561
+ }
562
+
563
+ :deep(.table-wrapper) {
564
+ margin-top: -39px;
565
+ }
566
+ }
567
+
568
+ // 顶部区域隐藏(与按钮隐藏一致的视觉需求)
569
+ &.h-form-table-top-hidden {
570
+ :deep(.ant-btn) {
571
+ display: none;
572
+ }
573
+
574
+ :deep(.table-wrapper) {
575
+ margin-top: -39px;
576
+ }
577
+ }
578
+
579
+ // 列样式1
580
+ &.h-form-table-formtable-col1 {
581
+ :deep(.table-wrapper) {
582
+ .ant-row {
583
+ .ant-col span {
584
+ border: none;
585
+ width: auto;
586
+ margin-bottom: auto;
587
+ }
588
+ }
589
+
590
+ .ant-table {
591
+ .ant-table-body {
592
+ .ant-table-fixed colgroup col:nth-child(2) {
593
+ width: 50px;
594
+ min-width: 50px;
595
+ }
596
+ }
597
+
598
+ .ant-table-header {
599
+ .ant-table-fixed colgroup col:nth-child(2) {
600
+ width: 50px;
601
+ min-width: 50px;
602
+ }
603
+ }
604
+ }
605
+ }
606
+ }
607
+
608
+ // 底部分页居中 & 自定义分页样式(共用样式)
609
+ &.h-form-table-bottom-center,
610
+ &.h-form-table-custom-pagination {
611
+ :deep(.table-wrapper) {
612
+ .ant-row-flex-start {
613
+ position: relative;
614
+ display: flex;
615
+ align-items: center;
616
+ margin-top: 12px !important;
617
+ height: 32px;
618
+
619
+ // 防止第一个子元素无限拉伸,影响分页居中
620
+ > :first-child {
621
+ flex: 0 0 auto;
622
+ }
623
+
624
+ // 将第二个子元素(分页)绝对居中
625
+ > :nth-child(2) {
626
+ position: absolute;
627
+ left: 50%;
628
+ transform: translateX(-50%);
629
+ }
630
+ }
631
+ }
632
+ }
633
+
634
+ // 按钮行0margin
635
+ &.h-form-table-button-row-0margin {
636
+ :deep(.ant-row) {
637
+ margin: 0px;
638
+ }
639
+ }
640
+ // crud按钮样式
641
+ &.h-form-table-button-style {
642
+ :deep(.ant-btn){
643
+ border-radius: 6px;
644
+ background-color: #FFFFFF;
645
+ border: 1px solid #9499A0;
646
+ color: #313131;
647
+ font-weight: normal;
648
+ letter-spacing: 0em;
649
+ font-size: 16px;
650
+ font-family: "Source Han Sans";
651
+ line-height: normal;
652
+ }
653
+ }
654
+ // 表格内容全部居中样式
655
+ &.h-form-table-header-center {
656
+ :deep(.ant-table-thead > tr > th),
657
+ :deep(.ant-table-tbody > tr > td) {
658
+ text-align: center !important;
659
+ }
660
+ }
661
+ // 行展开白色背景
662
+ &.h-form-table-expanded-grid-white {
663
+ :deep(.ant-table-expanded-row){
664
+ background-color: white;
665
+ }
666
+ }
667
+ // listView模式下隐藏“已选择”按钮(该按钮包含 monitor 图标)
668
+ &.h-form-table-listview-hide-selected {
669
+ :deep(.ant-badge:has(.ant-btn .anticon-monitor)) {
670
+ display: none !important;
671
+ }
672
+ }
673
+ // 报表样式
674
+ @skip-cells: 2;
675
+ &.h-form-table-report-mode {
676
+ --skip-cells: 4;
677
+ :deep(.ant-table-header){
678
+ padding-bottom: 0px !important;
679
+ }
680
+ :deep(.ant-table-content){
681
+ border: 1px solid #E5E9F0;
682
+ }
683
+ :deep(.resize-table-th){
684
+ background-color: white !important;
685
+ }
686
+ :deep(.ant-table-row) {
687
+ .ant-table-row-cell-ellipsis {
688
+ &:nth-child(n + @{skip-cells}) {
689
+ color: #3362DA !important;
690
+ }
691
+ }
692
+ }
693
+ }
694
+ }
695
+ </style>
696
+