uniapp图片循环上传使用使用 Promise.allSettled,避免一个失败全部失败

35 阅读1分钟
  uni.chooseImage({
    count: 9,
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    async success(res) {
      try {
        const tempFilePaths: any = res.tempFilePaths
 
        // 显示上传 loading
        uni.showLoading({
          title: '图片上传中...',
          mask: true,
        })
 
        // 使用 Promise.allSettled 而不是 Promise.all,避免一个失败全部失败
        const uploadResults = await Promise.allSettled(
            
          tempFilePaths.map(filePath =>
            new Promise((resolve, reject) => {
              uni.uploadFile({
                url: `${baseUrl}/dev/file/uploadsLocalReturnUrl/batch`,
                filePath,
                name: 'file',
                success: (uploadRes) => {
                  try {
                    const data = JSON.parse(uploadRes.data)
                    resolve(data.data)
                  }
                  catch (e) {
                    reject(new Error('解析响应数据失败'))
                  }
                },
                fail: (err) => {
                  reject(new Error(`上传失败: ${err.errMsg || '未知错误'}`))
                },
              })
            }),
          ),
        )
 
        // 处理上传结果
        const successfulUploads = uploadResults.filter(result => result.status === 'fulfilled')
        const failedUploads = uploadResults.filter(result => result.status === 'rejected')
 
        const imageUrls = successfulUploads.map(result => (result as PromiseFulfilledResult<string>).value)
 
        // 如果有上传失败的图片,提示用户
        if (failedUploads.length > 0) {
          uni.showToast({
            title: `${failedUploads.length}张图片上传失败`,
            icon: 'none',
            duration: 2000,
          })
        }
 
        // 如果没有图片上传成功,直接返回
        if (imageUrls.length === 0) {
          uni.showToast({
            title: '所有图片上传失败',
            icon: 'error',
          })
          return
        }
 
        // 构建图片HTML - 优化显示效果
        const imagesHtml = imageUrls.map(url =>
          `<img style="width: 80rpx; height: 80rpx; border-radius: 8rpx; object-fit: cover;" src="${url}">`,
        ).join('')
 
        // 添加到聊天列表
        chatList.value.push({
          nodes: `
          <div style="display: flex; flex-wrap: wrap; gap: 16rpx; padding: 16rpx;">
            ${imagesHtml}
          </div>
        `,
          isMe: true,
        })
 
        // 发送对话请求
        try {
          const res: any = await sendDialog({
            type: tabbarIns.value,
            content: imageUrls.flat(),
            step: step.value,
          })
 
          if (res.data) {
            chatList.value.push(res.data)
            step.value = res.data.step || null
          }
        }
        catch (error) {
          console.error('发送对话失败:', error)
          toast.error('系统发生错误')
 
          chatList.value.push({
            nodes: '<div style="color: #ff4d4f;">网络超时请重试</div>',
            isMe: false,
          })
        }
      }
      catch (error) {
        console.error('选择图片流程错误:', error)
      }
      finally {
        uni.hideLoading()
        inputValue.value = ''
        sendBefore.value = false
      }
    },
    fail(err) {
      console.log('取消选择', err)
      sendBefore.value = false
    },
  })