Files
Environment-Monitoring-System/Report/系统设计_v3.md
ChuXun 02a830145e 1
2025-10-25 19:18:43 +08:00

252 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 系统设计文档
本文档旨在详细阐述环境监督系统EMS的系统架构、功能模块和实现细节为开发、测试和维护提供指导。
## 1. 总体设计
总体设计旨在从宏观上描述系统的架构、设计原则和核心组成部分,为后续的详细设计奠定基础。
### 1.1 系统架构设计
#### 1.1.1 架构选型与原则
本系统采用业界成熟的 **前后端分离** 架构。该架构将用户界面(前端)与业务逻辑处理(后端)彻底分离,二者通过定义良好的 **RESTful API** 进行通信。这种模式的优势在于:
- **并行开发**: 前后端团队可以并行开发、测试和部署只需遵守统一的API约定从而显著提升开发效率。
- **技术栈灵活性**: 前后端可以独立选择最适合自身场景的技术栈,便于未来对任一端进行技术升级或重构。
- **关注点分离**: 前端专注于用户体验和界面呈现,后端专注于业务逻辑、数据处理和系统安全,使得系统各部分职责更清晰,更易于维护。
在架构设计中,我们遵循了以下核心原则:
- **高内聚,低耦合**: 将相关功能组织在独立的模块中,并最小化模块间的依赖。
- **可扩展性**: 架构设计应能方便地横向扩展(增加更多服务器实例)和纵向扩展(增加新功能模块)。
- **安全性**: 从设计之初就考虑认证、授权、数据加密和输入验证等安全问题。
- **可维护性**: 采用清晰的代码分层、统一的编码规范和完善的文档,降低长期维护成本。
#### 1.1.2 后端架构
后端服务基于 **Spring Boot 3****Java 17** 构建,这是一个现代化、高性能的组合。其内部采用了经典的三层分层架构模式:
- **表现层 (Controller Layer)**: 负责接收前端的HTTP请求使用 `@RestController` 定义RESTful API。此层负责解析HTTP请求、验证输入参数使用JSR-303注解并调用业务逻辑层处理请求但不包含任何业务逻辑。
- **业务逻辑层 (Service Layer)**: 系统的核心,使用 `@Service` 注解。它封装了所有的业务规则、流程控制和复杂计算。它通过调用数据访问层来操作数据,并通过事件发布等机制与其他服务进行解耦交互。
- **数据访问层 (Repository/Persistence Layer)**: 负责与数据存储进行交互。本项目独创性地采用了一套基于JSON文件的持久化方案。通过自定义的`JsonStorageService`和一系列Repository类模拟了类似JPA的接口实现了对`users.json`, `tasks.json`等核心数据文件的增删改查CRUD操作。选择JSON文件存储简化了项目的部署和配置特别适合快速迭代和中小型应用场景。
此架构同时利用了 **Spring WebFlux** 进行异步处理,具备响应式编程能力,以提升高并发场景下的性能。其清晰的分层和模块化设计也为未来向微服务架构演进奠定了良好基础。
![后端分层架构图](https://www.plantuml.com/plantuml/svg/SoWkIImgAStDuG8oX1An24dCoKnELT2gKiX8p-L8AawncdNa5A2gY2pDoN820000)
#### 1.1.3 前端架构
前端应用是一个基于 **Vue 3** 的单页面应用SPA使用 **Vite** 作为构建工具。选择Vue 3是因为其优秀的性能、丰富的生态系统和渐进式的学习曲线。
- **UI组件库**: **Element Plus**提供了一套高质量、符合设计规范的UI组件加速了界面的开发。
- **状态管理**: **Pinia**作为Vue 3官方推荐的状态管理库它提供了极简的API和强大的类型推断支持能有效管理复杂的应用状态。
- **路由管理**: **Vue Router**,负责管理前端页面的跳转和路由。
### 1.2 功能模块划分
系统在功能上被划分为一系列高内聚的模块,每个模块负责一块具体的业务领域。这种划分方式便于团队分工和独立开发。
| 核心模块 | 主要职责 | 关键功能点 |
| ------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| **认证与授权模块** | 管理所有用户的身份认证和访问权限 | - 用户注册/登录/登出<br>- JWT令牌生成与验证<br>- 密码重置<br>- 基于角色的访问控制(RBAC) |
| **用户与人员管理模块** | 维护系统中的所有用户账户及其信息 | - 用户信息的增、删、改、查<br>- 用户角色分配与变更<br>- 用户状态管理(激活/禁用) |
| **反馈管理模块** | 处理来自外部和内部的环境问题反馈 | - 接收公众/认证用户的反馈<br>- 集成AI进行内容预审核<br>- 人工审核与处理<br>- 反馈状态跟踪与统计 |
| **任务管理模块** | 对具体工作任务进行全生命周期管理 | - 从反馈创建任务<br>- 任务分配给网格员<br>- 任务状态(分配、执行、完成)跟踪<br>- 任务审核与结果归档 |
| **网格与地图模块** | 对地理空间进行网格化管理,并提供路径支持 | - 地理网格的定义与划分<br>- 网格员与网格的关联<br>- **A\*寻路算法**服务,优化任务路径 |
| **决策支持模块** | 为管理层提供数据洞察和可视化报告 | - 核心业务指标KPI统计<br>- AQI、任务完成率等数据的可视化<br>- 生成反馈热力图 |
| **个人中心模块** | 为登录用户提供个性化的信息管理和查询功能 | - 查看/修改个人资料<br>- 查询个人提交历史<br>- 查看个人操作日志 |
![功能模块图](https://www.plantuml.com/plantuml/svg/XLD1Jy5358xXF-S5wGgNkgRD1s2aD2gbzEd-Lgy_8QduTqb2lC_A5gYXaIikIeylC-yS339vj2vj-1e9z9oY-Oq9kGSpT8T5yPiU5sO1rKqpwXWkGZJ9G8P7k9y5Zt9B1pZ2b7h93e0b8B8pX78sYcQ6G2vE_uHlGgC0)
## 2. 详细设计
### 2.1 功能模块详细设计
本章节将对核心功能模块的内部设计进行更深入的阐述。
#### 2.1.1 反馈管理模块
该模块是系统与用户交互的核心,负责处理所有环境问题的上报和初步处理。
- **主要控制器**: `FeedbackController`, `PublicController`
- **核心服务**: `FeedbackService`, `FeedbackAiReviewService`
- **关键DTO**: `FeedbackSubmissionRequest`, `FeedbackResponseDTO`, `ProcessFeedbackRequest`
- **设计要点**:
- 采用 `@RequestPart` 同时接收JSON数据和文件上传实现了富文本内容的反馈提交。
- 通过发布 `FeedbackSubmittedForAiReviewEvent` 事件将AI审核流程解耦并异步化提高了API的响应速度。
- 提供了强大的多条件动态查询能力,支持按状态、类型、严重等级、地理位置和时间范围进行组合过滤。
#### 2.1.2 任务管理模块
该模块负责将已批准的反馈转化为具体的可执行任务,并对其进行全生命周期管理。
- **主要控制器**: `TaskManagementController`, `TaskAssignmentController`, `GridWorkerTaskController`
- **核心服务**: `TaskService`, `TaskAssignmentService`
- **关键DTO**: `TaskCreationRequest`, `TaskDetailDTO`, `TaskAssignmentRequest`, `TaskSummaryDTO`
- **设计要点**:
- 清晰的状态机管理任务的生命周期CREATED → ASSIGNED → IN_PROGRESS → SUBMITTED → APPROVED/REJECTED
- 任务分配逻辑考虑了网格员的地理位置和当前负载,旨在实现智能化的高效分配。
- 为主管和网格员提供了完全独立的API端点严格分离了不同角色的操作权限。
### 2.2 类和对象的设计
本节定义了系统核心业务对象的静态结构,即类图。
#### 2.2.1 `Feedback` 类图
`Feedback` 对象是系统中最核心的数据模型之一,代表一次环境问题反馈。
![Feedback Class Diagram](https://www.plantuml.com/plantuml/svg/VP1DJy8n48Rl-HH5s9Y2dAnAEoiT3qajR_GAnWmaGZDIyB9n-Oa9e6iY2p9oPQuAU1y8jAY8576d1gtP7Z6sZY8DkTGVKgI9gL1pCBP_O2Cudn-ex3lVgoqHhq9wHlDMXe8pY5pT5VdqzImeD-eXoVxuFOyO1jD4dfhWh6uiofWKbv0GgXg9T8nK0gWzYlBv4AAYk2f7uVoqioIp2kXyG-uTQ2tD_oT_Eeyc2hXv8ALa2iYtHAg4g5KzGv-pB2c_X9vR-y9o5m00)
### 2.3 动态模型设计
本节描述了系统在运行时,对象之间的交互行为。
#### 2.3.1 核心时序图
**反馈提交与处理时序图**
该图展示了从用户提交反馈到系统创建任务的完整交互流程。
```mermaid
sequenceDiagram
participant User as 用户
participant FeedbackController as 反馈控制器
participant FeedbackService as 反馈服务
participant EventPublisher as 事件发布器
participant FeedbackAiReviewService as AI审核服务
participant TaskService as 任务服务
User->>FeedbackController: POST /api/feedback/submit
FeedbackController->>FeedbackService: submitFeedback(request, files)
FeedbackService->>EventPublisher: publishEvent(FeedbackSubmittedEvent)
FeedbackService-->>FeedbackController: 返回初步响应
FeedbackController-->>User: 201 Created
EventPublisher-->>FeedbackAiReviewService: 异步触发
FeedbackAiReviewService->>FeedbackAiReviewService: 调用火山引擎AI分析
FeedbackAiReviewService->>FeedbackService: updateFeedbackStatus(AI_REVIEWED)
Supervisor->>FeedbackService: approveFeedback(feedbackId)
FeedbackService->>TaskService: createTaskFromFeedback(feedback)
TaskService-->>FeedbackService: 任务创建成功
```
#### 2.3.2 核心状态图
**反馈状态机 (Feedback Status)**
![Feedback Status Diagram](https://www.plantuml.com/plantuml/svg/LOrDIy5058xXF-S5wGgNkgRD1s2aD2oXzE9-Lgy_8kduTqbWlC_A5gYvaWMLR-yY_YoHqC1f9YpT9opT9ooHqC1f-HpX-A_p9t9oY-Gq9kGSpTgEBAoC1IayWjMDaIqjLMa2b7h95t9h93t0b8B8p_DoYcQ6G2vE_uHlGgC0)
### 2.4 算法设计
#### 2.4.1 A* 寻路算法
- **目的**: 为网格员规划从当前位置到任务目标点的最优(最短或最快)路径。
- **输入**:
- `startNode`: 起始点坐标。
- `endNode`: 目标点坐标。
- `grid`: 包含障碍物信息的地图网格数据。
- **核心逻辑**:
1. 维护一个开放列表(`openList`)和一个关闭列表(`closedList`)。
2.`openList` 中选取F值G值+H值最小的节点作为当前节点。
- G值: 从起点到当前节点的实际代价。
- H值: 从当前节点到终点的预估代价(启发函数,通常使用曼哈顿距离或欧氏距离)。
3. 遍历当前节点的相邻节点,如果邻居不在`closedList`中且不是障碍物则计算其G值和H值并将其加入`openList`
4. 重复此过程,直到当前节点为目标节点,或`openList`为空。
- **输出**: 从起点到终点的一系列坐标点,即规划好的路径。
- **应用**: 在`PathfindingController`中通过`/api/pathfinding/find`接口暴露。
### 2.5 数据持久化设计
系统不使用传统数据库所有数据均以JSON文件的形式存储在服务器的文件系统中。每个核心模型对应一个JSON文件。这种设计简化了部署但也对数据一致性和并发控制提出了更高的要求。
#### 2.5.1 `users.json` - 用户账户数据
| 字段名 | JSON数据类型 | 约束/说明 | 描述 |
| --------------------- | ----------------- | ------------------------ | ---------------------------------------- |
| `id` | `Number` | **唯一标识**, 自增 | 用户的唯一标识符 |
| `name` | `String` | 非空 | 用户姓名 |
| `phone` | `String` | 非空, **唯一** | 手机号码,可用于登录 |
| `email` | `String` | 非空, **唯一** | 电子邮箱,可用于登录 |
| `password` | `String` | 非空, 长度>=8 | 加密后的用户密码 |
| `gender` | `String` | (ENUM) | 性别 (MALE, FEMALE, OTHER) |
| `role` | `String` | (ENUM) | 用户角色 (ADMIN, SUPERVISOR, GRID_WORKER等) |
| `status` | `String` | 非空, (ENUM) | 账户状态 (ACTIVE, INACTIVE, SUSPENDED) |
| `grid_x` | `Number` | | 关联的网格X坐标 (主要用于网格员) |
| `grid_y` | `Number` | | 关联的网格Y坐标 (主要用于网格员) |
| `region` | `String` | | 所属区域或地区 |
| `level` | `String` | (ENUM) | 用户等级 (JUNIOR, SENIOR, EXPERT) |
| `skills` | `Array` | | 技能列表 (JSON数组格式的字符串) |
| `enabled` | `Boolean` | 非空, 默认 `true` | 账户是否启用 |
| `current_latitude` | `Number` | | 当前纬度坐标 (用于实时定位) |
| `current_longitude` | `Number` | | 当前经度坐标 (用于实时定位) |
| `failed_login_attempts` | `Number` | 默认 `0` | 连续失败登录次数 |
| `lockout_end_time` | `String` | | 账户锁定截止时间 |
| `created_at` | `String` | 非空 | 记录创建时间 |
| `updated_at` | `String` | 非空 | 记录最后更新时间 |
#### 2.5.2 `feedback.json` - 环境问题反馈数据
| 字段名 | JSON数据类型 | 约束/说明 | 描述 |
| ---------------- | --------------- | ------------------------ | ---------------------------------------- |
| `id` | `Number` | **唯一标识**, 自增 | 反馈的唯一标识符 |
| `event_id` | `String` | 非空, **唯一** | 人类可读的事件ID |
| `title` | `String` | 非空 | 反馈标题 |
| `description` | `String` | | 问题详细描述 |
| `pollution_type` | `String` | 非空, (ENUM) | 污染类型 (AIR, WATER, SOIL, NOISE) |
| `severity_level` | `String` | 非空, (ENUM) | 严重程度 (LOW, MEDIUM, HIGH, CRITICAL) |
| `status` | `String` | 非空, (ENUM) | 反馈状态 (PENDING_REVIEW, PROCESSED等) |
| `text_address` | `String` | | 文字描述的地址 |
| `grid_x` | `Number` | | 事发地网格X坐标 |
| `grid_y` | `Number` | | 事发地网格Y坐标 |
| `latitude` | `Number` | | 事发地纬度 |
| `longitude` | `Number` | | 事发地经度 |
| `submitter_id` | `Number` | 外键 (FK) -> users.id (可为空) | 提交者ID (公众提交时可为空) |
| `created_at` | `String` | 非空 | 记录创建时间 |
| `updated_at` | `String` | 非空 | 记录最后更新时间 |
#### 2.5.3 `tasks.json` - 任务数据
| 字段名 | JSON数据类型 | 约束/说明 | 描述 |
| ---------------- | --------------- | ------------------------ | ---------------------------------------- |
| `id` | `Number` | **唯一标识**, 自增 | 任务的唯一标识符 |
| `feedback_id` | `Number` | 外键 (FK) -> feedback.id (可为空) | 关联的原始反馈ID |
| `assignee_id` | `Number` | 外键 (FK) -> users.id (可为空) | 任务执行人网格员ID |
| `created_by` | `Number` | 外键 (FK) -> users.id | 任务创建人主管ID |
| `status` | `String` | 非空, (ENUM) | 任务状态 (PENDING, IN_PROGRESS, COMPLETED) |
| `title` | `String` | | 任务标题 |
| `description` | `String` | | 任务详细描述 |
| `pollution_type` | `String` | (ENUM) | 污染类型 |
| `severity_level` | `String` | (ENUM) | 严重程度 |
| `text_address` | `String` | | 任务地点文字描述 |
| `grid_x` | `Number` | | 任务地点网格X坐标 |
| `grid_y` | `Number` | | 任务地点网格Y坐标 |
| `latitude` | `Number` | | 任务地点纬度 |
| `longitude` | `Number` | | 任务地点经度 |
| `assigned_at` | `String` | | 任务分配时间 |
| `completed_at` | `String` | | 任务完成时间 |
| `created_at` | `String` | 非空 | 记录创建时间 |
| `updated_at` | `String` | 非空 | 记录最后更新时间 |
| `deadline` | `String` | | 任务截止日期 |
#### 2.5.4 `grids.json` - 业务网格数据
| 字段名 | JSON数据类型 | 约束/说明 | 描述 |
| --------------- | --------------- | ------------------- | ---------------------------------- |
| `id` | `Number` | **唯一标识**, 自增 | 网格的唯一标识符 |
| `gridx` | `Number` | | 网格X坐标 |
| `gridy` | `Number` | | 网格Y坐标 |
| `city_name` | `String` | | 所属城市 |
| `district_name` | `String` | | 所属区县 |
| `description` | `String` | | 网格描述信息 |
| `is_obstacle` | `Boolean` | 默认 `false` | 是否为障碍物(如禁区) |
#### 2.5.5 `assignments.json` - 任务分配记录数据
| 字段名 | JSON数据类型 | 约束/说明 | 描述 |
| ---------------- | --------------- | ------------------------ | -------------------------- |
| `id` | `Number` | **唯一标识**, 自增 | 分配记录的唯一标识符 |
| `task_id` | `Number` | 非空, 外键 (FK) -> tasks.id | 关联的任务ID |
| `assigner_id` | `Number` | 非空, 外键 (FK) -> users.id | 分配者主管ID |
| `status` | `String` | 非空, (ENUM) | 分配状态 |
| `remarks` | `String` | | 分配备注 |
| `assignment_time`| `String` | 非空 | 分配时间 |
| `deadline` | `String` | | 任务截止日期 |
```