@ibiz-template/core 0.0.1-beta.1 → 0.0.1-beta.130

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 (64) hide show
  1. package/dist/system/index.system.js +1 -1
  2. package/out/constant/core/core.d.ts +9 -0
  3. package/out/constant/core/core.d.ts.map +1 -1
  4. package/out/constant/core/core.js +9 -0
  5. package/out/context/index.d.ts +63 -4
  6. package/out/context/index.d.ts.map +1 -1
  7. package/out/context/index.js +73 -3
  8. package/out/environment/environment.d.ts.map +1 -1
  9. package/out/environment/environment.js +5 -0
  10. package/out/error/http-error/http-error.d.ts.map +1 -1
  11. package/out/error/http-error/http-error.js +0 -4
  12. package/out/interface/click-outside/click-outside.d.ts +1 -1
  13. package/out/interface/click-outside/click-outside.d.ts.map +1 -1
  14. package/out/interface/i-environment/i-environment.d.ts +36 -0
  15. package/out/interface/i-environment/i-environment.d.ts.map +1 -1
  16. package/out/types.d.ts +31 -0
  17. package/out/types.d.ts.map +1 -1
  18. package/out/utils/download-file/download-file.d.ts +10 -0
  19. package/out/utils/download-file/download-file.d.ts.map +1 -1
  20. package/out/utils/download-file/download-file.js +20 -0
  21. package/out/utils/index.d.ts +4 -0
  22. package/out/utils/index.d.ts.map +1 -1
  23. package/out/utils/index.js +4 -0
  24. package/out/utils/net/net.d.ts +18 -1
  25. package/out/utils/net/net.d.ts.map +1 -1
  26. package/out/utils/net/net.js +29 -3
  27. package/out/utils/plural/plural.d.ts.map +1 -1
  28. package/out/utils/plural/plural.js +2 -0
  29. package/out/utils/string-util/string-util.d.ts +46 -0
  30. package/out/utils/string-util/string-util.d.ts.map +1 -0
  31. package/out/utils/string-util/string-util.js +71 -0
  32. package/out/utils/sync/await-timeout.d.ts +14 -0
  33. package/out/utils/sync/await-timeout.d.ts.map +1 -0
  34. package/out/utils/sync/await-timeout.js +23 -0
  35. package/out/utils/sync/count-latch.d.ts +60 -0
  36. package/out/utils/sync/count-latch.d.ts.map +1 -0
  37. package/out/utils/sync/count-latch.js +90 -0
  38. package/out/utils/sync/index.d.ts +3 -0
  39. package/out/utils/sync/index.d.ts.map +1 -0
  40. package/out/utils/sync/index.js +2 -0
  41. package/out/utils/upload/select-file.d.ts +53 -0
  42. package/out/utils/upload/select-file.d.ts.map +1 -0
  43. package/out/utils/upload/select-file.js +47 -0
  44. package/out/utils/upload/upload-file.d.ts +46 -0
  45. package/out/utils/upload/upload-file.d.ts.map +1 -0
  46. package/out/utils/upload/upload-file.js +150 -0
  47. package/package.json +7 -6
  48. package/src/constant/core/core.ts +10 -0
  49. package/src/context/index.ts +115 -5
  50. package/src/environment/environment.ts +5 -0
  51. package/src/error/http-error/http-error.ts +0 -4
  52. package/src/interface/i-environment/i-environment.ts +41 -0
  53. package/src/types.ts +35 -0
  54. package/src/utils/download-file/download-file.ts +21 -0
  55. package/src/utils/index.ts +4 -0
  56. package/src/utils/net/net.ts +31 -3
  57. package/src/utils/plural/plural.ts +3 -0
  58. package/src/utils/string-util/string-util.ts +75 -0
  59. package/src/utils/sync/await-timeout.ts +27 -0
  60. package/src/utils/sync/count-latch.ts +96 -0
  61. package/src/utils/sync/index.ts +2 -0
  62. package/src/utils/upload/select-file.ts +86 -0
  63. package/src/utils/upload/upload-file.ts +206 -0
  64. package/LICENSE +0 -21
