# Alarms + Media 薄卡片组件设计 ## 背景 TDesign 表单/页签/标准列表迁移与 Devices 真分页已收口。仍有一批**强定制卡列表**沿用原型 `article + prototype.css`: - Alarms:线性 `alarm-item` - Media:直播/原始视频网格卡 - Monitor:侧栏 `device-card`(树形绑定机、多选) - Tasks:航线库 `route-grid` 本阶段只做 **Alarms + Media** 的本地薄展示组件,降低页面模板体积,为后续 Monitor 设备卡抽离铺路。 ## 目标 1. 抽出 `AlarmItem.vue`、`MediaCard.vue` 两个展示组件。 2. `AlarmsView` / `MediaView` 仅用组件替换 `v-for` 内的 `article` 循环体。 3. **视觉与交互保持现状**:class 仍走 `prototype.css`,不引入 `t-list` / `t-card` 硬套。 4. 数据加载、空态、映射、请求、tab 仍留在页面。 ## 非目标 - 不改 Monitor 侧栏 / 地图 / 飞行控制 / LivePlayer - 不改 Tasks 航线库卡与航线编辑器 - 不迁 CSS 到 scoped(本阶段) - 不改后端 API、分页策略、业务字段语义 - 不做通用 `BusinessCard` 抽象 ## 方案(已选 A) 按视图各抽 **1 个列表项组件**: | 组件 | 用途 | |------|------| | `src/components/AlarmItem.vue` | 告警列表单行 | | `src/components/MediaCard.vue` | 直播卡 / 原始视频卡(`variant` 区分) | 不抽 `AlarmList` / `MediaGrid` 容器层(循环与空态仍在页面,避免无收益透传)。 ## 组件契约 ### AlarmItem **Props(展示用,与现映射字段对齐)** | prop | 类型 | 说明 | |------|------|------| | `severity` | string | 严重 / 警告 / 提示 | | `severityClass` | string | `critical` / `medium` / `low` | | `title` | string | 告警标题 | | `device` | string | 设备标识文案 | | `time` | string | 触发时间文案 | | `status` | string | 待处理 / 已确认 / 已恢复 | | `statusClass` | string | 状态样式 class | **Events** | event | payload | 说明 | |-------|---------|------| | `handle` | — | 点击「处理」;页面侧带上整条 alarm 调 API | 根节点保持: ```html
``` 内部结构与现 `AlarmsView` 模板一致(severity 标签、title/device·time、status、`t-button` 处理)。 ### MediaCard **Props** | prop | 类型 | 说明 | |------|------|------| | `variant` | `'live' \| 'video'` | 直播 / 原始视频 | | `name` | string | 主标题 | | `desc` | string | 副文案 | | `visualClass` | string | 封面背景 class(如 `dock-camera`) | | `source` | string? | live:画面来源角标 | | `duration` | string? | video:时长角标 | **Events** | event | 何时 | |-------|------| | `play` | 点击播放按钮(live / video 共用) | | `action` | live:更多;video:下载 | 根节点: ```html
``` - `variant === 'live'`:LIVE 角标 + `source` + 更多按钮(`#i-more`) - `variant === 'video'`:`duration` + 下载按钮(`#i-download`) 网格容器 class(`live-media-grid` / `media-grid`)仍在 `MediaView`,不进组件。 ## 页面改造 ### AlarmsView ```html
暂无告警
``` - `load` / `handle` / 指标 computed / 侧栏 bars 不变 - 可用小函数或直接逐 prop 绑定;**禁止**把 resolve API 塞进组件 ### MediaView ```html
``` - tabs、load、download、路由 `view` query 不变 ## 样式 - 组件 **不加** 会改变视觉的 scoped 新规则 - 继续依赖全局 `prototype.css` 中: - `.alarm-item` 及相关 - `.live-media-grid` / `.media-grid` / `.media-visual` / `.media-card-copy` / `.live-corner` / `.media-duration` 等 - 若为消除 Vue 属性继承告警需 `inheritAttrs`,不得改 class 语义 ## 文件清单 | 动作 | 路径 | |------|------| | 新增 | `src/components/AlarmItem.vue` | | 新增 | `src/components/MediaCard.vue` | | 修改 | `src/views/AlarmsView/AlarmsView.vue` | | 修改 | `src/views/MediaView/MediaView.vue` | ## 实现顺序 1. **A** — `AlarmItem` + `AlarmsView` 接入;单独 commit 2. **B** — `MediaCard` + `MediaView` 接入;单独 commit 3. **C** — 浏览器冒烟:告警列表/处理按钮;媒体直播卡/视频卡播放与操作 建议 commit message: - `refactor: 抽取 AlarmItem 告警列表项组件` - `refactor: 抽取 MediaCard 媒体网格卡组件` ## 验收标准 1. Alarms 页:列表渲染、空态、处理确认流与 resolve 成功刷新仍可用 2. Media 页:直播/视频 tab、卡数量、播放/更多/下载行为与抽离前一致 3. DOM:仍为 `article.alarm-item` / 媒体 `article > .media-visual + .media-card-copy` 4. 无控制台 error;不回归 Monitor / Devices / Tasks 5. 不修改 `prototype.css`(本阶段无必要删除/搬迁) ## 风险与后续 | 风险 | 处理 | |------|------| | 漏绑 class 导致样式掉 | 对照现模板逐字段复制;冒烟看截图 | | emit 丢上下文 | 页面 `@handle="handle(a)"` 闭包带 id | | 过早抽象 | 明确禁止 BusinessCard;Monitor 另阶段 | **后续(不在本 spec)**:Monitor `DockDeviceCard`;Tasks `RouteCard`;可选 CSS 迁 scoped。 ## 约束 - 工作目录:`/Users/qingyuan/CodeProject/laic-frontend` - 不改后台 - 不 `git add -A`;按文件精确 add + 中文 commit - 跳过全量单测;以页面冒烟为准