118 lines
4.0 KiB
Vue
118 lines
4.0 KiB
Vue
|
|
<script setup>
|
|||
|
|
import { computed } from "vue";
|
|||
|
|
import {
|
|||
|
|
deviceView,
|
|||
|
|
snapshot,
|
|||
|
|
bridge,
|
|||
|
|
accessLabel,
|
|||
|
|
} from "../composables/bridge.js";
|
|||
|
|
import AppIcon from "./AppIcon.vue";
|
|||
|
|
import NetworkStatus from "./NetworkStatus.vue";
|
|||
|
|
const home = computed(() =>
|
|||
|
|
(snapshot.value.state.households || []).find(
|
|||
|
|
(h) => h.id === snapshot.value.state.familyId,
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
</script>
|
|||
|
|
<template>
|
|||
|
|
<div id="device-topology" hidden>
|
|||
|
|
<section class="panel network-map">
|
|||
|
|
<div class="network-platform">
|
|||
|
|
<AppIcon name="network" />
|
|||
|
|
<div>
|
|||
|
|
<h3>{{ home?.name || "当前场所" }}</h3>
|
|||
|
|
<p>{{ deviceView.devices.length }} 台设备 · 随设备档案自动更新</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<p class="description">
|
|||
|
|
连线来自已确认的上级设备关系。上级未填写时单独列出;不代表已自动发现所有交换机或布线。
|
|||
|
|
</p>
|
|||
|
|
<div class="topology-nodes">
|
|||
|
|
<article
|
|||
|
|
v-for="row in deviceView.rows"
|
|||
|
|
:key="row.device.id"
|
|||
|
|
class="network-node card"
|
|||
|
|
:class="{ nested: row.depth > 0 }"
|
|||
|
|
:style="{ '--depth': Math.min(row.depth, 5) }"
|
|||
|
|
>
|
|||
|
|
<div class="card-body">
|
|||
|
|
<div class="device-card-heading">
|
|||
|
|
<AppIcon
|
|||
|
|
:name="row.device.source === 'camera' ? 'camera' : 'router'"
|
|||
|
|
/>
|
|||
|
|
<div class="flex-grow-1">
|
|||
|
|
<span class="small text-secondary"
|
|||
|
|
>{{ row.device.deviceType }} ·
|
|||
|
|
{{ accessLabel(row.device.networkAccess) }}</span
|
|||
|
|
>
|
|||
|
|
<h3>
|
|||
|
|
<button
|
|||
|
|
class="device-title"
|
|||
|
|
@click="
|
|||
|
|
bridge().enterDevice(row.device.source, row.device.id)
|
|||
|
|
"
|
|||
|
|
>
|
|||
|
|
{{ row.device.name }}
|
|||
|
|
</button>
|
|||
|
|
</h3>
|
|||
|
|
</div>
|
|||
|
|
<button
|
|||
|
|
class="btn btn-sm btn-outline-secondary"
|
|||
|
|
@click="
|
|||
|
|
bridge().enterDevice(
|
|||
|
|
row.device.source,
|
|||
|
|
row.device.id,
|
|||
|
|
'device',
|
|||
|
|
)
|
|||
|
|
"
|
|||
|
|
>
|
|||
|
|
详情 →
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
<p class="device-location">
|
|||
|
|
{{ bridge().location?.(row.device.siteId) || "未指定区域" }}
|
|||
|
|
<template v-if="row.device.point">
|
|||
|
|
· {{ row.device.point }}</template
|
|||
|
|
>
|
|||
|
|
</p>
|
|||
|
|
<div class="network-facts">
|
|||
|
|
<span
|
|||
|
|
>IP
|
|||
|
|
<b>{{
|
|||
|
|
row.device.networkHosts.join(" / ") || "待填写"
|
|||
|
|
}}</b></span
|
|||
|
|
><span v-if="row.device.tailscaleHost"
|
|||
|
|
>Tailscale <b>{{ row.device.tailscaleHost }}</b></span
|
|||
|
|
><span v-if="row.device.networkCidr"
|
|||
|
|
>网段 <b>{{ row.device.networkCidr }}</b></span
|
|||
|
|
><span
|
|||
|
|
>上级 <b>{{ row.parentName || "待确认 / 直接接入" }}</b></span
|
|||
|
|
><span
|
|||
|
|
>连接
|
|||
|
|
<b>{{
|
|||
|
|
{ wired: "网线", wifi: "Wi-Fi" }[row.device.connectionType] ||
|
|||
|
|
"待确认"
|
|||
|
|
}}</b></span
|
|||
|
|
><span v-if="row.via.length"
|
|||
|
|
>取流经录像机 <b>{{ row.via.join("、") }}</b></span
|
|||
|
|
><span v-if="row.archiveVia.length"
|
|||
|
|
>录像归档 <b>{{ row.archiveVia.join("、") }}</b></span
|
|||
|
|
>
|
|||
|
|
</div>
|
|||
|
|
<NetworkStatus
|
|||
|
|
v-if="/路由|网关|服务器/.test(row.device.deviceType)"
|
|||
|
|
:device="row.device"
|
|||
|
|
:active="
|
|||
|
|
snapshot.page === 'objects' && deviceView.mode === 'topology'
|
|||
|
|
"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</article>
|
|||
|
|
<p v-if="!deviceView.rows.length" class="empty">
|
|||
|
|
当前范围尚未登记设备。
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
</div>
|
|||
|
|
</template>
|