无人机管理后台前端(已迁走)
shuishen
2025-04-15 df42fa7e97c4a93caa17b2aed5aecdc768d8bbd7
Merge branch 'master' of http://139.196.74.78:10010/r/drone/drone-web-manage
1 files modified
312 ■■■■■ changed files
src/views/tickets/ticket.vue 312 ●●●●● patch | view | raw | blame | history
src/views/tickets/ticket.vue
@@ -32,18 +32,10 @@
            @size-change="sizeChange" @current-change="handleCurrentChange" :table-loading="loading"
            @selection-change="handleSelectionChange">
            <template #menu-left>
              <el-button
                v-if="activeTab === 'all' || activeTab === 'myTickets'"
                type="primary"
                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 v-if="activeTab === 'all' || activeTab === 'myTickets'" type="primary" 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 }">
@@ -89,14 +81,16 @@
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="所属部门" prop="department">
                <el-select v-model="form.department" placeholder="请选择所属部门" @change="handleDepartmentChange" class="full-width">
                <el-select v-model="form.department" placeholder="请选择所属部门" @change="handleDepartmentChange"
                  class="full-width">
                  <el-option v-for="dept in departments" :key="dept.value" :label="dept.label" :value="dept.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="处理人员" prop="handler">
                <el-select v-model="form.handler" placeholder="请先选择所属部门" :disabled="!form.department" class="full-width">
                <el-select v-model="form.handler" placeholder="请先选择所属部门" :disabled="!form.department"
                  class="full-width">
                  <el-option v-for="user in availableHandlers" :key="user.id" :label="user.name" :value="user.id" />
                </el-select>
              </el-form-item>
@@ -114,7 +108,8 @@
            <el-col :span="12">
              <el-form-item label="选择位置" prop="location" required>
                <div class="location-wrapper">
                  <avue-input-map v-model="form.location" :params="mapParams" @change="handleLocationChange" type="button">
                  <avue-input-map v-model="form.location" :params="mapParams" @change="handleLocationChange"
                    type="button">
                    <el-button type="primary" plain class="map-button">
                      <i class="el-icon-map-location"></i> 地图选点
                    </el-button>
@@ -133,18 +128,9 @@
            </el-col>
            <el-col :span="12">
              <el-form-item label="附件图片" prop="photos" required class="upload-wrapper">
                <el-upload ref="upload"
                  :action="'#'"
                  :auto-upload="false"
                  list-type="picture-card"
                  :on-change="handleFileChange"
                  :on-remove="handleUploadRemove"
                  :before-upload="beforeUpload"
                  :file-list="form.photos"
                  :limit="1"
                  accept="image/*"
                  class="uploader"
                >
                <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card"
                  :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload"
                  :file-list="form.photos" :limit="1" accept="image/*" class="uploader">
                  <i class="el-icon-plus"></i>
                </el-upload>
                <div class="upload-tip">支持jpg/png格式图片,单张不超过5MB</div>
@@ -169,18 +155,11 @@
        <div class="custom-steps-container">
          <!-- 标题行 -->
          <div class="steps-titles">
            <div
              class="step-title"
              :class="{ active: true }"
            >
            <div class="step-title" :class="{ active: true }">
              发起任务
            </div>
            <div
              v-for="(status, index) in dynamicFixedStatuses"
              :key="index"
              :class="{ active: Number(currentDetail.status) >= Number(status) }"
              class="step-title"
            >
            <div v-for="(status, index) in dynamicFixedStatuses" :key="index"
              :class="{ active: Number(currentDetail.status) >= Number(status) }" class="step-title">
              {{ mapStatus(status) }}
            </div>
          </div>
@@ -409,22 +388,15 @@
    <!-- 添加在其他 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 v-if="selections.length > 1 && currentReviewImage" class="arrow-button left" @click="handlePrevImage">
            <i class="el-icon-arrow-left"></i>
      </div>
      <!-- 图片显示区域 -->
      <div class="review-image-container">
        <el-image
          :src="currentReviewImage"
          fit="cover"
          :preview-src-list="getImageList()"
          :initial-index="currentImageIndex - 1"
          class="preview-image"
        >
            <el-image v-if="currentReviewImage" :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>
