Merge remote-tracking branch 'origin/develop' into zhaoyun
This commit is contained in:
157
MD/design/PHASE3_MILESTONE_REVIEW.md
Normal file
157
MD/design/PHASE3_MILESTONE_REVIEW.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# Phase 3 里程碑评审报告
|
||||
|
||||
> **文档类型**: 里程碑评审
|
||||
> **版本**: v1.0
|
||||
> **日期**: 2026-06-18
|
||||
> **状态**: Phase 3 完成
|
||||
|
||||
---
|
||||
|
||||
## 1. Phase 3 完成统计
|
||||
|
||||
### Sprint 9: EMPI合并/拆分 + 重复检测 + 质控指标 + 随访管理
|
||||
|
||||
| 任务 | 状态 | Commit |
|
||||
|------|------|--------|
|
||||
| T9.1 患者身份合并/拆分 | ✅ 完成 | `0c0fd3315` |
|
||||
| T9.2 重复检测+跨系统同步 | ✅ 完成 | `4c3f7e406` |
|
||||
| T9.3 质控指标自动采集 | ✅ 完成 | `d863e54ff` |
|
||||
| T9.4 随访管理 | ✅ 完成 | `0e27b9f8d` |
|
||||
|
||||
### Sprint 10: 药品追溯 + CSSD + 术前讨论 + 3D重建
|
||||
|
||||
> Sprint 10 的功能在更早阶段已有完整实现(V31__cssd_3d_reconstruction.sql, V36__drug_traceability.sql 等),无需额外开发。
|
||||
|
||||
### Sprint 11: DRG/DIP分析 + 经营分析 + 仪表盘 + 肝肾功能调量
|
||||
|
||||
| 任务 | 状态 | Commit |
|
||||
|------|------|--------|
|
||||
| T11.1 DRG/DIP分析模块 | ✅ 完成 | `965418dc4` |
|
||||
| T11.2 经营分析+数据导出 | ✅ 完成 | `abafd4b2a` |
|
||||
| T11.3 可视化仪表盘 | ✅ 完成 | `632d0828b` |
|
||||
| T11.4 肝肾功能自动调量 | ✅ 完成 | `c004badf3` |
|
||||
|
||||
### Sprint 12: 集成测试
|
||||
|
||||
| 任务 | 状态 | Commit |
|
||||
|------|------|--------|
|
||||
| Phase 3 集成测试 | ✅ 通过 | `cb8a67cb3` |
|
||||
| 质量API修复 | ✅ 完成 | `7f315175a` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 三甲能力覆盖统计
|
||||
|
||||
| Phase | Sprint | 覆盖项数 | 说明 |
|
||||
|-------|--------|---------|------|
|
||||
| Phase 1 | Sprint 1-4 | 17项 | P0核心达标(病历、护理、院感、药品等) |
|
||||
| Phase 2 | Sprint 5-8 | 15项 | P1评审保障(质控、护理增强、实验室、ESB等) |
|
||||
| Phase 3 | Sprint 9-11 | 12项 | 空壳补全+其他(EMPI、质控指标、随访、DRG/DIP等) |
|
||||
| **合计** | | **44/84项** | **52.4% 覆盖率** |
|
||||
|
||||
### Phase 3 新增能力清单
|
||||
|
||||
| # | 能力项 | Sprint | 优先级 |
|
||||
|---|--------|--------|--------|
|
||||
| 1 | 患者身份合并/拆分 | 9 | P1 |
|
||||
| 2 | 重复检测+跨系统同步 | 9 | P1 |
|
||||
| 3 | 质控指标自动采集 | 9 | P2 |
|
||||
| 4 | 随访管理 | 9 | P1 |
|
||||
| 5 | DRG/DIP分析模块 | 11 | P1 |
|
||||
| 6 | 经营分析+数据导出 | 11 | P2 |
|
||||
| 7 | 可视化仪表盘 | 11 | P1 |
|
||||
| 8 | 肝肾功能自动调量 | 11 | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 新增文件统计
|
||||
|
||||
### Flyway 数据库迁移
|
||||
|
||||
Phase 3 新增迁移脚本(V57-V65):
|
||||
|
||||
| 版本 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| V57 | blood_transfusion.sql | 输血管理 |
|
||||
| V58 | clinical_pathway_variance.sql | 临床路径变异 |
|
||||
| V59 | fix_clinical_pathway_variance_delete_flag.sql | 变异删除标记修复 |
|
||||
| V60 | critical_value_handle_record.sql | 危急值处理记录 |
|
||||
| V61 | fix_critical_value_handle_record_columns.sql | 危急值字段修复 |
|
||||
| V62 | anes_asa_assessment.sql | 麻醉ASA评估 |
|
||||
| V63 | anes_summary.sql | 麻醉小结 |
|
||||
| V64 | emr_version_management.sql | 病历版本管理 |
|
||||
| V65 | mr_hqms_report.sql | 病案质量报告 |
|
||||
|
||||
**合计**: 9个迁移脚本(V57-V65)
|
||||
|
||||
### Java 文件
|
||||
|
||||
Phase 3 新增 Java 文件约 **60个**,分布在以下模块:
|
||||
|
||||
| 模块 | 主要文件 |
|
||||
|------|---------|
|
||||
| empi | EmpiMergeController, EmpiMergeService, EmpiDuplicateDetectionService, EmpiSyncService |
|
||||
| quality | QualityIndicatorController, QualityIndicatorAppService |
|
||||
| followup | FollowupController, FollowupAppService, FollowupPlanService |
|
||||
| reportmanage | DrAnalysisController, BusinessAnalysisController, DashboardController |
|
||||
| rationaldrug | DoseAdjustmentService, DoseAdjustmentController |
|
||||
| anes | AnesAsaAssessment, AnesSummary |
|
||||
| emr | EmrVersionManagement |
|
||||
|
||||
### Vue 文件
|
||||
|
||||
Phase 3 新增 Vue 文件约 **25个**,主要包括:
|
||||
|
||||
- `empi/MergeManagement.vue` — 患者合并/拆分管理
|
||||
- `empi/DuplicateDetection.vue` — 重复检测tab
|
||||
- `quality/QualityIndicatorPage.vue` — 质控指标页面
|
||||
- `followup/FollowupManagement.vue` — 随访管理页面
|
||||
- `reportmanage/DrAnalysisPage.vue` — DRG/DIP分析
|
||||
- `reportmanage/BusinessAnalysisPage.vue` — 经营分析
|
||||
- `reportmanage/DashboardPage.vue` — 可视化仪表盘
|
||||
- `anes/AnesAsaAssessment.vue` — ASA评估
|
||||
- `anes/AnesSummary.vue` — 麻醉小结
|
||||
- `emr/EmrVersionManagement.vue` — 病历版本管理
|
||||
|
||||
### Mapper XML
|
||||
|
||||
Phase 3 新增 Mapper XML 约 **12个**,覆盖 EMPI、质控、随访、报表、麻醉等模块的数据访问层。
|
||||
|
||||
---
|
||||
|
||||
## 4. 剩余工作(Phase 4)
|
||||
|
||||
### Phase 4: 广西地方特色 (5项)
|
||||
|
||||
| # | 功能 | 优先级 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| 1 | 壮医/中医 | P1 | 广西壮族自治区特色中医诊疗 |
|
||||
| 2 | 传染病直报 | P1 | 疾控中心传染病网络直报 |
|
||||
| 3 | 电子健康卡 | P2 | 居民电子健康卡对接 |
|
||||
| 4 | 电子票据 | P2 | 财政电子票据系统对接 |
|
||||
| 5 | DRG/DIP深化 | P2 | DRG/DIP付费精细化管理 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 风险与建议
|
||||
|
||||
### 已识别风险
|
||||
|
||||
| 风险 | 影响 | 缓解措施 |
|
||||
|------|------|---------|
|
||||
| EMPI数据质量 | 合并/拆分依赖高质量患者数据 | 上线前需完成历史数据清洗 |
|
||||
| DRG/DIP规则时效性 | 分组规则随政策调整 | 预留规则配置接口,支持动态更新 |
|
||||
| 随访管理覆盖率 | 随访计划需科室配合执行 | 结合绩效考核推动执行 |
|
||||
| 仪表盘性能 | 大数据量聚合查询可能较慢 | 建议引入Redis缓存热数据 |
|
||||
|
||||
### 建议
|
||||
|
||||
1. **Phase 4 优先级建议**:传染病直报 > 壮医/中医 > 电子健康卡 > 电子票据 > DRG/DIP深化
|
||||
2. **性能优化**:对报表类接口增加缓存层,避免实时计算
|
||||
3. **数据治理**:EMPI上线前完成患者数据去重和标准化
|
||||
4. **培训计划**:质控指标、随访管理模块需对临床科室进行操作培训
|
||||
|
||||
---
|
||||
|
||||
> 📅 报告生成时间: 2026-06-18
|
||||
> 📊 基于 git log 统计,共 3816 条 commit 记录
|
||||
@@ -7,6 +7,7 @@ import com.healthlink.his.check.domain.*;
|
||||
import com.healthlink.his.check.service.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -24,6 +25,7 @@ public class RadiologyEnhancedController {
|
||||
|
||||
// ==================== 紧急报告 ====================
|
||||
@GetMapping("/urgent-report/page")
|
||||
@PreAuthorize("@ss.hasPermi('infection:check:list')")
|
||||
public R<?> getUrgentReportPage(
|
||||
@RequestParam(value = "patientName", required = false) String patientName,
|
||||
@RequestParam(value = "notifyStatus", required = false) Integer status,
|
||||
@@ -37,6 +39,7 @@ public class RadiologyEnhancedController {
|
||||
}
|
||||
|
||||
@PostMapping("/urgent-report/add")
|
||||
@PreAuthorize("@ss.hasPermi('infection:check:edit')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> addUrgentReport(@RequestBody RadiologyUrgentReport r) {
|
||||
r.setNotifyStatus(0);
|
||||
@@ -47,6 +50,7 @@ public class RadiologyEnhancedController {
|
||||
}
|
||||
|
||||
@PostMapping("/urgent-report/notify")
|
||||
@PreAuthorize("@ss.hasPermi('infection:check:edit')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> notifyReport(@RequestParam Long id) {
|
||||
RadiologyUrgentReport r = urgentReportService.getById(id);
|
||||
@@ -60,6 +64,7 @@ public class RadiologyEnhancedController {
|
||||
|
||||
// ==================== 检查统计 ====================
|
||||
@GetMapping("/statistics/page")
|
||||
@PreAuthorize("@ss.hasPermi('infection:check:list')")
|
||||
public R<?> getStatisticsPage(
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.web.ehcard.appservice;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.healthlink.his.ehcard.domain.EhcardCard;
|
||||
|
||||
public interface IEhcardAppService {
|
||||
void apply(EhcardCard card);
|
||||
IPage<EhcardCard> page(String status, String patientName, Integer pageNum, Integer pageSize);
|
||||
void lock(Long id, String reason);
|
||||
void unlock(Long id);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.healthlink.his.web.ehcard.appservice.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.healthlink.his.ehcard.domain.EhcardCard;
|
||||
import com.healthlink.his.ehcard.domain.EhcardUsageLog;
|
||||
import com.healthlink.his.ehcard.service.IEhcardCardService;
|
||||
import com.healthlink.his.ehcard.service.IEhcardUsageLogService;
|
||||
import com.healthlink.his.web.ehcard.appservice.IEhcardAppService;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class EhcardAppServiceImpl implements IEhcardAppService {
|
||||
|
||||
@Autowired
|
||||
private IEhcardCardService cardService;
|
||||
|
||||
@Autowired
|
||||
private IEhcardUsageLogService usageLogService;
|
||||
|
||||
@Override
|
||||
public void apply(EhcardCard card) {
|
||||
card.setCardNo("EHC" + System.currentTimeMillis());
|
||||
card.setCardType("HEALTH");
|
||||
card.setStatus("ACTIVE");
|
||||
card.setApplyTime(new Date());
|
||||
cardService.save(card);
|
||||
|
||||
EhcardUsageLog log = new EhcardUsageLog();
|
||||
log.setCardId(card.getId());
|
||||
log.setPatientId(card.getPatientId());
|
||||
log.setUsageType("APPLY");
|
||||
log.setUsageDesc("申请电子健康卡");
|
||||
log.setOperatorName(SecurityUtils.getUsername());
|
||||
log.setUsageTime(new Date());
|
||||
usageLogService.save(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<EhcardCard> page(String status, String patientName, Integer pageNum, Integer pageSize) {
|
||||
LambdaQueryWrapper<EhcardCard> w = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.hasText(status)) {
|
||||
w.eq(EhcardCard::getStatus, status);
|
||||
}
|
||||
if (StringUtils.hasText(patientName)) {
|
||||
w.like(EhcardCard::getPatientName, patientName);
|
||||
}
|
||||
w.orderByDesc(EhcardCard::getCreateTime);
|
||||
return cardService.page(new Page<>(pageNum, pageSize), w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock(Long id, String reason) {
|
||||
EhcardCard card = cardService.getById(id);
|
||||
if (card == null) {
|
||||
throw new RuntimeException("电子健康卡不存在");
|
||||
}
|
||||
card.setStatus("LOCKED");
|
||||
card.setLockTime(new Date());
|
||||
card.setLockReason(reason);
|
||||
cardService.updateById(card);
|
||||
|
||||
EhcardUsageLog log = new EhcardUsageLog();
|
||||
log.setCardId(id);
|
||||
log.setPatientId(card.getPatientId());
|
||||
log.setUsageType("LOCK");
|
||||
log.setUsageDesc("锁定: " + reason);
|
||||
log.setOperatorName(SecurityUtils.getUsername());
|
||||
log.setUsageTime(new Date());
|
||||
usageLogService.save(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock(Long id) {
|
||||
EhcardCard card = cardService.getById(id);
|
||||
if (card == null) {
|
||||
throw new RuntimeException("电子健康卡不存在");
|
||||
}
|
||||
card.setStatus("ACTIVE");
|
||||
card.setUnlockTime(new Date());
|
||||
cardService.updateById(card);
|
||||
|
||||
EhcardUsageLog log = new EhcardUsageLog();
|
||||
log.setCardId(id);
|
||||
log.setPatientId(card.getPatientId());
|
||||
log.setUsageType("UNLOCK");
|
||||
log.setUsageDesc("解锁");
|
||||
log.setOperatorName(SecurityUtils.getUsername());
|
||||
log.setUsageTime(new Date());
|
||||
usageLogService.save(log);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.healthlink.his.web.ehcard.controller;
|
||||
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.healthlink.his.ehcard.domain.EhcardCard;
|
||||
import com.healthlink.his.web.ehcard.appservice.IEhcardAppService;
|
||||
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.*;
|
||||
|
||||
@Tag(name = "电子健康卡管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/ehcard")
|
||||
public class EhcardController {
|
||||
|
||||
@Autowired
|
||||
private IEhcardAppService ehcardAppService;
|
||||
|
||||
@Operation(summary = "申请电子健康卡")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:ehcard:edit')")
|
||||
@PostMapping("/apply")
|
||||
public AjaxResult apply(@RequestBody EhcardCard card) {
|
||||
ehcardAppService.apply(card);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "电子健康卡分页")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:ehcard:list')")
|
||||
@GetMapping("/page")
|
||||
public AjaxResult page(@RequestParam(required = false) String status,
|
||||
@RequestParam(required = false) String patientName,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
return AjaxResult.success(ehcardAppService.page(status, patientName, pageNum, pageSize));
|
||||
}
|
||||
|
||||
@Operation(summary = "锁定电子健康卡")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:ehcard:edit')")
|
||||
@PostMapping("/lock")
|
||||
public AjaxResult lock(@RequestParam Long id, @RequestParam(required = false) String reason) {
|
||||
ehcardAppService.lock(id, reason);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "解锁电子健康卡")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:ehcard:edit')")
|
||||
@PostMapping("/unlock")
|
||||
public AjaxResult unlock(@RequestParam Long id) {
|
||||
ehcardAppService.unlock(id);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.healthlink.his.web.einvoice.appservice;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceHeader;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IEinvoiceAppService {
|
||||
EinvoiceHeader generate(EinvoiceHeader header);
|
||||
IPage<EinvoiceHeader> page(String invoiceStatus, String patientName, Integer pageNum, Integer pageSize);
|
||||
void voidInvoice(Long id, String reason);
|
||||
Map<String, Object> getReconciliation(Integer pageNum, Integer pageSize);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.healthlink.his.web.einvoice.appservice.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceHeader;
|
||||
import com.healthlink.his.einvoice.service.IEinvoiceHeaderService;
|
||||
import com.healthlink.his.einvoice.service.IEinvoiceReconciliationService;
|
||||
import com.healthlink.his.web.einvoice.appservice.IEinvoiceAppService;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class EinvoiceAppServiceImpl implements IEinvoiceAppService {
|
||||
|
||||
@Autowired
|
||||
private IEinvoiceHeaderService headerService;
|
||||
|
||||
@Autowired
|
||||
private IEinvoiceReconciliationService reconciliationService;
|
||||
|
||||
@Override
|
||||
public EinvoiceHeader generate(EinvoiceHeader header) {
|
||||
header.setInvoiceNo("EINV" + System.currentTimeMillis());
|
||||
header.setInvoiceType("ELECTRONIC");
|
||||
header.setInvoiceStatus("ISSUED");
|
||||
header.setIssueTime(new Date());
|
||||
header.setIssuerName(SecurityUtils.getUsername());
|
||||
headerService.save(header);
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<EinvoiceHeader> page(String invoiceStatus, String patientName, Integer pageNum, Integer pageSize) {
|
||||
LambdaQueryWrapper<EinvoiceHeader> w = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.hasText(invoiceStatus)) {
|
||||
w.eq(EinvoiceHeader::getInvoiceStatus, invoiceStatus);
|
||||
}
|
||||
if (StringUtils.hasText(patientName)) {
|
||||
w.like(EinvoiceHeader::getPatientName, patientName);
|
||||
}
|
||||
w.orderByDesc(EinvoiceHeader::getCreateTime);
|
||||
return headerService.page(new Page<>(pageNum, pageSize), w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void voidInvoice(Long id, String reason) {
|
||||
EinvoiceHeader header = headerService.getById(id);
|
||||
if (header == null) {
|
||||
throw new RuntimeException("发票不存在");
|
||||
}
|
||||
header.setInvoiceStatus("VOID");
|
||||
header.setVoidTime(new Date());
|
||||
header.setVoidReason(reason);
|
||||
headerService.updateById(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getReconciliation(Integer pageNum, Integer pageSize) {
|
||||
LambdaQueryWrapper<EinvoiceHeader> w = new LambdaQueryWrapper<>();
|
||||
w.eq(EinvoiceHeader::getInvoiceStatus, "ISSUED");
|
||||
w.orderByDesc(EinvoiceHeader::getIssueTime);
|
||||
IPage<EinvoiceHeader> page = headerService.page(new Page<>(pageNum, pageSize), w);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("records", page.getRecords());
|
||||
result.put("total", page.getTotal());
|
||||
|
||||
LambdaQueryWrapper<EinvoiceHeader> totalW = new LambdaQueryWrapper<>();
|
||||
totalW.eq(EinvoiceHeader::getInvoiceStatus, "ISSUED");
|
||||
long totalCount = headerService.count(totalW);
|
||||
result.put("totalCount", totalCount);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.healthlink.his.web.einvoice.controller;
|
||||
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceHeader;
|
||||
import com.healthlink.his.web.einvoice.appservice.IEinvoiceAppService;
|
||||
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 = "电子票据管理")
|
||||
@RestController
|
||||
@RequestMapping("/invoice")
|
||||
public class EinvoiceController {
|
||||
|
||||
@Autowired
|
||||
private IEinvoiceAppService einvoiceAppService;
|
||||
|
||||
@Operation(summary = "生成电子票据")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:invoice:edit')")
|
||||
@PostMapping("/generate")
|
||||
public AjaxResult generate(@RequestBody EinvoiceHeader header) {
|
||||
return AjaxResult.success(einvoiceAppService.generate(header));
|
||||
}
|
||||
|
||||
@Operation(summary = "电子票据分页")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:invoice:list')")
|
||||
@GetMapping("/page")
|
||||
public AjaxResult page(@RequestParam(required = false) String invoiceStatus,
|
||||
@RequestParam(required = false) String patientName,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
return AjaxResult.success(einvoiceAppService.page(invoiceStatus, patientName, pageNum, pageSize));
|
||||
}
|
||||
|
||||
@Operation(summary = "作废电子票据")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:invoice:edit')")
|
||||
@PostMapping("/void")
|
||||
public AjaxResult voidInvoice(@RequestParam Long id, @RequestParam(required = false) String reason) {
|
||||
einvoiceAppService.voidInvoice(id, reason);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "票据对账")
|
||||
@PreAuthorize("@ss.hasPermi('basicmanage:invoice:list')")
|
||||
@GetMapping("/reconciliation")
|
||||
public AjaxResult reconciliation(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
return AjaxResult.success(einvoiceAppService.getReconciliation(pageNum, pageSize));
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,7 @@ public interface IEpidemicAppService {
|
||||
void confirmReport(Long id, String cdcNo);
|
||||
List<EpidemicReport> getReports(String status);
|
||||
Map<String, Object> getStatistics(String startDate, String endDate);
|
||||
EpidemicReport autoScreen(EpidemicReport r);
|
||||
EpidemicReport saveReport(EpidemicReport r);
|
||||
Map<String, Object> getReportStats(String startDate, String endDate);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,18 @@ import java.util.*;
|
||||
@Service
|
||||
public class EpidemicAppServiceImpl implements IEpidemicAppService {
|
||||
@Autowired private IEpidemicReportService reportService;
|
||||
|
||||
private static final Set<String> NOTIFIABLE_DISEASES = Set.of(
|
||||
"鼠疫", "霍乱", "传染性非典型肺炎", "艾滋病", "病毒性肝炎", "脊髓灰质炎",
|
||||
"人感染高致病性禽流感", "麻疹", "流行性出血热", "狂犬病", "流行性乙型脑炎",
|
||||
"登革热", "炭疽", "细菌性和阿米巴性痢疾", "肺结核", "伤寒和副伤寒",
|
||||
"流行性脑脊髓膜炎", "百日咳", "白喉", "新生儿破伤风", "猩红热",
|
||||
"布鲁氏菌病", "淋病", "梅毒", "钩端螺旋体病", "血吸虫病", "疟疾",
|
||||
"手足口病", "流行性感冒", "流行性腮腺炎", "风疹", "急性出血性结膜炎",
|
||||
"麻风病", "流行性和地方性斑疹伤寒", "黑热病", "包虫病", "丝虫病",
|
||||
"感染性腹泻", "甲型H1N1流感", "新型冠状病毒肺炎"
|
||||
);
|
||||
|
||||
@Override
|
||||
public EpidemicReport report(EpidemicReport r) { r.setStatus("PENDING"); r.setDelFlag("0"); r.setReportDate(new Date()); reportService.save(r); return r; }
|
||||
@Override
|
||||
@@ -27,4 +39,40 @@ public class EpidemicAppServiceImpl implements IEpidemicAppService {
|
||||
r.put("confirmed", reportService.count(new LambdaQueryWrapper<EpidemicReport>().eq(EpidemicReport::getStatus, "CONFIRMED")));
|
||||
return r;
|
||||
}
|
||||
@Override
|
||||
public EpidemicReport autoScreen(EpidemicReport r) {
|
||||
boolean match = r.getDiseaseName() != null && NOTIFIABLE_DISEASES.stream()
|
||||
.anyMatch(d -> r.getDiseaseName().contains(d));
|
||||
r.setScreenResult(match ? "MATCHED" : "NOT_MATCHED");
|
||||
r.setScreenLevel(match ? "LEVEL_A" : "NORMAL");
|
||||
r.setScreenTime(new Date());
|
||||
if (match && (r.getStatus() == null || "DRAFT".equals(r.getStatus()))) {
|
||||
r.setStatus("PENDING");
|
||||
}
|
||||
r.setDelFlag("0");
|
||||
r.setReportDate(new Date());
|
||||
reportService.save(r);
|
||||
return r;
|
||||
}
|
||||
@Override
|
||||
public EpidemicReport saveReport(EpidemicReport r) {
|
||||
if (r.getId() == null) {
|
||||
r.setStatus("DRAFT"); r.setDelFlag("0"); r.setReportDate(new Date());
|
||||
reportService.save(r);
|
||||
} else {
|
||||
reportService.updateById(r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@Override
|
||||
public Map<String, Object> getReportStats(String startDate, String endDate) {
|
||||
Map<String, Object> r = new HashMap<>();
|
||||
LambdaQueryWrapper<EpidemicReport> base = new LambdaQueryWrapper<EpidemicReport>().eq(EpidemicReport::getDelFlag, "0");
|
||||
r.put("total", reportService.count(base));
|
||||
r.put("pending", reportService.count(new LambdaQueryWrapper<EpidemicReport>().eq(EpidemicReport::getStatus, "PENDING").eq(EpidemicReport::getDelFlag, "0")));
|
||||
r.put("confirmed", reportService.count(new LambdaQueryWrapper<EpidemicReport>().eq(EpidemicReport::getStatus, "CONFIRMED").eq(EpidemicReport::getDelFlag, "0")));
|
||||
r.put("screenMatched", reportService.count(new LambdaQueryWrapper<EpidemicReport>().eq(EpidemicReport::getScreenResult, "MATCHED").eq(EpidemicReport::getDelFlag, "0")));
|
||||
r.put("screenNormal", reportService.count(new LambdaQueryWrapper<EpidemicReport>().eq(EpidemicReport::getScreenResult, "NOT_MATCHED").eq(EpidemicReport::getDelFlag, "0")));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,32 @@ import com.healthlink.his.web.epidemic.appservice.IEpidemicAppService;
|
||||
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.*;
|
||||
@Tag(name = "传染病直报") @RestController @RequestMapping("/api/v1/epidemic")
|
||||
public class EpidemicController {
|
||||
@Autowired private IEpidemicAppService epidemicAppService;
|
||||
|
||||
@Operation(summary = "上报") @PostMapping("/report")
|
||||
@PreAuthorize("hasAuthority('epidemic:edit')")
|
||||
public AjaxResult report(@RequestBody EpidemicReport r) { return AjaxResult.success(epidemicAppService.report(r)); }
|
||||
@Operation(summary = "确认") @PutMapping("/confirm/{id}")
|
||||
@PreAuthorize("hasAuthority('epidemic:edit')")
|
||||
public AjaxResult confirm(@PathVariable Long id, @RequestParam String cdcNo) { epidemicAppService.confirmReport(id, cdcNo); return AjaxResult.success(); }
|
||||
@Operation(summary = "列表") @GetMapping("/list")
|
||||
@PreAuthorize("hasAuthority('epidemic:list')")
|
||||
public AjaxResult list(@RequestParam(required = false) String status) { return AjaxResult.success(epidemicAppService.getReports(status)); }
|
||||
@Operation(summary = "统计") @GetMapping("/statistics")
|
||||
@PreAuthorize("hasAuthority('epidemic:list')")
|
||||
public AjaxResult statistics(@RequestParam(required = false) String s, @RequestParam(required = false) String e) { return AjaxResult.success(epidemicAppService.getStatistics(s, e)); }
|
||||
|
||||
@Operation(summary = "自动筛查") @PostMapping("/auto-screen")
|
||||
@PreAuthorize("hasAuthority('epidemic:edit')")
|
||||
public AjaxResult autoScreen(@RequestBody EpidemicReport r) { return AjaxResult.success(epidemicAppService.autoScreen(r)); }
|
||||
@Operation(summary = "保存报告") @PostMapping("/save")
|
||||
@PreAuthorize("hasAuthority('epidemic:edit')")
|
||||
public AjaxResult saveReport(@RequestBody EpidemicReport r) { return AjaxResult.success(epidemicAppService.saveReport(r)); }
|
||||
@Operation(summary = "报告统计") @GetMapping("/report-stats")
|
||||
@PreAuthorize("hasAuthority('epidemic:list')")
|
||||
public AjaxResult reportStats(@RequestParam(required = false) String s, @RequestParam(required = false) String e) { return AjaxResult.success(epidemicAppService.getReportStats(s, e)); }
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.healthlink.his.lab.domain.LabResultComparison;
|
||||
import com.healthlink.his.lab.service.ILabResultComparisonService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -20,6 +21,7 @@ public class LabHistoryController {
|
||||
private final ILabResultComparisonService comparisonService;
|
||||
|
||||
@GetMapping("/compare")
|
||||
@PreAuthorize("@ss.hasPermi('infection:lab:list')")
|
||||
public R<?> compareResults(
|
||||
@RequestParam Long patientId,
|
||||
@RequestParam(required = false) String testItem) {
|
||||
@@ -31,6 +33,7 @@ public class LabHistoryController {
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@PreAuthorize("@ss.hasPermi('infection:lab:edit')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> addResult(@RequestBody LabResultComparison result) {
|
||||
result.setCreateTime(new java.util.Date());
|
||||
@@ -39,6 +42,7 @@ public class LabHistoryController {
|
||||
}
|
||||
|
||||
@GetMapping("/trend")
|
||||
@PreAuthorize("@ss.hasPermi('infection:lab:list')")
|
||||
public R<?> getTrend(
|
||||
@RequestParam Long patientId,
|
||||
@RequestParam String testItem) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.healthlink.his.prescription.domain.PrescriptionInterceptLog;
|
||||
import com.healthlink.his.prescription.service.IPrescriptionInterceptLogService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -105,6 +106,7 @@ public class OutpatientEnhancedController {
|
||||
|
||||
// ==================== 出院小结 ====================
|
||||
@GetMapping("/discharge/page")
|
||||
@PreAuthorize("hasAuthority('outpatient:discharge:list')")
|
||||
public R<?> getDischargePage(
|
||||
@RequestParam(value = "status", required = false) Integer status,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@@ -116,6 +118,7 @@ public class OutpatientEnhancedController {
|
||||
}
|
||||
|
||||
@PostMapping("/discharge/add")
|
||||
@PreAuthorize("hasAuthority('outpatient:discharge:add')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> addDischarge(@RequestBody DischargeSummary summary) {
|
||||
summary.setStatus(0);
|
||||
@@ -125,6 +128,7 @@ public class OutpatientEnhancedController {
|
||||
}
|
||||
|
||||
@PostMapping("/discharge/complete")
|
||||
@PreAuthorize("hasAuthority('outpatient:discharge:edit')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> completeDischarge(@RequestParam Long id) {
|
||||
DischargeSummary s = dischargeService.getById(id);
|
||||
|
||||
@@ -8,4 +8,7 @@ public interface ITcmAppService {
|
||||
TcmConstitutionAssessment assess(TcmConstitutionAssessment a);
|
||||
List<TcmConstitutionAssessment> getAssessmentsByEncounter(Long encounterId);
|
||||
Map<String, Object> getStatistics();
|
||||
TcmDiagnosis saveDiagnosis(TcmDiagnosis d);
|
||||
List<TcmDiagnosis> getDiagnosesByEncounter(Long encounterId);
|
||||
TcmConstitutionAssessment saveConstitution(TcmConstitutionAssessment a);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.*;
|
||||
public class TcmAppServiceImpl implements ITcmAppService {
|
||||
@Autowired private ITcmPrescriptionService prescriptionService;
|
||||
@Autowired private ITcmConstitutionAssessmentService assessmentService;
|
||||
@Autowired private ITcmDiagnosisService diagnosisService;
|
||||
|
||||
@Override
|
||||
public List<TcmPrescription> getPrescriptions(String type) {
|
||||
@@ -33,4 +34,13 @@ public class TcmAppServiceImpl implements ITcmAppService {
|
||||
r.put("totalAssessments", assessmentService.count(new LambdaQueryWrapper<TcmConstitutionAssessment>().eq(TcmConstitutionAssessment::getDeleteFlag, "0")));
|
||||
return r;
|
||||
}
|
||||
@Override
|
||||
public TcmDiagnosis saveDiagnosis(TcmDiagnosis d) { d.setDeleteFlag("0"); d.setEnabled("1"); diagnosisService.save(d); return d; }
|
||||
@Override
|
||||
public List<TcmDiagnosis> getDiagnosesByEncounter(Long encounterId) {
|
||||
return diagnosisService.list(new LambdaQueryWrapper<TcmDiagnosis>()
|
||||
.eq(TcmDiagnosis::getEncounterId, encounterId).eq(TcmDiagnosis::getDeleteFlag, "0"));
|
||||
}
|
||||
@Override
|
||||
public TcmConstitutionAssessment saveConstitution(TcmConstitutionAssessment a) { a.setDeleteFlag("0"); assessmentService.save(a); return a; }
|
||||
}
|
||||
|
||||
@@ -5,19 +5,37 @@ import com.healthlink.his.web.tcm.appservice.ITcmAppService;
|
||||
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.List;
|
||||
@Tag(name = "壮医中医特色") @RestController @RequestMapping("/api/v1/tcm")
|
||||
public class TcmController {
|
||||
@Autowired private ITcmAppService tcmAppService;
|
||||
|
||||
@Operation(summary = "中医方剂列表") @GetMapping("/prescriptions")
|
||||
@PreAuthorize("hasAuthority('tcm:edit')")
|
||||
public AjaxResult prescriptions(@RequestParam(required = false) String type) { return AjaxResult.success(tcmAppService.getPrescriptions(type)); }
|
||||
@Operation(summary = "新增方剂") @PostMapping("/prescription")
|
||||
@PreAuthorize("hasAuthority('tcm:edit')")
|
||||
public AjaxResult savePrescription(@RequestBody TcmPrescription p) { return AjaxResult.success(tcmAppService.savePrescription(p)); }
|
||||
@Operation(summary = "统计") @GetMapping("/statistics")
|
||||
@PreAuthorize("hasAuthority('tcm:list')")
|
||||
public AjaxResult statistics() { return AjaxResult.success(tcmAppService.getStatistics()); }
|
||||
|
||||
@Operation(summary = "体质辨识") @PostMapping("/constitution")
|
||||
@PreAuthorize("hasAuthority('tcm:edit')")
|
||||
public AjaxResult assess(@RequestBody TcmConstitutionAssessment a) { return AjaxResult.success(tcmAppService.assess(a)); }
|
||||
@Operation(summary = "体质辨识记录") @GetMapping("/constitution/encounter/{encounterId}")
|
||||
@PreAuthorize("hasAuthority('tcm:list')")
|
||||
public AjaxResult getAssessments(@PathVariable Long encounterId) { return AjaxResult.success(tcmAppService.getAssessmentsByEncounter(encounterId)); }
|
||||
@Operation(summary = "统计") @GetMapping("/statistics")
|
||||
public AjaxResult statistics() { return AjaxResult.success(tcmAppService.getStatistics()); }
|
||||
@Operation(summary = "保存体质辨识") @PostMapping("/constitution/save")
|
||||
@PreAuthorize("hasAuthority('tcm:edit')")
|
||||
public AjaxResult saveConstitution(@RequestBody TcmConstitutionAssessment a) { return AjaxResult.success(tcmAppService.saveConstitution(a)); }
|
||||
|
||||
@Operation(summary = "保存诊断") @PostMapping("/diagnosis")
|
||||
@PreAuthorize("hasAuthority('tcm:edit')")
|
||||
public AjaxResult saveDiagnosis(@RequestBody TcmDiagnosis d) { return AjaxResult.success(tcmAppService.saveDiagnosis(d)); }
|
||||
@Operation(summary = "诊断记录") @GetMapping("/diagnosis/encounter/{encounterId}")
|
||||
@PreAuthorize("hasAuthority('tcm:list')")
|
||||
public AjaxResult getDiagnoses(@PathVariable Long encounterId) { return AjaxResult.success(tcmAppService.getDiagnosesByEncounter(encounterId)); }
|
||||
}
|
||||
|
||||
@@ -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<String, Object> params);
|
||||
R<?> getCostAlert(Map<String, Object> params);
|
||||
R<?> getOptimization(Map<String, Object> params);
|
||||
}
|
||||
@@ -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<String, Object> params) {
|
||||
String startDate = (String) params.get("startDate");
|
||||
String endDate = (String) params.get("endDate");
|
||||
String groupingType = (String) params.get("groupingType");
|
||||
|
||||
LambdaQueryWrapper<MrDrgGrouping> 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<MrDrgGrouping> list = drgGroupingService.list(w);
|
||||
|
||||
Map<String, Object> 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<String, Integer> typeCount = list.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
g -> g.getGroupingType() != null ? g.getGroupingType() : "UNKNOWN",
|
||||
Collectors.summingInt(g -> 1)));
|
||||
result.put("typeDistribution", typeCount);
|
||||
|
||||
Map<String, BigDecimal> drgCostMap = new LinkedHashMap<>();
|
||||
Map<String, Integer> 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<Map<String, Object>> topDrg = drgCostMap.entrySet().stream()
|
||||
.sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
|
||||
.limit(10)
|
||||
.map(e -> {
|
||||
Map<String, Object> 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<String, Object> params) {
|
||||
String alertLevel = (String) params.get("alertLevel");
|
||||
String handleStatus = (String) params.get("handleStatus");
|
||||
|
||||
LambdaQueryWrapper<DrgCostAlert> 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<DrgCostAlert> list = drgCostAlertService.list(w);
|
||||
|
||||
Map<String, Object> 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<String, Object> params) {
|
||||
LambdaQueryWrapper<DrgPerformance> w = new LambdaQueryWrapper<>();
|
||||
w.orderByDesc(DrgPerformance::getStatMonth);
|
||||
List<DrgPerformance> perfList = drgPerformanceService.list(w);
|
||||
|
||||
Map<String, Object> 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<Map<String, Object>> trend = new ArrayList<>();
|
||||
for (DrgPerformance p : perfList) {
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<String, Object> params) {
|
||||
return AjaxResult.success(drgDeepAppService.analyzeDrg(params).getData());
|
||||
}
|
||||
|
||||
@Operation(summary = "费用预警查询")
|
||||
@PreAuthorize("@ss.hasPermi('ybmanage:drgdeep:list')")
|
||||
@PostMapping("/cost-alert")
|
||||
public AjaxResult getCostAlert(@RequestBody Map<String, Object> params) {
|
||||
return AjaxResult.success(drgDeepAppService.getCostAlert(params).getData());
|
||||
}
|
||||
|
||||
@Operation(summary = "优化建议")
|
||||
@PreAuthorize("@ss.hasPermi('ybmanage:drgdeep:list')")
|
||||
@PostMapping("/optimization")
|
||||
public AjaxResult getOptimization(@RequestBody Map<String, Object> params) {
|
||||
return AjaxResult.success(drgDeepAppService.getOptimization(params).getData());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
-- V66__update_menu_icons.sql
|
||||
-- 更新菜单图标 - 根据菜单功能名称匹配合适的图标
|
||||
-- 仅使用 src/assets/icons/svg/ 目录下实际存在的图标
|
||||
|
||||
SET search_path TO healthlink_his;
|
||||
|
||||
-- ========== 一级菜单(顶级目录)==========
|
||||
UPDATE sys_menu SET icon = 'system' WHERE menu_id = 1; -- 系统管理
|
||||
UPDATE sys_menu SET icon = 'monitor' WHERE menu_id = 2; -- 系统监控
|
||||
UPDATE sys_menu SET icon = 'tool' WHERE menu_id = 3; -- 系统工具
|
||||
UPDATE sys_menu SET icon = 'log' WHERE menu_id = 108; -- 日志管理
|
||||
UPDATE sys_menu SET icon = 'inpatient' WHERE menu_id = 235; -- 住院管理
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 268; -- 药库管理
|
||||
UPDATE sys_menu SET icon = 'outpatient' WHERE menu_id = 270; -- 门诊管理
|
||||
UPDATE sys_menu SET icon = 'inventory' WHERE menu_id = 313; -- 库房管理
|
||||
UPDATE sys_menu SET icon = 'drug-dispensing' WHERE menu_id = 342; -- 发药管理
|
||||
UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 350; -- 财务管理
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 360; -- 报表管理
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 386; -- 医保管理
|
||||
UPDATE sys_menu SET icon = 'connection' WHERE menu_id = 418; -- 接口管理
|
||||
UPDATE sys_menu SET icon = 'workflow' WHERE menu_id = 2020; -- 流程管理
|
||||
UPDATE sys_menu SET icon = 'task' WHERE menu_id = 2023; -- 任务管理
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 2078; -- 收费工作站
|
||||
UPDATE sys_menu SET icon = 'pharmacy' WHERE menu_id = 2079; -- 药房管理
|
||||
UPDATE sys_menu SET icon = 'tool' WHERE menu_id = 2083; -- 维护系统
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 2084; -- 门诊医生工作站
|
||||
UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2092; -- 预约管理
|
||||
UPDATE sys_menu SET icon = 'triage' WHERE menu_id = 2110; -- 分诊排队管理
|
||||
UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 2119; -- 手术管理
|
||||
UPDATE sys_menu SET icon = 'user' WHERE menu_id = 2140; -- 患者管理
|
||||
UPDATE sys_menu SET icon = 'consultation' WHERE menu_id = 2147; -- 会诊管理
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 2159; -- 疾病报告管理
|
||||
UPDATE sys_MENU SET icon = 'infection' WHERE menu_id = 10001; -- 院感管理
|
||||
UPDATE sys_menu SET icon = 'log' WHERE menu_id = 10011; -- 药品追溯管理
|
||||
UPDATE sys_menu SET icon = 'edit' WHERE menu_id = 10021; -- 电子签名管理
|
||||
UPDATE sys_menu SET icon = 'alert' WHERE menu_id = 10031; -- 危急值管理
|
||||
UPDATE sys_menu SET icon = 'peoples' WHERE menu_id = 10041; -- 患者主索引(EMPI)
|
||||
UPDATE sys_menu SET icon = 'peoples' WHERE menu_id = 10051; -- 质量管理
|
||||
UPDATE sys_menu SET icon = 'shopping' WHERE menu_id = 10061; -- 手术安全核查
|
||||
UPDATE sys_menu SET icon = 'guide' WHERE menu_id = 10071; -- 临床路径
|
||||
UPDATE sys_menu SET icon = 'anesthesia' WHERE menu_id = 20001; -- 麻醉管理
|
||||
UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20011; -- 合理用药
|
||||
UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20021; -- 急诊管理
|
||||
UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20031; -- 护理管理
|
||||
UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20041; -- 病理管理
|
||||
UPDATE sys_menu SET icon = 'medical-record' WHERE menu_id = 20051; -- 病案管理
|
||||
UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20061; -- 影像管理
|
||||
UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20071; -- 随访管理
|
||||
UPDATE sys_menu SET icon = 'monitor' WHERE menu_id = 20081; -- ESB管理
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20091; -- 检查检验
|
||||
UPDATE sys_menu SET icon = 'consent' WHERE menu_id = 20101; -- 知情同意管理
|
||||
UPDATE sys_menu SET icon = 'order' WHERE menu_id = 20111; -- 医嘱闭环
|
||||
UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20131; -- 审核管理
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20141; -- 跨模块协同
|
||||
UPDATE sys_menu SET icon = 'sample' WHERE menu_id = 20151; -- 标本管理
|
||||
UPDATE sys_menu SET icon = 'standard' WHERE menu_id = 20161; -- FHIR/CDA标准
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20201; -- 电子病历管理
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20211; -- 检验增强
|
||||
|
||||
-- ========== 二级菜单图标更新 ==========
|
||||
-- 系统管理子菜单
|
||||
UPDATE sys_menu SET icon = 'user' WHERE menu_id = 100; -- 用户管理
|
||||
UPDATE sys_menu SET icon = 'peoples' WHERE menu_id = 101; -- 角色管理
|
||||
UPDATE sys_menu SET icon = 'post' WHERE menu_id = 104; -- 岗位管理
|
||||
UPDATE sys_menu SET icon = 'system' WHERE menu_id = 102; -- 菜单管理
|
||||
UPDATE sys_menu SET icon = 'tree-table' WHERE menu_id = 103; -- 部门管理
|
||||
UPDATE sys_menu SET icon = 'dict' WHERE menu_id = 105; -- 字典管理
|
||||
UPDATE sys_menu SET icon = 'edit' WHERE menu_id = 106; -- 参数设置
|
||||
UPDATE sys_menu SET icon = 'message' WHERE menu_id = 107; -- 通知公告
|
||||
|
||||
-- 系统监控子菜单
|
||||
UPDATE sys_menu SET icon = 'online' WHERE menu_id = 109; -- 在线用户
|
||||
UPDATE sys_menu SET icon = 'job' WHERE menu_id = 110; -- 定时任务
|
||||
UPDATE sys_menu SET icon = 'druid' WHERE menu_id = 111; -- 数据监控
|
||||
UPDATE sys_menu SET icon = 'server' WHERE menu_id = 112; -- 服务监控
|
||||
UPDATE sys_menu SET icon = 'monitor' WHERE menu_id = 113; -- 缓存监控
|
||||
UPDATE sys_menu SET icon = 'log' WHERE menu_id = 2104; -- 监控日志
|
||||
|
||||
-- 系统工具子菜单
|
||||
UPDATE sys_menu SET icon = 'form' WHERE menu_id = 115; -- 表单构建
|
||||
UPDATE sys_menu SET icon = 'code' WHERE menu_id = 116; -- 代码生成
|
||||
UPDATE sys_menu SET icon = 'swagger' WHERE menu_id = 117; -- 系统接口
|
||||
|
||||
-- 日志管理子菜单
|
||||
UPDATE sys_menu SET icon = 'log' WHERE menu_id = 500; -- 操作日志
|
||||
UPDATE sys_menu SET icon = 'log' WHERE menu_id = 501; -- 登录日志
|
||||
|
||||
-- 住院管理子菜单
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 288; -- 住院医生工作站
|
||||
UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 295; -- 住院护士站
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 307; -- 住院收费工作站
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 20171; -- 住院医生增强
|
||||
UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20181; -- 住院护士增强
|
||||
UPDATE sys_menu SET icon = 'hospital' WHERE menu_id = 20221; -- 住院辅助
|
||||
|
||||
-- 药库管理子菜单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2049; -- 药库订货单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2050; -- 药库退货单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2051; -- 药库进货单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2053; -- 药库出库单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2054; -- 药库退库单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2055; -- 药库损益单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2056; -- 药库盘点单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2058; -- 库房单据管理
|
||||
|
||||
-- 门诊管理子菜单
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 269; -- 门诊工作站
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 277; -- 医技工作站
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 282; -- 门诊收费工作站
|
||||
|
||||
-- 门诊工作站子菜单
|
||||
UPDATE sys_MENU SET icon = 'drug' WHERE menu_id = 272; -- 门诊退药
|
||||
UPDATE sys_menu SET icon = 'registration' WHERE menu_id = 274; -- 门诊退号
|
||||
|
||||
-- 门诊收费工作站子菜单
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 283; -- 门诊收费
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 284; -- 门诊退费
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 285; -- 门诊划价
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 287; -- 收费详情查询
|
||||
|
||||
-- 药房管理子菜单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 343; -- 门诊发药
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 344; -- 门诊退药
|
||||
|
||||
-- 住院护士站子菜单
|
||||
UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 296; -- 门户
|
||||
UPDATE sys_menu SET icon = 'admission' WHERE menu_id = 297; -- 入出转管理
|
||||
UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 298; -- 护理记录
|
||||
UPDATE sys_menu SET icon = 'vital-signs' WHERE menu_id = 299; -- 三测单
|
||||
UPDATE sys_menu SET icon = 'order' WHERE menu_id = 2061; -- 医嘱执行
|
||||
UPDATE sys_menu SET icon = 'order' WHERE menu_id = 2064; -- 医嘱校对
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 301; -- 汇总发药申请
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 302; -- 住院记账
|
||||
UPDATE sys_menu SET icon = 'allergy' WHERE menu_id = 303; -- 皮试管理
|
||||
UPDATE sys_menu SET icon = 'order' WHERE menu_id = 276; -- 医嘱查看与打印
|
||||
UPDATE sys_menu SET icon = 'discharge' WHERE menu_id = 304; -- 出院管理
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 305; -- 退药管理
|
||||
UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 306; -- 手术记录
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 2062; -- 住院领药
|
||||
|
||||
-- 住院收费工作站子菜单
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 308; -- 费用管理
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 309; -- 住院费用结算
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 311; -- 住院收费详情
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 312; -- 中途结算
|
||||
|
||||
-- 财务管理子菜单
|
||||
UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 354; -- 日结结算单管理
|
||||
UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 356; -- 药房对账
|
||||
UPDATE sys_menu SET icon = 'finance' WHERE menu_id = 357; -- 库房审批
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 358; -- 医保结算
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 359; -- 医保对账
|
||||
|
||||
-- 报表管理子菜单
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 213; -- 门诊就诊记录
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 208; -- 项目定价
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 262; -- 门诊收费报表
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 363; -- 费用整体查询
|
||||
|
||||
-- 医保管理子菜单
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 390; -- 省医保
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 391; -- 市医保
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 392; -- 医保对账
|
||||
UPDATE sys_menu SET icon = 'insurance' WHERE menu_id = 394; -- 医保结算
|
||||
|
||||
-- 检查检验子菜单
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20092; -- 检查申请
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20093; -- 检查仪器
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20094; -- LIS配置
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20095; -- 检验组套
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20096; -- 标本采集
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20097; -- 标本类型
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20098; -- 观察项目
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20099; -- 检验增强
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20100; -- 检验ICD10
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20102; -- 检验预约
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20103; -- 检验路径
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20104; -- 参考范围
|
||||
UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20105; -- 放射报告
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 20106; -- 检验历史
|
||||
|
||||
-- 院感管理子菜单
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10002; -- 感染病例监测
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10003; -- 手卫生监测
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10004; -- 环境监测
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10005; -- 抗菌药物使用
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10006; -- 多重耐药菌
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10007; -- 职业暴露
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10008; -- 疫情预警
|
||||
UPDATE sys_menu SET icon = 'infection' WHERE menu_id = 10009; -- 目标性监测
|
||||
|
||||
-- 药品追溯管理子菜单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10012; -- 追溯码管理
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10013; -- 批次管理
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10014; -- 扫码记录
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 10015; -- 追溯预警
|
||||
|
||||
-- 麻醉管理子菜单
|
||||
UPDATE sys_menu SET icon = 'anesthesia' WHERE menu_id = 20002; -- 麻醉记录
|
||||
UPDATE sys_menu SET icon = 'anesthesia' WHERE menu_id = 20003; -- 麻醉增强
|
||||
|
||||
-- 合理用药子菜单
|
||||
UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20012; -- 抗菌药物规则
|
||||
UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20013; -- 药物相互作用
|
||||
UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20014; -- 审核日志
|
||||
UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20015; -- 合理用药统计
|
||||
|
||||
-- 急诊管理子菜单
|
||||
UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20022; -- 急诊分诊
|
||||
UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20023; -- 急诊抢救
|
||||
UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20024; -- 急诊观察
|
||||
UPDATE sys_menu SET icon = 'emergency' WHERE menu_id = 20025; -- 绿色通道
|
||||
|
||||
-- 护理管理子菜单
|
||||
UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20032; -- 护理评估
|
||||
UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20033; -- 护理增强
|
||||
UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20034; -- 护理执行
|
||||
UPDATE sys_menu SET icon = 'nursing' WHERE menu_id = 20035; -- 护理质量
|
||||
UPDATE sys_menu SET icon = 'vital-signs' WHERE menu_id = 20036; -- 生命体征图表
|
||||
|
||||
-- 病理管理子菜单
|
||||
UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20042; -- 病理医嘱
|
||||
UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20043; -- 病理报告
|
||||
UPDATE sys_menu SET icon = 'pathology' WHERE menu_id = 20044; -- 病理标本
|
||||
|
||||
-- 病案管理子菜单
|
||||
UPDATE sys_menu SET icon = 'medical-record' WHERE menu_id = 20052; -- 病案管理
|
||||
UPDATE sys_menu SET icon = 'medical-record' WHERE menu_id = 20053; -- 病案首页管理
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 20054; -- DRG分析
|
||||
UPDATE sys_menu SET icon = 'report' WHERE menu_id = 20055; -- 病案统计
|
||||
|
||||
-- 影像管理子菜单
|
||||
UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20062; -- 影像增强
|
||||
UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20063; -- 影像对比
|
||||
UPDATE sys_menu SET icon = 'radiology' WHERE menu_id = 20064; -- 3D重建
|
||||
|
||||
-- 随访管理子菜单
|
||||
UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20072; -- 随访计划
|
||||
UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20073; -- 随访记录
|
||||
UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20074; -- 随访任务
|
||||
UPDATE sys_menu SET icon = 'follow-up' WHERE menu_id = 20075; -- 随访调查
|
||||
|
||||
-- 电子病历管理子菜单
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20202; -- 病案归档
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20203; -- 修订历史
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20204; -- 病历时效
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20205; -- 病历检索
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20206; -- 进程记录
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20207; -- 知识库
|
||||
|
||||
-- 审核管理子菜单
|
||||
UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20132; -- 审核统计
|
||||
UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20133; -- 点评计划
|
||||
UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20134; -- 点评工作台
|
||||
UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20135; -- 点评记录
|
||||
UPDATE sys_menu SET icon = 'audit' WHERE menu_id = 20136; -- 医生排名
|
||||
|
||||
-- 跨模块协同子菜单
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20142; -- 会诊反馈
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20143; -- 会诊超时
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20144; -- DRG绩效
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20145; -- 药品效期
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20146; -- 增强救护
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20147; -- 增强抗菌
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20148; -- 增强知情
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20149; -- DRG预警
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20150; -- 增强护理
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20152; -- 交接统计
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20153; -- 检验预警
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20154; -- 病案质量
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20155; -- 护士执行
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20156; -- 报告反馈
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20157; -- 审核统计
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20158; -- 库存拦截
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20159; -- 手术闭环
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20160; -- 手术关联
|
||||
UPDATE sys_menu SET icon = 'teamwork' WHERE menu_id = 20162; -- 患者转运
|
||||
|
||||
-- 门诊医生工作站子菜单
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 2114; -- 医生常用语
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 2143; -- 今日门诊
|
||||
|
||||
-- 预约管理子菜单
|
||||
UPDATE sys_menu SET icon = 'schedule' WHERE menu_id = 2105; -- 医生排班管理
|
||||
UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2097; -- 门诊出诊医生诊室设置
|
||||
UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2112; -- 科室预约工作时间维护
|
||||
UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 2113; -- 门诊预约挂号
|
||||
|
||||
-- 手术管理子菜单
|
||||
UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 2120; -- 手术管理
|
||||
UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 2144; -- 手术室管理
|
||||
|
||||
-- 住院医生增强子菜单
|
||||
UPDATE sys_menu SET icon = 'doctor' WHERE menu_id = 20172; -- 住院病历
|
||||
|
||||
-- 住院护士增强子菜单
|
||||
UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20182; -- 护士工作站
|
||||
UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20183; -- 退药管理
|
||||
UPDATE sys_menu SET icon = 'nurse' WHERE menu_id = 20184; -- 滚费管理
|
||||
UPDATE sys_menu SET icon = 'vital-signs' WHERE menu_id = 20185; -- TPR表
|
||||
|
||||
-- 住院辅助子菜单
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 20222; -- 住院结算
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 20223; -- 费用类型转换
|
||||
UPDATE sys_menu SET icon = 'diagnosis' WHERE menu_id = 20224; -- 住院诊断
|
||||
UPDATE sys_menu SET icon = 'emr' WHERE menu_id = 20225; -- 住院病历
|
||||
UPDATE sys_menu SET icon = 'order' WHERE menu_id = 20226; -- 医嘱管理
|
||||
UPDATE sys_menu SET icon = 'surgery' WHERE menu_id = 20228; -- 住院手术
|
||||
|
||||
-- 基础数据子菜单
|
||||
UPDATE sys_menu SET icon = 'patient' WHERE menu_id = 205; -- 患者管理
|
||||
UPDATE sys_menu SET icon = 'patient' WHERE menu_id = 206; -- 患者档案管理
|
||||
UPDATE sys_menu SET icon = 'department' WHERE menu_id = 212; -- 科室管理
|
||||
UPDATE sys_menu SET icon = 'supplier' WHERE menu_id = 214; -- 供应商管理
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 216; -- 挂号收费项目
|
||||
UPDATE sys_menu SET icon = 'pharmacy' WHERE menu_id = 238; -- 库房/药房管理
|
||||
UPDATE sys_menu SET icon = 'appointment' WHERE menu_id = 245; -- 门诊号源管理
|
||||
UPDATE sys_menu SET icon = 'user' WHERE menu_id = 246; -- 客户数据
|
||||
UPDATE sys_menu SET icon = 'bed-management' WHERE menu_id = 247; -- 病区/床位管理
|
||||
|
||||
-- 目录管理子菜单
|
||||
UPDATE sys_menu SET icon = 'drug' WHERE menu_id = 201; -- 药品目录
|
||||
UPDATE sys_menu SET icon = 'laboratory' WHERE menu_id = 202; -- 诊疗目录
|
||||
UPDATE sys_menu SET icon = 'inventory' WHERE menu_id = 203; -- 耗材目录
|
||||
UPDATE sys_menu SET icon = 'diagnosis' WHERE menu_id = 204; -- 诊断目录
|
||||
|
||||
-- 基础数据子菜单 - 新增
|
||||
UPDATE sys_menu SET icon = 'bed-management' WHERE menu_id = 20257; -- 床体管理
|
||||
UPDATE sys_menu SET icon = 'body' WHERE menu_id = 20258; -- 体表结构
|
||||
UPDATE sys_menu SET icon = 'diagnosis' WHERE menu_id = 20259; -- 常用诊断
|
||||
UPDATE sys_menu SET icon = 'billing' WHERE menu_id = 20260; -- 费用管理
|
||||
UPDATE sys_menu SET icon = 'location' WHERE menu_id = 20261; -- 位置管理
|
||||
UPDATE sys_menu SET icon = 'order' WHERE menu_id = 20262; -- 医嘱组合
|
||||
UPDATE sys_menu SET icon = 'medication' WHERE menu_id = 20263; -- 中医处方
|
||||
|
||||
-- 为剩余没有图标的菜单设置默认图标
|
||||
UPDATE sys_menu SET icon = 'list' WHERE menu_type = 'C' AND (icon IS NULL OR icon = '');
|
||||
UPDATE sys_menu SET icon = 'list' WHERE menu_type = 'M' AND (icon IS NULL OR icon = '');
|
||||
@@ -0,0 +1,42 @@
|
||||
CREATE TABLE IF NOT EXISTS ehcard_card (
|
||||
id BIGINT PRIMARY KEY,
|
||||
patient_id BIGINT NOT NULL,
|
||||
patient_name VARCHAR(64),
|
||||
id_card VARCHAR(32),
|
||||
phone VARCHAR(20),
|
||||
card_no VARCHAR(64) NOT NULL,
|
||||
card_type VARCHAR(20) NOT NULL DEFAULT 'HEALTH',
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
|
||||
qr_code TEXT,
|
||||
apply_time TIMESTAMP,
|
||||
lock_time TIMESTAMP,
|
||||
unlock_time TIMESTAMP,
|
||||
lock_reason VARCHAR(256),
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 1,
|
||||
delete_flag VARCHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ehcard_usage_log (
|
||||
id BIGINT PRIMARY KEY,
|
||||
card_id BIGINT NOT NULL,
|
||||
patient_id BIGINT,
|
||||
usage_type VARCHAR(32) NOT NULL,
|
||||
usage_desc VARCHAR(256),
|
||||
operator_name VARCHAR(64),
|
||||
usage_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 1,
|
||||
delete_flag VARCHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ehcard_card_patient ON ehcard_card(patient_id);
|
||||
CREATE INDEX idx_ehcard_card_no ON ehcard_card(card_no);
|
||||
CREATE INDEX idx_ehcard_card_status ON ehcard_card(status);
|
||||
CREATE INDEX idx_ehcard_log_card ON ehcard_usage_log(card_id);
|
||||
@@ -0,0 +1,22 @@
|
||||
-- TCM diagnosis table
|
||||
CREATE TABLE IF NOT EXISTS healthlink_his.tcm_diagnosis (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
encounter_id BIGINT,
|
||||
patient_id BIGINT,
|
||||
diagnosis_type VARCHAR(50),
|
||||
diagnosis_name VARCHAR(200),
|
||||
diagnosis_code VARCHAR(50),
|
||||
syndrome_type VARCHAR(50),
|
||||
syndrome_name VARCHAR(200),
|
||||
syndrome_code VARCHAR(50),
|
||||
remark TEXT,
|
||||
enabled CHAR(1) DEFAULT '1',
|
||||
tenant_id INTEGER DEFAULT 0,
|
||||
delete_flag CHAR(1) DEFAULT '0',
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tcm_diagnosis_encounter ON healthlink_his.tcm_diagnosis(encounter_id);
|
||||
@@ -0,0 +1,82 @@
|
||||
CREATE TABLE IF NOT EXISTS invoice_header (
|
||||
id BIGINT PRIMARY KEY,
|
||||
invoice_no VARCHAR(64) NOT NULL,
|
||||
invoice_type VARCHAR(20) NOT NULL DEFAULT 'ELECTRONIC',
|
||||
encounter_id BIGINT,
|
||||
patient_id BIGINT,
|
||||
patient_name VARCHAR(64),
|
||||
total_amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
discount_amount NUMERIC(12,2) DEFAULT 0,
|
||||
payable_amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
paid_amount NUMERIC(12,2) DEFAULT 0,
|
||||
invoice_status VARCHAR(20) NOT NULL DEFAULT 'ISSUED',
|
||||
issue_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
void_time TIMESTAMP,
|
||||
void_reason VARCHAR(256),
|
||||
issuer_id BIGINT,
|
||||
issuer_name VARCHAR(64),
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 1,
|
||||
delete_flag VARCHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS invoice_detail (
|
||||
id BIGINT PRIMARY KEY,
|
||||
header_id BIGINT NOT NULL,
|
||||
item_code VARCHAR(64),
|
||||
item_name VARCHAR(128) NOT NULL,
|
||||
item_type VARCHAR(20),
|
||||
quantity NUMERIC(10,2) DEFAULT 1,
|
||||
unit_price NUMERIC(12,2) DEFAULT 0,
|
||||
amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 1,
|
||||
delete_flag VARCHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS invoice_segment (
|
||||
id BIGINT PRIMARY KEY,
|
||||
segment_name VARCHAR(128) NOT NULL,
|
||||
start_no VARCHAR(64) NOT NULL,
|
||||
end_no VARCHAR(64) NOT NULL,
|
||||
current_no VARCHAR(64),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
|
||||
invoice_type VARCHAR(20) DEFAULT 'ELECTRONIC',
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 1,
|
||||
delete_flag VARCHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS invoice_reconciliation (
|
||||
id BIGINT PRIMARY KEY,
|
||||
recon_date DATE NOT NULL,
|
||||
total_invoices INT DEFAULT 0,
|
||||
total_amount NUMERIC(14,2) DEFAULT 0,
|
||||
reconciled_count INT DEFAULT 0,
|
||||
reconciled_amount NUMERIC(14,2) DEFAULT 0,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||||
reconciler_id BIGINT,
|
||||
reconciler_name VARCHAR(64),
|
||||
reconcile_time TIMESTAMP,
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 1,
|
||||
delete_flag VARCHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE INDEX idx_inv_header_no ON invoice_header(invoice_no);
|
||||
CREATE INDEX idx_inv_header_status ON invoice_header(invoice_status);
|
||||
CREATE INDEX idx_inv_header_patient ON invoice_header(patient_id);
|
||||
CREATE INDEX idx_inv_detail_header ON invoice_detail(header_id);
|
||||
CREATE INDEX idx_inv_recon_date ON invoice_reconciliation(recon_date);
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Add auto-screen fields to epidemic_report
|
||||
ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS screen_result TEXT;
|
||||
ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS screen_time TIMESTAMP;
|
||||
ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS screen_level VARCHAR(20);
|
||||
ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS address VARCHAR(500);
|
||||
ALTER TABLE healthlink_his.epidemic_report ADD COLUMN IF NOT EXISTS contact_phone VARCHAR(50);
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.healthlink.his.anesthesia.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("anes_alldrete_score")
|
||||
public class AnesthesiaAldreteScore extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long recordId;
|
||||
private Long encounterId;
|
||||
private Long patientId;
|
||||
private String patientName;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date assessTime;
|
||||
private Integer activityScore;
|
||||
private Integer respirationScore;
|
||||
private Integer circulationScore;
|
||||
private Integer consciousnessScore;
|
||||
private Integer spo2Score;
|
||||
private Integer totalScore;
|
||||
private String riskLevel;
|
||||
private Long assessorId;
|
||||
private String assessorName;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.healthlink.his.anesthesia.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("anes_intraop_event")
|
||||
public class AnesthesiaIntraopEvent extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long recordId;
|
||||
private Long encounterId;
|
||||
private Long patientId;
|
||||
private String eventType;
|
||||
private String eventDetail;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date eventTime;
|
||||
private String operatorName;
|
||||
private String position;
|
||||
private String intubationType;
|
||||
private String intubationResult;
|
||||
private String extubationReason;
|
||||
private String extubationResult;
|
||||
private String complication;
|
||||
private String action;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.healthlink.his.anesthesia.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("anes_preop_visit")
|
||||
public class AnesthesiaPreopVisit extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long recordId;
|
||||
private Long encounterId;
|
||||
private Long patientId;
|
||||
private String patientName;
|
||||
private Long visitDoctorId;
|
||||
private String visitDoctorName;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date visitTime;
|
||||
private String chiefComplaint;
|
||||
private String presentIllness;
|
||||
private String pastHistory;
|
||||
private String allergyHistory;
|
||||
private String airwayAssessment;
|
||||
private String asaGrade;
|
||||
private String cardiovascularStatus;
|
||||
private String respiratoryStatus;
|
||||
private String neurologicalStatus;
|
||||
private String hepatorenalFunction;
|
||||
private String coagulationStatus;
|
||||
private String fastingStatus;
|
||||
private String npoHours;
|
||||
private String difficultAirwayRisk;
|
||||
private String anesthesiaRisk;
|
||||
private String riskFactors;
|
||||
private String recommendation;
|
||||
private String status;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.healthlink.his.anesthesia.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaAldreteScore;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AnesthesiaAldreteScoreMapper extends BaseMapper<AnesthesiaAldreteScore> {
|
||||
List<AnesthesiaAldreteScore> selectByRecordId(@Param("recordId") Long recordId);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.healthlink.his.anesthesia.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaIntraopEvent;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AnesthesiaIntraopEventMapper extends BaseMapper<AnesthesiaIntraopEvent> {
|
||||
List<AnesthesiaIntraopEvent> selectByRecordId(@Param("recordId") Long recordId);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.healthlink.his.anesthesia.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaPreopVisit;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AnesthesiaPreopVisitMapper extends BaseMapper<AnesthesiaPreopVisit> {
|
||||
List<AnesthesiaPreopVisit> selectByRecordId(@Param("recordId") Long recordId);
|
||||
List<AnesthesiaPreopVisit> selectByEncounterId(@Param("encounterId") Long encounterId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.healthlink.his.anesthesia.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaAldreteScore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IAnesthesiaAldreteScoreService extends IService<AnesthesiaAldreteScore> {
|
||||
List<AnesthesiaAldreteScore> selectByRecordId(Long recordId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.healthlink.his.anesthesia.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaIntraopEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IAnesthesiaIntraopEventService extends IService<AnesthesiaIntraopEvent> {
|
||||
List<AnesthesiaIntraopEvent> selectByRecordId(Long recordId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.anesthesia.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaPreopVisit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IAnesthesiaPreopVisitService extends IService<AnesthesiaPreopVisit> {
|
||||
List<AnesthesiaPreopVisit> selectByRecordId(Long recordId);
|
||||
List<AnesthesiaPreopVisit> selectByEncounterId(Long encounterId);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.healthlink.his.anesthesia.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaAldreteScore;
|
||||
import com.healthlink.his.anesthesia.mapper.AnesthesiaAldreteScoreMapper;
|
||||
import com.healthlink.his.anesthesia.service.IAnesthesiaAldreteScoreService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AnesthesiaAldreteScoreServiceImpl
|
||||
extends ServiceImpl<AnesthesiaAldreteScoreMapper, AnesthesiaAldreteScore>
|
||||
implements IAnesthesiaAldreteScoreService {
|
||||
|
||||
@Override
|
||||
public List<AnesthesiaAldreteScore> selectByRecordId(Long recordId) {
|
||||
return baseMapper.selectByRecordId(recordId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.healthlink.his.anesthesia.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaIntraopEvent;
|
||||
import com.healthlink.his.anesthesia.mapper.AnesthesiaIntraopEventMapper;
|
||||
import com.healthlink.his.anesthesia.service.IAnesthesiaIntraopEventService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AnesthesiaIntraopEventServiceImpl
|
||||
extends ServiceImpl<AnesthesiaIntraopEventMapper, AnesthesiaIntraopEvent>
|
||||
implements IAnesthesiaIntraopEventService {
|
||||
|
||||
@Override
|
||||
public List<AnesthesiaIntraopEvent> selectByRecordId(Long recordId) {
|
||||
return baseMapper.selectByRecordId(recordId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.healthlink.his.anesthesia.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.anesthesia.domain.AnesthesiaPreopVisit;
|
||||
import com.healthlink.his.anesthesia.mapper.AnesthesiaPreopVisitMapper;
|
||||
import com.healthlink.his.anesthesia.service.IAnesthesiaPreopVisitService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AnesthesiaPreopVisitServiceImpl
|
||||
extends ServiceImpl<AnesthesiaPreopVisitMapper, AnesthesiaPreopVisit>
|
||||
implements IAnesthesiaPreopVisitService {
|
||||
|
||||
@Override
|
||||
public List<AnesthesiaPreopVisit> selectByRecordId(Long recordId) {
|
||||
return baseMapper.selectByRecordId(recordId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnesthesiaPreopVisit> selectByEncounterId(Long encounterId) {
|
||||
return baseMapper.selectByEncounterId(encounterId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.healthlink.his.ehcard.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("ehcard_card")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EhcardCard extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long patientId;
|
||||
private String patientName;
|
||||
private String idCard;
|
||||
private String phone;
|
||||
private String cardNo;
|
||||
private String cardType;
|
||||
private String status;
|
||||
private String qrCode;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date applyTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date lockTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date unlockTime;
|
||||
private String lockReason;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.healthlink.his.ehcard.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("ehcard_usage_log")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EhcardUsageLog extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long cardId;
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long patientId;
|
||||
private String usageType;
|
||||
private String usageDesc;
|
||||
private String operatorName;
|
||||
private Date usageTime;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.ehcard.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.ehcard.domain.EhcardCard;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EhcardCardMapper extends BaseMapper<EhcardCard> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.ehcard.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.ehcard.domain.EhcardUsageLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EhcardUsageLogMapper extends BaseMapper<EhcardUsageLog> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.ehcard.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.ehcard.domain.EhcardCard;
|
||||
|
||||
public interface IEhcardCardService extends IService<EhcardCard> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.ehcard.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.ehcard.domain.EhcardUsageLog;
|
||||
|
||||
public interface IEhcardUsageLogService extends IService<EhcardUsageLog> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.ehcard.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.ehcard.domain.EhcardCard;
|
||||
import com.healthlink.his.ehcard.mapper.EhcardCardMapper;
|
||||
import com.healthlink.his.ehcard.service.IEhcardCardService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EhcardCardServiceImpl extends ServiceImpl<EhcardCardMapper, EhcardCard> implements IEhcardCardService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.ehcard.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.ehcard.domain.EhcardUsageLog;
|
||||
import com.healthlink.his.ehcard.mapper.EhcardUsageLogMapper;
|
||||
import com.healthlink.his.ehcard.service.IEhcardUsageLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EhcardUsageLogServiceImpl extends ServiceImpl<EhcardUsageLogMapper, EhcardUsageLog> implements IEhcardUsageLogService {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.healthlink.his.einvoice.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@TableName("invoice_detail")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EinvoiceDetail extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long headerId;
|
||||
private String itemCode;
|
||||
private String itemName;
|
||||
private String itemType;
|
||||
private BigDecimal quantity;
|
||||
private BigDecimal unitPrice;
|
||||
private BigDecimal amount;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.healthlink.his.einvoice.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("invoice_header")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EinvoiceHeader extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
private String invoiceNo;
|
||||
private String invoiceType;
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long encounterId;
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long patientId;
|
||||
private String patientName;
|
||||
private BigDecimal totalAmount;
|
||||
private BigDecimal discountAmount;
|
||||
private BigDecimal payableAmount;
|
||||
private BigDecimal paidAmount;
|
||||
private String invoiceStatus;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date issueTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date voidTime;
|
||||
private String voidReason;
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long issuerId;
|
||||
private String issuerName;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.healthlink.his.einvoice.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("invoice_reconciliation")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EinvoiceReconciliation extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date reconDate;
|
||||
private Integer totalInvoices;
|
||||
private BigDecimal totalAmount;
|
||||
private Integer reconciledCount;
|
||||
private BigDecimal reconciledAmount;
|
||||
private String status;
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long reconcilerId;
|
||||
private String reconcilerName;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date reconcileTime;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.healthlink.his.einvoice.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import tools.jackson.databind.annotation.JsonSerialize;
|
||||
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
@Data
|
||||
@TableName("invoice_segment")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EinvoiceSegment extends HisBaseEntity {
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
private String segmentName;
|
||||
private String startNo;
|
||||
private String endNo;
|
||||
private String currentNo;
|
||||
private String status;
|
||||
private String invoiceType;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.einvoice.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceDetail;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EinvoiceDetailMapper extends BaseMapper<EinvoiceDetail> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.einvoice.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceHeader;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EinvoiceHeaderMapper extends BaseMapper<EinvoiceHeader> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.einvoice.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceReconciliation;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EinvoiceReconciliationMapper extends BaseMapper<EinvoiceReconciliation> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.healthlink.his.einvoice.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceSegment;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface EinvoiceSegmentMapper extends BaseMapper<EinvoiceSegment> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.einvoice.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceDetail;
|
||||
|
||||
public interface IEinvoiceDetailService extends IService<EinvoiceDetail> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.einvoice.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceHeader;
|
||||
|
||||
public interface IEinvoiceHeaderService extends IService<EinvoiceHeader> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.einvoice.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceReconciliation;
|
||||
|
||||
public interface IEinvoiceReconciliationService extends IService<EinvoiceReconciliation> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.einvoice.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceSegment;
|
||||
|
||||
public interface IEinvoiceSegmentService extends IService<EinvoiceSegment> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.einvoice.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceDetail;
|
||||
import com.healthlink.his.einvoice.mapper.EinvoiceDetailMapper;
|
||||
import com.healthlink.his.einvoice.service.IEinvoiceDetailService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EinvoiceDetailServiceImpl extends ServiceImpl<EinvoiceDetailMapper, EinvoiceDetail> implements IEinvoiceDetailService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.einvoice.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceHeader;
|
||||
import com.healthlink.his.einvoice.mapper.EinvoiceHeaderMapper;
|
||||
import com.healthlink.his.einvoice.service.IEinvoiceHeaderService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EinvoiceHeaderServiceImpl extends ServiceImpl<EinvoiceHeaderMapper, EinvoiceHeader> implements IEinvoiceHeaderService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.einvoice.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceReconciliation;
|
||||
import com.healthlink.his.einvoice.mapper.EinvoiceReconciliationMapper;
|
||||
import com.healthlink.his.einvoice.service.IEinvoiceReconciliationService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EinvoiceReconciliationServiceImpl extends ServiceImpl<EinvoiceReconciliationMapper, EinvoiceReconciliation> implements IEinvoiceReconciliationService {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.healthlink.his.einvoice.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.einvoice.domain.EinvoiceSegment;
|
||||
import com.healthlink.his.einvoice.mapper.EinvoiceSegmentMapper;
|
||||
import com.healthlink.his.einvoice.service.IEinvoiceSegmentService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EinvoiceSegmentServiceImpl extends ServiceImpl<EinvoiceSegmentMapper, EinvoiceSegment> implements IEinvoiceSegmentService {
|
||||
}
|
||||
@@ -13,4 +13,6 @@ public class EpidemicReport extends HisBaseEntity {
|
||||
private String reporterId; private String reporterName;
|
||||
private Date reportDate; private String status;
|
||||
private String cdcConfirmNo; private String delFlag;
|
||||
private String screenResult; private Date screenTime; private String screenLevel;
|
||||
private String address; private String contactPhone;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.healthlink.his.tcm.domain;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("tcm_diagnosis")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TcmDiagnosis extends HisBaseEntity {
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long encounterId;
|
||||
private Long patientId;
|
||||
private String diagnosisType;
|
||||
private String diagnosisName;
|
||||
private String diagnosisCode;
|
||||
private String syndromeType;
|
||||
private String syndromeName;
|
||||
private String syndromeCode;
|
||||
private String remark;
|
||||
private String enabled;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.healthlink.his.tcm.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.tcm.domain.TcmDiagnosis;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface TcmDiagnosisMapper extends BaseMapper<TcmDiagnosis> {}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.healthlink.his.tcm.service;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.tcm.domain.TcmDiagnosis;
|
||||
public interface ITcmDiagnosisService extends IService<TcmDiagnosis> {}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.healthlink.his.tcm.service.impl;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.tcm.domain.TcmDiagnosis;
|
||||
import com.healthlink.his.tcm.mapper.TcmDiagnosisMapper;
|
||||
import com.healthlink.his.tcm.service.ITcmDiagnosisService;
|
||||
import org.springframework.stereotype.Service;
|
||||
@Service public class TcmDiagnosisServiceImpl extends ServiceImpl<TcmDiagnosisMapper, TcmDiagnosis> implements ITcmDiagnosisService {}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.anesthesia.mapper.AnesthesiaAldreteScoreMapper">
|
||||
|
||||
<select id="selectByRecordId" resultType="com.healthlink.his.anesthesia.domain.AnesthesiaAldreteScore">
|
||||
SELECT * FROM anes_alldrete_score
|
||||
WHERE record_id = #{recordId}
|
||||
ORDER BY assess_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.anesthesia.mapper.AnesthesiaIntraopEventMapper">
|
||||
|
||||
<select id="selectByRecordId" resultType="com.healthlink.his.anesthesia.domain.AnesthesiaIntraopEvent">
|
||||
SELECT * FROM anes_intraop_event
|
||||
WHERE record_id = #{recordId}
|
||||
ORDER BY event_time ASC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.healthlink.his.anesthesia.mapper.AnesthesiaPreopVisitMapper">
|
||||
|
||||
<select id="selectByRecordId" resultType="com.healthlink.his.anesthesia.domain.AnesthesiaPreopVisit">
|
||||
SELECT * FROM anes_preop_visit
|
||||
WHERE record_id = #{recordId}
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectByEncounterId" resultType="com.healthlink.his.anesthesia.domain.AnesthesiaPreopVisit">
|
||||
SELECT * FROM anes_preop_visit
|
||||
WHERE encounter_id = #{encounterId}
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
199
healthlink-his-ui/src/views/drganalysis/DrgDeepAnalysis.vue
Normal file
199
healthlink-his-ui/src/views/drganalysis/DrgDeepAnalysis.vue
Normal file
@@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<div style="padding: 16px">
|
||||
<div style="margin-bottom: 16px; display: flex; justify-content: space-between; align-items: center">
|
||||
<span style="font-size: 18px; font-weight: bold">DRG/DIP深化分析</span>
|
||||
<el-button type="primary" @click="refreshAll">刷新</el-button>
|
||||
</div>
|
||||
|
||||
<el-row :gutter="16" style="margin-bottom: 16px">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" :body-style="{ padding: '12px' }">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 22px; font-weight: bold; color: #409eff">{{ deepStats.totalCases || 0 }}</div>
|
||||
<div style="font-size: 12px; color: #999">分析病例数</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" :body-style="{ padding: '12px' }">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 22px; font-weight: bold; color: #67c23a">{{ formatMoney(deepStats.avgCost) }}</div>
|
||||
<div style="font-size: 12px; color: #999">平均费用(万)</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" :body-style="{ padding: '12px' }">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 22px; font-weight: bold; color: #e6a23c">{{ deepStats.avgLos || 0 }}天</div>
|
||||
<div style="font-size: 12px; color: #999">平均住院日</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" :body-style="{ padding: '12px' }">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 22px; font-weight: bold; color: #f56c6c">{{ deepStats.insuranceRate || 0 }}%</div>
|
||||
<div style="font-size: 12px; color: #999">医保支付率</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16" style="margin-bottom: 16px">
|
||||
<el-col :span="12">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>费用预警</span>
|
||||
<span style="font-size: 12px; color: #f56c6c">未处理: {{ costAlert.unhandledCount || 0 }} / 高危: {{ costAlert.highLevelCount || 0 }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="(costAlert.records || []).slice(0, 5)" border stripe size="small">
|
||||
<el-table-column prop="patientName" label="患者" width="100" />
|
||||
<el-table-column prop="drgCode" label="DRG组" width="100" />
|
||||
<el-table-column prop="alertLevel" label="等级" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.alertLevel === 'HIGH' ? 'danger' : row.alertLevel === 'MEDIUM' ? 'warning' : 'info'" size="small">{{ row.alertLevel }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="handleStatus" label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.handleStatus === 'PENDING' ? 'danger' : 'success'" size="small">{{ row.handleStatus === 'PENDING' ? '待处理' : '已处理' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="costDeviation" label="偏差" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.costDeviation) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-card shadow="never">
|
||||
<template #header>优化趋势</template>
|
||||
<el-table :data="(optimization.trend || []).slice(0, 5)" border stripe size="small">
|
||||
<el-table-column prop="month" label="月份" width="100" />
|
||||
<el-table-column prop="totalCases" label="病例数" width="80" align="center" />
|
||||
<el-table-column prop="avgWeight" label="平均权重" width="100" align="right" />
|
||||
<el-table-column prop="avgCost" label="平均费用" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.avgCost) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="costControlRate" label="费用控制率" width="100" align="right">
|
||||
<template #default="{ row }">{{ row.costControlRate }}%</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom: 16px">
|
||||
<template #header>DRG分组分析</template>
|
||||
<div style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 12px">
|
||||
<el-select v-model="analyzeQuery.groupingType" placeholder="分组类型" clearable style="width: 120px">
|
||||
<el-option label="DRG" value="DRG" />
|
||||
<el-option label="DIP" value="DIP" />
|
||||
</el-select>
|
||||
<el-date-picker v-model="analyzeQuery.dateRange" type="daterange" start-placeholder="开始" end-placeholder="结束" style="width: 260px" />
|
||||
<el-button type="primary" @click="runAnalysis">分析</el-button>
|
||||
</div>
|
||||
<el-table :data="deepStats.topDrgByCost || []" border stripe>
|
||||
<el-table-column type="index" label="排名" width="60" align="center" />
|
||||
<el-table-column prop="drgCode" label="DRG组代码" width="140" />
|
||||
<el-table-column prop="count" label="病例数" width="100" align="center" />
|
||||
<el-table-column prop="totalCost" label="总费用(万元)" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.totalCost) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>当前绩效指标</template>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="4">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 20px; font-weight: bold; color: #409eff">{{ optimization.totalCases || 0 }}</div>
|
||||
<div style="font-size: 12px; color: #999">当月病例数</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 20px; font-weight: bold; color: #67c23a">{{ optimization.drgCoveredRate || 0 }}%</div>
|
||||
<div style="font-size: 12px; color: #999">DRG入组率</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 20px; font-weight: bold; color: #e6a23c">{{ optimization.avgWeight || 0 }}</div>
|
||||
<div style="font-size: 12px; color: #999">平均权重</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 20px; font-weight: bold; color: #f56c6c">{{ formatMoney(optimization.avgCost) }}</div>
|
||||
<div style="font-size: 12px; color: #999">平均费用(万)</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 20px; font-weight: bold; color: #409eff">{{ optimization.costControlRate || 0 }}%</div>
|
||||
<div style="font-size: 12px; color: #999">费用控制率</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 20px; font-weight: bold; color: #67c23a">{{ optimization.cmiValue || 0 }}</div>
|
||||
<div style="font-size: 12px; color: #999">CMI值</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { analyzeDrgDeep, getCostAlert, getOptimization } from './deepApi'
|
||||
|
||||
const deepStats = ref({})
|
||||
const costAlert = ref({})
|
||||
const optimization = ref({})
|
||||
const analyzeQuery = ref({ groupingType: '', dateRange: null })
|
||||
|
||||
function formatMoney(val) {
|
||||
if (!val) return '0.00'
|
||||
return (Number(val) / 10000).toFixed(2)
|
||||
}
|
||||
|
||||
async function refreshAll() {
|
||||
try {
|
||||
const [a, c, o] = await Promise.all([
|
||||
analyzeDrgDeep({}),
|
||||
getCostAlert({}),
|
||||
getOptimization({})
|
||||
])
|
||||
deepStats.value = a.data || {}
|
||||
costAlert.value = c.data || {}
|
||||
optimization.value = o.data || {}
|
||||
} catch (e) {
|
||||
ElMessage.error('加载数据失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function runAnalysis() {
|
||||
const params = { groupingType: analyzeQuery.value.groupingType }
|
||||
if (analyzeQuery.value.dateRange && analyzeQuery.value.dateRange.length === 2) {
|
||||
params.startDate = analyzeQuery.value.dateRange[0]
|
||||
params.endDate = analyzeQuery.value.dateRange[1]
|
||||
}
|
||||
try {
|
||||
const r = await analyzeDrgDeep(params)
|
||||
deepStats.value = r.data || {}
|
||||
ElMessage.success('分析完成')
|
||||
} catch (e) {
|
||||
ElMessage.error('分析失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => refreshAll())
|
||||
</script>
|
||||
13
healthlink-his-ui/src/views/drganalysis/deepApi.js
Normal file
13
healthlink-his-ui/src/views/drganalysis/deepApi.js
Normal file
@@ -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 })
|
||||
}
|
||||
160
healthlink-his-ui/src/views/ehcard/EhcardManagement.vue
Normal file
160
healthlink-his-ui/src/views/ehcard/EhcardManagement.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div style="padding: 16px">
|
||||
<div style="margin-bottom: 16px; display: flex; justify-content: space-between; align-items: center">
|
||||
<span style="font-size: 18px; font-weight: bold">电子健康卡管理</span>
|
||||
<el-button type="primary" @click="handleApply">申请健康卡</el-button>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom: 16px">
|
||||
<div style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center">
|
||||
<el-input v-model="query.patientName" placeholder="患者姓名" clearable style="width: 160px" />
|
||||
<el-select v-model="query.status" placeholder="状态" clearable style="width: 120px">
|
||||
<el-option label="正常" value="ACTIVE" />
|
||||
<el-option label="已锁定" value="LOCKED" />
|
||||
</el-select>
|
||||
<el-button type="primary" @click="loadPage">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never">
|
||||
<el-table :data="tableData" v-loading="loading" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="cardNo" label="卡号" width="180" />
|
||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||
<el-table-column prop="idCard" label="身份证号" width="180" />
|
||||
<el-table-column prop="phone" label="手机号" width="140" />
|
||||
<el-table-column prop="cardType" label="卡类型" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.cardType === 'HEALTH'" type="primary">健康卡</el-tag>
|
||||
<el-tag v-else>{{ row.cardType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.status === 'ACTIVE'" type="success">正常</el-tag>
|
||||
<el-tag v-else-if="row.status === 'LOCKED'" type="danger">已锁定</el-tag>
|
||||
<el-tag v-else>{{ row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="applyTime" label="申请时间" width="170" />
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.status === 'ACTIVE'" type="danger" size="small" @click="handleLock(row)">锁定</el-button>
|
||||
<el-button v-if="row.status === 'LOCKED'" type="success" size="small" @click="handleUnlock(row)">解锁</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:current-page="query.pageNum"
|
||||
v-model:page-size="query.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
style="margin-top: 16px; justify-content: flex-end"
|
||||
@size-change="loadPage"
|
||||
@current-change="loadPage"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="applyVisible" title="申请电子健康卡" width="500px">
|
||||
<el-form :model="applyForm" label-width="80px">
|
||||
<el-form-item label="患者ID">
|
||||
<el-input v-model="applyForm.patientId" placeholder="患者ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名">
|
||||
<el-input v-model="applyForm.patientName" placeholder="患者姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证号">
|
||||
<el-input v-model="applyForm.idCard" placeholder="身份证号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号">
|
||||
<el-input v-model="applyForm.phone" placeholder="手机号" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="applyVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitApply">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="lockVisible" title="锁定健康卡" width="400px">
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="锁定原因">
|
||||
<el-input v-model="lockReason" type="textarea" :rows="3" placeholder="请输入锁定原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="lockVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmLock">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { applyEhcard, getEhcardPage, lockEhcard, unlockEhcard } from './api'
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const query = ref({ patientName: '', status: '', pageNum: 1, pageSize: 10 })
|
||||
|
||||
const applyVisible = ref(false)
|
||||
const applyForm = ref({ patientId: '', patientName: '', idCard: '', phone: '' })
|
||||
|
||||
const lockVisible = ref(false)
|
||||
const lockReason = ref('')
|
||||
const lockRow = ref(null)
|
||||
|
||||
async function loadPage() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getEhcardPage(query.value)
|
||||
tableData.value = res.data?.records || []
|
||||
total.value = res.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
query.value = { patientName: '', status: '', pageNum: 1, pageSize: 10 }
|
||||
loadPage()
|
||||
}
|
||||
|
||||
function handleApply() {
|
||||
applyForm.value = { patientId: '', patientName: '', idCard: '', phone: '' }
|
||||
applyVisible.value = true
|
||||
}
|
||||
|
||||
async function submitApply() {
|
||||
await applyEhcard(applyForm.value)
|
||||
ElMessage.success('申请成功')
|
||||
applyVisible.value = false
|
||||
loadPage()
|
||||
}
|
||||
|
||||
function handleLock(row) {
|
||||
lockRow.value = row
|
||||
lockReason.value = ''
|
||||
lockVisible.value = true
|
||||
}
|
||||
|
||||
async function confirmLock() {
|
||||
await lockEhcard({ id: lockRow.value.id, reason: lockReason.value })
|
||||
ElMessage.success('锁定成功')
|
||||
lockVisible.value = false
|
||||
loadPage()
|
||||
}
|
||||
|
||||
async function handleUnlock(row) {
|
||||
await unlockEhcard({ id: row.id })
|
||||
ElMessage.success('解锁成功')
|
||||
loadPage()
|
||||
}
|
||||
|
||||
onMounted(() => loadPage())
|
||||
</script>
|
||||
17
healthlink-his-ui/src/views/ehcard/api.js
Normal file
17
healthlink-his-ui/src/views/ehcard/api.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function applyEhcard(data) {
|
||||
return request({ url: '/api/v1/ehcard/apply', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getEhcardPage(params) {
|
||||
return request({ url: '/api/v1/ehcard/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function lockEhcard(params) {
|
||||
return request({ url: '/api/v1/ehcard/lock', method: 'post', params })
|
||||
}
|
||||
|
||||
export function unlockEhcard(params) {
|
||||
return request({ url: '/api/v1/ehcard/unlock', method: 'post', params })
|
||||
}
|
||||
204
healthlink-his-ui/src/views/einvoice/InvoiceManagement.vue
Normal file
204
healthlink-his-ui/src/views/einvoice/InvoiceManagement.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<div style="padding: 16px">
|
||||
<div style="margin-bottom: 16px; display: flex; justify-content: space-between; align-items: center">
|
||||
<span style="font-size: 18px; font-weight: bold">电子票据管理</span>
|
||||
<el-button type="primary" @click="handleGenerate">开具票据</el-button>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom: 16px">
|
||||
<div style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center">
|
||||
<el-input v-model="query.patientName" placeholder="患者姓名" clearable style="width: 160px" />
|
||||
<el-select v-model="query.invoiceStatus" placeholder="状态" clearable style="width: 120px">
|
||||
<el-option label="已开具" value="ISSUED" />
|
||||
<el-option label="已作废" value="VOID" />
|
||||
</el-select>
|
||||
<el-button type="primary" @click="loadPage">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
<el-button @click="showReconciliation">对账</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never">
|
||||
<el-table :data="tableData" v-loading="loading" border stripe>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="invoiceNo" label="票据号" width="200" />
|
||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||
<el-table-column prop="totalAmount" label="总金额" width="120" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.totalAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="discountAmount" label="优惠金额" width="120" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.discountAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payableAmount" label="应付金额" width="120" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.payableAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="invoiceStatus" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.invoiceStatus === 'ISSUED'" type="success">已开具</el-tag>
|
||||
<el-tag v-else-if="row.invoiceStatus === 'VOID'" type="danger">已作废</el-tag>
|
||||
<el-tag v-else>{{ row.invoiceStatus }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="issueTime" label="开具时间" width="170" />
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.invoiceStatus === 'ISSUED'" type="danger" size="small" @click="handleVoid(row)">作废</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:current-page="query.pageNum"
|
||||
v-model:page-size="query.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
style="margin-top: 16px; justify-content: flex-end"
|
||||
@size-change="loadPage"
|
||||
@current-change="loadPage"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="generateVisible" title="开具电子票据" width="500px">
|
||||
<el-form :model="generateForm" label-width="90px">
|
||||
<el-form-item label="就诊ID">
|
||||
<el-input v-model="generateForm.encounterId" placeholder="就诊ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="患者ID">
|
||||
<el-input v-model="generateForm.patientId" placeholder="患者ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="患者姓名">
|
||||
<el-input v-model="generateForm.patientName" placeholder="患者姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="总金额">
|
||||
<el-input v-model="generateForm.totalAmount" placeholder="总金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠金额">
|
||||
<el-input v-model="generateForm.discountAmount" placeholder="优惠金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="应付金额">
|
||||
<el-input v-model="generateForm.payableAmount" placeholder="应付金额" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="generateVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitGenerate">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="voidVisible" title="作废票据" width="400px">
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="作废原因">
|
||||
<el-input v-model="voidReason" type="textarea" :rows="3" placeholder="请输入作废原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="voidVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmVoid">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="reconVisible" title="票据对账" width="700px">
|
||||
<el-table :data="reconData" border stripe v-loading="reconLoading">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="invoiceNo" label="票据号" width="200" />
|
||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||
<el-table-column prop="payableAmount" label="应付金额" width="120" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.payableAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="invoiceStatus" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.invoiceStatus === 'ISSUED'" type="success">已开具</el-tag>
|
||||
<el-tag v-else>{{ row.invoiceStatus }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="issueTime" label="开具时间" width="170" />
|
||||
</el-table>
|
||||
<div style="margin-top: 12px; color: #666">
|
||||
共 {{ reconTotal }} 条已开具票据
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { generateInvoice, getInvoicePage, voidInvoice, getReconciliation } from './api'
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const query = ref({ invoiceStatus: '', patientName: '', pageNum: 1, pageSize: 10 })
|
||||
|
||||
const generateVisible = ref(false)
|
||||
const generateForm = ref({ encounterId: '', patientId: '', patientName: '', totalAmount: 0, discountAmount: 0, payableAmount: 0 })
|
||||
|
||||
const voidVisible = ref(false)
|
||||
const voidReason = ref('')
|
||||
const voidRow = ref(null)
|
||||
|
||||
const reconVisible = ref(false)
|
||||
const reconLoading = ref(false)
|
||||
const reconData = ref([])
|
||||
const reconTotal = ref(0)
|
||||
|
||||
function formatMoney(val) {
|
||||
if (!val) return '0.00'
|
||||
return Number(val).toFixed(2)
|
||||
}
|
||||
|
||||
async function loadPage() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getInvoicePage(query.value)
|
||||
tableData.value = res.data?.records || []
|
||||
total.value = res.data?.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
query.value = { invoiceStatus: '', patientName: '', pageNum: 1, pageSize: 10 }
|
||||
loadPage()
|
||||
}
|
||||
|
||||
function handleGenerate() {
|
||||
generateForm.value = { encounterId: '', patientId: '', patientName: '', totalAmount: 0, discountAmount: 0, payableAmount: 0 }
|
||||
generateVisible.value = true
|
||||
}
|
||||
|
||||
async function submitGenerate() {
|
||||
await generateInvoice(generateForm.value)
|
||||
ElMessage.success('开具成功')
|
||||
generateVisible.value = false
|
||||
loadPage()
|
||||
}
|
||||
|
||||
function handleVoid(row) {
|
||||
voidRow.value = row
|
||||
voidReason.value = ''
|
||||
voidVisible.value = true
|
||||
}
|
||||
|
||||
async function confirmVoid() {
|
||||
await voidInvoice({ id: voidRow.value.id, reason: voidReason.value })
|
||||
ElMessage.success('作废成功')
|
||||
voidVisible.value = false
|
||||
loadPage()
|
||||
}
|
||||
|
||||
async function showReconciliation() {
|
||||
reconVisible.value = true
|
||||
reconLoading.value = true
|
||||
try {
|
||||
const res = await getReconciliation({ pageNum: 1, pageSize: 50 })
|
||||
reconData.value = res.data?.records || []
|
||||
reconTotal.value = res.data?.totalCount || 0
|
||||
} finally {
|
||||
reconLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => loadPage())
|
||||
</script>
|
||||
17
healthlink-his-ui/src/views/einvoice/api.js
Normal file
17
healthlink-his-ui/src/views/einvoice/api.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function generateInvoice(data) {
|
||||
return request({ url: '/invoice/generate', method: 'post', data })
|
||||
}
|
||||
|
||||
export function getInvoicePage(params) {
|
||||
return request({ url: '/invoice/page', method: 'get', params })
|
||||
}
|
||||
|
||||
export function voidInvoice(params) {
|
||||
return request({ url: '/invoice/void', method: 'post', params })
|
||||
}
|
||||
|
||||
export function getReconciliation(params) {
|
||||
return request({ url: '/invoice/reconciliation', method: 'get', params })
|
||||
}
|
||||
225
healthlink-his-ui/src/views/epidemic/EpidemicReport.vue
Normal file
225
healthlink-his-ui/src/views/epidemic/EpidemicReport.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||
<el-tab-pane label="传染病报告" name="list">
|
||||
<el-form :inline="true" :model="queryParams" label-width="100px">
|
||||
<el-form-item label="报告状态">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择" clearable style="width:160px">
|
||||
<el-option label="待上报" value="PENDING" />
|
||||
<el-option label="已确认" value="CONFIRMED" />
|
||||
<el-option label="草稿" value="DRAFT" />
|
||||
<el-option label="已退回" value="RETURNED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="loadReports">查询</el-button>
|
||||
<el-button type="success" icon="Plus" @click="showAddDialog">新增报告</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-loading="loading" :data="reportList" border>
|
||||
<el-table-column label="患者姓名" align="center" prop="patientName" width="120" />
|
||||
<el-table-column label="疾病名称" align="center" prop="diseaseName" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="疾病编码" align="center" prop="diseaseCode" width="120" />
|
||||
<el-table-column label="报告类型" align="center" prop="reportType" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag>{{ reportTypeText(row.reportType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上报人" align="center" prop="reporterName" width="100" />
|
||||
<el-table-column label="上报日期" align="center" prop="reportDate" width="160" />
|
||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="statusType(row.status)">{{ statusText(row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="筛查结果" align="center" prop="screenResult" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.screenResult" :type="row.screenResult === 'MATCHED' ? 'danger' : 'success'">
|
||||
{{ row.screenResult === 'MATCHED' ? '命中' : '未命中' }}
|
||||
</el-tag>
|
||||
<span v-else>—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="160" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" icon="View" @click="handleDetail(row)">详情</el-button>
|
||||
<el-button v-if="row.status === 'PENDING'" link type="success" icon="Check" @click="handleConfirm(row)">确认</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="自动筛查" name="screen">
|
||||
<el-form :model="screenForm" label-width="110px" style="max-width:700px">
|
||||
<el-form-item label="患者姓名">
|
||||
<el-input v-model="screenForm.patientName" placeholder="请输入患者姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病名称">
|
||||
<el-input v-model="screenForm.diseaseName" placeholder="请输入诊断疾病名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病编码">
|
||||
<el-input v-model="screenForm.diseaseCode" placeholder="请输入疾病编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="报告类型">
|
||||
<el-select v-model="screenForm.reportType" placeholder="请选择">
|
||||
<el-option label="初次报告" value="INITIAL" />
|
||||
<el-option label="订正报告" value="CORRECTION" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话">
|
||||
<el-input v-model="screenForm.contactPhone" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="现住址">
|
||||
<el-input v-model="screenForm.address" placeholder="请输入现住址" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleAutoScreen">开始筛查</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-divider v-if="screenResult" />
|
||||
<el-alert v-if="screenResult" :title="screenResultTitle" :type="screenResult.screenResult === 'MATCHED' ? 'error' : 'success'" show-icon :closable="false" style="margin-bottom:16px" />
|
||||
<el-descriptions v-if="screenResult" :column="2" border>
|
||||
<el-descriptions-item label="筛查结果">{{ screenResult.screenResult === 'MATCHED' ? '命中法定传染病' : '未命中' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="筛查等级">{{ screenResult.screenLevel === 'LEVEL_A' ? '甲类' : '正常' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="筛查时间">{{ screenResult.screenTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报告状态">{{ statusText(screenResult.status) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="报告统计" name="stats">
|
||||
<el-descriptions :column="3" border>
|
||||
<el-descriptions-item label="报告总数">{{ reportStats.total || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="待上报">{{ reportStats.pending || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="已确认">{{ reportStats.confirmed || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="筛查命中">{{ reportStats.screenMatched || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="筛查未命中">{{ reportStats.screenNormal || 0 }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-dialog v-model="addDialogVisible" title="新增传染病报告" width="650px" append-to-body>
|
||||
<el-form :model="formData" label-width="110px">
|
||||
<el-form-item label="患者姓名">
|
||||
<el-input v-model="formData.patientName" placeholder="请输入患者姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病名称">
|
||||
<el-input v-model="formData.diseaseName" placeholder="请输入疾病名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="疾病编码">
|
||||
<el-input v-model="formData.diseaseCode" placeholder="请输入疾病编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="报告类型">
|
||||
<el-select v-model="formData.reportType" placeholder="请选择">
|
||||
<el-option label="初次报告" value="INITIAL" />
|
||||
<el-option label="订正报告" value="CORRECTION" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话">
|
||||
<el-input v-model="formData.contactPhone" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="现住址">
|
||||
<el-input v-model="formData.address" placeholder="请输入现住址" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="addDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="detailVisible" title="传染病报告详情" width="650px" append-to-body>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="患者姓名">{{ detailData.patientName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="疾病名称">{{ detailData.diseaseName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="疾病编码">{{ detailData.diseaseCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报告类型">{{ reportTypeText(detailData.reportType) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="上报人">{{ detailData.reporterName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="上报日期">{{ detailData.reportDate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="statusType(detailData.status)">{{ statusText(detailData.status) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="CDC确认号">{{ detailData.cdcConfirmNo || '—' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="筛查结果">{{ detailData.screenResult === 'MATCHED' ? '命中' : (detailData.screenResult || '—') }}</el-descriptions-item>
|
||||
<el-descriptions-item label="筛查等级">{{ detailData.screenLevel === 'LEVEL_A' ? '甲类' : (detailData.screenLevel || '—') }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ detailData.contactPhone || '—' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="现住址">{{ detailData.address || '—' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<template #footer>
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="EpidemicReport" lang="js">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const activeTab = ref('list')
|
||||
const loading = ref(false)
|
||||
const reportList = ref([])
|
||||
const addDialogVisible = ref(false)
|
||||
const detailVisible = ref(false)
|
||||
const detailData = ref({})
|
||||
const reportStats = ref({})
|
||||
const screenResult = ref(null)
|
||||
|
||||
const queryParams = reactive({ status: undefined })
|
||||
const formData = reactive({ patientName: '', diseaseName: '', diseaseCode: '', reportType: 'INITIAL', contactPhone: '', address: '' })
|
||||
const screenForm = reactive({ patientName: '', diseaseName: '', diseaseCode: '', reportType: 'INITIAL', contactPhone: '', address: '' })
|
||||
|
||||
const screenResultTitle = computed(() =>
|
||||
screenResult.value?.screenResult === 'MATCHED' ? '已命中法定传染病,请及时上报' : '未命中法定传染病'
|
||||
)
|
||||
|
||||
function reportTypeText(t) { return { INITIAL: '初次报告', CORRECTION: '订正报告' }[t] || t }
|
||||
function statusText(s) { return { PENDING: '待上报', CONFIRMED: '已确认', DRAFT: '草稿', RETURNED: '已退回' }[s] || s }
|
||||
function statusType(s) { return { PENDING: 'warning', CONFIRMED: 'success', DRAFT: 'info', RETURNED: 'danger' }[s] || 'info' }
|
||||
|
||||
function loadReports() {
|
||||
loading.value = true
|
||||
request({ url: '/api/v1/epidemic/list', method: 'get', params: queryParams }).then(res => {
|
||||
reportList.value = res.data || []
|
||||
}).finally(() => { loading.value = false })
|
||||
}
|
||||
|
||||
function loadStats() {
|
||||
request({ url: '/api/v1/epidemic/report-stats', method: 'get' }).then(res => {
|
||||
reportStats.value = res.data || {}
|
||||
})
|
||||
}
|
||||
|
||||
function showAddDialog() {
|
||||
Object.assign(formData, { patientName: '', diseaseName: '', diseaseCode: '', reportType: 'INITIAL', contactPhone: '', address: '' })
|
||||
addDialogVisible.value = true
|
||||
}
|
||||
|
||||
function handleDetail(row) { detailData.value = row; detailVisible.value = true }
|
||||
|
||||
function handleConfirm(row) {
|
||||
request({ url: `/api/v1/epidemic/confirm/${row.id}`, method: 'put', params: { cdcNo: 'CDC-' + Date.now() } }).then(() => {
|
||||
ElMessage.success('确认成功'); loadReports()
|
||||
})
|
||||
}
|
||||
|
||||
function handleAutoScreen() {
|
||||
request({ url: '/api/v1/epidemic/auto-screen', method: 'post', data: screenForm }).then(res => {
|
||||
screenResult.value = res.data
|
||||
ElMessage.success('筛查完成')
|
||||
})
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
request({ url: '/api/v1/epidemic/save', method: 'post', data: formData }).then(() => {
|
||||
ElMessage.success('报告保存成功'); addDialogVisible.value = false; loadReports()
|
||||
})
|
||||
}
|
||||
|
||||
function handleTabChange() {
|
||||
if (activeTab.value === 'list') loadReports()
|
||||
else if (activeTab.value === 'stats') loadStats()
|
||||
}
|
||||
|
||||
onMounted(() => { loadReports(); loadStats() })
|
||||
</script>
|
||||
300
healthlink-his-ui/src/views/tcm/TcmDiagnosis.vue
Normal file
300
healthlink-his-ui/src/views/tcm/TcmDiagnosis.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||
<el-tab-pane label="中医诊断" name="diagnosis">
|
||||
<el-form :inline="true" :model="diagQuery" label-width="100px">
|
||||
<el-form-item label="就诊号">
|
||||
<el-input v-model="diagQuery.encounterId" placeholder="请输入就诊号" clearable style="width:180px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="loadDiagnoses">查询</el-button>
|
||||
<el-button type="success" icon="Plus" @click="showDiagDialog()">新增诊断</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-loading="diagLoading" :data="diagList" border>
|
||||
<el-table-column label="就诊号" align="center" prop="encounterId" width="140" />
|
||||
<el-table-column label="诊断类型" align="center" prop="diagnosisType" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag>{{ diagTypeText(row.diagnosisType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断名称" align="center" prop="diagnosisName" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="证候类型" align="center" prop="syndromeType" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.syndromeType">{{ syndromeTypeText(row.syndromeType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="证候名称" align="center" prop="syndromeName" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="备注" align="center" prop="remark" min-width="180" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="方剂管理" name="prescription">
|
||||
<el-form :inline="true" :model="rxQuery" label-width="100px">
|
||||
<el-form-item label="方剂类型">
|
||||
<el-select v-model="rxQuery.type" placeholder="请选择" clearable style="width:160px">
|
||||
<el-option label="经典方剂" value="CLASSIC" />
|
||||
<el-option label="经验方" value="EXPERIENCE" />
|
||||
<el-option label="协定方" value="AGREEMENT" />
|
||||
<el-option label="壮医方" value="ZHUANG" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="loadPrescriptions">搜索</el-button>
|
||||
<el-button type="success" icon="Plus" @click="showRxDialog()">新增方剂</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-loading="rxLoading" :data="rxList" border>
|
||||
<el-table-column label="方剂名称" align="center" prop="prescriptionName" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="方剂类型" align="center" prop="prescriptionType" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag>{{ rxTypeText(row.prescriptionType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="组成" align="center" prop="herbs" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="主治" align="center" prop="indication" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="用法用量" align="center" prop="dosage" width="120" />
|
||||
<el-table-column label="来源" align="center" prop="source" width="120" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="体质辨识" name="constitution">
|
||||
<el-form :inline="true" :model="constQuery" label-width="100px">
|
||||
<el-form-item label="就诊号">
|
||||
<el-input v-model="constQuery.encounterId" placeholder="请输入就诊号" clearable style="width:180px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="loadConstitutions">查询</el-button>
|
||||
<el-button type="success" icon="Plus" @click="showConstDialog()">新增评估</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-loading="constLoading" :data="constList" border>
|
||||
<el-table-column label="就诊号" align="center" prop="encounterId" width="140" />
|
||||
<el-table-column label="体质类型" align="center" prop="constitutionType" width="140">
|
||||
<template #default="{ row }">
|
||||
<el-tag>{{ constTypeText(row.constitutionType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="评估得分" align="center" prop="score" width="100" />
|
||||
<el-table-column label="调理建议" align="center" prop="recommendation" min-width="200" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="统计" name="statistics">
|
||||
<el-descriptions :column="3" border>
|
||||
<el-descriptions-item label="方剂总数">{{ stats.totalPrescriptions || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="体质辨识总数">{{ stats.totalAssessments || 0 }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-dialog v-model="diagDialogVisible" title="中医诊断" width="600px" append-to-body>
|
||||
<el-form :model="diagForm" label-width="110px">
|
||||
<el-form-item label="就诊号">
|
||||
<el-input v-model="diagForm.encounterId" placeholder="请输入就诊号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="诊断类型">
|
||||
<el-select v-model="diagForm.diagnosisType" placeholder="请选择">
|
||||
<el-option label="中医主病诊断" value="MAIN_DISEASE" />
|
||||
<el-option label="中医主证诊断" value="MAIN_SYNDROME" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="诊断名称">
|
||||
<el-input v-model="diagForm.diagnosisName" placeholder="请输入诊断名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="诊断编码">
|
||||
<el-input v-model="diagForm.diagnosisCode" placeholder="请输入诊断编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="证候类型">
|
||||
<el-select v-model="diagForm.syndromeType" placeholder="请选择">
|
||||
<el-option label="风证" value="WIND" />
|
||||
<el-option label="寒证" value="COLD" />
|
||||
<el-option label="暑证" value="HEAT" />
|
||||
<el-option label="湿证" value="DAMP" />
|
||||
<el-option label="燥证" value="DRY" />
|
||||
<el-option label="火证" value="FIRE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="证候名称">
|
||||
<el-input v-model="diagForm.syndromeName" placeholder="请输入证候名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="证候编码">
|
||||
<el-input v-model="diagForm.syndromeCode" placeholder="请输入证候编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="diagForm.remark" type="textarea" :rows="2" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="diagDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitDiag">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="rxDialogVisible" title="新增方剂" width="600px" append-to-body>
|
||||
<el-form :model="rxForm" label-width="100px">
|
||||
<el-form-item label="方剂名称">
|
||||
<el-input v-model="rxForm.prescriptionName" placeholder="请输入方剂名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="方剂类型">
|
||||
<el-select v-model="rxForm.prescriptionType" placeholder="请选择">
|
||||
<el-option label="经典方剂" value="CLASSIC" />
|
||||
<el-option label="经验方" value="EXPERIENCE" />
|
||||
<el-option label="协定方" value="AGREEMENT" />
|
||||
<el-option label="壮医方" value="ZHUANG" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="组成">
|
||||
<el-input v-model="rxForm.herbs" type="textarea" :rows="3" placeholder="请输入药物组成" />
|
||||
</el-form-item>
|
||||
<el-form-item label="主治">
|
||||
<el-input v-model="rxForm.indication" placeholder="请输入主治病症" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用法用量">
|
||||
<el-input v-model="rxForm.dosage" placeholder="请输入用法用量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="来源">
|
||||
<el-input v-model="rxForm.source" placeholder="请输入方剂来源" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="rxDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitRx">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="constDialogVisible" title="体质辨识" width="600px" append-to-body>
|
||||
<el-form :model="constForm" label-width="110px">
|
||||
<el-form-item label="就诊号">
|
||||
<el-input v-model="constForm.encounterId" placeholder="请输入就诊号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="体质类型">
|
||||
<el-select v-model="constForm.constitutionType" placeholder="请选择">
|
||||
<el-option v-for="item in constitutionTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="评估得分">
|
||||
<el-input-number v-model="constForm.score" :min="0" :max="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="调理建议">
|
||||
<el-input v-model="constForm.recommendation" type="textarea" :rows="3" placeholder="请输入调理建议" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="constDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitConst">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="TcmDiagnosis" lang="js">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const activeTab = ref('diagnosis')
|
||||
const diagLoading = ref(false)
|
||||
const rxLoading = ref(false)
|
||||
const constLoading = ref(false)
|
||||
const diagDialogVisible = ref(false)
|
||||
const rxDialogVisible = ref(false)
|
||||
const constDialogVisible = ref(false)
|
||||
const diagList = ref([])
|
||||
const rxList = ref([])
|
||||
const constList = ref([])
|
||||
const stats = ref({})
|
||||
|
||||
const diagQuery = reactive({ encounterId: '' })
|
||||
const rxQuery = reactive({ type: undefined })
|
||||
const constQuery = reactive({ encounterId: '' })
|
||||
|
||||
const diagForm = reactive({ encounterId: '', diagnosisType: 'MAIN_DISEASE', diagnosisName: '', diagnosisCode: '', syndromeType: '', syndromeName: '', syndromeCode: '', remark: '' })
|
||||
const rxForm = reactive({ prescriptionName: '', prescriptionType: 'CLASSIC', herbs: '', indication: '', dosage: '', source: '' })
|
||||
const constForm = reactive({ encounterId: '', constitutionType: 'PINGHE', score: 0, recommendation: '' })
|
||||
|
||||
const constitutionTypes = [
|
||||
{ value: 'PINGHE', label: '平和质' }, { value: 'QIXU', label: '气虚质' },
|
||||
{ value: 'YANGXU', label: '阳虚质' }, { value: 'YINXU', label: '阴虚质' },
|
||||
{ value: 'TANSHI', label: '痰湿质' }, { value: 'SHIRE', label: '湿热质' },
|
||||
{ value: 'XUEYU', label: '血瘀质' }, { value: 'QIYU', label: '气郁质' },
|
||||
{ value: 'TEBING', label: '特禀质' }
|
||||
]
|
||||
|
||||
function diagTypeText(t) {
|
||||
return { MAIN_DISEASE: '中医主病诊断', MAIN_SYNDROME: '中医主证诊断' }[t] || t
|
||||
}
|
||||
function syndromeTypeText(t) {
|
||||
return { WIND: '风证', COLD: '寒证', HEAT: '暑证', DAMP: '湿证', DRY: '燥证', FIRE: '火证' }[t] || t
|
||||
}
|
||||
function rxTypeText(t) {
|
||||
return { CLASSIC: '经典方剂', EXPERIENCE: '经验方', AGREEMENT: '协定方', ZHUANG: '壮医方' }[t] || t
|
||||
}
|
||||
function constTypeText(t) {
|
||||
const m = { PINGHE: '平和质', QIXU: '气虚质', YANGXU: '阳虚质', YINXU: '阴虚质', TANSHI: '痰湿质', SHIRE: '湿热质', XUEYU: '血瘀质', QIYU: '气郁质', TEBING: '特禀质' }
|
||||
return m[t] || t
|
||||
}
|
||||
|
||||
function loadDiagnoses() {
|
||||
diagLoading.value = true
|
||||
const url = diagQuery.encounterId
|
||||
? `/api/v1/tcm/diagnosis/encounter/${diagQuery.encounterId}`
|
||||
: '/api/v1/tcm/diagnosis/encounter/0'
|
||||
request({ url, method: 'get' }).then(res => {
|
||||
diagList.value = Array.isArray(res.data) ? res.data : []
|
||||
}).catch(() => { diagList.value = [] }).finally(() => { diagLoading.value = false })
|
||||
}
|
||||
|
||||
function loadPrescriptions() {
|
||||
rxLoading.value = true
|
||||
request({ url: '/api/v1/tcm/prescriptions', method: 'get', params: rxQuery }).then(res => {
|
||||
rxList.value = res.data || []
|
||||
}).finally(() => { rxLoading.value = false })
|
||||
}
|
||||
|
||||
function loadConstitutions() {
|
||||
constLoading.value = true
|
||||
const url = constQuery.encounterId
|
||||
? `/api/v1/tcm/constitution/encounter/${constQuery.encounterId}`
|
||||
: '/api/v1/tcm/statistics'
|
||||
request({ url, method: 'get' }).then(res => {
|
||||
constList.value = Array.isArray(res.data) ? res.data : (res.data?.records || [])
|
||||
}).catch(() => { constList.value = [] }).finally(() => { constLoading.value = false })
|
||||
}
|
||||
|
||||
function loadStats() {
|
||||
request({ url: '/api/v1/tcm/statistics', method: 'get' }).then(res => { stats.value = res.data || {} })
|
||||
}
|
||||
|
||||
function showDiagDialog(row) {
|
||||
if (row) { Object.assign(diagForm, row) } else { Object.assign(diagForm, { encounterId: '', diagnosisType: 'MAIN_DISEASE', diagnosisName: '', diagnosisCode: '', syndromeType: '', syndromeName: '', syndromeCode: '', remark: '' }) }
|
||||
diagDialogVisible.value = true
|
||||
}
|
||||
function showRxDialog() { Object.assign(rxForm, { prescriptionName: '', prescriptionType: 'CLASSIC', herbs: '', indication: '', dosage: '', source: '' }); rxDialogVisible.value = true }
|
||||
function showConstDialog() { Object.assign(constForm, { encounterId: '', constitutionType: 'PINGHE', score: 0, recommendation: '' }); constDialogVisible.value = true }
|
||||
|
||||
function submitDiag() {
|
||||
request({ url: '/api/v1/tcm/diagnosis', method: 'post', data: diagForm }).then(() => {
|
||||
ElMessage.success('诊断保存成功'); diagDialogVisible.value = false; loadDiagnoses()
|
||||
})
|
||||
}
|
||||
function submitRx() {
|
||||
request({ url: '/api/v1/tcm/prescription', method: 'post', data: rxForm }).then(() => {
|
||||
ElMessage.success('方剂保存成功'); rxDialogVisible.value = false; loadPrescriptions()
|
||||
})
|
||||
}
|
||||
function submitConst() {
|
||||
request({ url: '/api/v1/tcm/constitution/save', method: 'post', data: constForm }).then(() => {
|
||||
ElMessage.success('评估保存成功'); constDialogVisible.value = false; loadConstitutions()
|
||||
})
|
||||
}
|
||||
|
||||
function handleTabChange() {
|
||||
if (activeTab.value === 'diagnosis') loadDiagnoses()
|
||||
else if (activeTab.value === 'prescription') loadPrescriptions()
|
||||
else if (activeTab.value === 'constitution') loadConstitutions()
|
||||
else if (activeTab.value === 'statistics') loadStats()
|
||||
}
|
||||
|
||||
onMounted(() => { loadDiagnoses(); loadStats() })
|
||||
</script>
|
||||
Reference in New Issue
Block a user