# 网络设备管理平台

## 项目概述

这是网络设备管理平台的前端项目，用于在地铁线路运管中心检测和查看各车站网络设备的详细数据、运行情况、异常告警，并提供分析、统计、日志和权限管理能力。

主要设备类型：

- 摄像机
- 网络录像机
- 交换机
- 解码器
- 智能安防箱
- 媒体服务器
- 视频服务器
- 网络键盘
- 报警主机

## 技术栈

- 包管理：pnpm
- 构建工具：Vite
- 前端框架：Vue 3
- 语言：TypeScript
- 路由：Vue Router
- 组件库：Naive UI
- 状态管理：Pinia + pinia-plugin-persistedstate
- 服务端状态/轮询：TanStack Vue Query
- 本地持久化：localStorage、sessionStorage、IndexedDB/localforage
- 网络请求：axios
- 实时消息：STOMP/WebSocket（`@stomp/stompjs`）
- 图表：ECharts
- 图标：lucide-vue-next
- 样式：Sass

## 环境与脚本

### 运行环境

- Node.js：`^20.19.0 || >=22.12.0`
- pnpm：以 `package.json` 中 `packageManager` 为准

### 常用命令

```bash
pnpm install      # 安装依赖
pnpm dev          # 启动开发服务，默认端口 9763
pnpm build        # 类型检查 + Vite 构建 + 构建产物压缩
pnpm preview      # 预览构建产物
pnpm build-only   # 仅执行 Vite 构建
pnpm type-check   # 执行 vue-tsc 类型检查
pnpm lint         # 执行 ESLint，并带 --fix
pnpm format       # 使用 Prettier 格式化 src/
```

当前项目未配置测试脚本，也未发现测试文件；不要声称已运行单元测试。需要验证改动时，优先运行 `pnpm type-check`、`pnpm lint`、`pnpm build` 中与改动相关的命令。

### 构建流程

`pnpm build` 的实际流程为：

1. `tsx build/pre-build.ts`：根据 `package.json` 的版本和构建时间写入 `public/manifest.json`。
2. `vue-tsc --build`：类型检查。
3. `vite build`：生成 `dist/`。
4. `tsx build/post-build.ts`：基于 `dist/` 生成 `.zip`、`.tar`、`.tar.gz` 压缩包。

压缩包命名格式为：`ndm-web-platform_v<version>_<YYMMDD-HHmmss>`。

## 目录结构

项目源码集中在 `src/`：

```text
src/
  apis/                    # 接口客户端、接口模型、业务请求封装
  components/              # 业务组件与全局组件
    device/
    global/
    permission/
    station/
  composables/             # 组合式函数
    alarm/
    common/
    device/
    permission/
    query/                 # TanStack Query 轮询与请求编排
    station/
    stomp/                 # STOMP/WebSocket 客户端
  constants/               # 常量
  enums/                   # 枚举
  helpers/                 # 辅助逻辑
  layouts/
    app-layout.vue         # 登录后主布局
  pages/                   # 页面
  plugins/                 # Pinia 持久化等插件
  router/
    index.ts               # 路由配置与守卫
  stores/                  # Pinia stores
  styles/                  # 全局样式
  types/                   # 全局/工具类型
  utils/                   # 通用工具函数
```

路径别名：`@/*` 指向 `src/*`。

## 页面与路由

路由配置在 `src/router/index.ts`。登录页独立于主布局；除 `/login` 外，其余页面都作为 `src/layouts/app-layout.vue` 的子路由。

```text
src/
  router/
    index.ts
  layouts/
    app-layout.vue
  pages/
    login/
      login-page.vue                 # 登录页，对应 /login
    station/
      station-page.vue               # 车站状态页/首页，对应 /station
    device/
      device-page.vue                # 设备诊断页，对应 /device
    alarm/
      alarm-log-page.vue             # 设备告警记录，对应 /alarm/alarm-log
      alarm-ignore-page.vue          # 告警忽略管理，对应 /alarm/alarm-ignore
    log/
      vimp-log-page.vue              # 视频平台日志，对应 /log/vimp-log
      call-log-page.vue              # 上级调用日志，对应 /log/call-log
    permission/
      permission-page.vue            # 权限管理，对应 /permission
    system/
      changelog/
        changelog-page.vue           # 更新记录，对应 /changelog
      error/
        not-found-page.vue           # 404 页面，对应 catch-all
```

路由守卫规则：

- 未登录访问非 `/login` 页面会跳转到 `/login`。
- 已登录访问 `/login` 会跳转到 `/`。
- `/` 默认重定向到 `/station`。
- `/permission` 需要 `useUserStore().isLamp` 为真，否则跳转到 404。

## 数据轮询与状态管理

由于后端服务按车站分布，前端需要向各车站服务依次请求数据。项目采用“单点驱动 + 变更监听 + 级联触发”的轮询模式。

核心文件位于 `src/composables/query/`：

- `use-line-stations-query.ts`：查询所有车站，是业务轮询入口。
- `use-user-permission-query.ts`：查询并计算当前用户在各车站的权限，负责调度后续设备/告警查询。
- `use-line-devices-query.ts`：查询设备数据。
- `use-line-alarms-query.ts`：查询告警数据。
- `use-verify-user-query.ts`：用户登录/校验相关请求。
- `use-version-check-query.ts`：版本检查，依赖构建阶段生成的 `/manifest.json`。