@@ -0,0 +1,150 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
2
+ /* eslint-disable no-param-reassign */
3
+ import { cloneDeep, isFunction, merge, round, uniqueId } from 'lodash-es';
4
+ import { selectFile } from './select-file';
5
+ /**
6
+ * 使用上传文件逻辑
7
+ *
8
+ * @author lxm
9
+ * @date 2022-11-20 21:11:52
10
+ * @export
11
+ * @param {IUploadFileOpts} _opts
12
+ * @returns {*}
13
+ */
14
+ export function uploadFile(_opts) {
15
+ const opts = merge({
16
+ multiple: true,
17
+ accept: '',
18
+ separate: true,
19
+ beforeUpload: (_fileData, _files) => true,
20
+ finish: (_resultFiles) => { },
21
+ success: (_resultFiles, _res) => { },
22
+ error: (_resultFiles, _error) => { },
23
+ progress: (_files) => { },
24
+ }, _opts);
25
+ /**
26
+ * 进度条回调
27
+ *
28
+ * @author lxm
29
+ * @date 2022-11-20 21:11:47
30
+ * @param {IParams} event
31
+ * @param {IUploadFile[]} files
32
+ */
33
+ const onUploadProgress = (event, files) => {
34
+ files.forEach(file => {
35
+ file.percentage = round(event.progress * 100);
36
+ });
37
+ opts.progress(cloneDeep(files));
38
+ };
39
+ /**
40
+ * 上传请求方法,返回响应对象
41
+ *
42
+ * @author lxm
43
+ * @date 2022-11-18 13:11:57
44
+ * @param {File[]} files
45
+ * @returns {*} {Promise<HttpResponse>}
46
+ */
47
+ const uploadRequest = async (files, onProgress) => {
48
+ // 自定义上传请求
49
+ if (opts.request && isFunction(opts.request)) {
50
+ return opts.request(files);
51
+ }
52
+ // 默认每次单个文件上传,可能存在接口一次上传多个文件,
53
+ const data = new FormData();
54
+ files.forEach(file => {
55
+ data.append('file', file);
56
+ });
57
+ const res = await ibiz.net.request(opts.uploadUrl, {
58
+ method: 'post',
59
+ baseURL: '',
60
+ data,
61
+ headers: { 'Content-Type': 'multipart/form-data' },
62
+ onUploadProgress: onProgress,
63
+ });
64
+ return res;
65
+ };
66
+ /**
67
+ * 执行一次上传,可能是一个文件也可能是多个文件
68
+ *
69
+ * @author lxm
70
+ * @date 2022-11-18 14:11:54
71
+ * @param {File[]} files 此次上传文件的集合
72
+ * @returns {*} {Promise<IUploadFile[]>}
73
+ */
74
+ const executeSingleUpload = async (files) => {
75
+ const resultFiles = files.map(file => {
76
+ return {
77
+ status: 'uploading',
78
+ name: file.name,
79
+ uid: uniqueId(),
80
+ percentage: 0,
81
+ };
82
+ });
83
+ // 上传前回调,可以取消此次下载
84
+ const pass = opts.beforeUpload(files, resultFiles);
85
+ if (!pass) {
86
+ resultFiles.forEach(file => {
87
+ file.status = 'cancel';
88
+ });
89
+ ibiz.log.debug('取消上传', resultFiles);
90
+ return resultFiles;
91
+ }
92
+ try {
93
+ const res = await uploadRequest(files, event => {
94
+ onUploadProgress(event, resultFiles);
95
+ });
96
+ resultFiles.forEach(file => {
97
+ file.status = 'finished';
98
+ });
99
+ // 上传成功事件
100
+ opts.success(resultFiles, res);
101
+ resultFiles.forEach(file => {
102
+ file.response = res;
103
+ });
104
+ }
105
+ catch (error) {
106
+ resultFiles.forEach(file => {
107
+ file.status = 'fail';
108
+ });
109
+ // 上传失败事件
110
+ opts.error(resultFiles, error);
111
+ resultFiles.forEach(file => {
112
+ file.error = error;
113
+ });
114
+ ibiz.log.error(error);
115
+ ibiz.log.error(`${files.map(file => file.name).join(',')}上传失败`);
116
+ }
117
+ return resultFiles;
118
+ };
119
+ /**
120
+ * 执行上传文件逻辑
121
+ *
122
+ * @author lxm
123
+ * @date 2022-11-18 13:11:21
124
+ * @param {files} File[] 文件集合
125
+ */
126
+ const uploadFiles = async (files) => {
127
+ const uploadSequence = opts.separate ? files.map(file => [file]) : [files];
128
+ const res = await Promise.allSettled(uploadSequence.map(async (sequence) => {
129
+ return executeSingleUpload(sequence);
130
+ }));
131
+ // 整合所有的返回文件
132
+ const resultFiles = [];
133
+ res.forEach(result => {
134
+ if (result.status === 'fulfilled') {
135
+ resultFiles.push(...result.value);
136
+ }
137
+ });
138
+ opts.finish(resultFiles);
139
+ };
140
+ const select = () => {
141
+ selectFile({
142
+ accept: opts.accept,
143
+ multiple: opts.multiple,
144
+ onSelected: files => {
145
+ uploadFiles(files);
146
+ },
147
+ });
148
+ };
149
+ select();
150
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibiz-template/core",
3
- "version": "0.0.1-beta.1",
3
+ "version": "0.0.1-beta.130",
4
4
  "description": "核心包",
5
5
  "type": "module",
6
6
  "main": "out/index.js",
@@ -30,7 +30,7 @@
30
30
  "author": "chitanda",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "axios": "^1.1.3",
33
+ "axios": "^1.2.1",
34
34
  "loglevel": "^1.8.0",
35
35
  "pluralize": "^8.0.0",
36
36
  "qs": "^6.11.0"
@@ -39,11 +39,12 @@
39
39
  "@types/pluralize": "^0.0.29",
40
40
  "@types/qs": "^6.9.7",
41
41
  "lodash-es": "^4.17.21",
42
- "qx-util": "^0.4.4"
42
+ "qx-util": "^0.4.8",
43
+ "ramda": "^0.28.0"
43
44
  },
