xt-element-ui 2.1.21 → 2.1.61

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 (75) hide show
  1. package/docs/components/base/xt-badge.md +0 -2
  2. package/docs/components/base/xt-bar.md +0 -27
  3. package/docs/components/base/xt-button.md +0 -2
  4. package/docs/components/base/xt-card-item.md +0 -2
  5. package/docs/components/base/xt-card.md +17 -19
  6. package/docs/components/base/xt-chart.md +5 -31
  7. package/docs/components/base/xt-config-provider.md +0 -2
  8. package/docs/components/base/xt-date-picker.md +185 -28
  9. package/docs/components/base/xt-flex-box.md +25 -25
  10. package/docs/components/base/xt-form-schema.md +356 -0
  11. package/docs/components/base/xt-grid-box.md +4 -6
  12. package/docs/components/base/xt-icon.md +0 -2
  13. package/docs/components/base/xt-input.md +204 -44
  14. package/docs/components/base/xt-line.md +0 -26
  15. package/docs/components/base/xt-list.md +456 -458
  16. package/docs/components/base/xt-map-provider.md +0 -2
  17. package/docs/components/base/xt-map.md +0 -2
  18. package/docs/components/base/xt-multi.md +0 -39
  19. package/docs/components/base/xt-page.md +17 -6
  20. package/docs/components/base/xt-pie.md +0 -25
  21. package/docs/components/base/xt-progress.md +0 -2
  22. package/docs/components/base/xt-scroll-arrow.md +0 -2
  23. package/docs/components/base/xt-select-tree.md +0 -2
  24. package/docs/components/base/xt-step-price.md +3 -4
  25. package/docs/components/base/xt-table.md +2 -2
  26. package/docs/components/base/xt-tabs.md +0 -2
  27. package/docs/components/base/xt-text.md +1 -2
  28. package/docs/components/base/xt-time.md +0 -2
  29. package/docs/components/base/xt-transfer-tree.md +270 -0
  30. package/docs/components/base/xt-upload.md +11 -8
  31. package/docs/components/utils/config.md +285 -0
  32. package/docs/components/utils/format.md +445 -0
  33. package/lib/index.common.js +96183 -115717
  34. package/lib/index.css +1 -1
  35. package/lib/index.umd.js +96183 -115717
  36. package/lib/index.umd.min.js +1 -34
  37. package/package.json +7 -4
  38. package/src/components/xt-badge/style/index.scss +0 -22
  39. package/src/components/xt-button/index.vue +2 -1
  40. package/src/components/xt-button/style/index.scss +2 -2
  41. package/src/components/xt-card/style/index.scss +2 -2
  42. package/src/components/xt-card-item/style/index.scss +5 -40
  43. package/src/components/xt-chart/XtBar.vue +0 -3
  44. package/src/components/xt-date-picker/component/Picker.vue +196 -0
  45. package/src/components/xt-date-picker/component/RangeDate.vue +136 -0
  46. package/src/components/xt-date-picker/index.vue +220 -80
  47. package/src/components/xt-flex-box/index.vue +1 -1
  48. package/src/components/xt-form-schema/index.js +8 -0
  49. package/src/components/xt-form-schema/index.vue +328 -0
  50. package/src/components/xt-grid-item/index.vue +2 -2
  51. package/src/components/xt-input/index.vue +224 -28
  52. package/src/components/xt-input/style/index.scss +10 -0
  53. package/src/components/xt-layout/ExFieldset.vue +4 -4
  54. package/src/components/xt-list/index.js +7 -7
  55. package/src/components/xt-list/index.vue +885 -885
  56. package/src/components/xt-page/index.vue +148 -75
  57. package/src/components/xt-progress/style/index.scss +0 -14
  58. package/src/components/xt-step-price/style/index.scss +0 -4
  59. package/src/components/xt-step-price-item/index.vue +1 -1
  60. package/src/components/xt-table/XtTableCell.vue +2 -2
  61. package/src/components/xt-table/index.vue +17 -10
  62. package/src/components/xt-tabs/style/index.scss +0 -40
  63. package/src/components/xt-text/index.vue +16 -4
  64. package/src/components/xt-text/style/index.scss +0 -15
  65. package/src/components/xt-transfer-tree/index.js +8 -0
  66. package/src/components/xt-transfer-tree/index.vue +494 -0
  67. package/src/components/xt-upload/index.vue +12 -6
  68. package/src/index.js +8 -2
  69. package/src/styles/theme/colors.scss +0 -44
  70. package/src/styles/theme/dark-variables.scss +0 -29
  71. package/src/styles/variables-export.scss +0 -72
  72. package/src/utils/index.js +278 -1
  73. package/src/components/xt-date-picker/SearchDate.vue +0 -45
  74. package/src/components/xt-date-picker/quarter.vue +0 -154
  75. package/src/components/xt-table/index copy.vue +0 -663