关键 Pinia stores 位于 `src/stores/`：

- `user.ts`：用户登录态、Token、用户类型等。
- `station.ts`：车站数据。
- `device.ts`：设备数据。
- `alarm.ts`：告警数据。
- `permission.ts`：权限数据。
- `setting.ts`：系统设置、调试开关、网络开关等。
- `polling.ts`：轮询状态控制。
- `unread.ts`：未读状态。

持久化注意事项：

- 大体量业务数据会使用 IndexedDB/localforage。
- 普通设置类状态会使用 localStorage/sessionStorage。
- `src/main.ts` 会比较 `VITE_STORAGE_VERSION` 与本地 `ndm-storage-version`，不一致时清空 localStorage 并清空 localforage。

## 接口与代理

接口相关代码位于 `src/apis/`：

- `client/`：HTTP 客户端基础封装。
- `domain/`：领域相关类型/逻辑。
- `model/`：接口模型。
- `request/`：按业务拆分的请求函数。

开发代理配置在 `vite.config.ts`：

- 开发服务端口：`9763`。
- 已配置多个线路/站点前缀代理，包括 01、02、04、10、21 相关站点。
- 当前配置包含 `/api`、`/minio`、`/ws` 等代理项。
- `ProxyItem.rewrite` 用于将本地请求前缀改写为后端真实路径，例如将 `/1001/api` 改写为 `/api`。

修改代理时，应同步检查 `key`、`target`、`rewrite`、`ws` 是否匹配实际环境。

## 环境变量

项目使用 Vite 环境变量，当前变量集中在 `.env`。文档或回答中只列变量名和用途，不要复述真实密钥、密码或授权值。

常见变量：

- `VITE_APP_TITLE`：页面标题。
- `VITE_REQUEST_INTERVAL`：轮询间隔，单位秒。
- `VITE_NDM_APP_KEY`：网管 appKey。
- `VITE_LAMP_CLIENT_ID`：LAMP clientId。
- `VITE_LAMP_CLIENT_SECRET`：LAMP clientSecret。
- `VITE_LAMP_USERNAME`：LAMP 登录用户名。
- `VITE_LAMP_PASSWORD`：LAMP 登录密码。
- `VITE_LAMP_AUTHORIZATION`：已有 Authorization 时直接使用，否则由 clientId/clientSecret 生成。
- `VITE_STORAGE_VERSION`：本地缓存版本，用于触发缓存清理。
- `VITE_DEBUG_CODE`：调试模式授权码。

## 调试模式与离线开发

调试模式默认隐藏，用于开发、联调和故障排查。

开启方式：

1. 使用快捷键 `Ctrl + Alt + D` 唤起验证弹窗。
2. 输入 `VITE_DEBUG_CODE` 对应授权码。
3. 验证通过后，“系统设置”中会显示调试分组。

调试相关能力：

- 显示设备原始数据。
- 控制是否轮询车站。
- 控制是否主动请求。
- 控制是否订阅 STOMP/WebSocket 消息。
- 启用模拟用户。
- 允许在特定场景下直接操作本地 IndexedDB。

离线开发：

- 如果浏览器已有现场缓存，可在调试模式中关闭轮询、主动请求和消息订阅，直接查看本地缓存。
- 全新环境可在登录页控制台设置 `window.$mockUser.value = true` 进入模拟登录，再通过调试面板导入 `docs/data/` 下的数据：
  - `ndm-station-store.json`
  - `ndm-device-store.json`
  - `ndm-alarm-store.json`

## 代码风格与约定

- 遵循现有 Vue SFC、TypeScript、组合式函数和 Pinia 写法。
- 新增业务请求时优先放入 `src/apis/request/` 对应业务分类。
- 新增页面时同步更新 `src/router/index.ts`，并保持 `src/pages/` 目录与路由语义一致。
- 新增共享逻辑优先放入 `src/composables/`、`src/helpers/` 或 `src/utils/`，不要在页面中堆积重复逻辑。
- 新增全局/业务组件时优先放入 `src/components/` 对应分类。
- 使用 `@/` 引用 `src/` 下模块。
- 不要在代码、文档或回复中泄露真实密码、Token、Authorization 或现场地址以外的敏感信息。

格式化配置来自 `.prettierrc.json`：

- LF 换行
- 2 空格缩进
- 单引号
- 使用分号
- `trailingComma: all`
- `printWidth: 200`

ESLint 重点规则：

- `@typescript-eslint/no-unused-vars` 为 warn。
- `@typescript-eslint/no-explicit-any` 当前关闭，但新增代码仍应尽量保持类型清晰。
- `vue/multi-word-component-names` 当前关闭。

## 协作规则

1. 默认不要直接修改项目代码；当用户明确授权修改时，只修改授权范围内的文件。
2. 修改前先阅读相关文件和既有实现，避免凭空猜测目录、接口或状态结构。
3. 修改后说明改了哪些文件、为什么改、如何验证。
4. 文档类修改至少重新读取目标文件确认内容正确。
5. 代码类修改应按影响范围运行 `pnpm type-check`、`pnpm lint`、`pnpm build` 或更小范围的可用验证命令。
6. 不要提交 Git commit，除非用户明确要求。
7. 不要删除失败测试或通过压制类型错误来规避问题。
8. 不要在最终说明中声称执行了未实际执行的命令。
