Browse Source

feat: 监控页搜索勾选与状态弹窗切换到 TDesign

main
xiaosi 3 weeks ago
parent
commit
6c5c830bc3
  1. 9
      src/styles/prototype.css
  2. 224
      src/views/MonitorView/MonitorView.vue

9
src/styles/prototype.css

@ -122,10 +122,9 @@ svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width:
.device-card:hover { border-color: #aab9c8; transform: translateY(-1px); }
.device-card.active { border-color: #5a93d4; background: #f4f8fd; box-shadow: inset 3px 0 var(--blue); }
.device-card.multi-selected { border-color: var(--blue); box-shadow: inset 3px 0 var(--blue); background: #f4f8fd; }
.device-select-checkbox { position: absolute; z-index: 2; top: 10px; left: 8px; width: 16px; height: 16px; display: block; cursor: pointer; }
.device-select-checkbox input { position: absolute; opacity: 0; }
.device-select-checkbox > span { width: 15px; height: 15px; display: block; border: 1px solid #b8c7d2; border-radius: 3px; background: #fff; }
.device-select-checkbox input:checked + span { border-color: var(--blue); background: var(--blue); box-shadow: inset 0 0 0 3px #fff; }
.device-select-checkbox { position: absolute; z-index: 2; top: 10px; left: 8px; width: auto; height: auto; display: flex; align-items: center; cursor: pointer; }
.device-select-checkbox .t-checkbox { margin: 0; }
.device-select-checkbox .t-checkbox__label { display: none; }
.device-card-main { width: 100%; min-height: 68px; padding: 11px 11px 11px 34px; display: grid; grid-template-columns: 34px 1fr auto; align-items: center; gap: 9px; color: inherit; background: transparent; text-align: left; }
.device-copy { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.device-copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
@ -485,6 +484,8 @@ svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width:
.modal-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-top: 18px; }
.modal-actions button { height: 38px; border-radius: 5px; font-size: 13px; }.modal-actions .cancel { background: #fff; border: 1px solid var(--line); }.modal-actions .confirm { color: #fff; background: var(--blue); }
.dock-status-dialog { width: min(700px, calc(100vw - 32px)); padding: 0; overflow: hidden; text-align: left; }
.dock-status-dialog .t-dialog__header { min-height: 58px; padding: 0 18px; border-bottom: 1px solid var(--line); }
.dock-status-dialog .t-dialog__body { padding: 0; }
.dock-status-header { min-height: 58px; padding: 0 18px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--line); cursor: grab; }
.dock-status-header:active { cursor: grabbing; }
.dock-status-header > div { display: flex; flex-direction: column; gap: 4px; }.dock-status-header span { color: var(--muted); font-size: 10px; }.dock-status-header h3 { margin: 0; font-size: 18px; }

224
src/views/MonitorView/MonitorView.vue

@ -6,10 +6,11 @@
<button class="icon-button" title="收起面板" @click="clearSelection"><svg><use href="#i-x" /></svg></button>
</div>
<label class="device-search">
<svg><use href="#i-search" /></svg>
<input v-model="search" type="text" placeholder="搜索机巢或无人机" />
</label>
<div class="device-search">
<t-input v-model="search" 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="filter = 'all'">全部 <b>{{ filterCounts.all }}</b></button>
@ -25,10 +26,12 @@
<div class="device-list">
<template v-for="dock in filteredDocks" :key="dock.id">
<article class="device-card" :class="{ active: isDockCardActive(dock), 'multi-selected': selectedDockIds.has(dock.id) }">
<label class="device-select-checkbox" :title="`选择${dock.name}`" @click.stop>
<input type="checkbox" :checked="selectedDockIds.has(dock.id)" @change="toggleDockSelection(dock.id)" />
<span></span>
</label>
<div class="device-select-checkbox" :title="`选择${dock.name}`" @click.stop>
<t-checkbox
:checked="selectedDockIds.has(dock.id)"
@change="(checked) => setDockSelection(dock.id, checked)"
/>
</div>
<button class="device-card-main" @click="select(dock.id)">
<span class="dock-glyph" :class="{ alarm: dock.statusClass === 'alarm', offline: dock.statusClass === 'offline' }">
<svg><use href="#i-home" /></svg>
@ -301,98 +304,94 @@
</section>
<div class="modal-backdrop" :class="{ open: dockStatusOpen }" :aria-hidden="!dockStatusOpen" @click.self="closeDockStatus">
<div class="modal dock-status-dialog" role="dialog" aria-modal="true" aria-labelledby="dockStatusTitle">
<header class="dock-status-header">
<t-dialog
v-model:visible="dockStatusOpen"
:header="dockStatusTitle"
width="700px"
:footer="false"
dialog-class-name="dock-status-dialog"
@close="closeDockStatus"
>
<div class="dock-status-body">
<div class="dock-status-grid">
<div>
<span>机巢运行状态</span>
<h3 id="dockStatusTitle">{{ dockStatusTitle }}</h3>
<span>设备连接</span>
<strong :class="{ 'green-text': dockStatusSummary.online }">{{ dockStatusSummary.connection }}</strong>
<small>{{ dockStatusSummary.connectionHint }}</small>
</div>
<button class="icon-button" type="button" title="关闭详情" @click="closeDockStatus">
<svg><use href="#i-x" /></svg>
</button>
</header>
<div class="dock-status-body">
<div class="dock-status-grid">
<div>
<span>设备连接</span>
<strong :class="{ 'green-text': dockStatusSummary.online }">{{ dockStatusSummary.connection }}</strong>
<small>{{ dockStatusSummary.connectionHint }}</small>
</div>
<div>
<span>无人机状态</span>
<strong>{{ dockStatusSummary.drone }}</strong>
<small>{{ dockStatusSummary.droneHint }}</small>
</div>
<div>
<span>舱门状态</span>
<strong>{{ dockStatusSummary.door }}</strong>
<small>{{ dockStatusSummary.doorHint }}</small>
</div>
<div>
<span>充电模块</span>
<strong :class="{ 'green-text': chargeTone }">{{ dockStatusSummary.charge }}</strong>
<small>{{ dockStatusSummary.chargeHint }}</small>
</div>
<div>
<span>控制模式</span>
<strong>{{ dockStatusSummary.mode }}</strong>
<small>{{ dockStatusSummary.modeHint }}</small>
</div>
<div>
<span>当前告警</span>
<strong :class="{ 'green-text': !dockStatusSummary.alarmCount }">{{ dockStatusSummary.alarm }}</strong>
<small>{{ dockStatusSummary.alarmHint }}</small>
</div>
<div>
<span>无人机状态</span>
<strong>{{ dockStatusSummary.drone }}</strong>
<small>{{ dockStatusSummary.droneHint }}</small>
</div>
<div>
<span>舱门状态</span>
<strong>{{ dockStatusSummary.door }}</strong>
<small>{{ dockStatusSummary.doorHint }}</small>
</div>
<div>
<span>充电模块</span>
<strong :class="{ 'green-text': chargeTone }">{{ dockStatusSummary.charge }}</strong>
<small>{{ dockStatusSummary.chargeHint }}</small>
</div>
<div>
<span>控制模式</span>
<strong>{{ dockStatusSummary.mode }}</strong>
<small>{{ dockStatusSummary.modeHint }}</small>
</div>
<div>
<span>当前告警</span>
<strong :class="{ 'green-text': !dockStatusSummary.alarmCount }">{{ dockStatusSummary.alarm }}</strong>
<small>{{ dockStatusSummary.alarmHint }}</small>
</div>
<section class="dock-state-section">
<div class="dock-state-heading">
<h4>状态</h4>
<span>PLC 实时反馈 · {{ selectedDock?.updated || record?.updated || '刚刚' }}</span>
</div>
<div class="dock-state-board">
<article>
<h5>舱门状态</h5>
<ul>
<li :class="{ active: isClosed(doorValue('left')) }"><i></i>左顶门关</li>
<li :class="{ active: doorValue('left') === 'open' }"><i></i>左顶门开</li>
<li :class="{ active: isClosed(doorValue('right')) }"><i></i>右顶门关</li>
<li :class="{ active: doorValue('right') === 'open' }"><i></i>右顶门开</li>
</ul>
</article>
<article>
<h5>杆件状态</h5>
<ul>
<li :class="{ active: isTight(centeringValue('leftRight')) }"><i></i>左右归中闭合</li>
<li :class="{ active: centeringValue('leftRight') === 'loose' }"><i></i>左右归中打开</li>
<li :class="{ active: isTight(centeringValue('frontBack')) }"><i></i>前后归中闭合</li>
<li :class="{ active: centeringValue('frontBack') === 'loose' }"><i></i>前后归中打开</li>
</ul>
</article>
<article>
<h5>系统状态</h5>
<ul>
<li :class="{ active: isTrue(rt('emergencyStop')) }"><i :class="{ warning: isTrue(rt('emergencyStop')) }"></i>急停</li>
<li :class="{ active: isAutoMode }"><i></i>自动模式</li>
<li :class="{ active: !dockStatusSummary.alarmCount }"><i></i>无报警</li>
<li :class="{ active: isTrue(rt('resetDone', 'resetComplete')) }"><i></i>复位完成</li>
</ul>
</article>
<article>
<h5>充电与在位</h5>
<ul>
<li :class="{ active: chargeTone }"><i></i>充电中</li>
<li :class="{ active: String(rt('chargingState') || '').toLowerCase() === 'idle' }"><i></i>充电空闲</li>
<li :class="{ active: isTrue(rt('dronePresent')) }"><i></i>无人机在位</li>
<li :class="{ active: isTrue(rt('powerOnline', 'powerOn')) }"><i></i>电源在线</li>
</ul>
</article>
</div>
</section>
</div>
<section class="dock-state-section">
<div class="dock-state-heading">
<h4>状态</h4>
<span>PLC 实时反馈 · {{ selectedDock?.updated || record?.updated || '刚刚' }}</span>
</div>
<div class="dock-state-board">
<article>
<h5>舱门状态</h5>
<ul>
<li :class="{ active: isClosed(doorValue('left')) }"><i></i>左顶门关</li>
<li :class="{ active: doorValue('left') === 'open' }"><i></i>左顶门开</li>
<li :class="{ active: isClosed(doorValue('right')) }"><i></i>右顶门关</li>
<li :class="{ active: doorValue('right') === 'open' }"><i></i>右顶门开</li>
</ul>
</article>
<article>
<h5>杆件状态</h5>
<ul>
<li :class="{ active: isTight(centeringValue('leftRight')) }"><i></i>左右归中闭合</li>
<li :class="{ active: centeringValue('leftRight') === 'loose' }"><i></i>左右归中打开</li>
<li :class="{ active: isTight(centeringValue('frontBack')) }"><i></i>前后归中闭合</li>
<li :class="{ active: centeringValue('frontBack') === 'loose' }"><i></i>前后归中打开</li>
</ul>
</article>
<article>
<h5>系统状态</h5>
<ul>
<li :class="{ active: isTrue(rt('emergencyStop')) }"><i :class="{ warning: isTrue(rt('emergencyStop')) }"></i>急停</li>
<li :class="{ active: isAutoMode }"><i></i>自动模式</li>
<li :class="{ active: !dockStatusSummary.alarmCount }"><i></i>无报警</li>
<li :class="{ active: isTrue(rt('resetDone', 'resetComplete')) }"><i></i>复位完成</li>
</ul>
</article>
<article>
<h5>充电与在位</h5>
<ul>
<li :class="{ active: chargeTone }"><i></i>充电中</li>
<li :class="{ active: String(rt('chargingState') || '').toLowerCase() === 'idle' }"><i></i>充电空闲</li>
<li :class="{ active: isTrue(rt('dronePresent')) }"><i></i>无人机在位</li>
<li :class="{ active: isTrue(rt('powerOnline', 'powerOn')) }"><i></i>电源在线</li>
</ul>
</article>
</div>
</section>
</div>
</div>
</t-dialog>
</template>
<script setup>
@ -1357,9 +1356,9 @@ function clearDockSelection() {
selectedDockIds.clear()
}
function toggleDockSelection(id) {
if (selectedDockIds.has(id)) selectedDockIds.delete(id)
else selectedDockIds.add(id)
function setDockSelection(id, checked) {
if (checked) selectedDockIds.add(id)
else selectedDockIds.delete(id)
}
function selectAllDocks() {
@ -1573,3 +1572,32 @@ async function runCommand(title, desc) {
}
}
</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;
}
.dock-status-body {
padding: 13px 18px 15px;
}
</style>

Loading…
Cancel
Save