9/30
1. 设备管理界面完成 2. 用户管理界面完成 3. 会话列表完成
This commit is contained in:
611
src/views/system/device/devicelist/main.vue
Normal file
611
src/views/system/device/devicelist/main.vue
Normal file
@@ -0,0 +1,611 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user