# IoT管理平台入门指南：从概念到部署

> 作者: 张煜
> 日期: 2026-05-26
> 标签: 物联网平台, 架构

---

# IoT管理平台入门指南：从概念到部署

> 本文档面向有 HTML/CSS/JavaScript + Flask 基础的初学者，用最通俗的大白话解释工业物联网平台的方方面面。

---

## 一、先理解这个项目到底是什么

### 1.1 一句话总结

这个项目不是单一的网站，而是**两个独立的管理系统**装在同一台服务器里，通过不同的网址访问：

| 系统 | 类比理解 | 访问地址 |
|------|---------|---------|
| **DC3 IoT 管理平台** | 工厂设备的"大管家"（管设备、管数据、管驱动） | `http://服务器IP:3000` |
| **SCADA 组态系统** | 工厂设备的"监控大屏"（拖拽画图、实时看数据） | `http://服务器IP:3001` |

**关键理解**：两个系统各自有各自的数据库、各自的后端程序、各自的前端页面。它们只是住在同一台服务器的不同房间里，互相不串门。

### 1.2 用你熟悉的东西做类比

你已经会写 Flask 网站了，想象一下你熟悉的结构：

```
浏览器 → Flask (Python) → SQLite/MySQL → 返回数据 → 浏览器显示
```

这个项目的本质和上面一样，只是**每个环节都升级成了专业工具**：

```
浏览器 → Vue 前端 → Nginx 代理 → Java 后端 → 数据库 → 返回数据
```

| 你熟悉的 | 这个项目用的 | 为什么换 |
|---------|-----------|---------|
| Flask (Python) | Spring Boot (Java) | 企业级、能扛高并发、微服务方便团队分工 |
| Jinja2 模板返回 HTML | Vue 3 前端独立渲染 | 前端体验像 App，响应更快 |
| SQLite | PostgreSQL + MySQL + Redis | 功能更强、分工更细 |
| 直接运行 `python app.py` | Docker 容器运行 | 一次打包，到处运行，环境不冲突 |

### 1.3 两个子系统的详细拆解

#### SCADA 组态系统（简单理解版）

**SCADA** 是工业领域的术语，意思是"监控与数据采集"。你可以把它理解成：

> 一个可以让管理员**拖拽画图**做出监控界面的系统。

比如工厂里有很多水泵、电机、温度计：
- 管理员在 SCADA 里拖一个"水泵"图标到画布上
- 把这个图标和真实的设备数据绑定
- 保存后，运行状态下这个水泵图标会实时显示转速、温度
- 如果温度超标，图标变红报警

**技术实现**：
- 前端用 `maotu` 组态引擎（专门画工业监控图的工具）
- 后端是单一的 Java 程序（Spring Boot）
- 数据库用 MySQL 存用户信息、组态项目、设备列表
- 用 Redis 存用户登录状态（谁在线、登录了多久）
- 用 WebSocket 推送实时数据（数据变了主动推给前端，不用前端一直问）

#### DC3 IoT 管理平台（简单理解版）

**DC3** 是设备管理平台，你可以把它理解成：

> 一个**注册、管理、监控所有工业设备**的后台系统。

它的核心功能是三层：

**第一层：驱动层（和设备说话）**
- 工厂里的设备说不同的"方言"（MQTT、Modbus、OPC UA 等）
- DC3 内置了各种"翻译员"（驱动），负责和设备通信
- 驱动把设备数据读上来，交给上层处理

**第二层：管理层（管设备的户口）**
- 每个设备都要在系统里"登记户口"：名称、型号、位置、参数
- 设备的每个"测点"（温度、压力、转速）也要登记
- 这些配置存在 PostgreSQL 数据库里

**第三层：数据层（存和处理数据）**
- 设备每秒产生大量数据，普通数据库存不下、查得慢
- 时序数据库（TDengine/InfluxDB）专门存这种"时间-数值"数据
- 数据层还负责报警：温度超了 80 度？发通知！

**为什么 DC3 用微服务架构？**

你可以理解成：一个工厂里，如果所有活都让一个人干（单体应用），会很累，而且一个人感冒了全厂停工。

微服务就是**分工**：
- 认证中心（auth）：只管登录、权限、谁是谁
- 管理中心（manager）：只管设备的增删改查
- 数据中心（data）：只管数据处理、存储、报警
- 网关（gateway）：像前台接待员，所有请求先找它，它再转给具体部门

每个服务独立运行，互不干扰。一个崩了，其他还能干活。

### 1.4 数据是怎么流的？（一张图看懂）

#### SCADA 系统的数据流

```
┌─────────────┐     ┌─────────────┐     ┌─────────────────┐
│   你的浏览器  │────▶│  Nginx:3001 │────▶│ SCADA Java后端   │
│ (看监控大屏)  │◀────│  (反向代理)  │◀────│   (端口 8887)    │
└─────────────┘     └─────────────┘     └────────┬────────┘
                                                  │
                    ┌─────────────────────────────┘
                    │
              ┌─────▼─────┐    ┌──────────┐
              │ MySQL 8.0 │    │ Redis 6  │
              │ (存数据)   │    │ (存缓存)  │
              └───────────┘    └──────────┘
```

**每一步发生了什么**：
1. 你打开 `http://服务器:3001`
2. Nginx 把前端的 HTML/CSS/JS 文件发给你，浏览器渲染出页面
3. 你点击登录，前端发请求到 `/prod-api/login`
4. Nginx 收到 `/prod-api/` 开头的请求，转发给后端的 Java 程序
5. Java 程序查 MySQL 验证账号密码，生成 JWT Token
6. Token 存到 Redis（这样下次你来，系统知道你是谁）
7. 后续你点"设备管理"，Java 程序查 MySQL 返回设备列表
8. 你打开"组态预览"，Java 程序通过 WebSocket 主动推送实时数据

#### DC3 系统的数据流

```
┌─────────────┐     ┌─────────────┐     ┌─────────────────┐
│   你的浏览器  │────▶│  Nginx:3000 │────▶│  Gateway:8000   │
│ (管设备后台)  │◀────│  (反向代理)  │◀────│   (API网关)      │
└─────────────┘     └─────────────┘     └────────┬────────┘
                                                  │
                    ┌──────────────┬──────────────┼──────────────┐
                    │              │              │              │
              ┌─────▼─────┐  ┌────▼─────┐  ┌────▼─────┐  ┌────▼─────┐
              │  Auth     │  │ Manager  │  │  Data    │  │ Driver   │
              │ :8300     │  │ :8400    │  │ :8500    │  │ (各种驱动) │
              └─────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘
                    │             │             │             │
              ┌─────▼─────┐  ┌────▼─────┐  ┌────▼─────┐  ┌────▼─────┐
              │ PostgreSQL│  │ PostgreSQL│  │ PostgreSQL│  │ RabbitMQ │
              │ (用户/权限)│  │ (设备配置)│  │ (规则/报警)│  │ (消息队列)│
              └───────────┘  └───────────┘  └───────────┘  └──────────┘
```

**每一步发生了什么**：
1. 你打开 `http://服务器:3000`
2. Nginx 给你发前端页面
3. 你登录，请求到 `/api/v3/auth/token/generate`
4. Gateway 收到请求，看路径里有 `/auth/`，转发给 Auth 服务 (8300)
5. Auth 服务查 PostgreSQL 的 `dc3_auth` 库，验证成功返回 Token
6. 你要看设备列表，请求到 `/api/v3/manager/device/list`
7. Gateway 转发给 Manager 服务 (8400)
8. Manager 查 PostgreSQL 的 `dc3_manager` 库，返回设备列表
9. 驱动（如 MQTT 驱动）通过 RabbitMQ 把设备实时数据送到 Data 服务
10. Data 服务处理后，写入 InfluxDB/TDengine 时序数据库