44
45
  "peerDependencies": {
45
46
  "lodash-es": "^4.17.21",
46
- "qx-util": "^0.4.4"
47
- },
48
- "gitHead": "9514cbc720208af6160c67bc43e822262274da1f"
47
+ "qx-util": "^0.4.8",
48
+ "ramda": "^0.28.0"
49
+ }
49
50
  }
@@ -20,4 +20,14 @@ export class CoreConst {
20
20
  * @static
21
21
  */
22
22
  static readonly TOKEN = 'access_token';
23
+
24
+ /**
25
+ * 访问令牌标识过期时间
26
+ *
27
+ * @author lxm
28
+ * @date 2023-02-13 07:11:33
29
+ * @static
30
+ * @memberof CoreConst
31
+ */
32
+ static readonly TOKEN_EXPIRES = 'access_token_expires';
23
33
  }
@@ -1,3 +1,5 @@
1
+ import { clone } from 'ramda';
2
+
1
3
  /**
2
4
  * 上下文处理类
3
5
  *
@@ -10,24 +12,65 @@ export class IBizContext implements IContext {
10
12
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
13
  [key: string | symbol]: any;
12
14
 
13
- protected _context!: IContext;
15
+ /**
16
+ * clone 后引用的上下文实例,需要在实例销毁时,同时销毁
17
+ *
18
+ * @author chitanda
19
+ * @date 2023-03-13 16:03:31
20
+ * @protected
21
+ * @type {IBizContext[]}
22
+ */
23
+ protected declare _associationContext: IBizContext[];
24
+
25
+ /**
26
+ * 修改的父上下文
27
+ *
28
+ * @author lxm
29
+ * @date 2022-12-08 18:12:16
30
+ * @protected
31
+ * @type {IData}
32
+ */
33
+ protected declare _context: IData;
34
+
35
+ /**
36
+ * 父的上下文源对象
37
+ *
38
+ * @author lxm
39
+ * @date 2022-12-08 18:12:31
40
+ * @type {IContext}
41
+ */
42
+ declare _parent?: IContext;
14
43
 
