Chandrasekhar711/Disaster-Management-Emergency-Alert-System-DM-EAS-
GitHub: Chandrasekhar711/Disaster-Management-Emergency-Alert-System-DM-EAS-
基于MERN栈构建的灾害管理与应急警报系统,支持市民实时上报灾害事件、SOS广播警报以及多应急机构基于地图的协同响应与调度。
Stars: 0 | Forks: 0
# 🚨 灾害管理与应急警报系统 (DM-EAS)
一个适用于生产环境的 MERN 技术栈 Web 应用程序,具备地理空间功能,用于实时灾害管理、应急响应协调和事件跟踪。
## 🌟 功能
### 核心功能
- **实时事件报告** - 市民可以上传照片/视频并附带地理位置报告灾害
- **地理空间跟踪** - 使用 MongoDB 地理空间查询查找半径内的事件
- **实时仪表盘** - 通过 WebSocket 进行实时事件更新
- **机构管理** - 警察、消防、医疗、救援协同响应
- **SOS 警报** - 关键紧急情况触发器,支持广播通知
- **分析仪表盘** - 使用 Recharts 进行事件统计和趋势分析
- **交互式地图** - 基于 Leaflet 的实时事件可视化
- **基于角色的访问控制** - 市民、机构、管理员权限
- **媒体上传** - 支持事件照片和视频
### 安全功能
- JWT 身份验证,token 有效期为 7 天
- 双重登录支持:邮箱或用户 ID
- 唯一的用户 ID 字段(4-20 个字符,字母数字 + 下划线)
- 使用 bcryptjs 进行密码哈希处理(盐因子为 10)
- 使用 express-validator 进行输入验证(前端 + 后端)
- CORS 配置
- 使用 RBAC 保护 API 路由
- 安全的错误处理及提示信息
- 不区分大小写的用户身份验证
- 做好限流准备
### UI/UX 功能
- 现代毛玻璃设计
- 流畅的 Framer Motion 动画
- Tailwind CSS 响应式布局
- 做好适配深色/浅色模式准备
- 定制的卡片和组件
- 加载骨架屏
- Toast 通知
- 响应式移动端设计
## 🏗️ 架构
### 技术栈
```
Frontend:
- React 18 with Vite
- Zustand for state management
- Socket.IO for real-time updates
- Framer Motion for animations
- Recharts for analytics
- Leaflet for maps
- Tailwind CSS for styling
Backend:
- Node.js + Express.js
- MongoDB with geospatial indexing
- Socket.IO for real-time broadcasting
- JWT for authentication
- Bcrypt for password hashing
```
### 项目结构
```
IMSD/
├── backend/
│ ├── controllers/
│ │ ├── authController.js
│ │ └── incidentController.js
│ ├── routes/
│ │ ├── authRoutes.js
│ │ └── incidentRoutes.js
│ ├── models/
│ │ ├── User.js
│ │ └── Incident.js
│ ├── middleware/
│ │ ├── auth.js
│ │ ├── errorHandler.js
│ │ └── validation.js
│ ├── services/
│ │ ├── authService.js
│ │ └── incidentService.js
│ ├── utils/
│ │ ├── tokenUtils.js
│ │ └── responseHandler.js
│ ├── config/
│ │ ├── database.js
│ │ └── socket.js
│ ├── server.js
│ ├── package.json
│ └── .env.example
│
└── frontend/
├── src/
│ ├── components/
│ │ ├── common.jsx
│ │ ├── ProtectedRoute.jsx
│ │ ├── Navbar.jsx
│ │ └── IncidentCard.jsx
│ ├── pages/
│ │ ├── LoginPage.jsx
│ │ ├── RegisterPage.jsx
│ │ ├── DashboardPage.jsx
│ │ ├── ReportIncidentPage.jsx
│ │ ├── AnalyticsPage.jsx
│ │ ├── MapPage.jsx
│ │ └── ErrorPage.jsx
│ ├── services/
│ │ ├── apiClient.js
│ │ ├── api.js
│ │ └── socket.js
│ ├── context/
│ │ └── store.js
│ ├── utils/
│ │ └── auth.js
│ ├── App.jsx
│ ├── main.jsx
│ └── index.css
├── index.html
├── vite.config.js
├── tailwind.config.js
├── postcss.config.js
├── package.json
└── .env.example
```
## 🚀 快速开始
### 前置条件
- Node.js (v16+)
- MongoDB (v4.4+)
- npm 或 yarn
### 后端配置
1. **进入后端目录**
cd backend
2. **安装依赖**
npm install
3. **创建 .env 文件**
cp .env.example .env
4. **配置环境变量**
MONGODB_URI=mongodb://localhost:27017/dm-eas
JWT_SECRET=your_jwt_secret_key_here_minimum_32_characters
PORT=5000
NODE_ENV=development
FRONTEND_URL=http://localhost:5173
5. **启动 MongoDB**
mongod
6. **运行后端服务器**
npm run dev
服务器运行在 `http://localhost:5000`
### 前端配置
1. **进入前端目录**
cd frontend
2. **安装依赖**
npm install
3. **创建 .env.local 文件**
cp .env.example .env.local
4. **配置环境变量**
VITE_API_URL=http://localhost:5000/api
VITE_SOCKET_URL=http://localhost:5000
5. **启动开发服务器**
npm run dev
应用运行在 `http://localhost:5173`
6. **构建生产环境**
npm run build
## 📝 API 文档
### 身份验证接口
#### 注册用户
```
POST /api/auth/register
Content-Type: application/json
{
"name": "John Doe",
"userId": "john_doe",
"email": "user@example.com",
"phone": "9876543210",
"password": "password123",
"role": "citizen",
"department": null
}
```
**注意**:必须提供 `userId`,长度必须为 4-20 个字符,仅支持字母数字 + 下划线。
#### 使用邮箱或用户 ID 登录
```
POST /api/auth/login
Content-Type: application/json
{
"emailOrUserId": "john_doe",
"password": "password123"
}
```
**或者使用邮箱:**
```
{
"emailOrUserId": "user@example.com",
"password": "password123"
}
```
**注意**:系统会自动检测邮箱(包含 @)或用户 ID(4-20 个字符)
#### 获取个人资料
```
GET /api/auth/profile
Authorization: Bearer
```
### 事件接口
#### 创建事件
```
POST /api/incidents
Authorization: Bearer
Content-Type: application/json
{
"title": "Building Fire",
"description": "Large fire reported at commercial building",
"type": "fire",
"severity": "critical",
"location": {
"coordinates": [77.1025, 28.7041],
"address": "123 Main Street, Delhi"
},
"media": []
}
```
#### 获取所有事件
```
GET /api/incidents?page=1&limit=10&type=fire&status=reported&severity=high
```
#### 获取附近事件
```
GET /api/incidents/nearby?longitude=77.1025&latitude=28.7041&radius=5000
```
#### 获取事件详情
```
GET /api/incidents/:id
```
#### 更新事件状态
```
PUT /api/incidents/:id/status
Authorization: Bearer
Content-Type: application/json
{
"status": "responding"
}
```
#### 指派响应人员
```
POST /api/incidents/:id/assign
Authorization: Bearer
Content-Type: application/json
{
"userId": "objectId",
"department": "fire"
}
```
#### 触发 SOS
```
POST /api/incidents/:id/sos
Authorization: Bearer
```
#### 获取统计数据
```
GET /api/incidents/stats
```
## 🔌 WebSocket 事件
### 服务端 → 客户端事件
```
// New incident created
socket.on('new-incident', (incident) => {
// Handle new incident
});
// Existing incident updated
socket.on('incident-update', (incident) => {
// Handle incident update
});
// SOS alert triggered
socket.on('sos-alert', (data) => {
// Handle SOS alert
});
// General notification
socket.on('notification', (data) => {
// Handle notification
});
```
### 客户端 → 服务端事件
```
// Join incident updates room
socket.emit('join-incident-updates');
// Join SOS alerts room
socket.emit('join-sos-alerts');
// Join live map room
socket.emit('join-live-map');
// Join global notifications room
socket.emit('join-global-notifications');
// Subscribe to user-specific updates
socket.emit('subscribe-user', userId);
// Send notification
socket.emit('send-notification', { message: 'Alert!' });
```
## 🗄️ MongoDB Schema
### User Schema
```
{
name: String,
userId: String (unique, 4-20 chars, alphanumeric + underscore),
email: String (unique),
phone: String,
password: String (hashed with bcryptjs),
role: 'citizen' | 'authority' | 'admin',
department: 'police' | 'fire' | 'medical' | 'rescue' | 'civil_defense',
location: { type: Point, coordinates: [longitude, latitude] },
address: String,
isVerified: Boolean,
isActive: Boolean,
profileImage: String,
bio: String,
incidentsReported: [ObjectId],
incidentsAssigned: [ObjectId],
createdAt: Date,
updatedAt: Date
}
```
### Incident Schema
```
{
title: String,
description: String,
type: 'flood' | 'fire' | 'accident' | 'earthquake' | 'hazard' | 'other',
status: 'reported' | 'verified' | 'responding' | 'resolved' | 'cancelled',
severity: 'low' | 'medium' | 'high' | 'critical',
location: {
type: Point,
coordinates: [longitude, latitude],
address: String
},
media: [{
url: String,
type: 'image' | 'video',
uploadedAt: Date
}],
reportedBy: ObjectId (User),
verifiedBy: ObjectId (User),
assignedTo: [{
userId: ObjectId,
department: String,
assignedAt: Date
}],
responders: [ObjectId],
comments: [{
author: ObjectId,
text: String,
createdAt: Date
}],
isSOS: Boolean,
sosTriggeredAt: Date,
sosTriggeredBy: ObjectId,
viewCount: Number,
affectedPeople: Number,
estimatedDamage: 'minimal' | 'moderate' | 'severe' | 'catastrophic',
resolutionNotes: String,
resolvedAt: Date,
priority: Number,
createdAt: Date,
updatedAt: Date
}
```
## 🔐 基于角色的访问控制
### 市民角色
- 报告事件
- 查看公开事件
- 为事件添加评论
- 触发 SOS
- 查看个人资料
### 机构角色(已验证)
- 所有市民权限
- 验证事件
- 更新事件状态
- 指派响应人员
- 查看分析数据
- 访问受保护的 endpoint
### 管理员角色
- 所有权限
- 用户管理
- 机构验证
- 系统管理
- 完整的分析数据访问权限
## 🧪 测试演示账号
```
Citizen Account:
User ID: demo_citizen
Email: citizen@demo.com
Password: password123
Authority Account:
User ID: demo_officer
Email: officer@demo.com
Password: password123
Admin Account:
User ID: admin_user
Email: admin@demo.com
Password: password123
Login Options:
- Use User ID (e.g., demo_citizen)
- Use Email (e.g., citizen@demo.com)
System automatically detects which format is being used
```
## 📊 API 响应示例
### 创建事件响应
```
{
"success": true,
"message": "Incident reported successfully",
"data": {
"_id": "507f1f77bcf86cd799439011",
"title": "Building Fire",
"description": "Large fire at commercial building",
"type": "fire",
"status": "reported",
"severity": "critical",
"location": {
"type": "Point",
"coordinates": [77.1025, 28.7041],
"address": "123 Main Street, Delhi"
},
"reportedBy": {
"_id": "507f1f77bcf86cd799439012",
"name": "John Doe",
"email": "john@example.com"
},
"createdAt": "2024-02-19T10:30:00Z"
}
}
```
### 获取事件响应
```
{
"success": true,
"message": "Incidents retrieved successfully",
"data": [
{
"_id": "507f1f77bcf86cd799439011",
"title": "Building Fire",
"description": "Large fire at commercial building",
"type": "fire",
"status": "verified",
"severity": "critical",
"isSOS": false,
"location": {
"coordinates": [77.1025, 28.7041],
"address": "123 Main Street, Delhi"
},
"reportedBy": {
"name": "John Doe"
},
"createdAt": "2024-02-19T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 45,
"pages": 5,
"hasNextPage": true,
"hasPrevPage": false
}
}
```
## 🛠️ 开发
### 后端开发
```
cd backend
npm run dev # Start with nodemon
npm start # Start production build
```
### 前端开发
```
cd frontend
npm run dev # Start Vite dev server
npm run build # Build for production
npm run preview # Preview production build
```
## 📦 部署
### 后端部署 (Heroku/Railway)
1. 推送代码到 Git 仓库
2. 在托管平台上设置环境变量
3. 部署到托管平台
4. 需要 MongoDB Atlas 连接字符串
### 前端部署 (Vercel/Netlify)
1. 构建:`npm run build`
2. 部署 `dist` 文件夹
3. 配置环境变量
4. 将 API_URL 设置为生产环境后端
## 🔄 实时功能
### 实时更新
- 事件创建广播给所有已连接用户
- 状态更新实时传播
- SOS 警报触发关键广播
- 评论添加即时更新
### Socket.IO 集成
- 带有指数退避的自动重连
- 支持 WebSocket 和轮询传输
- 基于房间的事件隔离
- 特定用户的订阅
## 🎨 自定义
### 配色方案
编辑 [tailwind.config.js](frontend/tailwind.config.js):
```
colors: {
primary: { /* Blue tones */ },
alert: { /* Red/Alert tones */ }
}
```
### 地图样式
修改 [MapPage.jsx](frontend/src/pages/MapPage.jsx) 中的地图提供商
### API Base URL
在 [apiClient.js](frontend/src/services/apiClient.js) 中更新
## 📚 文档
- **API 文档**:查看上方的 [API 文档](#📝-api-documentation)
- **数据库 Schema**:查看上方的 [MongoDB Schema](#🗄️-mongodb-schema)
- **WebSocket 事件**:查看上方的 [WebSocket 事件](#🔌-websocket-events)
- **Socket 配置**:[backend/config/socket.js](backend/config/socket.js)
## 🐛 故障排除
### MongoDB 连接问题
```
# 检查 MongoDB 正在运行
mongod --version
# 验证 .env 中的 connection string
```
### WebSocket 连接失败
- 确保后端在正确的端口上运行
- 检查 CORS 源配置
- 验证防火墙设置
### CORS 错误
- 在后端的 .env 中更新 `FRONTEND_URL`
- 验证 [server.js](backend/server.js) 中的 CORS 中间件配置
### 登录问题
- 清除浏览器 cookie 和 localStorage
- 确认已设置 JWT_SECRET
- 检查数据库中是否存在该用户
## 📝 环境变量
### 后端 (.env)
```
MONGODB_URI=mongodb://localhost:27017/dm-eas
JWT_SECRET=<32+ character secret>
PORT=5000
NODE_ENV=development
FRONTEND_URL=http://localhost:5173
MAX_FILE_SIZE=5242880
```
### 前端 (.env.local)
```
VITE_API_URL=http://localhost:5000/api
VITE_SOCKET_URL=http://localhost:5000
```
## 🤝 贡献
1. Fork 该仓库
2. 创建功能分支:`git checkout -b feature/amazing-feature`
3. 提交更改:`git commit -m 'Add amazing feature'`
4. 推送到分支:`git push origin feature/amazing-feature`
5. 发起 Pull Request
## 📄 许可证
本项目基于 MIT 许可证授权 - 详情请参阅 LICENSE 文件。
## 👥 支持
如需支持,请发送电子邮件至 support@dm-eas.com 或在 GitHub 上提交 issue。
## 🙈 鸣谢
- MongoDB 提供的地理空间功能
- Socket.IO 提供的实时通信
- Recharts 提供的精美分析图表
- Leaflet 提供的交互式地图
- Framer Motion 提供的流畅动画
- Tailwind CSS 提供的实用优先样式
**为应急管理和灾害响应倾心打造 ❤️**
最后更新:2024 年 2 月
标签:MERN技术栈, MITM代理, 地理空间追踪, 实时通信, 应急响应系统, 灾害管理, 角色权限控制