Skip to content

feat(aiot): 设备台账 UI/UX 优化 — 引入产品/分组导航树 + 服务端分页 #4

@ronger-x

Description

@ronger-x

Umbrella PRD

具体实现 Issue 已拆分到对应子仓库,本 Issue 作为跟踪入口。

子仓库 Issue

仓库 Issue 范围
rymcu/mortise-aiot rymcu/mortise-aiot#13 后端:分页筛选 API + 统计计数 API
rymcu/admin-aiot rymcu/admin-aiot#2 前端:导航树 + 页面重构 + 跨页面联动

问题陈述

当前设备台账页面(/aiot/devices)是一个扁平的设备列表,存在以下体验问题:

  1. 无层级导航:产品→设备、分组→设备的关系在界面上完全没有体现。管理数百台跨品类设备时,只能靠搜索关键字定位。
  2. 无筛选能力:没有按产品、按分组、按在线/激活状态的筛选器。
  3. 客户端分页:一次性加载全部设备再前端分页,设备量大时性能差。
  4. 分组页面孤立:设备分组页面(/aiot/device-groups)与设备台账之间没有任何导航联动。
  5. 缺少概览信息:没有按产品或分组展示设备数量统计。

解决方案(总体)

将设备台账页面重构为 左侧导航树 + 右侧设备表格 的 master-detail 布局(类阿里云 IoT 控制台风格)。

左侧导航树面板

  • 顶部 Tab 切换两种视图:「按产品」和「按分组」。
  • 按产品视图:以产品为根节点,展示该产品下的设备数量。点击产品节点,右侧过滤显示该产品下的设备。顶部「全部设备」节点显示所有设备。
  • 按分组视图:以设备分组为根节点(支持层级),展示该分组下的设备数量。支持「未分组」虚拟节点显示不属于任何分组的设备。
  • 树节点显示:名称 + 设备计数 badge。

右侧设备表格

  • 表格顶部工具栏:
    • 面包屑导航:显示当前筛选路径(如 "全部设备 > 温度传感器")。
    • 状态快速筛选:全部 / 在线 / 离线 / 待激活。
    • 搜索框、刷新、新建设备、批量导入。
    • 服务端分页替代客户端分页。
    • 空状态优化:按当前筛选条件给出有意义的提示。

交叉导航

  • 设备分组页面增加「查看设备」按钮,跳转到设备台账并自动选中对应分组。
  • 设备详情面板中的产品归属和所属分组可点击跳转。

用户故事

  1. 作为设备管理员,我希望能按产品分类浏览设备,以便快速定位某一品类下的所有设备。
  2. 作为设备管理员,我希望能按设备分组浏览设备,以便按业务场景管理设备。
  3. 作为设备管理员,我希望能一目了然地看到每个产品/分组下有多少台设备,以便掌握整体设备分布。
  4. 作为设备管理员,我希望能快速筛选在线/离线/待激活设备,以便及时发现异常设备。
  5. 作为设备管理员,我希望从设备分组页面能一键跳转到该组设备列表,避免手动重复搜索。
  6. 作为设备管理员,在设备量大(数千台)时,我希望分页请求由服务端完成,保证页面响应速度。
  7. 作为设备管理员,我希望当前筛选路径以面包屑方式显示,便于理解当前视图范围并快速返回上级。

实现决策

后端变更

新增 API

  1. 设备列表分页 + 筛选 API

    • 接口:GET /admin/aiot/devices
    • 查询参数:productId、groupId、activationStatus、onlineStatus、keyword、pageNum、pageSize
    • 返回:分页结果(records + total + pageNum + pageSize)
    • note:groupId 筛选需 JOIN aiot_device_group_member
  2. 设备统计计数 API

    • GET /admin/aiot/devices/count-by-product — 返回 [{productId, count}]
    • GET /admin/aiot/devices/count-by-group — 返回 [{groupId, count}](含未分组数量)

模块层面

  • Service 层新增 listDevices(DeviceQuery query) 分页查询方法。
  • 通过 MyBatisFlex QueryWrapper 动态组装查询条件。
  • 统计接口单独走聚合查询,避免 N+1。

前端变更

页面布局重构

  • devices.vue 从单一表格重构为左右双面板布局。
  • 左侧面板:独立子组件 DeviceTreePanel.vue(≤300 行),包含 Tab 切换 + 树渲染。
  • 右侧面板:增强的表格,增加面包屑和状态筛选。
  • 布局:CSS Grid/Flex,左侧固定宽度 280px,右侧自适应。

新增组件

  • device/TreePanel.vue — 左侧导航树面板。

新增 Composable

  • useDeviceListQuery — 封装设备分页查询逻辑。
  • useDeviceTreeNavigation — 封装树节点选择、视图切换、计数加载逻辑。

交叉导航

  • device-groups.vue 增加「查看设备」操作按钮,使用 navigateTo('/aiot/devices?groupId=XXX')
  • devices.vue 通过 useRoute().query 读取初始筛选参数。

不需要的变更

  • 不需要新建后端模块,所有变更在 mortise-aiot 现有子模块内完成。
  • 不需要数据库 Schema 变更(关联关系已存在)。
  • 不需要修改菜单配置。

测试决策

  • Service 层分页查询方法需要单元测试,覆盖多条件组合筛选。
  • 统计接口的聚合查询需要集成测试验证 SQL 正确性。
  • 前端组件级别依赖手动验证(树面板切换、筛选联动、面包屑路径)。
  • 参考 mortise-aiot-applicationmortise-aiot-infra 中现有测试模式。

垂直切片拆分

切片 1:后端分页筛选 API

切片 2:后端设备统计计数 API

  • 覆盖的用户故事:#3
  • 验收标准:
    • GET /admin/aiot/devices/count-by-product 返回正确的每产品设备数
    • GET /admin/aiot/devices/count-by-group 返回正确的每分组设备数(含未分组)
  • 依赖关系:无

切片 3:前端导航树面板组件

切片 4:设备台账页面布局重构 + 联动

切片 5:跨页面导航联动

  • 覆盖的用户故事:PRD: AIoT 管理后台体验优化 Phase 2(Umbrella) #5
  • 验收标准:
    • 设备分组页面「查看设备」按钮跳转到 /aiot/devices?groupId=XXX
    • 设备台账自动切换到分组视图并选中对应节点
    • 设备详情面板中的产品、分组标签可点击跳转
  • 依赖关系:依赖切片 4

范围外

  • 设备分组的 CRUD 管理(已在分组页面完成)。
  • 产品管理页面(产品来自 mortise-product 模块,本次仅读取)。
  • 设备拓扑图或地图视图。
  • 导出设备列表功能。
  • 设备批量操作(批量激活、批量退役等)。
  • 移动端适配。

补充说明

  • DeviceGroup 实体已有 parentId 字段,支持层级分组树,但当前 API 未暴露层级关系。需后端在列表 API 中包含 parentId 并前端递归构建树。
  • 现有 useDeviceModelProducts composable 已有加载产品列表能力,可直接复用于产品树视图。
  • 现有 AdminPagedTableCard 组件可继续在右侧使用,但分页逻辑需切换为服务端分页模式。

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions