612 lines
17 KiB
Vue
612 lines
17 KiB
Vue
<script lang="ts" setup>
|
||
import cardNav from '@/components/cardNav/index.vue';
|
||
import {getDevice} from "@/api/system/device";
|
||
import {DeviceForm} from "@/api/system/device/types";
|
||
|
||
const router = useRouter();
|
||
|
||
function backList() {
|
||
router.replace({
|
||
path: '/device/deviceList'
|
||
})
|
||
}
|
||
|
||
function editDevice() {
|
||
router.push({
|
||
path: '/device/deviceEdit'
|
||
})
|
||
}
|
||
|
||
const route = useRoute();
|
||
const initFormData: DeviceForm = {
|
||
deviceId: undefined,
|
||
deviceNo: undefined,
|
||
imei: undefined,
|
||
name: undefined,
|
||
productId: undefined,
|
||
model: undefined,
|
||
sn: undefined,
|
||
hwVersion: undefined,
|
||
swVersion: undefined,
|
||
fwVersion: undefined,
|
||
pkgVersion: undefined,
|
||
ip: undefined,
|
||
mac: undefined,
|
||
wifiSsid: undefined,
|
||
bluetoothConnected: undefined,
|
||
status: undefined,
|
||
bindUserId: undefined,
|
||
bindTime: undefined,
|
||
homeId: undefined,
|
||
locationId: undefined,
|
||
signalLevel: undefined,
|
||
lng: undefined,
|
||
lat: undefined,
|
||
address: undefined,
|
||
charging: undefined,
|
||
deviceBattery: undefined,
|
||
lastReportTime: undefined,
|
||
lastOnlineTime: undefined,
|
||
remark: undefined,
|
||
createDept: undefined,
|
||
createBy: undefined,
|
||
createTime: undefined,
|
||
updateBy: undefined,
|
||
updateTime: undefined,
|
||
activeDeviceNo: undefined,
|
||
activeImei: undefined,
|
||
activeMac: undefined,
|
||
}
|
||
|
||
const form = ref();
|
||
|
||
function init() {
|
||
form.value = {...initFormData};
|
||
console.log(form.value);
|
||
if (route.query.id) {
|
||
getDevice(route.query.id as string).then(res => {
|
||
Object.assign(form.value, res.data);
|
||
});
|
||
}
|
||
}
|
||
|
||
init()
|
||
|
||
</script>
|
||
|
||
<template>
|
||
<div class="Main">
|
||
<nav class="flex justify-between">
|
||
<Pagecrumb></Pagecrumb>
|
||
<div>
|
||
<el-button plain type="info" @click="backList">返回设备列表</el-button>
|
||
<el-button type="primary" @click="editDevice">编辑设备</el-button>
|
||
</div>
|
||
</nav>
|
||
<div class="infoBox">
|
||
<div class="info-item">
|
||
<el-image class="info_img"
|
||
src="https://ts2.tc.mm.bing.net/th/id/OIP-C.2KXRoOZ1EPBDMf6jrp6xeAHaE7?r=0&rs=1&pid=ImgDetMain&o=7&rm=3"></el-image>
|
||
<div class="info">
|
||
<div class="nav">
|
||
<div class="title">{{ form.name }}</div>
|
||
<div class="tag online">
|
||
<i class="circle"></i>
|
||
<span>在线</span>
|
||
</div>
|
||
</div>
|
||
<div class="info-list">
|
||
<div class="info-list-item">
|
||
<div class="title">设备ID</div>
|
||
<div class="value">{{ form.deviceid }}</div>
|
||
</div>
|
||
<div class="info-list-item">
|
||
<div class="title">MAC地址</div>
|
||
<div class="value">{{ form.mac }}</div>
|
||
</div>
|
||
<div class="info-list-item">
|
||
<div class="title">所在房间</div>
|
||
<div class="value">{{ form.locationName }}</div>
|
||
</div>
|
||
<div class="info-list-item">
|
||
<div class="title">产品型号</div>
|
||
<div class="value">{{ form.model }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="timeBox">
|
||
<div class="title">最后上报时间</div>
|
||
<div class="time">{{ form.lastReportTime }}</div>
|
||
<div class="tip">
|
||
<i class="circle"></i>
|
||
<span>每30s自动刷新</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="baseInfo">
|
||
<cardNav subTitle="静态档案信息,如需修改请前往「编辑设备」页" title="设备基础档案"></cardNav>
|
||
<div class=" gridBox">
|
||
<div class="grid-item">
|
||
<div class="title">设备ID</div>
|
||
<div class="value">{{ form.deviceId }}</div>
|
||
</div>
|
||
<div class="grid-item">
|
||
<div class="title">设备名称</div>
|
||
<div class="value">{{ form.name }}</div>
|
||
</div>
|
||
<div class="grid-item">
|
||
<div class="title">MAC地址</div>
|
||
<div class="value">{{ form.mac }}</div>
|
||
</div>
|
||
<div class="grid-item">
|
||
<div class="title">产品型号</div>
|
||
<div class="value">{{ form.model }}</div>
|
||
</div>
|
||
<div class="grid-item">
|
||
<div class="title">所在房间</div>
|
||
<div class="value">{{ form.homeName }}</div>
|
||
</div>
|
||
<div class="grid-item">
|
||
</div>
|
||
<div class="grid-item">
|
||
<div class="title">档案创建时间</div>
|
||
<div class="value">{{ form.createTime }}</div>
|
||
</div>
|
||
<div class="grid-item">
|
||
<div class="title">档案更新时间</div>
|
||
<div class="value">{{ form.updateTime }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="readTimeBox">
|
||
<cardNav line-color="#14b8a6" subTitle="设备蓝牙上报 · 只读 · 每 30 秒自动刷新"
|
||
title="设备实时运行状态"></cardNav>
|
||
<div class="flexBox">
|
||
<div class="flex-item">
|
||
<div class="flex-item-nav">
|
||
<i class="circle"></i>
|
||
<span>环境数据</span>
|
||
</div>
|
||
<div class="numBox">
|
||
<div class="num">{{ form.tvoc }}</div>
|
||
<div class="tag">
|
||
<i class="circle"></i>
|
||
<span>在线</span>
|
||
</div>
|
||
</div>
|
||
<div class="subTitle">TVOC 传感器原始读数(未换算为浓度值)</div>
|
||
<div class="footer">
|
||
<span>数据更新时间</span>
|
||
<span style="color: rgba(17, 24, 39, 1);">2026-09-30 12:50:30</span>
|
||
</div>
|
||
</div>
|
||
<div class="flex-item flex flex-col">
|
||
<div class="flex-item-nav">
|
||
<i class="circle" style="background: #2563eb"></i>
|
||
<span>运行数据</span>
|
||
</div>
|
||
<div class="flex-1 flex flex-col justify-evenly">
|
||
<div class="footer" style="margin-top: 0">
|
||
<span>运行模式</span>
|
||
<div>
|
||
<span v-if="form.runMode == '2'" style="color: rgba(17, 24, 39, 1);">桌面模式</span>
|
||
<span v-else-if="form.runMode == '1'" style="color: rgba(17, 24, 39, 1);">车载模式</span>
|
||
<span v-else style="color: rgba(17, 24, 39, 1);">自动</span>
|
||
</div>
|
||
</div>
|
||
<div class="footer" style="margin-top: 0">
|
||
<span>风速挡位</span>
|
||
<div>
|
||
<span v-if="form.fanLevel == '1'" style="color: rgba(17, 24, 39, 1);">强力</span>
|
||
<span v-else-if="form.fanLevel == '2'" style="color: rgba(17, 24, 39, 1);">低档</span>
|
||
<span v-else style="color: rgba(17, 24, 39, 1);">标准</span>
|
||
</div>
|
||
</div>
|
||
<div class="footer" style="margin-top: 0">
|
||
<span>供电模式</span>
|
||
<div>
|
||
<span v-if="form.powerMode == '0'" style="color: rgba(17, 24, 39, 1);">USB供电</span>
|
||
<span v-else style="color: rgba(17, 24, 39, 1);">电池供电</span>
|
||
</div>
|
||
</div>
|
||
<div class="footer" style="margin-top: 0">
|
||
<span>停车关机模式</span>
|
||
<el-tag v-if="form.parkingShutdown == '1'" type="success">开启</el-tag>
|
||
<el-tag v-else type="danger">关闭</el-tag>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex-item flex flex-col ">
|
||
<div class="flex-item-nav">
|
||
<i class="circle" style="background: #f59e0b"></i>
|
||
<span>耗材与电量</span>
|
||
</div>
|
||
<div class="flex-1 flex justify-evenly">
|
||
<div class="ageBox">
|
||
<div class="title">滤芯寿命</div>
|
||
<div class="processInfo">
|
||
<span class="num">76</span>
|
||
<span class="unit">%</span>
|
||
</div>
|
||
<el-progress :percentage="30" :show-text="false"></el-progress>
|
||
<div class="tip">
|
||
<span>预计剩余可用128天</span>
|
||
</div>
|
||
</div>
|
||
<div class="line"></div>
|
||
<div class="ageBox BatteryBox">
|
||
<div class="title">滤芯寿命</div>
|
||
<div class="processInfo">
|
||
<span class="num">76</span>
|
||
<span class="unit">%</span>
|
||
</div>
|
||
<el-progress :percentage="30" :show-text="false" color="#22C55E"></el-progress>
|
||
<el-tag type="success">充电中</el-tag>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex-item flex flex-col ">
|
||
<div class="flex-item-nav">
|
||
<i class="circle" style="background: #6366f1"></i>
|
||
<span>策略说明 · 停车关机模式</span>
|
||
</div>
|
||
<ul style="margin-top: 16px;">
|
||
<li class="modelLi">
|
||
<el-tag type="success">开启</el-tag>
|
||
<span class="describe">USB 外部供电断开后,电池供电继续运行 5 分钟消杀再自动关机;低电量 SOC<10% 时关闭等离子消杀;SOC<5% 整机锁机(防止过放)。</span>
|
||
</li>
|
||
<li class="modelLi">
|
||
<el-tag type="info">关闭</el-tag>
|
||
<span class="describe">不执行该套低电量策略,仅保留基础净化逻辑。</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
.Main {
|
||
height: 100%;
|
||
width: 100%;
|
||
overflow: auto;
|
||
|
||
.infoBox {
|
||
padding: 24px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
max-height: 177px;
|
||
min-width: 750px;
|
||
border-radius: 16px 16px 16px 16px;
|
||
border: 1px solid rgba(238, 240, 243, 1);
|
||
margin-top: 8px;
|
||
|
||
.info-item {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.info_img {
|
||
width: 97px;
|
||
height: 97px;
|
||
border-radius: 16px 16px 16px 16px;
|
||
}
|
||
|
||
.info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
margin-left: 24px;
|
||
|
||
.nav {
|
||
display: flex;
|
||
align-items: end;
|
||
|
||
.title {
|
||
height: 28px;
|
||
line-height: 28px;
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 22px;
|
||
text-align: left;
|
||
}
|
||
|
||
.tag {
|
||
margin-left: 5px;
|
||
width: 62px;
|
||
height: 28px;
|
||
border-radius: 14px;
|
||
|
||
&.online {
|
||
background-color: rgba(232, 247, 238, 1);
|
||
color: rgba(22, 163, 74, 1);
|
||
font-size: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.circle {
|
||
margin-right: 6px;
|
||
display: block;
|
||
width: 7px;
|
||
height: 6px;
|
||
border-radius: 3px;
|
||
background-color: rgba(22, 163, 74, 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
.info-list {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20px;
|
||
margin-top: 28px;
|
||
|
||
.info-list-item {
|
||
.title {
|
||
height: 16px;
|
||
line-height: 16px;
|
||
color: rgba(156, 163, 175, 1);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.value {
|
||
height: 40px;
|
||
line-height: 20px;
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.timeBox {
|
||
.title {
|
||
text-align: right;
|
||
line-height: 16px;
|
||
color: rgba(156, 163, 175, 1);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.time {
|
||
line-height: 22px;
|
||
background-color: rgba(0, 0, 0, 0);
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 16px;
|
||
margin-top: 6px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.tip {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: end;
|
||
|
||
span {
|
||
background-color: rgba(0, 0, 0, 0);
|
||
color: rgba(37, 99, 235, 1);
|
||
font-size: 12px;
|
||
text-align: left;
|
||
}
|
||
|
||
.circle {
|
||
margin-right: 6px;
|
||
display: block;
|
||
width: 7px;
|
||
height: 6px;
|
||
border-radius: 3px;
|
||
background-color: #2563eb;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.baseInfo {
|
||
padding: 25px;
|
||
min-height: 248px;
|
||
border-radius: 16px 16px 16px 16px;
|
||
border: 1px solid rgba(238, 240, 243, 1);
|
||
margin: 16px 0;
|
||
|
||
.gridBox {
|
||
margin-top: 44px;
|
||
display: grid;
|
||
grid-template-columns: repeat(4, minmax(381px, 1fr));
|
||
gap: 20px;
|
||
|
||
@media (max-width: 1659px) {
|
||
grid-template-columns: repeat(3, minmax(381px, 1fr));
|
||
}
|
||
@media (max-width: 1250px) {
|
||
grid-template-columns: repeat(2, minmax(381px, 1fr));
|
||
}
|
||
@media (max-width: 600px) {
|
||
grid-template-columns: repeat(1, minmax(381px, 1fr));
|
||
}
|
||
|
||
.grid-item {
|
||
max-width: 381px;
|
||
|
||
.title {
|
||
height: 16px;
|
||
line-height: 16px;
|
||
color: rgba(156, 163, 175, 1);
|
||
font-size: 12px;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.value {
|
||
height: 20px;
|
||
line-height: 20px;
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 14px;
|
||
text-align: left;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.readTimeBox {
|
||
padding: 25px;
|
||
border-radius: 16px 16px 16px 16px;
|
||
border: 1px solid rgba(238, 240, 243, 1);
|
||
|
||
.flexBox {
|
||
margin-top: 44px;
|
||
gap: 20px;
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(381px, 1fr));
|
||
@media (max-width: 900px) {
|
||
grid-template-columns: repeat(1, minmax(381px, 1fr));
|
||
}
|
||
|
||
.flex-item {
|
||
min-height: 201px;
|
||
border-radius: 12px 12px 12px 12px;
|
||
background-color: rgba(247, 249, 252, 1);
|
||
border: 1px solid rgba(238, 240, 243, 1);
|
||
padding: 21px;
|
||
|
||
.flex-item-nav {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.circle {
|
||
margin-right: 6px;
|
||
display: block;
|
||
width: 7px;
|
||
height: 6px;
|
||
border-radius: 3px;
|
||
background-color: rgba(22, 163, 74, 1);
|
||
}
|
||
|
||
span {
|
||
font-size: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
}
|
||
|
||
.numBox {
|
||
display: flex;
|
||
align-items: end;
|
||
margin-top: 17px;
|
||
|
||
.num {
|
||
line-height: 43px;
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 36px;
|
||
text-align: left;
|
||
}
|
||
|
||
.tag {
|
||
margin-left: 5px;
|
||
width: 62px;
|
||
height: 28px;
|
||
border-radius: 14px;
|
||
|
||
$backColor: rgba(232, 247, 238, 1);
|
||
$textColor: rgba(22, 163, 74, 1);
|
||
|
||
background-color: $backColor;
|
||
color: $textColor;
|
||
font-size: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.circle {
|
||
margin-right: 6px;
|
||
display: block;
|
||
width: 7px;
|
||
height: 6px;
|
||
border-radius: 3px;
|
||
background-color: $textColor;
|
||
}
|
||
}
|
||
}
|
||
|
||
.subTitle {
|
||
margin-top: 12px;
|
||
line-height: 16px;
|
||
color: rgba(156, 163, 175, 1);
|
||
font-size: 12px;
|
||
}
|
||
|
||
.footer {
|
||
margin-top: 44px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
line-height: 14px;
|
||
color: rgba(107, 114, 128, 1);
|
||
font-size: 12px;
|
||
}
|
||
|
||
|
||
// 滤芯寿命
|
||
.ageBox {
|
||
flex: 1;
|
||
margin-top: 16px;
|
||
|
||
.title {
|
||
line-height: 18px;
|
||
color: rgba(107, 114, 128, 1);
|
||
font-size: 13px;
|
||
}
|
||
|
||
.processInfo {
|
||
margin: 12px 0;
|
||
|
||
.num {
|
||
line-height: 31px;
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 26px;
|
||
}
|
||
|
||
.unit {
|
||
line-height: 17px;
|
||
color: rgba(107, 114, 128, 1);
|
||
font-size: 14px;
|
||
margin-left: 4px;
|
||
}
|
||
}
|
||
|
||
.tip {
|
||
line-height: 16px;
|
||
color: rgba(156, 163, 175, 1);
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
|
||
.line {
|
||
width: 2px;
|
||
height: 96px;
|
||
background-color: rgba(238, 240, 243, 1);
|
||
margin: 15px 24px;
|
||
}
|
||
|
||
.modelLi {
|
||
margin-bottom: 12px;
|
||
|
||
span.describe {
|
||
margin-left: 12px;
|
||
line-height: 16px;
|
||
color: rgba(75, 85, 99, 1);
|
||
font-size: 13px;
|
||
text-align: left;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|