madhav3289/CDRN
GitHub: madhav3289/CDRN
基于 React 和 Spring Boot 构建的全栈实时社区灾难响应平台,提供多角色协同仪表盘、GPS 事件上报和 WebSocket 实时调度功能。
Stars: 0 | Forks: 0
# CDRN — 社区灾难响应网络
一个具有针对市民、志愿者和政府官员的基于角色仪表盘的全栈实时灾难响应平台。使用 React、Spring Boot、PostgreSQL 和 WebSocket (STOMP) 构建。
## 截图
### 登录 — 角色选择
使用任意手机号注册,选择您的角色(市民 / 志愿者 / 政府官员),并使用 OTP `123456`。

### 市民仪表盘
按类型、描述和 GPS 坐标报告事件。一键发送紧急 SOS。接收实时广播警报。


### 政府官员仪表盘
全面操作视图:实时事件地图 (OpenStreetMap)、事件表格、志愿者任务分配、广播警报以及活跃的 SOS 请求。


### 志愿者仪表盘
实时查看已分配的任务。随着工作进展更新任务状态。

## 架构
```
┌─────────────┐ REST + WS ┌──────────────┐ JPA ┌────────────┐
│ React App │ ◄────────────► │ Spring Boot │ ◄───────► │ PostgreSQL │
│ (Port 3000)│ │ (Port 8080) │ │ (Port 5432)│
└─────────────┘ └──────────────┘ └────────────┘
```
## 技术栈
| 层级 | 技术 |
|-----------|---------------------------------------------------|
| 前端 | React 18, React Router v6, Axios, Leaflet |
| 后端 | Spring Boot 3.2, Spring Security, Spring WebSocket|
| 数据库 | PostgreSQL 16 |
| 实时通信 | 基于 SockJS WebSocket 的 STOMP |
| 地图 | 通过 react-leaflet 接入的 OpenStreetMap |
| 认证 | 基于 OTP 登录并使用 JWT token |
## 前置条件
| 工具 | 版本 |
|------|---------|
| Java (JDK) | 17+ (在 Java 25 上测试) |
| Maven | 3.8+ |
| Node.js | 18+ |
| npm | 9+ |
| PostgreSQL | 14+ |
## 设置与运行
### 1. PostgreSQL — 创建数据库
```
psql -U postgres
CREATE DATABASE cdrn;
\q
```
表将在首次运行时由 JPA 自动创建 (`spring.jpa.hibernate.ddl-auto=update`)。
后端期望的默认凭据 (`application.properties`):
```
Host: localhost:5432
Database: cdrn
Username: postgres
Password: postgres
```
如有需要,请在 [backend/src/main/resources/application.properties](backend/src/main/resources/application.properties) 中进行修改。
### 2. 后端
```
cd backend
mvn clean install -DskipTests
mvn spring-boot:run
```
启动于 **http://localhost:8080**。首次启动会自动创建所有表。
### 3. 前端
```
cd frontend
npm install
npm start
```
启动于 **http://localhost:3000** 并会自动在浏览器中打开。
## 认证
认证基于 OTP。在开发环境中,任何手机号的 OTP 始终为 **`123456`**。
### 登录流程
1. 输入手机号 + 姓名(适用于新帐户)+ 角色
2. 点击 **发送 OTP**
3. 输入 `123456`
4. 您将被重定向至对应角色的仪表盘
### 角色选择
注册时(首次使用手机号登录),请选择以下角色之一:
| 角色 | 仪表盘 | 权限 |
|------|-----------|--------------|
| **CITIZEN** | `/citizen` | 报告事件、发送 SOS、查看警报 |
| **VOLUNTEER** | `/volunteer` | 查看和更新已分配的任务 |
| **AUTHORITY** | `/authority` | 地图视图、分配任务、发送警报、查看 SOS |
## API 参考
### 认证 — 无需 token
| 方法 | 端点 | 请求体 | 描述 |
|--------|----------|------|-------------|
| POST | `/api/auth/send-otp` | `{ phone }` | 请求 OTP |
| POST | `/api/auth/verify-otp` | `{ phone, otp, name?, role? }` | 验证 OTP,获取 JWT 和用户信息 |
### 事件 — 需要 token
| 方法 | 端点 | 请求体 | 描述 |
|--------|----------|------|-------------|
| POST | `/api/incident/report` | `{ type, description, latitude, longitude }` | 报告事件 |
| GET | `/api/incident/all` | — | 列出所有事件 |
### SOS — 需要 token
| 方法 | 端点 | 请求体 | 描述 |
|--------|----------|------|-------------|
| POST | `/api/sos/request` | `{ latitude, longitude }` | 发送 SOS |
| GET | `/api/sos/all` | — | 列出所有 SOS 请求 |
### 任务 — 需要 token
| 方法 | 端点 | 请求体 | 描述 |
|--------|----------|------|-------------|
| POST | `/api/task/assign` | `{ volunteerId, incidentId }` | 分配任务 (仅限 AUTHORITY) |
| PUT | `/api/task/update` | `{ taskId, status }` | 更新任务状态 (仅限 VOLUNTEER) |
| GET | `/api/task/my` | — | 当前用户的任务 |
| GET | `/api/task/volunteer/{id}` | — | 特定志愿者的任务 |
### 警报 — 需要 token
| 方法 | 端点 | 请求体 | 描述 |
|--------|----------|------|-------------|
| POST | `/api/alert/send` | `{ message }` | 广播警报 (仅限 AUTHORITY) |
| GET | `/api/alert/all` | — | 列出所有警报 |
### 用户 — 需要 token
| 方法 | 端点 | 请求体 | 描述 |
|--------|----------|------|-------------|
| GET | `/api/users/volunteers` | — | 列出所有 VOLUNTEER 用户 |
| PUT | `/api/users/{id}/role` | `{ role }` | 更新用户角色 |
## WebSocket
使用 SockJS + STOMP 连接到 `ws://localhost:8080/ws`。
| 主题 | 触发时机 |
|-------|-----------|
| `/topic/incidents` | 报告新事件时 |
| `/topic/alerts` | 发送警报或触发 SOS 时 |
| `/topic/tasks` | 分配任务或更新状态时 |
## 项目结构
```
CDRN/
├── README.md
├── backend/
│ ├── pom.xml
│ └── src/main/
│ ├── java/com/cdrn/backend/
│ │ ├── BackendApplication.java
│ │ ├── config/
│ │ │ ├── CorsConfig.java # CorsConfigurationSource bean
│ │ │ ├── SecurityConfig.java # Spring Security + JWT filter chain
│ │ │ ├── JwtAuthFilter.java # Bearer token extraction
│ │ │ ├── JwtUtil.java # Token generation & validation
│ │ │ └── WebSocketConfig.java # STOMP endpoint config
│ │ ├── controller/ # REST endpoints
│ │ ├── dto/ # Request / Response DTOs
│ │ ├── model/ # JPA entities (User, Incident, Task, Alert, SosRequest)
│ │ ├── repository/ # Spring Data JPA repositories
│ │ └── service/ # Business logic
│ └── resources/
│ └── application.properties
└── frontend/
├── package.json
└── src/
├── App.js # Router + protected routes
├── api.js # Axios instance with JWT interceptor
├── websocket.js # STOMP WebSocket client
├── context/AuthContext.js # Auth state (token, user, login/logout)
├── pages/
│ ├── Login.js # Two-step OTP login with role selector
│ ├── CitizenDashboard.js
│ ├── VolunteerDashboard.js
│ └── AuthorityDashboard.js
├── components/
│ ├── IncidentForm.js # Report incident form
│ ├── IncidentList.js # Incident table
│ ├── IncidentMap.js # Leaflet map with markers
│ ├── SOSButton.js # One-tap SOS
│ ├── TaskList.js # Volunteer task list
│ ├── TaskAssignForm.js # Assign task (Authority)
│ ├── AlertList.js # Live alert feed
│ └── Navbar.js
└── styles/App.css
```
## 快速测试流程
1. 启动 PostgreSQL、后端和前端
2. 打开 **http://localhost:3000**
**作为政府官员:**
- 手机号:`1111111111`,姓名:`Arnav`,角色:`Authority`,OTP:`123456`
- 查看事件地图,分配任务,发送警报
**作为市民:**
- 手机号:`2222222222`,姓名:`Madhav`,角色:`Citizen`,OTP:`123456`
- 报告事件(例如类型:FLOOD,添加坐标)
- 按下 SOS 按钮 —— 政府官员仪表盘将实时更新
- 政府官员发送的警报会出现在“实时警报”部分
**作为志愿者:**
- 手机号:`3333333333`,角色:`Volunteer`,OTP:`123456`
- 政府官员分配任务后,该任务会通过 WebSocket 立即显示在这里
- 更新任务状态以标记进度
标签:Axios, GPS定位, JPA, JS文件枚举, Leaflet, OpenStreetMap, OTP身份验证, PostgreSQL, PostgreSQL 16, RBAC, React, React 18, React Router v6, SOS报警, Spring Boot, Spring Boot 3.2, Spring Security, Spring WebSocket, STOMP, Syscalls, WebSocket, Web地图, 事件上报, 任务分配, 依赖分析, 公共安全, 公民面板, 前后端分离, 域名枚举, 基于角色的访问控制, 实时灾害管理, 实时状态更新, 实时警报广播, 实时通信, 应急管理信息系统, 志愿服务管理, 志愿者面板, 政府机构面板, 测试用例, 灾害响应网络, 社区应急响应平台, 紧急求助