无人机管理后台前端(已迁走)
张含笑
2025-12-09 5808f76456ca0d40de5074f132b73a5a488e3e13
src/views/tickets/ticket.vue
@@ -27,6 +27,9 @@
                <el-col :span="5">
                  <el-form-item label="选择日期:">
                  <el-date-picker
                   clearable
                      @clear="handleKeyWords"
                       @change="handleSearch"
                    v-model="filters.dateRange"
                    type="daterange"
                    class="filter-item"
@@ -82,7 +85,7 @@
                  />
                  </el-form-item>
                </el-col>
                <el-col :span="4">
                <el-col :span="4" v-if="activeTab === 'completed'">
                  <el-form-item label="复核状态:">
                  <el-select
                    v-model="filters.isReview"
@@ -128,7 +131,7 @@
              >
                批量审核
              </el-button>
              <el-button
                v-if="permissionList.exportBtn"
                type="success"
@@ -146,7 +149,7 @@
           class="ztzf-public-general-el-table custom-header"
          ref="elTable"
          :data="tableData"
          v-loading="loading"
          v-loading="loading"
          @selection-change="handleSelectionChange"
          border
          style="width: 100%"
@@ -168,40 +171,40 @@
              </el-tooltip-copy>
            </template>
          </el-table-column>
          <el-table-column prop="department" label="所属部门" show-overflow-tooltip />
          <el-table-column prop="startTime" label="发起任务时间" width="160" show-overflow-tooltip />
          <el-table-column prop="aiType" label="关联算法" show-overflow-tooltip />
          <el-table-column prop="type" label="工单类型" width="110" show-overflow-tooltip>
            <template #default="{ row }">
              {{ getTypeLabel(row.type) }}
            </template>
          </el-table-column>
          <el-table-column prop="content" label="工单内容" width="132" show-overflow-tooltip>
            <template #default="{ row }">
              {{ row.address || row.content }}
            </template>
          </el-table-column>
          <el-table-column prop="creator" label="创建人" width="120" show-overflow-tooltip />
          <el-table-column prop="handler" label="处理人" width="120" show-overflow-tooltip />
          <el-table-column
            v-if="['all', 'completed', 'myTickets'].includes(activeTab)"
            label="复核状态"
            prop="isReview"
          <el-table-column
            v-if="['all', 'completed', 'myTickets'].includes(activeTab)"
            label="复核状态"
            prop="isReview"
            width="90"
          >
            <template #default="{ row }">
              <span>{{ showIsReviewText(row) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="工单状态" prop="status" width="90">
            <template #default="{ row }">
              <span :style="getStatusTagType(row.status) ? 'color:' + getStatusTagType(row.status) : ''">
@@ -209,7 +212,7 @@
              </span>
            </template>
          </el-table-column>
          <!-- 操作列 -->
          <el-table-column label="操作" width="200" align="center">
            <template #default="{ row }">
@@ -219,15 +222,15 @@
                  删除
                </el-button>
              </template>
              <template v-else>
                <el-button type="text" icon="el-icon-view" @click="handleViewDetail(row)">详情</el-button>
              </template>
              <template v-if="row.status === 4 && activeTab === 'completed'">
              <!-- <template v-if="row.status === 4 && !isProd">
                <el-button type="text" icon="el-icon-download" @click="exportTheTick(row)">导出</el-button>
              </template>
              </template> -->
              <template v-if="permission.tickets_repeat_review">
                <el-button
                  v-if="row.status === 4 && row.isReview !== 1"
@@ -240,9 +243,19 @@
              </template>
            </template>
            </el-table-column>
          <template #empty>
            <el-empty
              class="custom-empty"
              :image-size="100"
            >
              <template #description>
                <span class="custom-text">暂无数据</span>
              </template>
            </el-empty>
          </template>
          </el-table>
          </div>
           <div  class="pagination">
           <div  class="pagination" v-if="tableData.length > 0">
             <el-pagination
            class="table-pagination"
            v-model:current-page="page.currentPage"
@@ -308,6 +321,7 @@
      v-model="reviewDialogVisible"
      title="批量审核"
      width="1100"
       align-center
      append-to-body
      class="ztzf-dialog-mange"
      custom-class="review-dialog"
@@ -421,6 +435,7 @@
import CreateTicketDialog from '@/views/tickets/ticketComponent/CreateTicketDialog.vue';
import TicketDetailDialog from '@/views/tickets/ticketComponent/TicketDetailDialog.vue';
const { envName } = getBaseConfig();
const isProd = import.meta.env.VITE_APP_ENV === 'production'
const route = useRoute()
const router = useRouter()
const store = useStore()
@@ -484,7 +499,6 @@
})
const dispatchDialogVisible = ref(false)
const stepInfos = ref([])
const fixedStatuses = ref(['2', '0', '3', '4'])
const userNameToIdMap = ref({})
const workType = ref(0)
const selections = ref([])
@@ -506,7 +520,7 @@
const checkedKeys = ref([])
const inputMapShowDefaultCenter = ref(null)
const userInfo = computed(() => store.state.user.userInfo)
const permission = computed(() => store.state.user.permission);
const permission = computed(() => store.state.user.permission);
// 计算属性
const firstRowData = computed(() => {
@@ -517,7 +531,7 @@
  const tabPending = permission.value?.tickets_tab_pending === true//待审核
  const tabMyTickets = permission.value?.tickets_tab_mytickets === true  //我的工单
  const tabALL = permission.value?.tickets_allWorkOrders === true //全部工单
  const tabInProgress= permission.value?.tickets_inProgress === true //处理中
  const tabInProgress= permission.value?.tickets_inProgress === true //处理中
  const tabProcessing= permission.value?.tickets_pending === true //待处理
  const tabCompleted= permission.value?.tickets_wasDone === true //已完成
  return tabs.value
@@ -547,14 +561,14 @@
    addBtn: validData(permission.value.tickets_add, false),
    delBtn: validData(permission.value.tickets_delete, false),
    exportBtn: validData(permission.value.tickets_export, false),
    reviewBtn: validData(permission.value.tickets_review, false),
    reviewBtn: validData(permission.value.tickets_review_btn, false),
  }
})
// 计算默认激活的标签(无全部工单时优先激活待审核)
const defaultActiveTab = computed(() => {
  const hasAllTab = filteredTabs.value.some(tab => tab.name === 'all')
  const hasPendingTab = filteredTabs.value.some(tab => tab.name === 'pending')
  // 如果没有全部工单权限,但有待审核权限,则默认显示待审核
  if (!hasAllTab && hasPendingTab) {
    return 'pending'
@@ -576,14 +590,6 @@
    .map(tab => String(tab.value));
});
const stepStatusList = computed(() => {
// “我发起的工单”tab用默认流程,其它tab用接口返回的stepInfos
  // if (activeTab.value === 'myTickets') {
  //   if (workType.value === 1) {
  //     return ['3', '4']
  //   }
  //   return fixedStatuses.value
  // }
   // 其它tab直接用接口返回的stepInfos
  return stepInfos.value.map(step => String(step.status))
})
const showIsReviewText = computed(() => (row) => {
@@ -630,7 +636,7 @@
      user_id: currentTab?.name === 'myTickets' ? userInfo.value.user_id : undefined,
      is_review: filters.isReview === '' ? undefined : filters.isReview,
      source: 1,
      status_list: statusListVal
      status_list:currentTab?.name !== 'myTickets'?  statusListVal : undefined
    }
    const response = await getList(params)
@@ -714,6 +720,7 @@
        }
      })
      dataList.value = filteredData
    }
  })
}
@@ -759,16 +766,16 @@
// 受理并派发
function handleApproveAndDispatch(detail) {
if(!detail.orderName){
   ElMessage.error('请填写工单名称');
   ElMessage.warning('请填写工单名称');
      return;
}
if(!detail.aiType){
   ElMessage.error('请选择关联算法');
   ElMessage.warning('请选择关联算法');
      return;
}
if(!detail.content){
   ElMessage.error('请填写工单内容');
   ElMessage.warning('请填写工单内容');
      return;
}
  currentDetail.value = detail
@@ -828,7 +835,7 @@
    })) || []
    algorithms2.value = _.cloneDeep(algorithms.value)
    userNameToIdMap.value = {}
    dept_data.forEach(dept => {
      (dept.user_data || []).forEach(user => {
@@ -867,7 +874,7 @@
function mapStatus(status) {
  const statusTextMap = {
    2: '待审核',
    0: '待处理',
    3: '处理中',
@@ -893,8 +900,11 @@
  }
  try {
    const response = await getstatusCount(params)
    const statusCount = response.data.data || {}
    const totalCount = Object.values(statusCount).reduce((sum, count) => sum + (count || 0), 0)
    const statusCount = response.data.data || {}
     const totalCount = Object.entries(statusCount).reduce((sum, [key, count]) => {
         if (key === '6') return sum
         return sum + (count || 0)
      }, 0)
    tabs.value.forEach(tab => {
      if (tab.name === 'all') {
        tab.count = totalCount
@@ -972,66 +982,24 @@
}
async function getStepInfoData(val) {
  try {
    const orderNum = val
    const stepResponse = await getStepInfo(orderNum)
    const steps = Array.isArray(stepResponse.data.data)
      ? stepResponse.data.data
      : stepResponse.data.data?.steps || []
    console.log('steps',steps);
    const finishedStep = steps.find(s => String(s.status) === '4')
    totalTime.value = finishedStep && finishedStep.total_time ? finishedStep.total_time : ''
    // if (activeTab.value !== 'myTickets') {
    //   stepInfos.value = steps.map(step => ({
    //     status: String(step.status),
    //     name: step.name,
    //     time: step.time,
    //     create_time: step.create_time,
    //   }))
    // } else {
      // const statusArr = workType.value === 1 ? ['3', '4'] : fixedStatuses.value
      // stepInfos.value = statusArr.map(status => {
      //   const step = steps.find(s => String(s.status) === String(status))
      //   return {
      //     status,
      //     name: step ? step.name : '',
      //     time: step ? step.time : null,
      //     create_time: step ? step.create_time : null,
      //   }
      // })
    //     stepInfos.value = steps.map(step => ({
    //     status: String(step.status),
    //     name: step.name,
    //     time: step.time,
    //     create_time: step.create_time,
    //   }))
    // }
      stepInfos.value = steps.map(step => ({
        status: String(step.status),
        name: step.name,
        time: step.time,
        create_time: step.create_time,
      }))
    return true
  } catch (error) {
    console.error('获取步骤信息失败:', error)
    if (activeTab.value === 'myTickets') {
      const statusArr = workType.value === 1 ? ['3', '4'] : fixedStatuses.value
      stepInfos.value = statusArr.map(status => ({
        status,
        name: status === row.status ? row.handler || '未分配' : '未处理',
        time: status === row.status ? row.startTime || '未知时间' : null,
      }))
    } else {
      stepInfos.value = []
    }
    return false
  }
}
// 详情
async function handleViewDetail(row) {
console.log('row',row);
  currentIndex.value = tableData.value.findIndex(item => item.id === row.id)
  workType.value = row.work_type !== undefined ? Number(row.work_type) : 0
  const detailData = {
@@ -1045,7 +1013,7 @@
  await getStepInfoData(row.orderNumber)
  currentDetail.value.status = row.status
  currentDetail.value = {
    ...detailData,
    showQR: false,
@@ -1090,6 +1058,7 @@
    if (exportData.length === 0) {
      console.warn('没有数据可供导出')
      ElMessage.warning('没有数据可供导出');
      return
    }
@@ -1425,9 +1394,11 @@
// 生命周期
onMounted(() => {
  inputMapShowDefaultCenter.value = null
  loadAMapScripts()
  fetchDropdownData()
  getAlgorithmList()
 // 设置默认activeTab
  activeTab.value = defaultActiveTab.value
 const href = window.location.href;
@@ -1478,7 +1449,7 @@
        }
      })
    }
    if (tab) {
      const isTabValid = filteredTabs.value.some(t => t.name === tab)
      if (isTabValid) {
@@ -1511,9 +1482,15 @@
  flex-direction: column;
}
.dataTable {
 height: 0;
    flex: 1;
    overflow: auto;
    // height: 0;
    // flex: 1;
     height: calc(100vh - 365px);
     :deep(.el-scrollbar__view) {
      height: 100%;
    }
    :deep(.el-table--fit,.el-scrollbar__view) {
      height: 100%;
    }
}
.pagination {
  display: flex;
@@ -1525,7 +1502,7 @@
  right: 0;
  padding: 0 30px;
  z-index: 1000;
  z-index: 1000;
}
:deep(.custom-header th.el-table__cell) {
  color: rgba(0, 0, 0, 0.85);
@@ -1560,16 +1537,20 @@
  :deep(.el-table__header-wrapper) {
    background-color: #f5f7fa;
  }
  :deep(.el-table th) {
    background-color: #f5f7fa;
    color: #606266;
    font-weight: 600;
  }
  :deep(.el-table--border) {
    border: 1px solid #ebeef5;
  }
  :deep(.el-table__empty-block) {
    height: calc(100vh - 400px) !important;
  }
}
::v-deep(.el-tabs) {
  height: 100%;