@lingxiteam/ebe-utils 0.0.24 → 0.0.27
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.
- package/es/index.d.ts +1 -0
- package/es/index.js +50 -42
- package/lib/h5public/src/hooks/usePageForm.ts +30 -3
- package/lib/h5public/yarn.lock +19383 -0
- package/lib/pcpublic/src/components/pcfactory/src/Table/hooks/useRowEdit.ts +4 -2
- package/lib/pcpublic/src/hooks/usePageForm.ts +5 -3
- package/lib/pcpublic/src/utils/exportCustomData/index.tsx +726 -0
- package/lib/pcpublic/src/utils/exportCustomData/tool.ts +399 -0
- package/lib/pcpublic/src/utils/messageApi.ts +25 -20
- package/lib/pcpublic/yarn.lock +11441 -0
- package/lib/public/src/components/ProgressComp/index.tsx +4 -14
- package/lib/public/src/hooks/useBaseDataSource.ts +2 -1
- package/lib/public/src/services/api/engine.ts +19 -0
- package/lib/public/src/utils/cmd.ts +455 -0
- package/lib/public/src/utils/useComponentHoc.ts +6 -3
- package/package.json +2 -2
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import {
|
|
2
|
+
closeProgressMsg,
|
|
3
|
+
openProgressMsg,
|
|
4
|
+
showProgressNotification,
|
|
5
|
+
} from '@/components/ProgressComp';
|
|
6
|
+
import { APPID } from '@/constants';
|
|
7
|
+
import engineServices from '@/services/api/engine';
|
|
8
|
+
import fileServices from '@/services/api/file';
|
|
9
|
+
import { messageApi } from '@/utils/messageApi';
|
|
10
|
+
import security from '@/utils/Security';
|
|
11
|
+
/**
|
|
12
|
+
* 文件保存方法
|
|
13
|
+
* @param data
|
|
14
|
+
* @param filename
|
|
15
|
+
*/
|
|
16
|
+
const saveBlobFile = ({ data, fileName }: any) => {
|
|
17
|
+
if (typeof (window as any).chrome !== 'undefined') {
|
|
18
|
+
// chrome
|
|
19
|
+
const link = document.createElement('a');
|
|
20
|
+
let href = window.URL.createObjectURL(new Blob([data]));
|
|
21
|
+
const format = typeof fileName === 'string' && fileName.split('.').pop();
|
|
22
|
+
if (/(csv|xls)$/.test(format as string) && typeof data === 'string') {
|
|
23
|
+
href = `data:text/${format};charset=utf-8,\ufeff${encodeURIComponent(
|
|
24
|
+
data,
|
|
25
|
+
)}`;
|
|
26
|
+
}
|
|
27
|
+
link.href = href; // eslint-disable-line
|
|
28
|
+
link.download = fileName;
|
|
29
|
+
link.click();
|
|
30
|
+
} else if (typeof (window as any).navigator.msSaveBlob !== 'undefined') {
|
|
31
|
+
// ie
|
|
32
|
+
const blob = new Blob([data], {
|
|
33
|
+
type: 'application/force-download',
|
|
34
|
+
}); // eslint-disable-line
|
|
35
|
+
(window as any).navigator.msSaveBlob(blob, fileName);
|
|
36
|
+
} else {
|
|
37
|
+
// firefox
|
|
38
|
+
const file = new File([data], fileName, {
|
|
39
|
+
type: 'application/force-download',
|
|
40
|
+
}); // eslint-disable-line
|
|
41
|
+
window.open(URL.createObjectURL(file));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const getFileName = (fileContentStr: string, newFileName?: string) => {
|
|
46
|
+
let fileName: string = '';
|
|
47
|
+
let suffix: string = '';
|
|
48
|
+
if (fileContentStr) {
|
|
49
|
+
fileName =
|
|
50
|
+
fileContentStr.split('filename=').pop()?.replace(/\"/g, '') || '';
|
|
51
|
+
const result = fileContentStr.match(
|
|
52
|
+
/(?:.*filename\*|filename)=(?:([^'"]*)''|("))([^;]+)\2(?:[;`\n]|$)/,
|
|
53
|
+
);
|
|
54
|
+
if (result && result[3]) {
|
|
55
|
+
fileName = result[3].replace(/['"]/g, '').replace(/[+]/g, '%20');
|
|
56
|
+
}
|
|
57
|
+
suffix = fileName.split('.').pop() || '';
|
|
58
|
+
fileName = decodeURIComponent(fileName);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (newFileName) {
|
|
62
|
+
if (!/\./.test(newFileName)) {
|
|
63
|
+
fileName = `${newFileName}.${suffix}`;
|
|
64
|
+
} else {
|
|
65
|
+
fileName = newFileName;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return fileName;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const isErrorStatus = (status: number) => {
|
|
72
|
+
switch (status) {
|
|
73
|
+
case 400:
|
|
74
|
+
case 401:
|
|
75
|
+
case 403:
|
|
76
|
+
case 404:
|
|
77
|
+
case 500:
|
|
78
|
+
case 501:
|
|
79
|
+
case 502:
|
|
80
|
+
case 503:
|
|
81
|
+
case 413:
|
|
82
|
+
return true;
|
|
83
|
+
default:
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const exportServiceMap = {
|
|
89
|
+
sql: engineServices.exportSqlDatasByAsync,
|
|
90
|
+
object: engineServices.exportInstsByAsync,
|
|
91
|
+
multiExport: engineServices.exportMultiServiceResultByAsync,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const exportPathMap = {
|
|
95
|
+
sql: engineServices.exportSqlDatasApiPath(),
|
|
96
|
+
object: engineServices.exportInstsApiPath(),
|
|
97
|
+
multiExport: engineServices.exportMultiServiceResultPath(),
|
|
98
|
+
};
|
|
99
|
+
const downloadByXMLHttpRequest = (params: {
|
|
100
|
+
newFileName?: string;
|
|
101
|
+
onError?: any;
|
|
102
|
+
methodPath: string;
|
|
103
|
+
downloadIndex?: string;
|
|
104
|
+
}) => {
|
|
105
|
+
const { newFileName, onError, methodPath, downloadIndex } = params;
|
|
106
|
+
|
|
107
|
+
if (window.XMLHttpRequest) {
|
|
108
|
+
const xhr = new XMLHttpRequest(); // ActiveXObject只存在于IE7及以下,无需兼容
|
|
109
|
+
xhr.open('GET', methodPath, true);
|
|
110
|
+
xhr.responseType = 'blob'; // 设置接受类型
|
|
111
|
+
const headers: any = {
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
|
+
// 'X-B-TARGET-ID': pageId,
|
|
114
|
+
'X-B-AUTH': '1',
|
|
115
|
+
'APP-ID': APPID,
|
|
116
|
+
};
|
|
117
|
+
Object.keys(headers).forEach((header) => {
|
|
118
|
+
xhr.setRequestHeader(header, headers[header]); // 设置请求头参数
|
|
119
|
+
});
|
|
120
|
+
xhr.setRequestHeader(
|
|
121
|
+
'X-SIGN',
|
|
122
|
+
security.createHttpSignStr(methodPath, {
|
|
123
|
+
method: 'GET',
|
|
124
|
+
headers,
|
|
125
|
+
body: '',
|
|
126
|
+
search: '',
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
xhr.withCredentials = true;
|
|
130
|
+
xhr.onprogress = (evt) => {
|
|
131
|
+
// 展示下载进度条
|
|
132
|
+
if (evt.lengthComputable) {
|
|
133
|
+
const percentComplete = Math.round((evt.loaded * 100) / evt.total);
|
|
134
|
+
openProgressMsg(downloadIndex, newFileName, percentComplete, '下载');
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
xhr.onload = async () => {
|
|
138
|
+
const data = xhr.response; // 获取响应体数据
|
|
139
|
+
if (xhr.status === 200) {
|
|
140
|
+
const fileName: string = getFileName(
|
|
141
|
+
xhr.getResponseHeader('Content-Disposition') || '',
|
|
142
|
+
newFileName,
|
|
143
|
+
);
|
|
144
|
+
saveBlobFile({
|
|
145
|
+
data,
|
|
146
|
+
fileName,
|
|
147
|
+
});
|
|
148
|
+
} else if (isErrorStatus(xhr.status)) {
|
|
149
|
+
messageApi.error('下载失败');
|
|
150
|
+
} else {
|
|
151
|
+
const errMessage = data;
|
|
152
|
+
let errorMessage = '';
|
|
153
|
+
try {
|
|
154
|
+
errorMessage = JSON.parse(errMessage)?.message || '下载失败';
|
|
155
|
+
} catch {
|
|
156
|
+
errorMessage = '下载失败';
|
|
157
|
+
}
|
|
158
|
+
messageApi.error(errorMessage);
|
|
159
|
+
if (typeof onError === 'function') {
|
|
160
|
+
onError(errorMessage);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
closeProgressMsg(downloadIndex);
|
|
164
|
+
};
|
|
165
|
+
xhr.ontimeout = () => {
|
|
166
|
+
xhr.abort(); // 取消请求
|
|
167
|
+
};
|
|
168
|
+
xhr.send();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 批量文件下载
|
|
174
|
+
* @param fileId
|
|
175
|
+
* @param newFileName
|
|
176
|
+
* @param onError
|
|
177
|
+
* @param messageApi
|
|
178
|
+
* @param zip
|
|
179
|
+
*/
|
|
180
|
+
const batchDownloadFileByIds = (params: any) => {
|
|
181
|
+
const { fileIds, zip } = params;
|
|
182
|
+
|
|
183
|
+
downloadByXMLHttpRequest({
|
|
184
|
+
methodPath: fileServices.batchDownloadFileByIds(fileIds, { zip }),
|
|
185
|
+
downloadIndex: `${fileIds}_${Math.random()}`,
|
|
186
|
+
...params,
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
// 异步导出文件并显示进度
|
|
190
|
+
export const exportFileShowProgressAsync = async (exportParams: any) => {
|
|
191
|
+
const {
|
|
192
|
+
fileOrigin,
|
|
193
|
+
fileName,
|
|
194
|
+
params = {},
|
|
195
|
+
onSuccess,
|
|
196
|
+
onFail,
|
|
197
|
+
downloadIndex,
|
|
198
|
+
} = exportParams;
|
|
199
|
+
let timeoutId: number | null = null;
|
|
200
|
+
let percent = 0;
|
|
201
|
+
let isStop = false;
|
|
202
|
+
// @ts-ignore
|
|
203
|
+
const serviceApi = exportServiceMap[fileOrigin];
|
|
204
|
+
const applyId = await serviceApi(params, {});
|
|
205
|
+
const messageConfig = {
|
|
206
|
+
title: fileName ? `导出-${fileName}` : undefined,
|
|
207
|
+
key: downloadIndex,
|
|
208
|
+
onCancel: () => {
|
|
209
|
+
if (timeoutId) {
|
|
210
|
+
isStop = true;
|
|
211
|
+
clearTimeout(timeoutId);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
const requestProgress = async (isPolled = true) => {
|
|
216
|
+
try {
|
|
217
|
+
const { fileId, statusCd, requestJson, responseJson, failReason } =
|
|
218
|
+
await engineServices.getImportExportApply({ applyId }, {});
|
|
219
|
+
// 点击取消时候刚好触发了下一次接口,接口未回调时
|
|
220
|
+
if (isStop) return -1;
|
|
221
|
+
let requestObj: {
|
|
222
|
+
descriptor?: {
|
|
223
|
+
[key: string]: any;
|
|
224
|
+
};
|
|
225
|
+
} = {};
|
|
226
|
+
let responseObj: {
|
|
227
|
+
total?: number;
|
|
228
|
+
currentCount?: number;
|
|
229
|
+
} = {};
|
|
230
|
+
try {
|
|
231
|
+
requestObj = JSON.parse(requestJson) || {};
|
|
232
|
+
responseObj = JSON.parse(responseJson) || {};
|
|
233
|
+
} catch (e) {
|
|
234
|
+
console.log(e);
|
|
235
|
+
}
|
|
236
|
+
let showLoading: boolean = false;
|
|
237
|
+
const { total = 0, currentCount = 0 } = responseObj;
|
|
238
|
+
if (!responseJson || (percent === 100 && statusCd === 1)) {
|
|
239
|
+
// 上一次导出进程还未结束,无法返回进度
|
|
240
|
+
// 已经导出完全但进程还未结束
|
|
241
|
+
showLoading = true;
|
|
242
|
+
} else {
|
|
243
|
+
percent = +((+currentCount / +total) * 100).toFixed(2);
|
|
244
|
+
}
|
|
245
|
+
showProgressNotification({
|
|
246
|
+
...messageConfig,
|
|
247
|
+
message: showLoading
|
|
248
|
+
? undefined
|
|
249
|
+
: `总记录${total}条,已生成数据${currentCount}条,剩余${
|
|
250
|
+
total - currentCount
|
|
251
|
+
}条完成到处。`,
|
|
252
|
+
percent,
|
|
253
|
+
showLoading,
|
|
254
|
+
loadingText:
|
|
255
|
+
percent === 100
|
|
256
|
+
? 'export.process.downloading'
|
|
257
|
+
: 'export.process.handling',
|
|
258
|
+
});
|
|
259
|
+
if (statusCd === 1 && isPolled) {
|
|
260
|
+
polledRequest();
|
|
261
|
+
} else if (statusCd === 10) {
|
|
262
|
+
onSuccess?.();
|
|
263
|
+
showProgressNotification({
|
|
264
|
+
...messageConfig,
|
|
265
|
+
percent: 100,
|
|
266
|
+
btn: () => null,
|
|
267
|
+
duration: 1,
|
|
268
|
+
});
|
|
269
|
+
if (fileId) {
|
|
270
|
+
const newFileName: string | undefined =
|
|
271
|
+
fileName || requestObj?.descriptor?.filename;
|
|
272
|
+
batchDownloadFileByIds({
|
|
273
|
+
fileIds: fileId,
|
|
274
|
+
newFileName,
|
|
275
|
+
onError: (errorMessage: any) => {
|
|
276
|
+
messageApi.error(errorMessage);
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
} else if (statusCd === -1) {
|
|
281
|
+
showProgressNotification({
|
|
282
|
+
...messageConfig,
|
|
283
|
+
type: 'error',
|
|
284
|
+
percent,
|
|
285
|
+
message: failReason || '导出失败,稍后请重试。',
|
|
286
|
+
btn: () => null,
|
|
287
|
+
duration: 2,
|
|
288
|
+
});
|
|
289
|
+
onFail?.();
|
|
290
|
+
}
|
|
291
|
+
return statusCd;
|
|
292
|
+
} catch (e) {
|
|
293
|
+
onFail?.();
|
|
294
|
+
return -1;
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
const polledRequest = (requestFlag = false) => {
|
|
298
|
+
if (applyId && (timeoutId || requestFlag)) {
|
|
299
|
+
timeoutId = window.setTimeout(async () => {
|
|
300
|
+
await requestProgress();
|
|
301
|
+
}, 1500);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const status = await requestProgress(false);
|
|
305
|
+
if (status === 1) {
|
|
306
|
+
// 如果未导出则定时轮询
|
|
307
|
+
polledRequest(true);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
// 导出文件显示进度条
|
|
311
|
+
export const exportFileShowProgress = async (exportParams: {
|
|
312
|
+
fileOrigin: any;
|
|
313
|
+
methodType?: 'POST' | undefined;
|
|
314
|
+
fileName: any;
|
|
315
|
+
params?: {} | undefined;
|
|
316
|
+
onSuccess?: any;
|
|
317
|
+
onFail?: any;
|
|
318
|
+
downloadIndex: any;
|
|
319
|
+
async: any;
|
|
320
|
+
}) => {
|
|
321
|
+
const {
|
|
322
|
+
fileOrigin,
|
|
323
|
+
methodType = 'POST',
|
|
324
|
+
fileName,
|
|
325
|
+
params = {},
|
|
326
|
+
onSuccess,
|
|
327
|
+
onFail,
|
|
328
|
+
downloadIndex,
|
|
329
|
+
async,
|
|
330
|
+
} = exportParams;
|
|
331
|
+
|
|
332
|
+
const _downloadIndex = downloadIndex || `${fileName}_${Math.random()}`;
|
|
333
|
+
if (async === 'async') {
|
|
334
|
+
await exportFileShowProgressAsync({
|
|
335
|
+
...exportParams,
|
|
336
|
+
downloadIndex: _downloadIndex,
|
|
337
|
+
});
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (fileOrigin && window.XMLHttpRequest) {
|
|
342
|
+
const xhr = new XMLHttpRequest(); // ActiveXObject只存在于IE7及以下,无需兼容
|
|
343
|
+
// @ts-ignore
|
|
344
|
+
const methodPath = exportPathMap[fileOrigin];
|
|
345
|
+
xhr.open(methodType, methodPath, true);
|
|
346
|
+
xhr.responseType = 'blob'; // 设置接受类型
|
|
347
|
+
const headers: any = {
|
|
348
|
+
'Content-Type': 'application/json',
|
|
349
|
+
// 'X-B-TARGET-ID': pageId,
|
|
350
|
+
'X-B-AUTH': '1',
|
|
351
|
+
'APP-ID': APPID,
|
|
352
|
+
};
|
|
353
|
+
Object.keys(headers).forEach((header) => {
|
|
354
|
+
xhr.setRequestHeader(header, headers[header]); // 设置请求头参数
|
|
355
|
+
});
|
|
356
|
+
xhr.setRequestHeader(
|
|
357
|
+
'X-SIGN',
|
|
358
|
+
security.createHttpSignStr(methodPath, {
|
|
359
|
+
method: methodType,
|
|
360
|
+
headers,
|
|
361
|
+
body: JSON.stringify(params) || '',
|
|
362
|
+
search: '',
|
|
363
|
+
}),
|
|
364
|
+
);
|
|
365
|
+
xhr.withCredentials = true;
|
|
366
|
+
xhr.onprogress = (evt) => {
|
|
367
|
+
// 展示下载进度条
|
|
368
|
+
if (evt.lengthComputable) {
|
|
369
|
+
const percentComplete = Math.round((evt.loaded * 100) / evt.total);
|
|
370
|
+
openProgressMsg(_downloadIndex, fileName, percentComplete, '导出');
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
xhr.onload = async () => {
|
|
374
|
+
const data = xhr.response; // 获取响应体数据
|
|
375
|
+
if (xhr.status === 200) {
|
|
376
|
+
saveBlobFile({
|
|
377
|
+
data,
|
|
378
|
+
fileName: getFileName(
|
|
379
|
+
xhr.getResponseHeader('Content-Disposition') || '',
|
|
380
|
+
fileName,
|
|
381
|
+
),
|
|
382
|
+
});
|
|
383
|
+
if (typeof onSuccess === 'function') {
|
|
384
|
+
onSuccess();
|
|
385
|
+
}
|
|
386
|
+
} else if (typeof onFail === 'function') {
|
|
387
|
+
onFail();
|
|
388
|
+
} else {
|
|
389
|
+
messageApi.error('导出失败');
|
|
390
|
+
}
|
|
391
|
+
closeProgressMsg(_downloadIndex);
|
|
392
|
+
};
|
|
393
|
+
xhr.ontimeout = () => {
|
|
394
|
+
closeProgressMsg(_downloadIndex);
|
|
395
|
+
xhr.abort(); // 取消请求
|
|
396
|
+
};
|
|
397
|
+
xhr.send(JSON.stringify(params));
|
|
398
|
+
}
|
|
399
|
+
};
|
|
@@ -68,26 +68,31 @@ const transformContent = (value: string) => {
|
|
|
68
68
|
}
|
|
69
69
|
return finalContent;
|
|
70
70
|
};
|
|
71
|
-
const messageApi =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
71
|
+
const messageApi = {
|
|
72
|
+
info: (content: string, duration?: number) => {
|
|
73
|
+
return message.info(transformContent(content), duration);
|
|
74
|
+
},
|
|
75
|
+
success: (content: string, duration?: number) => {
|
|
76
|
+
return message.success(transformContent(content), duration);
|
|
77
|
+
},
|
|
78
|
+
error: (content: string, duration?: number) => {
|
|
79
|
+
return message.error(transformContent(content), duration);
|
|
80
|
+
},
|
|
81
|
+
warning: (content: string, duration?: number) => {
|
|
82
|
+
return message.warning(transformContent(content), duration);
|
|
83
|
+
},
|
|
84
|
+
warn: (content: string, duration?: number) => {
|
|
85
|
+
return message.warning(transformContent(content), duration);
|
|
86
|
+
},
|
|
87
|
+
loading: (content: string, duration?: number) => {
|
|
88
|
+
return message.loading(transformContent(content), duration);
|
|
89
|
+
},
|
|
90
|
+
destroy: () => {
|
|
91
|
+
return message.destroy();
|
|
92
|
+
},
|
|
93
|
+
hidden: () => {
|
|
94
|
+
return message.destroy();
|
|
95
|
+
},
|
|
91
96
|
};
|
|
92
97
|
|
|
93
98
|
const MessageApiModal = Modal;
|