<!-- eslint-disable vue/max-attributes-per-line -->
<template>
  <div id="screen" class="allShow" :style="{
    width: `${style.width}px`,
    height: `${style.height}px`,
    transform: `${style.transform}`,
  }">

    <div class="title-png">
      <span class="title-text">大陆架零部件智能生产线数字孪生系统</span>
      <div class="df-header__right">
        <div class="df-header__timebar">
          <span class="df-header__year">{{ headerDateCn }}</span>
          <span class="df-header__time">{{ headerTime }}</span>
        </div>
      </div>
      <!-- <img style="
        width: 200px;
        height: 30px;
        position: absolute;
        left: 55px;
        top: 20px;
      " src="/png/logo.png" alt="东方理工大学logo" /> -->
    </div>
    <div class="leftLine"></div>
    <div class="rightLine"></div>
    <!-- <button class="button1" @click="togglePanelLayout" :style="buttonStyle"></button> -->
    <div class="main-content">
      <iframe
            id="dmtIframe"
            :src="iframeAddress"
            style="
              width: 100%;
              height: 100%;
              border: none;
              filter: blur(10);
              z-index: 100;
            " />
      <div v-show="!isPanelCollapsed" class="realtimeTask-box">
        <div class="realtime-task-grid">
          <div class="realtime-task-item">
            <span class="realtime-task-label">订单号</span>
            <span class="realtime-task-value">{{ realtimeTaskInfo.orderNo }}</span>
          </div>
          <div class="realtime-task-item">
            <span class="realtime-task-label">物料号</span>
            <span class="realtime-task-value">{{ realtimeTaskInfo.materialNo }}</span>
          </div>
          <div class="realtime-task-item">
            <span class="realtime-task-label">数量</span>
            <span class="realtime-task-value">{{ realtimeTaskInfo.quantity }}</span>
          </div>
        </div>
      </div>
      <div v-show="!isPanelCollapsed" class="left-box">
        <!-- 日产量模块 -->
        <div class="daily-output-box">
          <div class="left-title-header">
            <span class="left-title-text">日产量</span>
          </div>
          <div class="daily-output-body">
            <div id="dailyOutputChart" class="daily-output-chart" />
          </div>
        </div>
        <!-- OEE模块 -->
        <div class="oee-analysis-box">
          <div class="left-title-header">
            <span class="left-title-text">OEE分析</span>
          </div>
          <div class="oee-analysis-body">
            <div class="oee-chart-group">
              <div class="oee-chart-item">
                <div id="oeeChart1" class="oee-chart" />
                <div class="oee-chart-title">OEE</div>
                <div class="oee-chart-value">{{ oeeValue }}%</div>
              </div>
              <div class="oee-chart-item oee-chart-item--editable" @click="startEditOeeField('time')">
                <div id="oeeChart2" class="oee-chart" />
                <div class="oee-chart-title">时间利用率</div>
                <div class="oee-chart-value" @click.stop>
                  <input
                    v-if="editingOeeField === 'time'"
                    ref="oeeTimeInput"
                    v-model.number="tempTimeUtilization"
                    class="oee-chart-input"
                    type="number"
                    min="0"
                    max="100"
                    @blur="saveTimeUtilization"
                    @keyup.enter="saveTimeUtilization"
                  >
                  <span v-else>{{ timeUtilization }}%</span>
                </div>
              </div>
              <div class="oee-chart-item oee-chart-item--editable" @click="startEditOeeField('performance')">
                <div id="oeeChart3" class="oee-chart" />
                <div class="oee-chart-title">性能利用率</div>
                <div class="oee-chart-value" @click.stop>
                  <input
                    v-if="editingOeeField === 'performance'"
                    ref="oeePerformanceInput"
                    v-model.number="tempPerformanceUtilization"
                    class="oee-chart-input"
                    type="number"
                    min="0"
                    max="100"
                    @blur="savePerformanceUtilization"
                    @keyup.enter="savePerformanceUtilization"
                  >
                  <span v-else>{{ performanceUtilization }}%</span>
                </div>
              </div>
              <div class="oee-chart-item oee-chart-item--editable" @click="startEditOeeField('quality')">
                <div id="oeeChart4" class="oee-chart" />
                <div class="oee-chart-title">良品率</div>
                <div class="oee-chart-value" @click.stop>
                  <input
                    v-if="editingOeeField === 'quality'"
                    ref="oeeQualityInput"
                    v-model.number="tempQualityRate"
                    class="oee-chart-input"
                    type="number"
                    min="0"
                    max="100"
                    @blur="saveQualityRate"
                    @keyup.enter="saveQualityRate"
                  >
                  <span v-else>{{ qualityRate }}%</span>
                </div>
              </div>
            </div>
          </div>
        </div>
        <!-- 零部件智能预测性维护模块 -->
        <div class="component-maintenance-box">
          <div class="left-title-header">
            <span class="left-title-text">零部件智能预测性维护</span>
          </div>
          <div class="component-maintenance-body">
            <div id="componentMaintenanceChart" class="component-maintenance-chart" />
          </div>
        </div>

        <!-- 设备状态模块 -->
        <div class="device-status-box">
          <div class="left-title-header">
            <span class="left-title-text">设备状态</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>
      <div v-show="!isPanelCollapsed" class="right-box">
        <!-- 实时状态模块 -->
        <div class="storage-status-box">
          <div class="right-title-header">
            <span class="right-title-text">实时状态</span>
          </div>
          <div class="storage-status-body now-status-body">
            <div class="now-status-fixed-row">
              <div class="now-status-fixed-label">设备状态</div>
              <div class="now-status-indicators">
                <div v-for="item in nowStatusIndicators" :key="item.label" class="now-status-indicator-item">
                  <span class="now-status-circle" :class="{ 'now-status-circle--active': item.active }" :style="{
                    backgroundColor: item.active ? getNowStatusCircleColor(item.label) : '#909399'
                  }"></span>
                  <span class="now-status-indicator-label">{{ item.label }}</span>
                </div>
              </div>
            </div>

            <div class="now-status-scroll-container">
              <scroll
                class="now-status-scroll-wrapper"
                :data="nowStatusList"
                :class-option="nowStatusScrollOption"
              >
                <div class="now-status-scroll-content">
                  <div v-for="item in nowStatusList" :key="item.key" class="now-status-row">
                    <div class="now-status-row-label">{{ item.label }}</div>
                    <div class="now-status-row-value">{{ item.value }}</div>
                  </div>
                </div>
              </scroll>
            </div>
          </div>
        </div>

        <!-- 刀具寿命管理模块 -->
        <div class="hourly-output-box">
          <div class="right-title-header">
            <span class="right-title-text">刀具寿命管理</span>
          </div>
          <div class="hourly-output-body">
            <div id="toolUseTimeChart" class="hourly-output-chart" />
          </div>
        </div>
        <!-- 故障统计模块 -->
        <div class="fault-stats-box">
          <div class="right-title-header">
            <span class="right-title-text">故障统计</span>
          </div>
          <div class="fault-stats-body">
            <div id="faultStatsChart" class="fault-stats-chart" />
          </div>
        </div>
      </div>

      <!-- 设备运行履历模块 -->
      <div v-show="!isPanelCollapsed" class="status-timeline-box">
        <div class="status-timeline-header"></div>
        <div class="bb-chart-container bb-chart-container--timeline">
          <div id="dashboardDeviceStatus" class="bb-chart bb-chart--status" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import 'echarts-gl'
