cloud-web-corejs 1.0.54-dev.57 → 1.0.54-dev.58

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.
@@ -66,7 +66,7 @@
66
66
  v-el-drag-dialog
67
67
  >
68
68
  <div>
69
- <div class="import-box">
69
+ <div class="import-box" v-loading="importLoading" :element-loading-text="loadingTitle" style="margin-bottom: 30px;">
70
70
  <div class="tips">
71
71
  {{ $t2('导入中,请勿关闭当前窗口', 'components.excelImport.tip2') }}
72
72
  <!-- <span class="fr">耗时:<em class="time-txt">0 时 0 分 0 秒 </em></span> -->
@@ -130,12 +130,20 @@
130
130
  <div class="clearfix screen-btns">
131
131
  <div class="fl">
132
132
  <vxe-button status="primary" class="button-sty" icon="el-icon-upload2" @click="exportToExcel()">
133
- 导出
133
+ {{ $t1('导出') }}
134
134
  </vxe-button>
135
135
  </div>
136
136
  <div class="fr"></div>
137
137
  </div>
138
138
  </template>
139
+ <template #attachment="{row,column}">
140
+ <base-attachment :option="{
141
+ title: column.title,
142
+ rows: row[column.field],
143
+ showViewButton: true,
144
+ edit:false
145
+ }" />
146
+ </template>
139
147
  </vxe-grid>
140
148
  </div>
141
149
  </div>
@@ -1,5 +1,7 @@
1
1
  /**version-1.0*/
2
2
  import {read, utils} from 'xlsx'
3
+ import axios from 'axios';
4
+ import SparkMD5 from "spark-md5";
3
5
 
4
6
  let tmixins = {};
5
7
  var XLSX = window.XLSX || {read, utils};
@@ -42,7 +44,13 @@ tmixins = {
42
44
  option: {},
43
45
  showContent: false,
44
46
  resOption: {},
45
- fileCellFields: []
47
+ fileCellFields: [],
48
+ importLoading: false,
49
+ loadingTitle: null,
50
+ loadingPercent: 0,
51
+ handleRowSize: 1,
52
+
53
+ headerRows: 3
46
54
  }
47
55
  },
