项目介绍
校园快递代收管理系统是一个面向高校的快递管理平台,旨在解决校园快递收发混乱、效率低下等问题。系统采用 Spring Boot + Vue.js 的前后端分离架构,实现了快递代收、分发、查询等核心功能。
技术栈
后端技术
- Spring Boot 2.5.x
- Spring Security
- MyBatis Plus
- MySQL 8.0
- Redis
- JWT
前端技术
- Vue.js 2.x
- Element UI
- Axios
- Vuex
- Vue Router
核心功能
1. 用户管理模块
- 学生注册登录
- 管理员账号管理
- 角色权限控制
2. 快递管理模块
- 快递信息录入
- 快递分发管理
- 快递状态追踪
- 取件码生成
3. 代收点管理
- 代收点信息维护
- 代收员管理
- 工作量统计
4. 通知提醒
- 到件通知
- 逾期提醒
- 系统公告
数据库设计
sql
-- 用户表
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`phone` varchar(20),
`role` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
);
-- 快递信息表
CREATE TABLE `express` (
`id` bigint NOT NULL AUTO_INCREMENT,
`tracking_number` varchar(50) NOT NULL,
`recipient_name` varchar(50) NOT NULL,
`recipient_phone` varchar(20) NOT NULL,
`pickup_code` varchar(10) NOT NULL,
`status` int NOT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`)
);
核心代码展示
后端接口示例
java
@RestController
@RequestMapping("/api/express")
public class ExpressController {
@Autowired
private ExpressService expressService;
@PostMapping("/create")
public Result createExpress(@RequestBody ExpressDTO expressDTO) {
Express express = expressService.createExpress(expressDTO);
return Result.success(express);
}
@GetMapping("/list")
public Result getExpressList(ExpressQuery query) {
Page<Express> page = expressService.getExpressList(query);
return Result.success(page);
}
}
前端代码示例
vue
<template>
<div class="express-list">
<el-table :data="expressList" border>
<el-table-column prop="trackingNumber" label="快递单号"/>
<el-table-column prop="recipientName" label="收件人"/>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
{{ getStatusText(scope.row.status) }}
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" @click="handlePickup(scope.row)">
确认取件
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
项目亮点
-
安全性设计
- 采用 JWT + Redis 实现登录认证
- 接口权限精细化控制
- 敏感数据加密存储
-
性能优化
- Redis 缓存热点数据
- MyBatis Plus 分页查询优化
- 前端组件按需加载
-
用户体验
- 响应式布局设计
- 取件码短信通知
- 操作日志完整记录
项目总结
通过本项目的开发,不仅实现了校园快递管理的信息化和规范化,也积累了完整的项目开发经验。项目中运用了主流的技术栈,采用前后端分离架构,在性能优化和用户体验方面都做了细致的工作。
项目收获
- 掌握了完整的项目开发流程
- 深入理解前后端分离架构
- 提升了代码质量和安全意识
- 积累了实际项目经验
后续优化方向
- 引入消息队列处理异步任务
- 添加微信小程序端
- 优化系统监控和告警机制
- 引入容器化部署方案
结语
校园快递代收管理系统是一个实用性强、技术栈完整的项目。通过这个项目,不仅解决了实际问题,也提供了很好的学习参考。
校园快递管理系统核心模块详解
一、用户管理模块
1. 用户角色设计
java
public enum UserRole {
STUDENT("学生"),
ADMIN("管理员"),
COURIER("快递员"),
PICKUP_STAFF("代收点工作人员");
private String description;
UserRole(String description) {
this.description = description;
}
}
2. 学生注册登录
2.1 注册流程
java
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
public void register(RegisterDTO dto) {
// 1. 验证学号是否已注册
if(userMapper.existsByStudentId(dto.getStudentId())) {
throw new BusinessException("该学号已注册");
}
// 2. 验证手机号
if(!PhoneUtil.isValid(dto.getPhone())) {
throw new BusinessException("手机号格式不正确");
}
// 3. 密码加密
String encodedPassword = passwordEncoder.encode(dto.getPassword());
// 4. 保存用户信息
User user = User.builder()
.studentId(dto.getStudentId())
.username(dto.getUsername())
.password(encodedPassword)
.phone(dto.getPhone())
.role(UserRole.STUDENT)
.build();
userMapper.insert(user);
}
}
2.2 登录认证
java
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private UserService userService;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private RedisTemplate redisTemplate;
public LoginVO login(LoginDTO dto) {
// 1. 验证用户名密码
User user = userService.validatePassword(dto);
// 2. 生成token
String token = jwtUtil.generateToken(user);
// 3. 存入Redis
redisTemplate.opsForValue().set(
"TOKEN:" + user.getId(),
token,
30,
TimeUnit.DAYS
);
return LoginVO.builder()
.token(token)
.userInfo(UserConverter.toVO(user))
.build();
}
}
3. 管理员账号管理
java
@RestController
@RequestMapping("/api/admin/user")
@PreAuthorize("hasRole('ADMIN')")
public class AdminUserController {
@Autowired
private UserService userService;
// 创建账号
@PostMapping("/create")
public Result createUser(@RequestBody AdminUserDTO dto) {
userService.createAdminUser(dto);
return Result.success();
}
// 禁用账号
@PostMapping("/disable/{userId}")
public Result disableUser(@PathVariable Long userId) {
userService.disableUser(userId);
return Result.success();
}
// 重置密码
@PostMapping("/reset-password/{userId}")
public Result resetPassword(@PathVariable Long userId) {
String newPassword = userService.resetPassword(userId);
return Result.success(newPassword);
}
}
4. 权限控制
java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 公开接口
.antMatchers("/api/auth/**").permitAll()
// 学生接口
.antMatchers("/api/student/**").hasRole("STUDENT")
// 快递员接口
.antMatchers("/api/courier/**").hasRole("COURIER")
// 管理员接口
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
}
二、快递管理模块
1. 快递信息录入
1.1 数据模型
java
@Data
@TableName("express")
public class Express {
@TableId(type = IdType.AUTO)
private Long id;
private String trackingNumber; // 快递单号
private String recipientName; // 收件人姓名
private String recipientPhone; // 收件人电话
private String address; // 收件地址
private String pickupCode; // 取件码
private ExpressStatus status; // 快递状态
private ExpressType type; // 快递类型
private Double weight; // 重量
private String remark; // 备注
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
1.2 快递录入接口
java
@RestController
@RequestMapping("/api/express")
public class ExpressController {
@Autowired
private ExpressService expressService;
@PostMapping("/create")
public Result createExpress(@RequestBody ExpressDTO dto) {
// 1. 生成取件码
String pickupCode = PickupCodeGenerator.generate();
// 2. 保存快递信息
Express express = Express.builder()
.trackingNumber(dto.getTrackingNumber())
.recipientName(dto.getRecipientName())
.recipientPhone(dto.getRecipientPhone())
.pickupCode(pickupCode)
.status(ExpressStatus.RECEIVED)
.build();
expressService.save(express);
// 3. 发送短信通知
smsService.sendPickupNotification(express);
return Result.success(express);
}
}
2. 快递分发管理
java
@Service
public class ExpressDistributionService {
@Autowired
private ExpressMapper expressMapper;
@Autowired
private PickupPointMapper pickupPointMapper;
// 分配快递到代收点
public void distributeExpress(Long expressId, Long pickupPointId) {
// 1. 验证快递和代收点
Express express = expressMapper.selectById(expressId);
PickupPoint point = pickupPointMapper.selectById(pickupPointId);
// 2. 更新快递状态和位置
express.setStatus(ExpressStatus.DISTRIBUTED);
express.setPickupPointId(pickupPointId);
express.setDistributionTime(LocalDateTime.now());
expressMapper.updateById(express);
// 3. 记录分发日志
saveDistributionLog(express, point);
}
}
3. 快递状态追踪
java
public enum ExpressStatus {
RECEIVED("已接收"),
DISTRIBUTED("已分发"),
READY_FOR_PICKUP("待取件"),
PICKED_UP("已取件"),
EXPIRED("已过期"),
RETURNED("已退回");
private String description;
}
@Service
public class ExpressTrackingService {
public List<ExpressTrackingVO> getTrackingInfo(String trackingNumber) {
List<ExpressTracking> trackingList = trackingMapper.selectByTrackingNumber(trackingNumber);
return trackingList.stream()
.map(tracking -> ExpressTrackingVO.builder()
.status(tracking.getStatus())
.operation(tracking.getOperation())
.operator(tracking.getOperator())
.operateTime(tracking.getOperateTime())
.remark(tracking.getRemark())
.build())
.collect(Collectors.toList());
}
}
4. 取件码生成与验证
java
@Component
public class PickupCodeGenerator {
private static final int CODE_LENGTH = 6;
// 生成取件码
public static String generate() {
// 生成6位随机数字
Random random = new Random();
StringBuilder code = new StringBuilder();
for(int i = 0; i < CODE_LENGTH; i++) {
code.append(random.nextInt(10));
}
return code.toString();
}
// 验证取件码
public boolean verifyPickupCode(String trackingNumber, String inputCode) {
Express express = expressMapper.selectByTrackingNumber(trackingNumber);
if(express == null) {
throw new BusinessException("快递不存在");
}
if(!express.getPickupCode().equals(inputCode)) {
throw new BusinessException("取件码错误");
}
if(express.getStatus() == ExpressStatus.PICKED_UP) {
throw new BusinessException("该快递已被取走");
}
return true;
}
}
以上是用户管理模块和快递管理模块的核心代码实现。每个功能点都包含了:
- 数据模型设计
- 业务逻辑实现
- 接口封装
- 安全控制
- 异常处理
这样的设计确保了系统的:
- 功能完整性
- 安全性
- 可维护性
- 可扩展性
校园快递管理系统功能模块详解(续)
三、代收点管理模块
1. 代收点信息维护
1.1 数据模型设计
java
@Data
@TableName("pickup_point")
public class PickupPoint {
@TableId(type = IdType.AUTO)
private Long id;
private String name; // 代收点名称
private String location; // 具体位置
private String contact; // 联系方式
private Integer capacity; // 最大容量
private Integer currentLoad;// 当前存放数量
private String openTime; // 营业时间
private Boolean isActive; // 是否营业
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
1.2 代收点管理接口
java
@RestController
@RequestMapping("/api/admin/pickup-point")
@PreAuthorize("hasRole('ADMIN')")
public class PickupPointController {
@Autowired
private PickupPointService pickupPointService;
// 新增代收点
@PostMapping("/create")
public Result createPickupPoint(@RequestBody PickupPointDTO dto) {
PickupPoint point = pickupPointService.createPickupPoint(dto);
return Result.success(point);
}
// 更新代收点信息
@PutMapping("/update/{id}")
public Result updatePickupPoint(@PathVariable Long id, @RequestBody PickupPointDTO dto) {
pickupPointService.updatePickupPoint(id, dto);
return Result.success();
}
// 获取代收点容量统计
@GetMapping("/capacity-stats")
public Result getCapacityStats() {
List<PickupPointCapacityVO> stats = pickupPointService.getCapacityStats();
return Result.success(stats);
}
}
2. 代收员管理
2.1 代收员信息模型
java
@Data
@TableName("pickup_staff")
public class PickupStaff {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private String phone;
private Long pickupPointId; // 所属代收点
private String workSchedule; // 工作时间安排
private StaffStatus status; // 在职状态
private String idCard; // 身份证号
@TableField(exist = false)
private PickupPoint pickupPoint;
}
2.2 代收员管理服务
java
@Service
public class PickupStaffService {
@Autowired
private PickupStaffMapper staffMapper;
// 分配工作时间
public void assignWorkSchedule(Long staffId, List<WorkScheduleDTO> schedules) {
PickupStaff staff = staffMapper.selectById(staffId);
if(staff == null) {
throw new BusinessException("员工不存在");
}
// 验证时间安排是否合理
validateWorkSchedule(schedules);
// 更新工作时间
staff.setWorkSchedule(JSON.toJSONString(schedules));
staffMapper.updateById(staff);
}
// 统计代收员工作情况
public StaffWorkStatsVO getWorkStats(Long staffId, LocalDate startDate, LocalDate endDate) {
return StaffWorkStatsVO.builder()
.expressCount(getHandledExpressCount(staffId, startDate, endDate))
.customerRating(getCustomerRating(staffId))
.workHours(calculateWorkHours(staffId, startDate, endDate))
.build();
}
}
3. 工作量统计
java
@Service
public class WorkloadStatisticsService {
@Autowired
private ExpressMapper expressMapper;
@Autowired
private PickupStaffMapper staffMapper;
// 统计代收点工作量
public PickupPointStatsVO getPickupPointStats(Long pointId, LocalDate date) {
// 1. 统计快递处理量
Integer expressCount = expressMapper.countByPointAndDate(pointId, date);
// 2. 统计高峰期
List<PeakHourVO> peakHours = calculatePeakHours(pointId, date);
// 3. 统计员工效率
List<StaffEfficiencyVO> staffEfficiency = calculateStaffEfficiency(pointId, date);
return PickupPointStatsVO.builder()
.expressCount(expressCount)
.peakHours(peakHours)
.staffEfficiency(staffEfficiency)
.build();
}
// 生成工作量报表
public WorkloadReportVO generateWorkloadReport(LocalDate startDate, LocalDate endDate) {
// 1. 收集基础数据
List<DailyStatsVO> dailyStats = getDailyStats(startDate, endDate);
// 2. 计算关键指标
WorkloadMetrics metrics = calculateMetrics(dailyStats);
// 3. 生成图表数据
List<ChartDataVO> chartData = generateChartData(dailyStats);
return WorkloadReportVO.builder()
.dailyStats(dailyStats)
.metrics(metrics)
.chartData(chartData)
.build();
}
}
四、通知提醒模块
1. 到件通知
1.1 通知服务实现
java
@Service
public class NotificationService {
@Autowired
private SmsService smsService;
@Autowired
private WechatService wechatService;
@Autowired
private EmailService emailService;
// 发送到件通知
public void sendArrivalNotification(Express express) {
// 1. 构建通知内容
NotificationMessage message = NotificationMessage.builder()
.recipientName(express.getRecipientName())
.trackingNumber(express.getTrackingNumber())
.pickupCode(express.getPickupCode())
.pickupPoint(express.getPickupPoint().getName())
.build();
// 2. 多渠道发送通知
CompletableFuture.allOf(
CompletableFuture.runAsync(() -> smsService.sendNotification(message)),
CompletableFuture.runAsync(() -> wechatService.sendNotification(message)),
CompletableFuture.runAsync(() -> emailService.sendNotification(message))
).join();
// 3. 记录通知日志
saveNotificationLog(express.getId(), message);
}
}
2. 逾期提醒
java
@Service
@Slf4j
public class ExpressExpirationService {
@Autowired
private ExpressMapper expressMapper;
@Autowired
private NotificationService notificationService;
// 定时检查逾期快递
@Scheduled(cron = "0 0 8 * * ?") // 每天早上8点执行
public void checkExpiredExpress() {
log.info("开始检查逾期快递...");
// 1. 获取即将逾期的快递(3天内未取)
List<Express> expiringExpress = expressMapper.findExpiringExpress();
// 2. 发送提醒通知
for (Express express : expiringExpress) {
notificationService.sendExpirationWarning(express);
}
// 3. 处理已逾期快递(7天未取)
List<Express> expiredExpress = expressMapper.findExpiredExpress();
handleExpiredExpress(expiredExpress);
log.info("逾期快递检查完成");
}
// 处理逾期快递
private void handleExpiredExpress(List<Express> expiredExpress) {
for (Express express : expiredExpress) {
// 1. 更新状态为已逾期
express.setStatus(ExpressStatus.EXPIRED);
expressMapper.updateById(express);
// 2. 通知快递公司处理
notificationService.notifyCourierCompany(express);
// 3. 记录处理日志
saveExpirationLog(express);
}
}
}
3. 系统公告
3.1 公告模型
java
@Data
@TableName("system_announcement")
public class Announcement {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
private String content;
private AnnouncementType type;
private AnnouncementStatus status;
private LocalDateTime publishTime;
private LocalDateTime expireTime;
private Integer priority; // 优先级
private Boolean isSticky; // 是否置顶
}
3.2 公告管理服务
java
@Service
public class AnnouncementService {
@Autowired
private AnnouncementMapper announcementMapper;
// 发布公告
public void publishAnnouncement(AnnouncementDTO dto) {
Announcement announcement = Announcement.builder()
.title(dto.getTitle())
.content(dto.getContent())
.type(dto.getType())
.status(AnnouncementStatus.PUBLISHED)
.publishTime(LocalDateTime.now())
.expireTime(dto.getExpireTime())
.priority(dto.getPriority())
.isSticky(dto.getIsSticky())
.build();
announcementMapper.insert(announcement);
// 如果是重要公告,推送到用户
if(dto.getPriority() > 5) {
pushImportantAnnouncement(announcement);
}
}
// 获取活动公告
public List<AnnouncementVO> getActiveAnnouncements() {
// 1. 获取未过期的公告
List<Announcement> announcements = announcementMapper.findActiveAnnouncements();
// 2. 按优先级和置顶状态排序
return announcements.stream()
.sorted(this::compareAnnouncements)
.map(this::convertToVO)
.collect(Collectors.toList());
}
// 推送重要公告
private void pushImportantAnnouncement(Announcement announcement) {
// 1. 获取所有在线用户
List<User> onlineUsers = userService.getOnlineUsers();
// 2. 通过WebSocket推送
WebSocketMessage message = WebSocketMessage.builder()
.type(MessageType.ANNOUNCEMENT)
.data(convertToVO(announcement))
.build();
webSocketService.broadcastMessage(message);
}
}
4. 消息推送中心
java
@Service
public class MessagePushCenter {
@Autowired
private WebSocketService webSocketService;
@Autowired
private NotificationService notificationService;
// 统一消息推送
public void pushMessage(PushMessage message) {
// 1. 确定推送渠道
List<PushChannel> channels = determinePushChannels(message);
// 2. 执行推送
for (PushChannel channel : channels) {
switch (channel) {
case WEBSOCKET:
webSocketService.pushToUser(message.getUserId(), message);
break;
case SMS:
notificationService.sendSms(message);
break;
case WECHAT:
notificationService.sendWechatMessage(message);
break;
case EMAIL:
notificationService.sendEmail(message);
break;
}
}
// 3. 记录推送日志
savePushLog(message, channels);
}
// 消息模板管理
private String getMessageContent(MessageTemplate template, Map<String, Object> params) {
String content = template.getContent();
for (Map.Entry<String, Object> entry : params.entrySet()) {
content = content.replace("${" + entry.getKey() + "}",
String.valueOf(entry.getValue()));
}
return content;
}
}
这些模块的实现特点:
-
代收点管理
- 完整的CRUD功能
- 实时容量监控
- 灵活的工作排班
- 详细的统计分析
-
通知提醒
- 多渠道推送
- 异步处理
- 定时任务
- 消息模板
- 实时推送
关键技术点:
- 使用Spring Task处理定时任务
- 使用WebSocket实现实时推送
- 使用CompletableFuture处理异步通知
- 使用消息模板实现灵活配置
- 统计分析使用多维度数据聚合