From fe11a72dccadc8aae644406b7d1e6b5465721fc1 Mon Sep 17 00:00:00 2001
From: rain <1679827795@qq.com>
Date: Tue, 15 Apr 2025 19:20:10 +0800
Subject: [PATCH] 批量审核

---
 src/views/tickets/ticket.vue |  362 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 361 insertions(+), 1 deletions(-)

diff --git a/src/views/tickets/ticket.vue b/src/views/tickets/ticket.vue
index 80aad20..e63ce87 100644
--- a/src/views/tickets/ticket.vue
+++ b/src/views/tickets/ticket.vue
@@ -38,6 +38,12 @@
                 icon="el-icon-plus"
                 @click="handleAdd"
               >新建工单</el-button>
+              <el-button
+    v-if="activeTab === 'pending'"
+    type="success"
+    icon="el-icon-check"
+    @click="openReviewDialog"
+  >批量审核</el-button>
               <el-button type="success" plain icon="el-icon-download" @click="exportData">导出</el-button>
             </template>
             <template #menu="{ row }">
@@ -399,6 +405,64 @@
         <el-button type="primary" @click="submitDispatch">确认派发</el-button>
       </template>
     </el-dialog>
+
+    <!-- 添加在其他 dialog 组件之后 -->
+<el-dialog v-model="reviewDialogVisible" title="批量审核" width="70%" append-to-body custom-class="review-dialog">
+  <div class="review-container">
+    <!-- 图片浏览区域 -->
+    <div class="review-image-wrapper">
+      <!-- 左箭头 -->
+      <div v-show="selections.length > 1" class="arrow-button left" @click="handlePrevImage">
+        <el-icon><ArrowLeft /></el-icon>
+      </div>
+
+      <!-- 图片显示区域 -->
+      <div class="review-image-container">
+        <el-image 
+          :src="currentReviewImage"
+          fit="cover"
+          :preview-src-list="getImageList()"
+          :initial-index="currentImageIndex - 1"
+          class="preview-image"
+        >
+          <template #error>
+            <div class="image-error">
+              <i class="el-icon-picture-outline"></i>
+              <span>图片加载失败</span>
+            </div>
+          </template>
+        </el-image>
+      </div>
+
+      <!-- 右箭头 -->
+      <div v-show="selections.length > 1" class="arrow-button right" @click="handleNextImage">
+        <el-icon><ArrowRight /></el-icon>
+      </div>
+    </div>
+    
+    <!-- 分页指示器 -->
+    <div class="review-pagination" v-if="selections.length > 1">
+      <el-pagination
+        small
+        layout="prev, pager, next"
+        hide-on-single-page
+        :total="selections.length"
+        :current-page.sync="currentImageIndex"
+        :page-size="1"
+        @current-change="handleImagePageChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+  
+  <template #footer>
+    <div class="dialog-footer">
+      <el-button type="primary" @click="handleBatchApprove">通过</el-button>
+      <el-button type="danger" @click="handleBatchReject">不通过</el-button>
+      <el-button @click="reviewDialogVisible = false">取消</el-button>
+    </div>
+  </template>
+</el-dialog>
   </basic-container>
 </template>
 
@@ -555,6 +619,9 @@
       userNameToIdMap: {}, // 新增用户名到ID的映射
       workType: 0, // 新增:当前工单work_type
       selections: [], // 添加选中行数据数组
+      reviewDialogVisible: false, // 新增:审核对话框可见性
+      currentReviewImage: '', // 新增:当前审核图片
+      currentImageIndex: 1, // 新增:当前图片索引
     };
   },
   created() {
@@ -709,7 +776,43 @@
         this.$message.error('地图加载失败,请检查网络或API Key配置');
       }
     },