15
44
  /**
16
45
  * Creates an instance of IBizContext.
17
46
  *
18
47
  * @author chitanda
19
48
  * @date 2022-07-14 10:07:15
20
- * @param {IContext} [context={}] 自身的上下文
21
- * @param {IBizContext} [parent]
49
+ * @param {IData} [context={}] 自身的上下文
50
+ * @param {IContext} [parent]
22
51
  */
23
52
  // eslint-disable-next-line default-param-last
24
- constructor(context: IContext = {}, parent?: IBizContext) {
53
+ private constructor(context: IData = {}, parent?: IContext) {
54
+ Object.defineProperty(this, '_associationContext', {
55
+ enumerable: false,
56
+ value: [],
57
+ });
58
+
25
59
  if (parent) {
26
60
  // eslint-disable-next-line @typescript-eslint/no-this-alias
27
61
  const self = this;
28
- // 定义私有变量,用于存储父已有上下文,方便覆盖
62
+
63
+ // 定义私有变量,存放父上下文源对象
64
+ Object.defineProperty(this, '_parent', {
65
+ enumerable: false,
66
+ writable: true,
67
+ value: parent,
68
+ });
69
+
70
+ // 定义私有变量,用于存储对父已有上下文的修改。
29
71
  Object.defineProperty(this, '_context', {
30
72
  enumerable: false,
73
+ writable: true,
31
74
  value: {},
32
75
  });
33
76
  // 监控父上下文参数,自身不存在时从父取
@@ -56,4 +99,71 @@ export class IBizContext implements IContext {
56
99
  // 合并给入上下文
57
100
  Object.assign(this, context);
58
101
  }
102
+
103
+ /**
104
+ * 返回自身的上下文,独有的和与父有差异的。
105
+ *
106
+ * @author lxm
107
+ * @date 2022-12-08 17:12:26
108
+ * @returns {*} {IData}
109
+ */
110
+ getOwnContext(): IData {
111
+ const result: IData = {};
112
+ Object.keys(this).forEach(key => {
113
+ // 父没有的,或者修改了父的上下文
114
+ // 父不存在则返回所有自身的属性
115
+ if (
116
+ !this._parent ||
117
+ !Object.prototype.hasOwnProperty.call(this._parent, key) ||
118
+ Object.prototype.hasOwnProperty.call(this._context, key)
119
+ ) {
120
+ result[key] = this[key];
121
+ }
122
+ });
123
+ return result;
124
+ }
125
+
126
+ /**
127
+ * 销毁当前上下文对象
128
+ *
129
+ * @author chitanda
130
+ * @date 2023-03-13 15:03:04
131
+ */
132
+ destroy(): void {
133
+ this._parent = undefined;
134
+ this._context = {};
135
+ this._associationContext.forEach(item => {
136
+ item.destroy();
137
+ });
138
+ }
139
+
140
+ /**
141
+ * 在非视图中,需要断开视图上下文联系时。只能使用 clone 创建新的局部上下文
142
+ *
143
+ * @author chitanda
144
+ * @date 2023-03-13 16:03:13
145
+ * @return {*} {IBizContext}
146
+ */
147
+ clone(): IBizContext {
148
+ const newContext = new IBizContext(
149
+ clone(this.getOwnContext()),
150
+ this._parent,
151
+ );
152
+ this._associationContext.push(newContext);
153
+ return newContext;
154
+ }
155
+
156
+ /**
157
+ * 上下文只有在视图初始化时,调用 create 方法
158
+ *
159
+ * @author chitanda
160
+ * @date 2023-03-13 16:03:32
161
+ * @static
162
+ * @param {IData} [context]
163
+ * @param {IContext} [parent]
164
+ * @return {*} {IContext}
165
+ */
166
+ static create(context?: IData, parent?: IContext): IBizContext {
167
+ return new IBizContext(context, parent);
168
+ }
59
169
  }
@@ -19,4 +19,9 @@ export const Environment: IEnvironment = {
19
19
  loginMode: LoginMode.DEFAULT,
20
20
  menuPermissionMode: MenuPermissionMode.MIXIN,
21
21
  enablePermission: true,
22
+ enableWfAllHistory: false,
23
+ routePlaceholder: '-',
24
+ loginViewName: 'AppLoginView',
25
+ version: '0.0.1',
26
+ favicon: './favicon.ico',
22
27
  };
@@ -1,5 +1,4 @@
1
1
  import { AxiosError, AxiosResponse } from 'axios';
2
- import { HttpStatusMessageConst } from '../../constant';
3
2
 
4
3
  /**
5
4
  * 请求异常
@@ -28,9 +27,6 @@ export class HttpError implements Error {
28
27
  } else {
29
28
  this.message = res.statusText;
30
29
  }
31
- if (!this.message) {
32
- this.message = HttpStatusMessageConst[res.status];
33
- }
34
30
  if (!this.message) {
35
31
  this.message = '网络异常,请稍后重试!';
36
32
  }
@@ -146,4 +146,45 @@ export interface IEnvironment {
146
146
  * @type {MenuPermissionMode}
147
147
  */
148
148
  menuPermissionMode: MenuPermissionMode;
149
+
150
+ /**
151
+ * 是否让所有工作流history接口走all
152
+ *
153
+ * @type {boolean}
154
+ * @memberof IEnvironment
155
+ */
156
+ enableWfAllHistory: boolean;
157
+
158
+ /**
159
+ * 路由占位符
160
+ *
161
+ * @type {string}
162
+ * @memberof IEnvironment
163
+ */
164
+ routePlaceholder: string;
165
+
166
+ /**
167
+ * 登录页视图组件名称
168
+ *
169
+ * @type {string}
170
+ * @memberof IEnvironment
171
+ */
172
+ loginViewName: string;
173
+
174
+ /**
175
+ * 版本
176
+ *
177
+ * @type {string}
178
+ * @memberof IEnvironment
179
+ */
180
+ version: string;
181
+
182
+ /**
183
+ * 应用图标地址
184
+ *
185
+ * @author chitanda
186
+ * @date 2023-07-17 17:07:23
187
+ * @type {string}
188
+ */
189
+ favicon?: string;
149
190
  }
package/src/types.ts CHANGED
@@ -27,6 +27,41 @@ declare global {
27
27
  */
28
28
  interface IContext {
29
29
  [key: string | symbol]: any;
30
+
31
+ /**
32
+ * 沙箱标识
33
+ *
34
+ * @author chitanda
35
+ * @date 2022-07-22 15:07:23
36
+ * @type {string}
37
+ */
38
+ srfsandbox?: string;
39
+
40
+ /**
41
+ * 返回自身的上下文,独有的和与父有差异的
42
+ *
43
+ * @author chitanda
44
+ * @date 2023-03-13 17:03:10
45
+ * @return {*} {IData}
46
+ */
47
+ getOwnContext(): IData;
48
+
49
+ /**
50
+ * 销毁当前上下文
51
+ *
52
+ * @author chitanda
53
+ * @date 2023-03-13 17:03:37
54
+ */
55
+ destroy(): void;
56
+
57
+ /**
58
+ * 克隆当前上下文
59
+ *
60
+ * @author chitanda
61
+ * @date 2023-03-13 17:03:45
62
+ * @return {*} {IContext}
63
+ */
64
+ clone(): IContext;
30
65
  }
31
66
 
32
67
  /**
@@ -51,12 +51,33 @@ export function calcMimeByFileName(fileName: string) {
51
51
  case '.tar':
52
52
  mime = 'application/x-tar';
53
53
  break;
54
+ case '.xlsx':
55
+ mime = 'application/vnd.ms-excel';
56
+ break;
54
57
  default:
55
58
  mime = '';
56
59
  }
57
60
  return mime;
58
61
  }
59
62
 
63
+ /**
64
+ * 判断是否是图片格式
65
+ *
66
+ * @author lxm
67
+ * @date 2022-11-21 13:11:23
68
+ * @export
69
+ * @param {string} fileName
70
+ * @returns {*} {boolean}
71
+ */
72
+ export function isImage(fileName: string): boolean {
73
+ const ext = fileName.split('.').pop();
74
+ if (!ext) {
75
+ return false;
76
+ }
77
+ const imageTypes = ['.jpeg', 'jpg', 'gif', 'png', 'bmp', 'svg'];
78
+ return imageTypes.includes(ext);
79
+ }
80
+
60
81
  /**
61
82
  * 纯JS触发下载文件
62
83
  *
@@ -10,3 +10,7 @@ export * from './event/event';
10
10
  export * from './click-outside/click-outside';
11
11
  export * from './color/color';
12
12
  export * from './download-file/download-file';
13
+ export * from './upload/select-file';
14
+ export * from './upload/upload-file';
15
+ export * from './sync';
16
+ export { StringUtil } from './string-util/string-util';
@@ -10,6 +10,7 @@ import { merge } from 'lodash-es';
10
10
  import { stringify } from 'qs';
11
11
  import { notNilEmpty } from 'qx-util';
12
12
  import { HttpError } from '../../error';
13
+ import { CoreInterceptor } from '../interceptor';
13
14
  import { Interceptor } from '../interceptor/interceptor';
14
15
  import { IHttpResponse } from './http-response';
15
16
 
@@ -32,6 +33,15 @@ export class Net {
32
33
  */
33
34
  protected instance: AxiosInstance;
34
35
 
36
+ /**
37
+ * 是否为 http || https 开头
38
+ *
39
+ * @author chitanda
40
+ * @date 2022-11-07 14:11:28
41
+ * @protected
42
+ */
43
+ protected urlReg = /^http[s]?:\/\/[^\s]*/;
44
+
35
45
  /**
36
46
  * Creates an instance of Net.
37
47
  * @author lxm
@@ -40,6 +50,7 @@ export class Net {
40
50
  */
41
51
  constructor(config?: CreateAxiosDefaults) {
42
52
  this.instance = axios.create(config);
53
+ this.addInterceptor('Default', new CoreInterceptor());
43
54
  }
44
55
 
45
56
  /**
@@ -91,7 +102,7 @@ export class Net {
91
102
  protected get presetConfig(): AxiosRequestConfig {
92
103
  return {
93
104
  // 请求前缀路径
94
- baseURL: this.instance.defaults.baseURL || ibiz.env.baseUrl,
105
+ baseURL: ibiz.env.baseUrl,
95
106
  headers: {
96
107
  'Content-Type': 'application/json;charset=UTF-8',
97
108
  Accept: 'application/json',
@@ -109,10 +120,15 @@ export class Net {
109
120
  * @returns {*}
110
121
  */
111
122
  protected mergeConfig(...configs: AxiosRequestConfig[]) {
123
+ const config = this.presetConfig;
112
124
  if (configs.length === 0) {
113
- return this.presetConfig;
125
+ return config;
126
+ }
127
+ const { url } = configs[0];
128
+ if (url && this.urlReg.test(url)) {
129
+ delete config.baseURL;
114
130
  }
115
- return merge(this.presetConfig, ...configs);
131
+ return merge(config, ...configs);
116
132
  }
117
133
 
118
134
  /**
@@ -278,6 +294,18 @@ export class Net {
278
294
  }
279
295
  }
280
296
 
297
+ /**
298
+ * 创建标准 axios 请求
299
+ *
300
+ * @author chitanda
301
+ * @date 2023-01-30 15:01:27
302
+ * @param {AxiosRequestConfig<IData>} config
303
+ * @return {*}
304
+ */
305
+ axios(config: AxiosRequestConfig<IData>) {
306
+ return axios(config);
307
+ }
308
+
281
309
  /**
282
310
  * 统一处理请求返回
283
311
  *
@@ -1,5 +1,8 @@
1
1
  import pluralize from 'pluralize';
2
2
 
3
+ // 补充特殊转换规则
4
+ pluralize.addPluralRule(/(matr|vert|ind)ix|ex$/, '$1ices');
5
+
3
6
  /**
4
7
  * 英文转复数写法
5
8
  *
@@ -0,0 +1,75 @@
1
+ import { notNilEmpty } from 'qx-util';
2
+
3
+ /**
4
+ * 字符串工具类
5
+ *
6
+ * @author chitanda
7
+ * @date 2021-04-23 20:04:27
8
+ * @export
9
+ * @class StringUtil
10
+ */
11
+ export class StringUtil {
12
+ /**
13
+ * 上下文替换正则
14
+ *
15
+ * @author chitanda
16
+ * @date 2021-04-23 20:04:01
17
+ * @static
18
+ */
19
+ static contextReg = /\$\{context.[a-zA-Z_$][a-zA-Z0-9_$]{1,}\}/g;
20
+
21
+ /**
22
+ * 数据替换正则
23
+ *
24
+ * @author chitanda
25
+ * @date 2021-04-23 20:04:09
26
+ * @static
27
+ */
28
+ static dataReg = /\$\{data.[a-zA-Z_$][a-zA-Z0-9_$]{1,}\}/g;
29
+
30
+ /**
31
+ * 填充字符串中的数据
32
+ *
33
+ * @author chitanda
34
+ * @date 2021-04-23 20:04:17
35
+ * @static
36
+ * @param {string} str
37
+ * @param {*} [context]
38
+ * @param {*} [data]
39
+ * @return {*} {string}
40
+ */
41
+ static fill(str: string, context?: IContext, data?: IData): string {
42
+ if (notNilEmpty(str)) {
43
+ if (notNilEmpty(context)) {
44
+ const strArr = str.match(this.contextReg);
45
+ strArr?.forEach(_key => {
46
+ const key = _key.slice(10, _key.length - 1);
47
+ str = str.replace(`\${context.${key}}`, context![key] || '');
48
+ });
49
+ }
50
+ if (notNilEmpty(data)) {
51
+ const strArr = str.match(this.dataReg);
52
+ strArr?.forEach(_key => {
53
+ const key = _key.slice(7, _key.length - 1);
54
+ str = str.replace(`\${data.${key}}`, data![key] || '');
55
+ });
56
+ }
57
+ }
58
+ return str;
59
+ }
60
+
61
+ /**
62
+ * 动态匹配${}
63
+ *
64
+ * @param str
65
+ * @param values
66
+ */
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ static dynamicMatch(str: string, values: any): string {
69
+ return str.replace(/\${(.*?)}/g, (_, key) => {
70
+ const [objKey, propName] = key.split('.');
71
+ const obj = values[objKey];
72
+ return obj ? obj[propName] : '';
73
+ });
74
+ }
75
+ }
@@ -0,0 +1,27 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /**
3
+ * 设置延迟wait毫米后执行fun方法,返回fun的返回值
4
+ *
5
+ * @author lxm
6
+ * @date 2023-03-06 08:20:57
7
+ * @export
8
+ * @template T
9
+ * @param {number} wait
10
+ * @param {T} fun
11
+ * @param {any[]} params
12
+ * @returns {*} {Promise<ReturnType<T>>}
13
+ */
14
+ export async function awaitTimeout<T extends (...args: any) => any>(
15
+ wait: number,
16
+ fun?: T,
17
+ params?: any[],
18
+ ): Promise<ReturnType<T> | undefined> {
19
+ await new Promise(resolve => {
20
+ setTimeout(() => {
21
+ resolve(true);
22
+ }, wait);
23
+ });
24
+ if (fun) {
25
+ return fun(...(params || []));
26
+ }
27
+ }