cloud-web-corejs 1.0.54-dev.756 → 1.0.54-dev.759

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.
@@ -1,1774 +1,1774 @@
1
- /**version-1.0*/
2
- import { read, utils } from "xlsx";
3
- import axios from "axios";
4
- import SparkMD5 from "spark-md5";
5
-
6
- let tmixins = {};
7
- let XLSX = window.XLSX || { read, utils };
8
- import { getToken } from "../../../../../utils/auth";
9
- import XEUtils from "xe-utils";
10
- import { getErrorMsg } from "@base/utils/index.js";
11
-
12
- let configUtil = {
13
- baseUrl: process.env.VUE_APP_BASE_API,
14
- XLSX,
15
- getToken,
16
- };
17
- // importTimer / loadingObj 原为模块级单例:两个导入弹窗并存时后者覆盖前者引用,
18
- // 前一个 interval(100ms/次)与 loading 永久失控——已改为实例属性 this.importTimer / this.loadingObj
19
- tmixins = {
20
- name: "excelImport",
21
- props: ["param", "parentTarget"],
22
- inject: ["getReportTemplate", "formHttp"],
23
- data() {
24
- return {
25
- excTime: 0,
26
- showImportDialog: false,
27
- showImportDialog2: false,
28
- falseValue: false,
29
- fileRaw: false,
30
- isEnd: false,
31
- currentIndex: 0,
32
- excelTemplate: "",
33
- prefix: "/user",
34
- dataSize: 0,
35
- totalSuccessNum: 0,
36
- totalErrorNum: 0,
37
- percentageNum: 0,
38
- successRows: [],
39
- failRows: [],
40
- oriCols: [],
41
- showImportResult: false,
42
- resultType: "",
43
- option: {},
44
- showContent: false,
45
- resOption: {},
46
- fileCellFields: [],
47
- importLoading: false,
48
- loadingTitle: null,
49
-
50
- percent1: 0,
51
- percent2: 0,
52
- percent3: 0,
53
-
54
- loadingPercent: 0,
55
- handleRowSize: 1,
56
-
57
- headerRows: 3,
58
- };
59
- },
60
- computed: {
61
- importFileLimitSize() {
62
- return Math.min(
63
- this.param?.importOption?.importFileLimitSize || 200,
64
- 200
65
- );
66
- },
67
- },
68
- created() {
69
- this.exc();
70
- },
71
- beforeDestroy() {
72
- this.clearImportTimer();
73
- },
74
- methods: {
75
- initResGird() {
76
- let that = this;
77
- let tableRef = "resGrid";
78
- let columns = [
79
- {
80
- type: "checkbox",
81
- fixed: "left",
82
- width: 48,
83
- resizable: false,
84
- headerClassName: "vxe-hcs",
85
- className: "vxe-hcs",
86
- },
87
- {
88
- field: "impNumber",
89
- title: this.$t2("行号", "components.excelImport.impNumber"),
90
- width: 100,
91
- fixed: "left",
92
- },
93
- {
94
- field: "_resultContent",
95
- title: this.$t2("结果", "components.excelImport.resultContent"),
96
- width: 250,
97
- fixed: "left",
98
- slots: {
99
- default: ({ row, $rowIndex, $table }) => {
100
- return that.handleRes(row._resultContent);
101
- },
102
- },
103
- },
104
- ];
105
- let cCols = this.oriCols.map((oriCol, index) => {
106
- let col = {
107
- field: oriCol.field,
108
- title: oriCol.title,
109
- width: 150,
110
- ...oriCol.otherConfig,
111
- };
112
- if (index === 0) {
113
- col.fixed = "left";
114
- }
115
- return col;
116
- });
117
- columns = columns.concat(cCols);
118
-
119
- let tableOption = {
120
- vue: this,
121
- tableRef: tableRef,
122
- tableNameRequired: false,
123
- columns: columns,
124
- config: {
125
- toolbarConfig: {
126
- custom: false,
127
- },
128
- },
129
- };
130
-
131
- this.$vxeTableUtil.initVxeTable(tableOption).then((opts) => {
132
- this.resOption = opts;
133
- });
134
- },
135
- exc() {
136
- this.option = this.param;
137
- this.showContent = true;
138
- this.showImportDialog = true;
139
- this.showImportDialog2 = false;
140
- },
141
- showSuccessResult() {
142
- this.showImportResult = true;
143
- this.resultType = 1;
144
- this.$nextTick(() => {
145
- this.initResGird();
146
- this.$nextTick(() => {
147
- let tDatas = this.successRows.map((item, index) => {
148
- item.id = index;
149
- return item;
150
- });
151
- this.$refs.resGrid.loadData(tDatas);
152
- });
153
- });
154
- },
155
- showErrorResult() {
156
- this.showImportResult = true;
157
- this.resultType = 0;
158
- this.$nextTick(() => {
159
- this.initResGird();
160
- this.$nextTick(() => {
161
- let tDatas = this.failRows.map((item, index) => {
162
- item.id = index;
163
- return item;
164
- });
165
- this.$refs.resGrid.loadData(tDatas);
166
- });
167
- });
168
- },
169
- fileChange(file) {
170
- if (file) {
171
- this.fileRaw = file.raw;
172
- } else {
173
- this.fileRaw = false;
174
- }
175
- },
176
- dialogClose1() {
177
- this.importLoading = false;
178
- if (!this.showImportDialog2) {
179
- this.$emit("update:visiable", false);
180
- this.showContent = false;
181
- }
182
- },
183
- async dialogPrimary1() {
184
- let that = this;
185
- let option = this.option;
186
-
187
- let fileRaw = this.fileRaw;
188
- if (!fileRaw) {
189
- this.$baseAlert(
190
- this.$t2("请上传附件", "components.excelImport.warmMsg1")
191
- );
192
- return false;
193
- }
194
- let importFileLimitSize = this.importFileLimitSize;
195
- let fileSize = fileRaw.size;
196
- let limitSize = importFileLimitSize * 1024 * 1024;
197
- if (fileSize > limitSize) {
198
- this.$baseAlert(
199
- this.$t1("导入文件不允许超过{fileSize}MB", {
200
- fileSize: importFileLimitSize,
201
- })
202
- );
203
- return false;
204
- }
205
-
206
- if (option.importFrontOnly) {
207
- this.dialogPrimary3();
208
- return false;
209
- }
210
-
211
- /* this.createImportTimer();
212
- this.showImportDialog = false;
213
- if (!option.onConfirm) {
214
- this.showImportDialog2 = true;
215
- } */
216
- // this.$nextTick(() => {
217
- try {
218
- this.readExcel(this.fileRaw, function (resultData) {
219
- that.createImportTimer();
220
- that.showImportDialog = false;
221
- if (!option.onConfirm) {
222
- that.showImportDialog2 = true;
223
- }
224
- that.$nextTick(() => {
225
- if (option.onConfirm) {
226
- option.onConfirm(resultData.data, that.fileRaw);
227
- } else {
228
- that.handleBeforeImport0(that.fileRaw, resultData, () => {
229
- that.syncDataForImport({
230
- multi: false,
231
- data: resultData,
232
- // saveUrl: saveUrl
233
- });
234
- });
235
- }
236
- });
237
- });
238
- } catch (et) {
239
- that.clearImportTimer();
240
- console.error(et);
241
- }
242
- // });
243
- },
244
- handleBeforeImport(file, resultData, callback) {
245
- let importOption = this.option.importOption;
246
- let that = this;
247
- if (importOption.onBeforeImport) {
248
- const toDo = (res) => {
249
- let rows = res?.objx || [];
250
- rows.forEach((row, rowIndex) => {
251
- let item = resultData[rowIndex];
252
- Object.keys(row).forEach((key) => {
253
- item[key] = row[key];
254
- });
255
- });
256
- callback && callback();
257
- };
258
- this.getFieldTarget().handleCustomEvent(
259
- importOption.onBeforeImport,
260
- ["file", "resultData", "done"],
261
- [file, resultData, toDo]
262
- );
263
- } else {
264
- callback && callback();
265
- }
266
- },
267
- handleBeforeImport0(file, resultData, callback) {
268
- if (!this.showImportDialog2) return;
269
- let importOption = this.option.importOption;
270
- if (!importOption.enabledImportPreHandle) {
271
- this.handleBeforeImport(file, resultData, () => {
272
- callback && callback();
273
- });
274
- return;
275
- }
276
-
277
- this.uploadFile(() => {
278
- this.importLoading = false;
279
- this.handleBeforeImport(file, resultData, () => {
280
- callback && callback();
281
- });
282
- });
283
- return;
284
- },
285
- handleBeforeClose(hide) {
286
- this.option.onCancel &&
287
- this.option.onCancel(this.getCallbackData(), this.fileRaw);
288
- let importOption = this.option.importOption;
289
- this.getFieldTarget().handleCustomEvent(
290
- importOption.onSuccessImport,
291
- ["resultData", "file"],
292
- [this.getCallbackData(), this.fileRaw]
293
- );
294
- this.handleTableCallback();
295
- hide();
296
- },
297
- dialogClose2() {
298
- this.showImportDialog2 = false;
299
- this.option.onBeforeCancel &&
300
- this.option.onBeforeCancel(this.getCallbackData(), this.fileRaw);
301
- let importOption = this.option.importOption;
302
- this.getFieldTarget().handleCustomEvent(
303
- importOption.onSuccessImport,
304
- ["resultData", "file"],
305
- [this.getCallbackData(), this.fileRaw]
306
- );
307
- this.handleTableCallback();
308
- },
309
- handleClose2() {
310
- this.clearImportTimer();
311
- this.showImportDialog2 = false;
312
- this.showContent = false;
313
- this.option.onClose &&
314
- this.option.onClose(this.getCallbackData(), this.fileRaw);
315
- this.option.callback &&
316
- this.option.callback(this.getCallbackData(), this.fileRaw);
317
- this.dialogClose1();
318
- },
319
- dialogPrimary2() {
320
- let importOption = this.option.importOption;
321
- this.showImportDialog2 = false;
322
- this.option.onBeforeConfirm &&
323
- this.option.onBeforeConfirm(this.getCallbackData(), this.fileRaw);
324
- this.getFieldTarget().handleCustomEvent(
325
- importOption.onSuccessImport,
326
- ["resultData", "file"],
327
- [this.getCallbackData(), this.fileRaw]
328
- );
329
- this.handleTableCallback();
330
- },
331
- getCallbackData() {
332
- return {
333
- ...this.resultData,
334
- successRows: this.successRows,
335
- failRows: this.failRows,
336
- };
337
- },
338
-
339
- /*dialogClose2(flag) {
340
- let importOption = this.option.importOption;
341
- this.clearImportTimer();
342
- this.showImportDialog2 = false;
343
- this.dialogClose1();
344
- this.handleTableCallback(flag);
345
- this.parentTarget.handleCustomEvent(importOption.onSuccessImport, ['resultData', 'file'], [this.resultData, this.fileRaw])
346
- this.option.callback && this.option.callback(this.resultData, this.fileRaw);
347
- },
348
- dialogPrimary2() {
349
- let importOption = this.option.importOption;
350
- this.clearImportTimer();
351
- this.showImportDialog2 = false;
352
- this.dialogClose1()
353
- this.handleTableCallback();
354
- let fileRaw = this.fileRaw;
355
- this.parentTarget.handleCustomEvent(importOption.onSuccessImport, ['resultData', 'file'], [this.resultData, this.fileRaw])
356
- this.option.callback && this.option.callback(this.resultData, this.fileRaw);
357
- },*/
358
- handleTableCallback(flag) {
359
- if (flag === 0) return;
360
- let importOption = this.option.importOption;
361
- let tableTarget;
362
- if (importOption.tableRef)
363
- tableTarget = this.getFieldTarget().getWidgetRef(importOption.tableRef);
364
- if (tableTarget) {
365
- let isQueryTable = tableTarget.widget.options.isQueryTable;
366
- if (isQueryTable) {
367
- tableTarget.searchEvent();
368
- }
369
- }
370
- },
371
- async readExcel(file, callback) {
372
- let that = this;
373
- let option = this.option;
374
-
375
- if (option.importOption.multipleSheet) {
376
- this.readExcel2(file, callback);
377
- return;
378
- }
379
-
380
- const fileReader = new FileReader();
381
- fileReader.onload = async (ev) => {
382
- let resultData;
383
- try {
384
- const data = ev.target.result;
385
- const workbook = configUtil.XLSX.read(data, {
386
- type: "binary",
387
- });
388
-
389
- let sheet = workbook.Sheets[workbook.SheetNames[0]];
390
- if (sheet["!ref"] === undefined || sheet["!ref"] === null) {
391
- /*that.showImportDialog2 = false;
392
- that.showContent = false;
393
- that.clearImportTimer();*/
394
- that.$baseAlert(
395
- this.$t2(
396
- "请使用正确的导入模版!",
397
- "components.excelImport.warmMsg2"
398
- )
399
- );
400
- that.handleClose2();
401
- return false;
402
- }
403
- let range = configUtil.XLSX.utils.decode_range(sheet["!ref"]);
404
- let dataSize = range.e.r + 1; //行数
405
- that.dataSize = dataSize - 3 >= 0 ? dataSize - 3 : 0;
406
- let titles = [];
407
- let fields = [];
408
-
409
- const ws = workbook.Sheets[sheet];
410
-
411
- let prefix = option.prefix;
412
- let excelUrl = option.excel;
413
-
414
- let excelRows = [];
415
- let row;
416
- let rowNum;
417
- let colNum;
418
- for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
419
- row = [];
420
- for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
421
- let nextCell =
422
- sheet[
423
- configUtil.XLSX.utils.encode_cell({
424
- r: rowNum,
425
- c: colNum,
426
- })
427
- ];
428
- if (typeof nextCell === "undefined") {
429
- row.push(void 0);
430
- } else {
431
- row.push(nextCell.w.trim());
432
- }
433
- }
434
- if (rowNum === 1) {
435
- titles = row;
436
- }
437
- if (rowNum === 2) {
438
- fields = row;
439
- let checkResult = true;
440
- /*await that.checkExcelForImport(titles, fields, excelUrl, prefix).then(
441
- res => {
442
- if (res.type !== "success") {
443
- checkResult = false;
444
- }
445
- });
446
- if (!checkResult) {
447
- that.showContent = false;
448
- that.clearImportTimer();
449
- return false;
450
- }*/
451
- }
452
- if (rowNum > 2) {
453
- let item = {};
454
- for (let i = 0; i < fields.length; i++) {
455
- let field = fields[i];
456
- if (field) {
457
- item[field] = row[i] ?? null;
458
- }
459
- }
460
- excelRows.push(item);
461
- }
462
- }
463
- if (
464
- !titles.length ||
465
- !fields.length ||
466
- titles.length !== fields.length
467
- ) {
468
- // that.showContent = false;
469
- // that.clearImportTimer();
470
- that.$baseAlert(
471
- this.$t2(
472
- "请使用正确的导入模版!",
473
- "components.excelImport.warmMsg2"
474
- )
475
- );
476
- that.handleClose2();
477
- return false;
478
- }
479
-
480
- let columns = [];
481
- let cols = [];
482
- let uniqueFields = [];
483
- for (let i = 0; i < titles.length; i++) {
484
- let title = titles[i];
485
- if (title) {
486
- let field = fields[i];
487
- if (field === null || field === undefined) {
488
- // that.showContent = false;
489
- // that.clearImportTimer();
490
- that.$baseAlert(
491
- this.$t2(
492
- "请使用正确的导入模版!",
493
- "components.excelImport.warmMsg2"
494
- )
495
- );
496
- that.handleClose2();
497
- return false;
498
- }
499
- let t = title.substr(-1);
500
- let u = title.length >= 2 ? title.substr(-2) : title;
501
- let isNeed = false;
502
- if (t === "*") {
503
- isNeed = true;
504
- }
505
- let isUnique = false;
506
- if (u === "**") {
507
- uniqueFields.push(field);
508
- isUnique = true;
509
- }
510
-
511
- let otherConfig = {};
512
- let isFile = false;
513
- if (field.startsWith("attachments_")) {
514
- that.fileCellFields.push(field);
515
- isFile = true;
516
- otherConfig = {
517
- slots: {
518
- default: "attachment",
519
- },
520
- };
521
- }
522
-
523
- let col = {
524
- field: field,
525
- title: title,
526
- width: 100,
527
- isNeed: isNeed,
528
- isUnique: isUnique,
529
- isFile,
530
- otherConfig,
531
- };
532
- cols.push(col);
533
- }
534
- }
535
-
536
- let oriCols = JSON.parse(JSON.stringify(cols)); //列信息
537
- if (uniqueFields.length) {
538
- //分组唯一字段为空时,全部不发包。
539
- for (let i = 0; i < oriCols.length; i++) {
540
- let oriCol = oriCols[i];
541
- if (oriCol.isNeed) {
542
- for (let j = 0; j < excelRows.length; j++) {
543
- let data = excelRows[j];
544
- let value = data[oriCol.field];
545
- if (value === null || value === undefined || value === "") {
546
- that.clearImportTimer();
547
- that.$baseAlert(
548
- this.$t2(
549
- "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
550
- "components.excelImport.warmMsg3",
551
- {
552
- lineNo: j + 4,
553
- title: oriCol.title,
554
- }
555
- )
556
- );
557
- that.handleClose2();
558
- return false;
559
- }
560
- }
561
- }
562
- }
563
- }
564
-
565
- this.oriCols = oriCols;
566
-
567
- resultData = {
568
- data: excelRows,
569
- titles: titles,
570
- fields: fields,
571
- uniqueFields: uniqueFields,
572
- oriCols: oriCols,
573
- };
574
- this.resultData = resultData;
575
- callback(resultData);
576
- } catch (et) {
577
- that.showContent = false;
578
- that.clearImportTimer();
579
- console.error(et);
580
- }
581
- };
582
- fileReader.readAsBinaryString(file);
583
- },
584
- async checkExcelForImport(titles, fields, turl, prefix) {
585
- if (!this.showImportDialog2) return;
586
- let that = this;
587
- let data = {
588
- filed_name: fields,
589
- field_note: titles,
590
- url: turl,
591
- };
592
- let param = JSON.stringify(data);
593
- return this.$http({
594
- url: prefix + "/sf_common/compareExcelFields",
595
- method: "post",
596
- headers: {
597
- "Content-Type": "application/json;charset=utf-8",
598
- },
599
- // data: param,
600
- data: data,
601
- });
602
- },
603
- saveImportHandle(data, opt) {
604
- let multi = this.option.multi;
605
- let importOption = this.option.importOption;
606
-
607
- let entity = importOption.importEntity;
608
-
609
- if (!entity) return;
610
-
611
- let reportTemplate = this.getReportTemplate();
612
- let formCode = reportTemplate?.formCode;
613
- let scriptCode = importOption.importScriptCode || "import";
614
- // let config = option?.config;
615
-
616
- // let reqData = this.getReqFormData();
617
- let fileCellFields = this.fileCellFields;
618
- let formData = null;
619
- if (multi) {
620
- formData = data;
621
- } else {
622
- formData = {
623
- [entity]: { ...data },
624
- };
625
- if (fileCellFields.length) {
626
- fileCellFields.forEach((field) => {
627
- let attachments = data[field] || [];
628
- delete formData[entity][field];
629
- formData[field] = attachments;
630
- });
631
- }
632
- }
633
-
634
- let reqData = {
635
- formCode: formCode,
636
- formVersion: reportTemplate.formVersion,
637
- taBm: entity,
638
- data: formData,
639
- };
640
-
641
- this.formHttp({
642
- scriptCode: scriptCode,
643
- data: reqData,
644
- modal: false,
645
- ...opt,
646
- });
647
- },
648
- syncDataForImport(opts) {
649
- let that = this;
650
- let multi = this.option.multi;
651
- let resultData = this.resultData;
652
- let datas = resultData.data;
653
- let titles = resultData.titles;
654
- let fields = resultData.fields;
655
- let uniqueFields = resultData.uniqueFields;
656
- let saveUrl = opts.saveUrl;
657
- let size = datas.length;
658
- let index = 0;
659
- let successNum = 0;
660
- let failNum = 0;
661
- let dialogObj = this.$refs.importDialog.$el;
662
- let successNumObj = dialogObj.querySelector(".successNum");
663
- let failNumObj = dialogObj.querySelector(".failNum");
664
- let percentageObj = dialogObj.querySelector(".percentage");
665
- let doneNumObj = dialogObj.querySelector(".doneNum");
666
- dialogObj.querySelector(".dataSize").innerText = size;
667
-
668
- that.successRows = [];
669
- that.failRows = [];
670
-
671
- let multiSize = this.option.multiSize || 2;
672
-
673
- let groupIndex = 0;
674
- let groupDatas = [];
675
- if (uniqueFields.length) {
676
- let d = XEUtils.groupBy(datas, function (item, itemIndex, items) {
677
- let keyArr = [];
678
- uniqueFields.forEach((field) => {
679
- keyArr.push(item[field]);
680
- });
681
- return keyArr.join("&_&");
682
- });
683
- for (let key in d) {
684
- groupDatas.push(d[key]);
685
- }
686
- datas.forEach((item, itemIndex) => {
687
- item.impSeq = itemIndex;
688
- item.impNumber = itemIndex + 4;
689
- });
690
- }
691
-
692
- let compareV = function (property) {
693
- return function (a, b) {
694
- let value1 = a[property];
695
- let value2 = b[property];
696
- return value1 - value2;
697
- };
698
- };
699
-
700
- let prevHandleData = function (percentageStr, excNum) {
701
- successNumObj.innerText = successNum;
702
- failNumObj.innerText = failNum;
703
- doneNumObj.innerText = successNum + failNum;
704
- that.percentageNum = percentageStr;
705
- let isEnd = false;
706
- if (multi && uniqueFields.length) {
707
- isEnd = groupIndex + 1 >= groupDatas.length;
708
- } else {
709
- isEnd = index + excNum >= size;
710
- }
711
- if (!isEnd) {
712
- index = index + excNum;
713
- groupIndex = groupIndex + 1;
714
- setTimeout(function () {
715
- handleData();
716
- }, 1);
717
- } else {
718
- setTimeout(function () {
719
- that.clearImportTimer();
720
- }, 300);
721
- }
722
- };
723
-
724
- let getDefaultValue = (row) => {
725
- let value = null;
726
- let defaultValue = this.option.defaultValue;
727
- if (defaultValue) {
728
- if (typeof defaultValue === "function") {
729
- value = defaultValue(row) || {};
730
- } else {
731
- value = defaultValue || {};
732
- }
733
- }
734
- return value;
735
- };
736
-
737
- let handleData = () => {
738
- if (!that.isEnd && index < size) {
739
- let param;
740
- let excNum;
741
- if (multi) {
742
- if (!uniqueFields.length) {
743
- if (index + multiSize < size) {
744
- excNum = multiSize;
745
- } else {
746
- excNum = size - index;
747
- }
748
-
749
- let dataList = [];
750
- for (let i = 0; i < excNum; i++) {
751
- let mIndex = index + i;
752
- let mData = datas[mIndex];
753
- mData.impSeq = mIndex;
754
- mData.impNumber = mIndex + 4;
755
-
756
- let errorInfo = that.vailData(mData, opts);
757
- if (errorInfo.length > 0) {
758
- mData._resultType = "error";
759
- mData._resultContent = errorInfo;
760
- failNum++;
761
- that.failRows.push(mData);
762
- } else {
763
- let defaultValue = getDefaultValue(mData);
764
- if (defaultValue) {
765
- Object.assign(mData, defaultValue);
766
- }
767
- dataList.push(mData);
768
- }
769
-
770
- datas[mIndex] = mData;
771
- }
772
- if (dataList.length > 0) {
773
- param = dataList;
774
- }
775
- } else {
776
- excNum = groupDatas[groupIndex].length;
777
- param = groupDatas[groupIndex];
778
- }
779
- } else {
780
- let data = that.resultData.data[index];
781
- data.impSeq = index;
782
- data.impNumber = index + 4;
783
- excNum = 1;
784
- datas[index] = data;
785
-
786
- let errorInfo = that.vailData(data, opts);
787
- if (errorInfo.length > 0) {
788
- data._resultType = "error";
789
- data._resultContent = errorInfo;
790
- failNum++;
791
- that.failRows.push(data);
792
- } else {
793
- param = data;
794
- let defaultValue = getDefaultValue(data);
795
- if (defaultValue) {
796
- Object.assign(param, defaultValue);
797
- }
798
- }
799
- }
800
-
801
- let percentageStr = parseInt(((index + excNum) * 100) / size);
802
- if (param === null || param === undefined || param.length === 0) {
803
- if (that.showContent) {
804
- prevHandleData(percentageStr, excNum);
805
- }
806
- return;
807
- }
808
-
809
- that.saveImportHandle(param, {
810
- failMsg: false,
811
- callback: (resultMsg) => {
812
- if (multi) {
813
- if (resultMsg.type === "success") {
814
- let multiRows = resultMsg.objx;
815
- for (let i = 0; i < multiRows.length; i++) {
816
- let multiRow = multiRows[i];
817
- let data = datas[multiRow.impSeq];
818
- data._resultType = multiRow.impReturnType;
819
- data._resultContent =
820
- multiRow.impReturnType === "success"
821
- ? this.$t2(
822
- "导入成功",
823
- "components.excelImport.importSucess"
824
- )
825
- : multiRow.impReturnMsg;
826
- if (multiRow.impReturnType === "success") {
827
- successNum++;
828
- that.successRows.push(data);
829
- } else {
830
- failNum++;
831
- that.failRows.push(data);
832
- }
833
- }
834
-
835
- that.failRows = that.failRows.sort(compareV("impSeq"));
836
- } else {
837
- // error_win(resultMsg);
838
- // layer.close(opts.dialogObjIndex);
839
-
840
- let items = param.map((item) => {
841
- return {
842
- ...item,
843
- _resultType: "error",
844
- _resultContent: resultMsg.content,
845
- };
846
- });
847
- failNum = failNum + items.length;
848
- that.failRows.push(...items);
849
-
850
- that.failRows = that.failRows.sort(compareV("impSeq"));
851
-
852
- /* that.$errorMsg(resultMsg);
853
- that.showContent = false;
854
- that.clearImportTimer();
855
- return; */
856
- }
857
- } else {
858
- let data = that.resultData.data[index];
859
- data._resultType = resultMsg.type;
860
- data._resultContent =
861
- resultMsg.type === "success"
862
- ? this.$t2(
863
- "导入成功",
864
- "components.excelImport.importSucess"
865
- )
866
- : resultMsg.content;
867
-
868
- if (resultMsg.type === "success") {
869
- successNum++;
870
- that.successRows.push(data);
871
- } else {
872
- failNum++;
873
- that.failRows.push(data);
874
- }
875
- }
876
- if (that.showContent) {
877
- prevHandleData(percentageStr, excNum);
878
- }
879
- },
880
- error: (et) => {
881
- that.isEnd = true;
882
- that.clearImportTimer();
883
- console.error(et);
884
- },
885
- });
886
- }
887
- };
888
- handleData();
889
- },
890
- commonLocalDownload() {
891
- let importOption = this.option.importOption;
892
- let importAttachCode = importOption.importAttachCode;
893
- if (!importAttachCode) return;
894
- this.$http({
895
- url: USER_PREFIX + "/bd_attach_setting/getByCode",
896
- method: "post",
897
- data: {
898
- stringOne: importAttachCode,
899
- },
900
- success: (res) => {
901
- let fileObj = res.objx;
902
- let url = fileObj?.url;
903
- if (fileObj && url) {
904
- this.$commonFileUtil.downloadFile(url,fileObj.name);
905
- }
906
- },
907
- });
908
- },
909
- vailData(data, opts) {
910
- let oriCols = opts.data.oriCols;
911
- let errorInfo = [];
912
- for (let i = 0; i < oriCols.length; i++) {
913
- let oriCol = oriCols[i];
914
- if (oriCol.isNeed) {
915
- let value = data[oriCol.field];
916
- if (value === null || value === undefined || value === "") {
917
- errorInfo.push(
918
- this.$t2(
919
- "[" + oriCol.title + "]不能为空;",
920
- "components.excelImport.warmMsg4",
921
- { title: oriCol.title }
922
- )
923
- );
924
- }
925
- }
926
- }
927
- return errorInfo.join("");
928
- },
929
- handleRes(val) {
930
- /* let content = val;
931
- let text = content;
932
- if (content && content.indexOf("Exception") >= 0) {
933
- let index0 = content.lastIndexOf("*]");
934
- if (index0 >= 0) {
935
- text = content.substr(index0);
936
- if (text) {
937
- let index1 = text.indexOf("Exception:");
938
- if (index1 >= 0) {
939
- text = text.substr(index1 + 10);
940
- }
941
- }
942
- }
943
- } */
944
- let text = getErrorMsg(val);
945
- return text;
946
- },
947
- exportToExcel() {
948
- let str =
949
- this.resultType === 1
950
- ? this.$t2("成功", "components.excelImport.success")
951
- : this.$t2("失败", "components.excelImport.fail");
952
- let fileName =
953
- this.$t2("导入结果导出", "components.excelImport.exportFileName") +
954
- "(" +
955
- str +
956
- ")";
957
- let $grid = this.$refs.resGrid;
958
- let columns = $grid.getColumns();
959
- if (columns && columns.length) {
960
- let fields = columns
961
- .filter((item, index) => {
962
- return index > 0 && item.property;
963
- })
964
- .map((item, index) => {
965
- return item.property;
966
- });
967
- this.$refs.resGrid.exportData({
968
- filename: fileName,
969
- mode: "all",
970
- type: "csv",
971
- columns: fields,
972
- });
973
- }
974
- },
975
- createImportTimer() {
976
- this.excTime = 0;
977
- let beginTime = new Date().getTime();
978
- this.importTimer = setInterval(() => {
979
- let nowTime = new Date().getTime();
980
- let diffTime = (nowTime - beginTime) / 1000;
981
- this.$set(this, "excTime", this.$baseLodash.round(diffTime, 2));
982
- }, 100);
983
- },
984
- clearImportTimer() {
985
- clearInterval(this.importTimer);
986
- this.importTimer = null;
987
- this.loadingObj && this.loadingObj.close();
988
- this.loadingObj = null;
989
- },
990
- getWidgetTarget() {},
991
- getFieldTarget() {
992
- return this.param.target;
993
- },
994
- async dialogPrimary3() {
995
- if (!this.fileRaw) {
996
- this.$baseAlert(
997
- this.$t2("请上传附件", "components.excelImport.warmMsg1")
998
- );
999
- return false;
1000
- }
1001
- let that = this;
1002
- let option = this.option;
1003
- this.loadingObj = this.$baseLoading({
1004
- target: document.body,
1005
- background: "unset",
1006
- });
1007
-
1008
- let importOption = option.importOption;
1009
- this.readExcel(this.fileRaw, function (resultData) {
1010
- let file = that.fileRaw;
1011
- let flag = false;
1012
- let done = () => {
1013
- if (flag) return;
1014
- flag = true;
1015
- that.showImportDialog = false;
1016
- return that
1017
- .getFieldTarget()
1018
- .handleCustomEvent(
1019
- importOption.onSuccessImport,
1020
- ["resultData", "file"],
1021
- [resultData, file]
1022
- );
1023
- };
1024
- const close = () => {
1025
- that.dialogClose1();
1026
- }
1027
- try {
1028
- if (importOption.onConfirmImportEnabled) {
1029
- if (
1030
- that
1031
- .getFieldTarget()
1032
- .handleCustomEvent(
1033
- importOption.onConfirmImport,
1034
- ["resultData", "file", "done", 'close'],
1035
- [resultData, file, done, close]
1036
- ) !== false
1037
- ) {
1038
- done();
1039
- }
1040
- } else if (importOption.tableRef) {
1041
- let tableRef = that
1042
- .getFieldTarget()
1043
- .getWidgetRef(importOption.tableRef);
1044
- tableRef && tableRef.addTableData(resultData.data);
1045
- done();
1046
- }
1047
- } catch (et) {
1048
- console.error(et);
1049
- }
1050
- setTimeout(function () {
1051
- that.loadingObj && that.loadingObj.close();
1052
- }, 200);
1053
- });
1054
- },
1055
-
1056
- //begin
1057
- fileParse(file, type = "base64", callback) {
1058
- let fileRead = new FileReader();
1059
- if (type === "base64") {
1060
- fileRead.readAsDataURL(file);
1061
- } else if (type === "buffer") {
1062
- fileRead.readAsArrayBuffer(file);
1063
- }
1064
- fileRead.onload = (ev) => {
1065
- callback(ev.target.result);
1066
- };
1067
- },
1068
- getUploadText(percent) {
1069
- return this.$t1("上传导入文件 {percent}%", { percent });
1070
- },
1071
- changeUploadPercent(percent) {
1072
- // return this.$t1('上传导入文件 {percent}%', {percent})
1073
- this.percent1 = percent;
1074
- this.loadingIndex = 1;
1075
- },
1076
- uploadFile(callback) {
1077
- let that = this;
1078
- that.loadingPercent = 0;
1079
- // that.loadingTitle = this.getUploadText(0);
1080
- that.changeUploadPercent(0);
1081
- let file = this.fileRaw;
1082
- let uploadChunkSize = 5;
1083
- this.importLoading = true;
1084
- this.fileUploadCallback = callback;
1085
- this.fileParse(file, "buffer", (buffer) => {
1086
- let spark = new SparkMD5.ArrayBuffer(),
1087
- chunkSize = uploadChunkSize * 1024 * 1024, // Read in chunks of 2MB
1088
- chunks = Math.ceil(file.size / chunkSize),
1089
- hash,
1090
- suffix;
1091
- spark.append(buffer);
1092
- hash = spark.end();
1093
- let md5 = hash;
1094
- let nameSplit = /\.([0-9a-zA-Z]+)$/i.exec(file.name);
1095
-
1096
- suffix = nameSplit && nameSplit.length > 1 ? nameSplit[1] : "";
1097
-
1098
- let chunkParam = {
1099
- fullFile: file,
1100
- chunkSize: chunkSize,
1101
- chunks: chunks,
1102
- chunkIndex: 0,
1103
- md5: hash,
1104
- uuid: "",
1105
- name: file.name,
1106
- };
1107
- file.chunkParam = chunkParam;
1108
-
1109
- this.sendRequest(file);
1110
- });
1111
- },
1112
- async sendRequest(fullFile) {
1113
- if (!this.showImportDialog2) return;
1114
- let that = this;
1115
- let uploadUrl = USER_PREFIX + "/excel_import/uploadFile";
1116
- let chunkParam = fullFile.chunkParam;
1117
- let target = that.$refs.upload;
1118
- let abort;
1119
- let config = {
1120
- headers: {
1121
- "Content-Type": "multipart/form-data",
1122
- },
1123
- cancelToken: new axios.CancelToken(function executor(c) {
1124
- abort = c;
1125
- fullFile.abort = c;
1126
- }),
1127
- onUploadProgress: (progressEvent) => {
1128
- let start = chunkParam.start;
1129
- let uploadedSize =
1130
- start +
1131
- Math.floor(
1132
- (chunkParam.currentSize * progressEvent.loaded) /
1133
- progressEvent.total
1134
- );
1135
- let percent = Math.floor((uploadedSize * 100) / fullFile.size);
1136
- if (percent === 100) {
1137
- percent = 99;
1138
- }
1139
- that.loadingPercent = percent;
1140
-
1141
- // that.$set(that, 'loadingTitle', this.getUploadText(percent))
1142
- that.changeUploadPercent(percent);
1143
- },
1144
- // failMsg: false,
1145
- modal: false,
1146
- callback: (res1) => {
1147
- if (res1.type === "success") {
1148
- let uuid = res1.objx.uuid;
1149
- chunkParam.uuid = uuid;
1150
- if (preFormData.chunk + 1 >= preFormData.chunks) {
1151
- let mergeData = {
1152
- name: chunkParam.name,
1153
- md5: chunkParam.md5,
1154
- uuid: uuid,
1155
- };
1156
- let _param = {
1157
- mergeData: mergeData,
1158
- chunkParam: chunkParam,
1159
- };
1160
- setTimeout(() => {
1161
- this.mergeFile(_param);
1162
- }, 100);
1163
- } else {
1164
- chunkParam.chunkIndex = chunkParam.chunkIndex + 1;
1165
- chunkParam.uuid = uuid;
1166
- setTimeout(() => {
1167
- this.sendRequest(fullFile);
1168
- }, 100);
1169
- }
1170
- } else {
1171
- this.dialogClose2(0);
1172
- }
1173
- return res1;
1174
- },
1175
- error: (err) => {
1176
- console.log(err);
1177
- this.dialogClose2(0);
1178
- },
1179
- }; //添加请求头
1180
-
1181
- let chunkIndex = chunkParam.chunkIndex;
1182
- let chunkSize = chunkParam.chunkSize;
1183
- let start = chunkIndex * chunkSize,
1184
- end =
1185
- start + chunkSize >= fullFile.size
1186
- ? fullFile.size
1187
- : start + chunkParam.chunkSize;
1188
- chunkParam.currentSize = end - start;
1189
- chunkParam.start = start;
1190
- chunkParam.end = end;
1191
-
1192
- let preFormData = {
1193
- file: fullFile.slice(start, end),
1194
- name: fullFile.name,
1195
- chunks: chunkParam.chunks,
1196
- chunk: chunkIndex,
1197
- md5: chunkParam.md5,
1198
- uuid: chunkParam.uuid,
1199
- };
1200
-
1201
- let formData = new FormData();
1202
- Object.keys(preFormData).forEach((key) => {
1203
- formData.append(key, preFormData[key]);
1204
- });
1205
-
1206
- let req = this.$http.post(uploadUrl, formData, config);
1207
- req.abort = () => {
1208
- abort(this.$t2("取消上传", "components.VabUpload.cancelUpload"));
1209
- };
1210
- },
1211
- mergeFile(param) {
1212
- if (!this.showImportDialog2) return;
1213
- let that = this;
1214
- let mergeData = param.mergeData;
1215
- let chunkParam = param.chunkParam;
1216
- let fullFile = chunkParam.fullFile;
1217
- let mergeUrl = USER_PREFIX + "/excel_import/mergeChunk";
1218
- let target = this.$refs.upload;
1219
- this.$http({
1220
- url: mergeUrl,
1221
- method: "post",
1222
- data: mergeData,
1223
- // failMsg: false,
1224
- modal: false,
1225
- cancelToken: new axios.CancelToken(function executor(c) {
1226
- if (fullFile) fullFile.abort = c;
1227
- }),
1228
- callback: (res) => {
1229
- if (res.type === "success") {
1230
- that.loadingPercent = 100;
1231
- // that.loadingTitle = this.getUploadText(100);
1232
- this.changeUploadPercent(100);
1233
- setTimeout(() => {
1234
- this.checkImportData();
1235
- }, 100);
1236
- } else {
1237
- this.dialogClose2(0);
1238
- }
1239
- },
1240
- error: (e) => {
1241
- console.log(err);
1242
- this.dialogClose2(0);
1243
- },
1244
- });
1245
- },
1246
- getCheckText(percent) {
1247
- return this.$t1("校验导入文件中的图片数据格式 {percent}%", { percent });
1248
- },
1249
- changeCheckTextPercent(percent) {
1250
- this.percent2 = percent;
1251
- this.loadingIndex = 2;
1252
- },
1253
- checkImportData() {
1254
- if (!this.showImportDialog2) return;
1255
- let that = this;
1256
- that.loadingPercent = 0;
1257
- // that.loadingTitle = this.getCheckText(0);
1258
- that.changeCheckTextPercent(0);
1259
- let fullFile = this.fileRaw;
1260
- let chunkParam = fullFile.chunkParam;
1261
-
1262
- this.$http({
1263
- url: USER_PREFIX + "/excel_import/checkData",
1264
- method: "post",
1265
- data: {
1266
- name: chunkParam.name,
1267
- md5: chunkParam.md5,
1268
- uuid: chunkParam.uuid,
1269
- },
1270
- // failMsg: false,
1271
- modal: false,
1272
- cancelToken: new axios.CancelToken(function executor(c) {
1273
- if (fullFile) fullFile.abort = c;
1274
- }),
1275
- onUploadProgress: (progressEvent) => {
1276
- let percent = Math.floor(
1277
- (progressEvent.loaded * 100) / progressEvent.total
1278
- );
1279
- if (percent === 100) {
1280
- percent = 99;
1281
- }
1282
- that.loadingPercent = percent;
1283
- // that.$set(that, 'loadingTitle', this.getCheckText(percent))
1284
- that.changeCheckTextPercent(percent);
1285
- },
1286
- callback: (res) => {
1287
- if (res.type === "success") {
1288
- that.loadingPercent = 100;
1289
- // that.loadingTitle = this.getCheckText(100);
1290
- that.changeCheckTextPercent(100);
1291
- this.handleImageData();
1292
- } else {
1293
- this.dialogClose2(0);
1294
- }
1295
- },
1296
- error: (e) => {
1297
- console.log(err);
1298
- this.dialogClose2(0);
1299
- },
1300
- });
1301
- },
1302
- getSaveImageText(percent) {
1303
- return this.$t1("存储导入文件中的图片 {percent}%", { percent });
1304
- },
1305
- changeSaveImageTextPercent(percent) {
1306
- // return this.$t1('存储导入文件中的图片 {percent}%', {percent})
1307
- this.percent3 = percent;
1308
- this.loadingIndex = 3;
1309
- },
1310
- handleImageData() {
1311
- let that = this;
1312
- that.loadingPercent = 0;
1313
- // that.loadingTitle = this.getSaveImageText(0);
1314
- that.changeSaveImageTextPercent(0);
1315
- this.getImportData(0);
1316
- },
1317
- getImportData(index) {
1318
- if (!this.showImportDialog2) return;
1319
- let that = this;
1320
- let rowSize = this.handleRowSize;
1321
- let fullFile = this.fileRaw;
1322
- let chunkParam = fullFile.chunkParam;
1323
- let rowDatas = this.resultData.data;
1324
- let size = rowDatas.length;
1325
- let currentLineNo = index + 1;
1326
- let rowNumber = index + 3;
1327
- let startRow = index + 3;
1328
- let endRow = index + 3 + rowSize - 1;
1329
- this.$http({
1330
- url: USER_PREFIX + "/excel_import/getData",
1331
- method: "post",
1332
- data: {
1333
- name: chunkParam.name,
1334
- md5: chunkParam.md5,
1335
- uuid: chunkParam.uuid,
1336
- startRow: startRow,
1337
- endRow: endRow,
1338
- },
1339
- // failMsg: false,
1340
- modal: false,
1341
- cancelToken: new axios.CancelToken(function executor(c) {
1342
- if (fullFile) fullFile.abort = c;
1343
- }),
1344
- callback: (res) => {
1345
- if (res.type === "success") {
1346
- let rows = res?.objx?.datas || [];
1347
- let fileCellFields = this.fileCellFields;
1348
- rows.forEach((row) => {
1349
- let rowIndex = row.row - 3;
1350
- let item = rowDatas[rowIndex];
1351
- Object.keys(row).forEach((key) => {
1352
- if (fileCellFields.includes(key)) {
1353
- let value = row[key] || [];
1354
- if (!Array.isArray(value)) {
1355
- value = [value];
1356
- }
1357
- item[key] = value;
1358
- }
1359
- });
1360
- });
1361
- let cIndex = index + rowSize - 1;
1362
- let percent = Math.floor(((cIndex + 1) * 100) / size);
1363
- that.loadingPercent = percent;
1364
- // that.loadingTitle = this.getSaveImageText(percent);
1365
- that.changeSaveImageTextPercent(percent);
1366
- if (cIndex + 1 < size) {
1367
- this.getImportData(cIndex + 1);
1368
- } else {
1369
- this.fileUploadCallback();
1370
- }
1371
- } else {
1372
- this.dialogClose2(0);
1373
- }
1374
- },
1375
- error: (e) => {
1376
- this.dialogClose2(0);
1377
- },
1378
- });
1379
- },
1380
- async generateNewExcel() {
1381
- let file = this.fileRaw;
1382
- try {
1383
- // 1. 读取原始文件
1384
- const workbook = XLSX.read(file, { type: "binary" });
1385
- const sheetName = workbook.SheetNames[0];
1386
- const rawData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
1387
-
1388
- // 2. 提取表头和数据
1389
- const headers = rawData.slice(0, this.headerRows);
1390
- const bodyData = rawData.slice(this.headerRows);
1391
-
1392
- let exporLineNos = [];
1393
- if (this.resultType) {
1394
- exporLineNos = this.successRows.map((item) => item.impNumber - 1);
1395
- } else {
1396
- exporLineNos = this.failRows.map((item) => item.impNumber - 1);
1397
- }
1398
- // 3. 应用筛选规则
1399
- let selectRule = (row, index) => {
1400
- return exporLineNos.includes(index);
1401
- };
1402
- const filteredData = bodyData.filter(
1403
- (row, index) => {
1404
- return selectRule(row, index + this.headerRows);
1405
- }
1406
- // this.selectRule(row, index + this.headerRows) // 注意索引转换
1407
- );
1408
-
1409
- // 4. 合并数据
1410
- const newData = [...headers, ...filteredData];
1411
-
1412
- // 5. 生成新文件
1413
- const newWorkbook = XLSX.utils.book_new();
1414
- const newSheet = XLSX.utils.aoa_to_sheet(newData);
1415
- XLSX.utils.book_append_sheet(newWorkbook, newSheet, "Sheet1");
1416
-
1417
- // 6. 下载文件
1418
- const blob = XLSX.write(newWorkbook, {
1419
- bookType: "xlsx",
1420
- type: "array",
1421
- });
1422
-
1423
- const url = URL.createObjectURL(blob);
1424
- const a = document.createElement("a");
1425
- a.href = url;
1426
- let fileName = null;
1427
- if (this.resultType) {
1428
- fileName = `导入结果(成功).xlsx`;
1429
- } else {
1430
- fileName = `导入结果(失败).xlsx`;
1431
- }
1432
- a.download = fileName;
1433
- a.click();
1434
-
1435
- // 7. 更新进度
1436
- this.progress = 100;
1437
- setTimeout(() => (this.progress = 0), 1000);
1438
- } catch (error) {
1439
- console.error("处理文件时出错:", error);
1440
- }
1441
- },
1442
- //end
1443
- getLoadingClass(flag, percent) {
1444
- let classStr = null;
1445
- let loadingIndex = this.loadingIndex;
1446
- if (percent >= 100) {
1447
- classStr = "ok";
1448
- } else if (flag === loadingIndex) {
1449
- classStr = "loading";
1450
- }
1451
- return classStr;
1452
- },
1453
-
1454
- /***sheet1 */
1455
- async readExcel2(file, callback) {
1456
- let that = this;
1457
- let option = this.option;
1458
-
1459
- const fileReader = new FileReader();
1460
- fileReader.onload = async (ev) => {
1461
- let resultData;
1462
- try {
1463
- const data = ev.target.result;
1464
- const workbook = configUtil.XLSX.read(data, {
1465
- type: "binary",
1466
- });
1467
-
1468
- let sheetDatas = [];
1469
- for (let pi = 0; pi < workbook.SheetNames.length; pi++) {
1470
- let sheetName = workbook.SheetNames[pi];
1471
- let sheet = workbook.Sheets[sheetName];
1472
-
1473
- if (sheet["!ref"] === undefined || sheet["!ref"] === null) {
1474
- that.$baseAlert(
1475
- this.$t2(
1476
- "请使用正确的导入模版!",
1477
- "components.excelImport.warmMsg2"
1478
- )
1479
- );
1480
- that.handleClose2();
1481
- return false;
1482
- }
1483
- let range = configUtil.XLSX.utils.decode_range(sheet["!ref"]);
1484
- let dataSize = range.e.r + 1; //行数
1485
- that.dataSize = dataSize - 3 >= 0 ? dataSize - 3 : 0;
1486
- let titles = [];
1487
- let fields = [];
1488
-
1489
- const ws = workbook.Sheets[sheet];
1490
-
1491
- let prefix = option.prefix;
1492
- let excelUrl = option.excel;
1493
-
1494
- let excelRows = [];
1495
- let row;
1496
- let rowNum;
1497
- let colNum;
1498
- for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
1499
- row = [];
1500
- for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
1501
- let nextCell =
1502
- sheet[
1503
- configUtil.XLSX.utils.encode_cell({
1504
- r: rowNum,
1505
- c: colNum,
1506
- })
1507
- ];
1508
- if (typeof nextCell === "undefined") {
1509
- row.push(void 0);
1510
- } else {
1511
- row.push(nextCell.w.trim());
1512
- }
1513
- }
1514
- if (rowNum === 1) {
1515
- titles = row;
1516
- }
1517
- if (rowNum === 2) {
1518
- fields = row;
1519
- let checkResult = true;
1520
- }
1521
- if (rowNum > 2) {
1522
- let item = {};
1523
- for (let i = 0; i < fields.length; i++) {
1524
- let field = fields[i];
1525
- if (field) {
1526
- item[field] = row[i] ?? null;
1527
- }
1528
- }
1529
- excelRows.push(item);
1530
- }
1531
- }
1532
- if (
1533
- !titles.length ||
1534
- !fields.length ||
1535
- titles.length !== fields.length
1536
- ) {
1537
- that.$baseAlert(
1538
- this.$t2(
1539
- "请使用正确的导入模版!",
1540
- "components.excelImport.warmMsg2"
1541
- )
1542
- );
1543
- // that.handleClose2();
1544
- return false;
1545
- }
1546
-
1547
- let columns = [];
1548
- let cols = [];
1549
- let uniqueFields = [];
1550
- let uniqueKeys = [];
1551
- for (let i = 0; i < titles.length; i++) {
1552
- let title = titles[i];
1553
- if (title) {
1554
- let field = fields[i];
1555
- if (field === null || field === undefined) {
1556
- that.$baseAlert(
1557
- this.$t2(
1558
- "请使用正确的导入模版!",
1559
- "components.excelImport.warmMsg2"
1560
- )
1561
- );
1562
- // that.handleClose2();
1563
- return false;
1564
- }
1565
- let t = title.substr(-1);
1566
- let u = title.length >= 2 ? title.substr(-2) : title;
1567
- let p = title.length >= 3 ? title.substr(-3) : title;
1568
- let isNeed = false;
1569
- if (t === "*") {
1570
- isNeed = true;
1571
- }
1572
- let isUnique = false;
1573
- /* if (u === "**") {
1574
- uniqueFields.push(field);
1575
- isUnique = true;
1576
- } */
1577
- let isSheetUnique = false;
1578
- if (p === "***") {
1579
- uniqueKeys.push(field);
1580
- isSheetUnique = true;
1581
- }
1582
- if (!uniqueKeys.length) {
1583
- // that.clearImportTimer();
1584
- that.$baseAlert(
1585
- `[${sheetName}]` + that.$t1("缺失单据唯一标识***")
1586
- );
1587
- // that.handleClose2();
1588
- return false;
1589
- }
1590
-
1591
- let otherConfig = {};
1592
- let isFile = false;
1593
- if (field.startsWith("attachments_")) {
1594
- that.fileCellFields.push(field);
1595
- isFile = true;
1596
- otherConfig = {
1597
- slots: {
1598
- default: "attachment",
1599
- },
1600
- };
1601
- }
1602
-
1603
- let col = {
1604
- field: field,
1605
- title: title,
1606
- width: 100,
1607
- isNeed: isNeed,
1608
- isUnique: isUnique,
1609
- isFile,
1610
- otherConfig,
1611
- isSheetUnique,
1612
- };
1613
- cols.push(col);
1614
- }
1615
- }
1616
-
1617
- let oriCols = JSON.parse(JSON.stringify(cols)); //列信息
1618
- /* if (uniqueKeys.length) {
1619
- //分组唯一字段为空时,全部不发包。
1620
- for (let i = 0; i < oriCols.length; i++) {
1621
- let oriCol = oriCols[i];
1622
- if (uniqueKeys.includes(oriCol.field)) {
1623
- for (let j = 0; j < excelRows.length; j++) {
1624
- let data = excelRows[j];
1625
- let value = data[oriCol.field];
1626
- if (value === null || value === undefined || value === "") {
1627
- that.errorHandle(`[${sheetName}]`+
1628
- that.$t2(
1629
- "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
1630
- "components.excelImport.warmMsg3",
1631
- {
1632
- lineNo: j + 4,
1633
- title: oriCol.title,
1634
- }
1635
- ));
1636
- return false;
1637
- }
1638
- }
1639
- }
1640
- }
1641
- } */
1642
- // this.oriCols = oriCols;
1643
-
1644
- let resultData1 = {
1645
- sheetName: sheetName,
1646
- data: excelRows,
1647
- titles: titles,
1648
- fields: fields,
1649
- uniqueFields: uniqueFields,
1650
- oriCols: oriCols,
1651
- uniqueKeys,
1652
- };
1653
- sheetDatas.push(resultData1);
1654
- }
1655
-
1656
- //校验必填
1657
- if (!that.checkAllSheetData(sheetDatas)) {
1658
- return false;
1659
- }
1660
-
1661
- //合并多sheet数据
1662
- let newDatas = [];
1663
- resultData = that.$baseLodash.cloneDeep(sheetDatas[0]);
1664
- let uniqueKey = resultData.uniqueKeys[0];
1665
- let data2 = [];
1666
- for (let i = 0; i < resultData.data.length; i++) {
1667
- let item = resultData.data[i];
1668
- let sheetName = resultData[sheetName];
1669
- let uniqueValue = item[uniqueKey];
1670
-
1671
- if (!that.isNull(uniqueValue)) {
1672
- let newItem = { ...item };
1673
- let allItems = [];
1674
- for (let j = 1; j < sheetDatas.length; j++) {
1675
- let sheetData = sheetDatas[j];
1676
- let fDatas = [];
1677
- for (let k = 0; k < sheetData.data.length; k++) {
1678
- let sheetItem = sheetData.data[k];
1679
- if (that.isNull(sheetItem[uniqueKey])) {
1680
- that.handleCellNotNull(k, sheetData);
1681
- return;
1682
- }
1683
- if (sheetItem[uniqueKey] === uniqueValue) {
1684
- fDatas.push(sheetItem);
1685
- }
1686
- }
1687
- allItems.push(fDatas);
1688
- }
1689
- newItem.sheetItems = allItems;
1690
- data2.push(newItem);
1691
- } else {
1692
- that.handleCellNotNull(i, resultData);
1693
- return false;
1694
- }
1695
- }
1696
-
1697
- resultData.sheetDatas = sheetDatas;
1698
- resultData.data = data2;
1699
- this.oriCols = resultData.oriCols;
1700
- this.resultData = resultData;
1701
- callback(resultData);
1702
- } catch (et) {
1703
- that.showContent = false;
1704
- that.clearImportTimer();
1705
- console.error(et);
1706
- }
1707
- };
1708
- fileReader.readAsBinaryString(file);
1709
- },
1710
- isNull(val) {
1711
- if (val === null || val === undefined || val === "" || val === undefined || val === null) {
1712
- return true;
1713
- }
1714
- },
1715
- checkAllSheetData(sheetItems){
1716
- let that = this;
1717
- for(let sheetItem of sheetItems){
1718
- let oriCols = sheetItem.oriCols;
1719
- let uniqueKeys = sheetItem.uniqueKeys;
1720
- let excelRows = sheetItem.data;
1721
- let sheetName = sheetItem.sheetName;
1722
-
1723
- for (let i = 0; i < oriCols.length; i++) {
1724
- let oriCol = oriCols[i];
1725
- if (oriCol.isNeed || uniqueKeys.includes(oriCol.field)) {
1726
- for (let j = 0; j < excelRows.length; j++) {
1727
- let data = excelRows[j];
1728
- let value = data[oriCol.field];
1729
- if (that.isNull(value)) {
1730
- that.errorHandle(`[${sheetName}]`+
1731
- that.$t2(
1732
- "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
1733
- "components.excelImport.warmMsg3",
1734
- {
1735
- lineNo: j + 4,
1736
- title: oriCol.title,
1737
- }
1738
- ));
1739
- return false;
1740
- }
1741
- }
1742
- }
1743
- }
1744
-
1745
- }
1746
- return true;
1747
- },
1748
-
1749
-
1750
- handleCellNotNull(i, sheetData) {
1751
- let that = this;
1752
- let uniqueKey = sheetData.uniqueKeys[0];
1753
- let oriCol = sheetData.oriCols.find((item) => item.field === uniqueKey);
1754
- that.errorHandle(
1755
- `[${sheetData.sheetName}]` +
1756
- that.$t2(
1757
- "第" + (i + 4) + "行[" + oriCol.title + "]不能为空;",
1758
- "components.excelImport.warmMsg3",
1759
- {
1760
- lineNo: i + 4,
1761
- title: oriCol.title,
1762
- }
1763
- )
1764
- );
1765
- },
1766
- errorHandle(errorText) {
1767
- this.clearImportTimer();
1768
- this.$baseAlert(errorText);
1769
- // this.handleClose2();
1770
- },
1771
- /***sheet2 */
1772
- },
1773
- };
1774
- export const mixins = tmixins;
1
+ /**version-1.0*/
2
+ import { read, utils } from "xlsx";
3
+ import axios from "axios";
4
+ import SparkMD5 from "spark-md5";
5
+
6
+ let tmixins = {};
7
+ let XLSX = window.XLSX || { read, utils };
8
+ import { getToken } from "../../../../../utils/auth";
9
+ import XEUtils from "xe-utils";
10
+ import { getErrorMsg } from "@base/utils/index.js";
11
+
12
+ let configUtil = {
13
+ baseUrl: process.env.VUE_APP_BASE_API,
14
+ XLSX,
15
+ getToken,
16
+ };
17
+ // importTimer / loadingObj 原为模块级单例:两个导入弹窗并存时后者覆盖前者引用,
18
+ // 前一个 interval(100ms/次)与 loading 永久失控——已改为实例属性 this.importTimer / this.loadingObj
19
+ tmixins = {
20
+ name: "excelImport",
21
+ props: ["param", "parentTarget"],
22
+ inject: ["getReportTemplate", "formHttp"],
23
+ data() {
24
+ return {
25
+ excTime: 0,
26
+ showImportDialog: false,
27
+ showImportDialog2: false,
28
+ falseValue: false,
29
+ fileRaw: false,
30
+ isEnd: false,
31
+ currentIndex: 0,
32
+ excelTemplate: "",
33
+ prefix: "/user",
34
+ dataSize: 0,
35
+ totalSuccessNum: 0,
36
+ totalErrorNum: 0,
37
+ percentageNum: 0,
38
+ successRows: [],
39
+ failRows: [],
40
+ oriCols: [],
41
+ showImportResult: false,
42
+ resultType: "",
43
+ option: {},
44
+ showContent: false,
45
+ resOption: {},
46
+ fileCellFields: [],
47
+ importLoading: false,
48
+ loadingTitle: null,
49
+
50
+ percent1: 0,
51
+ percent2: 0,
52
+ percent3: 0,
53
+
54
+ loadingPercent: 0,
55
+ handleRowSize: 1,
56
+
57
+ headerRows: 3,
58
+ };
59
+ },
60
+ computed: {
61
+ importFileLimitSize() {
62
+ return Math.min(
63
+ this.param?.importOption?.importFileLimitSize || 200,
64
+ 200
65
+ );
66
+ },
67
+ },
68
+ created() {
69
+ this.exc();
70
+ },
71
+ beforeDestroy() {
72
+ this.clearImportTimer();
73
+ },
74
+ methods: {
75
+ initResGird() {
76
+ let that = this;
77
+ let tableRef = "resGrid";
78
+ let columns = [
79
+ {
80
+ type: "checkbox",
81
+ fixed: "left",
82
+ width: 48,
83
+ resizable: false,
84
+ headerClassName: "vxe-hcs",
85
+ className: "vxe-hcs",
86
+ },
87
+ {
88
+ field: "impNumber",
89
+ title: this.$t2("行号", "components.excelImport.impNumber"),
90
+ width: 100,
91
+ fixed: "left",
92
+ },
93
+ {
94
+ field: "_resultContent",
95
+ title: this.$t2("结果", "components.excelImport.resultContent"),
96
+ width: 250,
97
+ fixed: "left",
98
+ slots: {
99
+ default: ({ row, $rowIndex, $table }) => {
100
+ return that.handleRes(row._resultContent);
101
+ },
102
+ },
103
+ },
104
+ ];
105
+ let cCols = this.oriCols.map((oriCol, index) => {
106
+ let col = {
107
+ field: oriCol.field,
108
+ title: oriCol.title,
109
+ width: 150,
110
+ ...oriCol.otherConfig,
111
+ };
112
+ if (index === 0) {
113
+ col.fixed = "left";
114
+ }
115
+ return col;
116
+ });
117
+ columns = columns.concat(cCols);
118
+
119
+ let tableOption = {
120
+ vue: this,
121
+ tableRef: tableRef,
122
+ tableNameRequired: false,
123
+ columns: columns,
124
+ config: {
125
+ toolbarConfig: {
126
+ custom: false,
127
+ },
128
+ },
129
+ };
130
+
131
+ this.$vxeTableUtil.initVxeTable(tableOption).then((opts) => {
132
+ this.resOption = opts;
133
+ });
134
+ },
135
+ exc() {
136
+ this.option = this.param;
137
+ this.showContent = true;
138
+ this.showImportDialog = true;
139
+ this.showImportDialog2 = false;
140
+ },
141
+ showSuccessResult() {
142
+ this.showImportResult = true;
143
+ this.resultType = 1;
144
+ this.$nextTick(() => {
145
+ this.initResGird();
146
+ this.$nextTick(() => {
147
+ let tDatas = this.successRows.map((item, index) => {
148
+ item.id = index;
149
+ return item;
150
+ });
151
+ this.$refs.resGrid.loadData(tDatas);
152
+ });
153
+ });
154
+ },
155
+ showErrorResult() {
156
+ this.showImportResult = true;
157
+ this.resultType = 0;
158
+ this.$nextTick(() => {
159
+ this.initResGird();
160
+ this.$nextTick(() => {
161
+ let tDatas = this.failRows.map((item, index) => {
162
+ item.id = index;
163
+ return item;
164
+ });
165
+ this.$refs.resGrid.loadData(tDatas);
166
+ });
167
+ });
168
+ },
169
+ fileChange(file) {
170
+ if (file) {
171
+ this.fileRaw = file.raw;
172
+ } else {
173
+ this.fileRaw = false;
174
+ }
175
+ },
176
+ dialogClose1() {
177
+ this.importLoading = false;
178
+ if (!this.showImportDialog2) {
179
+ this.$emit("update:visiable", false);
180
+ this.showContent = false;
181
+ }
182
+ },
183
+ async dialogPrimary1() {
184
+ let that = this;
185
+ let option = this.option;
186
+
187
+ let fileRaw = this.fileRaw;
188
+ if (!fileRaw) {
189
+ this.$baseAlert(
190
+ this.$t2("请上传附件", "components.excelImport.warmMsg1")
191
+ );
192
+ return false;
193
+ }
194
+ let importFileLimitSize = this.importFileLimitSize;
195
+ let fileSize = fileRaw.size;
196
+ let limitSize = importFileLimitSize * 1024 * 1024;
197
+ if (fileSize > limitSize) {
198
+ this.$baseAlert(
199
+ this.$t1("导入文件不允许超过{fileSize}MB", {
200
+ fileSize: importFileLimitSize,
201
+ })
202
+ );
203
+ return false;
204
+ }
205
+
206
+ if (option.importFrontOnly) {
207
+ this.dialogPrimary3();
208
+ return false;
209
+ }
210
+
211
+ /* this.createImportTimer();
212
+ this.showImportDialog = false;
213
+ if (!option.onConfirm) {
214
+ this.showImportDialog2 = true;
215
+ } */
216
+ // this.$nextTick(() => {
217
+ try {
218
+ this.readExcel(this.fileRaw, function (resultData) {
219
+ that.createImportTimer();
220
+ that.showImportDialog = false;
221
+ if (!option.onConfirm) {
222
+ that.showImportDialog2 = true;
223
+ }
224
+ that.$nextTick(() => {
225
+ if (option.onConfirm) {
226
+ option.onConfirm(resultData.data, that.fileRaw);
227
+ } else {
228
+ that.handleBeforeImport0(that.fileRaw, resultData, () => {
229
+ that.syncDataForImport({
230
+ multi: false,
231
+ data: resultData,
232
+ // saveUrl: saveUrl
233
+ });
234
+ });
235
+ }
236
+ });
237
+ });
238
+ } catch (et) {
239
+ that.clearImportTimer();
240
+ console.error(et);
241
+ }
242
+ // });
243
+ },
244
+ handleBeforeImport(file, resultData, callback) {
245
+ let importOption = this.option.importOption;
246
+ let that = this;
247
+ if (importOption.onBeforeImport) {
248
+ const toDo = (res) => {
249
+ let rows = res?.objx || [];
250
+ rows.forEach((row, rowIndex) => {
251
+ let item = resultData[rowIndex];
252
+ Object.keys(row).forEach((key) => {
253
+ item[key] = row[key];
254
+ });
255
+ });
256
+ callback && callback();
257
+ };
258
+ this.getFieldTarget().handleCustomEvent(
259
+ importOption.onBeforeImport,
260
+ ["file", "resultData", "done"],
261
+ [file, resultData, toDo]
262
+ );
263
+ } else {
264
+ callback && callback();
265
+ }
266
+ },
267
+ handleBeforeImport0(file, resultData, callback) {
268
+ if (!this.showImportDialog2) return;
269
+ let importOption = this.option.importOption;
270
+ if (!importOption.enabledImportPreHandle) {
271
+ this.handleBeforeImport(file, resultData, () => {
272
+ callback && callback();
273
+ });
274
+ return;
275
+ }
276
+
277
+ this.uploadFile(() => {
278
+ this.importLoading = false;
279
+ this.handleBeforeImport(file, resultData, () => {
280
+ callback && callback();
281
+ });
282
+ });
283
+ return;
284
+ },
285
+ handleBeforeClose(hide) {
286
+ this.option.onCancel &&
287
+ this.option.onCancel(this.getCallbackData(), this.fileRaw);
288
+ let importOption = this.option.importOption;
289
+ this.getFieldTarget().handleCustomEvent(
290
+ importOption.onSuccessImport,
291
+ ["resultData", "file"],
292
+ [this.getCallbackData(), this.fileRaw]
293
+ );
294
+ this.handleTableCallback();
295
+ hide();
296
+ },
297
+ dialogClose2() {
298
+ this.showImportDialog2 = false;
299
+ this.option.onBeforeCancel &&
300
+ this.option.onBeforeCancel(this.getCallbackData(), this.fileRaw);
301
+ let importOption = this.option.importOption;
302
+ this.getFieldTarget().handleCustomEvent(
303
+ importOption.onSuccessImport,
304
+ ["resultData", "file"],
305
+ [this.getCallbackData(), this.fileRaw]
306
+ );
307
+ this.handleTableCallback();
308
+ },
309
+ handleClose2() {
310
+ this.clearImportTimer();
311
+ this.showImportDialog2 = false;
312
+ this.showContent = false;
313
+ this.option.onClose &&
314
+ this.option.onClose(this.getCallbackData(), this.fileRaw);
315
+ this.option.callback &&
316
+ this.option.callback(this.getCallbackData(), this.fileRaw);
317
+ this.dialogClose1();
318
+ },
319
+ dialogPrimary2() {
320
+ let importOption = this.option.importOption;
321
+ this.showImportDialog2 = false;
322
+ this.option.onBeforeConfirm &&
323
+ this.option.onBeforeConfirm(this.getCallbackData(), this.fileRaw);
324
+ this.getFieldTarget().handleCustomEvent(
325
+ importOption.onSuccessImport,
326
+ ["resultData", "file"],
327
+ [this.getCallbackData(), this.fileRaw]
328
+ );
329
+ this.handleTableCallback();
330
+ },
331
+ getCallbackData() {
332
+ return {
333
+ ...this.resultData,
334
+ successRows: this.successRows,
335
+ failRows: this.failRows,
336
+ };
337
+ },
338
+
339
+ /*dialogClose2(flag) {
340
+ let importOption = this.option.importOption;
341
+ this.clearImportTimer();
342
+ this.showImportDialog2 = false;
343
+ this.dialogClose1();
344
+ this.handleTableCallback(flag);
345
+ this.parentTarget.handleCustomEvent(importOption.onSuccessImport, ['resultData', 'file'], [this.resultData, this.fileRaw])
346
+ this.option.callback && this.option.callback(this.resultData, this.fileRaw);
347
+ },
348
+ dialogPrimary2() {
349
+ let importOption = this.option.importOption;
350
+ this.clearImportTimer();
351
+ this.showImportDialog2 = false;
352
+ this.dialogClose1()
353
+ this.handleTableCallback();
354
+ let fileRaw = this.fileRaw;
355
+ this.parentTarget.handleCustomEvent(importOption.onSuccessImport, ['resultData', 'file'], [this.resultData, this.fileRaw])
356
+ this.option.callback && this.option.callback(this.resultData, this.fileRaw);
357
+ },*/
358
+ handleTableCallback(flag) {
359
+ if (flag === 0) return;
360
+ let importOption = this.option.importOption;
361
+ let tableTarget;
362
+ if (importOption.tableRef)
363
+ tableTarget = this.getFieldTarget().getWidgetRef(importOption.tableRef);
364
+ if (tableTarget) {
365
+ let isQueryTable = tableTarget.widget.options.isQueryTable;
366
+ if (isQueryTable) {
367
+ tableTarget.searchEvent();
368
+ }
369
+ }
370
+ },
371
+ async readExcel(file, callback) {
372
+ let that = this;
373
+ let option = this.option;
374
+
375
+ if (option.importOption.multipleSheet) {
376
+ this.readExcel2(file, callback);
377
+ return;
378
+ }
379
+
380
+ const fileReader = new FileReader();
381
+ fileReader.onload = async (ev) => {
382
+ let resultData;
383
+ try {
384
+ const data = ev.target.result;
385
+ const workbook = configUtil.XLSX.read(data, {
386
+ type: "binary",
387
+ });
388
+
389
+ let sheet = workbook.Sheets[workbook.SheetNames[0]];
390
+ if (sheet["!ref"] === undefined || sheet["!ref"] === null) {
391
+ /*that.showImportDialog2 = false;
392
+ that.showContent = false;
393
+ that.clearImportTimer();*/
394
+ that.$baseAlert(
395
+ this.$t2(
396
+ "请使用正确的导入模版!",
397
+ "components.excelImport.warmMsg2"
398
+ )
399
+ );
400
+ that.handleClose2();
401
+ return false;
402
+ }
403
+ let range = configUtil.XLSX.utils.decode_range(sheet["!ref"]);
404
+ let dataSize = range.e.r + 1; //行数
405
+ that.dataSize = dataSize - 3 >= 0 ? dataSize - 3 : 0;
406
+ let titles = [];
407
+ let fields = [];
408
+
409
+ const ws = workbook.Sheets[sheet];
410
+
411
+ let prefix = option.prefix;
412
+ let excelUrl = option.excel;
413
+
414
+ let excelRows = [];
415
+ let row;
416
+ let rowNum;
417
+ let colNum;
418
+ for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
419
+ row = [];
420
+ for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
421
+ let nextCell =
422
+ sheet[
423
+ configUtil.XLSX.utils.encode_cell({
424
+ r: rowNum,
425
+ c: colNum,
426
+ })
427
+ ];
428
+ if (typeof nextCell === "undefined") {
429
+ row.push(void 0);
430
+ } else {
431
+ row.push(nextCell.w.trim());
432
+ }
433
+ }
434
+ if (rowNum === 1) {
435
+ titles = row;
436
+ }
437
+ if (rowNum === 2) {
438
+ fields = row;
439
+ let checkResult = true;
440
+ /*await that.checkExcelForImport(titles, fields, excelUrl, prefix).then(
441
+ res => {
442
+ if (res.type !== "success") {
443
+ checkResult = false;
444
+ }
445
+ });
446
+ if (!checkResult) {
447
+ that.showContent = false;
448
+ that.clearImportTimer();
449
+ return false;
450
+ }*/
451
+ }
452
+ if (rowNum > 2) {
453
+ let item = {};
454
+ for (let i = 0; i < fields.length; i++) {
455
+ let field = fields[i];
456
+ if (field) {
457
+ item[field] = row[i] ?? null;
458
+ }
459
+ }
460
+ excelRows.push(item);
461
+ }
462
+ }
463
+ if (
464
+ !titles.length ||
465
+ !fields.length ||
466
+ titles.length !== fields.length
467
+ ) {
468
+ // that.showContent = false;
469
+ // that.clearImportTimer();
470
+ that.$baseAlert(
471
+ this.$t2(
472
+ "请使用正确的导入模版!",
473
+ "components.excelImport.warmMsg2"
474
+ )
475
+ );
476
+ that.handleClose2();
477
+ return false;
478
+ }
479
+
480
+ let columns = [];
481
+ let cols = [];
482
+ let uniqueFields = [];
483
+ for (let i = 0; i < titles.length; i++) {
484
+ let title = titles[i];
485
+ if (title) {
486
+ let field = fields[i];
487
+ if (field === null || field === undefined) {
488
+ // that.showContent = false;
489
+ // that.clearImportTimer();
490
+ that.$baseAlert(
491
+ this.$t2(
492
+ "请使用正确的导入模版!",
493
+ "components.excelImport.warmMsg2"
494
+ )
495
+ );
496
+ that.handleClose2();
497
+ return false;
498
+ }
499
+ let t = title.substr(-1);
500
+ let u = title.length >= 2 ? title.substr(-2) : title;
501
+ let isNeed = false;
502
+ if (t === "*") {
503
+ isNeed = true;
504
+ }
505
+ let isUnique = false;
506
+ if (u === "**") {
507
+ uniqueFields.push(field);
508
+ isUnique = true;
509
+ }
510
+
511
+ let otherConfig = {};
512
+ let isFile = false;
513
+ if (field.startsWith("attachments_")) {
514
+ that.fileCellFields.push(field);
515
+ isFile = true;
516
+ otherConfig = {
517
+ slots: {
518
+ default: "attachment",
519
+ },
520
+ };
521
+ }
522
+
523
+ let col = {
524
+ field: field,
525
+ title: title,
526
+ width: 100,
527
+ isNeed: isNeed,
528
+ isUnique: isUnique,
529
+ isFile,
530
+ otherConfig,
531
+ };
532
+ cols.push(col);
533
+ }
534
+ }
535
+
536
+ let oriCols = JSON.parse(JSON.stringify(cols)); //列信息
537
+ if (uniqueFields.length) {
538
+ //分组唯一字段为空时,全部不发包。
539
+ for (let i = 0; i < oriCols.length; i++) {
540
+ let oriCol = oriCols[i];
541
+ if (oriCol.isNeed) {
542
+ for (let j = 0; j < excelRows.length; j++) {
543
+ let data = excelRows[j];
544
+ let value = data[oriCol.field];
545
+ if (value === null || value === undefined || value === "") {
546
+ that.clearImportTimer();
547
+ that.$baseAlert(
548
+ this.$t2(
549
+ "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
550
+ "components.excelImport.warmMsg3",
551
+ {
552
+ lineNo: j + 4,
553
+ title: oriCol.title,
554
+ }
555
+ )
556
+ );
557
+ that.handleClose2();
558
+ return false;
559
+ }
560
+ }
561
+ }
562
+ }
563
+ }
564
+
565
+ this.oriCols = oriCols;
566
+
567
+ resultData = {
568
+ data: excelRows,
569
+ titles: titles,
570
+ fields: fields,
571
+ uniqueFields: uniqueFields,
572
+ oriCols: oriCols,
573
+ };
574
+ this.resultData = resultData;
575
+ callback(resultData);
576
+ } catch (et) {
577
+ that.showContent = false;
578
+ that.clearImportTimer();
579
+ console.error(et);
580
+ }
581
+ };
582
+ fileReader.readAsBinaryString(file);
583
+ },
584
+ async checkExcelForImport(titles, fields, turl, prefix) {
585
+ if (!this.showImportDialog2) return;
586
+ let that = this;
587
+ let data = {
588
+ filed_name: fields,
589
+ field_note: titles,
590
+ url: turl,
591
+ };
592
+ let param = JSON.stringify(data);
593
+ return this.$http({
594
+ url: prefix + "/sf_common/compareExcelFields",
595
+ method: "post",
596
+ headers: {
597
+ "Content-Type": "application/json;charset=utf-8",
598
+ },
599
+ // data: param,
600
+ data: data,
601
+ });
602
+ },
603
+ saveImportHandle(data, opt) {
604
+ let multi = this.option.multi;
605
+ let importOption = this.option.importOption;
606
+
607
+ let entity = importOption.importEntity;
608
+
609
+ if (!entity) return;
610
+
611
+ let reportTemplate = this.getReportTemplate();
612
+ let formCode = reportTemplate?.formCode;
613
+ let scriptCode = importOption.importScriptCode || "import";
614
+ // let config = option?.config;
615
+
616
+ // let reqData = this.getReqFormData();
617
+ let fileCellFields = this.fileCellFields;
618
+ let formData = null;
619
+ if (multi) {
620
+ formData = data;
621
+ } else {
622
+ formData = {
623
+ [entity]: { ...data },
624
+ };
625
+ if (fileCellFields.length) {
626
+ fileCellFields.forEach((field) => {
627
+ let attachments = data[field] || [];
628
+ delete formData[entity][field];
629
+ formData[field] = attachments;
630
+ });
631
+ }
632
+ }
633
+
634
+ let reqData = {
635
+ formCode: formCode,
636
+ formVersion: reportTemplate.formVersion,
637
+ taBm: entity,
638
+ data: formData,
639
+ };
640
+
641
+ this.formHttp({
642
+ scriptCode: scriptCode,
643
+ data: reqData,
644
+ modal: false,
645
+ ...opt,
646
+ });
647
+ },
648
+ syncDataForImport(opts) {
649
+ let that = this;
650
+ let multi = this.option.multi;
651
+ let resultData = this.resultData;
652
+ let datas = resultData.data;
653
+ let titles = resultData.titles;
654
+ let fields = resultData.fields;
655
+ let uniqueFields = resultData.uniqueFields;
656
+ let saveUrl = opts.saveUrl;
657
+ let size = datas.length;
658
+ let index = 0;
659
+ let successNum = 0;
660
+ let failNum = 0;
661
+ let dialogObj = this.$refs.importDialog.$el;
662
+ let successNumObj = dialogObj.querySelector(".successNum");
663
+ let failNumObj = dialogObj.querySelector(".failNum");
664
+ let percentageObj = dialogObj.querySelector(".percentage");
665
+ let doneNumObj = dialogObj.querySelector(".doneNum");
666
+ dialogObj.querySelector(".dataSize").innerText = size;
667
+
668
+ that.successRows = [];
669
+ that.failRows = [];
670
+
671
+ let multiSize = this.option.multiSize || 2;
672
+
673
+ let groupIndex = 0;
674
+ let groupDatas = [];
675
+ if (uniqueFields.length) {
676
+ let d = XEUtils.groupBy(datas, function (item, itemIndex, items) {
677
+ let keyArr = [];
678
+ uniqueFields.forEach((field) => {
679
+ keyArr.push(item[field]);
680
+ });
681
+ return keyArr.join("&_&");
682
+ });
683
+ for (let key in d) {
684
+ groupDatas.push(d[key]);
685
+ }
686
+ datas.forEach((item, itemIndex) => {
687
+ item.impSeq = itemIndex;
688
+ item.impNumber = itemIndex + 4;
689
+ });
690
+ }
691
+
692
+ let compareV = function (property) {
693
+ return function (a, b) {
694
+ let value1 = a[property];
695
+ let value2 = b[property];
696
+ return value1 - value2;
697
+ };
698
+ };
699
+
700
+ let prevHandleData = function (percentageStr, excNum) {
701
+ successNumObj.innerText = successNum;
702
+ failNumObj.innerText = failNum;
703
+ doneNumObj.innerText = successNum + failNum;
704
+ that.percentageNum = percentageStr;
705
+ let isEnd = false;
706
+ if (multi && uniqueFields.length) {
707
+ isEnd = groupIndex + 1 >= groupDatas.length;
708
+ } else {
709
+ isEnd = index + excNum >= size;
710
+ }
711
+ if (!isEnd) {
712
+ index = index + excNum;
713
+ groupIndex = groupIndex + 1;
714
+ setTimeout(function () {
715
+ handleData();
716
+ }, 1);
717
+ } else {
718
+ setTimeout(function () {
719
+ that.clearImportTimer();
720
+ }, 300);
721
+ }
722
+ };
723
+
724
+ let getDefaultValue = (row) => {
725
+ let value = null;
726
+ let defaultValue = this.option.defaultValue;
727
+ if (defaultValue) {
728
+ if (typeof defaultValue === "function") {
729
+ value = defaultValue(row) || {};
730
+ } else {
731
+ value = defaultValue || {};
732
+ }
733
+ }
734
+ return value;
735
+ };
736
+
737
+ let handleData = () => {
738
+ if (!that.isEnd && index < size) {
739
+ let param;
740
+ let excNum;
741
+ if (multi) {
742
+ if (!uniqueFields.length) {
743
+ if (index + multiSize < size) {
744
+ excNum = multiSize;
745
+ } else {
746
+ excNum = size - index;
747
+ }
748
+
749
+ let dataList = [];
750
+ for (let i = 0; i < excNum; i++) {
751
+ let mIndex = index + i;
752
+ let mData = datas[mIndex];
753
+ mData.impSeq = mIndex;
754
+ mData.impNumber = mIndex + 4;
755
+
756
+ let errorInfo = that.vailData(mData, opts);
757
+ if (errorInfo.length > 0) {
758
+ mData._resultType = "error";
759
+ mData._resultContent = errorInfo;
760
+ failNum++;
761
+ that.failRows.push(mData);
762
+ } else {
763
+ let defaultValue = getDefaultValue(mData);
764
+ if (defaultValue) {
765
+ Object.assign(mData, defaultValue);
766
+ }
767
+ dataList.push(mData);
768
+ }
769
+
770
+ datas[mIndex] = mData;
771
+ }
772
+ if (dataList.length > 0) {
773
+ param = dataList;
774
+ }
775
+ } else {
776
+ excNum = groupDatas[groupIndex].length;
777
+ param = groupDatas[groupIndex];
778
+ }
779
+ } else {
780
+ let data = that.resultData.data[index];
781
+ data.impSeq = index;
782
+ data.impNumber = index + 4;
783
+ excNum = 1;
784
+ datas[index] = data;
785
+
786
+ let errorInfo = that.vailData(data, opts);
787
+ if (errorInfo.length > 0) {
788
+ data._resultType = "error";
789
+ data._resultContent = errorInfo;
790
+ failNum++;
791
+ that.failRows.push(data);
792
+ } else {
793
+ param = data;
794
+ let defaultValue = getDefaultValue(data);
795
+ if (defaultValue) {
796
+ Object.assign(param, defaultValue);
797
+ }
798
+ }
799
+ }
800
+
801
+ let percentageStr = parseInt(((index + excNum) * 100) / size);
802
+ if (param === null || param === undefined || param.length === 0) {
803
+ if (that.showContent) {
804
+ prevHandleData(percentageStr, excNum);
805
+ }
806
+ return;
807
+ }
808
+
809
+ that.saveImportHandle(param, {
810
+ failMsg: false,
811
+ callback: (resultMsg) => {
812
+ if (multi) {
813
+ if (resultMsg.type === "success") {
814
+ let multiRows = resultMsg.objx;
815
+ for (let i = 0; i < multiRows.length; i++) {
816
+ let multiRow = multiRows[i];
817
+ let data = datas[multiRow.impSeq];
818
+ data._resultType = multiRow.impReturnType;
819
+ data._resultContent =
820
+ multiRow.impReturnType === "success"
821
+ ? this.$t2(
822
+ "导入成功",
823
+ "components.excelImport.importSucess"
824
+ )
825
+ : multiRow.impReturnMsg;
826
+ if (multiRow.impReturnType === "success") {
827
+ successNum++;
828
+ that.successRows.push(data);
829
+ } else {
830
+ failNum++;
831
+ that.failRows.push(data);
832
+ }
833
+ }
834
+
835
+ that.failRows = that.failRows.sort(compareV("impSeq"));
836
+ } else {
837
+ // error_win(resultMsg);
838
+ // layer.close(opts.dialogObjIndex);
839
+
840
+ let items = param.map((item) => {
841
+ return {
842
+ ...item,
843
+ _resultType: "error",
844
+ _resultContent: resultMsg.content,
845
+ };
846
+ });
847
+ failNum = failNum + items.length;
848
+ that.failRows.push(...items);
849
+
850
+ that.failRows = that.failRows.sort(compareV("impSeq"));
851
+
852
+ /* that.$errorMsg(resultMsg);
853
+ that.showContent = false;
854
+ that.clearImportTimer();
855
+ return; */
856
+ }
857
+ } else {
858
+ let data = that.resultData.data[index];
859
+ data._resultType = resultMsg.type;
860
+ data._resultContent =
861
+ resultMsg.type === "success"
862
+ ? this.$t2(
863
+ "导入成功",
864
+ "components.excelImport.importSucess"
865
+ )
866
+ : resultMsg.content;
867
+
868
+ if (resultMsg.type === "success") {
869
+ successNum++;
870
+ that.successRows.push(data);
871
+ } else {
872
+ failNum++;
873
+ that.failRows.push(data);
874
+ }
875
+ }
876
+ if (that.showContent) {
877
+ prevHandleData(percentageStr, excNum);
878
+ }
879
+ },
880
+ error: (et) => {
881
+ that.isEnd = true;
882
+ that.clearImportTimer();
883
+ console.error(et);
884
+ },
885
+ });
886
+ }
887
+ };
888
+ handleData();
889
+ },
890
+ commonLocalDownload() {
891
+ let importOption = this.option.importOption;
892
+ let importAttachCode = importOption.importAttachCode;
893
+ if (!importAttachCode) return;
894
+ this.$http({
895
+ url: USER_PREFIX + "/bd_attach_setting/getByCode",
896
+ method: "post",
897
+ data: {
898
+ stringOne: importAttachCode,
899
+ },
900
+ success: (res) => {
901
+ let fileObj = res.objx;
902
+ let url = fileObj?.url;
903
+ if (fileObj && url) {
904
+ this.$commonFileUtil.downloadFile(url,fileObj.name);
905
+ }
906
+ },
907
+ });
908
+ },
909
+ vailData(data, opts) {
910
+ let oriCols = opts.data.oriCols;
911
+ let errorInfo = [];
912
+ for (let i = 0; i < oriCols.length; i++) {
913
+ let oriCol = oriCols[i];
914
+ if (oriCol.isNeed) {
915
+ let value = data[oriCol.field];
916
+ if (value === null || value === undefined || value === "") {
917
+ errorInfo.push(
918
+ this.$t2(
919
+ "[" + oriCol.title + "]不能为空;",
920
+ "components.excelImport.warmMsg4",
921
+ { title: oriCol.title }
922
+ )
923
+ );
924
+ }
925
+ }
926
+ }
927
+ return errorInfo.join("");
928
+ },
929
+ handleRes(val) {
930
+ /* let content = val;
931
+ let text = content;
932
+ if (content && content.indexOf("Exception") >= 0) {
933
+ let index0 = content.lastIndexOf("*]");
934
+ if (index0 >= 0) {
935
+ text = content.substr(index0);
936
+ if (text) {
937
+ let index1 = text.indexOf("Exception:");
938
+ if (index1 >= 0) {
939
+ text = text.substr(index1 + 10);
940
+ }
941
+ }
942
+ }
943
+ } */
944
+ let text = getErrorMsg(val);
945
+ return text;
946
+ },
947
+ exportToExcel() {
948
+ let str =
949
+ this.resultType === 1
950
+ ? this.$t2("成功", "components.excelImport.success")
951
+ : this.$t2("失败", "components.excelImport.fail");
952
+ let fileName =
953
+ this.$t2("导入结果导出", "components.excelImport.exportFileName") +
954
+ "(" +
955
+ str +
956
+ ")";
957
+ let $grid = this.$refs.resGrid;
958
+ let columns = $grid.getColumns();
959
+ if (columns && columns.length) {
960
+ let fields = columns
961
+ .filter((item, index) => {
962
+ return index > 0 && item.property;
963
+ })
964
+ .map((item, index) => {
965
+ return item.property;
966
+ });
967
+ this.$refs.resGrid.exportData({
968
+ filename: fileName,
969
+ mode: "all",
970
+ type: "csv",
971
+ columns: fields,
972
+ });
973
+ }
974
+ },
975
+ createImportTimer() {
976
+ this.excTime = 0;
977
+ let beginTime = new Date().getTime();
978
+ this.importTimer = setInterval(() => {
979
+ let nowTime = new Date().getTime();
980
+ let diffTime = (nowTime - beginTime) / 1000;
981
+ this.$set(this, "excTime", this.$baseLodash.round(diffTime, 2));
982
+ }, 100);
983
+ },
984
+ clearImportTimer() {
985
+ clearInterval(this.importTimer);
986
+ this.importTimer = null;
987
+ this.loadingObj && this.loadingObj.close();
988
+ this.loadingObj = null;
989
+ },
990
+ getWidgetTarget() {},
991
+ getFieldTarget() {
992
+ return this.param.target;
993
+ },
994
+ async dialogPrimary3() {
995
+ if (!this.fileRaw) {
996
+ this.$baseAlert(
997
+ this.$t2("请上传附件", "components.excelImport.warmMsg1")
998
+ );
999
+ return false;
1000
+ }
1001
+ let that = this;
1002
+ let option = this.option;
1003
+ this.loadingObj = this.$baseLoading({
1004
+ target: document.body,
1005
+ background: "unset",
1006
+ });
1007
+
1008
+ let importOption = option.importOption;
1009
+ this.readExcel(this.fileRaw, function (resultData) {
1010
+ let file = that.fileRaw;
1011
+ let flag = false;
1012
+ let done = () => {
1013
+ if (flag) return;
1014
+ flag = true;
1015
+ that.showImportDialog = false;
1016
+ return that
1017
+ .getFieldTarget()
1018
+ .handleCustomEvent(
1019
+ importOption.onSuccessImport,
1020
+ ["resultData", "file"],
1021
+ [resultData, file]
1022
+ );
1023
+ };
1024
+ const close = () => {
1025
+ that.dialogClose1();
1026
+ }
1027
+ try {
1028
+ if (importOption.onConfirmImportEnabled) {
1029
+ if (
1030
+ that
1031
+ .getFieldTarget()
1032
+ .handleCustomEvent(
1033
+ importOption.onConfirmImport,
1034
+ ["resultData", "file", "done", 'close'],
1035
+ [resultData, file, done, close]
1036
+ ) !== false
1037
+ ) {
1038
+ done();
1039
+ }
1040
+ } else if (importOption.tableRef) {
1041
+ let tableRef = that
1042
+ .getFieldTarget()
1043
+ .getWidgetRef(importOption.tableRef);
1044
+ tableRef && tableRef.addTableData(resultData.data);
1045
+ done();
1046
+ }
1047
+ } catch (et) {
1048
+ console.error(et);
1049
+ }
1050
+ setTimeout(function () {
1051
+ that.loadingObj && that.loadingObj.close();
1052
+ }, 200);
1053
+ });
1054
+ },
1055
+
1056
+ //begin
1057
+ fileParse(file, type = "base64", callback) {
1058
+ let fileRead = new FileReader();
1059
+ if (type === "base64") {
1060
+ fileRead.readAsDataURL(file);
1061
+ } else if (type === "buffer") {
1062
+ fileRead.readAsArrayBuffer(file);
1063
+ }
1064
+ fileRead.onload = (ev) => {
1065
+ callback(ev.target.result);
1066
+ };
1067
+ },
1068
+ getUploadText(percent) {
1069
+ return this.$t1("上传导入文件 {percent}%", { percent });
1070
+ },
1071
+ changeUploadPercent(percent) {
1072
+ // return this.$t1('上传导入文件 {percent}%', {percent})
1073
+ this.percent1 = percent;
1074
+ this.loadingIndex = 1;
1075
+ },
1076
+ uploadFile(callback) {
1077
+ let that = this;
1078
+ that.loadingPercent = 0;
1079
+ // that.loadingTitle = this.getUploadText(0);
1080
+ that.changeUploadPercent(0);
1081
+ let file = this.fileRaw;
1082
+ let uploadChunkSize = 5;
1083
+ this.importLoading = true;
1084
+ this.fileUploadCallback = callback;
1085
+ this.fileParse(file, "buffer", (buffer) => {
1086
+ let spark = new SparkMD5.ArrayBuffer(),
1087
+ chunkSize = uploadChunkSize * 1024 * 1024, // Read in chunks of 2MB
1088
+ chunks = Math.ceil(file.size / chunkSize),
1089
+ hash,
1090
+ suffix;
1091
+ spark.append(buffer);
1092
+ hash = spark.end();
1093
+ let md5 = hash;
1094
+ let nameSplit = /\.([0-9a-zA-Z]+)$/i.exec(file.name);
1095
+
1096
+ suffix = nameSplit && nameSplit.length > 1 ? nameSplit[1] : "";
1097
+
1098
+ let chunkParam = {
1099
+ fullFile: file,
1100
+ chunkSize: chunkSize,
1101
+ chunks: chunks,
1102
+ chunkIndex: 0,
1103
+ md5: hash,
1104
+ uuid: "",
1105
+ name: file.name,
1106
+ };
1107
+ file.chunkParam = chunkParam;
1108
+
1109
+ this.sendRequest(file);
1110
+ });
1111
+ },
1112
+ async sendRequest(fullFile) {
1113
+ if (!this.showImportDialog2) return;
1114
+ let that = this;
1115
+ let uploadUrl = USER_PREFIX + "/excel_import/uploadFile";
1116
+ let chunkParam = fullFile.chunkParam;
1117
+ let target = that.$refs.upload;
1118
+ let abort;
1119
+ let config = {
1120
+ headers: {
1121
+ "Content-Type": "multipart/form-data",
1122
+ },
1123
+ cancelToken: new axios.CancelToken(function executor(c) {
1124
+ abort = c;
1125
+ fullFile.abort = c;
1126
+ }),
1127
+ onUploadProgress: (progressEvent) => {
1128
+ let start = chunkParam.start;
1129
+ let uploadedSize =
1130
+ start +
1131
+ Math.floor(
1132
+ (chunkParam.currentSize * progressEvent.loaded) /
1133
+ progressEvent.total
1134
+ );
1135
+ let percent = Math.floor((uploadedSize * 100) / fullFile.size);
1136
+ if (percent === 100) {
1137
+ percent = 99;
1138
+ }
1139
+ that.loadingPercent = percent;
1140
+
1141
+ // that.$set(that, 'loadingTitle', this.getUploadText(percent))
1142
+ that.changeUploadPercent(percent);
1143
+ },
1144
+ // failMsg: false,
1145
+ modal: false,
1146
+ callback: (res1) => {
1147
+ if (res1.type === "success") {
1148
+ let uuid = res1.objx.uuid;
1149
+ chunkParam.uuid = uuid;
1150
+ if (preFormData.chunk + 1 >= preFormData.chunks) {
1151
+ let mergeData = {
1152
+ name: chunkParam.name,
1153
+ md5: chunkParam.md5,
1154
+ uuid: uuid,
1155
+ };
1156
+ let _param = {
1157
+ mergeData: mergeData,
1158
+ chunkParam: chunkParam,
1159
+ };
1160
+ setTimeout(() => {
1161
+ this.mergeFile(_param);
1162
+ }, 100);
1163
+ } else {
1164
+ chunkParam.chunkIndex = chunkParam.chunkIndex + 1;
1165
+ chunkParam.uuid = uuid;
1166
+ setTimeout(() => {
1167
+ this.sendRequest(fullFile);
1168
+ }, 100);
1169
+ }
1170
+ } else {
1171
+ this.dialogClose2(0);
1172
+ }
1173
+ return res1;
1174
+ },
1175
+ error: (err) => {
1176
+ console.log(err);
1177
+ this.dialogClose2(0);
1178
+ },
1179
+ }; //添加请求头
1180
+
1181
+ let chunkIndex = chunkParam.chunkIndex;
1182
+ let chunkSize = chunkParam.chunkSize;
1183
+ let start = chunkIndex * chunkSize,
1184
+ end =
1185
+ start + chunkSize >= fullFile.size
1186
+ ? fullFile.size
1187
+ : start + chunkParam.chunkSize;
1188
+ chunkParam.currentSize = end - start;
1189
+ chunkParam.start = start;
1190
+ chunkParam.end = end;
1191
+
1192
+ let preFormData = {
1193
+ file: fullFile.slice(start, end),
1194
+ name: fullFile.name,
1195
+ chunks: chunkParam.chunks,
1196
+ chunk: chunkIndex,
1197
+ md5: chunkParam.md5,
1198
+ uuid: chunkParam.uuid,
1199
+ };
1200
+
1201
+ let formData = new FormData();
1202
+ Object.keys(preFormData).forEach((key) => {
1203
+ formData.append(key, preFormData[key]);
1204
+ });
1205
+
1206
+ let req = this.$http.post(uploadUrl, formData, config);
1207
+ req.abort = () => {
1208
+ abort(this.$t2("取消上传", "components.VabUpload.cancelUpload"));
1209
+ };
1210
+ },
1211
+ mergeFile(param) {
1212
+ if (!this.showImportDialog2) return;
1213
+ let that = this;
1214
+ let mergeData = param.mergeData;
1215
+ let chunkParam = param.chunkParam;
1216
+ let fullFile = chunkParam.fullFile;
1217
+ let mergeUrl = USER_PREFIX + "/excel_import/mergeChunk";
1218
+ let target = this.$refs.upload;
1219
+ this.$http({
1220
+ url: mergeUrl,
1221
+ method: "post",
1222
+ data: mergeData,
1223
+ // failMsg: false,
1224
+ modal: false,
1225
+ cancelToken: new axios.CancelToken(function executor(c) {
1226
+ if (fullFile) fullFile.abort = c;
1227
+ }),
1228
+ callback: (res) => {
1229
+ if (res.type === "success") {
1230
+ that.loadingPercent = 100;
1231
+ // that.loadingTitle = this.getUploadText(100);
1232
+ this.changeUploadPercent(100);
1233
+ setTimeout(() => {
1234
+ this.checkImportData();
1235
+ }, 100);
1236
+ } else {
1237
+ this.dialogClose2(0);
1238
+ }
1239
+ },
1240
+ error: (e) => {
1241
+ console.log(err);
1242
+ this.dialogClose2(0);
1243
+ },
1244
+ });
1245
+ },
1246
+ getCheckText(percent) {
1247
+ return this.$t1("校验导入文件中的图片数据格式 {percent}%", { percent });
1248
+ },
1249
+ changeCheckTextPercent(percent) {
1250
+ this.percent2 = percent;
1251
+ this.loadingIndex = 2;
1252
+ },
1253
+ checkImportData() {
1254
+ if (!this.showImportDialog2) return;
1255
+ let that = this;
1256
+ that.loadingPercent = 0;
1257
+ // that.loadingTitle = this.getCheckText(0);
1258
+ that.changeCheckTextPercent(0);
1259
+ let fullFile = this.fileRaw;
1260
+ let chunkParam = fullFile.chunkParam;
1261
+
1262
+ this.$http({
1263
+ url: USER_PREFIX + "/excel_import/checkData",
1264
+ method: "post",
1265
+ data: {
1266
+ name: chunkParam.name,
1267
+ md5: chunkParam.md5,
1268
+ uuid: chunkParam.uuid,
1269
+ },
1270
+ // failMsg: false,
1271
+ modal: false,
1272
+ cancelToken: new axios.CancelToken(function executor(c) {
1273
+ if (fullFile) fullFile.abort = c;
1274
+ }),
1275
+ onUploadProgress: (progressEvent) => {
1276
+ let percent = Math.floor(
1277
+ (progressEvent.loaded * 100) / progressEvent.total
1278
+ );
1279
+ if (percent === 100) {
1280
+ percent = 99;
1281
+ }
1282
+ that.loadingPercent = percent;
1283
+ // that.$set(that, 'loadingTitle', this.getCheckText(percent))
1284
+ that.changeCheckTextPercent(percent);
1285
+ },
1286
+ callback: (res) => {
1287
+ if (res.type === "success") {
1288
+ that.loadingPercent = 100;
1289
+ // that.loadingTitle = this.getCheckText(100);
1290
+ that.changeCheckTextPercent(100);
1291
+ this.handleImageData();
1292
+ } else {
1293
+ this.dialogClose2(0);
1294
+ }
1295
+ },
1296
+ error: (e) => {
1297
+ console.log(err);
1298
+ this.dialogClose2(0);
1299
+ },
1300
+ });
1301
+ },
1302
+ getSaveImageText(percent) {
1303
+ return this.$t1("存储导入文件中的图片 {percent}%", { percent });
1304
+ },
1305
+ changeSaveImageTextPercent(percent) {
1306
+ // return this.$t1('存储导入文件中的图片 {percent}%', {percent})
1307
+ this.percent3 = percent;
1308
+ this.loadingIndex = 3;
1309
+ },
1310
+ handleImageData() {
1311
+ let that = this;
1312
+ that.loadingPercent = 0;
1313
+ // that.loadingTitle = this.getSaveImageText(0);
1314
+ that.changeSaveImageTextPercent(0);
1315
+ this.getImportData(0);
1316
+ },
1317
+ getImportData(index) {
1318
+ if (!this.showImportDialog2) return;
1319
+ let that = this;
1320
+ let rowSize = this.handleRowSize;
1321
+ let fullFile = this.fileRaw;
1322
+ let chunkParam = fullFile.chunkParam;
1323
+ let rowDatas = this.resultData.data;
1324
+ let size = rowDatas.length;
1325
+ let currentLineNo = index + 1;
1326
+ let rowNumber = index + 3;
1327
+ let startRow = index + 3;
1328
+ let endRow = index + 3 + rowSize - 1;
1329
+ this.$http({
1330
+ url: USER_PREFIX + "/excel_import/getData",
1331
+ method: "post",
1332
+ data: {
1333
+ name: chunkParam.name,
1334
+ md5: chunkParam.md5,
1335
+ uuid: chunkParam.uuid,
1336
+ startRow: startRow,
1337
+ endRow: endRow,
1338
+ },
1339
+ // failMsg: false,
1340
+ modal: false,
1341
+ cancelToken: new axios.CancelToken(function executor(c) {
1342
+ if (fullFile) fullFile.abort = c;
1343
+ }),
1344
+ callback: (res) => {
1345
+ if (res.type === "success") {
1346
+ let rows = res?.objx?.datas || [];
1347
+ let fileCellFields = this.fileCellFields;
1348
+ rows.forEach((row) => {
1349
+ let rowIndex = row.row - 3;
1350
+ let item = rowDatas[rowIndex];
1351
+ Object.keys(row).forEach((key) => {
1352
+ if (fileCellFields.includes(key)) {
1353
+ let value = row[key] || [];
1354
+ if (!Array.isArray(value)) {
1355
+ value = [value];
1356
+ }
1357
+ item[key] = value;
1358
+ }
1359
+ });
1360
+ });
1361
+ let cIndex = index + rowSize - 1;
1362
+ let percent = Math.floor(((cIndex + 1) * 100) / size);
1363
+ that.loadingPercent = percent;
1364
+ // that.loadingTitle = this.getSaveImageText(percent);
1365
+ that.changeSaveImageTextPercent(percent);
1366
+ if (cIndex + 1 < size) {
1367
+ this.getImportData(cIndex + 1);
1368
+ } else {
1369
+ this.fileUploadCallback();
1370
+ }
1371
+ } else {
1372
+ this.dialogClose2(0);
1373
+ }
1374
+ },
1375
+ error: (e) => {
1376
+ this.dialogClose2(0);
1377
+ },
1378
+ });
1379
+ },
1380
+ async generateNewExcel() {
1381
+ let file = this.fileRaw;
1382
+ try {
1383
+ // 1. 读取原始文件
1384
+ const workbook = XLSX.read(file, { type: "binary" });
1385
+ const sheetName = workbook.SheetNames[0];
1386
+ const rawData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
1387
+
1388
+ // 2. 提取表头和数据
1389
+ const headers = rawData.slice(0, this.headerRows);
1390
+ const bodyData = rawData.slice(this.headerRows);
1391
+
1392
+ let exporLineNos = [];
1393
+ if (this.resultType) {
1394
+ exporLineNos = this.successRows.map((item) => item.impNumber - 1);
1395
+ } else {
1396
+ exporLineNos = this.failRows.map((item) => item.impNumber - 1);
1397
+ }
1398
+ // 3. 应用筛选规则
1399
+ let selectRule = (row, index) => {
1400
+ return exporLineNos.includes(index);
1401
+ };
1402
+ const filteredData = bodyData.filter(
1403
+ (row, index) => {
1404
+ return selectRule(row, index + this.headerRows);
1405
+ }
1406
+ // this.selectRule(row, index + this.headerRows) // 注意索引转换
1407
+ );
1408
+
1409
+ // 4. 合并数据
1410
+ const newData = [...headers, ...filteredData];
1411
+
1412
+ // 5. 生成新文件
1413
+ const newWorkbook = XLSX.utils.book_new();
1414
+ const newSheet = XLSX.utils.aoa_to_sheet(newData);
1415
+ XLSX.utils.book_append_sheet(newWorkbook, newSheet, "Sheet1");
1416
+
1417
+ // 6. 下载文件
1418
+ const blob = XLSX.write(newWorkbook, {
1419
+ bookType: "xlsx",
1420
+ type: "array",
1421
+ });
1422
+
1423
+ const url = URL.createObjectURL(blob);
1424
+ const a = document.createElement("a");
1425
+ a.href = url;
1426
+ let fileName = null;
1427
+ if (this.resultType) {
1428
+ fileName = `导入结果(成功).xlsx`;
1429
+ } else {
1430
+ fileName = `导入结果(失败).xlsx`;
1431
+ }
1432
+ a.download = fileName;
1433
+ a.click();
1434
+
1435
+ // 7. 更新进度
1436
+ this.progress = 100;
1437
+ setTimeout(() => (this.progress = 0), 1000);
1438
+ } catch (error) {
1439
+ console.error("处理文件时出错:", error);
1440
+ }
1441
+ },
1442
+ //end
1443
+ getLoadingClass(flag, percent) {
1444
+ let classStr = null;
1445
+ let loadingIndex = this.loadingIndex;
1446
+ if (percent >= 100) {
1447
+ classStr = "ok";
1448
+ } else if (flag === loadingIndex) {
1449
+ classStr = "loading";
1450
+ }
1451
+ return classStr;
1452
+ },
1453
+
1454
+ /***sheet1 */
1455
+ async readExcel2(file, callback) {
1456
+ let that = this;
1457
+ let option = this.option;
1458
+
1459
+ const fileReader = new FileReader();
1460
+ fileReader.onload = async (ev) => {
1461
+ let resultData;
1462
+ try {
1463
+ const data = ev.target.result;
1464
+ const workbook = configUtil.XLSX.read(data, {
1465
+ type: "binary",
1466
+ });
1467
+
1468
+ let sheetDatas = [];
1469
+ for (let pi = 0; pi < workbook.SheetNames.length; pi++) {
1470
+ let sheetName = workbook.SheetNames[pi];
1471
+ let sheet = workbook.Sheets[sheetName];
1472
+
1473
+ if (sheet["!ref"] === undefined || sheet["!ref"] === null) {
1474
+ that.$baseAlert(
1475
+ this.$t2(
1476
+ "请使用正确的导入模版!",
1477
+ "components.excelImport.warmMsg2"
1478
+ )
1479
+ );
1480
+ that.handleClose2();
1481
+ return false;
1482
+ }
1483
+ let range = configUtil.XLSX.utils.decode_range(sheet["!ref"]);
1484
+ let dataSize = range.e.r + 1; //行数
1485
+ that.dataSize = dataSize - 3 >= 0 ? dataSize - 3 : 0;
1486
+ let titles = [];
1487
+ let fields = [];
1488
+
1489
+ const ws = workbook.Sheets[sheet];
1490
+
1491
+ let prefix = option.prefix;
1492
+ let excelUrl = option.excel;
1493
+
1494
+ let excelRows = [];
1495
+ let row;
1496
+ let rowNum;
1497
+ let colNum;
1498
+ for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
1499
+ row = [];
1500
+ for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
1501
+ let nextCell =
1502
+ sheet[
1503
+ configUtil.XLSX.utils.encode_cell({
1504
+ r: rowNum,
1505
+ c: colNum,
1506
+ })
1507
+ ];
1508
+ if (typeof nextCell === "undefined") {
1509
+ row.push(void 0);
1510
+ } else {
1511
+ row.push(nextCell.w.trim());
1512
+ }
1513
+ }
1514
+ if (rowNum === 1) {
1515
+ titles = row;
1516
+ }
1517
+ if (rowNum === 2) {
1518
+ fields = row;
1519
+ let checkResult = true;
1520
+ }
1521
+ if (rowNum > 2) {
1522
+ let item = {};
1523
+ for (let i = 0; i < fields.length; i++) {
1524
+ let field = fields[i];
1525
+ if (field) {
1526
+ item[field] = row[i] ?? null;
1527
+ }
1528
+ }
1529
+ excelRows.push(item);
1530
+ }
1531
+ }
1532
+ if (
1533
+ !titles.length ||
1534
+ !fields.length ||
1535
+ titles.length !== fields.length
1536
+ ) {
1537
+ that.$baseAlert(
1538
+ this.$t2(
1539
+ "请使用正确的导入模版!",
1540
+ "components.excelImport.warmMsg2"
1541
+ )
1542
+ );
1543
+ // that.handleClose2();
1544
+ return false;
1545
+ }
1546
+
1547
+ let columns = [];
1548
+ let cols = [];
1549
+ let uniqueFields = [];
1550
+ let uniqueKeys = [];
1551
+ for (let i = 0; i < titles.length; i++) {
1552
+ let title = titles[i];
1553
+ if (title) {
1554
+ let field = fields[i];
1555
+ if (field === null || field === undefined) {
1556
+ that.$baseAlert(
1557
+ this.$t2(
1558
+ "请使用正确的导入模版!",
1559
+ "components.excelImport.warmMsg2"
1560
+ )
1561
+ );
1562
+ // that.handleClose2();
1563
+ return false;
1564
+ }
1565
+ let t = title.substr(-1);
1566
+ let u = title.length >= 2 ? title.substr(-2) : title;
1567
+ let p = title.length >= 3 ? title.substr(-3) : title;
1568
+ let isNeed = false;
1569
+ if (t === "*") {
1570
+ isNeed = true;
1571
+ }
1572
+ let isUnique = false;
1573
+ /* if (u === "**") {
1574
+ uniqueFields.push(field);
1575
+ isUnique = true;
1576
+ } */
1577
+ let isSheetUnique = false;
1578
+ if (p === "***") {
1579
+ uniqueKeys.push(field);
1580
+ isSheetUnique = true;
1581
+ }
1582
+ if (!uniqueKeys.length) {
1583
+ // that.clearImportTimer();
1584
+ that.$baseAlert(
1585
+ `[${sheetName}]` + that.$t1("缺失单据唯一标识***")
1586
+ );
1587
+ // that.handleClose2();
1588
+ return false;
1589
+ }
1590
+
1591
+ let otherConfig = {};
1592
+ let isFile = false;
1593
+ if (field.startsWith("attachments_")) {
1594
+ that.fileCellFields.push(field);
1595
+ isFile = true;
1596
+ otherConfig = {
1597
+ slots: {
1598
+ default: "attachment",
1599
+ },
1600
+ };
1601
+ }
1602
+
1603
+ let col = {
1604
+ field: field,
1605
+ title: title,
1606
+ width: 100,
1607
+ isNeed: isNeed,
1608
+ isUnique: isUnique,
1609
+ isFile,
1610
+ otherConfig,
1611
+ isSheetUnique,
1612
+ };
1613
+ cols.push(col);
1614
+ }
1615
+ }
1616
+
1617
+ let oriCols = JSON.parse(JSON.stringify(cols)); //列信息
1618
+ /* if (uniqueKeys.length) {
1619
+ //分组唯一字段为空时,全部不发包。
1620
+ for (let i = 0; i < oriCols.length; i++) {
1621
+ let oriCol = oriCols[i];
1622
+ if (uniqueKeys.includes(oriCol.field)) {
1623
+ for (let j = 0; j < excelRows.length; j++) {
1624
+ let data = excelRows[j];
1625
+ let value = data[oriCol.field];
1626
+ if (value === null || value === undefined || value === "") {
1627
+ that.errorHandle(`[${sheetName}]`+
1628
+ that.$t2(
1629
+ "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
1630
+ "components.excelImport.warmMsg3",
1631
+ {
1632
+ lineNo: j + 4,
1633
+ title: oriCol.title,
1634
+ }
1635
+ ));
1636
+ return false;
1637
+ }
1638
+ }
1639
+ }
1640
+ }
1641
+ } */
1642
+ // this.oriCols = oriCols;
1643
+
1644
+ let resultData1 = {
1645
+ sheetName: sheetName,
1646
+ data: excelRows,
1647
+ titles: titles,
1648
+ fields: fields,
1649
+ uniqueFields: uniqueFields,
1650
+ oriCols: oriCols,
1651
+ uniqueKeys,
1652
+ };
1653
+ sheetDatas.push(resultData1);
1654
+ }
1655
+
1656
+ //校验必填
1657
+ if (!that.checkAllSheetData(sheetDatas)) {
1658
+ return false;
1659
+ }
1660
+
1661
+ //合并多sheet数据
1662
+ let newDatas = [];
1663
+ resultData = that.$baseLodash.cloneDeep(sheetDatas[0]);
1664
+ let uniqueKey = resultData.uniqueKeys[0];
1665
+ let data2 = [];
1666
+ for (let i = 0; i < resultData.data.length; i++) {
1667
+ let item = resultData.data[i];
1668
+ let sheetName = resultData[sheetName];
1669
+ let uniqueValue = item[uniqueKey];
1670
+
1671
+ if (!that.isNull(uniqueValue)) {
1672
+ let newItem = { ...item };
1673
+ let allItems = [];
1674
+ for (let j = 1; j < sheetDatas.length; j++) {
1675
+ let sheetData = sheetDatas[j];
1676
+ let fDatas = [];
1677
+ for (let k = 0; k < sheetData.data.length; k++) {
1678
+ let sheetItem = sheetData.data[k];
1679
+ if (that.isNull(sheetItem[uniqueKey])) {
1680
+ that.handleCellNotNull(k, sheetData);
1681
+ return;
1682
+ }
1683
+ if (sheetItem[uniqueKey] === uniqueValue) {
1684
+ fDatas.push(sheetItem);
1685
+ }
1686
+ }
1687
+ allItems.push(fDatas);
1688
+ }
1689
+ newItem.sheetItems = allItems;
1690
+ data2.push(newItem);
1691
+ } else {
1692
+ that.handleCellNotNull(i, resultData);
1693
+ return false;
1694
+ }
1695
+ }
1696
+
1697
+ resultData.sheetDatas = sheetDatas;
1698
+ resultData.data = data2;
1699
+ this.oriCols = resultData.oriCols;
1700
+ this.resultData = resultData;
1701
+ callback(resultData);
1702
+ } catch (et) {
1703
+ that.showContent = false;
1704
+ that.clearImportTimer();
1705
+ console.error(et);
1706
+ }
1707
+ };
1708
+ fileReader.readAsBinaryString(file);
1709
+ },
1710
+ isNull(val) {
1711
+ if (val === null || val === undefined || val === "" || val === undefined || val === null) {
1712
+ return true;
1713
+ }
1714
+ },
1715
+ checkAllSheetData(sheetItems){
1716
+ let that = this;
1717
+ for(let sheetItem of sheetItems){
1718
+ let oriCols = sheetItem.oriCols;
1719
+ let uniqueKeys = sheetItem.uniqueKeys;
1720
+ let excelRows = sheetItem.data;
1721
+ let sheetName = sheetItem.sheetName;
1722
+
1723
+ for (let i = 0; i < oriCols.length; i++) {
1724
+ let oriCol = oriCols[i];
1725
+ if (oriCol.isNeed || uniqueKeys.includes(oriCol.field)) {
1726
+ for (let j = 0; j < excelRows.length; j++) {
1727
+ let data = excelRows[j];
1728
+ let value = data[oriCol.field];
1729
+ if (that.isNull(value)) {
1730
+ that.errorHandle(`[${sheetName}]`+
1731
+ that.$t2(
1732
+ "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
1733
+ "components.excelImport.warmMsg3",
1734
+ {
1735
+ lineNo: j + 4,
1736
+ title: oriCol.title,
1737
+ }
1738
+ ));
1739
+ return false;
1740
+ }
1741
+ }
1742
+ }
1743
+ }
1744
+
1745
+ }
1746
+ return true;
1747
+ },
1748
+
1749
+
1750
+ handleCellNotNull(i, sheetData) {
1751
+ let that = this;
1752
+ let uniqueKey = sheetData.uniqueKeys[0];
1753
+ let oriCol = sheetData.oriCols.find((item) => item.field === uniqueKey);
1754
+ that.errorHandle(
1755
+ `[${sheetData.sheetName}]` +
1756
+ that.$t2(
1757
+ "第" + (i + 4) + "行[" + oriCol.title + "]不能为空;",
1758
+ "components.excelImport.warmMsg3",
1759
+ {
1760
+ lineNo: i + 4,
1761
+ title: oriCol.title,
1762
+ }
1763
+ )
1764
+ );
1765
+ },
1766
+ errorHandle(errorText) {
1767
+ this.clearImportTimer();
1768
+ this.$baseAlert(errorText);
1769
+ // this.handleClose2();
1770
+ },
1771
+ /***sheet2 */
1772
+ },
1773
+ };
1774
+ export const mixins = tmixins;