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