---

## 二、架构层面的大概念

### 2.1 单体应用 vs 微服务

#### 单体应用（Monolithic）

**类比**：一家小餐馆，老板一个人兼任厨师、服务员、收银员。

所有功能都在一个程序里：
- 用户登录、设备管理、数据查询、报表生成……全部写在一个 Flask 项目里。
- 优点：简单，开发快。
- 缺点：功能越来越多时，代码膨胀，一个人改登录功能可能不小心把设备管理搞崩。

**本项目中的例子**：SCADA 系统就是一个单体应用（`iot-scada-api`）。

#### 微服务架构（Microservices）

**类比**：一家连锁酒店集团，分成不同的部门：
- 前台部（负责接待/登录）
- 客房部（负责房间/设备管理）
- 餐饮部（负责数据处理）

每个部门独立运营，互不干扰。但对外有一个总机（网关），客人打电话到总机，总机转接到具体部门。

**本项目中的例子**：DC3 系统是微服务架构：
- `auth` 服务：专门负责登录认证
- `manager` 服务：专门管设备
- `data` 服务：专门处理采集的数据
- `gateway` 服务：总机/网关，统一接收请求再分发

| 对比 | 单体应用 | 微服务 |
|------|---------|--------|
| 代码量 | 一个项目 | 多个独立项目 |
| 部署 | 启动一个程序 | 启动多个程序 |
| 协作 | 容易冲突 | 团队可以各自负责一个服务 |
| 复杂度 | 低 | 高（需要解决服务间通信） |
| 故障影响 | 一处崩全部崩 | 一个服务崩不影响其他 |

### 2.2 前后端分离

**你已经熟悉的（非前后端分离）**：
Flask 用 `render_template()` 直接返回 HTML 页面，后端把页面都拼好了给浏览器。

**前后端分离（现代主流）**：
- 后端只提供 **API 接口**（返回纯数据，通常是 JSON 格式）。
- 前端是一个独立的程序（Vue 项目），用 JavaScript 请求 API 获取数据，然后在浏览器里动态渲染页面。

**类比**：
- 非分离：餐厅厨房直接把菜端到你桌上（后端返回完整 HTML）。
- 分离：餐厅只提供食材清单（JSON 数据），你自己在家按照菜谱做（前端 Vue 自己渲染页面）。

**好处**：
- 前端和后端可以完全用不同的技术栈。
- 前端可以做成类似手机 App 的体验（单页应用 SPA）。
- 一套后端 API 可以同时给网页、手机 App、小程序用。

### 2.3 API 接口：REST 和 gRPC

#### REST API

**你最熟悉的概念**：Flask 里写 `@app.route('/users', methods=['GET'])`，这就是 REST API。

REST 是一种设计风格：
- 用 URL 表示资源（`/devices` 表示设备）
- 用 HTTP 方法表示操作（GET 获取、POST 创建、PUT 更新、DELETE 删除）
- 数据用 JSON 格式传输

**本项目中的例子**：SCADA 系统用的是 REST API。

#### gRPC

**类比**：REST 像寄明信片（文本，人人能读但速度慢），gRPC 像打电话（二进制，效率高但双方需要约定好协议）。

- gRPC 是 Google 开发的**高性能远程调用框架**。
- 用 **Protobuf**（协议缓冲区）定义数据结构，自动生成代码。
- 基于 HTTP/2，支持流式传输。
- **缺点**：浏览器不直接支持，主要用于服务之间内部通信。

**本项目中的例子**：DC3 的微服务之间用 gRPC 通信（比如 auth 服务查询 manager 服务的数据）。

---

## 三、前端技术栈详解

### 3.1 Vue.js（Vue 3）

**类比**：jQuery 像手工工具，Vue 像电动工具套装。

你已经会用 JavaScript 操作 DOM：`document.getElementById('box').innerHTML = 'hello'`。

Vue 是一种**前端框架**，核心思想：
- **数据驱动**：你只需要改数据，Vue 自动帮你更新页面。
- **组件化**：把页面拆成独立的"乐高积木"（组件），比如导航栏组件、表格组件、图表组件，拼起来就是一个页面。
- **单文件组件（.vue）**：一个文件里同时包含 HTML 模板、JavaScript 逻辑、CSS 样式。

```vue
<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  data() {
    return { message: 'Hello Vue!' }
  }
}
</script>

<style>
div { color: red; }
</style>
```

**Vue 3 的新特性**：
- 使用 **Composition API**（组合式 API），逻辑可以更灵活地组织。
- 性能更好，包体积更小。

### 3.2 TypeScript（TS）

**类比**：JavaScript 像 Python（动态类型，灵活但容易出错），TypeScript 像 Java（静态类型，严谨但能提前发现错误）。

TypeScript = JavaScript + **类型系统**。

```typescript
// JavaScript
function add(a, b) {
  return a + b  // 不知道 a 和 b 应该是什么类型
}

// TypeScript
function add(a: number, b: number): number {
  return a + b  // 明确告诉编译器：a 和 b 必须是数字，返回值也是数字
}
```

**好处**：
- 写代码时编辑器能提示你哪里类型不对。
- 重构代码更安全（改名一个地方，相关的地方会自动检查）。
- 大型项目必备。

**本项目中的例子**：DC3 前端用 TypeScript，SCADA 前端用普通 JavaScript。

### 3.3 Vite

**类比**：Vite 像汽车的涡轮增压器，让开发体验飞速提升。

Vite 是一个**前端构建工具**，替代了 older 的 Webpack。

**它做什么**：
- **开发时**：启动极快（秒级），修改代码后页面瞬间更新（热更新 HMR）。
- **打包时**：把 Vue/TS 代码编译成浏览器能理解的纯 HTML/CSS/JS，做代码压缩、合并、优化。

**配置文件**：`vite.config.ts`（DC3）或 `vite.config.js`（SCADA）。

### 3.4 Element Plus

**类比**：像 Bootstrap，但是专门为 Vue 3 设计的一套 UI 组件库。

提供现成的、好看的组件：
- 按钮、表格、表单、对话框、日期选择器、下拉菜单……

你只需要：
```vue
<template>
  <el-button type="primary">点击我</el-button>
  <el-table :data="tableData">...</el-table>
</template>
```

就能得到一个好看的、有交互效果的按钮和表格，不用自己写 CSS。

### 3.5 状态管理：Vuex vs Pinia

**问题**：多个组件怎么共享数据？

**类比**：
- 没有状态管理：每个组件像独立的办公室，传文件需要一层层递交（props 层层传递）。
- 有状态管理：有一个公共的"档案室"，任何办公室都能直接存取。

#### Vuex
- Vue 官方老牌状态管理库。
- 概念：State（数据）、Mutations（修改数据的方法）、Actions（异步操作）。
- **本项目 DC3 前端使用 Vuex**。

#### Pinia
- Vuex 的下一代替代品，更简单、更轻量。
- 用法更接近普通 JavaScript。
- **本项目 SCADA 前端使用 Pinia**。

### 3.6 Axios

