@agile-team/wl-skills-kit 1.0.0

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/CHANGELOG.md +13 -0
  2. package/README.md +328 -0
  3. package/bin/wl-skills.js +104 -0
  4. package/files/.github/copilot-instructions.md +211 -0
  5. package/files/.github/docs/SYS_MENU_INFO.md +247 -0
  6. package/files/.github/docs/menu-sync-design.md +265 -0
  7. package/files/.github/docs/use-skill.md +379 -0
  8. package/files/.github/docs/wl-skills-kit.md +266 -0
  9. package/files/.github/skills/api-contract/SKILL.md +247 -0
  10. package/files/.github/skills/convention-extract/SKILL.md +355 -0
  11. package/files/.github/skills/menu-sync/SKILL.md +255 -0
  12. package/files/.github/skills/menu-sync/env/guide.md +73 -0
  13. package/files/.github/skills/page-codegen/SKILL.md +825 -0
  14. package/files/.github/skills/page-codegen/TPL-CHANGE-HISTORY.md +281 -0
  15. package/files/.github/skills/page-codegen/TPL-DETAIL-TABS.md +1112 -0
  16. package/files/.github/skills/page-codegen/TPL-DRIVEN.md +124 -0
  17. package/files/.github/skills/page-codegen/TPL-FORM-ROUTE.md +441 -0
  18. package/files/.github/skills/page-codegen/TPL-LIST.md +196 -0
  19. package/files/.github/skills/page-codegen/TPL-MASTER-DETAIL.md +153 -0
  20. package/files/.github/skills/page-codegen/TPL-OPERATION-STATION.md +442 -0
  21. package/files/.github/skills/page-codegen/TPL-RECORD-FORM.md +376 -0
  22. package/files/.github/skills/page-codegen/TPL-TREE-LIST.md +191 -0
  23. package/files/.github/skills/prototype-scan/SKILL.md +414 -0
  24. package/files/demo/README.md +44 -0
  25. package/files/demo/produce/aiflow/mmwr-customer-apply-add/api.md +54 -0
  26. package/files/demo/produce/aiflow/mmwr-customer-apply-add/data.ts +346 -0
  27. package/files/demo/produce/aiflow/mmwr-customer-apply-add/index.scss +1 -0
  28. package/files/demo/produce/aiflow/mmwr-customer-apply-add/index.vue +28 -0
  29. package/files/demo/produce/aiflow/mmwr-customer-apply-add-form/data.ts +115 -0
  30. package/files/demo/produce/aiflow/mmwr-customer-apply-add-form/index.scss +44 -0
  31. package/files/demo/produce/aiflow/mmwr-customer-apply-add-form/index.vue +43 -0
  32. package/files/demo/produce/aiflow/mmwr-customer-apply-change/data.ts +338 -0
  33. package/files/demo/produce/aiflow/mmwr-customer-apply-change/index.scss +1 -0
  34. package/files/demo/produce/aiflow/mmwr-customer-apply-change/index.vue +28 -0
  35. package/files/demo/produce/aiflow/mmwr-customer-apply-change-form/data.ts +115 -0
  36. package/files/demo/produce/aiflow/mmwr-customer-apply-change-form/index.scss +44 -0
  37. package/files/demo/produce/aiflow/mmwr-customer-apply-change-form/index.vue +43 -0
  38. package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/data.ts +196 -0
  39. package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.scss +150 -0
  40. package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.vue +79 -0
  41. package/files/demo/produce/aiflow/mmwr-customer-archive/api.md +88 -0
  42. package/files/demo/produce/aiflow/mmwr-customer-archive/data.ts +601 -0
  43. package/files/demo/produce/aiflow/mmwr-customer-archive/index.scss +1 -0
  44. package/files/demo/produce/aiflow/mmwr-customer-archive/index.vue +64 -0
  45. package/files/demo/produce/aiflow/mmwr-customer-detail/api.md +67 -0
  46. package/files/demo/produce/aiflow/mmwr-customer-detail/data.ts +286 -0
  47. package/files/demo/produce/aiflow/mmwr-customer-detail/index.scss +139 -0
  48. package/files/demo/produce/aiflow/mmwr-customer-detail/index.vue +318 -0
  49. package/files/demo/produce/aiflow/mmwr-temp-customer-archive/api.md +98 -0
  50. package/files/demo/produce/aiflow/mmwr-temp-customer-archive/data.ts +543 -0
  51. package/files/demo/produce/aiflow/mmwr-temp-customer-archive/index.scss +1 -0
  52. package/files/demo/produce/aiflow/mmwr-temp-customer-archive/index.vue +52 -0
  53. package/files/demo/sale/demo/add-demo/data.ts +518 -0
  54. package/files/demo/sale/demo/add-demo/index.scss +207 -0
  55. package/files/demo/sale/demo/add-demo/index.vue +167 -0
  56. package/files/demo/sale/demo/billet-flame-cut-plan/data.ts +524 -0
  57. package/files/demo/sale/demo/billet-flame-cut-plan/index.scss +155 -0
  58. package/files/demo/sale/demo/billet-flame-cut-plan/index.vue +117 -0
  59. package/files/demo/sale/demo/domestic-trade-order/data.ts +308 -0
  60. package/files/demo/sale/demo/domestic-trade-order/index.scss +99 -0
  61. package/files/demo/sale/demo/domestic-trade-order/index.vue +77 -0
  62. package/files/demo/sale/demo/heat-batch-return/data.ts +367 -0
  63. package/files/demo/sale/demo/heat-batch-return/index.scss +100 -0
  64. package/files/demo/sale/demo/heat-batch-return/index.vue +170 -0
  65. package/files/demo/sale/demo/heat-batch-return/meltDialog.vue +320 -0
  66. package/files/demo/sale/demo/metallurgical-spec/data.ts +825 -0
  67. package/files/demo/sale/demo/metallurgical-spec/index.scss +264 -0
  68. package/files/demo/sale/demo/metallurgical-spec/index.vue +309 -0
  69. package/files/docs/jh-date-range.md +257 -0
  70. package/files/docs/jh-date.md +222 -0
  71. package/files/docs/jh-dept-picker.md +190 -0
  72. package/files/docs/jh-drag-row.md +590 -0
  73. package/files/docs/jh-file-upload.md +216 -0
  74. package/files/docs/jh-pagination.md +505 -0
  75. package/files/docs/jh-picker.md +218 -0
  76. package/files/docs/jh-select.md +148 -0
  77. package/files/docs/jh-text.md +248 -0
  78. package/files/docs/jh-user-picker.md +197 -0
  79. package/files/docs/page-query-hook-best-practices.md +362 -0
  80. package/files/docs/request.md +925 -0
  81. package/files/src/components/global/C_ParentView/index.vue +3 -0
  82. package/files/src/components/global/C_RightToolbar/index.vue +459 -0
  83. package/files/src/components/global/C_Splitter/index.vue +195 -0
  84. package/files/src/components/global/C_SvgIcon/index.vue +61 -0
  85. package/files/src/components/global/C_SvgIcon/svgicon.js +10 -0
  86. package/files/src/components/global/C_TagStatus/README.md +264 -0
  87. package/files/src/components/global/C_TagStatus/config.ts +192 -0
  88. package/files/src/components/global/C_TagStatus/index.vue +127 -0
  89. package/files/src/components/global/C_TagStatus/types.ts +64 -0
  90. package/files/src/components/global/C_Tree/README.md +153 -0
  91. package/files/src/components/global/C_Tree/index.scss +42 -0
  92. package/files/src/components/global/C_Tree/index.vue +119 -0
  93. package/files/src/components/global/C_Tree/types.ts +59 -0
  94. package/files/src/components/local/c_formModal/README.md +235 -0
  95. package/files/src/components/local/c_formModal/data.ts +95 -0
  96. package/files/src/components/local/c_formModal/index.scss +8 -0
  97. package/files/src/components/local/c_formModal/index.vue +107 -0
  98. package/files/src/components/local/c_formSections/README.md +496 -0
  99. package/files/src/components/local/c_formSections/data.ts +175 -0
  100. package/files/src/components/local/c_formSections/index.scss +280 -0
  101. package/files/src/components/local/c_formSections/index.vue +429 -0
  102. package/files/src/components/local/c_listModal/data.ts +41 -0
  103. package/files/src/components/local/c_listModal/index.vue +136 -0
  104. package/files/src/components/local/c_spliterTitle/index.scss +25 -0
  105. package/files/src/components/local/c_spliterTitle/index.vue +21 -0
  106. package/files/src/components/remote/AGGrid/README.md +530 -0
  107. package/files/src/components/remote/BaseForm/README.md +508 -0
  108. package/files/src/components/remote/BaseQuery/README.md +865 -0
  109. package/files/src/components/remote/BaseTable/README.md +941 -0
  110. package/files/src/components/remote/BaseToolbar/README.md +496 -0
  111. package/files/src/types/page.ts +24 -0
  112. package/package.json +31 -0
@@ -0,0 +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/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/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)