@agile-team/wl-skills-kit 2.11.0 → 2.11.2

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 (95) hide show
  1. package/CHANGELOG.md +47 -9
  2. package/README.md +41 -23
  3. package/bin/wl-skills.js +133 -39
  4. package/docs/agent-pipeline-runbook.md +3 -3
  5. package/docs//345/205/250/347/233/230/345/210/206/346/236/220/344/270/216/346/231/272/350/203/275/344/275/223/346/220/255/345/273/272/346/214/207/345/215/227.md +4 -4
  6. package/files/.wl-skills/copilot-instructions-full.md +233 -233
  7. package/files/.wl-skills/docs/jh-pagination.md +505 -505
  8. package/files/.wl-skills/docs/page-spec-schema.md +109 -0
  9. package/files/.wl-skills/docs/request.md +940 -940
  10. package/files/.wl-skills/guides/architecture.md +1 -1
  11. package/files/.wl-skills/skills/core/convention-audit/SKILL.md +3 -3
  12. package/files/.wl-skills/skills/core/page-codegen/SKILL.md +10 -4
  13. package/files/.wl-skills/skills/core/spec-doc-parse/SKILL.md +332 -332
  14. package/files/.wl-skills/skills/core/spec-doc-parse/USAGE.md +97 -97
  15. package/files/.wl-skills/skills/sync/permission-sync/USAGE.md +107 -107
  16. package/files/.wl-skills/src/components/global/C_ParentView/index.vue +3 -3
  17. package/files/.wl-skills/src/components/global/C_RightToolbar/index.vue +157 -157
  18. package/files/.wl-skills/src/components/global/C_SvgIcon/index.vue +31 -31
  19. package/files/.wl-skills/src/components/global/C_SvgIcon/svgicon.js +10 -10
  20. package/files/.wl-skills/src/components/global/C_TagStatus/README.md +264 -264
  21. package/files/.wl-skills/src/components/global/C_TagStatus/config.ts +192 -192
  22. package/files/.wl-skills/src/components/global/C_TagStatus/index.vue +106 -106
  23. package/files/.wl-skills/src/components/global/C_TagStatus/types.ts +64 -64
  24. package/files/.wl-skills/src/components/global/C_Tree/README.md +153 -153
  25. package/files/.wl-skills/src/components/global/C_Tree/index.scss +42 -42
  26. package/files/.wl-skills/src/components/global/C_Tree/index.vue +78 -78
  27. package/files/.wl-skills/src/components/global/C_Tree/types.ts +59 -59
  28. package/files/.wl-skills/src/components/local/c_formModal/README.md +235 -235
  29. package/files/.wl-skills/src/components/local/c_formModal/data.ts +95 -95
  30. package/files/.wl-skills/src/components/local/c_formModal/index.scss +8 -8
  31. package/files/.wl-skills/src/components/local/c_formModal/index.vue +107 -107
  32. package/files/.wl-skills/src/components/local/c_formSections/data.ts +175 -175
  33. package/files/.wl-skills/src/components/local/c_formSections/index.scss +280 -280
  34. package/files/.wl-skills/src/components/local/c_formSections/index.vue +429 -429
  35. package/files/.wl-skills/src/components/local/c_listModal/data.ts +41 -41
  36. package/files/.wl-skills/src/components/local/c_listModal/index.vue +136 -136
  37. package/files/.wl-skills/src/components/local/c_spliterTitle/index.scss +25 -25
  38. package/files/.wl-skills/src/components/local/c_spliterTitle/index.vue +21 -21
  39. package/files/.wl-skills/src/components/remote/AGGrid/README.md +530 -530
  40. package/files/.wl-skills/src/components/remote/BaseForm/README.md +508 -508
  41. package/files/.wl-skills/src/components/remote/BaseQuery/README.md +865 -865
  42. package/files/.wl-skills/src/components/remote/BaseTable/README.md +941 -941
  43. package/files/.wl-skills/src/components/remote/BaseToolbar/README.md +496 -496
  44. package/files/.wl-skills/src/types/page.ts +24 -24
  45. package/files/.wl-skills/standards/04-coding-basics.md +39 -1
  46. package/files/.wl-skills/standards/09-typescript.md +26 -3
  47. package/files/.wl-skills/standards/14-layout-containers.md +6 -6
  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 +304 -9
  88. package/lib/page-spec.js +588 -0
  89. package/lib/safe-fix.js +115 -0
  90. package/mcp/config.js +47 -47
  91. package/mcp/registry.js +6 -1
  92. package/mcp/tools/projectTools.js +19 -1
  93. package/package.json +16 -11
  94. package/files/.wl-skills/src/components/global/C_Splitter/index.scss +0 -61
  95. package/files/.wl-skills/src/components/global/C_Splitter/index.vue +0 -149