**你已经熟悉的概念**：JavaScript 里用 `fetch()` 发网络请求。

Axios 是一个**HTTP 请求库**，比 `fetch` 更好用：
- 自动转换 JSON 数据
- 支持请求/响应拦截器（比如统一加 Token、统一处理错误）
- 支持取消请求

```javascript
import axios from 'axios'

axios.get('/api/devices').then(res => {
  console.log(res.data)
})
```

### 3.7 ECharts / AntV G2Plot

**类比**：像 Python 的 Matplotlib/Plotly，但是专门用于网页。

数据可视化图表库：
- **ECharts**：百度开源，功能极其丰富（折线图、柱状图、地图、雷达图……）。
- **AntV G2Plot**：阿里开源，开箱即用，配置更简单。

本项目用来做设备数据的大屏展示、趋势图等。

---

## 四、后端技术栈详解

### 4.1 Spring Boot

**类比**：Flask 是轻量级框架，Spring Boot 是 Java 世界里的"重型但功能齐全的框架"。

Spring Boot 是 Java 最流行的 Web 开发框架：
- 内置 Tomcat 服务器（像 Flask 内置开发服务器，但是生产级）。
- **自动配置**：写很少的配置就能跑起来。
- **约定大于配置**：按照它的目录结构和命名规范，很多东西自动生效。

**核心概念**：
- **Controller**：处理 HTTP 请求（类似 Flask 的 `@app.route`）。
- **Service**：业务逻辑层。
- **Mapper/Repository**：数据库访问层。
- **Entity/POJO**：数据模型类（类似 Python 的 dataclass）。

### 4.2 Spring Cloud

**类比**：Spring Boot 是单个饭店的运营手册，Spring Cloud 是连锁饭店的管理体系。

Spring Cloud 是**微服务架构的一整套解决方案**，包含：
- **服务注册与发现**：新开个分店，自动登记到总部（Nacos）。
- **网关（Gateway）**：客人统一打电话给总机，总机转接。
- **负载均衡**：多个相同的服务，自动分配请求。
- **配置中心**：统一管理所有服务的配置。

**本项目中的例子**：DC3 使用 Spring Cloud，SCADA 只用 Spring Boot（单体不需要）。

### 4.3 Nacos

**类比**：像企业的通讯录 + 公告栏系统。

Nacos 是阿里的开源产品，两个核心功能：
- **服务注册与发现**：每个微服务启动时"报到"，其他服务可以"查通讯录"找到它。
- **配置中心**：统一管理配置文件，修改一处，所有服务自动更新。

### 4.4 Maven

**类比**：Python 里的 `pip`，但是更强大、更规范。

Maven 是 Java 的**项目构建和依赖管理工具**：
- `pom.xml` 文件声明项目信息和依赖（类似 Python 的 `requirements.txt`，但更复杂）。
- 自动下载 jar 包（Java 的库文件）。
- 编译代码、运行测试、打包成可执行文件。

**常用命令**：
```bash
mvn clean package    # 清理 + 编译 + 打包
```

### 4.5 MyBatis / MyBatis Plus

**类比**：Python 里你用 SQLAlchemy 或原生的 `cursor.execute()` 操作数据库，MyBatis 就是 Java 世界的 ORM 工具。

#### MyBatis
- 把 Java 方法和 SQL 语句映射起来。
- 你在 XML 文件里写 SQL，MyBatis 帮你执行并映射结果到 Java 对象。

#### MyBatis Plus
- MyBatis 的增强版。
- 提供了通用的 CRUD 方法（增删改查），不用写 SQL。
- 支持分页、代码生成等功能。

### 4.6 Lombok

**类比**：Python 的 `@dataclass` 装饰器，自动生成重复的代码。

Java 需要写很多"样板代码"（getter、setter、构造函数等），Lombok 用注解自动生成：

```java
@Data  // 自动生成 getter/setter/toString/equals/hashCode
public class User {
    private String name;
    private Integer age;
}
```

### 4.7 MapStruct

**类比**：像 Python 里的字典转换或 Pydantic 模型转换。

用于自动转换不同类型的对象（比如数据库实体转 DTO 传输对象），避免手写转换代码。

### 4.8 JWT（JSON Web Token）

**类比**：像游乐园的"通票手环"，你登录后拿到一个 Token，之后所有请求都带着它，服务器一看就知道你是谁。

**认证流程**：
1. 用户输入账号密码 → 服务器验证 → 返回 JWT Token。
2. 前端把 Token 存起来（通常放内存或 localStorage）。
3. 后续请求在 HTTP Header 里带上 Token：`Authorization: Bearer <token>`。
4. 服务器验证 Token 的有效性（签名、过期时间）。

**本项目**：
- DC3 用自定义的请求头（`X-Auth-Token`）。
- SCADA 用标准 JWT（`Authorization: Bearer ***`）。

### 4.9 Spring Security

**类比**：像大楼的安保系统，控制谁能进哪个门。

Spring Security 是 Java 的安全框架：
- 认证（Authentication）：你是谁？（查账号密码）
- 授权（Authorization）：你能做什么？（管理员能删数据，普通用户只能看）
- 防止 CSRF、XSS 等攻击。

**本项目中的例子**：SCADA 系统使用 Spring Security。

### 4.10 Druid

**类比**：数据库连接池像一个"预热的游泳池"，不用每次都重新接水管放水。

数据库连接是昂贵资源，Druid 是阿里开源的**数据库连接池**：
- 维护一组预先建立好的数据库连接。
- 请求来时取一个用，用完放回。
- 带监控功能，可以看 SQL 执行情况和性能。

### 4.11 Quartz

**类比**：像 Linux 的 cron 定时任务，或者 Python 的 `schedule` 库。

Quartz 是 Java 的**定时任务调度框架**：
- 每隔 5 分钟执行一次数据同步。
- 每天早上 8 点发送报表。
- 支持复杂的调度规则（Cron 表达式）。

**本项目中的例子**：SCADA 系统用 Quartz 做定时任务。

### 4.12 Swagger (springfox)

**类比**：像自动生成的 API 文档网站，类似 Python FastAPI 自带的 `/docs` 页面。

后端在代码里写注解，Swagger 自动生成：
- 所有接口列表
- 请求参数说明
- 响应格式示例
- 甚至可以直接在页面上调试接口

---

## 五、数据库与中间件

### 5.1 关系型数据库：PostgreSQL / MySQL

**你已经熟悉的概念**：像 SQLite，但功能更强大、支持并发。

| 特性 | PostgreSQL | MySQL |
|------|-----------|-------|
| 本项目用途 | DC3 主数据库 | SCADA 数据库 |
| 特点 | 功能最丰富，支持复杂查询 | 简单快速，使用广泛 |
| 数据组织 | 表、行、列，用 SQL 操作 | 同上 |

两者都是关系型数据库，用 SQL 语言操作数据。

### 5.2 时序数据库：TDengine / InfluxDB

**问题**：IoT 设备每秒产生大量数据（温度、湿度、电压……），用传统数据库存储和查询会很慢。

**类比**：普通数据库像Excel表格，时序数据库像专门记录"时间-数值"的日志本。

时序数据库专门为**时间序列数据**优化：
- 数据按时间顺序写入。
- 查询时通常按时间范围查（"最近一小时的数据"）。
- 支持数据压缩和过期自动删除。

| 数据库 | 特点 |
|--------|------|
| **TDengine** | 国产开源，专为物联网设计，性能极高 |
| **InfluxDB** | 业界最流行的时序数据库，生态丰富 |

