Files
Environment-Monitoring-System/Report/系统实现_第二部分.md
ChuXun 02a830145e 1
2025-10-25 19:18:43 +08:00

242 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**实现要点分析**:
1. **动态地图加载**: 算法从数据库动态加载地图数据,包括障碍物信息和地图尺寸,使得路径规划能够适应地图的变化。
2. **优先队列优化**: 使用优先队列PriorityQueue存储开放列表确保每次都能高效地选择F值最小的节点大大提高了算法效率。
3. **曼哈顿距离启发函数**: 选择曼哈顿距离作为启发函数,适合网格化的移动模式,能够准确估计网格间的距离。
4. **路径重建**: 通过记录每个节点的父节点,实现了从终点回溯到起点的路径重建,返回完整的路径点列表。
**程序流程图**:
```mermaid
flowchart TD
A[开始] --> B[加载地图数据]
B --> C[初始化开放列表和关闭列表]
C --> D[将起点加入开放列表]
D --> E{开放列表为空?}
E -->|是| F[返回空路径]
E -->|否| G[从开放列表取出F值最小的节点]
G --> H{是终点?}
H -->|是| I[重建并返回路径]
H -->|否| J[处理相邻节点]
J --> E
```
**API接口**:
```java
@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. 反馈管理模块
反馈管理模块是系统的核心业务模块之一,负责处理用户提交的环境问题反馈。我实现了完整的反馈提交、审核和处理流程,包括多条件查询、状态流转和文件上传等功能。
**关键代码展示**:
```java
@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);
}
}
```
**服务层实现**:
```java
@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;
}
}
}
```
**实现要点分析**:
1. **多部分表单处理**: 使用`@RequestPart`注解同时处理JSON数据和文件上传实现了富媒体反馈提交。
2. **事件驱动架构**: 通过Spring的事件机制实现了反馈提交后的异步处理如AI审核和任务创建提高了系统响应速度。
3. **状态机模式**: 使用状态机模式管理反馈的生命周期,确保状态转换的合法性,防止非法操作。
4. **多条件动态查询**: 实现了灵活的多条件组合查询,支持按状态、类型、严重程度、地理位置和时间范围等进行过滤。