代码整合

This commit is contained in:
2026-07-28 21:38:48 +08:00
parent 9d447346ad
commit 96f0f69ac3
57 changed files with 2802 additions and 876 deletions
+124 -93
View File
@@ -1,118 +1,145 @@
# 数据治理看板 Vue3 版
本目录是原版数据治理看板的 Vue3 升级版本。原版 `indexV2.html`、`res/` 和 `server.js` 保持不变,Vue3 版可独立开发和构建,并保持既有接口参数、业务口径、外部页签参数和 1920×1080 大屏布局。
本目录是原数据治理看板的 Vue3 重构版本,可独立开发、测试和构建。项目保持原有接口协议、业务口径、外部页签参数和 1920×1080 大屏布局;上级目录中的 `indexV2.html`、`res/` 与旧版脚本不受影响。
## 技术栈
- Vue 3 + TypeScript + Vite:组件化开发、类型检查和静态构建。
- Pinia:集中管理筛选条件、监控数据、项目详情和穿透弹窗状态。
- Vue Router:集团、公司、项目三级哈希路由。
- ECharts:柱状图和折线图按需加载,Canvas 渲染。
- Vitest:数据适配和业务口径单元测试。
| 分类 | 技术 | 当前版本 | 用途 |
|------|------|----------|------|
| 视图 | Vue | 3.5.39 | Composition API、`<script setup>` 与响应式渲染 |
| 状态 | Pinia | 3.0.4 | 筛选、监控、项目详情和穿透状态 |
| 路由 | Vue Router | 5.1.0 | 集团、企业、项目三级哈希路由 |
| 构建 | Vite | 8.1.4 | 开发服务、代理与生产构建 |
| 类型 | TypeScript | 5.9.3 | 严格类型检查与 ViewModel 约束 |
| 图表 | ECharts | 6.1.0 | 柱状图、折线图和 Canvas 渲染 |
| 单元测试 | Vitest | 4.1.10 | Adapter、Store 和纯函数测试 |
| 组件测试 | Vue Test Utils | 2.4.6 | Vue 组件渲染与事件测试 |
| 端到端测试 | Playwright | 1.55.1 | 路由、筛选、接口拦截与大屏截图验证 |
## 项目架构
## 架构概览
### 分层关系
项目采用 feature-first 目录,将业务能力、共享基础设施和应用装配分开。页面只读取稳定 ViewModel,不直接兼容接口的 PascalCase/camelCase 字段。
```mermaid
flowchart LR
A[App 应用壳层] --> B[Router 路由页面]
B --> C[Pinia Dashboard Store]
C --> D[HTTP Service]
D --> E[同源网关 /qhse_webapi]
E --> F[数据治理接口]
C --> G[Adapter 数据适配]
G --> H[稳定 ViewModel]
H --> B
B --> I[业务组件]
I --> J[ECharts 生命周期组件]
A[App.vue 与 Router] --> B[页面与布局]
B --> C[页面 composable]
C --> D[特性 Setup Store]
D --> E[特性 API]
E --> F[共享 HTTP Client]
F --> G[同源网关 /qhse_webapi]
G --> H[数据治理接口]
D --> I[Adapter]
I --> J[稳定 ViewModel]
J --> B
B --> K[共享 UI 与图表组件]
```
数据读取遵循单向链路:页面触发 Store Action,Service 请求接口,Adapter 将原始响应转换为 ViewModel,Store 更新状态后由 Vue 响应式刷新页面。页面组件不直接兼容后端字段别名,也不直接持有认证令牌。
### 目录职责
### 目录结构
```text
next/
├─ src/
│ ├─ adapters/ 接口原始数据到 ViewModel 的转换及口径测试
│ ├─ components/ KPI、指标列表、ECharts 和全局穿透弹窗
│ ├─ config/ 接口路径、外链、系统枚举和报告文件映射
│ ├─ router/ 集团、公司、项目三级路由
│ ├─ services/ 请求参数、超时、取消、请求 ID 和错误处理
│ ├─ stores/ 筛选、监控数据、项目数据和弹窗状态
│ ├─ styles/ Vue3 版增量样式
│ ├─ types/ API、ViewModel、筛选和弹窗类型
│ ├─ views/ 集团级、公司级、项目级页面
│ ├─ App.vue 大屏壳层、筛选、面包屑和缩放
│ └─ main.ts Vue、Pinia、Router 和样式入口
├─ vite.config.ts 开发服务器和接口代理
├─ tsconfig.json TypeScript 配置
└─ package.json 依赖和工程命令
│ ├─ api/ HTTP 客户端、端点定义和特性 API
│ ├─ assets/styles/next.css Vue3 版本增量样式
│ ├─ components/
│ │ ├─ base/EChart.vue 通用 ECharts 生命周期组件
│ │ └─ features/ 监控和穿透业务展示组件
│ ├─ composables/ 页面生命周期和跨 Store 操作
│ ├─ layouts/DashboardLayout.vue 应用壳层、大屏缩放、筛选和导航
│ ├─ pages/ 集团、企业、项目路由页面
│ ├─ router/index.ts 三级哈希路由与页面懒加载
│ ├─ stores/ 筛选、监控、项目、穿透四个 Setup Store
│ ├─ types/ API、ViewModel 和业务类型
│ ├─ utils/
│ │ ├─ adapters/ 原始接口到 ViewModel 的转换
│ │ ├─ charts/ 各特性的纯图表 option 构造函数
│ │ └─ dashboardConfig.ts 系统、外链和报告文件配置
│ ├─ App.vue 根组件
│ ├─ main.ts Vue、Pinia、Router 和样式入口
│ └─ vite-env.d.ts Vite 环境变量类型声明
├─ e2e/ Playwright 主流程测试
├─ .env.example 环境变量模板
├─ playwright.config.ts E2E 配置
├─ vitest.config.ts 单元和组件测试配置
├─ vite.config.ts 开发服务器与接口代理
└─ package.json 依赖和工程命令
```
`main.ts` 会引入上级 `res/css/` 中的原版模块化样式作为视觉基线,Vite 构建时会将这些 CSS 合并进 `dist/assets/`。Vue3 专属修正放在 `src/styles/next.css`,禁止修改或重新聚合原版 CSS 文件。
### 状态边界
### 页面与路由
| Store | 职责 |
|-------|------|
| `useFilterStore` | `system`、`dimension`、`allowedSystems` 及接口 `type/range` 映射 |
| `useMonitoringStore` | 集团/企业监控数据、当前单位、加载和错误状态 |
| `useProjectStore` | 项目详情 ViewModel、加载和错误状态 |
| `useDrilldownStore` | 弹窗、指标穿透、动不动报告及各自请求状态 |
| 层级 | 路由 | 页面职责 |
`useMonitoringPage` 和 `useProjectPage` 监听路由参数及筛选状态。参数变化或组件销毁时会取消旧请求;各 Store 同时使用请求序号,避免失效响应覆盖最新状态。
### Adapter 与 ViewModel
- `monitoringAdapter.ts`:集团/企业汇总、单位、项目、指标、趋势和动不动报告。
- `projectAdapter.ts`:项目信息与项目指标历史值。
- `drilldownAdapter.ts`:集团单位分析和企业项目指标穿透。
- 页面模板禁止读取 `MetricProjectInfo`、`ProjectMetrics` 等原始接口字段。
- 图表 option 由 `utils/charts` 下的纯函数生成,`components/base/EChart.vue` 只管理实例生命周期、更新、尺寸监听和销毁。
## 页面与参数
| 层级 | 路由 | 主要内容 |
|------|------|----------|
| 集团级 | `#/` | 集团 KPI、重点指标、三率趋势、企业分析、报告入口、指标穿透 |
| 公司级 | `#/enterprise/:unitId` | 公司 KPI、三率趋势、项目分析、公司指标穿透 |
| 项目级 | `#/project/:unitId/:projectId` | 项目信息、指标历史值、异常状态 |
| 集团 | `#/` | KPI、重点指标、三率趋势、企业分析、报告与集团指标穿透 |
| 企业 | `#/enterprise/:unitId` | 企业 KPI、趋势、项目分析和企业指标穿透 |
| 项目 | `#/project/:unitId/:projectId` | 项目信息、指标历史值和异常状态 |
外部系统的页签参数位于哈希前,例如 `?type=1,2#/`。参数映射保持原规则:`1` 为安全、`2` 为质量、`3` 为应急;未传或传入非法值时展示全部系统。
外部页签参数必须位于哈希前,例如 `?type=1,2#/`:
### 状态管理
- `type=1`:安全。
- `type=2`:质量。
- `type=3`:应急。
- `type=1,2`:安全和质量。
- 未传或值无效:显示全部系统。
`stores/dashboardStore.ts` 是唯一业务状态入口,主要状态分为:
本版本严格保留当前界面的 70% 未达标阈值和现有文案;如调整为其他业务口径,需要同步 Adapter、页面文案和测试。
- 筛选状态:`system`、`dimension`、`allowedSystems`。
- 监控状态:集团或当前公司的 `monitoring`、`loading`、`error`。
- 项目状态:`projectData`、`projectLoading`、`projectError`。
- 穿透状态:`dialog`、`selectedMetric`、`metricAnalysis`、`metricLoading`。
- 指标列表弹窗:集团和企业复用 `allMetrics`,使用率低于 70% 的指标显示红色告警卡片。
- 动不动报告状态:`moveReport`、`moveReportLoading`、`moveReportError`。
## 接口约定
集团和公司监控共用 `loadMonitoring`。新请求开始时会取消旧请求,并通过递增请求序号阻止旧响应覆盖最新筛选结果。项目详情和指标穿透分别使用独立 Action,避免页面组件自行维护请求状态。
接口前缀为 `/qhse_webapi/api/DataGovernance`:
### 接口与数据适配
| 接口 | 用途 |
|------|------|
| `GetMetricMonitoringSituation` | 集团监控 |
| `GetUnitMetricMonitoringSituation` | 企业监控 |
| `GetGroupMetricAnalysis` | 集团指标穿透 |
| `GetUnitMetricAnalysis` | 企业指标穿透 |
| `GetProjectMonitoringSituation` | 项目详情 |
| `GetGroupMoveReportMetricData` | 动不动报告动态指标列 |
| `GetGroupMetricAnalysisMoveReport` | 动不动报告企业数据 |
所有接口使用同源前缀 `/qhse_webapi/api/DataGovernance`:
集团监控请求即使没有单位也必须保留 `unitId=`。指标穿透参数继续使用后端既有拼写 `filed`,不要自行更名。
- `GetMetricMonitoringSituation`:集团监控。
- `GetUnitMetricMonitoringSituation`:公司监控。
- `GetGroupMetricAnalysis`:集团指标穿透。
- `GetGroupMoveReportMetricData`:动不动报告动态指标列,`type=0/1` 分别对应安全/质量。
- `GetGroupMetricAnalysisMoveReport`:动不动报告企业行,`range=0/1` 分别对应所有项目/新开工项目。
- `GetUnitMetricAnalysis`:公司指标穿透。
- `GetProjectMonitoringSituation`:项目详情。
集团监控接口要求查询字符串始终包含 `unitId=`,即使值为空也不能省略。`services/http.ts` 因此只过滤 `undefined`,显式空字符串会被保留。
`adapters/dashboardAdapter.ts` 负责兼容 PascalCase/camelCase 字段、非法数字、布尔字符串和空数组,并集中维护上线率口径:
上线率兜底计算口径为:
```text
(已关联项目数 + 预立项项目数) / (主数据项目数 + 预立项项目数 - 申请不用项目数)
```
组件只能读取适配后的 ViewModel。新增或调整接口字段时,应先修改 `types/` 和 `adapters/`,不要在 Vue 模板中增加字段兼容分支。
## 环境变量
动不动报告由两个接口共同组成:指标定义接口决定动态列顺序和中文名称,企业行接口通过 `MetricAnalysis[].Field` 绑定每列使用率。若指标定义接口临时返回空字段,适配层会使用当前监控接口的指标名称兜底,并对重复 `Field` 去重,避免生成空表头或重复列。
安装依赖后创建本地配置:
### 图表与大屏布局
```powershell
Copy-Item .env.example .env.local
```
`components/EChart.vue` 统一负责 ECharts 初始化、响应式更新、`ResizeObserver` 监听和 `dispose`。当前只注册柱状图、折线图、网格、图例、提示框和 Canvas 渲染器。
设置浏览器端接口 token:
页面按照 1920×1080 设计尺寸渲染,由 `App.vue` 等比缩放到实际窗口。趋势图宽度跟随面板;项目和企业数量较多的柱状图使用动态最小宽度和横向滚动,避免柱体被强制压缩。
```dotenv
VITE_QHSE_API_TOKEN=实际令牌
```
### 安全与部署边界
- 浏览器只访问同源 `/qhse_webapi/`,由开发服务器或生产网关转发到正式接口。
- 接口 token 固定在 `config/dashboardConfig.ts`,由 `services/http.ts` 写入每个请求的 `token` 请求头。
- token 会进入浏览器构建产物,只适用于当前受控内网部署环境。
- 生产环境仍需将 `/qhse_webapi/` 反向代理到 `https://qhse.cncecoa.com/qhse_webapi`,但无需在网关重复注入 token。
- 网关应配置上游超时、请求 ID 透传、访问日志和 5xx 告警。
该变量由 Vite 在构建期注入,最终会进入浏览器构建产物,仅适用于当前受控内网部署模式。不要提交真实生产 token。
## 本地开发
@@ -121,33 +148,37 @@ npm install
npm run dev
```
访问 `http://127.0.0.1:18081/`。外部页签参数仍支持 `?type=1`、`?type=2`、`?type=3` 和 `?type=1,2`。
默认地址:<http://127.0.0.1:18081/>。
## 测试
开发服务会把 `/qhse_webapi` 转发到 `https://qhse.cncecoa.com`。生产环境也必须配置相同的同源反向代理;应用使用哈希路由,不需要 SPA history fallback。
## 测试与构建
```powershell
# Adapter、Store 和组件测试
npm run test
# TypeScript 与 Vue 模板检查
npm run typecheck
```
当前单元测试重点覆盖接口字段归一化、上线率口径、空数据、非法数字和布尔字符串。页面结构或交互调整后,还需要在浏览器验证集团、公司、项目三级路由以及统计和指标穿透弹窗。
## 构建与部署
```powershell
# 生产构建
npm run build
# 集团、企业、项目路由和外部页签主流程
npm run test:e2e
```
产物位于 `dist/`,可部署到静态 Web 服务。生产环境需要由同源网关代理 `/qhse_webapi/`;token 已由前端请求头携带。
本地 Playwright 默认使用系统 Edge 通道,CI 使用标准 Chromium。E2E 通过接口拦截运行,不访问正式数据,并在 1920×1080 视口生成集团页面截图。
建议网关同时配置 12 秒上游超时、请求 ID 透传、访问日志和 5xx 告警。应用采用哈希路由,无需 Web 服务器配置 SPA history fallback。
构建产物位于 `dist/`。当前 ECharts 独立懒加载块约 535 kB,Vite 会提示大块告警,但不影响构建和运行。
## 开发约定
- 新接口先在 `config/dashboardConfig.ts` 注册,再通过 `services/http.ts` 请求。
- 后端响应必须先经过 `adapters/`,页面不得直接依赖原始字段命名。
- 跨页面状态进入 Pinia;仅组件内部使用的展示状态保留在组件中。
- 通用展示提取到 `components/`,集团、公司、项目编排保留在 `views/`。
- 图表必须复用 `EChart.vue`,不要在页面中直接创建实例。
- 样式优先复用原版 CSS 类;Vue3 增量样式只添加到 `styles/next.css`。
- 修改后至少执行 `npm run test` 和 `npm run build`。
- 新页面放入 `pages`,页面专属展示组件放入 `components/features/<name>`,跨页面基础能力放入 `components/base`、`utils` 或 `api`。
- Store 使用 Setup Store;异步 action 必须维护 loading、error、取消和竞态保护。
- 接口响应先转换为 ViewModel,页面和共享 UI 不得直接依赖原始字段。
- 页面 composable 负责连接路由、筛选和 Store,并在作用域销毁时清理副作用。
- 通用组件使用 props/emits,不读取业务 Store;弹窗等业务组件留在所属特性。
- 图表统一复用 `components/base/EChart.vue`,页面不得直接创建或销毁 ECharts 实例。
- 原版模块化 CSS 继续作为视觉基线,Vue3 增量样式只写入 `src/assets/styles/next.css`。
- 修改后至少执行 `npm run test`、`npm run typecheck` 和 `npm run build`;涉及路由或交互时还需执行 `npm run test:e2e`。