@@ -432,25 +404,19 @@
            </div>
          </template>
        </el-image>
            <div v-else class="no-image">暂无图片</div>
      </div>
      <!-- 右箭头 -->
      <div v-show="selections.length > 1" class="arrow-button right" @click="handleNextImage">
        <el-icon><ArrowRight /></el-icon>
          <!-- 修改右箭头的显示条件 -->
          <div v-if="selections.length > 1 && currentReviewImage" class="arrow-button right" @click="handleNextImage">
            <i class="el-icon-arrow-right"></i>
      </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"
      >
        <!-- 修改分页器的显示条件 -->
        <div class="review-pagination" v-if="selections.length > 1 && currentReviewImage">
          <el-pagination small layout="prev, pager, next" hide-on-single-page :total="selections.length"
            :current-page="currentImageIndex" :page-size="1" @current-change="handleImagePageChange">
      </el-pagination>
    </div>
  </div>
@@ -459,7 +425,7 @@
    <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>
          <el-button @click="cancleBatchReject">取消</el-button>
    </div>
  </template>
</el-dialog>
@@ -778,39 +744,61 @@
    },
    async handleBatchApprove() {
    try {
      await this.$confirm('确认批量审核通过选中的工单?', '提示', {
        if (this.selections.length === 0) {
          this.$message.warning('没有选中的工单');
          return;
        }
        const currentItem = this.selections[this.currentImageIndex - 1];
        if (!currentItem) {
          this.$message.warning('当前工单数据无效');
          return;
        }
        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,
          id: currentItem.id,
          status: currentItem.status,
          isPass: 0,
          eventNum: currentItem.orderNumber,
          eventName: currentItem.orderName,
          eventType: currentItem.type,
        };
        return flowEvent(data);
      });
      const results = await Promise.all(promises);
      const successCount = results.filter(res => res.data.code === 0).length;
        const response = await flowEvent(data);
        if (response.data.code === 0) {
          this.$message.success('工单审核通过');
      
      if (successCount > 0) {
        this.$message.success(`成功审核通过 ${successCount} 个工单`);
        // 清空选择
        this.clearSelection();
        // 刷新数据
          // 创建新的数组而不是修改原数组
          const newSelections = [...this.selections];
          newSelections.splice(this.currentImageIndex - 1, 1);
          this.selections = newSelections;
          // 修正索引并更新图片
          if (this.selections.length > 0) {
            if (this.currentImageIndex > this.selections.length) {
              this.currentImageIndex = this.selections.length;
            }
            this.updateCurrentReviewImage();
          } else {
            this.reviewDialogVisible = false;
            this.currentImageIndex = 1;
            this.currentReviewImage = '';
          }
          // 刷新表格数据
        this.fetchTableData();
      } else {
        throw new Error('批量审核失败');
          throw new Error(response.data.msg || '审核失败');
      }
    } catch (error) {
      if (error === 'cancel') return;
      this.$message.error(error.message || '批量审核失败,请稍后重试');
        this.$message.error(error.message || '审核失败,请稍后重试');
    }
  },
    async fetchDropdownData() {
@@ -1721,8 +1709,22 @@
    // 更新当前审核图片
    updateCurrentReviewImage() {
      if (this.selections.length > 0 && this.currentImageIndex > 0) {
        const currentItem = this.selections[this.currentImageIndex - 1];
      // 修正索引范围
      if (!this.selections || this.selections.length === 0) {
        this.currentReviewImage = '';
        this.currentImageIndex = 1;
        return;
      }
      // 如果当前索引超出范围,自动回退到最后一张
      if (this.currentImageIndex > this.selections.length) {
        this.currentImageIndex = this.selections.length;
      }
      if (this.currentImageIndex < 1) {
        this.currentImageIndex = 1;
      }
      const index = this.currentImageIndex - 1;
      if (index >= 0 && index < this.selections.length) {
        const currentItem = this.selections[index];
        this.currentReviewImage = currentItem.photo_url || '';
      } else {
        this.currentReviewImage = '';
@@ -1731,89 +1733,138 @@
    // 处理图片分页变化
    handleImagePageChange(page) {
      if (page > 0 && page <= this.selections.length) {
      this.currentImageIndex = page;
      this.updateCurrentReviewImage();
      }
    },
    // 批量审核通过
    async handleBatchApprove() {
      try {
        await this.$confirm('确认批量审核通过选中的工单?', '提示', {
        if (this.selections.length === 0) {
          this.$message.warning('没有选中的工单');
          return;
        }
        const currentItem = this.selections[this.currentImageIndex - 1];
        if (!currentItem) {
          this.$message.warning('当前工单数据无效');
          return;
        }
        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,
          id: currentItem.id,
          status: currentItem.status,
          isPass: 0,
          eventNum: currentItem.orderNumber,
          eventName: currentItem.orderName,
          eventType: currentItem.type,
          };
          return flowEvent(data);
        });
        console.log('删除前:', this.selections)
        const response = await flowEvent(data);
        if (response.data.code === 0) {
          this.$message.success('工单审核通过');
        const results = await Promise.all(promises);
        const successCount = results.filter(res => res.data.code === 0).length;
          // 创建新的数组而不是修改原数组
          const newSelections = [...this.selections];
          newSelections.splice(this.currentImageIndex - 1, 1);
        
        if (successCount > 0) {
          this.$message.success(`成功审核通过 ${successCount} 个工单`);
          // 清空选择
          this.clearSelection();
          // 刷新数据
          this.fetchTableData();
          // 关闭审核对话框
          this.reviewDialogVisible = false;
          // 修正索引并更新图片
          if (newSelections.length > 0) {
            if (this.currentImageIndex > this.selections.length) {
              this.currentImageIndex = this.selections.length;
            }
            this.updateCurrentReviewImage();
        } else {
          throw new Error('批量审核失败');
            this.reviewDialogVisible = false;
            this.currentImageIndex = 1;
            this.currentReviewImage = '';
            this.fetchTableData();
          }
          // 刷新表格数据
          // this.fetchTableData();
          this.selections = newSelections;
        } else {
          throw new Error(response.data.msg || '审核失败');
        }
      } catch (error) {
        if (error === 'cancel') return;
        this.$message.error(error.message || '批量审核失败,请稍后重试');
        this.$message.error(error.message || '审核失败,请稍后重试');
      }
    },
    cancleBatchReject(){
      reviewDialogVisible = false;
      this.fetchTableData();
    },
    // 批量审核不通过
    async handleBatchReject() {
      try {
        await this.$confirm('确认批量审核不通过选中的工单?', '提示', {
        if (this.selections.length === 0) {
          this.$message.warning('没有选中的工单');
          return;
        }
        const currentItem = this.selections[this.currentImageIndex - 1];
        if (!currentItem) {
          this.$message.warning('当前工单数据无效');
          return;
        }
        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,
          id: currentItem.id,
          status: currentItem.status,
          isPass: 1,
          eventNum: currentItem.orderNumber,
          eventName: currentItem.orderName,
          eventType: currentItem.type,
          };
          return flowEvent(data);
        });
        const results = await Promise.all(promises);
        const successCount = results.filter(res => res.data.code === 0).length;
        const response = await flowEvent(data);
        if (response.data.code === 0) {
          this.$message.success('工单已驊回');
        
        if (successCount > 0) {
          this.$message.success(`成功审核不通过 ${successCount} 个工单`);
          // 清空选择
          this.clearSelection();
          // 刷新数据
          this.fetchTableData();
          // 关闭审核对话框
          this.reviewDialogVisible = false;
          // 创建新的数组而不是修改原数组
          const newSelections = [...this.selections];
          newSelections.splice(this.currentImageIndex - 1, 1);
          this.selections = newSelections;
          // 修正索引并更新图片
          if (this.selections.length > 0) {
            if (this.currentImageIndex > this.selections.length) {
              this.currentImageIndex = this.selections.length;
            }
            this.updateCurrentReviewImage();
        } else {
          throw new Error('批量审核失败');
            this.reviewDialogVisible = false;
            this.currentImageIndex = 1;
            this.currentReviewImage = '';
            this.fetchTableData();
          }
          // 刷新表格数据
          // this.fetchTableData();
        } else {
          throw new Error(response.data.msg || '驳回失败');
        }
      } catch (error) {
        if (error === 'cancel') return;
        this.$message.error(error.message || '批量审核失败,请稍后重试');
        this.$message.error(error.message || '驳回失败,请稍后重试');
      }
    },
@@ -1947,6 +1998,7 @@
  .location-wrapper {
    width: 100%; // 修改为100%以适应父容器
    height: auto; // 修改为auto以自适应内容
    .map-button {
      width: 100%; // 让按钮填满容器宽度
      height: 36px; // 与其他输入框保持一致的高度
@@ -2423,6 +2475,7 @@
    background-color: #fff;
    :deep(.el-pagination) {
      .btn-prev,
      .btn-next {
        display: none;
@@ -2455,4 +2508,3 @@
  }
}
</style>
```