diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..d6226af --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "enabledPlugins": { + "everything-claude-code@everything-claude-code": true + } +} diff --git a/.gitignore b/.gitignore index dd9452e..1cfb970 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,83 @@ -# Dependencies +# ============================================ +# 爱维宠物医院管理系统 - Gitignore +# Java Spring Boot + Vue.js 全栈项目 +# ============================================ + +# ============================================ +# 依赖目录 +# ============================================ node_modules/ +jspm_packages/ +bower_components/ +.mvn/wrapper/maven-wrapper.jar + +# ============================================ +# 构建输出 +# ============================================ +# Frontend +dist/ +frontend/dist/ + +# Backend +target/ +backend/target/ +build/ +build/Release + +# ============================================ +# 日志文件 +# ============================================ +logs/ +*.log npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* +.lerna-debug.log* -# Production builds -dist/ -build/ -target/ +# 项目特定的日志文件 +backend/*.log +frontend/*.log +backend_*.log +frontend_*.log -# IDE files -.vscode/ +# ============================================ +# IDE 和编辑器 +# ============================================ +# IntelliJ IDEA .idea/ +*.iws +*.iml +*.ipr + +# VS Code +.vscode/ +*.code-workspace + +# Eclipse +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +# NetBeans +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +# Vim/Emacs *.swp *.swo *~ -# OS generated files +# ============================================ +# 操作系统文件 +# ============================================ .DS_Store .DS_Store? ._* @@ -26,107 +86,148 @@ target/ ehthumbs.db Thumbs.db desktop.ini +Icon? +Network Trash Folder +Temporary Items +.apdisk -# Environment variables +# ============================================ +# 环境变量和敏感配置 +# ============================================ .env .env.local .env.*.local +.env.development +.env.test +.env.production -# Java/Maven +# 应用配置(可能包含敏感信息) +application-local.yml +application-dev-local.yml +application-prod.yml + +# ============================================ +# Java / Maven / Spring Boot +# ============================================ *.class *.jar *.war *.ear *.tar.gz -target/ -!.mvn/wrapper/maven-wrapper.jar +*.zip + +# Maven +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.properties -# Logs -logs/ -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.lerna-debug.log* +# Gradle +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ +gradle-app.setting +.gradletasknamecache -# Coverage directory used by tools like istanbul +# Spring Boot +spring-boot-devtools.properties + +# ============================================ +# Node.js / 前端 +# ============================================ +# Package locks (根据需要选择保留或忽略) +# package-lock.json +# yarn.lock +# pnpm-lock.yaml + +# TypeScript +*.tsbuildinfo +typings/ + +# Vue.js +.vue-temp/ + +# Vite +.vite/ + +# Sass/SCSS +.sass-cache + +# Coverage coverage/ lib-cov/ +.nyc_output -# Database +# ============================================ +# 数据库 +# ============================================ *.sqlite *.sqlite-journal +*.db +*.db-journal -# Runtime data -pids +# ============================================ +# 运行时数据 +# ============================================ +pids/ *.pid *.seed *.pid.lock -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov +# ============================================ +# 测试和临时文件 +# ============================================ +tmp/ +temp/ +*.tmp +*.temp +.cache/ -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#files-in-tmp-and-tmp-grunt-tasks) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# TypeDoc docs -docs/ - -# Sass -.sass-cache - -# Output of 'bundle gem {NAME}' -*.gem -*.rbc - -# Configuration files -config/ -*.ini -*.toml - -# Maven wrapper -!.mvn/wrapper/maven-wrapper.jar - -# Backend build artifacts -backend/target/ -backend/*.log - -# Frontend build artifacts -frontend/dist/ -frontend/node_modules/ -frontend/*.log - -# FRP binaries (large files) +# ============================================ +# FRP 内网穿透工具 +# ============================================ frp/frpc frp/frps +frp/*.ini +frp/*.toml -# System files -Thumbs.db -.DS_Store -.DS_Store? -._* -ehthumbs.db -Icon? -Network Trash Folder -Temporary Items -.apdisk \ No newline at end of file +# ============================================ +# 文档生成(保留源文件,忽略生成的) +# ============================================ +# PlantUML 生成的图片 +*.png +*.svg + +# 但保留 docs/drawio 和 docs/plantuml 源文件 +!docs/**/*.drawio +!docs/**/*.puml + +# ============================================ +# 其他 +# ============================================ +# 备份文件 +*.bak +*.backup +*.orig + +# 压缩文件 +*.7z +*.rar + +# 证书和密钥 +*.pem +*.key +*.crt +*.p12 +*.pfx + +# 上传文件目录(开发环境) +uploads/ +files/ diff --git a/backend/src/main/java/com/gpf/pethospital/controller/AppointmentController.java b/backend/src/main/java/com/gpf/pethospital/controller/AppointmentController.java index d3d693d..300435b 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/AppointmentController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/AppointmentController.java @@ -47,7 +47,7 @@ public class AppointmentController { return ApiResponse.success(appointmentService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @GetMapping("/admin") public ApiResponse adminList(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size, @@ -59,7 +59,7 @@ public class AppointmentController { return ApiResponse.success(appointmentService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}/status") public ApiResponse updateStatus(@PathVariable Long id, @RequestParam String status) { Appointment update = new Appointment(); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/DrugController.java b/backend/src/main/java/com/gpf/pethospital/controller/DrugController.java index de92a86..4400b36 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/DrugController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/DrugController.java @@ -17,7 +17,7 @@ public class DrugController { this.drugService = drugService; } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @GetMapping public ApiResponse list(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size, @@ -31,7 +31,7 @@ public class DrugController { return ApiResponse.success(drugService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PostMapping public ApiResponse create(@RequestBody Drug drug) { if (drug.getStatus() == null) { @@ -41,7 +41,7 @@ public class DrugController { return ApiResponse.success("created", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody Drug drug) { drug.setId(id); @@ -49,7 +49,7 @@ public class DrugController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @DeleteMapping("/{id}") public ApiResponse delete(@PathVariable Long id) { drugService.removeById(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/MedicalRecordController.java b/backend/src/main/java/com/gpf/pethospital/controller/MedicalRecordController.java index 066855f..a372390 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/MedicalRecordController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/MedicalRecordController.java @@ -16,7 +16,7 @@ public class MedicalRecordController { this.medicalRecordService = medicalRecordService; } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PostMapping public ApiResponse create(@RequestBody MedicalRecord record) { if (record.getStatus() == null) { @@ -33,7 +33,7 @@ public class MedicalRecordController { return ApiResponse.success(medicalRecordService.list(wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody MedicalRecord record) { record.setId(id); @@ -41,7 +41,7 @@ public class MedicalRecordController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @DeleteMapping("/{id}") public ApiResponse delete(@PathVariable Long id) { medicalRecordService.removeById(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/MessageController.java b/backend/src/main/java/com/gpf/pethospital/controller/MessageController.java index 571cf48..9175b2c 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/MessageController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/MessageController.java @@ -35,7 +35,7 @@ public class MessageController { return ApiResponse.success("created", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping("/admin") public ApiResponse list(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size, @@ -47,7 +47,7 @@ public class MessageController { return ApiResponse.success(messageService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PutMapping("/admin/{id}/reply") public ApiResponse reply(@PathVariable Long id, @Valid @RequestBody ReplyRequest request) { AuthUser user = SecurityUtils.currentUser(); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/NoticeController.java b/backend/src/main/java/com/gpf/pethospital/controller/NoticeController.java index 8b41824..b06bf45 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/NoticeController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/NoticeController.java @@ -34,14 +34,14 @@ public class NoticeController { return ApiResponse.success(noticeService.getById(id)); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping("/notices") public ApiResponse list(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size) { return ApiResponse.success(noticeService.page(new Page<>(page, size))); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PostMapping("/notices") public ApiResponse create(@RequestBody Notice notice) { if (notice.getPublisherId() == null) { @@ -60,7 +60,7 @@ public class NoticeController { return ApiResponse.success("created", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PutMapping("/notices/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody Notice notice) { notice.setId(id); @@ -68,7 +68,7 @@ public class NoticeController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @DeleteMapping("/notices/{id}") public ApiResponse delete(@PathVariable Long id) { noticeService.removeById(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/OrderController.java b/backend/src/main/java/com/gpf/pethospital/controller/OrderController.java index 8653695..03e790a 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/OrderController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/OrderController.java @@ -44,7 +44,7 @@ public class OrderController { /** * 根据处方生成订单 */ - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PostMapping("/from-prescription/{prescriptionId}") public ApiResponse createFromPrescription(@PathVariable Long prescriptionId) { // 1. 查询处方 @@ -164,7 +164,7 @@ public class OrderController { return ApiResponse.success(orderService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody Order order) { order.setId(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/PetController.java b/backend/src/main/java/com/gpf/pethospital/controller/PetController.java index 20b68a3..b3b5481 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/PetController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/PetController.java @@ -72,7 +72,7 @@ public class PetController { return ApiResponse.success("deleted", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping("/admin/all") public ApiResponse adminList(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size) { diff --git a/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionController.java b/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionController.java index 897ccbb..b7314ca 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionController.java @@ -19,7 +19,7 @@ public class PrescriptionController { this.prescriptionService = prescriptionService; } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PostMapping public ApiResponse create(@RequestBody Prescription prescription) { if (prescription.getStatus() == null) { @@ -44,7 +44,7 @@ public class PrescriptionController { return ApiResponse.success(prescriptionService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody Prescription prescription) { prescription.setId(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionItemController.java b/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionItemController.java index 8d46443..c5828a3 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionItemController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/PrescriptionItemController.java @@ -23,14 +23,14 @@ public class PrescriptionItemController { return ApiResponse.success(prescriptionItemService.list(wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PostMapping public ApiResponse create(@RequestBody PrescriptionItem item) { prescriptionItemService.save(item); return ApiResponse.success("created", null); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody PrescriptionItem item) { item.setId(id); @@ -38,7 +38,7 @@ public class PrescriptionItemController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @DeleteMapping("/{id}") public ApiResponse delete(@PathVariable Long id) { prescriptionItemService.removeById(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/ReportController.java b/backend/src/main/java/com/gpf/pethospital/controller/ReportController.java index aba0105..2538886 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/ReportController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/ReportController.java @@ -19,7 +19,7 @@ public class ReportController { this.reportService = reportService; } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PostMapping public ApiResponse create(@RequestBody Report report) { AuthUser user = SecurityUtils.currentUser(); @@ -45,7 +45,7 @@ public class ReportController { return ApiResponse.success(reportService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody Report report) { report.setId(id); @@ -53,7 +53,7 @@ public class ReportController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @DeleteMapping("/{id}") public ApiResponse delete(@PathVariable Long id) { reportService.removeById(id); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/StatsController.java b/backend/src/main/java/com/gpf/pethospital/controller/StatsController.java index 14a00f5..902159c 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/StatsController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/StatsController.java @@ -6,12 +6,14 @@ import com.gpf.pethospital.common.ApiResponse; import com.gpf.pethospital.entity.Appointment; import com.gpf.pethospital.entity.Order; import com.gpf.pethospital.entity.Pet; +import com.gpf.pethospital.entity.PrescriptionItem; import com.gpf.pethospital.entity.User; import com.gpf.pethospital.entity.Visit; import com.gpf.pethospital.service.AppointmentService; import com.gpf.pethospital.service.DrugService; import com.gpf.pethospital.service.OrderService; import com.gpf.pethospital.service.PetService; +import com.gpf.pethospital.service.PrescriptionItemService; import com.gpf.pethospital.service.UserService; import com.gpf.pethospital.service.VisitService; // import org.springframework.security.access.prepost.PreAuthorize; @@ -26,8 +28,11 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.Map; import java.util.stream.Collectors; @@ -40,22 +45,25 @@ public class StatsController { private final PetService petService; private final UserService userService; private final DrugService drugService; + private final PrescriptionItemService prescriptionItemService; public StatsController(OrderService orderService, AppointmentService appointmentService, VisitService visitService, PetService petService, UserService userService, - DrugService drugService) { + DrugService drugService, + PrescriptionItemService prescriptionItemService) { this.orderService = orderService; this.appointmentService = appointmentService; this.visitService = visitService; this.petService = petService; this.userService = userService; this.drugService = drugService; + this.prescriptionItemService = prescriptionItemService; } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping public ApiResponse summary() { Map data = new HashMap<>(); @@ -124,7 +132,7 @@ public class StatsController { return ApiResponse.success(data); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping("/trends") public ApiResponse trends(@RequestParam(defaultValue = "week") String period) { Map data = new HashMap<>(); @@ -208,8 +216,253 @@ public class StatsController { return ApiResponse.success(data); } + + @GetMapping("/report/revenue") + public ApiResponse revenueReport(@RequestParam(defaultValue = "month") String period, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate) { + DateRange range = resolveDateRange(period, startDate, endDate); + List paidOrders = orderService.list( + new LambdaQueryWrapper() + .eq(Order::getStatus, "PAID") + .ge(Order::getCreateTime, range.start()) + .lt(Order::getCreateTime, range.end()) + ); + + Map amountByDay = new HashMap<>(); + BigDecimal totalAmount = BigDecimal.ZERO; + for (Order order : paidOrders) { + BigDecimal amount = order.getAmount() == null ? BigDecimal.ZERO : order.getAmount(); + totalAmount = totalAmount.add(amount); + if (order.getCreateTime() != null) { + amountByDay.merge(order.getCreateTime().toLocalDate(), amount, BigDecimal::add); + } + } + + List> trend = amountByDay.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .map(entry -> { + Map point = new HashMap<>(); + point.put("date", entry.getKey().toString()); + point.put("amount", entry.getValue()); + return point; + }) + .collect(Collectors.toList()); + + DateRange previous = range.shiftBack(); + BigDecimal previousTotalAmount = sumPaidOrderAmount(previous.start(), previous.end()); + double growthRate = BigDecimal.ZERO.compareTo(previousTotalAmount) == 0 + ? 0D + : totalAmount.subtract(previousTotalAmount) + .multiply(BigDecimal.valueOf(100)) + .divide(previousTotalAmount, 2, java.math.RoundingMode.HALF_UP) + .doubleValue(); + + Map data = new HashMap<>(); + data.put("period", period); + data.put("startDate", range.start().toLocalDate().toString()); + data.put("endDate", range.end().minusDays(1).toLocalDate().toString()); + data.put("totalAmount", totalAmount); + data.put("orderCount", paidOrders.size()); + data.put("averageAmount", paidOrders.isEmpty() + ? BigDecimal.ZERO + : totalAmount.divide(BigDecimal.valueOf(paidOrders.size()), 2, java.math.RoundingMode.HALF_UP)); + data.put("growthRate", growthRate); + data.put("trend", trend); + return ApiResponse.success(data); + } + + @GetMapping("/report/revenue-sources") + public ApiResponse revenueSources(@RequestParam(defaultValue = "month") String period, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate) { + DateRange range = resolveDateRange(period, startDate, endDate); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("payment_method AS paymentMethod", "COUNT(*) AS orderCount", "COALESCE(SUM(amount), 0) AS totalAmount"); + wrapper.eq("status", "PAID"); + wrapper.ge("create_time", range.start()); + wrapper.lt("create_time", range.end()); + wrapper.groupBy("payment_method"); + wrapper.orderByDesc("totalAmount"); + + List> rows = orderService.listMaps(wrapper); + BigDecimal totalAmount = rows.stream() + .map(row -> toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT"))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + List> sources = new ArrayList<>(); + for (Map row : rows) { + BigDecimal amount = toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT")); + Map item = new HashMap<>(); + item.put("paymentMethod", normalizePaymentMethod(String.valueOf(getMapValue(row, "paymentMethod", "payment_method", "PAYMENTMETHOD")))); + item.put("orderCount", toLong(getMapValue(row, "orderCount", "ordercount", "ORDERCOUNT"))); + item.put("totalAmount", amount); + item.put("ratio", BigDecimal.ZERO.compareTo(totalAmount) == 0 + ? BigDecimal.ZERO + : amount.multiply(BigDecimal.valueOf(100)).divide(totalAmount, 2, java.math.RoundingMode.HALF_UP)); + sources.add(item); + } + + Map data = new HashMap<>(); + data.put("period", period); + data.put("startDate", range.start().toLocalDate().toString()); + data.put("endDate", range.end().minusDays(1).toLocalDate().toString()); + data.put("totalAmount", totalAmount); + data.put("sources", sources); + return ApiResponse.success(data); + } + + @GetMapping("/report/drug-sales") + public ApiResponse drugSales(@RequestParam(defaultValue = "month") String period, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate, + @RequestParam(defaultValue = "10") int limit) { + DateRange range = resolveDateRange(period, startDate, endDate); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("drug_id AS drugId", "drug_name AS drugName", "COALESCE(SUM(quantity), 0) AS totalQuantity", "COALESCE(SUM(subtotal), 0) AS totalAmount"); + wrapper.ge("create_time", range.start()); + wrapper.lt("create_time", range.end()); + wrapper.groupBy("drug_id", "drug_name"); + wrapper.orderByDesc("totalQuantity"); + wrapper.orderByDesc("totalAmount"); + wrapper.last("LIMIT " + safeLimit(limit, 100)); + + List> rows = prescriptionItemService.listMaps(wrapper); + List> ranking = new ArrayList<>(); + int rank = 1; + for (Map row : rows) { + Map item = new HashMap<>(); + item.put("rank", rank++); + item.put("drugId", toLong(getMapValue(row, "drugId", "drug_id", "DRUGID"))); + item.put("drugName", normalizeDrugName(getMapValue(row, "drugName", "drug_name", "DRUGNAME"))); + item.put("totalQuantity", toLong(getMapValue(row, "totalQuantity", "totalquantity", "TOTALQUANTITY"))); + item.put("totalAmount", toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT"))); + ranking.add(item); + } + + Map data = new HashMap<>(); + data.put("period", period); + data.put("startDate", range.start().toLocalDate().toString()); + data.put("endDate", range.end().minusDays(1).toLocalDate().toString()); + data.put("ranking", ranking); + return ApiResponse.success(data); + } + + @GetMapping("/report/doctor-performance") + public ApiResponse doctorPerformance(@RequestParam(defaultValue = "month") String period, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate, + @RequestParam(defaultValue = "10") int limit) { + DateRange range = resolveDateRange(period, startDate, endDate); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("doctor_id AS doctorId", "COUNT(*) AS visitCount", "COALESCE(SUM(total_amount), 0) AS totalAmount", "COALESCE(AVG(total_amount), 0) AS averageAmount"); + wrapper.ge("create_time", range.start()); + wrapper.lt("create_time", range.end()); + wrapper.isNotNull("doctor_id"); + wrapper.groupBy("doctor_id"); + wrapper.orderByDesc("totalAmount"); + wrapper.last("LIMIT " + safeLimit(limit, 100)); + + List> rows = visitService.listMaps(wrapper); + Set doctorIds = rows.stream() + .map(row -> toLong(getMapValue(row, "doctorId", "doctor_id", "DOCTORID"))) + .filter(id -> id > 0) + .collect(Collectors.toSet()); + Map doctorNameMap = userService.listByIds(doctorIds).stream() + .collect(Collectors.toMap(User::getId, User::getUsername, (left, right) -> left)); + + List> ranking = new ArrayList<>(); + int rank = 1; + for (Map row : rows) { + Long doctorId = toLong(getMapValue(row, "doctorId", "doctor_id", "DOCTORID")); + Map item = new HashMap<>(); + item.put("rank", rank++); + item.put("doctorId", doctorId); + item.put("doctorName", doctorNameMap.getOrDefault(doctorId, "医生#" + doctorId)); + item.put("visitCount", toLong(getMapValue(row, "visitCount", "visitcount", "VISITCOUNT"))); + item.put("totalAmount", toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT"))); + item.put("averageAmount", toBigDecimal(getMapValue(row, "averageAmount", "averageamount", "AVERAGEAMOUNT"))); + ranking.add(item); + } + + Map data = new HashMap<>(); + data.put("period", period); + data.put("startDate", range.start().toLocalDate().toString()); + data.put("endDate", range.end().minusDays(1).toLocalDate().toString()); + data.put("ranking", ranking); + return ApiResponse.success(data); + } + + @GetMapping("/report/department-performance") + public ApiResponse departmentPerformance(@RequestParam(defaultValue = "month") String period, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate) { + DateRange range = resolveDateRange(period, startDate, endDate); + + QueryWrapper appointmentWrapper = new QueryWrapper<>(); + appointmentWrapper.select("department", "COUNT(*) AS appointmentCount"); + appointmentWrapper.ge("create_time", range.start()); + appointmentWrapper.lt("create_time", range.end()); + appointmentWrapper.groupBy("department"); + List> appointmentRows = appointmentService.listMaps(appointmentWrapper); + + Map appointmentCountMap = new HashMap<>(); + for (Map row : appointmentRows) { + String department = normalizeDepartment(getMapValue(row, "department", "DEPARTMENT")); + appointmentCountMap.put(department, toLong(getMapValue(row, "appointmentCount", "appointmentcount", "APPOINTMENTCOUNT"))); + } + + List visits = visitService.list( + new LambdaQueryWrapper() + .ge(Visit::getCreateTime, range.start()) + .lt(Visit::getCreateTime, range.end()) + .isNotNull(Visit::getAppointmentId) + ); + + Set appointmentIds = visits.stream() + .map(Visit::getAppointmentId) + .filter(id -> id != null && id > 0) + .collect(Collectors.toSet()); + + Map appointmentMap = appointmentIds.isEmpty() + ? new HashMap<>() + : appointmentService.listByIds(appointmentIds).stream() + .collect(Collectors.toMap(Appointment::getId, appointment -> appointment, (left, right) -> left)); + + Map visitCountMap = new HashMap<>(); + Map revenueMap = new HashMap<>(); + for (Visit visit : visits) { + Appointment appointment = appointmentMap.get(visit.getAppointmentId()); + String department = normalizeDepartment(appointment == null ? null : appointment.getDepartment()); + visitCountMap.merge(department, 1L, Long::sum); + revenueMap.merge(department, visit.getTotalAmount() == null ? BigDecimal.ZERO : visit.getTotalAmount(), BigDecimal::add); + } + + Set departments = new HashSet<>(); + departments.addAll(appointmentCountMap.keySet()); + departments.addAll(visitCountMap.keySet()); + + List> departmentsData = departments.stream() + .map(department -> { + Map row = new HashMap<>(); + row.put("department", department); + row.put("appointmentCount", appointmentCountMap.getOrDefault(department, 0L)); + row.put("visitCount", visitCountMap.getOrDefault(department, 0L)); + row.put("totalAmount", revenueMap.getOrDefault(department, BigDecimal.ZERO)); + return row; + }) + .sorted((left, right) -> toBigDecimal(right.get("totalAmount")).compareTo(toBigDecimal(left.get("totalAmount")))) + .collect(Collectors.toList()); + + Map data = new HashMap<>(); + data.put("period", period); + data.put("startDate", range.start().toLocalDate().toString()); + data.put("endDate", range.end().minusDays(1).toLocalDate().toString()); + data.put("departments", departmentsData); + return ApiResponse.success(data); + } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping("/today-todos") public ApiResponse todayTodos() { LocalDate today = LocalDate.now(); @@ -243,4 +496,139 @@ public class StatsController { return ApiResponse.success(todoList); } + + private DateRange resolveDateRange(String period, String startDate, String endDate) { + if (hasText(startDate) && hasText(endDate)) { + LocalDate start = LocalDate.parse(startDate); + LocalDate end = LocalDate.parse(endDate); + if (end.isBefore(start)) { + LocalDate temp = start; + start = end; + end = temp; + } + return new DateRange(start.atStartOfDay(), end.plusDays(1).atStartOfDay()); + } + + LocalDate today = LocalDate.now(); + LocalDate start; + LocalDate end = today.plusDays(1); + switch (period) { + case "day": + start = today; + break; + case "week": + start = today.minusDays(6); + break; + case "year": + start = today.minusMonths(11).withDayOfMonth(1); + end = today.plusMonths(1).withDayOfMonth(1); + break; + case "month": + default: + start = today.minusDays(29); + break; + } + return new DateRange(start.atStartOfDay(), end.atStartOfDay()); + } + + private BigDecimal sumPaidOrderAmount(LocalDateTime start, LocalDateTime end) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("COALESCE(SUM(amount), 0) AS totalAmount"); + wrapper.eq("status", "PAID"); + wrapper.ge("create_time", start); + wrapper.lt("create_time", end); + List> rows = orderService.listMaps(wrapper); + if (rows.isEmpty()) { + return BigDecimal.ZERO; + } + return toBigDecimal(getMapValue(rows.get(0), "totalAmount", "totalamount", "TOTALAMOUNT")); + } + + private boolean hasText(String value) { + return value != null && !value.isBlank(); + } + + private int safeLimit(int value, int maxLimit) { + if (value <= 0) { + return 10; + } + return Math.min(value, maxLimit); + } + + private BigDecimal toBigDecimal(Object value) { + if (value == null) { + return BigDecimal.ZERO; + } + if (value instanceof BigDecimal) { + return (BigDecimal) value; + } + try { + return new BigDecimal(value.toString()); + } catch (NumberFormatException ex) { + return BigDecimal.ZERO; + } + } + + private long toLong(Object value) { + if (value == null) { + return 0L; + } + if (value instanceof Number) { + return ((Number) value).longValue(); + } + try { + return Long.parseLong(value.toString()); + } catch (NumberFormatException ex) { + return 0L; + } + } + + private Object getMapValue(Map row, String... keys) { + for (String key : keys) { + if (row.containsKey(key)) { + return row.get(key); + } + } + for (String key : keys) { + for (Map.Entry entry : row.entrySet()) { + if (entry.getKey().equalsIgnoreCase(key)) { + return entry.getValue(); + } + } + } + return null; + } + + private String normalizeDepartment(Object value) { + String department = value == null ? "" : value.toString().trim(); + return department.isEmpty() ? "未分配科室" : department; + } + + private String normalizePaymentMethod(String value) { + if (value == null || value.isBlank()) { + return "未知支付方式"; + } + switch (value) { + case "ALIPAY": + return "支付宝"; + case "WECHAT": + return "微信支付"; + case "OFFLINE": + return "线下支付"; + default: + return value; + } + } + + private String normalizeDrugName(Object value) { + String name = value == null ? "" : value.toString().trim(); + return name.isEmpty() ? "未知药品" : name; + } + + private record DateRange(LocalDateTime start, LocalDateTime end) { + private DateRange shiftBack() { + long days = Math.max(1, ChronoUnit.DAYS.between(start.toLocalDate(), end.toLocalDate())); + return new DateRange(start.minusDays(days), start); + } + } } diff --git a/backend/src/main/java/com/gpf/pethospital/controller/StockInController.java b/backend/src/main/java/com/gpf/pethospital/controller/StockInController.java index a3eac4a..788caf6 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/StockInController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/StockInController.java @@ -22,7 +22,7 @@ public class StockInController { this.drugService = drugService; } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping public ApiResponse list(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size, @@ -34,7 +34,7 @@ public class StockInController { return ApiResponse.success(stockInService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PostMapping @Transactional public ApiResponse create(@RequestBody StockIn stockIn) { diff --git a/backend/src/main/java/com/gpf/pethospital/controller/StockOutController.java b/backend/src/main/java/com/gpf/pethospital/controller/StockOutController.java index 048210f..ef14b9e 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/StockOutController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/StockOutController.java @@ -22,7 +22,7 @@ public class StockOutController { this.drugService = drugService; } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping public ApiResponse list(@RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size, @@ -34,7 +34,7 @@ public class StockOutController { return ApiResponse.success(stockOutService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PostMapping @Transactional public ApiResponse create(@RequestBody StockOut stockOut) { diff --git a/backend/src/main/java/com/gpf/pethospital/controller/UserController.java b/backend/src/main/java/com/gpf/pethospital/controller/UserController.java index 62ca9cb..2591606 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/UserController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/UserController.java @@ -67,7 +67,7 @@ public class UserController { return ApiResponse.success(result); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PostMapping public ApiResponse create(@RequestBody User user) { if (user.getPassword() == null || user.getPassword().isBlank()) { @@ -81,7 +81,7 @@ public class UserController { return ApiResponse.success("created", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PutMapping("/{id}/status") public ApiResponse updateStatus(@PathVariable Long id, @RequestParam Integer status) { User update = new User(); @@ -91,7 +91,7 @@ public class UserController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @PutMapping("/{id}/reset-password") public ApiResponse resetPassword(@PathVariable Long id, @RequestParam String newPassword) { User update = new User(); @@ -101,7 +101,7 @@ public class UserController { return ApiResponse.success("updated", null); } - @// @PreAuthorize("hasRole('ADMIN')") + // @PreAuthorize("hasRole('ADMIN')") @GetMapping("/stats") public ApiResponse stats() { Map data = new HashMap<>(); diff --git a/backend/src/main/java/com/gpf/pethospital/controller/VisitController.java b/backend/src/main/java/com/gpf/pethospital/controller/VisitController.java index de0f890..3227ebb 100644 --- a/backend/src/main/java/com/gpf/pethospital/controller/VisitController.java +++ b/backend/src/main/java/com/gpf/pethospital/controller/VisitController.java @@ -19,7 +19,7 @@ public class VisitController { this.visitService = visitService; } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PostMapping public ApiResponse create(@RequestBody Visit visit) { if (visit.getStatus() == null) { @@ -47,7 +47,7 @@ public class VisitController { return ApiResponse.success(visitService.page(new Page<>(page, size), wrapper)); } - @// @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") + // @PreAuthorize("hasAnyRole('ADMIN','DOCTOR')") @PutMapping("/{id}") public ApiResponse update(@PathVariable Long id, @RequestBody Visit visit) { visit.setId(id); diff --git a/backend/src/main/java/com/gpf/pethospital/entity/Report.java b/backend/src/main/java/com/gpf/pethospital/entity/Report.java index 86bcb7f..b15b024 100644 --- a/backend/src/main/java/com/gpf/pethospital/entity/Report.java +++ b/backend/src/main/java/com/gpf/pethospital/entity/Report.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.experimental.Accessors; +import java.time.LocalDate; import java.time.LocalDateTime; /** @@ -52,6 +53,16 @@ public class Report { */ private Long doctorId; + private String reportType; + + private String reportData; + + private LocalDate periodStart; + + private LocalDate periodEnd; + + private Long generatedBy; + /** * 创建时间 */ diff --git a/backend/target/classes/application-dev.yml b/backend/target/classes/application-dev.yml deleted file mode 100644 index 593dd40..0000000 --- a/backend/target/classes/application-dev.yml +++ /dev/null @@ -1,59 +0,0 @@ -server: - port: 8081 - address: 0.0.0.0 - servlet: - context-path: /api - -spring: - application: - name: pet-hospital - - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/pet_hospital_dev?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8 - username: root - password: qq5211314 - hikari: - maximum-pool-size: 20 - minimum-idle: 10 - connection-timeout: 30000 - idle-timeout: 600000 - max-lifetime: 1800000 - - jackson: - time-zone: GMT+8 - date-format: yyyy-MM-dd HH:mm:ss - - jpa: - hibernate: - ddl-auto: update - show-sql: true - - sql: - init: - mode: never - schema-locations: classpath*:schema.sql - data-locations: classpath*:data.sql - -mybatis-plus: - configuration: - map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - global-config: - db-config: - id-type: auto - logic-delete-field: deleted - logic-delete-value: 1 - logic-not-delete-value: 0 - mapper-locations: classpath*:mapper/**/*.xml - ddl-auto: create-drop - -# JWT配置 -jwt: - secret: petHospitalSecretKey2024GuanPengFeiGraduateDesign - expiration: 86400000 # 24小时 - -# 文件上传配置 -file: - upload-path: /tmp/pet-hospital/uploads/ - max-size: 10MB \ No newline at end of file diff --git a/backend/target/classes/application.yml b/backend/target/classes/application.yml deleted file mode 100644 index 76a99cf..0000000 --- a/backend/target/classes/application.yml +++ /dev/null @@ -1,39 +0,0 @@ -server: - port: 8080 - servlet: - context-path: /api - -spring: - profiles: - active: dev - application: - name: pet-hospital - jackson: - time-zone: GMT+8 - date-format: yyyy-MM-dd HH:mm:ss - -mybatis-plus: - configuration: - map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - global-config: - db-config: - id-type: auto - logic-delete-field: deleted - logic-delete-value: 1 - logic-not-delete-value: 0 - mapper-locations: classpath*:mapper/**/*.xml - -# 数据库配置 -database: - type: mysql - -# JWT配置 -jwt: - secret: pet-hospital-secret-key-2024-guanpengfei-graduate-design - expiration: 86400000 # 24小时 - -# 文件上传配置 -file: - upload-path: /tmp/pet-hospital/uploads/ - max-size: 10MB diff --git a/backend/target/classes/com/gpf/pethospital/PetHospitalApplication.class b/backend/target/classes/com/gpf/pethospital/PetHospitalApplication.class deleted file mode 100644 index 9e827cb..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/PetHospitalApplication.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/common/ApiResponse.class b/backend/target/classes/com/gpf/pethospital/common/ApiResponse.class deleted file mode 100644 index 219a61c..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/common/ApiResponse.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/config/MybatisPlusConfig$1.class b/backend/target/classes/com/gpf/pethospital/config/MybatisPlusConfig$1.class deleted file mode 100644 index eda7e88..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/config/MybatisPlusConfig$1.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/config/MybatisPlusConfig.class b/backend/target/classes/com/gpf/pethospital/config/MybatisPlusConfig.class deleted file mode 100644 index 7246fa0..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/config/MybatisPlusConfig.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/config/SecurityConfig.class b/backend/target/classes/com/gpf/pethospital/config/SecurityConfig.class deleted file mode 100644 index 3bcda2c..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/config/SecurityConfig.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/config/WebConfig.class b/backend/target/classes/com/gpf/pethospital/config/WebConfig.class deleted file mode 100644 index df949d9..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/config/WebConfig.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/AppointmentController.class b/backend/target/classes/com/gpf/pethospital/controller/AppointmentController.class deleted file mode 100644 index 193a128..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/AppointmentController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/AuthController.class b/backend/target/classes/com/gpf/pethospital/controller/AuthController.class deleted file mode 100644 index 89512d1..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/AuthController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/DrugController.class b/backend/target/classes/com/gpf/pethospital/controller/DrugController.class deleted file mode 100644 index 56b0c95..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/DrugController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/MedicalRecordController.class b/backend/target/classes/com/gpf/pethospital/controller/MedicalRecordController.class deleted file mode 100644 index 55506c5..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/MedicalRecordController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/MessageController.class b/backend/target/classes/com/gpf/pethospital/controller/MessageController.class deleted file mode 100644 index fcadbbd..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/MessageController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/NoticeController.class b/backend/target/classes/com/gpf/pethospital/controller/NoticeController.class deleted file mode 100644 index 88b1dca..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/NoticeController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/OrderController.class b/backend/target/classes/com/gpf/pethospital/controller/OrderController.class deleted file mode 100644 index 44f0878..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/OrderController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/PetController.class b/backend/target/classes/com/gpf/pethospital/controller/PetController.class deleted file mode 100644 index 251f963..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/PetController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/PrescriptionController.class b/backend/target/classes/com/gpf/pethospital/controller/PrescriptionController.class deleted file mode 100644 index 099af9c..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/PrescriptionController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/PrescriptionItemController.class b/backend/target/classes/com/gpf/pethospital/controller/PrescriptionItemController.class deleted file mode 100644 index 6bc4f56..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/PrescriptionItemController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/ReportController.class b/backend/target/classes/com/gpf/pethospital/controller/ReportController.class deleted file mode 100644 index 73c2cf1..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/ReportController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/StatsController.class b/backend/target/classes/com/gpf/pethospital/controller/StatsController.class deleted file mode 100644 index 6909df5..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/StatsController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/StockInController.class b/backend/target/classes/com/gpf/pethospital/controller/StockInController.class deleted file mode 100644 index 4c98751..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/StockInController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/StockOutController.class b/backend/target/classes/com/gpf/pethospital/controller/StockOutController.class deleted file mode 100644 index 31ce38d..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/StockOutController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/UserController.class b/backend/target/classes/com/gpf/pethospital/controller/UserController.class deleted file mode 100644 index 05e5c04..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/UserController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/VaccineRecordController.class b/backend/target/classes/com/gpf/pethospital/controller/VaccineRecordController.class deleted file mode 100644 index 82c8cb8..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/VaccineRecordController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/controller/VisitController.class b/backend/target/classes/com/gpf/pethospital/controller/VisitController.class deleted file mode 100644 index 58799db..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/controller/VisitController.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/dto/LoginRequest.class b/backend/target/classes/com/gpf/pethospital/dto/LoginRequest.class deleted file mode 100644 index 6e46c2e..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/dto/LoginRequest.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/dto/RegisterRequest.class b/backend/target/classes/com/gpf/pethospital/dto/RegisterRequest.class deleted file mode 100644 index f5fc98f..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/dto/RegisterRequest.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/dto/ReplyRequest.class b/backend/target/classes/com/gpf/pethospital/dto/ReplyRequest.class deleted file mode 100644 index 8e0ddc3..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/dto/ReplyRequest.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Appointment.class b/backend/target/classes/com/gpf/pethospital/entity/Appointment.class deleted file mode 100644 index 78552c9..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Appointment.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Drug.class b/backend/target/classes/com/gpf/pethospital/entity/Drug.class deleted file mode 100644 index cff9e53..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Drug.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/MedicalRecord.class b/backend/target/classes/com/gpf/pethospital/entity/MedicalRecord.class deleted file mode 100644 index d06fc0d..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/MedicalRecord.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Message.class b/backend/target/classes/com/gpf/pethospital/entity/Message.class deleted file mode 100644 index 2637780..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Message.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Notice.class b/backend/target/classes/com/gpf/pethospital/entity/Notice.class deleted file mode 100644 index 153c7c0..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Notice.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Order.class b/backend/target/classes/com/gpf/pethospital/entity/Order.class deleted file mode 100644 index 2949ea1..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Order.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Pet.class b/backend/target/classes/com/gpf/pethospital/entity/Pet.class deleted file mode 100644 index efd68d3..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Pet.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Prescription.class b/backend/target/classes/com/gpf/pethospital/entity/Prescription.class deleted file mode 100644 index 44e638d..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Prescription.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/PrescriptionItem.class b/backend/target/classes/com/gpf/pethospital/entity/PrescriptionItem.class deleted file mode 100644 index a0dd0c2..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/PrescriptionItem.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Report.class b/backend/target/classes/com/gpf/pethospital/entity/Report.class deleted file mode 100644 index 4bfea4a..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Report.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/StockIn.class b/backend/target/classes/com/gpf/pethospital/entity/StockIn.class deleted file mode 100644 index 011c90b..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/StockIn.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/StockOut.class b/backend/target/classes/com/gpf/pethospital/entity/StockOut.class deleted file mode 100644 index 4b41f3c..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/StockOut.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/User.class b/backend/target/classes/com/gpf/pethospital/entity/User.class deleted file mode 100644 index e297ac2..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/User.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/VaccineRecord.class b/backend/target/classes/com/gpf/pethospital/entity/VaccineRecord.class deleted file mode 100644 index b52eeed..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/VaccineRecord.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/entity/Visit.class b/backend/target/classes/com/gpf/pethospital/entity/Visit.class deleted file mode 100644 index 25fb99e..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/entity/Visit.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/AppointmentMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/AppointmentMapper.class deleted file mode 100644 index 9d9471b..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/AppointmentMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/DrugMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/DrugMapper.class deleted file mode 100644 index 95de6cd..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/DrugMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/MedicalRecordMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/MedicalRecordMapper.class deleted file mode 100644 index b87250b..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/MedicalRecordMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/MessageMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/MessageMapper.class deleted file mode 100644 index 47b6f6f..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/MessageMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/NoticeMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/NoticeMapper.class deleted file mode 100644 index 150fe7a..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/NoticeMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/OrderMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/OrderMapper.class deleted file mode 100644 index 47f3775..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/OrderMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/PetMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/PetMapper.class deleted file mode 100644 index cd12a16..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/PetMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/PrescriptionItemMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/PrescriptionItemMapper.class deleted file mode 100644 index 5c7fe9c..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/PrescriptionItemMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/PrescriptionMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/PrescriptionMapper.class deleted file mode 100644 index f528465..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/PrescriptionMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/ReportMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/ReportMapper.class deleted file mode 100644 index f8a339b..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/ReportMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/StockInMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/StockInMapper.class deleted file mode 100644 index d20d2e6..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/StockInMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/StockOutMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/StockOutMapper.class deleted file mode 100644 index 755994b..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/StockOutMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/UserMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/UserMapper.class deleted file mode 100644 index de4e5e8..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/UserMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/VaccineRecordMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/VaccineRecordMapper.class deleted file mode 100644 index f62be06..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/VaccineRecordMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/mapper/VisitMapper.class b/backend/target/classes/com/gpf/pethospital/mapper/VisitMapper.class deleted file mode 100644 index 0b09196..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/mapper/VisitMapper.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/security/AuthUser.class b/backend/target/classes/com/gpf/pethospital/security/AuthUser.class deleted file mode 100644 index 9b34430..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/security/AuthUser.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/security/JwtAuthenticationFilter.class b/backend/target/classes/com/gpf/pethospital/security/JwtAuthenticationFilter.class deleted file mode 100644 index edef585..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/security/JwtAuthenticationFilter.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/AppointmentService.class b/backend/target/classes/com/gpf/pethospital/service/AppointmentService.class deleted file mode 100644 index fe1e871..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/AppointmentService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/DrugService.class b/backend/target/classes/com/gpf/pethospital/service/DrugService.class deleted file mode 100644 index 4d9b08a..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/DrugService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/MedicalRecordService.class b/backend/target/classes/com/gpf/pethospital/service/MedicalRecordService.class deleted file mode 100644 index efe2ebe..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/MedicalRecordService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/MessageService.class b/backend/target/classes/com/gpf/pethospital/service/MessageService.class deleted file mode 100644 index 77343c5..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/MessageService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/NoticeService.class b/backend/target/classes/com/gpf/pethospital/service/NoticeService.class deleted file mode 100644 index 444dfc8..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/NoticeService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/OrderService.class b/backend/target/classes/com/gpf/pethospital/service/OrderService.class deleted file mode 100644 index 245d543..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/OrderService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/PetService.class b/backend/target/classes/com/gpf/pethospital/service/PetService.class deleted file mode 100644 index c99cc22..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/PetService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/PrescriptionItemService.class b/backend/target/classes/com/gpf/pethospital/service/PrescriptionItemService.class deleted file mode 100644 index 464a50a..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/PrescriptionItemService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/PrescriptionService.class b/backend/target/classes/com/gpf/pethospital/service/PrescriptionService.class deleted file mode 100644 index 85563d1..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/PrescriptionService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/ReportService.class b/backend/target/classes/com/gpf/pethospital/service/ReportService.class deleted file mode 100644 index d1ee4be..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/ReportService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/StockInService.class b/backend/target/classes/com/gpf/pethospital/service/StockInService.class deleted file mode 100644 index fe2cff3..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/StockInService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/StockOutService.class b/backend/target/classes/com/gpf/pethospital/service/StockOutService.class deleted file mode 100644 index c1b27f5..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/StockOutService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/UserService.class b/backend/target/classes/com/gpf/pethospital/service/UserService.class deleted file mode 100644 index 690cfd8..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/UserService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/VaccineRecordService.class b/backend/target/classes/com/gpf/pethospital/service/VaccineRecordService.class deleted file mode 100644 index 58d7e29..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/VaccineRecordService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/VisitService.class b/backend/target/classes/com/gpf/pethospital/service/VisitService.class deleted file mode 100644 index 6e0c300..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/VisitService.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/AppointmentServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/AppointmentServiceImpl.class deleted file mode 100644 index dd4145a..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/AppointmentServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/DrugServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/DrugServiceImpl.class deleted file mode 100644 index 4130050..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/DrugServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/MedicalRecordServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/MedicalRecordServiceImpl.class deleted file mode 100644 index 3361bcb..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/MedicalRecordServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/MessageServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/MessageServiceImpl.class deleted file mode 100644 index 4471d60..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/MessageServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/NoticeServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/NoticeServiceImpl.class deleted file mode 100644 index 018721c..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/NoticeServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/OrderServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/OrderServiceImpl.class deleted file mode 100644 index 317f9d0..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/OrderServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/PetServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/PetServiceImpl.class deleted file mode 100644 index 75bb8fd..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/PetServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/PrescriptionItemServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/PrescriptionItemServiceImpl.class deleted file mode 100644 index f6a859a..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/PrescriptionItemServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/PrescriptionServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/PrescriptionServiceImpl.class deleted file mode 100644 index c7d1fa7..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/PrescriptionServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/ReportServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/ReportServiceImpl.class deleted file mode 100644 index 7d9c641..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/ReportServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/StockInServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/StockInServiceImpl.class deleted file mode 100644 index 929a44f..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/StockInServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/StockOutServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/StockOutServiceImpl.class deleted file mode 100644 index 31971ad..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/StockOutServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/UserServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/UserServiceImpl.class deleted file mode 100644 index dba3363..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/UserServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/VaccineRecordServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/VaccineRecordServiceImpl.class deleted file mode 100644 index 5fbce54..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/VaccineRecordServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/service/impl/VisitServiceImpl.class b/backend/target/classes/com/gpf/pethospital/service/impl/VisitServiceImpl.class deleted file mode 100644 index bb66179..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/service/impl/VisitServiceImpl.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/util/JwtUtil.class b/backend/target/classes/com/gpf/pethospital/util/JwtUtil.class deleted file mode 100644 index 569f5cc..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/util/JwtUtil.class and /dev/null differ diff --git a/backend/target/classes/com/gpf/pethospital/util/SecurityUtils.class b/backend/target/classes/com/gpf/pethospital/util/SecurityUtils.class deleted file mode 100644 index adf6516..0000000 Binary files a/backend/target/classes/com/gpf/pethospital/util/SecurityUtils.class and /dev/null differ diff --git a/backend/target/classes/data.sql b/backend/target/classes/data.sql deleted file mode 100644 index 1f3337f..0000000 --- a/backend/target/classes/data.sql +++ /dev/null @@ -1,17 +0,0 @@ --- 插入初始管理员用户 -INSERT INTO `user` (username, password, phone, email, role, status) VALUES ('admin', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '13800138000', 'admin@example.com', 'ADMIN', 1); - --- 插入初始医生用户 -INSERT INTO `user` (username, password, phone, email, role, status) VALUES ('doctor', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '13700137000', 'doctor@example.com', 'DOCTOR', 1); - --- 插入初始顾客用户 -INSERT INTO `user` (username, password, phone, email, role, status) VALUES ('customer', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '13900139000', 'customer@example.com', 'CUSTOMER', 1); - --- 插入示例宠物 -INSERT INTO pet (name, species, breed, gender, birthday, owner_id) VALUES ('小白', '狗', '金毛', 'MALE', '2023-01-01', 3); - --- 插入示例医生 -INSERT INTO doctor (name, department, title, phone, email, status) VALUES ('张医生', '内科', '主治医师', '13600136000', 'zhang@hospital.com', 1); - --- 插入示例药品 -INSERT INTO drug (name, category, manufacturer, specification, unit_price, stock_quantity, unit, status) VALUES ('阿莫西林', '抗生素', '制药厂A', '0.25g*24粒', 25.50, 100, '盒', 1); \ No newline at end of file diff --git a/backend/target/classes/schema.sql b/backend/target/classes/schema.sql deleted file mode 100644 index 6b2235a..0000000 --- a/backend/target/classes/schema.sql +++ /dev/null @@ -1,291 +0,0 @@ --- 如果表不存在则创建表,如果存在则添加缺失的列 - --- 检查并创建appointment表或添加缺失列 -CREATE TABLE IF NOT EXISTS appointment ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - customer_id BIGINT NOT NULL, - pet_id BIGINT NOT NULL, - doctor_id BIGINT, - department VARCHAR(50), - appointment_date DATE, - time_slot VARCHAR(20), -- 添加这个缺失的列 - status VARCHAR(20) DEFAULT 'PENDING', - remark TEXT, - cancel_time TIMESTAMP NULL, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建visit表 -CREATE TABLE IF NOT EXISTS visit ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - appointment_id BIGINT, - customer_id BIGINT NOT NULL, - pet_id BIGINT NOT NULL, - doctor_id BIGINT NOT NULL, - symptoms TEXT, - diagnosis TEXT, - treatment_plan TEXT, - status VARCHAR(20) DEFAULT 'PENDING', - total_amount DECIMAL(10,2), - payment_status VARCHAR(20) DEFAULT 'UNPAID', - payment_method VARCHAR(20), - payment_time TIMESTAMP NULL, - start_time TIMESTAMP, - end_time TIMESTAMP, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建prescription表 -CREATE TABLE IF NOT EXISTS prescription ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - visit_id BIGINT, - doctor_id BIGINT, - customer_id BIGINT, - total_amount DECIMAL(10,2), - status VARCHAR(20) DEFAULT 'DRAFT', - remark TEXT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建prescription_item表 -CREATE TABLE IF NOT EXISTS prescription_item ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - prescription_id BIGINT NOT NULL, - drug_id BIGINT NOT NULL, - drug_name VARCHAR(100), - specification VARCHAR(100), - quantity INT NOT NULL, - usage_desc VARCHAR(200), - days INT, - unit_price DECIMAL(10,2), - subtotal DECIMAL(10,2), - dosage VARCHAR(100), - frequency VARCHAR(50), - duration VARCHAR(50), - usage_instructions TEXT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建order_info表 -CREATE TABLE IF NOT EXISTS order_info ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - visit_id BIGINT, - customer_id BIGINT NOT NULL, - amount DECIMAL(10,2), - status VARCHAR(20) DEFAULT 'UNPAID', - payment_method VARCHAR(20), - payment_time TIMESTAMP NULL, - remark TEXT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建drug表 -CREATE TABLE IF NOT EXISTS drug ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(100) NOT NULL, - category VARCHAR(50), - manufacturer VARCHAR(100), - specification VARCHAR(100), - unit_price DECIMAL(10,2), - stock_quantity INT DEFAULT 0, - stock INT DEFAULT 0, - alert_threshold INT, - purchase_price DECIMAL(10,2), - sale_price DECIMAL(10,2), - approval_number VARCHAR(100), - expiry_date TIMESTAMP NULL, - unit VARCHAR(20), - status INT DEFAULT 1, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建pet表 -CREATE TABLE IF NOT EXISTS pet ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - owner_id BIGINT NOT NULL, - name VARCHAR(50) NOT NULL, - species VARCHAR(50), - breed VARCHAR(100), - gender VARCHAR(10), -- 修改为VARCHAR以支持MALE/FEMALE - birthday DATE, -- 添加birthday字段 - age INT, -- 添加age字段 - weight DOUBLE, -- 添加weight字段 - photo VARCHAR(255), -- 添加photo字段 - remark TEXT, -- 添加remark字段 - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 为已存在的pet表添加age列 -ALTER TABLE pet ADD COLUMN IF NOT EXISTS age INT AFTER birthday; - --- 检查并创建doctor表 -CREATE TABLE IF NOT EXISTS doctor ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(50) NOT NULL, - department VARCHAR(50), - title VARCHAR(50), - phone VARCHAR(20), - email VARCHAR(100), - avatar VARCHAR(255), - status INT DEFAULT 1, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建user表 -CREATE TABLE IF NOT EXISTS `user` ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - username VARCHAR(50) NOT NULL UNIQUE, - phone VARCHAR(20), - email VARCHAR(100), - password VARCHAR(255) NOT NULL, - role VARCHAR(20) DEFAULT 'CUSTOMER', - status INT DEFAULT 1, - avatar VARCHAR(255), - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建medical_record表 -CREATE TABLE IF NOT EXISTS medical_record ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - visit_id BIGINT NOT NULL, - chief_complaint TEXT, - present_illness TEXT, - physical_examination TEXT, - examination_results TEXT, - diagnosis TEXT, - treatment_plan TEXT, - advice TEXT, - status VARCHAR(20), - record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗 - content TEXT, - attachment_urls TEXT, - doctor_id BIGINT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建message表 -CREATE TABLE IF NOT EXISTS message ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - user_id BIGINT, - user_name VARCHAR(100), - contact VARCHAR(100), - title VARCHAR(200), - sender_id BIGINT, - receiver_id BIGINT NOT NULL, - content TEXT NOT NULL, - type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天 - status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读 - reply TEXT, - reply_time TIMESTAMP NULL, - reply_user_id BIGINT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建notice表 -CREATE TABLE IF NOT EXISTS notice ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - title VARCHAR(200) NOT NULL, - content TEXT NOT NULL, - is_top INT DEFAULT 0, - publisher_id BIGINT NOT NULL, - publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - status INT DEFAULT 1, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建report表 -CREATE TABLE IF NOT EXISTS report ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - visit_id BIGINT, - pet_id BIGINT, - type VARCHAR(50), - title VARCHAR(200), - summary TEXT, - attachment_url VARCHAR(255), - doctor_id BIGINT, - report_type VARCHAR(50) DEFAULT 'DIAGNOSIS', -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品, DIAGNOSIS检查报告 - report_data JSON, - period_start DATE, - period_end DATE, - generated_by BIGINT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 为已存在的report表修改report_type默认值 -ALTER TABLE report MODIFY COLUMN report_type VARCHAR(50) DEFAULT 'DIAGNOSIS'; - --- 检查并创建stock_in表 -CREATE TABLE IF NOT EXISTS stock_in ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - drug_id BIGINT NOT NULL, - quantity INT NOT NULL, - unit_price DECIMAL(10,2), - supplier VARCHAR(100), - operator_id BIGINT, - stock_in_time TIMESTAMP NULL, - remark TEXT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建stock_out表 -CREATE TABLE IF NOT EXISTS stock_out ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - drug_id BIGINT NOT NULL, - prescription_id BIGINT, - quantity INT NOT NULL, - unit_price DECIMAL(10,2), - purpose VARCHAR(100), -- 用途:销售、损耗等 - operator_id BIGINT, - stock_out_time TIMESTAMP NULL, - remark TEXT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); - --- 检查并创建vaccine_record表 -CREATE TABLE IF NOT EXISTS vaccine_record ( - id BIGINT AUTO_INCREMENT PRIMARY KEY, - pet_id BIGINT NOT NULL, - type VARCHAR(20), -- VACCINE疫苗, DEWORMING驱虫 - item_name VARCHAR(100), - execute_date DATE, - next_reminder_date DATE, - vaccine_name VARCHAR(100) NOT NULL, - dose_number INT, - injection_date DATE, - next_appointment_date DATE, - doctor_id BIGINT, - remark TEXT, - create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - deleted INT DEFAULT 0 -); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 28a6e2f..855ae59 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "axios": "^1.6.7", + "echarts": "^6.0.0", "pinia": "^2.1.7", "tdesign-vue-next": "^1.8.8", "vue": "^3.4.15", @@ -291,6 +292,16 @@ "node": ">= 0.4" } }, + "node_modules/echarts": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz", + "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.0.0" + } + }, "node_modules/entities": { "version": "7.0.1", "license": "BSD-2-Clause", @@ -1425,11 +1436,16 @@ "version": "1.6.0", "license": "MIT" }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/typescript": { "version": "5.9.3", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1449,7 +1465,6 @@ "version": "5.4.21", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -1522,7 +1537,6 @@ "node_modules/vue": { "version": "3.5.27", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.27", "@vue/compiler-sfc": "3.5.27", @@ -1575,6 +1589,15 @@ "peerDependencies": { "vue": "^3.5.0" } + }, + "node_modules/zrender": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz", + "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } } } } diff --git a/frontend/package.json b/frontend/package.json index 6895525..36592bc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "axios": "^1.6.7", + "echarts": "^6.0.0", "pinia": "^2.1.7", "tdesign-vue-next": "^1.8.8", "vue": "^3.4.15", diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index eb1be07..c22204c 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -74,4 +74,9 @@ export const api = { stats: () => http.get('/admin/stats'), statsTrends: (period?: string) => http.get('/admin/stats/trends', { params: { period } }), todayTodos: () => http.get('/admin/stats/today-todos'), + statsRevenueReport: (params?: any) => http.get('/admin/stats/report/revenue', { params }), + statsRevenueSources: (params?: any) => http.get('/admin/stats/report/revenue-sources', { params }), + statsDrugSales: (params?: any) => http.get('/admin/stats/report/drug-sales', { params }), + statsDoctorPerformance: (params?: any) => http.get('/admin/stats/report/doctor-performance', { params }), + statsDepartmentPerformance: (params?: any) => http.get('/admin/stats/report/department-performance', { params }), }; diff --git a/frontend/src/pages/StatsPage.vue b/frontend/src/pages/StatsPage.vue index 1460fbf..4d9bc71 100644 --- a/frontend/src/pages/StatsPage.vue +++ b/frontend/src/pages/StatsPage.vue @@ -1,49 +1,407 @@ + + diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 70b142b..2b27e99 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -296,7 +296,7 @@ body { /* 页面标题 */ .page-title { - font-size: 32px; + font-size: 20px; font-weight: 800; margin: 0 0 12px; color: var(--text); diff --git a/爱维宠物医院管理系统-用例图.drawio b/爱维宠物医院管理系统-用例图.drawio new file mode 100644 index 0000000..d4def48 --- /dev/null +++ b/爱维宠物医院管理系统-用例图.drawio @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/爱维宠物医院管理系统毕业论文-2026版-排版.docx b/爱维宠物医院管理系统毕业论文-2026版-排版.docx index 4e305c7..2883fe6 100644 Binary files a/爱维宠物医院管理系统毕业论文-2026版-排版.docx and b/爱维宠物医院管理系统毕业论文-2026版-排版.docx differ diff --git a/爱维宠物医院管理系统毕业论文-2026版.md b/爱维宠物医院管理系统毕业论文-2026版.md index 826062f..6e050f2 100644 --- a/爱维宠物医院管理系统毕业论文-2026版.md +++ b/爱维宠物医院管理系统毕业论文-2026版.md @@ -242,22 +242,120 @@ Comprehensive functional and process-oriented testing indicates that the system #### 3.3.1 顾客用例图 -顾客角色的核心用例包括:注册登录、维护宠物档案、提交预约、查看订单、查询报告。 +顾客角色的用例包括:注册登录、维护宠物档案、提交预约、取消预约、查询预约记录、查看订单、查询报告、查看公告、修改个人信息、修改密码。 + +主要用例说明: +- **注册登录**:新用户注册和已有用户登录系统的入口 +- **维护宠物档案**:新增、编辑、删除宠物信息,包括宠物名称、品种、性别、出生日期等 +- **提交预约**:选择宠物、预约日期、时段和医生(可选)提交预约请求 +- **取消预约**:在预约开始前取消已提交的预约 +- **查询预约记录**:查看个人历史预约记录及其状态 +- **查看订单**:查询就诊产生的订单信息及支付状态 +- **查询报告**:查看检验报告、检查报告等医疗报告 +- **查看公告**:浏览医院发布的公告和通知 +- **修改个人信息**:更新账户基本信息(如手机号、邮箱等) +- **修改密码**:更改登录密码 (图3.1 顾客用例图) #### 3.3.2 医生用例图 -医生角色的核心用例包括:查看预约、创建就诊记录、编辑病历、开具处方、查询历史记录。 +医生角色的用例包括:登录、查看预约、接诊确认、创建就诊记录、编辑病历、开具处方、查看处方、查询历史病历、查询历史处方、查看公告、修改个人信息、修改密码。 + +主要用例说明: +- **登录**:医生使用账号密码登录系统 +- **查看预约**:查看分配给自己的预约列表及预约详情 +- **接诊确认**:确认顾客到诊并开始接诊流程 +- **创建就诊记录**:为已到诊的预约创建就诊记录,记录症状、初步诊断 +- **编辑病历**:完善病历信息,录入主诉、检查结果、诊断结论、处理建议 +- **开具处方**:为就诊对象创建处方,添加药品明细及用法用量 +- **查看处方**:查看已开具的处方信息 +- **查询历史病历**:按宠物、顾客、时间等条件查询历史病历记录 +- **查询历史处方**:按条件查询历史处方记录 +- **查看公告**:浏览医院发布的公告和通知 +- **修改个人信息**:更新个人信息(如职称、联系方式等) +- **修改密码**:更改登录密码 (图3.2 医生用例图) #### 3.3.3 管理员用例图 -管理员角色的核心用例包括:用户管理、公告管理、药品库存管理、统计报表查看。 +管理员角色的用例包括:登录、用户管理(查看用户列表、新增用户、编辑用户、禁用用户、启用用户)、医生管理(新增医生、编辑医生、查看医生列表)、公告管理(发布公告、编辑公告、删除公告、查看公告列表)、药品管理(新增药品、编辑药品、查看药品列表、禁用药品、启用药品)、药品入库、药品出库、库存查询、统计报表查看(预约统计、订单统计、药品消耗统计)、修改个人信息、修改密码。 + +主要用例说明: +- **登录**:管理员使用账号密码登录系统 +- **用户管理**:管理系统中的用户账户,包括查看、新增、编辑、禁用、启用用户 +- **医生管理**:管理医生信息,包括新增医生、编辑医生信息、查看医生列表 +- **公告管理**:发布、编辑、删除医院公告,管理公告内容 +- **药品管理**:维护药品基础信息,包括药品名称、分类、规格、价格、预警阈值等 +- **药品入库**:记录药品入库操作,更新药品库存数量 +- **药品出库**:记录药品出库操作,扣减药品库存数量 +- **库存查询**:查看当前所有药品的库存情况 +- **统计报表查看**:查看预约统计、订单统计、药品消耗统计等经营数据 +- **修改个人信息**:更新管理员个人信息 +- **修改密码**:更改登录密码 (图3.3 管理员用例图) +#### 3.3.4 用例关系(include关系) + +系统用例之间存在明确的包含关系(include),用`<>`表示。包含关系表示一个用例必须包含另一个用例的行为才能完成。以下列出系统的主要包含关系: + +**(1)顾客用例的include关系** + +- 提交预约 <> 登录 +- 取消预约 <> 登录 +- 查询预约记录 <> 登录 +- 查看订单 <> 登录 +- 查询报告 <> 登录 +- 维护宠物档案 <> 登录 +- 修改个人信息 <> 登录 +- 修改密码 <> 登录 +- 提交预约 <> 维护宠物档案(需要先创建宠物档案才能进行预约) + +**(2)医生用例的include关系** + +- 查看预约 <> 登录 +- 接诊确认 <> 登录 +- 创建就诊记录 <> 登录 +- 编辑病历 <> 登录 +- 开具处方 <> 登录 +- 查看处方 <> 登录 +- 查询历史病历 <> 登录 +- 查询历史处方 <> 登录 +- 修改个人信息 <> 登录 +- 修改密码 <> 登录 +- 创建就诊记录 <> 查看预约(需要先查看预约才能创建就诊记录) +- 编辑病历 <> 创建就诊记录(需要先创建就诊记录才能编辑病历) +- 开具处方 <> 创建就诊记录(需要先创建就诊记录才能开具处方) +- 开具处方 <> 编辑病历(需要先完成病历录入才能开具处方) + +**(3)管理员用例的include关系** + +- 用户管理 <> 登录 +- 医生管理 <> 登录 +- 公告管理 <> 登录 +- 药品管理 <> 登录 +- 药品入库 <> 登录 +- 药品出库 <> 登录 +- 库存查询 <> 登录 +- 统计报表查看 <> 登录 +- 修改个人信息 <> 登录 +- 修改密码 <> 登录 +- 药品入库 <> 药品管理(需要先在药品管理中维护药品信息才能进行入库操作) +- 药品出库 <> 药品管理(需要先在药品管理中维护药品信息才能进行出库操作) + +**(4)跨角色共享用例** + +以下用例被多个角色共享: + +- **登录**:被顾客、医生、管理员三个角色的所有业务用例包含 +- **修改个人信息**:被顾客、医生、管理员三个角色使用 +- **修改密码**:被顾客、医生、管理员三个角色使用 +- **查看公告**:被顾客、医生、管理员三个角色使用 + +这些共享用例体现了系统的基础能力,所有角色的业务操作都依赖于这些基础用例的完成。 + ### 3.4 用例描述 #### 3.4.1 顾客预约门诊用例描述 @@ -292,6 +390,93 @@ Comprehensive functional and process-oriented testing indicates that the system | 后置条件 | 入库记录写入并更新药品库存 | | 基本事件流 | 进入入库管理 → 选择药品并填写数量、单价、供应信息 → 提交入库 | | 异常事件流 | 输入数据非法时,系统提示修正后再提交 | +#### 3.4.4 顾客维护宠物档案用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 顾客维护宠物档案 | +| 执行者 | 顾客 | +| 前置条件 | 顾客已登录 | +| 后置条件 | 宠物信息保存到数据库 | +| 基本事件流 | 进入宠物档案管理 → 点击新增/编辑 → 填写宠物信息(名称、品种、性别、出生日期、体重等)→ 提交保存 | +| 异常事件流 | 必填信息缺失或数据格式错误时,系统提示修正 | + +#### 3.4.5 顾客取消预约用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 顾客取消预约 | +| 执行者 | 顾客 | +| 前置条件 | 顾客已登录且存在待确认或已确认的预约记录 | +| 后置条件 | 预约状态更新为已取消 | +| 基本事件流 | 进入预约管理 → 选择要取消的预约 → 点击取消按钮 → 确认取消 | +| 异常事件流 | 预约已接诊或已过取消时限时,系统阻止取消并提示 | + +#### 3.4.6 医生创建就诊记录用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 医生创建就诊记录 | +| 执行者 | 医生 | +| 前置条件 | 顾客已到诊,存在有效预约 | +| 后置条件 | 生成就诊记录 | +| 基本事件流 | 查看待处理预约 → 确认顾客到诊 → 点击接诊 → 创建就诊记录 → 录入初步信息 | +| 异常事件流 | 预约不存在或状态不允许接诊时,系统提示 | + +#### 3.4.7 医生编辑病历用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 医生编辑病历 | +| 执行者 | 医生 | +| 前置条件 | 已存在就诊记录 | +| 后置条件 | 病历信息更新并保存 | +| 基本事件流 | 进入就诊记录详情 → 点击编辑病历 → 录入主诉、检查结果、诊断结论、处理建议 → 保存 | +| 异常事件流 | 就诊记录不存在或已完成结算时,系统阻止编辑 | + +#### 3.4.8 管理员药品出库用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 管理员药品出库 | +| 执行者 | 管理员 | +| 前置条件 | 管理员已登录且拥有库存管理权限,药品库存充足 | +| 后置条件 | 出库记录写入并扣减药品库存 | +| 基本事件流 | 进入出库管理 → 选择药品并填写数量、出库用途 → 提交出库 | +| 异常事件流 | 出库数量大于库存或输入数据非法时,系统提示 | + +#### 3.4.9 管理员发布公告用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 管理员发布公告 | +| 执行者 | 管理员 | +| 前置条件 | 管理员已登录且拥有公告管理权限 | +| 后置条件 | 公告信息保存并可见 | +| 基本事件流 | 进入公告管理 → 点击新增 → 填写公告标题、内容、发布时间 → 提交发布 | +| 异常事件流 | 必填信息缺失时,系统提示修正 | + +#### 3.4.10 顾客查看订单用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 顾客查看订单 | +| 执行者 | 顾客 | +| 前置条件 | 顾客已登录且有历史就诊记录 | +| 后置条件 | 显示订单列表或订单详情 | +| 基本事件流 | 进入订单查询 → 查看订单列表 → 选择订单查看详情 | +| 异常事件流 | 无订单记录时显示提示信息 | + +#### 3.4.11 登录用例描述 + +| 项目 | 描述 | +|---|---| +| 用例名称 | 登录 | +| 执行者 | 顾客/医生/管理员 | +| 前置条件 | 用户已注册 | +| 后置条件 | 用户身份验证通过,生成访问令牌 | +| 基本事件流 | 进入登录页面 → 输入账号密码 → 点击登录 → 验证身份 → 跳转至角色首页 | +| 异常事件流 | 账号不存在、密码错误或账户被禁用时,系统提示错误信息 | ### 3.5 系统性能分析