You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

107 lines
3.4 KiB

<template>
<aside class="device-panel">
<div class="panel-heading">
<div><h1>设备列表</h1><span>{{ dockCount }} · {{ droneCount }} </span></div>
<button class="icon-button" title="收起面板" @click="emit('clear-selection')"><svg><use href="#i-x" /></svg></button>
</div>
<div class="device-search">
<t-input v-model="searchModel" clearable placeholder="搜索机巢或无人机">
<template #prefix-icon><t-icon name="search" /></template>
</t-input>
</div>
<div class="filter-row">
<button class="filter" :class="{ active: filter === 'all' }" @click="emit('update:filter', 'all')">全部 <b>{{ filterCounts.all }}</b></button>
<button class="filter" :class="{ active: filter === 'online' }" @click="emit('update:filter', 'online')">在线 <b>{{ filterCounts.online }}</b></button>
<button class="filter" :class="{ active: filter === 'alarm' }" @click="emit('update:filter', 'alarm')">告警 <b>{{ filterCounts.alarm }}</b></button>
</div>
<div v-if="docks.length" class="multi-select-bar" :class="{ 'has-selection': selectedSize }">
<span>已选择 {{ selectedSize }} 个机巢</span>
<button type="button" @click="emit('select-all')">全选</button>
<button type="button" @click="emit('clear-dock-selection')">取消选择</button>
</div>
<div class="device-list">
<DockDeviceCard
v-for="dock in docks"
:key="dock.id"
:dock="dock"
:active="isDockActive(dock)"
:multi-selected="selectedDockIds.has(dock.id)"
:selected-drone-id="selectedId"
:altitude-of="altitudeOf"
@select="emit('select', $event)"
@toggle-select="(id, checked) => emit('toggle-select', id, checked)"
/>
<div v-if="!docks.length" class="table-empty" style="height:120px;display:grid;place-items:center;color:var(--muted);font-size:10px">暂无匹配设备</div>
</div>
</aside>
</template>
<script setup>
import { computed } from 'vue'
import DockDeviceCard from '@/components/DockDeviceCard.vue'
const props = defineProps({
dockCount: { type: Number, default: 0 },
droneCount: { type: Number, default: 0 },
search: { type: String, default: '' },
filter: { type: String, default: 'all' },
filterCounts: {
type: Object,
default: () => ({ all: 0, online: 0, alarm: 0 }),
},
docks: { type: Array, default: () => [] },
selectedDockIds: {
type: Object,
default: () => new Set(),
},
selectedId: { type: String, default: null },
isDockActive: { type: Function, required: true },
altitudeOf: { type: Function, default: null },
})
const emit = defineEmits([
'clear-selection',
'select-all',
'clear-dock-selection',
'select',
'toggle-select',
'update:search',
'update:filter',
])
const selectedSize = computed(() => props.selectedDockIds?.size ?? 0)
const searchModel = computed({
get: () => props.search,
set: (value) => emit('update:search', value ?? ''),
})
</script>
<style scoped>
.device-search {
height: auto;
margin-top: 16px;
padding: 0;
border: 0;
background: transparent;
}
.device-search :deep(.t-input) {
width: 100%;
}
.device-select-checkbox {
width: auto;
height: auto;
display: flex;
align-items: center;
justify-content: center;
}
.device-select-checkbox :deep(.t-checkbox) {
margin: 0;
}
.device-select-checkbox :deep(.t-checkbox__input) {
margin: 0;
}
</style>