**本项目中的例子**：DC3 采集的设备传感器数据存储在时序数据库中。

### 5.3 文档数据库：MongoDB

**类比**：关系数据库像填固定格式的表格，MongoDB 像自由格式的笔记本（JSON 文档）。

MongoDB 存储的是 BSON（类似 JSON）文档，没有固定的表结构：
```json
{
  "deviceId": "D001",
  "properties": { "temp": 25, "humidity": 60 },
  "tags": ["factory1", "lineA"]
}
```

适合存储结构不固定、灵活的数据。

### 5.4 Redis（缓存）

**类比**：像电脑的内存条，速度极快但断电丢失（默认）。

Redis 是一个**内存中的键值数据库**：
- 速度比 PostgreSQL/MySQL 快 100 倍以上。
- 适合存临时数据：用户会话、热点数据、验证码、排行榜……
- 支持设置过期时间（比如验证码 5 分钟后自动删除）。

**为什么用缓存**：
- 数据库查询慢 → 第一次查完后把结果放 Redis。
- 下次直接从 Redis 取，极大提升响应速度。

### 5.5 消息队列：RabbitMQ

**类比**：像医院的叫号系统，病人（消息）在队列里等待，医生（消费者）依次处理。

**解决的问题**：
- 系统 A 产生大量数据，系统 B 处理不过来 → 先放到队列里缓冲。
- 系统 A 和系统 B 不需要同时在线（解耦）。
- 一个任务可以分给多个工人并行处理。

**工作流程**：
1. 生产者（Producer）发送消息到队列。
2. 队列（Queue）暂存消息。
3. 消费者（Consumer）从队列取出消息处理。

**本项目中的例子**：DC3 的设备数据通过 RabbitMQ 在不同服务之间传递。

---

## 六、容器化与部署

### 6.1 Docker

**类比**：像"集装箱"标准化运输。

**问题**：你的程序在 Windows 能跑，到 Linux 服务器上可能因为环境不同跑不起来（"在我电脑上好好的"）。

**Docker 解决什么**：
- 把程序 + 运行环境（操作系统、依赖库、配置）打包成一个**镜像（Image）**。
- 镜像在任何地方运行结果都一样。
- 运行中的镜像叫**容器（Container）**。

**关键概念**：
- **镜像（Image）**：只读的模板，类似安装盘。
- **容器（Container）**：镜像的运行实例，类似装好的系统。
- **Dockerfile**：描述怎么构建镜像的脚本。

### 6.2 Docker Compose

**类比**：像乐高的搭建说明书，一次指令搭建一整套场景。

一个系统有多个服务（前端、后端、数据库、缓存……），Docker Compose 用一个 `docker-compose.yml` 文件定义：
- 有哪些服务
- 每个服务用哪个镜像
- 端口怎么映射
- 服务之间怎么连接

**一键启动整个系统**：
```bash
docker compose up -d    # -d 表示后台运行
```

**本项目中的例子**：
- `docker-compose-env.yml`：启动基础设施（数据库、缓存等）。
- `docker-compose.yml`：启动应用服务（网关、各微服务、前端）。

### 6.3 Nginx / 反向代理

**你已经熟悉的概念**：Flask 开发服务器监听一个端口（如 `127.0.0.1:5000`）。

**Nginx 是什么**：
- 高性能的 Web 服务器/反向代理服务器。
- 能同时处理几万个并发连接。

#### 正向代理 vs 反向代理

- **正向代理**：你（客户端）通过代理访问外网（代理代表你）。
- **反向代理**：外网请求通过代理访问内部服务器（代理代表服务器）。

**本项目中的反向代理作用**：
```
用户访问 http://服务器:3000
    ↓
Nginx（端口 3000）
    ↓
如果是静态文件（HTML/CSS/JS）→ 直接返回
如果是 API 请求 /api/xxx → 转发给 dc3-gateway:8000
```

这样用户只感知到一个地址，实际上背后有多个服务。

### 6.4 环境变量与 Profile

**你已经熟悉的概念**：Python 的 `os.environ.get('SECRET_KEY')`。

**环境变量**：在程序外部设置配置，不用改代码。

**Profile（Spring 的概念）**：
- `application.yml`：通用配置
- `application-dev.yml`：开发环境配置（连本地数据库）
- `application-pro.yml`：生产环境配置（连线上数据库）

启动时通过环境变量 `NODE_ENV=pro` 切换。

---

## 七、IoT / SCADA 专用概念

### 7.1 IoT（物联网）

**物联网** = 各种物理设备（传感器、机器、电器）连接到互联网，可以采集数据或远程控制。

**本项目中的场景**：
- 工厂里的温度传感器、电表、PLC 控制器……
- 它们通过网络把数据发到平台。
- 平台存储、展示、分析这些数据。

### 7.2 SCADA（监控与数据采集）

**类比**：像工厂的"中控室大屏幕"。

SCADA 是工业领域的专用系统：
- **采集**：从设备读取数据（温度、压力、开关状态）。
- **监控**：在屏幕上实时显示设备状态和数值。
- **控制**：远程发送指令（比如打开某个阀门）。
- **报警**：数据异常时告警（温度过高！）。

### 7.3 组态

**类比**：像搭积木或做 PPT，不用写代码就能做出监控画面。

"组态"是工业软件的概念：
- 从工具箱拖一个"泵"图标到画布上。
- 把这个图标绑定到真实的设备数据点。
- 运行后，图标会实时显示泵的状态（运转中/停止）。

**本项目中的例子**：SCADA 系统的组态编辑器，让用户拖拽组件设计监控大屏。

### 7.4 工业通信协议

**类比**：不同国家的人说不同语言，协议就是"翻译规则"。

设备要和平台通信，必须约定好"怎么说"：

| 协议 | 用途 | 类比 |
|------|------|------|
| **MQTT** | 轻量级的物联网消息协议 | 像发短信：简短、省电、适合弱网环境 |
| **OPC UA** | 工业自动化标准协议 | 像商务英语：正式、功能全面、跨平台 |
| **Modbus TCP** | simplest 工业协议 | 像手势语：简单、老旧但广泛支持 |
| **PLC S7** | 西门子 PLC 专用协议 | 像方言：只适用于西门子设备 |

**本项目中的例子**：DC3 系统内置了这些协议的"驱动"（Driver），负责和设备对话。

### 7.5 驱动（Driver）

**类比**：像打印机的驱动程序，让电脑能和硬件对话。

在 IoT 平台中：
- 驱动负责通过特定协议连接设备。
- 采集设备数据并上传到平台。
- 接收平台的指令下发给设备。

**本项目中的例子**：`dc3-driver-mqtt` 是 MQTT 协议的驱动服务。

---

## 八、系统架构详解

### 8.1 整体架构图

```
┌─────────────────────────────────────────────────────────────┐
│                      前端层 (Web/Client)                      │
│  iot-management-platform-web (Vue 3 + TypeScript)            │
└────────────────────────┬────────────────────────────────────┘
                         │ HTTP/WebSocket
┌────────────────────────▼────────────────────────────────────┐
│                      网关层 (Gateway)                         │
│  dc3-gateway (Spring Cloud Gateway + Nginx)                 │
└────────────────────────┬────────────────────────────────────┘
                         │
┌────────────────────────▼────────────────────────────────────┐
│                      服务中心 (Center)                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │   Auth      │  │   Manager   │  │    Data     │          │
│  │  认证服务   │  │  管理服务   │  │  数据服务   │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
└────────────────────────┬────────────────────────────────────┘
                         │
┌────────────────────────▼────────────────────────────────────┐
│                      驱动层 (Driver)                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐       │
│  │  MQTT    │ │ OPC UA   │ │ Modbus   │ │ Virtual  │       │
│  │  驱动    │ │  驱动    │ │  TCP 驱动 │ │  虚拟驱动 │       │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘       │
└─────────────────────────────────────────────────────────────┘
```

