2025-05-23 14:14:05 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="equipment-container">
|
|
|
|
|
<div class="data-overview">
|
|
|
|
|
<div class="data-left">
|
2025-06-05 09:27:13 +08:00
|
|
|
|
<div class="equipment-name">{{ deviceInfo?.deviceName }}({{deviceInfo?.deviceCode}})</div>
|
|
|
|
|
<el-button type="info" size="small" v-if="deviceShowStatus">{{deviceShowStatus}}</el-button>
|
|
|
|
|
<!-- <div style="margin-left:16px;color:#606266">时间显示</div>-->
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="action-buttons">
|
|
|
|
|
<div class="button-group">
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<!-- <el-button-->
|
|
|
|
|
<!-- type="primary"-->
|
|
|
|
|
<!-- link-->
|
|
|
|
|
<!-- @click="handleShowImage()"-->
|
|
|
|
|
<!-- >-->
|
|
|
|
|
<!-- {{proxy.$t('equipment.imagePage')}}-->
|
|
|
|
|
<!-- </el-button>-->
|
2025-05-23 14:14:05 +08:00
|
|
|
|
<el-button
|
|
|
|
|
:type="mode === 'fast' ? 'primary' : ''"
|
2025-06-05 09:27:13 +08:00
|
|
|
|
@click="handleModeChange()"
|
2025-05-23 14:14:05 +08:00
|
|
|
|
>
|
|
|
|
|
<el-icon><Timer /></el-icon>
|
2025-06-05 09:27:13 +08:00
|
|
|
|
{{modeTypeMap[deviceMode]}}
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<el-button
|
2025-06-04 13:25:40 +08:00
|
|
|
|
plain
|
2025-05-23 14:14:05 +08:00
|
|
|
|
:type="xRayStatus ? 'danger' : 'success'"
|
|
|
|
|
@click="handleXRayToggle"
|
|
|
|
|
>
|
|
|
|
|
X{{proxy.$t('equipment.Ray')}}:{{ xRayStatus ? proxy.$t('common.open') : proxy.$t('common.close') }}
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
plain
|
|
|
|
|
@click="handleGenerateReport"
|
|
|
|
|
>
|
|
|
|
|
{{proxy.$t('equipment.reporting')}}
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
type="success"
|
|
|
|
|
plain
|
|
|
|
|
@click="handleDeviceShare"
|
|
|
|
|
>
|
|
|
|
|
{{proxy.$t('equipment.deviceShare')}}
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chart-container">
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<div class="chart-box">
|
2025-05-23 14:14:05 +08:00
|
|
|
|
<el-tabs
|
|
|
|
|
v-model="activeName"
|
|
|
|
|
type="card"
|
|
|
|
|
class="demo-tabs"
|
|
|
|
|
@tab-click="handleClick"
|
|
|
|
|
>
|
|
|
|
|
<el-tab-pane label="数据组1" name="first">
|
|
|
|
|
<div class="card-container">
|
|
|
|
|
<div class="card-list">
|
|
|
|
|
<div class="eccentricity-card" v-for="(item, index) in cardList" :key="index">
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
<span class="title">{{item.title}}</span>
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<el-icon class="close-icon" @click="deleteCard(index)"><Close /></el-icon>
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<div class="card-text">
|
|
|
|
|
<div>
|
|
|
|
|
<div class="difference">
|
|
|
|
|
<span class="plus">收缩率</span>
|
|
|
|
|
<span class="label">9%</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="difference">
|
|
|
|
|
<span class="plus">+</span>
|
|
|
|
|
<span class="label">公差</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="value">
|
|
|
|
|
21.15<span class="unit">%</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="tolerance-section">
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
plain
|
|
|
|
|
class="switch-btn left"
|
|
|
|
|
@click="handlePrevious"
|
|
|
|
|
>
|
|
|
|
|
<el-icon><ArrowLeft /></el-icon>
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<div class="tolerance-text">
|
|
|
|
|
偏心度公差 {{ toleranceList[currentIndex] }}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
plain
|
|
|
|
|
class="switch-btn right"
|
|
|
|
|
@click="handleNext"
|
|
|
|
|
>
|
|
|
|
|
<el-icon><ArrowRight /></el-icon>
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<div class="eccentricity-card" @click="openDialog">
|
2025-06-05 09:27:13 +08:00
|
|
|
|
<div style="display: flex;justify-content: center;align-content: center;cursor: pointer">
|
|
|
|
|
<el-icon style="font-size: 50px;color:red"><Plus></Plus></el-icon>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-06-04 13:25:40 +08:00
|
|
|
|
</div>
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
2025-06-04 13:25:40 +08:00
|
|
|
|
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="数据组2" name="second">数据组2</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="数据组3" name="third">数据组3</el-tab-pane>
|
|
|
|
|
</el-tabs>
|
|
|
|
|
</div>
|
2025-06-04 13:25:40 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div class="chart-container">
|
|
|
|
|
<div class="chart-box">
|
2025-05-23 14:14:05 +08:00
|
|
|
|
<el-tabs
|
|
|
|
|
v-model="activeTwoName"
|
|
|
|
|
type="card"
|
|
|
|
|
class="demo-tabs"
|
|
|
|
|
@tab-click="handleClick"
|
|
|
|
|
>
|
|
|
|
|
<el-tab-pane :label="proxy.$t('equipment.sketch')" name="first">
|
|
|
|
|
<div class="detection-section">
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<el-radio-group v-model="selectedLayer" class="layer-select">
|
|
|
|
|
<el-radio label="outer">外屏蔽层</el-radio>
|
|
|
|
|
<el-radio label="middle">绝缘层</el-radio>
|
|
|
|
|
<el-radio label="inner">内屏蔽层</el-radio>
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
<!-- <CircleDetectionChart-->
|
|
|
|
|
<!-- :inner-data="innerLayerData"-->
|
|
|
|
|
<!-- :middle-data="middleLayerData"-->
|
|
|
|
|
<!-- :outer-data="outerLayerData"-->
|
|
|
|
|
<!-- />-->
|
|
|
|
|
<CircleDetectionChart :selected-layer="selectedLayer" />
|
|
|
|
|
<!-- <CircleDetectionChart :eccentricity="0.08" :thickness="20" />-->
|
2025-05-23 14:14:05 +08:00
|
|
|
|
<div class="history-content">
|
|
|
|
|
<div>左边指南针</div>
|
|
|
|
|
<div class="history-right">
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<div>
|
|
|
|
|
<el-button v-if="showHistory" type="primary" @click="showHistoryDialog">选择历史数据</el-button>
|
|
|
|
|
<el-switch
|
|
|
|
|
v-model="showHistory"
|
|
|
|
|
size="large"
|
|
|
|
|
style="margin-left: 6px"
|
|
|
|
|
:inactive-text="proxy.$t('equipment.historyData')"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2025-05-23 14:14:05 +08:00
|
|
|
|
<div class="scanItem">扫描时间:2025/01/07 04:34:8</div>
|
|
|
|
|
<div class="scanItem">2025-01-07_04_30_34_866_direction_1_device2.json</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane :label="proxy.$t('equipment.deviceInfo')" name="second">
|
|
|
|
|
<div class="device-status">
|
2025-06-05 09:27:13 +08:00
|
|
|
|
<DeviceStatus :status-data="deviceStatus" />
|
|
|
|
|
<!-- <DeviceSetting v-if="showBtn" @update="handleSettingUpdate" />-->
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
</el-tabs>
|
2025-06-05 09:27:13 +08:00
|
|
|
|
<!-- <div class="btn" v-if="activeTwoName === 'second'">-->
|
|
|
|
|
<!-- <el-button v-if="!showBtn" type="primary" @click="paramsHandle">{{proxy.$t('equipment.paramsSetting')}}</el-button>-->
|
|
|
|
|
<!-- <el-button v-if="showBtn" type="primary" @click="paramsHandle">{{proxy.$t('button.return')}}</el-button>-->
|
|
|
|
|
<!-- </div>-->
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chart-container" style="margin-top: 14px">
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<div class="chart-box">
|
2025-05-23 14:14:05 +08:00
|
|
|
|
<el-tabs
|
|
|
|
|
v-model="activeThreeName"
|
|
|
|
|
type="card"
|
|
|
|
|
class="demo-tabs"
|
|
|
|
|
@tab-click="handleClick"
|
|
|
|
|
>
|
|
|
|
|
<el-tab-pane :label="proxy.$t('equipment.deviceTemperature')" name="first">
|
|
|
|
|
<TemperatureChart :chart-data="temperatureData"></TemperatureChart>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane :label="proxy.$t('equipment.warningInfo')" name="second">
|
|
|
|
|
<div class="warning-container">
|
|
|
|
|
<div class="warning-item" v-for="(item, index) in warningList" :key="index">
|
2025-06-05 09:27:13 +08:00
|
|
|
|
<template v-if="item.info">
|
|
|
|
|
{{item.label}}:{{item.info}}
|
|
|
|
|
</template>
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane :label="proxy.$t('equipment.imageView')" name="third">
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<el-button-group>
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
plain
|
|
|
|
|
class="switch-btn right"
|
|
|
|
|
@click="handleImagePrev"
|
|
|
|
|
>
|
|
|
|
|
<el-icon><ArrowLeft /></el-icon>
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
plain
|
|
|
|
|
class="switch-btn right switch"
|
|
|
|
|
@click="handleImageNext"
|
|
|
|
|
>
|
|
|
|
|
<el-icon><ArrowRight /></el-icon>
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-button-group>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="display: flex">
|
|
|
|
|
<div v-if="showRed">
|
|
|
|
|
<CurveChart ref="bowlCurveRef" :title="chartTitle.left" :color="colorRed"/>
|
|
|
|
|
<CurveChart ref="bowlCurveRef" :title="chartTitle.right" :color="colorRed"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="showGreen">
|
|
|
|
|
<CurveChart ref="bowlCurveRef" :title="chartTitle.left" :color="colorGreen"/>
|
|
|
|
|
<CurveChart ref="bowlCurveRef" :title="chartTitle.right" :color="colorGreen"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="showRedGreen">
|
|
|
|
|
<DualChannelChart
|
|
|
|
|
title="扫描臂1"
|
|
|
|
|
ref="dualChart1Ref"
|
|
|
|
|
:chart-data="arm1ChartData"
|
|
|
|
|
/>
|
|
|
|
|
<DualChannelChart
|
|
|
|
|
title="扫描臂2"
|
|
|
|
|
ref="dualChart2Ref"
|
|
|
|
|
:chart-data="arm2ChartData"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane :label="proxy.$t('equipment.trendChart')" name="four">
|
2025-06-05 16:33:14 +08:00
|
|
|
|
<RealtimeChart ref="realtimeChartRef" :real-data="trendData" v-if="activeThreeName === 'four'"/>
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</el-tab-pane>
|
|
|
|
|
</el-tabs>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- 历史数据弹框-->
|
|
|
|
|
<HistoryDataDialog
|
|
|
|
|
ref="historyDialogRef"
|
|
|
|
|
@confirm="handleHistoryConfirm"
|
|
|
|
|
@cancel="handleHistoryCancel"
|
|
|
|
|
/>
|
2025-06-04 13:25:40 +08:00
|
|
|
|
<!-- 添加数据弹框-->
|
|
|
|
|
<AddMonitorData ref="addMonitorRef" @confirm="handleDataConfirm" />
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, onMounted } from 'vue'
|
2025-06-04 13:25:40 +08:00
|
|
|
|
import {getDeviceDetailApi} from "@/api/equipment/index.js";
|
|
|
|
|
import {Close, ArrowLeft, ArrowRight, Timer, Refresh, Plus} from '@element-plus/icons-vue'
|
2025-05-23 14:14:05 +08:00
|
|
|
|
import TemperatureChart from './common/TemperatureChart.vue'
|
|
|
|
|
import RealtimeChart from './common/RealtimeChart.vue';
|
|
|
|
|
import DeviceStatus from './common/DeviceStatus.vue';
|
|
|
|
|
import DeviceSetting from './common/DeviceSetting.vue';
|
|
|
|
|
import DualChannelChart from './common/DualChannelChart.vue';
|
|
|
|
|
import CurveChart from './common/CurveChart.vue';
|
|
|
|
|
import CircleDetectionChart from "./common/CircleDetectionChart.vue";
|
|
|
|
|
import HistoryDataDialog from './common/HistoryDataDialog.vue';
|
2025-06-04 13:25:40 +08:00
|
|
|
|
import {ElMessageBox, ElMessage} from "element-plus";
|
|
|
|
|
import { useMqtt } from '@/utils/mqttClient.js';
|
|
|
|
|
import {useRoute} from 'vue-router';
|
2025-06-05 16:33:14 +08:00
|
|
|
|
import AddMonitorData from './common/AddMonitorData.vue';
|
|
|
|
|
import { base64Decode, base64Encode } from '@/utils/base64'
|
|
|
|
|
import { timestampArrayToTime } from '@/utils/time'
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const deviceShowStatus = ref('')
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const {
|
|
|
|
|
connected,
|
|
|
|
|
messageData,
|
|
|
|
|
connect,
|
|
|
|
|
subscribe,
|
|
|
|
|
disconnect,
|
|
|
|
|
publish
|
|
|
|
|
} = useMqtt()
|
2025-06-05 16:33:14 +08:00
|
|
|
|
// const clientId = ref('lkk' + Math.random().toString(16).substring(2, 8))
|
|
|
|
|
const clientId = ref('lkk40a9bc')
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const deviceInfo = ref({})
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const deviceData = ref(null)
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const deviceMode = ref(null)
|
|
|
|
|
const xRayStatus = ref(null)
|
2025-05-23 14:14:05 +08:00
|
|
|
|
const { proxy } = getCurrentInstance();
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const route = useRoute()
|
|
|
|
|
const deviceId = ref(null)
|
|
|
|
|
const selectedLayer = ref('outer')
|
2025-05-23 14:14:05 +08:00
|
|
|
|
const toleranceList = ['15%', '20%', '25%']
|
|
|
|
|
const showRed = ref(true)
|
|
|
|
|
const showGreen = ref(false)
|
|
|
|
|
const showRedGreen = ref(false)
|
|
|
|
|
const showImagePageRed = ref(true)
|
|
|
|
|
const showImagePageGreen = ref(false)
|
|
|
|
|
const showImagePageRedGreen = ref(false)
|
|
|
|
|
const colorRed = ref('#ff4444')
|
|
|
|
|
const colorGreen = ref('#67c23a')
|
|
|
|
|
const currentIndex = ref(0)
|
|
|
|
|
const showHistory = ref(false)
|
|
|
|
|
const mode = ref('normal')
|
|
|
|
|
const realtimeChartRef = ref(null)
|
2025-06-05 16:33:14 +08:00
|
|
|
|
const trendData = ref({
|
|
|
|
|
datetime:[],
|
|
|
|
|
WtOSC: [],
|
|
|
|
|
WtINS:[],
|
|
|
|
|
WtISC: [],
|
|
|
|
|
EccentricityINS: [],
|
|
|
|
|
EccentricityOSC: [],
|
|
|
|
|
EccentricityISC: [],
|
|
|
|
|
DmCORE: [],
|
|
|
|
|
DmALL: []
|
|
|
|
|
})
|
2025-05-23 14:14:05 +08:00
|
|
|
|
const dualChart1Ref = ref(null)
|
|
|
|
|
const dualChart2Ref = ref(null)
|
|
|
|
|
const dualChart1PageRef = ref(null)
|
|
|
|
|
const dualChart2PageRef = ref(null)
|
|
|
|
|
const bowlCurvePageRef = ref(null)
|
|
|
|
|
const activeName = ref('first')
|
|
|
|
|
const activeTwoName = ref('first')
|
|
|
|
|
const activeThreeName = ref('first')
|
|
|
|
|
const bowlCurveRef = ref(null)
|
|
|
|
|
const showBtn = ref(false)
|
|
|
|
|
const historyDialogRef = ref(null)
|
|
|
|
|
const currentTime = ref('2021-02-11 13:23:39')
|
|
|
|
|
const chartTitle = ref({
|
|
|
|
|
left: '扫描臂1 曲线',
|
|
|
|
|
right: '扫描臂2 曲线'
|
|
|
|
|
})
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const modeTypeMap = {
|
|
|
|
|
'fast':'快速模式',
|
|
|
|
|
'normal':'正常速度',
|
|
|
|
|
'slow':'慢速模式'
|
|
|
|
|
};
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const cardList = ref([
|
2025-05-23 14:14:05 +08:00
|
|
|
|
{ title: '外屏层偏心度' },
|
|
|
|
|
{ title: '内屏层偏心度' },
|
|
|
|
|
{ title: '绝缘层偏心度' },
|
|
|
|
|
{ title: '外屏层厚度' },
|
|
|
|
|
{ title: '内屏层厚度' },
|
2025-06-04 13:25:40 +08:00
|
|
|
|
// { title: '绝缘层厚度' }
|
|
|
|
|
])
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const warningList = ref([])
|
|
|
|
|
const warningInserted = ref(false)
|
|
|
|
|
|
2025-05-23 14:14:05 +08:00
|
|
|
|
// 示意图数据
|
|
|
|
|
const innerLayerData = ref([0.68, 0.85, 1.07, 1.18, 1.13, 0.97, 0.67, 0.98])
|
|
|
|
|
const middleLayerData = ref([9.52, 9.95, 10.53, 11.04, 11.34, 11.15, 9.66, 10.40])
|
|
|
|
|
const outerLayerData = ref([1.15, 1.19, 1.21, 1.17, 1.05, 0.96, 1.06, 0.79])
|
|
|
|
|
// 温度数据
|
|
|
|
|
const temperatureData = ref({
|
2025-06-05 16:33:14 +08:00
|
|
|
|
SCANNER1: [],
|
|
|
|
|
SCANNER2: [],
|
|
|
|
|
datetime: []
|
2025-05-23 14:14:05 +08:00
|
|
|
|
})
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const deviceStatus = ref({})
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const addMonitorRef = ref(null)
|
2025-05-23 14:14:05 +08:00
|
|
|
|
// 表格数据
|
|
|
|
|
const tableData = ref([
|
|
|
|
|
{ name: '射线电源反馈电压[V]', arm1: '15', arm2: '0' },
|
|
|
|
|
{ name: '射线电源设定电压[V]', arm1: '55000', arm2: '55000' },
|
|
|
|
|
// ... 其他数据
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
// 图表数据
|
|
|
|
|
const arm1ChartData = ref({
|
|
|
|
|
a: Array.from({ length: 100 }, () => Math.random() * 9000),
|
|
|
|
|
b: Array.from({ length: 100 }, () => Math.random() * 9000)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const arm2ChartData = ref({
|
|
|
|
|
a: Array.from({ length: 100 }, () => Math.random() * 9000),
|
|
|
|
|
b: Array.from({ length: 100 }, () => Math.random() * 9000)
|
|
|
|
|
})
|
2025-06-04 13:25:40 +08:00
|
|
|
|
// 打开新增设备弹框
|
|
|
|
|
const openDialog = () => {
|
|
|
|
|
addMonitorRef.value.showDialog()
|
2025-05-23 14:14:05 +08:00
|
|
|
|
}
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const handleDataConfirm = (dataType) => {
|
|
|
|
|
console.log('选择的数据项:', dataType)
|
|
|
|
|
// 这里处理选择的数据项
|
|
|
|
|
}
|
|
|
|
|
// mqtt连接
|
|
|
|
|
const mqttConnect = () => {
|
2025-06-05 09:27:13 +08:00
|
|
|
|
console.log(clientId.value)
|
2025-06-04 13:25:40 +08:00
|
|
|
|
connect('ws://123.57.81.127:8085/mqtt', { // 添加 /mqtt 路径
|
2025-06-05 09:27:13 +08:00
|
|
|
|
clientId: clientId.value,
|
2025-06-04 13:25:40 +08:00
|
|
|
|
username: 'cepianyi',
|
|
|
|
|
password: 'cpy123',
|
|
|
|
|
protocol: 'ws',
|
|
|
|
|
protocolVersion: 4,
|
|
|
|
|
keepalive: 60,
|
|
|
|
|
reconnectPeriod: 1000,
|
|
|
|
|
connectTimeout: 30 * 1000,
|
|
|
|
|
path: '/mqtt'// 指定 WebSocket 路径
|
|
|
|
|
})
|
2025-05-23 14:14:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-06-04 13:25:40 +08:00
|
|
|
|
const deleteCard = (index) => {
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
'确认删除该卡片吗?',
|
|
|
|
|
'提示',
|
|
|
|
|
{
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
type: 'warning'
|
|
|
|
|
}
|
|
|
|
|
).then(() => {
|
|
|
|
|
cardList.value.splice(index, 1)
|
|
|
|
|
ElMessage.success('删除成功')
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
// 用户取消删除
|
|
|
|
|
})
|
2025-05-23 14:14:05 +08:00
|
|
|
|
}
|
|
|
|
|
// 打开历史数据弹窗
|
|
|
|
|
const showHistoryDialog = () => {
|
|
|
|
|
historyDialogRef.value.show()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleHistoryConfirm = (data) => {
|
|
|
|
|
console.log('选择的历史数据:', data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleHistoryCancel = () => {
|
|
|
|
|
console.log('取消选择')
|
|
|
|
|
}
|
|
|
|
|
// 图像预览
|
|
|
|
|
const handleImageNext = () => {
|
|
|
|
|
if (showRedGreen.value) {
|
|
|
|
|
showRedGreen.value = false
|
|
|
|
|
showRed.value = true
|
|
|
|
|
showGreen.value = false
|
|
|
|
|
} else if (showRed.value) {
|
|
|
|
|
showRedGreen.value = false
|
|
|
|
|
showRed.value = false
|
|
|
|
|
showGreen.value = true
|
|
|
|
|
} else if (showGreen.value) {
|
|
|
|
|
showRedGreen.value = true
|
|
|
|
|
showRed.value = false
|
|
|
|
|
showGreen.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleImagePrev = () => {
|
|
|
|
|
if (showRedGreen.value) {
|
|
|
|
|
showRedGreen.value = false
|
|
|
|
|
showRed.value = false
|
|
|
|
|
showGreen.value = true
|
|
|
|
|
} else if (showGreen.value) {
|
|
|
|
|
showRedGreen.value = false
|
|
|
|
|
showRed.value = true
|
|
|
|
|
showGreen.value = false
|
|
|
|
|
} else if (showRed.value) {
|
|
|
|
|
showRedGreen.value = true
|
|
|
|
|
showRed.value = false
|
|
|
|
|
showGreen.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const generateData = (type) => {
|
|
|
|
|
const data = []
|
|
|
|
|
for (let i = 0; i <= 90; i++) {
|
|
|
|
|
let value
|
|
|
|
|
if (i < 45) {
|
|
|
|
|
value = type === 'a' ? 8500 : 7500
|
|
|
|
|
} else if (i >= 45 && i < 60) {
|
|
|
|
|
value = 8500 - ((i - 45) * 500)
|
|
|
|
|
} else if (i >= 60 && i < 75) {
|
|
|
|
|
value = 1000 + ((i - 60) * 500)
|
|
|
|
|
} else {
|
|
|
|
|
value = type === 'a' ? 8500 : 7500
|
|
|
|
|
}
|
|
|
|
|
data.push([i, value])
|
|
|
|
|
}
|
|
|
|
|
arm1ChartData.value = data
|
|
|
|
|
}
|
|
|
|
|
// 标签页切换
|
|
|
|
|
const handleClick = (tab, event) => {
|
2025-06-05 09:27:13 +08:00
|
|
|
|
console.log(deviceStatus.value,'===')
|
2025-06-05 16:33:14 +08:00
|
|
|
|
nextTick(async() => {
|
2025-05-23 14:14:05 +08:00
|
|
|
|
if(tab.props.label === '趋势图') {
|
2025-06-05 16:33:14 +08:00
|
|
|
|
await sendDeviceTrend()
|
2025-05-23 14:14:05 +08:00
|
|
|
|
realtimeChartRef.value?.resize()
|
|
|
|
|
}
|
|
|
|
|
if(tab.props.label === '图像预览') {
|
|
|
|
|
bowlCurveRef.value?.resize()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
const handlePrevious = () => {
|
|
|
|
|
if (currentIndex.value > 0) {
|
|
|
|
|
currentIndex.value--
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleNext = () => {
|
|
|
|
|
if (currentIndex.value < toleranceList.length - 1) {
|
|
|
|
|
currentIndex.value++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 图像预览
|
|
|
|
|
const handleDataUpdate = (data) => {
|
|
|
|
|
console.log('数据更新:', data)
|
|
|
|
|
}
|
|
|
|
|
// 快速模式
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const handleModeChange = () => {
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
'是否确认切换模式?',
|
|
|
|
|
'提示',
|
|
|
|
|
{
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
type: 'warning'
|
|
|
|
|
}
|
|
|
|
|
).then(async() => {
|
|
|
|
|
try {
|
|
|
|
|
await publish(`v1/cpy/${deviceInfo.value.deviceCode}/control`, JSON.stringify({
|
|
|
|
|
method: 'devinput',
|
|
|
|
|
cid: clientId.value, // guid
|
|
|
|
|
scanner: "global_dev",
|
|
|
|
|
dev: 'device', // 高压源power电机 motor 采集板acquisition_board 射线xray 其他设备 device
|
|
|
|
|
key: 'sports_mode',
|
|
|
|
|
value: '' // 运动模式 fast快速 normal正常速度 slow慢速
|
|
|
|
|
}))
|
|
|
|
|
ElMessage.success('发送命令成功')
|
|
|
|
|
initSubscribe()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('发送命令失败')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
// 用户取消操作
|
|
|
|
|
})
|
2025-05-23 14:14:05 +08:00
|
|
|
|
}
|
|
|
|
|
//x射线
|
|
|
|
|
const handleXRayToggle = () => {
|
|
|
|
|
ElMessageBox.confirm(
|
|
|
|
|
'是否确认切换X射线状态?',
|
|
|
|
|
'提示',
|
|
|
|
|
{
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
type: 'warning'
|
|
|
|
|
}
|
2025-06-05 09:27:13 +08:00
|
|
|
|
).then(async() => {
|
|
|
|
|
try {
|
|
|
|
|
// 这里可以调用接口来切换X射线状态
|
|
|
|
|
await publish(`v1/cpy/${deviceInfo.value.deviceCode}/control`, JSON.stringify({
|
|
|
|
|
method: 'devinput',
|
|
|
|
|
cid:clientId.value,
|
|
|
|
|
scanner:'scanner1',
|
|
|
|
|
dev:'xray',
|
|
|
|
|
key: "switch",
|
|
|
|
|
value:"1" // 1开 0关
|
|
|
|
|
}))
|
|
|
|
|
await publish(`v1/cpy/${deviceInfo.value.deviceCode}/control`, JSON.stringify({
|
|
|
|
|
method: 'devinput',
|
|
|
|
|
cid:clientId.value,
|
|
|
|
|
scanner:'scanner2',
|
|
|
|
|
dev:'xray',
|
|
|
|
|
key: "switch",
|
|
|
|
|
value:"1" // 1开 0关
|
|
|
|
|
}))
|
|
|
|
|
ElMessage.success('发送命令成功')
|
|
|
|
|
initSubscribe()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('发送命令失败')
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-23 14:14:05 +08:00
|
|
|
|
}).catch(() => {
|
|
|
|
|
// 用户取消操作
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// 生成报告
|
|
|
|
|
const handleGenerateReport = () => {
|
|
|
|
|
}
|
|
|
|
|
// 设备分享
|
|
|
|
|
const handleDeviceShare = () => {
|
|
|
|
|
}
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const initSubscribe = () => {
|
|
|
|
|
// 设备信息
|
|
|
|
|
subscribe(`v1/cpy/${deviceInfo.value?.deviceCode}/infos`, (message) => {
|
|
|
|
|
console.log('设备信息消息:', message)
|
|
|
|
|
// deviceData.value = message
|
|
|
|
|
if(message){
|
|
|
|
|
deviceMode.value = message.global_dev.device.sports_mode
|
|
|
|
|
xRayStatus.value = message.scanner1.xray.enable_status
|
|
|
|
|
deviceStatus.value = { ...message }
|
|
|
|
|
if (!warningInserted.value) {
|
|
|
|
|
warningList.value.push(
|
|
|
|
|
{label:'scanner1采集板故障信息', info: message.scanner1.acquisition_board.failure_info},
|
|
|
|
|
{label:'scanner1电源故障信息', info: message.scanner1.power.failure_info},
|
|
|
|
|
{label:'scanner1射线故障信息', info: message.scanner1.xray.failure_info},
|
|
|
|
|
{label:'scanner1电机通信状态', info: message.scanner1.motor.failure_info},
|
|
|
|
|
{label:'scanner2采集板故障信息', info: message.scanner2.acquisition_board.failure_info},
|
|
|
|
|
{label:'scanner2电源故障信息', info: message.scanner2.power.failure_info},
|
|
|
|
|
{label:'scanner2射线故障信息', info: message.scanner2.xray.failure_info},
|
|
|
|
|
{label:'scanner2电机通信状态', info: message.scanner2.motor.failure_info}
|
|
|
|
|
)
|
|
|
|
|
warningInserted.value = true
|
|
|
|
|
}
|
|
|
|
|
}})
|
|
|
|
|
// 设备状态
|
|
|
|
|
subscribe(`v1/cpycal/${deviceInfo.value?.deviceCode}/status`, (message) => {
|
|
|
|
|
// console.log('设备状态消息:', message)
|
|
|
|
|
if(message && message.running) {
|
|
|
|
|
deviceShowStatus.value = proxy.$t('common.online')
|
|
|
|
|
} else {
|
|
|
|
|
deviceShowStatus.value = proxy.$t('common.offline')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 计算数据
|
|
|
|
|
subscribe(`v1/cpy/${deviceInfo.value?.deviceCode}/calculation`, (message) => {
|
2025-06-05 16:33:14 +08:00
|
|
|
|
console.log('计算数据:', message)
|
2025-06-05 09:27:13 +08:00
|
|
|
|
// deviceData.value = message
|
|
|
|
|
// if(message){
|
|
|
|
|
// deviceMode.value = message.global_dev.device.sports_mode
|
|
|
|
|
// console.log(deviceMode.value)
|
|
|
|
|
// xRayStatus.value = message.scanner1.xray.enable_status
|
|
|
|
|
// }
|
|
|
|
|
})
|
2025-06-05 16:33:14 +08:00
|
|
|
|
//图像预览
|
|
|
|
|
subscribe(`v1/cpy/${deviceInfo.value?.deviceCode}/collect`, (message) => {
|
|
|
|
|
console.log('图像预览数据:', message)
|
|
|
|
|
// deviceData.value = message
|
|
|
|
|
// if(message){
|
|
|
|
|
// deviceMode.value = message.global_dev.device.sports_mode
|
|
|
|
|
// console.log(deviceMode.value)
|
|
|
|
|
// xRayStatus.value = message.scanner1.xray.enable_status
|
|
|
|
|
// }
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// 设备温度
|
|
|
|
|
const sendDeviceTemperature = async () => {
|
|
|
|
|
try {
|
|
|
|
|
await publish(`v1/cpy/1/request`, JSON.stringify({
|
|
|
|
|
method: 'temperature',
|
|
|
|
|
cid: clientId.value,
|
|
|
|
|
duration: 60,
|
|
|
|
|
}))
|
|
|
|
|
ElMessage.success('发送命令成功')
|
|
|
|
|
subscribe(`v1/cpy/${clientId.value}/receive`, (message) => {
|
|
|
|
|
console.log('设备温度:', message)
|
|
|
|
|
if(message.method === 'temperature') {
|
|
|
|
|
temperatureData.value.SCANNER1 = base64Decode(message.SCANNER1,true)
|
|
|
|
|
temperatureData.value.SCANNER2 = base64Decode(message.SCANNER1,true)
|
|
|
|
|
temperatureData.value.datetime = timestampArrayToTime(base64Decode(message.datetime,true))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('发送命令失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 趋势图
|
|
|
|
|
const sendDeviceTrend = async () => {
|
|
|
|
|
try {
|
|
|
|
|
await publish(`v1/cpy/1/request`, JSON.stringify({
|
|
|
|
|
method: 'trend',
|
|
|
|
|
cid: clientId.value,
|
|
|
|
|
duration: 30,
|
|
|
|
|
filters:'WtOSC'
|
|
|
|
|
}))
|
|
|
|
|
ElMessage.success('发送命令成功')
|
|
|
|
|
subscribe(`v1/cpy/${clientId.value}/receive`, (message) => {
|
|
|
|
|
console.log('趋势数据:', message)
|
|
|
|
|
if(message.method === 'trend') {
|
|
|
|
|
trendData.value.datetime = base64Decode(message.datetime,true)
|
|
|
|
|
trendData.value.WtOSC = base64Decode(message.WtOSC,true)
|
|
|
|
|
trendData.value.WtINS = base64Decode(message.WtINS,true)
|
|
|
|
|
trendData.value.WtISC = base64Decode(message.WtISC,true)
|
|
|
|
|
trendData.value.EccentricityINS = base64Decode(message.EccentricityINS,true)
|
|
|
|
|
trendData.value.EccentricityOSC = base64Decode(message.EccentricityOSC,true)
|
|
|
|
|
trendData.value.EccentricityISC = base64Decode(message.EccentricityISC,true)
|
|
|
|
|
trendData.value.DmCORE = base64Decode(message.DmCORE,true)
|
|
|
|
|
trendData.value.DmALL = base64Decode(message.DmALL,true)
|
|
|
|
|
console.log(trendData.value,'==')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('发送命令失败')
|
|
|
|
|
}
|
2025-06-05 09:27:13 +08:00
|
|
|
|
}
|
2025-06-04 13:25:40 +08:00
|
|
|
|
// 获取设备详细信息
|
|
|
|
|
const getDeviceDetail = async () => {
|
|
|
|
|
try {
|
2025-06-05 09:27:13 +08:00
|
|
|
|
const res = await getDeviceDetailApi(deviceId.value)
|
|
|
|
|
deviceInfo.value = res.data
|
|
|
|
|
initSubscribe()
|
2025-06-04 13:25:40 +08:00
|
|
|
|
} catch (error) {
|
2025-06-05 09:27:13 +08:00
|
|
|
|
ElMessage.error(error.message)
|
2025-06-04 13:25:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-05 09:27:13 +08:00
|
|
|
|
onMounted(async() => {
|
2025-06-05 16:33:14 +08:00
|
|
|
|
mqttConnect()
|
2025-06-04 13:25:40 +08:00
|
|
|
|
if(route.query.id) {
|
|
|
|
|
deviceId.value= route.query.id;
|
2025-06-05 09:27:13 +08:00
|
|
|
|
await getDeviceDetail()
|
2025-06-04 13:25:40 +08:00
|
|
|
|
}
|
2025-06-05 16:33:14 +08:00
|
|
|
|
await sendDeviceTemperature()
|
|
|
|
|
await sendDeviceTrend()
|
2025-05-23 14:14:05 +08:00
|
|
|
|
generateData()
|
|
|
|
|
})
|
2025-06-04 13:25:40 +08:00
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
disconnect()
|
|
|
|
|
})
|
2025-05-23 14:14:05 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.equipment-container {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
|
margin: 0 0 20px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.data-overview {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
.data-left {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.data-card {
|
|
|
|
|
flex: 1;
|
|
|
|
|
display: flex;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
align-items: center;
|
|
|
|
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
|
|
|
|
.img-icon {
|
|
|
|
|
border:1px dashed #ccc;
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
}
|
|
|
|
|
.number {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
color:#333333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.label {
|
|
|
|
|
color: #999;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chart-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
|
|
|
|
.chart-box {
|
2025-06-04 13:25:40 +08:00
|
|
|
|
flex:1;
|
2025-05-23 14:14:05 +08:00
|
|
|
|
position: relative;
|
|
|
|
|
padding: 14px;
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
|
|
|
|
.btn {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top:14px;
|
|
|
|
|
right: 14px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.action-buttons {
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
|
|
|
|
.button-group {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
|
|
|
|
.el-button {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 5px;
|
|
|
|
|
|
|
|
|
|
&.el-button--danger {
|
|
|
|
|
background-color: #f56c6c;
|
|
|
|
|
border-color: #f56c6c;
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
background-color: #f78989;
|
|
|
|
|
border-color: #f78989;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.demo-tabs > .el-tabs__content {
|
|
|
|
|
padding: 32px;
|
|
|
|
|
color: #6b778c;
|
|
|
|
|
font-size: 32px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
.eccentricity-card {
|
|
|
|
|
background-color: #F5F7FA;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
padding: 14px;
|
|
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
|
|
|
|
.card-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
border-bottom:1px solid #ccc;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.close-icon {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
color: #999;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
.card-text {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
.difference {
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
|
|
.plus {
|
|
|
|
|
color: #f56c6c;
|
|
|
|
|
margin-right: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.label {
|
|
|
|
|
color: #f56c6c;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.value {
|
|
|
|
|
font-size: 32px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: red;
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
|
|
|
|
.unit {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
margin-left: 5px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tolerance-section {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
background: #E5ECF6 ;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.tolerance-text {
|
|
|
|
|
color: #666;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.card-container {
|
|
|
|
|
|
|
|
|
|
.card-list {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
gap: 15px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.chart-bottom-left {
|
|
|
|
|
width:38%;
|
|
|
|
|
}
|
|
|
|
|
.chart-bottom-right {
|
|
|
|
|
flex:1
|
|
|
|
|
}
|
|
|
|
|
.warning-container {
|
|
|
|
|
padding-left:10px;
|
|
|
|
|
.warning-item {
|
|
|
|
|
color:red;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.device-status {
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
height: 346px;
|
|
|
|
|
overflow-y: scroll;
|
|
|
|
|
:deep(.el-table) {
|
|
|
|
|
.el-tag {
|
|
|
|
|
width: 100%;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
|
|
&.el-tag--danger {
|
|
|
|
|
background-color: #fef0f0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.cell {
|
|
|
|
|
padding: 8px 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.header {
|
|
|
|
|
//display: flex;
|
|
|
|
|
//justify-content: space-between;
|
|
|
|
|
//align-items: center;
|
|
|
|
|
//margin-bottom: 14px;
|
|
|
|
|
.time {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #606266;
|
|
|
|
|
margin-left: 6px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.imagePage-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
.imagePage-left {
|
|
|
|
|
width: 52%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.charts {
|
|
|
|
|
//display: flex;
|
|
|
|
|
//gap: 20px;
|
|
|
|
|
padding: 0 6px;
|
|
|
|
|
flex:1;
|
|
|
|
|
//
|
|
|
|
|
//> div {
|
|
|
|
|
// flex: 1;
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
.controls {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
.switch {
|
|
|
|
|
margin-left: 5px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.switch-btn {
|
|
|
|
|
padding: 5px;
|
|
|
|
|
|
|
|
|
|
//&:hover {
|
|
|
|
|
// background: #f0f9eb;
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
.detection-section {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
.history-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
.history-right {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
}
|
|
|
|
|
.scanItem {
|
|
|
|
|
color:#666;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|