feat: 初始化设计文档草稿
- SPEC.md: 项目概览与文档索引 - docs/architecture.md: 系统架构设计 - docs/api.md: 后台 API 接口设计 - docs/database.md: 数据库表结构设计 - docs/h5.md: H5 页面结构与交互设计 - docs/offline.md: 离线数据方案 状态: 设计中,待设备API协议确认后细化
This commit is contained in:
48
SPEC.md
Normal file
48
SPEC.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# 郑州智慧工地管理系统 - 产品设计规格书
|
||||
|
||||
> 版本: v0.1.0 draft
|
||||
> 状态: 设计中
|
||||
> 仓库: https://git.jesxion.com/jesxion/smart-project
|
||||
|
||||
---
|
||||
|
||||
## 文档索引
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [architecture.md](./architecture.md) | 系统架构设计 |
|
||||
| [api.md](./api.md) | 后台 API 接口设计 |
|
||||
| [database.md](./database.md) | 数据库表结构设计 |
|
||||
| [h5.md](./h5.md) | H5 页面结构与交互设计 |
|
||||
| [offline.md](./offline.md) | 离线数据方案 |
|
||||
|
||||
---
|
||||
|
||||
## 项目概述
|
||||
|
||||
### 背景
|
||||
|
||||
郑州智慧工地项目面向施工现场安全管理的数字化升级需求,提供塔吊、升降机等特种设备的实时监测与预警功能。
|
||||
|
||||
### 核心功能
|
||||
|
||||
- **设备监控**:塔吊、升降机实时数据接入(来自已有 API)
|
||||
- **预警管理**:设备异常实时推送与记录
|
||||
- **H5 移动端**:移动端随时查看设备状态、接收预警
|
||||
- **数据持久化**:监测数据与预警记录云端存储
|
||||
|
||||
### 技术栈
|
||||
|
||||
| 层级 | 技术选型 |
|
||||
|------|----------|
|
||||
| 后台 API | Python / FastAPI(或 Flask) |
|
||||
| H5 前端 | 原生 HTML/CSS/JS,无框架依赖 |
|
||||
| 数据库 | PostgreSQL / SQLite(MVP 阶段) |
|
||||
| 文件存储 | 阿里云 OSS |
|
||||
| 设备数据 | 已有第三方 API(塔吊/升降机) |
|
||||
|
||||
### 文档更新记录
|
||||
|
||||
| 日期 | 版本 | 更新内容 |
|
||||
|------|------|----------|
|
||||
| 2026-04-14 | v0.1.0 | 初始化草稿,架构设计 |
|
||||
294
docs/api.md
Normal file
294
docs/api.md
Normal file
@@ -0,0 +1,294 @@
|
||||
# 后台 API 接口设计
|
||||
|
||||
> 状态: 设计中(待设备 API 协议确认后细化)
|
||||
|
||||
---
|
||||
|
||||
## 1. API 概览
|
||||
|
||||
- **Base URL**: `https://api.example.com/v1`
|
||||
- **认证**: `Authorization: Bearer <jwt_token>`
|
||||
- **数据格式**: JSON
|
||||
- **字符编码**: UTF-8
|
||||
|
||||
---
|
||||
|
||||
## 2. 认证接口
|
||||
|
||||
### 2.1 登录
|
||||
|
||||
```
|
||||
POST /auth/login
|
||||
```
|
||||
|
||||
**请求体**:
|
||||
```json
|
||||
{
|
||||
"username": "string",
|
||||
"password": "string"
|
||||
}
|
||||
```
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"token": "eyJhbGciOiJIUzI1NiIs...",
|
||||
"expires_at": "2026-04-15T11:00:00Z",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 设备接口
|
||||
|
||||
### 3.1 获取设备台账列表
|
||||
|
||||
```
|
||||
GET /devices
|
||||
```
|
||||
|
||||
**Query 参数**:
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| type | string | 设备类型: `tower_crane` / `elevator` / 空(全部) |
|
||||
| status | string | 在线状态: `online` / `offline` / 空(全部) |
|
||||
| page | int | 页码,默认 1 |
|
||||
| page_size | int | 每页数量,默认 20 |
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"page_size": 20,
|
||||
"items": [
|
||||
{
|
||||
"id": "device_001",
|
||||
"name": "1号塔吊",
|
||||
"type": "tower_crane",
|
||||
"model": "QTZ500",
|
||||
"location": "A区施工现场",
|
||||
"status": "online",
|
||||
"last_seen": "2026-04-14T10:30:00Z",
|
||||
"install_date": "2026-01-15"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 获取设备实时数据
|
||||
|
||||
```
|
||||
GET /devices/{device_id}/realtime
|
||||
```
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"device_id": "device_001",
|
||||
"timestamp": "2026-04-14T10:30:00Z",
|
||||
"data": {
|
||||
// 塔吊
|
||||
"load": 45.2, // 当前载重 (kN)
|
||||
"range": 30.5, // 回转幅度 (m)
|
||||
"height": 85.0, // 起升高度 (m)
|
||||
"wind_speed": 5.2, // 风速 (m/s)
|
||||
"torque": 320.5, // 力矩 (kN·m)
|
||||
"angle": 120.5, // 回转角度 (°)
|
||||
// 升降机
|
||||
"speed": 1.2, // 升降速度 (m/s)
|
||||
"floor": 12, // 当前楼层
|
||||
"door_status": "closed"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 获取设备历史数据
|
||||
|
||||
```
|
||||
GET /devices/{device_id}/history
|
||||
```
|
||||
|
||||
**Query 参数**:
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| start | datetime | 开始时间 ISO8601 |
|
||||
| end | datetime | 结束时间 ISO8601 |
|
||||
| metric | string | 指标字段名(可选,默认全量) |
|
||||
| page | int | 页码 |
|
||||
| page_size | int | 每页数量,默认 100 |
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"device_id": "device_001",
|
||||
"total": 1000,
|
||||
"items": [
|
||||
{
|
||||
"timestamp": "2026-04-14T10:00:00Z",
|
||||
"load": 44.8,
|
||||
"range": 30.2,
|
||||
"height": 84.8
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 预警接口
|
||||
|
||||
### 4.1 获取预警列表
|
||||
|
||||
```
|
||||
GET /alerts
|
||||
```
|
||||
|
||||
**Query 参数**:
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| device_id | string | 设备ID(可选) |
|
||||
| level | string | 预警级别: `warning` / `danger` / 空(全部) |
|
||||
| status | string | 处理状态: `unread` / `handled` / `ignored` / 空(全部) |
|
||||
| page | int | 页码 |
|
||||
| page_size | int | 每页数量,默认 20 |
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"total": 50,
|
||||
"unread_count": 3,
|
||||
"items": [
|
||||
{
|
||||
"id": "alert_001",
|
||||
"device_id": "device_001",
|
||||
"device_name": "1号塔吊",
|
||||
"level": "danger",
|
||||
"message": "载重超限: 当前45.2kN,超过额定值40kN",
|
||||
"metric": "load",
|
||||
"value": 45.2,
|
||||
"threshold": 40.0,
|
||||
"created_at": "2026-04-14T10:25:00Z",
|
||||
"status": "unread"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 获取预警详情
|
||||
|
||||
```
|
||||
GET /alerts/{alert_id}
|
||||
```
|
||||
|
||||
### 4.3 处理预警
|
||||
|
||||
```
|
||||
POST /alerts/{alert_id}/handle
|
||||
```
|
||||
|
||||
**请求体**:
|
||||
```json
|
||||
{
|
||||
"action": "handled",
|
||||
"note": "已现场确认,正常作业"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 忽略预警
|
||||
|
||||
```
|
||||
POST /alerts/{alert_id}/ignore
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. OSS 文件接口
|
||||
|
||||
### 5.1 获取上传凭证(预签名 URL)
|
||||
|
||||
```
|
||||
POST /oss/upload-token
|
||||
```
|
||||
|
||||
**请求体**:
|
||||
```json
|
||||
{
|
||||
"filename": "report_2026_04.pdf",
|
||||
"content_type": "application/pdf"
|
||||
}
|
||||
```
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"upload_url": "https://bucket.oss-cn-beijing.aliyuncs.com/...",
|
||||
"object_key": "reports/2026/04/report_xxx.pdf",
|
||||
"expires_at": "2026-04-14T11:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 获取文件下载链接
|
||||
|
||||
```
|
||||
GET /oss/download-url
|
||||
```
|
||||
|
||||
**Query 参数**:
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| object_key | string | OSS 对象路径 |
|
||||
|
||||
**响应** (200):
|
||||
```json
|
||||
{
|
||||
"download_url": "https://bucket.oss-cn-beijing.aliyuncs.com/...?Signature=...",
|
||||
"expires_at": "2026-04-14T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 通用响应格式
|
||||
|
||||
**成功**:
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
**错误**:
|
||||
```json
|
||||
{
|
||||
"code": 1001,
|
||||
"message": "设备不存在",
|
||||
"detail": "device_id: device_999 不在系统中"
|
||||
}
|
||||
```
|
||||
|
||||
**HTTP 状态码**:
|
||||
| 状态码 | 说明 |
|
||||
|--------|------|
|
||||
| 200 | 成功 |
|
||||
| 400 | 参数错误 |
|
||||
| 401 | 未认证 |
|
||||
| 403 | 无权限 |
|
||||
| 404 | 资源不存在 |
|
||||
| 500 | 服务器内部错误 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 待确认
|
||||
|
||||
- [ ] 设备 API 协议格式(塔吊/升降机数据字段)
|
||||
- [ ] JWT Secret 如何管理
|
||||
- [ ] 预警推送机制(轮询 vs WebSocket)
|
||||
- [ ] OSS bucket 名称和目录结构
|
||||
139
docs/architecture.md
Normal file
139
docs/architecture.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# 系统架构设计
|
||||
|
||||
> 状态: 设计中
|
||||
|
||||
---
|
||||
|
||||
## 1. 系统架构图
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 阿里云 OSS │
|
||||
│ (文件存储: 证书/报告/日志) │
|
||||
└───────────────┬─────────────────────────┘
|
||||
│ upload
|
||||
▼
|
||||
┌──────────┐ ┌─────────────────────────┐ ┌──────────────┐
|
||||
│ 已有API │───▶│ 后台 API 服务 │◀───│ H5 客户端 │
|
||||
│ (塔吊/ │ │ Python / FastAPI │ │ (移动端浏览器)│
|
||||
│ 升降机) │ │ │ │ │
|
||||
└──────────┘ │ ┌───────────────────┐ │ └──────────────┘
|
||||
│ │ 设备数据接入层 │ │ ▲
|
||||
│ │ 预警引擎 │ │ │ polling / websocket
|
||||
│ │ OSS 文件管理 │ │
|
||||
│ │ REST API │ │
|
||||
│ └───────────────────┘ │ │
|
||||
└────────────┬────────────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌─────────────────────────┐ │
|
||||
│ PostgreSQL │ │
|
||||
│ (设备台账/预警记录/ │◀────────────┘
|
||||
│ 用户/OSS文件索引) │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 模块划分
|
||||
|
||||
### 2.1 后台 API 服务
|
||||
|
||||
**职责**:数据聚合层,统一对接已有设备 API,屏蔽异构数据源差异,对 H5 提供标准化 REST API。
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| `device_adapter` | 设备 API 适配器:塔吊协议解析、升降机协议解析 |
|
||||
| `monitor` | 设备状态监控:定时轮询已有 API,写入本地 DB |
|
||||
| `alert_engine` | 预警引擎:阈值判断、预警生成、通知分发 |
|
||||
| `file_mgr` | OSS 文件管理:上传、下载、索引 |
|
||||
| `api_routes` | REST API 路由:设备台账、实时数据、历史查询、预警、OSS |
|
||||
|
||||
### 2.2 H5 客户端
|
||||
|
||||
**职责**:移动端展示与操作界面,基于响应式 H5 开发,适配手机浏览器。
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| `dashboard` | 首页仪表盘:设备总数、在线/离线、告警统计 |
|
||||
| `device_list` | 设备列表:塔吊/升降机分类展示 |
|
||||
| `device_detail` | 设备详情:实时数据面板、历史曲线 |
|
||||
| `alert_list` | 预警列表:未读/已处理筛选 |
|
||||
| `alert_detail` | 预警详情:处理/忽略操作 |
|
||||
| `profile` | 个人中心:账号信息、通知设置 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据流向
|
||||
|
||||
### 3.1 设备数据采集
|
||||
|
||||
```
|
||||
已有设备 API
|
||||
│ (定时轮询: 每 30s 或设备主动推送)
|
||||
▼
|
||||
device_adapter (协议解析)
|
||||
│
|
||||
▼
|
||||
monitor (写入 DB + 触发预警判断)
|
||||
│
|
||||
├──────────────────┐
|
||||
▼ ▼
|
||||
PostgreSQL alert_engine
|
||||
(设备状态表) (阈值判断)
|
||||
│
|
||||
▼
|
||||
alert_records (预警记录表)
|
||||
│
|
||||
▼
|
||||
通知分发 (站内/OSS记录)
|
||||
```
|
||||
|
||||
### 3.2 H5 数据请求
|
||||
|
||||
```
|
||||
H5 浏览器
|
||||
│ GET /api/devices
|
||||
│ GET /api/devices/{id}/realtime
|
||||
│ GET /api/alerts
|
||||
▼
|
||||
api_routes (FastAPI)
|
||||
│
|
||||
├──────────────┐
|
||||
▼ ▼
|
||||
PostgreSQL OSS
|
||||
(结构化数据) (文件URL)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 部署架构
|
||||
|
||||
MVP 阶段采用轻量部署:
|
||||
|
||||
| 组件 | 部署方式 |
|
||||
|------|----------|
|
||||
| 后台 API | 阿里云函数计算(FC)或轻量服务器 |
|
||||
| PostgreSQL | 阿里云 RDS 或轻量服务器自建 |
|
||||
| OSS | 阿里云 OSS 标准存储 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 安全设计
|
||||
|
||||
| 措施 | 说明 |
|
||||
|------|------|
|
||||
| HTTPS | 全链路 HTTPS,证书由阿里云管理 |
|
||||
| Token 认证 | H5 API 请求携带 JWT Token |
|
||||
| CORS | 限制允许的 H5 域名 |
|
||||
| OSS 鉴权 | H5 通过后台签发临时 URL 访问 OSS 文件 |
|
||||
| 输入校验 | FastAPI Pydantic 模型全量参数校验 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 待细化
|
||||
|
||||
- [ ] 设备 API 协议细节(目前尚未获取,需跟进沟通)
|
||||
- [ ] 预警阈值配置方案(管理员界面 or 配置文件)
|
||||
- [ ] 实时通知方案(WebSocket / SSE / 轮询)
|
||||
- [ ] 多租户隔离方案(目前 MVP 单租户设计)
|
||||
194
docs/database.md
Normal file
194
docs/database.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# 数据库表结构设计
|
||||
|
||||
> 状态: 设计中(MVP 版本,PostgreSQL)
|
||||
|
||||
---
|
||||
|
||||
## 1. ER 图概述
|
||||
|
||||
```
|
||||
users ─────────┐
|
||||
│ 1:N
|
||||
▼
|
||||
user_device_access (N:M)
|
||||
│
|
||||
▼
|
||||
devices ───────┤
|
||||
│
|
||||
├──── 1:N ──── device_realtime (最新状态)
|
||||
│
|
||||
├──── 1:N ──── device_history (历史数据)
|
||||
│
|
||||
└──── 1:N ──── alert_records (预警记录)
|
||||
|
||||
alert_records ────── N:1 ──── users (处理人)
|
||||
|
||||
oss_files ──────────────────────────────────────────────────┐
|
||||
│
|
||||
(其他模块按需关联) │
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 表结构
|
||||
|
||||
### 2.1 users(用户表)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| id | SERIAL | PRIMARY KEY | 自增ID |
|
||||
| username | VARCHAR(64) | UNIQUE NOT NULL | 用户名 |
|
||||
| password_hash | VARCHAR(256) | NOT NULL | bcrypt 密码哈希 |
|
||||
| role | VARCHAR(32) | NOT NULL DEFAULT 'viewer' | 角色: admin / operator / viewer |
|
||||
| real_name | VARCHAR(128) | | 真实姓名 |
|
||||
| phone | VARCHAR(32) | | 手机号 |
|
||||
| is_active | BOOLEAN | DEFAULT true | 是否启用 |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 |
|
||||
| updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 |
|
||||
|
||||
**索引**:
|
||||
- `idx_users_username` ON (`username`)
|
||||
|
||||
---
|
||||
|
||||
### 2.2 devices(设备台账表)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| id | VARCHAR(64) | PRIMARY KEY | 设备ID(对接已有API的设备编号) |
|
||||
| name | VARCHAR(128) | NOT NULL | 设备名称,如 "1号塔吊" |
|
||||
| type | VARCHAR(32) | NOT NULL | 类型: `tower_crane` / `elevator` |
|
||||
| model | VARCHAR(128) | | 设备型号,如 "QTZ500" |
|
||||
| manufacturer | VARCHAR(128) | | 制造商 |
|
||||
| location | VARCHAR(256) | | 安装位置,如 "A区施工现场" |
|
||||
| install_date | DATE | | 安装日期 |
|
||||
| status | VARCHAR(32) | DEFAULT 'offline' | 在线状态: online / offline |
|
||||
| last_seen | TIMESTAMP | | 最后在线时间 |
|
||||
| config | JSONB | DEFAULT '{}' | 设备配置(预警阈值等) |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 |
|
||||
| updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 |
|
||||
|
||||
**索引**:
|
||||
- `idx_devices_type` ON (`type`)
|
||||
- `idx_devices_status` ON (`status`)
|
||||
|
||||
---
|
||||
|
||||
### 2.3 device_realtime(设备实时状态)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| id | SERIAL | PRIMARY KEY | 自增ID |
|
||||
| device_id | VARCHAR(64) | FOREIGN KEY → devices(id) | 设备ID |
|
||||
| timestamp | TIMESTAMP | NOT NULL | 数据时间戳 |
|
||||
| raw_data | JSONB | NOT NULL | 原始数据快照 |
|
||||
| parsed_data | JSONB | NOT NULL | 解析后的结构化数据 |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW() | 写入时间 |
|
||||
|
||||
**索引**:
|
||||
- `idx_realtime_device_id` ON (`device_id`)
|
||||
- `idx_realtime_timestamp` ON (`timestamp` DESC)
|
||||
|
||||
> 每次设备数据更新时,UPSERT 写入此表,仅保留最新一条记录。
|
||||
|
||||
---
|
||||
|
||||
### 2.4 device_history(设备历史数据)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| id | BIGSERIAL | PRIMARY KEY | 自增ID |
|
||||
| device_id | VARCHAR(64) | FOREIGN KEY → devices(id) | 设备ID |
|
||||
| timestamp | TIMESTAMP | NOT NULL | 数据时间戳 |
|
||||
| metric_name | VARCHAR(64) | NOT NULL | 指标名: load / range / height 等 |
|
||||
| metric_value | DECIMAL(18,4) | NOT NULL | 指标值 |
|
||||
| unit | VARCHAR(32) | | 单位: kN / m / m/s 等 |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW() | 写入时间 |
|
||||
|
||||
**索引**:
|
||||
- `idx_history_device_time` ON (`device_id`, `timestamp` DESC)
|
||||
- `idx_history_metric` ON (`metric_name`)
|
||||
- **分区**: 按月分区(`timestamp`),按设备ID + 时间范围查询
|
||||
|
||||
> 为节省存储空间,历史数据可定期归档到 OSS(冷存储),DB 仅保留近3个月数据。
|
||||
|
||||
---
|
||||
|
||||
### 2.5 alert_records(预警记录表)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| id | VARCHAR(64) | PRIMARY KEY | 预警ID(UUID) |
|
||||
| device_id | VARCHAR(64) | FOREIGN KEY → devices(id) | 设备ID |
|
||||
| device_name | VARCHAR(128) | | 冗余存储,查询方便 |
|
||||
| level | VARCHAR(32) | NOT NULL | 级别: warning / danger |
|
||||
| metric | VARCHAR(64) | NOT NULL | 触发指标: load / wind_speed 等 |
|
||||
| message | VARCHAR(512) | NOT NULL | 预警消息 |
|
||||
| value | DECIMAL(18,4) | NOT NULL | 触发值 |
|
||||
| threshold | DECIMAL(18,4) | NOT NULL | 阈值 |
|
||||
| status | VARCHAR(32) | DEFAULT 'unread' | 状态: unread / handled / ignored |
|
||||
| handled_by | INTEGER | FOREIGN KEY → users(id) | 处理人 |
|
||||
| handle_note | TEXT | | 处理备注 |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 |
|
||||
| handled_at | TIMESTAMP | | 处理时间 |
|
||||
|
||||
**索引**:
|
||||
- `idx_alerts_device` ON (`device_id`)
|
||||
- `idx_alerts_status` ON (`status`)
|
||||
- `idx_alerts_level` ON (`level`)
|
||||
- `idx_alerts_created` ON (`created_at` DESC)
|
||||
|
||||
---
|
||||
|
||||
### 2.6 oss_files(OSS 文件索引表)
|
||||
|
||||
| 字段 | 类型 | 约束 | 说明 |
|
||||
|------|------|------|------|
|
||||
| id | SERIAL | PRIMARY KEY | 自增ID |
|
||||
| object_key | VARCHAR(512) | UNIQUE NOT NULL | OSS 对象路径 |
|
||||
| filename | VARCHAR(256) | NOT NULL | 原始文件名 |
|
||||
| content_type | VARCHAR(128) | | MIME 类型 |
|
||||
| size | BIGINT | | 文件大小(字节) |
|
||||
| category | VARCHAR(64) | | 分类: report / certificate / log |
|
||||
| uploaded_by | INTEGER | FOREIGN KEY → users(id) | 上传人 |
|
||||
| uploaded_at | TIMESTAMP | DEFAULT NOW() | 上传时间 |
|
||||
| expires_at | TIMESTAMP | | 过期时间(临时文件) |
|
||||
|
||||
**索引**:
|
||||
- `idx_oss_category` ON (`category`)
|
||||
- `idx_oss_uploaded_by` ON (`uploaded_by`)
|
||||
|
||||
---
|
||||
|
||||
## 3. 初始数据
|
||||
|
||||
### 3.1 超级管理员
|
||||
|
||||
| username | password | role |
|
||||
|----------|----------|------|
|
||||
| admin | (首次部署时设置) | admin |
|
||||
|
||||
---
|
||||
|
||||
## 4. 迁移工具
|
||||
|
||||
使用 **Alembic** 管理数据库迁移:
|
||||
|
||||
```bash
|
||||
# 初始化
|
||||
alembic init alembic
|
||||
|
||||
# 生成迁移脚本
|
||||
alembic revision --autogenerate -m "init schema"
|
||||
|
||||
# 执行迁移
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 待确认
|
||||
|
||||
- [ ] 设备历史数据保留策略(多久归档到 OSS)
|
||||
- [ ] 多租户隔离方案(MVP 单租户,后续扩展)
|
||||
- [ ] 预警阈值配置(存 DB 还是配置文件)
|
||||
299
docs/h5.md
Normal file
299
docs/h5.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# H5 页面结构与交互设计
|
||||
|
||||
> 状态: 设计中
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术选型
|
||||
|
||||
| 项目 | 选型 |
|
||||
|------|------|
|
||||
| 页面渲染 | 原生 HTML5 + CSS3 + Vanilla JS |
|
||||
| UI 框架 | 无,响应式布局手工实现 |
|
||||
| 图表 | ECharts(CDN 引入) |
|
||||
| 字体图标 | 阿里巴巴矢量图标库(iconfont) |
|
||||
| 构建 | 无构建步骤,单 HTML 文件按模块拆分 |
|
||||
|
||||
**设计原则**:
|
||||
- 移动端优先(适配 375px ~ 414px 宽度)
|
||||
- 低依赖,不依赖任何 JS 框架
|
||||
- 离线可缓存核心资产(Service Worker)
|
||||
|
||||
---
|
||||
|
||||
## 2. 页面清单
|
||||
|
||||
| 页面 | 路由 | 说明 |
|
||||
|------|------|------|
|
||||
| 登录 | `/login.html` | 账号密码登录 |
|
||||
| 首页仪表盘 | `/index.html` | 设备统计、预警统计、快捷入口 |
|
||||
| 设备列表 | `/devices.html` | 塔吊/升降机分类列表 |
|
||||
| 设备详情 | `/device.html?id=xxx` | 实时数据 + 历史曲线 |
|
||||
| 预警列表 | `/alerts.html` | 预警推送列表 |
|
||||
| 预警详情 | `/alert.html?id=xxx` | 预警详情 + 处理操作 |
|
||||
| 个人中心 | `/profile.html` | 个人信息、设置 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 页面结构
|
||||
|
||||
### 3.1 首页仪表盘 `/index.html`
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ ☰ 郑州智慧工地 [👤 个人中心] │ ← 顶栏
|
||||
├──────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ 塔吊 │ │ 升降机 │ │ ← 设备数量卡片
|
||||
│ │ 12 台 │ │ 8 台 │ │
|
||||
│ │ 12 在线 │ │ 8 在线 │ │
|
||||
│ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 今日预警 │ │ ← 预警统计卡片
|
||||
│ │ 危险 2 警告 5 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ 最新预警 │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🔴 1号塔吊 载重超限 │ │ ← 预警列表(最新5条)
|
||||
│ │ 10:25 │ │
|
||||
│ ├──────────────────────────────┤ │
|
||||
│ │ 🟡 3号升降机 风速过大 │ │
|
||||
│ │ 10:20 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ [查看全部预警] │
|
||||
│ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 设备列表 `/devices.html`
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ ☰ 设备列表 [筛选 ▼] │
|
||||
├──────────────────────────────────────┤
|
||||
│ [全部] [塔吊] [升降机] │ ← Tab 切换
|
||||
├──────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🏗️ 1号塔吊 🟢 在线 │ │ ← 设备卡片
|
||||
│ │ QTZ500 | A区施工现场 │ │
|
||||
│ │ 最后在线: 10:30 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🏗️ 2号塔吊 ⚫ 离线 │ │
|
||||
│ │ QTZ500 | B区施工现场 │ │
|
||||
│ │ 最后离线: 04-13 18:00 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.3 设备详情 `/device.html`
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ ← 返回 1号塔吊 │
|
||||
├──────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 实时数据面板 │ │ ← 关键指标卡片
|
||||
│ │ 载重 幅度 起升高度 │ │
|
||||
│ │ 45.2kN 30.5m 85.0m │ │
|
||||
│ │ │ │
|
||||
│ │ 风速 力矩 回转角度 │ │
|
||||
│ │ 5.2m/s 320.5 120.5° │ │
|
||||
│ │ │ │
|
||||
│ │ ⚠️ 载重超限 │ │ ← 告警状态
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ 历史趋势(最近24小时) │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 📈 ECharts 折线图 │ │ ← ECharts 图表
|
||||
│ │ 载重 / 幅度 / 风速 曲线 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ [ 刷新 ] │
|
||||
│ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.4 预警列表 `/alerts.html`
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ 预警中心 [筛选 ▼] │
|
||||
├──────────────────────────────────────┤
|
||||
│ [全部] [危险] [警告] [已处理] │ ← Tab 筛选
|
||||
├──────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🔴 载重超限 │ │ ← 危险预警(红色)
|
||||
│ │ 1号塔吊 | 2026-04-14 10:25 │ │
|
||||
│ │ 当前45.2kN,超过额定40kN │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🟡 风速过大 │ │ ← 警告预警(黄色)
|
||||
│ │ 3号升降机 | 2026-04-14 10:20 │ │
|
||||
│ │ 当前8.5m/s,超过阈值6m/s │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.5 预警详情 `/alert.html`
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ ← 返回 预警详情 │
|
||||
├──────────────────────────────────────┤
|
||||
│ │
|
||||
│ 🔴 危险 │
|
||||
│ │
|
||||
│ 载重超限 │
|
||||
│ │
|
||||
│ 设备: 1号塔吊(QTZ500) │
|
||||
│ 位置: A区施工现场 │
|
||||
│ 时间: 2026-04-14 10:25:00 │
|
||||
│ │
|
||||
│ 当前载重: 45.2 kN │
|
||||
│ 额定载重: 40.0 kN(阈值) │
|
||||
│ 超限幅度: 13% │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 处理方式: │ │
|
||||
│ │ │ │
|
||||
│ │ [确认处理] [忽略] │ │ ← 操作按钮
|
||||
│ │ │ │
|
||||
│ │ 备注: ____________________ │ │
|
||||
│ │ │ │
|
||||
│ │ [提交] │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.6 个人中心 `/profile.html`
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ ← 返回 个人中心 │
|
||||
├──────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────┐ │
|
||||
│ │ 👤 │ │
|
||||
│ └──────────┘ │
|
||||
│ 张三(管理员) │
|
||||
│ 138****1234 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 📊 预警接收设置 │ │
|
||||
│ │ [ ] 危险预警推送 │ │
|
||||
│ │ [ ] 警告预警推送 │ │
|
||||
│ │ [x] 短信通知 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🔔 消息推送设置 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 🔐 修改密码 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ [退出登录] │
|
||||
│ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 页面交互
|
||||
|
||||
### 4.1 API 请求
|
||||
|
||||
所有页面通过 `fetch` 调用后台 API,基础封装:
|
||||
|
||||
```javascript
|
||||
// api.js
|
||||
const API_BASE = '/v1';
|
||||
|
||||
async function api(endpoint, options = {}) {
|
||||
const token = localStorage.getItem('token');
|
||||
const resp = await fetch(API_BASE + endpoint, {
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': token ? `Bearer ${token}` : '',
|
||||
...options.headers,
|
||||
}
|
||||
});
|
||||
if (resp.status === 401) {
|
||||
location.href = '/login.html';
|
||||
return;
|
||||
}
|
||||
const json = await resp.json();
|
||||
if (json.code !== 0) {
|
||||
alert(json.message);
|
||||
return;
|
||||
}
|
||||
return json.data;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 数据加载流程
|
||||
|
||||
```
|
||||
页面加载
|
||||
│
|
||||
▼
|
||||
检查登录状态(localStorage.token)
|
||||
│
|
||||
├─ 无 token → 跳转 login.html
|
||||
│
|
||||
└─ 有 token → API 请求
|
||||
│
|
||||
├─ 成功 → 渲染页面
|
||||
│
|
||||
└─ 失败 → 显示错误提示
|
||||
```
|
||||
|
||||
### 4.3 实时数据刷新
|
||||
|
||||
- **策略**: 首次加载后,每 **30 秒**自动刷新实时数据
|
||||
- **实现**: `setInterval` 定时调用 `GET /devices/{id}/realtime`
|
||||
- **优化**: 仅在设备详情页刷新,其他页面用户主动下拉刷新
|
||||
|
||||
### 4.4 离线缓存
|
||||
|
||||
使用 **Service Worker** 缓存静态资源:
|
||||
|
||||
```javascript
|
||||
// 缓存策略:Network First, Fallback to Cache
|
||||
// 缓存内容:HTML / CSS / JS / iconfont 字体
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 响应式断点
|
||||
|
||||
| 断点 | 宽度 | 适配 |
|
||||
|------|------|------|
|
||||
| mobile-s | 320px ~ 374px | 小屏手机 |
|
||||
| mobile-l | 375px ~ 413px | 主流手机 |
|
||||
| tablet | 768px ~ 1023px | 平板 |
|
||||
| desktop | 1024px+ | 桌面端 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 待确认
|
||||
|
||||
- [ ] 预警推送机制(轮询 vs WebSocket)
|
||||
- [ ] 登录 Session 管理方案(JWT 有效期)
|
||||
- [ ] 是否有扫码登录需求
|
||||
- [ ] 报表导出(H5 直接拉 OSS 预签名 URL)
|
||||
191
docs/offline.md
Normal file
191
docs/offline.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# 离线数据方案
|
||||
|
||||
> 状态: 设计中(MVP 阶段可简化)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景
|
||||
|
||||
工地现场网络环境不稳定,H5 移动端可能出现网络中断。需要保证:
|
||||
|
||||
1. **已加载数据可继续浏览**(设备列表、预警等)
|
||||
2. **网络恢复后数据自动同步**
|
||||
3. **离线期间的操作不丢失**
|
||||
|
||||
---
|
||||
|
||||
## 2. 离线存储策略
|
||||
|
||||
### 2.1 存储层级
|
||||
|
||||
| 层级 | 技术 | 容量 | 适用场景 |
|
||||
|------|------|------|----------|
|
||||
| Memory | JavaScript 变量 | 无限 | 页面运行期间 |
|
||||
| LocalStorage | 浏览器本地存储 | ~5MB | 永久存储(小数据) |
|
||||
| IndexedDB | 浏览器索引数据库 | ~50MB+ | 结构化数据存储 |
|
||||
|
||||
**选型**: 以 **IndexedDB** 为主,LocalStorage 辅助。
|
||||
|
||||
---
|
||||
|
||||
## 3. 离线缓存设计
|
||||
|
||||
### 3.1 IndexedDB 表设计
|
||||
|
||||
```javascript
|
||||
// 数据库: SmartProjectDB
|
||||
// 版本: 1
|
||||
|
||||
// 对象存储 1: devices
|
||||
{
|
||||
store: 'devices',
|
||||
keyPath: 'id',
|
||||
indexes: ['type', 'status'],
|
||||
data: { id, name, type, model, location, status, last_seen }
|
||||
}
|
||||
|
||||
// 对象存储 2: alerts
|
||||
{
|
||||
store: 'alerts',
|
||||
keyPath: 'id',
|
||||
indexes: ['status', 'level', 'created_at'],
|
||||
data: { id, device_id, device_name, level, message, status, created_at }
|
||||
}
|
||||
|
||||
// 对象存储 3: sync_queue(离线操作队列)
|
||||
{
|
||||
store: 'sync_queue',
|
||||
keyPath: 'id',
|
||||
autoIncrement: true,
|
||||
data: { id, action, payload, created_at, status }
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 缓存更新策略
|
||||
|
||||
| 数据类型 | 更新频率 | 缓存策略 |
|
||||
|----------|----------|----------|
|
||||
| 设备列表 | 每 5 分钟 | 后台静默更新 |
|
||||
| 设备详情 | 每 30 秒 | 页面打开时拉取 + 定时刷新 |
|
||||
| 预警列表 | 每 1 分钟 | 后台静默更新 + 新预警推送 |
|
||||
| 预警详情 | 实时 | 打开时拉取 |
|
||||
|
||||
**更新流程**:
|
||||
```
|
||||
用户打开页面
|
||||
│
|
||||
├─ 有网络 → API 请求 → 更新 IndexedDB → 渲染
|
||||
│
|
||||
└─ 无网络 → 读取 IndexedDB → 渲染(显示"离线模式")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 离线操作队列
|
||||
|
||||
### 4.1 场景
|
||||
|
||||
用户在离线状态下执行操作(如处理预警、提交备注),操作记录存入 `sync_queue`,网络恢复后自动同步。
|
||||
|
||||
### 4.2 同步流程
|
||||
|
||||
```
|
||||
检测到网络恢复(navigator.onLine 事件)
|
||||
│
|
||||
▼
|
||||
读取 sync_queue(status: pending)
|
||||
│
|
||||
▼
|
||||
逐条执行 API 请求
|
||||
│
|
||||
├─ 成功 → 删除队列记录,更新本地数据
|
||||
│
|
||||
└─ 失败 → 重试3次,仍失败标记为 failed,用户手动处理
|
||||
```
|
||||
|
||||
### 4.3 队列记录格式
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: 1,
|
||||
action: 'handle_alert',
|
||||
payload: {
|
||||
alert_id: 'alert_001',
|
||||
action: 'handled',
|
||||
note: '已现场确认'
|
||||
},
|
||||
created_at: '2026-04-14T10:00:00Z',
|
||||
status: 'pending', // pending / syncing / failed
|
||||
retry_count: 0
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Service Worker
|
||||
|
||||
### 5.1 职责
|
||||
|
||||
- 拦截 H5 页面的 HTTP 请求
|
||||
- 实现缓存策略(静态资源优先缓存,网络优先等)
|
||||
- 离线时返回缓存的页面
|
||||
|
||||
### 5.2 缓存策略
|
||||
|
||||
| 资源类型 | 缓存策略 | 说明 |
|
||||
|----------|----------|------|
|
||||
| HTML | Network First | 始终尝试获取最新 |
|
||||
| CSS/JS | Cache First | 优先使用缓存,性能优先 |
|
||||
| API 数据 | Network Only | 实时性要求高,不缓存 |
|
||||
| 图标/字体 | Cache First | 长期不变 |
|
||||
|
||||
### 5.3 Service Worker 注册
|
||||
|
||||
```javascript
|
||||
// main.js
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then(reg => console.log('SW registered'))
|
||||
.catch(err => console.error('SW registration failed:', err));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 网络状态提示
|
||||
|
||||
页面监听网络状态,给用户明确反馈:
|
||||
|
||||
```javascript
|
||||
// 监听网络状态
|
||||
window.addEventListener('online', () => {
|
||||
showToast('网络已恢复,正在同步...');
|
||||
syncPendingOperations();
|
||||
});
|
||||
|
||||
window.addEventListener('offline', () => {
|
||||
showToast('网络已断开,显示离线数据');
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 简化方案(MVP)
|
||||
|
||||
MVP 阶段可降低离线复杂度:
|
||||
|
||||
| 方案 | 说明 |
|
||||
|------|------|
|
||||
| 简单缓存 | 仅在 LocalStorage 缓存用户信息 + 最后设备列表,H5 页面可离线展示 |
|
||||
| 无离线操作 | 离线期间禁用操作按钮,提示"网络异常" |
|
||||
| 手动刷新 | 网络恢复后用户下拉刷新 |
|
||||
|
||||
**后续迭代再实现完整离线能力**。
|
||||
|
||||
---
|
||||
|
||||
## 8. 待确认
|
||||
|
||||
- [ ] 是否需要 PWA(可安装到桌面/主屏幕)
|
||||
- [ ] IndexedDB 库选型(idb / Dexie.js 还是原生)
|
||||
- [ ] 离线数据保留时长策略
|
||||
Reference in New Issue
Block a user