Procházet zdrojové kódy

添加图片上传失败处理

zengjun před 6 měsíci
rodič
revize
545658e24d
2 změnil soubory, kde provedl 204 přidání a 16 odebrání
  1. 11 0
      src/api/processing/index.ts
  2. 193 16
      src/views/processing/photoTask/index.vue

+ 11 - 0
src/api/processing/index.ts

@@ -60,3 +60,14 @@ export function uploadPhoto(id, params) {
     data: params,
   })
 }
+
+/**
+ * 对应的状态
+ */
+export function status(){
+  return request({
+    url: 'api/device/check/processing/photo-task/status',
+    method: 'get',
+  })
+}
+

+ 193 - 16
src/views/processing/photoTask/index.vue

@@ -1,4 +1,4 @@
-<template>
+  <template>
   <div class="container">
     <div class="processing-photo-task">
       <div class="top">
@@ -23,12 +23,44 @@
               </div>
             </template>
             <template #right>
-              <div class="nav-right" style="color: #fff">刷新</div>
+              <div class="nav-right" style="color: #fff">重置</div>
             </template>
           </van-nav-bar>
         </div>
 
         <div class="context">
+          <!-- 筛选区域 -->
+          <div class="filter-section">
+            <van-row gutter="10">
+              <van-col span="8">
+                <van-field
+                  v-model="filterForm.owners"
+                  placeholder="请选择货主"
+                  readonly
+                  clickable
+                  clearable
+                  clear-trigger="always"
+                  @click="showOwnerDialog"
+                  @clear="onOwnerClear"
+                />
+              </van-col>
+              <van-col span="8">
+                <van-field
+                  v-model="filterForm.status"
+                  placeholder="请选择状态"
+                  readonly
+                  clickable
+                  @click="showStatusPicker = true"
+                />
+              </van-col>
+              <van-col span="8">
+                <van-button type="primary" size="small" block @click="onFilterSearch">
+                  搜索
+                </van-button>
+              </van-col>
+            </van-row>
+          </div>
+
           <van-pull-refresh
             v-model="loading"
             @refresh="onRefresh"
@@ -89,6 +121,21 @@
         </div>
       </div>
 
+      <!-- 货主选择器弹窗 -->
+      <Owner 
+        ref="ownerRef" 
+        @onOwner="onOwnerSelect"
+      />
+
+      <!-- 状态选择器弹窗 -->
+      <van-popup v-model:show="showStatusPicker" position="bottom">
+        <van-picker
+          :columns="statusOptions"
+          @confirm="onStatusConfirm"
+          @cancel="showStatusPicker = false"
+        />
+      </van-popup>
+
       <!-- 图片上传弹窗 -->
       <van-popup v-model:show="showUpload" position="bottom" :style="{ height: '80%' }">
         <div class="upload-popup">