### 8.2 后端项目结构

```
iot-management-platform-backend/
├── dc3-api/                 # API 接口模块
│   ├── dc3-api-auth/       # 认证 API
│   ├── dc3-api-data/       # 数据 API
│   ├── dc3-api-driver/     # 驱动 API
│   └── dc3-api-manager/    # 管理 API
├── dc3-center/             # 服务中心模块
│   ├── dc3-center-auth/    # 认证服务
│   ├── dc3-center-data/    # 数据服务
│   ├── dc3-center-manager/ # 管理服务
│   └── dc3-center-single/  # 单体服务
├── dc3-common/             # 公共模块
│   ├── dc3-common-api/     # 公共 API
│   ├── dc3-common-auth/    # 认证工具
│   ├── dc3-common-dal/     # 数据访问层
│   ├── dc3-common-driver/  # 驱动工具
│   ├── dc3-common-manager/ # 管理工具
│   ├── dc3-common-model/   # 数据模型
│   ├── dc3-common-mqtt/    # MQTT 工具
│   ├── dc3-common-redis/   # Redis 工具
│   ├── dc3-common-rabbitmq/# RabbitMQ 工具
│   └── ...
├── dc3-driver/             # 驱动模块
│   ├── dc3-driver-mqtt/    # MQTT 驱动
│   ├── dc3-driver-opc-ua/  # OPC UA 驱动
│   ├── dc3-driver-opc-da/  # OPC DA 驱动
│   ├── dc3-driver-modbus-tcp/ # Modbus TCP 驱动
│   ├── dc3-driver-plcs7/   # PLC S7 驱动
│   └── dc3-driver-virtual/ # 虚拟驱动
├── dc3-gateway/            # 网关服务
├── deploy/                 # 部署配置
├── pom.xml                 # 父 POM
└── .env/                   # 环境变量配置
```

### 8.3 各服务端口配置

| 服务 | HTTP 端口 | gRPC 端口 | 说明 |
|------|---------|----------|------|
| dc3-center-auth | 8200 | - | 认证服务 |
| dc3-center-manager | 8400 | 9400 | 管理服务 |
| dc3-center-data | 8300 | - | 数据服务 |
| dc3-gateway | 8000 | - | 网关服务 |

### 8.4 服务启动顺序

1. 基础设施（PostgreSQL, Redis, RabbitMQ）
2. dc3-center-auth（认证服务）
3. dc3-center-manager（管理服务）
4. dc3-center-data（数据服务）
5. dc3-gateway（网关服务）
6. 各类驱动服务

### 8.5 前端技术架构

#### 目录结构

```
src/
├── api/                    # API 接口定义
│   ├── attribute.ts       # 属性 API
│   ├── device.ts          # 设备 API
│   ├── dictionary.ts      # 字典 API
│   ├── driver.ts          # 驱动 API
│   ├── info.ts            # 信息 API
│   ├── point.ts           # 点位 API
│   ├── profile.ts         # 模板 API
│   ├── rule.ts            # 规则 API
│   └── token.ts           # Token API
├── components/            # 公共组件
│   ├── card/             # 卡片组件
│   │   ├── base/         # 基础卡片
│   │   ├── blank/        # 空白卡片
│   │   ├── detail/       # 详情卡片
│   │   └── title/        # 标题卡片
│   ├── error/            # 错误页面组件
│   ├── layout/           # 布局组件
│   └── particles/        # 粒子效果组件
├── config/               # 配置文件
│   ├── axios/            # Axios 配置
│   ├── constant/         # 常量配置
│   ├── entity/           # 实体定义
│   ├── env/              # 环境配置
│   ├── plugins/          # 插件配置
│   ├── router/           # 路由配置
│   └── types/            # TypeScript 类型定义
└── views/                # 页面
    ├── device/           # 设备管理
    ├── driver/           # 驱动管理
    ├── home/             # 首页
    ├── login/            # 登录
    └── point/            # 点位管理
```

#### 核心技术

- **Vue 3**: 采用 Composition API
- **TypeScript**: 类型安全
- **Element Plus**: UI 组件库
- **Axios**: HTTP 客户端
- **Pinia**: 状态管理
- **Vue Router**: 路由管理
- **Vite**: 构建工具
- **Sass**: CSS 预处理器
- **ECharts/G2Plot**: 图表库

---

## 九、部署原理（为什么要这样做）

### 9.1 为什么要用 Docker？

**问题**：你以前跑 Flask，直接 `python app.py` 就行。为什么这里要用 Docker？

**答案**：这个项目太复杂了，有 10+ 个程序要同时跑：
- 2 个前端（Vue 编译后的静态文件）
- 2 个后端（SCADA 单体 + DC3 多个微服务）
- 4+ 个数据库（PostgreSQL、MySQL、Redis、MongoDB、InfluxDB...）
- 消息队列（RabbitMQ）

**不用 Docker 的问题**：
- Java 程序要装 JDK，Node 前端要装 Node.js，数据库要各自安装配置
- 它们之间还要配置网络连接（后端怎么找到数据库？IP 是多少？端口是多少？）
- 换一台服务器，所有配置重来一遍

**用 Docker 的好处**：
- 每个程序打包成一个"集装箱"（镜像），里面包含了运行所需的一切（代码 + 环境 + 配置）
- 像乐高积木一样，一条命令启动/停止
- 换服务器？把集装箱搬过去就行，里面的东西不变

### 9.2 为什么要分两次启动？

**第一次启动基础设施**：`docker-compose-env.yml`

```
PostgreSQL  ← DC3 的数据库
Redis       ← DC3 的缓存
RabbitMQ    ← DC3 的消息队列
MongoDB     ← DC3 的文档数据库
MySQL       ← SCADA 的数据库
Redis       ← SCADA 的缓存
```

这些就像**地基**，必须先打好。房子（应用服务）才能盖上去。

**第二次启动应用服务**：`docker-compose.yml`

```
Gateway、Auth、Manager、Data  ← DC3 后端
SCADA Server                   ← SCADA 后端
Nginx (DC3 Web)                ← DC3 前端
Nginx (SCADA Web)              ← SCADA 前端
```

### 9.3 为什么需要构建？

你拿到的源码是"原材料"，需要加工成"成品"才能运行：