48
56
  created() {
@@ -89,7 +97,8 @@ tmixins = {
89
97
  let col = {
90
98
  field: oriCol.field,
91
99
  title: oriCol.title,
92
- width: 150
100
+ width: 150,
101
+ ...oriCol.otherConfig
93
102
  };
94
103
  if (index == 0) {
95
104
  col.fixed = 'left';
@@ -156,6 +165,7 @@ tmixins = {
156
165
  }
157
166
  },
158
167
  dialogClose1() {
168
+ this.importLoading = false;
159
169
  if (!this.showImportDialog2) {
160
170
  this.$emit("update:visiable", false);
161
171
  this.showContent = false;
@@ -229,6 +239,14 @@ tmixins = {
229
239
  return
230
240
  }
231
241
 
242
+ this.uploadFile(() => {
243
+ this.importLoading = false;
244
+ this.handleBeforeImport(file, resultData, () => {
245
+ callback && callback()
246
+ })
247
+ })
248
+ return
249
+
232
250
  let reportTemplate = this.getReportTemplate();
233
251
  let formCode = reportTemplate?.formCode;
234
252
  let scriptCode = importOption.importScriptCode || "import"
@@ -408,10 +426,16 @@ tmixins = {
408
426
  isUnique = true;
409
427
  }
410
428
 
429
+ let otherConfig = {};
411
430
  let isFile = false;
412
431
  if (field.startsWith('attachments_')) {
413
432
  that.fileCellFields.push(field)
414
433
  isFile = true
434
+ otherConfig = {
435
+ slots: {
436
+ default: 'attachment'
437
+ }
438
+ }
415
439
  }
416
440
 
417
441
  let col = {
@@ -420,7 +444,8 @@ tmixins = {
420
444
  width: 100,
421
445
  isNeed: isNeed,
422
446
  isUnique: isUnique,
423
- isFile
447
+ isFile,
448
+ otherConfig
424
449
  };
425
450
  cols.push(col);
426
451
  }
@@ -502,7 +527,7 @@ tmixins = {
502
527
  // let reqData = this.getReqFormData();
503
528
  let fileCellFields = this.fileCellFields;
504
529
  let formData = {
505
- [entity]: data
530
+ [entity]: {...data}
506
531
  }
507
532
  if (fileCellFields.length) {
508
533
  fileCellFields.forEach(field => {
@@ -528,7 +553,7 @@ tmixins = {
528
553
  syncDataForImport(opts) {
529
554
  let that = this;
530
555
  var multi = this.option.multi;
531
- var resultData = opts.data;
556
+ var resultData = this.resultData;
532
557
  var datas = resultData.data;
533
558
  var titles = resultData.titles;
534
559
  var fields = resultData.fields;
@@ -659,7 +684,7 @@ tmixins = {
659
684
  }
660
685
 
661
686
  } else {
662
- var data = datas[index];
687
+ var data = that.resultData.data[index];
663
688
  data.impSeq = index;
664
689
  data.impNumber = index + 4;
665
690
  excNum = 1;
@@ -719,7 +744,7 @@ tmixins = {
719
744
  return;
720
745
  }
721
746
  } else {
722
- var data = datas[index];
747
+ var data = that.resultData.data[index];
723
748
  data._resultType = resultMsg.type;
724
749
  data._resultContent = (resultMsg.type == "success") ? this.$t2('导入成功', 'components.excelImport.importSucess') : resultMsg.content;
725
750
 
@@ -906,7 +931,358 @@ tmixins = {
906
931
  loadingObj && loadingObj.close();
907
932
  }, 200);
908
933
  });
934
+ },
935
+
936
+ //begin
937
+ fileParse(file, type = "base64", callback) {
938
+ let fileRead = new FileReader();
939
+ if (type === "base64") {
940
+ fileRead.readAsDataURL(file);
941
+ } else if (type === "buffer") {
942
+ fileRead.readAsArrayBuffer(file);
943
+ }
944
+ fileRead.onload = (ev) => {
945
+ callback(ev.target.result)
946
+ };
947
+ },
948
+ uploadFile(callback) {
949
+ let that = this;
950
+ that.loadingPercent = 0;
951
+ that.loadingTitle = `上传导入文件 0%`;
952
+ let file = this.fileRaw;
953
+ let uploadChunkSize = 5;
954
+ this.importLoading = true;
955
+ this.fileUploadCallback = callback;
956
+ this.fileParse(file, "buffer", (buffer) => {
957
+ let spark = new SparkMD5.ArrayBuffer(),
958
+ chunkSize = uploadChunkSize * 1024 * 1024, // Read in chunks of 2MB
959
+ chunks = Math.ceil(file.size / chunkSize),
960
+ hash,
961
+ suffix;
962
+ spark.append(buffer);
963
+ hash = spark.end();
964
+ let md5 = hash;
965
+ let nameSplit = /\.([0-9a-zA-Z]+)$/i.exec(file.name);
966
+
967
+ suffix = (nameSplit && nameSplit.length > 1) ? nameSplit[1] : '';
968
+
969
+ let chunkParam = {
970
+ fullFile: file,
971
+ chunkSize: chunkSize,
972
+ chunks: chunks,
973
+ chunkIndex: 0,
974
+ md5: hash,
975
+ uuid: '',
976
+ name: file.name
977
+ };
978
+ file.chunkParam = chunkParam;
979
+
980
+ this.sendRequest(file);
981
+ });
982
+ },
983
+ async sendRequest(fullFile) {
984
+ let that = this;
985
+ let uploadUrl = USER_PREFIX + '/excel_import/uploadFile';
986
+ let chunkParam = fullFile.chunkParam;
987
+ let target = that.$refs.upload;
988
+ let abort;
989
+ let config = {
990
+ headers: {
991
+ 'Content-Type': 'multipart/form-data'
992
+ },
993
+ cancelToken: new axios.CancelToken(function executor(c) {
994
+ abort = c;
995
+ fullFile.abort = c;
996
+ }),
997
+ onUploadProgress: progressEvent => {
998
+ let start = chunkParam.start;
999
+ let uploadedSize = start + Math.floor(chunkParam.currentSize *
1000
+ progressEvent
1001
+ .loaded / progressEvent.total);
1002
+ let percent = Math.floor((uploadedSize * 100) / fullFile.size);
1003
+ if (percent == 100) {
1004
+ percent = 99;
1005
+ }
1006
+ that.loadingPercent = percent;
1007
+ // that.loadingTitle = `上传导入文件 ${percent}%`;
1008
+ that.$set(that, 'loadingTitle', `上传导入文件 ${percent}%`)
1009
+ },
1010
+ // failMsg: false,
1011
+ modal: false,
1012
+ callback: res1 => {
1013
+ if (res1.type == "success") {
1014
+ let uuid = res1.objx.uuid;
1015
+ chunkParam.uuid = uuid;
1016
+ if (preFormData.chunk + 1 >= preFormData.chunks) {
1017
+ let mergeData = {
1018
+ name: chunkParam.name,
1019
+ md5: chunkParam.md5,
1020
+ uuid: uuid,
1021
+ };
1022
+ let _param = {
1023
+ mergeData: mergeData,
1024
+ chunkParam: chunkParam
1025
+ };
1026
+ setTimeout(() => {
1027
+ this.mergeFile(_param);
1028
+ }, 100)
1029
+
1030
+
1031
+ } else {
1032
+ chunkParam.chunkIndex = chunkParam.chunkIndex + 1;
1033
+ chunkParam.uuid = uuid;
1034
+ setTimeout(() => {
1035
+ this.sendRequest(fullFile);
1036
+ }, 100)
1037
+ }
1038
+ } else {
1039
+ this.dialogClose1();
1040
+ }
1041
+ return res1;
1042
+ },
1043
+ error: (err) => {
1044
+ console.log(err);
1045
+ this.dialogClose1();
1046
+ }
1047
+ }; //添加请求头
1048
+
1049
+ let chunkIndex = chunkParam.chunkIndex;
1050
+ let chunkSize = chunkParam.chunkSize;
1051
+ var start = chunkIndex * chunkSize,
1052
+ end = start + chunkSize >= fullFile.size ? fullFile.size : start + chunkParam.chunkSize;
1053
+ chunkParam.currentSize = end - start;
1054
+ chunkParam.start = start;
1055
+ chunkParam.end = end;
1056
+
1057
+ let preFormData = {
1058
+ file: fullFile.slice(start, end),
1059
+ name: fullFile.name,
1060
+ chunks: chunkParam.chunks,
1061
+ chunk: chunkIndex,
1062
+ md5: chunkParam.md5,
1063
+ uuid: chunkParam.uuid
1064
+ };
1065
+
1066
+ let formData = new FormData();
1067
+ Object.keys(preFormData).forEach(key => {
1068
+ formData.append(key, preFormData[key]);
1069
+ });
1070
+
1071
+ let req = this.$http.post(uploadUrl, formData, config);
1072
+ req.abort = () => {
1073
+ abort(this.$t2('取消上传', 'components.VabUpload.cancelUpload'));
1074
+ }
1075
+ },
1076
+ mergeFile(param) {
1077
+ let that = this;
1078
+ let mergeData = param.mergeData;
1079
+ let chunkParam = param.chunkParam;
1080
+ let fullFile = chunkParam.fullFile;
1081
+ let mergeUrl = USER_PREFIX + '/excel_import/mergeChunk';
1082
+ let target = this.$refs.upload;
1083
+ this.$http({
1084
+ url: mergeUrl,
1085
+ method: 'post',
1086
+ data: mergeData,
1087
+ failMsg: false,
1088
+ modal: false,
1089
+ cancelToken: new axios.CancelToken(function executor(c) {
1090
+ if (fullFile) fullFile.abort = c;
1091
+ }),
1092
+ callback: res => {
1093
+ if (res.type == "success") {
1094
+ that.loadingPercent = 100;
1095
+ that.loadingTitle = `上传导入文件 100%`;
1096
+ setTimeout(() => {
1097
+ this.checkImportData()
1098
+ }, 100)
1099
+ } else {
1100
+ this.dialogClose1();
1101
+ }
1102
+ },
1103
+ error: e => {
1104
+ console.log(err);
1105
+ this.dialogClose1();
1106
+ }
1107
+ });
1108
+ },
1109
+ checkImportData() {
1110
+ let that = this;
1111
+ that.loadingPercent = 0;
1112
+ that.loadingTitle = `校验导入文件中的图片数据格式 0%`;
1113
+ let fullFile = this.fileRaw;
1114
+ let chunkParam = fullFile.chunkParam;
1115
+
1116
+ this.$http({
1117
+ url: USER_PREFIX + '/excel_import/checkData',
1118
+ method: 'post',
1119
+ data: {
1120
+ name: chunkParam.name,
1121
+ md5: chunkParam.md5,
1122
+ uuid: chunkParam.uuid
1123
+ },
1124
+ failMsg: false,
1125
+ modal: false,
1126
+ cancelToken: new axios.CancelToken(function executor(c) {
1127
+ if (fullFile) fullFile.abort = c;
1128
+ }),
1129
+ onUploadProgress: progressEvent => {
1130
+ let percent = Math.floor((progressEvent
1131
+ .loaded * 100) / progressEvent.total);
1132
+ if (percent == 100) {
1133
+ percent = 99;
1134
+ }
1135
+ that.loadingPercent = percent;
1136
+ // that.loadingTitle = `校验导入文件中的图片数据格式 ${percent}%`;
1137
+ that.$set(that, 'loadingTitle', `校验导入文件中的图片数据格式 ${percent}%`)
1138
+ },
1139
+ callback: res => {
1140
+ if (res.type == "success") {
1141
+ that.loadingPercent = 100;
1142
+ that.loadingTitle = `校验导入文件中的图片数据格式 100%`;
1143
+ this.handleImageData();
1144
+ } else {
1145
+ this.dialogClose1();
1146
+ }
1147
+ },
1148
+ error: e => {
1149
+ console.log(err);
1150
+ this.dialogClose1();
1151
+ }
1152
+ });
1153
+ },
1154
+ handleImageData() {
1155
+ let that = this;
1156
+ that.loadingPercent = 0;
1157
+ that.loadingTitle = `存储导入文件中的图片 0%`;
1158
+ this.getImportData(0)
1159
+ },
1160
+ getImportData(index) {
1161
+ let that = this;
1162
+ let rowSize = this.handleRowSize;
1163
+ let fullFile = this.fileRaw;
1164
+ let chunkParam = fullFile.chunkParam;
1165
+ let rowDatas = this.resultData.data;
1166
+ let size = rowDatas.length;
1167
+ let currentLineNo = index + 1;
1168
+ let rowNumber = index + 3;
1169
+ let startRow = index + 3;
1170
+ let endRow = index + 3 + rowSize - 1;
1171
+ this.$http({
1172
+ url: USER_PREFIX + '/excel_import/getData',
1173
+ method: 'post',
1174
+ data: {
1175
+ name: chunkParam.name,
1176
+ md5: chunkParam.md5,
1177
+ uuid: chunkParam.uuid,
1178
+ startRow: startRow,
1179
+ endRow: endRow,
1180
+ },
1181
+ failMsg: false,
1182
+ modal: false,
1183
+ cancelToken: new axios.CancelToken(function executor(c) {
1184
+ if (fullFile) fullFile.abort = c;
1185
+ }),
1186
+ callback: res => {
1187
+ if (res.type == "success") {
1188
+ let rows = res?.objx?.datas || []
1189
+ let fileCellFields = this.fileCellFields
1190
+ rows.forEach((row) => {
1191
+ let rowIndex = row.row - 3;
1192
+ let item = rowDatas[rowIndex]
1193
+ Object.keys(row).forEach(key => {
1194
+ if (fileCellFields.includes(key)) {
1195
+ let value = row[key] || []
1196
+ if (!Array.isArray(value)) {
1197
+ value = [value];
1198
+ }
1199
+ item[key] = value;
1200
+ }
1201
+ })
1202
+ })
1203
+ let cIndex = index + rowSize - 1;
1204
+ let percent = Math.floor(((cIndex + 1) * 100) / size);
1205
+ that.loadingPercent = percent;
1206
+ that.loadingTitle = `存储导入文件中的图片 ${percent}%`;
1207
+ if (cIndex + 1 < size) {
1208
+ this.getImportData(cIndex + 1)
1209
+ } else {
1210
+ this.fileUploadCallback();
1211
+ }
1212
+ } else {
1213
+ this.dialogClose1();
1214
+ }
1215
+ },
1216
+ error: e => {
1217
+ this.dialogClose1();
1218
+ }
1219
+ });
1220
+ },
1221
+ async generateNewExcel() {
1222
+
1223
+ let file = this.fileRaw
1224
+ try {
1225
+ // 1. 读取原始文件
1226
+ const workbook = XLSX.read(file, {type: 'binary'});
1227
+ const sheetName = workbook.SheetNames[0];
1228
+ const rawData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
1229
+
1230
+ // 2. 提取表头和数据
1231
+ const headers = rawData.slice(0, this.headerRows);
1232
+ const bodyData = rawData.slice(this.headerRows);
1233
+
1234
+ let exporLineNos = [];
1235
+ if (this.resultType) {
1236
+ exporLineNos = this.successRows.map(item => (item.impNumber - 1))
1237
+ } else {
1238
+ exporLineNos = this.failRows.map(item => (item.impNumber - 1))
1239
+ }
1240
+ // 3. 应用筛选规则
1241
+ let selectRule = (row, index) => {
1242
+ return exporLineNos.includes(index);
1243
+ }
1244
+ const filteredData = bodyData.filter((row, index) => {
1245
+ return selectRule(row, index + this.headerRows)
1246
+ }
1247
+ // this.selectRule(row, index + this.headerRows) // 注意索引转换
1248
+ );
1249
+
1250
+ // 4. 合并数据
1251
+ const newData = [...headers, ...filteredData];
1252
+
1253
+ // 5. 生成新文件
1254
+ const newWorkbook = XLSX.utils.book_new();
1255
+ const newSheet = XLSX.utils.aoa_to_sheet(newData);
1256
+ XLSX.utils.book_append_sheet(newWorkbook, newSheet, 'Sheet1');
1257
+
1258
+ // 6. 下载文件
1259
+ const blob = XLSX.write(newWorkbook, {
1260
+ bookType: 'xlsx',
1261
+ type: 'array'
1262
+ });
1263
+
1264
+ const url = URL.createObjectURL(blob);
1265
+ const a = document.createElement('a');
1266
+ a.href = url;
1267
+ let fileName = null;
1268
+ if (this.resultType) {
1269
+ fileName = `导入结果(成功).xlsx`;
1270
+ } else {
1271
+ fileName = `导入结果(失败).xlsx`;
1272
+ }
1273
+ a.download = fileName;
1274
+ a.click();
1275
+
1276
+ // 7. 更新进度
1277
+ this.progress = 100;
1278
+ setTimeout(() => this.progress = 0, 1000);
1279
+
1280
+ } catch (error) {
1281
+ console.error('处理文件时出错:', error);
1282
+ alert('文件处理失败!');
1283
+ }
909
1284
  }
1285
+ //end
910
1286
  }
911
1287
  };
912
1288
  export const mixins = tmixins;
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <el-form-item label="onAfterConfirmFile" label-width="150px">
3
+ <a href="javascript:void(0);" class="a-link link-oneLind" @click="editEventHandler('onAfterConfirmFile', eventParams)">
4
+ <span>{{ optionModel.onAfterConfirmFile }}</span>
5
+ <i class="el-icon-edit"></i>
6
+ </a>
7
+ </el-form-item>
8
+ </template>
9
+
10
+ <script>
11
+ import i18n from "../../../../../../components/xform/utils/i18n";
12
+ import eventMixin from "../../../../../../components/xform/form-designer/setting-panel/property-editor/event-handler/eventMixin";
13
+
14
+ export default {
15
+ name: "onAfterConfirmFile-editor",
16
+ mixins: [i18n, eventMixin],
17
+ props: {
18
+ designer: Object,
19
+ selectedWidget: Object,
20
+ optionModel: Object,
21
+ },
22
+ data() {
23
+ return {
24
+ eventParams: ["attachments", "fileInfos"],
25
+ };
26
+ },
27
+ };
28
+ </script>
29
+
30
+ <style scoped></style>
@@ -212,6 +212,7 @@ const EVENT_PROPERTIES = {
212
212
  'onAppendButtonClick': 'onAppendButtonClick-editor',
213
213
  'onSearchConfirm': 'onSearchConfirm-editor',
214
214
  'onSearchClear': 'onSearchClear-editor',
215
+ 'onAfterConfirmFile': 'onAfterConfirmFile-editor',
215
216
 
216
217
  //容器
217
218
  'onSubFormRowAdd': 'onSubFormRowAdd-editor',
@@ -2513,6 +2513,7 @@ export const advancedFields = [
2513
2513
  entityTableDesc: null,
2514
2514
  onCreated: "this.loadDataDefaultHandle();",
2515
2515
  onMounted: "",
2516
+ onAfterConfirmFile:"",
2516
2517
  vabUpload: 1,
2517
2518
  formScriptEnabled: true,
2518
2519
  formScriptCode: "getList",
@@ -2922,6 +2923,7 @@ export const advancedFields = [
2922
2923
  entityTableDesc: null,
2923
2924
  onCreated: "",
2924
2925
  onMounted: "",
2926
+ onAfterConfirmFile:"",
2925
2927
  wfFlag: 1,
2926
2928
  wfEdit: false,
2927
2929
  enabledByWf: false,