From 979c2a99e040a9a52eeb4a8f24d72e4e3469f7ea Mon Sep 17 00:00:00 2001 From: MaDaLei Date: Sun, 19 Apr 2026 14:26:25 +0800 Subject: [PATCH] deploy: rebuild jar --- README.en.md | 2 +- README.md | 2 +- pom.xml | 2 +- .../controller/AppointmentController.java | 14 +--- .../petstore/controller/ReportController.java | 36 +++++++++ .../petstore/controller/SmsController.java | 2 +- .../petstore/service/AppointmentService.java | 74 +++++++++++++++---- .../com/petstore/service/ReportService.java | 10 ++- 8 files changed, 109 insertions(+), 33 deletions(-) diff --git a/README.en.md b/README.en.md index c4dd558..86fb5e8 100644 --- a/README.en.md +++ b/README.en.md @@ -1,7 +1,7 @@ # petstore-backend #### Description -宠伴生活馆 +宠小它 #### Software Architecture Software architecture description diff --git a/README.md b/README.md index 2d1d3ec..7747d61 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # petstore-backend #### 介绍 -宠伴生活馆 +宠小它 #### 软件架构 软件架构说明 diff --git a/pom.xml b/pom.xml index 12db726..a5a927e 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 1.0.0 jar petstore-backend - 宠伴生活馆 后端服务 + 宠小它 后端服务|智慧宠物门店服务系统 17 diff --git a/src/main/java/com/petstore/controller/AppointmentController.java b/src/main/java/com/petstore/controller/AppointmentController.java index 402b92e..8691e99 100644 --- a/src/main/java/com/petstore/controller/AppointmentController.java +++ b/src/main/java/com/petstore/controller/AppointmentController.java @@ -117,21 +117,13 @@ public class AppointmentController { public Map start(@RequestBody Map params) { Long appointmentId = Long.valueOf(params.get("appointmentId").toString()); Long staffUserId = Long.valueOf(params.get("staffUserId").toString()); - Appointment updated = appointmentService.startService(appointmentId, staffUserId); - if (updated != null) { - return Map.of("code", 200, "message", "已开始服务", "data", updated); - } - return Map.of("code", 404, "message", "预约不存在"); + return appointmentService.startService(appointmentId, staffUserId); } - /** 更新预约状态 */ + /** 更新预约状态(合法迁移见 AppointmentService.transitionStatus) */ @PutMapping("/status") public Map updateStatus(@RequestParam Long id, @RequestParam String status) { - Appointment updated = appointmentService.updateStatus(id, status); - if (updated != null) { - return Map.of("code", 200, "message", "更新成功", "data", updated); - } - return Map.of("code", 404, "message", "预约不存在"); + return appointmentService.transitionStatus(id, status); } @DeleteMapping("/delete") diff --git a/src/main/java/com/petstore/controller/ReportController.java b/src/main/java/com/petstore/controller/ReportController.java index e103c23..497f792 100644 --- a/src/main/java/com/petstore/controller/ReportController.java +++ b/src/main/java/com/petstore/controller/ReportController.java @@ -5,6 +5,8 @@ import com.petstore.entity.Report; import com.petstore.entity.ReportImage; import com.petstore.entity.Store; import com.petstore.entity.User; +import com.petstore.entity.Appointment; +import com.petstore.service.AppointmentService; import com.petstore.service.ReportHighlightVideoService; import com.petstore.service.ReportService; import com.petstore.service.ReportTestimonialService; @@ -13,6 +15,8 @@ import com.petstore.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; @@ -24,7 +28,9 @@ import java.util.stream.Collectors; @RequiredArgsConstructor @CrossOrigin public class ReportController { + private static final Logger log = LoggerFactory.getLogger(ReportController.class); private final ReportService reportService; + private final AppointmentService appointmentService; private final StoreService storeService; private final ReportHighlightVideoService reportHighlightVideoService; private final ReportTestimonialService reportTestimonialService; @@ -92,9 +98,39 @@ public class ReportController { return reportHighlightVideoService.requestGenerate(reportId, operatorUserId, role, composeMode); } + /** + * P0 埋点:报告打开(首访/再次)。当前写入应用日志,便于日志平台统计;不落库。 + */ + @PostMapping("/open-track") + public Map trackReportOpen(@RequestBody Map body) { + Object rawTok = body == null ? null : body.get("token"); + String token = rawTok == null ? "" : rawTok.toString().trim(); + if (token.isEmpty()) { + return Map.of("code", 400, "message", "token 必填"); + } + String visitType = body.get("visitType") == null ? "" : body.get("visitType").toString(); + String prefix = token.length() > 16 ? token.substring(0, 16) + "…" : token; + log.info("report_open tokenPrefix={} visitType={}", prefix, visitType); + return Map.of("code", 200); + } + @PostMapping("/create") public Map create(@RequestBody Report report) { System.out.println(">>> Report create received: appointmentId=" + report.getAppointmentId() + ", userId=" + report.getUserId() + ", images count=" + (report.getImages() == null ? 0 : report.getImages().size())); + if (report.getAppointmentId() != null) { + Appointment appt = appointmentService.getById(report.getAppointmentId()); + if (appt == null) { + return Map.of("code", 404, "message", "关联预约不存在", "bizCode", "NOT_FOUND"); + } + String st = appt.getStatus() == null ? "" : appt.getStatus().trim().toLowerCase(); + if (!"doing".equals(st)) { + return Map.of( + "code", 400, + "message", "请先开始服务后再提交报告", + "bizCode", "INVALID_STATUS" + ); + } + } Report created = reportService.create(report); Map result = new HashMap<>(); diff --git a/src/main/java/com/petstore/controller/SmsController.java b/src/main/java/com/petstore/controller/SmsController.java index 3bb2375..ebebc75 100644 --- a/src/main/java/com/petstore/controller/SmsController.java +++ b/src/main/java/com/petstore/controller/SmsController.java @@ -35,7 +35,7 @@ public class SmsController { // 阿里云示例: dysmsapi.aliyuncs.com // 腾讯云示例: sms.tencentcloudapi.com - System.out.println("【宠伴生活馆】验证码:" + code + ",您正在登录,5分钟内有效。"); + System.out.println("【宠小它】验证码:" + code + ",您正在登录,5分钟内有效。"); result.put("code", 200); result.put("message", "发送成功"); diff --git a/src/main/java/com/petstore/service/AppointmentService.java b/src/main/java/com/petstore/service/AppointmentService.java index ff0e10e..e4aa009 100644 --- a/src/main/java/com/petstore/service/AppointmentService.java +++ b/src/main/java/com/petstore/service/AppointmentService.java @@ -177,26 +177,72 @@ public class AppointmentService { return ok; } - public Appointment updateStatus(Long id, String status) { + /** + * 预约状态迁移(PUT /appointment/status 等)。 + * 允许:new→cancel、doing→done;new→doing 请走 {@link #startService}。 + */ + public Map transitionStatus(Long id, String nextStatus) { Appointment appointment = appointmentMapper.findByIdAndDeletedFalse(id).orElse(null); - if (appointment != null) { - appointment.setStatus(status); - appointment.setUpdateTime(LocalDateTime.now()); - return appointmentMapper.save(appointment); + if (appointment == null) { + return Map.of("code", 404, "message", "预约不存在", "bizCode", "NOT_FOUND"); } - return null; + if (nextStatus == null || nextStatus.isBlank()) { + return Map.of("code", 400, "message", "状态不能为空", "bizCode", "INVALID_STATUS"); + } + String to = nextStatus.trim().toLowerCase(); + String from = appointment.getStatus() == null ? "" : appointment.getStatus().trim().toLowerCase(); + + if ("cancel".equals(to)) { + if (!"new".equals(from)) { + return Map.of( + "code", 400, + "message", "仅待开始的预约可取消", + "bizCode", "CANCEL_NOT_ALLOWED" + ); + } + } else if ("done".equals(to)) { + if (!"doing".equals(from)) { + return Map.of( + "code", 400, + "message", "仅进行中的预约可标记为已完成", + "bizCode", "INVALID_STATUS" + ); + } + } else if ("doing".equals(to)) { + return Map.of( + "code", 400, + "message", "请使用「开始服务」接口将预约置为进行中", + "bizCode", "USE_START_ENDPOINT" + ); + } else { + return Map.of("code", 400, "message", "不支持的状态变更", "bizCode", "INVALID_STATUS"); + } + + appointment.setStatus(to); + appointment.setUpdateTime(LocalDateTime.now()); + Appointment saved = appointmentMapper.save(appointment); + return Map.of("code", 200, "message", "更新成功", "data", saved); } - /** 开始服务:状态变为进行中,同时指定技师为当前用户 */ - public Appointment startService(Long appointmentId, Long staffUserId) { + /** 开始服务:仅 new → doing,并指定技师 */ + public Map startService(Long appointmentId, Long staffUserId) { Appointment appointment = appointmentMapper.findByIdAndDeletedFalse(appointmentId).orElse(null); - if (appointment != null) { - appointment.setStatus("doing"); - appointment.setAssignedUserId(staffUserId); - appointment.setUpdateTime(LocalDateTime.now()); - return appointmentMapper.save(appointment); + if (appointment == null) { + return Map.of("code", 404, "message", "预约不存在", "bizCode", "NOT_FOUND"); } - return null; + String from = appointment.getStatus() == null ? "" : appointment.getStatus().trim().toLowerCase(); + if (!"new".equals(from)) { + return Map.of( + "code", 400, + "message", "仅待开始的预约可开始服务", + "bizCode", "INVALID_STATUS" + ); + } + appointment.setStatus("doing"); + appointment.setAssignedUserId(staffUserId); + appointment.setUpdateTime(LocalDateTime.now()); + Appointment saved = appointmentMapper.save(appointment); + return Map.of("code", 200, "message", "已开始服务", "data", saved); } public boolean softDelete(Long id) { diff --git a/src/main/java/com/petstore/service/ReportService.java b/src/main/java/com/petstore/service/ReportService.java index 7bff2bb..1161d7a 100644 --- a/src/main/java/com/petstore/service/ReportService.java +++ b/src/main/java/com/petstore/service/ReportService.java @@ -41,10 +41,12 @@ public class ReportService { report.setStaffName(staff.getName()); } } - // 填写完报告,自动标记预约为已完成 - appt.setStatus("done"); - appt.setUpdateTime(LocalDateTime.now()); - appointmentMapper.save(appt); + // 填写完报告:仅进行中 → 已完成(与预约状态机一致) + if ("doing".equalsIgnoreCase(appt.getStatus())) { + appt.setStatus("done"); + appt.setUpdateTime(LocalDateTime.now()); + appointmentMapper.save(appt); + } } } // 如果预约没分配技师,则用当前操作人