Browse Source

作业流程小平时当前以步骤为中心展示

wyn 3 months ago
parent
commit
372646d136
1 changed files with 70 additions and 24 deletions
  1. 70 24
      src/views/jobTicket/job/JobMonitor.vue

+ 70 - 24
src/views/jobTicket/job/JobMonitor.vue

@@ -16,7 +16,7 @@
         <p>作业类型: <span>{{ ticketTypeLabel }}</span></p>
         <p>作业状态: <span>{{ ticketStatusLabel }}</span></p>
         <p>开始时间: <span>{{JobForm.ticketStartTime}}</span> </p>
-        <p>结束时间: <span>{{JobForm.ticketEndTime}}</span> </p>
+        <p>结束时间: <span>{{JobForm.ticketEndTime || '-'}}  </span> </p>
         <p>当前步骤: <span class="specialText">{{ currentStepTitle }}</span> </p>
         <p>最新日志: <span>待更新</span> </p>
       </div>
@@ -33,8 +33,8 @@
       <div class="processDetail" ref="scrollContainer">
         <!-- VueFlow 主画布 -->
         <VueFlow style="width: 100%; height: 300px" :min-zoom="1" :max-zoom="1" :default-zoom="1" :nodes="nodes" :edges="edges">
-          <template #node-default="{ id, data }">
-            <div class="custom-node" :id="id">
+          <template #node-default="{ id, data }" >
+            <div class="custom-node" :id="id" >
               <div class="node-content">
                 <!-- 图标显示 -->
                 <div style="font-size: 30px">
@@ -295,9 +295,6 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import type { TableInstance } from 'element-plus'
 import { CaretRight } from '@element-plus/icons-vue'
 
-const tableLayout = ref<TableInstance['tableLayout']>('fixed')
-const tableLayout1 = ref<TableInstance['tableLayout1']>('fixed')
-
 const JobForm = reactive({
   createTime: null,
   id: null,
@@ -361,12 +358,13 @@ const joblogDialogVisible= ref(false)
 // 初始化
 onMounted(async () => {
   await getDetail()
+  //基础信息
   jobTypeOptions.value = await getIntDictOptions(DICT_TYPE.TICKET_TYPE)
   jobStatusOptions.value = await getIntDictOptions(DICT_TYPE.TICKET_STATUS)
   await fetchAllGroupsAndPoints() //获取所有分组和点位 来渲染SOP的首页
-  await onModeContent()
+  await onModeContent()  //作业流程
   window.addEventListener('resize', onResize)
-  await onResize()
+  onResize()
 })
 onBeforeUnmount(() => {
   window.removeEventListener('resize', onResize)
@@ -406,41 +404,67 @@ const getDetail = async () => {
 
 // 作业流程绘制
 const scrollContainer = ref(null)
+const nodes = ref([]) //储存节点
+const edges = ref([]) // 存储连接线
+const allSteps = ref([]) // 缓存完整流程数据
+const { addNodes, addEdges, setEdges, setNodes } = useVueFlow()
 
 const scrollToCurrentNode = () => {
   nextTick(() => {
-    if (!scrollContainer.value) return
+    const container = scrollContainer.value
+    if (!container) return
+
+    const currentIndex = nodes.value.findIndex(n => n.data.stepStatus === 0)
+    if (currentIndex === -1) return
 
-    const firstZeroIndex = nodes.value.findIndex(n => n.data.stepStatus === 0)
-    if (firstZeroIndex === -1) return
+    const currentNodeId = nodes.value[currentIndex]?.id
+    const nextNodeId = nodes.value[currentIndex + 1]?.id
 
-    const currentNodeId = nodes.value[firstZeroIndex].id
     const currentNodeEl = document.getElementById(currentNodeId)
+    const nextNodeEl = nextNodeId ? document.getElementById(nextNodeId) : null
+
     if (!currentNodeEl) return
 
-    // 计算滚动,让当前节点居中
-    const container = scrollContainer.value
-    const containerRect = container.getBoundingClientRect()
-    const nodeRect = currentNodeEl.getBoundingClientRect()
+    // 获取节点相对于容器的偏移位置
+    const currentLeft = currentNodeEl.offsetLeft
+    const currentWidth = currentNodeEl.offsetWidth
 
-    const offset = nodeRect.left - containerRect.left - (containerRect.width / 2) + (nodeRect.width / 2)
+    let centerPos = currentLeft + currentWidth / 2
 
-    container.scrollBy({
-      left: offset,
+    if (nextNodeEl) {
+      const nextLeft = nextNodeEl.offsetLeft
+      const nextWidth = nextNodeEl.offsetWidth
+      centerPos = (centerPos + nextLeft + nextWidth / 2) / 2
+    }
+
+    // 目标是让 centerPos 居中容器
+    const scrollTarget = centerPos - container.clientWidth / 2
+
+    container.scrollTo({
+      right: scrollTarget,
       behavior: 'smooth'
     })
   })
 }
 
 const onResize = () => {
-  if (window.innerWidth <= 600) {
+  const isMobile = window.innerWidth <= 600
+  const stepsData = [...allSteps.value] // 缓存的完整流程步骤数据
+
+  const currentIndex = stepsData.findIndex(item => item.stepStatus === 0)
+  const filtered = isMobile && currentIndex !== -1
+    ? stepsData.slice(currentIndex) // 小屏只显示当前及后续
+    : stepsData // 大屏恢复全部
+
+  renderNodesFromData(filtered)
+  renderEdgesFromData(filtered)
+
+  nextTick(() => {
     scrollToCurrentNode()
-  }
+  })
 }
 
-const nodes = ref([]) //储存节点
-const edges = ref([]) // 存储连接线
-const { addNodes, addEdges, setEdges, setNodes } = useVueFlow()
+
 // 模式初始化
 const onModeContent = async (value) => {
   JobForm.modeId = value
@@ -449,6 +473,24 @@ const onModeContent = async (value) => {
   const sortedData = Data.ticketStepList.sort((a, b) => (a.stepIndex || 0) - (b.stepIndex || 0))
   renderNodesFromData(sortedData)
   renderEdgesFromData(sortedData)
+  allSteps.value = sortedData // 缓存原始数据
+  renderResponsiveSteps()
+}
+const renderResponsiveSteps = () => {
+  const isMobile = window.innerWidth <= 600
+  const stepsData = [...allSteps.value]
+
+  const currentIndex = stepsData.findIndex(item => item.stepStatus === 0)
+  const filtered = isMobile && currentIndex !== -1
+    ? stepsData.slice(currentIndex) // 从当前步骤开始
+    : stepsData // 全部步骤
+
+  renderNodesFromData(filtered)
+  renderEdgesFromData(filtered)
+
+  nextTick(() => {
+    scrollToCurrentNode()
+  })
 }
 
 // 独立的清空画布函数
@@ -512,6 +554,10 @@ const renderNodesFromData = (data) => {
       draggable: false //设置是否可以拖动生成的图
     })
   })
+  nextTick(() => {
+    scrollToCurrentNode()
+  })
+
 }
 
 // const renderNodesFromData = (data) => {