فهرست منبع

完善窨井-运维任务管理

zengy 9 ساعت پیش
والد
کامیت
7cecd3c443
5فایلهای تغییر یافته به همراه49 افزوده شده و 115 حذف شده
  1. 0 3
      .env.development
  2. 0 3
      .env.production
  3. 0 2
      src/App.vue
  4. 0 106
      src/utils/deviceStatusWebSocket.js
  5. 49 1
      src/views/subSystem/manholeCover/operation/operationTask.vue

+ 0 - 3
.env.development

@@ -9,6 +9,3 @@ VITE_APP_BASE_API = '/dev-api'
 
 # MinIO文件访问基础地址
 VITE_APP_MINIO_BASE_URL = 'http://111.23.174.45:9000/pipe/'
-
-# 百度地图 WebGL AK
-VITE_BAIDU_MAP_AK = 'vMma3LYQQyrfhlFUm0CFzXFQhBrwxAmi'

+ 0 - 3
.env.production

@@ -12,6 +12,3 @@ VITE_BUILD_COMPRESS = gzip
 
 # MinIO 统一通过同源 Nginx 路径访问,不在前端绑定服务器 IP
 VITE_APP_MINIO_BASE_URL = '/minio/pipe/'
-
-# PC 工单 WebSocket 由 Nginx 同源转发到后端
-VITE_DEVICE_STATUS_WS_URL = ''

+ 0 - 2
src/App.vue

@@ -5,11 +5,9 @@
 <script setup>
 import useSettingsStore from '@/store/modules/settings'
 import { handleThemeStyle } from '@/utils/theme'
