4848 class =" w-full mb-4"
4949 drag
5050 multiple
51- v-model :file-list =" form.fileList"
51+ :file-list =" form.fileList"
5252 action =" #"
5353 :auto-upload =" false"
5454 :show-file-list =" false"
106106 class =" w-full mb-4"
107107 drag
108108 multiple
109- v-model :file-list =" form.fileList"
109+ :file-list =" form.fileList"
110110 action =" #"
111111 :auto-upload =" false"
112112 :show-file-list =" false"
152152 class =" w-full"
153153 drag
154154 multiple
155- v-model :file-list =" form.fileList"
155+ :file-list =" form.fileList"
156156 action =" #"
157157 :auto-upload =" false"
158158 :show-file-list =" false"
184184 </el-upload >
185185 </el-form-item >
186186 </el-form >
187- <el-row :gutter =" 8" v-if =" form.fileList?.length" >
187+ <div v-if =" form.fileList?.length" class =" flex-between w-full mt-16" >
188+ <span >
189+ {{
190+ $t('dynamicsForm.UploadInput.uploadStatus', {
191+ success: successCount,
192+ total: form.fileList.length,
193+ })
194+ }}
195+ </span >
196+ <span v-if =" uploadingCount" class =" flex align-center" >
197+ <el-icon class =" is-loading color-primary" size =" 18" ><Loading /></el-icon >
198+ <span class =" ml-4" >{{ $t('dynamicsForm.UploadInput.uploading') }}</span >
199+ </span >
200+ <span v-else-if =" errorCount" class =" flex align-center" >
201+ <el-icon class =" color-danger ml-4" size =" 18" ><WarningFilled /></el-icon >
202+ <span class =" ml-4" >
203+ {{ $t('dynamicsForm.UploadInput.failedStatus', { count: errorCount }) }}
204+ </span >
205+ <el-button v-if =" retryList.length" text @click =" retryAll" >
206+ <AppIcon iconName="app-refresh"></AppIcon >
207+ {{ $t('dynamicsForm.UploadInput.reUpload') }}
208+ </el-button >
209+ </span >
210+ </div >
211+ <el-row :gutter =" 8" v-if =" form.fileList?.length" class =" mt-8" >
188212 <template v-for =" (item , index ) in form .fileList " :key =" index " >
189213 <el-col :span =" 12" class =" mb-8" >
190- <el-card shadow =" never" style =" --el-card-padding : 8px 12px ; line-height : normal " >
214+ <el-card
215+ shadow =" never"
216+ style ="
217+ --el-card-padding : 8px 12px ;
218+ line-height : normal ;
219+ position : relative ;
220+ overflow : hidden ;
221+ "
222+ :class =" item.status === 'error' ? 'border-danger' : ''"
223+ >
191224 <div class =" flex-between" >
192225 <div class =" flex" >
193226 <img :src =" getImgUrl(item && item?.name)" alt =" " width =" 40" />
194227 <div class =" ml-8" >
195228 <p class =" ellipsis-1" :title =" item && item?.name" >{{ item && item?.name }}</p >
196- <el-text type =" info" size =" small" >{{
197- filesize(item && item?.size) || '0K'
198- }}</el-text >
229+ <el-text type =" info" size =" small" >
230+ <template v-if =" item .status === ' uploading' " >
231+ {{ filesize((item.size * item.percentage) / 100) }} /
232+ {{ filesize(item.size) || '0K' }}
233+ </template >
234+ <template v-else >{{ filesize(item && item?.size) || '0K' }}</template >
235+ </el-text >
236+ <el-text class =" ml-8" v-if =" item.status === 'error'" type =" danger" size =" small" >
237+ {{ item.errMsg }}
238+ </el-text >
199239 </div >
200240 </div >
201- <el-button text @click =" deleteFile(index)" >
202- <AppIcon iconName="app-delete"></AppIcon >
203- </el-button >
241+ <div class =" flex align-center" >
242+ <el-button v-if =" item.canRetry" text @click =" uploadFile(item)" >
243+ <AppIcon iconName="app-refresh"></AppIcon >
244+ </el-button >
245+ <el-button text @click =" deleteFile(index, item)" >
246+ <AppIcon iconName="app-delete"></AppIcon >
247+ </el-button >
248+ </div >
204249 </div >
250+ <el-progress
251+ v-if =" item.status === 'uploading'"
252+ class =" card-progress"
253+ :percentage =" item.percentage"
254+ :stroke-width =" 4"
255+ :show-text =" false"
256+ />
205257 </el-card >
206258 </el-col >
207259 </template >
@@ -213,6 +265,7 @@ import { useRoute } from 'vue-router'
213265import type { UploadFiles } from ' element-plus'
214266import { filesize , getImgUrl , isRightType } from ' @/utils/common'
215267import { MsgError } from ' @/utils/message'
268+ import applicationApi from ' @/api/application/application'
216269import { loadSharedApi } from ' @/utils/dynamics-api/shared-api'
217270import useStore from ' @/stores'
218271import { t } from ' @/locales'
@@ -237,6 +290,7 @@ const documentsType = computed(() => knowledge.documentsType)
237290
238291const FormRef = ref ()
239292const loading = ref (false )
293+ const uploadLoading = ref (false )
240294
241295const form = ref ({
242296 fileType: ' txt' ,
@@ -251,6 +305,21 @@ const rules = reactive({
251305
252306const file_count_limit = ref (50 )
253307const file_size_limit = ref (100 )
308+ const successCount = computed (
309+ () => form .value .fileList .filter ((i : any ) => i .status !== ' uploading' ).length ,
310+ )
311+ const errorCount = computed (
312+ () => form .value .fileList .filter ((i : any ) => i .status === ' error' ).length ,
313+ )
314+ const uploadingCount = computed (
315+ () => form .value .fileList .filter ((i : any ) => i .status === ' uploading' ).length ,
316+ )
317+ const retryList = computed (() =>
318+ form .value .fileList .filter ((i : any ) => i .status === ' error' && i .canRetry ),
319+ )
320+ const retryAll = () => {
321+ retryList .value .forEach ((i : any ) => uploadFile (i ))
322+ }
254323
255324watch (form .value , (value ) => {
256325 knowledge .saveDocumentsType (value .fileType )
@@ -272,10 +341,22 @@ function downloadTableTemplate(type: string) {
272341}
273342
274343function radioChange() {
344+ form .value .fileList .forEach ((item : any ) => {
345+ if (item ?.status === ' uploading' && typeof item .abort === ' function' ) {
346+ item .aborted = true
347+ item .abort ()
348+ }
349+ })
275350 form .value .fileList = []
276351}
277352
278- function deleteFile(index : number | string ) {
353+ function deleteFile(index : number | string , item ? : any ) {
354+ if (item ?.status === ' uploading' && typeof item .abort === ' function' ) {
355+ item .aborted = true
356+ item .abort ()
357+ } else if (item ?.status === ' success' && item ?.file_id ) {
358+ applicationApi .deleteFile (item .file_id )
359+ }
279360 form .value .fileList .splice (index , 1 )
280361}
281362
@@ -309,6 +390,55 @@ const fileHandleChange = (file: any, fileList: UploadFiles) => {
309390 removeCurrentFile ()
310391 return false
311392 }
393+
394+ const item = reactive ({
395+ name: file .name ,
396+ size: file .size ,
397+ file_id: ' ' ,
398+ source_file_id: ' ' ,
399+ percentage: 0 ,
400+ status: ' uploading' as ' uploading' | ' success' | ' error' ,
401+ errMsg: ' ' ,
402+ canRetry: false ,
403+ raw: file .raw ,
404+ abort: null as null | (() => void ),
405+ aborted: false ,
406+ })
407+ form .value .fileList .push (item )
408+ uploadFile (item )
409+ }
410+
411+ const uploadFile = (item : any ) => {
412+ item .status = ' uploading'
413+ item .percentage = 0
414+ item .errMsg = ' '
415+ item .canRetry = false
416+ item .aborted = false
417+ const res: any = applicationApi .postUploadFileProgress (
418+ item .raw ,
419+ id as string ,
420+ ' KNOWLEDGE' ,
421+ (percent : number ) => {
422+ item .percentage = percent
423+ },
424+ uploadLoading ,
425+ )
426+ item .abort = typeof res ?.abort === ' function' ? res .abort : null
427+ const request: Promise <any > = res ?.then ? res : res ?.request
428+ request
429+ .then ((ok : any ) => {
430+ const split_path = ok .data .split (' /' )
431+ item .file_id = split_path [split_path .length - 1 ]
432+ item .source_file_id = item .file_id
433+ item .percentage = 100
434+ item .status = ' success'
435+ })
436+ .catch (() => {
437+ if (item .aborted ) return
438+ item .status = ' error'
439+ item .errMsg = t (' dynamicsForm.UploadInput.errorTip.networkError' )
440+ item .canRetry = true
441+ })
312442}
313443
314444const onExceed = () => {
@@ -334,6 +464,14 @@ const handlePreview = (bool: boolean) => {
334464*/
335465function validate() {
336466 if (! FormRef .value ) return
467+ if (uploadingCount .value ) {
468+ MsgError (t (' dynamicsForm.UploadInput.uploading' ))
469+ return false
470+ }
471+ if (errorCount .value ) {
472+ MsgError (t (' dynamicsForm.UploadInput.failedStatus' , { count: errorCount .value }))
473+ return false
474+ }
337475 return FormRef .value .validate ((valid : any ) => {
338476 return valid
339477 })
0 commit comments