@hzab/data-model 1.8.9-alpha.0 → 2.0.0-alpha.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.
@@ -0,0 +1,583 @@
1
+ import { merge, pickBy, isNil, cloneDeep, isObject } from "lodash";
2
+
3
+ import { _$Temp } from "./utils";
4
+ import ArrayUtils, { STATE_CODE, FindListResult, ItemQuery, ArrayUtilsOptions } from "./ArrayUtils";
5
+
6
+ const errMsg: Record<number | string, string> = {
7
+ 404: "未找到对应子项",
8
+ 501: "未传入表单 id",
9
+ };
10
+
11
+ /**
12
+ * ArrayDataModel 构造函数参数接口
13
+ */
14
+ export interface ArrayDataModelOptions<T = any> extends ArrayUtilsOptions<T> {
15
+ /** 请求 url 替换的额外参数 */
16
+ ctx?: Record<string, any>;
17
+ /** GET 请求的参数 */
18
+ query?: Record<string, any>;
19
+
20
+ /** POST 接口地址 */
21
+ createApi?: string;
22
+ /** POST 接口提交前的数据处理回调 */
23
+ createMap?: (record: T) => T;
24
+ /** GET 详情 接口地址 */
25
+ getApi?: string;
26
+ /** GET 详情 接口返回后的数据处理回调 */
27
+ getMap?: (record: T) => T;
28
+ /** GET 列表 接口地址 */
29
+ getListApi?: string;
30
+ /** GET 列表 接口返回后的数据处理回调 */
31
+ getListMap?: (record: T) => T;
32
+ /** GET 列表 接口回调,用于自定义列表请求接口 */
33
+ getListFunc?: (query: Record<string, any>) => Promise<FindListResult<T>>;
34
+ /** PUT 接口地址 */
35
+ updateApi?: string;
36
+ /** PUT 接口提交前的数据处理回调 */
37
+ updateMap?: (record: T) => T;
38
+ /** PATCH 接口地址 */
39
+ patchApi?: string;
40
+ /** PATCH 接口提交前的数据处理回调 */
41
+ patchMap?: (record: T) => T;
42
+ /** DELETE 接口地址 */
43
+ deleteApi?: string;
44
+ /** DELETE 批量删除 接口地址 */
45
+ multipleDeleteApi?: string;
46
+
47
+ /** GET 列表 接口请求前数据处理回调 */
48
+ getListReqMap?: (params: Record<string, any>) => Record<string, any>;
49
+ /** GET 列表 接口请求结果数据处理回调 */
50
+ getListResMap?: (result: FindListResult<T>) => FindListResult<T>;
51
+ /** GET 详情 接口请求前数据处理回调 */
52
+ getReqMap?: (params: Record<string, any>) => Record<string, any>;
53
+ /** GET 详情 接口请求结果数据处理回调 */
54
+ getResMap?: (record: T) => T;
55
+ /** POST 接口请求前数据处理回调 */
56
+ createReqMap?: (params: Record<string, any>, originalParams?: any) => Record<string, any>;
57
+ /** POST 接口请求结果数据处理回调 */
58
+ createResMap?: (data: Record<string, any>) => Record<string, any>;
59
+ /** PUT 接口请求前数据处理回调 */
60
+ updateReqMap?: (params: Record<string, any>, originalParams?: any) => Record<string, any>;
61
+ /** PUT 接口请求结果数据处理回调 */
62
+ updateResMap?: (data: Record<string, any>) => Record<string, any>;
63
+ /** PATCH 接口请求前数据处理回调 */
64
+ patchReqMap?: (params: Record<string, any>, originalParams?: any) => Record<string, any>;
65
+ /** PATCH 接口请求结果数据处理回调 */
66
+ patchResMap?: (data: Record<string, any>) => Record<string, any>;
67
+ /** DELETE 接口请求前数据处理回调 */
68
+ deleteReqMap?: (config: Record<string, any>) => Record<string, any>;
69
+ /** DELETE 接口请求结果数据处理回调 */
70
+ deleteResMap?: (data: Record<string, any>) => Record<string, any>;
71
+ /** DELETE 批量删除 接口请求前数据处理回调 */
72
+ multipleDeleteReqMap?: (config: Record<string, any>) => Record<string, any>;
73
+ /** DELETE 批量删除 接口请求结果数据处理回调 */
74
+ multipleDeleteResMap?: (data: { sucList: any[]; failList: any[] }) => { sucList: any[]; failList: any[] };
75
+
76
+ /** 查询选项 */
77
+ arrOptions?: ArrOptions;
78
+ }
79
+
80
+ /**
81
+ * 查询选项
82
+ */
83
+ export interface ArrOptions {
84
+ /** 字符串字段是否开启模糊匹配 */
85
+ fuzzy?: boolean;
86
+ /** 模糊匹配时是否忽略大小写 */
87
+ ignoreCase?: boolean;
88
+ }
89
+
90
+ /**
91
+ * 删除请求配置接口
92
+ */
93
+ export interface ArrayDeleteConfig {
94
+ /** axios delete url 参数 */
95
+ params?: Record<string, any>;
96
+ /** axios delete data 参数 */
97
+ data?: Record<string, any>;
98
+ /** 其他 axios delete 配置 */
99
+ [key: string]: any;
100
+ }
101
+
102
+ /**
103
+ * 错误处理选项接口
104
+ */
105
+ export interface HandleMsgOptions {
106
+ /** 是否使用 response.statusText 作为兜底 msg */
107
+ useStatusText?: boolean;
108
+ }
109
+
110
+ /**
111
+ * 批量删除结果接口
112
+ */
113
+ export interface MultipleDeleteResult {
114
+ /** 成功删除的 ID 列表 */
115
+ sucList: any[];
116
+ /** 失败删除的 ID 列表 */
117
+ failList: any[];
118
+ }
119
+
120
+ /**
121
+ * ArrayDataModel 本地数据 DataModel
122
+ * @template T - 数据类型
123
+ */
124
+ class ArrayDataModel<T = any> extends ArrayUtils<T> {
125
+ /** 请求 url 替换的额外参数 */
126
+ ctx: Record<string, any>;
127
+ /** GET 请求的参数 */
128
+ query: Record<string, any>;
129
+
130
+ /** POST 接口地址 */
131
+ createApi?: string;
132
+ /** POST 接口提交前的数据处理回调 */
133
+ createMap?: (record: T) => T;
134
+ /** GET 详情 接口地址 */
135
+ getApi?: string;
136
+ /** GET 详情 接口返回后的数据处理回调 */
137
+ getMap?: (record: T) => T;
138
+ /** GET 列表 接口地址 */
139
+ getListApi?: string;
140
+ /** GET 列表 接口返回后的数据处理回调 */
141
+ getListMap?: (record: T) => T;
142
+ /** GET 列表 接口回调,用于自定义列表请求接口。query => ({list: [], pagination: { total: 0 }}) 优先级高于 getListApi */
143
+ getListFunc?: (query: Record<string, any>) => Promise<FindListResult<T>>;
144
+ /** PUT 接口地址 */
145
+ updateApi?: string;
146
+ /** PUT 接口提交前的数据处理回调 */
147
+ updateMap?: (record: T) => T;
148
+ /** PATCH 接口地址 */
149
+ patchApi?: string;
150
+ /** PATCH 接口提交前的数据处理回调 */
151
+ patchMap?: (record: T) => T;
152
+ /** DELETE 接口地址 */
153
+ deleteApi?: string;
154
+ /** DELETE 批量删除 接口地址 */
155
+ multipleDeleteApi?: string;
156
+
157
+ /** GET 列表 接口请求前数据处理回调 */
158
+ getListReqMap?: (params: Record<string, any>) => Record<string, any>;
159
+ /** GET 列表 接口请求结果数据处理回调 */
160
+ getListResMap?: (result: FindListResult<T>) => FindListResult<T>;
161
+ /** GET 详情 接口请求前数据处理回调 */
162
+ getReqMap?: (params: Record<string, any>) => Record<string, any>;
163
+ /** GET 详情 接口请求结果数据处理回调 */
164
+ getResMap?: (record: T) => T;
165
+ /** POST 接口请求前数据处理回调 */
166
+ createReqMap?: (params: Record<string, any>, originalParams?: any) => Record<string, any>;
167
+ /** POST 接口请求结果数据处理回调 */
168
+ createResMap?: (data: Record<string, any>) => Record<string, any>;
169
+ /** PUT 接口请求前数据处理回调 */
170
+ updateReqMap?: (params: Record<string, any>, originalParams?: any) => Record<string, any>;
171
+ /** PUT 接口请求结果数据处理回调 */
172
+ updateResMap?: (data: Record<string, any>) => Record<string, any>;
173
+ /** PATCH 接口请求前数据处理回调 */
174
+ patchReqMap?: (params: Record<string, any>, originalParams?: any) => Record<string, any>;
175
+ /** PATCH 接口请求结果数据处理回调 */
176
+ patchResMap?: (data: Record<string, any>) => Record<string, any>;
177
+ /** DELETE 接口请求前数据处理回调 */
178
+ deleteReqMap?: (config: Record<string, any>) => Record<string, any>;
179
+ /** DELETE 接口请求结果数据处理回调 */
180
+ deleteResMap?: (data: Record<string, any>) => Record<string, any>;
181
+ /** DELETE 批量删除 接口请求前数据处理回调 */
182
+ multipleDeleteReqMap?: (config: Record<string, any>) => Record<string, any>;
183
+ /** DELETE 批量删除 接口请求结果数据处理回调 */
184
+ multipleDeleteResMap?: (data: MultipleDeleteResult) => MultipleDeleteResult;
185
+
186
+ /** 查询选项 */
187
+ private _arrOptions?: ArrOptions;
188
+
189
+ constructor(params: ArrayDataModelOptions<T> = {} as ArrayDataModelOptions<T>) {
190
+ super(params);
191
+ const {
192
+ ctx,
193
+ query,
194
+ createApi,
195
+ createMap,
196
+ getApi,
197
+ getMap,
198
+ getListApi,
199
+ getListMap,
200
+ getListFunc,
201
+ updateApi,
202
+ updateMap,
203
+ patchApi,
204
+ patchMap,
205
+ deleteApi,
206
+ multipleDeleteApi,
207
+ } = params;
208
+
209
+ this.ctx = ctx || {};
210
+ this.query = query || {};
211
+
212
+ this.createApi = createApi;
213
+ this.createMap = createMap;
214
+ this.getApi = getApi;
215
+ this.getMap = getMap;
216
+ this.getListApi = getListApi;
217
+ this.getListMap = getListMap;
218
+ this.getListFunc = getListFunc;
219
+ this.updateApi = updateApi;
220
+ this.updateMap = updateMap;
221
+ this.patchApi = patchApi;
222
+ this.patchMap = patchMap;
223
+ this.deleteApi = deleteApi;
224
+ this.multipleDeleteApi = multipleDeleteApi;
225
+
226
+ const {
227
+ getListReqMap,
228
+ getListResMap,
229
+ getReqMap,
230
+ getResMap,
231
+ createReqMap,
232
+ createResMap,
233
+ updateReqMap,
234
+ updateResMap,
235
+ patchReqMap,
236
+ patchResMap,
237
+ deleteReqMap,
238
+ deleteResMap,
239
+ multipleDeleteReqMap,
240
+ multipleDeleteResMap,
241
+ arrOptions,
242
+ } = params || {};
243
+
244
+ this.getListReqMap = getListReqMap;
245
+ this.getListResMap = getListResMap;
246
+ this.getReqMap = getReqMap;
247
+ this.getResMap = getResMap;
248
+ this.createReqMap = createReqMap;
249
+ this.createResMap = createResMap;
250
+ this.updateReqMap = updateReqMap;
251
+ this.updateResMap = updateResMap;
252
+ this.patchReqMap = patchReqMap;
253
+ this.patchResMap = patchResMap;
254
+ this.deleteReqMap = deleteReqMap;
255
+ this.deleteResMap = deleteResMap;
256
+ this.multipleDeleteReqMap = multipleDeleteReqMap;
257
+ this.multipleDeleteResMap = multipleDeleteResMap;
258
+ this._arrOptions = arrOptions;
259
+ }
260
+
261
+ /**
262
+ * GET 详情请求
263
+ * @param q query 参数
264
+ * @returns Promise<T>
265
+ */
266
+ get(q: Record<string, any> = {}): Promise<T | null> {
267
+ let query = merge({}, this.query, q);
268
+ query = pickBy(query, (val) => !isNil(val) && val !== "");
269
+
270
+ if (this.getReqMap) {
271
+ query = this.getReqMap(query);
272
+ }
273
+
274
+ return new Promise((resolve) => {
275
+ let res = this.findItem(query, this._arrOptions);
276
+ if (res && this.getMap) {
277
+ res = this.getMap(res);
278
+ }
279
+ if (res && this.getResMap) {
280
+ res = this.getResMap(res);
281
+ }
282
+ resolve(res);
283
+ });
284
+ }
285
+
286
+ /**
287
+ * GET 列表请求
288
+ * @param q query 参数
289
+ * @returns Promise<FindListResult<T>>
290
+ */
291
+ async getList(q: Record<string, any> = {}): Promise<FindListResult<T>> {
292
+ let query = merge({}, this.query, q);
293
+ query = pickBy(query, (val) => !isNil(val) && val !== "");
294
+
295
+ if (this.getListReqMap) {
296
+ query = this.getListReqMap(query);
297
+ }
298
+
299
+ let resultList: FindListResult<T>;
300
+ if (this.getListFunc) {
301
+ resultList = await this.getListFunc(query);
302
+ } else {
303
+ resultList = await this.findListByQuery(query, this._arrOptions);
304
+ }
305
+
306
+ const getListMap = this.getListMap;
307
+ if (getListMap) {
308
+ resultList.list = resultList?.list?.map((record) => getListMap(record));
309
+ }
310
+
311
+ const getListResMap = this.getListResMap;
312
+ if (getListResMap) {
313
+ resultList = getListResMap(resultList);
314
+ }
315
+
316
+ return resultList;
317
+ }
318
+
319
+ /**
320
+ * POST 请求
321
+ * @param params 参数
322
+ * @returns Promise<Record<string, any>>
323
+ */
324
+ create(params: Record<string, any> | FormData): Promise<Record<string, any>> {
325
+ return new Promise((resolve, reject) => {
326
+ const _params = this.handleInputParams(params, this.createReqMap);
327
+ const res = this.pushItem(_params);
328
+ if (res === STATE_CODE.SUC) {
329
+ let _res: Record<string, any> = {};
330
+ if (this.createResMap) {
331
+ _res = this.createResMap(_res);
332
+ }
333
+ resolve(_res);
334
+ } else {
335
+ reject({
336
+ code: res,
337
+ _message: errMsg[res] || "未知错误",
338
+ });
339
+ }
340
+ });
341
+ }
342
+
343
+ /**
344
+ * PUT 请求
345
+ * @param params 参数
346
+ * @returns Promise<Record<string, any>>
347
+ */
348
+ update(params: Record<string, any> | FormData): Promise<Record<string, any>> {
349
+ return new Promise((resolve, reject) => {
350
+ const _params = this.handleInputParams(params, this.updateReqMap);
351
+ const res = this.replaceItem(_params as T);
352
+ if (res === STATE_CODE.SUC) {
353
+ let _res: Record<string, any> = {};
354
+ if (this.updateResMap) {
355
+ _res = this.updateResMap(_res);
356
+ }
357
+ resolve(_res);
358
+ } else {
359
+ reject({
360
+ code: res,
361
+ _message: errMsg[res] || "未知错误",
362
+ });
363
+ }
364
+ });
365
+ }
366
+
367
+ /**
368
+ * PATCH 请求
369
+ * @param params 参数
370
+ * @returns Promise<Record<string, any>>
371
+ */
372
+ patch(params: Record<string, any> | FormData): Promise<Record<string, any>> {
373
+ return new Promise((resolve, reject) => {
374
+ const _params = this.handleInputParams(params, this.patchReqMap);
375
+ const res = this.updateItemValue(_params);
376
+ if (res === STATE_CODE.SUC) {
377
+ let _res: Record<string, any> = {};
378
+ if (this.patchResMap) {
379
+ _res = this.patchResMap(_res);
380
+ }
381
+ resolve(_res);
382
+ } else {
383
+ reject({
384
+ code: res,
385
+ _message: errMsg[res] || "未知错误",
386
+ });
387
+ }
388
+ });
389
+ }
390
+
391
+ /**
392
+ * 删除接口
393
+ * @param config axios.delete config 参数
394
+ * @param config.params axios.delete url 参数
395
+ * @param config.data axios.delete data 参数
396
+ * @param ctx url 替换的额外参数
397
+ * @returns Promise<Record<string, any>>
398
+ */
399
+ delete(config?: ArrayDeleteConfig, ctx?: Record<string, any>): Promise<Record<string, any>> {
400
+ let _config = cloneDeep(config) || {};
401
+ if (this.deleteReqMap) {
402
+ _config = this.deleteReqMap(_config);
403
+ }
404
+ return new Promise((resolve, reject) => {
405
+ const { _idKey } = this;
406
+ const id = (config as any)?.[_idKey] || config?.params?.[_idKey] || config?.data?.[_idKey] || ctx?.[_idKey];
407
+ const res = this.delItem(id);
408
+ if (res === STATE_CODE.SUC) {
409
+ let _res: Record<string, any> = {};
410
+ if (this.deleteResMap) {
411
+ _res = this.deleteResMap(_res);
412
+ }
413
+ resolve(_res);
414
+ } else {
415
+ reject({
416
+ code: res,
417
+ _message: errMsg[res] || "未知错误",
418
+ });
419
+ }
420
+ });
421
+ }
422
+
423
+ /**
424
+ * 批量删除接口
425
+ * @param config axios.delete config 参数
426
+ * @param config.params axios.delete url 参数
427
+ * @param config.data axios.delete data 参数
428
+ * @param ctx url 替换的额外参数
429
+ * @returns Promise<MultipleDeleteResult>
430
+ */
431
+ multipleDelete(config?: ArrayDeleteConfig, ctx?: Record<string, any>): Promise<MultipleDeleteResult> {
432
+ let _config = cloneDeep(config) || {};
433
+ if (this.multipleDeleteReqMap) {
434
+ _config = this.multipleDeleteReqMap(_config);
435
+ }
436
+ return new Promise((resolve, reject) => {
437
+ const { _idKey } = this;
438
+ let ids = (config as any)?.[_idKey] || config?.params?.[_idKey] || config?.data?.[_idKey] || ctx?.[_idKey];
439
+
440
+ if (typeof ids === "string") {
441
+ ids = ids.split(",");
442
+ }
443
+
444
+ if (Array.isArray(ids)) {
445
+ const sucList: any[] = [];
446
+ const failList: any[] = [];
447
+ ids.forEach((id: any) => {
448
+ try {
449
+ const res = this.delItem(id);
450
+ if (res === STATE_CODE.SUC) {
451
+ sucList.push(id);
452
+ } else {
453
+ failList.push(id);
454
+ }
455
+ } catch (error) {
456
+ console.log("error", error);
457
+ }
458
+ });
459
+ if (sucList.length > 0) {
460
+ let _res: MultipleDeleteResult = { sucList, failList };
461
+ if (this.multipleDeleteResMap) {
462
+ _res = this.multipleDeleteResMap(_res);
463
+ }
464
+ resolve(_res);
465
+ } else {
466
+ reject({ failList });
467
+ }
468
+ return;
469
+ }
470
+
471
+ reject({});
472
+ });
473
+ }
474
+
475
+ /**
476
+ * 处理传入的数据
477
+ * @param params 参数
478
+ * @param reqMapFn 请求前处理函数
479
+ * @returns 处理后的参数
480
+ */
481
+ handleInputParams(
482
+ params: any,
483
+ reqMapFn?: (params: Record<string, any>, originalParams?: any) => Record<string, any>,
484
+ ): Record<string, any> {
485
+ let _params = cloneDeep(params);
486
+ if (reqMapFn) {
487
+ _params = reqMapFn.bind(this)(_params, params);
488
+ }
489
+ // TODO: FormData 文件存储?
490
+ // if (params instanceof FormData) {
491
+ // _params = objToFormData(_params);
492
+ // }
493
+ return _params;
494
+ }
495
+
496
+ /**
497
+ * 处理响应结果
498
+ * @param response 响应对象
499
+ * @param resolve 成功回调
500
+ * @param reject 失败回调
501
+ */
502
+ handleRes(response: any, resolve: (res: any) => void, reject: (err: any) => void): void {
503
+ if (typeof response !== "object") {
504
+ reject(new Error("response not object"));
505
+ return;
506
+ }
507
+ let _res = response;
508
+ // 兼容 传入的是 response.data 的情况
509
+ if (_res.data && _res.headers && _res.request) {
510
+ _res = _res.data;
511
+ }
512
+ const { code, data } = _res;
513
+ const message = this.handleMsg(response);
514
+ if (code == 200) {
515
+ const _data = data ?? {};
516
+ if (isObject(_data)) {
517
+ if (_data.content && _data.pageNumber && _data.total) {
518
+ _data.list = _data.content;
519
+ _data.pagination = { current: _data.pageNumber, total: _data.total };
520
+ }
521
+ // 前缀 _ 避免与 data 里已有的 message 冲突
522
+ _data._msg = message;
523
+ _data._message = message;
524
+ }
525
+ resolve(_data);
526
+ } else {
527
+ const error = new Error(message);
528
+ (error as any).code = code;
529
+ (error as any).response = response;
530
+ (error as any)._msg = message;
531
+ (error as any)._message = message;
532
+ reject(error);
533
+ }
534
+ }
535
+
536
+ /**
537
+ * 错误处理器
538
+ * @param err 错误对象
539
+ * @param reject Promise reject 回调
540
+ */
541
+ errorHandler(err: any = {}, reject: (err: any) => void): void {
542
+ const response = err.response || err;
543
+ if (response) {
544
+ const message = this.handleMsg(response, { useStatusText: true });
545
+ const error = new Error(message);
546
+ (error as any).code = response.status;
547
+ (error as any).response = response;
548
+ if (message) {
549
+ // 前缀 _ 避免与 data 里已有的 message 冲突
550
+ (error as any)._message = message;
551
+ (error as any)._msg = message;
552
+ }
553
+ reject(error);
554
+ return;
555
+ }
556
+ reject(err || { _msg: _$Temp.defaultErrMsg });
557
+ }
558
+
559
+ /**
560
+ * 处理错误消息
561
+ * @param response 响应对象
562
+ * @param opt 选项
563
+ * @returns 错误消息
564
+ */
565
+ handleMsg(
566
+ response: any,
567
+ opt: HandleMsgOptions = {
568
+ useStatusText: false,
569
+ },
570
+ ): string {
571
+ const { useStatusText } = opt || {};
572
+ let message = (response.data && (response.data.message || response.data.msg)) || response.msg || response.message;
573
+ if (!message && useStatusText) {
574
+ message = response.statusText;
575
+ }
576
+
577
+ return message || _$Temp.defaultErrMsg;
578
+ }
579
+ }
580
+
581
+ export { ArrayDataModel };
582
+
583
+ export default ArrayDataModel;