<template>
  <div
    id="screen"
    class="allShow"
    :style="{
      width: `${style.width}px`,
      height: `${style.height}px`,
      transform: `${style.transform}`,
    }"
  >
    <header class="df-header">
      <div class="df-header__left" />
      <div class="df-header__center">
        <span class="df-header__title">{{ titleText }}</span>
        <!-- <img class="df-header__title-img" src="/png/智能制造数字孪生系统.png" alt="智能制造数字孪生系统" /> -->
      </div>
      <div class="df-header__right">
          <div class="df-header__timebar">
            <span class="df-header__time">{{ headerTime }}</span>
            <span class="df-header__sep">|</span>
            <div class="df-header__date-wrapper">
              <span class="df-header__year">{{ headerDateCn }}</span>
              <span class="df-header__week">{{ headerWeekCn }}</span>
            </div>
          </div>
        </div>
        <img style="width: 200px; height: 30px;position: absolute;left:55px;top: 20px;" src="/png/logo.png" alt="东方理工大学logo">
    </header>
    <el-row>
      <div class="main-content">
        <div style="height: 100%; width: 100%; position: absolute">
          <iframe
            id="dmtIframe"
            :src="iframeAddress"
            style="
              width: 100%;
              height: 1080px;
              border: none;
              filter: blur(10);
              z-index: 100;
            " />
        </div>

        <!-- 日产量模块 -->
        <div
          :style="{ display: isShow }"
          class="daily-output-box"
        >
          <div class="daily-output-header">
            <span class="box-title">日产量</span>
          </div>
          <div class="daily-output-body">
            <div id="dailyOutputChart" class="daily-output-chart" />
          </div>
        </div>
       <!-- 零部件智能预测性维护模块 -->
        <div :style="{ display: isShow }" class="component-maintenance-box">
          <div class="component-maintenance-header" style="padding-left: 10px;">
            <span class="box-title">零部件智能预测性维护</span>
          </div>
          <div class="component-maintenance-body">
            <div id="componentMaintenanceChart" class="component-maintenance-chart" />
          </div>
        </div>

        <!-- 设备状态模块 -->
        <div :style="{ display: isShow }" class="device-status-box" style="height: 305px;">
          <div class="device-status-header">
            <span class="box-title">设备状态</span>
          </div>
          <div class="device-status-body">
            <div class="device-status-table">
              <div class="device-status-row device-status-row--header">
                <div class="device-status-cell">工位</div>
                <div class="device-status-cell">工位名称</div>
                <div class="device-status-cell">手自动</div>
                <div class="device-status-cell">状态</div>
              </div>
              <div v-for="(row, index) in deviceStatusList" :key="index" class="device-status-row">
                <div class="device-status-cell">{{ row.station }}</div>
                <div class="device-status-cell">{{ row.stationName }}</div>
                <div class="device-status-cell">{{ row.mode }}</div>
                <div class="device-status-cell">
                  <span class="device-status-pill" :class="`device-status-pill--${row.statusType}`">
                    {{ row.statusText }}
                  </span>
                </div>
              </div>
            </div>
          </div>
        </div>
        <!-- 库位状态模块 -->
        <div
          :style="{ display: isShow }"
          class="storage-status-box"
        >
          <div class="storage-status-header">
            <span class="box-title">库位状态</span>
          </div>
          <div class="storage-status-body">
            <div class="storage-status-grid">
              <div
                v-for="item in storageStatusList"
                :key="item.id"
                class="storage-status-cell"
                :class="item.active ? 'storage-status-cell--active' : 'storage-status-cell--inactive'"
              >
                {{ item.label }}
              </div>
            </div>
          </div>
        </div>

        <!-- 小时产品模块 -->
        <div
          :style="{ display: isShow }"
          class="hourly-output-box"
        >
          <div class="hourly-output-header">
            <span class="box-title">小时产品</span>
          </div>
          <div class="hourly-output-body">
            <div id="hourlyOutputChart" class="hourly-output-chart" />
          </div>
        </div>

        <!-- 故障统计模块 -->
        <div
          :style="{ display: isShow }"
          class="fault-stats-box"
          style="height: 305px;"
        >
          <div class="fault-stats-header">
            <span class="box-title">故障统计</span>
          </div>
          <div class="fault-stats-body">
            <div class="fault-stats-legend">
              <div v-for="(item, index) in faultStatsData" :key="index" class="fault-stats-item">
                <span class="fault-stats-dot" :style="{ backgroundColor: item.itemStyle && item.itemStyle.color ? item.itemStyle.color : '#50edff' }"></span>
                <span class="fault-stats-text" :title="item.name">{{ formatFaultLegendName(item.name) }}</span>
              </div>
            </div>
            <div id="faultStatsChart" class="fault-stats-chart" />
          </div>
        </div>
        <div :style="{ display: isShow }" class="status-timeline-box" style="height: 305px;">
          <div class="device-status-header status-timeline-header">
            <span class="box-title">设备运行履历</span>
          </div>
          <div class="bb-chart-container bb-chart-container--timeline">
            <div id="dashboardDeviceStatus" class="bb-chart bb-chart--status" />
          </div>
        </div>
        <div :style="{ display: isShow }" class="platform-credit">
          大连昆宇智能科技有限责任公司数字孪生平台制作
        </div>
      </div>
    </el-row>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import 'echarts-gl'
