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,922 @@
1
+ import JhFormFields from './JhFormFields.vue';
2
+
3
+ export default {
4
+ title: '数据录入/JhFormFields - 数据结构化',
5
+ component: JhFormFields,
6
+ parameters: {
7
+ docs: {
8
+ description: {
9
+ component: '基于 Ant Design ProComponents FieldSet 设计的字段集组件,支持字段依赖、动态联动等高级特性。',
10
+ },
11
+ },
12
+ },
13
+ };
14
+
15
+ // 基础用法
16
+ export const Basic = () => ({
17
+ components: { JhFormFields },
18
+ data() {
19
+ return {
20
+ formData: {
21
+ username: '',
22
+ email: '',
23
+ phone: '',
24
+ },
25
+ fields: [
26
+ {
27
+ key: 'username',
28
+ label: '用户名',
29
+ type: 'text',
30
+ placeholder: '请输入用户名',
31
+ required: true,
32
+ },
33
+ {
34
+ key: 'email',
35
+ label: '邮箱',
36
+ type: 'text',
37
+ placeholder: '请输入邮箱',
38
+ rules: 'email',
39
+ },
40
+ {
41
+ key: 'phone',
42
+ label: '手机号',
43
+ type: 'text',
44
+ placeholder: '请输入手机号',
45
+ rules: 'phone',
46
+ },
47
+ ],
48
+ };
49
+ },
50
+ template: `
51
+ <v-container>
52
+ <JhFormFields
53
+ v-model="formData"
54
+ :fields="fields"
55
+ title="基本信息"
56
+ description="请填写您的基本信息"
57
+ />
58
+ <v-divider class="my-4"></v-divider>
59
+ <div class="text-caption">表单数据:</div>
60
+ <pre>{{ formData }}</pre>
61
+ </v-container>
62
+ `,
63
+ });
64
+
65
+ // 字段依赖 - ProFormDependency
66
+ export const FieldDependency = () => ({
67
+ components: { JhFormFields },
68
+ data() {
69
+ return {
70
+ formData: {
71
+ userType: 'personal',
72
+ country: 'china',
73
+ },
74
+ fields: [
75
+ {
76
+ key: 'userType',
77
+ label: '用户类型',
78
+ type: 'radio',
79
+ options: [
80
+ { text: '个人用户', value: 'personal' },
81
+ { text: '企业用户', value: 'company' },
82
+ ],
83
+ defaultValue: 'personal',
84
+ cols: { md: 12 },
85
+ },
86
+ {
87
+ key: 'personalName',
88
+ label: '真实姓名',
89
+ type: 'text',
90
+ placeholder: '请输入真实姓名',
91
+ required: true,
92
+ visible: (values) => values.userType === 'personal',
93
+ dependencies: ['userType'],
94
+ },
95
+ {
96
+ key: 'idCard',
97
+ label: '身份证号',
98
+ type: 'text',
99
+ placeholder: '请输入身份证号',
100
+ visible: (values) => values.userType === 'personal',
101
+ dependencies: ['userType'],
102
+ },
103
+ {
104
+ key: 'companyName',
105
+ label: '公司名称',
106
+ type: 'text',
107
+ placeholder: '请输入公司名称',
108
+ required: true,
109
+ visible: (values) => values.userType === 'company',
110
+ dependencies: ['userType'],
111
+ },
112
+ {
113
+ key: 'businessLicense',
114
+ label: '营业执照号',
115
+ type: 'text',
116
+ placeholder: '请输入营业执照号',
117
+ visible: (values) => values.userType === 'company',
118
+ dependencies: ['userType'],
119
+ },
120
+ { type: 'group', title: '地址信息', divider: true },
121
+ {
122
+ key: 'country',
123
+ label: '国家',
124
+ type: 'select',
125
+ options: [
126
+ { text: '中国', value: 'china' },
127
+ { text: '美国', value: 'usa' },
128
+ { text: '日本', value: 'japan' },
129
+ ],
130
+ defaultValue: 'china',
131
+ },
132
+ {
133
+ key: 'province',
134
+ label: '省份',
135
+ type: 'select',
136
+ placeholder: '请选择省份',
137
+ options: (values) => {
138
+ const provinceMap = {
139
+ china: [
140
+ { text: '北京', value: 'beijing' },
141
+ { text: '上海', value: 'shanghai' },
142
+ { text: '广东', value: 'guangdong' },
143
+ ],
144
+ usa: [
145
+ { text: '加利福尼亚', value: 'california' },
146
+ { text: '纽约', value: 'newyork' },
147
+ { text: '德克萨斯', value: 'texas' },
148
+ ],
149
+ japan: [
150
+ { text: '东京', value: 'tokyo' },
151
+ { text: '大阪', value: 'osaka' },
152
+ { text: '京都', value: 'kyoto' },
153
+ ],
154
+ };
155
+ return provinceMap[values.country] || [];
156
+ },
157
+ dependencies: ['country'],
158
+ },
159
+ ],
160
+ };
161
+ },
162
+ template: `
163
+ <v-container>
164
+ <JhFormFields
165
+ v-model="formData"
166
+ :fields="fields"
167
+ title="用户注册"
168
+ description="根据用户类型显示不同的字段"
169
+ tooltip="字段会根据选择动态显示"
170
+ @field-dependency-change="handleDependencyChange"
171
+ />
172
+ <v-divider class="my-4"></v-divider>
173
+ <div class="text-caption">表单数据:</div>
174
+ <pre>{{ formData }}</pre>
175
+ </v-container>
176
+ `,
177
+ methods: {
178
+ handleDependencyChange(event) {
179
+ console.log('字段依赖变化:', event);
180
+ },
181
+ },
182
+ });
183
+
184
+ // 动态禁用字段
185
+ export const DynamicDisabled = () => ({
186
+ components: { JhFormFields },
187
+ data() {
188
+ return {
189
+ formData: {
190
+ agreeTerms: false,
191
+ subscribeNewsletter: false,
192
+ },
193
+ fields: [
194
+ {
195
+ key: 'agreeTerms',
196
+ label: '同意服务条款',
197
+ type: 'checkbox',
198
+ checkboxLabel: '我已阅读并同意服务条款',
199
+ defaultValue: false,
200
+ cols: { md: 12 },
201
+ },
202
+ {
203
+ key: 'username',
204
+ label: '用户名',
205
+ type: 'text',
206
+ placeholder: '请输入用户名',
207
+ disabled: (values) => !values.agreeTerms,
208
+ dependencies: ['agreeTerms'],
209
+ tooltip: '需要先同意服务条款',
210
+ },
211
+ {
212
+ key: 'email',
213
+ label: '邮箱',
214
+ type: 'text',
215
+ placeholder: '请输入邮箱',
216
+ disabled: (values) => !values.agreeTerms,
217
+ dependencies: ['agreeTerms'],
218
+ },
219
+ {
220
+ key: 'subscribeNewsletter',
221
+ label: '订阅新闻',
222
+ type: 'checkbox',
223
+ checkboxLabel: '订阅我们的新闻通讯',
224
+ disabled: (values) => !values.agreeTerms,
225
+ dependencies: ['agreeTerms'],
226
+ },
227
+ {
228
+ key: 'frequency',
229
+ label: '订阅频率',
230
+ type: 'select',
231
+ options: [
232
+ { text: '每日', value: 'daily' },
233
+ { text: '每周', value: 'weekly' },
234
+ { text: '每月', value: 'monthly' },
235
+ ],
236
+ disabled: (values) => !values.agreeTerms || !values.subscribeNewsletter,
237
+ dependencies: ['agreeTerms', 'subscribeNewsletter'],
238
+ },
239
+ ],
240
+ };
241
+ },
242
+ template: `
243
+ <v-container>
244
+ <JhFormFields
245
+ v-model="formData"
246
+ :fields="fields"
247
+ title="注册表单"
248
+ description="字段根据条件动态启用/禁用"
249
+ />
250
+ <v-divider class="my-4"></v-divider>
251
+ <div class="text-caption">表单数据:</div>
252
+ <pre>{{ formData }}</pre>
253
+ </v-container>
254
+ `,
255
+ });
256
+
257
+ // 水平布局
258
+ export const HorizontalLayout = () => ({
259
+ components: { JhFormFields },
260
+ data() {
261
+ return {
262
+ formData: {},
263
+ fields: [
264
+ {
265
+ key: 'username',
266
+ label: '用户名',
267
+ type: 'text',
268
+ placeholder: '请输入用户名',
269
+ required: true,
270
+ },
271
+ {
272
+ key: 'password',
273
+ label: '密码',
274
+ type: 'text',
275
+ placeholder: '请输入密码',
276
+ props: { type: 'password' },
277
+ required: true,
278
+ },
279
+ {
280
+ key: 'email',
281
+ label: '邮箱',
282
+ type: 'text',
283
+ placeholder: '请输入邮箱',
284
+ rules: 'email',
285
+ },
286
+ {
287
+ key: 'phone',
288
+ label: '手机号',
289
+ type: 'text',
290
+ placeholder: '请输入手机号',
291
+ rules: 'phone',
292
+ },
293
+ ],
294
+ };
295
+ },
296
+ template: `
297
+ <v-container>
298
+ <JhFormFields
299
+ v-model="formData"
300
+ :fields="fields"
301
+ title="登录信息"
302
+ layout="horizontal"
303
+ :labelWidth="100"
304
+ labelAlign="right"
305
+ :defaultColsMd="12"
306
+ />
307
+ <v-divider class="my-4"></v-divider>
308
+ <div class="text-caption">表单数据:</div>
309
+ <pre>{{ formData }}</pre>
310
+ </v-container>
311
+ `,
312
+ });
313
+
314
+ // 行内布局
315
+ export const InlineLayout = () => ({
316
+ components: { JhFormFields },
317
+ data() {
318
+ return {
319
+ formData: {},
320
+ fields: [
321
+ {
322
+ key: 'keyword',
323
+ label: '关键词',
324
+ type: 'text',
325
+ placeholder: '请输入关键词',
326
+ },
327
+ {
328
+ key: 'category',
329
+ label: '分类',
330
+ type: 'select',
331
+ options: [
332
+ { text: '全部', value: 'all' },
333
+ { text: '文章', value: 'article' },
334
+ { text: '视频', value: 'video' },
335
+ ],
336
+ },
337
+ {
338
+ key: 'status',
339
+ label: '状态',
340
+ type: 'select',
341
+ options: [
342
+ { text: '全部', value: 'all' },
343
+ { text: '已发布', value: 'published' },
344
+ { text: '草稿', value: 'draft' },
345
+ ],
346
+ },
347
+ ],
348
+ };
349
+ },
350
+ template: `
351
+ <v-container>
352
+ <JhFormFields
353
+ v-model="formData"
354
+ :fields="fields"
355
+ title="搜索筛选"
356
+ layout="inline"
357
+ >
358
+ <template #footer="{ values }">
359
+ <v-btn color="primary" class="ml-2">搜索</v-btn>
360
+ <v-btn text class="ml-2">重置</v-btn>
361
+ </template>
362
+ </JhFormFields>
363
+ <v-divider class="my-4"></v-divider>
364
+ <div class="text-caption">表单数据:</div>
365
+ <pre>{{ formData }}</pre>
366
+ </v-container>
367
+ `,
368
+ });
369
+
370
+ // 字段分组
371
+ export const FieldGroups = () => ({
372
+ components: { JhFormFields },
373
+ data() {
374
+ return {
375
+ formData: {},
376
+ fields: [
377
+ { type: 'group', title: '基本信息' },
378
+ {
379
+ key: 'username',
380
+ label: '用户名',
381
+ type: 'text',
382
+ placeholder: '请输入用户名',
383
+ required: true,
384
+ },
385
+ {
386
+ key: 'email',
387
+ label: '邮箱',
388
+ type: 'text',
389
+ placeholder: '请输入邮箱',
390
+ rules: 'email',
391
+ },
392
+ { type: 'group', title: '联系方式', divider: true, description: '请填写您的联系方式' },
393
+ {
394
+ key: 'phone',
395
+ label: '手机号',
396
+ type: 'text',
397
+ placeholder: '请输入手机号',
398
+ rules: 'phone',
399
+ },
400
+ {
401
+ key: 'address',
402
+ label: '地址',
403
+ type: 'textarea',
404
+ placeholder: '请输入地址',
405
+ rows: 3,
406
+ cols: { md: 12 },
407
+ },
408
+ { type: 'group', title: '其他信息', divider: true },
409
+ {
410
+ key: 'bio',
411
+ label: '个人简介',
412
+ type: 'textarea',
413
+ placeholder: '请输入个人简介',
414
+ rows: 4,
415
+ cols: { md: 12 },
416
+ },
417
+ ],
418
+ };
419
+ },
420
+ template: `
421
+ <v-container>
422
+ <JhFormFields
423
+ v-model="formData"
424
+ :fields="fields"
425
+ title="用户资料"
426
+ />
427
+ <v-divider class="my-4"></v-divider>
428
+ <div class="text-caption">表单数据:</div>
429
+ <pre>{{ formData }}</pre>
430
+ </v-container>
431
+ `,
432
+ });
433
+
434
+ // 只读模式
435
+ export const ReadonlyMode = () => ({
436
+ components: { JhFormFields },
437
+ data() {
438
+ return {
439
+ formData: {
440
+ username: 'johndoe',
441
+ email: 'john@example.com',
442
+ phone: '13800138000',
443
+ userType: 'company',
444
+ status: 'active',
445
+ subscribe: true,
446
+ bio: '这是一段个人简介...',
447
+ },
448
+ fields: [
449
+ {
450
+ key: 'username',
451
+ label: '用户名',
452
+ type: 'text',
453
+ },
454
+ {
455
+ key: 'email',
456
+ label: '邮箱',
457
+ type: 'text',
458
+ },
459
+ {
460
+ key: 'phone',
461
+ label: '手机号',
462
+ type: 'text',
463
+ },
464
+ {
465
+ key: 'userType',
466
+ label: '用户类型',
467
+ type: 'radio',
468
+ options: [
469
+ { text: '个人用户', value: 'personal' },
470
+ { text: '企业用户', value: 'company' },
471
+ ],
472
+ },
473
+ {
474
+ key: 'status',
475
+ label: '状态',
476
+ type: 'select',
477
+ options: [
478
+ { text: '激活', value: 'active' },
479
+ { text: '禁用', value: 'disabled' },
480
+ ],
481
+ },
482
+ {
483
+ key: 'subscribe',
484
+ label: '订阅状态',
485
+ type: 'switch',
486
+ },
487
+ {
488
+ key: 'bio',
489
+ label: '个人简介',
490
+ type: 'textarea',
491
+ cols: { md: 12 },
492
+ },
493
+ ],
494
+ };
495
+ },
496
+ template: `
497
+ <v-container>
498
+ <JhFormFields
499
+ v-model="formData"
500
+ :fields="fields"
501
+ title="用户详情"
502
+ description="只读模式展示"
503
+ readonly
504
+ />
505
+ <v-divider class="my-4"></v-divider>
506
+ <div class="text-caption">表单数据:</div>
507
+ <pre>{{ formData }}</pre>
508
+ </v-container>
509
+ `,
510
+ });
511
+
512
+ // 带边框样式
513
+ export const BorderedStyle = () => ({
514
+ components: { JhFormFields },
515
+ data() {
516
+ return {
517
+ formData: {},
518
+ fields: [
519
+ {
520
+ key: 'username',
521
+ label: '用户名',
522
+ type: 'text',
523
+ placeholder: '请输入用户名',
524
+ },
525
+ {
526
+ key: 'email',
527
+ label: '邮箱',
528
+ type: 'text',
529
+ placeholder: '请输入邮箱',
530
+ },
531
+ {
532
+ key: 'phone',
533
+ label: '手机号',
534
+ type: 'text',
535
+ placeholder: '请输入手机号',
536
+ },
537
+ ],
538
+ };
539
+ },
540
+ template: `
541
+ <v-container>
542
+ <JhFormFields
543
+ v-model="formData"
544
+ :fields="fields"
545
+ title="基本信息"
546
+ description="带边框的字段集"
547
+ tooltip="这是一个带边框的字段集组件"
548
+ bordered
549
+ />
550
+ <v-divider class="my-4"></v-divider>
551
+ <JhFormFields
552
+ v-model="formData"
553
+ :fields="fields"
554
+ title="联系方式"
555
+ bordered
556
+ class="mt-4"
557
+ />
558
+ </v-container>
559
+ `,
560
+ });
561
+
562
+ // 复杂联动示例
563
+ export const ComplexDependency = () => ({
564
+ components: { JhFormFields },
565
+ data() {
566
+ return {
567
+ formData: {
568
+ productType: 'physical',
569
+ hasDiscount: false,
570
+ },
571
+ fields: [
572
+ {
573
+ key: 'productType',
574
+ label: '商品类型',
575
+ type: 'radio',
576
+ options: [
577
+ { text: '实物商品', value: 'physical' },
578
+ { text: '虚拟商品', value: 'virtual' },
579
+ { text: '服务商品', value: 'service' },
580
+ ],
581
+ defaultValue: 'physical',
582
+ cols: { md: 12 },
583
+ },
584
+ {
585
+ key: 'productName',
586
+ label: '商品名称',
587
+ type: 'text',
588
+ placeholder: '请输入商品名称',
589
+ required: true,
590
+ },
591
+ {
592
+ key: 'price',
593
+ label: '价格',
594
+ type: 'number',
595
+ placeholder: '请输入价格',
596
+ required: true,
597
+ },
598
+ {
599
+ key: 'weight',
600
+ label: '重量(kg)',
601
+ type: 'number',
602
+ placeholder: '请输入重量',
603
+ visible: (values) => values.productType === 'physical',
604
+ dependencies: ['productType'],
605
+ },
606
+ {
607
+ key: 'shippingMethod',
608
+ label: '配送方式',
609
+ type: 'select',
610
+ options: [
611
+ { text: '快递', value: 'express' },
612
+ { text: '自提', value: 'pickup' },
613
+ ],
614
+ visible: (values) => values.productType === 'physical',
615
+ dependencies: ['productType'],
616
+ },
617
+ {
618
+ key: 'downloadUrl',
619
+ label: '下载链接',
620
+ type: 'text',
621
+ placeholder: '请输入下载链接',
622
+ visible: (values) => values.productType === 'virtual',
623
+ dependencies: ['productType'],
624
+ },
625
+ {
626
+ key: 'serviceTime',
627
+ label: '服务时长(小时)',
628
+ type: 'number',
629
+ placeholder: '请输入服务时长',
630
+ visible: (values) => values.productType === 'service',
631
+ dependencies: ['productType'],
632
+ },
633
+ { type: 'group', title: '优惠设置', divider: true },
634
+ {
635
+ key: 'hasDiscount',
636
+ label: '启用优惠',
637
+ type: 'checkbox',
638
+ checkboxLabel: '启用优惠价格',
639
+ defaultValue: false,
640
+ cols: { md: 12 },
641
+ },
642
+ {
643
+ key: 'discountType',
644
+ label: '优惠类型',
645
+ type: 'radio',
646
+ options: [
647
+ { text: '固定金额', value: 'fixed' },
648
+ { text: '百分比', value: 'percent' },
649
+ ],
650
+ visible: (values) => values.hasDiscount,
651
+ dependencies: ['hasDiscount'],
652
+ cols: { md: 12 },
653
+ },
654
+ {
655
+ key: 'discountAmount',
656
+ label: '优惠金额',
657
+ type: 'number',
658
+ placeholder: '请输入优惠金额',
659
+ visible: (values) => values.hasDiscount && values.discountType === 'fixed',
660
+ dependencies: ['hasDiscount', 'discountType'],
661
+ },
662
+ {
663
+ key: 'discountPercent',
664
+ label: '优惠百分比',
665
+ type: 'number',
666
+ placeholder: '请输入优惠百分比',
667
+ suffix: '%',
668
+ visible: (values) => values.hasDiscount && values.discountType === 'percent',
669
+ dependencies: ['hasDiscount', 'discountType'],
670
+ },
671
+ ],
672
+ };
673
+ },
674
+ template: `
675
+ <v-container>
676
+ <JhFormFields
677
+ v-model="formData"
678
+ :fields="fields"
679
+ title="商品信息"
680
+ description="根据商品类型和优惠设置显示不同字段"
681
+ />
682
+ <v-divider class="my-4"></v-divider>
683
+ <div class="text-caption">表单数据:</div>
684
+ <pre>{{ formData }}</pre>
685
+ </v-container>
686
+ `,
687
+ });
688
+
689
+ // 自定义字段插槽
690
+ export const CustomFieldSlot = () => ({
691
+ components: { JhFormFields },
692
+ data() {
693
+ return {
694
+ formData: {
695
+ rating: 3,
696
+ color: '#1976D2',
697
+ },
698
+ fields: [
699
+ {
700
+ key: 'username',
701
+ label: '用户名',
702
+ type: 'text',
703
+ placeholder: '请输入用户名',
704
+ },
705
+ {
706
+ key: 'rating',
707
+ label: '评分',
708
+ type: 'slot',
709
+ defaultValue: 3,
710
+ },
711
+ {
712
+ key: 'color',
713
+ label: '颜色',
714
+ type: 'slot',
715
+ defaultValue: '#1976D2',
716
+ },
717
+ {
718
+ key: 'description',
719
+ label: '描述',
720
+ type: 'textarea',
721
+ placeholder: '请输入描述',
722
+ cols: { md: 12 },
723
+ },
724
+ ],
725
+ };
726
+ },
727
+ template: `
728
+ <v-container>
729
+ <JhFormFields
730
+ v-model="formData"
731
+ :fields="fields"
732
+ title="自定义字段"
733
+ description="使用插槽自定义字段渲染"
734
+ >
735
+ <template #field-rating="{ value, updateField }">
736
+ <v-rating
737
+ :value="value"
738
+ @input="updateField('rating', $event)"
739
+ color="warning"
740
+ background-color="grey lighten-1"
741
+ half-increments
742
+ hover
743
+ ></v-rating>
744
+ </template>
745
+
746
+ <template #field-color="{ value, updateField }">
747
+ <v-color-picker
748
+ :value="value"
749
+ @input="updateField('color', $event)"
750
+ hide-inputs
751
+ show-swatches
752
+ ></v-color-picker>
753
+ </template>
754
+ </JhFormFields>
755
+ <v-divider class="my-4"></v-divider>
756
+ <div class="text-caption">表单数据:</div>
757
+ <pre>{{ formData }}</pre>
758
+ </v-container>
759
+ `,
760
+ });
761
+
762
+ // 响应式布局
763
+ export const ResponsiveLayout = () => ({
764
+ components: { JhFormFields },
765
+ data() {
766
+ return {
767
+ formData: {},
768
+ fields: [
769
+ {
770
+ key: 'field1',
771
+ label: '字段1 (全宽)',
772
+ type: 'text',
773
+ placeholder: '所有屏幕全宽',
774
+ cols: { xs: 12, sm: 12, md: 12, lg: 12 },
775
+ },
776
+ {
777
+ key: 'field2',
778
+ label: '字段2 (响应式)',
779
+ type: 'text',
780
+ placeholder: 'xs:12, sm:6, md:4, lg:3',
781
+ cols: { xs: 12, sm: 6, md: 4, lg: 3 },
782
+ },
783
+ {
784
+ key: 'field3',
785
+ label: '字段3 (响应式)',
786
+ type: 'text',
787
+ placeholder: 'xs:12, sm:6, md:4, lg:3',
788
+ cols: { xs: 12, sm: 6, md: 4, lg: 3 },
789
+ },
790
+ {
791
+ key: 'field4',
792
+ label: '字段4 (响应式)',
793
+ type: 'text',
794
+ placeholder: 'xs:12, sm:6, md:4, lg:3',
795
+ cols: { xs: 12, sm: 6, md: 4, lg: 3 },
796
+ },
797
+ {
798
+ key: 'field5',
799
+ label: '字段5 (响应式)',
800
+ type: 'text',
801
+ placeholder: 'xs:12, sm:6, md:4, lg:3',
802
+ cols: { xs: 12, sm: 6, md: 4, lg: 3 },
803
+ },
804
+ {
805
+ key: 'field6',
806
+ label: '字段6 (半宽)',
807
+ type: 'text',
808
+ placeholder: 'xs:12, md:6',
809
+ cols: { xs: 12, md: 6 },
810
+ },
811
+ {
812
+ key: 'field7',
813
+ label: '字段7 (半宽)',
814
+ type: 'text',
815
+ placeholder: 'xs:12, md:6',
816
+ cols: { xs: 12, md: 6 },
817
+ },
818
+ ],
819
+ };
820
+ },
821
+ template: `
822
+ <v-container>
823
+ <JhFormFields
824
+ v-model="formData"
825
+ :fields="fields"
826
+ title="响应式布局"
827
+ description="调整浏览器窗口大小查看效果"
828
+ />
829
+ <v-divider class="my-4"></v-divider>
830
+ <div class="text-caption">表单数据:</div>
831
+ <pre>{{ formData }}</pre>
832
+ </v-container>
833
+ `,
834
+ });
835
+
836
+ // 在 JhForm 中使用
837
+ export const WithinJhForm = () => ({
838
+ components: { JhFormFields },
839
+ data() {
840
+ return {
841
+ formData: {
842
+ userType: 'personal',
843
+ },
844
+ basicFields: [
845
+ {
846
+ key: 'username',
847
+ label: '用户名',
848
+ type: 'text',
849
+ placeholder: '请输入用户名',
850
+ required: true,
851
+ },
852
+ {
853
+ key: 'email',
854
+ label: '邮箱',
855
+ type: 'text',
856
+ placeholder: '请输入邮箱',
857
+ rules: 'email',
858
+ },
859
+ ],
860
+ typeFields: [
861
+ {
862
+ key: 'userType',
863
+ label: '用户类型',
864
+ type: 'radio',
865
+ options: [
866
+ { text: '个人用户', value: 'personal' },
867
+ { text: '企业用户', value: 'company' },
868
+ ],
869
+ defaultValue: 'personal',
870
+ cols: { md: 12 },
871
+ },
872
+ {
873
+ key: 'personalName',
874
+ label: '真实姓名',
875
+ type: 'text',
876
+ placeholder: '请输入真实姓名',
877
+ visible: (values) => values.userType === 'personal',
878
+ dependencies: ['userType'],
879
+ },
880
+ {
881
+ key: 'companyName',
882
+ label: '公司名称',
883
+ type: 'text',
884
+ placeholder: '请输入公司名称',
885
+ visible: (values) => values.userType === 'company',
886
+ dependencies: ['userType'],
887
+ },
888
+ ],
889
+ };
890
+ },
891
+ template: `
892
+ <v-container>
893
+ <v-form>
894
+ <JhFormFields
895
+ v-model="formData"
896
+ :fields="basicFields"
897
+ title="基本信息"
898
+ bordered
899
+ />
900
+
901
+ <JhFormFields
902
+ v-model="formData"
903
+ :fields="typeFields"
904
+ title="用户类型"
905
+ bordered
906
+ class="mt-4"
907
+ />
908
+
909
+ <v-row class="mt-4">
910
+ <v-col cols="12" class="text-right">
911
+ <v-btn class="mr-2">重置</v-btn>
912
+ <v-btn color="primary">提交</v-btn>
913
+ </v-col>
914
+ </v-row>
915
+ </v-form>
916
+
917
+ <v-divider class="my-4"></v-divider>
918
+ <div class="text-caption">表单数据:</div>
919
+ <pre>{{ formData }}</pre>
920
+ </v-container>
921
+ `,
922
+ });