@agile-team/wl-skills-kit 2.11.1 → 2.11.3

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 (91) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +38 -21
  3. package/bin/wl-skills.js +27 -3
  4. package/files/.wl-skills/docs/jh-pagination.md +505 -505
  5. package/files/.wl-skills/docs/request.md +940 -940
  6. package/files/.wl-skills/docs/validate-exempt.md +113 -0
  7. package/files/.wl-skills/guides/architecture.md +1 -1
  8. package/files/.wl-skills/skills/_compat/headers/cursor-mdc.txt +1 -1
  9. package/files/.wl-skills/skills/_compat/headers/kiro.txt +1 -1
  10. package/files/.wl-skills/skills/_compat/headers/trae.txt +1 -1
  11. package/files/.wl-skills/skills/core/convention-audit/SKILL.md +3 -3
  12. package/files/.wl-skills/skills/core/spec-doc-parse/SKILL.md +332 -332
  13. package/files/.wl-skills/skills/core/spec-doc-parse/USAGE.md +97 -97
  14. package/files/.wl-skills/skills/sync/permission-sync/USAGE.md +107 -107
  15. package/files/.wl-skills/src/components/global/C_ParentView/index.vue +3 -3
  16. package/files/.wl-skills/src/components/global/C_RightToolbar/index.vue +157 -157
  17. package/files/.wl-skills/src/components/global/C_SvgIcon/index.vue +31 -31
  18. package/files/.wl-skills/src/components/global/C_SvgIcon/svgicon.js +10 -10
  19. package/files/.wl-skills/src/components/global/C_TagStatus/README.md +264 -264
  20. package/files/.wl-skills/src/components/global/C_TagStatus/config.ts +192 -192
  21. package/files/.wl-skills/src/components/global/C_TagStatus/index.vue +106 -106
  22. package/files/.wl-skills/src/components/global/C_TagStatus/types.ts +64 -64
  23. package/files/.wl-skills/src/components/global/C_Tree/README.md +153 -153
  24. package/files/.wl-skills/src/components/global/C_Tree/index.scss +42 -42
  25. package/files/.wl-skills/src/components/global/C_Tree/index.vue +78 -78
  26. package/files/.wl-skills/src/components/global/C_Tree/types.ts +59 -59
  27. package/files/.wl-skills/src/components/local/c_formModal/README.md +235 -235
  28. package/files/.wl-skills/src/components/local/c_formModal/data.ts +95 -95
  29. package/files/.wl-skills/src/components/local/c_formModal/index.scss +8 -8
  30. package/files/.wl-skills/src/components/local/c_formModal/index.vue +107 -107
  31. package/files/.wl-skills/src/components/local/c_formSections/data.ts +175 -175
  32. package/files/.wl-skills/src/components/local/c_formSections/index.scss +280 -280
  33. package/files/.wl-skills/src/components/local/c_formSections/index.vue +429 -429
  34. package/files/.wl-skills/src/components/local/c_listModal/data.ts +41 -41
  35. package/files/.wl-skills/src/components/local/c_listModal/index.vue +136 -136
  36. package/files/.wl-skills/src/components/local/c_spliterTitle/index.scss +25 -25
  37. package/files/.wl-skills/src/components/local/c_spliterTitle/index.vue +21 -21
  38. package/files/.wl-skills/src/components/remote/AGGrid/README.md +530 -530
  39. package/files/.wl-skills/src/components/remote/BaseForm/README.md +508 -508
  40. package/files/.wl-skills/src/components/remote/BaseQuery/README.md +865 -865
  41. package/files/.wl-skills/src/components/remote/BaseTable/README.md +941 -941
  42. package/files/.wl-skills/src/components/remote/BaseToolbar/README.md +496 -496
  43. package/files/.wl-skills/src/types/page.ts +24 -24
  44. package/files/.wl-skills/standards/04-coding-basics.md +39 -1
  45. package/files/.wl-skills/standards/09-typescript.md +26 -3
  46. package/files/.wl-skills/standards/12-base-table.md +56 -4
  47. package/files/.wl-skills/standards/13-platform-components.md +1 -0
  48. package/files/.wl-skills/standards/index.md +2 -2
  49. package/files/.wl-skills/templates/README.md +44 -44
  50. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/api.md +54 -54
  51. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/data.ts +346 -346
  52. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/index.scss +1 -1
  53. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/index.vue +28 -28
  54. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/data.ts +115 -115
  55. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/index.scss +44 -44
  56. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/index.vue +43 -43
  57. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/data.ts +338 -338
  58. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/index.scss +1 -1
  59. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/index.vue +28 -28
  60. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/data.ts +115 -115
  61. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/index.scss +44 -44
  62. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/index.vue +43 -43
  63. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/api.md +88 -88
  64. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/data.ts +601 -601
  65. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/index.scss +1 -1
  66. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/index.vue +64 -64
  67. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/api.md +67 -67
  68. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/data.ts +286 -286
  69. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/index.scss +139 -139
  70. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/index.vue +318 -318
  71. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/api.md +98 -98
  72. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/data.ts +543 -543
  73. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/index.scss +1 -1
  74. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/index.vue +52 -52
  75. package/files/.wl-skills/templates/sale/demo/add-demo/data.ts +518 -518
  76. package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/data.ts +524 -524
  77. package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/index.scss +154 -154
  78. package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/index.vue +117 -117
  79. package/files/.wl-skills/templates/sale/demo/domestic-trade-order/data.ts +308 -308
  80. package/files/.wl-skills/templates/sale/demo/domestic-trade-order/index.scss +99 -99
  81. package/files/.wl-skills/templates/sale/demo/domestic-trade-order/index.vue +77 -77
  82. package/files/.wl-skills/templates/sale/demo/heat-batch-return/data.ts +367 -367
  83. package/files/.wl-skills/templates/sale/demo/heat-batch-return/index.scss +100 -100
  84. package/files/.wl-skills/templates/sale/demo/heat-batch-return/index.vue +170 -170
  85. package/files/.wl-skills/templates/sale/demo/heat-batch-return/meltDialog.vue +320 -320
  86. package/files/.wl-skills/templates/sale/demo/metallurgical-spec/data.ts +824 -824
  87. package/lib/ast-rules.js +395 -12
  88. package/mcp/config.js +46 -46
  89. package/mcp/registry.js +6 -1
  90. package/mcp/tools/projectTools.js +9 -1
  91. package/package.json +2 -2
