jianghu-ui 1.0.1

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 (112) hide show
  1. package/README.md +376 -0
  2. package/dist/jianghu-ui.css +2318 -0
  3. package/dist/jianghu-ui.js +2 -0
  4. package/dist/jianghu-ui.js.LICENSE.txt +1 -0
  5. package/package.json +56 -0
  6. package/src/Design.stories.mdx +195 -0
  7. package/src/Introduction.stories.mdx +148 -0
  8. package/src/components/JhAddressSelect/JhAddressSelect.md +250 -0
  9. package/src/components/JhAddressSelect/JhAddressSelect.stories.js +282 -0
  10. package/src/components/JhAddressSelect/JhAddressSelect.vue +261 -0
  11. package/src/components/JhCard/JhCard.md +246 -0
  12. package/src/components/JhCard/JhCard.stories.js +688 -0
  13. package/src/components/JhCard/JhCard.vue +604 -0
  14. package/src/components/JhCheckCard/JhCheckCard.md +245 -0
  15. package/src/components/JhCheckCard/JhCheckCard.stories.js +750 -0
  16. package/src/components/JhCheckCard/JhCheckCard.vue +476 -0
  17. package/src/components/JhConfirmDialog/JhConfirmDialog.md +70 -0
  18. package/src/components/JhConfirmDialog/JhConfirmDialog.stories.js +550 -0
  19. package/src/components/JhConfirmDialog/JhConfirmDialog.vue +181 -0
  20. package/src/components/JhDateRangePicker/JhDateRangePicker.md +56 -0
  21. package/src/components/JhDateRangePicker/JhDateRangePicker.stories.js +320 -0
  22. package/src/components/JhDateRangePicker/JhDateRangePicker.vue +307 -0
  23. package/src/components/JhDescriptions/JhDescriptions.md +724 -0
  24. package/src/components/JhDescriptions/JhDescriptions.stories.js +858 -0
  25. package/src/components/JhDescriptions/JhDescriptions.vue +933 -0
  26. package/src/components/JhDraggable/JhDraggable.md +66 -0
  27. package/src/components/JhDraggable/JhDraggable.stories.js +161 -0
  28. package/src/components/JhDraggable/JhDraggable.vue +254 -0
  29. package/src/components/JhDrawer/JhDrawer.md +68 -0
  30. package/src/components/JhDrawer/JhDrawer.stories.js +478 -0
  31. package/src/components/JhDrawer/JhDrawer.vue +281 -0
  32. package/src/components/JhDrawerForm/JhDrawerForm.md +69 -0
  33. package/src/components/JhDrawerForm/JhDrawerForm.stories.js +492 -0
  34. package/src/components/JhDrawerForm/JhDrawerForm.vue +297 -0
  35. package/src/components/JhEditableTable/JhEditableTable.md +507 -0
  36. package/src/components/JhEditableTable/JhEditableTable.stories.js +615 -0
  37. package/src/components/JhEditableTable/JhEditableTable.vue +685 -0
  38. package/src/components/JhFileInput/JhFileInput.md +56 -0
  39. package/src/components/JhFileInput/JhFileInput.stories.js +103 -0
  40. package/src/components/JhFileInput/JhFileInput.vue +253 -0
  41. package/src/components/JhForm/JhForm.md +676 -0
  42. package/src/components/JhForm/JhForm.stories.js +1375 -0
  43. package/src/components/JhForm/JhForm.vue +657 -0
  44. package/src/components/JhFormField/JhFormField.stories.js +217 -0
  45. package/src/components/JhFormField/JhFormField.vue +439 -0
  46. package/src/components/JhFormFields/JhFormFields.md +647 -0
  47. package/src/components/JhFormFields/JhFormFields.stories.js +922 -0
  48. package/src/components/JhFormFields/JhFormFields.vue +998 -0
  49. package/src/components/JhFormList/JhFormList.md +303 -0
  50. package/src/components/JhFormList/JhFormList.stories.js +661 -0
  51. package/src/components/JhFormList/JhFormList.vue +1127 -0
  52. package/src/components/JhJsonEditor/JhJsonEditor.md +54 -0
  53. package/src/components/JhJsonEditor/JhJsonEditor.stories.js +157 -0
  54. package/src/components/JhJsonEditor/JhJsonEditor.vue +178 -0
  55. package/src/components/JhLayout/JhLayout.md +580 -0
  56. package/src/components/JhLayout/JhLayout.stories.js +414 -0
  57. package/src/components/JhLayout/JhLayout.vue +387 -0
  58. package/src/components/JhList/JhList.md +441 -0
  59. package/src/components/JhList/JhList.stories.js +524 -0
  60. package/src/components/JhList/JhList.vue +571 -0
  61. package/src/components/JhMarkdownEditor/JhMarkdownEditor.md +56 -0
  62. package/src/components/JhMarkdownEditor/JhMarkdownEditor.stories.js +191 -0
  63. package/src/components/JhMarkdownEditor/JhMarkdownEditor.vue +188 -0
  64. package/src/components/JhMask/JhMask.md +62 -0
  65. package/src/components/JhMask/JhMask.stories.js +270 -0
  66. package/src/components/JhMask/JhMask.vue +123 -0
  67. package/src/components/JhMenu/JhMenu.md +85 -0
  68. package/src/components/JhMenu/JhMenu.stories.js +384 -0
  69. package/src/components/JhMenu/JhMenu.vue +545 -0
  70. package/src/components/JhModal/JhModal.md +68 -0
  71. package/src/components/JhModal/JhModal.stories.js +562 -0
  72. package/src/components/JhModal/JhModal.vue +235 -0
  73. package/src/components/JhModalForm/JhModalForm.md +69 -0
  74. package/src/components/JhModalForm/JhModalForm.stories.js +592 -0
  75. package/src/components/JhModalForm/JhModalForm.vue +298 -0
  76. package/src/components/JhPageContainer/JhPageContainer.md +409 -0
  77. package/src/components/JhPageContainer/JhPageContainer.stories.js +209 -0
  78. package/src/components/JhPageContainer/JhPageContainer.vue +72 -0
  79. package/src/components/JhQueryFilter/JhQueryFilter.md +77 -0
  80. package/src/components/JhQueryFilter/JhQueryFilter.stories.js +684 -0
  81. package/src/components/JhQueryFilter/JhQueryFilter.vue +429 -0
  82. package/src/components/JhScene/JhScene.md +64 -0
  83. package/src/components/JhScene/JhScene.stories.js +317 -0
  84. package/src/components/JhScene/JhScene.vue +376 -0
  85. package/src/components/JhStatisticCard/JhStatisticCard.md +363 -0
  86. package/src/components/JhStatisticCard/JhStatisticCard.stories.js +847 -0
  87. package/src/components/JhStatisticCard/JhStatisticCard.vue +459 -0
  88. package/src/components/JhStepsForm/JhStepsForm.md +666 -0
  89. package/src/components/JhStepsForm/JhStepsForm.stories.js +1224 -0
  90. package/src/components/JhStepsForm/JhStepsForm.vue +749 -0
  91. package/src/components/JhTable/JhTable.md +730 -0
  92. package/src/components/JhTable/JhTable.stories.js +1444 -0
  93. package/src/components/JhTable/JhTable.vue +2298 -0
  94. package/src/components/JhTableAttachment/JhTableAttachment.md +70 -0
  95. package/src/components/JhTableAttachment/JhTableAttachment.stories.js +198 -0
  96. package/src/components/JhTableAttachment/JhTableAttachment.vue +264 -0
  97. package/src/components/JhToast/JhToast.md +67 -0
  98. package/src/components/JhToast/JhToast.stories.js +386 -0
  99. package/src/components/JhToast/JhToast.vue +239 -0
  100. package/src/components/JhTreeSelect/JhTreeSelect.md +82 -0
  101. package/src/components/JhTreeSelect/JhTreeSelect.stories.js +391 -0
  102. package/src/components/JhTreeSelect/JhTreeSelect.vue +727 -0
  103. package/src/components/JhWaterMark/JhWaterMark.md +190 -0
  104. package/src/components/JhWaterMark/JhWaterMark.stories.js +675 -0
  105. package/src/components/JhWaterMark/JhWaterMark.vue +351 -0
  106. package/src/components/README.md +52 -0
  107. package/src/index.js +135 -0
  108. package/src/style/globalCSSJHV4.css +348 -0
  109. package/src/style/globalCSSVuetifyV4.css +637 -0
  110. package/src/style/storybook.css +4 -0
  111. package/src/tailwind.css +3 -0
  112. package/src/utils/vuetify.js +31 -0
