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,647 @@
1
+ # JhFormFields - 表单字段集组件
2
+
3
+ JhFormFields 是基于 Ant Design ProComponents FieldSet 设计的表单字段集组件,支持字段依赖、动态联动等高级特性。可以独立使用,也可以在 JhForm 中组合使用。
4
+
5
+ ## ✨ 特性
6
+
7
+ - 🔗 **字段依赖** - 类似 ProFormDependency,支持字段间的依赖关系
8
+ - 🎯 **动态联动** - 字段的显示/隐藏、启用/禁用可根据其他字段值动态变化
9
+ - 📦 **字段分组** - 支持字段分组展示,提高表单可读性
10
+ - 🎨 **多种布局** - 支持 horizontal、vertical、inline 三种布局模式
11
+ - 📐 **响应式** - 支持响应式栅格布局
12
+ - 💡 **提示信息** - 支持 title、description、tooltip 等多种提示方式
13
+ - 🎭 **只读模式** - 支持只读展示
14
+ - 🔧 **灵活配置** - 支持边框样式、紧凑模式等多种配置
15
+ - 🧩 **组合使用** - 可在 JhForm 中组合多个 JhFormFields
16
+
17
+ ## 📦 安装
18
+
19
+ ```javascript
20
+ import JhFormFields from '@/components/JhFormFields/JhFormFields.vue';
21
+ ```
22
+
23
+ ## 🔨 基础用法
24
+
25
+ ### 简单示例
26
+
27
+ ```vue
28
+ <template>
29
+ <JhFormFields
30
+ v-model="formData"
31
+ :fields="fields"
32
+ title="基本信息"
33
+ description="请填写您的基本信息"
34
+ />
35
+ </template>
36
+
37
+ <script>
38
+ export default {
39
+ data() {
40
+ return {
41
+ formData: {
42
+ username: '',
43
+ email: '',
44
+ },
45
+ fields: [
46
+ {
47
+ key: 'username',
48
+ label: '用户名',
49
+ type: 'text',
50
+ placeholder: '请输入用户名',
51
+ required: true,
52
+ },
53
+ {
54
+ key: 'email',
55
+ label: '邮箱',
56
+ type: 'text',
57
+ placeholder: '请输入邮箱',
58
+ rules: 'email',
59
+ },
60
+ ],
61
+ };
62
+ },
63
+ };
64
+ </script>
65
+ ```
66
+
67
+ ## 📋 API
68
+
69
+ ### Props
70
+
71
+ | 参数 | 说明 | 类型 | 默认值 |
72
+ |------|------|------|--------|
73
+ | value (v-model) | 表单数据对象 | `Object` | `{}` |
74
+ | fields | 字段配置数组 | `Array<FieldConfig>` | `[]` |
75
+ | title | 标题 | `String` | `''` |
76
+ | description | 描述信息 | `String` | `''` |
77
+ | tooltip | 提示信息 | `String` | `''` |
78
+ | layout | 布局模式 | `'horizontal' \| 'vertical' \| 'inline'` | `'vertical'` |
79
+ | showLabels | 是否显示标签 | `Boolean` | `true` |
80
+ | labelWidth | 标签宽度(horizontal 布局) | `Number \| String` | `'auto'` |
81
+ | labelAlign | 标签对齐方式 | `'left' \| 'right' \| 'center'` | `'right'` |
82
+ | showRequiredMark | 是否显示必填标记 | `Boolean` | `true` |
83
+ | readonly | 只读模式 | `Boolean` | `false` |
84
+ | disabled | 禁用模式 | `Boolean` | `false` |
85
+ | defaultDense | 默认紧凑模式 | `Boolean` | `true` |
86
+ | defaultFilled | 默认填充样式 | `Boolean` | `true` |
87
+ | defaultOutlined | 默认轮廓样式 | `Boolean` | `false` |
88
+ | defaultColsMd | 默认列宽(md 断点) | `Number` | `6` |
89
+ | hideDetails | 隐藏详情信息 | `Boolean \| String` | `false` |
90
+ | dense | 紧凑模式 | `Boolean` | `false` |
91
+ | bordered | 显示边框 | `Boolean` | `false` |
92
+ | dependencies | 依赖字段数组 | `Array<String>` | `[]` |
93
+ | rowProps | 传递给内部 `v-row` 的属性 | `Object` | `{}` |
94
+
95
+ ### FieldConfig 字段配置
96
+
97
+ | 参数 | 说明 | 类型 | 默认值 |
98
+ |------|------|------|--------|
99
+ | key | 字段唯一标识 | `String` | - |
100
+ | label | 字段标签 | `String` | - |
101
+ | type | 字段类型 | `String` | `'text'` |
102
+ | placeholder | 占位符 | `String` | - |
103
+ | required | 是否必填 | `Boolean` | `false` |
104
+ | rules | 验证规则 | `Array \| String` | - |
105
+ | defaultValue | 默认值 | `Any` | - |
106
+ | cols | 响应式列宽配置 | `Number \| Object` | - |
107
+ | visible | 是否可见 | `Boolean \| Function` | `true` |
108
+ | disabled | 是否禁用 | `Boolean \| Function` | `false` |
109
+ | readonly | 是否只读 | `Boolean \| Function` | `false` |
110
+ | tooltip | 提示信息 | `String` | - |
111
+ | extra | 额外提示信息 | `String` | - |
112
+ | dependencies | 依赖字段数组 | `Array<String>` | - |
113
+ | onDependencyChange | 依赖变化回调 | `Function` | - |
114
+ | options | 选项数据 | `Array \| Function` | - |
115
+ | layout | 字段布局(覆盖全局) | `String` | - |
116
+ | labelWidth | 标签宽度(覆盖全局) | `Number \| String` | - |
117
+ | labelAlign | 标签对齐(覆盖全局) | `String` | - |
118
+
119
+ ### 字段类型 (type)
120
+
121
+ - **text** - 文本输入框
122
+ - **textarea** - 文本域
123
+ - **number** - 数字输入框
124
+ - **select** - 下拉选择框
125
+ - **autocomplete** - 自动完成
126
+ - **date** - 日期选择器
127
+ - **time** - 时间选择器
128
+ - **color** - 颜色选择器
129
+ - **slider** - 数值滑块
130
+ - **range-slider** - 区间滑块
131
+ - **switch** - 开关
132
+ - **checkbox** - 复选框
133
+ - **radio** - 单选按钮组
134
+ - **slot** - 自定义插槽
135
+ - **group** - 分组标题
136
+
137
+ ### Events
138
+
139
+ | 事件名 | 说明 | 回调参数 |
140
+ |--------|------|----------|
141
+ | input | 值变化(v-model) | `(values: Object)` |
142
+ | field-input | 字段输入 | `{ key, value, values }` |
143
+ | field-change | 字段改变 | `{ key, value, values }` |
144
+ | field-blur | 字段失焦 | `{ key, value, values }` |
145
+ | dependency-change | 依赖字段变化 | `{ key, value, oldValue, values }` |
146
+ | field-dependency-change | 字段依赖变化 | `{ field, dependency, value, oldValue, values }` |
147
+ | reset | 重置 | `(values: Object)` |
148
+
149
+ ### Methods
150
+
151
+ | 方法名 | 说明 | 参数 | 返回值 |
152
+ |--------|------|------|--------|
153
+ | getValues | 获取所有字段值 | - | `Object` |
154
+ | setFieldsValue | 设置多个字段值 | `(values: Object)` | - |
155
+ | setFieldValue | 设置单个字段值 | `(key: String, value: Any)` | - |
156
+ | resetFields | 重置所有字段 | - | - |
157
+
158
+ ### Slots
159
+
160
+ | 插槽名 | 说明 | 参数 |
161
+ |--------|------|------|
162
+ | title | 自定义标题 | - |
163
+ | footer | 底部内容 | `{ values }` |
164
+ | field-{key} | 自定义字段(type='slot') | `{ field, value, values, updateField }` |
165
+
166
+ ## 🎨 拓展字段类型示例
167
+
168
+ ```js
169
+ fields: [
170
+ {
171
+ key: 'themeColor',
172
+ label: '主题色',
173
+ type: 'color',
174
+ defaultValue: '#4caf50',
175
+ pickerProps: { mode: 'hexa' }, // 透传到 v-color-picker
176
+ },
177
+ {
178
+ key: 'opacity',
179
+ label: '透明度',
180
+ type: 'slider',
181
+ min: 0,
182
+ max: 100,
183
+ step: 5,
184
+ thumbLabel: true,
185
+ },
186
+ {
187
+ key: 'priceRange',
188
+ label: '价格区间',
189
+ type: 'range-slider',
190
+ min: 0,
191
+ max: 1000,
192
+ step: 10,
193
+ defaultValue: [100, 600],
194
+ },
195
+ ];
196
+ ```
197
+
198
+ > 📌 `type='color'` 会自动在文本框内显示颜色块,可用 `pickerProps` 调整 `v-color-picker`。滑块类字段支持 `min/max/step/thumbLabel/ticks` 等常用参数,也可通过 `field.props` 继续透传到对应 Vuetify 组件。
199
+
200
+ ## 🎯 核心特性详解
201
+
202
+ ### 1. 字段依赖 (ProFormDependency)
203
+
204
+ 字段依赖是 JhFormFields 的核心特性,类似于 Ant Design ProComponents 的 ProFormDependency。
205
+
206
+ #### 基础依赖
207
+
208
+ ```javascript
209
+ fields: [
210
+ {
211
+ key: 'userType',
212
+ label: '用户类型',
213
+ type: 'radio',
214
+ options: [
215
+ { text: '个人用户', value: 'personal' },
216
+ { text: '企业用户', value: 'company' },
217
+ ],
218
+ },
219
+ {
220
+ key: 'personalName',
221
+ label: '真实姓名',
222
+ type: 'text',
223
+ // 根据 userType 动态显示
224
+ visible: (values) => values.userType === 'personal',
225
+ dependencies: ['userType'],
226
+ },
227
+ {
228
+ key: 'companyName',
229
+ label: '公司名称',
230
+ type: 'text',
231
+ visible: (values) => values.userType === 'company',
232
+ dependencies: ['userType'],
233
+ },
234
+ ]
235
+ ```
236
+
237
+ #### 多字段依赖
238
+
239
+ ```javascript
240
+ {
241
+ key: 'discountAmount',
242
+ label: '优惠金额',
243
+ type: 'number',
244
+ // 依赖多个字段
245
+ visible: (values) => values.hasDiscount && values.discountType === 'fixed',
246
+ dependencies: ['hasDiscount', 'discountType'],
247
+ }
248
+ ```
249
+
250
+ #### 动态选项
251
+
252
+ ```javascript
253
+ {
254
+ key: 'province',
255
+ label: '省份',
256
+ type: 'select',
257
+ // 根据国家动态生成省份选项
258
+ options: (values) => {
259
+ const provinceMap = {
260
+ china: [
261
+ { text: '北京', value: 'beijing' },
262
+ { text: '上海', value: 'shanghai' },
263
+ ],
264
+ usa: [
265
+ { text: '加利福尼亚', value: 'california' },
266
+ { text: '纽约', value: 'newyork' },
267
+ ],
268
+ };
269
+ return provinceMap[values.country] || [];
270
+ },
271
+ dependencies: ['country'],
272
+ }
273
+ ```
274
+
275
+ #### 动态禁用
276
+
277
+ ```javascript
278
+ {
279
+ key: 'username',
280
+ label: '用户名',
281
+ type: 'text',
282
+ // 根据条件动态禁用
283
+ disabled: (values) => !values.agreeTerms,
284
+ dependencies: ['agreeTerms'],
285
+ }
286
+ ```
287
+
288
+ ### 2. 依赖变化回调
289
+
290
+ ```javascript
291
+ {
292
+ key: 'province',
293
+ label: '省份',
294
+ type: 'select',
295
+ dependencies: ['country'],
296
+ // 当依赖字段变化时触发
297
+ onDependencyChange: (depKey, newVal, oldVal, values) => {
298
+ console.log(`${depKey} 从 ${oldVal} 变为 ${newVal}`);
299
+ // 可以在这里执行额外的逻辑
300
+ },
301
+ }
302
+ ```
303
+
304
+ ### 3. 全局依赖监听
305
+
306
+ ```vue
307
+ <JhFormFields
308
+ v-model="formData"
309
+ :fields="fields"
310
+ :dependencies="['country', 'userType']"
311
+ @dependency-change="handleDependencyChange"
312
+ />
313
+ ```
314
+
315
+ ```javascript
316
+ methods: {
317
+ handleDependencyChange({ key, value, oldValue, values }) {
318
+ console.log(`依赖字段 ${key} 变化:`, value);
319
+ // 执行全局依赖逻辑
320
+ },
321
+ }
322
+ ```
323
+
324
+ ## 🎨 使用示例
325
+
326
+ ### 1. 基础用法
327
+
328
+ ```vue
329
+ <JhFormFields
330
+ v-model="formData"
331
+ :fields="fields"
332
+ title="基本信息"
333
+ description="请填写您的基本信息"
334
+ />
335
+ ```
336
+
337
+ ### 2. 水平布局
338
+
339
+ ```vue
340
+ <JhFormFields
341
+ v-model="formData"
342
+ :fields="fields"
343
+ layout="horizontal"
344
+ :labelWidth="100"
345
+ labelAlign="right"
346
+ :defaultColsMd="12"
347
+ />
348
+ ```
349
+
350
+ ### 3. 行内布局(搜索表单)
351
+
352
+ ```vue
353
+ <JhFormFields
354
+ v-model="formData"
355
+ :fields="searchFields"
356
+ layout="inline"
357
+ >
358
+ <template #footer>
359
+ <v-btn color="primary">搜索</v-btn>
360
+ <v-btn text>重置</v-btn>
361
+ </template>
362
+ </JhFormFields>
363
+ ```
364
+
365
+ ### 4. 字段分组
366
+
367
+ ```javascript
368
+ fields: [
369
+ { type: 'group', title: '基本信息' },
370
+ { key: 'username', label: '用户名', type: 'text' },
371
+ { key: 'email', label: '邮箱', type: 'text' },
372
+
373
+ { type: 'group', title: '联系方式', divider: true, description: '请填写您的联系方式' },
374
+ { key: 'phone', label: '手机号', type: 'text' },
375
+ { key: 'address', label: '地址', type: 'textarea', cols: { md: 12 } },
376
+ ]
377
+ ```
378
+
379
+ ### 5. 带边框样式
380
+
381
+ ```vue
382
+ <JhFormFields
383
+ v-model="formData"
384
+ :fields="fields"
385
+ title="基本信息"
386
+ bordered
387
+ />
388
+ ```
389
+
390
+ ### 6. 只读模式
391
+
392
+ ```vue
393
+ <JhFormFields
394
+ v-model="formData"
395
+ :fields="fields"
396
+ title="用户详情"
397
+ readonly
398
+ />
399
+ ```
400
+
401
+ ### 7. 自定义字段插槽
402
+
403
+ ```vue
404
+ <JhFormFields v-model="formData" :fields="fields">
405
+ <template #field-rating="{ value, updateField }">
406
+ <v-rating
407
+ :value="value"
408
+ @input="updateField('rating', $event)"
409
+ color="warning"
410
+ />
411
+ </template>
412
+
413
+ <template #field-color="{ value, updateField }">
414
+ <v-color-picker
415
+ :value="value"
416
+ @input="updateField('color', $event)"
417
+ />
418
+ </template>
419
+ </JhFormFields>
420
+ ```
421
+
422
+ ```javascript
423
+ fields: [
424
+ {
425
+ key: 'rating',
426
+ label: '评分',
427
+ type: 'slot',
428
+ defaultValue: 3,
429
+ },
430
+ {
431
+ key: 'color',
432
+ label: '颜色',
433
+ type: 'slot',
434
+ defaultValue: '#1976D2',
435
+ },
436
+ ]
437
+ ```
438
+
439
+ ### 8. 响应式布局
440
+
441
+ ```javascript
442
+ fields: [
443
+ {
444
+ key: 'field1',
445
+ label: '字段1',
446
+ type: 'text',
447
+ cols: {
448
+ xs: 12, // 手机端全宽
449
+ sm: 6, // 平板端半宽
450
+ md: 4, // 桌面端1/3宽
451
+ lg: 3, // 大屏1/4宽
452
+ },
453
+ },
454
+ ]
455
+ ```
456
+
457
+ ## 🔧 在 JhForm 中使用
458
+
459
+ JhFormFields 可以在 JhForm 中组合使用,实现更灵活的表单布局:
460
+
461
+ ```vue
462
+ <template>
463
+ <v-form>
464
+ <!-- 基本信息字段集 -->
465
+ <JhFormFields
466
+ v-model="formData"
467
+ :fields="basicFields"
468
+ title="基本信息"
469
+ bordered
470
+ />
471
+
472
+ <!-- 用户类型字段集 -->
473
+ <JhFormFields
474
+ v-model="formData"
475
+ :fields="typeFields"
476
+ title="用户类型"
477
+ bordered
478
+ class="mt-4"
479
+ />
480
+
481
+ <!-- 联系方式字段集 -->
482
+ <JhFormFields
483
+ v-model="formData"
484
+ :fields="contactFields"
485
+ title="联系方式"
486
+ bordered
487
+ class="mt-4"
488
+ />
489
+
490
+ <!-- 提交按钮 -->
491
+ <v-row class="mt-4">
492
+ <v-col cols="12" class="text-right">
493
+ <v-btn class="mr-2" @click="resetForm">重置</v-btn>
494
+ <v-btn color="primary" @click="submitForm">提交</v-btn>
495
+ </v-col>
496
+ </v-row>
497
+ </v-form>
498
+ </template>
499
+
500
+ <script>
501
+ export default {
502
+ data() {
503
+ return {
504
+ formData: {},
505
+ basicFields: [
506
+ { key: 'username', label: '用户名', type: 'text', required: true },
507
+ { key: 'email', label: '邮箱', type: 'text', rules: 'email' },
508
+ ],
509
+ typeFields: [
510
+ {
511
+ key: 'userType',
512
+ label: '用户类型',
513
+ type: 'radio',
514
+ options: [
515
+ { text: '个人用户', value: 'personal' },
516
+ { text: '企业用户', value: 'company' },
517
+ ],
518
+ },
519
+ {
520
+ key: 'personalName',
521
+ label: '真实姓名',
522
+ type: 'text',
523
+ visible: (values) => values.userType === 'personal',
524
+ dependencies: ['userType'],
525
+ },
526
+ ],
527
+ contactFields: [
528
+ { key: 'phone', label: '手机号', type: 'text', rules: 'phone' },
529
+ { key: 'address', label: '地址', type: 'textarea', cols: { md: 12 } },
530
+ ],
531
+ };
532
+ },
533
+ methods: {
534
+ submitForm() {
535
+ console.log('提交数据:', this.formData);
536
+ },
537
+ resetForm() {
538
+ this.formData = {};
539
+ },
540
+ },
541
+ };
542
+ </script>
543
+ ```
544
+
545
+ ## 💡 高级用法
546
+
547
+ ### 复杂联动示例
548
+
549
+ ```javascript
550
+ fields: [
551
+ {
552
+ key: 'productType',
553
+ label: '商品类型',
554
+ type: 'radio',
555
+ options: [
556
+ { text: '实物商品', value: 'physical' },
557
+ { text: '虚拟商品', value: 'virtual' },
558
+ { text: '服务商品', value: 'service' },
559
+ ],
560
+ },
561
+ {
562
+ key: 'weight',
563
+ label: '重量(kg)',
564
+ type: 'number',
565
+ visible: (values) => values.productType === 'physical',
566
+ dependencies: ['productType'],
567
+ },
568
+ {
569
+ key: 'downloadUrl',
570
+ label: '下载链接',
571
+ type: 'text',
572
+ visible: (values) => values.productType === 'virtual',
573
+ dependencies: ['productType'],
574
+ },
575
+ {
576
+ key: 'serviceTime',
577
+ label: '服务时长(小时)',
578
+ type: 'number',
579
+ visible: (values) => values.productType === 'service',
580
+ dependencies: ['productType'],
581
+ },
582
+ { type: 'group', title: '优惠设置', divider: true },
583
+ {
584
+ key: 'hasDiscount',
585
+ label: '启用优惠',
586
+ type: 'checkbox',
587
+ checkboxLabel: '启用优惠价格',
588
+ },
589
+ {
590
+ key: 'discountType',
591
+ label: '优惠类型',
592
+ type: 'radio',
593
+ options: [
594
+ { text: '固定金额', value: 'fixed' },
595
+ { text: '百分比', value: 'percent' },
596
+ ],
597
+ visible: (values) => values.hasDiscount,
598
+ dependencies: ['hasDiscount'],
599
+ },
600
+ {
601
+ key: 'discountAmount',
602
+ label: '优惠金额',
603
+ type: 'number',
604
+ visible: (values) => values.hasDiscount && values.discountType === 'fixed',
605
+ dependencies: ['hasDiscount', 'discountType'],
606
+ },
607
+ {
608
+ key: 'discountPercent',
609
+ label: '优惠百分比',
610
+ type: 'number',
611
+ suffix: '%',
612
+ visible: (values) => values.hasDiscount && values.discountType === 'percent',
613
+ dependencies: ['hasDiscount', 'discountType'],
614
+ },
615
+ ]
616
+ ```
617
+
618
+ ## 🎯 最佳实践
619
+
620
+ 1. **合理使用字段依赖** - 使用 `dependencies` 数组明确声明字段间的依赖关系
621
+ 2. **避免循环依赖** - 确保字段依赖关系不形成循环
622
+ 3. **使用字段分组** - 将相关字段分组,提高表单可读性
623
+ 4. **动态选项优化** - 使用函数动态生成选项时,注意性能优化
624
+ 5. **边框样式** - 使用 `bordered` 属性区分不同的字段集
625
+ 6. **组合使用** - 在复杂表单中,使用多个 JhFormFields 组合
626
+ 7. **响应式设计** - 使用 `cols` 配置实现响应式布局
627
+ 8. **只读模式** - 详情页面使用只读模式展示数据
628
+
629
+ ## 🔗 与 ProComponents 的对应关系
630
+
631
+ | ProComponents | JhFormFields | 说明 |
632
+ |---------------|--------------|------|
633
+ | ProFormFieldSet | JhFormFields | 字段集组件 |
634
+ | ProFormDependency | dependencies + visible/disabled | 字段依赖 |
635
+ | fieldProps | props | 字段属性 |
636
+ | dependencies | dependencies | 依赖字段数组 |
637
+ | transform | - | 暂不支持 |
638
+
639
+ ## 📚 相关组件
640
+
641
+ - [JhForm](../JhForm) - 高级表单组件
642
+ - [JhFormList](../JhFormList) - 动态表单列表
643
+ - [JhTable](../JhTable) - 高级表格
644
+
645
+ ## 📄 License
646
+
647
+ MIT