@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,338 @@
1
+ import {
2
+ AbstractPageQueryHook,
3
+ BaseQueryItemDesc,
4
+ ActionButtonDesc,
5
+ TableColumnDesc
6
+ } from "@/types/page";
7
+ import { postAction } from "@jhlc/common-core/src/api/action";
8
+ import envConfig from "@jhlc/common-core/src/store/env-config";
9
+ import { ElMessage, ElMessageBox } from "element-plus";
10
+ import { h, resolveComponent } from "vue";
11
+
12
+ const STATUS_TAG_MAP: Record<string, Record<string, string>> = {
13
+ approvalStatus: {
14
+ 开立审批中: "",
15
+ 审批完成: "success",
16
+ 驳回: "danger",
17
+ 流程终止: "info"
18
+ },
19
+ verifyStatus: { 已核实: "success", 未核实: "info" }
20
+ };
21
+ function renderStatusTag(row: any, field: string) {
22
+ const val = row[field];
23
+ const typeMap = STATUS_TAG_MAP[field];
24
+ if (!typeMap) return val;
25
+ const type = Object.prototype.hasOwnProperty.call(typeMap, val)
26
+ ? typeMap[val]
27
+ : undefined;
28
+ if (type === undefined) return val;
29
+ return h(
30
+ resolveComponent("ElTag") as any,
31
+ { type: type || "", effect: "light", size: "small" },
32
+ () => val
33
+ );
34
+ }
35
+
36
+ export const API_CONFIG = {
37
+ list: "/sale/customerApply/changeList",
38
+ remove: "/sale/customerApply/remove",
39
+ getById: "/sale/customerApply/getById",
40
+ save: "/sale/customerApply/save",
41
+ update: "/sale/customerApply/update",
42
+ submit: "/sale/customerApply/submit",
43
+ withdraw: "/sale/customerApply/withdraw",
44
+ export: "/sale/customerApply/export"
45
+ } as const;
46
+
47
+ const OPTS = {
48
+ approvalProduct: [
49
+ { label: "热轧", value: "热轧" },
50
+ { label: "盘元", value: "盘元" },
51
+ { label: "冷精", value: "冷精" },
52
+ { label: "汽车", value: "汽车" }
53
+ ],
54
+ applyOrg: [
55
+ { label: "不锈鋼接單中心", value: "不锈鋼接單中心" },
56
+ {
57
+ label: "江阴华新特殊合金材料有限公司",
58
+ value: "江阴华新特殊合金材料有限公司"
59
+ },
60
+ { label: "揉瞒管理中心", value: "揉瞒管理中心" },
61
+ { label: "烟台华鑫再生资源有限公司", value: "烟台华鑫再生资源有限公司" }
62
+ ],
63
+ applyType: [
64
+ { label: "新增", value: "新增" },
65
+ { label: "变更", value: "变更" }
66
+ ],
67
+ applyDept: [
68
+ { label: "業務管理處", value: "業務管理處" },
69
+ { label: "線材銷售部", value: "線材銷售部" },
70
+ { label: "無縫管銷售處", value: "無縫管銷售處" }
71
+ ],
72
+ applicant: [
73
+ { label: "魏子明", value: "魏子明" },
74
+ { label: "龚辉鉴", value: "龚辉鉴" },
75
+ { label: "宋书迪", value: "宋书迪" },
76
+ { label: "李锋", value: "李锋" }
77
+ ],
78
+ approvalStatus: [
79
+ { label: "开立审批中", value: "开立审批中" },
80
+ { label: "审批完成", value: "审批完成" },
81
+ { label: "驳回", value: "驳回" },
82
+ { label: "流程终止", value: "流程终止" }
83
+ ],
84
+ verifyStatus: [
85
+ { label: "已核实", value: "已核实" },
86
+ { label: "未核实", value: "未核实" }
87
+ ]
88
+ };
89
+
90
+ const FORM_ROUTE = "/aiflow/mmwrCustomerApplyChangeForm";
91
+
92
+ function navigateToForm(query?: Record<string, string>) {
93
+ const router = envConfig()?.router;
94
+ if (!router) {
95
+ ElMessage.error("路由未初始化,请刷新页面重试");
96
+ return;
97
+ }
98
+ const target: any = { path: FORM_ROUTE };
99
+ if (query) target.query = query;
100
+ location.href = router.resolve(target).href;
101
+ }
102
+
103
+ export function createPage() {
104
+ const Page = new (class extends AbstractPageQueryHook {
105
+ constructor() {
106
+ super({ url: { list: API_CONFIG.list, remove: API_CONFIG.remove } });
107
+ }
108
+
109
+ queryDef(): BaseQueryItemDesc<any>[] {
110
+ return [
111
+ { name: "customerCode", label: "客户编码", placeholder: "请输入" },
112
+ {
113
+ name: "approvalProduct",
114
+ label: "审批产品别",
115
+ component: () => ({ tag: "jh-select", items: OPTS.approvalProduct })
116
+ },
117
+ {
118
+ name: "applyOrg",
119
+ label: "申请组织",
120
+ component: () => ({ tag: "jh-select", items: OPTS.applyOrg })
121
+ },
122
+ { name: "customerName", label: "客户名称", placeholder: "请输入" },
123
+ {
124
+ name: "applyType",
125
+ label: "申请类型",
126
+ component: () => ({ tag: "jh-select", items: OPTS.applyType })
127
+ },
128
+ {
129
+ name: "applyDept",
130
+ label: "申请部门",
131
+ component: () => ({ tag: "jh-select", items: OPTS.applyDept })
132
+ },
133
+ {
134
+ name: "applicant",
135
+ label: "申请人",
136
+ component: () => ({ tag: "jh-select", items: OPTS.applicant })
137
+ },
138
+ {
139
+ name: "approvalStatus",
140
+ label: "审批状态",
141
+ component: () => ({ tag: "jh-select", items: OPTS.approvalStatus })
142
+ },
143
+ {
144
+ name: "applyDate",
145
+ startName: "applyDateStart",
146
+ endName: "applyDateEnd",
147
+ label: "申请日期",
148
+ component: () => ({
149
+ tag: "jh-date",
150
+ type: "daterange",
151
+ rangeSeparator: "至",
152
+ showFormat: "YYYY-MM-DD",
153
+ valueFormat: "YYYY-MM-DD"
154
+ })
155
+ },
156
+ {
157
+ name: "verifyStatus",
158
+ label: "核实状态",
159
+ component: () => ({ tag: "jh-select", items: OPTS.verifyStatus })
160
+ }
161
+ ];
162
+ }
163
+
164
+ toolbarDef(): ActionButtonDesc[] {
165
+ return [
166
+ { name: "primary", label: "新增申请", onClick: () => navigateToForm() },
167
+ {
168
+ label: "提交",
169
+ type: "primary",
170
+ plain: true,
171
+ onClick: () => {
172
+ const rows = this.tableRef.value?.getSelectionRows();
173
+ if (!rows?.length) {
174
+ ElMessage.warning("请先选择数据");
175
+ return;
176
+ }
177
+ const ids = rows.map((r: any) => r.id);
178
+ ElMessageBox.confirm("确定提交选中申请?", "提示", { type: "info" })
179
+ .then(() => {
180
+ postAction(API_CONFIG.submit, { ids }).then(() => {
181
+ ElMessage.success("提交成功");
182
+ this.select();
183
+ });
184
+ })
185
+ .catch(() => {});
186
+ }
187
+ },
188
+ {
189
+ label: "删除",
190
+ type: "danger",
191
+ plain: true,
192
+ onClick: () => {
193
+ const rows = this.tableRef.value?.getSelectionRows();
194
+ if (!rows?.length) {
195
+ ElMessage.warning("请先选择数据");
196
+ return;
197
+ }
198
+ this.removeBatch();
199
+ }
200
+ },
201
+ {
202
+ label: "审批驳回",
203
+ type: "danger",
204
+ plain: true,
205
+ onClick: () => {
206
+ const rows = this.tableRef.value?.getSelectionRows();
207
+ if (!rows?.length) {
208
+ ElMessage.warning("请先选择数据");
209
+ return;
210
+ }
211
+ const ids = rows.map((r: any) => r.id);
212
+ ElMessageBox.confirm("确定驳回选中申请?", "提示", {
213
+ type: "warning"
214
+ })
215
+ .then(() => {
216
+ postAction(API_CONFIG.update, {
217
+ ids,
218
+ approvalStatus: "驳回"
219
+ }).then(() => {
220
+ ElMessage.success("已驳回");
221
+ this.select();
222
+ });
223
+ })
224
+ .catch(() => {});
225
+ }
226
+ },
227
+ {
228
+ label: "审批通过",
229
+ type: "success",
230
+ plain: true,
231
+ onClick: () => {
232
+ const rows = this.tableRef.value?.getSelectionRows();
233
+ if (!rows?.length) {
234
+ ElMessage.warning("请先选择数据");
235
+ return;
236
+ }
237
+ const ids = rows.map((r: any) => r.id);
238
+ ElMessageBox.confirm("确定审批通过?", "提示", { type: "success" })
239
+ .then(() => {
240
+ postAction(API_CONFIG.update, {
241
+ ids,
242
+ approvalStatus: "审批完成"
243
+ }).then(() => {
244
+ ElMessage.success("审批通过");
245
+ this.select();
246
+ });
247
+ })
248
+ .catch(() => {});
249
+ }
250
+ },
251
+ {
252
+ label: "导出",
253
+ plain: true,
254
+ onClick: () => {
255
+ postAction(API_CONFIG.export, this.queryParam.value).then(() =>
256
+ ElMessage.success("导出成功")
257
+ );
258
+ }
259
+ }
260
+ ];
261
+ }
262
+
263
+ columnsDef(): TableColumnDesc<any>[] {
264
+ return [
265
+ { type: "selection" },
266
+ { type: "index" },
267
+ {
268
+ label: "申请编码",
269
+ name: "applyCode",
270
+ minWidth: 160,
271
+ defaultSlot: ({ row }: any) =>
272
+ h(
273
+ "span",
274
+ {
275
+ style:
276
+ "color:#409eff;cursor:pointer;text-decoration:underline;",
277
+ onClick: () => navigateToForm({ id: row.id })
278
+ },
279
+ row.applyCode
280
+ )
281
+ },
282
+ { label: "申请类型", name: "applyType", minWidth: 100 },
283
+ { label: "客户编码", name: "customerCode", minWidth: 120 },
284
+ {
285
+ label: "客户名称",
286
+ name: "customerName",
287
+ minWidth: 200,
288
+ showOverflowTooltip: true
289
+ },
290
+ { label: "审批产品别", name: "approvalProduct", minWidth: 100 },
291
+ { label: "申请原因", name: "applyReason", minWidth: 120 },
292
+ { label: "申请人", name: "applicant", minWidth: 100 },
293
+ { label: "申请部门", name: "applyDept", minWidth: 130 },
294
+ {
295
+ label: "申请组织",
296
+ name: "applyOrg",
297
+ minWidth: 180,
298
+ showOverflowTooltip: true
299
+ },
300
+ { label: "创建人", name: "creator", minWidth: 100 },
301
+ { label: "创建时间", name: "createTime", minWidth: 160 },
302
+ {
303
+ label: "审批状态",
304
+ name: "approvalStatus",
305
+ minWidth: 110,
306
+ fixed: "right",
307
+ defaultSlot: ({ row }: any) => renderStatusTag(row, "approvalStatus")
308
+ },
309
+ {
310
+ label: "核实状态",
311
+ name: "verifyStatus",
312
+ minWidth: 100,
313
+ fixed: "right",
314
+ defaultSlot: ({ row }: any) => renderStatusTag(row, "verifyStatus")
315
+ },
316
+ {
317
+ label: "操作",
318
+ width: 140,
319
+ fixed: "right",
320
+ operations: [
321
+ {
322
+ name: "edit",
323
+ label: "编辑",
324
+ onClick: (row: any) => navigateToForm({ id: row.id })
325
+ },
326
+ {
327
+ name: "remove",
328
+ label: "删除",
329
+ onClick: (row: any) => this.remove(row.id)
330
+ }
331
+ ]
332
+ }
333
+ ];
334
+ }
335
+ })();
336
+
337
+ return (Page as any).create() as any;
338
+ }
@@ -0,0 +1 @@
1
+ // 新增申请列表页样式
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <div class="app-container app-page-container">
3
+ <BaseQuery :form="queryParam" :items="queryItems" @select="select" @reset="select" />
4
+ <BaseToolbar :items="toolbars" />
5
+ <BaseTable ref="tableRef" :data="list" :columns="columns" showToolbar />
6
+ <jh-pagination
7
+ v-show="page.total && page.total > 0"
8
+ :total="page.total || 0"
9
+ v-model:currentPage="page.current"
10
+ v-model:pageSize="page.size"
11
+ @current-change="select"
12
+ @size-change="select"
13
+ />
14
+ </div>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ import { createPage } from "./data";
19
+
20
+ const Page = createPage();
21
+ const { tableRef, page, queryParam, list, queryItems, columns, toolbars, select } = Page;
22
+
23
+ onMounted(() => select());
24
+ </script>
25
+
26
+ <style scoped lang="scss">
27
+ @import "./index.scss";
28
+ </style>
@@ -0,0 +1,115 @@
1
+ import { postAction, getAction } from "@jhlc/common-core/src/api/action";
2
+ import { ElMessage } from "element-plus";
3
+ import { useRouter } from "vue-router";
4
+ import { createChangeMockData } from "@/components/local/c_customerTabs/data";
5
+ import envConfig from "@jhlc/common-core/src/store/env-config";
6
+
7
+ export const API_CONFIG = {
8
+ getById: "/sale/customerApply/getById",
9
+ save: "/sale/customerApply/save",
10
+ submit: "/sale/customerApply/submit",
11
+ changeHistory: "/sale/customerApply/changeHistory"
12
+ } as const;
13
+
14
+ export function useApplyChangeForm(tabsRef: any) {
15
+ const router = useRouter();
16
+ const loading = ref(false);
17
+ const isEdit = ref(false);
18
+ const currentId = ref<string>("");
19
+
20
+ async function loadDetail(id: string) {
21
+ loading.value = true;
22
+ isEdit.value = true;
23
+ currentId.value = id;
24
+ try {
25
+ const res = await getAction(API_CONFIG.getById, { id });
26
+ if (res?.data) tabsRef.value?.loadData(res.data);
27
+ } finally {
28
+ loading.value = false;
29
+ }
30
+ }
31
+
32
+ function loadMockData() {
33
+ tabsRef.value?.loadData(createChangeMockData());
34
+ }
35
+
36
+ async function handleSave() {
37
+ const valid = await tabsRef.value?.validate();
38
+ if (!valid) {
39
+ ElMessage.warning("请完善必填项");
40
+ return;
41
+ }
42
+ loading.value = true;
43
+ try {
44
+ const formData = tabsRef.value?.collectFormData();
45
+ const payload = isEdit.value
46
+ ? { ...formData, id: currentId.value }
47
+ : formData;
48
+ const res = await postAction(API_CONFIG.save, payload);
49
+ if (res?.code === 200) {
50
+ ElMessage.success("保存成功");
51
+ if (!isEdit.value && res.data?.id) {
52
+ currentId.value = res.data.id;
53
+ isEdit.value = true;
54
+ }
55
+ }
56
+ } finally {
57
+ loading.value = false;
58
+ }
59
+ }
60
+
61
+ async function handleSaveAndChange() {
62
+ const valid = await tabsRef.value?.validate();
63
+ if (!valid) {
64
+ ElMessage.warning("请完善必填项");
65
+ return;
66
+ }
67
+ loading.value = true;
68
+ try {
69
+ const formData = tabsRef.value?.collectFormData();
70
+ const payload = isEdit.value
71
+ ? { ...formData, id: currentId.value }
72
+ : formData;
73
+ const saveRes = await postAction(API_CONFIG.save, payload);
74
+ if (saveRes?.code === 200) {
75
+ const id = currentId.value || saveRes.data?.id;
76
+ const submitRes = await postAction(API_CONFIG.submit, { ids: [id] });
77
+ if (submitRes?.code === 200) ElMessage.success("保存并变更成功");
78
+ }
79
+ } finally {
80
+ loading.value = false;
81
+ }
82
+ }
83
+
84
+ const HISTORY_ROUTE = "/aiflow/mmwrCustomerApplyChangeHistory";
85
+ function handleChangeHistory() {
86
+ if (!currentId.value) {
87
+ ElMessage.warning("请先保存申请后再查看变更历史");
88
+ return;
89
+ }
90
+ const router = envConfig()?.router;
91
+ if (!router) {
92
+ ElMessage.error("路由未初始化,请刷新页面重试");
93
+ return;
94
+ }
95
+ location.href = router.resolve({
96
+ path: HISTORY_ROUTE,
97
+ query: { id: currentId.value }
98
+ }).href;
99
+ }
100
+
101
+ function handleCancel() {
102
+ router.back();
103
+ }
104
+
105
+ return {
106
+ loading,
107
+ isEdit,
108
+ loadDetail,
109
+ loadMockData,
110
+ handleSave,
111
+ handleSaveAndChange,
112
+ handleChangeHistory,
113
+ handleCancel
114
+ };
115
+ }
@@ -0,0 +1,44 @@
1
+ .app-page-container {
2
+ overflow-y: auto;
3
+ padding-bottom: 24px;
4
+ }
5
+
6
+ .page-header {
7
+ display: flex;
8
+ align-items: center;
9
+ margin-bottom: 8px;
10
+
11
+ .page-title {
12
+ font-size: 18px;
13
+ font-weight: 600;
14
+ margin-right: 12px;
15
+ }
16
+
17
+ .page-tag {
18
+ display: inline-block;
19
+ padding: 2px 8px;
20
+ font-size: 12px;
21
+ border-radius: 4px;
22
+ margin-right: 8px;
23
+
24
+ &--add {
25
+ background-color: var(--el-color-primary-light-9);
26
+ color: var(--el-color-primary);
27
+ border: 1px solid var(--el-color-primary-light-7);
28
+ }
29
+
30
+ &--status {
31
+ background-color: var(--el-color-warning-light-9);
32
+ color: var(--el-color-warning);
33
+ border: 1px solid var(--el-color-warning-light-7);
34
+ }
35
+ }
36
+
37
+ .only-required-check {
38
+ margin-left: 8px;
39
+ }
40
+ }
41
+
42
+ .page-toolbar {
43
+ margin-bottom: 12px;
44
+ }
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <div class="app-container app-page-container" v-loading="loading">
3
+ <div class="page-header">
4
+ <span class="page-title">客户申请详情</span>
5
+ <span v-if="isEdit" class="page-tag page-tag--change">变更</span>
6
+ <span class="page-tag page-tag--status">未审核</span>
7
+ <el-checkbox v-model="onlyRequired" class="only-required-check">只看必填项</el-checkbox>
8
+ </div>
9
+ <div class="page-toolbar">
10
+ <el-button type="danger" @click="handleSaveAndChange">保存并变更</el-button>
11
+ <el-button type="warning" @click="handleSave">保存</el-button>
12
+ <el-button type="primary" @click="handleChangeHistory">变更历史查询</el-button>
13
+ <el-button @click="handleCancel">取消</el-button>
14
+ </div>
15
+ <c_customerTabs ref="tabsRef" mode="change" :only-required="onlyRequired" />
16
+ </div>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import { useRoute } from "vue-router";
21
+ import { useApplyChangeForm } from "./data";
22
+ import c_customerTabs from "@/components/local/c_customerTabs/index.vue";
23
+
24
+ const tabsRef = ref();
25
+ const route = useRoute();
26
+ const onlyRequired = ref(false);
27
+
28
+ const { loading, isEdit, loadDetail, loadMockData, handleSave, handleSaveAndChange, handleChangeHistory, handleCancel } =
29
+ useApplyChangeForm(tabsRef);
30
+
31
+ onMounted(() => {
32
+ const id = route.query.id as string;
33
+ if (id) {
34
+ loadDetail(id);
35
+ } else {
36
+ loadMockData();
37
+ }
38
+ });
39
+ </script>
40
+
41
+ <style scoped lang="scss">
42
+ @import "./index.scss";
43
+ </style>