| 原材料 | 加工工具 | 成品 |
|--------|---------|------|
| Vue 前端源码 | npm + Vite | dist/ 目录（HTML/CSS/JS） |
| Java 后端源码 | Maven | target/*.jar（可运行程序） |

**构建过程类比**：
- Vue 源码就像设计图纸，Vite 是加工厂，把图纸变成浏览器能看的网页
- Java 源码就像建筑蓝图，Maven 是施工队，把蓝图变成可运行的程序

### 9.4 Nginx 是干什么的？

**类比**：Nginx 像酒店的**前台接待员**。

- 客人（浏览器）来到酒店（服务器），只认识一个地址 `http://服务器:3000`
- 前台根据客人的需求，引导到不同的部门：
  - 要静态页面（HTML/CSS/JS）→ 直接给文件
  - 要 API 数据（`/api/xxx`）→ 转给后端的 Java 程序

**为什么需要它**：
- 前端和后端可以用不同技术栈
- 一个 Nginx 可以服务多个系统
- 可以做负载均衡、缓存、HTTPS 等高级功能

---

## 十、部署操作指南（一步一步跟着做）

### 10.1 环境要求

#### 硬件要求

- **CPU**: 4 核以上（推荐 8 核）
- **内存**: 8GB 以上（推荐 16GB）
- **磁盘**: 50GB 以上可用空间
- **网络**: 稳定的网络连接（用于拉取镜像）

#### 软件要求

- **操作系统**: Linux (Ubuntu 20.04+, CentOS 7+) / Windows 10+ / macOS
- **Docker**: 20.10.0 及以上版本
- **Docker Compose**: 2.0.0 及以上版本

### 10.2 安装必要工具

#### Step 1：安装 Docker

Docker 是运行容器的工具，相当于集装箱的搬运工。

```bash
# 更新软件源
sudo apt-get update

# 安装 Docker
sudo apt-get install -y docker.io

# 验证安装
docker --version
# 应该输出类似：Docker version 29.1.3
```

#### Step 2：安装 Docker Compose

Docker Compose 是同时管理多个容器的工具，相当于集装箱的调度员。

```bash
# 下载 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.27.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version
# 应该输出：Docker Compose version v2.27.1
```

#### Step 3：配置 Docker 镜像加速器（中国大陆服务器必须做）

Docker Hub 在国外，直接下载很慢或超时。配置国内镜像加速器：

```bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}
EOF
sudo systemctl restart docker
```

#### Step 4：安装 Java（JDK）

DC3 后端需要 Java 21，SCADA 后端需要 Java 17。

```bash
# 同时安装两个版本
sudo apt-get install -y openjdk-21-jdk openjdk-17-jdk

# 验证
java -version
# 默认会显示 Java 21
```

#### Step 5：安装 Maven

Maven 是 Java 项目的构建工具，相当于 Java 世界的 `pip`。

```bash
sudo apt-get install -y maven

# 验证
mvn -version
```

#### Step 6：安装 Node.js 和 pnpm

```bash
# Node.js 通常系统已预装，检查版本
node --version
# 需要 >= 18.0.0

# 安装 pnpm（SCADA 前端用它管理依赖）
sudo npm install -g pnpm

# 验证
pnpm --version
```

### 10.3 获取项目代码

假设项目代码已经放在服务器上，路径是 `/home/你的用户名/Projects/iot-platform/`。

```bash
cd /home/你的用户名/Projects/iot-platform/
```

目录结构应该是这样的：

```
iot-platform/
├── iot-management-platform-backend/    # DC3 后端源码
├── iot-management-platform-web/        # DC3 前端源码
├── iot-scada-api/                      # SCADA 后端源码
├── iot-scada-web/                      # SCADA 前端源码
├── deploy/                             # 部署配置
│   ├── docker-compose-env.yml          # 基础设施编排
│   ├── docker-compose.yml              # 应用服务编排（原版）
│   ├── docker-compose-scada.yml        # 我们实际用的简化版
│   ├── auth/                           # DC3 Auth Dockerfile
│   ├── gateway/                        # DC3 Gateway Dockerfile
│   ├── manager/                        # DC3 Manager Dockerfile
│   ├── data/                           # DC3 Data Dockerfile
│   ├── mqtt/                           # DC3 MQTT Dockerfile
│   ├── nginx/                          # DC3 Web Nginx 配置
│   │   ├── nginx.conf
│   │   └── html/                       # 构建后的前端文件放这里
│   └── scada/                          # SCADA 配置
│       ├── Dockerfile
│       ├── nginx.conf
│       ├── init.sql                    # SCADA 数据库初始化脚本
│       └── html/                       # 构建后的前端文件放这里
└── ...
```

### 10.4 构建前端（把源码变成浏览器能看的网页）

#### 构建 SCADA 前端

```bash
# 进入 SCADA 前端目录
cd /home/你的用户名/Projects/iot-platform/iot-scada-web/

# 安装依赖（第一次需要，类似 pip install -r requirements.txt）
pnpm install

# 如果提示需要批准构建脚本
pnpm approve-builds esbuild vue-demi vue-echarts

# 生产构建
pnpm build:prod

# 构建完成后，dist/ 目录下会生成 HTML/CSS/JS 文件
```

**构建完成后，复制到部署目录**：

```bash
# 创建目录（如果不存在）
mkdir -p /home/你的用户名/Projects/iot-platform/deploy/scada/html

# 清空旧文件
rm -rf /home/你的用户名/Projects/iot-platform/deploy/scada/html/*

# 复制新构建的文件
cp -r /home/你的用户名/Projects/iot-platform/iot-scada-web/dist/* \
  /home/你的用户名/Projects/iot-platform/deploy/scada/html/
```

#### 构建 DC3 前端

```bash
# 进入 DC3 前端目录
cd /home/你的用户名/Projects/iot-platform/iot-management-platform-web/

# 安装依赖
npm install

# 生产构建
npm run build

# 构建完成后，dist/ 目录下会生成文件
```

**复制到部署目录**：

```bash
mkdir -p /home/你的用户名/Projects/iot-platform/deploy/nginx/html
rm -rf /home/你的用户名/Projects/iot-platform/deploy/nginx/html/*
cp -r /home/你的用户名/Projects/iot-platform/iot-management-platform-web/dist/* \
  /home/你的用户名/Projects/iot-platform/deploy/nginx/html/
```

### 10.5 构建后端（把 Java 源码变成可运行程序）

#### 构建 SCADA 后端

```bash
# 进入 SCADA 后端目录
cd /home/你的用户名/Projects/iot-platform/iot-scada-api/

# 切换到 Java 17（SCADA 用 Java 17 编译更稳定）
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH

# 构建
mvn clean package -DskipTests

# 构建成功后，JAR 文件在：
# ruoyi-admin/target/iot-scada.jar
```

**复制到部署目录**：

```bash
cp /home/你的用户名/Projects/iot-platform/iot-scada-api/ruoyi-admin/target/iot-scada.jar \
  /home/你的用户名/Projects/iot-platform/deploy/scada/iot-scada.jar
```

#### 构建 DC3 后端（可选，如果缺少数据库则无法运行）

```bash
# 进入 DC3 后端目录
cd /home/你的用户名/Projects/iot-platform/iot-management-platform-backend/

# 默认 Java 21 即可

# 构建（首次需要下载大量依赖，可能需要 10-20 分钟）
mvn -U -e -B clean package -DskipTests -P dev

# 构建成功后，各服务的 JAR 文件在对应目录的 target/ 下：
# dc3-gateway/target/dc3-gateway.jar
# dc3-center/dc3-center-auth/target/dc3-center-auth.jar
# dc3-center/dc3-center-manager/target/dc3-center-manager.jar
# dc3-center/dc3-center-data/target/dc3-center-data.jar
# dc3-center/dc3-center-single/target/dc3-center-single.jar
# ... 等等
```

**复制到部署目录**：

```bash
# 以 gateway 为例
cp /home/你的用户名/Projects/iot-platform/iot-management-platform-backend/dc3-gateway/target/dc3-gateway.jar \
  /home/你的用户名/Projects/iot-platform/deploy/gateway/dc3-gateway.jar

# auth
cp /home/你的用户名/Projects/iot-platform/iot-management-platform-backend/dc3-center/dc3-center-auth/target/dc3-center-auth.jar \
  /home/你的用户名/Projects/iot-platform/deploy/auth/dc3-center-auth.jar

# manager
cp /home/你的用户名/Projects/iot-platform/iot-management-platform-backend/dc3-center/dc3-center-manager/target/dc3-center-manager.jar \
  /home/你的用户名/Projects/iot-platform/deploy/manager/dc3-center-manager.jar

# data
cp /home/你的用户名/Projects/iot-platform/iot-management-platform-backend/dc3-center/dc3-center-data/target/dc3-center-data.jar \
  /home/你的用户名/Projects/iot-platform/deploy/data/dc3-center-data.jar
```

> ⚠️ **注意**：DC3 后端构建出来的 JAR 文件**需要数据库才能运行**。如果数据库没准备好，启动会报错。

### 10.6 修改配置（让程序知道数据库在哪里）

#### SCADA 后端配置修改

**问题**：SCADA 后端的配置文件中，数据库和 Redis 地址硬编码了开发环境地址（如 `127.0.0.1` 或远程公网 IP），在 Docker 容器中不适用。

**修改 1：`application.yml`（Redis 地址）**

文件路径：`iot-scada-api/ruoyi-admin/src/main/resources/application.yml`

找到 Redis 配置部分：

```yaml
# 原来
redis:
  host: 127.0.0.1
  port: 6379

# 改为（读取环境变量，默认回退到 127.0.0.1）
redis:
  host: ${REDIS_HOST:127.0.0.1}
  port: 6379
  password: ${REDIS_PASSWORD:***}
```

**修改 2：`application-druid.yml`（数据库地址）**

文件路径：`iot-scada-api/ruoyi-admin/src/main/resources/application-druid.yml`

找到数据库配置部分：

```yaml
# 原来（硬编码了远程地址）
master:
  url: jdbc:mysql://117.89.85.67:3306/maotu-scada?...
  username: maotu-scada
  password: maotu-scada

# 改为（读取环境变量）
master:
  url: jdbc:mysql://${DATABASE_HOST:127.0.0.1}:3306/${DATABASE_NAME:scada}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
  username: root
  password: ${DATABASE_PASSWORD:***}
```

**修改后需要重新构建 JAR**（见 10.5 节）。

#### DC3 前端 Nginx 配置修改（如果 DC3 后端未部署）

如果 DC3 后端无法部署（缺少数据库），Nginx 配置中引用 `dc3-gateway` 会导致容器不断重启。

文件路径：`deploy/nginx/nginx.conf`

注释掉 API 代理部分：

```nginx
# 注释掉这段，因为 dc3-gateway 没有运行
# location ^~ /api/ {
#     proxy_pass http://dc3-gateway:8000/api/;
# }
```

### 10.7 启动部署

#### 方案 A：只部署 SCADA + DC3 前端（当前实际可行的方案）

创建一个精简的 `docker-compose-scada.yml`：

```yaml
services:
  # SCADA 数据库
  iot-scada-mysql:
    image: mysql:8.0.24
    container_name: iot-scada-mysql
    environment:
      - MYSQL_ROOT_PASSWORD=***
    volumes:
      # 初始化脚本：容器第一次启动时自动执行
      - ./scada/init.sql:/docker-entrypoint-initdb.d/init.sql
      # 数据持久化：即使容器删除，数据还在
      - ./mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
      interval: 5s
      timeout: 10s
      retries: 60
    networks:
      - dc3net

  # SCADA 缓存
  iot-scada-redis:
    image: redis:6.2.6
    container_name: iot-scada-redis
    networks:
      - dc3net

  # SCADA 后端
  iot-scada-server:
    build:
      context: ./scada/
      dockerfile: ./Dockerfile
    image: iot-scada-server:2025.2.1
    container_name: iot-scada-server
    environment:
      REDIS_HOST: iot-scada-redis
      DATABASE_NAME: scada
      DATABASE_HOST: iot-scada-mysql
      DATABASE_PASSWORD: ***
    healthcheck:
      test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:8887 || exit 1"]
      interval: 5s
      timeout: 10s
      retries: 60
    volumes:
      - ./scada/logs:/app/logs
      - ./scada/uploadPath:/app/uploadPath
    networks:
      - dc3net
    # 等 MySQL 健康检查通过后再启动
    depends_on:
      iot-scada-mysql:
        condition: service_healthy

  # SCADA 前端
  iot-scada-web:
    image: nginx:stable-alpine
    restart: always
    ports:
      - '3001:80'
    container_name: iot-scada-web
    volumes:
      - ./scada/log:/var/log/nginx
      - ./scada/nginx.conf:/etc/nginx/nginx.conf
      - ./scada/html:/usr/share/nginx/html
    networks:
      - dc3net
    depends_on:
      - iot-scada-server

  # DC3 前端（只有静态页面）
  dc3-web:
    image: nginx:stable-alpine
    restart: always
    ports:
      - '3000:80'
    container_name: dc3-web
    volumes:
      - ./nginx/log:/var/log/nginx
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/html:/usr/share/nginx/html
    networks:
      - dc3net

# 所有容器共享同一个网络，可以通过容器名互相访问
networks:
  dc3net:
    driver: bridge
```

**启动命令**：

```bash
cd /home/你的用户名/Projects/iot-platform/deploy/

# 启动所有服务
sudo docker-compose -f docker-compose-scada.yml up -d
```

`-d` 表示后台运行（detach 模式）。

#### 方案 B：完整部署（需要 DC3 数据库）

如果你拿到了 DC3 的 PostgreSQL 初始化脚本（`dc3.sql`），可以按以下步骤：

**Step 1：准备 DC3 数据库**

```bash
# 创建存放初始化脚本的目录
mkdir -p /home/你的用户名/Projects/iot-platform/deploy/postgres-init

# 把拿到的 dc3.sql 放进去
cp /path/to/dc3.sql /home/你的用户名/Projects/iot-platform/deploy/postgres-init/
```

**Step 2：修改 `docker-compose-env.yml`**

把 PostgreSQL 服务从 `pnoker/dc3-postgres:2025.2.dev` 改为标准镜像，并挂载初始化脚本：

```yaml
services:
  postgres:
    image: postgres:15          # 改用标准镜像
    restart: always
    ports:
      - '35432:5432'
    environment:
      - POSTGRES_USER=dc3
      - POSTGRES_PASSWORD=***
      - POSTGRES_DB=dc3
    volumes:
      - postgres:/var/lib/postgresql/data
      - ./postgres-init:/docker-entrypoint-initdb.d   # 挂载初始化脚本
    networks:
      - dc3net

volumes:
  postgres:
```

**Step 3：先启动基础设施**

```bash
cd /home/你的用户名/Projects/iot-platform/deploy/
sudo docker-compose -f docker-compose-env.yml up -d
```

**Step 4：等待数据库初始化完成**

PostgreSQL 容器第一次启动时会自动执行 `/docker-entrypoint-initdb.d/` 下的 SQL 脚本，创建所有表和数据。这个过程可能需要 1-5 分钟。

**Step 5：启动应用服务**

```bash
sudo docker-compose -f docker-compose.yml up -d
```

### 10.8 验证服务状态

```bash
# 查看所有容器运行状态
docker compose ps

# 或者查看特定服务状态
docker compose -f docker-compose-env.yml ps
docker compose -f docker-compose.yml ps
```

### 10.9 访问系统

- **DC3 IoT 管理平台**: http://服务器IP:3000
- **SCADA 组态系统**: http://服务器IP:3001

### 10.10 停止所有服务

```bash
# 停止应用服务
docker compose -f docker-compose.yml down

# 停止基础设施服务（数据库、缓存、消息队列）
docker compose -f docker-compose-env.yml down
```

> **注意**: 使用 `down` 命令会停止并删除容器，但数据卷（volumes）会保留。如需同时删除数据卷，请添加 `-v` 参数（慎用！）:
> ```bash
> docker compose -f docker-compose-env.yml down -v
> ```

---

## 十一、开发工具与工程化

### 11.1 ESLint

**类比**：像语文作文的自动批改工具。

ESLint 是 JavaScript/TypeScript 的**代码检查工具**：
- 检查语法错误。
- 检查代码风格（比如是否用了分号、缩进几个空格）。
- 检查潜在 Bug（比如定义了变量没使用）。

### 11.2 Prettier

**类比**：像 Word 的"自动排版"功能。

Prettier 是**代码格式化工具**：
- 不管你怎么写的，保存后自动按统一风格排版。
- 解决团队协作中的"代码风格之争"。

**本项目中的 DC3 前端 Prettier 配置**：
- 4 空格缩进
- 单引号
- 不要分号
- 一行最长 180 字符

### 11.3 Husky + lint-staged

**类比**：像考试前的自动检查，提交代码前自动跑一遍检查。

- **Husky**：Git 钩子工具，在 `git commit` 前自动执行脚本。
- **lint-staged**：只检查本次提交修改的文件。

**流程**：
```
git commit -m "xxx"
  ↓
Husky 触发 pre-commit 钩子
  ↓
lint-staged 对改动的文件运行 ESLint + Prettier
  ↓
有问题 → 阻止提交，提示修改
没问题 → 正常提交
```

### 11.4 Git / Git 工作流

**你已经熟悉的概念**：`git add`、`git commit`、`git push`。

**补充概念**：
- **分支（Branch）**：从主代码线分叉出来独立开发，完成后合并回去。
- **.gitignore**：告诉 Git 哪些文件不要跟踪（如 `node_modules/`、`*.log`）。

---

## 十二、Java 特有概念

### 12.1 JDK / JRE / JVM

| 术语 | 全称 | 类比 | 作用 |
|------|------|------|------|
| **JDK** | Java Development Kit | Python 安装包 + pip | Java 开发工具包（写代码必备） |
| **JRE** | Java Runtime Environment | Python 解释器 | Java 运行环境（只运行不开发） |
| **JVM** | Java Virtual Machine | Python 解释器内核 | Java 虚拟机，运行字节码 |

**字节码**：Java 代码编译成 `.class` 文件（不是机器码），JVM 负责解释/编译执行。

**"一次编写，到处运行"**：编译好的 Java 程序只要有 JVM 就能跑，不管底层是 Windows 还是 Linux。

### 12.2 JAR 文件

**类比**：像 Python 的 `.zip` 打包文件，包含了程序的所有类和资源。

Spring Boot 用 `spring-boot-maven-plugin` 打包成**可执行 JAR**：
```bash
java -jar myapp.jar    # 直接运行，不需要额外配置 Tomcat
```

### 12.3 Spring Boot Actuator

**类比**：像汽车的仪表盘，显示发动机转速、油量等健康指标。

提供生产环境的监控端点：
- `/actuator/health`：服务是否健康
- `/actuator/metrics`：内存使用、请求数量等指标

---

## 十三、网络与安全概念

### 13.1 HTTP / HTTPS / TLS

**你已经熟悉的概念**：浏览器地址栏的 `http://`。

- **HTTP**：明文传输，数据可能被窃听或篡改。
- **HTTPS**：HTTP + TLS/SSL 加密，数据安全传输。
- **TLS/SSL**：加密协议，像给信件加上密码锁。

**本项目现状**：目前使用 HTTP，没有配置 HTTPS。

### 13.2 CORS（跨域资源共享）

**你已经遇到过的问题**：前端在 `http://localhost:5173`，后端在 `http://localhost:5000`，浏览器报"跨域错误"。

**原因**：浏览器的**同源策略**（Same-Origin Policy）限制不同域名/端口的请求。

**解决方案**：
- 开发时：Vite 代理或 Nginx 反向代理（让浏览器以为请求的是同域）。
- 生产时：后端配置 CORS 响应头，允许特定域名访问。

### 13.3 WebSocket

**你已经熟悉的概念**：HTTP 是"一问一答"（请求 → 响应）。

**WebSocket**：
- 建立一次连接后，服务器可以主动推送数据给客户端。
- 适合实时场景：聊天、股票行情、设备实时数据推送。

**本项目中的例子**：SCADA 系统用 WebSocket 推送实时设备数据到前端大屏。

---

## 十四、学习路径建议

如果你要逐步理解并参与这个项目，建议按以下顺序学习：

### 第一阶段：巩固基础
1. 深入学 JavaScript（ES6+：箭头函数、Promise、async/await、解构赋值）
2. 学 Vue 3 基础（选项式 API 和组合式 API）
3. 理解 npm/pnpm（包管理）

### 第二阶段：理解现代前端工程
4. 学 TypeScript 基础类型系统
5. 理解 Vite 和前端构建流程
6. 学 Element Plus 常用组件
7. 理解 Axios 和 HTTP 拦截器

### 第三阶段：理解后端
8. 学 Java 基础语法（如果你要做后端）
9. 理解 Spring Boot 的 Controller/Service/Mapper 分层
10. 学 MyBatis Plus 的基本 CRUD

### 第四阶段：理解部署与运维
11. 学 Docker 基础和常用命令
12. 理解 Docker Compose 的编排逻辑
13. 学 Nginx 反向代理配置
14. 理解日志排查和容器调试

### 第五阶段：深入 IoT 领域
15. 了解 MQTT 协议和消息发布订阅模型
16. 学习工业通信协议（Modbus、OPC UA）的基础概念
17. 理解时序数据库的数据模型
18. 学习 SCADA 组态系统的设计思路

---

## 十五、总结

这个项目是一个完整的**工业物联网平台**，包含：

| 系统 | 用途 | 技术特点 |
|------|------|---------|
| **DC3 IoT 管理平台** | 设备管理、数据采集、报警处理 | 微服务架构、Vue 3 + TS、Spring Cloud |
| **SCADA 组态系统** | 可视化监控大屏、拖拽组态 | 单体架构、Vue 3 + JS、Spring Boot |

**核心价值**：
- 让不懂代码的工程师也能搭建工业监控界面
- 让设备数据实时汇聚、存储、分析
- 让工厂运维从"人盯屏幕"变成"系统自动报警"

**技术亮点**：
- 前后端分离，现代前端工程化
- 微服务架构，服务独立扩展
- Docker 容器化，一次构建到处运行
- 多协议驱动，适配各种工业设备

---

> **文档信息**
> - 作者：张煜
> - 日期：2026-05-26
> - 版本：v1.0
> - 适用对象：有 HTML/CSS/JavaScript + Flask 基础的初学者
> - 项目地址：[IoT Platform](https://github.com/your-repo/iot-platform)