|
|
@@ -1,243 +1,203 @@
|
|
|
<template>
|
|
|
<div class="ignition-view monitor-view">
|
|
|
- <!-- 左上:设备运行状态 -->
|
|
|
+ <!-- 左上:自然发火阶段 -->
|
|
|
<ModuleCommon
|
|
|
- :show-style="panelShowStyle(23, 105, 328, 430)"
|
|
|
+ :show-style="panelShowStyle(20, 77, 380, 330)"
|
|
|
:module-data="EMPTY_MODULE_DATA"
|
|
|
- module-name="设备运行状态"
|
|
|
- device-type="ignition_device_status"
|
|
|
+ module-name="自然发火阶段"
|
|
|
+ device-type="ignition_fire_stage"
|
|
|
:data="{}"
|
|
|
:visible="true"
|
|
|
>
|
|
|
- <div class="device-panel">
|
|
|
- <div v-for="device in devices" :key="device.name" class="device-item">
|
|
|
- <span class="device-badge"><i></i></span>
|
|
|
- <div class="device-main">
|
|
|
- <div class="device-line">
|
|
|
- <span class="device-name">{{ device.name }}</span>
|
|
|
- <span class="device-rate">{{ runningRate(device) }}%</span>
|
|
|
- </div>
|
|
|
- <div class="device-bar"><i :style="{ width: `${runningRate(device)}%` }"></i></div>
|
|
|
- <div class="device-meta">
|
|
|
- 安装 <em>{{ device.installed }}</em> 套 · 运行 <em>{{ device.running }}</em> 套
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <div class="stage-panel">
|
|
|
+ <button class="evaluation-entry" @click="emit('view-evaluation')">查看评价结果</button>
|
|
|
+ <div class="stage-level" :style="{ color: NATURAL_FIRE_STAGE.color }">
|
|
|
+ {{ NATURAL_FIRE_STAGE.levelText }} {{ NATURAL_FIRE_STAGE.levelName }}
|
|
|
</div>
|
|
|
+ <div class="stage-bar"></div>
|
|
|
</div>
|
|
|
</ModuleCommon>
|
|
|
|
|
|
- <!-- 左下:实时预警信息 -->
|
|
|
+ <!-- 左中:光纤测温 -->
|
|
|
<ModuleCommon
|
|
|
- :show-style="panelShowStyle(23, 555, 328, 420)"
|
|
|
+ class="fiber-module"
|
|
|
+ :show-style="panelShowStyle(20, 425, 380, 237)"
|
|
|
:module-data="EMPTY_MODULE_DATA"
|
|
|
- module-name="实时预警信息"
|
|
|
- device-type="ignition_realtime_alert"
|
|
|
+ module-name="光纤测温"
|
|
|
+ device-type="ignition_fiber_temperature"
|
|
|
:data="{}"
|
|
|
:visible="true"
|
|
|
>
|
|
|
- <div class="alert-panel">
|
|
|
- <div v-for="alert in alerts" :key="alert.id" class="alert-item" :style="{ '--alert-color': alertColor(alert.level) }">
|
|
|
- <div class="alert-top">
|
|
|
- <span class="alert-time">{{ alert.time }}</span>
|
|
|
- <span class="alert-level">{{ alertLevelName(alert.level) }}</span>
|
|
|
- <span class="alert-location">{{ alert.location }}</span>
|
|
|
+ <div class="fiber-panel">
|
|
|
+ <FiberTemperatureChart :data="FIBER_CHART_DATA" :active="active" />
|
|
|
+ </div>
|
|
|
+ </ModuleCommon>
|
|
|
+
|
|
|
+ <!-- 右上:传感器监测 -->
|
|
|
+ <ModuleCommon
|
|
|
+ :show-style="panelShowStyle(1519, 77, 379, 330)"
|
|
|
+ :module-data="EMPTY_MODULE_DATA"
|
|
|
+ module-name="传感器监测"
|
|
|
+ device-type="ignition_sensor_monitor"
|
|
|
+ :data="{}"
|
|
|
+ :visible="true"
|
|
|
+ >
|
|
|
+ <div class="sensor-panel">
|
|
|
+ <div v-for="group in SENSOR_GROUPS" :key="group.name" class="sensor-group">
|
|
|
+ <div class="sensor-group-title">{{ group.name }}</div>
|
|
|
+ <div v-for="row in group.rows" :key="row.label" class="sensor-row">
|
|
|
+ <span>{{ row.label }}:</span>
|
|
|
+ <em>{{ row.value }}</em>
|
|
|
</div>
|
|
|
- <div class="alert-message">{{ alert.message }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</ModuleCommon>
|
|
|
|
|
|
- <!-- 右上:束管监测实时分析 -->
|
|
|
+ <!-- 右中:预警处置意见 -->
|
|
|
<ModuleCommon
|
|
|
- :show-style="panelShowStyle(380, 145, 1477, 390)"
|
|
|
+ :show-style="panelShowStyle(1519, 425, 379, 237)"
|
|
|
:module-data="EMPTY_MODULE_DATA"
|
|
|
- module-name="束管监测实时分析"
|
|
|
+ module-name="预警处置意见"
|
|
|
+ device-type="ignition_alert_advice"
|
|
|
+ :data="{}"
|
|
|
+ :visible="true"
|
|
|
+ >
|
|
|
+ <div class="advice-panel">
|
|
|
+ <span class="advice-icon"></span>
|
|
|
+ <p>{{ ALERT_ADVICE }}</p>
|
|
|
+ </div>
|
|
|
+ </ModuleCommon>
|
|
|
+
|
|
|
+ <!-- 左下:束管监测 -->
|
|
|
+ <ModuleCommon
|
|
|
+ class="wide-module"
|
|
|
+ :show-style="panelShowStyle(20, 710, 930, 349)"
|
|
|
+ :module-data="EMPTY_MODULE_DATA"
|
|
|
+ module-name="束管监测"
|
|
|
device-type="ignition_bundle_monitor"
|
|
|
:data="{}"
|
|
|
:visible="true"
|
|
|
>
|
|
|
- <div class="bundle-panel">
|
|
|
- <div class="bundle-head">
|
|
|
- <span class="col-point">测点名称</span>
|
|
|
- <span class="col-value">O₂(%)</span>
|
|
|
- <span class="col-value">CO(ppm)</span>
|
|
|
- <span class="col-value">CH₄(%)</span>
|
|
|
- <span class="col-value">C₂H₄(ppm)</span>
|
|
|
- <span class="col-value">温度(℃)</span>
|
|
|
- <span class="col-status">状态</span>
|
|
|
- </div>
|
|
|
- <div class="bundle-body">
|
|
|
- <div v-for="row in bundleRows" :key="row.point" class="bundle-row">
|
|
|
- <span class="col-point">{{ row.point }}</span>
|
|
|
- <span class="col-value" :class="{ warning: Number(row.o2) < 18 }">{{ row.o2 }}</span>
|
|
|
- <span class="col-value" :class="{ warning: row.co >= 24 }">{{ row.co }}</span>
|
|
|
- <span class="col-value">{{ row.ch4 }}</span>
|
|
|
- <span class="col-value">{{ row.c2h4 }}</span>
|
|
|
- <span class="col-value">{{ row.temp.toFixed(1) }}</span>
|
|
|
- <span class="col-status">
|
|
|
- <i class="status-tag" :class="statusClass(row.status)">{{ row.status }}</i>
|
|
|
- </span>
|
|
|
+ <div class="table-panel">
|
|
|
+ <div class="data-table bundle-table">
|
|
|
+ <div class="table-head">
|
|
|
+ <span>设备编号</span>
|
|
|
+ <span>氧气</span>
|
|
|
+ <span>氮气</span>
|
|
|
+ <span>一氧化碳</span>
|
|
|
+ <span>二氧化碳</span>
|
|
|
+ <span>甲烷</span>
|
|
|
+ <span>乙烯</span>
|
|
|
+ <span>乙烷</span>
|
|
|
+ <span>乙炔</span>
|
|
|
+ </div>
|
|
|
+ <div ref="bundleBodyRef" class="table-body">
|
|
|
+ <div v-for="(row, index) in pagedBundleRows" :key="`${row.deviceNo}-${bundlePage}-${index}`" class="table-row">
|
|
|
+ <span>{{ row.deviceNo }}</span>
|
|
|
+ <span>{{ row.o2 }}</span>
|
|
|
+ <span>{{ row.n2 }}</span>
|
|
|
+ <span>{{ row.co }}</span>
|
|
|
+ <span>{{ row.co2 }}</span>
|
|
|
+ <span>{{ row.ch4 }}</span>
|
|
|
+ <span>{{ row.c2h4 }}</span>
|
|
|
+ <span>{{ row.c2h6 }}</span>
|
|
|
+ <span>{{ row.c2h2 }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="table-pager">
|
|
|
+ <i v-for="page in totalPages" :key="page" :class="{ active: page === bundlePage }" @click="changeBundlePage(page)"></i>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</ModuleCommon>
|
|
|
|
|
|
- <!-- 右下:光纤测温趋势分析 -->
|
|
|
+ <!-- 右下:设备实时监测与分析 -->
|
|
|
<ModuleCommon
|
|
|
- :show-style="panelShowStyle(380, 555, 1477, 420)"
|
|
|
+ class="wide-module"
|
|
|
+ :show-style="panelShowStyle(969, 710, 929, 349)"
|
|
|
:module-data="EMPTY_MODULE_DATA"
|
|
|
- module-name="光纤测温趋势分析"
|
|
|
- device-type="ignition_fiber_trend"
|
|
|
+ module-name="设备实时监测与分析"
|
|
|
+ device-type="ignition_device_monitor"
|
|
|
:data="{}"
|
|
|
:visible="true"
|
|
|
>
|
|
|
- <div class="fiber-panel">
|
|
|
- <div class="chart-area">
|
|
|
- <div class="chart-legend">
|
|
|
- <span class="legend-item"><i class="legend-max"></i>最高温度</span>
|
|
|
- <span class="legend-item"><i class="legend-avg"></i>平均温度</span>
|
|
|
+ <div class="table-panel">
|
|
|
+ <div class="data-table device-table">
|
|
|
+ <div class="table-head">
|
|
|
+ <span>设备编号</span>
|
|
|
+ <span>氧气</span>
|
|
|
+ <span>一氧化碳</span>
|
|
|
+ <span>二氧化碳</span>
|
|
|
+ <span>甲烷</span>
|
|
|
+ <span>温度</span>
|
|
|
+ <span>压差</span>
|
|
|
</div>
|
|
|
- <svg class="chart-svg" viewBox="0 0 1100 300" preserveAspectRatio="none">
|
|
|
- <defs>
|
|
|
- <linearGradient id="ignitionFiberArea" x1="0" y1="0" x2="0" y2="1">
|
|
|
- <stop offset="0" stop-color="#3df6ff" stop-opacity="0.28" />
|
|
|
- <stop offset="1" stop-color="#3df6ff" stop-opacity="0" />
|
|
|
- </linearGradient>
|
|
|
- </defs>
|
|
|
- <g>
|
|
|
- <line
|
|
|
- v-for="tick in yTicks"
|
|
|
- :key="`grid-${tick}`"
|
|
|
- :x1="chartPadding.left"
|
|
|
- :x2="chartWidth - chartPadding.right"
|
|
|
- :y1="yPosition(tick)"
|
|
|
- :y2="yPosition(tick)"
|
|
|
- stroke="rgba(61, 246, 255, 0.14)"
|
|
|
- stroke-width="1"
|
|
|
- vector-effect="non-scaling-stroke"
|
|
|
- />
|
|
|
- <text
|
|
|
- v-for="tick in yTicks"
|
|
|
- :key="`label-${tick}`"
|
|
|
- :x="chartPadding.left - 10"
|
|
|
- :y="yPosition(tick) + 4"
|
|
|
- fill="#8fc7e8"
|
|
|
- font-size="11"
|
|
|
- text-anchor="end"
|
|
|
- >
|
|
|
- {{ tick }}℃
|
|
|
- </text>
|
|
|
- </g>
|
|
|
- <path :d="maxAreaPath" fill="url(#ignitionFiberArea)" />
|
|
|
- <polyline :points="maxPoints" fill="none" stroke="#3df6ff" stroke-width="2" vector-effect="non-scaling-stroke" stroke-linejoin="round" />
|
|
|
- <polyline
|
|
|
- :points="avgPoints"
|
|
|
- fill="none"
|
|
|
- stroke="#ffd15c"
|
|
|
- stroke-width="1.5"
|
|
|
- stroke-dasharray="5 3"
|
|
|
- vector-effect="non-scaling-stroke"
|
|
|
- stroke-linejoin="round"
|
|
|
- />
|
|
|
- <g>
|
|
|
- <text v-for="item in xLabels" :key="item.text" :x="item.x" :y="chartHeight - 8" fill="#8fc7e8" font-size="11" text-anchor="middle">
|
|
|
- {{ item.text }}
|
|
|
- </text>
|
|
|
- </g>
|
|
|
- </svg>
|
|
|
- </div>
|
|
|
- <div class="fiber-summary">
|
|
|
- <div class="summary-item">
|
|
|
- <span>最高温度</span>
|
|
|
- <em class="max">{{ fiber.maxValue.toFixed(1) }}℃</em>
|
|
|
- </div>
|
|
|
- <div class="summary-item">
|
|
|
- <span>平均温度</span>
|
|
|
- <em class="avg">{{ fiber.avgValue.toFixed(1) }}℃</em>
|
|
|
- </div>
|
|
|
- <div class="summary-item">
|
|
|
- <span>测温点数</span>
|
|
|
- <em>{{ fiber.pointCount }} 个</em>
|
|
|
+ <div ref="deviceBodyRef" class="table-body">
|
|
|
+ <div v-for="(row, index) in pagedDeviceRows" :key="`${row.deviceNo}-${devicePage}-${index}`" class="table-row">
|
|
|
+ <span>{{ row.deviceNo }}</span>
|
|
|
+ <span>{{ row.o2 }}</span>
|
|
|
+ <span>{{ row.co }}</span>
|
|
|
+ <span>{{ row.co2 }}</span>
|
|
|
+ <span>{{ row.ch4 }}</span>
|
|
|
+ <span>{{ row.temp }}</span>
|
|
|
+ <span>{{ row.pressureDiff }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="table-pager">
|
|
|
+ <i v-for="page in totalPages" :key="page" :class="{ active: page === devicePage }" @click="changeDevicePage(page)"></i>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</ModuleCommon>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
- import { computed } from 'vue';
|
|
|
+ import { computed, nextTick, ref } from 'vue';
|
|
|
import ModuleCommon from '../../configurable/components/ModuleCommon.vue';
|
|
|
+ import FiberTemperatureChart from './FiberTemperatureChart.vue';
|
|
|
import { EMPTY_MODULE_DATA, panelShowStyle } from '../utils';
|
|
|
- import { RISK_LEVELS } from '../data';
|
|
|
- import type { AlertItem, BundleRow, DeviceInstallItem, FiberTrend } from '../data';
|
|
|
-
|
|
|
- const props = defineProps<{
|
|
|
- devices: DeviceInstallItem[];
|
|
|
- alerts: AlertItem[];
|
|
|
- bundleRows: BundleRow[];
|
|
|
- fiber: FiberTrend;
|
|
|
- }>();
|
|
|
+ import { ALERT_ADVICE, BUNDLE_MONITOR_ROWS, DEVICE_MONITOR_ROWS, FIBER_CHART_DATA, NATURAL_FIRE_STAGE, SENSOR_GROUPS } from '../data';
|
|
|
|
|
|
- const chartWidth = 1100;
|
|
|
- const chartHeight = 300;
|
|
|
- const chartPadding = { left: 52, right: 16, top: 16, bottom: 30 };
|
|
|
- const yMin = 10;
|
|
|
- const yMax = 40;
|
|
|
- const yTicks = [10, 20, 30, 40];
|
|
|
+ defineProps<{
|
|
|
+ active?: boolean;
|
|
|
+ }>();
|
|
|
|
|
|
- function runningRate(device: DeviceInstallItem) {
|
|
|
- if (!device.installed) return '0';
|
|
|
- return ((device.running / device.installed) * 100).toFixed(1);
|
|
|
- }
|
|
|
+ const emit = defineEmits<{
|
|
|
+ (event: 'view-evaluation'): void;
|
|
|
+ }>();
|
|
|
|
|
|
- function alertColor(level: number) {
|
|
|
- return RISK_LEVELS[Math.min(Math.max(level, 1), 5) - 1].color;
|
|
|
- }
|
|
|
+ const PAGE_SIZE = 8;
|
|
|
+ const bundlePage = ref(1);
|
|
|
+ const devicePage = ref(1);
|
|
|
+ const bundleBodyRef = ref<HTMLElement>();
|
|
|
+ const deviceBodyRef = ref<HTMLElement>();
|
|
|
|
|
|
- function alertLevelName(level: number) {
|
|
|
- return RISK_LEVELS[Math.min(Math.max(level, 1), 5) - 1].name.replace(/^[IVX]+\s*/, '');
|
|
|
- }
|
|
|
+ const totalPages = computed(() => Math.max(1, Math.ceil(BUNDLE_MONITOR_ROWS.length / PAGE_SIZE)));
|
|
|
|
|
|
- function statusClass(status: BundleRow['status']) {
|
|
|
- if (status === '预警') return 'warning';
|
|
|
- if (status === '关注') return 'attention';
|
|
|
- return 'normal';
|
|
|
- }
|
|
|
+ const pagedBundleRows = computed(() => {
|
|
|
+ const start = (bundlePage.value - 1) * PAGE_SIZE;
|
|
|
+ return BUNDLE_MONITOR_ROWS.slice(start, start + PAGE_SIZE);
|
|
|
+ });
|
|
|
|
|
|
- function xPosition(index: number) {
|
|
|
- const plotWidth = chartWidth - chartPadding.left - chartPadding.right;
|
|
|
- const step = plotWidth / Math.max(1, props.fiber.times.length - 1);
|
|
|
- return chartPadding.left + index * step;
|
|
|
- }
|
|
|
+ const pagedDeviceRows = computed(() => {
|
|
|
+ const start = (devicePage.value - 1) * PAGE_SIZE;
|
|
|
+ return DEVICE_MONITOR_ROWS.slice(start, start + PAGE_SIZE);
|
|
|
+ });
|
|
|
|
|
|
- function yPosition(value: number) {
|
|
|
- const plotHeight = chartHeight - chartPadding.top - chartPadding.bottom;
|
|
|
- const ratio = (value - yMin) / (yMax - yMin);
|
|
|
- return chartPadding.top + (1 - Math.min(Math.max(ratio, 0), 1)) * plotHeight;
|
|
|
+ function changeBundlePage(page: number) {
|
|
|
+ bundlePage.value = page;
|
|
|
+ nextTick(() => {
|
|
|
+ if (bundleBodyRef.value) bundleBodyRef.value.scrollTop = 0;
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- function toPoints(values: number[]) {
|
|
|
- return values.map((value, index) => `${xPosition(index)},${yPosition(value)}`).join(' ');
|
|
|
+ function changeDevicePage(page: number) {
|
|
|
+ devicePage.value = page;
|
|
|
+ nextTick(() => {
|
|
|
+ if (deviceBodyRef.value) deviceBodyRef.value.scrollTop = 0;
|
|
|
+ });
|
|
|
}
|
|
|
-
|
|
|
- const maxPoints = computed(() => toPoints(props.fiber.maxTemp));
|
|
|
- const avgPoints = computed(() => toPoints(props.fiber.avgTemp));
|
|
|
-
|
|
|
- const maxAreaPath = computed(() => {
|
|
|
- const plotBottom = chartHeight - chartPadding.bottom;
|
|
|
- const firstX = xPosition(0);
|
|
|
- const lastX = xPosition(props.fiber.maxTemp.length - 1);
|
|
|
- return `M ${firstX},${plotBottom} L ${maxPoints.value.replace(/ /g, ' L ')} L ${lastX},${plotBottom} Z`;
|
|
|
- });
|
|
|
-
|
|
|
- const xLabels = computed(() => {
|
|
|
- const indexes = [0, 4, 8, 12, 16, 20, props.fiber.times.length - 1];
|
|
|
- return indexes.map((index) => ({
|
|
|
- x: xPosition(index),
|
|
|
- text: index === props.fiber.times.length - 1 ? '24:00' : props.fiber.times[index],
|
|
|
- }));
|
|
|
- });
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
@@ -246,106 +206,140 @@
|
|
|
inset: 0;
|
|
|
}
|
|
|
|
|
|
- .device-panel {
|
|
|
+ /* 自然发火阶段 */
|
|
|
+ .stage-panel {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 9px;
|
|
|
+ align-items: center;
|
|
|
height: 100%;
|
|
|
- padding: 12px 12px 14px;
|
|
|
+ padding-top: 34px;
|
|
|
box-sizing: border-box;
|
|
|
+ background: radial-gradient(ellipse at 50% 32%, rgba(255, 157, 28, 0.16), transparent 62%);
|
|
|
}
|
|
|
|
|
|
- .device-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- flex: 1;
|
|
|
- min-height: 0;
|
|
|
- gap: 10px;
|
|
|
- padding: 6px 12px 6px 10px;
|
|
|
- box-sizing: border-box;
|
|
|
- border: 1px solid rgba(61, 246, 255, 0.16);
|
|
|
- background: linear-gradient(90deg, rgba(11, 57, 90, 0.72), rgba(8, 37, 61, 0.3));
|
|
|
+ .evaluation-entry {
|
|
|
+ width: 160px;
|
|
|
+ height: 40px;
|
|
|
+ border: 1px solid rgba(61, 246, 255, 0.65);
|
|
|
+ border-radius: 5px;
|
|
|
+ background: linear-gradient(180deg, #1b7fbe 0%, #0b4c7b 100%);
|
|
|
+ box-shadow: 0 0 14px rgba(61, 246, 255, 0.22);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 15px;
|
|
|
+ letter-spacing: 1px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition:
|
|
|
+ filter 0.2s,
|
|
|
+ box-shadow 0.2s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ filter: brightness(1.12);
|
|
|
+ box-shadow: 0 0 18px rgba(61, 246, 255, 0.42);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .device-badge {
|
|
|
- position: relative;
|
|
|
- width: 30px;
|
|
|
- height: 30px;
|
|
|
- flex: none;
|
|
|
- border: 1px solid rgba(61, 246, 255, 0.55);
|
|
|
- border-radius: 50%;
|
|
|
- background: radial-gradient(circle, rgba(61, 246, 255, 0.28), rgba(5, 32, 55, 0.4));
|
|
|
+ .stage-level {
|
|
|
+ margin-top: 26px;
|
|
|
+ font-size: 42px;
|
|
|
+ line-height: 1.15;
|
|
|
+ letter-spacing: 4px;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-shadow:
|
|
|
+ 0 0 16px currentColor,
|
|
|
+ 0 0 30px rgba(255, 157, 28, 0.35);
|
|
|
+ }
|
|
|
|
|
|
- i {
|
|
|
+ .stage-bar {
|
|
|
+ position: relative;
|
|
|
+ width: 300px;
|
|
|
+ height: 42px;
|
|
|
+ margin-top: 20px;
|
|
|
+ clip-path: polygon(2% 0, 98% 0, 89% 100%, 11% 100%);
|
|
|
+ background: linear-gradient(180deg, rgba(61, 246, 255, 0.22) 0%, rgba(9, 39, 65, 0.9) 55%, rgba(4, 20, 35, 0.95) 100%);
|
|
|
+ filter: drop-shadow(0 6px 10px rgba(61, 246, 255, 0.25));
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
position: absolute;
|
|
|
- left: 50%;
|
|
|
- top: 50%;
|
|
|
- width: 10px;
|
|
|
- height: 10px;
|
|
|
- margin: -5px 0 0 -5px;
|
|
|
- border-radius: 2px;
|
|
|
- background: #3df6ff;
|
|
|
- box-shadow: 0 0 9px rgba(61, 246, 255, 0.9);
|
|
|
+ top: 0;
|
|
|
+ left: 8%;
|
|
|
+ right: 8%;
|
|
|
+ height: 2px;
|
|
|
+ background: linear-gradient(90deg, transparent, #ff9d1c, #ffd15c, #ff9d1c, transparent);
|
|
|
+ box-shadow: 0 0 10px rgba(255, 157, 28, 0.65);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .device-main {
|
|
|
- flex: 1;
|
|
|
- min-width: 0;
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 10%;
|
|
|
+ right: 10%;
|
|
|
+ bottom: 0;
|
|
|
+ height: 1px;
|
|
|
+ background: linear-gradient(90deg, transparent, #3df6ff, transparent);
|
|
|
+ box-shadow: 0 0 12px rgba(61, 246, 255, 0.8);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .device-line {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
+ /* 光纤测温 */
|
|
|
+ :deep(.fiber-module .box1-center) {
|
|
|
+ height: calc(100% - 35px) !important;
|
|
|
}
|
|
|
|
|
|
- .device-name {
|
|
|
- color: #fff;
|
|
|
- font-size: 14px;
|
|
|
+ .fiber-panel {
|
|
|
+ height: 100%;
|
|
|
+ padding: 2px 6px 2px;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
- .device-rate {
|
|
|
- color: #3df6ff;
|
|
|
- font-family: electronicFont, sans-serif;
|
|
|
- font-size: 18px;
|
|
|
+ /* 传感器监测 */
|
|
|
+ .sensor-panel {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 14px;
|
|
|
+ height: 100%;
|
|
|
+ padding: 10px 14px;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
- .device-bar {
|
|
|
- position: relative;
|
|
|
- height: 4px;
|
|
|
- margin: 7px 0 6px;
|
|
|
- overflow: hidden;
|
|
|
- background: rgba(61, 246, 255, 0.12);
|
|
|
-
|
|
|
- i {
|
|
|
- display: block;
|
|
|
- height: 100%;
|
|
|
- background: linear-gradient(90deg, #0e7fc1, #3df6ff);
|
|
|
- box-shadow: 0 0 8px rgba(61, 246, 255, 0.7);
|
|
|
- transition: width 0.4s ease;
|
|
|
- }
|
|
|
+ .sensor-group-title {
|
|
|
+ height: 24px;
|
|
|
+ padding-left: 8px;
|
|
|
+ border-left: 2px solid #3df6ff;
|
|
|
+ background: linear-gradient(90deg, rgba(61, 246, 255, 0.55) 0%, rgba(61, 246, 255, 0.08) 70%, transparent 100%);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 24px;
|
|
|
+ letter-spacing: 1px;
|
|
|
}
|
|
|
|
|
|
- .device-meta {
|
|
|
- color: #9fcde3;
|
|
|
+ .sensor-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 27px;
|
|
|
+ padding: 0 4px 0 10px;
|
|
|
+ border-bottom: 1px solid rgba(61, 246, 255, 0.12);
|
|
|
+ color: #d9f7ff;
|
|
|
font-size: 12px;
|
|
|
|
|
|
em {
|
|
|
color: #3df6ff;
|
|
|
font-style: normal;
|
|
|
font-size: 13px;
|
|
|
+ text-shadow: 0 0 8px rgba(61, 246, 255, 0.45);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .alert-panel {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 8px;
|
|
|
+ /* 预警处置意见 */
|
|
|
+ .advice-panel {
|
|
|
+ position: relative;
|
|
|
height: 100%;
|
|
|
- padding: 12px;
|
|
|
+ padding: 14px 16px 14px 34px;
|
|
|
box-sizing: border-box;
|
|
|
overflow-y: auto;
|
|
|
+ border: 1px solid rgba(61, 246, 255, 0.4);
|
|
|
+ background: url('@/assets/images/vent/home/selfIgnition/result-block-bg.png') no-repeat center / 100% 100%;
|
|
|
|
|
|
&::-webkit-scrollbar {
|
|
|
width: 4px;
|
|
|
@@ -355,231 +349,215 @@
|
|
|
background: rgba(61, 246, 255, 0.35);
|
|
|
border-radius: 2px;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .alert-item {
|
|
|
- flex: none;
|
|
|
- padding: 8px 10px 8px 12px;
|
|
|
- border-left: 2px solid var(--alert-color);
|
|
|
- background: linear-gradient(90deg, rgba(11, 57, 90, 0.72), rgba(8, 37, 61, 0.25));
|
|
|
- }
|
|
|
-
|
|
|
- .alert-top {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8px;
|
|
|
- height: 20px;
|
|
|
+ p {
|
|
|
+ margin: 0;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 27px;
|
|
|
+ letter-spacing: 0.5px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .alert-time {
|
|
|
- color: #8fc7e8;
|
|
|
- font-size: 12px;
|
|
|
- font-family: electronicFont, sans-serif;
|
|
|
- letter-spacing: 1px;
|
|
|
+ .advice-icon {
|
|
|
+ position: absolute;
|
|
|
+ left: 16px;
|
|
|
+ top: 20px;
|
|
|
+ width: 9px;
|
|
|
+ height: 9px;
|
|
|
+ background: #f5222d;
|
|
|
+ box-shadow: 0 0 9px rgba(245, 34, 45, 0.85);
|
|
|
+ transform: rotate(45deg);
|
|
|
}
|
|
|
|
|
|
- .alert-level {
|
|
|
- padding: 0 5px;
|
|
|
- border: 1px solid var(--alert-color);
|
|
|
- color: var(--alert-color);
|
|
|
- font-size: 11px;
|
|
|
- line-height: 16px;
|
|
|
+ /* 底部宽表格面板:使用短边框图,保证标题和装饰点居中 */
|
|
|
+ :deep(.wide-module .box1-top) {
|
|
|
+ --image-box1-top: url('@/assets/images/vent/border/box1-top.png');
|
|
|
+ background-image: var(--image-box1-top) !important;
|
|
|
}
|
|
|
|
|
|
- .alert-location {
|
|
|
- margin-left: auto;
|
|
|
- color: #fff;
|
|
|
- font-size: 12px;
|
|
|
+ :deep(.wide-module .box1-bottom) {
|
|
|
+ --image-box1-bottom: url('@/assets/images/vent/border/box1-bottom.png');
|
|
|
+ background-image: var(--image-box1-bottom) !important;
|
|
|
}
|
|
|
|
|
|
- .alert-message {
|
|
|
- margin-top: 5px;
|
|
|
- color: #fff;
|
|
|
- font-size: 13px;
|
|
|
- line-height: 20px;
|
|
|
- }
|
|
|
-
|
|
|
- .bundle-panel {
|
|
|
+ .table-panel {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
height: 100%;
|
|
|
- padding: 12px 16px 14px;
|
|
|
+ padding: 4px 12px 6px;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
- .bundle-head,
|
|
|
- .bundle-row {
|
|
|
+ .data-table {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ flex-direction: column;
|
|
|
+ border: 1px solid rgba(61, 246, 255, 0.4);
|
|
|
+ background: rgba(6, 30, 52, 0.2);
|
|
|
+ }
|
|
|
+
|
|
|
+ .table-head,
|
|
|
+ .table-row {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
- .bundle-head {
|
|
|
+ .table-head {
|
|
|
flex: none;
|
|
|
height: 38px;
|
|
|
- border: 1px solid rgba(61, 246, 255, 0.4);
|
|
|
+ border-bottom: 1px solid rgba(61, 246, 255, 0.35);
|
|
|
+ background: linear-gradient(180deg, #0d3b58 0%, #0a2c48 100%);
|
|
|
color: #3df6ff;
|
|
|
font-size: 14px;
|
|
|
- letter-spacing: 1px;
|
|
|
- background: linear-gradient(180deg, rgba(14, 70, 108, 0.85), rgba(10, 49, 79, 0.6));
|
|
|
+ letter-spacing: 0.5px;
|
|
|
}
|
|
|
|
|
|
- .bundle-body {
|
|
|
- display: flex;
|
|
|
+ .table-body {
|
|
|
flex: 1;
|
|
|
min-height: 0;
|
|
|
- flex-direction: column;
|
|
|
- border: 1px solid rgba(61, 246, 255, 0.18);
|
|
|
- border-top: none;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: rgba(61, 246, 255, 0.08);
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ border-radius: 4px;
|
|
|
+ background: linear-gradient(180deg, #3df6ff 0%, #0d7fc1 100%);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .bundle-row {
|
|
|
- flex: 1;
|
|
|
- min-height: 0;
|
|
|
+ .table-row {
|
|
|
+ height: 50px;
|
|
|
+ border-top: 1px solid rgba(61, 246, 255, 0.1);
|
|
|
+ background: #0b3355;
|
|
|
color: #fff;
|
|
|
font-size: 14px;
|
|
|
- background: rgba(11, 51, 85, 0.55);
|
|
|
|
|
|
&:nth-child(even) {
|
|
|
- background: rgba(13, 65, 103, 0.62);
|
|
|
- }
|
|
|
-
|
|
|
- & + & {
|
|
|
- border-top: 1px solid rgba(61, 246, 255, 0.1);
|
|
|
+ background: #0d4167;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .col-point {
|
|
|
- width: 24%;
|
|
|
- text-align: left;
|
|
|
- padding-left: 22px;
|
|
|
- box-sizing: border-box;
|
|
|
+ .table-head span,
|
|
|
+ .table-row span {
|
|
|
+ flex: none;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
- .col-value {
|
|
|
- width: 12%;
|
|
|
- }
|
|
|
+ .bundle-table {
|
|
|
+ .table-head span:nth-child(1),
|
|
|
+ .table-row span:nth-child(1) {
|
|
|
+ width: 15%;
|
|
|
+ }
|
|
|
|
|
|
- .col-status {
|
|
|
- width: 16%;
|
|
|
- }
|
|
|
+ .table-head span:nth-child(2),
|
|
|
+ .table-row span:nth-child(2) {
|
|
|
+ width: 10%;
|
|
|
+ }
|
|
|
|
|
|
- .warning {
|
|
|
- color: #ffd15c;
|
|
|
- text-shadow: 0 0 8px rgba(255, 209, 92, 0.45);
|
|
|
- }
|
|
|
+ .table-head span:nth-child(3),
|
|
|
+ .table-row span:nth-child(3) {
|
|
|
+ width: 10%;
|
|
|
+ }
|
|
|
|
|
|
- .status-tag {
|
|
|
- display: inline-block;
|
|
|
- min-width: 52px;
|
|
|
- padding: 2px 10px;
|
|
|
- box-sizing: border-box;
|
|
|
- border: 1px solid currentColor;
|
|
|
- font-style: normal;
|
|
|
- font-size: 12px;
|
|
|
- line-height: 18px;
|
|
|
+ .table-head span:nth-child(4),
|
|
|
+ .table-row span:nth-child(4) {
|
|
|
+ width: 12%;
|
|
|
+ }
|
|
|
|
|
|
- &.normal {
|
|
|
- color: #3df6ff;
|
|
|
- background: rgba(61, 246, 255, 0.08);
|
|
|
+ .table-head span:nth-child(5),
|
|
|
+ .table-row span:nth-child(5) {
|
|
|
+ width: 12%;
|
|
|
}
|
|
|
|
|
|
- &.attention {
|
|
|
- color: #ffd15c;
|
|
|
- background: rgba(255, 209, 92, 0.08);
|
|
|
+ .table-head span:nth-child(6),
|
|
|
+ .table-row span:nth-child(6) {
|
|
|
+ width: 10%;
|
|
|
}
|
|
|
|
|
|
- &.warning {
|
|
|
- color: #ff9d1c;
|
|
|
- background: rgba(255, 157, 28, 0.1);
|
|
|
+ .table-head span:nth-child(7),
|
|
|
+ .table-row span:nth-child(7) {
|
|
|
+ width: 10%;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .fiber-panel {
|
|
|
- display: flex;
|
|
|
- gap: 16px;
|
|
|
- height: 100%;
|
|
|
- padding: 12px 16px 14px;
|
|
|
- box-sizing: border-box;
|
|
|
- }
|
|
|
+ .table-head span:nth-child(8),
|
|
|
+ .table-row span:nth-child(8) {
|
|
|
+ width: 10%;
|
|
|
+ }
|
|
|
|
|
|
- .chart-area {
|
|
|
- display: flex;
|
|
|
- flex: 1;
|
|
|
- min-width: 0;
|
|
|
- flex-direction: column;
|
|
|
+ .table-head span:nth-child(9),
|
|
|
+ .table-row span:nth-child(9) {
|
|
|
+ width: 11%;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .chart-legend {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 20px;
|
|
|
- height: 26px;
|
|
|
- flex: none;
|
|
|
- color: #a9dcf4;
|
|
|
- font-size: 12px;
|
|
|
- }
|
|
|
+ .device-table {
|
|
|
+ .table-head span:nth-child(1),
|
|
|
+ .table-row span:nth-child(1) {
|
|
|
+ width: 18%;
|
|
|
+ }
|
|
|
|
|
|
- .legend-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 6px;
|
|
|
- }
|
|
|
+ .table-head span:nth-child(2),
|
|
|
+ .table-row span:nth-child(2) {
|
|
|
+ width: 13%;
|
|
|
+ }
|
|
|
|
|
|
- .legend-max,
|
|
|
- .legend-avg {
|
|
|
- display: inline-block;
|
|
|
- width: 16px;
|
|
|
- height: 2px;
|
|
|
- }
|
|
|
+ .table-head span:nth-child(3),
|
|
|
+ .table-row span:nth-child(3) {
|
|
|
+ width: 14%;
|
|
|
+ }
|
|
|
|
|
|
- .legend-max {
|
|
|
- background: #3df6ff;
|
|
|
- box-shadow: 0 0 6px rgba(61, 246, 255, 0.8);
|
|
|
- }
|
|
|
+ .table-head span:nth-child(4),
|
|
|
+ .table-row span:nth-child(4) {
|
|
|
+ width: 14%;
|
|
|
+ }
|
|
|
|
|
|
- .legend-avg {
|
|
|
- background: #ffd15c;
|
|
|
- }
|
|
|
+ .table-head span:nth-child(5),
|
|
|
+ .table-row span:nth-child(5) {
|
|
|
+ width: 12%;
|
|
|
+ }
|
|
|
|
|
|
- .chart-svg {
|
|
|
- flex: 1;
|
|
|
- min-height: 0;
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
+ .table-head span:nth-child(6),
|
|
|
+ .table-row span:nth-child(6) {
|
|
|
+ width: 14%;
|
|
|
+ }
|
|
|
|
|
|
- .fiber-summary {
|
|
|
- display: flex;
|
|
|
- flex: none;
|
|
|
- width: 230px;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: center;
|
|
|
- gap: 18px;
|
|
|
- padding-left: 22px;
|
|
|
- border-left: 1px solid rgba(61, 246, 255, 0.18);
|
|
|
+ .table-head span:nth-child(7),
|
|
|
+ .table-row span:nth-child(7) {
|
|
|
+ width: 15%;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .summary-item {
|
|
|
+ .table-pager {
|
|
|
display: flex;
|
|
|
- align-items: baseline;
|
|
|
- justify-content: space-between;
|
|
|
- color: #a9dcf4;
|
|
|
- font-size: 13px;
|
|
|
-
|
|
|
- em {
|
|
|
- color: #fff;
|
|
|
- font-style: normal;
|
|
|
- font-family: electronicFont, sans-serif;
|
|
|
- font-size: 26px;
|
|
|
- line-height: 1;
|
|
|
- text-shadow: 0 0 10px rgba(255, 255, 255, 0.25);
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 8px;
|
|
|
+ height: 24px;
|
|
|
+ flex: none;
|
|
|
|
|
|
- &.max {
|
|
|
- color: #3df6ff;
|
|
|
- }
|
|
|
+ i {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ border-radius: 1px;
|
|
|
+ background: rgba(61, 246, 255, 0.35);
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s;
|
|
|
|
|
|
- &.avg {
|
|
|
- color: #ffd15c;
|
|
|
+ &.active {
|
|
|
+ width: 16px;
|
|
|
+ background: #3df6ff;
|
|
|
+ box-shadow: 0 0 8px rgba(61, 246, 255, 0.85);
|
|
|
}
|
|
|
}
|
|
|
}
|