-import { startWorkOrderReminder } from '@/utils/deviceStatusWebSocket'
 import { connectSse } from '@/utils/dispatchSse'
 
 onMounted(() => {
-  startWorkOrderReminder()
   // 应急调度:SSE 实时消息(催办提醒等),登录后自动建立连接
   connectSse()
   nextTick(() => {

+ 0 - 106
src/utils/deviceStatusWebSocket.js

@@ -1,106 +0,0 @@
-import { ref } from 'vue'
-import { ElNotification } from 'element-plus'
-import { getToken } from '@/utils/auth'
-
-const DEFAULT_URL = `${location.protocol === 'https:' ? 'wss:' : 'ws:'}//${location.host}/pipe/ws/deviceStatus`
-
-export const workOrders = ref([])
-export const workOrderTotal = ref(0)
-export const workOrderWsState = ref('closed')
-
-let socket = null
-let heartbeatTimer = null
-let reconnectTimer = null
-let stopped = true
-let reconnectAttempts = 0
-let initialized = false
-let lastOrderIds = new Set()
-
-function send(data) {
-  if (socket && socket.readyState === WebSocket.OPEN) socket.send(JSON.stringify(data))
-}
-function clearTimers() {
-  if (heartbeatTimer) clearInterval(heartbeatTimer)
-  if (reconnectTimer) clearTimeout(reconnectTimer)
-  heartbeatTimer = null
-  reconnectTimer = null
-}
-function scheduleReconnect() {
-  if (stopped || reconnectTimer) return
-  const delay = Math.min(30000, 5000 * Math.pow(2, reconnectAttempts++))
-  reconnectTimer = setTimeout(() => { reconnectTimer = null; connect() }, delay)
-}
-function notifyNewOrders(items) {
-  const newItems = items.filter(item => {
-    const id = String(item.orderId || item.orderNo || '')
-    return id && !lastOrderIds.has(id)
-  })
-  lastOrderIds = new Set(items.map(item => String(item.orderId || item.orderNo || '')).filter(Boolean))
-  if (initialized && newItems.length) {
-    const first = newItems[0]
-    ElNotification({
-      title: '工单提醒',
-      message: newItems.length === 1 ? `${first.orderNo || '新工单'}:${first.orderDesc || '有新的待处理工单'}` : `收到 ${newItems.length} 条新的待处理工单`,
-      type: 'warning',
-      duration: 5000
-    })
-  }
-  initialized = true
-}
-function startHeartbeat() {
-  if (heartbeatTimer) clearInterval(heartbeatTimer)
-  heartbeatTimer = setInterval(() => send({ type: 'ping' }), 25000)
-}
-function connect() {
-  if (stopped || (socket && [WebSocket.CONNECTING, WebSocket.OPEN].includes(socket.readyState))) return
-  const rawToken = getToken()
-  if (!rawToken) { workOrderWsState.value = 'waiting-token'; scheduleReconnect(); return }
-  clearTimers()
-  workOrderWsState.value = 'connecting'
-  try {
-    socket = new WebSocket(import.meta.env.VITE_DEVICE_STATUS_WS_URL || DEFAULT_URL)
-    socket.onopen = () => {
-      reconnectAttempts = 0
-      const token = rawToken.startsWith('Bearer ') ? rawToken : `Bearer ${rawToken}`
-      send({ type: 'authenticate', token })
-    }
-    socket.onmessage = event => {
-      let message
-      try { message = JSON.parse(event.data) } catch { return }
-      if (message.type === 'authenticated') {
-        if (!message.success) { workOrderWsState.value = 'auth-failed'; stopped = true; socket.close(); return }
-        workOrderWsState.value = 'open'
-        send({ type: 'workOrderReminder' })
-        startHeartbeat()
-        return
-      }
-      if (message.type === 'workOrderReminderPush' || message.type === 'workOrderReminder') {
-        if (!message.success) return
-        const data = message.data || {}
-        const items = Array.isArray(data.items) ? data.items : []
-        workOrders.value = items
-        workOrderTotal.value = Number(data.total || 0)
-        notifyNewOrders(items)
-      }
-    }
-    socket.onerror = () => { workOrderWsState.value = 'error' }
-    socket.onclose = () => {
-      clearTimers(); socket = null
-      if (!stopped) { workOrderWsState.value = 'closed'; scheduleReconnect() }
-    }
-  } catch (error) {
-    workOrderWsState.value = 'error'; socket = null; scheduleReconnect()
-  }
-}
-export function startWorkOrderReminder() {
-  stopped = false
-  connect()
-  return { workOrders, workOrderTotal, workOrderWsState }
-}
-export function stopWorkOrderReminder() {
-  stopped = true
-  clearTimers()
-  if (socket) socket.close(1000, 'application stop')
-  socket = null
-  workOrderWsState.value = 'closed'
-}

+ 49 - 1
src/views/subSystem/manholeCover/operation/operationTask.vue

@@ -1,6 +1,16 @@
 <!--运维任务管理 - 窨井设备待派单工单(内联复用 workOrder/list.vue 的列表,固定查 order_status=0 + rootTypeId=4)-->
 <template>
   <div class="operation-task">
+    <!-- 页头:功能描述 -->
+    <div class="page-head">
+      <div class="page-head-titles">
+        <div class="page-title">
+          <el-icon class="page-title-icon"><Tickets /></el-icon>
+          <span>待派单运维任务</span>
+        </div>
+      </div>
+    </div>
+
     <!-- 搜索栏 -->
     <el-card shadow="never" class="search-card">
       <el-form :model="queryParams" inline class="search-form" @submit.prevent>
@@ -73,7 +83,14 @@
             <el-tag :type="orderStatusType(row.orderStatus)">{{ orderStatusText(row.orderStatus) }}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="操作" width="160" align="center" fixed="right">
+        <el-table-column
+          label="操作"
+          width="160"
+          align="center"
+          fixed="right"
+          class-name="op-col-divider"
+          label-class-name="op-col-divider"
+        >
           <template #default="{ row }">
             <el-button link type="primary" @click="goDispatch(row)">派单</el-button>
             <el-button link type="primary" @click="openHistory(row)">历史处置</el-button>
@@ -240,6 +257,32 @@ function goDispatch(row) {
   min-height: calc(100vh - 84px);
 }
 
+/* 页头 */
+.page-head {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 20px;
+}
+.page-head-titles {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  min-width: 0;
+}
+.page-title {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #0a1628;
+}
+.page-title-icon {
+  color: #014db2;
+  font-size: 22px;
+}
+
 .search-card {
   margin-bottom: 12px;
 }
@@ -255,6 +298,11 @@ function goDispatch(row) {
   }
 }
 
+/* 操作列为固定列(fixed=right),Element Plus 固定列默认缺失左侧分割线,这里补上 */
+:deep(.el-table .op-col-divider) {
+  border-left: 1px solid var(--el-table-border-color) !important;
+}
+
 /* 单元格内省略:交给自定义 tooltip 展示全文 */
 .desc-cell {
   display: inline-block;