+    async handleBatchApprove() {
+    try {
+      await this.$confirm('确认批量审核通过选中的工单?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      });
 
+      const promises = this.selections.map(async (item) => {
+        const data = {
+          id: item.id,
+          status: item.status,
+          isPass: 0, // 0 表示通过
+          eventNum: item.orderNumber,
+          eventName: item.orderName,
+          eventType: item.type,
+        };
+        return flowEvent(data);
+      });
+
+      const results = await Promise.all(promises);
+      const successCount = results.filter(res => res.data.code === 0).length;
+      
+      if (successCount > 0) {
+        this.$message.success(`成功审核通过 ${successCount} 个工单`);
+        // 清空选择
+        this.clearSelection();
+        // 刷新数据
+        this.fetchTableData();
+      } else {
+        throw new Error('批量审核失败');
+      }
+    } catch (error) {
+      if (error === 'cancel') return;
+      this.$message.error(error.message || '批量审核失败,请稍后重试');
+    }
+  },
     async fetchDropdownData() {
       try {
         const response = await getTicketInfo();
@@ -1604,6 +1707,143 @@
     clearSelection() {
       this.$refs.avueCrud.clearSelection();
     },
+
+    // 打开审核对话框
+    openReviewDialog() {
+      if (this.selections.length === 0) {
+        this.$message.warning('请先选择要审核的工单');
+        return;
+      }
+      this.currentImageIndex = 1;
+      this.updateCurrentReviewImage();
+      this.reviewDialogVisible = true;
+    },
+
+    // 更新当前审核图片
+    updateCurrentReviewImage() {
+      if (this.selections.length > 0 && this.currentImageIndex > 0) {
+        const currentItem = this.selections[this.currentImageIndex - 1];
+        this.currentReviewImage = currentItem.photo_url || '';
+      } else {
+        this.currentReviewImage = '';
+      }
+    },
+
+    // 处理图片分页变化
+    handleImagePageChange(page) {
+      this.currentImageIndex = page;
+      this.updateCurrentReviewImage();
+    },
+
+    // 批量审核通过
+    async handleBatchApprove() {
+      try {
+        await this.$confirm('确认批量审核通过选中的工单?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        });
+
+        const promises = this.selections.map(async (item) => {
+          const data = {
+            id: item.id,
+            status: item.status,
+            isPass: 0, // 0 表示通过
+            eventNum: item.orderNumber,
+            eventName: item.orderName,
+            eventType: item.type,
+          };
+          return flowEvent(data);
+        });
+
+        const results = await Promise.all(promises);
+        const successCount = results.filter(res => res.data.code === 0).length;
+        
+        if (successCount > 0) {
+          this.$message.success(`成功审核通过 ${successCount} 个工单`);
+          // 清空选择
+          this.clearSelection();
+          // 刷新数据
+          this.fetchTableData();
+          // 关闭审核对话框
+          this.reviewDialogVisible = false;
+        } else {
+          throw new Error('批量审核失败');
+        }
+      } catch (error) {
+        if (error === 'cancel') return;
+        this.$message.error(error.message || '批量审核失败,请稍后重试');
+      }
+    },
+
+    // 批量审核不通过
+    async handleBatchReject() {
+      try {
+        await this.$confirm('确认批量审核不通过选中的工单?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        });
+
+        const promises = this.selections.map(async (item) => {
+          const data = {
+            id: item.id,
+            status: item.status,
+            isPass: 1, // 1 表示不通过
+            eventNum: item.orderNumber,
+            eventName: item.orderName,
+            eventType: item.type,
+          };
+          return flowEvent(data);
+        });
+
+        const results = await Promise.all(promises);
+        const successCount = results.filter(res => res.data.code === 0).length;
+        
+        if (successCount > 0) {
+          this.$message.success(`成功审核不通过 ${successCount} 个工单`);
+          // 清空选择
+          this.clearSelection();
+          // 刷新数据
+          this.fetchTableData();
+          // 关闭审核对话框
+          this.reviewDialogVisible = false;
+        } else {
+          throw new Error('批量审核失败');
+        }
+      } catch (error) {
+        if (error === 'cancel') return;
+        this.$message.error(error.message || '批量审核失败,请稍后重试');
+      }
+    },
+
+    // 获取所有图片列表用于预览
+    getImageList() {
+      return this.selections
+        .map(item => item.photo_url)
+        .filter(url => url); // 过滤掉空值
+    },
+
+    // 处理图片点击
+    handleImageClick() {
+      // 图片点击事件由 el-image 的预览功能处理
+    },
+
+    // 处理上一张图片
+    handlePrevImage() {
+      if (this.currentImageIndex > 1) {
+        this.currentImageIndex--;
+        this.updateCurrentReviewImage();
+      }
+    },
+
+    // 处理下一张图片
+    handleNextImage() {
+      if (this.currentImageIndex < this.selections.length) {
+        this.currentImageIndex++;
+        this.updateCurrentReviewImage();
+      }
+    },
   },
 };
 </script>
@@ -2095,4 +2335,124 @@
     }
   }
 }
-</style>
\ No newline at end of file
+
+// 添加新的样式
+.review-dialog {
+  :deep(.el-dialog__body) {
+    padding: 0;
+    background-color: #f5f7fa;
+  }
+}
+
+.review-container {
+  position: relative;
+  
+  .review-image-wrapper {
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 600px;
+    background-color: #f5f7fa;
+  }
+
+  .review-image-container {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    
+    :deep(.el-image) {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .el-image__inner {
+        max-height: 100%;
+        max-width: 100%;
+        object-fit: contain;
+      }
+    }
+  }
+
+  .arrow-button {
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 44px;
+    height: 44px;
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    transition: all 0.3s;
+    z-index: 100;
+
+    &:hover {
+      background: rgba(0, 0, 0, 0.6);
+    }
+
+    i {
+      color: #fff;
+      font-size: 24px;
+    }
+
+    &.left {
+      left: 20px;
+    }
+
+    &.right {
+      right: 20px;
+    }
+  }
+
+  .preview-image {
+    max-width: 100%;
+    max-height: 100%;
+  }
+
+  .review-pagination {
+    padding: 16px 0;
+    display: flex;
+    justify-content: center;
+    background-color: #fff;
+
+    :deep(.el-pagination) {
+      .btn-prev,
+      .btn-next {
+        display: none;
+      }
+
+      .el-pager {
+        .number {
+          margin: 0 4px;
+        }
+      }
+    }
+  }
+
+  .image-error {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    color: #909399;
+    
+    i {
+      font-size: 48px;
+      margin-bottom: 16px;
+    }
+    
+    span {
+      font-size: 16px;
+    }
+  }
+}
+</style>
+```
\ No newline at end of file

--
Gitblit v1.9.3