@@ -1,518 +1,518 @@
1
- /*
2
- * @Author: ChenYu ycyplus@gmail.com
3
- * @Date: 2025-12-29 15:38:58
4
- * @LastEditors: ChenYu ycyplus@gmail.com
5
- * @LastEditTime: 2026-01-03 10:00:00
6
- * @FilePath: \cx-ui-sale\src\views\sale\demo\add-demo\data.ts
7
- * @Description: 新增编辑页示例 - 数据逻辑层(可作为新增编辑页模板)
8
- * Copyright (c) 2025 by CHENY, All Rights Reserved 😎.
9
- */
10
- import { ref, reactive, h, Component, computed } from "vue";
11
- import { ElMessageBox, ElMessage } from "element-plus";
12
- import { Check, Document } from "@element-plus/icons-vue";
13
- import request from "@jhlc/common-core/src/util/request";
14
- import type {
15
- SectionConfig,
16
- NavTabConfig,
17
- HeaderAction
18
- } from "@/components/local/c_formSections/data";
19
-
20
- // ===== 类型定义 =====
21
- interface ItemData {
22
- id: number;
23
- title: string;
24
- furnaceNumber: string;
25
- batchNumber: string;
26
- productionLine: string;
27
- feedCount: number;
28
- feedWeight: number;
29
- scrapCount: number;
30
- scrapWeight: number;
31
- operationTime: string;
32
- shift: string;
33
- team: string;
34
- }
35
-
36
- /**
37
- * API 配置 - 统一管理所有接口地址
38
- */
39
- export const API_CONFIG = {
40
- // 主档操作
41
- save: "/api/order-form/save",
42
- saveDraft: "/api/order-form/draft",
43
- update: "/api/order-form/update",
44
- getById: "/api/order-form/getOneById",
45
- // 项次操作
46
- itemList: "/api/order-items/list",
47
- itemAdd: "/api/order-items/add",
48
- itemRemove: "/api/order-items/remove"
49
- } as const;
50
-
51
- // ===== 状态定义 =====
52
- /** 项次信息表格全屏状态 */
53
- export const isItemTableFullscreen = ref(false);
54
-
55
- /** 折叠面板展开状态 */
56
- export const activeNames = ref(["1", "2", "3", "4", "5"]);
57
-
58
- // ===== 顶部操作按钮配置 =====
59
- export const headerActions: HeaderAction[] = [
60
- {
61
- label: "保存",
62
- type: "primary",
63
- icon: Check as Component,
64
- onClick: async () => {
65
- await saveForm(false);
66
- }
67
- },
68
- {
69
- label: "保存为草稿",
70
- icon: Document as Component,
71
- onClick: async () => {
72
- await saveForm(true);
73
- }
74
- },
75
- {
76
- label: "取消",
77
- onClick: () => {
78
- ElMessageBox.confirm("确认放弃当前更改吗?", "提示", {
79
- confirmButtonText: "确定",
80
- cancelButtonText: "取消",
81
- type: "warning"
82
- })
83
- .then(() => {
84
- resetForm();
85
- ElMessage.success("已清空表单数据");
86
- })
87
- .catch(() => {
88
- // 用户取消操作
89
- });
90
- }
91
- }
92
- ];
93
-
94
- // ===== 楼层导航配置 =====
95
- export const navTabsConfig: NavTabConfig[] = [
96
- { label: "订单信息", name: "order", sectionName: null },
97
- { label: "基本信息", name: "basic", sectionName: "1" },
98
- { label: "产品规格", name: "spec", sectionName: "5" },
99
- { label: "价格信息", name: "price", sectionName: null },
100
- { label: "生产要求", name: "production", sectionName: null },
101
- { label: "运输信息", name: "shipping", sectionName: "2" },
102
- { label: "特殊需求", name: "special", sectionName: "3" },
103
- { label: "变更信息", name: "change", sectionName: "4" }
104
- ];
105
-
106
- /** 切换项次信息表格全屏状态 */
107
- export const toggleItemTableFullscreen = () => {
108
- isItemTableFullscreen.value = !isItemTableFullscreen.value;
109
- };
110
-
111
- // ===== 表单数据配置(数据+配置合一) =====
112
- const formFieldsData = {
113
- // 基本信息
114
- basicInfo: {
115
- mpsRequirement: {
116
- value: "0-无",
117
- label: "MPS要求",
118
- type: "select",
119
- options: [{ label: "0-无", value: "0-无" }]
120
- },
121
- mpsNumber: { value: "", label: "MPS编号", type: "input" },
122
- mpsText: { value: "", label: "MPS文本", type: "input" },
123
- supervisionRequirement: {
124
- value: "0-无",
125
- label: "监制要求",
126
- type: "select",
127
- options: [{ label: "0-无", value: "0-无" }]
128
- },
129
- firstDayInspection: {
130
- value: "0-否",
131
- label: "首日检",
132
- type: "select",
133
- options: [{ label: "0-否", value: "0-否" }]
134
- },
135
- isCollaborative: {
136
- value: "0-否",
137
- label: "是否协同",
138
- type: "select",
139
- options: [{ label: "0-否", value: "0-否" }]
140
- },
141
- orderEngineeringNo: { value: "", label: "订单工程编号", type: "input" },
142
- process: { value: "", label: "制程", type: "input" },
143
- fullOrderDelivery: {
144
- value: "0-否",
145
- label: "整单交付",
146
- type: "select",
147
- options: [{ label: "0-否", value: "0-否" }]
148
- },
149
- forcedRelease: {
150
- value: "0-否",
151
- label: "强制放行",
152
- type: "select",
153
- required: true,
154
- options: [{ label: "0-否", value: "0-否" }]
155
- },
156
- isSampleDeliveryFree: {
157
- value: "0-否",
158
- label: "是否免费送样",
159
- type: "select",
160
- options: [{ label: "0-否", value: "0-否" }]
161
- }
162
- },
163
- // 运输信息
164
- shippingInfo: {
165
- shippingMethod: {
166
- value: "Q-汽运",
167
- label: "运输方式",
168
- type: "input",
169
- required: true
170
- },
171
- consignee: { value: "002", label: "收货人", type: "input", required: true },
172
- consigneeUnit: {
173
- value: "中国石化国际石油工...",
174
- label: "收货单位",
175
- type: "input"
176
- },
177
- deliveryLocation: { value: "产出库", label: "交运地点", type: "input" },
178
- arrivalStation: { value: "", label: "到站", type: "input" },
179
- dedicatedLine: { value: "", label: "专用线", type: "input" },
180
- consigneeAddress: {
181
- value: "北京市朝阳区6A",
182
- label: "收货地址",
183
- type: "input"
184
- },
185
- consigneeSequenceNo: {
186
- value: "002",
187
- label: "收货人序号",
188
- type: "input",
189
- required: true
190
- }
191
- },
192
- // 变更信息
193
- changeInfo: {
194
- changeType: { value: "", label: "变更类型", type: "input" },
195
- changePerson: { value: "", label: "变更人", type: "input" },
196
- changeTime: { value: "", label: "变更时间", type: "input" },
197
- changeReason: { value: "", label: "变更原因", type: "textarea", rows: 2 },
198
- changeFirstDayInspection: {
199
- value: "0-否",
200
- label: "首日检",
201
- type: "select",
202
- options: [{ label: "0-否", value: "0-否" }]
203
- },
204
- changeIsCollaborative: {
205
- value: "0-否",
206
- label: "是否协同",
207
- type: "select",
208
- options: [{ label: "0-否", value: "0-否" }]
209
- },
210
- changeOrderEngineeringNo: {
211
- value: "",
212
- label: "订单工程编号",
213
- type: "input"
214
- },
215
- changeIsSampleDeliveryFree: {
216
- value: "0-否",
217
- label: "是否免费送样",
218
- type: "select",
219
- options: [{ label: "0-否", value: "0-否" }]
220
- }
221
- },
222
- // 产品规格
223
- productSpec: {
224
- productName: {
225
- value: "",
226
- label: "产品名称",
227
- type: "input",
228
- required: true
229
- },
230
- productCode: {
231
- value: "",
232
- label: "产品编码",
233
- type: "input",
234
- required: true
235
- },
236
- specification: { value: "", label: "规格型号", type: "input" },
237
- material: { value: "", label: "材质", type: "input", required: true },
238
- diameter: { value: "", label: "直径(mm)", type: "input" },
239
- length: { value: "", label: "长度(mm)", type: "input" },
240
- thickness: { value: "", label: "壁厚(mm)", type: "input" },
241
- unitWeight: { value: "", label: "单重(kg)", type: "input" },
242
- standard: { value: "", label: "执行标准", type: "input" },
243
- surfaceTreatment: { value: "", label: "表面处理", type: "input" }
244
- }
245
- };
246
-
247
- /** 表单数据(自动从配置生成) */
248
- export const form = reactive(
249
- Object.values(formFieldsData).reduce((acc, section) => {
250
- Object.entries(section).forEach(([key, config]) => {
251
- acc[key] = config.value;
252
- });
253
- return acc;
254
- }, {} as Record<string, any>)
255
- );
256
-
257
- // ===== 区块元数据配置 =====
258
- const sectionsMeta = [
259
- { key: "basicInfo", name: "1", id: "section-1", title: "基本信息" },
260
- { key: "shippingInfo", name: "2", id: "section-2", title: "运输信息" },
261
- {
262
- key: "special",
263
- name: "3",
264
- id: "section-3",
265
- title: "特殊需求",
266
- isSpecial: true
267
- },
268
- { key: "changeInfo", name: "4", id: "section-4", title: "变更信息" },
269
- { key: "productSpec", name: "5", id: "section-5", title: "产品规格" }
270
- ] as const;
271
-
272
- /** 自动生成区块配置 */
273
- const sectionsConfigRaw: SectionConfig[] = sectionsMeta.map((meta) => ({
274
- name: meta.name,
275
- id: meta.id,
276
- title: meta.title,
277
- isSpecial: "isSpecial" in meta ? meta.isSpecial : undefined,
278
- fieldsConfig:
279
- meta.key === "special"
280
- ? []
281
- : Object.entries(
282
- formFieldsData[meta.key as keyof typeof formFieldsData] || {}
283
- ).map(([prop, config]) => {
284
- const { value, ...rest } = config;
285
- return { prop, ...rest } as any;
286
- })
287
- }));
288
-
289
- /** 表单区域配置(组件内部处理过滤逻辑) */
290
- export const sectionsConfig = sectionsConfigRaw;
291
-
292
- // ===== 项次信息表格配置 =====
293
-
294
- /**
295
- * 处理标题点击事件
296
- * @param row 当前行数据
297
- * @param index 行索引(从 0 开始)
298
- */
299
- export const handleTitleClick = (row: ItemData, index: number) => {
300
- ElMessageBox.alert(
301
- `你可以对我做点什么操作?
302
-
303
- 行 ID: ${row.id}
304
- 行序号: ${index + 1}
305
- 标题: ${row.title}
306
- 炉号: ${row.furnaceNumber}
307
- 批号: ${row.batchNumber}
308
-
309
- 这里可以添加编辑、查看详情、删除等操作按钮。`,
310
- `点击了第 ${index + 1} 行`,
311
- {
312
- confirmButtonText: "知道了",
313
- type: "info"
314
- }
315
- );
316
- };
317
-
318
- export const itemColumnsConfig = [
319
- { type: "selection", width: 40 },
320
- { type: "index", label: "序号", width: 60 },
321
- {
322
- name: "title",
323
- label: "标题",
324
- minWidth: 90,
325
- // 使用 defaultSlot 自定义渲染蓝色链接样式,添加点击事件
326
- defaultSlot: ({ row, $index }: { row: any; $index: number }) => {
327
- return h(
328
- "span",
329
- {
330
- style: "color: #409eff; cursor: pointer; text-decoration: underline;",
331
- onClick: () => handleTitleClick(row, $index)
332
- },
333
- row.title
334
- );
335
- }
336
- },
337
- {
338
- name: "furnaceNumber",
339
- label: "炉号",
340
- minWidth: 110,
341
- showOverflowTooltip: true
342
- },
343
- {
344
- name: "batchNumber",
345
- label: "批号",
346
- minWidth: 110,
347
- showOverflowTooltip: true
348
- },
349
- {
350
- name: "productionLine",
351
- label: "生产线",
352
- minWidth: 150,
353
- showOverflowTooltip: true
354
- },
355
- {
356
- name: "feedCount",
357
- label: "上料支数",
358
- minWidth: 90,
359
- showOverflowTooltip: true
360
- },
361
- {
362
- name: "feedWeight",
363
- label: "上料重量",
364
- minWidth: 90,
365
- showOverflowTooltip: true
366
- },
367
- {
368
- name: "scrapCount",
369
- label: "废品支数",
370
- minWidth: 90,
371
- showOverflowTooltip: true
372
- },
373
- {
374
- name: "scrapWeight",
375
- label: "废品重量",
376
- minWidth: 90,
377
- showOverflowTooltip: true
378
- },
379
- {
380
- name: "operationTime",
381
- label: "操作时间",
382
- minWidth: 140,
383
- showOverflowTooltip: true
384
- },
385
- {
386
- name: "shift",
387
- label: "班次",
388
- minWidth: 80,
389
- showOverflowTooltip: true,
390
- filterable: true
391
- },
392
- { name: "team", label: "班组", minWidth: 80, showOverflowTooltip: true }
393
- ];
394
-
395
- // ===== 数据生成 =====
396
- /** 项次数据 */
397
- export const itemData = ref<ItemData[]>([]);
398
-
399
- /** 分页状态 */
400
- export const currentPage = ref(1);
401
- export const pageSize = ref(10);
402
-
403
- /** 项次数据总数 */
404
- export const itemTotal = ref(0);
405
-
406
- /** 分页后的项次数据 */
407
- export const paginatedItemData = computed(() => {
408
- const start = (currentPage.value - 1) * pageSize.value;
409
- const end = start + pageSize.value;
410
- return itemData.value.slice(start, end);
411
- });
412
-
413
- // ========== 方法定义 ==========
414
- /** 添加特殊需求 */
415
- export const addSpecialRequirement = () => {
416
- console.log("添加特殊需求");
417
- };
418
-
419
- /**
420
- * 表单验证
421
- */
422
- const validateForm = (): boolean => {
423
- // 检查必填字段
424
- const requiredFields = [
425
- { key: "productName", label: "产品名称" },
426
- { key: "productCode", label: "产品编码" },
427
- { key: "material", label: "材质" },
428
- { key: "shippingMethod", label: "运输方式" },
429
- { key: "consignee", label: "收货人" },
430
- { key: "consigneeSequenceNo", label: "收货人序号" },
431
- { key: "forcedRelease", label: "强制放行" }
432
- ];
433
-
434
- for (const field of requiredFields) {
435
- if (!form[field.key]) {
436
- ElMessage.error(`请填写${field.label}`);
437
- return false;
438
- }
439
- }
440
-
441
- return true;
442
- };
443
-
444
- /**
445
- * 保存表单
446
- * @param isDraft 是否保存为草稿
447
- */
448
- const saveForm = async (isDraft: boolean) => {
449
- try {
450
- // 草稿可以不验证必填项
451
- if (!isDraft && !validateForm()) {
452
- return;
453
- }
454
-
455
- const res = await request({
456
- url: isDraft ? API_CONFIG.saveDraft : API_CONFIG.save,
457
- method: "post",
458
- data: {
459
- ...form,
460
- isDraft
461
- }
462
- });
463
-
464
- ElMessage.success(res.message || (isDraft ? "草稿保存成功" : "保存成功"));
465
- } catch (err) {
466
- console.error("保存失败:", err);
467
- }
468
- };
469
-
470
- /**
471
- * 重置表单
472
- */
473
- const resetForm = () => {
474
- Object.keys(form).forEach((key) => {
475
- if (typeof form[key] === "string") {
476
- form[key] = "";
477
- } else if (typeof form[key] === "number") {
478
- form[key] = 0;
479
- } else if (Array.isArray(form[key])) {
480
- form[key] = [];
481
- }
482
- });
483
- };
484
-
485
- /**
486
- * 加载项次数据
487
- */
488
- export const fetchItemData = async () => {
489
- try {
490
- const res = await request({
491
- url: API_CONFIG.itemList,
492
- method: "get",
493
- params: {
494
- page: currentPage.value,
495
- size: pageSize.value
496
- }
497
- });
498
-
499
- itemData.value = res.data.records || res.data;
500
- itemTotal.value = res.data.total || res.data.length;
501
- } catch (err) {
502
- console.error("加载项次数据失败:", err);
503
- }
504
- };
505
-
506
- /**
507
- * 刷新项次数据
508
- */
509
- export const refreshItemData = () => {
510
- fetchItemData();
511
- };
512
-
513
- /**
514
- * 页面初始化
515
- */
516
- export const initPage = () => {
517
- fetchItemData();
518
- };
1
+ /*
2
+ * @Author: ChenYu ycyplus@gmail.com
3
+ * @Date: 2025-12-29 15:38:58
4
+ * @LastEditors: ChenYu ycyplus@gmail.com
5
+ * @LastEditTime: 2026-01-03 10:00:00
6
+ * @FilePath: \cx-ui-sale\src\views\sale\demo\add-demo\data.ts
7
+ * @Description: 新增编辑页示例 - 数据逻辑层(可作为新增编辑页模板)
8
+ * Copyright (c) 2025 by CHENY, All Rights Reserved 😎.
9
+ */
10
+ import { ref, reactive, h, Component, computed } from "vue";
11
+ import { ElMessageBox, ElMessage } from "element-plus";
12
+ import { Check, Document } from "@element-plus/icons-vue";
13
+ import request from "@jhlc/common-core/src/util/request";
14
+ import type {
15
+ SectionConfig,
16
+ NavTabConfig,
17
+ HeaderAction
18
+ } from "@/components/local/c_formSections/data";
19
+
20
+ // ===== 类型定义 =====
21
+ interface ItemData {
22
+ id: number;
23
+ title: string;
24
+ furnaceNumber: string;
25
+ batchNumber: string;
26
+ productionLine: string;
27
+ feedCount: number;
28
+ feedWeight: number;
29
+ scrapCount: number;
30
+ scrapWeight: number;
31
+ operationTime: string;
32
+ shift: string;
33
+ team: string;
34
+ }
35
+
36
+ /**
37
+ * API 配置 - 统一管理所有接口地址
38
+ */
39
+ export const API_CONFIG = {
40
+ // 主档操作
41
+ save: "/api/order-form/save",
42
+ saveDraft: "/api/order-form/draft",
43
+ update: "/api/order-form/update",
44
+ getById: "/api/order-form/getOneById",
45
+ // 项次操作
46
+ itemList: "/api/order-items/list",
47
+ itemAdd: "/api/order-items/add",
48
+ itemRemove: "/api/order-items/remove"
49
+ } as const;
50
+
51
+ // ===== 状态定义 =====
52
+ /** 项次信息表格全屏状态 */
53
+ export const isItemTableFullscreen = ref(false);
54
+
55
+ /** 折叠面板展开状态 */
56
+ export const activeNames = ref(["1", "2", "3", "4", "5"]);
57
+
58
+ // ===== 顶部操作按钮配置 =====
59
+ export const headerActions: HeaderAction[] = [
60
+ {
61
+ label: "保存",
62
+ type: "primary",
63
+ icon: Check as Component,
64
+ onClick: async () => {
65
+ await saveForm(false);
66
+ }
67
+ },
68
+ {
69
+ label: "保存为草稿",
70
+ icon: Document as Component,
71
+ onClick: async () => {
72
+ await saveForm(true);
73
+ }
74
+ },
75
+ {
76
+ label: "取消",
77
+ onClick: () => {
78
+ ElMessageBox.confirm("确认放弃当前更改吗?", "提示", {
79
+ confirmButtonText: "确定",
80
+ cancelButtonText: "取消",
81
+ type: "warning"
82
+ })
83
+ .then(() => {
84
+ resetForm();
85
+ ElMessage.success("已清空表单数据");
86
+ })
87
+ .catch(() => {
88
+ // 用户取消操作
89
+ });
90
+ }
91
+ }
92
+ ];
93
+
94
+ // ===== 楼层导航配置 =====
95
+ export const navTabsConfig: NavTabConfig[] = [
96
+ { label: "订单信息", name: "order", sectionName: null },
97
+ { label: "基本信息", name: "basic", sectionName: "1" },
98
+ { label: "产品规格", name: "spec", sectionName: "5" },
99
+ { label: "价格信息", name: "price", sectionName: null },
100
+ { label: "生产要求", name: "production", sectionName: null },
101
+ { label: "运输信息", name: "shipping", sectionName: "2" },
102
+ { label: "特殊需求", name: "special", sectionName: "3" },
103
+ { label: "变更信息", name: "change", sectionName: "4" }
104
+ ];
105
+
106
+ /** 切换项次信息表格全屏状态 */
107
+ export const toggleItemTableFullscreen = () => {
108
+ isItemTableFullscreen.value = !isItemTableFullscreen.value;
109
+ };
110
+
111
+ // ===== 表单数据配置(数据+配置合一) =====
112
+ const formFieldsData = {
113
+ // 基本信息
114
+ basicInfo: {
115
+ mpsRequirement: {
116
+ value: "0-无",
117
+ label: "MPS要求",
118
+ type: "select",
119
+ options: [{ label: "0-无", value: "0-无" }]
120
+ },
121
+ mpsNumber: { value: "", label: "MPS编号", type: "input" },
122
+ mpsText: { value: "", label: "MPS文本", type: "input" },
123
+ supervisionRequirement: {
124
+ value: "0-无",
125
+ label: "监制要求",
126
+ type: "select",
127
+ options: [{ label: "0-无", value: "0-无" }]
128
+ },
129
+ firstDayInspection: {
130
+ value: "0-否",
131
+ label: "首日检",
132
+ type: "select",
133
+ options: [{ label: "0-否", value: "0-否" }]
134
+ },
135
+ isCollaborative: {
136
+ value: "0-否",
137
+ label: "是否协同",
138
+ type: "select",
139
+ options: [{ label: "0-否", value: "0-否" }]
140
+ },
141
+ orderEngineeringNo: { value: "", label: "订单工程编号", type: "input" },
142
+ process: { value: "", label: "制程", type: "input" },
143
+ fullOrderDelivery: {
144
+ value: "0-否",
145
+ label: "整单交付",
146
+ type: "select",
147
+ options: [{ label: "0-否", value: "0-否" }]
148
+ },
149
+ forcedRelease: {
150
+ value: "0-否",
151
+ label: "强制放行",
152
+ type: "select",
153
+ required: true,
154
+ options: [{ label: "0-否", value: "0-否" }]
155
+ },
156
+ isSampleDeliveryFree: {
157
+ value: "0-否",
158
+ label: "是否免费送样",
159
+ type: "select",
160
+ options: [{ label: "0-否", value: "0-否" }]
161
+ }
162
+ },
163
+ // 运输信息
164
+ shippingInfo: {
165
+ shippingMethod: {
166
+ value: "Q-汽运",
167
+ label: "运输方式",
168
+ type: "input",
169
+ required: true
170
+ },
171
+ consignee: { value: "002", label: "收货人", type: "input", required: true },
172
+ consigneeUnit: {
173
+ value: "中国石化国际石油工...",
174
+ label: "收货单位",
175
+ type: "input"
176
+ },
177
+ deliveryLocation: { value: "产出库", label: "交运地点", type: "input" },
178
+ arrivalStation: { value: "", label: "到站", type: "input" },
179
+ dedicatedLine: { value: "", label: "专用线", type: "input" },
180
+ consigneeAddress: {
181
+ value: "北京市朝阳区6A",
182
+ label: "收货地址",
183
+ type: "input"
184
+ },
185
+ consigneeSequenceNo: {
186
+ value: "002",
187
+ label: "收货人序号",
188
+ type: "input",
189
+ required: true
190
+ }
191
+ },
192
+ // 变更信息
193
+ changeInfo: {
194
+ changeType: { value: "", label: "变更类型", type: "input" },
195
+ changePerson: { value: "", label: "变更人", type: "input" },
196
+ changeTime: { value: "", label: "变更时间", type: "input" },
197
+ changeReason: { value: "", label: "变更原因", type: "textarea", rows: 2 },
198
+ changeFirstDayInspection: {
199
+ value: "0-否",
200
+ label: "首日检",
201
+ type: "select",
202
+ options: [{ label: "0-否", value: "0-否" }]
203
+ },
204
+ changeIsCollaborative: {
205
+ value: "0-否",
206
+ label: "是否协同",
207
+ type: "select",
208
+ options: [{ label: "0-否", value: "0-否" }]
209
+ },
210
+ changeOrderEngineeringNo: {
211
+ value: "",
212
+ label: "订单工程编号",
213
+ type: "input"
214
+ },
215
+ changeIsSampleDeliveryFree: {
216
+ value: "0-否",
217
+ label: "是否免费送样",
218
+ type: "select",
219
+ options: [{ label: "0-否", value: "0-否" }]
220
+ }
221
+ },
222
+ // 产品规格
223
+ productSpec: {
224
+ productName: {
225
+ value: "",
226
+ label: "产品名称",
227
+ type: "input",
228
+ required: true
229
+ },
230
+ productCode: {
231
+ value: "",
232
+ label: "产品编码",
233
+ type: "input",
234
+ required: true
235
+ },
236
+ specification: { value: "", label: "规格型号", type: "input" },
237
+ material: { value: "", label: "材质", type: "input", required: true },
238
+ diameter: { value: "", label: "直径(mm)", type: "input" },
239
+ length: { value: "", label: "长度(mm)", type: "input" },
240
+ thickness: { value: "", label: "壁厚(mm)", type: "input" },
241
+ unitWeight: { value: "", label: "单重(kg)", type: "input" },
242
+ standard: { value: "", label: "执行标准", type: "input" },
243
+ surfaceTreatment: { value: "", label: "表面处理", type: "input" }
244
+ }
245
+ };
246
+
247
+ /** 表单数据(自动从配置生成) */
248
+ export const form = reactive(
249
+ Object.values(formFieldsData).reduce((acc, section) => {
250
+ Object.entries(section).forEach(([key, config]) => {
251
+ acc[key] = config.value;
252
+ });
253
+ return acc;
254
+ }, {} as Record<string, any>)
255
+ );
256
+
257
+ // ===== 区块元数据配置 =====
258
+ const sectionsMeta = [
259
+ { key: "basicInfo", name: "1", id: "section-1", title: "基本信息" },
260
+ { key: "shippingInfo", name: "2", id: "section-2", title: "运输信息" },
261
+ {
262
+ key: "special",
263
+ name: "3",
264
+ id: "section-3",
265
+ title: "特殊需求",
266
+ isSpecial: true
267
+ },
268
+ { key: "changeInfo", name: "4", id: "section-4", title: "变更信息" },
269
+ { key: "productSpec", name: "5", id: "section-5", title: "产品规格" }
270
+ ] as const;
271
+
272
+ /** 自动生成区块配置 */
273
+ const sectionsConfigRaw: SectionConfig[] = sectionsMeta.map((meta) => ({
274
+ name: meta.name,
275
+ id: meta.id,
276
+ title: meta.title,
277
+ isSpecial: "isSpecial" in meta ? meta.isSpecial : undefined,
278
+ fieldsConfig:
279
+ meta.key === "special"
280
+ ? []
281
+ : Object.entries(
282
+ formFieldsData[meta.key as keyof typeof formFieldsData] || {}
283
+ ).map(([prop, config]) => {
284
+ const { value, ...rest } = config;
285
+ return { prop, ...rest } as any;
286
+ })
287
+ }));
288
+
289
+ /** 表单区域配置(组件内部处理过滤逻辑) */
290
+ export const sectionsConfig = sectionsConfigRaw;
291
+
292
+ // ===== 项次信息表格配置 =====
293
+
294
+ /**
295
+ * 处理标题点击事件
296
+ * @param row 当前行数据
297
+ * @param index 行索引(从 0 开始)
298
+ */
299
+ export const handleTitleClick = (row: ItemData, index: number) => {
300
+ ElMessageBox.alert(
301
+ `你可以对我做点什么操作?
302
+
303
+ 行 ID: ${row.id}
304
+ 行序号: ${index + 1}
305
+ 标题: ${row.title}
306
+ 炉号: ${row.furnaceNumber}
307
+ 批号: ${row.batchNumber}
308
+
309
+ 这里可以添加编辑、查看详情、删除等操作按钮。`,
310
+ `点击了第 ${index + 1} 行`,
311
+ {
312
+ confirmButtonText: "知道了",
313
+ type: "info"
314
+ }
315
+ );
316
+ };
317
+
318
+ export const itemColumnsConfig = [
319
+ { type: "selection", width: 40 },
320
+ { type: "index", label: "序号", width: 60 },
321
+ {
322
+ name: "title",
323
+ label: "标题",
324
+ minWidth: 90,
325
+ // 使用 defaultSlot 自定义渲染蓝色链接样式,添加点击事件
326
+ defaultSlot: ({ row, $index }: { row: any; $index: number }) => {
327
+ return h(
328
+ "span",
329
+ {
330
+ style: "color: #409eff; cursor: pointer; text-decoration: underline;",
331
+ onClick: () => handleTitleClick(row, $index)
332
+ },
333
+ row.title
334
+ );
335
+ }
336
+ },
337
+ {
338
+ name: "furnaceNumber",
339
+ label: "炉号",
340
+ minWidth: 110,
341
+ showOverflowTooltip: true
342
+ },
343
+ {
344
+ name: "batchNumber",
345
+ label: "批号",
346
+ minWidth: 110,
347
+ showOverflowTooltip: true
348
+ },
349
+ {
350
+ name: "productionLine",
351
+ label: "生产线",
352
+ minWidth: 150,
353
+ showOverflowTooltip: true
354
+ },
355
+ {
356
+ name: "feedCount",
357
+ label: "上料支数",
358
+ minWidth: 90,
359
+ showOverflowTooltip: true
360
+ },
361
+ {
362
+ name: "feedWeight",
363
+ label: "上料重量",
364
+ minWidth: 90,
365
+ showOverflowTooltip: true
366
+ },
367
+ {
368
+ name: "scrapCount",
369
+ label: "废品支数",
370
+ minWidth: 90,
371
+ showOverflowTooltip: true
372
+ },
373
+ {
374
+ name: "scrapWeight",
375
+ label: "废品重量",
376
+ minWidth: 90,
377
+ showOverflowTooltip: true
378
+ },
379
+ {
380
+ name: "operationTime",
381
+ label: "操作时间",
382
+ minWidth: 140,
383
+ showOverflowTooltip: true
384
+ },
385
+ {
386
+ name: "shift",
387
+ label: "班次",
388
+ minWidth: 80,
389
+ showOverflowTooltip: true,
390
+ filterable: true
391
+ },
392
+ { name: "team", label: "班组", minWidth: 80, showOverflowTooltip: true }
393
+ ];
394
+
395
+ // ===== 数据生成 =====
396
+ /** 项次数据 */
397
+ export const itemData = ref<ItemData[]>([]);
398
+
399
+ /** 分页状态 */
400
+ export const currentPage = ref(1);
401
+ export const pageSize = ref(10);
402
+
403
+ /** 项次数据总数 */
404
+ export const itemTotal = ref(0);
405
+
406
+ /** 分页后的项次数据 */
407
+ export const paginatedItemData = computed(() => {
408
+ const start = (currentPage.value - 1) * pageSize.value;
409
+ const end = start + pageSize.value;
410
+ return itemData.value.slice(start, end);
411
+ });
412
+
413
+ // ========== 方法定义 ==========
414
+ /** 添加特殊需求 */
415
+ export const addSpecialRequirement = () => {
416
+ console.log("添加特殊需求");
417
+ };
418
+
419
+ /**
420
+ * 表单验证
421
+ */
422
+ const validateForm = (): boolean => {
423
+ // 检查必填字段
424
+ const requiredFields = [
425
+ { key: "productName", label: "产品名称" },
426
+ { key: "productCode", label: "产品编码" },
427
+ { key: "material", label: "材质" },
428
+ { key: "shippingMethod", label: "运输方式" },
429
+ { key: "consignee", label: "收货人" },
430
+ { key: "consigneeSequenceNo", label: "收货人序号" },
431
+ { key: "forcedRelease", label: "强制放行" }
432
+ ];
433
+
434
+ for (const field of requiredFields) {
435
+ if (!form[field.key]) {
436
+ ElMessage.error(`请填写${field.label}`);
437
+ return false;
438
+ }
439
+ }
440
+
441
+ return true;
442
+ };
443
+
444
+ /**
445
+ * 保存表单
446
+ * @param isDraft 是否保存为草稿
447
+ */
448
+ const saveForm = async (isDraft: boolean) => {
449
+ try {
450
+ // 草稿可以不验证必填项
451
+ if (!isDraft && !validateForm()) {
452
+ return;
453
+ }
454
+
455
+ const res = await request({
456
+ url: isDraft ? API_CONFIG.saveDraft : API_CONFIG.save,
457
+ method: "post",
458
+ data: {
459
+ ...form,
460
+ isDraft
461
+ }
462
+ });
463
+
464
+ ElMessage.success(res.message || (isDraft ? "草稿保存成功" : "保存成功"));
465
+ } catch (err) {
466
+ console.error("保存失败:", err);
467
+ }
468
+ };
469
+
470
+ /**
471
+ * 重置表单
472
+ */
473
+ const resetForm = () => {
474
+ Object.keys(form).forEach((key) => {
475
+ if (typeof form[key] === "string") {
476
+ form[key] = "";
477
+ } else if (typeof form[key] === "number") {
478
+ form[key] = 0;
479
+ } else if (Array.isArray(form[key])) {
480
+ form[key] = [];
481
+ }
482
+ });
483
+ };
484
+
485
+ /**
486
+ * 加载项次数据
487
+ */
488
+ export const fetchItemData = async () => {
489
+ try {
490
+ const res = await request({
491
+ url: API_CONFIG.itemList,
492
+ method: "get",
493
+ params: {
494
+ page: currentPage.value,
495
+ size: pageSize.value
496
+ }
497
+ });
498
+
499
+ itemData.value = res.data.records || res.data;
500
+ itemTotal.value = res.data.total || res.data.length;
501
+ } catch (err) {
502
+ console.error("加载项次数据失败:", err);
503
+ }
504
+ };
505
+
506
+ /**
507
+ * 刷新项次数据
508
+ */
509
+ export const refreshItemData = () => {
510
+ fetchItemData();
511
+ };
512
+
513
+ /**
514
+ * 页面初始化
515
+ */
516
+ export const initPage = () => {
517
+ fetchItemData();
518
+ };