1 changed files with 150 additions and 0 deletions
@ -0,0 +1,150 @@ |
|||||
|
# Monitor DockDeviceCard 设计 |
||||
|
|
||||
|
## 背景 |
||||
|
|
||||
|
Alarms / Media 薄卡片已抽离。Monitor 侧栏仍是整段内联 `article.device-card`(checkbox、主行、绑定机子树、告警/离线条),与地图/控制逻辑挤在同一超大 SFC 中。 |
||||
|
|
||||
|
本阶段只抽 **单张机巢设备卡**,降低侧栏模板体积;搜索、筛选、多选条、列表容器与地图控制保持不动。 |
||||
|
|
||||
|
## 目标 |
||||
|
|
||||
|
1. 新增 `src/components/DockDeviceCard.vue`。 |
||||
|
2. `MonitorView` 的 `device-list` 循环改为渲染该组件。 |
||||
|
3. 视觉与交互保持现状(`prototype.css` 类名不变)。 |
||||
|
4. 选中态、多选 Set、过滤、地图联动仍由页面持有。 |
||||
|
|
||||
|
## 非目标 |
||||
|
|
||||
|
- 不抽 `BoundDroneRow` / filter-row / multi-select-bar / device-panel |
||||
|
- 不改地图、map-type、飞行控制、LivePlayer、详情抽屉 |
||||
|
- 不迁 CSS 到 scoped |
||||
|
- 不改 `devicesStore` 数据语义与加载策略 |
||||
|
- 不抽 Tasks 航线库卡 |
||||
|
|
||||
|
## 方案(已选) |
||||
|
|
||||
|
**dock 对象 + 选中态 props + 事件上抛。** |
||||
|
|
||||
|
| 项 | 说明 | |
||||
|
|----|------| |
||||
|
| 组件 | `DockDeviceCard.vue` | |
||||
|
| 数据 | 传入已带 `children` 的 dock(即现 `filteredDocks` 元素) | |
||||
|
| 状态 | `active` / `multiSelected` / `selectedDroneId` 由页面计算传入 | |
||||
|
| 行为 | `select`、`toggle-select` 上抛;页面继续调现有 `select` / `setDockSelection` | |
||||
|
|
||||
|
## 组件契约 |
||||
|
|
||||
|
### Props |
||||
|
|
||||
|
| prop | 类型 | 说明 | |
||||
|
|------|------|------| |
||||
|
| `dock` | Object | 含 `id/name/code/status/statusClass/updated/children[]`;child 含 `id/name/statusClass/battery` 等 | |
||||
|
| `active` | Boolean | 机巢卡高亮(机巢或其子机被选中) | |
||||
|
| `multiSelected` | Boolean | 多选勾选态样式 | |
||||
|
| `selectedDroneId` | String \| null | 当前选中无人机 id,用于 `bound-drone.active` | |
||||
|
| `altitudeOf` | Function \| null | 可选 `(droneId) => number \| null \| undefined`;飞行中摘要显示高度。页面传入 `(id) => devices.asset(id)?.altitude` | |
||||
|
|
||||
|
### Events |
||||
|
|
||||
|
| event | payload | 页面接线 | |
||||
|
|-------|---------|----------| |
||||
|
| `select` | `id: string` | `@select="select"` 或 `@select="select($event)"` | |
||||
|
| `toggle-select` | `{ id, checked }` 或 `(id, checked)` | 调 `setDockSelection` | |
||||
|
|
||||
|
推荐 payload:`@toggle-select="(id, checked) => setDockSelection(id, checked)"`(与现 checkbox `@change` 一致,两参数)。 |
||||
|
|
||||
|
### 内部职责 |
||||
|
|
||||
|
- 渲染现有 DOM 结构与 class: |
||||
|
- `article.device-card` + `active` / `multi-selected` |
||||
|
- `device-select-checkbox` + `t-checkbox` |
||||
|
- `device-card-main` / `dock-glyph` / `device-copy` / status |
||||
|
- `bound-drone` 子树(`flying` / `offline` / `active`) |
||||
|
- `device-alert` / `device-alert muted` |
||||
|
- **迁入** `droneSummary` / `droneTag`(逻辑与现 MonitorView 一致;高度走 `altitudeOf`) |
||||
|
- 不读写 Pinia;不直接改 `selectedDockIds` |
||||
|
|
||||
|
### 根结构(保持) |
||||
|
|
||||
|
```html |
||||
|
<article class="device-card" :class="{ active, 'multi-selected': multiSelected }"> |
||||
|
<!-- checkbox --> |
||||
|
<!-- device-card-main @click emit select(dock.id) --> |
||||
|
<!-- bound-drone v-for children @click emit select(drone.id) --> |
||||
|
<!-- device-alert by statusClass --> |
||||
|
</article> |
||||
|
``` |
||||
|
|
||||
|
## MonitorView 改造 |
||||
|
|
||||
|
```html |
||||
|
<div class="device-list"> |
||||
|
<DockDeviceCard |
||||
|
v-for="dock in filteredDocks" |
||||
|
:key="dock.id" |
||||
|
:dock="dock" |
||||
|
:active="isDockCardActive(dock)" |
||||
|
:multi-selected="selectedDockIds.has(dock.id)" |
||||
|
:selected-drone-id="selectedId" |
||||
|
:altitude-of="droneAltitude" |
||||
|
@select="select" |
||||
|
@toggle-select="setDockSelection" |
||||
|
/> |
||||
|
<div v-if="!filteredDocks.length" class="table-empty" …>暂无匹配设备</div> |
||||
|
</div> |
||||
|
``` |
||||
|
|
||||
|
```js |
||||
|
import DockDeviceCard from '@/components/DockDeviceCard.vue' |
||||
|
|
||||
|
function droneAltitude(id) { |
||||
|
return devices.asset(id)?.altitude |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- 删除页面内联的 `droneSummary` / `droneTag`(迁入组件后) |
||||
|
- 保留:`groupedDocks` / `filteredDocks` / `filterCounts` / `selectedDockIds` / `isDockCardActive` / 搜索与 filter-row / multi-select-bar |
||||
|
- `setDockSelection(id, checked)` 签名保持,便于直接作事件处理器 |
||||
|
|
||||
|
## 样式 |
||||
|
|
||||
|
- 继续用全局 `prototype.css`:`.device-card`、`.bound-drone`、`.device-alert` 等 |
||||
|
- 组件不加改变视觉的 scoped 规则 |
||||
|
|
||||
|
## 文件清单 |
||||
|
|
||||
|
| 动作 | 路径 | |
||||
|
|------|------| |
||||
|
| 新增 | `src/components/DockDeviceCard.vue` | |
||||
|
| 修改 | `src/views/MonitorView/MonitorView.vue` | |
||||
|
|
||||
|
## 实现顺序 |
||||
|
|
||||
|
1. **A** — 创建 `DockDeviceCard`,迁入 summary/tag;MonitorView 接入;单独 commit |
||||
|
2. **B** — 浏览器冒烟:筛选、点选机巢/无人机、多选 checkbox、告警/离线条、地图选中联动 |
||||
|
|
||||
|
建议 commit: |
||||
|
|
||||
|
- `refactor: 抽取 Monitor DockDeviceCard 侧栏设备卡` |
||||
|
|
||||
|
## 验收标准 |
||||
|
|
||||
|
1. 侧栏卡外观与抽离前一致(含 active / multi-selected / bound-drone / alert) |
||||
|
2. 点击机巢/无人机仍触发原 `select` → 地图/详情聚焦 |
||||
|
3. checkbox 多选、全选/取消选择仍可用 |
||||
|
4. 飞行中摘要在有高度时显示 `飞行中 · N m` |
||||
|
5. 无 console error;不回归 Alarms/Media/Devices |
||||
|
|
||||
|
## 风险 |
||||
|
|
||||
|
| 风险 | 处理 | |
||||
|
|------|------| |
||||
|
| `altitudeOf` 未传导致高度丢失 | 页面必须传入;组件无回调时降级为「飞行中」 | |
||||
|
| checkbox `@change` 参数形态 | 与 TDesign 一致,组件内转成 `(id, checked)` 再 emit | |
||||
|
| Monitor SFC 仍很大 | 本阶段只抽卡;地图/控制后续另议 | |
||||
|
|
||||
|
## 约束 |
||||
|
|
||||
|
- 工作目录:`/Users/qingyuan/CodeProject/laic-frontend` |
||||
|
- 不改后台;精确 `git add`;中文 commit |
||||
|
- 跳过全量单测;以页面冒烟为准 |
||||
Loading…
Reference in new issue