EMS4J是一款基于Spring Boot多模块架构的能源管理系统,支持预付费和能耗分析两种模式。系统具有远程设备的控制能力,支持按需、合并、包月等多种计费方式。支持微信支付与线下支付。提供尖峰平谷计量、阶梯电价、账户管理与财务核算等完整功能,兼容多协议设备接入。代码结构清晰,易于二次开发与功能扩展。
在AI能快速生成代码的今天,单纯“能运行”的代码正在贬值,而代码的品味与设计愈发珍贵。这种品味并非一蹴而就,它来自长期的架构锤炼与深刻的设计思考。
本项目正是这样一次实践:我对原有生产代码的架构进行了重构与精炼——通过清晰的层次划分和彻底的模块解耦,使核心逻辑更纯粹、更适应多变需求。
代码中融入了一些设计巧思,希望它能带来启发。正如“授人以鱼,不如授人以渔”,我更愿意分享的,是其中蕴含的设计思维与架构之道。
如果本项目对你有所帮助,欢迎点个 Star ⭐️ 作为支持,我将深感荣幸。
- 多协议设备接入
- 计费模式(按需付费 / 合并付费 / 包月付费)
- 计量计费(尖峰平谷 / 阶梯电价)
- 账户管理(开户 / 销户 / 充值)
- 远程控制(合闸 / 分闸 / 复费率设置)
- 财务核算(账单 / 流水 / 对账)
| 页面 | 截图 |
|---|---|
| 账户列表 | ![]() |
| 账户详情 | ![]() |
| 销户结算 | ![]() |
| 页面 | 截图 |
|---|---|
| 电表列表 | ![]() |
| 电表详情 | ![]() |
| 网关列表 | ![]() |
| 网关详情 | ![]() |
| 设备品类 | ![]() |
| 页面 | 截图 |
|---|---|
| 预警方案列表 | ![]() |
| 预警方案详情 | ![]() |
| 订单列表 | ![]() |
| 订单创建 | ![]() |
| 页面 | 截图 |
|---|---|
| 电价方案列表 | ![]() |
| 电价方案详情 | ![]() |
| 尖峰平谷时段 | ![]() |
系统支持按需、合并与包月三种计费模式。其中按需与合并模式都是根据实际的使用对余额扣费。按需模式每个水电表独立核算。合并模式是把金额充值在一个水电表上,其他的表都用这个金额。包月按周期固定金额结算。
典型流程为开户后进行充值,扣费并持续更新余额,余额不足或触达预警阈值时可联动通知与远程断闸。全量销户时会进行清算并生成结算订单,产生退费或补缴。
| 组件 | 版本 | 必需 |
|---|---|---|
| JDK | 17+ | 是 |
| Maven | 3.8+ | 是 |
| MySQL | 8.0+ | 是 |
| Redis | 6.0+ | 是 |
| RabbitMQ | 4.1+ | 否 |
| Node.js | 18.18+ | 前端开发/构建需要 |
| pnpm | 10.32+ | 前端开发/构建需要 |
先克隆项目:
git clone <repository-url>
cd ems4j后端依赖中间件可使用 Docker Compose 拉起:
cp deploy/env.example .env
docker compose -f deploy/compose/docker-compose.infra.yml up -d然后分别启动后端和前端:
# 后端
mvn clean package -DskipTests
java -jar ems-bootstrap/target/ems-0.1.0.jar --spring.profiles.active=dev
# 前端
cd frontend-web
pnpm install
pnpm dev默认访问地址:
- 后端 API 文档:
http://127.0.0.1:8080/doc.html - 前端页面:
http://127.0.0.1:4173
cp deploy/env.example .env
### 改模式运行模式使用:`ems-bootstrap/src/main/resources/application-docker.yml`
docker compose -f deploy/compose/docker-compose.full.yml up -d --build说明:
deploy/compose/docker-compose.infra.yml:只启动 MySQL / Redis / RabbitMQdeploy/compose/docker-compose.full.yml:同时启动 backend / frontend / middleware- RabbitMQ 镜像已集成
x-delayed-message插件
### 导入数据库
mysql -u <user> -p <db> < sql/ems.sql
### 安装RabbitMQ x-delayed-message 插件
### @see https://github.com/rabbitmq/rabbitmq-delayed-message-exchange编辑 ems-bootstrap/src/main/resources/application-dev.yml:
- 数据库连接(
spring.datasource) - Redis 连接(
spring.data.redis) - RabbitMQ 连接(
spring.rabbitmq,可选)
前端代理目标默认是 http://127.0.0.1:8080,可通过环境变量覆盖:
cd frontend-web
VITE_PROXY_TARGET=http://127.0.0.1:18080 pnpm dev构建并启动:
mvn clean package -DskipTests
java -jar ems-bootstrap/target/ems-0.1.0.jar --spring.profiles.active=dev# 全量构建(跳过测试)
mvn clean install -DskipTests
# 运行测试
mvn test
# 模块级构建/测试(示例)
mvn -pl ems-business/ems-business-device -am test
# 前端
cd frontend-web
pnpm typecheck
pnpm test:unit
pnpm test:unit:coverage
pnpm test:e2e| 类别 | 技术 |
|---|---|
| 语言/框架 | Java 17 / Spring Boot 3.5 |
| 持久层 | MyBatis-Plus / MySQL 8.0 |
| 缓存 | Redis / Redisson |
| 消息队列 | RabbitMQ(可选) |
| IoT 接入 | Netty |
| 认证 | Sa-Token + JWT |
| API 文档 | Knife4j / SpringDoc OpenAPI |
+-------------------------------+ +-------------------------------+
| ems-bootstrap | | ems-iot |
| (Web Service Entry) | | (IoT Service Standalone) |
+-------------------------------+ +-------------------------------+
| |
+-----------+-----------+-----------+ |
| | | | |
+--v-----+ +---v----+ +----v-------+ | |
| ems-web| | ems-mq | |ems-schedule| | |
|(HTTP | | (Msg) | | (Schedule)| | |
| API) | | | | | | |
+--+-----+ +---+----+ +-----+------+ | |
| | | | |
+-----------+------------+----------+------------------+
|
+------------------------------------------------------------------+
| ems-business |
| +------------+ +------------+ +------------+ +------------+ |
| | device | | account | | billing | | order | |
| | (Device Mgmt)| | (Account | | (Balance & | | (Trade & | |
| | | | Mgmt) | | Consume) | | Payment) | |
| +------------+ +------------+ +------------+ +------------+ |
| | lease | | plan | | aggregation| |
| | (Owner & | | (Pricing | | (Cross- | |
| | Space) | | Plan) | | domain) | |
| +------------+ +------------+ +------------+ |
+------------------------------------------------------------------+
|
+-----------+-----------+
| |
+--v-------------------+ +v-----------------------+
| ems-foundation | | ems-components |
| +------+ +---------+ | | +----------+ +------+ |
| | user | |integrat.| | | |datasource| | lock | |
| +------+ +---------+ | | +----------+ +------+ |
| +------+ +---------+ | | +---------+ +-------+ |
| | space| | system | | | | context | | redis | |
| +------+ +---------+ | | +---------+ +-------+ |
| +------+ +---------+ | +------------------------+
| | org | | notifi. | |
| +------+ +---------+ |
+----------------------+
|
+-------v-------+
| ems-common |
| (Common Utils)|
+---------------+
说明:
- ems-web 可直接依赖 ems-business 与 ems-foundation(用户/组织/空间/系统等基础域)。
- ems-web 仅依赖 service/dto,避免直接引用 repository/entity/mapper。
- ems-foundation 不反向依赖 ems-business/ems-web,保持基础域可复用。
+----------+ 命令下发 +----------+ 协议转换 +----------+
| ems-web |-------------->| ems-iot |-------------->| 设备 |
+----------+ +----------+ +----------+
^ | |
| | 数据上报 |
| v |
| +----------+ |
+-------------------| 业务层 |<---------------------+
业务结果 +----------+
|
v
+----------+
| MySQL |
+----------+
说明:
- ems-mq-api 提供消息契约与基础服务接口(基础设施层)。
- ems-mq-rabbitmq 属于业务消息应用层实现,承载业务消息监听与编排。
- 前端详细说明见
frontend-web/README.md。
| 厂商 | 类型 |
|---|---|
| 安科瑞 (Acrel) | 电表 / 网关 |
| 斯菲尔 (Sfere) | 电表 |
| 仪歌 (Yige) | 电表 |
| 燕赵 (Yke) | 电表 |
对接方式可分为两类:
- 设备直连(自有平台)
- 第三方 IoT 平台接入
- 建议在
ems-foundation/integration侧实现平台对接与数据同步,再与ems-iot/业务域协同。 - 推荐参考:
详细平台集成解决方案请参见:
| 文档 | 说明 |
|---|---|
| 开发实践指南 | 代码风格、命名约定及开发实践 |
| 业务模块文档 | 业务模块文档(设备、账户、财务、方案) |
| 基础模块文档 | 基础模块文档(用户、组织、空间、系统、集成) |
| IoT 模块文档 | IoT 模块文档,用于设备接入和协议集成 |
| 测试指南 | 单元测试和集成测试标准及最佳实践 |
本项目采用 MIT 许可证,详见 LICENSE。















