2 changed files with 125 additions and 65 deletions
@ -0,0 +1,107 @@ |
|||||
|
<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> |
||||
Loading…
Reference in new issue