@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,601 @@
1
+ import {
2
+ AbstractPageQueryHook,
3
+ BaseQueryItemDesc,
4
+ ActionButtonDesc,
5
+ TableColumnDesc
6
+ } from "@/types/page";
7
+ import type { BaseFormItemDesc } from "@jhlc/common-core/src/components/form/common/type";
8
+ import { postAction } from "@jhlc/common-core/src/api/action";
9
+ import * as XLSX from "xlsx";
10
+ import { h, resolveComponent } from "vue";
11
+
12
+ /** 状态色块映射 */
13
+ const STATUS_TAG_MAP: Record<string, Record<string, string>> = {
14
+ enableStatus: { 已启用: "success", 已停用: "danger" }
15
+ };
16
+ function renderStatusTag(row: any, field: string) {
17
+ const val = row[field];
18
+ const type = STATUS_TAG_MAP[field]?.[val];
19
+ if (type === undefined) return val;
20
+ return h(
21
+ resolveComponent("ElTag") as any,
22
+ { type, effect: "light", size: "small" },
23
+ () => val
24
+ );
25
+ }
26
+
27
+ export const API_CONFIG = {
28
+ list: "/sale/customerArchive/list",
29
+ remove: "/sale/customerArchive/remove",
30
+ getById: "/sale/customerArchive/getById",
31
+ save: "/sale/customerArchive/save",
32
+ update: "/sale/customerArchive/update",
33
+ export: "/sale/customerArchive/export",
34
+ batchUpdate: "/sale/customerArchive/batchUpdate",
35
+ enable: "/sale/customerArchive/enable",
36
+ disable: "/sale/customerArchive/disable",
37
+ import: "/sale/customerArchive/import"
38
+ } as const;
39
+
40
+ /** 下拉选项常量 */
41
+ const OPTS = {
42
+ approvalProduct: [
43
+ { label: "热轧", value: "热轧" },
44
+ { label: "盘元", value: "盘元" },
45
+ { label: "冷精", value: "冷精" },
46
+ { label: "汽车", value: "汽车" }
47
+ ],
48
+ applyOrg: [
49
+ { label: "不锈鋼接單中心", value: "不锈鋼接單中心" },
50
+ {
51
+ label: "江阴华新特殊合金材料有限公司",
52
+ value: "江阴华新特殊合金材料有限公司"
53
+ },
54
+ { label: "採瞒管理中心", value: "採瞒管理中心" },
55
+ { label: "烟台华鑫再生资源有限公司", value: "烟台华鑫再生资源有限公司" }
56
+ ],
57
+ applyType: [
58
+ { label: "新增", value: "新增" },
59
+ { label: "变更", value: "变更" }
60
+ ],
61
+ applicant: [
62
+ { label: "魏子明", value: "魏子明" },
63
+ { label: "龚辉鉴", value: "龚辉鉴" },
64
+ { label: "宋书迪", value: "宋书迪" },
65
+ { label: "李锋", value: "李锋" },
66
+ { label: "杨松", value: "杨松" },
67
+ { label: "王之勤", value: "王之勤" },
68
+ { label: "邹建军", value: "邹建军" },
69
+ { label: "龙成金", value: "龙成金" }
70
+ ],
71
+ applyDept: [
72
+ { label: "業務管理處", value: "業務管理處" },
73
+ { label: "線材銷售部", value: "線材銷售部" },
74
+ { label: "無縫管銷售處", value: "無縫管銷售處" },
75
+ { label: "華南銷售科", value: "華南銷售科" },
76
+ { label: "汽車產業銷售科", value: "汽車產業銷售科" },
77
+ { label: "大陸行銷部", value: "大陸行銷部" },
78
+ { label: "冷精棒業管部(台北)", value: "冷精棒業管部(台北)" },
79
+ { label: "業管科", value: "業管科" },
80
+ { label: "華東銷售科", value: "華東銷售科" }
81
+ ],
82
+ approvalStatus: [
83
+ { label: "开立审批中", value: "开立审批中" },
84
+ { label: "审批完成", value: "审批完成" },
85
+ { label: "流程终止", value: "流程终止" },
86
+ { label: "驳回", value: "驳回" }
87
+ ],
88
+ verifyStatus: [
89
+ { label: "未核实", value: "未核实" },
90
+ { label: "已核实", value: "已核实" }
91
+ ],
92
+ enableStatus: [
93
+ { label: "已启用", value: "已启用" },
94
+ { label: "已停用", value: "已停用" }
95
+ ],
96
+ customerType: [
97
+ { label: "交易客户", value: "交易客户" },
98
+ { label: "非交易客户", value: "非交易客户" }
99
+ ],
100
+ relatedPartyType: [
101
+ { label: "01-关联企业", value: "01-关联企业" },
102
+ { label: "02-合并关系人", value: "02-合并关系人" },
103
+ { label: "03-非关系人", value: "03-非关系人" },
104
+ { label: "04-实质关系人", value: "04-实质关系人" }
105
+ ],
106
+ customerLevel: [
107
+ { label: "大客户(B1)", value: "大客户(B1)" },
108
+ { label: "一般客户(A1)", value: "一般客户(A1)" }
109
+ ],
110
+ customerClassify: [
111
+ { label: "01-一级管厂", value: "01-一级管厂" },
112
+ { label: "02-二级管厂", value: "02-二级管厂" },
113
+ { label: "03-其他", value: "03-其他" },
114
+ { label: "04-长约经销商", value: "04-长约经销商" },
115
+ { label: "05-锻造及机加工", value: "05-锻造及机加工" }
116
+ ],
117
+ customerNature: [
118
+ { label: "001-直接客户", value: "001-直接客户" },
119
+ { label: "002-盘商", value: "002-盘商" },
120
+ { label: "003-贸易商", value: "003-贸易商" },
121
+ { label: "004-非交易-未分类", value: "004-非交易-未分类" }
122
+ ]
123
+ };
124
+
125
+ export { OPTS };
126
+
127
+ /** c_formModal 配置 */
128
+ export const modalConfig = {
129
+ titlePrefix: "客户",
130
+ width: "850px",
131
+ columns: 2,
132
+ labelWidth: "110px",
133
+ formItems: [
134
+ {
135
+ name: "customerCode",
136
+ label: "客户编码",
137
+ disabled: true,
138
+ placeholder: "系统自动生成"
139
+ },
140
+ {
141
+ name: "customerName",
142
+ label: "客户名称",
143
+ required: true,
144
+ placeholder: "请输入客户名称"
145
+ },
146
+ {
147
+ name: "customerShortName",
148
+ label: "客户简称",
149
+ placeholder: "请输入客户简称"
150
+ },
151
+ {
152
+ name: "customerType",
153
+ label: "客户类型",
154
+ required: true,
155
+ component: () => ({ tag: "jh-select", items: OPTS.customerType })
156
+ },
157
+ {
158
+ name: "country",
159
+ label: "国家/地区",
160
+ component: () => ({
161
+ tag: "jh-select",
162
+ items: [
163
+ { label: "中国大陆", value: "中国大陆" },
164
+ { label: "日本", value: "日本" },
165
+ { label: "韩国", value: "韩国" },
166
+ { label: "美国", value: "美国" }
167
+ ]
168
+ })
169
+ },
170
+ {
171
+ name: "currency",
172
+ label: "交易币种",
173
+ component: () => ({
174
+ tag: "jh-select",
175
+ items: [
176
+ { label: "CNY", value: "CNY" },
177
+ { label: "USD", value: "USD" },
178
+ { label: "JPY", value: "JPY" }
179
+ ]
180
+ })
181
+ },
182
+ {
183
+ name: "taxCategory",
184
+ label: "纳税类别",
185
+ component: () => ({
186
+ tag: "jh-select",
187
+ items: [
188
+ { label: "一般纳税人", value: "一般纳税人" },
189
+ { label: "小规模纳税人", value: "小规模纳税人" },
190
+ { label: "海外纳税", value: "海外纳税" }
191
+ ]
192
+ })
193
+ },
194
+ {
195
+ name: "enableStatus",
196
+ label: "启用状态",
197
+ component: () => ({ tag: "jh-select", items: OPTS.enableStatus })
198
+ }
199
+ ] as BaseFormItemDesc<any>[],
200
+ api: {
201
+ getById: API_CONFIG.getById,
202
+ save: API_CONFIG.save,
203
+ update: API_CONFIG.update
204
+ }
205
+ };
206
+
207
+ let _editModalRef: any = null;
208
+
209
+ /** 查看客户详情(打开弹窗-查看模式) */
210
+ function handleCustomerCodeClick(row: any) {
211
+ _editModalRef?.value?.view(row.id);
212
+ }
213
+
214
+ /** 管理视角列定义 */
215
+ export function managementColumns(): TableColumnDesc<any>[] {
216
+ return [
217
+ { type: "selection" },
218
+ { type: "index" },
219
+ {
220
+ label: "客户编码",
221
+ name: "customerCode",
222
+ minWidth: 120,
223
+ defaultSlot: ({ row }: any) => {
224
+ return h(
225
+ "span",
226
+ {
227
+ style:
228
+ "color: #409eff; cursor: pointer; text-decoration: underline;",
229
+ onClick: () => handleCustomerCodeClick(row)
230
+ },
231
+ row.customerCode
232
+ );
233
+ }
234
+ },
235
+ {
236
+ label: "客户名称",
237
+ name: "customerName",
238
+ minWidth: 189,
239
+ showOverflowTooltip: true
240
+ },
241
+ { label: "客户简称", name: "customerShortName", minWidth: 116 },
242
+ { label: "客户类型", name: "customerType", minWidth: 105 },
243
+ { label: "国家/地区", name: "country", minWidth: 100 },
244
+ { label: "交易币种", name: "currency", minWidth: 93 },
245
+ { label: "纳税类别", name: "taxCategory", minWidth: 100 },
246
+ { label: "关系人分类", name: "relatedPartyType", minWidth: 122 },
247
+ {
248
+ label: "上级客户",
249
+ name: "parentCustomer",
250
+ minWidth: 119,
251
+ showOverflowTooltip: true
252
+ },
253
+ { label: "集团", name: "groupName", minWidth: 113 },
254
+ { label: "建立人", name: "creator", minWidth: 100 },
255
+ { label: "建立时间", name: "createTime", minWidth: 165 },
256
+ {
257
+ label: "申请组织",
258
+ name: "applyOrg",
259
+ minWidth: 150,
260
+ showOverflowTooltip: true
261
+ },
262
+ {
263
+ label: "启用状态",
264
+ name: "enableStatus",
265
+ minWidth: 100,
266
+ fixed: "right",
267
+ defaultSlot: ({ row }: any) => renderStatusTag(row, "enableStatus")
268
+ },
269
+ { label: "停用时间", name: "disableTime", minWidth: 157, fixed: "right" },
270
+ {
271
+ label: "操作",
272
+ width: 100,
273
+ fixed: "right",
274
+ operations: [
275
+ {
276
+ name: "edit",
277
+ label: "编辑",
278
+ onClick: (row: any) => _editModalRef?.value?.edit(row.id)
279
+ },
280
+ {
281
+ name: "remove",
282
+ label: "删除",
283
+ onClick: (row: any) => Page?.remove(row.id)
284
+ }
285
+ ]
286
+ }
287
+ ];
288
+ }
289
+
290
+ /** 使用视角列定义(含业务字段) */
291
+ export function usageColumns(): TableColumnDesc<any>[] {
292
+ return [
293
+ { type: "selection" },
294
+ { type: "index" },
295
+ {
296
+ label: "客户编码",
297
+ name: "customerCode",
298
+ minWidth: 120,
299
+ defaultSlot: ({ row }: any) => {
300
+ return h(
301
+ "span",
302
+ {
303
+ style:
304
+ "color: #409eff; cursor: pointer; text-decoration: underline;",
305
+ onClick: () => handleCustomerCodeClick(row)
306
+ },
307
+ row.customerCode
308
+ );
309
+ }
310
+ },
311
+ {
312
+ label: "客户名称",
313
+ name: "customerName",
314
+ minWidth: 189,
315
+ showOverflowTooltip: true
316
+ },
317
+ { label: "客户简称", name: "customerShortName", minWidth: 116 },
318
+ { label: "客户类型", name: "customerType", minWidth: 105 },
319
+ { label: "国家/地区", name: "country", minWidth: 100 },
320
+ { label: "交易币种", name: "currency", minWidth: 93 },
321
+ { label: "纳税类别", name: "taxCategory", minWidth: 100 },
322
+ { label: "关系人分类", name: "relatedPartyType", minWidth: 122 },
323
+ {
324
+ label: "上级客户",
325
+ name: "parentCustomer",
326
+ minWidth: 119,
327
+ showOverflowTooltip: true
328
+ },
329
+ { label: "集团", name: "groupName", minWidth: 113 },
330
+ {
331
+ label: "使用组织",
332
+ name: "useOrg",
333
+ minWidth: 160,
334
+ showOverflowTooltip: true
335
+ },
336
+ { label: "销售别", name: "salesType", minWidth: 100 },
337
+ { label: "客户性质", name: "customerNature", minWidth: 100 },
338
+ { label: "客户分类", name: "customerClassify", minWidth: 140 },
339
+ { label: "客户级别", name: "customerLevel", minWidth: 120 },
340
+ { label: "业务人员", name: "businessPerson", minWidth: 120 },
341
+ { label: "业务部门", name: "businessDept", minWidth: 140 },
342
+ { label: "收款协议", name: "paymentAgreement", minWidth: 140 },
343
+ { label: "银承贴息", name: "bankAcceptanceDiscount", minWidth: 120 },
344
+ { label: "免息天数", name: "interestFreeDays", minWidth: 100 },
345
+ { label: "主要行业", name: "mainIndustry", minWidth: 120 },
346
+ { label: "下游行业", name: "downstreamIndustry", minWidth: 140 },
347
+ { label: "采购钢种", name: "steelType", minWidth: 120 },
348
+ { label: "需求产品型态", name: "demandProductType", minWidth: 130 },
349
+ { label: "月需求量", name: "monthDemand", minWidth: 100 },
350
+ { label: "授信额度", name: "creditLimit", minWidth: 120 },
351
+ { label: "佣金否", name: "commission", minWidth: 80 },
352
+ { label: "备注", name: "remark", minWidth: 120, showOverflowTooltip: true },
353
+ { label: "建立人", name: "creator", minWidth: 100 },
354
+ { label: "建立时间", name: "createTime", minWidth: 165 },
355
+ {
356
+ label: "申请组织",
357
+ name: "applyOrg",
358
+ minWidth: 150,
359
+ showOverflowTooltip: true
360
+ },
361
+ {
362
+ label: "启用状态",
363
+ name: "enableStatus",
364
+ minWidth: 124,
365
+ fixed: "right",
366
+ defaultSlot: ({ row }: any) => renderStatusTag(row, "enableStatus")
367
+ },
368
+ { label: "停用时间", name: "disableTime", minWidth: 157, fixed: "right" },
369
+ {
370
+ label: "操作",
371
+ width: 100,
372
+ fixed: "right",
373
+ operations: [
374
+ {
375
+ name: "edit",
376
+ label: "编辑",
377
+ onClick: (row: any) => _editModalRef?.value?.edit(row.id)
378
+ },
379
+ {
380
+ name: "remove",
381
+ label: "删除",
382
+ onClick: (row: any) => Page?.remove(row.id)
383
+ }
384
+ ]
385
+ }
386
+ ];
387
+ }
388
+
389
+ let Page: any = null;
390
+
391
+ export function createPage(editModalRef?: any) {
392
+ _editModalRef = editModalRef;
393
+
394
+ let Page_inst = new (class extends AbstractPageQueryHook {
395
+ constructor() {
396
+ super({ url: { list: API_CONFIG.list, remove: API_CONFIG.remove } });
397
+ }
398
+
399
+ queryDef(): BaseQueryItemDesc<any>[] {
400
+ return [
401
+ { name: "customerCode", label: "客户编码", placeholder: "请输入" },
402
+ {
403
+ name: "approvalProduct",
404
+ label: "审批产品别",
405
+ component: () => ({ tag: "jh-select", items: OPTS.approvalProduct })
406
+ },
407
+ {
408
+ name: "applyDate",
409
+ startName: "applyDateStart",
410
+ endName: "applyDateEnd",
411
+ label: "申请日期",
412
+ component: () => ({
413
+ tag: "jh-date",
414
+ type: "daterange",
415
+ rangeSeparator: "至",
416
+ showFormat: "YYYY-MM-DD",
417
+ valueFormat: "YYYY-MM-DD"
418
+ })
419
+ },
420
+ {
421
+ name: "applyOrg",
422
+ label: "申请组织",
423
+ component: () => ({ tag: "jh-select", items: OPTS.applyOrg })
424
+ },
425
+ { name: "customerName", label: "客户名称", placeholder: "请输入" },
426
+ {
427
+ name: "applyType",
428
+ label: "申请类型",
429
+ component: () => ({ tag: "jh-select", items: OPTS.applyType })
430
+ },
431
+ {
432
+ name: "applicant",
433
+ label: "申请人",
434
+ component: () => ({ tag: "jh-select", items: OPTS.applicant })
435
+ },
436
+ {
437
+ name: "applyDept",
438
+ label: "申请部门",
439
+ component: () => ({ tag: "jh-select", items: OPTS.applyDept })
440
+ },
441
+ {
442
+ name: "approvalStatus",
443
+ label: "审批状态",
444
+ component: () => ({ tag: "jh-select", items: OPTS.approvalStatus })
445
+ },
446
+ {
447
+ name: "verifyStatus",
448
+ label: "核实状态",
449
+ component: () => ({ tag: "jh-select", items: OPTS.verifyStatus })
450
+ }
451
+ ];
452
+ }
453
+
454
+ toolbarDef(): ActionButtonDesc[] {
455
+ return [
456
+ {
457
+ name: "primary",
458
+ label: "新增申请",
459
+ onClick: () => _editModalRef?.value?.open()
460
+ },
461
+ {
462
+ label: "变更申请",
463
+ plain: true,
464
+ onClick: () => _editModalRef?.value?.open()
465
+ },
466
+ {
467
+ label: "批量修改",
468
+ plain: true,
469
+ onClick: () => {
470
+ const rows = this.tableRef.value?.getSelectionRows();
471
+ if (!rows?.length) {
472
+ ElMessage.warning("请先选择数据");
473
+ return;
474
+ }
475
+ ElMessage.info("批量修改功能开发中");
476
+ }
477
+ },
478
+ {
479
+ label: "导入",
480
+ plain: true,
481
+ onClick: () => {
482
+ const input = document.createElement("input");
483
+ input.type = "file";
484
+ input.accept = ".xlsx,.xls";
485
+ input.onchange = async (e: any) => {
486
+ const file = e.target.files?.[0];
487
+ if (!file) return;
488
+ try {
489
+ const buf = await file.arrayBuffer();
490
+ const wb = XLSX.read(buf, { type: "array" });
491
+ const rows = XLSX.utils.sheet_to_json(
492
+ wb.Sheets[wb.SheetNames[0]]
493
+ ) as any[];
494
+ if (!rows.length) {
495
+ ElMessage.warning("文件无有效数据");
496
+ return;
497
+ }
498
+ await postAction(API_CONFIG.import, { rows });
499
+ ElMessage.success(`导入成功 ${rows.length} 条`);
500
+ this.select();
501
+ } catch {
502
+ ElMessage.error("导入失败,请检查文件格式");
503
+ }
504
+ };
505
+ input.click();
506
+ }
507
+ },
508
+ {
509
+ label: "导出",
510
+ plain: true,
511
+ onClick: async () => {
512
+ const data = this.list.value;
513
+ if (!data?.length) {
514
+ ElMessage.warning("无数据可导出");
515
+ return;
516
+ }
517
+ const exportData = data.map((row: any) => ({
518
+ 客户编码: row.customerCode,
519
+ 客户名称: row.customerName,
520
+ 客户简称: row.customerShortName,
521
+ 客户类型: row.customerType,
522
+ "国家/地区": row.country,
523
+ 交易币种: row.currency,
524
+ 纳税类别: row.taxCategory,
525
+ 启用状态: row.enableStatus,
526
+ 建立时间: row.createTime
527
+ }));
528
+ const ws = XLSX.utils.json_to_sheet(exportData);
529
+ const wb = XLSX.utils.book_new();
530
+ XLSX.utils.book_append_sheet(wb, ws, "客户档案");
531
+ XLSX.writeFile(wb, "客户档案.xlsx");
532
+ ElMessage.success("导出成功");
533
+ }
534
+ },
535
+ {
536
+ name: "primary",
537
+ label: "启用",
538
+ onClick: () => {
539
+ const rows = this.tableRef.value?.getSelectionRows();
540
+ if (!rows?.length) {
541
+ ElMessage.warning("请先选择数据");
542
+ return;
543
+ }
544
+ const ids = rows.map((r: any) => r.id);
545
+ ElMessageBox.confirm("确定启用选中客户?", "提示", { type: "info" })
546
+ .then(() => {
547
+ postAction(API_CONFIG.enable, { ids }).then(() => {
548
+ ElMessage.success("启用成功");
549
+ this.select();
550
+ });
551
+ })
552
+ .catch(() => {});
553
+ }
554
+ },
555
+ {
556
+ name: "warning",
557
+ label: "停用",
558
+ onClick: () => {
559
+ const rows = this.tableRef.value?.getSelectionRows();
560
+ if (!rows?.length) {
561
+ ElMessage.warning("请先选择数据");
562
+ return;
563
+ }
564
+ const ids = rows.map((r: any) => r.id);
565
+ ElMessageBox.confirm("确定停用选中客户?", "提示", {
566
+ type: "warning"
567
+ })
568
+ .then(() => {
569
+ postAction(API_CONFIG.disable, { ids }).then(() => {
570
+ ElMessage.success("停用成功");
571
+ this.select();
572
+ });
573
+ })
574
+ .catch(() => {});
575
+ }
576
+ },
577
+ {
578
+ name: "danger",
579
+ label: "删除",
580
+ onClick: () => {
581
+ const rows = this.tableRef.value?.getSelectionRows();
582
+ if (!rows?.length) {
583
+ ElMessage.warning("请先选择数据");
584
+ return;
585
+ }
586
+ this.removeBatch();
587
+ }
588
+ }
589
+ ];
590
+ }
591
+
592
+ columnsDef(): TableColumnDesc<any>[] {
593
+ return managementColumns();
594
+ }
595
+ })();
596
+
597
+ Page = Page_inst;
598
+ let result = (Page_inst as any).create() as any;
599
+
600
+ return result;
601
+ }
@@ -0,0 +1 @@
1
+ // 客户档案 - 页面样式
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <div class="app-container app-page-container">
3
+ <BaseQuery
4
+ :form="queryParam"
5
+ :items="queryItems"
6
+ @select="select"
7
+ @reset="select"
8
+ />
9
+ <BaseToolbar :items="toolbars" />
10
+ <el-tabs v-model="activeView">
11
+ <el-tab-pane label="管理视角" name="management">
12
+ <BaseTable
13
+ v-if="activeView === 'management'"
14
+ ref="tableRef"
15
+ :data="list"
16
+ :columns="mgmtCols"
17
+ showToolbar
18
+ />
19
+ </el-tab-pane>
20
+ <el-tab-pane label="使用视角" name="usage">
21
+ <BaseTable
22
+ v-if="activeView === 'usage'"
23
+ ref="tableRef"
24
+ :data="list"
25
+ :columns="useCols"
26
+ showToolbar
27
+ />
28
+ </el-tab-pane>
29
+ </el-tabs>
30
+ <jh-pagination
31
+ v-show="page.total && page.total > 0"
32
+ :total="page.total || 0"
33
+ v-model:currentPage="page.current"
34
+ v-model:pageSize="page.size"
35
+ @current-change="select"
36
+ @size-change="select"
37
+ />
38
+ <c_formModal ref="editModalRef" v-bind="modalConfig" @ok="select" />
39
+ </div>
40
+ </template>
41
+
42
+ <script setup lang="ts">
43
+ import {
44
+ createPage,
45
+ modalConfig,
46
+ managementColumns,
47
+ usageColumns
48
+ } from "./data";
49
+ import c_formModal from "@/components/local/c_formModal/index.vue";
50
+
51
+ const editModalRef = ref();
52
+ const Page = createPage(editModalRef);
53
+ const { tableRef, page, queryParam, list, queryItems, toolbars, select } = Page;
54
+
55
+ const activeView = ref("management");
56
+ const mgmtCols = managementColumns();
57
+ const useCols = usageColumns();
58
+
59
+ onMounted(() => select());
60
+ </script>
61
+
62
+ <style scoped lang="scss">
63
+ @import "./index.scss";
64
+ </style>