10 KiB
10 KiB
实现要点分析:
- 动态地图加载: 算法从数据库动态加载地图数据,包括障碍物信息和地图尺寸,使得路径规划能够适应地图的变化。
- 优先队列优化: 使用优先队列(PriorityQueue)存储开放列表,确保每次都能高效地选择F值最小的节点,大大提高了算法效率。
- 曼哈顿距离启发函数: 选择曼哈顿距离作为启发函数,适合网格化的移动模式,能够准确估计网格间的距离。
- 路径重建: 通过记录每个节点的父节点,实现了从终点回溯到起点的路径重建,返回完整的路径点列表。
程序流程图:
flowchart TD
A[开始] --> B[加载地图数据]
B --> C[初始化开放列表和关闭列表]
C --> D[将起点加入开放列表]
D --> E{开放列表为空?}
E -->|是| F[返回空路径]
E -->|否| G[从开放列表取出F值最小的节点]
G --> H{是终点?}
H -->|是| I[重建并返回路径]
H -->|否| J[处理相邻节点]
J --> E
API接口:
@RestController
@RequestMapping("/api/pathfinding")
@RequiredArgsConstructor
public class PathfindingController {
private final AStarService aStarService;
@GetMapping("/find")
@PreAuthorize("hasRole('GRID_WORKER')")
public ResponseEntity<List<Point>> findPath(
@RequestParam int startX, @RequestParam int startY,
@RequestParam int endX, @RequestParam int endY) {
Point start = new Point(startX, startY);
Point end = new Point(endX, endY);
List<Point> path = aStarService.findPath(start, end);
return ResponseEntity.ok(path);
}
}
3. 反馈管理模块
反馈管理模块是系统的核心业务模块之一,负责处理用户提交的环境问题反馈。我实现了完整的反馈提交、审核和处理流程,包括多条件查询、状态流转和文件上传等功能。
关键代码展示:
@RestController
@RequestMapping("/api/feedback")
@RequiredArgsConstructor
public class FeedbackController {
private final FeedbackService feedbackService;
/**
* 提交反馈(正式接口)
* 使用multipart/form-data格式提交反馈,支持附件上传
*/
@PostMapping(value = "/submit", consumes = {"multipart/form-data"})
@PreAuthorize("isAuthenticated()")
public ResponseEntity<Feedback> submitFeedback(
@Valid @RequestPart("feedback") FeedbackSubmissionRequest request,
@RequestPart(value = "files", required = false) MultipartFile[] files,
@AuthenticationPrincipal CustomUserDetails userDetails) {
Feedback createdFeedback = feedbackService.submitFeedback(request, files);
return new ResponseEntity<>(createdFeedback, HttpStatus.CREATED);
}
/**
* 获取所有反馈(分页+多条件过滤)
* 支持按状态、污染类型、严重程度、地理位置、时间范围和关键词进行组合查询
*/
@GetMapping
@PreAuthorize("isAuthenticated()")
public ResponseEntity<Page<FeedbackResponseDTO>> getAllFeedback(
@AuthenticationPrincipal CustomUserDetails userDetails,
@RequestParam(required = false) FeedbackStatus status,
@RequestParam(required = false) PollutionType pollutionType,
@RequestParam(required = false) SeverityLevel severityLevel,
@RequestParam(required = false) String cityName,
@RequestParam(required = false) String districtName,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
@RequestParam(required = false) String keyword,
Pageable pageable) {
Page<FeedbackResponseDTO> feedbackPage = feedbackService.getFeedback(
userDetails, status, pollutionType, severityLevel, cityName, districtName,
startDate, endDate, keyword, pageable);
return ResponseEntity.ok(feedbackPage);
}
/**
* 处理反馈 (例如, 批准)
*/
@PostMapping("/{id}/process")
@PreAuthorize("hasAnyRole('ADMIN', 'SUPERVISOR')")
public ResponseEntity<FeedbackResponseDTO> processFeedback(
@PathVariable Long id,
@Valid @RequestBody ProcessFeedbackRequest request) {
FeedbackResponseDTO updatedFeedback = feedbackService.processFeedback(id, request);
return ResponseEntity.ok(updatedFeedback);
}
}
服务层实现:
@Service
@RequiredArgsConstructor
public class FeedbackServiceImpl implements FeedbackService {
private final FeedbackRepository feedbackRepository;
private final UserAccountRepository userAccountRepository;
private final FileStorageService fileStorageService;
private final ApplicationEventPublisher eventPublisher;
@Override
public Feedback submitFeedback(FeedbackSubmissionRequest request, MultipartFile[] files) {
// 1. 获取当前用户
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String email = authentication.getName();
UserAccount user = userAccountRepository.findByEmail(email)
.orElseThrow(() -> new ResourceNotFoundException("User", "email", email));
// 2. 创建反馈实体
Feedback feedback = new Feedback();
feedback.setTitle(request.getTitle());
feedback.setDescription(request.getDescription());
feedback.setPollutionType(request.getPollutionType());
feedback.setSeverityLevel(request.getSeverityLevel());
feedback.setLatitude(request.getLatitude());
feedback.setLongitude(request.getLongitude());
feedback.setTextAddress(request.getTextAddress());
feedback.setGridX(request.getGridX());
feedback.setGridY(request.getGridY());
feedback.setStatus(FeedbackStatus.SUBMITTED);
feedback.setSubmitter(user);
feedback.setEventId(generateEventId());
// 3. 保存反馈
Feedback savedFeedback = feedbackRepository.save(feedback);
// 4. 处理附件
if (files != null && files.length > 0) {
List<Attachment> attachments = new ArrayList<>();
for (MultipartFile file : files) {
String fileName = fileStorageService.storeFile(file);
Attachment attachment = new Attachment();
attachment.setFileName(fileName);
attachment.setFilePath("/uploads/" + fileName);
attachment.setFileType(file.getContentType());
attachment.setFileSize(file.getSize());
attachments.add(attachment);
}
savedFeedback.setAttachments(attachments);
feedbackRepository.save(savedFeedback);
}
// 5. 发布事件,触发AI审核
eventPublisher.publishEvent(new FeedbackSubmittedEvent(savedFeedback));
return savedFeedback;
}
@Override
public FeedbackResponseDTO processFeedback(Long id, ProcessFeedbackRequest request) {
Feedback feedback = feedbackRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Feedback", "id", id));
// 验证状态转换是否有效
if (!isValidStatusTransition(feedback.getStatus(), request.getStatus())) {
throw new IllegalStateException("Invalid status transition from " +
feedback.getStatus() + " to " + request.getStatus());
}
// 更新反馈状态
feedback.setStatus(request.getStatus());
// 如果批准反馈,则更新为PENDING_ASSIGNMENT状态
if (request.getStatus() == FeedbackStatus.APPROVED) {
feedback.setStatus(FeedbackStatus.PENDING_ASSIGNMENT);
}
Feedback updatedFeedback = feedbackRepository.save(feedback);
// 如果反馈被批准,发布事件通知任务管理模块
if (request.getStatus() == FeedbackStatus.APPROVED) {
eventPublisher.publishEvent(new FeedbackApprovedEvent(updatedFeedback));
}
return mapToDTO(updatedFeedback);
}
// 生成唯一的事件ID
private String generateEventId() {
return "EMS-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-"
+ UUID.randomUUID().toString().substring(0, 8).toUpperCase();
}
// 验证状态转换是否有效
private boolean isValidStatusTransition(FeedbackStatus current, FeedbackStatus next) {
// 实现状态机逻辑
switch (current) {
case SUBMITTED:
return next == FeedbackStatus.AI_REVIEWED;
case AI_REVIEWED:
return next == FeedbackStatus.PENDING_REVIEW;
case PENDING_REVIEW:
return next == FeedbackStatus.APPROVED || next == FeedbackStatus.REJECTED;
case APPROVED:
return next == FeedbackStatus.PENDING_ASSIGNMENT;
case PENDING_ASSIGNMENT:
return next == FeedbackStatus.ASSIGNED;
case ASSIGNED:
return next == FeedbackStatus.PROCESSED;
case PROCESSED:
return next == FeedbackStatus.CLOSED;
default:
return false;
}
}
}
实现要点分析:
- 多部分表单处理: 使用
@RequestPart注解同时处理JSON数据和文件上传,实现了富媒体反馈提交。 - 事件驱动架构: 通过Spring的事件机制,实现了反馈提交后的异步处理,如AI审核和任务创建,提高了系统响应速度。
- 状态机模式: 使用状态机模式管理反馈的生命周期,确保状态转换的合法性,防止非法操作。
- 多条件动态查询: 实现了灵活的多条件组合查询,支持按状态、类型、严重程度、地理位置和时间范围等进行过滤。