@@ -140,9 +187,10 @@ import { showNotify, showImagePreview, showFailToast, showLoadingToast, closeToa
 import {
   getProcessingPhotoTask,
   processingPhotoTaskItems,
-  uploadPhoto
+  uploadPhoto,status
 } from '@/api/processing/index'
 import { getHeader, goBack } from '@/utils/android'
+import Owner from '@/components/Owner.vue'
 try {
   getHeader()
 } catch (error) {
@@ -157,6 +205,7 @@ const showUpload = ref(false)
 const uploadImages = ref([])
 const uploading = ref(false)
 const currentTaskId = ref(null)
+const ownerRef = ref(null)
 
 const paginate = ref({
   page: 1,
@@ -166,6 +215,16 @@ const paginate = ref({
 })
 const reviewImages = ref([])
 
+// 筛选相关数据
+const filterForm = ref({
+  owners: '',
+  status: '',
+  statusCode: ''
+})
+
+const showStatusPicker = ref(false)
+const statusOptions = ref([])
+
 // 计算最大高度适配手持设备
 const computedMaxHeight = computed(() => {
   return window.innerHeight - 46 - 20 + 'px'
@@ -178,6 +237,14 @@ onMounted(() => {
     // 如果有传入id参数,可以做特殊处理
     console.log('接收到参数id:', route.query.id)
   }
+
+  status().then(res=>{
+    if (res.data) {
+      statusOptions.value = res.data.map(item=>{
+        return {text:item.name,value:item.code}
+      })
+    }
+  })
 })
 
 // 显示notes信息 - 改为弹框方式
@@ -194,12 +261,21 @@ function showNotes(row) {
 function onRefresh() {
   // 刷新时重置到第一页
   paginate.value.page = 1
+  filterForm.value.owners = null
+  filterForm.value.status = null
+  filterForm.value.statusCode = null
   listProcessingPhoto()
 }
 
 function listProcessingPhoto() {
   loading.value = true
-  getProcessingPhotoTask(paginate.value).then((res) => {
+  // 合并筛选条件和分页参数,使用statusCode而不是status
+  const params = {
+    ...paginate.value,
+    owners: filterForm.value.owners,
+    status: filterForm.value.statusCode
+  }
+  getProcessingPhotoTask(params).then((res) => {
     photoTasks.value = res?.data?.records || []
     // 更新分页信息
     if (res?.data) {
@@ -307,34 +383,129 @@ const submitUpload = async () => {
   const toast = showLoadingToast('上传中...')
 
   try {
+    const totalImages = uploadImages.value.length
+    let successCount = 0
+    let failedImages = []
+
     // 逐个上传图片
-    for (const image of uploadImages.value) {
-      const formData = new FormData()
-      formData.append('file', image.file)
-      // 调用上传API
-      await uploadPhoto(currentTaskId.value, formData)
+    for (let i = 0; i < uploadImages.value.length; i++) {
+      const image = uploadImages.value[i]
+      try {
+        const formData = new FormData()
+        formData.append('file', image.file)
+        // 调用上传API
+        await uploadPhoto(currentTaskId.value, formData)
+        successCount++
+      } catch (err) {
+        console.error(`第${i + 1}张图片上传失败:`, err)
+        failedImages.push({
+          index: i,
+          image: image,
+          error: err.message || '上传失败'
+        })
+      }
     }
 
     closeToast()
-    showNotify({ type: 'success', message: '上传成功' })
 
-    // 关闭弹窗并刷新列表
-    showUpload.value = false
-    uploadImages.value = []
-    onRefresh()
+    if (successCount === totalImages) {
+      // 全部上传成功
+      showNotify({ type: 'success', message: '全部图片上传成功' })
+      // 关闭弹窗并刷新列表
+      showUpload.value = false
+      uploadImages.value = []
+      onRefresh()
+    } else if (successCount > 0) {
+      // 部分上传成功
+      showNotify({ 
+        type: 'warning', 
+        message: `${successCount}/${totalImages}张图片上传成功,${failedImages.length}张失败` 
+      })
+      // 移除上传成功的图片,保留失败的图片
+      uploadImages.value = failedImages.map(item => item.image)
+    } else {
+      // 全部上传失败
+      showNotify({ 
+        type: 'danger', 
+        message: '所有图片上传失败,请检查网络连接或重试' 
+      })
+      // 保留所有失败的图片,让用户可以重试
+    }
   } catch (err) {
     closeToast()
-    showNotify({ type: 'danger', message: '上传失败: ' + (err.message || '未知错误') })
+    showNotify({ type: 'danger', message: '上传过程发生异常: ' + (err.message || '未知错误') })
+    // 发生异常时保留所有图片,让用户可以重试
   } finally {
     uploading.value = false
   }
 }
 
+// 筛选相关方法
+function onFilterChange() {
+  // 清除筛选时自动搜索
+  onFilterSearch()
+}
+
+function onFilterSearch() {
+  // 搜索时重置到第一页
+  paginate.value.page = 1
+  listProcessingPhoto()
+}
+
+// 显示货主选择弹窗
+function showOwnerDialog() {
+  if (ownerRef.value) {
+    ownerRef.value.show('filter')
+  }
+}
+
+// 处理货主选择
+function onOwnerSelect(item, type) {
+  filterForm.value.owners = item.name
+  // 选择货主后自动搜索
+  onFilterSearch()
+}
+
+// 处理货主清空
+function onOwnerClear() {
+  filterForm.value.owners = ''
+  // 清空货主后自动搜索
+  onFilterSearch()
+}
+
+function onStatusConfirm({ selectedOptions }) {
+  filterForm.value.status = selectedOptions[0].text
+  filterForm.value.statusCode = selectedOptions[0].value
+  showStatusPicker.value = false
+  // 选择状态后自动搜索
+  onFilterSearch()
+}
+
 // 初始化加载数据
 onRefresh()
 </script>
 
 <style scoped lang="scss">
+// 确保van-field的清空按钮样式正确显示
+:deep(.van-field__clear) {
+  display: flex !important;
+  align-items: center;
+  justify-content: center;
+  color: #c8c9cc;
+  font-size: 16px;
+  cursor: pointer;
+
+  &:active {
+    color: #969799;
+  }
+}
+
+// 确保van-field右侧区域有足够空间显示清空按钮
+:deep(.van-field__right-icon) {
+  display: flex !important;
+  align-items: center;
+}
+
 .photo-task-table {
   width: 100%;
   border-collapse: collapse;
@@ -420,6 +591,12 @@ onRefresh()
   }
 }
 
+.filter-section {
+  padding: 10px;
+  background: #fff;
+  border-bottom: 1px solid #e0e0e0;
+}
+
 .code-link {
   color: #1989fa;
   cursor: pointer;
@@ -429,4 +606,4 @@ onRefresh()
     color: #0570db;
   }
 }
-</style>
+</style>