@ebiz/designer-components 0.0.57 → 0.0.59

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 (199) hide show
  1. package/README.md +29 -29
  2. package/dist/designer-components.css +1 -1
  3. package/dist/index.mjs +4822 -4822
  4. package/package.json +1 -1
  5. package/src/App.vue +26 -26
  6. package/src/apiService/SIMPLE_DATA_SERVICE.md +284 -284
  7. package/src/apiService/mockDataService.js +115 -115
  8. package/src/apiService/simpleDataService.js +297 -297
  9. package/src/assets/base.css +86 -86
  10. package/src/assets/logo.svg +1 -1
  11. package/src/components/Button.vue +149 -149
  12. package/src/components/DataContainer.vue +40 -40
  13. package/src/components/EbizApproval.vue +332 -338
  14. package/src/components/EbizAutoForm.vue +596 -596
  15. package/src/components/EbizAvatar.vue +115 -115
  16. package/src/components/EbizCheckbox.vue +93 -93
  17. package/src/components/EbizCheckboxGroup.vue +69 -69
  18. package/src/components/EbizDepartmentSelector.vue +144 -144
  19. package/src/components/EbizDescriptions.vue +340 -340
  20. package/src/components/EbizDescriptionsItem.vue +47 -47
  21. package/src/components/EbizDetailBlock.vue +81 -81
  22. package/src/components/EbizDialog.vue +260 -260
  23. package/src/components/EbizDiv.vue +32 -32
  24. package/src/components/EbizDivider.vue +96 -96
  25. package/src/components/EbizEmployeeInfo.vue +138 -138
  26. package/src/components/EbizEmployeeSelector.vue +1093 -1086
  27. package/src/components/EbizFileUpload.vue +238 -238
  28. package/src/components/EbizMap.vue +541 -541
  29. package/src/components/EbizOkrTree.vue +99 -99
  30. package/src/components/EbizPageHeader.vue +95 -95
  31. package/src/components/EbizPagination.vue +162 -162
  32. package/src/components/EbizPopconfirm.vue +47 -47
  33. package/src/components/EbizRadio.vue +86 -86
  34. package/src/components/EbizRadioGroup.vue +83 -83
  35. package/src/components/EbizRemoteSelect.vue +232 -232
  36. package/src/components/EbizRouteBreadcrumb.vue +46 -46
  37. package/src/components/EbizSelect.vue +85 -85
  38. package/src/components/EbizSpace.vue +100 -100
  39. package/src/components/EbizStatistic.vue +149 -149
  40. package/src/components/EbizStatsCard.vue +113 -113
  41. package/src/components/EbizSwiper.vue +113 -113
  42. package/src/components/EbizSwiperItem.vue +13 -13
  43. package/src/components/EbizSwitch.vue +85 -85
  44. package/src/components/EbizTabHeader.vue +132 -132
  45. package/src/components/EbizTabPanel.vue +22 -22
  46. package/src/components/EbizTable.vue +469 -469
  47. package/src/components/EbizTableColumn.vue +116 -116
  48. package/src/components/EbizTableSort.vue +179 -179
  49. package/src/components/EbizTabs.vue +142 -142
  50. package/src/components/EbizTdesignButtonDialog.vue +332 -332
  51. package/src/components/EbizTdesignLoading.vue +107 -107
  52. package/src/components/EbizTimePicker.vue +143 -143
  53. package/src/components/EbizTitle.vue +91 -91
  54. package/src/components/EbizTree.vue +152 -152
  55. package/src/components/EbizTreeMergeTable.vue +1414 -1414
  56. package/src/components/EbizTreeSelector.vue +418 -418
  57. package/src/components/EbizVxeTable.vue +290 -290
  58. package/src/components/Form.vue +28 -28
  59. package/src/components/Home.vue +7 -7
  60. package/src/components/MyComponent.vue +39 -39
  61. package/src/components/Table.vue +45 -45
  62. package/src/components/TdesignAlert.vue +115 -115
  63. package/src/components/TdesignButton.vue +135 -135
  64. package/src/components/TdesignCalendar/index.vue +145 -145
  65. package/src/components/TdesignCard.vue +195 -195
  66. package/src/components/TdesignCol.vue +101 -101
  67. package/src/components/TdesignCollapse.vue +142 -142
  68. package/src/components/TdesignCollapsePanel.vue +79 -79
  69. package/src/components/TdesignDatePicker.vue +124 -124
  70. package/src/components/TdesignDescriptions.vue +74 -74
  71. package/src/components/TdesignDescriptionsItem.vue +50 -50
  72. package/src/components/TdesignDialog.vue +225 -225
  73. package/src/components/TdesignForm.vue +138 -138
  74. package/src/components/TdesignFormItem.vue +105 -105
  75. package/src/components/TdesignGrid.vue +55 -55
  76. package/src/components/TdesignIcon.vue +67 -67
  77. package/src/components/TdesignImage.vue +162 -162
  78. package/src/components/TdesignImageViewer.vue +200 -200
  79. package/src/components/TdesignInput.vue +242 -242
  80. package/src/components/TdesignSelect.vue +444 -444
  81. package/src/components/TdesignTag.vue +117 -117
  82. package/src/components/TdesignTextarea.vue +142 -142
  83. package/src/components/TdesignTimeline.vue +58 -58
  84. package/src/components/TdesignTimelineItem.vue +71 -71
  85. package/src/components/TdesignUpload.vue +388 -388
  86. package/src/components/TdesignWatermark.vue +107 -107
  87. package/src/components/ebiz-form/components/cascader.vue +61 -61
  88. package/src/components/ebiz-form/components/checkbox.vue +37 -37
  89. package/src/components/ebiz-form/components/city.vue +137 -137
  90. package/src/components/ebiz-form/components/date-panel.vue +52 -52
  91. package/src/components/ebiz-form/components/date-range-panel.vue +52 -52
  92. package/src/components/ebiz-form/components/date-range.vue +56 -56
  93. package/src/components/ebiz-form/components/date.vue +52 -52
  94. package/src/components/ebiz-form/components/editor-multi-language.vue +47 -47
  95. package/src/components/ebiz-form/components/editor.vue +78 -78
  96. package/src/components/ebiz-form/components/file-multi-language.vue +52 -52
  97. package/src/components/ebiz-form/components/file.vue +149 -149
  98. package/src/components/ebiz-form/components/images-multi-language.vue +52 -52
  99. package/src/components/ebiz-form/components/images.vue +129 -129
  100. package/src/components/ebiz-form/components/img-multi-language.vue +51 -51
  101. package/src/components/ebiz-form/components/img.vue +129 -129
  102. package/src/components/ebiz-form/components/number.vue +50 -50
  103. package/src/components/ebiz-form/components/radio.vue +28 -28
  104. package/src/components/ebiz-form/components/select.vue +119 -119
  105. package/src/components/ebiz-form/components/switch.vue +23 -23
  106. package/src/components/ebiz-form/components/text-multi-language.vue +47 -47
  107. package/src/components/ebiz-form/components/text.vue +52 -52
  108. package/src/components/ebiz-form/components/textarea-multi-language.vue +48 -48
  109. package/src/components/ebiz-form/components/textarea.vue +29 -29
  110. package/src/components/ebiz-form/components/video-multi-language.vue +51 -51
  111. package/src/components/ebiz-form/components/video.vue +97 -97
  112. package/src/components/ebiz-form/index.vue +157 -157
  113. package/src/components/examples/PopconfirmExample.vue +149 -149
  114. package/src/components/icons/IconCommunity.vue +7 -7
  115. package/src/components/icons/IconDocumentation.vue +7 -7
  116. package/src/components/icons/IconEcosystem.vue +7 -7
  117. package/src/components/icons/IconSupport.vue +7 -7
  118. package/src/components/icons/IconTooling.vue +19 -19
  119. package/src/components/senior/EbizSData/index.vue +260 -260
  120. package/src/components/senior/EbizSDialog/index.vue +713 -712
  121. package/src/components/senior/EbizSForm/README.md +157 -157
  122. package/src/components/senior/EbizSForm/index.vue +668 -668
  123. package/src/components/senior/EbizSForm/item.vue +522 -522
  124. package/src/components/senior/EbizSForm/mItems/DateTimePicker.vue +51 -51
  125. package/src/components/senior/EbizSForm/mItems/Picker.vue +63 -63
  126. package/src/index.js +218 -218
  127. package/src/main.js +55 -55
  128. package/src/router/index.js +374 -374
  129. package/src/utils/formatCode.js +24 -24
  130. package/src/utils/generateImportStatement.js +52 -52
  131. package/src/utils/hasJsx.js +25 -25
  132. package/src/utils/index.js +166 -166
  133. package/src/utils/mergeOptions.js +29 -29
  134. package/src/utils/parseRequiredBlocks.js +18 -18
  135. package/src/utils/upload.ts +126 -126
  136. package/src/utils/vue-sfc-validator.js +155 -155
  137. package/src/views/Button.vue +23 -23
  138. package/src/views/CheckboxDemo.vue +104 -104
  139. package/src/views/DataContainer.vue +19 -19
  140. package/src/views/DialogDemo.vue +125 -125
  141. package/src/views/EbizApprovalDemo.vue +76 -76
  142. package/src/views/EbizAutoFormDemo.vue +129 -129
  143. package/src/views/EbizAvatar.vue +223 -223
  144. package/src/views/EbizDepartmentSelectorDemo.vue +169 -169
  145. package/src/views/EbizDetailBlockDemo.vue +30 -30
  146. package/src/views/EbizEmployeeInfo.vue +249 -249
  147. package/src/views/EbizEmployeeSelector.vue +83 -83
  148. package/src/views/EbizMap.vue +201 -201
  149. package/src/views/EbizRadioDemo.vue +151 -151
  150. package/src/views/EbizSDataDemo.vue +136 -136
  151. package/src/views/EbizSDialogDemo.vue +301 -301
  152. package/src/views/EbizSForm/index.vue +359 -359
  153. package/src/views/EbizSFormDemo.vue +420 -420
  154. package/src/views/EbizSpace.vue +185 -185
  155. package/src/views/EbizSwiper.vue +157 -157
  156. package/src/views/EbizTdesignButtonDialogExample.vue +437 -437
  157. package/src/views/Form.vue +19 -19
  158. package/src/views/GridDemo.vue +238 -238
  159. package/src/views/Home.vue +146 -146
  160. package/src/views/Mindmap.vue +17 -17
  161. package/src/views/MyComponent.vue +19 -19
  162. package/src/views/OkrTree.vue +19 -19
  163. package/src/views/PageHeaderDemo.vue +104 -104
  164. package/src/views/PaginationDemo.vue +96 -96
  165. package/src/views/PermissionBoxDemo.vue +85 -85
  166. package/src/views/PopconfirmDemo.vue +80 -80
  167. package/src/views/RemoteSelect.vue +350 -350
  168. package/src/views/StatisticDemo.vue +190 -190
  169. package/src/views/SwitchDemo.vue +79 -79
  170. package/src/views/Table.vue +19 -19
  171. package/src/views/TableDemo.vue +334 -334
  172. package/src/views/TableSortDemo.vue +143 -143
  173. package/src/views/TableView.vue +68 -68
  174. package/src/views/TabsDemo.vue +282 -282
  175. package/src/views/TagDemo.vue +101 -101
  176. package/src/views/TdesignAlert.vue +98 -98
  177. package/src/views/TdesignButton.vue +190 -190
  178. package/src/views/TdesignCalendar.vue +94 -94
  179. package/src/views/TdesignCard.vue +296 -296
  180. package/src/views/TdesignCollapse.vue +293 -293
  181. package/src/views/TdesignDatePicker.vue +187 -187
  182. package/src/views/TdesignDescriptions.vue +101 -101
  183. package/src/views/TdesignForm.vue +248 -248
  184. package/src/views/TdesignIcon.vue +203 -203
  185. package/src/views/TdesignImage.vue +215 -215
  186. package/src/views/TdesignImageViewer.vue +198 -198
  187. package/src/views/TdesignInput.vue +252 -252
  188. package/src/views/TdesignSelect.vue +473 -473
  189. package/src/views/TdesignSwiper.vue +157 -157
  190. package/src/views/TextareaDemo.vue +93 -93
  191. package/src/views/TimePickerDemo.vue +146 -146
  192. package/src/views/TimelineDemo.vue +160 -160
  193. package/src/views/Title.vue +19 -19
  194. package/src/views/TreeDemo.vue +254 -254
  195. package/src/views/TreeMergeTableDemo.vue +239 -239
  196. package/src/views/TreeSelectorDemo.vue +245 -245
  197. package/src/views/UploadDemo.vue +121 -121
  198. package/src/views/VxeTableDemo.vue +279 -279
  199. package/src/views/WatermarkDemo.vue +85 -85