@@ -0,0 +1,661 @@
1
+ import JhFormList from './JhFormList.vue';
2
+
3
+ export default {
4
+ title: '数据录入/JhFormList - 数据结构化',
5
+ component: JhFormList,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ mode: {
9
+ control: 'select',
10
+ options: ['card', 'table', 'inline'],
11
+ description: '渲染模式',
12
+ },
13
+ min: {
14
+ control: 'number',
15
+ description: '最小项数',
16
+ },
17
+ max: {
18
+ control: 'number',
19
+ description: '最大项数',
20
+ },
21
+ sortable: {
22
+ control: 'boolean',
23
+ description: '是否可拖拽排序',
24
+ },
25
+ copyable: {
26
+ control: 'boolean',
27
+ description: '是否可复制',
28
+ },
29
+ showIndex: {
30
+ control: 'boolean',
31
+ description: '是否显示序号',
32
+ },
33
+ dense: {
34
+ control: 'boolean',
35
+ description: '紧凑模式',
36
+ },
37
+ outlined: {
38
+ control: 'boolean',
39
+ description: '边框样式',
40
+ },
41
+ disabled: {
42
+ control: 'boolean',
43
+ description: '禁用状态',
44
+ },
45
+ readonly: {
46
+ control: 'boolean',
47
+ description: '只读状态',
48
+ },
49
+ },
50
+ };
51
+
52
+ // 基础示例 - Card 模式
53
+ export const BasicCard = {
54
+ render: (args, { argTypes }) => ({
55
+ components: { JhFormList },
56
+ props: Object.keys(argTypes),
57
+ data() {
58
+ return {
59
+ contacts: [
60
+ { name: '张三', phone: '13800138000', email: 'zhangsan@example.com', role: 'manager' },
61
+ { name: '李四', phone: '13900139000', email: 'lisi@example.com', role: 'developer' },
62
+ ],
63
+ fields: [
64
+ {
65
+ key: 'name',
66
+ label: '姓名',
67
+ type: 'text',
68
+ required: true,
69
+ cols: 6,
70
+ placeholder: '请输入姓名'
71
+ },
72
+ {
73
+ key: 'phone',
74
+ label: '电话',
75
+ type: 'text',
76
+ rules: [(v) => !v || /^1[3-9]\d{9}$/.test(v) || '请输入正确的手机号'],
77
+ cols: 6,
78
+ placeholder: '请输入电话'
79
+ },
80
+ {
81
+ key: 'email',
82
+ label: '邮箱',
83
+ type: 'text',
84
+ rules: [(v) => !v || /.+@.+\..+/.test(v) || '请输入正确的邮箱'],
85
+ cols: 6,
86
+ placeholder: '请输入邮箱'
87
+ },
88
+ {
89
+ key: 'role',
90
+ label: '角色',
91
+ type: 'select',
92
+ options: [
93
+ { text: '管理员', value: 'manager' },
94
+ { text: '开发者', value: 'developer' },
95
+ { text: '测试', value: 'tester' },
96
+ ],
97
+ cols: 6,
98
+ },
99
+ ],
100
+ };
101
+ },
102
+ template: `
103
+ <v-app>
104
+ <v-container>
105
+ <jh-form-list
106
+ v-model="contacts"
107
+ :fields="fields"
108
+ v-bind="$props"
109
+ title="联系人列表"
110
+ description="请填写联系人信息,至少需要一位联系人"
111
+ :min="1"
112
+ :max="5"
113
+ @add="(item, index) => console.log('添加:', item, index)"
114
+ @remove="(item, index) => console.log('删除:', item, index)"
115
+ @copy="(source, newItem) => console.log('复制:', source, newItem)"
116
+ />
117
+ <v-divider class="my-6"></v-divider>
118
+ <div>
119
+ <h4 class="mb-2">当前数据:</h4>
120
+ <pre class="grey lighten-4 pa-3">{{ contacts }}</pre>
121
+ </div>
122
+ </v-container>
123
+ </v-app>
124
+ `,
125
+ }),
126
+ args: {
127
+ mode: 'card',
128
+ sortable: false,
129
+ copyable: true,
130
+ showIndex: true,
131
+ dense: true,
132
+ outlined: true,
133
+ disabled: false,
134
+ readonly: false,
135
+ },
136
+ };
137
+
138
+ // Table 模式
139
+ export const TableMode = {
140
+ render: () => ({
141
+ components: { JhFormList },
142
+ data() {
143
+ return {
144
+ items: [
145
+ { product: 'MacBook Pro', quantity: 2, price: 12999, note: '16寸 M3' },
146
+ { product: 'iPhone 15', quantity: 1, price: 5999, note: '128GB' },
147
+ { product: 'AirPods Pro', quantity: 3, price: 1999, note: '第二代' },
148
+ ],
149
+ fields: [
150
+ {
151
+ key: 'product',
152
+ label: '商品名称',
153
+ type: 'text',
154
+ required: true,
155
+ placeholder: '请输入商品名称'
156
+ },
157
+ {
158
+ key: 'quantity',
159
+ label: '数量',
160
+ type: 'number',
161
+ required: true,
162
+ placeholder: '请输入数量'
163
+ },
164
+ {
165
+ key: 'price',
166
+ label: '单价',
167
+ type: 'number',
168
+ required: true,
169
+ placeholder: '请输入单价'
170
+ },
171
+ {
172
+ key: 'note',
173
+ label: '备注',
174
+ type: 'text',
175
+ placeholder: '请输入备注'
176
+ },
177
+ ],
178
+ };
179
+ },
180
+ computed: {
181
+ totalAmount() {
182
+ return this.items.reduce((sum, item) => {
183
+ return sum + (item.quantity || 0) * (item.price || 0);
184
+ }, 0);
185
+ },
186
+ },
187
+ template: `
188
+ <v-app>
189
+ <v-container>
190
+ <jh-form-list
191
+ v-model="items"
192
+ :fields="fields"
193
+ mode="table"
194
+ title="订单商品"
195
+ :min="1"
196
+ :sortable="true"
197
+ :show-index="true"
198
+ />
199
+ <v-card class="mt-4 pa-4">
200
+ <div class="text-right">
201
+ <span class="text-h6">总金额: </span>
202
+ <span class="text-h5 error--text">¥{{ totalAmount.toFixed(2) }}</span>
203
+ </div>
204
+ </v-card>
205
+ </v-container>
206
+ </v-app>
207
+ `,
208
+ }),
209
+ };
210
+
211
+ // Inline 模式
212
+ export const InlineMode = {
213
+ render: () => ({
214
+ components: { JhFormList },
215
+ data() {
216
+ return {
217
+ tags: [
218
+ { name: 'Vue.js' },
219
+ { name: 'React' },
220
+ { name: 'Angular' },
221
+ { name: 'Svelte' },
222
+ ],
223
+ fields: [
224
+ {
225
+ key: 'name',
226
+ label: '标签名称',
227
+ type: 'text',
228
+ required: true,
229
+ },
230
+ ],
231
+ };
232
+ },
233
+ template: `
234
+ <v-app>
235
+ <v-container>
236
+ <div class="mb-2">
237
+ <strong>技术栈标签:</strong>
238
+ </div>
239
+ <jh-form-list
240
+ v-model="tags"
241
+ :fields="fields"
242
+ mode="inline"
243
+ inline-display-key="name"
244
+ :sortable="true"
245
+ add-button-text="添加标签"
246
+ />
247
+ </v-container>
248
+ </v-app>
249
+ `,
250
+ }),
251
+ };
252
+
253
+ // 自定义渲染
254
+ export const CustomRender = {
255
+ render: () => ({
256
+ components: { JhFormList },
257
+ data() {
258
+ return {
259
+ members: [
260
+ {
261
+ name: '张三',
262
+ avatar: 'https://i.pravatar.cc/150?img=1',
263
+ role: 'admin',
264
+ status: 'active'
265
+ },
266
+ {
267
+ name: '李四',
268
+ avatar: 'https://i.pravatar.cc/150?img=2',
269
+ role: 'member',
270
+ status: 'active'
271
+ },
272
+ ],
273
+ fields: [
274
+ {
275
+ key: 'name',
276
+ label: '姓名',
277
+ type: 'text',
278
+ required: true,
279
+ cols: 6,
280
+ },
281
+ {
282
+ key: 'role',
283
+ label: '角色',
284
+ type: 'select',
285
+ options: [
286
+ { text: '管理员', value: 'admin' },
287
+ { text: '普通成员', value: 'member' },
288
+ ],
289
+ cols: 6,
290
+ },
291
+ {
292
+ key: 'avatar',
293
+ label: '头像URL',
294
+ type: 'text',
295
+ cols: 12,
296
+ },
297
+ ],
298
+ };
299
+ },
300
+ template: `
301
+ <v-app>
302
+ <v-container>
303
+ <jh-form-list
304
+ v-model="members"
305
+ :fields="fields"
306
+ title="团队成员"
307
+ mode="card"
308
+ >
309
+ <!-- 自定义列表项头部 -->
310
+ <template #item="{ item, index, fields, updateItem }">
311
+ <div class="d-flex align-center mb-4">
312
+ <v-avatar size="48" class="mr-3">
313
+ <v-img :src="item.avatar || 'https://i.pravatar.cc/150?img=' + index"></v-img>
314
+ </v-avatar>
315
+ <div>
316
+ <div class="font-weight-medium">{{ item.name || '未命名' }}</div>
317
+ <div class="text-caption grey--text">
318
+ {{ item.role === 'admin' ? '管理员' : '普通成员' }}
319
+ </div>
320
+ </div>
321
+ </div>
322
+
323
+ <!-- 使用默认表单字段 -->
324
+ <jh-form
325
+ :fields="fields"
326
+ :initial-data="item"
327
+ layout="horizontal"
328
+ @field-change="({ key, value }) => updateItem(key, value)"
329
+ />
330
+ </template>
331
+ </jh-form-list>
332
+ </v-container>
333
+ </v-app>
334
+ `,
335
+ }),
336
+ };
337
+
338
+ // 嵌套列表
339
+ export const NestedList = {
340
+ render: () => ({
341
+ components: { JhFormList },
342
+ data() {
343
+ return {
344
+ projects: [
345
+ {
346
+ name: '项目A',
347
+ description: '电商平台',
348
+ members: [
349
+ { name: '张三', role: 'frontend' },
350
+ { name: '李四', role: 'backend' },
351
+ ],
352
+ },
353
+ ],
354
+ projectFields: [
355
+ {
356
+ key: 'name',
357
+ label: '项目名称',
358
+ type: 'text',
359
+ required: true,
360
+ cols: 6,
361
+ },
362
+ {
363
+ key: 'description',
364
+ label: '项目描述',
365
+ type: 'text',
366
+ cols: 6,
367
+ },
368
+ ],
369
+ memberFields: [
370
+ {
371
+ key: 'name',
372
+ label: '成员姓名',
373
+ type: 'text',
374
+ required: true,
375
+ },
376
+ {
377
+ key: 'role',
378
+ label: '角色',
379
+ type: 'select',
380
+ options: [
381
+ { text: '前端', value: 'frontend' },
382
+ { text: '后端', value: 'backend' },
383
+ { text: '测试', value: 'tester' },
384
+ ],
385
+ },
386
+ ],
387
+ };
388
+ },
389
+ template: `
390
+ <v-app>
391
+ <v-container>
392
+ <jh-form-list
393
+ v-model="projects"
394
+ :fields="projectFields"
395
+ title="项目列表"
396
+ mode="card"
397
+ >
398
+ <template #field-members="{ item, updateItem }">
399
+ <div class="mt-4">
400
+ <div class="text-subtitle-2 mb-2">项目成员:</div>
401
+ <jh-form-list
402
+ :value="item.members || []"
403
+ @input="updateItem('members', $event)"
404
+ :fields="memberFields"
405
+ mode="table"
406
+ :show-index="false"
407
+ :dense="true"
408
+ add-button-text="添加成员"
409
+ />
410
+ </div>
411
+ </template>
412
+ </jh-form-list>
413
+ </v-container>
414
+ </v-app>
415
+ `,
416
+ }),
417
+ };
418
+
419
+ // 高级验证
420
+ export const AdvancedValidation = {
421
+ render: () => ({
422
+ components: { JhFormList },
423
+ data() {
424
+ return {
425
+ emails: [
426
+ { email: 'admin@example.com', isPrimary: true },
427
+ ],
428
+ fields: [
429
+ {
430
+ key: 'email',
431
+ label: '邮箱地址',
432
+ type: 'text',
433
+ required: true,
434
+ rules: [(v) => /.+@.+\..+/.test(v) || '请输入正确的邮箱格式'],
435
+ cols: 8,
436
+ },
437
+ {
438
+ key: 'isPrimary',
439
+ label: '主邮箱',
440
+ type: 'switch',
441
+ cols: 4,
442
+ },
443
+ ],
444
+ listRules: [
445
+ (items) => items.length >= 1 || '至少需要一个邮箱',
446
+ (items) => items.length <= 5 || '最多只能添加5个邮箱',
447
+ (items) => {
448
+ const emails = items.map(i => i.email).filter(Boolean);
449
+ const unique = new Set(emails);
450
+ return emails.length === unique.size || '邮箱地址不能重复';
451
+ },
452
+ (items) => {
453
+ const primaryCount = items.filter(i => i.isPrimary).length;
454
+ return primaryCount <= 1 || '只能有一个主邮箱';
455
+ },
456
+ ],
457
+ };
458
+ },
459
+ methods: {
460
+ async handleValidate() {
461
+ const isValid = await this.$refs.formList.validate();
462
+ if (isValid) {
463
+ alert('验证通过!');
464
+ } else {
465
+ alert('验证失败,请检查输入');
466
+ }
467
+ },
468
+ },
469
+ template: `
470
+ <v-app>
471
+ <v-container>
472
+ <jh-form-list
473
+ ref="formList"
474
+ v-model="emails"
475
+ :fields="fields"
476
+ :rules="listRules"
477
+ title="邮箱列表"
478
+ description="请添加您的邮箱地址,至少一个,最多五个"
479
+ :min="1"
480
+ :max="5"
481
+ />
482
+ <v-btn color="primary" class="mt-4" @click="handleValidate">
483
+ 验证表单
484
+ </v-btn>
485
+ </v-container>
486
+ </v-app>
487
+ `,
488
+ }),
489
+ };
490
+
491
+ // 只读模式
492
+ export const ReadonlyMode = {
493
+ render: () => ({
494
+ components: { JhFormList },
495
+ data() {
496
+ return {
497
+ educations: [
498
+ {
499
+ school: '清华大学',
500
+ major: '计算机科学与技术',
501
+ degree: 'bachelor',
502
+ startDate: '2015-09',
503
+ endDate: '2019-06',
504
+ },
505
+ {
506
+ school: '北京大学',
507
+ major: '软件工程',
508
+ degree: 'master',
509
+ startDate: '2019-09',
510
+ endDate: '2022-06',
511
+ },
512
+ ],
513
+ fields: [
514
+ { key: 'school', label: '学校', type: 'text', cols: 6 },
515
+ { key: 'major', label: '专业', type: 'text', cols: 6 },
516
+ {
517
+ key: 'degree',
518
+ label: '学历',
519
+ type: 'select',
520
+ options: [
521
+ { text: '本科', value: 'bachelor' },
522
+ { text: '硕士', value: 'master' },
523
+ { text: '博士', value: 'doctor' },
524
+ ],
525
+ cols: 4,
526
+ },
527
+ { key: 'startDate', label: '开始时间', type: 'text', cols: 4 },
528
+ { key: 'endDate', label: '结束时间', type: 'text', cols: 4 },
529
+ ],
530
+ };
531
+ },
532
+ template: `
533
+ <v-app>
534
+ <v-container>
535
+ <jh-form-list
536
+ v-model="educations"
537
+ :fields="fields"
538
+ title="教育经历"
539
+ mode="card"
540
+ :readonly="true"
541
+ />
542
+ </v-container>
543
+ </v-app>
544
+ `,
545
+ }),
546
+ };
547
+
548
+ // 禁用状态
549
+ export const DisabledState = {
550
+ render: () => ({
551
+ components: { JhFormList },
552
+ data() {
553
+ return {
554
+ items: [
555
+ { name: '项目A', status: 'completed' },
556
+ { name: '项目B', status: 'pending' },
557
+ ],
558
+ fields: [
559
+ { key: 'name', label: '项目名称', type: 'text', cols: 8 },
560
+ {
561
+ key: 'status',
562
+ label: '状态',
563
+ type: 'select',
564
+ options: [
565
+ { text: '待处理', value: 'pending' },
566
+ { text: '进行中', value: 'processing' },
567
+ { text: '已完成', value: 'completed' },
568
+ ],
569
+ cols: 4,
570
+ },
571
+ ],
572
+ };
573
+ },
574
+ template: `
575
+ <v-app>
576
+ <v-container>
577
+ <jh-form-list
578
+ v-model="items"
579
+ :fields="fields"
580
+ title="项目列表(禁用状态)"
581
+ :disabled="true"
582
+ />
583
+ </v-container>
584
+ </v-app>
585
+ `,
586
+ }),
587
+ };
588
+
589
+ // 动态默认值
590
+ export const DynamicDefaultValue = {
591
+ render: () => ({
592
+ components: { JhFormList },
593
+ data() {
594
+ return {
595
+ tasks: [],
596
+ fields: [
597
+ {
598
+ key: 'title',
599
+ label: '任务标题',
600
+ type: 'text',
601
+ required: true,
602
+ cols: 8,
603
+ },
604
+ {
605
+ key: 'priority',
606
+ label: '优先级',
607
+ type: 'select',
608
+ options: [
609
+ { text: '低', value: 'low' },
610
+ { text: '中', value: 'medium' },
611
+ { text: '高', value: 'high' },
612
+ ],
613
+ cols: 4,
614
+ },
615
+ {
616
+ key: 'dueDate',
617
+ label: '截止日期',
618
+ type: 'date',
619
+ cols: 6,
620
+ },
621
+ {
622
+ key: 'assignee',
623
+ label: '负责人',
624
+ type: 'text',
625
+ cols: 6,
626
+ },
627
+ ],
628
+ };
629
+ },
630
+ methods: {
631
+ getDefaultValue(index) {
632
+ const today = new Date();
633
+ const dueDate = new Date(today);
634
+ dueDate.setDate(today.getDate() + 7);
635
+
636
+ return {
637
+ title: `任务 ${index + 1}`,
638
+ priority: 'medium',
639
+ dueDate: dueDate.toISOString().split('T')[0],
640
+ assignee: '',
641
+ };
642
+ },
643
+ },
644
+ template: `
645
+ <v-app>
646
+ <v-container>
647
+ <jh-form-list
648
+ v-model="tasks"
649
+ :fields="fields"
650
+ :default-value="getDefaultValue"
651
+ title="任务列表"
652
+ description="新增任务会自动填充默认值"
653
+ />
654
+ <div class="mt-4">
655
+ <pre class="grey lighten-4 pa-3">{{ tasks }}</pre>
656
+ </div>
657
+ </v-container>
658
+ </v-app>
659
+ `,
660
+ }),
661
+ };