系统架构与公共模块说明
本文档描述项目整体架构、双应用部署、模块依赖、公共组件及开发规范要点。
帮助开发人员快速理解“为什么这样设计”以及各环节的特殊处理方式。
一、系统架构
1.1 双应用架构
| 应用 |
模块 |
端口 |
Context-Path |
用途 |
| AdminApplication |
haha-admin |
7070 |
/admin |
运营平台后端 |
| MiniappApplication |
haha-miniapp |
7077 |
/api |
小程序后端 |
两个应用共享 haha-common / haha-entity / haha-mapper / haha-service,通过 @ComponentScan(basePackages = {"com.haha"}) 和 @MapperScan("com.haha.mapper") 自动扫描。
为什么采用双应用而非单应用?
运营平台(haha-admin)和小程序后端(haha-miniapp)的认证方式、API风格、安全要求完全不同:
- 运营平台:Sa-Token 管理员登录,权限控制严格(@RequirePermission),仅运营人员访问
- 小程序:微信登录 + accessToken,面向所有用户,无权限注解
分离部署的优势:
- 独立扩缩容:小程序端流量远大于运营端
- 安全隔离:运营平台不暴露给用户端
- 独立发布:两端可独立上线,互不影响
1.2 模块依赖方向(严格单向)
haha-admin --> haha-service --> haha-mapper --> haha-entity
haha-miniapp --> haha-service --> haha-mapper --> haha-entity
|
haha-common <---------------------------+(所有模块均可依赖)
haha-sdk(独立模块,不依赖其他内部模块)
禁止反向依赖:
- haha-mapper 不可依赖 haha-service
- haha-entity 不可依赖 haha-mapper 或 haha-service
- haha-common 不可依赖任何其他内部模块
- haha-admin 与 haha-miniapp 不可互相依赖
1.3 技术栈版本
| 技术 |
版本 |
说明 |
| Java |
21 |
禁止使用 Java 22+ 特性 |
| Spring Boot |
4.0.3 |
使用 Jakarta 命名空间 |
| MyBatis-Plus |
3.5.16 |
mybatis-plus-spring-boot4-starter |
| Sa-Token |
1.45.0 |
sa-token-spring-boot3-starter |
| Hutool |
5.8.40 |
禁止使用 hutool 6.x API |
| FastJson2 |
2.0.53 |
禁止使用 fastjson (v1) |
| Lombok |
1.18.36 |
-- |
| Jakarta EE |
Jakarta |
非 Javax |
二、前端应用
2.1 运营平台(haha-admin-web)
- 框架:Vue 3 + Element Plus + TypeScript
- 构建:Vite
- 状态管理:Pinia
- 路由:Vue Router
2.2 用户小程序(haha-mp)
- 框架:UniApp + Vue 3 + TypeScript
- 构建:Vite
- 微信登录 + 支付分集成
2.3 管理端小程序(haha-admin-mp)
- 框架:UniApp + Vue 3 + TypeScript
- 用途:合作商管理、门店巡检等
三、公共模块 (haha-common)
3.1 枚举类 (com.haha.common.enums)
| 枚举 |
说明 |
code类型 |
| OrderStatus |
订单状态 |
int |
| PayStatus |
支付状态 |
String |
| PaymentChannel |
支付渠道 |
String |
| DeviceDoorStatus |
门状态 |
String |
| DeviceAlertType |
告警类型 |
String |
| ActivityTypeEnum |
活动类型 |
int |
| ActivityStatusEnum |
活动状态 |
int |
| CouponTypeEnum |
优惠券类型 |
int |
| CouponStatusEnum |
优惠券状态 |
int |
| DiscountTypeEnum |
折扣类型 |
int |
| ValidTypeEnum |
有效期类型 |
int |
| DistributeTypeEnum |
发放类型 |
int |
| ApplyScopeEnum |
适用范围 |
int |
| OpenType |
开门类型 |
String |
| InviteStatusEnum |
邀请状态 |
int |
| InviteRewardStatusEnum |
邀请奖励状态 |
int |
| PayScoreState |
支付分状态 |
String |
枚举规范:
- 只含
code + description/label 字段
- 必须提供
fromCode() / getByCode() 静态方法
- 数据库存储
code 值,禁止存储 description
3.2 常量类 (com.haha.common.constant)
| 常量类 |
说明 |
| OrderConstants |
订单状态/支付状态/订单类型常量 |
| DeviceConstants |
设备相关常量 |
| MarketingConstants |
营销相关常量 |
| RedisConstants |
Redis Key 定义 |
| CallbackConstants |
回调类型常量 |
| CommonConstants |
通用常量 |
| ResponseEnum |
业务响应码枚举 |
3.3 通用VO
| VO |
说明 |
| Result<T> |
统一返回封装(code/message/data) |
| PageResult<T> |
分页返回(通过 PageResult.of(IPage<T>) 转换) |
| StatusLabel |
状态标签(label + color) |
| OrderVO |
订单详情VO |
3.4 统一返回格式
{
"code": 200,
"message": "操作成功",
"data": { ... }
}
| 场景 |
code |
message |
| 成功 |
200 |
操作成功 / 具体描述 |
| 参数错误 |
400 |
字段错误描述 |
| 未登录 |
401 |
未登录 / token已过期 |
| 无权限 |
403 |
无访问权限 |
| 资源不存在 |
404 |
xxx不存在 |
| 业务异常 |
自定义 |
BusinessException 消息 |
| 系统异常 |
500 |
系统繁忙,请稍后重试 |
四、哈哈SDK (haha-sdk)
4.1 用途
独立模块,封装与哈哈平台(智能售卖机设备平台)的API交互,不依赖其他内部模块。
4.2 核心功能
| 功能 |
说明 |
| 设备API |
开门、查询状态、设置温度/音量 |
| 商品API |
商品查询、同步 |
| 订单API |
创建订单、查询订单 |
| 回调验证 |
签名校验 |
4.3 认证方式
通过 authToken 进行设备级认证,SDK内部处理签名和请求构建。
五、权限体系
5.1 运营平台权限(Sa-Token)
- 权限注解:
@RequirePermission("module:operation")
- operation 标准值:
read / create / update / delete / other
- 小程序端不需要
@RequirePermission(通过 accessToken 鉴权)
5.2 数据权限 (DataPermission)
支持按门店维度的数据隔离,运营人员只能查看授权门店的数据。
5.3 操作日志
- 注解:
@Log(module = "模块名", operation = OperationType.XXX, summary = "描述")
- OperationType:CREATE / UPDATE / DELETE / OTHER
- 读操作不加
@Log
六、数据库规范
6.1 表命名
- 前缀
t_,如 t_order、t_device
- 关联表:
t_{主实体}_{关联实体},如 t_activity_device、t_coupon_shop
6.2 ID策略
- 全局雪花算法:
@TableId(type = IdType.ASSIGN_ID)
- 数据库列类型:BIGINT
- 禁止自增ID
6.3 字段命名
- 数据库列:下划线(create_time, pay_status)
- Java字段:驼峰(createTime, payStatus)
- 自动映射:
map-underscore-to-camel-case: true
6.4 XML映射文件
- 位置:
haha-mapper/src/main/resources/mapper/XxxMapper.xml
- 必须定义
resultMap,禁止 resultType
- 逻辑删除不会自动添加到手写SQL中
七、数据库表总览
核心业务表
| 表名 |
说明 |
| t_order |
订单表 |
| t_order_goods |
订单商品明细 |
| t_order_item |
订单商品项 |
| t_device |
设备表 |
| t_shop |
门店表 |
| t_product |
商品表 |
| t_device_inventory |
设备库存表 |
| t_door_record |
开关门记录表 |
| t_user |
用户表 |
| t_account |
用户账户表 |
营销优惠表
| 表名 |
说明 |
| t_marketing_activity |
营销活动表 |
| t_activity_shop |
活动-门店关联 |
| t_activity_device |
活动-设备关联 |
| t_activity_product |
活动-商品关联 |
| t_coupon_template |
优惠券模板表 |
| t_user_coupon |
用户优惠券表 |
| t_coupon_shop |
优惠券-门店关联 |
| t_coupon_product |
优惠券-商品关联 |
| t_coupon_distribute |
优惠券发放记录 |
| t_timed_discount_activity |
定时折扣活动表 |
| t_timed_discount_device |
定时折扣-设备关联 |
| t_timed_discount_shop |
定时折扣-门店关联 |
| t_timed_discount_product |
定时折扣-商品关联 |
| t_timed_discount_record |
定时折扣执行记录 |
| t_timed_discount_statistics |
定时折扣统计 |
| t_invite_activity |
邀请活动表 |
| t_invite_record |
邀请记录表 |
| t_invite_reward |
邀请奖励表 |
| t_marketing_statistics |
营销统计表 |
库存管理表
| 表名 |
说明 |
| t_stock_record |
补货记录表 |
| t_stock_record_item |
补货明细表 |
| t_inventory_log |
库存变更日志 |
| t_price_adjustment_log |
价格调整日志 |
系统管理表
| 表名 |
说明 |
| t_admin |
管理员表 |
| t_role |
角色表 |
| t_role_permission |
角色权限关联 |
| t_data_permission |
数据权限表 |
| t_operation_log |
操作日志表 |
| t_dict_type |
字典类型表 |
| t_dict_data |
字典数据表 |
| t_device_alert_record |
设备告警记录 |
| t_announcement |
公告表 |
分销模块表
| 表名 |
说明 |
| t_distributor |
合作商表 |
| t_distributor_commission |
佣金记录表 |
| t_distributor_config |
合作商配置表 |
| t_distributor_referral |
推荐记录表 |
| t_distributor_withdrawal |
提现记录表 |
| t_distributor_monthly_report |
月度报表 |
统计报表表
| 表名 |
说明 |
| t_stat_category_daily |
品类日统计 |
| t_stat_device_daily |
设备日统计 |
| t_stat_product_daily |
商品日统计 |
| t_stat_shop_daily |
门店日统计 |
| t_stat_user_repurchase |
用户复购统计 |
八、层模板管理
8.1 LayerTemplate 实体
设备货架层配置模板,定义每一层的商品排列方式。
8.2 核心功能
| 功能 |
说明 |
| 模板CRUD |
创建/编辑/删除层模板 |
| 层配置 |
每层的商品类型、数量、位置 |
| 设备应用 |
将模板应用到指定设备 |
九、开发规范要点
- Long类型序列化:所有 Long 类型 ID 和外键字段必须添加
@JsonSerialize(using = ToStringSerializer.class) 防精度丢失
- 日期格式:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
- 金额字段:必须使用
BigDecimal,禁止 double / float
- 依赖注入:构造器注入(
final + @RequiredArgsConstructor),循环依赖时用 @Autowired @Lazy
- 事务:写操作必须
@Transactional(rollbackFor = Exception.class)
- 分页校验:
page < 1 设为 1,pageSize > 100 设为 10
- 业务异常:使用
BusinessException + ResponseEnum,禁止 Controller 中抛出未处理异常