import scroll from 'vue-seamless-scroll'
export default {
  name: 'DaLuJia',
  components: { scroll },
  data() {
    return {
      style: {
        width: '1920',
        height: '1080',
        transform: 'scaleY(1) scaleX(1) translate(-50%, -50%)'
      },
      isPanelCollapsed: false,
      workstationStatusLoading: false,
      workstationStatusTimer: null,
      equipmentRuntimeHistoryLoading: false,
      equipmentRuntimeHistoryRefreshTimer: null,
      nowStatusLoading: false,
      nowStatusRefreshTimer: null,
      nowStatusIndicators: [
        { label: '关机', active: false },
        { label: '待机', active: false },
        { label: '运行', active: false },
        { label: '报警', active: false }
      ],
      nowStatusList: [
        { key: 'status', label: 'status', value: '待机' }
      ],
      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'
        }
      ],
      deviceStatusChart: null, // 设备运行状态图表
      componentMaintenanceChart: null, // 零部件预测性维护图表
      dailyOutputChart: null, // 日产量图表
      oeeCharts: [], // OEE仪表盘图表集合
      oeeRefreshTimer: null,
      timeUtilization: 100,
      qualityRate: 100,
      performanceUtilization: 88,
      editingOeeField: '',
      tempTimeUtilization: 100,
      tempPerformanceUtilization: 88,
      tempQualityRate: 100,
      hourlyOutputChart: null, // 刀具寿命管理图表
      toolUseTimeNames: [],
      toolUseTimePlanned: [],
      toolUseTimeActual: [],
      toolUseTimeLoading: false,
      toolUseTimeRefreshTimer: null,
      componentMaintenanceLoading: false,
      componentMaintenanceRefreshTimer: null,
      realtimeTaskLoading: false,
      realtimeTaskRefreshTimer: null,
      realtimeTaskInfo: {
        orderNo: '--',
        materialNo: '--',
        quantity: '--'
      },
      faultStatsLoading: false,
      faultStatsRefreshTimer: null,
      faultStatsChart: null,
      faultStatsData: [
        { name: 'OP1020', value: 2 }
      ],
      // 日产量数据（只使用存储过程返回的数据）
      dailyOutputDates: [],
      dailyOutputValues: [],
      dailyOutputLoading: false,
      dailyOutputRefreshTimer: null,
      // 零部件预测性维护数据
      componentNames: [],
      predictedHours: [],
      usedHours: [],
      remainingHours: [],
      date: new Date(),
      iframe: '',
      iframeAddress: '',
      handleWindowResize: null,
      lastWorkstationStatusSignature: ''
    }
  },
  created() {
    this.iframe = document.getElementById('dmtIframe')
    this.iframeAddress = window.dt_Config?.iframeAddress
    this.loadEquipmentRuntimeHistory() // 历史_工位设备状态每分钟记录_查询
    this.loadNowStatusData() // 当前_设备数据_查询
    this.loadWorkstationStatus() // 基础_工位_查询
    this.setScale()
  },
  mounted() {
    this.timer = setInterval(() => {
      this.date = new Date()
    }, 1000)
    this.initEcharts()
    this.startEquipmentRuntimeHistoryRefresh() // 每分钟刷新一次设备运行履历
    this.startComponentMaintenanceRefresh() // 每分钟刷新一次零部件智能预测性维护
    this.startDailyOutputHistoryRefresh() // 每分钟刷新一次日产量历史数据
    this.startOeeRefresh() // 每2秒刷新一次OEE数据
    this.startWorkstationStatusRefresh() // 每2秒刷新一次设备状态（调用存储过程：基础_工位_查询）
    this.startNowStatusRefresh() // 每2秒刷新一次实时状态（调用存储过程：当前_设备数据_查询）
    this.startToolUseTimeRefresh() // 每分钟刷新一次刀具寿命管理数据
    this.startRealtimeTaskRefresh() // 每2秒刷新一次生产任务实时信息
    this.startFaultStatsRefresh() // 每分钟刷新一次故障统计（过去24小时）
    this.setScale()
    this.handleWindowResize = () => {
      this.setScale()
      if (this.dailyOutputChart) this.dailyOutputChart.resize()
      this.resizeOeeCharts()
      if (this.componentMaintenanceChart) this.componentMaintenanceChart.resize()
      if (this.hourlyOutputChart) this.hourlyOutputChart.resize()
      if (this.faultStatsChart) this.faultStatsChart.resize()
      if (this.deviceStatusChart) this.deviceStatusChart.resize()
    }
    window.addEventListener('resize', this.handleWindowResize)
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
    }
    if (this.dailyOutputRefreshTimer) {
      clearInterval(this.dailyOutputRefreshTimer)
      this.dailyOutputRefreshTimer = null
    }
    if (this.oeeRefreshTimer) {
      clearInterval(this.oeeRefreshTimer)
      this.oeeRefreshTimer = null
    }
    if (this.workstationStatusTimer) {
      clearInterval(this.workstationStatusTimer)
      this.workstationStatusTimer = null
    }
    if (this.nowStatusRefreshTimer) {
      clearInterval(this.nowStatusRefreshTimer)
      this.nowStatusRefreshTimer = null
    }
    if (this.equipmentRuntimeHistoryRefreshTimer) {
      clearInterval(this.equipmentRuntimeHistoryRefreshTimer)
      this.equipmentRuntimeHistoryRefreshTimer = null
    }
    if (this.componentMaintenanceRefreshTimer) {
      clearInterval(this.componentMaintenanceRefreshTimer)
      this.componentMaintenanceRefreshTimer = null
    }
    if (this.toolUseTimeRefreshTimer) {
      clearInterval(this.toolUseTimeRefreshTimer)
      this.toolUseTimeRefreshTimer = null
    }
    if (this.realtimeTaskRefreshTimer) {
      clearInterval(this.realtimeTaskRefreshTimer)
      this.realtimeTaskRefreshTimer = null
    }
    if (this.faultStatsRefreshTimer) {
      clearInterval(this.faultStatsRefreshTimer)
      this.faultStatsRefreshTimer = null
    }
    if (this.handleWindowResize) {
      window.removeEventListener('resize', this.handleWindowResize)
      this.handleWindowResize = null
    }
    if (this.deviceStatusChart) {
      this.deviceStatusChart.dispose()
      this.deviceStatusChart = null
    }
    if (this.componentMaintenanceChart) {
      this.componentMaintenanceChart.dispose()
      this.componentMaintenanceChart = null
    }
    if (this.dailyOutputChart) {
      this.dailyOutputChart.dispose()
      this.dailyOutputChart = null
    }
    this.disposeOeeCharts()
    if (this.hourlyOutputChart) {
      this.hourlyOutputChart.dispose()
      this.hourlyOutputChart = null
    }
    if (this.faultStatsChart) {
      this.faultStatsChart.dispose()
      this.faultStatsChart = null
    }
  },
  computed: {
    oeeValue() {
      return Math.round(
        (Number(this.timeUtilization || 0) *
          Number(this.performanceUtilization || 0) *
          Number(this.qualityRate || 0)) /
          10000,
      )
    },
    nowStatusScrollOption() {
      return {
        step: 0.5,
        limitMoveNum: 6,
        hoverStop: true,
        direction: 1,
        openTouch: false,
        singleHeight: 40,
        waitTime: 1000,
        autoPlay: this.nowStatusList.length > 6
      }
    },
    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')
      const ss = String(d.getSeconds()).padStart(2, '0')
      return `${hh}:${mm}:${ss}`
    },
    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}`
    }
  },
  methods: {
    getScale() {
      const w = window.innerWidth / this.style.width
      const h = window.innerHeight / this.style.height
      return { x: w, y: h }
    },
    getOeeGaugeOption(value) {
      return {
        series: [
          {
            name: 'OEE',
            type: 'gauge',
            radius: '100%',
            center: ['50%', '50%'],
            startAngle: 225,
            endAngle: -45,
            min: 0,
            max: 100,
            splitNumber: 10,
            axisLine: {
              lineStyle: {
                width: 8,
                color: [
                  [0.3, '#91c7ae'],
                  [0.7, '#63869e'],
                  [1, '#c23531']
                ]
              }
            },
            pointer: {
              icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z',
              length: '70%',
              width: 6,
              offsetCenter: [0, '0%'],
              itemStyle: {
                color: 'auto'
              }
            },
            axisTick: {
              show: false
            },
            splitLine: {
              show: false
            },
            axisLabel: {
              color: '#fff',
              fontSize: 7,
              distance: -10
            },
            title: {
              show: false
            },
            detail: {
              show: false
            },
            data: [
              {
                value
              }
            ]
          }
        ]
      }
    },
    initOeeCharts() {
      this.disposeOeeCharts()
      const chartIds = ['oeeChart1', 'oeeChart2', 'oeeChart3', 'oeeChart4']
      this.oeeCharts = chartIds.map((id) => {
        const el = document.getElementById(id)
        return el ? echarts.init(el) : null
      })
      this.updateOeeCharts()
    },
    updateOeeCharts() {
      const values = [
        this.oeeValue,
        this.timeUtilization,
        this.performanceUtilization,
        this.qualityRate
      ]
      this.oeeCharts.forEach((chart, index) => {
        if (!chart) return
        chart.setOption(this.getOeeGaugeOption(values[index]), true)
      })
    },
    resizeOeeCharts() {
      this.oeeCharts.forEach((chart) => {
        if (chart) chart.resize()
      })
    },
    disposeOeeCharts() {
      this.oeeCharts.forEach((chart) => {
        if (chart) chart.dispose()
      })
      this.oeeCharts = []
    },
    startEditOeeField(type) {
      if (type === 'time') {
        this.editingOeeField = 'time'
        this.tempTimeUtilization = this.timeUtilization
        this.$nextTick(() => {
          if (this.$refs.oeeTimeInput) {
            this.$refs.oeeTimeInput.focus()
            this.$refs.oeeTimeInput.select()
          }
        })
        return
      }
      if (type === 'performance') {
        this.editingOeeField = 'performance'
        this.tempPerformanceUtilization = this.performanceUtilization
        this.$nextTick(() => {
          if (this.$refs.oeePerformanceInput) {
            this.$refs.oeePerformanceInput.focus()
            this.$refs.oeePerformanceInput.select()
          }
        })
        return
      }
      if (type === 'quality') {
        this.editingOeeField = 'quality'
        this.tempQualityRate = this.qualityRate
        this.$nextTick(() => {
          if (this.$refs.oeeQualityInput) {
            this.$refs.oeeQualityInput.focus()
            this.$refs.oeeQualityInput.select()
          }
        })
      }
    },
    saveTimeUtilization() {
      const value = Math.max(0, Math.min(100, Number(this.tempTimeUtilization) || 0))
      this.timeUtilization = value
      this.tempTimeUtilization = value
      this.editingOeeField = ''
      this.saveOeeData()
      this.updateOeeCharts()
    },
    savePerformanceUtilization() {
      const value = Math.max(0, Math.min(100, Number(this.tempPerformanceUtilization) || 0))
      this.performanceUtilization = value
      this.tempPerformanceUtilization = value
      this.editingOeeField = ''
      this.saveOeeData()
      this.updateOeeCharts()
    },
    saveQualityRate() {
      const value = Math.max(0, Math.min(100, Number(this.tempQualityRate) || 0))
      this.qualityRate = value
      this.tempQualityRate = value
      this.editingOeeField = ''
      this.saveOeeData()
      this.updateOeeCharts()
    },
    saveOeeData() {
      const data = {
        timeUtilization: this.timeUtilization,
        qualityRate: this.qualityRate,
        performanceUtilization: this.performanceUtilization
      }
      try {
        localStorage.setItem('oeeData', JSON.stringify(data))
      } catch (e) {
        console.error('保存OEE数据失败:', e)
      }
    },
    loadSavedOeeData() {
      try {
        const savedData = localStorage.getItem('oeeData')
        if (!savedData) return
        const data = JSON.parse(savedData)
        const timeValue = Number(data.timeUtilization)
        const qualityValue = Number(data.qualityRate)
        const performanceValue = Number(data.performanceUtilization)
        if (Number.isFinite(timeValue)) {
          this.timeUtilization = timeValue
        }
        if (Number.isFinite(qualityValue)) {
          this.qualityRate = qualityValue
        }
        if (Number.isFinite(performanceValue)) {
          this.performanceUtilization = performanceValue
        }
        this.tempTimeUtilization = this.timeUtilization
        this.tempPerformanceUtilization = this.performanceUtilization
        this.tempQualityRate = this.qualityRate
      } catch (e) {
        console.error('加载保存的OEE数据失败:', e)
      }
    },
    startOeeRefresh() {
      if (this.oeeRefreshTimer) {
        clearInterval(this.oeeRefreshTimer)
        this.oeeRefreshTimer = null
      }
      this.oeeRefreshTimer = setInterval(() => {
        this.loadOeePerformanceData()
      }, 2000)
      this.loadOeePerformanceData()
    },
    loadOeePerformanceData() {
      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) return
          const row = list.find((item) => {
            const workstation = item && (item['工位号'] != null ? item['工位号'] : item.工位号)
            return String(workstation || '').trim() === 'OP1010'
          })
          if (!row) return

          const timeValue = Number(row['OEE_时间利用率'] != null ? row['OEE_时间利用率'] : row.OEE_时间利用率)
          const performanceValue = Number(row['OEE_性能利用率'] != null ? row['OEE_性能利用率'] : row.OEE_性能利用率)
          const qualityValue = Number(row['OEE_良品率'] != null ? row['OEE_良品率'] : row.OEE_良品率)

          if (Number.isFinite(timeValue)) {
            this.timeUtilization = timeValue
            this.tempTimeUtilization = timeValue
          }
          if (Number.isFinite(performanceValue)) {
            this.performanceUtilization = performanceValue
            this.tempPerformanceUtilization = performanceValue
          }
          if (Number.isFinite(qualityValue)) {
            this.qualityRate = qualityValue
            this.tempQualityRate = qualityValue
          }
          this.saveOeeData()
          this.updateOeeCharts()
        })
        .catch((err) => {
          console.error('基础_工位_查询 OEE数据获取失败', err)
        })
    },
    // 实时状态模块：数据库定时刷新
    startNowStatusRefresh() {
      if (this.nowStatusRefreshTimer) {
        clearInterval(this.nowStatusRefreshTimer)
        this.nowStatusRefreshTimer = null
      }
      this.nowStatusRefreshTimer = setInterval(() => {
        this.loadNowStatusData()
      }, 2000)
      this.loadNowStatusData()
    },
    getNowStatusCircleColor(label) {
      const colorMap = {
        关机: 'grey',
        待机: 'orange',
        运行: 'green',
        报警: 'red'
      }
      return colorMap[label] || 'grey'
    },
    updateNowStatusIndicator(statusCode) {
      this.nowStatusIndicators.forEach((item) => {
        item.active = false
      })
      const statusMap = {
        '-1': 0,
        0: 1,
        1: 2,
        2: 3
      }
      const statusIndex = statusMap[String(statusCode)]
      if (statusIndex !== undefined && this.nowStatusIndicators[statusIndex]) {
        this.nowStatusIndicators[statusIndex].active = true
      }
    },
    mapNowStatusText(statusCode) {
      const textMap = {
        '-1': '关机',
        0: '待机',
        1: '运行',
        2: '报警'
      }
      return textMap[String(statusCode)] || String(statusCode || '--')
    },
    applyNowStatusData(tagList) {
      const list = Array.isArray(tagList) ? tagList : []
      const statusRow = list.find((item) => {
        const tagName = item && (item.TagName != null ? item.TagName : item['TagName'])
        return String(tagName || '').trim().toLowerCase() === 'status'
      })
      const statusValue = statusRow && (statusRow.TagValue != null ? statusRow.TagValue : statusRow['TagValue'])
      this.updateNowStatusIndicator(statusValue)
      this.nowStatusList = list
        .filter((item) => {
          const tagName = item && (item.TagName != null ? item.TagName : item['TagName'])
          return String(tagName || '').trim().toLowerCase() !== 'status'
        })
        .map((item, index) => {
          const tagName = item && (item.TagName != null ? item.TagName : item['TagName'])
          const rawValue = item && (item.TagValue != null ? item.TagValue : item['TagValue'])
          return {
            key: `${String(tagName || 'tag')}-${index}`,
            label: String(tagName || '--'),
            value: String(rawValue != null ? rawValue : '--')
          }
        })
    },
    loadNowStatusData() {
      if (this.nowStatusLoading) return
      this.nowStatusLoading = 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)) {
            this.applyNowStatusData(list)
          } else {
            this.nowStatusList = []
          }
        })
        .catch((err) => {
          console.error('实时状态数据获取失败', err)
          this.nowStatusList = []
        })
        .finally(() => {
          this.nowStatusLoading = false
        })
    },
    setScale() {
      const scale = this.getScale()
      this.style.transform =
        'scaleY(' + scale.y + ') scaleX(' + scale.x + ') translate(-50%, -50%)'
    },
    startToolUseTimeRefresh() {
      if (this.toolUseTimeRefreshTimer) {
        clearInterval(this.toolUseTimeRefreshTimer)
        this.toolUseTimeRefreshTimer = null
      }
      this.toolUseTimeRefreshTimer = setInterval(() => {
        this.loadToolUseTimeData()
      }, 60 * 1000)
    },
    startRealtimeTaskRefresh() {
      if (this.realtimeTaskRefreshTimer) {
        clearInterval(this.realtimeTaskRefreshTimer)
        this.realtimeTaskRefreshTimer = null
      }
      this.realtimeTaskRefreshTimer = setInterval(() => {
        this.loadRealtimeTaskData()
      }, 2000)
      this.loadRealtimeTaskData()
    },
    loadRealtimeTaskData() {
      if (this.realtimeTaskLoading) return
      this.realtimeTaskLoading = true
      const param = []
      const data = this.CreateData('11', '接口_生产任务_实时_查询', param)
      this.ExecDatabase(data)
        .then((response) => {
          const list = response && response.data ? response.data : null
          const row = Array.isArray(list) && list.length > 0 ? list[0] : null
          this.realtimeTaskInfo = {
            orderNo: row && row['计划号'] != null ? String(row['计划号']) : '--',
            materialNo: row && row['物料号'] != null ? String(row['物料号']) : '--',
            quantity: row && row['数量'] != null ? String(row['数量']) : '--'
          }
        })
        .catch((err) => {
          console.error('接口_生产任务_实时_查询失败', err)
          this.realtimeTaskInfo = {
            orderNo: '--',
            materialNo: '--',
            quantity: '--'
          }
        })
        .finally(() => {
          this.realtimeTaskLoading = false
        })
    },
    loadToolUseTimeData() {
      if (this.toolUseTimeLoading) return
      if (!this.hourlyOutputChart) return
      this.toolUseTimeLoading = 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.toolUseTimeNames = []
            this.toolUseTimePlanned = []
            this.toolUseTimeActual = []
            this.drawToolUseTimeChart()
            return
          }

          const toolNames = []
          const planned = []
          const actual = []
          list.forEach((item, index) => {
            const toolNo = item && (item['刀具号'] != null ? item['刀具号'] : item.toolNo)
            const toolName = toolNo != null && String(toolNo).trim() !== ''
              ? `刀具${String(toolNo).trim()}`
              : `刀具${index + 1}`
            const plannedTime = Number(item && (item['设定时长'] != null ? item['设定时长'] : item.plannedTime))
            const actualTime = Number(item && (item['使用时长'] != null ? item['使用时长'] : item.actualTime))
            toolNames.push(toolName)
            planned.push(Number.isFinite(plannedTime) ? plannedTime : 0)
            actual.push(Number.isFinite(actualTime) ? actualTime : 0)
          })

          this.toolUseTimeNames = toolNames
          this.toolUseTimePlanned = planned
          this.toolUseTimeActual = actual
          this.drawToolUseTimeChart()
        })
        .catch((err) => {
          console.error('刀具寿命管理数据获取失败', err)
          this.toolUseTimeNames = []
          this.toolUseTimePlanned = []
          this.toolUseTimeActual = []
          this.drawToolUseTimeChart()
        })
        .finally(() => {
          this.toolUseTimeLoading = false
        })
    },
    drawToolUseTimeChart() {
      if (!this.hourlyOutputChart) return
      const toolNames = this.toolUseTimeNames || []
      const planned = this.toolUseTimePlanned || []
      const actual = this.toolUseTimeActual || []

      this.hourlyOutputChart.clear()
      if (!toolNames.length) {
        this.hourlyOutputChart.setOption({
          backgroundColor: 'transparent',
          animation: false,
          xAxis: { show: false, type: 'value' },
          yAxis: { show: false, type: 'category', data: [] },
          series: [],
          graphic: {
            type: 'text',
            left: 'center',
            top: 'middle',
            style: {
              text: '未查询到刀具寿命数据',
              fill: '#fff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        }, true)
        return
      }

      const maxValue = Math.max(...planned, ...actual, 1)
      const plannedDisplay = planned.map((value) => ({
        value,
        realValue: value,
        displayValue: value,
        isActual: false
      }))
      const actualDisplay = actual.map((value) => ({
        value: value > 0 ? Math.max(value, maxValue * 0.03) : 0,
        realValue: value,
        displayValue: value,
        isActual: true
      }))
      const buildBlueBarGradient = () => ({
        type: 'linear',
        x: 0,
        y: 1,
        x2: 0,
        y2: 0,
        colorStops: [
          { offset: 0, color: 'rgba(143, 201, 255, 0.10)' },
          { offset: 0.55, color: '#4d799d' },
          { offset: 1, color: '#eef7ff' }
        ]
      })
      const buildYellowBarGradient = () => ({
        type: 'linear',
        x: 0,
        y: 1,
        x2: 0,
        y2: 0,
        colorStops: [
          { offset: 0, color: 'rgba(255, 193, 131, 0.10)' },
          { offset: 0.55, color: '#ffc183' },
          { offset: 1, color: '#fff4ea' }
        ]
      })

      const option = {
        backgroundColor: 'transparent',
        animation: false,
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          },
          formatter: (params) => {
            let result = `${params[0].name}<br/>`
            params.forEach((param) => {
              const raw = param.data && param.data.realValue != null ? param.data.realValue : param.value
              result += `${param.seriesName}: ${raw}h<br/>`
            })
            return result
          }
        },
        legend: {
          data: ['计划使用时长', '实际使用时长'],
          textStyle: {
            color: '#ffffff'
          },
          orient: 'horizontal',
          right: 10,
          top: 0
        },
        grid: {
          left: '4%',
          right: '4%',
          bottom: '8%',
          top: '18%',
          containLabel: true
        },
        xAxis: {
          type: 'value',
          boundaryGap: [0, 0.01],
          axisLabel: {
            color: '#ffffff',
            fontSize: 10,
            formatter: '{value}h'
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: '#1B3F66'
            }
          },
          splitLine: {
            lineStyle: {
              color: 'rgba(27, 63, 102, 0.6)'
            }
          }
        },
        yAxis: {
          type: 'category',
          data: toolNames,
          axisLabel: {
            color: '#fff',
            fontSize: 10,
            formatter: function(value) {
              if (!value) return ''
              return value.length > 4 ? value.substring(0, 4) + '...' : value
            }
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: '#1B3F66'
            }
          },
          axisTick: {
            alignWithLabel: true
          }
        },
        series: [
          {
            name: '计划使用时长',
            type: 'bar',
            data: plannedDisplay,
            barWidth: 8,
            itemStyle: {
              borderRadius: [0, 2, 2, 0],
              color: buildBlueBarGradient()
            }
          },
          {
            name: '实际使用时长',
            type: 'bar',
            data: actualDisplay,
            barWidth: 8,
            itemStyle: {
              borderRadius: [0, 2, 2, 0],
              color: buildYellowBarGradient()
            },
            label: {
              show: true,
              position: 'right',
              color: '#fff4ea',
              fontSize: 10,
              formatter: (params) => {
                const raw = params.data && params.data.realValue != null ? params.data.realValue : params.value
                return raw > 0 ? `${raw}h` : ''
              }
            }
          }
        ]
      }
      this.hourlyOutputChart.setOption(option, true)
    },
    togglePanelLayout() {
      this.isPanelCollapsed = !this.isPanelCollapsed
    },
    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 oeeDomIds = ['oeeChart1', 'oeeChart2', 'oeeChart3', 'oeeChart4']
      const hasAllOeeDoms = oeeDomIds.every((id) => document.getElementById(id))
      if (hasAllOeeDoms) {
        this.loadSavedOeeData()
        this.$nextTick(() => {
          this.initOeeCharts()
          this.loadOeePerformanceData()
        })
      }
      // 刀具寿命管理图表
      const hourlyEl = document.getElementById('toolUseTimeChart')
      if (hourlyEl) {
        this.hourlyOutputChart = echarts.init(hourlyEl)
        this.drawToolUseTimeChart()
        this.loadToolUseTimeData()
      }
      // 故障统计柱状图
      const faultEl = document.getElementById('faultStatsChart')
      if (faultEl) {
        this.faultStatsChart = echarts.init(faultEl)
        this.faultStatsEventsBound = false
        this.drawFaultStatsChart()
      }
    },
    openModelInfoPopup({ left, top, ModelId, ModelName }) {
      this.modelInfoPopup.visible = true
      this.modelInfoPopup.loading = true
      this.modelInfoPopup.error = ''
      this.modelInfoPopup.base.ModelId = ModelId || ''
      this.modelInfoPopup.base.ModelName = ModelName || ''
      this.modelInfoPopup.detail = null
      this.modelInfoPopup.left = Number(left) || 0
      this.modelInfoPopup.top = Number(top) || 0
      this.$nextTick(() => {
        this.fixModelInfoPopupPosition()
      })
      this.fetchModelInfoPopupDetail(ModelId)
    },
    closeModelInfoPopup() {
      this.modelInfoPopup.visible = false
      this.modelInfoPopup.loading = false
      this.modelInfoPopup.error = ''
      this.modelInfoPopup.detail = null
    },
    fixModelInfoPopupPosition() {
      const el = this.$refs.modelInfoPopupRef
      if (!el) return
      const rect = el.getBoundingClientRect()
      const margin = 10
      let left = this.modelInfoPopup.left
      let top = this.modelInfoPopup.top
      const maxLeft = window.innerWidth - rect.width - margin
      const maxTop = window.innerHeight - rect.height - margin
      left = Math.max(margin, Math.min(left, maxLeft))
      top = Math.max(margin, Math.min(top, maxTop))
      this.modelInfoPopup.left = left
      this.modelInfoPopup.top = top
    },
    // 设备状态模块：每秒刷新一次（调用存储过程：基础_工位_查询）
    startWorkstationStatusRefresh() {
      if (this.workstationStatusTimer) {
        clearInterval(this.workstationStatusTimer)
        this.workstationStatusTimer = null
      }
      this.workstationStatusTimer = setInterval(() => {
        this.loadWorkstationStatus()
      }, 2000)
    },
    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' }
          }

          const nextDeviceStatusList = 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
            }
          })
          const signature = JSON.stringify(nextDeviceStatusList)
          if (signature !== this.lastWorkstationStatusSignature) {
            this.lastWorkstationStatusSignature = signature
            this.deviceStatusList = nextDeviceStatusList
          }
        })
        .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() // key: YYYY-MM-DD -> { md, time, sum }
          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)
            .slice(-7)
          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
        })
    },
    // 绘制日产量折线图
    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: '#fff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        }
        this.dailyOutputChart.setOption(optionEmpty)
        return
      }

      const maxValue = Math.max.apply(null, data)
      const maxIndex = data.indexOf(maxValue)
      const lineColor = '#4fc3e8'
      const pointColor = '#dff8ff'
      const topAreaColor = 'rgba(79, 195, 232, 0.30)'
      const option = {
        backgroundColor: 'transparent',
        animation: false,
        grid: {
          top: '18%',
          bottom: '11%',
          left: '8%',
          right: '8%'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'line',
            lineStyle: {
              color: 'rgba(79, 195, 232, 0.45)'
            }
          },
          formatter: (params) => {
            const p = params && params[0]
            if (!p) return ''
            return `${p.axisValue}<br/>日产量：${p.value}`
          }
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: dates,
          axisLabel: {
            color: '#fff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          axisTick: { show: false }
        },
        yAxis: {
          type: 'value',
          axisLabel: {
            color: '#fff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          splitLine: {
            lineStyle: { color: 'rgba(27, 63, 102, 0.6)' }
          }
        },
        graphic: [],
        series: [
          {
            type: 'line',
            name: '日产量',
            smooth: false,
            showSymbol: true,
            symbol: 'circle',
            symbolSize: 5,
            data: data,
            lineStyle: {
              color: lineColor,
              width: 1
            },
            itemStyle: {
              color: pointColor,
              borderColor: lineColor,
              borderWidth: 2
            },
            areaStyle: {
              color: {
                type: 'linear',
                x: 0,
                y: 0,
                x2: 0,
                y2: 1,
                colorStops: [
                  { offset: 0, color: topAreaColor },
                  { offset: 1, color: 'rgba(79, 195, 232, 0)' }
                ]
              }
            },
            markPoint: {
              symbol: 'circle',
              symbolSize: 5,
              itemStyle: {
                color: pointColor,
                borderColor: lineColor,
                borderWidth: 2
              },
              label: {
                show: true,
                position: 'top',
                distance: 10,
                color: '#dff8ff',
                fontSize: 12,
                fontWeight: 'bold',
                formatter: 'Max:{c}'
              },
              data: [
                {
                  coord: [dates[maxIndex], maxValue],
                  value: maxValue
                }
              ]
            },
            emphasis: {
              focus: 'series'
            }
          }
        ]
      }
      this.dailyOutputChart.setOption(option)
    },

    drawFaultStatsChart() {
      if (!this.faultStatsChart) return
      const optionData = (this.faultStatsData || []).map((item) => ({
        name: item && item.name != null ? String(item.name) : '',
        value: Number(item && item.value) || 0
      }))

      this.faultStatsChart.clear()
      if (!optionData.length) {
        this.faultStatsChart.setOption({
          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: '#fff',
              fontSize: 16,
              fontFamily: 'Microsoft YaHei'
            }
          }
        })
        return
      }

      const values = optionData.map((item) => item.value)
      const maxAxis = this.getMaintenanceAxisMax(values)
      const buildBlueBarGradient = () => ({
        type: 'linear',
        x: 0,
        y: 1,
        x2: 0,
        y2: 0,
        colorStops: [
          { offset: 0, color: 'rgba(143, 201, 255, 0.10)' },
          { offset: 0.55, color: '#4d799d' },
          { offset: 1, color: '#eef7ff' }
        ]
      })

      const option = {
        backgroundColor: 'transparent',
        animation: false,
        grid: {
          top: '16%',
          bottom: '10%',
          left: '10%',
          right: '6%'
        },
        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: optionData.map((item) => item.name),
          axisLabel: {
            color: '#fff',
            fontSize: 11,
            interval: 0
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          axisTick: { show: false }
        },
        yAxis: {
          type: 'value',
          minInterval: 1,
          max: maxAxis,
          interval: maxAxis / 5,
          axisLabel: {
            color: '#fff',
            fontSize: 10
          },
          axisLine: {
            show: true,
            lineStyle: { color: '#1B3F66' }
          },
          splitLine: {
            lineStyle: { color: 'rgba(27, 63, 102, 0.6)' }
          }
        },
        series: [
          {
            type: 'bar',
            name: '报警次数',
            data: values,
            barWidth: 18,
            itemStyle: {
              borderRadius: [2, 2, 0, 0],
              color: buildBlueBarGradient()
            },
            label: {
              show: true,
              position: 'top',
              color: '#dff8ff',
              fontSize: 12,
              fontWeight: 'bold',
              formatter: '{c}'
            }
          }
        ]
      }

      this.faultStatsChart.setOption(option, true)
    },
    startFaultStatsRefresh() {
      if (this.faultStatsRefreshTimer) {
        clearInterval(this.faultStatsRefreshTimer)
        this.faultStatsRefreshTimer = null
      }
      this.faultStatsRefreshTimer = setInterval(() => {
        this.loadFaultStatsHistory()
      }, 60 * 1000)
      this.loadFaultStatsHistory()
    },
    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
          if (!Array.isArray(list) || list.length === 0) {
            this.faultStatsData = []
            this.drawFaultStatsChart()
            return
          }

          this.faultStatsData = list.map((row, index) => {
            const alarmContent =
              row && (row['报警内容'] != null ? row['报警内容'] : row.报警内容)
            const workstation =
              row && (row['工位号'] != null ? row['工位号'] : row.工位号)
            const rawCount =
              row && (row['报警数量'] != null ? row['报警数量'] : row.报警数量)
            const name = alarmContent != null && String(alarmContent).trim()
              ? String(alarmContent).trim()
              : (workstation != null && String(workstation).trim()
                ? String(workstation).trim()
                : `报警${index + 1}`)
            return {
              name,
              value: Number(rawCount) || 0
            }
          })
          this.drawFaultStatsChart()
        })
        .catch((err) => {
          console.error('报警_记录_历史_查询_简化版失败', err)
          this.faultStatsData = []
          this.drawFaultStatsChart()
        })
        .then(() => {
          this.faultStatsLoading = false
        })
    },
    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: '#fff',
                fontSize: 16,
                fontFamily: 'Microsoft YaHei'
              }
            }
          },
          true,
        )
        return
      }
      // 设备状态映射
      const statusMap = {
        '-1': {
          name: '离线',
          color: '#878787'
        },
        0: {
          name: '待机',
          color: '#d49436'
        },
        1: {
          name: '运行',
          color: '#2d8f47'
        },
        2: {
          name: '报警',
          color: '#c23b48'
        }
      }
      // 处理数据，按工位号分组并按时间排序
      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,
                shadowBlur: 8,
                shadowColor: statusInfo.shadowColor || 'rgba(0, 0, 0, 0.25)',
                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: '2%',
          right: '5%',
          bottom: '8%',
          top: '7%',
          containLabel: true
        },
        xAxis: {
          type: 'time',
          axisLine: { show: false, lineStyle: { color: '#fff' }},
          axisLabel: {
            show: true,
            color: '#fff',
            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: '#fff' }},
          axisLabel: { color: '#fff', 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
                  },
                  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()
      },  60000)
    },
    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 predicted = item['制定'] != null ? Number(item['制定']) : 0
              const used = item['已用'] != null ? Number(item['已用']) : 0
              const remaining =
                item['剩余'] != null
                  ? Number(item['剩余'])
                  : Math.max(predicted - used, 0)
              this.componentNames.push(name)
              this.predictedHours.push(predicted)
              this.usedHours.push(used)
              this.remainingHours.push(remaining)
            })
            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: '#fff',
                fontSize: 16,
                fontFamily: 'Microsoft YaHei'
              }
            }
          },
          true,
        )
        return
      }
      const maxAxis = this.getMaintenanceAxisMax([
        ...predicted,
        ...used,
        ...remaining
      ])
      const barWidth = 8
      const barGap = '20%'
      const categoryGap = '20%'
      const displayNames = names.slice(0, 5)
      const buildBarGradient = (bottomColor, middleColor, topColor) => ({
        type: 'linear',
        x: 0,
        y: 1,
        x2: 0,
        y2: 0,
        colorStops: [
          { offset: 0, color: bottomColor },
          { offset: 0.55, color: middleColor },
          { offset: 1, color: topColor }
        ]
      })

      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) {
              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: '5%',
          bottom: '20%',
          top: '10%'
        },
        xAxis: {
          type: 'category',
          data: displayNames,
          axisLabel: {
            color: '#fff',
            fontSize: 12,
            interval: 0,
            lineHeight: 16,
            formatter: function(value) {
              if (!value) return ''
              if (value.length <= 4) return value
              const lines = []
              for (let i = 0; i < value.length; i += 4) {
                lines.push(value.slice(i, i + 4))
              }
              return lines.join('\n')
            }
          },
          axisLine: {
            show: false
          },
          axisTick: {
            alignWithLabel: true
          }
        },
        yAxis: {
          type: 'value',
          max: maxAxis,
          interval: maxAxis / 5,
          axisLabel: {
            color: '#ffffff',
            formatter: function(value) {
              return `${Math.round(value / 1000)}Kh`
            }
          },
          axisLine: {
            show: false
          },
          splitLine: {
            lineStyle: {
              color: 'rgba(255, 255, 255, 0.1)'
            }
          }
        },
        series: [
          {
            type: 'bar',
            name: '预测时间',
            data: predicted.slice(0, 5),
            barWidth,
            barGap,
            barCategoryGap: categoryGap,
            itemStyle: {
              borderRadius: [2, 2, 0, 0],
              color: buildBarGradient(
                'rgba(146, 226, 173, 0.10)',
                '#92e2ad',
                '#eefcf2',
              )
            }
          },
          {
            type: 'bar',
            name: '使用时间',
            data: used.slice(0, 5),
            barWidth,
            barGap,
            barCategoryGap: categoryGap,
            itemStyle: {
              borderRadius: [2, 2, 0, 0],
              color: buildBarGradient(
                'rgba(143, 201, 255, 0.10)',
                '#4d799d',
                '#eef7ff',
              )
            }
          },
          {
            type: 'bar',
            name: '剩余时间',
            data: remaining.slice(0, 5),
            barWidth,
            barGap,
            barCategoryGap: categoryGap,
            itemStyle: {
              borderRadius: [2, 2, 0, 0],
              color: buildBarGradient(
                'rgba(255, 193, 131, 0.10)',
                '#ffc183',
                '#fff4ea',
              )
            }
          }
        ]
      }

      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: url("/png/背景底图.png") no-repeat center center;
  background-size: cover;
  color: white;
}

.daily-output-box {
  width: 100%;
  height: 180px;
  overflow: hidden;
}

.oee-analysis-box {
  width: 100%;
  height: 185px;
  overflow: hidden;
}

.left-title-header {
  width: 100%;
  height: 35px;
  background: url("/png/left.png") no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  padding-left: 25px;
  box-sizing: border-box;
}
.left-title-text{
  font-size: 20px;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}
.box-title {
  font-size: 25px;
  font-weight: 700;
  -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% - 35px);
  box-sizing: border-box;
}

.oee-analysis-body {
  width: 100%;
  height: calc(100% - 35px);
  box-sizing: border-box;
}

.oee-chart-group {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.oee-chart-item {
  position: relative;
  flex: 1;
  height: 100%;
  margin: 0 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.oee-chart-item--editable {
  cursor: pointer;
}

.oee-chart-item--editable:hover .oee-chart {
  transform: scale(1.04);
}

.oee-chart {
  width: 100%;
  height: 108px;
  transition: transform 0.3s;
}

.oee-chart-title {
  position: absolute;
  top: 92px;
  color: #fff;
  font-size: 12px;
  text-align: center;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.oee-chart-value {
  position: absolute;
  top: 108px;
  min-height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #409EFF;
  font-size: 14px;
  text-align: center;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.oee-chart-input {
  width: 50px;
  padding: 2px 4px;
  box-sizing: border-box;
  border: 1px solid #0070c0;
  border-radius: 2px;
  outline: none;
  background: rgba(255, 255, 255, 0.1);
  color: #409EFF;
  font-size: 14px;
  text-align: center;
}

.oee-chart-input:focus {
  border-color: #67C23A;
  background: rgba(255, 255, 255, 0.2);
}

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

.storage-status-box {
  height: 410px;
  overflow: hidden;
}

.right-title-header {
  width: 100%;
  height: 35px;
  background: url("/png/right.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;
}
.right-title-text{
  font-size: 20px;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}
.storage-status-body {
  width: 100%;
  height: calc(100% - 35px);
  box-sizing: border-box;
  padding: 10px;
}

.now-status-body {
  position: relative;
  overflow: hidden;
}

.now-status-scroll-wrapper {
  height: 100%;
  overflow: hidden;
}

.now-status-fixed-row {
  display: grid;
  grid-template-columns: 95px 1fr;
  align-items: center;
  min-height: 42px;
  margin-bottom: 8px;
  padding: 6px 10px;
  box-sizing: border-box;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
}

.now-status-fixed-label {
  color: #fff;
  font-size: 16px;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.now-status-indicators {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}

.now-status-indicator-item {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}

.now-status-circle {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  display: inline-block;
  background: grey;
  transition: background-color 0.3s ease;
}

.now-status-circle--active {
  box-shadow: 0 0 8px currentColor;
}

.now-status-indicator-label {
  margin-left: 5px;
  color: #fff;
  font-size: 12px;
  white-space: nowrap;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.now-status-scroll-container {
  position: relative;
  height: calc(100% - 50px);
  overflow: hidden;
}

.now-status-scroll-wrapper {
  height: 100%;
  overflow: hidden;
}

.now-status-scroll-content {
  width: 100%;
}

.now-status-row {
  display: grid;
  grid-template-columns: 95px 1fr;
  align-items: center;
  height: 40px;
  padding: 5px 10px;
  box-sizing: border-box;
  color: #fff;
  font-size: 15px;
  border-radius: 4px;
  transition: background-color 0.3s;
}

.now-status-row:hover {
  background: rgba(0, 112, 192, 0.2);
}

.now-status-row-label,
.now-status-row-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.realtimeTask-box {
  position: absolute;
  top: 18px;
  left: 392px;
  width: 1070px;
  height: 72px;
  display: flex;
  align-items: center;
  padding: 0 14px;
  box-sizing: border-box;
  background: linear-gradient(180deg, rgba(17, 52, 98, 0.92) 0%, rgba(7, 26, 56, 0.92) 100%);
  border: 1px solid rgba(91, 180, 255, 0.45);
  box-shadow: inset 0 0 24px rgba(37, 111, 184, 0.35);
}

.realtime-task-grid {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 18px;
}

.realtime-task-item {
  min-width: 0;
  display: grid;
  grid-template-columns: 65px 1fr;
  align-items: center;
  padding: 0 14px;
  box-sizing: border-box;
}

.realtime-task-label {
  color: #cfe8ff;
  font-size: 18px;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.realtime-task-value {
  color: #ffffff;
  font-size: 20px;
  font-weight: 700;
  text-align: right;
  overflow: hidden;
  white-space: nowrap;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

.hourly-output-box {
  height: 250px;
  overflow: hidden;
}

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

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

.fault-stats-box {
  height: 250px;
  overflow: visible;
}

.fault-stats-body {
  width: 100%;
  height: calc(100% - 35px);
  box-sizing: border-box;
  overflow: hidden;
}

.fault-stats-chart {
  width: 100%;
  height: 100%;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
  font-size: 18px;
  font-weight: 700;
}

.component-maintenance-box {
  width: 100%;
  height: 280px;
  overflow: hidden;
}

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

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

.device-status-box {
  width: 100%;
  height: 262px;
  overflow: hidden;
}

.device-status-body {
  width: 100%;
  height: calc(100% - 35px);
  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 {
  background: rgba(79, 131, 180, 0.5);
}

.device-status-cell {
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
  color: #fff;
  font-family: "Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif;
}

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

.device-status-pill--running {
  background: radial-gradient(circle at center, rgba(56, 136, 17, 0.3) 0%, rgba(56, 136, 17, 1) 100%);
}

.device-status-pill--alarm {
  background: radial-gradient(circle at center, rgba(210, 73, 86, 0.3) 0%, rgba(210, 73, 86, 1) 100%);
}

.device-status-pill--standby {
  background: radial-gradient(circle at center, rgba(204, 121, 0, 0.3) 0%, rgba(204, 121, 0, 1) 100%);
}

.device-status-pill--offline {
  background: radial-gradient(circle at center, rgba(135, 135, 135, 0.3) 0%, rgba(135, 135, 135, 1) 100%);
}

.df-header__right {
  position: absolute;
  top: 30px;
  right: 30px;
  width: 200px;
}

.df-header__timebar {
  display: flex;
  align-items: center;
  gap: 20px;
  color: #ffffff;
}

.df-header__time {
  order: 1;
  /* 确保时间在最左侧 */
}

.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% - 35px);
  min-height: 0;
}

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

.main-content {
  height: 100%;
  width: 100%;
  position: absolute;
  top: 100px;
}
.realtimeTask-box{
  position: absolute;
  left: 526px;
  top: 0px;
  width: 907px;
  height: 80px;
}
.status-timeline-box {
  position: absolute;
  left: 526px;
  top: 732px;
  width: 907px;
  height: 202px;
  overflow: hidden;
  background-image: url("/png/2.png");
  background-size: cover;
  background-repeat: no-repeat;
}

.status-timeline-header {
  width: 36%;
  height: 35px;
  background: url(/png/小标题-6.png) no-repeat center center;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  margin-top: 5px;
  margin-left: 16px;
}

.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;
}

.title-png {
  position: absolute;
  top: 0;
  left: 0;
  height: 100px;
  width: 100%;
  background-image: url("/png/top1.png");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
  display: flex;
  justify-content: center;
}

.title-text {
  color: #fff;
  font-size: 37px;
  font-weight: bold;
  text-align: center;
  margin-top: 15px;
  margin-right: 37px;
  font-family: "Microsoft YaHei", "\5FAE\8F6F\96C5\9ED1", "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.leftLine {
  z-index: 30;
  position: absolute;
  width: 54px;
  height: 1020px;
  top: 30px;
  left: 10px;
  margin-top: 20px;
  background-image: url(/png/左边条.png);
  background-size: 100% 100%;
  background-position: center;
}
.rightLine {
  z-index: 30;
  position: absolute;
  width: 54px;
  height: 1020px;
  top: 30px;
  right: 10px;
  margin-top: 20px;
  background-image: url(/png/右边条.png);
  background-size: 100% 100%;
  background-position: center;
}
.left-box {
  position: absolute;
  top: 0px;
  left: 30px;
  width: 336px;
  background-image: url(/png/1.png);
  background-size: cover;
  background-repeat: no-repeat;
  min-height: 724px;
}

.right-box {
  position: absolute;
  top: 0px;
  right: 30px;
  width: 336px;
  min-height: 724px;
  background-image: url(/png/1.png);
  background-size: cover;
  background-repeat: no-repeat;
}

.button1 {
  position: absolute;
  top: 100px;
  left: 0;
  width: 88px;
  height: 35px;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  border: none;
  padding: 0;
  cursor: pointer;
  z-index: 20;
}

.cirle {
  pointer-events: none;
  background-image: url(/png/圆环.png);
  position: absolute;
  inset: 0;
  top: 20px;
  background-size: 95% 95%;
  background-repeat: no-repeat;
  background-position: center;
  border: none;
  padding: 0;
  z-index: 1;
}
</style>
