n20-common-lib 2.22.66 → 2.22.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "2.22.66",
3
+ "version": "2.22.69",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -57,26 +57,30 @@
57
57
  <slot slot="header" slot-scope="scope" name="type-header" :column="scope.column">{{ '附件类型' | $lc }}</slot>
58
58
  <slot slot-scope="{ row }" name="type" :row="row">
59
59
  <span v-if="readonly">{{ row[keys.type] | typeFiter(typeOptions) }}</span>
60
- <div v-else class="flex-box flex-v">
60
+ <div v-else class="flex-box flex-v file-upload-table__type-cell">
61
61
  <span v-if="requiredTypes.includes(row[keys.type])" style="color: red" class="m-r-s">*</span>
62
- <el-select
63
- v-model="row[keys.type]"
64
- :disabled="row._typeDisabled || row._typeUpdating"
65
- :placeholder="'请选择' | $lc"
66
- style="width: calc(100% - 16px)"
67
- @change="handleTypeChange(row)"
68
- >
69
- <el-option
70
- v-for="item in typeOptions"
71
- :key="item.type"
72
- :disabled="item.disabled"
73
- :value="item.type"
74
- :label="item.label"
75
- />
76
- </el-select>
62
+ <div class="file-upload-table__type-content">
63
+ <el-select
64
+ v-model="row[keys.type]"
65
+ :class="{ 'file-upload-table__type-error': row._typeError }"
66
+ :disabled="row._typeDisabled || row._typeUpdating"
67
+ :placeholder="'请选择' | $lc"
68
+ style="width: 100%"
69
+ @change="handleTypeChange(row)"
70
+ >
71
+ <el-option
72
+ v-for="item in typeOptions"
73
+ :key="item.type"
74
+ :disabled="item.disabled"
75
+ :value="item.type"
76
+ :label="item.label"
77
+ />
78
+ </el-select>
79
+ </div>
77
80
  </div>
78
81
  </slot>
79
82
  </el-table-column>
83
+ <slot name="type-after"></slot>
80
84
  <el-table-column :label="'附件名称' | $lc" :prop="keys.name" sortable="custom">
81
85
  <slot slot="header" slot-scope="scope" name="name-header" :column="scope.column">{{ '附件名称' | $lc }}</slot>
82
86
  <slot slot-scope="{ row }" name="name" :row="row">
@@ -86,10 +90,11 @@
86
90
  v-title
87
91
  :value="row[keys.name] ? row[keys.name].replace(/\.[A-z0-9]+$/, '') : ''"
88
92
  disabled
89
- :placeholder="'请输入' | $lc"
93
+ :placeholder="'上传后自动带出' | $lc"
90
94
  />
91
95
  </slot>
92
96
  </el-table-column>
97
+
93
98
  <el-table-column v-if="readonly" :label="'附件上传' | $lc" :prop="keys.name">
94
99
  <slot slot="header" slot-scope="scope" name="upload-header" :column="scope.column"
95
100
  >{{ '附件上传' | $lc }}
@@ -113,7 +118,7 @@
113
118
  :action="apiPrefix ? apiPrefix + action : action"
114
119
  :multiple="multiple"
115
120
  :headers="headers"
116
- :disabled="!row[keys.type] || row._typeDisabled || row._uploadDisabled"
121
+ :disabled="row._typeDisabled || row._uploadDisabled"
117
122
  :accept="row[keys.type] | acceptFilter(typeOptions, fileAccept)"
118
123
  :size="row[keys.type] | sizeFilter(typeOptions, fileSize)"
119
124
  :http-request="uploadHttpRequest ? (options) => uploadHttpRequest(options, row) : undefined"
@@ -126,6 +131,7 @@
126
131
  : onSuccessFn(response, file, fileList, row)
127
132
  "
128
133
  :on-error="(err, file, fileList) => errorFn(err, file, fileList, row, $index)"
134
+ @click.native.capture="handleUploadClick($event, row)"
129
135
  />
130
136
  </slot>
131
137
  </el-table-column>
@@ -561,12 +567,19 @@ export default {
561
567
  return false
562
568
  }
563
569
  this.setTableData()
570
+ this.setSingleTypeForEmptyRows()
564
571
  },
565
572
  immediate: true,
566
573
  deep: true
567
574
  },
568
575
  tableKey() {
569
576
  this.initSortable()
577
+ },
578
+ tableData: {
579
+ handler() {
580
+ this.setSingleTypeForEmptyRows()
581
+ },
582
+ immediate: true
570
583
  }
571
584
  },
