1. 项目背景与需求分析
胡小楼行政村位于华北平原农业区,现有农用灌溉机井32口,服务耕地面积约5800亩。在传统管理模式下,村民需要通过手写登记或口头预约的方式使用机井,经常出现以下问题:
- 排队混乱:农忙季节经常出现村民凌晨排队抢号的情况,去年曾因排队纠纷引发肢体冲突
- 水资源浪费:约35%的预约用户未按时使用但未及时取消,导致机井空转浪费
- 管理低效:村委会需要人工记录使用情况,每月统计用水量需要3-5个工作日
- 信息不对称:60%的村民反映不知道附近哪些机井当前可用,经常白跑一趟
实际调研数据显示:传统管理方式下机井平均利用率仅62%,而通过信息化系统可提升至85%以上
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 整体技术方案
采用分层架构设计,分为表现层、业务逻辑层、数据访问层三层结构:
code复制表现层:Vue3 + Element Plus
↓ (RESTful API)
业务逻辑层:Spring Boot 2.7 + Spring MVC
↓ (MyBatis)
数据访问层:MySQL 8.0
技术选型理由:
- Vue3:响应式特性适合频繁交互的预约场景,组合式API便于功能模块封装
- Element Plus:提供丰富的PC/移动端适配组件,减少UI开发工作量
- Spring Boot:快速构建RESTful服务,内置Tomcat简化部署
- MyBatis-Plus:增强的CRUD操作减少70%以上的基础SQL编写
2.2 数据库设计
核心表结构设计:
sql复制CREATE TABLE `well` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '机井名称',
`location` point NOT NULL COMMENT '地理坐标',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '0-可用 1-维修中',
`flow_rate` decimal(5,2) NOT NULL COMMENT '出水量(m³/h)',
PRIMARY KEY (`id`),
SPATIAL INDEX `idx_location` (`location`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `reservation` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`well_id` int NOT NULL,
`start_time` datetime NOT NULL,
`duration` int NOT NULL COMMENT '预约时长(分钟)',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '0-待审核 1-已预约 2-已取消',
`actual_water` decimal(8,2) DEFAULT NULL COMMENT '实际用水量',
PRIMARY KEY (`id`),
KEY `idx_user` (`user_id`),
KEY `idx_well_time` (`well_id`,`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意:location字段使用MySQL的GIS空间数据类型,便于后续距离计算和地图展示
3. 核心功能实现
3.1 预约业务流程
完整预约流程包含以下步骤:
- 身份认证:村民通过手机号+验证码登录,确保真实用户
- 机井查询:
- 地图展示周边3km范围内机井
- 筛选条件:状态、出水量、距离
- 时段选择:
- 系统自动排除冲突时段
- 显示历史用水量参考
- 提交预约:
- 需确认《用水公约》
- 设置提醒通知
- 审核通过:
- 村干部审核用水合理性
- 短信通知预约结果
java复制// 预约冲突检测核心逻辑
public boolean checkConflict(int wellId, LocalDateTime startTime, int duration) {
LocalDateTime endTime = startTime.plusMinutes(duration);
return reservationMapper.selectCount(new QueryWrapper<Reservation>()
.eq("well_id", wellId)
.eq("status", 1)
.and(wrapper -> wrapper
.between("start_time", startTime, endTime)
.or()
.le("start_time", startTime)
.ge("DATE_ADD(start_time, INTERVAL duration MINUTE)", startTime)
)) == 0;
}
3.2 地图集成方案
采用高德地图JavaScript API实现:
- 坐标转换:将MySQL中的POINT数据转换为高德坐标
- 覆盖物渲染:
- 绿色图标:可用机井
- 红色图标:维修中
- 点击弹出详情窗口
- 路径规划:提供导航到选定机井的路线
javascript复制// 地图初始化示例
const map = new AMap.Map('map-container', {
zoom: 14,
center: [116.397428, 39.90923]
});
// 添加机井标记
wells.forEach(well => {
const marker = new AMap.Marker({
position: well.location,
icon: well.status === 0 ? 'green.png' : 'red.png'
});
marker.on('click', () => {
showWellDetail(well);
});
map.add(marker);
});
4. 关键问题解决方案
4.1 高并发预约处理
农忙季节早8点可能出现集中预约,采用以下优化措施:
- Redis缓存:
- 预加载热门机井时段数据
- 使用SETNX实现分布式锁
- 数据库优化:
- 为reservation表添加复合索引(well_id, start_time)
- 使用悲观锁避免超卖
- 前端限流:
- 提交按钮防重复点击
- 失败请求自动重试机制
4.2 离线使用场景
考虑农村网络不稳定的情况:
- Service Worker缓存:关键页面和资源离线可用
- 本地存储:使用IndexedDB暂存未提交的预约
- 短信备用通道:当WebSocket断开时降级为短信通知
5. 安全防护措施
- 认证安全:
- 短信验证码60秒有效期
- 连续错误锁定机制
- 数据安全:
- 密码加盐哈希存储
- 敏感字段AES加密
- 接口防护:
- Spring Security防CSRF
- 预约接口频率限制
- 内容审核:
- 论坛敏感词过滤
- 图片OCR识别
实测效果:经过防护措施后,系统成功抵御了模拟的SQL注入和XSS攻击测试
6. 部署实施方案
6.1 硬件环境
- 村级服务器:NUC迷你主机(i5/16GB/512GB)
- 网络要求:4G路由器+备用有线宽带
- 供电保障:配备UPS不间断电源
6.2 软件部署
采用Docker容器化部署:
dockerfile复制# 后端服务
FROM openjdk:11
COPY target/well-booking.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
# 前端部署
FROM nginx:alpine
COPY dist/ /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
6.3 运维监控
- 健康检查:Spring Boot Actuator端点监控
- 日志收集:Filebeat + ELK日志系统
- 自动备份:每日凌晨3点全量备份+binlog增量
7. 实际应用效果
系统上线3个月后的关键指标:
| 指标 | 改进前 | 改进后 | 提升幅度 |
|---|---|---|---|
| 机井利用率 | 62% | 88% | +42% |
| 平均等待时间 | 2.3h | 0.5h | -78% |
| 纠纷事件 | 7起/月 | 0起/月 | 100% |
| 管理耗时 | 15h/周 | 3h/周 | -80% |
村民反馈的典型评价:
- "现在不用半夜排队了,手机上就能约"
- "系统会提醒我该去浇地,不会错过时间"
- "村干部说用水情况一目了然"
我在开发过程中最大的收获是理解了如何将技术真正应用到实际生产场景。比如最初设计的复杂预约规则在实际测试中发现农民难以理解,最终简化为"选择机井-选择时间-确认"三步流程。这让我意识到用户体验比技术先进性更重要。
