fix: 设备运行时长应该是一直再走的一个时间,而不是点停止之后出来时间
已修改1个文件
132 ■■■■■ 文件已修改
src/views/equipmentManagement/operationManagement/index.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/operationManagement/index.vue
@@ -104,7 +104,7 @@
          align="center"
        >
          <template #default="scope">
            {{ scope.row.runtimeDuration || '-' }}
            {{ getRuntimeDurationDisplay(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column
@@ -154,7 +154,8 @@
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ref, onMounted, onUnmounted, computed } from 'vue'
import dayjs from 'dayjs'
import { ElMessage } from 'element-plus'
import {
  VideoPlay,
@@ -193,6 +194,98 @@
  return filtered
})
// 运行中无结束时间时,运行时长需随当前时间变化,用 tick 触发模板重算
const runtimeDisplayTick = ref(0)
/** 取后端可能使用的开始/结束时间字段 */
const pickStartTime = (row) => row?.startRuntimeTime ?? row?.startTime ?? row?.start_time
const pickEndTime = (row) => row?.endRuntimeTime ?? row?.endTime ?? row?.end_time
/**
 * 解析接口/前端写入的各类时间:时间戳、ISO 字符串、yyyy-MM-dd HH:mm:ss、Jackson 数组 [y,M,d,h,m,s]、含中文的 toLocaleString 等
 */
const parseDeviceTime = (input) => {
  if (input === null || input === undefined || input === '') return null
  if (typeof input === 'number' && !Number.isNaN(input)) {
    const d = dayjs(input)
    return d.isValid() ? d.toDate() : null
  }
  if (Array.isArray(input)) {
    const [y, mo, day, h = 0, mi = 0, se = 0] = input
    if (y == null || y === '') return null
    const d = dayjs()
        .year(Number(y))
        .month(Number(mo || 1) - 1)
        .date(Number(day || 1))
        .hour(Number(h) || 0)
        .minute(Number(mi) || 0)
        .second(Number(se) || 0)
    return d.isValid() ? d.toDate() : null
  }
  const s = String(input).trim()
  if (!s || s === '-') return null
  let d = dayjs(s)
  if (d.isValid()) return d.toDate()
  d = dayjs(s.replace(/-/g, '/'))
  if (d.isValid()) return d.toDate()
  d = dayjs(s.replace(/\//g, '-'))
  if (d.isValid()) return d.toDate()
  return null
}
const formatDurationMs = (durationMs) => {
  if (durationMs == null || Number.isNaN(durationMs) || durationMs < 0) return '-'
  const hours = Math.floor(durationMs / (1000 * 60 * 60))
  const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60))
  if (hours === 0 && minutes === 0) return '不足1分钟'
  return `${hours}小时${minutes}分钟`
}
const hasMeaningfulEnd = (endRaw) =>
    endRaw !== null &&
    endRaw !== undefined &&
    String(endRaw).trim() !== '' &&
    String(endRaw).trim() !== '-'
const formatStoredDuration = (row) => {
  const rd = row?.runtimeDuration
  if (rd === null || rd === undefined) return ''
  const t = String(rd).trim()
  return t === '' || t === '-' ? '' : String(rd)
}
/** 运行中:始终用「当前时间 - 开始时间」;已停止:优先接口 runtimeDuration,否则用结束-开始;无结束可看已存时长或动态推算 */
const getRuntimeDurationDisplay = (row) => {
  void runtimeDisplayTick.value
  const start = parseDeviceTime(pickStartTime(row))
  if (!start) {
    return formatStoredDuration(row) || '-'
  }
  const statusStr = String(row?.status ?? '').trim()
  const isRunning = statusStr === '运行中' || statusStr === '1'
  const endRaw = pickEndTime(row)
  const hasEnd = hasMeaningfulEnd(endRaw)
  // 无结束时间:运行中一定动态算;已停止则优先展示后端已存时长,没有再按当前时间推算
  if (!hasEnd) {
    if (isRunning) return formatDurationMs(Date.now() - start.getTime())
    const stored = formatStoredDuration(row)
    if (stored) return stored
    return formatDurationMs(Date.now() - start.getTime())
  }
  if (isRunning) {
    return formatDurationMs(Date.now() - start.getTime())
  }
  const end = parseDeviceTime(endRaw)
  const stored = formatStoredDuration(row)
  if (stored) return stored
  if (end) return formatDurationMs(end.getTime() - start.getTime())
  return '-'
}
// 检查设备是否超时未启动
const isOverdue = (device) => {
@@ -246,12 +339,11 @@
      device.endRuntimeTime = currentTime
      // 计算运行时长
      if (device.startRuntimeTime) {
        const startTime = new Date(device.startRuntimeTime)
        const endTime = new Date(currentTime)
        const duration = endTime - startTime
        const hours = Math.floor(duration / (1000 * 60 * 60))
        const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60))
        device.runtimeDuration = `${hours}小时${minutes}分钟`
        const startTime = parseDeviceTime(device.startRuntimeTime)
        const endTime = parseDeviceTime(currentTime)
        if (startTime && endTime) {
          device.runtimeDuration = formatDurationMs(endTime.getTime() - startTime.getTime())
        }
      }
    }
    const params = {
@@ -297,9 +389,31 @@
// 组件挂载时初始化数据
const POLL_MS = 60 * 1000
const RUNTIME_TICK_MS = 30 * 1000
let listPollTimer = null
let runtimeTickTimer = null
// 组件挂载时拉取数据,并每分钟刷新一次列表;运行中时长每 30 秒刷新显示
onMounted(() => {
  getList()
  listPollTimer = setInterval(() => {
    getList()
  }, POLL_MS)
  runtimeTickTimer = setInterval(() => {
    runtimeDisplayTick.value++
  }, RUNTIME_TICK_MS)
})
onUnmounted(() => {
  if (listPollTimer != null) {
    clearInterval(listPollTimer)
    listPollTimer = null
  }
  if (runtimeTickTimer != null) {
    clearInterval(runtimeTickTimer)
    runtimeTickTimer = null
  }
})
</script>