26 KiB
系统设计文档
本文档旨在详细阐述环境监督系统(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 进行异步处理,具备响应式编程能力,以提升高并发场景下的性能。其清晰的分层和模块化设计也为未来向微服务架构演进奠定了良好基础。
后端分层架构图
@startuml
package "Backend Architecture" {
[Controller Layer] <<Spring @RestController>>
[Service Layer] <<Spring @Service>>
[Repository Layer] <<Custom Persistence>>
[Controller Layer] --> [Service Layer]
[Service Layer] --> [Repository Layer]
}
@enduml
1.1.3 前端架构
前端应用是一个基于 Vue 3 的单页面应用(SPA),使用 Vite 作为构建工具。选择Vue 3是因为其优秀的性能、丰富的生态系统和渐进式的学习曲线。
- UI组件库: Element Plus,提供了一套高质量、符合设计规范的UI组件,加速了界面的开发。
- 状态管理: Pinia,作为Vue 3官方推荐的状态管理库,它提供了极简的API和强大的类型推断支持,能有效管理复杂的应用状态。
- 路由管理: Vue Router,负责管理前端页面的跳转和路由。
1.2 功能模块划分
系统在功能上被划分为一系列高内聚的模块,每个模块负责一块具体的业务领域。这种划分方式便于团队分工和独立开发。
| 核心模块 | 主要职责 | 关键功能点 |
|---|---|---|
| 认证与授权模块 | 管理所有用户的身份认证和访问权限 | - 用户注册/登录/登出 - JWT令牌生成与验证 - 密码重置 - 基于角色的访问控制(RBAC) |
| 用户与人员管理模块 | 维护系统中的所有用户账户及其信息 | - 用户信息的增、删、改、查 - 用户角色分配与变更 - 用户状态管理(激活/禁用) |
| 反馈管理模块 | 处理来自外部和内部的环境问题反馈 | - 接收公众/认证用户的反馈 - 集成AI进行内容预审核 - 人工审核与处理 - 反馈状态跟踪与统计 |
| 任务管理模块 | 对具体工作任务进行全生命周期管理 | - 从反馈创建任务 - 任务分配给网格员 - 任务状态(分配、执行、完成)跟踪 - 任务审核与结果归档 |
| 网格与地图模块 | 对地理空间进行网格化管理,并提供路径支持 | - 地理网格的定义与划分 - 网格员与网格的关联 - A*寻路算法服务,优化任务路径 |
| 决策支持模块 | 为管理层提供数据洞察和可视化报告 | - 核心业务指标(KPI)统计 - AQI、任务完成率等数据的可视化 - 生成反馈热力图 |
| 个人中心模块 | 为登录用户提供个性化的信息管理和查询功能 | - 查看/修改个人资料 - 查询个人提交历史 - 查看个人操作日志 |
功能模块图
@startuml
left to right direction
actor User
rectangle "环境监督系统 (EMS)" {
User -- (认证与授权模块)
(认证与授权模块) ..> (用户与人员管理模块) : 依赖
User -- (反馈管理模块)
(反馈管理模块) ..> (任务管理模块) : 创建任务
(任务管理模块) ..> (网格与地图模块) : 路径规划
(任务管理模块) ..> (用户与人员管理模块) : 分配任务
(决策支持模块) .up.> (反馈管理模块) : 数据分析
(决策支持模块) .up.> (任务管理模块) : 数据分析
User -- (个人中心模块)
}
@enduml
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.1.3 用户与人员管理模块
该模块为系统的权限管理和组织架构提供了基础。
- 主要控制器:
PersonnelController - 核心服务:
UserAccountService,OperationLogService - 关键DTO:
UserCreationRequest,UserUpdateRequest,UserRoleUpdateRequest - 设计要点:
- 提供了对用户账户的完整CRUD操作。
- 实现了用户角色和状态的精细化管理。
- 所有关键操作均通过
OperationLogService记录日志,便于审计和追踪。
2.1.4 网格与地图模块
该模块是系统实现区域化、网格化管理的核心。
- 主要控制器:
GridController,MapController - 核心服务:
GridService,PathfindingService - 设计要点:
- 支持对地理区域进行灵活的网格化定义,并可将网格标记为障碍。
- 实现了网格与网格员的关联管理。
- 核心亮点是集成了
PathfindingService,该服务封装了A*寻路算法,为任务路径规划提供支持。
2.2 类和对象的设计
本节定义了系统核心业务对象的静态结构,即类图。
2.2.1 UserAccount 类图
@startuml
class UserAccount {
- Long id
- String name
- String phone
- String email
- String password
- Gender gender
- Role role
- UserStatus status
- Integer gridX
- Integer gridY
+ isValid()
}
enum Gender {
MALE
FEMALE
OTHER
}
enum Role {
ADMIN
SUPERVISOR
GRID_WORKER
}
enum UserStatus {
ACTIVE
INACTIVE
}
UserAccount *-- Gender
UserAccount *-- Role
UserAccount *-- UserStatus
@enduml
2.2.2 Feedback 类图
@startuml
class Feedback {
- Long id
- String eventId
- String title
- PollutionType pollutionType
- SeverityLevel severityLevel
- FeedbackStatus status
- Long submitterId
+ process()
+ approve()
}
enum PollutionType {
AIR
WATER
SOIL
NOISE
}
enum SeverityLevel {
LOW
MEDIUM
HIGH
CRITICAL
}
enum FeedbackStatus {
PENDING_REVIEW
AI_REJECTED
PROCESSED
}
Feedback *-- PollutionType
Feedback *-- SeverityLevel
Feedback *-- FeedbackStatus
@enduml
2.2.3 Task 类图
@startuml
class Task {
- Long id
- Long feedbackId
- Long assigneeId
- Long createdBy
- TaskStatus status
- String title
+ assignTo(workerId)
+ complete()
+ approve()
}
enum TaskStatus {
CREATED
ASSIGNED
IN_PROGRESS
SUBMITTED
APPROVED
REJECTED
}
Task *-- TaskStatus
@enduml
2.2.4 Grid 和 Assignment 类图
@startuml
class Grid {
- Long id
- Integer gridX
- Integer gridY
- String cityName
- boolean isObstacle
}
class Assignment {
- Long id
- Long taskId
- Long assignerId
- AssignmentStatus status
- String remarks
- LocalDateTime assignmentTime
}
enum AssignmentStatus {
PENDING
ACCEPTED
REJECTED
}
Assignment *-- AssignmentStatus
@enduml
2.3 动态模型设计
本节描述了系统在运行时,对象之间的交互行为。
2.3.1 核心时序图
用户登录认证时序图
sequenceDiagram
participant User as 用户
participant AuthController as 认证控制器
participant AuthService as 认证服务
participant JwtUtil as JWT工具
User->>AuthController: POST /api/auth/login (email, password)
AuthController->>AuthService: signIn(LoginRequest)
AuthService->>AuthService: 验证凭证
alt 验证成功
AuthService->>JwtUtil: generateToken(user)
JwtUtil-->>AuthService: 返回JWT令牌
AuthService-->>AuthController: 返回JwtAuthenticationResponse
AuthController-->>User: 200 OK (token)
else 验证失败
AuthService-->>AuthController: 抛出AuthenticationException
AuthController-->>User: 401 Unauthorized
end
反馈提交与处理时序图
sequenceDiagram
participant User as 用户
participant FeedbackController as 反馈控制器
participant FeedbackService as 反馈服务
participant EventPublisher as 事件发布器
participant FeedbackAiReviewService as AI审核服务
User->>FeedbackController: POST /api/feedback/submit
FeedbackController->>FeedbackService: submitFeedback(request, files)
FeedbackService->>EventPublisher: publishEvent(FeedbackSubmittedEvent)
FeedbackService-->>FeedbackController: 返回初步响应
Controller-->>User: 201 Created
EventPublisher-->>FeedbackAiReviewService: 异步触发AI审核
FeedbackAiReviewService->>FeedbackService: updateFeedbackStatus(AI_REVIEWED)
主管分配任务时序图
sequenceDiagram
participant Supervisor as 主管
participant TaskMgmtController as 任务管理控制器
participant TaskService as 任务服务
participant AssignmentService as 分配服务
participant NotificationService as 通知服务
Supervisor->>TaskMgmtController: POST /tasks/{taskId}/assign (workerId)
TaskMgmtController->>TaskService: assignTask(taskId, workerId)
TaskService->>AssignmentService: createAssignment(task, worker)
AssignmentService-->>TaskService: 返回Assignment
TaskService->>TaskService: 更新任务状态为ASSIGNED
TaskService->>NotificationService: notifyWorker(workerId, taskId)
TaskService-->>TaskMgmtController: 分配成功
TaskMgmtController-->>Supervisor: 200 OK
2.3.2 核心状态图
反馈状态机 (Feedback Status)
@startuml
state "待审核" as PENDING_REVIEW
state "AI审核通过" as AI_APPROVED
state "AI拒绝" as AI_REJECTED
state "已处理" as PROCESSED
state "已关闭" as CLOSED
[*] --> PENDING_REVIEW : 提交反馈
PENDING_REVIEW --> AI_APPROVED : AI审核通过
PENDING_REVIEW --> AI_REJECTED : AI审核拒绝
AI_APPROVED --> PROCESSED : 主管创建任务
PROCESSED --> CLOSED : 任务完成
AI_REJECTED --> CLOSED : 归档
@enduml
任务状态机 (Task Status)
@startuml
state "已创建" as CREATED
state "已分配" as ASSIGNED
state "进行中" as IN_PROGRESS
state "已提交" as SUBMITTED
state "已批准" as APPROVED
state "已拒绝" as REJECTED
[*] --> CREATED : 创建任务
CREATED --> ASSIGNED : 分配给网格员
ASSIGNED --> IN_PROGRESS : 网格员接受任务
IN_PROGRESS --> SUBMITTED : 网格员完成并提交
SUBMITTED --> APPROVED : 主管审核通过
SUBMITTED --> REJECTED : 主管审核拒绝
REJECTED --> ASSIGNED : 重新分配
APPROVED --> [*]
@enduml
2.4 算法与策略设计
2.4.1 A* 寻路算法
- 目的: 为网格员规划从当前位置到任务目标点的最优(最短或最快)路径。
- 输入:
startNode: 起始点坐标。endNode: 目标点坐标。grid: 包含障碍物信息的地图网格数据。
- 核心逻辑:
- 维护一个开放列表(
openList)和一个关闭列表(closedList)。 - 从
openList中选取F值(G值+H值)最小的节点作为当前节点。- G值: 从起点到当前节点的实际代价。
- H值: 从当前节点到终点的预估代价(启发函数,通常使用曼哈顿距离或欧氏距离)。
- 遍历当前节点的相邻节点,如果邻居不在
closedList中且不是障碍物,则计算其G值和H值,并将其加入openList。 - 重复此过程,直到当前节点为目标节点,或
openList为空。
- 维护一个开放列表(
- 输出: 从起点到终点的一系列坐标点,即规划好的路径。
- 应用: 在
PathfindingController中通过/api/pathfinding/find接口暴露。
2.4.2 任务分配策略
- 目的: 在多个可用网格员中,为新任务选择最合适的执行者。
- 核心逻辑: 这是一个复合策略,综合考虑以下因素,并计算加权得分:
- 地理位置优先: 优先选择任务所在网格或邻近网格的网格员。
- 负载均衡: 优先选择当前进行中任务数量最少的网格员。
- 技能匹配: (未来扩展)可根据任务需要的技能(
skills字段)与网格员的技能进行匹配。 - 任务优先级: 对于高优先级任务,可以适当放宽地理位置限制,确保有可用人员处理。
- 应用: 在
TaskAssignmentService中实现,当主管触发自动分配或系统基于反馈自动创建任务时调用。
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 |
任务截止日期 |