@@ -1,459 +1,457 @@
1
- ## XtList 卡片列表组件
2
-
3
- 基于 ElementUI Card 封装的列表渲染组件,一个卡片代表一条数据,支持分组、虚拟滚动、搜索筛选、排序等功能。
4
-
5
- ### 基本用法
6
-
7
- ::: demo 基本用法
8
- ```vue
9
- <template>
10
- <XtList
11
- :data="listData"
12
- title="订单列表"
13
- />
14
- </template>
15
-
16
- <script>
17
- export default {
18
- data() {
19
- return {
20
- listData: [
21
- { id: 1, title: '订单 #001', subtitle: '2024-01-15', content: '金额: ¥299.00', footer: '已完成' },
22
- { id: 2, title: '订单 #002', subtitle: '2024-01-16', content: '金额: ¥599.00', footer: '待发货' },
23
- { id: 3, title: '订单 #003', subtitle: '2024-01-17', content: '金额: ¥199.00', footer: '已完成' }
24
- ]
25
- }
26
- }
27
- }
28
- </script>
29
- ```
30
- :::
31
-
32
- ### 分组展示
33
-
34
- ::: demo 分组展示
35
- ```vue
36
- <template>
37
- <XtList
38
- :data="listData"
39
- group-by="status"
40
- title="订单列表(按状态分组)"
41
- />
42
- </template>
43
-
44
- <script>
45
- export default {
46
- data() {
47
- return {
48
- listData: [
49
- { id: 1, title: '订单 #001', status: '已完成', content: '金额: ¥299.00' },
50
- { id: 2, title: '订单 #002', status: '待发货', content: '金额: ¥599.00' },
51
- { id: 3, title: '订单 #003', status: '已完成', content: '金额: ¥199.00' },
52
- { id: 4, title: '订单 #004', status: '待发货', content: '金额: ¥899.00' },
53
- { id: 5, title: '订单 #005', status: '已取消', content: '金额: ¥129.00' }
54
- ]
55
- }
56
- }
57
- }
58
- </script>
59
- ```
60
- :::
61
-
62
- ### 手风琴模式
63
-
64
- ::: demo 手风琴模式
65
- ```vue
66
- <template>
67
- <XtList
68
- :data="listData"
69
- group-by="status"
70
- :accordion="true"
71
- title="手风琴模式(同时只展开一个分组)"
72
- />
73
- </template>
74
-
75
- <script>
76
- export default {
77
- data() {
78
- return {
79
- listData: [
80
- { id: 1, title: '订单 #001', status: '已完成', content: '金额: ¥299.00' },
81
- { id: 2, title: '订单 #002', status: '待发货', content: '金额: ¥599.00' },
82
- { id: 3, title: '订单 #003', status: '已完成', content: '金额: ¥199.00' },
83
- { id: 4, title: '订单 #004', status: '待发货', content: '金额: ¥899.00' }
84
- ]
85
- }
86
- }
87
- }
88
- </script>
89
- ```
90
- :::
91
-
92
- ### 自定义卡片配置
93
-
94
- 通过 `cardConfig` 配置字段映射,自动渲染卡片内容。
95
-
96
- ::: demo 自定义卡片配置
97
- ```vue
98
- <template>
99
- <XtList
100
- :data="listData"
101
- :card-config="cardConfig"
102
- title="商品列表"
103
- />
104
- </template>
105
-
106
- <script>
107
- export default {
108
- data() {
109
- return {
110
- listData: [
111
- { id: 1, name: 'iPhone 15', price: 5999, desc: '全新 A17 Pro 芯片', tag: '热卖', tagType: 'danger' },
112
- { id: 2, name: 'MacBook Pro', price: 12999, desc: 'M3 Pro 芯片', tag: '新品', tagType: 'success' },
113
- { id: 3, name: 'AirPods Pro', price: 1899, desc: '主动降噪', tag: '推荐', tagType: '' }
114
- ],
115
- cardConfig: {
116
- title: 'name',
117
- subtitle: 'price',
118
- content: 'desc',
119
- tag: 'tag',
120
- tagType: 'tagType',
121
- footer: 'price'
122
- }
123
- }
124
- }
125
- }
126
- </script>
127
- ```
128
- :::
129
-
130
- ### 自定义渲染(插槽)
131
-
132
- ::: demo 自定义渲染
133
- ```vue
134
- <template>
135
- <XtList :data="listData" title="自定义卡片内容">
136
- <template #default="{ item, index }">
137
- <div style="display: flex; align-items: center; gap: 12px;">
138
- <div style="width: 48px; height: 48px; background: #409eff; border-radius: 8px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 20px; flex-shrink: 0;">
139
- {{ index + 1 }}
140
- </div>
141
- <div style="flex: 1; min-width: 0;">
142
- <div style="font-weight: 600; font-size: 15px; color: #303133; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ item.name }}</div>
143
- <div style="font-size: 13px; color: #909399; margin-top: 4px;">{{ item.desc }}</div>
144
- </div>
145
- <XtButton size="small" type="primary" plain>查看</XtButton>
146
- </div>
147
- </template>
148
- </XtList>
149
- </template>
150
-
151
- <script>
152
- export default {
153
- data() {
154
- return {
155
- listData: [
156
- { id: 1, name: 'iPhone 15', desc: '全新 A17 Pro 芯片' },
157
- { id: 2, name: 'MacBook Pro', desc: 'M3 Pro 芯片' },
158
- { id: 3, name: 'AirPods Pro', desc: '主动降噪' }
159
- ]
160
- }
161
- }
162
- }
163
- </script>
164
- ```
165
- :::
166
-
167
- ### 虚拟滚动
168
-
169
- 大数据量场景下启用虚拟滚动,仅渲染可见区域的卡片。
170
-
171
- ::: demo 虚拟滚动
172
- ```vue
173
- <template>
174
- <XtList
175
- :data="largeData"
176
- :height="500"
177
- :item-height="140"
178
- :virtual-scroll="true"
179
- title="虚拟滚动(10000条数据)"
180
- />
181
- </template>
182
-
183
- <script>
184
- export default {
185
- data() {
186
- const items = []
187
- for (let i = 0; i < 10000; i++) {
188
- items.push({
189
- id: i + 1,
190
- title: `数据项 #${i + 1}`,
191
- subtitle: `分类 ${Math.floor(Math.random() * 10) + 1}`,
192
- content: `这是第 ${i + 1} 条数据的描述内容`
193
- })
194
- }
195
- return {
196
- largeData: items
197
- }
198
- }
199
- }
200
- </script>
201
- ```
202
- :::
203
-
204
- ### 搜索筛选
205
-
206
- ::: demo 搜索筛选
207
- ```vue
208
- <template>
209
- <XtList
210
- :data="listData"
211
- :filterable="true"
212
- filter-placeholder="搜索订单..."
213
- title="订单列表"
214
- />
215
- </template>
216
-
217
- <script>
218
- export default {
219
- data() {
220
- return {
221
- listData: [
222
- { id: 1, title: '手机订单', content: '¥2999.00' },
223
- { id: 2, title: '电脑订单', content: '¥8999.00' },
224
- { id: 3, title: '耳机订单', content: '¥599.00' },
225
- { id: 4, title: '平板订单', content: '¥3499.00' },
226
- { id: 5, title: '键盘订单', content: '¥299.00' }
227
- ]
228
- }
229
- }
230
- }
231
- </script>
232
- ```
233
- :::
234
-
235
- ### 排序
236
-
237
- ::: demo 排序
238
- ```vue
239
- <template>
240
- <XtList
241
- :data="listData"
242
- :sortable="true"
243
- sort-by="price"
244
- title="商品列表(按价格排序)"
245
- />
246
- </template>
247
-
248
- <script>
249
- export default {
250
- data() {
251
- return {
252
- listData: [
253
- { id: 1, title: '商品A', price: 299 },
254
- { id: 2, title: '商品B', price: 599 },
255
- { id: 3, title: '商品C', price: 199 },
256
- { id: 4, title: '商品D', price: 899 },
257
- { id: 5, title: '商品E', price: 399 }
258
- ]
259
- }
260
- }
261
- }
262
- </script>
263
- ```
264
- :::
265
-
266
- ### 多列布局
267
-
268
- ::: demo 多列布局
269
- ```vue
270
- <template>
271
- <XtList
272
- :data="listData"
273
- :columns="2"
274
- title="双列商品列表"
275
- />
276
- </template>
277
-
278
- <script>
279
- export default {
280
- data() {
281
- return {
282
- listData: [
283
- { id: 1, title: '商品 1', content: '¥99.00' },
284
- { id: 2, title: '商品 2', content: '¥199.00' },
285
- { id: 3, title: '商品 3', content: '¥299.00' },
286
- { id: 4, title: '商品 4', content: '¥399.00' }
287
- ]
288
- }
289
- }
290
- }
291
- </script>
292
- ```
293
- :::
294
-
295
- ### 加载更多
296
-
297
- ::: demo 加载更多
298
- ```vue
299
- <template>
300
- <XtList
301
- :data="listData"
302
- :load-more="true"
303
- :has-more="hasMore"
304
- load-more-text="点击加载更多"
305
- title="商品列表"
306
- @load-more="handleLoadMore"
307
- />
308
- </template>
309
-
310
- <script>
311
- export default {
312
- data() {
313
- return {
314
- listData: [],
315
- hasMore: true,
316
- page: 1
317
- }
318
- },
319
- created() {
320
- this.loadData()
321
- },
322
- methods: {
323
- loadData() {
324
- const newItems = Array.from({ length: 10 }, (_, i) => ({
325
- id: (this.page - 1) * 10 + i + 1,
326
- title: `商品 #${(this.page - 1) * 10 + i + 1}`,
327
- content: `¥${Math.floor(Math.random() * 1000) + 100}.00`
328
- }))
329
- this.listData = [...this.listData, ...newItems]
330
- this.page++
331
- this.hasMore = this.page <= 3
332
- },
333
- handleLoadMore() {
334
- setTimeout(() => {
335
- this.loadData()
336
- }, 500)
337
- }
338
- }
339
- }
340
- </script>
341
- ```
342
- :::
343
-
344
- ## 属性说明
345
-
346
- ### 基础属性
347
-
348
- | 属性 | 类型 | 默认值 | 说明 |
349
- |------|------|--------|------|
350
- | `data` | Array | `[]` | 列表数据 |
351
- | `title` | String | `''` | 列表标题 |
352
- | `columns` | Number | `1` | 列数(1/2/3) |
353
- | `shadow` | String | `'hover'` | 卡片阴影('always' / 'hover' / 'never') |
354
- | `cardBodyStyle` | Object | `{}` | 卡片 body 样式 |
355
- | `loading` | Boolean | `false` | 是否加载中 |
356
- | `emptyText` | String | `'暂无数据'` | 空数据提示 |
357
-
358
- ### 分组配置
359
-
360
- | 属性 | 类型 | 默认值 | 说明 |
361
- |------|------|--------|------|
362
- | `groupBy` | String | `''` | 分组字段名 |
363
- | `groupLabel` | String / Function | `''` | 分组标题(空字符串显示分组值,字符串为字段名,函数返回自定义内容) |
364
- | `expandAll` | Boolean | `true` | 是否默认展开所有分组 |
365
- | `accordion` | Boolean | `false` | 手风琴模式(同时只展开一个分组) |
366
-
367
- ### 卡片配置
368
-
369
- | 属性 | 类型 | 默认值 | 说明 |
370
- |------|------|--------|------|
371
- | `cardConfig` | Object | `{ title: 'title', ... }` | 卡片字段映射配置 |
372
-
373
- cardConfig 子属性:
374
-
375
- | 属性 | 类型 | 说明 |
376
- |------|------|------|
377
- | `title` | String / Function | 卡片标题字段 |
378
- | `subtitle` | String / Function | 卡片副标题字段 |
379
- | `content` | String / Function | 卡片内容字段 |
380
- | `image` | String / Function | 卡片图片字段 |
381
- | `tag` | String / Function | 卡片标签字段 |
382
- | `tagType` | String / Function | 标签类型 |
383
- | `footer` | String / Function | 卡片底部字段 |
384
-
385
- ### 虚拟滚动
386
-
387
- | 属性 | 类型 | 默认值 | 说明 |
388
- |------|------|--------|------|
389
- | `virtualScroll` | Boolean | `false` | 是否启用虚拟滚动 |
390
- | `height` | Number / String | - | 容器高度 |
391
- | `maxHeight` | Number / String | - | 容器最大高度 |
392
- | `itemHeight` | Number | `160` | 每行卡片预估高度 |
393
- | `bufferSize` | Number | `3` | 缓冲区行数 |
394
-
395
- ### 搜索筛选
396
-
397
- | 属性 | 类型 | 默认值 | 说明 |
398
- |------|------|--------|------|
399
- | `filterable` | Boolean | `false` | 是否启用搜索 |
400
- | `filterPlaceholder` | String | `'请输入搜索内容'` | 搜索框占位文本 |
401
- | `filterMethod` | Function | - | 自定义筛选方法 `(item, searchText) => boolean` |
402
-
403
- ### 排序
404
-
405
- | 属性 | 类型 | 默认值 | 说明 |
406
- |------|------|--------|------|
407
- | `sortable` | Boolean | `false` | 是否启用排序 |
408
- | `sortBy` | String | `''` | 排序字段 |
409
- | `sortOrder` | String | `''` | 默认排序方向('ascending' / 'descending') |
410
- | `sortMethod` | Function | - | 自定义排序方法 `(a, b) => number` |
411
-
412
- ### 加载更多
413
-
414
- | 属性 | 类型 | 默认值 | 说明 |
415
- |------|------|--------|------|
416
- | `loadMore` | Boolean | `false` | 是否启用加载更多 |
417
- | `hasMore` | Boolean | `false` | 是否有更多数据 |
418
- | `loadMoreText` | String | `'加载更多'` | 加载更多按钮文本 |
419
- | `loadMoreLoading` | Boolean | `false` | 加载更多按钮加载状态 |
420
-
421
- ### 分页
422
-
423
- | 属性 | 类型 | 默认值 | 说明 |
424
- |------|------|--------|------|
425
- | `pagination` | Object | `null` | 分页配置 `{ pageNum, pageSize, pageSizes }` |
426
- | `total` | Number | `0` | 数据总数 |
427
-
428
- ## 事件
429
-
430
- | 事件名 | 说明 | 参数 |
431
- |--------|------|------|
432
- | `click-item` | 点击卡片 | `{ item, groupKey }` |
433
- | `group-toggle` | 分组展开/折叠 | `{ key, expanded }` |
434
- | `search` | 搜索输入变化 | `searchText` |
435
- | `sort-change` | 排序变化 | `{ prop, order }` |
436
- | `load-more` | 点击加载更多 | - |
437
- | `size-change` | 每页条数变化 | `size` |
438
- | `page-change` | 当前页变化 | `page` |
439
-
440
- ## 方法
441
-
442
- | 方法名 | 说明 | 参数 |
443
- |--------|------|------|
444
- | `scrollToTop()` | 滚动到顶部 | - |
445
- | `expandGroup(key)` | 展开指定分组 | `key` |
446
- | `collapseGroup(key)` | 折叠指定分组 | `key` |
447
- | `collapseAll()` | 折叠所有分组 | - |
448
- | `expandAllGroups()` | 展开所有分组 | - |
449
-
450
- ## 插槽
451
-
452
- | 插槽名 | 作用域 | 说明 |
453
- |--------|--------|------|
454
- | `default` | `{ item, index, group }` | 自定义卡片内容 |
455
- | `group-title` | `{ group, items, expanded }` | 自定义分组标题 |
456
- | `card-footer` | `{ item, index }` | 自定义卡片底部 |
457
- | `toolbar` | - | 工具栏区域(搜索和排序按钮右侧) |
458
- | `empty` | - | 自定义空状态 |
1
+ 基于 ElementUI Card 封装的列表渲染组件,一个卡片代表一条数据,支持分组、虚拟滚动、搜索筛选、排序等功能。
2
+
3
+ ### 基本用法
4
+
5
+ ::: demo 基本用法
6
+ ```vue
7
+ <template>
8
+ <XtList
9
+ :data="listData"
10
+ title="订单列表"
11
+ />
12
+ </template>
13
+
14
+ <script>
15
+ export default {
16
+ data() {
17
+ return {
18
+ listData: [
19
+ { id: 1, title: '订单 #001', subtitle: '2024-01-15', content: '金额: ¥299.00', footer: '已完成' },
20
+ { id: 2, title: '订单 #002', subtitle: '2024-01-16', content: '金额: ¥599.00', footer: '待发货' },
21
+ { id: 3, title: '订单 #003', subtitle: '2024-01-17', content: '金额: ¥199.00', footer: '已完成' }
22
+ ]
23
+ }
24
+ }
25
+ }
26
+ </script>
27
+ ```
28
+ :::
29
+
30
+ ### 分组展示
31
+
32
+ ::: demo 分组展示
33
+ ```vue
34
+ <template>
35
+ <XtList
36
+ :data="listData"
37
+ group-by="status"
38
+ title="订单列表(按状态分组)"
39
+ />
40
+ </template>
41
+
42
+ <script>
43
+ export default {
44
+ data() {
45
+ return {
46
+ listData: [
47
+ { id: 1, title: '订单 #001', status: '已完成', content: '金额: ¥299.00' },
48
+ { id: 2, title: '订单 #002', status: '待发货', content: '金额: ¥599.00' },
49
+ { id: 3, title: '订单 #003', status: '已完成', content: '金额: ¥199.00' },
50
+ { id: 4, title: '订单 #004', status: '待发货', content: '金额: ¥899.00' },
51
+ { id: 5, title: '订单 #005', status: '已取消', content: '金额: ¥129.00' }
52
+ ]
53
+ }
54
+ }
55
+ }
56
+ </script>
57
+ ```
58
+ :::
59
+
60
+ ### 手风琴模式
61
+
62
+ ::: demo 手风琴模式
63
+ ```vue
64
+ <template>
65
+ <XtList
66
+ :data="listData"
67
+ group-by="status"
68
+ :accordion="true"
69
+ title="手风琴模式(同时只展开一个分组)"
70
+ />
71
+ </template>
72
+
73
+ <script>
74
+ export default {
75
+ data() {
76
+ return {
77
+ listData: [
78
+ { id: 1, title: '订单 #001', status: '已完成', content: '金额: ¥299.00' },
79
+ { id: 2, title: '订单 #002', status: '待发货', content: '金额: ¥599.00' },
80
+ { id: 3, title: '订单 #003', status: '已完成', content: '金额: ¥199.00' },
81
+ { id: 4, title: '订单 #004', status: '待发货', content: '金额: ¥899.00' }
82
+ ]
83
+ }
84
+ }
85
+ }
86
+ </script>
87
+ ```
88
+ :::
89
+
90
+ ### 自定义卡片配置
91
+
92
+ 通过 `cardConfig` 配置字段映射,自动渲染卡片内容。
93
+
94
+ ::: demo 自定义卡片配置
95
+ ```vue
96
+ <template>
97
+ <XtList
98
+ :data="listData"
99
+ :card-config="cardConfig"
100
+ title="商品列表"
101
+ />
102
+ </template>
103
+
104
+ <script>
105
+ export default {
106
+ data() {
107
+ return {
108
+ listData: [
109
+ { id: 1, name: 'iPhone 15', price: 5999, desc: '全新 A17 Pro 芯片', tag: '热卖', tagType: 'danger' },
110
+ { id: 2, name: 'MacBook Pro', price: 12999, desc: 'M3 Pro 芯片', tag: '新品', tagType: 'success' },
111
+ { id: 3, name: 'AirPods Pro', price: 1899, desc: '主动降噪', tag: '推荐', tagType: '' }
112
+ ],
113
+ cardConfig: {
114
+ title: 'name',
115
+ subtitle: 'price',
116
+ content: 'desc',
117
+ tag: 'tag',
118
+ tagType: 'tagType',
119
+ footer: 'price'
120
+ }
121
+ }
122
+ }
123
+ }
124
+ </script>
125
+ ```
126
+ :::
127
+
128
+ ### 自定义渲染(插槽)
129
+
130
+ ::: demo 自定义渲染
131
+ ```vue
132
+ <template>
133
+ <XtList :data="listData" title="自定义卡片内容">
134
+ <template #default="{ item, index }">
135
+ <div style="display: flex; align-items: center; gap: 12px;">
136
+ <div style="width: 48px; height: 48px; background: #409eff; border-radius: 8px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 20px; flex-shrink: 0;">
137
+ {{ index + 1 }}
138
+ </div>
139
+ <div style="flex: 1; min-width: 0;">
140
+ <div style="font-weight: 600; font-size: 15px; color: #303133; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ item.name }}</div>
141
+ <div style="font-size: 13px; color: #909399; margin-top: 4px;">{{ item.desc }}</div>
142
+ </div>
143
+ <XtButton size="small" type="primary" plain>查看</XtButton>
144
+ </div>
145
+ </template>
146
+ </XtList>
147
+ </template>
148
+
149
+ <script>
150
+ export default {
151
+ data() {
152
+ return {
153
+ listData: [
154
+ { id: 1, name: 'iPhone 15', desc: '全新 A17 Pro 芯片' },
155
+ { id: 2, name: 'MacBook Pro', desc: 'M3 Pro 芯片' },
156
+ { id: 3, name: 'AirPods Pro', desc: '主动降噪' }
157
+ ]
158
+ }
159
+ }
160
+ }
161
+ </script>
162
+ ```
163
+ :::
164
+
165
+ ### 虚拟滚动
166
+
167
+ 大数据量场景下启用虚拟滚动,仅渲染可见区域的卡片。
168
+
169
+ ::: demo 虚拟滚动
170
+ ```vue
171
+ <template>
172
+ <XtList
173
+ :data="largeData"
174
+ :height="500"
175
+ :item-height="140"
176
+ :virtual-scroll="true"
177
+ title="虚拟滚动(10000条数据)"
178
+ />
179
+ </template>
180
+
181
+ <script>
182
+ export default {
183
+ data() {
184
+ const items = []
185
+ for (let i = 0; i < 10000; i++) {
186
+ items.push({
187
+ id: i + 1,
188
+ title: `数据项 #${i + 1}`,
189
+ subtitle: `分类 ${Math.floor(Math.random() * 10) + 1}`,
190
+ content: `这是第 ${i + 1} 条数据的描述内容`
191
+ })
192
+ }
193
+ return {
194
+ largeData: items
195
+ }
196
+ }
197
+ }
198
+ </script>
199
+ ```
200
+ :::
201
+
202
+ ### 搜索筛选
203
+
204
+ ::: demo 搜索筛选
205
+ ```vue
206
+ <template>
207
+ <XtList
208
+ :data="listData"
209
+ :filterable="true"
210
+ filter-placeholder="搜索订单..."
211
+ title="订单列表"
212
+ />
213
+ </template>
214
+
215
+ <script>
216
+ export default {
217
+ data() {
218
+ return {
219
+ listData: [
220
+ { id: 1, title: '手机订单', content: '¥2999.00' },
221
+ { id: 2, title: '电脑订单', content: '¥8999.00' },
222
+ { id: 3, title: '耳机订单', content: '¥599.00' },
223
+ { id: 4, title: '平板订单', content: '¥3499.00' },
224
+ { id: 5, title: '键盘订单', content: '¥299.00' }
225
+ ]
226
+ }
227
+ }
228
+ }
229
+ </script>
230
+ ```
231
+ :::
232
+
233
+ ### 排序
234
+
235
+ ::: demo 排序
236
+ ```vue
237
+ <template>
238
+ <XtList
239
+ :data="listData"
240
+ :sortable="true"
241
+ sort-by="price"
242
+ title="商品列表(按价格排序)"
243
+ />
244
+ </template>
245
+
246
+ <script>
247
+ export default {
248
+ data() {
249
+ return {
250
+ listData: [
251
+ { id: 1, title: '商品A', price: 299 },
252
+ { id: 2, title: '商品B', price: 599 },
253
+ { id: 3, title: '商品C', price: 199 },
254
+ { id: 4, title: '商品D', price: 899 },
255
+ { id: 5, title: '商品E', price: 399 }
256
+ ]
257
+ }
258
+ }
259
+ }
260
+ </script>
261
+ ```
262
+ :::
263
+
264
+ ### 多列布局
265
+
266
+ ::: demo 多列布局
267
+ ```vue
268
+ <template>
269
+ <XtList
270
+ :data="listData"
271
+ :columns="2"
272
+ title="双列商品列表"
273
+ />
274
+ </template>
275
+
276
+ <script>
277
+ export default {
278
+ data() {
279
+ return {
280
+ listData: [
281
+ { id: 1, title: '商品 1', content: '¥99.00' },
282
+ { id: 2, title: '商品 2', content: '¥199.00' },
283
+ { id: 3, title: '商品 3', content: '¥299.00' },
284
+ { id: 4, title: '商品 4', content: '¥399.00' }
285
+ ]
286
+ }
287
+ }
288
+ }
289
+ </script>
290
+ ```
291
+ :::
292
+
293
+ ### 加载更多
294
+
295
+ ::: demo 加载更多
296
+ ```vue
297
+ <template>
298
+ <XtList
299
+ :data="listData"
300
+ :load-more="true"
301
+ :has-more="hasMore"
302
+ load-more-text="点击加载更多"
303
+ title="商品列表"
304
+ @load-more="handleLoadMore"
305
+ />
306
+ </template>
307
+
308
+ <script>
309
+ export default {
310
+ data() {
311
+ return {
312
+ listData: [],
313
+ hasMore: true,
314
+ page: 1
315
+ }
316
+ },
317
+ created() {
318
+ this.loadData()
319
+ },
320
+ methods: {
321
+ loadData() {
322
+ const newItems = Array.from({ length: 10 }, (_, i) => ({
323
+ id: (this.page - 1) * 10 + i + 1,
324
+ title: `商品 #${(this.page - 1) * 10 + i + 1}`,
325
+ content: `¥${Math.floor(Math.random() * 1000) + 100}.00`
326
+ }))
327
+ this.listData = [...this.listData, ...newItems]
328
+ this.page++
329
+ this.hasMore = this.page <= 3
330
+ },
331
+ handleLoadMore() {
332
+ setTimeout(() => {
333
+ this.loadData()
334
+ }, 500)
335
+ }
336
+ }
337
+ }
338
+ </script>
339
+ ```
340
+ :::
341
+
342
+ ## 属性说明
343
+
344
+ ### 基础属性
345
+
346
+ | 属性 | 类型 | 默认值 | 说明 |
347
+ |------|------|--------|------|
348
+ | `data` | Array | `[]` | 列表数据 |
349
+ | `title` | String | `''` | 列表标题 |
350
+ | `columns` | Number | `1` | 列数(1/2/3) |
351
+ | `shadow` | String | `'hover'` | 卡片阴影('always' / 'hover' / 'never') |
352
+ | `cardBodyStyle` | Object | `{}` | 卡片 body 样式 |
353
+ | `loading` | Boolean | `false` | 是否加载中 |
354
+ | `emptyText` | String | `'暂无数据'` | 空数据提示 |
355
+
356
+ ### 分组配置
357
+
358
+ | 属性 | 类型 | 默认值 | 说明 |
359
+ |------|------|--------|------|
360
+ | `groupBy` | String | `''` | 分组字段名 |
361
+ | `groupLabel` | String / Function | `''` | 分组标题(空字符串显示分组值,字符串为字段名,函数返回自定义内容) |
362
+ | `expandAll` | Boolean | `true` | 是否默认展开所有分组 |
363
+ | `accordion` | Boolean | `false` | 手风琴模式(同时只展开一个分组) |
364
+
365
+ ### 卡片配置
366
+
367
+ | 属性 | 类型 | 默认值 | 说明 |
368
+ |------|------|--------|------|
369
+ | `cardConfig` | Object | `{ title: 'title', ... }` | 卡片字段映射配置 |
370
+
371
+ cardConfig 子属性:
372
+
373
+ | 属性 | 类型 | 说明 |
374
+ |------|------|------|
375
+ | `title` | String / Function | 卡片标题字段 |
376
+ | `subtitle` | String / Function | 卡片副标题字段 |
377
+ | `content` | String / Function | 卡片内容字段 |
378
+ | `image` | String / Function | 卡片图片字段 |
379
+ | `tag` | String / Function | 卡片标签字段 |
380
+ | `tagType` | String / Function | 标签类型 |
381
+ | `footer` | String / Function | 卡片底部字段 |
382
+
383
+ ### 虚拟滚动
384
+
385
+ | 属性 | 类型 | 默认值 | 说明 |
386
+ |------|------|--------|------|
387
+ | `virtualScroll` | Boolean | `false` | 是否启用虚拟滚动 |
388
+ | `height` | Number / String | - | 容器高度 |
389
+ | `maxHeight` | Number / String | - | 容器最大高度 |
390
+ | `itemHeight` | Number | `160` | 每行卡片预估高度 |
391
+ | `bufferSize` | Number | `3` | 缓冲区行数 |
392
+
393
+ ### 搜索筛选
394
+
395
+ | 属性 | 类型 | 默认值 | 说明 |
396
+ |------|------|--------|------|
397
+ | `filterable` | Boolean | `false` | 是否启用搜索 |
398
+ | `filterPlaceholder` | String | `'请输入搜索内容'` | 搜索框占位文本 |
399
+ | `filterMethod` | Function | - | 自定义筛选方法 `(item, searchText) => boolean` |
400
+
401
+ ### 排序
402
+
403
+ | 属性 | 类型 | 默认值 | 说明 |
404
+ |------|------|--------|------|
405
+ | `sortable` | Boolean | `false` | 是否启用排序 |
406
+ | `sortBy` | String | `''` | 排序字段 |
407
+ | `sortOrder` | String | `''` | 默认排序方向('ascending' / 'descending') |
408
+ | `sortMethod` | Function | - | 自定义排序方法 `(a, b) => number` |
409
+
410
+ ### 加载更多
411
+
412
+ | 属性 | 类型 | 默认值 | 说明 |
413
+ |------|------|--------|------|
414
+ | `loadMore` | Boolean | `false` | 是否启用加载更多 |
415
+ | `hasMore` | Boolean | `false` | 是否有更多数据 |
416
+ | `loadMoreText` | String | `'加载更多'` | 加载更多按钮文本 |
417
+ | `loadMoreLoading` | Boolean | `false` | 加载更多按钮加载状态 |
418
+
419
+ ### 分页
420
+
421
+ | 属性 | 类型 | 默认值 | 说明 |
422
+ |------|------|--------|------|
423
+ | `pagination` | Object | `null` | 分页配置 `{ pageNum, pageSize, pageSizes }` |
424
+ | `total` | Number | `0` | 数据总数 |
425
+
426
+ ## 事件
427
+
428
+ | 事件名 | 说明 | 参数 |
429
+ |--------|------|------|
430
+ | `click-item` | 点击卡片 | `{ item, groupKey }` |
431
+ | `group-toggle` | 分组展开/折叠 | `{ key, expanded }` |
432
+ | `search` | 搜索输入变化 | `searchText` |
433
+ | `sort-change` | 排序变化 | `{ prop, order }` |
434
+ | `load-more` | 点击加载更多 | - |
435
+ | `size-change` | 每页条数变化 | `size` |
436
+ | `page-change` | 当前页变化 | `page` |
437
+
438
+ ## 方法
439
+
440
+ | 方法名 | 说明 | 参数 |
441
+ |--------|------|------|
442
+ | `scrollToTop()` | 滚动到顶部 | - |
443
+ | `expandGroup(key)` | 展开指定分组 | `key` |
444
+ | `collapseGroup(key)` | 折叠指定分组 | `key` |
445
+ | `collapseAll()` | 折叠所有分组 | - |
446
+ | `expandAllGroups()` | 展开所有分组 | - |
447
+
448
+ ## 插槽
449
+
450
+ | 插槽名 | 作用域 | 说明 |
451
+ |--------|--------|------|
452
+ | `default` | `{ item, index, group }` | 自定义卡片内容 |
453
+ | `group-title` | `{ group, items, expanded }` | 自定义分组标题 |
454
+ | `card-footer` | `{ item, index }` | 自定义卡片底部 |
455
+ | `toolbar` | - | 工具栏区域(搜索和排序按钮右侧) |
456
+ | `empty` | - | 自定义空状态 |
459
457
  | `loading` | - | 自定义加载状态 |