markdown复制## 1. 项目背景与核心需求
去年参与某地应急物资调度项目时,我深刻体会到传统Excel表格管理救援物资的局限性。当某次需要紧急调配200顶帐篷时,工作人员花了近3小时才确认完库存分布,这种效率在救灾场景下是致命的。这正是我们开发这套救援物资管理系统的初衷。
系统需要解决三个核心痛点:
1. 物资状态实时可视化(库存量/位置/有效期)
2. 多维度快速检索(按类型/区域/紧急程度)
3. 全流程追踪(从入库到发放的完整链路)
## 2. 技术架构设计
### 2.1 整体技术栈选型
采用经典的三层架构:
- 前端:Vue.js + ElementUI(响应式布局适配移动终端)
- 后端:Spring Boot 2.7 + MyBatis Plus
- 数据库:MySQL 8.0(分库分表设计)
选择这套组合主要考虑:
1. 开发效率:MyBatis Plus的代码生成器可快速构建CRUD接口
2. 稳定性:Spring Boot的actuator模块提供完善的健康监控
3. 扩展性:预留Redis接入位置应对未来高并发场景
### 2.2 关键数据结构设计
物资主表包含这些核心字段:
```sql
CREATE TABLE `rescue_goods` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '物资ID',
`category_code` varchar(20) NOT NULL COMMENT '物资分类编码',
`current_stock` int DEFAULT '0' COMMENT '当前库存',
`safety_stock` int DEFAULT '0' COMMENT '安全库存',
`storage_location` point NOT NULL COMMENT 'GIS坐标',
`batch_no` varchar(50) DEFAULT NULL COMMENT '批次号',
`expire_date` datetime DEFAULT NULL COMMENT '失效日期',
PRIMARY KEY (`id`),
SPATIAL KEY `idx_location` (`storage_location`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现
3.1 智能预警模块
通过定时任务检查库存状态:
java复制@Scheduled(cron = "0 0 8 * * ?")
public void checkStock() {
List<RescueGoods> goodsList = mapper.selectList(null);
goodsList.forEach(goods -> {
if(goods.getCurrentStock() < goods.getSafetyStock()) {
String msg = String.format("%s库存不足!当前%d件,安全阈值%d件",
goods.getCategoryCode(),
goods.getCurrentStock(),
goods.getSafetyStock());
alertService.sendToAllManagers(msg);
}
});
}
3.2 物资调拨算法
考虑距离、库存、时效的加权计算:
java复制public List<Warehouse> calculateOptimalSources(RescueDemand demand) {
return warehouseMapper.selectList(new QueryWrapper<Warehouse>()
.select("id", "name", "ST_Distance(location, ST_GeomFromText(?)) as distance",
"current_stock")
.last("HAVING distance < 50 AND current_stock > " + demand.getAmount())
.orderByAsc("distance"))
.stream()
.sorted(Comparator.comparingDouble(w ->
w.getDistance() * 0.6 +
(1 - w.getCurrentStock()/demand.getAmount()) * 0.4))
.limit(3)
.collect(Collectors.toList());
}
4. 系统特色功能
4.1 可视化大屏
使用ECharts实现的三层展示架构:
- 宏观层:全国物资热力图
- 中观层:区域库存环形图
- 微观层:单品类库存趋势折线图
4.2 移动端适配
通过CSS媒体查询实现:
css复制@media screen and (max-width: 768px) {
.goods-card {
width: 100%;
margin-bottom: 10px;
}
.operation-buttons {
flex-direction: column;
}
}
5. 部署与优化实践
5.1 性能调优记录
通过JProfiler发现的问题:
- 物资分类树查询N+1问题 → 添加@Cacheable注解
- 批量导入时Full GC频繁 → 调整JVM参数为:
code复制-XX:+UseG1GC -Xms2048m -Xmx2048m -XX:MaxGCPauseMillis=200
5.2 安全防护措施
- 所有接口添加@PreAuthorize注解
- 敏感操作记录审计日志
- 采用BCryptPasswordEncoder加密密码
6. 踩坑经验分享
-
GIS坐标存储坑点:
- MySQL默认SRID是0,需要显式设置SRID=4326
- 空间索引要在建表时立即创建
-
并发修改库存的解决方案:
java复制@Transactional public boolean reduceStock(Long goodsId, int amount) { RescueGoods goods = mapper.selectByIdForUpdate(goodsId); if(goods.getCurrentStock() >= amount) { goods.setCurrentStock(goods.getCurrentStock() - amount); return mapper.updateById(goods) > 0; } return false; } -
文档编写建议:
- Swagger接口文档要包含枚举值说明
- 数据库字段注释要完整
- 复杂业务逻辑要有流程图辅助说明
这套系统在实际救灾演练中,将物资查询时间从小时级缩短到秒级,调拨方案生成时间控制在3分钟内。特别提醒:开发此类系统时,务必预留应急通道接口,在极端情况下允许跳过部分审批流程。
code复制