import DMT from '../components/DMT/index'
import $ from 'jquery'
export default {
  name: 'BeiDaFangZheng',
  components: { DMT },
  data() {
    return {
      style: {
        width: '1920',
        height: '1080',
        transform: 'scaleY(1) scaleX(1) translate(-50%, -50%)'
      },
      titleText: window.dt_Config?.titleText,
      isShow: 'inline',
      src: localStorage.getItem('twinAddress'),
      deviceStatusTable: [],
      data: [],
      index: 0,
      colors: [],
      workstationStatusLoading: false,
      workstationStatusTimer: null,
      equipmentRuntimeHistoryLoading: false,
      equipmentRuntimeHistoryRefreshTimer: null,
      storageStatusLoading: false,
      storageStatusTimer: null,
      deviceStatusList: [
        { station: 'OP1010', stationName: '3D打印机', mode: '自动', statusText: '运行', statusType: 'running' },
        { station: 'OP1010', stationName: '加工单元', mode: '自动', statusText: '报警', statusType: 'alarm' },
        { station: 'OP1010', stationName: '检测', mode: '自动', statusText: '待机', statusType: 'standby' },
        { station: 'OP1010', stationName: '装配', mode: '自动', statusText: '运行', statusType: 'running' },
        { station: 'OP1010', stationName: '打标', mode: '自动', statusText: '离线', statusType: 'offline' }
      ],
      storageStatusList: [
        { id: 11, label: 'L-3-1', active: false },
        { id: 12, label: 'L-3-2', active: false },
        { id: 13, label: 'L-3-3', active: false },
        { id: 14, label: 'L-3-4', active: false },
        { id: 15, label: 'L-3-5', active: false },
        { id: 6, label: 'L-2-1', active: false },
        { id: 7, label: 'L-2-2', active: false },
        { id: 8, label: 'L-2-3', active: false },
        { id: 9, label: 'L-2-4', active: false },
        { id: 10, label: 'L-2-5', active: false },
        { id: 1, label: 'L-1-1', active: false },
        { id: 2, label: 'L-1-2', active: false },
        { id: 3, label: 'L-1-3', active: false },
        { id: 4, label: 'L-1-4', active: false },
        { id: 5, label: 'L-1-5', active: false },
        { id: 26, label: 'R-3-1', active: false },
        { id: 27, label: 'R-3-2', active: false },
        { id: 28, label: 'R-3-3', active: false },
        { id: 29, label: 'R-3-4', active: false },
        { id: 30, label: 'R-3-5', active: false },
        { id: 21, label: 'R-2-1', active: false },
        { id: 22, label: 'R-2-2', active: false },
        { id: 23, label: 'R-2-3', active: false },
        { id: 24, label: 'R-2-4', active: false },
        { id: 25, label: 'R-2-5', active: false },
        { id: 16, label: 'R-1-1', active: false },
        { id: 17, label: 'R-1-2', active: false },
        { id: 18, label: 'R-1-3', active: false },
        { id: 19, label: 'R-1-4', active: false },
        { id: 20, label: 'R-1-5', active: false }
      ],
      deviceStatusChart: null, // 设备运行状态图表
      statusTimelineStations: ['OP10', 'OP20', 'OP30', 'OP40'],
      componentMaintenanceChart: null, // 零部件预测性维护图表
      dailyOutputChart: null, // 日产量图表
      hourlyOutputChart: null, // 小时产品图表
      hourlyOutputTimes: [],
      hourlyOutputValues: [],
      hourlyOutputLoading: false,
      hourlyOutputRefreshTimer: null,
      componentMaintenanceLoading: false,
      componentMaintenanceRefreshTimer: null,
      faultStatsLoading: false,
      faultStatsRefreshTimer: null,
      faultStatsChart: null,
      faultStatsData: [],
      // 日产量数据（只使用存储过程返回的数据）
      dailyOutputDates: [],
      dailyOutputValues: [],
      dailyOutputLoading: false,
      dailyOutputRefreshTimer: null,
      // 零部件预测性维护数据
      componentNames: [],
      predictedHours: [],
      usedHours: [],
      remainingHours: [],
      date: new Date(),
      year: '',
      month: '',
      day: '',
      minute: '',
      hour: '',
      second: '',
      week: '',
      PageCount: 0,
      total: 0, // 总条数
      iframe: '',
      iframeAddress: ''
    }
  },
  created() {
    this.iframe = document.getElementById('dmtIframe')
    this.iframeAddress = window.dt_Config?.iframeAddress
    this.loadStorageStatus // 当前_立库状态_查询
    this.loadDailyOutputHistory // 测量数据合格索引_日产量查询
    this.loadHourlyOutputHistory // 测量数据合格索引_小时产量查询
    this.loadFaultStatsHistory // 报警_记录_历史_查询_简化版
    this.loadEquipmentRuntimeHistory() // 历史_工位设备状态每分钟记录_查询
    this.loadWorkstationStatus() // 基础_工位_查询
  },
  mounted() {
    const _this = this // 声明一个变量指向Vue实例this，保证作用域一致
    this.timer = setInterval(() => {
      _this.date = new Date()
      this.year = new Date().getFullYear() + 1 < 10 ? '0' + (new Date().getFullYear() + 1) : new Date().getFullYear()
      this.month = new Date().getMonth() + 1 < 10 ? '0' + (new Date().getMonth() + 1) : new Date().getMonth() + 1
      this.day = new Date().getDate() < 10 ? '0' + new Date().getDate() : new Date().getDate()
      this.hour = new Date().getHours() < 10 ? '0' + new Date().getHours() : new Date().getHours()
      this.minute = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes()
      this.second = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds()
      this.week = '日一二三四五六'.charAt(new Date().getDay())
    }, 1000)
    this.initEcharts()
    this.startEquipmentRuntimeHistoryRefresh() // 每分钟刷新一次设备运行履历
    this.startComponentMaintenanceRefresh() // 每小时刷新一次零部件智能预测性维护
    this.startDailyOutputHistoryRefresh() // 每分钟刷新一次最近七日产量数据
    this.startWorkstationStatusRefresh() // 设备状态模块：每秒刷新一次（调用存储过程：基础_工位_查询）
    this.startStorageStatusRefresh() // 库位状态模块：每秒刷新一次（调用存储过程：当前_立库状态_查询）
    this.startHourlyOutputHistoryRefresh() // 每分钟刷新一次小时产量（最近24小时）
    this.startFaultStatsRefresh() // 每分钟刷新一次故障统计（过去24小时）
    this.setScale()
    this.$nextTick(() => {
      $(window).on('resize', () => {
        if (this.dailyOutputChart) this.dailyOutputChart.resize()
        if (this.componentMaintenanceChart) this.componentMaintenanceChart.resize()
        if (this.hourlyOutputChart) this.hourlyOutputChart.resize()
        if (this.faultStatsChart) this.faultStatsChart.resize()
      })
    })
    /* 窗口改变事件*/
    $(window).resize(() => {
      this.setScale()
    })
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
    }
    if (this.dailyOutputRefreshTimer) {
      clearInterval(this.dailyOutputRefreshTimer)
      this.dailyOutputRefreshTimer = null
    }
    if (this.workstationStatusTimer) {
      clearInterval(this.workstationStatusTimer)
      this.workstationStatusTimer = null
    }
    if (this.equipmentRuntimeHistoryRefreshTimer) {
      clearInterval(this.equipmentRuntimeHistoryRefreshTimer)
      this.equipmentRuntimeHistoryRefreshTimer = null
    }
    if (this.storageStatusTimer) {
      clearInterval(this.storageStatusTimer)
      this.storageStatusTimer = null
    }
    if (this.componentMaintenanceRefreshTimer) {
      clearInterval(this.componentMaintenanceRefreshTimer)
      this.componentMaintenanceRefreshTimer = null
    }
    if (this.hourlyOutputRefreshTimer) {
      clearInterval(this.hourlyOutputRefreshTimer)
      this.hourlyOutputRefreshTimer = null
    }
    if (this.faultStatsRefreshTimer) {
      clearInterval(this.faultStatsRefreshTimer)
      this.faultStatsRefreshTimer = null
    }
  },
  computed: {
    headerTime() {
      const d = this.date instanceof Date ? this.date : new Date()
      const hh = String(d.getHours()).padStart(2, '0')
      const mm = String(d.getMinutes()).padStart(2, '0')
      return `${hh}:${mm}`
    },
    headerDate() {
      const d = this.date instanceof Date ? this.date : new Date()
      const y = d.getFullYear()
      const m = String(d.getMonth() + 1).padStart(2, '0')
      const day = String(d.getDate()).padStart(2, '0')
      return `${y}/${m}/${day}`
    },
    headerDateCn() {
      const d = this.date instanceof Date ? this.date : new Date()
      const y = d.getFullYear()
      const m = d.getMonth() + 1
      const day = d.getDate()
      return `${y}年${m}月${day}日`
    },
    headerWeekCn() {
      const d = this.date instanceof Date ? this.date : new Date()
      const map = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
      return map[d.getDay()] || '星期'
    }
  },
  methods: {
    getScale() {
      const w = window.innerWidth / this.style.width
      const h = window.innerHeight / this.style.height
      return { x: w, y: h }
    },
    setScale() {
      const scale = this.getScale()
      this.style.transform = 'scaleY(' + scale.y + ') scaleX(' + scale.x + ') translate(-50%, -50%)'
    },
    initEcharts() {
      // 设备运行履历甘特图
      this.deviceStatusChart = echarts.init(document.getElementById('dashboardDeviceStatus'))
      // 零部件预测性维护柱状图
      const maintenanceEl = document.getElementById('componentMaintenanceChart')
      if (maintenanceEl) {
        this.componentMaintenanceChart = echarts.init(maintenanceEl)
        this.loadComponentMaintenanceData()
      }
      // 日产量柱状图
      const dailyEl = document.getElementById('dailyOutputChart')
      if (dailyEl) {
        this.dailyOutputChart = echarts.init(dailyEl)
        this.initDailyOutputData()
        this.drawDailyOutputChart()
        this.loadDailyOutputHistory()
      }
      // 小时产量柱状图
      const hourlyEl = document.getElementById('hourlyOutputChart')
      if (hourlyEl) {
        this.hourlyOutputChart = echarts.init(hourlyEl)
        this.initHourlyOutputData()
        this.drawHourlyOutputChart()
        this.loadHourlyOutputHistory()
      }
      // 故障统计柱状图
      const faultEl = document.getElementById('faultStatsChart')
      if (faultEl) {
        this.faultStatsChart = echarts.init(faultEl)
        this.drawFaultStatsChart()
      }
    },
    // 库位状态模块：每秒刷新一次（调用存储过程：当前_立库状态_查询）
    startStorageStatusRefresh() {
      if (this.storageStatusTimer) {
        clearInterval(this.storageStatusTimer)
        this.storageStatusTimer = null
      }
      this.storageStatusTimer = setInterval(() => {
        this.loadStorageStatus()
      }, 1000)
      this.loadStorageStatus()
    },
    loadStorageStatus() {
      if (this.storageStatusLoading) return
      const baseList = Array.isArray(this.storageStatusList) ? this.storageStatusList : []
      if (!baseList.length) return

      this.storageStatusLoading = true
      const param = [] // 无入参
      const data = this.CreateData('11', '当前_立库状态_查询', param)
      this.ExecDatabase(data)
        .then((response) => {
          const list = response && response.data ? response.data : null
          if (!Array.isArray(list)) return

          const normalizeLocation = (v) => {
            if (v == null) return ''
            return String(v).trim().toUpperCase()
          }

          const map = new Map()
          list.forEach((row) => {
            const kw = row && (row['库位'] != null ? row['库位'] : row.库位)
            const yl = row && (row['有料'] != null ? row['有料'] : row.有料)
            const location = normalizeLocation(kw)
            if (!location) return
            map.set(location, Number(yl) === 1)
          })

          // 保持页面原有库位顺序不变：按完整库位编号更新 active，避免 L-1-1 / L-1-2 等被数字 1 误匹配
          this.storageStatusList = baseList.map((cell) => {
            const location = normalizeLocation(cell && cell.label)
            const active = map.has(location) ? map.get(location) : false
            return { ...cell, active }
          })
        })
        .catch((err) => {
          console.error('当前_立库状态_查询失败', err)
        })
        .then(() => {
          this.storageStatusLoading = false
        })
    },
    // 设备状态模块：每秒刷新一次（调用存储过程：基础_工位_查询）
    startWorkstationStatusRefresh() {
      if (this.workstationStatusTimer) {
        clearInterval(this.workstationStatusTimer)
        this.workstationStatusTimer = null
      }
      this.workstationStatusTimer = setInterval(() => {
        this.loadWorkstationStatus()
      }, 1000)
    },
    loadWorkstationStatus() {
      if (this.workstationStatusLoading) return
      this.workstationStatusLoading = true

      const param = [] // 无入参
      const data = this.CreateData('11', '基础_工位_查询', param)
      this.ExecDatabase(data)
        .then((response) => {
          const list = response && response.data ? response.data : null
          if (!Array.isArray(list)) return

          const mapStatus = (code) => {
            const c = Number(code)
            if (c === -1) return { statusText: '离线', statusType: 'offline' }
            if (c === 0) return { statusText: '待机', statusType: 'standby' }
            if (c === 1) return { statusText: '运行', statusType: 'running' }
            if (c === 2) return { statusText: '报警', statusType: 'alarm' }
            return { statusText: '未知', statusType: 'offline' }
          }

          this.deviceStatusList = list.map((item) => {
            const station = item && (item['工位号'] != null ? String(item['工位号']) : '')
            const stationName = item && (item['工位名称'] != null ? String(item['工位名称']) : '')
            const statusCode = item && (item['状态代码'] != null ? item['状态代码'] : null)
            const st = mapStatus(statusCode)
            return {
              station,
              stationName,
              mode: '自动',
              statusText: st.statusText,
              statusType: st.statusType
            }
          })
        })
        .catch((err) => {
          console.error('基础_工位_查询失败', err)
        })
        .then(() => {
          this.workstationStatusLoading = false
        })
    },
    // 每分钟刷新一次最近七日产量数据
    startDailyOutputHistoryRefresh() {
      if (this.dailyOutputRefreshTimer) {
        clearInterval(this.dailyOutputRefreshTimer)
        this.dailyOutputRefreshTimer = null
      }
      this.dailyOutputRefreshTimer = setInterval(() => {
        this.loadDailyOutputHistory()
      }, 60 * 1000)
    },
    // 初始化日产量数据（首次为空，由存储过程填充）
    initDailyOutputData() {
      this.dailyOutputDates = []
      this.dailyOutputValues = []
    },
    // 拉取日产量数据（调用存储过程：测量数据合格索引_日产量查询）
    loadDailyOutputHistory() {
      if (this.dailyOutputLoading) return
      if (!this.dailyOutputChart) return
      this.dailyOutputLoading = true

      const param4 = [] // 无入参
      const Data4 = this.CreateData('11', '测量数据合格索引_日产量查询', param4)
      this.ExecDatabase(Data4)
        .then(response => {
          const list = response && response.data ? response.data : null
          if (!Array.isArray(list) || list.length === 0) {
            // 查询不到数据：清空数据，在图表中显示“暂无最近七日产量数据”
            this.dailyOutputDates = []
            this.dailyOutputValues = []
            this.drawDailyOutputChart()
            return
          }

          // 兼容存储过程返回多行时按日期汇总
          const parseDate = (rawDate) => {
            if (rawDate == null) return null
            // 优先从字符串中直接截取 YYYY-MM-DD，避免时区造成的日期偏移
            if (typeof rawDate === 'string') {
              const m = rawDate.match(/^(\d{4})[-\/.](\d{1,2})[-\/.](\d{1,2})/)
              if (m) {
                const y = String(m[1]).padStart(4, '0')
                const mo = String(m[2]).padStart(2, '0')
                const da = String(m[3]).padStart(2, '0')
                const key = `${y}-${mo}-${da}`
                return { key, md: `${mo}-${da}`, time: new Date(`${key}T00:00:00`).getTime() }
              }
            }
            const dt = rawDate instanceof Date ? rawDate : new Date(rawDate)
            if (!dt || Number.isNaN(dt.getTime())) return null
            const y = String(dt.getFullYear()).padStart(4, '0')
            const mo = String(dt.getMonth() + 1).padStart(2, '0')
            const da = String(dt.getDate()).padStart(2, '0')
            const key = `${y}-${mo}-${da}`
            return { key, md: `${mo}-${da}`, time: new Date(`${key}T00:00:00`).getTime() }
          }

          const sumByDate = new Map()
          list.forEach((item) => {
            const rawDate = item && (item['日期'] != null ? item['日期'] : item.日期)
            const rawValue = item && (item['产量'] != null ? item['产量'] : item.产量)
            const d = parseDate(rawDate)
            if (!d) return
            const num = Number(rawValue)
            if (!Number.isFinite(num)) return
            const prev = sumByDate.get(d.key)
            if (prev) {
              prev.sum += num
            } else {
              sumByDate.set(d.key, { md: d.md, time: d.time, sum: num })
            }
          })

          const sorted = Array.from(sumByDate.values()).sort((a, b) => a.time - b.time)
          const dates = sorted.map((d) => d.md)
          const values = sorted.map((d) => Math.round(Number(d.sum) || 0))

          this.dailyOutputDates = dates
          this.dailyOutputValues = values
          this.drawDailyOutputChart()
        })
        .catch(err => {
          console.error('测量数据合格索引_日产量查询失败', err)
          this.dailyOutputDates = []
          this.dailyOutputValues = []
          this.drawDailyOutputChart()
        })
        .then(() => {
          this.dailyOutputLoading = false
        })
    },
    // 绘制日产量3D柱状图
    drawDailyOutputChart() {
      if (!this.dailyOutputChart) return
      const data = this.dailyOutputValues || []
      const dates = this.dailyOutputDates || []

      // 先清空，避免上一次的图形或文字残留
      this.dailyOutputChart.clear()

      // 如果没有任何数据，就只显示“暂无最近七日产量数据”提示
      if (!data.length || !dates.length) {
        const optionEmpty = {
          backgroundColor: 'transparent',
          animation: false,
          xAxis: { show: false, type: 'category', data: [] },
          yAxis: { show: false, type: 'value' },
          series: [],
          graphic: {
            type: 'text',
            left: 'center',
            top: 'middle',
            style: {
              text: '暂无最近七日产量数据',
              fill: '#7fd7ff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        }
        this.dailyOutputChart.setOption(optionEmpty)
        return
      }

      const constData = []
      const showData = []
      data.forEach(val => {
        if (val != null) {
          constData.push(1)
          showData.push(val)
        } else {
          constData.push(0)
          showData.push({
            value: 1,
            itemStyle: {
              normal: {
                borderColor: 'rgba(0,0,0,0)',
                borderWidth: 2,
                color: 'rgba(0,0,0,0)'
              }
            }
          })
        }
      })
      const colorArr = ['#C5E0EC', '#8CBFD4', '#D8EAF2']
      const linearColor = {
        type: 'linear',
        x: 0,
        x2: 1,
        y: 0,
        y2: 0,
        colorStops: [
          { offset: 0, color: colorArr[0] },
          { offset: 0.5, color: colorArr[0] },
          { offset: 0.5, color: colorArr[1] },
          { offset: 1, color: colorArr[1] }
        ]
      }
      const barWidth = 26
      const option = {
        backgroundColor: 'transparent',
        animation: false,
        grid: {
          top: '10%',
          bottom: '11%',
          left: '8%',
          right: '4%'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
          formatter: (params) => {
            const p = params && params[0]
            if (!p) return ''
            return `${p.axisValue}<br/>日产量：${p.value}`
          }
        },
        xAxis: {
          type: 'category',
          data: dates,
          axisLabel: {
            color: '#7fd7ff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          axisTick: { show: false }
        },
        yAxis: {
          type: 'value',
          axisLabel: {
            color: '#7fd7ff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          splitLine: {
            lineStyle: { color: '#1B3F66' }
          }
        },
        graphic: [],
        series: [
          {
            z: 1,
            type: 'bar',
            name: '日产量',
            barWidth,
            itemStyle: {
              borderRadius: [0, 0, 0, 0],
              color: linearColor
            },
            data: data
          },
          {
            z: 2,
            name: '日产量底座',
            type: 'pictorialBar',
            data: constData,
            symbol: 'diamond',
            symbolOffset: ['0%', '50%'],
            symbolSize: [barWidth - 4, 10],
            itemStyle: {
              normal: {
                color: linearColor
              }
            },
            tooltip: { show: false }
          },
          {
            z: 3,
            name: '日产量顶部',
            type: 'pictorialBar',
            symbolPosition: 'end',
            data: showData,
            symbol: 'diamond',
            symbolOffset: ['0%', '-50%'],
            symbolSize: [barWidth - 4, (10 * (barWidth - 4)) / barWidth],
            itemStyle: {
              normal: {
                color: colorArr[2]
              }
            },
            tooltip: { show: false }
          }
        ]
      }
      this.dailyOutputChart.setOption(option)
    },
    initHourlyOutputData() {
      const times = []
      for (let i = 0; i < 24; i++) {
        times.push(String(i).padStart(2, '0'))
      }
      this.hourlyOutputTimes = times
      // 不再使用随机假数据，真实数据由存储过程填充
      this.hourlyOutputValues = []
    },
    // 每分钟刷新一次小时产量数据
    startHourlyOutputHistoryRefresh() {
      if (this.hourlyOutputRefreshTimer) {
        clearInterval(this.hourlyOutputRefreshTimer)
        this.hourlyOutputRefreshTimer = null
      }
      this.hourlyOutputRefreshTimer = setInterval(() => {
        this.loadHourlyOutputHistory()
      }, 60 * 1000)
    },
    // 拉取小时产量数据（调用存储过程：测量数据合格索引_小时产量查询）
    loadHourlyOutputHistory() {
      if (this.hourlyOutputLoading) return
      if (!this.hourlyOutputChart) return
      this.hourlyOutputLoading = true

      const param = [] // 无入参
      const data = this.CreateData('11', '测量数据合格索引_小时产量查询', param)
      this.ExecDatabase(data)
        .then((response) => {
          const list = response && response.data ? response.data : null
          if (!Array.isArray(list) || list.length === 0) {
            this.hourlyOutputValues = []
            this.drawHourlyOutputChart()
            return
          }

          const values = new Array(24).fill(0)
          list.forEach((row) => {
            const rawHour = row && (row['点'] != null ? row['点'] : row.点)
            const rawVal = row && (row['产量'] != null ? row['产量'] : row.产量)
            const h = Number(rawHour)
            const num = Number(rawVal)
            if (!Number.isFinite(h) || h < 0 || h > 23) return
            if (!Number.isFinite(num)) return
            values[Math.trunc(h)] += num
          })

          this.hourlyOutputValues = values.map((v) => Math.round(Number(v) || 0))
          this.drawHourlyOutputChart()
        })
        .catch((err) => {
          console.error('测量数据合格索引_小时产量查询失败', err)
          this.hourlyOutputValues = []
          this.drawHourlyOutputChart()
        })
        .then(() => {
          this.hourlyOutputLoading = false
        })
    },
    drawHourlyOutputChart() {
      if (!this.hourlyOutputChart) return
      const data = this.hourlyOutputValues || []
      const constData = []
      const showData = []
      data.forEach(val => {
        if (val != null) {
          constData.push(1)
          showData.push(val)
        } else {
          constData.push(0)
          showData.push({
            value: 1,
            itemStyle: {
              normal: {
                borderColor: 'rgba(0,0,0,0)',
                borderWidth: 2,
                color: 'rgba(0,0,0,0)'
              }
            }
          })
        }
      })
      // 先清空，避免上一次的图形或文字残留
      this.hourlyOutputChart.clear()

      // 如果没有任何数据，就只显示“未查询到当天小时产量数据”提示
      if (!data.length) {
        const optionEmpty = {
          backgroundColor: 'transparent',
          animation: false,
          xAxis: { show: false, type: 'category', data: [] },
          yAxis: { show: false, type: 'value' },
          series: [],
          graphic: {
            type: 'text',
            left: 'center',
            top: 'middle',
            style: {
              text: '未查询到当天小时产量数据',
              fill: '#7fd7ff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        }
        this.hourlyOutputChart.setOption(optionEmpty)
        return
      }

      const colorArr = ['#C5E0EC', '#8CBFD4', '#D8EAF2']
      const linearColor = {
        type: 'linear',
        x: 0,
        x2: 1,
        y: 0,
        y2: 0,
        colorStops: [
          { offset: 0, color: colorArr[0] },
          { offset: 0.5, color: colorArr[0] },
          { offset: 0.5, color: colorArr[1] },
          { offset: 1, color: colorArr[1] }
        ]
      }
      const barWidth = 18
      const maxAxis = this.getMaintenanceAxisMax(data)
      const option = {
        backgroundColor: 'transparent',
        animation: false,
        grid: {
          top: '10%',
          bottom: '10%',
          left: '8%',
          right: '4%'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
          formatter: (params) => {
            const p = params && params[0]
            if (!p) return ''
            return `${p.axisValue}时<br/>个数：${p.value}`
          }
        },
        xAxis: {
          type: 'category',
          data: this.hourlyOutputTimes,
          axisLabel: {
            color: '#7fd7ff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          axisTick: { show: false }
        },
        yAxis: {
          type: 'value',
          max: maxAxis,
          interval: maxAxis / 5,
          axisLabel: {
            color: '#7fd7ff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          splitLine: {
            lineStyle: { color: '#1B3F66' }
          }
        },
        series: [
          {
            z: 1,
            type: 'bar',
            name: '小时产品',
            barWidth,
            itemStyle: {
              borderRadius: [0, 0, 0, 0],
              color: linearColor
            },
            data: data
          },
          {
            z: 2,
            name: '小时产品底座',
            type: 'pictorialBar',
            data: constData,
            symbol: 'diamond',
            symbolOffset: ['0%', '50%'],
            symbolSize: [barWidth - 4, 10],
            itemStyle: {
              normal: {
                color: linearColor
              }
            },
            tooltip: { show: false }
          },
          {
            z: 3,
            name: '小时产品顶部',
            type: 'pictorialBar',
            symbolPosition: 'end',
            data: showData,
            symbol: 'diamond',
            symbolOffset: ['0%', '-50%'],
            symbolSize: [barWidth - 4, (10 * (barWidth - 4)) / barWidth],
            itemStyle: {
              normal: {
                color: colorArr[2]
              }
            },
            tooltip: { show: false }
          }
        ]
      }
      this.hourlyOutputChart.setOption(option)
    },
    drawFaultStatsChart() {
      if (!this.faultStatsChart) return
      const optionData = this.faultStatsData.map(item => ({
        ...item,
        value: Number(item.value) || 0
      }))
      const total = optionData.reduce((sum, item) => sum + (Number(item.value) || 0), 0)

      this.faultStatsChart.clear()
      if (total <= 0) {
        this.faultStatsChart.setOption({
          backgroundColor: 'transparent',
          xAxis3D: { show: false, min: -1, max: 1 },
          yAxis3D: { show: false, min: -1, max: 1 },
          zAxis3D: { show: false, min: -1, max: 1 },
          grid3D: { show: false },
          series: [],
          graphic: {
            type: 'text',
            left: 'center',
            top: 'middle',
            style: {
              text: '暂无报警数据',
              fill: '#7fd7ff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        })
        return
      }
      // internalDiameterRatio 控制圆环厚度：值越大，空心越大，环越薄
      const option = this.getPie3D(optionData, 0.72)
      option.legend = { show: false }
      option.label = { show: false }
      option.labelLine = { show: false }
      option.grid3D.viewControl = {
        // distance 影响圆环视觉半径（越大看起来越小）
        // alpha 控制圆环侧翻角度
        alpha: 30,
        distance: 140,
        rotateSensitivity: 0,
        zoomSensitivity: 0,
        panSensitivity: 0,
        autoRotate: false
      }
      this.faultStatsChart.setOption(option)
      this.bindFaultStatsEvents()
    },
    startFaultStatsRefresh() {
      if (this.faultStatsRefreshTimer) {
        clearInterval(this.faultStatsRefreshTimer)
        this.faultStatsRefreshTimer = null
      }
      this.faultStatsRefreshTimer = setInterval(() => {
        this.loadFaultStatsHistory()
      }, 60 * 1000)
      this.loadFaultStatsHistory()
    },
    formatFaultLegendName(name) {
      const text = name == null ? '' : String(name)
      return text
    },
    loadFaultStatsHistory() {
      if (this.faultStatsLoading) return
      if (!this.faultStatsChart) return
      this.faultStatsLoading = true

      const param = []
      const data = this.CreateData('11', '报警_记录_历史_查询_简化版', param)
      this.ExecDatabase(data)
        .then((response) => {
          const list = response && response.data ? response.data : null
          const colors = ['#50edff', '#eedcc0', '#82c2f1', '#808fcb', '#4cd39b', '#f6c85f', '#ef6f6c', '#9b8cff']
          this.faultStatsData = Array.isArray(list)
            ? list.map((row, index) => {
              const rawName = row && (row['报警内容'] != null ? row['报警内容'] : row.报警内容)
              const rawCount = row && (
                row['报警数量'] != null ? row['报警数量']
                  : row['频次'] != null ? row['频次']
                    : row['次数'] != null ? row['次数']
                      : row['Count'] != null ? row['Count']
                        : row.count
              )
              const name = rawName != null && String(rawName).trim() ? String(rawName).trim() : '未知报警'
              const num = Number(rawCount)
              return {
                name,
                value: Number.isFinite(num) ? num : 0,
                itemStyle: { color: colors[index % colors.length] }
              }
            })
            : []
          this.drawFaultStatsChart()
        })
        .catch((err) => {
          console.error('报警_记录_历史_查询_简化版失败', err)
          this.faultStatsData = []
          this.drawFaultStatsChart()
        })
        .then(() => {
          this.faultStatsLoading = false
        })
    },
    getPie3D(pieData, internalDiameterRatio) {
      const series = []
      let sumValue = 0
      let startValue = 0
      let endValue = 0
      const k = 1 - internalDiameterRatio
      pieData.sort((a, b) => b.value - a.value)
      for (let i = 0; i < pieData.length; i++) {
        sumValue += pieData[i].value
        const seriesItem = {
          name: pieData[i].name || `series${i}`,
          type: 'surface',
          parametric: true,
          wireframe: { show: false },
          pieData: pieData[i],
          pieStatus: {
            selected: false,
            hovered: false,
            k: k
          }
        }
        if (pieData[i].itemStyle) {
          seriesItem.itemStyle = {
            color: pieData[i].itemStyle.color,
            opacity: pieData[i].itemStyle.opacity
          }
        }
        series.push(seriesItem)
      }

      for (let i = 0; i < series.length; i++) {
        endValue = startValue + series[i].pieData.value
        series[i].pieData.startRatio = startValue / sumValue
        series[i].pieData.endRatio = endValue / sumValue
        series[i].parametricEquation = this.getParametricEquation(
          series[i].pieData.startRatio,
          series[i].pieData.endRatio,
          false,
          false,
          k,
          series[i].pieData.value
        )
        startValue = endValue
      }
      // height 影响圆环高度（z 方向厚度）
      const boxHeight = this.getHeight3D(series, 2)
      return {
        tooltip: {
          formatter: (params) => {
            if (params.seriesType === 'surface') {
              const count = Number(series?.[params.seriesIndex]?.pieData?.value)
              const display = Number.isFinite(count) ? count : 0
              // 使用真实业务值，避免 surface 点位 value 引起 tooltip 波动
              return `${params.seriesName}<br/>故障次数：${display}`
            }
            return ''
          }
        },
        xAxis3D: { min: -1, max: 1 },
        yAxis3D: { min: -1, max: 1 },
        zAxis3D: { min: -1, max: 1 },
        grid3D: {
          show: false,
          boxHeight: boxHeight,
          top: -10
        },
        series
      }
    },
    getHeight3D(series, height) {
      // height 控制圆环高度基准值（数值越大，整体越“高”）
      const sorted = [...series].sort((a, b) => b.pieData.value - a.pieData.value)
      return height * 10 / (sorted[0]?.pieData?.value || 1)
    },
    getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
      const midRatio = (startRatio + endRatio) / 2
      const startRadian = startRatio * Math.PI * 2
      const endRadian = endRatio * Math.PI * 2
      const midRadian = midRatio * Math.PI * 2
      if (startRatio === 0 && endRatio === 1) {
        isSelected = false
      }
      // k 控制圆环厚度（k 越大，环越厚）
      k = typeof k !== 'undefined' ? k : 1 / 2
      const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
      const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0
      const hoverRate = isHovered ? 1.05 : 1
      return {
        u: {
          min: -Math.PI,
          max: Math.PI * 3,
          step: Math.PI / 32
        },
        v: {
          min: 0,
          max: Math.PI * 2,
          step: Math.PI / 20
        },
        x: function(u, v) {
          if (u < startRadian) {
            return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          if (u > endRadian) {
            return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        y: function(u, v) {
          if (u < startRadian) {
            return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          if (u > endRadian) {
            return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          }
          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        z: function(u, v) {
          // h 控制圆环高度（z 方向厚度）
          if (u < -Math.PI * 0.5) {
            return Math.sin(u)
          }
          if (u > Math.PI * 2.5) {
            return Math.sin(u) * h * 0.1
          }
          return Math.sin(v) > 0 ? 1 * h * 0.1 : -1
        }
      }
    },
    bindFaultStatsEvents() {
      if (!this.faultStatsChart) return
      let hoveredIndex = ''
      this.faultStatsChart.on('mouseover', (params) => {
        if (hoveredIndex === params.seriesIndex) return
        if (hoveredIndex !== '') {
          this.updateFaultStatsHover(hoveredIndex, false)
          hoveredIndex = ''
        }
        if (params.seriesType === 'surface') {
          this.updateFaultStatsHover(params.seriesIndex, true)
          hoveredIndex = params.seriesIndex
        }
      })
      this.faultStatsChart.on('globalout', () => {
        if (hoveredIndex !== '') {
          this.updateFaultStatsHover(hoveredIndex, false)
          hoveredIndex = ''
        }
      })
    },
    updateFaultStatsHover(index, hovered) {
      const option = this.faultStatsChart.getOption()
      const series = option.series || []
      const item = series[index]
      if (!item || !item.pieData) return
      const startRatio = item.pieData.startRatio
      const endRatio = item.pieData.endRatio
      const k = item.pieStatus.k
      item.parametricEquation = this.getParametricEquation(
        startRatio,
        endRatio,
        false,
        hovered,
        k,
        hovered ? item.pieData.value + 4 : item.pieData.value
      )
      item.pieStatus.hovered = hovered
      this.faultStatsChart.setOption({ series })
    },
    getMaintenanceAxisMax(values) {
      const maxVal = Math.max(...values, 1)
      const roughStep = maxVal / 5
      const pow10 = Math.pow(10, Math.floor(Math.log10(roughStep)))
      const normalized = roughStep / pow10
      let step
      if (normalized <= 1) step = 1 * pow10
      else if (normalized <= 2) step = 2 * pow10
      else if (normalized <= 5) step = 5 * pow10
      else step = 10 * pow10
      return Math.ceil(maxVal / step) * step
    },
    // 每分钟刷新一次设备运行履历（调用存储过程：历史_工位设备状态每分钟记录_查询）
    startEquipmentRuntimeHistoryRefresh() {
      if (this.equipmentRuntimeHistoryRefreshTimer) {
        clearInterval(this.equipmentRuntimeHistoryRefreshTimer)
        this.equipmentRuntimeHistoryRefreshTimer = null
      }
      this.equipmentRuntimeHistoryRefreshTimer = setInterval(() => {
        this.loadEquipmentRuntimeHistory()
      }, 60 * 1000)
    },
    // 查询设备运行履历（调用存储过程：历史_工位设备状态每分钟记录_查询，过去24小时）
    loadEquipmentRuntimeHistory() {
      if (this.equipmentRuntimeHistoryLoading) return
      this.equipmentRuntimeHistoryLoading = true
      const endTime = new Date()
      const startTime = new Date(endTime.getTime() - 24 * 60 * 60 * 1000) // 近24小时
      const fmt = (d) => this.formatDateTime(d)
      const param4 = [
        ['开始时间', fmt(startTime)],
        ['结束时间', fmt(endTime)],
        ['记录条数', '2000']
      ]
      const Data4 = this.CreateData('11', '历史_工位设备状态每分钟记录_查询', param4)
      this.ExecDatabase(Data4).then(response => {
        const list = response.data
        if (Array.isArray(list) && list.length > 0) {
          this.processEquipmentRuntimeData(list)
        } else {
          this.deviceStatusTable = []
        }
        this.drawDeviceStatusChart()
      }).catch(err => {
        console.error('设备运行履历数据获取失败', err)
        this.deviceStatusTable = []
        this.drawDeviceStatusChart()
      }).finally(() => {
        this.equipmentRuntimeHistoryLoading = false
      })
    },
    // 处理设备运行履历数据
    processEquipmentRuntimeData(records) {
      this.deviceStatusTable = records.map(record => ({
        工位号: record.工位号 || '设备1',
        设备状态: record.设备状态,
        创建时间: record.创建时间
      }))
    },
    // 格式化日期时间
    formatDateTime(date) {
      const year = date.getFullYear()
      const month = (date.getMonth() + 1).toString().padStart(2, '0')
      const day = date.getDate().toString().padStart(2, '0')
      const hours = date.getHours().toString().padStart(2, '0')
      const minutes = date.getMinutes().toString().padStart(2, '0')
      const seconds = date.getSeconds().toString().padStart(2, '0')
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
    },
    drawDeviceStatusChart() {
      if (!this.deviceStatusChart) {
        return
      }
      const hasData = Array.isArray(this.deviceStatusTable) && this.deviceStatusTable.length > 0
      if (!hasData) {
        this.deviceStatusChart.clear()
        this.deviceStatusChart.setOption({
          backgroundColor: 'transparent',
          xAxis: { show: false, type: 'time' },
          yAxis: { show: false, type: 'category', data: [] },
          series: [],
          graphic: {
            type: 'text',
            left: 'center',
            top: 'middle',
            style: {
              text: '暂未查询到设备运行履历',
              fill: '#7fd7ff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        }, true)
        return
      }
      // 设备状态映射
      const statusMap = {
        '-1': { name: '离线', color: '#878787' },
        '0': { name: '待机', color: '#CC7900' },
        '1': { name: '运行', color: '#388811' },
        '2': { name: '报警', color: '#D24956' }
      }
      // 处理数据，按工位号分组并按时间排序
      const groupedData = {}
      this.deviceStatusTable.forEach((item) => {
        const workstation = item.工位号 || 'OP10'
        if (!groupedData[workstation]) {
          groupedData[workstation] = []
        }
        groupedData[workstation].push(item)
      })
      // 对每组数据按时间排序
      Object.keys(groupedData).forEach((workstation) => {
        groupedData[workstation].sort(
          (a, b) => new Date(a.创建时间).getTime() - new Date(b.创建时间).getTime()
        )
      })
      // 构建图表数据 - 为每个状态创建一个系列
      const seriesData = []
      const yAxisData = Object.keys(groupedData)
      // 为每个工位和状态创建数据
      yAxisData.forEach((workstation, yIndex) => {
        const records = groupedData[workstation]
        records.forEach((record, index) => {
          const statusInfo = statusMap[String(record.设备状态)] || { name: '未知', color: '#909399' }
          // 计算结束时间
          let endTime
          if (index === records.length - 1) {
            const startTime = new Date(record.创建时间)
            endTime = new Date(startTime.getTime() + 60000) // 默认1分钟
          } else {
            endTime = new Date(records[index + 1].创建时间)
          }
          const startTime = new Date(record.创建时间)
          // 确保开始时间小于结束时间
          if (startTime.getTime() < endTime.getTime()) {
            seriesData.push({
              name: statusInfo.name,
              value: [
                workstation, // y轴类别
                startTime.getTime(), // 开始时间
                endTime.getTime(), // 结束时间
                statusInfo.name // 状态名称
              ],
              itemStyle: {
                color: statusInfo.color,
                borderRadius: 6,
                shadowBlur: 6,
                shadowColor: 'rgba(0, 0, 0, 0.35)',
                shadowOffsetX: 0,
                shadowOffsetY: 0
              }
            })
          }
        })
      })
      // 创建配置选项
      const option = {
        backgroundColor: 'transparent',
        animation: false,
        tooltip: {
          trigger: 'item',
          formatter: function(params) {
            const data = params.value
            const startTime = new Date(data[1])
            const endTime = new Date(data[2])
            const startStr = `${startTime.getHours().toString().padStart(2, '0')}:${startTime.getMinutes().toString().padStart(2, '0')}`
            const endStr = `${endTime.getHours().toString().padStart(2, '0')}:${endTime.getMinutes().toString().padStart(2, '0')}`
            return `${data[3]}<br/>${data[0]}<br/>${startStr} ~ ${endStr}`
          },
          backgroundColor: 'rgba(0, 0, 0, 0.8)',
          textStyle: { color: '#fff' },
          borderColor: 'rgba(255, 255, 255, 0.3)',
          borderWidth: 1,
          confine: true,
          position: function(point, params, dom, rect, size) {
            const mouseX = point[0]
            const mouseY = point[1]
            const tooltipWidth = size.contentSize[0]
            const tooltipHeight = size.contentSize[1]
            const chartWidth = size.viewSize[0]
            const chartHeight = size.viewSize[1]
            // 默认显示在鼠标上方
            let x = mouseX - tooltipWidth / 2
            let y = mouseY - tooltipHeight - 10
            // 水平边界检查
            x = Math.max(5, Math.min(x, chartWidth - tooltipWidth - 5))
            // 垂直边界检查 - 确保不超出顶部
            if (y < 0) {
              // 上方放不下，放到鼠标下方
              y = mouseY + 20 // 增加下方偏移量，避免紧贴鼠标
            }
            // 检查是否超出底部
            if (y + tooltipHeight > chartHeight) {
              // 超出底部，尝试放回上方
              y = mouseY - tooltipHeight - 20
              // 如果上方也放不下，就放在图表顶部，留出边距
              if (y < 0) {
                y = 10 // 固定在顶部，留10px边距
              }
            }
            // 最终检查：确保整个tooltip都在可视区域内
            y = Math.max(5, Math.min(y, chartHeight - tooltipHeight - 5))
            return [x, y]
          }
        },
        grid: {
          left: '1%',
          right: '1%',
          bottom: '7%',
          top: '7%',
          containLabel: true
        },
        xAxis: {
          type: 'time',
          axisLine: { show: true, lineStyle: { color: '#7fd7ff' }},
          axisLabel: {
            show: true,
            color: '#7fd7ff',
            fontSize: 15,
            formatter: function(value) {
              const date = new Date(value)
              return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
            }
          },
          splitLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.1)' }}
        },
        yAxis: {
          type: 'category',
          data: yAxisData,
          axisLine: { show: false, lineStyle: { color: '#7fd7ff' }},
          axisLabel: { color: '#7fd7ff', fontSize: 15, show: true },
          splitLine: { show: false }
        },
        series: [
          {
            type: 'custom',
            name: '设备状态',
            renderItem: function(params, api) {
              try {
                const categoryIndex = api.value(0)
                const start = api.coord([api.value(1), categoryIndex])
                const end = api.coord([api.value(2), categoryIndex])
                if (!start || !end || start[0] === end[0]) {
                  return null
                }
                const height = api.size([0, 1])[1] * 0.6
                return {
                  type: 'rect',
                  shape: {
                    x: start[0],
                    y: start[1] - height / 2,
                    width: Math.max(end[0] - start[0], 1),
                    height: height,
                    r: 6
                  },
                  style: api.style()
                }
              } catch (error) {
                return null
              }
            },
            encode: {
              x: [1, 2],
              y: 0
            },
            data: seriesData
          }
        ]
      }

      this.deviceStatusChart.setOption(option, true)
    },
    // 每小时刷新一次零部件智能预测性维护
    startComponentMaintenanceRefresh() {
      if (this.componentMaintenanceRefreshTimer) {
        clearInterval(this.componentMaintenanceRefreshTimer)
        this.componentMaintenanceRefreshTimer = null
      }
      this.componentMaintenanceRefreshTimer = setInterval(() => {
        this.loadComponentMaintenanceData()
      }, 60 * 1000)
    },
    loadComponentMaintenanceData() {
      if (this.componentMaintenanceLoading) return
      // 使用 CreateData 和 ExecDatabase 调用存储过程获取真数据
      var param4 = []
      var Data4 = this.CreateData('11', '零部件智能预测性维护_基础表_查询_简化版', param4)
      this.componentMaintenanceLoading = true
      this.ExecDatabase(Data4)
        .then(response => {
          if (response.data && response.data.length > 0) {
            this.componentNames = []
            this.predictedHours = []
            this.usedHours = []
            this.remainingHours = []
            response.data.forEach(item => {
              const name = item['名称'] != null ? String(item['名称']) : ''
              const predictedRaw = item['制定寿命'] != null ? item['制定寿命'] : item['制定']
              const predicted = predictedRaw != null ? Number(predictedRaw) : 0
              const usedRaw = item['使用次数'] != null ? item['使用次数'] : item['已用']
              const used = usedRaw != null ? Number(usedRaw) : 0
              const remaining = item['剩余'] != null ? Number(item['剩余']) : Math.max(predicted - used, 0)
              this.componentNames.push(name)
              this.predictedHours.push(Number.isFinite(predicted) ? predicted : 0)
              this.usedHours.push(Number.isFinite(used) ? used : 0)
              this.remainingHours.push(Number.isFinite(remaining) ? remaining : 0)
            })
            this.drawComponentMaintenanceChart()
          } else {
            this.componentNames = []
            this.predictedHours = []
            this.usedHours = []
            this.remainingHours = []
            this.drawComponentMaintenanceChart()
          }
        })
        .catch(error => {
          console.error('零部件智能预测性维护数据获取失败', error)
          this.componentNames = []
          this.predictedHours = []
          this.usedHours = []
          this.remainingHours = []
          this.drawComponentMaintenanceChart()
        })
        .finally(() => {
          this.componentMaintenanceLoading = false
        })
    },
    drawComponentMaintenanceChart() {
      if (!this.componentMaintenanceChart) {
        return
      }
      const names = this.componentNames || []
      const predicted = this.predictedHours || []
      const used = this.usedHours || []
      const remaining = this.remainingHours || []
      const hasAnyData =
        (Array.isArray(names) && names.length > 0) ||
        (Array.isArray(predicted) && predicted.length > 0) ||
        (Array.isArray(used) && used.length > 0) ||
        (Array.isArray(remaining) && remaining.length > 0)

      this.componentMaintenanceChart.clear()
      if (!hasAnyData) {
        this.componentMaintenanceChart.setOption({
          backgroundColor: 'transparent',
          xAxis: { show: false, type: 'category', data: [] },
          yAxis: { show: false, type: 'value' },
          series: [],
          graphic: {
            type: 'text',
            left: 'center',
            top: 'middle',
            style: {
              text: '暂未查询到零部件维护数据',
              fill: '#7fd7ff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        }, true)
        return
      }
      const maxAxis = this.getMaintenanceAxisMax([...predicted, ...used, ...remaining])
      const barWidth = 20

      // 计算每个柱子的偏移量 - 修正版
      const getSymbolOffset = (seriesIndex) => {
        // 根据实际显示效果调整这些值
        // 数值越大，偏移越靠右；数值越小（负值越大），偏移越靠左
        const offsets = [-24, 0, 24] // 蓝色偏左，黄色居中，紫色偏右

        // 如果你需要更精确的调整，可以修改上面的数值
        // 比如如果蓝色还不够左，改成 -25；如果紫色还不够右，改成 25

        return offsets[seriesIndex] + 'px'
      }

      const build3DSeries = (name, data, colors, seriesIndex) => {
        const constData = data.map(val => (val != null ? 1 : 0))
        const showData = data.map(val => {
          if (val != null) return val
          return {
            value: 1,
            itemStyle: {
              normal: {
                borderColor: 'rgba(0,0,0,0)',
                borderWidth: 2,
                color: 'rgba(0,0,0,0)'
              }
            }
          }
        })
        const linearColor = {
          type: 'linear',
          x: 0,
          x2: 1,
          y: 0,
          y2: 0,
          colorStops: [
            { offset: 0, color: colors[0] },
            { offset: 0.5, color: colors[0] },
            { offset: 0.5, color: colors[1] },
            { offset: 1, color: colors[1] }
          ]
        }

        // 计算当前系列的偏移量
        const offsetValue = getSymbolOffset(seriesIndex)

        return [
          {
            z: 1,
            type: 'bar',
            name,
            barWidth,
            itemStyle: {
              borderRadius: [0, 0, 0, 0],
              color: linearColor
            },
            data
          },
          {
            z: 2,
            name: `${name}底座`,
            type: 'pictorialBar',
            data: constData,
            symbol: 'diamond',
            symbolOffset: [offsetValue, '50%'],
            symbolSize: [barWidth - 2, 6],
            itemStyle: {
              normal: {
                color: linearColor
              }
            },
            tooltip: { show: false }
          },
          {
            z: 3,
            name: `${name}顶部`,
            type: 'pictorialBar',
            symbolPosition: 'end',
            data: showData,
            symbol: 'diamond',
            symbolOffset: [offsetValue, '-50%'],
            symbolSize: [barWidth - 2, (6 * (barWidth - 2)) / barWidth],
            itemStyle: {
              normal: {
                color: colors[2]
              }
            },
            tooltip: { show: false }
          }
        ]
      }

      const option = {
        backgroundColor: 'transparent',
        animation: false,
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          },
          backgroundColor: 'rgba(0, 0, 0, 0.8)',
          textStyle: { color: '#fff' },
          borderColor: 'rgba(255, 255, 255, 0.3)',
          borderWidth: 1,
          formatter: function(params) {
            let result = `${params[0].name}<br/>`
            params.forEach(function(param) {
              if (param.seriesType === 'pictorialBar') return
              const value = param.value != null ? `${param.value}h` : '0h'
              result += `${param.seriesName}: ${value}<br/>`
            })
            return result
          }
        },
        legend: {
          show: false,
          data: ['预测时间', '使用时间', '剩余时间'],
          textStyle: {
            color: '#ffffff'
          },
          orient: 'horizontal',
          right: 10,
          top: 0
        },
        grid: {
          left: '15%',
          right: '4%',
          bottom: '20%',
          top: '10%'
        },
        xAxis: {
          type: 'category',
          data: names.slice(0, 5),
          axisLabel: {
            color: '#7fd7ff',
            fontSize: 12,
            interval: 0,
            formatter: function(value) {
              if (!value) return ''
              const text = String(value)
              return text.length > 5 ? text.slice(0, 5) + '\n' + text.slice(5) : text
            }
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: '#7fd7ff'
            }
          },
          axisTick: {
            alignWithLabel: true
          }
        },
        yAxis: {
          type: 'value',
          max: maxAxis,
          interval: maxAxis / 5,
          axisLabel: {
            color: '#ffffff',
            formatter: '{value}h'
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: '#ffffff'
            }
          },
          splitLine: {
            lineStyle: {
              color: 'rgba(255, 255, 255, 0.1)'
            }
          }
        },
        series: [
          ...build3DSeries('预测时间', predicted.slice(0, 5), ['#C5E0EC', '#8CBFD4', '#D8EAF2'], 0),
          ...build3DSeries('使用时间', used.slice(0, 5), ['#C3A86F', '#D9C08F', '#E6D1A6'], 1),
          ...build3DSeries('剩余时间', remaining.slice(0, 5), ['#B1A0D0', '#917AB2', '#E1D9EC'], 2)
        ]
      }

      this.componentMaintenanceChart.setOption(option, true)
    }
  }
}
</script>
<style>
HTML {
  overflow: auto;
}

body {
  margin: 0;
  padding: 0;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  position: relative;
  font-family: MiSans Bold, serif;
}

/*css主要部分的样式*/
/*定义滚动条宽高及背景，宽高分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
  width: 0px;
  /*对垂直流动条有效*/
  height: 0px;
  /*对水平流动条有效*/
}

/*定义滚动条的轨道颜色、内阴影及圆角*/
::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  background-color: rgb(14, 50, 97);
  /*background-color: #ffffff;*/
  border-radius: 2px;
}

/*定义滑块颜色、内阴影及圆角*/
::-webkit-scrollbar-thumb {
  border-radius: 5px;
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  background-color: rgb(10, 35, 82);
}

/*定义两端按钮的样式*/
::-webkit-scrollbar-button {
  display: none;
}

/*定义右下角汇合处的样式*/
::-webkit-scrollbar-corner {
  background: #dedede;
}
</style>
<style scoped="scoped">
.allShow {
  overflow-y: hidden;
  z-index: 100;
  transform-origin: 0 0;
  position: fixed;
  left: 50%;
  top: 50%;
  transition: 0.3s;
  /* background-color: #898b8d; */
  background: url('/png/背景.png') no-repeat center center;
  /* background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)),
        url('/png/background.jpg') no-repeat center center; */
  background-size: cover;
  color: white;
}

.daily-output-box {
position: absolute;
  width: 432px;
  height: 290px;
  left: 40px;
  top: 1px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.daily-output-header {
  width: 100%;
  height: 45px;
  background: url('/png/左一标签.png') no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  padding-left: 25px;
  box-sizing: border-box;
}

.box-title {
  font-size: 25px;
  font-weight: 700;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.daily-output-body {
  width: 100%;
  height: calc(100% - 45px);
  box-sizing: border-box;
}

.daily-output-chart {
  width: 100%;
  height: 100%;
}

.storage-status-box {
  position: absolute;
  width: 432px;
  height: 290px;
  right: 40px;
  top: 1px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.storage-status-header {
  width: 100%;
  height: 45px;
  background: url('/png/右一标签.png') no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 25px;
  box-sizing: border-box;
}

.storage-status-title {
  font-size: 25px;
  font-weight: 700;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.storage-status-body {
  width: 100%;
  height: calc(100% - 45px);
  box-sizing: border-box;
  padding: 10px;
}

.storage-status-grid {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-template-rows: repeat(6, 1fr);
  gap: 5px;
}

.storage-status-cell {
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 700;
  color: #ffffff;
  box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.35);
}

.storage-status-cell--active {
  background: #388811;
}

.storage-status-cell--inactive {
  background: #878787;
}

.hourly-output-box {
  position: absolute;
  width: 432px;
  height: 290px;
  right: 40px;
  top: 316px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.hourly-output-header {
  width: 100%;
  height: 45px;
  background: url('/png/右二标签.png') no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 25px;
  box-sizing: border-box;
}

.hourly-output-title {
  font-size: 25px;
  font-weight: 700;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hourly-output-body {
  width: 100%;
  height: calc(100% - 45px);
  box-sizing: border-box;
}

.hourly-output-chart {
  width: 100%;
  height: 100%;
}

.fault-stats-box {
  position: absolute;
  width: 432px;
  height: 290px;
  right: 40px;
  top: 631px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.fault-stats-header {
  width: 100%;
  height: 45px;
  background: url('/png/右三标签.png') no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 25px;
  box-sizing: border-box;
}

.fault-stats-title {
  font-size: 25px;
  font-weight: 700;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.fault-stats-body {
  width: 100%;
  height: calc(100% - 45px);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 10px;
}

.fault-stats-legend {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  column-gap: 10px;
  row-gap: 4px;
  width: 100%;
  min-height: 20px;
  max-height: 44px;
  margin-top: 8px;
  flex-shrink: 0;
  overflow: hidden;
  font-size: 15px;
  color: #ffffff;
}

.fault-stats-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: none;
  min-width: 0;
  flex-shrink: 0;
}

.fault-stats-text {
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
}
.fault-stats-dot {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  display: inline-block;
}
.fault-stats-dot--cyan {
  background: #50edff;
}

.fault-stats-dot--orange {
  background: #eedcc0;
}

.fault-stats-dot--lake {
  background: #82c2f1;
}

.fault-stats-dot--purple {
  background: #808fcb;
}

.fault-stats-dot--green {
  background: #4cd39b;
}

.fault-stats-chart {
  width: 100%;
  flex: 1;
}

.component-maintenance-box {
  position: absolute;
  width: 432px;
  height: 290px;
  left: 40px;
  top: 316px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.component-maintenance-header {
  width: 100%;
  height: 45px;
  background: url('/png/左二标签.png') no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  padding-left: 25px;
  box-sizing: border-box;
}

.component-maintenance-title {
  font-size: 25px;
  font-weight: 700;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.component-maintenance-body {
  width: 100%;
  height: calc(100% - 45px);
  box-sizing: border-box;
}

.component-maintenance-chart {
  width: 100%;
  height: 100%;
}

.device-status-box {
  position: absolute;
  width: 432px;
  height: 290px;
  left: 40px;
  top: 631px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.device-status-header {
  width: 100%;
  height: 45px;
  background: url('/png/左三标签.png') no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  padding-left: 25px;
  box-sizing: border-box;
}

.device-status-title {
  font-size: 25px;
  font-weight: 700;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.device-status-body {
  width: 100%;
  height: calc(100% - 45px);
  box-sizing: border-box;
  padding: 8px;
}

.device-status-table {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.device-status-row {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: center;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 4px;
  box-sizing: border-box;
  font-size: 13px;
  color: #ffffff;
}

.device-status-row--header {
  font-weight: 700;
}

.device-status-cell {
  text-align: center;
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
  font-size: 18px;
  color: #7fd7ff;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.device-status-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 5px 25px;
  border-radius: 5px;
  font-size: 18px;
  color: #ffffff;
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.35);
}

.device-status-pill--running {
  background: #388811;
}

.device-status-pill--alarm {
  background: #D24956;
}

.device-status-pill--standby {
  background: #CC7900;
}

.device-status-pill--offline {
  background: #878787;
}

.df-header {
  height: 115px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding: 0 24px;
  background: url('/png/头部.png') no-repeat center center;
  background-size: 100% 100%;
}

.df-header__left {
  width: 220px;
  height: 100%;
}

.df-header__center {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  overflow: hidden;
}

.df-header__title {
  position: relative;
  top: -20px;
  left: 68px;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  font-size: 50px;
  font-weight: 1000;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.df-header__right {
  width: 360px;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-start;
  padding-top: 12px;
  box-sizing: border-box;
}

.df-header__timebar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: #ffffff;
  line-height: 1;
}

.df-header__time {
  order: 1;
  font-size: 27px;
  font-weight: 1000;
  /* 确保时间在最左侧 */
}

.df-header__sep {
  opacity: 0.85;
  order: 2;
  /* 分隔符在中间 */
}

.df-header__date-wrapper {
  display: flex;
  flex-direction: column;
  /* 垂直排列 */
  align-items: flex-start;
  /* 右对齐 */
  gap: 2px;
  order: 3;
}

.df-header__year {
  font-size: 16px;
  /* 可以稍小一些 */
  line-height: 1.2;
}

.df-header__week {
  font-size: 14px;
  opacity: 0.85;

}
.other-params-label {
  padding: 10px 0;
}

.other-params-value {
  color: #ffcb6f;
  font-size: 20px;
  text-align: center;
}

.background {
  width: 1920px;
  height: 1080px;
  background-color: rgb(8, 31, 72);
  color: white;
  background-size: 100%;
}

/*表格透明写法*/
::v-deep .el-table,
.el-table__expanded-cell {
  background-color: transparent;
}

::v-deep .el-table th {
  background-color: transparent !important;
  color: #fefefe;
}

::v-deep .el-table tr {
  background-color: transparent !important;
}

::v-deep .el-table--enable-row-transition .el-table__body td,
::v-deep.el-table .cell {
  background-color: transparent;
  color: white;
  border: none;
  padding-left: 0 !important;
  padding-right: 0 !important;
}

::v-deep.el-table th > .cell {
  color: rgba(254, 254, 254, 1);
  font-weight: 700;
}

::v-deep .el-table td,
.el-table th {
  padding: 8px 0;
}

.el-table__body-wrapper::-webkit-scrollbar {
  /*width: 0;宽度为0隐藏*/
  width: 0;
}

.el-table::before {
  /*left: 0;*/
  /*bottom: 0;*/
  width: 100%;
  height: 0;
}
table {
  border-right: 1px solid #d7d7d7;
  border-bottom: 1px solid #d7d7d7;
  text-align: center;
}

table th {
  border-left: 1px solid #d7d7d7;
  border-top: 1px solid #d7d7d7;
}

table td {
  border-left: 1px solid #d7d7d7;
  border-top: 1px solid #d7d7d7;
}
/* 设备运行履历样式 */
.bb-chart-container {
  width: 100%;
  height: 110px;
  box-sizing: border-box;
  position: relative;
  min-height: 110px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.3);
}

.bb-chart-container--timeline {
  height: calc(100% - 45px);
  min-height: 0;
}

.bb-chart {
  width: 100% !important;
  height: 100% !important;
  min-height: 110px;
}

.main-content {
  position: relative;
  height: 980px;
}

.status-timeline-box {
  position: absolute;
  left: 512px;
  top: 590px;
  width: 895px;
  height: 290px;
  box-shadow: inset 0 0 30px rgb(24, 78, 135);
  border-radius: 2px;
  overflow: hidden;
}

.platform-credit {
  position: absolute;
  left: 50%;
  top: 895px;
  transform: translateX(-50%);
  width: 100%;
  text-align: center;
  background: linear-gradient(to top, #7fd7ff, #ffffff);
  font-size: 30px;
  font-weight: 1000;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
  letter-spacing: 2px;
}
.status-timeline-header {
  background: url('/png/中间标签.png') no-repeat center center;
  background-size: 100% 100%;
}

.bb-chart--status {
  height: 100%;
  width: 100%;
  min-height: 0;
}
.fault-stats-text{
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
  font-size: 15px;
  color: #7fd7ff;
}
</style>