@@ -1,508 +1,508 @@
1
- # BaseForm 表单组件
2
-
3
- > 来源:`@jhlc/common-core` 远程组件
4
-
5
- BaseForm 是一个功能强大的表单组件,支持多列布局、数据验证、逻辑数据类型、自定义组件等功能。适用于新增、编辑场景。
6
-
7
- ## 📦 导入方式
8
-
9
- ```typescript
10
- // 全局注册(已在项目中配置)
11
- // 直接使用 <BaseForm /> 即可
12
-
13
- // 类型导入
14
- import type { BaseFormItemDesc } from "@jhlc/common-core/.wl-skills/src/components/form/common/type";
15
- ```
16
-
17
- ## 🚀 基本用法
18
-
19
- ```vue
20
- <template>
21
- <BaseForm
22
- ref="formRef"
23
- :form="form"
24
- :items="formItems"
25
- :columns="2"
26
- label-width="100px"
27
- />
28
- </template>
29
-
30
- <script setup lang="ts">
31
- import { ref, reactive, computed } from "vue";
32
-
33
- const formRef = ref();
34
- const form = reactive({
35
- userName: "",
36
- phone: "",
37
- userType: ""
38
- });
39
-
40
- const formItems = computed(() => [
41
- {
42
- name: "userName",
43
- label: "用户名",
44
- required: true,
45
- placeholder: "请输入用户名"
46
- },
47
- {
48
- name: "phone",
49
- label: "手机号",
50
- placeholder: "请输入手机号"
51
- },
52
- {
53
- name: "userType",
54
- label: "用户类型",
55
- logicType: "dict",
56
- logicValue: "USER_TYPE"
57
- }
58
- ]);
59
- </script>
60
- ```
61
-
62
- ---
63
-
64
- ## 📋 Props 属性
65
-
66
- | 属性名 | 类型 | 默认值 | 说明 |
67
- | ------------ | ------------------------------ | --------- | ---------------- |
68
- | `form` | `Object` | - | 表单数据对象 |
69
- | `items` | `BaseFormItemDesc[]` | `[]` | 表单项配置数组 |
70
- | `columns` | `number` | - | 列数 |
71
- | `labelWidth` | `string` | - | 标签宽度 |
72
- | `size` | `'default' \| 'large' \| 'small'` | - | 表单尺寸 |
73
- | `disabled` | `boolean` | `false` | 是否禁用 |
74
- | `isViewer` | `boolean` | `false` | 是否查看模式 |
75
- | `noForm` | `boolean` | `false` | 不使用 form 包裹 |
76
- | `style` | `string \| Object` | - | 自定义样式 |
77
- | `classnames` | `Array \| string` | - | 自定义类名 |
78
-
79
- ---
80
-
81
- ## 📋 Expose 方法 (通过 ref 调用)
82
-
83
- | 方法名 | 参数 | 返回值 | 说明 |
84
- | ----------------- | --------------------------- | ------ | -------------- |
85
- | `validate` | `cb: (valid: boolean) => void` | - | 验证表单 |
86
- | `setDefaultValue` | - | - | 设置默认值 |
87
- | `reset` | - | - | 重置表单 |
88
- | `resetFields` | - | - | 重置表单字段 |
89
-
90
- ---
91
-
92
- ## 📋 表单项配置 BaseFormItemDesc
93
-
94
- ### 基础属性
95
-
96
- ```typescript
97
- interface BaseFormItemDesc<T = any> {
98
- // 字段名(绑定 form 对象的属性名)
99
- name?: string;
100
- // 标签文本
101
- label?: string;
102
- // 标签宽度
103
- labelWidth?: string;
104
- // 显示冒号
105
- showColon?: boolean;
106
- // 占位提示
107
- placeholder?: string;
108
- // 栅格数(24 格布局)
109
- span?: number;
110
- // 是否禁用
111
- disabled?: boolean | ((form: T) => boolean);
112
- // 是否可清空
113
- clearable?: boolean;
114
- // 是否显示
115
- show?: boolean | ((form: T) => boolean);
116
- }
117
- ```
118
-
119
- ### 校验规则
120
-
121
- ```typescript
122
- {
123
- name: "userName",
124
- label: "用户名",
125
- // 必填
126
- required: true,
127
- // 或使用函数动态判断
128
- required: (form) => form.userType === "admin",
129
- // 校验提示
130
- message: "请输入用户名",
131
- // 自定义校验规则
132
- rules: [
133
- { required: true, message: "请输入用户名", trigger: "blur" },
134
- { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
135
- {
136
- pattern: /^[a-zA-Z0-9_]+$/,
137
- message: "只能包含字母、数字和下划线",
138
- trigger: "blur"
139
- },
140
- {
141
- validator: (rule, value, callback) => {
142
- if (value === "admin") {
143
- callback(new Error("不能使用 admin 作为用户名"));
144
- } else {
145
- callback();
146
- }
147
- },
148
- trigger: "blur"
149
- }
150
- ]
151
- }
152
- ```
153
-
154
- ### 逻辑数据类型
155
-
156
- 组件会根据 `logicType` 自动选择合适的表单控件:
157
-
158
- ```typescript
159
- {
160
- name: "status",
161
- label: "状态",
162
- // 字典类型 - 自动渲染为下拉选择
163
- logicType: "dict",
164
- logicValue: "ORDER_STATUS"
165
- }
166
-
167
- {
168
- name: "createTime",
169
- label: "创建时间",
170
- // 日期类型 - 自动渲染为日期选择器
171
- logicType: "date"
172
- }
173
-
174
- {
175
- name: "createDatetime",
176
- label: "创建时间",
177
- // 日期时间类型
178
- logicType: "datetime"
179
- }
180
-
181
- {
182
- name: "amount",
183
- label: "金额",
184
- // 数字类型 - 自动渲染为数字输入框
185
- logicType: "number"
186
- }
187
-
188
- {
189
- name: "isActive",
190
- label: "是否启用",
191
- // 布尔类型 - 自动渲染为开关
192
- logicType: "boolean"
193
- }
194
-
195
- {
196
- name: "userId",
197
- label: "负责人",
198
- // 用户类型 - 自动渲染为用户选择器
199
- logicType: "user"
200
- }
201
-
202
- {
203
- name: "deptId",
204
- label: "部门",
205
- // 部门类型 - 自动渲染为部门选择器
206
- logicType: "dept"
207
- }
208
-
209
- {
210
- name: "remark",
211
- label: "备注",
212
- // 多行文本
213
- logicType: "textarea"
214
- }
215
- ```
216
-
217
- ### 默认值配置
218
-
219
- ```typescript
220
- {
221
- name: "createTime",
222
- label: "创建时间",
223
- logicType: "date",
224
- // 支持多种默认值类型
225
- defaultValue: "currentDay" // 当天
226
- // defaultValue: "currentMonth" // 当月
227
- // defaultValue: "currentYear" // 当年
228
- }
229
-
230
- // 日期范围默认值
231
- {
232
- type: "range",
233
- name: "dateRange",
234
- startName: "startDate",
235
- endName: "endDate",
236
- logicType: "date",
237
- defaultValue: "recentDay7" // 最近 7 天
238
- // defaultValue: "recentDay30" // 最近 30 天
239
- // defaultValue: "rangeDayCurrentMonth1ToToday" // 当月1号到今天
240
- }
241
- ```
242
-
243
- **支持的默认值类型:**
244
-
245
- | 值 | 说明 |
246
- | ------------------------------- | ----------------------- |
247
- | `currentDay` | 当天 (2024-09-22) |
248
- | `currentMonth` | 当月 (2024-09) |
249
- | `currentYear` | 当年 (2024) |
250
- | `currentDept` | 当前部门 |
251
- | `recentDay3` | 最近 3 天 |
252
- | `recentDay7` | 最近 7 天 |
253
- | `recentDay30` | 最近 30 天 |
254
- | `rangeDatetimeToday` | 当天 0 点到 23 点 |
255
- | `rangeDayCurrentMonth1ToToday` | 当月 1 号到今天 |
256
- | `rangeDayCurrentMonth1ToLastDay`| 当月 1 号到月末 |
257
-
258
- ### 范围输入
259
-
260
- ```typescript
261
- {
262
- type: "range",
263
- label: "日期范围",
264
- startName: "startDate",
265
- endName: "endDate",
266
- logicType: "date",
267
- rangeSeparator: "至",
268
- // 自定义起止表单项
269
- startFormItem: {
270
- placeholder: "开始日期"
271
- },
272
- endFormItem: {
273
- placeholder: "结束日期"
274
- }
275
- }
276
- ```
277
-
278
- ### 自定义组件
279
-
280
- ```typescript
281
- import { h } from "vue";
282
-
283
- // 方式一:使用 component
284
- {
285
- name: "color",
286
- label: "颜色",
287
- component: (form) => ({
288
- tag: "el-color-picker",
289
- props: { showAlpha: true }
290
- })
291
- }
292
-
293
- // 方式二:使用 componentVNode
294
- {
295
- name: "custom",
296
- label: "自定义",
297
- componentVNode: (form) => {
298
- return h("div", { class: "custom-component" }, [
299
- h("span", form.custom),
300
- h("el-button", { onClick: () => {} }, "选择")
301
- ]);
302
- }
303
- }
304
-
305
- // 方式三:自定义属性
306
- {
307
- name: "amount",
308
- label: "金额",
309
- logicType: "number",
310
- customProps: (form) => ({
311
- min: 0,
312
- max: 10000,
313
- precision: 2,
314
- step: 100
315
- })
316
- }
317
- ```
318
-
319
- ---
320
-
321
- ## 💡 完整示例
322
-
323
- ### 基础表单
324
-
325
- ```vue
326
- <template>
327
- <el-card>
328
- <BaseForm
329
- ref="formRef"
330
- :form="form"
331
- :items="formItems"
332
- :columns="2"
333
- label-width="100px"
334
- />
335
- <div class="form-footer">
336
- <el-button type="primary" @click="handleSubmit">提交</el-button>
337
- <el-button @click="handleReset">重置</el-button>
338
- </div>
339
- </el-card>
340
- </template>
341
-
342
- <script setup lang="ts">
343
- import { ref, reactive, computed } from "vue";
344
- import type { BaseFormItemDesc } from "@jhlc/common-core/.wl-skills/src/components/form/common/type";
345
-
346
- const formRef = ref();
347
-
348
- const form = reactive({
349
- orderNo: "",
350
- customerName: "",
351
- amount: 0,
352
- orderDate: "",
353
- status: "",
354
- remark: ""
355
- });
356
-
357
- const formItems = computed<BaseFormItemDesc[]>(() => [
358
- {
359
- name: "orderNo",
360
- label: "订单号",
361
- required: true,
362
- placeholder: "请输入订单号"
363
- },
364
- {
365
- name: "customerName",
366
- label: "客户名称",
367
- required: true,
368
- placeholder: "请输入客户名称"
369
- },
370
- {
371
- name: "amount",
372
- label: "订单金额",
373
- logicType: "number",
374
- required: true,
375
- customProps: () => ({
376
- min: 0,
377
- precision: 2
378
- })
379
- },
380
- {
381
- name: "orderDate",
382
- label: "订单日期",
383
- logicType: "date",
384
- required: true
385
- },
386
- {
387
- name: "status",
388
- label: "订单状态",
389
- logicType: "dict",
390
- logicValue: "ORDER_STATUS"
391
- },
392
- {
393
- name: "remark",
394
- label: "备注",
395
- logicType: "textarea",
396
- span: 24
397
- }
398
- ]);
399
-
400
- const handleSubmit = () => {
401
- formRef.value?.validate((valid) => {
402
- if (valid) {
403
- console.log("表单数据:", form);
404
- // 提交逻辑
405
- }
406
- });
407
- };
408
-
409
- const handleReset = () => {
410
- formRef.value?.resetFields();
411
- };
412
- </script>
413
- ```
414
-
415
- ### 动态表单
416
-
417
- ```vue
418
- <template>
419
- <BaseForm
420
- ref="formRef"
421
- :form="form"
422
- :items="dynamicItems"
423
- :columns="2"
424
- label-width="100px"
425
- />
426
- </template>
427
-
428
- <script setup lang="ts">
429
- import { ref, reactive, computed } from "vue";
430
-
431
- const form = reactive({
432
- type: "person",
433
- name: "",
434
- idCard: "",
435
- companyName: "",
436
- businessLicense: ""
437
- });
438
-
439
- const dynamicItems = computed(() => {
440
- const baseItems = [
441
- {
442
- name: "type",
443
- label: "类型",
444
- logicType: "dict",
445
- logicValue: "CUSTOMER_TYPE"
446
- }
447
- ];
448
-
449
- // 根据类型动态显示不同字段
450
- if (form.type === "person") {
451
- return [
452
- ...baseItems,
453
- { name: "name", label: "姓名", required: true },
454
- { name: "idCard", label: "身份证号", required: true }
455
- ];
456
- } else {
457
- return [
458
- ...baseItems,
459
- { name: "companyName", label: "公司名称", required: true },
460
- { name: "businessLicense", label: "营业执照", required: true }
461
- ];
462
- }
463
- });
464
- </script>
465
- ```
466
-
467
- ---
468
-
469
- ## ⚠️ 注意事项
470
-
471
- 1. **字段名使用 `name` 而非 `prop`**
472
-
473
- ```typescript
474
- // ✅ 正确
475
- { name: "userName", label: "用户名" }
476
-
477
- // ❌ 错误
478
- { prop: "userName", label: "用户名" }
479
- ```
480
-
481
- 2. **logicType 会自动选择组件**
482
-
483
- - 不需要手动指定 `type: "select"`
484
- - 设置 `logicType: "dict"` 即可
485
-
486
- 3. **范围类型需要设置 startName 和 endName**
487
-
488
- ```typescript
489
- {
490
- type: "range",
491
- startName: "startDate",
492
- endName: "endDate",
493
- logicType: "date"
494
- }
495
- ```
496
-
497
- 4. **使用 computed 包装 items 实现响应式**
498
-
499
- ```typescript
500
- const formItems = computed(() => [...]);
501
- ```
502
-
503
- ---
504
-
505
- ## 📚 相关文档
506
-
507
- - [BaseQuery 查询组件](../BaseQuery/README.md)
508
- - [BaseTable 表格组件](../BaseTable/README.md)
1
+ # BaseForm 表单组件
2
+
3
+ > 来源:`@jhlc/common-core` 远程组件
4
+
5
+ BaseForm 是一个功能强大的表单组件,支持多列布局、数据验证、逻辑数据类型、自定义组件等功能。适用于新增、编辑场景。
6
+
7
+ ## 📦 导入方式
8
+
9
+ ```typescript
10
+ // 全局注册(已在项目中配置)
11
+ // 直接使用 <BaseForm /> 即可
12
+
13
+ // 类型导入
14
+ import type { BaseFormItemDesc } from "@jhlc/common-core/.wl-skills/src/components/form/common/type";
15
+ ```
16
+
17
+ ## 🚀 基本用法
18
+
19
+ ```vue
20
+ <template>
21
+ <BaseForm
22
+ ref="formRef"
23
+ :form="form"
24
+ :items="formItems"
25
+ :columns="2"
26
+ label-width="100px"
27
+ />
28
+ </template>
29
+
30
+ <script setup lang="ts">
31
+ import { ref, reactive, computed } from "vue";
32
+
33
+ const formRef = ref();
34
+ const form = reactive({
35
+ userName: "",
36
+ phone: "",
37
+ userType: ""
38
+ });
39
+
40
+ const formItems = computed(() => [
41
+ {
42
+ name: "userName",
43
+ label: "用户名",
44
+ required: true,
45
+ placeholder: "请输入用户名"
46
+ },
47
+ {
48
+ name: "phone",
49
+ label: "手机号",
50
+ placeholder: "请输入手机号"
51
+ },
52
+ {
53
+ name: "userType",
54
+ label: "用户类型",
55
+ logicType: "dict",
56
+ logicValue: "USER_TYPE"
57
+ }
58
+ ]);
59
+ </script>
60
+ ```
61
+
62
+ ---
63
+
64
+ ## 📋 Props 属性
65
+
66
+ | 属性名 | 类型 | 默认值 | 说明 |
67
+ | ------------ | ------------------------------ | --------- | ---------------- |
68
+ | `form` | `Object` | - | 表单数据对象 |
69
+ | `items` | `BaseFormItemDesc[]` | `[]` | 表单项配置数组 |
70
+ | `columns` | `number` | - | 列数 |
71
+ | `labelWidth` | `string` | - | 标签宽度 |
72
+ | `size` | `'default' \| 'large' \| 'small'` | - | 表单尺寸 |
73
+ | `disabled` | `boolean` | `false` | 是否禁用 |
74
+ | `isViewer` | `boolean` | `false` | 是否查看模式 |
75
+ | `noForm` | `boolean` | `false` | 不使用 form 包裹 |
76
+ | `style` | `string \| Object` | - | 自定义样式 |
77
+ | `classnames` | `Array \| string` | - | 自定义类名 |
78
+
79
+ ---
80
+
81
+ ## 📋 Expose 方法 (通过 ref 调用)
82
+
83
+ | 方法名 | 参数 | 返回值 | 说明 |
84
+ | ----------------- | --------------------------- | ------ | -------------- |
85
+ | `validate` | `cb: (valid: boolean) => void` | - | 验证表单 |
86
+ | `setDefaultValue` | - | - | 设置默认值 |
87
+ | `reset` | - | - | 重置表单 |
88
+ | `resetFields` | - | - | 重置表单字段 |
89
+
90
+ ---
91
+
92
+ ## 📋 表单项配置 BaseFormItemDesc
93
+
94
+ ### 基础属性
95
+
96
+ ```typescript
97
+ interface BaseFormItemDesc<T = any> {
98
+ // 字段名(绑定 form 对象的属性名)
99
+ name?: string;
100
+ // 标签文本
101
+ label?: string;
102
+ // 标签宽度
103
+ labelWidth?: string;
104
+ // 显示冒号
105
+ showColon?: boolean;
106
+ // 占位提示
107
+ placeholder?: string;
108
+ // 栅格数(24 格布局)
109
+ span?: number;
110
+ // 是否禁用
111
+ disabled?: boolean | ((form: T) => boolean);
112
+ // 是否可清空
113
+ clearable?: boolean;
114
+ // 是否显示
115
+ show?: boolean | ((form: T) => boolean);
116
+ }
117
+ ```
118
+
119
+ ### 校验规则
120
+
121
+ ```typescript
122
+ {
123
+ name: "userName",
124
+ label: "用户名",
125
+ // 必填
126
+ required: true,
127
+ // 或使用函数动态判断
128
+ required: (form) => form.userType === "admin",
129
+ // 校验提示
130
+ message: "请输入用户名",
131
+ // 自定义校验规则
132
+ rules: [
133
+ { required: true, message: "请输入用户名", trigger: "blur" },
134
+ { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
135
+ {
136
+ pattern: /^[a-zA-Z0-9_]+$/,
137
+ message: "只能包含字母、数字和下划线",
138
+ trigger: "blur"
139
+ },
140
+ {
141
+ validator: (rule, value, callback) => {
142
+ if (value === "admin") {
143
+ callback(new Error("不能使用 admin 作为用户名"));
144
+ } else {
145
+ callback();
146
+ }
147
+ },
148
+ trigger: "blur"
149
+ }
150
+ ]
151
+ }
152
+ ```
153
+
154
+ ### 逻辑数据类型
155
+
156
+ 组件会根据 `logicType` 自动选择合适的表单控件:
157
+
158
+ ```typescript
159
+ {
160
+ name: "status",
161
+ label: "状态",
162
+ // 字典类型 - 自动渲染为下拉选择
163
+ logicType: "dict",
164
+ logicValue: "ORDER_STATUS"
165
+ }
166
+
167
+ {
168
+ name: "createTime",
169
+ label: "创建时间",
170
+ // 日期类型 - 自动渲染为日期选择器
171
+ logicType: "date"
172
+ }
173
+
174
+ {
175
+ name: "createDatetime",
176
+ label: "创建时间",
177
+ // 日期时间类型
178
+ logicType: "datetime"
179
+ }
180
+
181
+ {
182
+ name: "amount",
183
+ label: "金额",
184
+ // 数字类型 - 自动渲染为数字输入框
185
+ logicType: "number"
186
+ }
187
+
188
+ {
189
+ name: "isActive",
190
+ label: "是否启用",
191
+ // 布尔类型 - 自动渲染为开关
192
+ logicType: "boolean"
193
+ }
194
+
195
+ {
196
+ name: "userId",
197
+ label: "负责人",
198
+ // 用户类型 - 自动渲染为用户选择器
199
+ logicType: "user"
200
+ }
201
+
202
+ {
203
+ name: "deptId",
204
+ label: "部门",
205
+ // 部门类型 - 自动渲染为部门选择器
206
+ logicType: "dept"
207
+ }
208
+
209
+ {
210
+ name: "remark",
211
+ label: "备注",
212
+ // 多行文本
213
+ logicType: "textarea"
214
+ }
215
+ ```
216
+
217
+ ### 默认值配置
218
+
219
+ ```typescript
220
+ {
221
+ name: "createTime",
222
+ label: "创建时间",
223
+ logicType: "date",
224
+ // 支持多种默认值类型
225
+ defaultValue: "currentDay" // 当天
226
+ // defaultValue: "currentMonth" // 当月
227
+ // defaultValue: "currentYear" // 当年
228
+ }
229
+
230
+ // 日期范围默认值
231
+ {
232
+ type: "range",
233
+ name: "dateRange",
234
+ startName: "startDate",
235
+ endName: "endDate",
236
+ logicType: "date",
237
+ defaultValue: "recentDay7" // 最近 7 天
238
+ // defaultValue: "recentDay30" // 最近 30 天
239
+ // defaultValue: "rangeDayCurrentMonth1ToToday" // 当月1号到今天
240
+ }
241
+ ```
242
+
243
+ **支持的默认值类型:**
244
+
245
+ | 值 | 说明 |
246
+ | ------------------------------- | ----------------------- |
247
+ | `currentDay` | 当天 (2024-09-22) |
248
+ | `currentMonth` | 当月 (2024-09) |
249
+ | `currentYear` | 当年 (2024) |
250
+ | `currentDept` | 当前部门 |
251
+ | `recentDay3` | 最近 3 天 |
252
+ | `recentDay7` | 最近 7 天 |
253
+ | `recentDay30` | 最近 30 天 |
254
+ | `rangeDatetimeToday` | 当天 0 点到 23 点 |
255
+ | `rangeDayCurrentMonth1ToToday` | 当月 1 号到今天 |
256
+ | `rangeDayCurrentMonth1ToLastDay`| 当月 1 号到月末 |
257
+
258
+ ### 范围输入
259
+
260
+ ```typescript
261
+ {
262
+ type: "range",
263
+ label: "日期范围",
264
+ startName: "startDate",
265
+ endName: "endDate",
266
+ logicType: "date",
267
+ rangeSeparator: "至",
268
+ // 自定义起止表单项
269
+ startFormItem: {
270
+ placeholder: "开始日期"
271
+ },
272
+ endFormItem: {
273
+ placeholder: "结束日期"
274
+ }
275
+ }
276
+ ```
277
+
278
+ ### 自定义组件
279
+
280
+ ```typescript
281
+ import { h } from "vue";
282
+
283
+ // 方式一:使用 component
284
+ {
285
+ name: "color",
286
+ label: "颜色",
287
+ component: (form) => ({
288
+ tag: "el-color-picker",
289
+ props: { showAlpha: true }
290
+ })
291
+ }
292
+
293
+ // 方式二:使用 componentVNode
294
+ {
295
+ name: "custom",
296
+ label: "自定义",
297
+ componentVNode: (form) => {
298
+ return h("div", { class: "custom-component" }, [
299
+ h("span", form.custom),
300
+ h("el-button", { onClick: () => {} }, "选择")
301
+ ]);
302
+ }
303
+ }
304
+
305
+ // 方式三:自定义属性
306
+ {
307
+ name: "amount",
308
+ label: "金额",
309
+ logicType: "number",
310
+ customProps: (form) => ({
311
+ min: 0,
312
+ max: 10000,
313
+ precision: 2,
314
+ step: 100
315
+ })
316
+ }
317
+ ```
318
+
319
+ ---
320
+
321
+ ## 💡 完整示例
322
+
323
+ ### 基础表单
324
+
325
+ ```vue
326
+ <template>
327
+ <el-card>
328
+ <BaseForm
329
+ ref="formRef"
330
+ :form="form"
331
+ :items="formItems"
332
+ :columns="2"
333
+ label-width="100px"
334
+ />
335
+ <div class="form-footer">
336
+ <el-button type="primary" @click="handleSubmit">提交</el-button>
337
+ <el-button @click="handleReset">重置</el-button>
338
+ </div>
339
+ </el-card>
340
+ </template>
341
+
342
+ <script setup lang="ts">
343
+ import { ref, reactive, computed } from "vue";
344
+ import type { BaseFormItemDesc } from "@jhlc/common-core/.wl-skills/src/components/form/common/type";
345
+
346
+ const formRef = ref();
347
+
348
+ const form = reactive({
349
+ orderNo: "",
350
+ customerName: "",
351
+ amount: 0,
352
+ orderDate: "",
353
+ status: "",
354
+ remark: ""
355
+ });
356
+
357
+ const formItems = computed<BaseFormItemDesc[]>(() => [
358
+ {
359
+ name: "orderNo",
360
+ label: "订单号",
361
+ required: true,
362
+ placeholder: "请输入订单号"
363
+ },
364
+ {
365
+ name: "customerName",
366
+ label: "客户名称",
367
+ required: true,
368
+ placeholder: "请输入客户名称"
369
+ },
370
+ {
371
+ name: "amount",
372
+ label: "订单金额",
373
+ logicType: "number",
374
+ required: true,
375
+ customProps: () => ({
376
+ min: 0,
377
+ precision: 2
378
+ })
379
+ },
380
+ {
381
+ name: "orderDate",
382
+ label: "订单日期",
383
+ logicType: "date",
384
+ required: true
385
+ },
386
+ {
387
+ name: "status",
388
+ label: "订单状态",
389
+ logicType: "dict",
390
+ logicValue: "ORDER_STATUS"
391
+ },
392
+ {
393
+ name: "remark",
394
+ label: "备注",
395
+ logicType: "textarea",
396
+ span: 24
397
+ }
398
+ ]);
399
+
400
+ const handleSubmit = () => {
401
+ formRef.value?.validate((valid) => {
402
+ if (valid) {
403
+ console.log("表单数据:", form);
404
+ // 提交逻辑
405
+ }
406
+ });
407
+ };
408
+
409
+ const handleReset = () => {
410
+ formRef.value?.resetFields();
411
+ };
412
+ </script>
413
+ ```
414
+
415
+ ### 动态表单
416
+
417
+ ```vue
418
+ <template>
419
+ <BaseForm
420
+ ref="formRef"
421
+ :form="form"
422
+ :items="dynamicItems"
423
+ :columns="2"
424
+ label-width="100px"
425
+ />
426
+ </template>
427
+
428
+ <script setup lang="ts">
429
+ import { ref, reactive, computed } from "vue";
430
+
431
+ const form = reactive({
432
+ type: "person",
433
+ name: "",
434
+ idCard: "",
435
+ companyName: "",
436
+ businessLicense: ""
437
+ });
438
+
439
+ const dynamicItems = computed(() => {
440
+ const baseItems = [
441
+ {
442
+ name: "type",
443
+ label: "类型",
444
+ logicType: "dict",
445
+ logicValue: "CUSTOMER_TYPE"
446
+ }
447
+ ];
448
+
449
+ // 根据类型动态显示不同字段
450
+ if (form.type === "person") {
451
+ return [
452
+ ...baseItems,
453
+ { name: "name", label: "姓名", required: true },
454
+ { name: "idCard", label: "身份证号", required: true }
455
+ ];
456
+ } else {
457
+ return [
458
+ ...baseItems,
459
+ { name: "companyName", label: "公司名称", required: true },
460
+ { name: "businessLicense", label: "营业执照", required: true }
461
+ ];
462
+ }
463
+ });
464
+ </script>
465
+ ```
466
+
467
+ ---
468
+
469
+ ## ⚠️ 注意事项
470
+
471
+ 1. **字段名使用 `name` 而非 `prop`**
472
+
473
+ ```typescript
474
+ // ✅ 正确
475
+ { name: "userName", label: "用户名" }
476
+
477
+ // ❌ 错误
478
+ { prop: "userName", label: "用户名" }
479
+ ```
480
+
481
+ 2. **logicType 会自动选择组件**
482
+
483
+ - 不需要手动指定 `type: "select"`
484
+ - 设置 `logicType: "dict"` 即可
485
+
486
+ 3. **范围类型需要设置 startName 和 endName**
487
+
488
+ ```typescript
489
+ {
490
+ type: "range",
491
+ startName: "startDate",
492
+ endName: "endDate",
493
+ logicType: "date"
494
+ }
495
+ ```
496
+
497
+ 4. **使用 computed 包装 items 实现响应式**
498
+
499
+ ```typescript
500
+ const formItems = computed(() => [...]);
501
+ ```
502
+
503
+ ---
504
+
505
+ ## 📚 相关文档
506
+
507
+ - [BaseQuery 查询组件](../BaseQuery/README.md)
508
+ - [BaseTable 表格组件](../BaseTable/README.md)