diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/appservice/IMrStatsDetailAppService.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/appservice/IMrStatsDetailAppService.java new file mode 100644 index 000000000..aeb3f4aad --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/appservice/IMrStatsDetailAppService.java @@ -0,0 +1,11 @@ +package com.healthlink.his.web.mrhomepage.appservice; + +import java.util.List; +import java.util.Map; + +public interface IMrStatsDetailAppService { + + Map getMrStatsByDept(Long deptId); + + Map getMrStatsByDoctor(Long doctorId); +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/appservice/impl/MrStatsDetailAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/appservice/impl/MrStatsDetailAppServiceImpl.java new file mode 100644 index 000000000..fc44d8e82 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/appservice/impl/MrStatsDetailAppServiceImpl.java @@ -0,0 +1,95 @@ +package com.healthlink.his.web.mrhomepage.appservice.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.healthlink.his.mrhomepage.domain.MrHomepage; +import com.healthlink.his.mrhomepage.service.IMrHomepageService; +import com.healthlink.his.web.mrhomepage.appservice.IMrStatsDetailAppService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class MrStatsDetailAppServiceImpl implements IMrStatsDetailAppService { + + private final IMrHomepageService mrHomepageService; + + @Override + public Map getMrStatsByDept(Long deptId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if (deptId != null) { + wrapper.eq(MrHomepage::getEncounterId, deptId); + } + List list = mrHomepageService.list(wrapper); + + Map result = new HashMap<>(); + result.put("totalCount", list.size()); + + BigDecimal totalCost = list.stream() + .map(MrHomepage::getTotalCost) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + result.put("totalCost", totalCost); + + result.put("avgCost", list.isEmpty() ? BigDecimal.ZERO : + totalCost.divide(BigDecimal.valueOf(list.size()), 2, RoundingMode.HALF_UP)); + + Map byStatus = list.stream() + .collect(Collectors.groupingBy( + h -> h.getQualityStatus() != null ? h.getQualityStatus() : "UNKNOWN", + Collectors.counting())); + result.put("byStatus", byStatus); + + Map byDrg = list.stream() + .filter(h -> h.getDrgGroup() != null) + .collect(Collectors.groupingBy(MrHomepage::getDrgGroup, Collectors.counting())); + result.put("byDrg", byDrg); + + long totalLos = list.stream() + .mapToInt(h -> h.getLosDays() != null ? h.getLosDays() : 0) + .sum(); + result.put("totalLosDays", totalLos); + result.put("avgLosDays", list.isEmpty() ? 0 : + Math.round(totalLos * 10.0 / list.size()) / 10.0); + + return result; + } + + @Override + public Map getMrStatsByDoctor(Long doctorId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if (doctorId != null) { + wrapper.eq(MrHomepage::getPatientId, doctorId); + } + List list = mrHomepageService.list(wrapper); + + Map result = new HashMap<>(); + result.put("totalCount", list.size()); + + BigDecimal totalCost = list.stream() + .map(MrHomepage::getTotalCost) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + result.put("totalCost", totalCost); + + result.put("avgCost", list.isEmpty() ? BigDecimal.ZERO : + totalCost.divide(BigDecimal.valueOf(list.size()), 2, RoundingMode.HALF_UP)); + + Map byStatus = list.stream() + .collect(Collectors.groupingBy( + h -> h.getQualityStatus() != null ? h.getQualityStatus() : "UNKNOWN", + Collectors.counting())); + result.put("byStatus", byStatus); + + Map byDiagnosis = list.stream() + .filter(h -> h.getPrimaryDiagnosisName() != null) + .collect(Collectors.groupingBy(MrHomepage::getPrimaryDiagnosisName, Collectors.counting())); + result.put("byDiagnosis", byDiagnosis); + + return result; + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/controller/MrStatsDetailController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/controller/MrStatsDetailController.java new file mode 100644 index 000000000..b3d3ba2ed --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/mrhomepage/controller/MrStatsDetailController.java @@ -0,0 +1,38 @@ +package com.healthlink.his.web.mrhomepage.controller; + +import com.core.common.core.domain.R; +import com.healthlink.his.web.mrhomepage.appservice.IMrStatsDetailAppService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@Tag(name = "病案统计明细") +@RestController +@RequestMapping("/mr-stats-detail") +@Slf4j +@AllArgsConstructor +public class MrStatsDetailController { + + private final IMrStatsDetailAppService mrStatsDetailAppService; + + @Operation(summary = "科室病案统计") + @PreAuthorize("@ss.hasPermi('mrhomepage:mrhomepage:list')") + @GetMapping("/by-dept") + public R> getMrStatsByDept( + @RequestParam(value = "deptId", required = false) Long deptId) { + return R.ok(mrStatsDetailAppService.getMrStatsByDept(deptId)); + } + + @Operation(summary = "医生病案统计") + @PreAuthorize("@ss.hasPermi('mrhomepage:mrhomepage:list')") + @GetMapping("/by-doctor") + public R> getMrStatsByDoctor( + @RequestParam(value = "doctorId", required = false) Long doctorId) { + return R.ok(mrStatsDetailAppService.getMrStatsByDoctor(doctorId)); + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V75__mr_stats_detail.sql b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V75__mr_stats_detail.sql new file mode 100644 index 000000000..059e1e142 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/resources/db/migration/V75__mr_stats_detail.sql @@ -0,0 +1,6 @@ +ALTER TABLE mr_homepage ADD COLUMN IF NOT EXISTS department_id BIGINT; +ALTER TABLE mr_homepage ADD COLUMN IF NOT EXISTS doctor_id BIGINT; +COMMENT ON COLUMN mr_homepage.department_id IS '科室ID'; +COMMENT ON COLUMN mr_homepage.doctor_id IS '主治医生ID'; +CREATE INDEX IF NOT EXISTS idx_mr_homepage_dept ON mr_homepage(department_id); +CREATE INDEX IF NOT EXISTS idx_mr_homepage_doctor ON mr_homepage(doctor_id); diff --git a/healthlink-his-ui/src/api/mrhomepage/statsDetail.js b/healthlink-his-ui/src/api/mrhomepage/statsDetail.js new file mode 100644 index 000000000..c3852dd31 --- /dev/null +++ b/healthlink-his-ui/src/api/mrhomepage/statsDetail.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getMrStatsByDept(params) { + return request({ url: '/mr-stats-detail/by-dept', method: 'get', params }) +} + +export function getMrStatsByDoctor(params) { + return request({ url: '/mr-stats-detail/by-doctor', method: 'get', params }) +} diff --git a/healthlink-his-ui/src/views/mrhomepage/statistics-detail/index.vue b/healthlink-his-ui/src/views/mrhomepage/statistics-detail/index.vue new file mode 100644 index 000000000..fd7d2926b --- /dev/null +++ b/healthlink-his-ui/src/views/mrhomepage/statistics-detail/index.vue @@ -0,0 +1,156 @@ + + + + +