@@ -1,341 +1,341 @@
1
- <template>
2
- <div class="ebiz-descriptions">
3
- <div v-if="title || $slots.title" class="ebiz-descriptions__header">
4
- <slot name="title">{{ title }}</slot>
5
- </div>
6
- <table
7
- class="ebiz-descriptions__body"
8
- :class="[
9
- `ebiz-descriptions--${size}`,
10
- { 'ebiz-descriptions__body--fixed': tableLayout === 'fixed' },
11
- { 'ebiz-descriptions__body--border': border }
12
- ]"
13
- :style="border && tableBorderColor ? {'--td-descriptions-border-color': tableBorderColor} : {}"
14
- >
15
- <tbody>
16
- <template v-if="rows.length > 0">
17
- <template v-if="layout === 'horizontal'">
18
- <tr v-for="(row, rowIndex) in rows" :key="`row-${rowIndex}`">
19
- <template v-for="(item, colIndex) in row" :key="`${rowIndex}-${colIndex}`">
20
- <template v-if="itemLayout === 'horizontal'">
21
- <th
22
- class="ebiz-descriptions__label"
23
- :class="[item.labelClassName]"
24
- >
25
- <slot :name="`${item.slotName}-label`">
26
- {{ item.label }}
27
- </slot>
28
- <span v-if="colon" class="ebiz-descriptions__colon">:</span>
29
- </th>
30
- <td
31
- :colspan="item.span * 2 - 1"
32
- class="ebiz-descriptions__content"
33
- :class="[item.contentClassName]"
34
- >
35
- <slot :name="item.slotName">
36
- {{ item.content }}
37
- </slot>
38
- </td>
39
- </template>
40
- </template>
41
- </tr>
42
- </template>
43
- <template v-else>
44
- <template v-for="(row, rowIndex) in rows" :key="`${rowIndex}`">
45
- <template v-if="itemLayout === 'horizontal'">
46
- <tr>
47
- <template v-for="(item, colIndex) in row" :key="`label-${rowIndex}-${colIndex}`">
48
- <th
49
- class="ebiz-descriptions__label"
50
- :class="[item.labelClassName]"
51
- >
52
- <slot :name="`${item.slotName}-label`">
53
- {{ item.label }}
54
- </slot>
55
- <span v-if="colon" class="ebiz-descriptions__colon">:</span>
56
- </th>
57
- <td
58
- :colspan="item.span"
59
- class="ebiz-descriptions__content"
60
- :class="[item.contentClassName]"
61
- >
62
- <slot :name="item.slotName">
63
- {{ item.content }}
64
- </slot>
65
- </td>
66
- </template>
67
- </tr>
68
- </template>
69
- <template v-else>
70
- <tr>
71
- <template v-for="(item, colIndex) in row" :key="`label-${rowIndex}-${colIndex}`">
72
- <th
73
- :colspan="item.span"
74
- class="ebiz-descriptions__label"
75
- :class="[item.labelClassName]"
76
- >
77
- <slot :name="`${item.slotName}-label`">
78
- {{ item.label }}
79
- </slot>
80
- <span v-if="colon" class="ebiz-descriptions__colon">:</span>
81
- </th>
82
- </template>
83
- </tr>
84
- <tr>
85
- <template v-for="(item, colIndex) in row" :key="`content-${rowIndex}-${colIndex}`">
86
- <td
87
- :colspan="item.span"
88
- class="ebiz-descriptions__content"
89
- :class="[item.contentClassName]"
90
- >
91
- <slot :name="item.slotName">
92
- {{ item.content }}
93
- </slot>
94
- </td>
95
- </template>
96
- </tr>
97
- </template>
98
- </template>
99
- </template>
100
- </template>
101
- <template v-else>
102
- <slot></slot>
103
- </template>
104
- </tbody>
105
- </table>
106
- </div>
107
- </template>
108
-
109
- <script setup>
110
- import { defineProps, defineEmits, computed, useSlots, ref } from 'vue';
111
- import { isArray, isNil } from 'lodash-es';
112
-
113
- const props = defineProps({
114
- border: {
115
- type: Boolean,
116
- default: false
117
- },
118
- colon: {
119
- type: Boolean,
120
- default: false
121
- },
122
- column: {
123
- type: Number,
124
- default: 2
125
- },
126
- layout: {
127
- type: String,
128
- default: 'horizontal',
129
- validator(val) {
130
- return ['horizontal', 'vertical'].includes(val);
131
- }
132
- },
133
- itemLayout: {
134
- type: String,
135
- default: 'horizontal',
136
- validator(val) {
137
- return ['horizontal', 'vertical'].includes(val);
138
- }
139
- },
140
- size: {
141
- type: String,
142
- default: 'medium',
143
- validator(val) {
144
- return ['small', 'medium', 'large'].includes(val);
145
- }
146
- },
147
- title: {
148
- type: String,
149
- default: ''
150
- },
151
- tableLayout: {
152
- type: String,
153
- default: 'fixed',
154
- validator(val) {
155
- return ['auto', 'fixed'].includes(val);
156
- }
157
- },
158
- tableBorderColor: {
159
- type: String,
160
- default: ''
161
- },
162
- items: {
163
- type: Array,
164
- default: () => []
165
- }
166
- });
167
-
168
- defineEmits([]);
169
-
170
- const slots = useSlots();
171
- const itemsType = ref('slots');
172
-
173
- // 计算行数据
174
- const rows = computed(() => {
175
- // 1. 获取要渲染的 items
176
- let items = [];
177
-
178
- if (isArray(props.items) && props.items.length > 0) {
179
- // 从 props.items 获取数据
180
- items = props.items.map(item => ({
181
- label: item.label,
182
- content: item.content,
183
- span: item.span || 1,
184
- labelClassName: item.labelClassName || '',
185
- contentClassName: item.contentClassName || '',
186
- slotName: item.name || `item-${items.length}`
187
- }));
188
- itemsType.value = 'props';
189
- } else {
190
- // 从 slots 获取数据
191
- const defaultSlot = slots.default?.();
192
- if (defaultSlot) {
193
- items = defaultSlot
194
- .filter(vnode => vnode.type &&
195
- (vnode.type.name === 'EbizDescriptionsItem' ||
196
- vnode.type.__name === 'EbizDescriptionsItem'))
197
- .map((vnode, index) => {
198
- const props = vnode.props || {};
199
- const span = isNil(props.span) ? 1 : Number(props.span);
200
- return {
201
- label: props.label || '',
202
- content: '',
203
- span: span > props.column ? props.column : span,
204
- labelClassName: props.labelClassName || '',
205
- contentClassName: props.contentClassName || '',
206
- slotName: props.name || `item-${index}`,
207
- children: vnode.children
208
- };
209
- });
210
- itemsType.value = 'slots';
211
- }
212
- }
213
-
214
- // 2. 判断布局,如果是垂直布局则直接返回
215
- if (props.layout === 'vertical') {
216
- return [items];
217
- }
218
-
219
- // 3. 水平布局时,计算每一行的item
220
- const rows = [];
221
- let currentRow = [];
222
- let currentRowSpan = 0;
223
- const { column } = props;
224
-
225
- items.forEach((item, index) => {
226
- const span = item.span || 1;
227
-
228
- // 如果当前行放不下了,创建新行
229
- if (currentRowSpan + span > column) {
230
- rows.push(currentRow);
231
- currentRow = [];
232
- currentRowSpan = 0;
233
- }
234
-
235
- // 添加到当前行
236
- currentRow.push({
237
- ...item,
238
- span: span
239
- });
240
-
241
- currentRowSpan += span;
242
-
243
- // 处理最后一个元素
244
- if (index === items.length - 1) {
245
- // 最后一个元素填充剩余空间
246
- if (currentRowSpan < column) {
247
- currentRow[currentRow.length - 1].span += (column - currentRowSpan);
248
- }
249
- rows.push(currentRow);
250
- }
251
- });
252
-
253
- return rows;
254
- });
255
- </script>
256
-
257
- <style scoped>
258
- .ebiz-descriptions {
259
- font-size: 14px;
260
- color: rgba(0, 0, 0, 0.9);
261
- line-height: 22px;
262
- }
263
-
264
- .ebiz-descriptions__header {
265
- margin-bottom: 16px;
266
- }
267
-
268
- .ebiz-descriptions__header > * {
269
- font-size: 16px;
270
- font-weight: 700;
271
- color: rgba(0, 0, 0, 0.9);
272
- line-height: 24px;
273
- }
274
-
275
- .ebiz-descriptions__body {
276
- width: 100%;
277
- border-collapse: collapse;
278
- table-layout: fixed;
279
- }
280
-
281
- .ebiz-descriptions__body--fixed {
282
- table-layout: fixed;
283
- }
284
-
285
- .ebiz-descriptions__body--border {
286
- border-collapse: separate;
287
- border-spacing: 0;
288
- border-top: 1px solid var(--td-descriptions-border-color, #dcdcdc);
289
- border-left: 1px solid var(--td-descriptions-border-color, #dcdcdc);
290
- }
291
-
292
- .ebiz-descriptions__body--border .ebiz-descriptions__label,
293
- .ebiz-descriptions__body--border .ebiz-descriptions__content {
294
- border-right: 1px solid var(--td-descriptions-border-color, #dcdcdc);
295
- border-bottom: 1px solid var(--td-descriptions-border-color, #dcdcdc);
296
- }
297
-
298
- .ebiz-descriptions__label {
299
- font-weight: normal;
300
- color: rgba(0, 0, 0, 0.6);
301
- background-color: #fafafa;
302
- text-align: left;
303
- padding: 12px 24px 12px 12px;
304
- vertical-align: top;
305
- }
306
-
307
- .ebiz-descriptions__colon {
308
- margin: 0 8px 0 2px;
309
- }
310
-
311
- .ebiz-descriptions__content {
312
- padding: 12px;
313
- text-align: left;
314
- vertical-align: top;
315
- }
316
-
317
- /* 尺寸相关样式 */
318
- .ebiz-descriptions--small .ebiz-descriptions__label,
319
- .ebiz-descriptions--small .ebiz-descriptions__content {
320
- padding: 8px;
321
- }
322
-
323
- .ebiz-descriptions--medium .ebiz-descriptions__label,
324
- .ebiz-descriptions--medium .ebiz-descriptions__content {
325
- padding: 12px;
326
- }
327
-
328
- .ebiz-descriptions--large .ebiz-descriptions__label,
329
- .ebiz-descriptions--large .ebiz-descriptions__content {
330
- padding: 16px;
331
- }
332
-
333
- /* 不同布局的padding调整 */
334
- .ebiz-descriptions__body:not(.ebiz-descriptions__body--border) .ebiz-descriptions__label {
335
- padding-left: 0;
336
- }
337
-
338
- .ebiz-descriptions__body:not(.ebiz-descriptions__body--border) .ebiz-descriptions__content {
339
- padding-right: 0;
340
- }
1
+ <template>
2
+ <div class="ebiz-descriptions">
3
+ <div v-if="title || $slots.title" class="ebiz-descriptions__header">
4
+ <slot name="title">{{ title }}</slot>
5
+ </div>
6
+ <table
7
+ class="ebiz-descriptions__body"
8
+ :class="[
9
+ `ebiz-descriptions--${size}`,
10
+ { 'ebiz-descriptions__body--fixed': tableLayout === 'fixed' },
11
+ { 'ebiz-descriptions__body--border': border }
12
+ ]"
13
+ :style="border && tableBorderColor ? {'--td-descriptions-border-color': tableBorderColor} : {}"
14
+ >
15
+ <tbody>
16
+ <template v-if="rows.length > 0">
17
+ <template v-if="layout === 'horizontal'">
18
+ <tr v-for="(row, rowIndex) in rows" :key="`row-${rowIndex}`">
19
+ <template v-for="(item, colIndex) in row" :key="`${rowIndex}-${colIndex}`">
20
+ <template v-if="itemLayout === 'horizontal'">
21
+ <th
22
+ class="ebiz-descriptions__label"
23
+ :class="[item.labelClassName]"
24
+ >
25
+ <slot :name="`${item.slotName}-label`">
26
+ {{ item.label }}
27
+ </slot>
28
+ <span v-if="colon" class="ebiz-descriptions__colon">:</span>
29
+ </th>
30
+ <td
31
+ :colspan="item.span * 2 - 1"
32
+ class="ebiz-descriptions__content"
33
+ :class="[item.contentClassName]"
34
+ >
35
+ <slot :name="item.slotName">
36
+ {{ item.content }}
37
+ </slot>
38
+ </td>
39
+ </template>
40
+ </template>
41
+ </tr>
42
+ </template>
43
+ <template v-else>
44
+ <template v-for="(row, rowIndex) in rows" :key="`${rowIndex}`">
45
+ <template v-if="itemLayout === 'horizontal'">
46
+ <tr>
47
+ <template v-for="(item, colIndex) in row" :key="`label-${rowIndex}-${colIndex}`">
48
+ <th
49
+ class="ebiz-descriptions__label"
50
+ :class="[item.labelClassName]"
51
+ >
52
+ <slot :name="`${item.slotName}-label`">
53
+ {{ item.label }}
54
+ </slot>
55
+ <span v-if="colon" class="ebiz-descriptions__colon">:</span>
56
+ </th>
57
+ <td
58
+ :colspan="item.span"
59
+ class="ebiz-descriptions__content"
60
+ :class="[item.contentClassName]"
61
+ >
62
+ <slot :name="item.slotName">
63
+ {{ item.content }}
64
+ </slot>
65
+ </td>
66
+ </template>
67
+ </tr>
68
+ </template>
69
+ <template v-else>
70
+ <tr>
71
+ <template v-for="(item, colIndex) in row" :key="`label-${rowIndex}-${colIndex}`">
72
+ <th
73
+ :colspan="item.span"
74
+ class="ebiz-descriptions__label"
75
+ :class="[item.labelClassName]"
76
+ >
77
+ <slot :name="`${item.slotName}-label`">
78
+ {{ item.label }}
79
+ </slot>
80
+ <span v-if="colon" class="ebiz-descriptions__colon">:</span>
81
+ </th>
82
+ </template>
83
+ </tr>
84
+ <tr>
85
+ <template v-for="(item, colIndex) in row" :key="`content-${rowIndex}-${colIndex}`">
86
+ <td
87
+ :colspan="item.span"
88
+ class="ebiz-descriptions__content"
89
+ :class="[item.contentClassName]"
90
+ >
91
+ <slot :name="item.slotName">
92
+ {{ item.content }}
93
+ </slot>
94
+ </td>
95
+ </template>
96
+ </tr>
97
+ </template>
98
+ </template>
99
+ </template>
100
+ </template>
101
+ <template v-else>
102
+ <slot></slot>
103
+ </template>
104
+ </tbody>
105
+ </table>
106
+ </div>
107
+ </template>
108
+
109
+ <script setup>
110
+ import { defineProps, defineEmits, computed, useSlots, ref } from 'vue';
111
+ import { isArray, isNil } from 'lodash-es';
112
+
113
+ const props = defineProps({
114
+ border: {
115
+ type: Boolean,
116
+ default: false
117
+ },
118
+ colon: {
119
+ type: Boolean,
120
+ default: false
121
+ },
122
+ column: {
123
+ type: Number,
124
+ default: 2
125
+ },
126
+ layout: {
127
+ type: String,
128
+ default: 'horizontal',
129
+ validator(val) {
130
+ return ['horizontal', 'vertical'].includes(val);
131
+ }
132
+ },
133
+ itemLayout: {
134
+ type: String,
135
+ default: 'horizontal',
136
+ validator(val) {
137
+ return ['horizontal', 'vertical'].includes(val);
138
+ }
139
+ },
140
+ size: {
141
+ type: String,
142
+ default: 'medium',
143
+ validator(val) {
144
+ return ['small', 'medium', 'large'].includes(val);
145
+ }
146
+ },
147
+ title: {
148
+ type: String,
149
+ default: ''
150
+ },
151
+ tableLayout: {
152
+ type: String,
153
+ default: 'fixed',
154
+ validator(val) {
155
+ return ['auto', 'fixed'].includes(val);
156
+ }
157
+ },
158
+ tableBorderColor: {
159
+ type: String,
160
+ default: ''
161
+ },
162
+ items: {
163
+ type: Array,
164
+ default: () => []
165
+ }
166
+ });
167
+
168
+ defineEmits([]);
169
+
170
+ const slots = useSlots();
171
+ const itemsType = ref('slots');
172
+
173
+ // 计算行数据
174
+ const rows = computed(() => {
175
+ // 1. 获取要渲染的 items
176
+ let items = [];
177
+
178
+ if (isArray(props.items) && props.items.length > 0) {
179
+ // 从 props.items 获取数据
180
+ items = props.items.map(item => ({
181
+ label: item.label,
182
+ content: item.content,
183
+ span: item.span || 1,
184
+ labelClassName: item.labelClassName || '',
185
+ contentClassName: item.contentClassName || '',
186
+ slotName: item.name || `item-${items.length}`
187
+ }));
188
+ itemsType.value = 'props';
189
+ } else {
190
+ // 从 slots 获取数据
191
+ const defaultSlot = slots.default?.();
192
+ if (defaultSlot) {
193
+ items = defaultSlot
194
+ .filter(vnode => vnode.type &&
195
+ (vnode.type.name === 'EbizDescriptionsItem' ||
196
+ vnode.type.__name === 'EbizDescriptionsItem'))
197
+ .map((vnode, index) => {
198
+ const props = vnode.props || {};
199
+ const span = isNil(props.span) ? 1 : Number(props.span);
200
+ return {
201
+ label: props.label || '',
202
+ content: '',
203
+ span: span > props.column ? props.column : span,
204
+ labelClassName: props.labelClassName || '',
205
+ contentClassName: props.contentClassName || '',
206
+ slotName: props.name || `item-${index}`,
207
+ children: vnode.children
208
+ };
209
+ });
210
+ itemsType.value = 'slots';
211
+ }
212
+ }
213
+
214
+ // 2. 判断布局,如果是垂直布局则直接返回
215
+ if (props.layout === 'vertical') {
216
+ return [items];
217
+ }
218
+
219
+ // 3. 水平布局时,计算每一行的item
220
+ const rows = [];
221
+ let currentRow = [];
222
+ let currentRowSpan = 0;
223
+ const { column } = props;
224
+
225
+ items.forEach((item, index) => {
226
+ const span = item.span || 1;
227
+
228
+ // 如果当前行放不下了,创建新行
229
+ if (currentRowSpan + span > column) {
230
+ rows.push(currentRow);
231
+ currentRow = [];
232
+ currentRowSpan = 0;
233
+ }
234
+
235
+ // 添加到当前行
236
+ currentRow.push({
237
+ ...item,
238
+ span: span
239
+ });
240
+
241
+ currentRowSpan += span;
242
+
243
+ // 处理最后一个元素
244
+ if (index === items.length - 1) {
245
+ // 最后一个元素填充剩余空间
246
+ if (currentRowSpan < column) {
247
+ currentRow[currentRow.length - 1].span += (column - currentRowSpan);
248
+ }
249
+ rows.push(currentRow);
250
+ }
251
+ });
252
+
253
+ return rows;
254
+ });
255
+ </script>
256
+
257
+ <style scoped>
258
+ .ebiz-descriptions {
259
+ font-size: 14px;
260
+ color: rgba(0, 0, 0, 0.9);
261
+ line-height: 22px;
262
+ }
263
+
264
+ .ebiz-descriptions__header {
265
+ margin-bottom: 16px;
266
+ }
267
+
268
+ .ebiz-descriptions__header > * {
269
+ font-size: 16px;
270
+ font-weight: 700;
271
+ color: rgba(0, 0, 0, 0.9);
272
+ line-height: 24px;
273
+ }
274
+
275
+ .ebiz-descriptions__body {
276
+ width: 100%;
277
+ border-collapse: collapse;
278
+ table-layout: fixed;
279
+ }
280
+
281
+ .ebiz-descriptions__body--fixed {
282
+ table-layout: fixed;
283
+ }
284
+
285
+ .ebiz-descriptions__body--border {
286
+ border-collapse: separate;
287
+ border-spacing: 0;
288
+ border-top: 1px solid var(--td-descriptions-border-color, #dcdcdc);
289
+ border-left: 1px solid var(--td-descriptions-border-color, #dcdcdc);
290
+ }
291
+
292
+ .ebiz-descriptions__body--border .ebiz-descriptions__label,
293
+ .ebiz-descriptions__body--border .ebiz-descriptions__content {
294
+ border-right: 1px solid var(--td-descriptions-border-color, #dcdcdc);
295
+ border-bottom: 1px solid var(--td-descriptions-border-color, #dcdcdc);
296
+ }
297
+
298
+ .ebiz-descriptions__label {
299
+ font-weight: normal;
300
+ color: rgba(0, 0, 0, 0.6);
301
+ background-color: #fafafa;
302
+ text-align: left;
303
+ padding: 12px 24px 12px 12px;
304
+ vertical-align: top;
305
+ }
306
+
307
+ .ebiz-descriptions__colon {
308
+ margin: 0 8px 0 2px;
309
+ }
310
+
311
+ .ebiz-descriptions__content {
312
+ padding: 12px;
313
+ text-align: left;
314
+ vertical-align: top;
315
+ }
316
+
317
+ /* 尺寸相关样式 */
318
+ .ebiz-descriptions--small .ebiz-descriptions__label,
319
+ .ebiz-descriptions--small .ebiz-descriptions__content {
320
+ padding: 8px;
321
+ }
322
+
323
+ .ebiz-descriptions--medium .ebiz-descriptions__label,
324
+ .ebiz-descriptions--medium .ebiz-descriptions__content {
325
+ padding: 12px;
326
+ }
327
+
328
+ .ebiz-descriptions--large .ebiz-descriptions__label,
329
+ .ebiz-descriptions--large .ebiz-descriptions__content {
330
+ padding: 16px;
331
+ }
332
+
333
+ /* 不同布局的padding调整 */
334
+ .ebiz-descriptions__body:not(.ebiz-descriptions__body--border) .ebiz-descriptions__label {
335
+ padding-left: 0;
336
+ }
337
+
338
+ .ebiz-descriptions__body:not(.ebiz-descriptions__body--border) .ebiz-descriptions__content {
339
+ padding-right: 0;
340
+ }
341
341
  </style>