572
585
  mounted() {
@@ -844,11 +857,17 @@ export default {
844
857
 
845
858
  let requestData = JSON.parse(this.fileData?.data || '{}')
846
859
  requestData.bussId = requestData.bussId ?? this.fileData?.bussId ?? ''
847
- requestData.bussValues = this.typeOptions.map((item) => item.type)
860
+ // bussValues 应为业务编码列表(与 updateFlieBuss/getByBussValues 契约一致),而非附件类型编号(attno)
861
+ let bussValues = [...new Set(this.typeOptions.map((item) => item.bussValue).filter(Boolean))]
862
+ requestData.bussValues = bussValues.length ? bussValues : [requestData.bussValue].filter(Boolean)
863
+ if (!requestData.bussValues.length) {
864
+ this.$message.warning($lc('附件类型业务编码缺失,无法自动识别上传,请检查附件类型配置'))
865
+ return
866
+ }
848
867
  FD.append('data', JSON.stringify(requestData))
849
868
 
850
869
  this.batchUploading = true
851
- let { data } = await axios.post(
870
+ let res = await axios.post(
852
871
  this.apiPrefix
853
872
  ? `${this.apiPrefix}/neams/eamsbaserecord/batchSaveFile`
854
873
  : '/neams/eamsbaserecord/batchSaveFile',
@@ -861,7 +880,14 @@ export default {
861
880
  }
862
881
  )
863
882
 
864
- let responseList = Array.isArray(data) ? data : []
883
+ // axios 封装会把 code:0 短路成 200 误判成功(utils/axios.js 拦截器 falsy 缺陷),此处必须二次校验
884
+ if (!res || Number(res.code) !== 200 || !Array.isArray(res.data)) {
885
+ throw { msg: (res && res.msg) || $lc('批量上传失败') }
886
+ }
887
+ let responseList = res.data
888
+ if (responseList.length < files.length) {
889
+ this.$message.warning($lc('部分文件上传失败,请检查附件列表'))
890
+ }
865
891
  let rows = responseList.map((item) => this.buildAutoMatchBatchRow(item))
866
892
  rows.forEach((row) => {
867
893
  let type = row[this.keys.type]
@@ -879,7 +905,8 @@ export default {
879
905
  let pendingFiles = [...files]
880
906
  rows.forEach((row) => {
881
907
  let fileIndex = pendingFiles.findIndex((item) => item.raw.name === row[this.keys.name])
882
- let sourceFile = pendingFiles.splice(fileIndex > -1 ? fileIndex : 0, 1)[0]
908
+ if (fileIndex === -1) return // 匹配不到不消费文件,避免错配
909
+ let sourceFile = pendingFiles.splice(fileIndex, 1)[0]
883
910
  this.$emit('on-success', sourceFile?.raw, row)
884
911
  })
885
912
 
@@ -917,6 +944,9 @@ export default {
917
944
  },
918
945
  handleTypeChange(row) {
919
946
  let type = row[this.keys.type]
947
+ if (type) {
948
+ this.$set(row, '_typeError', false)
949
+ }
920
950
  this.$emit('typeChange', type)
921
951
  if (!row._shouldUpdateFileType || !type) {
922
952
  return
@@ -1022,6 +1052,32 @@ export default {
1022
1052
  addRow() {
1023
1053
  this.$emit('add-row')
1024
1054
  },
1055
+ setSingleTypeForEmptyRows() {
1056
+ if (this.readonly || this.typeOptions.length !== 1) {
1057
+ return
1058
+ }
1059
+
1060
+ let type = this.typeOptions[0].type
1061
+ this.tableData.forEach((row) => {
1062
+ let isEmptyRow = !row[this.keys.url] && !row[this.keys.name] && !row._name
1063
+ if (isEmptyRow && !row[this.keys.type]) {
1064
+ // 新增行可能由业务侧异步写入,通过监听数据确保唯一附件类型仍能自动带出。
1065
+ this.$set(row, this.keys.type, type)
1066
+ this.$set(row, '_typeError', false)
1067
+ }
1068
+ })
1069
+ },
1070
+ handleUploadClick(event, row) {
1071
+ if (row[this.keys.type]) {
1072
+ return
1073
+ }
1074
+
1075
+ // 文件选择窗口打开前完成类型校验,避免用户选完文件后才收到错误提示。
1076
+ event.preventDefault()
1077
+ event.stopPropagation()
1078
+ this.$set(row, '_typeError', true)
1079
+ this.$message.warning($lc('请先选择附件类型'))
1080
+ },
1025
1081
  downRows() {
1026
1082
  if (!this.selectionList.length) {
1027
1083
  return this.$message({
@@ -1304,4 +1360,16 @@ export default {
1304
1360
  color: #fff !important;
1305
1361
  background: #42b983 !important;
1306
1362
  }
1363
+
1364
+ .file-upload-table__type-cell {
1365
+ align-items: flex-start;
1366
+ }
1367
+
1368
+ .file-upload-table__type-content {
1369
+ width: calc(100% - 16px);
1370
+ }
1371
+
1372
+ .file-upload-table__type-error .el-input__inner {
1373
+ border-color: var(--color-danger);
1374
+ }
1307
1375
  </style>
package/src/i18n.json CHANGED
@@ -9364,5 +9364,17 @@
9364
9364
  "th": "กลับไปยังขั้นตอนก่อนหน้า",
9365
9365
  "vi": "Quay lại bước trước",
9366
9366
  "ja": "前のステップに戻る"
9367
+ },
9368
+ "请先选择附件类型": {
9369
+ "en": "Please select an attachment type",
9370
+ "th": "โปรดเลือกประเภทไฟล์แนบ",
9371
+ "vi": "Vui lòng chọn loại tệp đính kèm",
9372
+ "ja": "添付ファイルの種類を選択してください"
9373
+ },
9374
+ "上传后自动带出": {
9375
+ "en": "Automatically filled after upload",
9376
+ "th": "กรอกโดยอัตโนมัติหลังอัปโหลด",
9377
+ "vi": "Tự động điền sau khi tải lên",
9378
+ "ja": "アップロード後に自動入力されます"
9367
9379
  }
9368
9380
  }