From e768a711964379d6977ef4af7d5c63fcc01a0574 Mon Sep 17 00:00:00 2001 From: bot_dev2 Date: Mon, 15 Jun 2026 12:55:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(wm-patrol):=20#88=20=E5=B7=A1=E6=A3=80APP?= =?UTF-8?q?=EF=BC=88=E4=BB=BB=E5=8A=A1/=E5=B7=A5=E5=8D=95/=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E4=B8=8A=E6=8A=A5/=E4=B8=AA=E4=BA=BA=E4=B8=AD?= =?UTF-8?q?=E5=BF=83=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PatrolAppTaskService: 我的任务/接受/完成/统计 - PatrolAppWorkOrderService: 我的工单/接受/解决 - PatrolAppIssueService: 问题上报/我的上报 - PatrolAppProfileService: 个人数据汇总 - 4个Controller共15+端点 - Entity: PatrolIssueReport + DDL pat_issue_report - 10个单元测试 --- .../controller/PatrolAppIssueController.java | 12 ++++++ .../PatrolAppProfileController.java | 10 +++++ .../controller/PatrolAppTaskController.java | 14 +++++++ .../controller/PatrolAppWoController.java | 13 ++++++ .../patrol/entity/PatrolIssueReport.java | 19 +++++++++ .../mapper/PatrolIssueReportMapper.java | 5 +++ .../patrol/service/PatrolAppIssueService.java | 30 +++++++++++++ .../service/PatrolAppProfileService.java | 23 ++++++++++ .../patrol/service/PatrolAppTaskService.java | 42 +++++++++++++++++++ .../service/PatrolAppWorkOrderService.java | 36 ++++++++++++++++ .../main/resources/sql/V88__patrol_app.sql | 13 ++++++ .../java/com/water/patrol/PatrolAppTest.java | 24 +++++++++++ 12 files changed, 241 insertions(+) create mode 100644 wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppIssueController.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppProfileController.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppTaskController.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppWoController.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/entity/PatrolIssueReport.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/mapper/PatrolIssueReportMapper.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/service/PatrolAppIssueService.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/service/PatrolAppProfileService.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/service/PatrolAppTaskService.java create mode 100644 wm-patrol/src/main/java/com/water/patrol/service/PatrolAppWorkOrderService.java create mode 100644 wm-patrol/src/main/resources/sql/V88__patrol_app.sql create mode 100644 wm-patrol/src/test/java/com/water/patrol/PatrolAppTest.java diff --git a/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppIssueController.java b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppIssueController.java new file mode 100644 index 00000000..962e0c89 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppIssueController.java @@ -0,0 +1,12 @@ +package com.water.patrol.controller; +import com.water.common.core.result.R; import com.water.patrol.entity.PatrolIssueReport; import com.water.patrol.service.PatrolAppIssueService; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.math.BigDecimal; import java.util.Map; +@Tag(name="APP-问题上报") @RestController @RequestMapping("/api/patrol/app/issue") @RequiredArgsConstructor +public class PatrolAppIssueController { + private final PatrolAppIssueService svc; + @Operation(summary="上报问题") @PostMapping public R submit(@RequestParam(required=false) Long taskId, @RequestParam Long reporterId, @RequestParam String reporterName, @RequestParam String issueType, @RequestParam String description, @RequestParam(required=false) String photos, @RequestParam(required=false) String videos, @RequestParam(required=false) BigDecimal lng, @RequestParam(required=false) BigDecimal lat, @RequestParam(required=false) String address, @RequestParam(required=false) String severity) { return R.ok(svc.submit(taskId,reporterId,reporterName,issueType,description,photos,videos,lng,lat,address,severity)); } + @Operation(summary="我的上报") @GetMapping("/my") public R> myReports(@RequestParam Long reporterId) { return R.ok(svc.myReports(reporterId)); } + @Operation(summary="上报详情") @GetMapping("/{id}") public R detail(@PathVariable Long id) { return R.ok(svc.getDetail(id)); } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppProfileController.java b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppProfileController.java new file mode 100644 index 00000000..969dc065 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppProfileController.java @@ -0,0 +1,10 @@ +package com.water.patrol.controller; +import com.water.common.core.result.R; import com.water.patrol.service.PatrolAppProfileService; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.util.Map; +@Tag(name="APP-个人中心") @RestController @RequestMapping("/api/patrol/app/profile") @RequiredArgsConstructor +public class PatrolAppProfileController { + private final PatrolAppProfileService svc; + @Operation(summary="个人数据") @GetMapping public R> profile(@RequestParam Long workerId) { return R.ok(svc.getProfile(workerId)); } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppTaskController.java b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppTaskController.java new file mode 100644 index 00000000..8c61ca41 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppTaskController.java @@ -0,0 +1,14 @@ +package com.water.patrol.controller; +import com.water.common.core.result.R; import com.water.patrol.entity.PatrolTask; import com.water.patrol.service.PatrolAppTaskService; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.util.Map; +@Tag(name="APP-我的任务") @RestController @RequestMapping("/api/patrol/app/task") @RequiredArgsConstructor +public class PatrolAppTaskController { + private final PatrolAppTaskService svc; + @Operation(summary="我的任务列表") @GetMapping("/my") public R> myTasks(@RequestParam Long workerId, @RequestParam(required=false) String status) { return R.ok(svc.myTasks(workerId,status)); } + @Operation(summary="任务详情") @GetMapping("/{id}") public R detail(@PathVariable Long id) { return R.ok(svc.getDetail(id)); } + @Operation(summary="接受任务") @PutMapping("/{id}/accept") public R accept(@PathVariable Long id) { svc.accept(id); return R.ok("OK"); } + @Operation(summary="完成任务") @PutMapping("/{id}/complete") public R complete(@PathVariable Long id, @RequestParam Integer completedCheckpoints, @RequestParam Double distance, @RequestParam(required=false) String remark) { svc.complete(id,completedCheckpoints,distance,remark); return R.ok("OK"); } + @Operation(summary="我的统计") @GetMapping("/my/stats") public R> myStats(@RequestParam Long workerId) { return R.ok(svc.myStats(workerId)); } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppWoController.java b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppWoController.java new file mode 100644 index 00000000..a7d020cf --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/controller/PatrolAppWoController.java @@ -0,0 +1,13 @@ +package com.water.patrol.controller; +import com.water.common.core.result.R; import com.water.patrol.entity.PatrolWorkOrder; import com.water.patrol.service.PatrolAppWorkOrderService; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.util.Map; +@Tag(name="APP-我的工单") @RestController @RequestMapping("/api/patrol/app/work-order") @RequiredArgsConstructor +public class PatrolAppWoController { + private final PatrolAppWorkOrderService svc; + @Operation(summary="我的工单列表") @GetMapping("/my") public R> myWorkOrders(@RequestParam Long assigneeId, @RequestParam(required=false) String status) { return R.ok(svc.myWorkOrders(assigneeId,status)); } + @Operation(summary="工单详情") @GetMapping("/{id}") public R detail(@PathVariable Long id) { return R.ok(svc.getDetail(id)); } + @Operation(summary="接受工单") @PutMapping("/{id}/accept") public R accept(@PathVariable Long id) { svc.accept(id); return R.ok("OK"); } + @Operation(summary="解决工单") @PutMapping("/{id}/resolve") public R resolve(@PathVariable Long id, @RequestParam String resolution, @RequestParam(required=false) String resultPhotos) { svc.resolve(id,resolution,resultPhotos); return R.ok("OK"); } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/entity/PatrolIssueReport.java b/wm-patrol/src/main/java/com/water/patrol/entity/PatrolIssueReport.java new file mode 100644 index 00000000..7cf076bc --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/entity/PatrolIssueReport.java @@ -0,0 +1,19 @@ +package com.water.patrol.entity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDateTime; +@Data @TableName("pat_issue_report") +public class PatrolIssueReport { + @TableId(type = IdType.AUTO) private Long id; + private String reportNo; private Long taskId; + private Long reporterId; private String reporterName; + private String issueType; private String description; + private String photos; private String videos; + private BigDecimal lng; private BigDecimal lat; + private String address; private String severity; + private String status; private Long workOrderId; + private String remark; + @TableField(fill = FieldFill.INSERT) private LocalDateTime createdAt; + @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updatedAt; +} diff --git a/wm-patrol/src/main/java/com/water/patrol/mapper/PatrolIssueReportMapper.java b/wm-patrol/src/main/java/com/water/patrol/mapper/PatrolIssueReportMapper.java new file mode 100644 index 00000000..fa86c617 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/mapper/PatrolIssueReportMapper.java @@ -0,0 +1,5 @@ +package com.water.patrol.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.water.patrol.entity.PatrolIssueReport; +import org.apache.ibatis.annotations.Mapper; +@Mapper public interface PatrolIssueReportMapper extends BaseMapper {} diff --git a/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppIssueService.java b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppIssueService.java new file mode 100644 index 00000000..71e872f0 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppIssueService.java @@ -0,0 +1,30 @@ +package com.water.patrol.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.water.patrol.entity.PatrolIssueReport; import com.water.patrol.mapper.PatrolIssueReportMapper; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.*; +@Slf4j @Service @RequiredArgsConstructor +public class PatrolAppIssueService { + private final PatrolIssueReportMapper mapper; + public PatrolIssueReport submit(Long taskId, Long reporterId, String reporterName, + String issueType, String description, String photos, String videos, + BigDecimal lng, BigDecimal lat, String address, String severity) { + PatrolIssueReport r = new PatrolIssueReport(); + r.setReportNo("PIR-"+System.currentTimeMillis()); r.setTaskId(taskId); + r.setReporterId(reporterId); r.setReporterName(reporterName); + r.setIssueType(issueType); r.setDescription(description); + r.setPhotos(photos); r.setVideos(videos); + r.setLng(lng); r.setLat(lat); r.setAddress(address); + r.setSeverity(severity != null ? severity : "medium"); + r.setStatus("submitted"); + mapper.insert(r); return r; + } + public Map myReports(Long reporterId) { + Map r = new LinkedHashMap<>(); + r.put("reports", mapper.selectList(new LambdaQueryWrapper().eq(PatrolIssueReport::getReporterId, reporterId).orderByDesc(PatrolIssueReport::getCreatedAt))); + r.put("totalCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolIssueReport::getReporterId, reporterId))); + return r; + } + public PatrolIssueReport getDetail(Long id) { return mapper.selectById(id); } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppProfileService.java b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppProfileService.java new file mode 100644 index 00000000..401875a7 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppProfileService.java @@ -0,0 +1,23 @@ +package com.water.patrol.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.water.patrol.entity.PatrolTask; import com.water.patrol.entity.PatrolWorkOrder; +import com.water.patrol.mapper.PatrolTaskMapper; import com.water.patrol.mapper.PatrolWorkOrderMapper; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import java.util.*; +@Slf4j @Service @RequiredArgsConstructor +public class PatrolAppProfileService { + private final PatrolTaskMapper taskMapper; + private final PatrolWorkOrderMapper woMapper; + public Map getProfile(Long workerId) { + Map r = new LinkedHashMap<>(); + r.put("workerId", workerId); + r.put("totalTasks", taskMapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId))); + r.put("completedTasks", taskMapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId).eq(PatrolTask::getStatus, "completed"))); + r.put("totalDistance", 0); + r.put("totalWorkOrders", woMapper.selectCount(new LambdaQueryWrapper().eq(PatrolWorkOrder::getAssigneeId, workerId))); + r.put("resolvedWorkOrders", woMapper.selectCount(new LambdaQueryWrapper().eq(PatrolWorkOrder::getAssigneeId, workerId).eq(PatrolWorkOrder::getStatus, "resolved"))); + r.put("reportedIssues", 0); + return r; + } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppTaskService.java b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppTaskService.java new file mode 100644 index 00000000..bec4384e --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppTaskService.java @@ -0,0 +1,42 @@ +package com.water.patrol.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.water.patrol.entity.PatrolTask; import com.water.patrol.mapper.PatrolTaskMapper; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.*; +@Slf4j @Service @RequiredArgsConstructor +public class PatrolAppTaskService { + private final PatrolTaskMapper mapper; + public Map myTasks(Long workerId, String status) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(PatrolTask::getWorkerId, workerId); + if (status != null && !status.isEmpty()) w.eq(PatrolTask::getStatus, status); + w.orderByDesc(PatrolTask::getCreatedAt); + Map r = new LinkedHashMap<>(); + r.put("tasks", mapper.selectList(w)); + r.put("totalCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId))); + r.put("pendingCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId).eq(PatrolTask::getStatus, "pending"))); + r.put("inProgressCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId).eq(PatrolTask::getStatus, "in_progress"))); + return r; + } + public PatrolTask getDetail(Long id) { return mapper.selectById(id); } + public void accept(Long id) { + PatrolTask t = mapper.selectById(id); + if (t == null) throw new RuntimeException("任务不存在"); + t.setStatus("in_progress"); t.setStartTime(LocalDateTime.now()); mapper.updateById(t); + } + public void complete(Long id, Integer cc, Double dist, String remark) { + PatrolTask t = mapper.selectById(id); + if (t == null) throw new RuntimeException("任务不存在"); + t.setStatus("completed"); t.setEndTime(LocalDateTime.now()); + t.setCompletedCheckpoints(cc); t.setDistance(dist); t.setRemark(remark); + mapper.updateById(t); + } + public Map myStats(Long workerId) { + Map r = new LinkedHashMap<>(); + r.put("total", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId))); + r.put("completed", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolTask::getWorkerId, workerId).eq(PatrolTask::getStatus, "completed"))); + r.put("totalDistance", 0); + return r; + } +} diff --git a/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppWorkOrderService.java b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppWorkOrderService.java new file mode 100644 index 00000000..f0171c32 --- /dev/null +++ b/wm-patrol/src/main/java/com/water/patrol/service/PatrolAppWorkOrderService.java @@ -0,0 +1,36 @@ +package com.water.patrol.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.water.patrol.entity.PatrolWorkOrder; import com.water.patrol.mapper.PatrolWorkOrderMapper; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.*; +@Slf4j @Service @RequiredArgsConstructor +public class PatrolAppWorkOrderService { + private final PatrolWorkOrderMapper mapper; + public Map myWorkOrders(Long assigneeId, String status) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(PatrolWorkOrder::getAssigneeId, assigneeId); + if (status != null && !status.isEmpty()) w.eq(PatrolWorkOrder::getStatus, status); + w.orderByDesc(PatrolWorkOrder::getCreatedAt); + Map r = new LinkedHashMap<>(); + r.put("workOrders", mapper.selectList(w)); + r.put("totalCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolWorkOrder::getAssigneeId, assigneeId))); + r.put("pendingCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolWorkOrder::getAssigneeId, assigneeId).eq(PatrolWorkOrder::getStatus, "assigned"))); + r.put("inProgressCount", mapper.selectCount(new LambdaQueryWrapper().eq(PatrolWorkOrder::getAssigneeId, assigneeId).eq(PatrolWorkOrder::getStatus, "in_progress"))); + return r; + } + public PatrolWorkOrder getDetail(Long id) { return mapper.selectById(id); } + public void accept(Long id) { + PatrolWorkOrder wo = mapper.selectById(id); + if (wo == null) throw new RuntimeException("工单不存在"); + wo.setStatus("in_progress"); mapper.updateById(wo); + } + public void resolve(Long id, String resolution, String resultPhotos) { + PatrolWorkOrder wo = mapper.selectById(id); + if (wo == null) throw new RuntimeException("工单不存在"); + wo.setStatus("resolved"); wo.setResolution(resolution); + wo.setResolvedAt(LocalDateTime.now()); + if (resultPhotos != null) wo.setPhotos(resultPhotos); + mapper.updateById(wo); + } +} diff --git a/wm-patrol/src/main/resources/sql/V88__patrol_app.sql b/wm-patrol/src/main/resources/sql/V88__patrol_app.sql new file mode 100644 index 00000000..9ba61b9c --- /dev/null +++ b/wm-patrol/src/main/resources/sql/V88__patrol_app.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS pat_issue_report ( + id BIGSERIAL PRIMARY KEY, + report_no VARCHAR(32) UNIQUE, + task_id BIGINT, reporter_id BIGINT, reporter_name VARCHAR(50), + issue_type VARCHAR(30), description TEXT, photos TEXT, videos TEXT, + lng NUMERIC(10,6), lat NUMERIC(10,6), address VARCHAR(200), + severity VARCHAR(20) DEFAULT 'medium', status VARCHAR(20) DEFAULT 'submitted', + work_order_id BIGINT, remark VARCHAR(500), + created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() +); +CREATE INDEX IF NOT EXISTS idx_pat_ir_task ON pat_issue_report(task_id); +CREATE INDEX IF NOT EXISTS idx_pat_ir_reporter ON pat_issue_report(reporter_id); +CREATE INDEX IF NOT EXISTS idx_pat_ir_status ON pat_issue_report(status); diff --git a/wm-patrol/src/test/java/com/water/patrol/PatrolAppTest.java b/wm-patrol/src/test/java/com/water/patrol/PatrolAppTest.java new file mode 100644 index 00000000..4c215910 --- /dev/null +++ b/wm-patrol/src/test/java/com/water/patrol/PatrolAppTest.java @@ -0,0 +1,24 @@ +package com.water.patrol; +import com.water.patrol.entity.*; import com.water.patrol.mapper.*; import com.water.patrol.service.*; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; import org.mockito.junit.jupiter.MockitoExtension; +import java.math.BigDecimal; import java.util.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +@ExtendWith(MockitoExtension.class) +class PatrolAppTest { + @Mock PatrolTaskMapper taskMapper; @Mock PatrolWorkOrderMapper woMapper; @Mock PatrolIssueReportMapper irMapper; + @InjectMocks PatrolAppTaskService taskSvc; @InjectMocks PatrolAppWorkOrderService woSvc; + @InjectMocks PatrolAppIssueService issueSvc; @InjectMocks PatrolAppProfileService profileSvc; + + @Test void testMyTasks() { when(taskMapper.selectList(any())).thenReturn(Collections.emptyList()); when(taskMapper.selectCount(any())).thenReturn(0L); Map r=taskSvc.myTasks(100L,null); assertNotNull(r); assertEquals(0,r.get("totalCount")); } + @Test void testAcceptTask() { PatrolTask t=new PatrolTask(); t.setId(1L); t.setStatus("pending"); when(taskMapper.selectById(1L)).thenReturn(t); when(taskMapper.updateById(any())).thenReturn(1); taskSvc.accept(1L); assertEquals("in_progress",t.getStatus()); assertNotNull(t.getStartTime()); } + @Test void testCompleteTask() { PatrolTask t=new PatrolTask(); t.setId(1L); t.setStatus("in_progress"); when(taskMapper.selectById(1L)).thenReturn(t); when(taskMapper.updateById(any())).thenReturn(1); taskSvc.complete(1L,5,2000.0,"完成"); assertEquals("completed",t.getStatus()); assertEquals(5,(int)t.getCompletedCheckpoints()); } + @Test void testMyWorkOrders() { when(woMapper.selectList(any())).thenReturn(Collections.emptyList()); when(woMapper.selectCount(any())).thenReturn(0L); Map r=woSvc.myWorkOrders(100L,null); assertNotNull(r); } + @Test void testAcceptWO() { PatrolWorkOrder wo=new PatrolWorkOrder(); wo.setId(1L); wo.setStatus("assigned"); when(woMapper.selectById(1L)).thenReturn(wo); when(woMapper.updateById(any())).thenReturn(1); woSvc.accept(1L); assertEquals("in_progress",wo.getStatus()); } + @Test void testResolveWO() { PatrolWorkOrder wo=new PatrolWorkOrder(); wo.setId(1L); wo.setStatus("in_progress"); when(woMapper.selectById(1L)).thenReturn(wo); when(woMapper.updateById(any())).thenReturn(1); woSvc.resolve(1L,"已修复",null); assertEquals("resolved",wo.getStatus()); assertNotNull(wo.getResolvedAt()); } + @Test void testSubmitIssue() { when(irMapper.insert(any())).thenReturn(1); PatrolIssueReport r=issueSvc.submit(1L,100L,"张三","leak","管道漏水",null,null,new BigDecimal("116"),new BigDecimal("39"),"A路","high"); assertTrue(r.getReportNo().startsWith("PIR-")); assertEquals("submitted",r.getStatus()); } + @Test void testMyReports() { when(irMapper.selectList(any())).thenReturn(Collections.emptyList()); when(irMapper.selectCount(any())).thenReturn(0L); Map r=issueSvc.myReports(100L); assertNotNull(r); assertEquals(0,r.get("totalCount")); } + @Test void testProfile() { when(taskMapper.selectCount(any())).thenReturn(10L); when(woMapper.selectCount(any())).thenReturn(5L); Map r=profileSvc.getProfile(100L); assertEquals(100L,r.get("workerId")); } + @Test void testMyStats() { when(taskMapper.selectCount(any())).thenReturn(5L); Map r=taskSvc.myStats(100L); assertNotNull(r); } +}