|
|
|
@ -27,11 +27,25 @@
|
|
|
|
<div class="center-shell">
|
|
|
|
<div class="center-shell">
|
|
|
|
<img class="dashboard-center-image" src="@/assets/imgs/dashboard_img.png" alt="dashboard" />
|
|
|
|
<img class="dashboard-center-image" src="@/assets/imgs/dashboard_img.png" alt="dashboard" />
|
|
|
|
<!-- 上面4个 -->
|
|
|
|
<!-- 上面4个 -->
|
|
|
|
<div v-for="(item, index) in topDevices" :key="'top-' + index" class="device-card top-card" :style="{ left: getTopLeft(index) }">
|
|
|
|
<div
|
|
|
|
|
|
|
|
v-for="(item, index) in topDevices"
|
|
|
|
|
|
|
|
:key="'top-' + index"
|
|
|
|
|
|
|
|
class="device-card top-card"
|
|
|
|
|
|
|
|
:class="`device-card--${getDeviceStatusType(item.operatingStatus)}`"
|
|
|
|
|
|
|
|
:style="{ left: getTopLeft(index) }"
|
|
|
|
|
|
|
|
>
|
|
|
|
<div class="device-header">
|
|
|
|
<div class="device-header">
|
|
|
|
<div class="header-left">
|
|
|
|
<div class="header-left">
|
|
|
|
<span class="device-dot"></span>
|
|
|
|
<span class="device-dot"></span>
|
|
|
|
<span class="device-name" :title="item.deviceName">{{ item.deviceName }}</span>
|
|
|
|
<span class="device-name" :title="item.deviceName">{{ item.deviceName }}</span>
|
|
|
|
|
|
|
|
<el-tag
|
|
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
|
|
effect="plain"
|
|
|
|
|
|
|
|
class="device-status-tag"
|
|
|
|
|
|
|
|
:class="`device-status-tag--${getDeviceStatusType(item.operatingStatus)}`"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{{ getDeviceStatusText(item.operatingStatus) }}
|
|
|
|
|
|
|
|
</el-tag>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="header-right">
|
|
|
|
<div class="header-right">
|
|
|
|
<span class="device-id">ID: {{ item.deviceId }}</span>
|
|
|
|
<span class="device-id">ID: {{ item.deviceId }}</span>
|
|
|
|
@ -45,11 +59,25 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- 下面4个 -->
|
|
|
|
<!-- 下面4个 -->
|
|
|
|
<div v-for="(item, index) in bottomDevices" :key="'bottom-' + index" class="device-card bottom-card" :style="{ left: getBottomLeft(index) }">
|
|
|
|
<div
|
|
|
|
|
|
|
|
v-for="(item, index) in bottomDevices"
|
|
|
|
|
|
|
|
:key="'bottom-' + index"
|
|
|
|
|
|
|
|
class="device-card bottom-card"
|
|
|
|
|
|
|
|
:class="`device-card--${getDeviceStatusType(item.operatingStatus)}`"
|
|
|
|
|
|
|
|
:style="{ left: getBottomLeft(index) }"
|
|
|
|
|
|
|
|
>
|
|
|
|
<div class="device-header">
|
|
|
|
<div class="device-header">
|
|
|
|
<div class="header-left">
|
|
|
|
<div class="header-left">
|
|
|
|
<span class="device-dot"></span>
|
|
|
|
<span class="device-dot"></span>
|
|
|
|
<span class="device-name" :title="item.deviceName">{{ item.deviceName }}</span>
|
|
|
|
<span class="device-name" :title="item.deviceName">{{ item.deviceName }}</span>
|
|
|
|
|
|
|
|
<el-tag
|
|
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
|
|
effect="plain"
|
|
|
|
|
|
|
|
class="device-status-tag"
|
|
|
|
|
|
|
|
:class="`device-status-tag--${getDeviceStatusType(item.operatingStatus)}`"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{{ getDeviceStatusText(item.operatingStatus) }}
|
|
|
|
|
|
|
|
</el-tag>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="header-right">
|
|
|
|
<div class="header-right">
|
|
|
|
<span class="device-id">ID: {{ item.deviceId }}</span>
|
|
|
|
<span class="device-id">ID: {{ item.deviceId }}</span>
|
|
|
|
@ -111,6 +139,7 @@ interface DeviceCardData {
|
|
|
|
deviceName: string
|
|
|
|
deviceName: string
|
|
|
|
deviceId: number
|
|
|
|
deviceId: number
|
|
|
|
attributes: DeviceAttribute[]
|
|
|
|
attributes: DeviceAttribute[]
|
|
|
|
|
|
|
|
operatingStatus?: string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const topDevices = ref<DeviceCardData[]>([])
|
|
|
|
const topDevices = ref<DeviceCardData[]>([])
|
|
|
|
@ -137,6 +166,7 @@ const loadDeviceAttributes = async () => {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
deviceName: d.deviceName || 'Device',
|
|
|
|
deviceName: d.deviceName || 'Device',
|
|
|
|
deviceId: d.deviceId,
|
|
|
|
deviceId: d.deviceId,
|
|
|
|
|
|
|
|
operatingStatus: d.operatingStatus,
|
|
|
|
attributes: (d.attributes || []).map((attr: any) => ({
|
|
|
|
attributes: (d.attributes || []).map((attr: any) => ({
|
|
|
|
attributeName: attr.attributeName || '-',
|
|
|
|
attributeName: attr.attributeName || '-',
|
|
|
|
addressValue: attr.addressValue,
|
|
|
|
addressValue: attr.addressValue,
|
|
|
|
@ -152,6 +182,21 @@ const loadDeviceAttributes = async () => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getDeviceStatusType = (status?: string) => {
|
|
|
|
|
|
|
|
if (!status) return 'info'
|
|
|
|
|
|
|
|
const s = String(status).toLowerCase()
|
|
|
|
|
|
|
|
if (s.includes('故障') || s === 'fault') return 'danger'
|
|
|
|
|
|
|
|
if (s.includes('待机') || s === 'standby') return 'primary'
|
|
|
|
|
|
|
|
if (s.includes('运行') || s === 'run' || s === 'running') return 'success'
|
|
|
|
|
|
|
|
if (s.includes('离线') || s === 'offline') return 'info'
|
|
|
|
|
|
|
|
return 'info'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getDeviceStatusText = (status?: string) => {
|
|
|
|
|
|
|
|
if (!status) return '离线'
|
|
|
|
|
|
|
|
return status
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
onMounted(() => {
|
|
|
|
loadDeviceAttributes()
|
|
|
|
loadDeviceAttributes()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
@ -301,6 +346,26 @@ main {
|
|
|
|
box-shadow: 0 0 10px rgb(0 0 0 / 50%);
|
|
|
|
box-shadow: 0 0 10px rgb(0 0 0 / 50%);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-card--success {
|
|
|
|
|
|
|
|
border-color: var(--green);
|
|
|
|
|
|
|
|
box-shadow: 0 0 10px rgb(34 197 94 / 45%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-card--primary {
|
|
|
|
|
|
|
|
border-color: var(--primary);
|
|
|
|
|
|
|
|
box-shadow: 0 0 10px rgb(56 189 248 / 45%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-card--danger {
|
|
|
|
|
|
|
|
border-color: var(--danger);
|
|
|
|
|
|
|
|
box-shadow: 0 0 10px rgb(239 68 68 / 45%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-card--info {
|
|
|
|
|
|
|
|
border-color: var(--muted);
|
|
|
|
|
|
|
|
box-shadow: 0 0 10px rgb(148 163 184 / 35%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.top-card {
|
|
|
|
.top-card {
|
|
|
|
top: 5%;
|
|
|
|
top: 5%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -348,6 +413,36 @@ main {
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
white-space: nowrap;
|
|
|
|
white-space: nowrap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.device-status-tag {
|
|
|
|
|
|
|
|
margin-left: 6px;
|
|
|
|
|
|
|
|
padding: 0 6px;
|
|
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-status-tag--success {
|
|
|
|
|
|
|
|
--el-tag-text-color: var(--green);
|
|
|
|
|
|
|
|
--el-tag-border-color: rgb(34 197 94 / 60%);
|
|
|
|
|
|
|
|
--el-tag-bg-color: rgb(22 163 74 / 15%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-status-tag--primary {
|
|
|
|
|
|
|
|
--el-tag-text-color: var(--primary);
|
|
|
|
|
|
|
|
--el-tag-border-color: rgb(56 189 248 / 60%);
|
|
|
|
|
|
|
|
--el-tag-bg-color: rgb(37 99 235 / 18%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-status-tag--danger {
|
|
|
|
|
|
|
|
--el-tag-text-color: var(--danger);
|
|
|
|
|
|
|
|
--el-tag-border-color: rgb(239 68 68 / 60%);
|
|
|
|
|
|
|
|
--el-tag-bg-color: rgb(185 28 28 / 18%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.device-status-tag--info {
|
|
|
|
|
|
|
|
--el-tag-text-color: var(--muted);
|
|
|
|
|
|
|
|
--el-tag-border-color: rgb(148 163 184 / 60%);
|
|
|
|
|
|
|
|
--el-tag-bg-color: rgb(30 41 59 / 60%);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.device-id {
|
|
|
|
.device-id {
|
|
|
|
font-size: 12px;
|
|
|
|
font-size: 12px;
|
|
|
|
|