diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/appservice/IDrgDeepAppService.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/appservice/IDrgDeepAppService.java new file mode 100644 index 000000000..b7cde8522 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/appservice/IDrgDeepAppService.java @@ -0,0 +1,10 @@ +package com.healthlink.his.web.ybmanage.appservice; + +import com.core.common.core.domain.R; +import java.util.Map; + +public interface IDrgDeepAppService { + R analyzeDrg(Map params); + R getCostAlert(Map params); + R getOptimization(Map params); +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/appservice/impl/DrgDeepAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/appservice/impl/DrgDeepAppServiceImpl.java new file mode 100644 index 000000000..aad8b9cd6 --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/appservice/impl/DrgDeepAppServiceImpl.java @@ -0,0 +1,160 @@ +package com.healthlink.his.web.ybmanage.appservice.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.core.common.core.domain.R; +import com.healthlink.his.crossmodule.domain.DrgCostAlert; +import com.healthlink.his.crossmodule.domain.DrgPerformance; +import com.healthlink.his.crossmodule.service.IDrgCostAlertService; +import com.healthlink.his.crossmodule.service.IDrgPerformanceService; +import com.healthlink.his.mrhomepage.domain.MrDrgGrouping; +import com.healthlink.his.mrhomepage.service.IMrDrgGroupingService; +import com.healthlink.his.web.ybmanage.appservice.IDrgDeepAppService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class DrgDeepAppServiceImpl implements IDrgDeepAppService { + + private final IMrDrgGroupingService drgGroupingService; + private final IDrgPerformanceService drgPerformanceService; + private final IDrgCostAlertService drgCostAlertService; + + @Override + public R analyzeDrg(Map params) { + String startDate = (String) params.get("startDate"); + String endDate = (String) params.get("endDate"); + String groupingType = (String) params.get("groupingType"); + + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.eq(StringUtils.hasText(groupingType), MrDrgGrouping::getGroupingType, groupingType) + .eq(MrDrgGrouping::getIsValid, true); + if (StringUtils.hasText(startDate)) { + w.ge(MrDrgGrouping::getDischargeDate, startDate); + } + if (StringUtils.hasText(endDate)) { + w.le(MrDrgGrouping::getDischargeDate, endDate); + } + + List list = drgGroupingService.list(w); + + Map result = new HashMap<>(); + result.put("totalCases", list.size()); + + BigDecimal totalCost = BigDecimal.ZERO; + BigDecimal totalInsurance = BigDecimal.ZERO; + int totalLos = 0; + for (MrDrgGrouping g : list) { + if (g.getTotalCost() != null) totalCost = totalCost.add(g.getTotalCost()); + if (g.getInsurancePayment() != null) totalInsurance = totalInsurance.add(g.getInsurancePayment()); + if (g.getLosDays() != null) totalLos += g.getLosDays(); + } + int count = list.size(); + result.put("totalCost", totalCost); + result.put("totalInsurance", totalInsurance); + result.put("avgCost", count > 0 ? totalCost.divide(BigDecimal.valueOf(count), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO); + result.put("avgLos", count > 0 ? BigDecimal.valueOf(totalLos).divide(BigDecimal.valueOf(count), 1, RoundingMode.HALF_UP) : BigDecimal.ZERO); + result.put("insuranceRate", totalCost.compareTo(BigDecimal.ZERO) > 0 + ? totalInsurance.multiply(BigDecimal.valueOf(100)).divide(totalCost, 2, RoundingMode.HALF_UP) : BigDecimal.ZERO); + + Map typeCount = list.stream() + .collect(Collectors.groupingBy( + g -> g.getGroupingType() != null ? g.getGroupingType() : "UNKNOWN", + Collectors.summingInt(g -> 1))); + result.put("typeDistribution", typeCount); + + Map drgCostMap = new LinkedHashMap<>(); + Map drgCountMap = new LinkedHashMap<>(); + for (MrDrgGrouping g : list) { + String code = g.getDrgCode(); + if (StringUtils.hasText(code)) { + drgCostMap.merge(code, g.getTotalCost() != null ? g.getTotalCost() : BigDecimal.ZERO, BigDecimal::add); + drgCountMap.merge(code, 1, Integer::sum); + } + } + List> topDrg = drgCostMap.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(10) + .map(e -> { + Map item = new HashMap<>(); + item.put("drgCode", e.getKey()); + item.put("count", drgCountMap.getOrDefault(e.getKey(), 0)); + item.put("totalCost", e.getValue()); + return item; + }) + .collect(Collectors.toList()); + result.put("topDrgByCost", topDrg); + + return R.ok(result); + } + + @Override + public R getCostAlert(Map params) { + String alertLevel = (String) params.get("alertLevel"); + String handleStatus = (String) params.get("handleStatus"); + + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + if (StringUtils.hasText(alertLevel)) { + w.eq(DrgCostAlert::getAlertLevel, alertLevel); + } + if (StringUtils.hasText(handleStatus)) { + w.eq(DrgCostAlert::getHandleStatus, handleStatus); + } + w.orderByDesc(DrgCostAlert::getCreateTime); + + List list = drgCostAlertService.list(w); + + Map result = new HashMap<>(); + result.put("total", list.size()); + + long unhandled = list.stream().filter(a -> "PENDING".equals(a.getHandleStatus())).count(); + long highLevel = list.stream().filter(a -> "HIGH".equals(a.getAlertLevel())).count(); + result.put("unhandledCount", unhandled); + result.put("highLevelCount", highLevel); + result.put("records", list); + + return R.ok(result); + } + + @Override + public R getOptimization(Map params) { + LambdaQueryWrapper w = new LambdaQueryWrapper<>(); + w.orderByDesc(DrgPerformance::getStatMonth); + List perfList = drgPerformanceService.list(w); + + Map result = new HashMap<>(); + + if (!perfList.isEmpty()) { + DrgPerformance latest = perfList.get(0); + result.put("latestMonth", latest.getStatMonth()); + result.put("totalCases", latest.getTotalCases()); + result.put("drgCoveredRate", latest.getDrgCoveredRate()); + result.put("avgWeight", latest.getAvgWeight()); + result.put("avgCost", latest.getAvgCost()); + result.put("costControlRate", latest.getCostControlRate()); + result.put("cmiValue", latest.getCmiValue()); + result.put("avgLos", latest.getAvgLos()); + } + + List> trend = new ArrayList<>(); + for (DrgPerformance p : perfList) { + Map item = new HashMap<>(); + item.put("month", p.getStatMonth()); + item.put("totalCases", p.getTotalCases()); + item.put("avgWeight", p.getAvgWeight()); + item.put("avgCost", p.getAvgCost()); + item.put("costControlRate", p.getCostControlRate()); + item.put("cmiValue", p.getCmiValue()); + trend.add(item); + } + result.put("trend", trend); + + return R.ok(result); + } +} diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/controller/DrgDeepController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/controller/DrgDeepController.java new file mode 100644 index 000000000..29a6c566d --- /dev/null +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/ybmanage/controller/DrgDeepController.java @@ -0,0 +1,41 @@ +package com.healthlink.his.web.ybmanage.controller; + +import com.core.common.core.domain.AjaxResult; +import com.healthlink.his.web.ybmanage.appservice.IDrgDeepAppService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@Tag(name = "DRG/DIP深化分析") +@RestController +@RequestMapping("/ybmanage/drg-deep") +public class DrgDeepController { + + @Autowired + private IDrgDeepAppService drgDeepAppService; + + @Operation(summary = "DRG分组分析") + @PreAuthorize("@ss.hasPermi('ybmanage:drgdeep:edit')") + @PostMapping("/analyze") + public AjaxResult analyzeDrg(@RequestBody Map params) { + return AjaxResult.success(drgDeepAppService.analyzeDrg(params).getData()); + } + + @Operation(summary = "费用预警查询") + @PreAuthorize("@ss.hasPermi('ybmanage:drgdeep:list')") + @PostMapping("/cost-alert") + public AjaxResult getCostAlert(@RequestBody Map params) { + return AjaxResult.success(drgDeepAppService.getCostAlert(params).getData()); + } + + @Operation(summary = "优化建议") + @PreAuthorize("@ss.hasPermi('ybmanage:drgdeep:list')") + @PostMapping("/optimization") + public AjaxResult getOptimization(@RequestBody Map params) { + return AjaxResult.success(drgDeepAppService.getOptimization(params).getData()); + } +} diff --git a/healthlink-his-ui/src/views/drganalysis/DrgDeepAnalysis.vue b/healthlink-his-ui/src/views/drganalysis/DrgDeepAnalysis.vue new file mode 100644 index 000000000..bcd8a5a69 --- /dev/null +++ b/healthlink-his-ui/src/views/drganalysis/DrgDeepAnalysis.vue @@ -0,0 +1,199 @@ + + + diff --git a/healthlink-his-ui/src/views/drganalysis/deepApi.js b/healthlink-his-ui/src/views/drganalysis/deepApi.js new file mode 100644 index 000000000..877b52649 --- /dev/null +++ b/healthlink-his-ui/src/views/drganalysis/deepApi.js @@ -0,0 +1,13 @@ +import request from '@/utils/request' + +export function analyzeDrgDeep(data) { + return request({ url: '/ybmanage/drg-deep/analyze', method: 'post', data }) +} + +export function getCostAlert(data) { + return request({ url: '/ybmanage/drg-deep/cost-alert', method: 'post', data }) +} + +export function getOptimization(data) { + return request({ url: '/ybmanage/drg-deep/optimization', method: 'post', data }) +}