zengy 1 mesiac pred
rodič
commit
b008e0da17

+ 0 - 20
src/api/pipeNetwork/basic.js

@@ -183,29 +183,9 @@ export function verifyManholeCase(data) {
   return request({ url: '/manhole/caseInfo/verifyCaseInfo', method: 'post', data })
 }
 
-export function getManholeWorkOrderPage(data) {
-  return request({ url: '/manhole/workOrder/findByPage', method: 'post', data })
-}
-
-export function getManholeWorkOrderProcessingPage(data) {
-  return request({ url: '/manhole/workOrder/findProcessingPage', method: 'post', data })
-}
-
-export function getManholeWorkOrderFinishedPage(data) {
-  return request({ url: '/manhole/workOrder/findFinishedPage', method: 'post', data })
-}
-
-export function getManholeWorkOrderDetail(id) {
-  return request({ url: '/manhole/workOrder/getById/' + id, method: 'get' })
-}
-
 export function addManholeWorkOrder(data) {
   return request({ url: '/manhole/workOrder/addWorkOrder', method: 'post', data })
 }
-
-export function operManholeWorkOrder(data) {
-  return request({ url: '/manhole/workOrder/operWorkOrder', method: 'post', data })
-}
 // 修改设备运维状态(currentStatus:1-在用 2-闲置 3-维修 4-报废 5-待入库)
 export function updateManholeDeviceStatus(data) {
   return request({ url: '/manhole/device/updateDeviceStatus', method: 'post', data })

+ 1 - 1
src/api/pipeNetwork/earlyWarning.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 /**
  * 设备预警管理 API
  * 数据源:early_warning 预警体系(/warning/*)
- * 处置人分配复用工单接口:addManholeWorkOrder / operManholeWorkOrder(basic.js)
+ * 处置人分配复用新增工单接口:addManholeWorkOrder(basic.js)
  */
 
 // 预警综合搜索(名称/编号/类型/级别/状态/位置/发布人/权属单位/时间范围)

+ 0 - 78
src/api/pipeNetwork/ops/pworkOrder.js

@@ -1,78 +0,0 @@
-import request from '@/utils/request'
-
-const BASE_URL = '/api/ops/pworkOrder'
-
-/** 分页查询工单列表 */
-export function listPworkOrder(params) {
-  return request({ url: BASE_URL + '/findByPage', method: 'get', params })
-}
-
-/** 查询工单详情(含操作日志) */
-export function getPworkOrder(orderId) {
-  return request({ url: `${BASE_URL}/getById/${orderId}`, method: 'get' })
-}
-
-/** 查询工单操作日志 */
-export function listPworkOrderLog(orderId) {
-  return request({ url: `${BASE_URL}/logs/${orderId}`, method: 'get' })
-}
-
-/** 新增故障工单 */
-export function addPworkOrder(data) {
-  return request({ url: BASE_URL + '/add', method: 'post', data })
-}
-
-/** 派单(待派单 → 待接单) */
-export function dispatchPworkOrder(data) {
-  return request({ url: BASE_URL + '/dispatch', method: 'put', data })
-}
-
-/** 核查接单(待接单 → 已接单) */
-export function acceptPworkOrder(data) {
-  return request({ url: BASE_URL + '/accept', method: 'put', data })
-}
-
-/** 工单处置(已接单/处理中/延期中 → 处理中) */
-export function processPworkOrder(data) {
-  return request({ url: BASE_URL + '/process', method: 'put', data })
-}
-
-/** 提交验收(处理中/延期中 → 待验收) */
-export function submitVerifyPworkOrder(data) {
-  return request({ url: BASE_URL + '/submitVerify', method: 'put', data })
-}
-
-/** 工单验收(待验收 → 已结案 / 处理中) */
-export function verifyPworkOrder(data) {
-  return request({ url: BASE_URL + '/verify', method: 'put', data })
-}
-
-/** 取消工单 */
-export function cancelPworkOrder(data) {
-  return request({ url: BASE_URL + '/cancel', method: 'put', data })
-}
-
-/** 申请延期 */
-export function applyDelayPworkOrder(data) {
-  return request({ url: BASE_URL + '/delay/apply', method: 'put', data })
-}
-
-/** 延期审核 */
-export function auditDelayPworkOrder(data) {
-  return request({ url: BASE_URL + '/delay/audit', method: 'put', data })
-}
-
-/** 删除工单(仅已取消) */
-export function delPworkOrder(orderId) {
-  return request({ url: `${BASE_URL}/deleteById/${orderId}`, method: 'delete' })
-}
-
-/** 可指派部门树 */
-export function pworkOrderDeptTree() {
-  return request({ url: BASE_URL + '/assignableDeptTree', method: 'get' })
-}
-
-/** 可指派用户 */
-export function pworkOrderUsers(deptId) {
-  return request({ url: BASE_URL + '/assignableUsers', method: 'get', params: { deptId } })
-}

+ 98 - 0
src/api/pipeNetwork/ops/workOrder.js

@@ -0,0 +1,98 @@
+import request from '@/utils/request'
+
+const BASE_URL = '/api/ops/workOrder'
+
+/** 分页查询工单列表 */
+export function listWorkOrder(params) {
+  return request({ url: BASE_URL, method: 'get', params })
+}
+
+/**
+ * 按状态统计工单数量(状态筛选条使用)。
+ * 与列表同条件,但需去掉 orderStatus,否则点击某状态后其它状态计数会变 0。
+ */
+export function workOrderStatusCount(params) {
+  return request({ url: `${BASE_URL}/statusCount`, method: 'get', params })
+}
+
+/** 查询工单详情(含操作日志) */
+export function getWorkOrder(orderId) {
+  return request({ url: `${BASE_URL}/${orderId}`, method: 'get' })
+}
+
+/** 查询工单操作日志 */
+export function listWorkOrderLog(orderId) {
+  return request({ url: `${BASE_URL}/${orderId}/logs`, method: 'get' })
+}
+
+/** 新增故障工单 */
+export function addWorkOrder(data) {
+  return request({ url: BASE_URL, method: 'post', data })
+}
+
+/**
+ * 状态流转类操作:工单ID 走 REST 路径变量,请求体只保留本次操作的业务参数。
+ * @param {string|number} orderId 工单ID
+ * @param {string} action 子资源动作(dispatch / accept / process ...)
+ * @param {object} data 业务参数(其中的 orderId 会被剥离,避免与路径重复)
+ */
+function flow(orderId, action, data) {
+  const body = { ...(data || {}) }
+  delete body.orderId
+  return request({ url: `${BASE_URL}/${orderId}/${action}`, method: 'put', data: body })
+}
+
+/** 派单(待派单 → 待接单) */
+export function dispatchWorkOrder(data = {}) {
+  return flow(data.orderId, 'dispatch', data)
+}
+
+/** 核查接单(待接单 → 已接单) */
+export function acceptWorkOrder(data = {}) {
+  return flow(data.orderId, 'accept', data)
+}
+
+/** 工单处置(已接单/处理中/延期中 → 处理中) */
+export function processWorkOrder(data = {}) {
+  return flow(data.orderId, 'process', data)
+}
+
+/** 提交验收(处理中/延期中 → 待验收) */
+export function submitVerifyWorkOrder(data = {}) {
+  return flow(data.orderId, 'submitVerify', data)
+}
+
+/** 工单验收(待验收 → 已结案 / 处理中) */
+export function verifyWorkOrder(data = {}) {
+  return flow(data.orderId, 'verify', data)
+}
+
+/** 取消工单 */
+export function cancelWorkOrder(data = {}) {
+  return flow(data.orderId, 'cancel', data)
+}
+
+/** 申请延期 */
+export function applyDelayWorkOrder(data = {}) {
+  return flow(data.orderId, 'delay/apply', data)
+}
+
+/** 延期审核 */
+export function auditDelayWorkOrder(data = {}) {
+  return flow(data.orderId, 'delay/audit', data)
+}
+
+/** 删除工单(仅已取消) */
+export function delWorkOrder(orderId) {
+  return request({ url: `${BASE_URL}/${orderId}`, method: 'delete' })
+}
+
+/** 可指派部门树 */
+export function workOrderDeptTree() {
+  return request({ url: `${BASE_URL}/assignable/deptTree`, method: 'get' })
+}
+
+/** 可指派用户 */
+export function workOrderUsers(deptId) {
+  return request({ url: `${BASE_URL}/assignable/users`, method: 'get', params: { deptId } })
+}

+ 0 - 348
src/views/subSystem/manholeCover/caseHandling/closeWorkOrder.vue

@@ -1,348 +0,0 @@
-<!--办结工单-->
-<template>
-  <div class="min-h-screen bg-[#f0f2f6] p-5">
-    <div class="mb-5 flex flex-wrap items-center justify-between gap-3 rounded-2xl bg-white px-6 py-4 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
-      <div class="flex items-center gap-3">
-        <el-icon><CircleCheck /></el-icon>
-        <span class="text-[20px] font-600 text-[#1f2d3d]">已办结工单</span>
-        <el-tag type="success" effect="dark">已完成 {{ completedOrdersCount }}</el-tag>
-      </div>
-      <div class="flex flex-wrap items-center gap-3">
-        <el-input
-          v-model="searchOrderNo"
-          placeholder="工单编号"
-          clearable
-          :prefix-icon="Search"
-          class="w-[140px]"
-          @keyup.enter="loadOrders"
-        />
-        <el-input
-          v-model="searchCaseNo"
-          placeholder="案件编号"
-          clearable
-          :prefix-icon="Search"
-          class="w-[140px]"
-          @keyup.enter="loadOrders"
-        />
-        <el-select v-model="orderLevelFilter" placeholder="优先级" clearable class="w-[120px]">
-          <el-option label="紧急" :value="0" />
-          <el-option label="一般" :value="1" />
-          <el-option label="低" :value="2" />
-        </el-select>
-        <el-date-picker
-          v-model="dateRange"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="办结开始"
-          end-placeholder="办结结束"
-          value-format="YYYY-MM-DD"
-          class="w-[280px]"
-        />
-        <el-button type="primary" :icon="Refresh" @click="loadOrders">刷新</el-button>
-      </div>
-    </div>
-
-    <div class="mb-5 flex flex-wrap gap-4">
-      <div
-        class="min-w-[110px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="timeFilter === 'week' ? 'border-2 border-[#67c23a] bg-[#f0f9f0]' : 'border-2 border-transparent'"
-        @click="setTimeFilter('week')"
-      >
-        <div class="text-[28px] font-bold text-[#2c3e50]">{{ weeklyCompleted }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">本周办结</div>
-      </div>
-      <div
-        class="min-w-[110px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="timeFilter === 'month' ? 'border-2 border-[#67c23a] bg-[#f0f9f0]' : 'border-2 border-transparent'"
-        @click="setTimeFilter('month')"
-      >
-        <div class="text-[28px] font-bold text-[#2c3e50]">{{ monthlyCompleted }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">本月办结</div>
-      </div>
-      <div
-        class="min-w-[110px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="timeFilter === 'all' ? 'border-2 border-[#67c23a] bg-[#f0f9f0]' : 'border-2 border-transparent'"
-        @click="setTimeFilter('all')"
-      >
-        <div class="text-[28px] font-bold text-[#2c3e50]">{{ completedOrdersCount }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">全部办结</div>
-      </div>
-    </div>
-
-    <div class="rounded-2xl bg-white p-4 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
-      <el-table :data="paginatedOrders" stripe border class="w-full" row-class-name="cursor-pointer" v-loading="loading" @row-click="handleRowClick">
-        <el-table-column type="index" label="序号" width="55" align="center" />
-        <el-table-column prop="orderNo" label="工单编号" min-width="170" />
-        <el-table-column prop="caseNo" label="关联案件编号" min-width="170" />
-        <el-table-column prop="orderLevelText" label="优先级" width="100" align="center">
-          <template #default="{ row }">
-            <el-tag :type="row.orderLevelTag" size="small">{{ row.orderLevelText }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="orderDesc" label="问题描述" min-width="220" show-overflow-tooltip />
-        <el-table-column prop="deviceCode" label="设备编号" width="150" />
-        <el-table-column prop="realFinishTimeText" label="办结时间" width="170" />
-        <el-table-column label="操作" width="120" fixed="right" align="center">
-          <template #default="{ row }">
-            <el-button link type="primary" size="small" @click.stop="viewDetail(row)">查看详情</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <div class="mt-4 flex justify-end border-t border-[#e9ecef] pt-3">
-        <el-pagination
-          background
-          layout="total, sizes, prev, pager, next, jumper"
-          :total="filteredOrders.length"
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[10, 20, 50]"
-        />
-      </div>
-    </div>
-
-    <el-drawer v-model="detailDrawerVisible" :title="`工单详情 - ${currentOrder?.orderNo || ''}`" size="560px" direction="rtl" class="detail-drawer">
-      <div v-if="currentOrder" class="p-2" v-loading="detailLoading">
-        <el-descriptions :column="1" border>
-          <el-descriptions-item label="工单编号">{{ currentOrder.orderNo }}</el-descriptions-item>
-          <el-descriptions-item label="关联案件编号">{{ currentOrder.caseNo || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="设备编号">{{ currentOrder.deviceCode || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="工单状态">
-            <el-tag :type="currentOrder.orderStatusTag">{{ currentOrder.orderStatusText }}</el-tag>
-          </el-descriptions-item>
-          <el-descriptions-item label="优先级">
-            <el-tag :type="currentOrder.orderLevelTag">{{ currentOrder.orderLevelText }}</el-tag>
-          </el-descriptions-item>
-          <el-descriptions-item label="问题描述">{{ currentOrder.orderDesc || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="设备类别">{{ currentOrder.equipmentTypeName || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="派单时间">{{ currentOrder.dispatchTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="创建时间">{{ currentOrder.createTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="计划完成时间">{{ currentOrder.planFinishTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="延期原因">{{ currentOrder.delayedReason || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="延期截止时间">{{ currentOrder.delayedDeadlineText }}</el-descriptions-item>
-          <el-descriptions-item label="验收时间">{{ currentOrder.verifyTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="办结时间">{{ currentOrder.realFinishTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="处置结果">{{ currentOrder.repairResult || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="设备运维状态">{{ currentOrder.currentStatusText }}</el-descriptions-item>
-          <el-descriptions-item label="设备在线状态">{{ currentOrder.onlineStatusText }}</el-descriptions-item>
-          <el-descriptions-item label="设备报警状态">{{ currentOrder.alarmStatusText }}</el-descriptions-item>
-        </el-descriptions>
-
-        <div class="mt-4">
-          <div class="mb-3 mt-5 text-[15px] font-600 text-[#2c3e50]">办理经过</div>
-          <el-timeline v-if="currentOrder.workOrderLogList?.length">
-            <el-timeline-item
-              v-for="log in currentOrder.workOrderLogList"
-              :key="log.logId"
-              :timestamp="formatDateTime(log.operTime)"
-              :type="getLogType(log.operType)"
-            >
-              {{ log.operDesc }}
-              <span v-if="log.operUserName" class="ml-3 text-[12px] text-[#909399]">操作人: {{ log.operUserName }}</span>
-            </el-timeline-item>
-          </el-timeline>
-          <el-empty v-else description="暂无办理日志" :image-size="80" />
-        </div>
-      </div>
-    </el-drawer>
-  </div>
-</template>
-
-<script setup>
-import {computed, onMounted, ref} from 'vue'
-import {CircleCheck, Refresh, Search} from '@element-plus/icons-vue'
-import {ElMessage} from 'element-plus'
-import {getManholeWorkOrderDetail, getManholeWorkOrderFinishedPage} from '@/api/pipeNetwork/basic'
-
-const orders = ref([])
-const loading = ref(false)
-const detailLoading = ref(false)
-const searchOrderNo = ref('')
-const searchCaseNo = ref('')
-const orderLevelFilter = ref('')
-const dateRange = ref([])
-const timeFilter = ref('all')
-const currentPage = ref(1)
-const pageSize = ref(10)
-const detailDrawerVisible = ref(false)
-const currentOrder = ref(null)
-
-function formatDateTime(value) {
-  if (!value) return '—'
-  return String(value).replace('T', ' ')
-}
-
-function getOrderLevelMeta(level) {
-  const map = {
-    0: { text: '紧急', tag: 'danger' },
-    1: { text: '一般', tag: 'warning' },
-    2: { text: '低', tag: 'info' }
-  }
-  return map[Number(level)] || { text: '—', tag: 'info' }
-}
-
-
-function getOrderStatusMeta(status) {
-  const map = {
-    5: { text: '已结案', tag: 'success' },
-    6: { text: '延期中', tag: 'warning' },
-    7: { text: '已取消', tag: 'info' }
-  }
-  return map[Number(status)] || { text: '—', tag: 'info' }
-}
-
-function getOnlineStatusText(status) {
-  const map = {
-    0: '离线',
-    1: '在线'
-  }
-  return map[Number(status)] || '—'
-}
-
-function getAlarmStatusText(status) {
-  const map = {
-    0: '正常',
-    1: '报警'
-  }
-  return map[Number(status)] || '—'
-}
-
-function getCurrentStatusText(status) {
-  const map = {
-    1: '在用',
-    2: '闲置',
-    3: '维修',
-    4: '报废',
-    5: '待入库'
-  }
-  return map[Number(status)] || '—'
-}
-
-function normalizeOrder(item) {
-  const levelMeta = getOrderLevelMeta(item.orderLevel)
-  const statusMeta = getOrderStatusMeta(item.orderStatus)
-  return {
-    ...item,
-    orderLevelText: levelMeta.text,
-    orderLevelTag: levelMeta.tag,
-    orderStatusText: statusMeta.text,
-    orderStatusTag: statusMeta.tag,
-    createTimeText: formatDateTime(item.createTime),
-    dispatchTimeText: formatDateTime(item.dispatchTime),
-    planFinishTimeText: formatDateTime(item.planFinishTime),
-    delayedDeadlineText: formatDateTime(item.delayedDeadline),
-    verifyTimeText: formatDateTime(item.verifyTime),
-    realFinishTimeText: formatDateTime(item.realFinishTime),
-    updateTimeText: formatDateTime(item.updateTime),
-    currentStatusText: getCurrentStatusText(item.equipmentStatus?.currentStatus),
-    onlineStatusText: getOnlineStatusText(item.equipmentStatus?.onlineStatus),
-    alarmStatusText: getAlarmStatusText(item.equipmentStatus?.alarmStatus),
-    statusUpdateTimeText: formatDateTime(item.equipmentStatus?.statusUpdateTime)
-  }
-}
-
-function isWithinRecentDays(value, days) {
-  if (!value) return false
-  const time = new Date(value).getTime()
-  if (Number.isNaN(time)) return false
-  return Date.now() - time <= days * 24 * 3600000
-}
-
-const filteredOrders = computed(() => {
-  if (timeFilter.value === 'week') {
-    return orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 7))
-  }
-  if (timeFilter.value === 'month') {
-    return orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 30))
-  }
-  return orders.value
-})
-
-const paginatedOrders = computed(() => {
-  const start = (currentPage.value - 1) * pageSize.value
-  return filteredOrders.value.slice(start, start + pageSize.value)
-})
-
-const completedOrdersCount = computed(() => orders.value.length)
-const weeklyCompleted = computed(() => orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 7)).length)
-const monthlyCompleted = computed(() => orders.value.filter(item => isWithinRecentDays(item.realFinishTime, 30)).length)
-
-async function loadOrders() {
-  loading.value = true
-  try {
-    const orderNo = searchOrderNo.value.trim()
-    const caseNo = searchCaseNo.value.trim()
-    const payload = {
-      pageNum: 1,
-      pageSize: 200,
-      orderLevel: orderLevelFilter.value || undefined,
-      orderNo: orderNo || undefined,
-      caseNo: caseNo || undefined,
-      startTime: dateRange.value?.[0] ? `${dateRange.value[0]} 00:00:00` : undefined,
-      endTime: dateRange.value?.[1] ? `${dateRange.value[1]} 23:59:59` : undefined
-    }
-    const res = await getManholeWorkOrderFinishedPage(payload)
-    const records = Array.isArray(res?.data?.records) ? res.data.records : []
-    orders.value = records
-      .filter(item => [6, 7].includes(Number(item.orderStatus)))
-      .map(normalizeOrder)
-    currentPage.value = 1
-    if (currentOrder.value) {
-      const matched = orders.value.find(item => item.orderId === currentOrder.value.orderId)
-      if (matched) {
-        await viewDetail(matched)
-      } else {
-        currentOrder.value = null
-        detailDrawerVisible.value = false
-      }
-    }
-  } catch (error) {
-    orders.value = []
-    currentOrder.value = null
-    ElMessage.error('办结工单加载失败')
-  } finally {
-    loading.value = false
-  }
-}
-
-async function viewDetail(order) {
-  detailLoading.value = true
-  detailDrawerVisible.value = true
-  try {
-    const res = await getManholeWorkOrderDetail(order.orderId)
-    currentOrder.value = normalizeOrder(res?.data || order)
-  } catch (error) {
-    currentOrder.value = order
-    ElMessage.error('工单详情加载失败')
-  } finally {
-    detailLoading.value = false
-  }
-}
-
-function handleRowClick(row) {
-  viewDetail(row)
-}
-
-function setTimeFilter(filter) {
-  timeFilter.value = filter
-  currentPage.value = 1
-}
-
-function getLogType(operType) {
-  const map = {
-    2: 'primary',
-    3: 'warning',
-    4: 'primary',
-    5: 'warning',
-    6: 'success',
-    7: 'danger',
-    8: 'warning',
-    9: 'warning'
-  }
-  return map[Number(operType)] || 'info'
-}
-
-onMounted(() => {
-  loadOrders()
-})
-</script>

+ 0 - 504
src/views/subSystem/manholeCover/caseHandling/handlingWorkO.vue

@@ -1,504 +0,0 @@
-<!--经办工单-->
-<template>
-  <div class="min-h-screen bg-[#f0f2f6] p-5">
-    <div class="mb-5 flex flex-wrap items-center justify-between gap-3 rounded-2xl bg-white px-6 py-4 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
-      <div class="flex items-center gap-3">
-        <el-icon><List /></el-icon>
-        <span class="text-[20px] font-600 text-[#1f2d3d]">经办工单</span>
-        <el-tag type="danger" effect="dark" v-if="pendingOrdersCount > 0">待处理 {{ pendingOrdersCount }}</el-tag>
-      </div>
-      <div class="flex flex-wrap items-center gap-3">
-        <el-input
-          v-model="searchKeyword"
-          placeholder="搜索工单编号/案件编号"
-          clearable
-          :prefix-icon="Search"
-          class="w-[260px]"
-          @keyup.enter="loadOrders"
-        />
-        <el-select v-model="orderLevelFilter" placeholder="优先级" clearable class="w-[120px]">
-          <el-option label="紧急" :value="0" />
-          <el-option label="一般" :value="1" />
-          <el-option label="低" :value="2" />
-        </el-select>
-        <el-button type="primary" :icon="Refresh" @click="loadOrders">刷新</el-button>
-      </div>
-    </div>
-
-    <div class="mb-5 flex flex-wrap gap-4">
-      <div
-        class="min-w-[100px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="statusFilter === '' ? 'border-2 border-[#409eff] bg-[#ecf5ff]' : 'border-2 border-transparent'"
-        @click="setStatusFilter('')"
-      >
-        <div class="text-[28px] font-bold">{{ totalOrders }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">全部工单</div>
-      </div>
-      <div
-        class="min-w-[100px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="statusFilter === 'pending' ? 'border-2 border-[#409eff] bg-[#ecf5ff]' : 'border-2 border-transparent'"
-        @click="setStatusFilter('pending')"
-      >
-        <div class="text-[28px] font-bold text-[#f56c6c]">{{ pendingOrdersCount }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">待处理</div>
-      </div>
-      <div
-        class="min-w-[100px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="statusFilter === 'processing' ? 'border-2 border-[#409eff] bg-[#ecf5ff]' : 'border-2 border-transparent'"
-        @click="setStatusFilter('processing')"
-      >
-        <div class="text-[28px] font-bold text-[#e6a23c]">{{ processingOrdersCount }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">处理中</div>
-      </div>
-      <div
-        class="min-w-[100px] cursor-pointer rounded-xl bg-white px-6 py-3 text-center shadow-[0_1px_4px_rgba(0,0,0,0.05)] transition-all duration-200 hover:-translate-y-[2px] hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)]"
-        :class="statusFilter === 'overdue' ? 'border-2 border-[#409eff] bg-[#ecf5ff]' : 'border-2 border-transparent'"
-        @click="setStatusFilter('overdue')"
-      >
-        <div class="text-[28px] font-bold text-[#f56c6c]">{{ overdueCount }}</div>
-        <div class="mt-1 text-[13px] text-[#606266]">已逾期</div>
-      </div>
-    </div>
-
-    <div class="rounded-2xl bg-white p-4 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
-      <el-table :data="paginatedOrders" stripe border class="w-full" row-class-name="cursor-pointer" v-loading="loading" @row-click="handleRowClick">
-        <el-table-column type="index" label="序号" width="55" align="center" />
-        <el-table-column prop="orderNo" label="工单编号" min-width="170" />
-        <el-table-column prop="caseNo" label="关联案件编号" min-width="170" />
-        <el-table-column prop="orderLevelText" label="优先级" width="100" align="center">
-          <template #default="{ row }">
-            <el-tag :type="row.orderLevelTag" size="small">{{ row.orderLevelText }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="orderDesc" label="问题描述" min-width="220" show-overflow-tooltip />
-        <el-table-column prop="deviceCode" label="设备编号" width="150" />
-        <el-table-column prop="orderStatusText" label="工单状态" width="110" align="center">
-          <template #default="{ row }">
-            <el-tag :type="row.orderStatusTag" size="small">{{ row.orderStatusText }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="createTimeText" label="创建时间" width="170" />
-        <el-table-column prop="planFinishTimeText" label="计划完成时间" width="170" />
-        <el-table-column label="操作" width="150" fixed="right" align="center">
-          <template #default="{ row }">
-            <el-button link type="primary" size="small" @click.stop="viewDetail(row)">查看详情</el-button>
-            <el-button v-if="canAcceptOrder(row)" link type="warning" size="small" @click.stop="acceptOrder(row)">接单</el-button>
-            <el-button v-else-if="canStartRepair(row)" link type="success" size="small" @click.stop="startRepair(row)">开始维修</el-button>
-            <el-button v-else-if="canSubmitVerify(row)" link type="warning" size="small" @click.stop="submitVerify(row)">提交验收</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <div class="mt-4 flex justify-end border-t border-[#e9ecef] pt-3">
-        <el-pagination
-          background
-          layout="total, sizes, prev, pager, next, jumper"
-          :total="filteredOrders.length"
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[10, 20, 50]"
-        />
-      </div>
-    </div>
-
-    <el-drawer v-model="detailDrawerVisible" :title="`工单详情 - ${currentOrder?.orderNo || ''}`" size="540px" direction="rtl" class="detail-drawer">
-      <div v-if="currentOrder" class="p-2" v-loading="detailLoading">
-        <el-descriptions :column="1" border>
-          <el-descriptions-item label="工单编号">{{ currentOrder.orderNo }}</el-descriptions-item>
-          <el-descriptions-item label="关联案件编号">{{ currentOrder.caseNo || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="设备编号">{{ currentOrder.deviceCode || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="工单状态">
-            <el-tag :type="currentOrder.orderStatusTag">{{ currentOrder.orderStatusText }}</el-tag>
-          </el-descriptions-item>
-          <el-descriptions-item label="优先级">
-            <el-tag :type="currentOrder.orderLevelTag">{{ currentOrder.orderLevelText }}</el-tag>
-          </el-descriptions-item>
-          <el-descriptions-item label="问题描述">{{ currentOrder.orderDesc || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="设备类别">{{ currentOrder.equipmentTypeName || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="派单时间">{{ currentOrder.dispatchTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="创建时间">{{ currentOrder.createTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="计划完成时间">{{ currentOrder.planFinishTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="延期原因">{{ currentOrder.delayedReason || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="延期截止时间">{{ currentOrder.delayedDeadlineText }}</el-descriptions-item>
-          <el-descriptions-item label="验收时间">{{ currentOrder.verifyTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="实际完成时间">{{ currentOrder.realFinishTimeText }}</el-descriptions-item>
-          <el-descriptions-item label="维修处置结果">{{ currentOrder.repairResult || '—' }}</el-descriptions-item>
-          <el-descriptions-item label="设备运维状态">{{ currentOrder.currentStatusText }}</el-descriptions-item>
-          <el-descriptions-item label="设备在线状态">{{ currentOrder.onlineStatusText }}</el-descriptions-item>
-          <el-descriptions-item label="设备报警状态">{{ currentOrder.alarmStatusText }}</el-descriptions-item>
-        </el-descriptions>
-
-        <div class="mt-4">
-          <div class="mb-3 mt-4 text-[14px] font-600 text-[#2c3e50]">处理记录</div>
-          <el-timeline v-if="currentOrder.workOrderLogList?.length">
-            <el-timeline-item
-              v-for="log in currentOrder.workOrderLogList"
-              :key="log.logId"
-              :timestamp="formatDateTime(log.operTime)"
-              :type="getLogType(log.operType)"
-            >
-              {{ log.operDesc }}
-              <span v-if="log.operUserName" class="ml-3 text-[12px] text-[#909399]">操作人: {{ log.operUserName }}</span>
-            </el-timeline-item>
-          </el-timeline>
-          <el-empty v-else description="暂无处理记录" :image-size="80" />
-        </div>
-
-        <div class="mt-6 flex justify-end gap-3">
-          <el-button v-if="canAcceptOrder(currentOrder)" type="warning" @click="acceptOrder(currentOrder)">接单</el-button>
-          <el-button v-if="canStartRepair(currentOrder)" type="primary" @click="startRepair(currentOrder)">开始维修</el-button>
-          <el-button v-if="canSubmitVerify(currentOrder)" type="success" @click="submitVerify(currentOrder)">提交验收</el-button>
-          <el-button
-            v-if="canDelay(currentOrder)"
-            type="warning"
-            plain
-            @click="openDelayDialog(currentOrder)"
-          >
-            申请延期
-          </el-button>
-        </div>
-        <el-alert
-          v-if="!hasOperationButtons(currentOrder)"
-          class="mt-4"
-          title="当前状态暂无可操作项"
-          type="info"
-          :closable="false"
-          show-icon
-        />
-      </div>
-    </el-drawer>
-
-    <el-dialog v-model="delayDialogVisible" title="申请延期" width="420px">
-      <el-form label-width="88px">
-        <el-form-item label="截止时间">
-          <el-date-picker
-            v-model="delayDeadline"
-            type="datetime"
-            value-format="YYYY-MM-DD HH:mm:ss"
-            placeholder="请选择延期截止时间"
-            class="w-full"
-          />
-        </el-form-item>
-        <el-form-item label="延期原因">
-          <el-input v-model="delayReason" type="textarea" rows="3" placeholder="请输入延期原因" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button @click="delayDialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="submitDelay">提交</el-button>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup>
-import {computed, onMounted, ref} from 'vue'
-import {List, Refresh, Search} from '@element-plus/icons-vue'
-import {ElMessage} from 'element-plus'
-import {getManholeWorkOrderDetail, getManholeWorkOrderPage, operManholeWorkOrder} from '@/api/pipeNetwork/basic'
-
-const DEFAULT_OPER_USER_ID = 1
-
-const orders = ref([])
-const loading = ref(false)
-const detailLoading = ref(false)
-const detailDrawerVisible = ref(false)
-const delayDialogVisible = ref(false)
-const currentOrder = ref(null)
-const searchKeyword = ref('')
-const orderLevelFilter = ref('')
-const statusFilter = ref('')
-const currentPage = ref(1)
-const pageSize = ref(10)
-const delayDeadline = ref('')
-const delayReason = ref('')
-
-function formatDateTime(value) {
-  if (!value) return '—'
-  return String(value).replace('T', ' ')
-}
-
-function getOrderLevelMeta(level) {
-  const map = {
-    0: { text: '紧急', tag: 'danger' },
-    1: { text: '一般', tag: 'warning' },
-    2: { text: '低', tag: 'info' }
-  }
-  return map[Number(level)] || { text: '—', tag: 'info' }
-}
-
-
-function getOrderStatusMeta(status) {
-  const map = {
-    0: { key: 'pending', text: '待派单', tag: 'danger' },
-    1: { key: 'pending', text: '待接单', tag: 'danger' },
-    2: { key: 'processing', text: '已接单', tag: 'warning' },
-    3: { key: 'processing', text: '处理中', tag: 'warning' },
-    4: { key: 'verify', text: '待验收', tag: 'primary' },
-    5: { key: 'completed', text: '已结案', tag: 'success' },
-    6: { key: 'processing', text: '延期中', tag: 'warning' },
-    7: { key: 'completed', text: '已取消', tag: 'info' }
-  }
-  return map[Number(status)] || { key: '', text: '—', tag: 'info' }
-}
-
-function getOnlineStatusText(status) {
-  const map = {
-    0: '离线',
-    1: '在线'
-  }
-  return map[Number(status)] || '—'
-}
-
-function getAlarmStatusText(status) {
-  const map = {
-    0: '正常',
-    1: '报警'
-  }
-  return map[Number(status)] || '—'
-}
-
-function getCurrentStatusText(status) {
-  const map = {
-    1: '在用',
-    2: '闲置',
-    3: '维修',
-    4: '报废',
-    5: '待入库'
-  }
-  return map[Number(status)] || '—'
-}
-
-function normalizeOrder(item) {
-  const levelMeta = getOrderLevelMeta(item.orderLevel)
-  const statusMeta = getOrderStatusMeta(item.orderStatus)
-  return {
-    ...item,
-    orderLevelText: levelMeta.text,
-    orderLevelTag: levelMeta.tag,
-    orderStatusKey: statusMeta.key,
-    orderStatusText: statusMeta.text,
-    orderStatusTag: statusMeta.tag,
-    createTimeText: formatDateTime(item.createTime),
-    dispatchTimeText: formatDateTime(item.dispatchTime),
-    planFinishTimeText: formatDateTime(item.planFinishTime),
-    delayedDeadlineText: formatDateTime(item.delayedDeadline),
-    realFinishTimeText: formatDateTime(item.realFinishTime),
-    verifyTimeText: formatDateTime(item.verifyTime),
-    updateTimeText: formatDateTime(item.updateTime),
-    currentStatusText: getCurrentStatusText(item.equipmentStatus?.currentStatus),
-    onlineStatusText: getOnlineStatusText(item.equipmentStatus?.onlineStatus),
-    alarmStatusText: getAlarmStatusText(item.equipmentStatus?.alarmStatus),
-    statusUpdateTimeText: formatDateTime(item.equipmentStatus?.statusUpdateTime)
-  }
-}
-
-function isOverdue(item) {
-  if (!item.planFinishTime) return false
-  return new Date(item.planFinishTime).getTime() < Date.now() && ![6, 7].includes(Number(item.orderStatus))
-}
-
-const filteredOrders = computed(() => {
-  let list = orders.value
-  if (statusFilter.value === 'pending') {
-    list = list.filter(item => item.orderStatusKey === 'pending')
-  } else if (statusFilter.value === 'processing') {
-    list = list.filter(item => item.orderStatusKey === 'processing' && !isOverdue(item))
-  } else if (statusFilter.value === 'overdue') {
-    list = list.filter(item => isOverdue(item))
-  }
-  return list
-})
-
-const paginatedOrders = computed(() => {
-  const start = (currentPage.value - 1) * pageSize.value
-  return filteredOrders.value.slice(start, start + pageSize.value)
-})
-
-const totalOrders = computed(() => orders.value.length)
-const pendingOrdersCount = computed(() => orders.value.filter(item => item.orderStatusKey === 'pending').length)
-const processingOrdersCount = computed(() => orders.value.filter(item => item.orderStatusKey === 'processing' && !isOverdue(item)).length)
-const overdueCount = computed(() => orders.value.filter(item => isOverdue(item)).length)
-
-async function loadOrders() {
-  loading.value = true
-  try {
-    const keyword = searchKeyword.value.trim()
-    const payload = {
-      pageNum: 1,
-      pageSize: 200,
-      orderLevel: orderLevelFilter.value || undefined,
-      orderNo: keyword || undefined,
-      caseNo: keyword || undefined
-    }
-    const res = await getManholeWorkOrderPage(payload)
-    const records = Array.isArray(res?.data?.records) ? res.data.records : []
-    orders.value = records
-      .filter(item => [2, 3, 4, 5, 8, 9].includes(Number(item.orderStatus)))
-      .map(normalizeOrder)
-    currentPage.value = 1
-    if (currentOrder.value) {
-      const matched = orders.value.find(item => item.orderId === currentOrder.value.orderId)
-      if (matched) {
-        await viewDetail(matched)
-      } else {
-        currentOrder.value = null
-        detailDrawerVisible.value = false
-      }
-    }
-  } catch (error) {
-    orders.value = []
-    currentOrder.value = null
-    ElMessage.error('经办工单加载失败')
-  } finally {
-    loading.value = false
-  }
-}
-
-async function viewDetail(order) {
-  detailLoading.value = true
-  detailDrawerVisible.value = true
-  try {
-    const res = await getManholeWorkOrderDetail(order.orderId)
-    currentOrder.value = normalizeOrder(res?.data || order)
-  } catch (error) {
-    currentOrder.value = order
-    ElMessage.error('工单详情加载失败')
-  } finally {
-    detailLoading.value = false
-  }
-}
-
-function handleRowClick(row) {
-  viewDetail(row)
-}
-
-function setStatusFilter(status) {
-  statusFilter.value = status
-  currentPage.value = 1
-  if (detailDrawerVisible.value && currentOrder.value) {
-    const first = filteredOrders.value[0]
-    if (first) {
-      viewDetail(first)
-    } else {
-      currentOrder.value = null
-      detailDrawerVisible.value = false
-    }
-  }
-}
-
-function canStartRepair(order) {
-  return Number(order.orderStatus) === 3
-}
-
-function canAcceptOrder(order) {
-  return [2, 9].includes(Number(order.orderStatus))
-}
-
-function canSubmitVerify(order) {
-  return Number(order.orderStatus) === 4
-}
-
-function canDelay(order) {
-  return [3, 4].includes(Number(order.orderStatus))
-}
-
-function hasOperationButtons(order) {
-  if (!order) return false
-  return canAcceptOrder(order) || canStartRepair(order) || canSubmitVerify(order) || canDelay(order)
-}
-
-async function operateOrder(orderId, operType, operDesc, extra = {}) {
-  await operManholeWorkOrder({
-    orderId,
-    operType,
-    operDesc,
-    operUserId: DEFAULT_OPER_USER_ID,
-    ...extra
-  })
-  await loadOrders()
-  if (currentOrder.value?.orderId === orderId) {
-    const matched = orders.value.find(item => item.orderId === orderId)
-    if (matched) {
-      await viewDetail(matched)
-    }
-  }
-}
-
-async function startRepair(order) {
-  try {
-    await operateOrder(order.orderId, 3, '开始维修')
-    ElMessage.success('已开始维修')
-  } catch (error) {
-    ElMessage.error(error?.message || '开始维修失败')
-  }
-}
-
-async function acceptOrder(order) {
-  try {
-    await operateOrder(order.orderId, 2, '接单')
-    ElMessage.success('已接单')
-  } catch (error) {
-    ElMessage.error(error?.message || '接单失败')
-  }
-}
-
-async function submitVerify(order) {
-  try {
-    await operateOrder(order.orderId, 4, '提交验收')
-    ElMessage.success('已提交验收')
-  } catch (error) {
-    ElMessage.error(error?.message || '提交验收失败')
-  }
-}
-
-function openDelayDialog(order) {
-  currentOrder.value = order
-  delayDeadline.value = ''
-  delayReason.value = ''
-  delayDialogVisible.value = true
-}
-
-async function submitDelay() {
-  if (!currentOrder.value?.orderId) return
-  if (!delayDeadline.value) {
-    ElMessage.warning('请选择延期截止时间')
-    return
-  }
-  if (!delayReason.value.trim()) {
-    ElMessage.warning('请输入延期原因')
-    return
-  }
-  try {
-    await operateOrder(currentOrder.value.orderId, 8, '申请延期', {
-      delayedReason: delayReason.value.trim(),
-      delayedDeadline: delayDeadline.value
-    })
-    delayDialogVisible.value = false
-    ElMessage.success('延期申请已提交')
-  } catch (error) {
-    ElMessage.error(error?.message || '延期申请失败')
-  }
-}
-
-function getLogType(operType) {
-  const map = {
-    0: 'primary',
-    1: 'primary',
-    2: 'warning',
-    3: 'primary',
-    4: 'warning',
-    5: 'success',
-    6: 'danger',
-    7: 'info',
-    8: 'warning',
-    9: 'success',
-    10: 'danger'
-  }
-  return map[Number(operType)] || 'info'
-}
-
-onMounted(() => {
-  loadOrders()
-})
-</script>

+ 13 - 2
src/views/subSystem/manholeCover/home/index.vue

@@ -102,7 +102,9 @@
 <script setup>
 import { ref, reactive, onMounted, onBeforeUnmount, nextTick, computed } from 'vue'
 import * as echarts from 'echarts'
-import { getManholeLayerData, getManholeWorkOrderProcessingPage } from '@/api/pipeNetwork/basic'
+import { getManholeLayerData } from '@/api/pipeNetwork/basic'
+import { listWorkOrder } from '@/api/pipeNetwork/ops/workOrder.js'
+import { ORDER_STATUS_GROUP } from '@/views/subSystem/pipeNetwork/ops/workOrder/workOrderDict.js'
 import { getAlarmDataPage } from '@/api/drainage'
 import { ElMessage } from 'element-plus'
 import locationIcon from '@/assets/images/location.png'
@@ -128,6 +130,10 @@ const tableHeaderStyle = { background: 'rgba(0,100,200,0.3)', color: '#fff', bor
 
 const priorityText = (l) => ({ 0: '紧急', 1: '一般', 2: '低' }[l] || '-')
 const priorityClass = (l) => ({ 0: 'high', 1: 'medium', 2: 'low' }[l] || 'low')
+/** 待办工单口径:待派单/待接单/已接单/处理中/延期中(枚举派生,见 workOrderDict.js) */
+const TODO_ORDER_STATUS = ORDER_STATUS_GROUP.todo.join(',')
+/** 设备父类别ID(equipment_type.parent_type_id),与工单列表页保持同一口径 */
+const DEVICE_TYPE_PARENT_ID = '4'
 const typeText = (id) => TYPE_MAP[id] || '-'
 const statusText = (s) => ({ normal: '在线', alert: '告警', offline: '离线' }[s] || s)
 const batteryTag = (b) => {
@@ -193,7 +199,12 @@ async function loadDevices() {
 async function loadWorkOrders() {
   loading.work = true
   try {
-    const res = await getManholeWorkOrderProcessingPage({ pageNum: 1, pageSize: 20 })
+    const res = await listWorkOrder({
+      pageNum: 1,
+      pageSize: 20,
+      orderStatus: TODO_ORDER_STATUS,
+      deviceTypeParentId: DEVICE_TYPE_PARENT_ID
+    })
     workOrders.value = res.data?.records || []
   } catch (e) {
     ElMessage.error('工单数据加载失败')

+ 8 - 2
src/views/subSystem/manholeCover/operation/faultMana.vue

@@ -234,7 +234,8 @@
 import { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue'
 import { Monitor, Search, Refresh, MapLocation, Location, Tools, Document, Warning } from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
-import { getManholeAlarmMonitorList, addManholeWorkOrder, getManholeWorkOrderPage, updateManholeDeviceStatus } from '@/api/pipeNetwork/basic'
+import { getManholeAlarmMonitorList, addManholeWorkOrder, updateManholeDeviceStatus } from '@/api/pipeNetwork/basic'
+import { listWorkOrder } from '@/api/pipeNetwork/ops/workOrder'
 import locationIcon from '@/assets/images/location.png'
 
 // ==================== 常量 ====================
@@ -434,10 +435,15 @@ const selectDevice = async (device) => {
 
 // ==================== 历史处置记录(工单处理记录) ====================
 async function loadOrderRecords(device) {
+  const deviceId = device?.equipmentId
+  if (!deviceId) {
+    orderRecords.value = []
+    return
+  }
   orderLoading.value = true
   orderRecords.value = []
   try {
-    const { data } = await getManholeWorkOrderPage({ deviceId: device.equipmentId, pageNum: 1, pageSize: 20 })
+    const { data } = await listWorkOrder({ deviceId, pageNum: 1, pageSize: 20 })
     orderRecords.value = data?.records || data?.rows || []
   } catch (error) {
     ElMessage.error('工单记录加载失败: ' + (error?.message || error?.msg || '未知错误'))

+ 4 - 7
src/views/subSystem/manholeCover/operation/operationTask.vue

@@ -293,7 +293,8 @@
 import { ref, computed, onMounted } from 'vue'
 import { Warning, Search, Refresh, Location, Monitor, MapLocation, Document, DataAnalysis } from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
-import { getManholeAlarmMonitorList, addManholeWorkOrder, getManholeWorkOrderProcessingPage } from '@/api/pipeNetwork/basic'
+import { getManholeAlarmMonitorList, addManholeWorkOrder } from '@/api/pipeNetwork/basic'
+import { listWorkOrder } from '@/api/pipeNetwork/ops/workOrder'
 
 // ==================== 常量 ====================
 const TYPE_MAP = { '5': '供水窨井', '9': '排水窨井', '10': '燃气窨井' }
@@ -354,12 +355,8 @@ async function loadWorkOrders(deviceId) {
   if (!deviceId) return
   loadingOrders.value = true
   try {
-    const res = await getManholeWorkOrderProcessingPage({
-      deviceId,
-      pageNum: 1,
-      pageSize: 20
-    })
-    workOrders.value = res.data?.records || res.rows || []
+    const { data } = await listWorkOrder({ deviceId, pageNum: 1, pageSize: 20 })
+    workOrders.value = data?.records || data?.rows || []
   } catch (error) {
     workOrders.value = []
     console.error('[operationTask] 工单记录加载失败:', error)

+ 124 - 55
src/views/subSystem/pipeNetwork/ops/workOrder/dispose.vue

@@ -17,9 +17,9 @@
           <div class="qf">
             <label>优先级</label>
             <el-select v-model="queryParams.orderLevel" placeholder="全部" clearable style="width: 120px">
-              <el-option label="紧急" :value="0" />
-              <el-option label="一般" :value="1" />
-              <el-option label="低" :value="2" />
+              <el-option label="紧急" :value="WO_LEVEL.EMERGENCY" />
+              <el-option label="一般" :value="WO_LEVEL.NORMAL" />
+              <el-option label="低" :value="WO_LEVEL.LOW" />
             </el-select>
           </div>
           <div class="qf">
@@ -43,8 +43,8 @@
 
     <!-- 状态筛选条 -->
     <div class="strips">
-      <button class="chip" :class="{ on: !queryParams.orderStatus && queryParams.orderStatus !== 0 }" @click="pickStatus(undefined)">
-        <b>全部</b><span class="cnt">{{ total }}</span>
+      <button class="chip" :class="{ on: queryParams.orderStatus === undefined }" @click="pickStatus(undefined)">
+        <b>全部</b><span class="cnt">{{ statusTotal }}</span>
       </button>
       <button
         v-for="s in STATUS_ORDER"
@@ -179,7 +179,7 @@
 
               <div class="sect nod">
                 <div class="sect-t">延期申请</div>
-                <div v-if="Number(selectedOrder.delayApplyStatus) > 0" class="delaybox">
+                <div v-if="Number(selectedOrder.delayApplyStatus) > DELAY_APPLY_STATUS.NONE" class="delaybox">
                   <span class="dchip">{{ delayApplyStatusText(selectedOrder.delayApplyStatus) }}</span>
                   <div class="di">
                     <b>{{ selectedOrder.delayedReason || '-' }}</b>
@@ -228,56 +228,56 @@
           <div class="abar">
             <el-button
               v-if="canOperate.delay(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:delay']"
+              v-hasPermi="['ops:workOrder:delay']"
               @click="openDelay(selectedOrder)"
             >申请延期</el-button>
             <el-button
               v-if="canOperate.delayAudit(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:delayAudit']"
+              v-hasPermi="['ops:workOrder:delayAudit']"
               @click="openDelayAudit(selectedOrder)"
             >延期审核</el-button>
             <el-button
               v-if="canOperate.cancel(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:cancel']"
+              v-hasPermi="['ops:workOrder:cancel']"
               type="danger" plain
               @click="openAction(selectedOrder, 'cancel')"
             >取消</el-button>
             <el-button
               v-if="canOperate.remove(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:remove']"
+              v-hasPermi="['ops:workOrder:remove']"
               type="danger" plain
               @click="handleDelete(selectedOrder)"
             >删除工单</el-button>
             <el-button
               v-if="canOperate.dispatch(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:dispatch']"
+              v-hasPermi="['ops:workOrder:dispatch']"
               type="primary"
               @click="openDispatch(selectedOrder)"
             >派单</el-button>
             <el-button
               v-if="canOperate.accept(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:accept']"
+              v-hasPermi="['ops:workOrder:accept']"
               type="primary"
               @click="openAction(selectedOrder, 'accept')"
             >核查接单</el-button>
             <el-button
               v-if="canOperate.process(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:process']"
+              v-hasPermi="['ops:workOrder:process']"
               type="primary"
               @click="openAction(selectedOrder, 'process')"
             >开始处理</el-button>
             <el-button
               v-if="canOperate.submitVerify(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:submitVerify']"
+              v-hasPermi="['ops:workOrder:submitVerify']"
               type="primary"
               @click="openAction(selectedOrder, 'submitVerify')"
             >提交验收</el-button>
             <el-button
               v-if="canOperate.verify(selectedOrder)"
-              v-hasPermi="['ops:pworkOrder:verify']"
+              v-hasPermi="['ops:workOrder:verify']"
               type="primary"
               @click="openVerify(selectedOrder)"
-            >验收通过</el-button>
+            >验收审核</el-button>
           </div>
         </template>
 
@@ -425,29 +425,33 @@
 <script setup>
 import { ref, reactive, computed, getCurrentInstance, onMounted, watch } from 'vue'
 import {
-  listPworkOrder,
-  getPworkOrder,
-  dispatchPworkOrder,
-  acceptPworkOrder,
-  processPworkOrder,
-  submitVerifyPworkOrder,
-  verifyPworkOrder,
-  cancelPworkOrder,
-  applyDelayPworkOrder,
-  auditDelayPworkOrder,
-  delPworkOrder,
-  pworkOrderDeptTree,
-  pworkOrderUsers
-} from '@/api/pipeNetwork/ops/pworkOrder.js'
+  listWorkOrder,
+  workOrderStatusCount,
+  getWorkOrder,
+  dispatchWorkOrder,
+  acceptWorkOrder,
+  processWorkOrder,
+  submitVerifyWorkOrder,
+  verifyWorkOrder,
+  cancelWorkOrder,
+  applyDelayWorkOrder,
+  auditDelayWorkOrder,
+  delWorkOrder,
+  workOrderDeptTree,
+  workOrderUsers
+} from '@/api/pipeNetwork/ops/workOrder.js'
 import {
   canOperate,
   orderLevelText,
-  ORDER_STATUS_MAP,
   orderStatusText,
   delayApplyStatusText,
   orderLogText,
   timeText,
-  splitAttach
+  splitAttach,
+  WO_STATUS,
+  WO_LOG_TYPE,
+  DELAY_APPLY_STATUS,
+  WO_LEVEL
 } from './workOrderDict.js'
 import ImageUpload from '@/components/ImageUpload/index.vue'
 import { useRoute } from 'vue-router'
@@ -489,12 +493,36 @@ function buildQueryParams() {
   }
 }
 
-const STATUS_ORDER = [0, 1, 2, 3, 4, 5, 6, 7]
+/** 状态统计入参:与列表同条件,但去掉状态筛选,保证各状态计数同时可见 */
+function buildStatQueryParams() {
+  const params = buildQueryParams()
+  delete params.orderStatus
+  return params
+}
+
+/** 状态筛选条顺序(与 WorkOrderStatusEnum 声明顺序一致:0~7) */
+const STATUS_ORDER = Object.values(WO_STATUS)
 const STEP_NODES = ['创建', '派单', '接单', '处置', '验收', '完成']
-const STEP_INDEX = { 0: 1, 1: 2, 2: 3, 3: 3, 4: 4, 5: 5, 6: 3 }
+/** 各状态对应的步骤条进度下标(已取消由 isCancelled 单独分支处理,故不在此表) */
+const STEP_INDEX = {
+  [WO_STATUS.PENDING_DISPATCH]: 1,
+  [WO_STATUS.PENDING_ACCEPT]: 2,
+  [WO_STATUS.ACCEPTED]: 3,
+  [WO_STATUS.PROCESSING]: 3,
+  [WO_STATUS.PENDING_VERIFY]: 4,
+  [WO_STATUS.CLOSED]: 5,
+  [WO_STATUS.DELAYING]: 3
+}
+/** 各状态的徽标配色(key 为 WorkOrderStatusEnum code) */
 const BADGE = {
-  0: ['#FAEEDA', '#854F0B'], 1: ['#E6F1FB', '#185FA5'], 2: ['#E1F5EE', '#0F6E56'], 3: ['#ECEEF9', '#3F51B5'],
-  4: ['#FAECE7', '#993C1D'], 5: ['#EAF3DE', '#3B6D11'], 6: ['#FBEAF0', '#993556'], 7: ['#F1EFE8', '#5F5E5A']
+  [WO_STATUS.PENDING_DISPATCH]: ['#FAEEDA', '#854F0B'],
+  [WO_STATUS.PENDING_ACCEPT]: ['#E6F1FB', '#185FA5'],
+  [WO_STATUS.ACCEPTED]: ['#E1F5EE', '#0F6E56'],
+  [WO_STATUS.PROCESSING]: ['#ECEEF9', '#3F51B5'],
+  [WO_STATUS.PENDING_VERIFY]: ['#FAECE7', '#993C1D'],
+  [WO_STATUS.CLOSED]: ['#EAF3DE', '#3B6D11'],
+  [WO_STATUS.DELAYING]: ['#FBEAF0', '#993556'],
+  [WO_STATUS.CANCELLED]: ['#F1EFE8', '#5F5E5A']
 }
 
 const listLoading = ref(false)
@@ -520,10 +548,10 @@ const currentOrderLogs = ref([])
 const activeTab = ref('info')
 
 const ACTION_CONFIG = {
-  accept: { title: '核查接单', label: '核查结论', placeholder: '请如实填写现场核查结论,注明故障是否属实、现场现状等内容', attachLabel: '上传现场情况', attachRequired: true, api: acceptPworkOrder },
-  process: { title: '工单处置', label: '处置内容', placeholder: '请记录故障原因、处置方案、实施措施及处理结果,支持多次处置填报', attachLabel: '上传附件(可选)', attachRequired: false, api: processPworkOrder },
-  submitVerify: { title: '提交验收', label: '验收说明', placeholder: '请填报维修处置完成情况,同步上传维修完成后的佐证材料', attachLabel: '上传维修后的情况', attachRequired: true, api: submitVerifyPworkOrder },
-  cancel: { title: '取消工单', label: '取消原因', placeholder: '请详细说明工单取消事由', attachLabel: '上传附件(可选)', attachRequired: false, api: cancelPworkOrder }
+  accept: { title: '核查接单', label: '核查结论', placeholder: '请如实填写现场核查结论,注明故障是否属实、现场现状等内容', attachLabel: '上传现场情况', attachRequired: true, api: acceptWorkOrder },
+  process: { title: '工单处置', label: '处置内容', placeholder: '请记录故障原因、处置方案、实施措施及处理结果,支持多次处置填报', attachLabel: '上传附件(可选)', attachRequired: false, api: processWorkOrder },
+  submitVerify: { title: '提交验收', label: '验收说明', placeholder: '请填报维修处置完成情况,同步上传维修完成后的佐证材料', attachLabel: '上传维修后的情况', attachRequired: true, api: submitVerifyWorkOrder },
+  cancel: { title: '取消工单', label: '取消原因', placeholder: '请详细说明工单取消事由', attachLabel: '上传附件(可选)', attachRequired: false, api: cancelWorkOrder }
 }
 
 /* ============ 展示辅助 ============ */
@@ -533,7 +561,7 @@ function badgeStyle(status) {
 }
 function priClass(level) {
   const n = Number(level)
-  return n === 0 ? 'h' : (n === 2 ? 'l' : 'm')
+  return n === WO_LEVEL.EMERGENCY ? 'h' : (n === WO_LEVEL.LOW ? 'l' : 'm')
 }
 function fileName(url) {
   if (!url) return '-'
@@ -567,8 +595,8 @@ function dayLabel(d) {
 
 const beforeAttach = computed(() => splitAttach(selectedOrder.value?.maintenanceBeforeImg))
 const afterAttach = computed(() => splitAttach(selectedOrder.value?.maintenanceAfterImg))
-const locked = computed(() => Number(selectedOrder.value?.orderStatus) === 5)
-const isCancelled = computed(() => Number(selectedOrder.value?.orderStatus) === 7)
+const locked = computed(() => Number(selectedOrder.value?.orderStatus) === WO_STATUS.CLOSED)
+const isCancelled = computed(() => Number(selectedOrder.value?.orderStatus) === WO_STATUS.CANCELLED)
 const stepIdxVal = computed(() => STEP_INDEX[Number(selectedOrder.value?.orderStatus)] ?? -1)
 
 const stepNodes = computed(() => {
@@ -576,8 +604,8 @@ const stepNodes = computed(() => {
   if (isCancelled.value) {
     let prog = 1
     const logs = currentOrderLogs.value || []
-    if (logs.some((l) => Number(l.operType) === 1)) prog = 2
-    if (logs.some((l) => Number(l.operType) === 2)) prog = 3
+    if (logs.some((l) => Number(l.operType) === WO_LOG_TYPE.DISPATCH)) prog = 2
+    if (logs.some((l) => Number(l.operType) === WO_LOG_TYPE.ACCEPT)) prog = 3
     return STEP_NODES.map((n, i) => {
       if (i < prog) return { label: n, cls: 'stp donegray', icon: '✓' }
       if (i === prog) return { label: '已终止', cls: 'stp offx', icon: '✕' }
@@ -604,8 +632,47 @@ const logGroups = computed(() => {
     .map((d) => ({ day: d, items: days[d].slice().sort((a, b) => logTime(b.operTime).localeCompare(logTime(a.operTime))) }))
 })
 
+/** 状态筛选条:全部状态合计(由后端聚合,随当前筛选条件联动) */
+const statusTotal = ref(0)
+/** 状态筛选条:状态码 → 数量 */
+const statusCounts = ref({})
+
+/**
+ * 拉取各状态工单数量。
+ *
+ * 必须走后端聚合:只用当前页数据统计会在分页时失真,
+ * 且选中某个状态后列表被过滤,其它状态的计数会全部变成 0。
+ * 接口异常时返回 false,由调用方降级,不影响列表展示。
+ */
+async function loadStatusStat() {
+  try {
+    const res = await workOrderStatusCount(buildStatQueryParams())
+    const data = res.data || {}
+    const map = {}
+    ;(data.counts || []).forEach((item) => {
+      map[Number(item.status)] = Number(item.count) || 0
+    })
+    statusCounts.value = map
+    statusTotal.value = Number(data.total) || 0
+    return true
+  } catch (e) {
+    return false
+  }
+}
+
+/** 统计接口不可用时的降级:按当前页数据估算,保证筛选条不空白 */
+function fallbackStatusStat() {
+  const map = {}
+  list.value.forEach((o) => {
+    const s = Number(o.orderStatus)
+    map[s] = (map[s] || 0) + 1
+  })
+  statusCounts.value = map
+  statusTotal.value = total.value
+}
+
 function statusCount(s) {
-  return list.value.filter((o) => Number(o.orderStatus) === s).length
+  return statusCounts.value[s] || 0
 }
 
 /* ============ 附件预览 ============ */
@@ -623,10 +690,12 @@ function preview(url, arr) {
 async function handleSearch() {
   listLoading.value = true
   try {
-    const res = await listPworkOrder(buildQueryParams())
+    // 列表与状态统计并行请求:统计失败只降级,不阻断列表
+    const [res, statLoaded] = await Promise.all([listWorkOrder(buildQueryParams()), loadStatusStat()])
     const data = res.data || {}
     list.value = data.records || []
     total.value = data.total || 0
+    if (!statLoaded) fallbackStatusStat()
   } finally {
     listLoading.value = false
   }
@@ -683,7 +752,7 @@ async function handleSelectOrder(o) {
   currentOrderLogs.value = []
   detailLoading.value = true
   try {
-    const res = await getPworkOrder(o.orderId)
+    const res = await getWorkOrder(o.orderId)
     const data = res.data || {}
     selectedOrder.value = { ...selectedOrder.value, ...(data.order || o) }
     currentOrderLogs.value = data.logs || []
@@ -720,7 +789,7 @@ async function submitDispatch() {
   }
   submitting.value = true
   try {
-    await dispatchPworkOrder({ orderId: dispatchForm.orderId, handlerId: dispatchForm.handlerId, remarks: dispatchForm.remarks })
+    await dispatchWorkOrder({ orderId: dispatchForm.orderId, handlerId: dispatchForm.handlerId, remarks: dispatchForm.remarks })
     proxy.$modal.msgSuccess('派单成功,工单状态变更为待接单')
     dispatchVisible.value = false
     await refresh(dispatchForm.orderId)
@@ -737,10 +806,10 @@ const selectedUserId = ref(null)
 const selectedUser = ref(null)
 
 function loadDeptTree() {
-  pworkOrderDeptTree().then((res) => { deptTree.value = res.data || [] })
+  workOrderDeptTree().then((res) => { deptTree.value = res.data || [] })
 }
 function loadDeptUsers(deptId) {
-  pworkOrderUsers(deptId).then((res) => { deptUserList.value = res.data || [] })
+  workOrderUsers(deptId).then((res) => { deptUserList.value = res.data || [] })
 }
 function handleDeptNodeClick(node) { loadDeptUsers(node.id) }
 function handleUserCurrentChange(row) {
@@ -820,7 +889,7 @@ function openVerify(o) {
 async function submitVerify() {
   submitting.value = true
   try {
-    await verifyPworkOrder({ orderId: verifyForm.orderId, passed: verifyForm.passed, content: verifyForm.content, attachUrl: verifyForm.attachUrl || '' })
+    await verifyWorkOrder({ orderId: verifyForm.orderId, passed: verifyForm.passed, content: verifyForm.content, attachUrl: verifyForm.attachUrl || '' })
     proxy.$modal.msgSuccess(verifyForm.passed ? '验收通过,工单已结案' : '验收驳回,工单退回处理中')
     verifyVisible.value = false
     await refresh(verifyForm.orderId)
@@ -845,7 +914,7 @@ async function submitDelay() {
   if (!delayForm.delayedReason || !delayForm.delayedReason.trim()) { proxy.$modal.msgWarning('请填写延期原因'); return }
   submitting.value = true
   try {
-    await applyDelayPworkOrder({
+    await applyDelayWorkOrder({
       orderId: delayForm.orderId,
       delayedDeadline: delayForm.delayedDeadline,
       delayedReason: delayForm.delayedReason.trim(),
@@ -872,7 +941,7 @@ function openDelayAudit(o) {
 async function submitDelayAudit() {
   submitting.value = true
   try {
-    await auditDelayPworkOrder({ orderId: delayAuditForm.orderId, approved: delayAuditForm.approved, auditOpinion: delayAuditForm.auditOpinion })
+    await auditDelayWorkOrder({ orderId: delayAuditForm.orderId, approved: delayAuditForm.approved, auditOpinion: delayAuditForm.auditOpinion })
     proxy.$modal.msgSuccess(delayAuditForm.approved ? '延期审核通过' : '延期审核驳回')
     delayAuditVisible.value = false
     await refresh(delayAuditForm.orderId)
@@ -885,7 +954,7 @@ async function submitDelayAudit() {
 function handleDelete(o) {
   proxy.$modal
     .confirm('确认删除该已取消工单吗?')
-    .then(() => delPworkOrder(o.orderId))
+    .then(() => delWorkOrder(o.orderId))
     .then(() => {
       proxy.$modal.msgSuccess('删除成功')
       clearSelection()

+ 126 - 38
src/views/subSystem/pipeNetwork/ops/workOrder/index.vue

@@ -2,7 +2,7 @@
   <div class="pwork-list-page">
     <!-- 搜索栏 -->
     <el-card shadow="never" class="search-card">
-      <el-form :model="queryParams" inline @submit.prevent>
+      <el-form :model="queryParams" inline class="search-form" @submit.prevent>
         <el-form-item label="关键字">
           <el-input
             v-model="queryParams.keyword"
@@ -14,9 +14,9 @@
         </el-form-item>
         <el-form-item label="优先级">
           <el-select v-model="queryParams.orderLevel" placeholder="全部" clearable style="width: 120px">
-            <el-option label="紧急" :value="0" />
-            <el-option label="一般" :value="1" />
-            <el-option label="低" :value="2" />
+            <el-option label="紧急" :value="WO_LEVEL.EMERGENCY" />
+            <el-option label="一般" :value="WO_LEVEL.NORMAL" />
+            <el-option label="低" :value="WO_LEVEL.LOW" />
           </el-select>
         </el-form-item>
         <el-form-item label="工单状态">
@@ -42,26 +42,32 @@
         <el-form-item>
           <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
           <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+          <el-button
+            v-hasPermi="['ops:workOrder:add']"
+            type="success"
+            icon="Plus"
+            @click="openAdd"
+          >新增工单</el-button>
         </el-form-item>
       </el-form>
     </el-card>
 
     <el-card shadow="never" class="table-card">
-      <template #header>
-        <div class="card-header">
-          <span class="card-title">故障工单</span>
-          <el-button
-            v-hasPermi="['ops:pworkOrder:add']"
-            type="primary"
-            icon="Plus"
-            @click="openAdd"
-          >新增故障工单</el-button>
-        </div>
-      </template>
-
       <el-table v-loading="loading" :data="list" border stripe>
         <el-table-column label="工单编号" prop="orderNo" min-width="180" show-overflow-tooltip />
-        <el-table-column label="故障描述" prop="orderDesc" min-width="240" show-overflow-tooltip />
+        <el-table-column label="故障描述" min-width="240">
+          <template #default="{ row }">
+            <el-tooltip
+              :content="row.orderDesc"
+              placement="top"
+              popper-class="order-desc-tooltip"
+              :show-after="200"
+              :disabled="!row.orderDesc"
+            >
+              <span class="desc-cell">{{ row.orderDesc || '-' }}</span>
+            </el-tooltip>
+          </template>
+        </el-table-column>
         <el-table-column label="优先级" width="100" align="center">
           <template #default="{ row }">
             <el-tag :type="orderLevelType(row.orderLevel)">{{ orderLevelText(row.orderLevel) }}</el-tag>
@@ -70,9 +76,15 @@
         <el-table-column label="设备编码" prop="deviceCode" min-width="150" show-overflow-tooltip>
           <template #default="{ row }">{{ row.deviceCode || '-' }}</template>
         </el-table-column>
-        <el-table-column label="故障发生时间" prop="faultTime" width="180" align="center">
+        <el-table-column label="责任人" prop="receiveUserName" min-width="100" show-overflow-tooltip>
+          <template #default="{ row }">{{ row.receiveUserName || '-' }}</template>
+        </el-table-column>
+        <el-table-column label="故障时间" prop="faultTime" width="180" align="center">
           <template #default="{ row }">{{ timeText(row.faultTime) }}</template>
         </el-table-column>
+        <el-table-column label="计划完成时间" prop="planFinishTime" width="180" align="center">
+          <template #default="{ row }">{{ timeText(row.planFinishTime) }}</template>
+        </el-table-column>
         <el-table-column label="状态" width="100" align="center">
           <template #default="{ row }">
             <el-tag :type="orderStatusType(row.orderStatus)">{{ orderStatusText(row.orderStatus) }}</el-tag>
@@ -89,8 +101,8 @@
       />
     </el-card>
 
-    <!-- 新增故障工单弹窗 -->
-    <el-dialog v-model="addVisible" title="新增故障工单" width="680px" append-to-body destroy-on-close>
+    <!-- 新增工单弹窗 -->
+    <el-dialog v-model="addVisible" title="新增工单" width="680px" append-to-body destroy-on-close>
       <el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px">
         <el-form-item label="关联设备">
           <el-select
@@ -126,21 +138,21 @@
 
         <el-form-item label="优先级" prop="orderLevel">
           <el-radio-group v-model="addForm.orderLevel">
-            <el-radio-button :value="0">紧急</el-radio-button>
-            <el-radio-button :value="1">一般</el-radio-button>
-            <el-radio-button :value="2">低</el-radio-button>
+            <el-radio-button :value="WO_LEVEL.EMERGENCY">紧急</el-radio-button>
+            <el-radio-button :value="WO_LEVEL.NORMAL">一般</el-radio-button>
+            <el-radio-button :value="WO_LEVEL.LOW">低</el-radio-button>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="故障时间" prop="faultTime">
           <el-date-picker
             v-model="addForm.faultTime"
             type="datetime"
-            placeholder="故障发生时间"
+            placeholder="故障时间"
             value-format="YYYY-MM-DD HH:mm:ss"
             style="width: 100%"
           />
         </el-form-item>
-        <el-form-item label="计划完成时间">
+        <el-form-item label="计划完成时间" prop="planFinishTime">
           <el-date-picker
             v-model="addForm.planFinishTime"
             type="datetime"
@@ -171,10 +183,11 @@
 <script setup>
 import { ref, reactive, computed, onMounted, watch } from 'vue'
 import { useRoute } from 'vue-router'
-import { addPworkOrder, listPworkOrder } from '@/api/pipeNetwork/ops/pworkOrder.js'
+import { addWorkOrder, listWorkOrder } from '@/api/pipeNetwork/ops/workOrder.js'
 import { listEquipment } from '@/api/pipeNetwork/pdeviceInform'
 import {
   ORDER_STATUS_MAP,
+  WO_LEVEL,
   orderLevelText,
   orderLevelType,
   orderStatusText,
@@ -233,7 +246,7 @@ const queryParams = reactive({
 async function getList() {
   loading.value = true
   try {
-    const res = await listPworkOrder(buildQueryParams())
+    const res = await listWorkOrder(buildQueryParams())
     const data = res.data || {}
     list.value = data.records || []
     total.value = data.total || 0
@@ -264,7 +277,7 @@ function resetQuery() {
   handleQuery()
 }
 
-/* 新增故障工单 */
+/* 新增工单 */
 const addVisible = ref(false)
 const addFormRef = ref(null)
 const deviceOptions = ref([])
@@ -272,19 +285,61 @@ const deviceLoading = ref(false)
 const deviceInfo = ref(null)
 const addForm = reactive({
   deviceId: '',
-  orderLevel: 1,
+  orderLevel: WO_LEVEL.NORMAL,
   faultTime: '',
   planFinishTime: '',
   orderDesc: ''
 })
+/** 当前时间文本,格式与 el-date-picker 的 value-format 保持一致('YYYY-MM-DD HH:mm:ss') */
+function nowText() {
+  const d = new Date()
+  const pad = (n) => String(n).padStart(2, '0')
+  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} `
+    + `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
+}
+
+/** 故障时间不能大于系统当前时间(定长字符串字典序即时间顺序) */
+function validateFaultTime(rule, value, callback) {
+  if (!value) {
+    callback()
+    return
+  }
+  if (String(value) > nowText()) {
+    callback(new Error('故障时间不能大于当前时间'))
+    return
+  }
+  callback()
+}
+
+/**
+ * 计划完成时间不能早于故障时间。
+ * 两者均为 el-date-picker 的 value-format 输出('YYYY-MM-DD HH:mm:ss' 定长字符串),
+ * 字典序与时间顺序一致,直接比较即可,无需解析为 Date 对象。
+ */
+function validatePlanFinishTime(rule, value, callback) {
+  if (!value || !addForm.faultTime) {
+    callback()
+    return
+  }
+  if (String(value) < String(addForm.faultTime)) {
+    callback(new Error('计划完成时间不能早于故障时间'))
+    return
+  }
+  callback()
+}
+
 const addRules = {
   orderDesc: [{ required: true, message: '请填写故障描述', trigger: 'blur' }],
-  faultTime: [{ required: true, message: '请选择故障发生时间', trigger: 'change' }]
+  faultTime: [
+    { required: true, message: '请选择故障发生时间', trigger: 'change' },
+    { validator: validateFaultTime, trigger: 'change' }
+  ],
+  planFinishTime: [{ validator: validatePlanFinishTime, trigger: 'change' }]
 }
 
 function openAdd() {
   addForm.deviceId = ''
-  addForm.orderLevel = 1
+  addForm.orderLevel = WO_LEVEL.NORMAL
   addForm.faultTime = ''
   addForm.planFinishTime = ''
   addForm.orderDesc = ''
@@ -333,7 +388,7 @@ async function submitAdd() {
     if (addForm.deviceId) data.deviceId = addForm.deviceId
     if (addForm.faultTime) data.faultTime = addForm.faultTime
     if (addForm.planFinishTime) data.planFinishTime = addForm.planFinishTime
-    await addPworkOrder(data)
+    await addWorkOrder(data)
     ElMessage.success('工单创建成功,状态为待派单')
     addVisible.value = false
     getList()
@@ -342,6 +397,16 @@ async function submitAdd() {
   }
 }
 
+// 故障时间变化后需重新校验计划完成时间:先填计划完成时间、再改故障时间时,
+// 原有校验结论会失效(比如故障时间改晚后,原合法的计划时间可能变得非法)
+watch(
+  () => addForm.faultTime,
+  () => {
+    if (!addVisible.value || !addForm.planFinishTime) return
+    addFormRef.value?.validateField('planFinishTime').catch(() => {})
+  }
+)
+
 // 同一组件被多个菜单复用(运维工单列表/设备维修记录),
 // 路由切换时组件实例被复用、onMounted 不会重新执行,
 // 必须监听路由变化按新菜单的业务口径重新拉取数据
@@ -370,14 +435,37 @@ onMounted(() => {
   margin-bottom: 12px;
 }
 
-.card-header {
+/* 查询栏:改用 flex + row-gap 控制换行时的行间距。
+   el-form-item 默认 margin-bottom: 18px 会让表单底部留白明显大于顶部,
+   这里清零后由卡片自身的上下 padding 决定留白,保证上下一致 */
+.search-form {
   display: flex;
-  align-items: center;
-  justify-content: space-between;
+  flex-wrap: wrap;
+  row-gap: 4px;
+
+  :deep(.el-form-item) {
+    margin-bottom: 0;
+  }
+}
+
+/* 单元格内省略:交给自定义 tooltip 展示全文 */
+.desc-cell {
+  display: inline-block;
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  vertical-align: bottom;
 }
+</style>
 
-.card-title {
-  font-size: 16px;
-  font-weight: 600;
+<style lang="scss">
+/* 故障描述悬浮提示:popper 挂在 body 下不受 scoped 限制,单独用全局样式块。
+   限制最大宽度并允许换行,替代默认"一行横穿全屏"的效果 */
+.el-popper.order-desc-tooltip {
+  max-width: 420px;
+  line-height: 1.6;
+  white-space: normal;
+  word-break: break-all;
 }
 </style>

+ 264 - 0
src/views/subSystem/pipeNetwork/ops/workOrder/list.vue

@@ -0,0 +1,264 @@
+<template>
+  <div class="pwork-list-page">
+    <!-- 搜索栏 -->
+    <el-card shadow="never" class="search-card">
+      <el-form :model="queryParams" inline class="search-form" @submit.prevent>
+        <el-form-item label="关键字">
+          <el-input
+            v-model="queryParams.keyword"
+            placeholder="工单编号 / 设备编码 / 故障描述"
+            clearable
+            style="width: 240px"
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="优先级">
+          <el-select v-model="queryParams.orderLevel" placeholder="全部" clearable style="width: 120px">
+            <el-option label="紧急" :value="0" />
+            <el-option label="一般" :value="1" />
+            <el-option label="低" :value="2" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="故障时间">
+          <el-date-picker
+            v-model="faultTimeRange"
+            type="datetimerange"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            style="width: 360px"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
+          <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <el-card shadow="never" class="table-card">
+      <el-table v-loading="loading" :data="list" border stripe>
+        <el-table-column label="工单编号" prop="orderNo" min-width="180" show-overflow-tooltip />
+        <el-table-column label="故障描述" min-width="240">
+          <template #default="{ row }">
+            <el-tooltip
+              :content="row.orderDesc"
+              placement="top"
+              popper-class="order-desc-tooltip"
+              :show-after="200"
+              :disabled="!row.orderDesc"
+            >
+              <span class="desc-cell">{{ row.orderDesc || '-' }}</span>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column label="优先级" width="100" align="center">
+          <template #default="{ row }">
+            <el-tag :type="orderLevelType(row.orderLevel)">{{ orderLevelText(row.orderLevel) }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="设备编码" prop="deviceCode" min-width="150" show-overflow-tooltip>
+          <template #default="{ row }">{{ row.deviceCode || '-' }}</template>
+        </el-table-column>
+        <el-table-column label="责任人" prop="receiveUserName" min-width="100" show-overflow-tooltip>
+          <template #default="{ row }">{{ row.receiveUserName || '-' }}</template>
+        </el-table-column>
+        <el-table-column label="故障时间" prop="faultTime" width="180" align="center">
+          <template #default="{ row }">{{ timeText(row.faultTime) }}</template>
+        </el-table-column>
+        <el-table-column label="计划完成时间" prop="planFinishTime" width="180" align="center">
+          <template #default="{ row }">{{ timeText(row.planFinishTime) }}</template>
+        </el-table-column>
+        <el-table-column label="状态" width="100" align="center">
+          <template #default="{ row }">
+            <el-tag :type="orderStatusType(row.orderStatus)">{{ orderStatusText(row.orderStatus) }}</el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination
+        v-show="total > 0"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        :total="total"
+        @pagination="getList"
+      />
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted, watch } from 'vue'
+import { useRoute } from 'vue-router'
+import { listWorkOrder } from '@/api/pipeNetwork/ops/workOrder.js'
+import {
+  orderLevelText,
+  orderLevelType,
+  orderStatusText,
+  orderStatusType,
+  ORDER_STATUS_GROUP,
+  WO_STATUS,
+  timeText
+} from './workOrderDict.js'
+
+defineOptions({ name: 'PworkOrderList' })
+
+const route = useRoute()
+
+/**
+ * 本组件服务于「案件管理」下两个列表菜单,展示与运维工单列表一致,仅查询口径不同:
+ * - 经办工单:未办结状态(待派单 / 待接单 / 已接单 / 处理中 / 待验收 / 延期中)
+ * - 办结工单:已结案
+ * 两者都只查 equipment_type.parent_type_id = 4(案件类设备)下的工单。
+ *
+ * 判定方式:同一组件由后台 sys_menu.component 指向本文件,菜单的 path 与菜单名会分别体现在
+ * 路由 path、route.meta.title 中,因此按关键字区分来源;两者都未命中时走默认(不限状态),
+ * 保证新增菜单接入不会误过滤。若后续调整菜单 path/名称,同步维护 MENU_SCOPES 即可。
+ */
+/** 办结口径:已结案(对应后端 WorkOrderStatusEnum.CLOSED) */
+const CLOSED_ORDER_STATUS = String(WO_STATUS.CLOSED)
+
+/** 经办口径:未办结(对应后端 WorkOrderStatusEnum.ACTIVE_CODES),与枚举同源,避免硬编码状态码 */
+const ACTIVE_ORDER_STATUS = ORDER_STATUS_GROUP.active.join(',')
+
+const MENU_SCOPES = [
+  {
+    name: '办结工单',
+    orderStatus: CLOSED_ORDER_STATUS,
+    match: (path, title) => path.includes('close') || title.includes('办结')
+  },
+  {
+    name: '经办工单',
+    orderStatus: ACTIVE_ORDER_STATUS,
+    match: (path, title) => path.includes('handling') || title.includes('经办')
+  }
+]
+
+/** 案件类设备的父类别ID(equipment_type.parent_type_id),本列表仅查询该类设备产生的工单 */
+const CASE_DEVICE_TYPE_PARENT_ID = '4'
+
+const menuScope = computed(() => {
+  const path = String(route.path || '').toLowerCase()
+  const title = String(route.meta?.title || '')
+  return MENU_SCOPES.find((m) => m.match(path, title))
+})
+
+/** 统一构造查询入参:状态按菜单口径固定,不随查询条件透出 */
+function buildQueryParams() {
+  return {
+    ...queryParams,
+    orderStatus: menuScope.value?.orderStatus || '',
+    deviceTypeParentId: CASE_DEVICE_TYPE_PARENT_ID
+  }
+}
+
+const loading = ref(false)
+const list = ref([])
+const total = ref(0)
+const faultTimeRange = ref([])
+
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  keyword: '',
+  orderLevel: undefined,
+  faultTimeStart: '',
+  faultTimeEnd: ''
+})
+
+/* 列表查询 */
+async function getList() {
+  loading.value = true
+  try {
+    const res = await listWorkOrder(buildQueryParams())
+    const data = res.data || {}
+    list.value = data.records || []
+    total.value = data.total || 0
+  } finally {
+    loading.value = false
+  }
+}
+
+function handleQuery() {
+  queryParams.pageNum = 1
+  if (faultTimeRange.value && faultTimeRange.value.length === 2) {
+    queryParams.faultTimeStart = faultTimeRange.value[0]
+    queryParams.faultTimeEnd = faultTimeRange.value[1]
+  } else {
+    queryParams.faultTimeStart = ''
+    queryParams.faultTimeEnd = ''
+  }
+  getList()
+}
+
+function resetQuery() {
+  queryParams.keyword = ''
+  queryParams.orderLevel = undefined
+  faultTimeRange.value = []
+  queryParams.faultTimeStart = ''
+  queryParams.faultTimeEnd = ''
+  handleQuery()
+}
+
+// 同一组件被多个菜单复用(经办工单/办结工单),
+// 路由切换时组件实例被复用、onMounted 不会重新执行,
+// 必须监听路由变化按新菜单的业务口径重新拉取数据
+watch(
+  () => route.path,
+  (nv, ov) => {
+    if (nv === ov) return
+    queryParams.pageNum = 1
+    getList()
+  }
+)
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped lang="scss">
+.pwork-list-page {
+  padding: 16px;
+  background: #f5f7fa;
+  min-height: calc(100vh - 84px);
+}
+
+.search-card {
+  margin-bottom: 12px;
+}
+
+/* 查询栏:改用 flex + row-gap 控制换行时的行间距。
+   el-form-item 默认 margin-bottom: 18px 会让表单底部留白明显大于顶部,
+   这里清零后由卡片自身的上下 padding 决定留白,保证上下一致 */
+.search-form {
+  display: flex;
+  flex-wrap: wrap;
+  row-gap: 4px;
+
+  :deep(.el-form-item) {
+    margin-bottom: 0;
+  }
+}
+
+/* 单元格内省略:交给自定义 tooltip 展示全文 */
+.desc-cell {
+  display: inline-block;
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  vertical-align: bottom;
+}
+</style>
+
+<style lang="scss">
+/* 故障描述悬浮提示:popper 挂在 body 下不受 scoped 限制,单独用全局样式块。
+   限制最大宽度并允许换行,替代默认"一行横穿全屏"的效果 */
+.el-popper.order-desc-tooltip {
+  max-width: 420px;
+  line-height: 1.6;
+  white-space: normal;
+  word-break: break-all;
+}
+</style>

+ 19 - 5
src/views/subSystem/pipeNetwork/ops/workOrder/workOrderDict.js

@@ -1,5 +1,5 @@
 // ========== 运维工单业务公共字典 ==========
-// 数据源:/api/ops/pworkOrder/* (PworkOrderController)
+// 数据源:/api/ops/workOrder/* (WorkOrderController)
 // 与后端枚举保持一致:
 //   WorkOrderStatusEnum        工单状态  work_order.order_status
 //   WorkOrderLogOperTypeEnum   操作类型  work_order_log.oper_type
@@ -41,11 +41,18 @@ export const WO_LOG_TYPE = {
   DELAY_REJECT: 10
 }
 
+/** 工单优先级枚举(work_order.order_level) */
+export const WO_LEVEL = {
+  EMERGENCY: 0,
+  NORMAL: 1,
+  LOW: 2
+}
+
 // 工单优先级:0-紧急 1-一般 2-低
 export const ORDER_LEVEL_MAP = {
-  0: { text: '紧急', type: 'danger' },
-  1: { text: '一般', type: 'warning' },
-  2: { text: '低', type: 'info' }
+  [WO_LEVEL.EMERGENCY]: { text: '紧急', type: 'danger' },
+  [WO_LEVEL.NORMAL]: { text: '一般', type: 'warning' },
+  [WO_LEVEL.LOW]: { text: '低', type: 'info' }
 }
 
 // 工单状态:0-待派单 1-待接单 2-已接单 3-处理中 4-待验收 5-已结案 6-延期中 7-已取消
@@ -73,7 +80,14 @@ export const ORDER_STATUS_GROUP = {
   pending: [WO_STATUS.PENDING_DISPATCH, WO_STATUS.PENDING_ACCEPT],
   processing: [WO_STATUS.ACCEPTED, WO_STATUS.PROCESSING, WO_STATUS.DELAYING],
   verifying: [WO_STATUS.PENDING_VERIFY],
-  finished: [WO_STATUS.CLOSED, WO_STATUS.CANCELLED]
+  finished: [WO_STATUS.CLOSED, WO_STATUS.CANCELLED],
+  // 待办口径(首页待办工单):待派单/待接单/已接单/处理中/延期中,
+  // 即「未办结」中剔除待验收(待验收已提交、不属于待办)
+  todo: [WO_STATUS.PENDING_DISPATCH, WO_STATUS.PENDING_ACCEPT, WO_STATUS.ACCEPTED,
+    WO_STATUS.PROCESSING, WO_STATUS.DELAYING],
+  // 未办结:与后端 WorkOrderStatusEnum.ACTIVE_CODES 对齐(不含已结案/已取消)
+  active: [WO_STATUS.PENDING_DISPATCH, WO_STATUS.PENDING_ACCEPT, WO_STATUS.ACCEPTED,
+    WO_STATUS.PROCESSING, WO_STATUS.PENDING_VERIFY, WO_STATUS.DELAYING]
 }
 
 // 工单操作日志类型(work_order_log.oper_type 数字枚举,从 0 开始)

+ 19 - 19
src/views/subSystem/waterSupply/monitorAlarm/workOrder.vue

@@ -171,54 +171,54 @@
                   <div class="action-buttons">
                     <el-button
                       v-if="canAccept()"
-                      v-hasPermi="['ops:pworkOrder:accept']"
+                      v-hasPermi="['ops:workOrder:accept']"
                       type="primary"
                       @click="handleAccept"
                     >接单</el-button>
                     <el-button
                       v-if="canStart()"
-                      v-hasPermi="['ops:pworkOrder:process']"
+                      v-hasPermi="['ops:workOrder:process']"
                       type="success"
                       @click="handleStart"
                     >开始处理</el-button>
                     <el-button
                       v-if="canDispatch()"
-                      v-hasPermi="['ops:pworkOrder:dispatch']"
+                      v-hasPermi="['ops:workOrder:dispatch']"
                       type="primary"
                       icon="Download"
                       @click="handleDispatch"
                     >下派任务</el-button>
                     <el-button
                       v-if="canVerify()"
-                      v-hasPermi="['ops:pworkOrder:accept']"
+                      v-hasPermi="['ops:workOrder:accept']"
                       type="warning"
                       icon="Check"
                       @click="handleVerify"
                     >核查</el-button>
                     <el-button
                       v-if="canProcess()"
-                      v-hasPermi="['ops:pworkOrder:process']"
+                      v-hasPermi="['ops:workOrder:process']"
                       type="success"
                       icon="Edit"
                       @click="handleProcess"
                     >处理</el-button>
                     <el-button
                       v-if="canComplete()"
-                      v-hasPermi="['ops:pworkOrder:submitVerify']"
+                      v-hasPermi="['ops:workOrder:submitVerify']"
                       type="danger"
                       icon="Checked"
                       @click="handleComplete"
                     >提交验收</el-button>
                     <el-button
                       v-if="canClose()"
-                      v-hasPermi="['ops:pworkOrder:verify']"
+                      v-hasPermi="['ops:workOrder:verify']"
                       type="success"
                       icon="CircleCheck"
                       @click="handleClose"
                     >验收通过</el-button>
                     <el-button
                       v-if="canReject()"
-                      v-hasPermi="['ops:pworkOrder:cancel']"
+                      v-hasPermi="['ops:workOrder:cancel']"
                       type="info"
                       icon="Close"
                       @click="handleReject"
@@ -359,7 +359,7 @@
 <script setup name="BusinessWorkOrder">
 import { ElMessage } from 'element-plus'
 import ImagePreview from '@/components/ImagePreview'
-import { listPworkOrder, getPworkOrder, dispatchPworkOrder, acceptPworkOrder, processPworkOrder, submitVerifyPworkOrder, verifyPworkOrder, cancelPworkOrder } from '@/api/pipeNetwork/ops/pworkOrder.js'
+import { listWorkOrder, getWorkOrder, dispatchWorkOrder, acceptWorkOrder, processWorkOrder, submitVerifyWorkOrder, verifyWorkOrder, cancelWorkOrder } from '@/api/pipeNetwork/ops/workOrder.js'
 import { listDept } from '@/api/system/dept'
 import { listUser } from '@/api/system/user'
 import { handleTree } from '@/utils/ruoyi'
@@ -456,7 +456,7 @@ const selectedUserNames = computed(() => {
 async function handleSearch() {
   listLoading.value = true
   try {
-    const res = await listPworkOrder({ ...queryParams, pageNum: pageNum.value, pageSize: pageSize.value })
+    const res = await listWorkOrder({ ...queryParams, pageNum: pageNum.value, pageSize: pageSize.value })
     const data = res.data || {}
     tableData.value = data.records || []
     total.value = data.total || 0
@@ -528,7 +528,7 @@ function handleDispatch() {
 
 async function handleAccept() {
   try {
-    await acceptPworkOrder({ orderId: selectedOrder.value.orderId })
+    await acceptWorkOrder({ orderId: selectedOrder.value.orderId })
     ElMessage.success('接单成功')
     await handleSearch()
     await loadOrderDetail(selectedOrder.value.orderId)
@@ -537,7 +537,7 @@ async function handleAccept() {
 
 async function handleStart() {
   try {
-    await processPworkOrder({ orderId: selectedOrder.value.orderId })
+    await processWorkOrder({ orderId: selectedOrder.value.orderId })
     ElMessage.success('已开始处理')
     await handleSearch()
     await loadOrderDetail(selectedOrder.value.orderId)
@@ -555,7 +555,7 @@ async function submitDispatch() {
     return
   }
   try {
-    await dispatchPworkOrder({
+    await dispatchWorkOrder({
       orderId: selectedOrder.value.orderId,
       handlerId: handlerIds[0],
       remarks: dispatchForm.remarks
@@ -604,9 +604,9 @@ async function submitAction() {
       content: actionFormData.solution
     }
     if (actionTitle.value === '核查工单') {
-      await acceptPworkOrder(data)
+      await acceptWorkOrder(data)
     } else {
-      await processPworkOrder(data)
+      await processWorkOrder(data)
     }
     ElMessage.success(actionTitle.value + '成功')
     actionDialogVisible.value = false
@@ -636,7 +636,7 @@ async function submitComplete() {
     return
   }
   try {
-    await submitVerifyPworkOrder({
+    await submitVerifyWorkOrder({
       orderId: selectedOrder.value.orderId,
       content: completeForm.result
     })
@@ -654,7 +654,7 @@ function handleReject() {
     ElMessage.warning('当前工单不允许取消')
     return
   }
-  cancelPworkOrder({ orderId: selectedOrder.value.orderId, content: '驳回工单' }).then(async () => {
+  cancelWorkOrder({ orderId: selectedOrder.value.orderId, content: '驳回工单' }).then(async () => {
     ElMessage.success('工单已驳回')
     await handleSearch()
     await loadOrderDetail(selectedOrder.value.orderId)
@@ -680,7 +680,7 @@ async function submitClose() {
     return
   }
   try {
-    await verifyPworkOrder({
+    await verifyWorkOrder({
       orderId: selectedOrder.value.orderId,
       passed: true,
       content: closeForm.result
@@ -718,7 +718,7 @@ function getLevelTag(level) {
 /** 加载工单详情和处理历史 */
 async function loadOrderDetail(orderId) {
   try {
-    const res = await getPworkOrder(orderId)
+    const res = await getWorkOrder(orderId)
     if (res.code === 200) {
       selectedOrder.value = { ...selectedOrder.value, ...res.data.order }
       currentOrderLogs.value = res.data.logs || []