Compare commits

...

59 Commits

Author SHA1 Message Date
6c14c1fda8 docs(markdown): 添加 HealthLink-HIS 系统介绍相关文章
- 新增三甲评审HIS系统选择指南文章
- 新增HealthLink-HIS产品推广介绍文章
- 新增HIS系统选型对比分析文章
- 新增HealthLink-HIS模块化报价方案文档
- 涵盖技术架构、功能对比、价格分析等内容
2026-07-01 09:45:39 +08:00
bcf0056137 fix: resolve pre-existing build errors in 6 Vue files 2026-07-01 08:53:22 +08:00
33fd9a3aea Merge remote-tracking branch 'origin/develop' into develop 2026-07-01 08:00:54 +08:00
wangjian963
ddf426123e 837 【住院护士站-体温单】体温单表头的标识错误,应将“病历号”字段文案及对应数据修改为“住院号” 2026-06-30 16:59:30 +08:00
wangjian963
df468d95c4 fix833 【住院护士站-出院办理】“待取药/待退药”列表缺少“医嘱状态”列,导致护士无法定位药品的具体流转状态
1. 新增待退药状态到SQL查询条件中,完善待发药列表筛选逻辑
2. 在Mapper接口新增pendingRefundStatus参数并更新ServiceImpl调用
3. 前端页面新增医嘱状态展示列,补充待退药等状态的标签显示逻辑
2026-06-30 16:01:04 +08:00
Ranyunqiao
58f35c6a80 bug 813 816 2026-06-30 10:42:40 +08:00
wangjian963
8e5c4d634f 823 【住院护士站-出院管理】出院“待取药/待退药”列表中尚未发药的药品错误提前显示发药时间和发药人,且发药人数据源错误 2026-06-29 17:15:43 +08:00
wangjian963
8ca4571386 824 【住院医生工作站-住院病历】选择一名患者时,保存住院病历无法保存成功,点击保存按钮无响应
838 【住院医生工作站-诊断录入】引入/选择门诊入院诊断时,诊断类别列错误显示为字典代码“11”而非文本“门/急诊诊断”
840 【住院医生工作站-临床医嘱】医嘱新增/保存/签发后,医嘱类型列的内容显示为空白
2026-06-29 16:39:24 +08:00
d3ed0f8a84 Merge remote-tracking branch 'origin/develop' into develop 2026-06-29 15:16:43 +08:00
c75f162652 fix(phase1): 修复EMR修订API路径、启用门诊EMR tab、清理废弃代码
- 修复revision-history api.js路径 (/emr/* → /api/v1/emr/*)
- 启用doctorstation outpatient EMR tab
- 移除EmrCompletenessCheckServiceImpl.executeCheck()硬编码PASS
- StructuredEmrAppServiceImpl改用EmrCompletenessAppServiceImpl
- 标注3个空壳Service为deprecated,移除@Service注解
2026-06-29 15:04:53 +08:00
wangjian963
d68f6d646b refactor(adviceProcess): 调整大数除法判断的代码结构
将取余判断的逻辑嵌套到数量大于等于单位占比的分支内,优化代码可读性
2026-06-29 15:02:16 +08:00
wangjian963
e1c3aebacd 822 【住院护士站-医嘱校对】药品医嘱“总量”数据换算及单位错误,导致未校对列表总量放大(医生开立2盒显示为30盒 2026-06-29 14:59:53 +08:00
wangjian963
8de3c9f4c6 fix(821 【住院护士站-出院管理】待处理执行单列表过滤规则错误,错误引入了药品(中成药)医嘱): 调整住院护理站执行单查询逻辑
移除原药品医嘱查询逻辑,新增注释说明待处理执行单仅展示非药品医嘱,药品相关查询由单独方法处理
2026-06-29 14:17:05 +08:00
42c6bdba76 Merge remote-tracking branch 'origin/develop' into develop 2026-06-29 13:13:23 +08:00
wangjian963
0200f444b5 i18n: add missing translation terms and internationalize consultation confirmation page
1. add sequence translation for viVN, enUS, zhCN locales
2. replace hardcoded table headers in consultation confirmation page with i18n keys
3. add new translation entries for consultation confirmation module
2026-06-29 12:08:27 +08:00
d2b4a6d229 docs(markdown): 添加 HealthLink-HIS 系统介绍相关文章
- 新增三甲评审HIS系统选择指南文章
- 新增HealthLink-HIS产品推广介绍文章
- 新增HIS系统选型对比分析文章
- 新增HealthLink-HIS模块化报价方案文档
- 涵盖技术架构、功能对比、价格分析等内容
2026-06-29 12:01:44 +08:00
3856b81934 docs(markdown): 删除多个HIS系统相关文章文档
- 移除 healthlink-his-grade3a-comparison-article.md 文件
- 移除 healthlink-his-promotion-article.md 文件
- 移除 HEALTHLINK_HIS_COMPARE_ARTICLE.md 文件
- 移除 HEALTHLINK_HIS_PRICING_PROPOSAL_0.2.md 文件
- 清理医院信息系统介绍、推广、对比及报价相关内容
- 删除Markdown格式的软文和方案文档
2026-06-29 12:01:19 +08:00
wangjian963
a0696d382c i18n: 完善会诊管理模块的中文国际化文案
1. 新增会诊申请和会诊确认的全量中文翻译词条
2. 将页面内的国际化引用从旧的consultation路径切换到新的consultationMgmt路径
3. 同步更新了原有医嘱相关的国际化文案为中文
2026-06-29 11:52:03 +08:00
wangjian963
be93a77b64 fix(医嘱核对): 修正截止时间筛选逻辑与默认值
1. 将前端默认截止时间从当天00:00:00改为23:59:59
2. 重构后端筛选条件,改为当日0点到指定截止时间的范围查询
3. 移除冗余的空安全终止时间判断逻辑
2026-06-29 11:11:31 +08:00
wangjian963
79478c6780 refactor(doctorstation): 调整国际化key命名并更新页面引用
1. 统一检查、检验、处方模块的国际化前缀为doctorstationExam、doctorstationInspection和doctorstationPrescription
2. 更新所有相关vue文件中的t函数调用路径,适配新的国际化key命名
3. 补充完善了三个模块的多语言文案(zhCN、enUS、viVN)
2026-06-29 10:18:10 +08:00
0649443845 feat(i18n): 添加国际化(i18n)基础设施和多语言支持
- 新增 I18nUtils 工具类提供多语言消息获取功能
- 创建多语言技术方案设计文档 MULTILANG_I18N_DESIGN.md
- 编写国际化战略文章 HEALTHLINK_HIS_INTERNATIONALIZATION_STRATEGY.md
- 添加国际化战略概述文档 HEALTHLINK_HIS_INTL_STRATEGY.md
- 实现基于 MessageSource 的多语言消息处理机制
- 设计支持中英越三语的国际化架构方案
- 规划前端 vue-i18n 和后端 MessageSource 集成方案
- 定义数据库多语言表结构支持菜单和字典国际化
- 制定硬编码消息迁移策略和实施计划
- 建立多语言工作量评估和风险应对措施
2026-06-29 10:04:06 +08:00
dd9f1cae5a feat(i18n): 添加国际化(i18n)基础设施和多语言支持
- 新增 I18nUtils 工具类提供多语言消息获取功能
- 创建多语言技术方案设计文档 MULTILANG_I18N_DESIGN.md
- 编写国际化战略文章 HEALTHLINK_HIS_INTERNATIONALIZATION_STRATEGY.md
- 添加国际化战略概述文档 HEALTHLINK_HIS_INTL_STRATEGY.md
- 实现基于 MessageSource 的多语言消息处理机制
- 设计支持中英越三语的国际化架构方案
- 规划前端 vue-i18n 和后端 MessageSource 集成方案
- 定义数据库多语言表结构支持菜单和字典国际化
- 制定硬编码消息迁移策略和实施计划
- 建立多语言工作量评估和风险应对措施
2026-06-29 06:10:03 +08:00
9081f1cfeb Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	healthlink-his-ui/src/views/inpatientDoctor/home/components/diagnosis/chineseMedicineDialog.vue
#	healthlink-his-ui/src/views/inpatientDoctor/home/components/diagnosis/diagnosis.vue
2026-06-28 07:04:03 +08:00
27273dbb57 feat(i18n): 添加国际化(i18n)基础设施和多语言支持
- 新增 I18nUtils 工具类提供多语言消息获取功能
- 创建多语言技术方案设计文档 MULTILANG_I18N_DESIGN.md
- 编写国际化战略文章 HEALTHLINK_HIS_INTERNATIONALIZATION_STRATEGY.md
- 添加国际化战略概述文档 HEALTHLINK_HIS_INTL_STRATEGY.md
- 实现基于 MessageSource 的多语言消息处理机制
- 设计支持中英越三语的国际化架构方案
- 规划前端 vue-i18n 和后端 MessageSource 集成方案
- 定义数据库多语言表结构支持菜单和字典国际化
- 制定硬编码消息迁移策略和实施计划
- 建立多语言工作量评估和风险应对措施
2026-06-28 07:01:58 +08:00
83f340b6bb feat(i18n): 实现门诊增强和门诊财务国际化功能
- 在门诊增强页面添加表格列的国际化标签
- 在门诊增强页面添加操作按钮的国际化文本
- 在门诊财务日结结算页面实现表单字段的国际化
- 在门诊财务日结结算页面实现表格列标题的国际化
- 在门诊财务日结结算页面添加操作按钮的国际化
- 集成 vue-i18n 并在组件中使用国际化方法
- 更新日结详情提示消息为国际化文本
- 实现导出文件名和成功消息的国际化
2026-06-28 06:58:53 +08:00
24d2e482c7 feat(i18n): 实现门诊增强和门诊财务国际化功能
- 在门诊增强页面添加表格列的国际化标签
- 在门诊增强页面添加操作按钮的国际化文本
- 在门诊财务日结结算页面实现表单字段的国际化
- 在门诊财务日结结算页面实现表格列标题的国际化
- 在门诊财务日结结算页面添加操作按钮的国际化
- 集成 vue-i18n 并在组件中使用国际化方法
- 更新日结详情提示消息为国际化文本
- 实现导出文件名和成功消息的国际化
2026-06-28 06:56:04 +08:00
wangjian963
275a76c2d7 820 【住院护士站-医嘱管理】“文字型”医嘱在护士站“医嘱校对”及“医嘱执行”页面不显示医嘱内容(内容为空白 2026-06-26 17:46:30 +08:00
wangjian963
12d53eb6b8 843 【门诊收费-收费项目】待收费患者的收费明细列表混入“已收费”项目,且错误计入合计金额 2026-06-26 16:59:54 +08:00
wangjian963
659ccab18b Merge remote-tracking branch 'origin/develop' into develop 2026-06-26 16:56:39 +08:00
Ranyunqiao
a9de9ee822 bug 628 804 806 818 2026-06-26 16:55:52 +08:00
wangjian963
bbe9bd7ef5 830 【收费工作站-住院登记】选择一名患者进行登记时入院病区下拉框无数据回显
819 【 门诊收费工作站】打开收费详情查询会出现报错:No static resource payment/bill/page for request '/healthlink-his/payment/bill/page'.
2026-06-26 16:38:35 +08:00
b278ad92b2 feat(i18n): 实现门诊增强和门诊财务国际化功能
- 在门诊增强页面添加表格列的国际化标签
- 在门诊增强页面添加操作按钮的国际化文本
- 在门诊财务日结结算页面实现表单字段的国际化
- 在门诊财务日结结算页面实现表格列标题的国际化
- 在门诊财务日结结算页面添加操作按钮的国际化
- 集成 vue-i18n 并在组件中使用国际化方法
- 更新日结详情提示消息为国际化文本
- 实现导出文件名和成功消息的国际化
2026-06-26 16:19:53 +08:00
24dc16b8d1 refactor(ybmock): 重构医保模拟接口并更新国际化配置
- 将医保模拟接口从通用路由改为具体功能路由
- 新增签到、取消门诊登记、预结算等功能接口
- 统一返回格式为 code/message/result 结构
- 移除旧版医保接口路由兼容处理
- 更新前端国际化配置文件中的医保相关词条
- 删除重复的无数据提示词条并补充新的字段翻译
- 移除药房模块独立词条合并至通用配置中
- 新增住院管理模块的完整国际化词条配置
2026-06-26 16:06:15 +08:00
284c2d7956 Merge remote-tracking branch 'origin/develop' into develop 2026-06-26 16:05:00 +08:00
70844b07ef feat(i18n): migrate drug, medicineStorage, pharmacystockalert modules to vue-i18n (402+ keys) 2026-06-26 15:05:07 +08:00
wangjian963
a71d818ffe 831
【住院管理-住院护士增强】打开TPR表会有报错信息:Incorrect result size: expected 1, actual 0
832 【住院护士站-住院记账】在科下患者的划价确费下的患者医嘱列表的选择了项目批量撤销,但还显示请先选择要撤销的划价项目
2026-06-26 14:23:14 +08:00
9650cc4d84 feat(bodyStructure): 实现身体部位管理页面国际化支持
- 将新增、删除、导出、刷新等按钮文本替换为国际化标签
- 将表格列标题如部位名称、拼音、五笔拼音等替换为国际化标签
- 将表单输入框占位符和标签替换为国际化标签
- 添加vue-i18n依赖并配置国际化函数
- 将验证规则中的提示消息替换为国际化消息
- 将操作成功提示消息替换为国际化消息
- 将页面标题如添加身体部位、编辑部位等替换为国际化标签
2026-06-26 13:03:13 +08:00
8f20634b46 feat(i18n): 实现病例模板统计模块国际化功能
- 将病例模板统计相关界面文本替换为国际化标签
- 添加 vue-i18n 依赖并配置翻译函数
- 实现表单验证消息的国际化显示
- 将按钮、表格列标题等界面元素转换为多语言支持
- 重构表单验证规则以支持动态国际化消息
- 更新常用诊断、耗材绑定等其他模块的国际化内容
2026-06-26 13:02:51 +08:00
1d4c168787 Merge remote-tracking branch 'origin/develop' into develop 2026-06-26 13:00:28 +08:00
wangjian963
a679fc1700 fix(ui): 修复剩余 TS strict 编译错误及类型定义
- EditableTable.d.ts: fixed 类型调整,新增 extraprops
  - FormItem.d.ts: 新增 disabled、onClick 属性
  - EditableTable/Form/FormItem/FormLayout: 添加参数类型注解
  - DataDashboard: screenData 类型修正 + 隐式 any 修复
  - api/datacollection: 新增 index.d.ts 声明文件
  - patientList/receipt: 补充缺失函数声明
2026-06-26 12:10:03 +08:00
Ranyunqiao
3236375154 bug 785 799 800 2026-06-26 11:49:52 +08:00
wangjian963
8eb2c1e0e2 fix(ui): 修复 TypeScript strict 编译错误及运行时 Array.join 崩溃
- 修复 console.error 包装器: String() 包裹 + try-catch 防止浏览器原生格式化崩溃
  - 修复 empienhanced/merge 模板中 && → &&
  - 修复 bedAllocation: ChangeBedDialog 组件缺失导致 patchAttr 渲染崩溃
  - 修复 inOut 组件: 添加隐式 any 类型注解, 修正 OptionItem 接口定义
  - 新增 api.d.ts: api.js 的 TypeScript 类型声明
2026-06-26 11:42:55 +08:00
e035a137d1 feat(i18n): merge pending translations, add missing UI terms, migrate features pages, fix defineProps error 2026-06-26 10:48:41 +08:00
f5c6007c37 i18n(ui): 国际化界面文本替换
- 替换费用配置页面的所有静态文本为国际化标签
- 替换组织机构管理页面的表单标签和按钮文本
- 替换病房管理页面的列标题和操作按钮
- 替换设备对照对话框的标题和占位符文本
- 替换诊断治疗对照对话框的标题和字段标签
- 替换CDSS告警页面的消息提示文本
- 在相关组件中引入vue-i18n并创建翻译实例
2026-06-26 09:21:39 +08:00
905d9c7ffc i18n(ui): 国际化界面文本替换
- 替换费用配置页面的所有静态文本为国际化标签
- 替换组织机构管理页面的表单标签和按钮文本
- 替换病房管理页面的列标题和操作按钮
- 替换设备对照对话框的标题和占位符文本
- 替换诊断治疗对照对话框的标题和字段标签
- 替换CDSS告警页面的消息提示文本
- 在相关组件中引入vue-i18n并创建翻译实例
2026-06-26 09:06:46 +08:00
2e1112b902 feat(i18n): 实现国际化支持并优化代码结构
- 在i18n模块中实现懒加载本地化配置,限制加载指定语言文件
- 为床位管理、合同管理、客户管理等界面组件添加国际化标签和消息
- 集成vue-i18n在多个组件中添加翻译功能和多语言支持
- 更新CDSS告警和规则管理界面以支持多语言显示
- 优化store模块导入结构,添加pinia依赖注入
- 实现表单验证消息和操作提示的国际化处理
2026-06-26 09:04:11 +08:00
11f1263157 Merge remote-tracking branch 'origin/develop' into develop 2026-06-26 08:58:35 +08:00
2abf38e14d feat(i18n): zero Chinese remaining in enUS/viVN locales + backend error msg translation + dict auto-translate 2026-06-25 22:53:51 +08:00
4e2e11292f feat(i18n): translate backend error messages, dict labels auto-translate, add 150+ medical dict terms 2026-06-25 21:15:44 +08:00
7c7b02225d feat(i18n): add department+table header translations, fix duplicate key error, translate system title 2026-06-25 20:59:26 +08:00
wangjian963
ea9acac589 778 【门诊医生站-检验】点击选中行检验申请单,下方“申请单”表单和项目选择区域未回显/绑定对应数据 2026-06-25 17:56:03 +08:00
wangjian963
d786b2595a Merge remote-tracking branch 'origin/develop' into develop 2026-06-25 17:13:01 +08:00
wangjian963
6925b93f73 767 【门诊医生工作站-检验】申请单下的就诊卡号无法填写 2026-06-25 17:12:33 +08:00
2c6a2bef33 Merge remote-tracking branch 'origin/develop' into develop 2026-06-25 16:46:41 +08:00
8d5871ca39 feat(i18n): translate system title, tenant name, shorten English translation, add tooltip 2026-06-25 16:36:18 +08:00
aa011c3721 feat(i18n): fix menu auto-translation fallback + expand dictionary with 200+ menu terms 2026-06-25 16:12:28 +08:00
05a59f2884 feat(i18n): add offline auto-translate plugin with 200+ common medical terms dictionary 2026-06-25 16:02:35 +08:00
d8c5269ab9 feat(i18n): complete all 475 menu mappings - 100% coverage 2026-06-25 15:32:25 +08:00
9c06666e5b feat(i18n): complete all 639 menu mappings from database + add nav translations 2026-06-25 15:30:56 +08:00
644 changed files with 55466 additions and 17891 deletions

5
.claude/settings.json Normal file
View File

@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"agent-sdk-dev@claude-plugins-official": true
}
}

View File

@@ -0,0 +1,356 @@
# HealthLink-HIS 国际化启航:从广西走向世界,搭建中越医疗信息化的数字桥梁
> **上海经创贺联信息科技有限公司**
> 文档类型: 公众号软文 / 品牌宣传
> 版本: V1.0
> 日期: 2026-06-25
---
## 引言:一条边境线上的医疗数字化机遇
中国广西与越南山水相连,边境线长达 2722 公里,两国人员往来频繁,跨境医疗合作日益深化。
随着 RCEP 全面生效、中国—东盟自贸区 3.0 版谈判深入推进,以及"一带一路"倡议在东南亚的持续落地,**广西正成为中国医疗信息化企业走向东盟的前沿阵地**。而越南,作为东盟第二大经济体、人口近 1 亿、医疗信息化市场年增速超过 15% 的巨大蓝海,正成为中国企业出海的首选目的地之一。
**但现实是残酷的:** 越南大多数基层医院仍在使用 20 年前的老旧系统,甚至完全没有 HIS 系统。这些医院急需一套**功能完整、价格透明、支持多语言、能快速部署**的现代化医院信息系统——而这,正是 HealthLink-HIS 能够提供的。
---
## 一、HealthLink-HIS 是什么?
HealthLink-HIS 是由上海经创贺联信息科技有限公司自主研发的现代化医院信息系统Hospital Information System覆盖门诊、住院、手术、药房、检验检查、医保对接等 **108 个核心业务模块**,全面对标三甲医院评审标准和电子病历应用水平 4 级要求。
### 关键数据
| 维度 | 数据 | 说明 |
|------|------|------|
| 代码提交 | **2,265 次** | 40+ 工程师密集迭代 |
| 新增功能 | **111 项** | 覆盖全业务场景 |
| Bug 修复 | **1,400+** | 系统稳定性持续打磨 |
| 业务模块 | **108 个** | 14 大业务域全覆盖 |
| 数据库表 | **181 张** | 全业务域数据模型 |
| 后端接口 | **230 个** | 统一接口规范 |
| 前端页面 | **209 个** | 统一操作体验 |
**一句话总结**:这不是一套 PPT 产品,是一套经过 1,400+ 个 Bug 修复打磨、已在多家医院上线运行的实战系统。
---
## 二、为什么选择 HealthLink-HIS
### 2.1 技术架构:走在行业前面
| 技术维度 | HealthLink-HIS | 行业主流 | 优势 |
|---------|:-------------:|:--------:|------|
| 后端框架 | **Spring Boot 4.0.6** | 2.x/3.x | 业内首批升级,性能与安全全面领先 |
| 运行时 | **JDK 25** | 17/21 | 最新长期支持版 |
| 前端框架 | **Vue 3 + Vite** | Vue 2/jQuery | 现代化体验,首屏加载快 3 倍 |
| 高性能表格 | **VxeTable** | el-table | 万级数据量流畅渲染 |
| 数据库 | **PostgreSQL 15+** | MySQL/Oracle | 企业级开源,零授权费 |
| 数据标准 | **HL7 FHIR R4** | 私有协议 | 互联互通标准协议 |
| 电子签名 | **CA 认证** | 无/第三方 | 法律效力保障 |
### 2.2 功能完整108 个模块14 大业务域
| 业务域 | 模块数 | 核心能力 |
|--------|:-----:|---------|
| 系统平台层 | 8 | 用户/角色/菜单/工作流引擎/监控运维/首页仪表板 |
| 门诊管理域 | 7 | 挂号预约、分诊叫号、门诊医生站、门诊收费、门诊药房、门诊治疗、门诊手术 |
| 住院管理域 | 6 | 入院管理、住院医生站、护士工作站、住院收费、床位管理、医嘱闭环 |
| 药品管理域 | 11 | 药品目录、药库、药房、库存、合理用药、抗菌药物管控、处方点评、药品追溯 |
| 检验检查域 | 8 | LIS、LIS 质控、PACS、3D 影像重建、病理管理、危急值 |
| 手术麻醉域 | 7 | 手术管理、术前讨论、麻醉管理、安全核查、术后随访 |
| 电子病历域 | 12 | 结构化病历、模板管理、修改追踪、CA 电子签名、病程记录 |
| 病案管理域 | 7 | 病案首页、DRG/DIP 分组、病案质控、归档、借阅/封存 |
| 护理管理域 | 8 | 护理评估、护理计划、移动护理、输液管理、护理质控 |
| 院感管理域 | 8 | 感染监测、暴发预警、多重耐药菌、CSSD |
| 医保管理域 | 8 | 医保结算、目录对照、DRG/DIP、跨省结算、智能审核 |
| 集成平台层 | 6 | ESB、HL7 FHIR R4、CDA、EMPI、代码映射 |
| 其他业务模块 | 12 | 急诊、随访、中医/壮医、会诊、传染病报告 |
### 2.3 灵活部署:适配各种基础设施条件
| 部署方式 | 适用场景 | 特点 |
|---------|---------|------|
| **私有化部署** | 有自建机房的医院 | 数据完全自主可控 |
| **混合云部署** | 兼顾安全与弹性 | 核心数据院内存储,非核心业务上云 |
| **SaaS 托管** | 基层医疗机构 | 零运维、按年付费、快速上线 |
| **信创环境部署** | 有信创要求的公立医院 | 适配国产全栈 |
---
## 三、国际化战略English + Vietnamese
### 3.1 为什么要做国际化?
**市场机遇:**
1. **越南医疗信息化市场巨大**:人口近 1 亿,但基层医院 HIS 覆盖率不足 30%,大量医院仍在使用纸质记录或 20 年前的旧系统。
2. **广西—越南跨境医疗合作深化**:凭祥、东兴、水口等口岸城市跨境医疗需求持续增长,双语/多语系统成为刚需。
3. **RCEP 带来制度红利**:区域内贸易壁垒降低,中国医疗 IT 企业出海迎来政策窗口期。
4. **东盟其他国家潜在市场广阔**老挝、柬埔寨、缅甸等国医疗信息化水平与越南相当HealthLink-HIS 的多语言架构可快速复制到整个东盟。
**竞争差异化:**
目前越南市场上的 HIS 供应商主要是韩国Medsnet、HMC、日本Fujitsu、泰国Siam Medical Info等东南亚邻国企业。**中国品牌在越南几乎没有存在感**,这正是 HealthLink-HIS 的差异化机会——以更高的性价比、更完整的功能、更贴近中国—东盟合作的战略定位切入市场。
### 3.2 多语言架构设计
HealthLink-HIS 的多语言i18n架构从设计之初就考虑了全球化需求目前已支持 **简体中文、英语、越南语** 三种语言:
#### 三层多语言体系
```
┌─────────────────────────────────────────────────────┐
│ 语言选择器(全局切换) │
│ Cookie / Session 存储当前语言偏好 │
└──────────────────────┬──────────────────────────────┘
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ zh_CN │ │ en_US │ │ vi_VN │
│ 简体中文 │ │ English │ │ Tiếng Việt│
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
┌────┴─────────────┴────────────┴────┐
│ │
┌──┴──┐ ┌───┴───┐
│前端 i18n│ │后端 i18n│
│vue-i18n│ │MessageSource│
└──┬───┘ └───┬───┘
│ │
JSON 语言包 Properties 资源文件
(src/locales/) (i18n/messages_*.properties)
│ │
└──────────┬────────────────────────────┘
┌─────────────────────┐
│ 数据库多语言 │
│ sys_menu_i18n │
│ sys_dict_data_i18n │
└─────────────────────┘
```
#### 前端多语言
- **技术选型**vue-i18n v11Composition APIElement Plus 动态语言包切换
- **语言包结构**
- `nav.*` — 导航菜单标签
- `common.*` — 按钮、标签、通用消息
- `login.*` — 登录页面
- `dict.*` — 字典值(性别、状态等)
- `module.*` — 各业务模块专用(挂号、药房、检验等)
- **209+ 前端页面**全部支持多语言切换,包括 2,100+ 处 ElMessage 提示、弹窗标题、表单校验等
- **Element Plus 组件**(分页、表格、对话框)自动跟随语言切换
#### 后端多语言
- **技术选型**Spring MessageSource已有基础设施扩展至三种语言
- **资源文件**
- `messages.properties` — 默认英文 fallback
- `messages_zh_CN.properties` — 中文
- `messages_en_US.properties` — 英文
- `messages_vi_VN.properties` — 越南语
- **850+ 处硬编码中文消息**全部迁移至 MessageUtils.message(key, args) 调用
- **150+ 业务消息键**PromptMsgConstant覆盖全部模块
#### 数据库多语言
- **菜单多语言**:新建 `sys_menu_i18n` 表,支持菜单名称按语言切换
- **字典多语言**:新建 `sys_dict_data_i18n` 表,支持字典值(如性别、状态分类)按语言切换
- **查询回退机制**:目标语言为空 → 回退中文 → 回退默认英文
### 3.3 多语言管理后台
系统内置多语言字典管理界面,管理员可直接在 Web 界面上编辑和翻译菜单名称、字典值,无需修改代码或配置文件:
- 每个字典项支持中/英/越三种语言的独立录入
- 支持批量导入/导出翻译
- 翻译缺失时自动回退到中文显示
---
## 四、广西—越南:我们的战略支点
### 4.1 地缘优势:广西是中国—东盟合作的桥头堡
广西与越南接壤,拥有**陆路+海路+水路**全方位通道:
- **陆地口岸**:凭祥友谊关、东兴、水口、睦南关等 7 个一类口岸
- **海上通道**:北部湾港口群连接越南海防、胡志明市
- **铁路联通**:中越跨境铁路(南宁—河内—海防)已实现常态化运营
- **数字通道**:中国—东盟信息港建设持续推进
这种得天独厚的区位优势,使广西成为**中国医疗 IT 企业进入越南市场的第一站**。
### 4.2 政策支持
| 政策 | 要点 | 对 HealthLink-HIS 的意义 |
|------|------|----------------------|
| **中国—东盟自贸区 3.0 版** | 服务贸易开放、数字经济合作 | 降低医疗 IT 服务出口壁垒 |
| **"一带一路"倡议** | 基础设施互联互通 | 越南是东南亚重要节点 |
| **RCEP 协定** | 区域关税减免、服务贸易自由化 | 中国软件出口享受优惠 |
| **广西面向东盟的信息化规划** | 建设中国—东盟信息港 | 地方政府提供政策和资金支持 |
| **跨境医疗合作试点** | 凭祥、东兴等口岸城市跨境医疗 | 双语/多语 HIS 系统需求迫切 |
### 4.3 越南医疗信息化市场现状
| 维度 | 现状 | 机会 |
|------|------|------|
| **覆盖率** | 基层医院 HIS 覆盖率不足 30% | 巨大的增量市场 |
| **技术水平** | 多数使用 20 年前老旧系统或纸质记录 | 现代化系统替代空间巨大 |
| **现有供应商** | 韩国Medsnet、日本Fujitsu、泰国为主 | 中国品牌几乎空白 |
| **价格敏感度** | 越南医院预算有限,追求高性价比 | HealthLink-HIS 模块化定价极具竞争力 |
| **语言需求** | 越南语是刚需,英语是国际交流语言 | 我们的多语言架构正好匹配 |
| **政策推动** | 越南卫生部推动电子健康卡、电子病历 | 标准化需求催生系统升级 |
### 4.4 我们的越南市场策略
**第一阶段2026 H2试点突破**
- 聚焦广西边境口岸城市(凭祥、东兴)的跨境医疗合作
- 与 1-2 家越南边境省份医院建立试点合作
- 完成越南语版本的本地化适配和测试
**第二阶段2027区域扩张**
- 以越南为核心,辐射老挝、柬埔寨、缅甸
- 建立越南语技术支持团队
- 与越南当地系统集成商建立合作伙伴关系
**第三阶段2028+):东盟全面布局**
- 覆盖东盟 10 国主要市场
- 在胡志明市或河内设立本地办事处
- 支持更多东南亚语言(泰语、印尼语、马来语)
---
## 五、越南市场适配:不只是翻译
### 5.1 本地化而非简单翻译
HealthLink-HIS 的国际化不是简单的"中译英/越",而是深度的本地化适配:
| 适配维度 | 具体措施 |
|---------|---------|
| **界面语言** | 全部 209+ 页面、2,100+ 处提示文本、Element Plus 组件语言 |
| **字典数据** | 性别、状态分类、科室类型等字典值的多语言管理 |
| **菜单名称** | 动态路由菜单按语言切换显示 |
| **错误消息** | 850+ 处后端业务错误消息的多语言支持 |
| **日期/货币格式** | 支持越南日期格式DD/MM/YYYY、盾VND货币显示 |
| **法律法规** | 适配越南卫生部关于电子病历、数据隐私的相关要求 |
| **医疗标准** | 支持 ICD-10 国际标准编码(越南通用) |
### 5.2 越南版特色功能规划
针对越南市场需求,我们计划推出以下特色功能:
1. **越南语电子病历模板**:符合越南卫生部标准的病历模板体系
2. **越南医保对接**:适配越南 BHXH社会保障局的医保结算接口
3. **跨境患者管理**:支持中越双语患者档案,方便跨境就医
4. **离线模式**:针对越南部分地区网络不稳定场景,支持断网续传
5. **移动端越南语**:小程序/移动端完整越南语支持
---
## 六、价格优势:为什么越南医院会选择我们?
### 6.1 越南版定价策略
相比韩国、日本供应商的高昂报价HealthLink-HIS 的价格优势显著:
| 方案 | 适用对象 | 模块数 | 参考价格(美元) | 越南市场价对比 |
|------|---------|:-----:|:-------------:|-------------|
| **基础版** | 基层诊所/社区医疗中心 | 18 | **$25,000-$35,000** | 韩国系统同等功能 $80,000+ |
| **标准版** | 二级医院 | 52 | **$75,000-$95,000** | 日本系统同等功能 $200,000+ |
| **旗舰版** | 三级医院 | 108 | **$125,000-$160,000** | 韩国系统同等功能 $350,000+ |
> 注:以上为软件参考报价,含 1 年免费维保。实施、培训、接口对接按实际工作量计费。
### 6.2 越南客户最关心的三个问题
**Q1系统稳定吗会不会出问题找不到人**
A我们提供 7×24 小时远程支持,重大问题 2 小时内响应。在越南市场,我们将建立本地技术团队,提供越南语技术支持。
**Q2上线周期多久会不会影响医院正常运营**
A标准版实施周期 3-5 个月。我们采用新旧系统并行方案,确保切换过程不影响日常诊疗。
**Q3以后想加新功能怎么办**
A108 个模块按需选配,每个模块明码标价。需要新增功能,按 1,500 元/人天的标准灵活定制开发。
---
## 七、技术实力:值得信赖的合作伙伴
### 7.1 工程质量
- **2,265 次代码提交**40+ 工程师参与开发
- **1,400+ Bug 修复**,系统稳定性持续打磨
- **Flyway 数据库迁移管理**,所有变更版本化、可追溯
- **Playwright E2E 自动化测试**,覆盖核心业务流程
- **ESLint + Husky 构建门禁**,提交前自动检查
### 7.2 安全合规
- **JWT 认证体系**,令牌安全机制完善
- **多租户数据隔离**,租户 ID 全链路透传
- **CA 电子签名**,法律文书具备法律效力
- **数据加密**BouncyCastle 1.80 加密库
- **操作审计**,登录日志、操作日志全量记录
### 7.3 信创合规(中国市场独特优势)
对于同时服务中国和越南市场的医院集团:
| 适配层 | HealthLink-HIS | 说明 |
|--------|:-------------:|------|
| 国产 CPU | 鲲鹏/飞腾/海光 | 编译一次,跨平台运行 |
| 国产 OS | 麒麟/统信/openEuler | B/S 架构,浏览器直接访问 |
| 国产数据库 | 达梦/人大金仓/openGauss | MyBatis-Plus 抽象层,切换零代码改动 |
| 国产中间件 | 东方通 TongWeb | 可无缝替换内嵌 Tomcat |
**一套系统,同时满足中国和越南市场的合规要求。**
---
## 八、我们的愿景
> **让每一家医院,无论在中国还是在越南,都能用上功能完整、价格透明、稳定可靠的现代化医院信息系统。**
HealthLink-HIS 的国际化,不是简单的产品出口,而是**中国医疗信息化经验的输出**。过去几年,我们在国内积累了大量医院实施经验,覆盖了从一级医院到三级医院的各种规模和复杂度场景。现在,我们把这些经验带到越南、带到东盟,帮助更多医疗机构实现数字化转型。
**我们相信:**
- 医疗信息化不应是少数大医院的专利,基层医疗机构同样需要好的系统
- 技术没有国界,好的系统应该让全世界的医护人员都能受益
- 中国—东盟合作不仅是经贸往来,更是民生领域的深度合作
- 一套好的 HIS 系统,能让医生专注于看病,让护士高效完成护理,让管理者实时掌握运营
---
## 联系我们
> **上海经创贺联信息科技有限公司**
>
> - 销售热线18017857330
> - 邮箱chen.qi@jin-group.cn
> - 官网www.health-link.com.cn
> - 地址:上海市闵行区甬虹路 69 号虹桥绿谷广场 G 座 G 栋 505
>
> **免费远程演示,欢迎预约体验!**
>
> *无论是中文版、英文版还是越南版,我们都能为您提供量身定制的方案。*
---
*HealthLink-HIS — 让医疗信息化更简单、更可靠、更智能。*
*108 个业务模块 | 181+ 数据库表 | 230+ 控制器 | 209+ 前端页面 | 3 种语言支持*
*从广西出发,服务中国,走向东盟。*

View File

@@ -0,0 +1,338 @@
# 壮医+中医+西医一套HIS如何支撑"多医合一"的诊疗模式?
> **上海经创贺联信息科技有限公司**
---
在中国医疗体系中,有一个独特的现象:一位患者走进诊室,可能同时需要三种诊疗体系的服务。
广西的壮族群众可能习惯壮医调理,北京的患者可能在中医科抓中药,上海的医生可能在用西医方案做手术。**"中西医结合""壮汉医药并存"不是口号,而是中国医院每天都在发生的真实场景。**
但大多数HIS系统只支持一种诊疗体系。
**HealthLink-HIS从架构设计之初就考虑到了这一点——一套系统同时支撑中医、壮医、西医的融合诊疗。**
---
## 一、现实困境传统HIS的"单医思维"
### 1.1 西医HIS的局限
主流HIS系统以西医为基础架构从诊断到处方都围绕化学药和生物药设计
| 西医HIS的特点 | 局限 |
|-------------|------|
| 诊断ICD-10/ICD-11 | 不支持中医辨证论治的"证候"概念 |
| 处方:西药(化学药+生物药) | 不支持中药饮片、颗粒剂的煎煮/服用规则 |
| 医嘱频次qd/bid/tid | 不支持"水煎服,分早晚两次温服" |
| 病历SOAP格式 | 不支持"望闻问切"四诊记录 |
**结果:** 医院要上中医科或壮医科,只能另外采购一套系统。两套系统数据不通,患者信息要录两遍,病历要写两份。
### 1.2 中医HIS的短板
一些专门做中医信息化的厂商确实支持了中医诊断和中药处方,但往往缺少:
- 完整的门诊/住院业务流程
- 医保对接能力(中医特色门诊报销)
- 手术、检验、检查等西医核心模块
- 电子病历评级支撑
**结果:** 中医医院要么用西医HIS凑合要么用中医HIS但失去西医科室的支持。
### 1.3 多医并存的真实场景
一家综合医院的中医科,日常会遇到这样的场景:
> 一位65岁的女性患者因高血压长期服用西药氨氯地平同时因失眠和关节疼痛来看中医。中医师辨证为"肝肾阴虚、血瘀阻络",开具了包含枸杞、菊花、丹参的中药方剂。患者还做过一次壮医药浴调理。
在这个场景里,患者同时涉及**西医诊断高血压ICD编码、中医诊断肝肾阴虚证+血瘀证)、壮医治疗(药浴)**。如果用两套系统,医生要在西医病历里记高血压,在中医病历里记证候,在壮医记录里记药浴——同一个患者,三份病历,数据互不相通。
**这就是"多医融合"要解决的核心问题。**
---
## 二、HealthLink-HIS的多医融合方案
### 2.1 诊断体系:中西医并行
HealthLink-HIS在诊断层面实现了**西医诊断ICD与中医诊断病名+证候)的双轨制**
| 维度 | 西医诊断 | 中医诊断 |
|------|---------|---------|
| **病名** | ICD-10/ICD-11编码 | 中医疾病诊断(国标中医病名) |
| **证候** | 不适用 | 中医证候诊断(如"气虚血瘀证" |
| **壮医诊断** | 不适用 | 壮医病名+壮医证候 |
| **组号** | 主诊断/次诊断排序 | 中医证候组号 |
**核心设计:** 不另建诊断表,而是在现有诊断表中通过标识字段区分中西医,通过证候组号关联中医证候组。这样既保留了数据统一性,又支持了多体系诊断。
**临床价值:** 一份病历同时包含西医诊断和中医诊断。电子病历评级时系统可以自动提取中医主病、中医主证、西医诊断满足4级评审对"多诊断体系并存"的要求。
### 2.2 处方体系:中药 vs 西药
中药处方和西药处方在系统中有完全不同的管理逻辑:
| 特性 | 西药处方 | 中药处方 |
|------|---------|---------|
| **剂型** | 片剂、胶囊、注射液等 | 饮片、颗粒、丸剂、散剂等 |
| **单位** | mg、ml、片 | 克g |
| **用法** | 口服、静脉滴注、肌注 | 水煎服、冲服、外用 |
| **煎煮** | 不需要 | 先煎、后下、包煎、烊化 |
| **疗程** | 按天数 | 按"剂"(一剂一煎) |
| **医保** | 医保目录编码 | 中医特色门诊+民族药编码 |
HealthLink-HIS的中药处方支持
- **中医方剂库**:经典方剂(如六味地黄丸、桂枝汤)作为模板,医生可直接调用
- **饮片管理**:支持中药饮片的库存、计价、发药全流程
- **煎煮规则**:记录先煎、后下等特殊煎煮要求
- **颗粒剂支持**:支持中药配方颗粒的处方和计费
**十八反十九畏:** 开中药处方时,系统自动检查"十八反""十九畏"配伍禁忌。比如医生同时开了"甘草"和"甘遂",系统会弹出警示——这是西医处方系统永远做不到的。
### 2.3 体质辨识:从"千人一方"到"一人一方"
中医讲究"辨证施治"而体质辨识是辨证的基础。HealthLink-HIS内置了**中医体质辨识**模块,基于国标《中医体质分类与判定》标准:
| 体质类型 | 特征 | 调理建议 |
|---------|------|---------|
| 平和质 | 体态适中、面色红润 | 保持良好生活习惯 |
| 气虚质 | 气短懒言、容易出汗 | 益气健脾 |
| 阳虚质 | 手脚发凉、畏寒怕冷 | 温阳补肾 |
| 阴虚质 | 手足心热、口干咽燥 | 滋阴清热 |
| 痰湿质 | 形体肥胖、腹部肥满 | 健脾利湿 |
| 湿热质 | 面垢油光、易生痤疮 | 清利湿热 |
| 血瘀质 | 肤色晦暗、舌质紫暗 | 活血化瘀 |
| 气郁质 | 忧郁脆弱、人情郁闷 | 疏肝解郁 |
| 特禀质 | 过敏体质、易起荨麻疹 | 益气固表 |
**应用场景:**
- 门诊医生站在开具处方前,可先进行体质辨识
- 辨识结果自动关联处方,辅助用药选择
- 体质数据纳入患者健康档案,支持长期追踪
**长期价值:** 体质不是一成不变的。一个痰湿质的患者,经过一段时间调理后可能变为平和质。体质数据的长期积累,为中医临床科研和疗效评估提供了结构化数据基础。
### 2.4 医保对接:中医特色门诊报销
2023年以来全国多地已将中医特色门诊纳入医保报销范围。HealthLink-HIS在医保模块中专门适配
| 医保字段 | 说明 | HealthLink-HIS支持 |
|---------|------|------------------|
| 中药用法 | 中药用法(水煎内服/外用/其他) | 自动映射 |
| 中药饮片另付标识 | 中药饮片是否单独标识 | 医保结算时自动标识 |
| 民族药编码 | 壮药、瑶药等特殊药品目录 | 支持104类民族药分类 |
| 中医特色门诊 | 医保分类码 | 已接入医保枚举 |
**实际价值:** 患者看中医/壮医时,系统自动按医保规则分类计费,无需手动选择,减少收费差错。
---
## 三、广西特色:壮医诊疗的信息化支撑
### 3.1 壮医的独特性
壮医是壮族人民的传统医学体系,与中医有渊源但也有明显区别:
| 对比项 | 中医 | 壮医 |
|--------|------|------|
| **理论基础** | 阴阳五行、脏腑经络 | 三道两路、龙蛇文化 |
| **诊断方法** | 望闻问切 | 目视、手摸、耳听 |
| **治疗手段** | 针灸、推拿、中药 | 药浴、挑治、刮痧、灸疗 |
| **药材特色** | 中草药 | 壮药(如田七、鸡血藤) |
| **证候体系** | 八纲辨证、脏腑辨证 | 虚实、冷热、气血 |
壮医的"三道两路"理论认为人体有"上中下三道"(气道、水道、谷道)和"左右两路"(龙路、火路),疾病的发生是因为三道两路不畅。这与中医的经络学说有相似之处,但理论体系和治疗方法完全不同。
### 3.2 壮医诊疗的信息化
| 壮医要素 | 系统实现 |
|---------|---------|
| **壮医病名** | 在诊断体系中扩展 `diagnosis_type`,支持"壮医病名"类型 |
| **壮医药材** | 药品字典支持民族药分类,壮药独立编码 |
| **壮医技法** | 在医嘱体系中新增壮医治疗项目(药浴、挑治、刮痧等) |
| **壮医体质** | 体质辨识模块预留壮医体质分型扩展字段 |
### 3.3 地方医保对接
广西作为壮族自治区,有独特的医保政策:
- **壮瑶医药纳入医保**:广西已将壮药、瑶药纳入医保报销目录
- **壮医诊疗项目报销**:壮医特色疗法(如药浴、针刀)可报销
- **县级医共体数据互通**:壮族聚居县的医共体需要上下级数据共享
HealthLink-HIS已在系统设计层面预留了这些对接能力。
### 3.4 壮医在更大范围的价值
壮医的价值不仅限于广西。随着国家对少数民族医药的重视,壮医正走出广西:
- **粤港澳大湾区**:壮瑶医药在港澳地区有深厚群众基础
- **东南亚**:壮药与越南、老挝的传统医药有同源关系,具备出海潜力
- **科研合作**:壮医"三道两路"理论与现代医学的肠道微生态、淋巴循环等研究方向存在交叉
一套支持壮医的HIS系统不仅是地方医院的刚需也可能成为医院面向区域乃至国际合作的信息化底座。
---
## 四、全链路数据流转:从诊断到处方
### 4.1 门诊中医诊疗流程
```
患者就诊
① 医生站:西医诊断 + 中医诊断(病名+证候)
② 体质辨识:系统推荐或手动评估体质类型
③ 开具处方:
- 西药处方 → 西药药房发药
- 中药处方 → 中药房 → 煎煮 → 发药
④ 合理用药审查:
- 西药:配伍禁忌、剂量超限
- 中药:十八反、十九畏
⑤ 医保结算:自动识别中医/民族药报销比例
⑥ 病历归档:中西医诊断均写入病案首页
```
### 4.2 中西医结合的真实场景
回到前面那位65岁女性患者的例子在HealthLink-HIS中的完整流转
1. **挂号**患者持社保卡挂号系统自动识别既往病史高血压3年
2. **西医诊断**医生录入ICD编码I10 原发性高血压)
3. **中医就诊**:患者主诉失眠、关节痛,中医师四诊后录入中医病名(不寐+痹症)和证候(肝肾阴虚+血瘀阻络)
4. **体质辨识**:系统根据问卷判定为"阴虚质"评分72分
5. **开具处方**
- 西药处方:氨氯地平 5mg qd系统检查与既往用药一致
- 中药处方枸杞15g、菊花10g、丹参15g、酸枣仁20g系统自动检查十八反无禁忌
- 壮医治疗:壮医药浴 1次系统自动归类民族药诊疗项目
6. **医保结算**:西药按高血压慢病报销,中药饮片按中医特色门诊报销,壮医药浴按民族医药项目报销,三种规则自动拆分
7. **病历归档**病案首页同时写入西医诊断、中医诊断、中医证候满足电子病历4级评审要求
**整个过程,患者只在一个系统中完成了一次就诊,医生只在一个界面中开具了三套方案的处方。**
---
## 五、多医融合的实际价值
### 5.1 对医院
| 痛点 | 传统方案 | HealthLink-HIS方案 |
|------|---------|-------------------|
| 中医科上线 | 另外采购中医HIS数据不通 | 一套系统,中医/西医/壮医统一 |
| 医保报销 | 手动分类,易出错 | 系统自动识别,按规则结算 |
| 电子病历评级 | 中医模块不达标 | 结构化中医病历支持4级 |
| 培训成本 | 两套系统,护士要学两次 | 统一操作界面,一次培训 |
### 5.2 对医生
- **一处录入,多处共享**:诊断信息在西医病历和中医病历中自动同步
- **处方智能辅助**:开中药时自动提示十八反十九畏,开西药时自动检查配伍禁忌
- **体质数据追踪**:同一患者的体质辨识结果随时间变化可追溯
### 5.3 对患者
- **少填一次信息**:不用在中医科和西医科分别填一遍基本信息
- **一张处方,统一缴费**:中药+西药一起结算,不用跑两趟收费处
- **医保少花钱**:系统自动按中医特色门诊规则报销,不遗漏可报销项目
### 5.4 对医保监管
多医融合不仅仅是方便医院,也对医保监管有重要价值:
- **费用透明**:中药、西药、民族药的费用在同一系统中记录,便于医保稽核
- **合理用药监测**:十八反十九畏审查、抗菌药物管控、处方点评,全部在系统内完成
- **数据上报**:中医诊疗人次、中药使用比例、民族医药服务量,自动统计上报卫健委
---
## 六、行业趋势:政策推动多医融合
### 6.1 国家政策
| 时间 | 政策 | 对HIS的影响 |
|------|------|-----------|
| 2017年 | 《中医药法》实施 | 中医诊疗项目纳入医保HIS需支持 |
| 2019年 | 《关于促进中医药传承创新发展的意见》 | 要求信息化支撑中医药发展 |
| 2021年 | 《"十四五"中医药发展规划》 | 中医医院信息化达标要求 |
| 2022年 | 《中医药振兴发展重大工程实施方案》 | 中医药数据互联互通 |
| 2024年 | 多地出台壮瑶医药管理条例 | 少数民族医药信息化需求增长 |
### 6.2 广西地方政策
- **《广西中医药条例》**:明确壮医、瑶医的法律地位,要求医疗机构提供民族医药服务
- **广西医保局**:将壮瑶医药诊疗项目纳入基本医疗保险支付范围
- **县域医共体**:要求县级中医院与乡镇卫生院数据互通,壮医特色服务下沉
### 6.3 电子病历评级的硬性要求
三甲医院电子病历评级必须达到4级4级的核心要求之一就是**多诊断体系支持**
| 4级要求 | 多医融合的关系 |
|---------|--------------|
| 全院信息共享 | 中医诊断与西医诊断在同一患者档案中共享 |
| 临床决策支持CDSS | 中药十八反、西药配伍禁忌统一审查 |
| 统一患者主索引EMPI | 同一患者在中医科和西医科的就诊记录关联 |
| 医嘱闭环管理 | 中药煎煮→发药→服用的全流程追踪 |
**不支持多医融合的HIS系统很难通过电子病历4级评审。**
---
## 七、选型建议如何判断HIS是否真支持多医融合
很多厂商号称"支持中医",但实际只是加了几个字典项。判断标准:
| 维度 | 真支持 | 假支持 |
|------|--------|--------|
| **诊断** | 中医病名+证候双轨,与西医诊断并存 | 只有中医诊断,没有证候 |
| **处方** | 中药饮片/颗粒剂独立管理,支持煎煮规则 | 中药当西药管,没有煎煮要求 |
| **医保** | 自动映射中医医保分类码 | 手动选择,容易错 |
| **质控** | 十八反十九畏审查 | 无中医质控 |
| **病历** | 结构化中医病历,支持四诊记录 | 中医病历=文本框 |
| **体质** | 体质辨识+调理建议 | 无体质辨识 |
| **民族药** | 壮药/瑶药独立编码 | 不支持 |
**HealthLink-HIS以上全部支持。**
---
## 结语
在中国,"中西医结合"不是选择题,而是必答题。
一套HIS系统如果只支持西医就无法满足中医医院的需求如果只支持中医就无法满足综合医院中医科的需求。**真正的多医融合,不是拼凑,而是在架构层面就设计好统一的数据模型和业务流程。**
HealthLink-HIS从第一天起就走在了这条路上
- **一套系统**:西医+中医+壮医,统一平台
- **一个数据模型**:诊断、处方、医嘱多轨并行
- **一次培训**:医生护士只用一套界面
- **一笔结算**:中西药、民族药统一医保报销
**HealthLink-HIS —— 让每一种医学传统,都能在数字化时代找到位置。**
---
## 联系我们
> **上海经创贺联信息科技有限公司**
>
> - 销售热线18017857330
> - 邮箱chen.qi@jin-group.cn
> - 官网www.health-link.com.cn
> - 地址上海市闵行区甬虹路69号虹桥绿谷广场G座G栋505
>
> **免费获取《中医/壮医HIS方案》欢迎联系**
---
*HealthLink-HIS — 多医融合,从架构开始。*
*108个业务模块 | 支持中医/壮医/西医三医合一 | 民族药医保自动对接*

View File

@@ -1 +0,0 @@
--sun-misc-unsafe-memory-access=allow

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.administration.domain.Device;
import com.healthlink.his.administration.domain.DeviceDefinition;
@@ -187,10 +188,10 @@ public class LisConfigManageAppServiceImpl implements ILisConfigManageAppServic
manageDto.getActivityDefDeviceDefs().size(),
manageDto.getActivityDefObservationDefs().size(),
manageDto.getActivityDefSpecimenDefs().size());
return R.ok("保存成功");
return R.ok(MessageUtils.message("msg.success"));
} catch (Exception e) {
log.error("保存检验项目设置失败id={}, error={}", manageDto.getId(), e.getMessage(), e);
return R.fail("保存失败:" + e.getMessage());
return R.fail(MessageUtils.message("his.lis.save_failed", e.getMessage()));
}
}

View File

@@ -98,16 +98,16 @@ public class ObservationManageAppServiceImpl implements IObservationManageAppSer
if (result) {
log.info("保存检验项目成功name={}, code={}, id={}",
Observation.getName(), Observation.getCode(), Observation.getId());
return R.ok("添加成功");
return R.ok(MessageUtils.message("msg.success"));
} else {
log.warn("保存检验项目失败name={}, code={}",
Observation.getName(), Observation.getCode());
return R.fail("添加失败:保存操作未成功");
return R.fail(MessageUtils.message("msg.failure"));
}
} catch (Exception e) {
log.error("保存检验项目异常name={}, code={}, error={}",
Observation.getName(), Observation.getCode(), e.getMessage(), e);
return R.fail("添加失败:" + e.getMessage());
return R.fail(MessageUtils.message("his.lis.add_failed", e.getMessage()));
}
}

View File

@@ -85,7 +85,7 @@ public class SpecimenManageAppServiceImpl implements ISpecimenManageAppService {
@Override
public R<?> updateOrAddSpecimen(SpecimenDefinition specimenDefinition) {
specimenDefinitionService.saveOrUpdate(specimenDefinition);
return R.ok(" 添加成功");
return R.ok(MessageUtils.message("msg.success"));
}
@Override

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.aidiagnosis.appservice.impl;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.aidiagnosis.domain.AiDiagnosisSuggestion;
import com.healthlink.his.aidiagnosis.service.IAiDiagnosisService;
import com.healthlink.his.web.aidiagnosis.appservice.IAiDiagnosisAppService;
@@ -27,10 +28,10 @@ public class AiDiagnosisAppServiceImpl implements IAiDiagnosisAppService {
@Override
public R<?> suggest(Long encounterId, Long patientId, String symptomText, String source) {
if (encounterId == null || patientId == null) {
return R.fail(400, "就诊ID和患者ID不能为空");
return R.fail(400, MessageUtils.message("his.ai.encounter_patient_required"));
}
if (symptomText == null || symptomText.trim().isEmpty()) {
return R.fail(400, "症状描述不能为空");
return R.fail(400, MessageUtils.message("his.ai.symptom_required"));
}
String suggestionText = generateSuggestion(symptomText);
@@ -61,7 +62,7 @@ public class AiDiagnosisAppServiceImpl implements IAiDiagnosisAppService {
@Override
public R<?> getHistory(Long patientId) {
if (patientId == null) {
return R.fail(400, "患者ID不能为空");
return R.fail(400, MessageUtils.message("his.ai.patient_id_required"));
}
List<AiDiagnosisSuggestion> history = aiDiagnosisService.findByPatientId(patientId);
return R.ok(history);
@@ -70,7 +71,7 @@ public class AiDiagnosisAppServiceImpl implements IAiDiagnosisAppService {
@Override
public R<?> getHistoryByEncounter(Long encounterId) {
if (encounterId == null) {
return R.fail(400, "就诊ID不能为空");
return R.fail(400, MessageUtils.message("his.ai.encounter_id_required"));
}
List<AiDiagnosisSuggestion> history = aiDiagnosisService.findByEncounterId(encounterId);
return R.ok(history);
@@ -79,15 +80,15 @@ public class AiDiagnosisAppServiceImpl implements IAiDiagnosisAppService {
@Override
public R<?> acceptSuggestion(Long id) {
if (id == null) {
return R.fail(400, "建议ID不能为空");
return R.fail(400, MessageUtils.message("his.ai.suggestion_id_required"));
}
AiDiagnosisSuggestion suggestion = aiDiagnosisService.getById(id);
if (suggestion == null) {
return R.fail(404, "建议不存在");
return R.fail(404, MessageUtils.message("his.ai.suggestion_not_found"));
}
suggestion.setAccepted(true);
aiDiagnosisService.updateById(suggestion);
return R.ok(null, "已采纳");
return R.ok(null, MessageUtils.message("his.ai.adopted"));
}
private String generateSuggestion(String symptomText) {

View File

@@ -4,6 +4,7 @@ import com.core.common.core.domain.R;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.appointmentmanage.domain.AppointmentConfig;
import com.healthlink.his.appointmentmanage.service.IAppointmentConfigService;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.web.appointmentmanage.appservice.IAppointmentConfigAppService;
import org.springframework.stereotype.Service;
@@ -26,7 +27,7 @@ public class AppointmentConfigAppServiceImpl implements IAppointmentConfigAppSer
// 获取当前登录用户的机构ID
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
if (tenantId == null) {
return R.fail("获取机构信息失败");
return R.fail(MessageUtils.message("his.appt_config.get_org_failed"));
}
AppointmentConfig config = appointmentConfigService.getConfigByTenantId(tenantId);
@@ -38,7 +39,7 @@ public class AppointmentConfigAppServiceImpl implements IAppointmentConfigAppSer
// 获取当前登录用户的机构ID
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
if (tenantId == null) {
return R.fail("获取机构信息失败");
return R.fail(MessageUtils.message("his.appt_config.get_org_failed"));
}
// 查询是否已存在配置

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.healthlink.his.appointmentmanage.domain.ClinicRoom;
import com.healthlink.his.appointmentmanage.service.IClinicRoomService;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.web.appointmentmanage.appservice.IClinicRoomAppService;
import org.springframework.stereotype.Service;
@@ -38,7 +39,7 @@ public class ClinicRoomAppServiceImpl implements IClinicRoomAppService {
public R<?> selectClinicRoomById(Long id) {
ClinicRoom clinicRoom = clinicRoomService.selectClinicRoomById(id);
if (clinicRoom == null) {
return R.fail(404, "诊室不存在");
return R.fail(404, MessageUtils.message("his.clinic_room.not_found"));
}
return R.ok(clinicRoom);
}
@@ -47,24 +48,24 @@ public class ClinicRoomAppServiceImpl implements IClinicRoomAppService {
public R<?> insertClinicRoom(ClinicRoom clinicRoom) {
// 数据校验
if (ObjectUtil.isEmpty(clinicRoom.getRoomName())) {
return R.fail(400, "诊室名称不能为空");
return R.fail(400, MessageUtils.message("his.clinic_room.name_required"));
}
if (ObjectUtil.isEmpty(clinicRoom.getDepartment())) {
return R.fail(400, "科室名称不能为空");
return R.fail(400, MessageUtils.message("his.clinic_room.dept_name_required"));
}
if (clinicRoom.getRoomName().length() > 50) {
return R.fail(400, "诊室名称长度不能超过50个字符");
return R.fail(400, MessageUtils.message("his.clinic_room.name_too_long"));
}
if (clinicRoom.getRemarks() != null && clinicRoom.getRemarks().length() > 500) {
return R.fail(400, "备注长度不能超过500个字符");
return R.fail(400, MessageUtils.message("his.clinic_room.remark_too_long"));
}
// 新增诊室
int result = clinicRoomService.insertClinicRoom(clinicRoom);
if (result > 0) {
return R.ok(null, "新增成功");
return R.ok(null, MessageUtils.message("msg.success"));
} else {
return R.fail("新增失败");
return R.fail(MessageUtils.message("msg.failure"));
}
}
@@ -72,33 +73,33 @@ public class ClinicRoomAppServiceImpl implements IClinicRoomAppService {
public R<?> updateClinicRoom(ClinicRoom clinicRoom) {
// 数据校验
if (ObjectUtil.isEmpty(clinicRoom.getId())) {
return R.fail(400, "诊室ID不能为空");
return R.fail(400, MessageUtils.message("his.clinic_room.id_required"));
}
if (ObjectUtil.isEmpty(clinicRoom.getRoomName())) {
return R.fail(400, "诊室名称不能为空");
return R.fail(400, MessageUtils.message("his.clinic_room.name_required"));
}
if (ObjectUtil.isEmpty(clinicRoom.getDepartment())) {
return R.fail(400, "科室名称不能为空");
return R.fail(400, MessageUtils.message("his.clinic_room.dept_name_required"));
}
if (clinicRoom.getRoomName().length() > 50) {
return R.fail(400, "诊室名称长度不能超过50个字符");
return R.fail(400, MessageUtils.message("his.clinic_room.name_too_long"));
}
if (clinicRoom.getRemarks() != null && clinicRoom.getRemarks().length() > 500) {
return R.fail(400, "备注长度不能超过500个字符");
return R.fail(400, MessageUtils.message("his.clinic_room.remark_too_long"));
}
// 检查诊室是否存在
ClinicRoom existingClinicRoom = clinicRoomService.selectClinicRoomById(clinicRoom.getId());
if (existingClinicRoom == null) {
return R.fail(404, "诊室不存在");
return R.fail(404, MessageUtils.message("his.clinic_room.not_found"));
}
// 更新诊室
int result = clinicRoomService.updateClinicRoom(clinicRoom);
if (result > 0) {
return R.ok(null, "修改成功");
return R.ok(null, MessageUtils.message("msg.success"));
} else {
return R.fail("修改失败");
return R.fail(MessageUtils.message("msg.failure"));
}
}
@@ -107,15 +108,15 @@ public class ClinicRoomAppServiceImpl implements IClinicRoomAppService {
// 检查诊室是否存在
ClinicRoom existingClinicRoom = clinicRoomService.selectClinicRoomById(id);
if (existingClinicRoom == null) {
return R.fail(404, "诊室不存在");
return R.fail(404, MessageUtils.message("his.clinic_room.not_found"));
}
// 删除诊室
int result = clinicRoomService.deleteClinicRoomById(id);
if (result > 0) {
return R.ok(null, "删除成功");
return R.ok(null, MessageUtils.message("msg.success"));
} else {
return R.fail("删除失败");
return R.fail(MessageUtils.message("msg.failure"));
}
}
}

View File

@@ -8,6 +8,7 @@ import com.core.common.core.domain.R;
import com.healthlink.his.appointmentmanage.domain.DeptAppointmentHours;
import com.healthlink.his.appointmentmanage.mapper.DeptAppointmentHoursMapper;
import com.healthlink.his.appointmentmanage.service.IDeptAppointmentHoursService;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.web.appointmentmanage.appservice.IDeptAppointmentHoursAppService;
import org.springframework.stereotype.Service;
@@ -44,11 +45,11 @@ public class DeptAppointmentHoursAppServiceImpl implements IDeptAppointmentHours
@Override
public R<?> getDeptAppthoursDetail(Long id) {
if (ObjectUtil.isNull(id)) {
return R.fail("ID不能为空");
return R.fail(MessageUtils.message("his.dept_hours.id_required"));
}
DeptAppointmentHours deptAppointmentHours = deptAppointmentHoursService.getById(id);
if (ObjectUtil.isNull(deptAppointmentHours)) {
return R.fail("数据不存在");
return R.fail(MessageUtils.message("his.dept_hours.data_not_found"));
}
return R.ok(deptAppointmentHours);
}
@@ -56,13 +57,13 @@ public class DeptAppointmentHoursAppServiceImpl implements IDeptAppointmentHours
@Override
public R<?> addDeptAppthours(DeptAppointmentHours deptAppointmentHours) {
if (ObjectUtil.isNull(deptAppointmentHours)) {
return R.fail("数据不能为空");
return R.fail(MessageUtils.message("his.dept_hours.data_required"));
}
if (StrUtil.isBlank(deptAppointmentHours.getInstitution())) {
return R.fail("所属机构不能为空");
return R.fail(MessageUtils.message("his.dept_hours.org_required"));
}
if (StrUtil.isBlank(deptAppointmentHours.getDepartment())) {
return R.fail("科室名称不能为空");
return R.fail(MessageUtils.message("his.dept_hours.dept_name_required"));
}
deptAppointmentHours.setCreatedTime(LocalDateTime.now());
@@ -73,12 +74,12 @@ public class DeptAppointmentHoursAppServiceImpl implements IDeptAppointmentHours
@Override
public R<?> updateDeptAppthours(DeptAppointmentHours deptAppointmentHours) {
if (ObjectUtil.isNull(deptAppointmentHours) || ObjectUtil.isNull(deptAppointmentHours.getId())) {
return R.fail("ID不能为空");
return R.fail(MessageUtils.message("his.dept_hours.id_required"));
}
DeptAppointmentHours existing = deptAppointmentHoursService.getById(deptAppointmentHours.getId());
if (ObjectUtil.isNull(existing)) {
return R.fail("数据不存在");
return R.fail(MessageUtils.message("his.dept_hours.data_not_found"));
}
deptAppointmentHours.setUpdatedTime(LocalDateTime.now());
@@ -89,12 +90,12 @@ public class DeptAppointmentHoursAppServiceImpl implements IDeptAppointmentHours
@Override
public R<?> deleteDeptAppthours(Long id) {
if (ObjectUtil.isNull(id)) {
return R.fail("ID不能为空");
return R.fail(MessageUtils.message("his.dept_hours.id_required"));
}
DeptAppointmentHours existing = deptAppointmentHoursService.getById(id);
if (ObjectUtil.isNull(existing)) {
return R.fail("数据不存在");
return R.fail(MessageUtils.message("his.dept_hours.data_not_found"));
}
boolean remove = deptAppointmentHoursService.removeById(id);

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.appointmentmanage.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.common.enums.SlotStatus;
import com.healthlink.his.appointmentmanage.domain.DoctorSchedule;
@@ -92,11 +93,11 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
@Override
public R<?> addDoctorSchedule(DoctorSchedule doctorSchedule) {
if (ObjectUtil.isEmpty(doctorSchedule)) {
return R.fail("医生排班不能为空");
return R.fail(MessageUtils.message("his.schedule.doctor_required"));
}
if (doctorSchedule.getLimitNumber() == null || doctorSchedule.getLimitNumber() <= 0) {
return R.fail("限号数量必须大于0");
return R.fail(MessageUtils.message("his.schedule.limit_must_positive"));
}
// 创建新对象排除id字段数据库id列是GENERATED ALWAYS由数据库自动生成
@@ -151,24 +152,24 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
throw new RuntimeException("创建号源池失败");
}
} else {
return R.fail("保存排班信息失败");
return R.fail(MessageUtils.message("his.schedule.save_failed"));
}
}
@Override
public R<?> addDoctorScheduleWithDate(DoctorSchedule doctorSchedule, String scheduledDate) {
if (ObjectUtil.isEmpty(doctorSchedule)) {
return R.fail("医生排班不能为空");
return R.fail(MessageUtils.message("his.schedule.doctor_required"));
}
if (doctorSchedule.getLimitNumber() == null || doctorSchedule.getLimitNumber() <= 0) {
return R.fail("限号数量必须大于0");
return R.fail(MessageUtils.message("his.schedule.limit_must_positive"));
}
// 检查结束时间必须大于开始时间
if (doctorSchedule.getStartTime() != null && doctorSchedule.getEndTime() != null) {
if (!doctorSchedule.getStartTime().isBefore(doctorSchedule.getEndTime())) {
return R.fail("结束时间必须大于开始时间");
return R.fail(MessageUtils.message("his.schedule.end_after_start"));
}
}
@@ -183,9 +184,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
doctorSchedule.getEndTime()
);
if (hasOverlap) {
return R.fail("该医生在 " + scheduledDate + ""
+ doctorSchedule.getStartTime() + "-" + doctorSchedule.getEndTime()
+ " 时间段与已有排班重叠,不能重复添加");
return R.fail(MessageUtils.message("his.schedule.time_overlap", scheduledDate, doctorSchedule.getStartTime(), doctorSchedule.getEndTime()));
}
}
@@ -237,7 +236,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
throw new RuntimeException("创建号源池失败");
}
} else {
return R.fail("保存排班信息失败");
return R.fail(MessageUtils.message("his.schedule.save_failed"));
}
}
@@ -245,12 +244,12 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
@Override
public R<?> updateDoctorSchedule(DoctorSchedule doctorSchedule) {
if (ObjectUtil.isEmpty(doctorSchedule) || ObjectUtil.isEmpty(doctorSchedule.getId())) {
return R.fail("医生排班ID不能为空");
return R.fail(MessageUtils.message("his.schedule.id_required"));
}
int result = doctorScheduleMapper.updateDoctorSchedule(doctorSchedule);
if (result <= 0) {
return R.fail("更新排班信息失败");
return R.fail(MessageUtils.message("his.schedule.update_failed"));
}
// 同步更新号源池,避免查询联表时医生/诊室等字段看起来“未更新”
@@ -488,7 +487,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
@Override
public R<?> removeDoctorSchedule(Integer doctorScheduleId) {
if (doctorScheduleId == null) {
return R.fail("排班id不能为空");
return R.fail(MessageUtils.message("his.schedule.id_required"));
}
// 1. 根据排班ID找到关联的号源池
@@ -505,7 +504,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService {
.in("status", SlotStatus.BOOKED.getValue(), SlotStatus.LOCKED.getValue(),
SlotStatus.CHECKED_IN.getValue()));
if (appointmentCount > 0) {
return R.fail("该排班已有患者预约,禁止删除!如需取消请先处理患者退预约或使用'停诊'功能。");
return R.fail(MessageUtils.message("his.schedule.has_appointments_no_delete"));
}
// 2. 根据号源池ID找到所有关联的号源槽

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.core.common.core.domain.R;
import com.healthlink.his.appointmentmanage.domain.SchedulePool;
import com.healthlink.his.appointmentmanage.service.ISchedulePoolService;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.web.appointmentmanage.appservice.ISchedulePoolAppService;
import com.healthlink.his.web.appointmentmanage.dto.SchedulePoolDto;
import org.springframework.stereotype.Service;
@@ -20,7 +21,7 @@ public class SchedulePoolAppServiceImpl implements ISchedulePoolAppService {
public R<?> addSchedulePool(SchedulePoolDto schedulePoolDto) {
//1.数据检验
if(ObjectUtil.isNull(schedulePoolDto)){
return R.fail("号源不能为空");
return R.fail(MessageUtils.message("his.schedule_pool.slot_required"));
}
//2.封装实体
SchedulePool schedulePool = new SchedulePool();

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.appointmentmanage.appservice.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.administration.domain.Patient;
import com.healthlink.his.administration.service.IPatientService;
import com.healthlink.his.appointmentmanage.mapper.ScheduleSlotMapper;
@@ -47,17 +48,17 @@ public class TicketAppServiceImpl implements ITicketAppService {
public R<?> bookTicket(com.healthlink.his.appointmentmanage.domain.AppointmentBookDTO dto) {
Long slotId = dto.getSlotId();
if (slotId == null) {
return R.fail("参数校验失败:缺少排班槽位唯一标识");
return R.fail(MessageUtils.message("his.ticket.slot_id_required"));
}
try {
int result = ticketService.bookTicket(dto);
if (result > 0) {
return R.ok("预约成功!号源已安全锁定。");
return R.ok(MessageUtils.message("his.ticket.appointment_success"));
}
return R.fail("预约挂单核发失败");
return R.fail(MessageUtils.message("his.ticket.issue_failed"));
} catch (Exception e) {
log.error("大厅挂号捕获系统异常", e);
return R.fail("系统异常:" + e.getMessage());
return R.fail(MessageUtils.message("his.common.system_error", e.getMessage()));
}
}
@@ -70,7 +71,7 @@ public class TicketAppServiceImpl implements ITicketAppService {
@Override
public R<?> cancelTicket(Long slotId) {
if (slotId == null) {
return R.fail("参数错误");
return R.fail(MessageUtils.message("his.ticket.param_error"));
}
try {
int result = ticketService.cancelTicket(slotId);
@@ -89,7 +90,7 @@ public class TicketAppServiceImpl implements ITicketAppService {
@Override
public R<?> checkInTicket(Long slotId) {
if (slotId == null) {
return R.fail("参数错误");
return R.fail(MessageUtils.message("his.ticket.param_error"));
}
try {
int result = ticketService.checkInTicket(slotId);
@@ -108,7 +109,7 @@ public class TicketAppServiceImpl implements ITicketAppService {
@Override
public R<?> cancelConsultation(Long slotId) {
if (slotId == null) {
return R.fail("参数错误");
return R.fail(MessageUtils.message("his.ticket.param_error"));
}
try {
int result = ticketService.cancelConsultation(slotId);

View File

@@ -105,7 +105,7 @@ public class LocationAppServiceImpl implements ILocationAppService {
locationService.updateLocation(location);
}
}
return R.ok("启用成功");
return R.ok(MessageUtils.message("his.location.enable_success"));
}
return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00010, null));
}
@@ -126,27 +126,27 @@ public class LocationAppServiceImpl implements ILocationAppService {
List<EncounterLocation> encounterLocationList =
encounterLocationService.getEncounterLocationInfo(null, location.getId());
if (encounterLocationList != null && !encounterLocationList.isEmpty()) {
return R.fail("有被占用的床位,不可停用");
return R.fail(MessageUtils.message("his.location.bed_occupied"));
}
} else if (LocationForm.HOUSE.getValue().equals(location.getFormEnum())) {
// 检查病房下是否有启用的病床
List<com.healthlink.his.web.common.dto.LocationDto> activeBeds =
commonService.getChildLocation(location.getId(), LocationForm.BED.getValue());
if ((activeBeds != null && !activeBeds.isEmpty())) {
return R.fail("病房下有启用或被占用的床位,不可停用");
return R.fail(MessageUtils.message("his.location.house_has_active_beds"));
}
} else if (LocationForm.WARD.getValue().equals(location.getFormEnum())) {
// 检查病区下是否有启用的病房
List<com.healthlink.his.web.common.dto.LocationDto> activeHouses =
commonService.getChildLocation(location.getId(), LocationForm.HOUSE.getValue());
if ((activeHouses != null && !activeHouses.isEmpty())) {
return R.fail("病区下有启用或被占用的病房,不可停用");
return R.fail(MessageUtils.message("his.location.ward_has_active_houses"));
}
}
location.setStatusEnum(LocationStatus.INACTIVE.getValue());
locationService.updateLocation(location);
}
return R.ok("停用成功");
return R.ok(MessageUtils.message("his.location.disable_success"));
}
return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00010, null));
}
@@ -263,13 +263,13 @@ public class LocationAppServiceImpl implements ILocationAppService {
public R<?> addLocation(LocationAddOrEditDto locationAddOrEditDto) {
// 不能为空
if (StringUtils.isEmpty(locationAddOrEditDto.getName())) {
return R.fail(false, "名称不能为空");
return R.fail(false, MessageUtils.message("his.location.name_required"));
}
// 去除空格
String name = locationAddOrEditDto.getName().replaceAll("[  ]", "");
// 判断是否存在同名
if (locationService.isExistName(name, locationAddOrEditDto.getBusNo(), locationAddOrEditDto.getId())) {
return R.fail(false, "" + name + "】已存在");
return R.fail(false, MessageUtils.message("his.location.name_exists", name));
}
Location location = new Location();
BeanUtils.copyProperties(locationAddOrEditDto, location);
@@ -308,13 +308,13 @@ public class LocationAppServiceImpl implements ILocationAppService {
public R<?> editLocation(LocationAddOrEditDto locationAddOrEditDto) {
// 不能为空
if (StringUtils.isEmpty(locationAddOrEditDto.getName())) {
return R.fail(false, "名称不能为空");
return R.fail(false, MessageUtils.message("his.location.name_required"));
}
// 去除空格
String name = locationAddOrEditDto.getName().replaceAll("[  ]", "");
// 判断是否存在同名
if (locationService.isExistName(name, locationAddOrEditDto.getBusNo(), locationAddOrEditDto.getId())) {
return R.fail(false, "" + name + "】已存在");
return R.fail(false, MessageUtils.message("his.location.name_exists", name));
}
Location location = new Location();
BeanUtils.copyProperties(locationAddOrEditDto, location);

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.ChineseConvertUtils;
import com.core.common.utils.DictUtils;
@@ -105,7 +106,7 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
public R<?> getOperatingRoomById(Long id) {
OperatingRoom operatingRoom = operatingRoomService.getById(id);
if (operatingRoom == null) {
return R.fail("手术室信息不存在");
return R.fail(MessageUtils.message("his.or.not_found"));
}
OperatingRoomDto operatingRoomDto = new OperatingRoomDto();
@@ -139,12 +140,12 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
public R<?> addOperatingRoom(OperatingRoomDto operatingRoomDto) {
// 校验名称不能为空
if (StringUtils.isEmpty(operatingRoomDto.getName())) {
return R.fail("手术室名称不能为空");
return R.fail(MessageUtils.message("his.or.name_required"));
}
// 校验房间号不能为空
if (StringUtils.isEmpty(operatingRoomDto.getBusNo())) {
return R.fail("房间号不能为空");
return R.fail(MessageUtils.message("his.or.room_no_required"));
}
// 去除空格
@@ -153,12 +154,12 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
// 判断是否存在同名
if (isExistName(name, null)) {
return R.fail("" + name + "】已存在");
return R.fail(MessageUtils.message("his.or.name_exists", name));
}
// 判断房间号是否已存在
if (isExistBusNo(operatingRoomDto.getBusNo(), null)) {
return R.fail("房间号【" + operatingRoomDto.getBusNo() + "】已存在");
return R.fail(MessageUtils.message("his.or.room_no_exists", operatingRoomDto.getBusNo()));
}
OperatingRoom operatingRoom = new OperatingRoom();
@@ -171,9 +172,9 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
boolean result = operatingRoomService.save(operatingRoom);
if (result) {
return R.ok(null, "新增成功");
return R.ok(null, MessageUtils.message("msg.success"));
}
return R.fail("新增失败");
return R.fail(MessageUtils.message("msg.failure"));
}
/**
@@ -187,17 +188,17 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
// 校验手术室是否存在
OperatingRoom existOperatingRoom = operatingRoomService.getById(operatingRoomDto.getId());
if (existOperatingRoom == null) {
return R.fail("手术室信息不存在");
return R.fail(MessageUtils.message("his.or.not_found"));
}
// 校验名称不能为空
if (StringUtils.isEmpty(operatingRoomDto.getName())) {
return R.fail("手术室名称不能为空");
return R.fail(MessageUtils.message("his.or.name_required"));
}
// 校验房间号不能为空
if (StringUtils.isEmpty(operatingRoomDto.getBusNo())) {
return R.fail("房间号不能为空");
return R.fail(MessageUtils.message("his.or.room_no_required"));
}
// 去除空格
@@ -206,12 +207,12 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
// 判断是否存在同名(排除自己)
if (isExistName(name, operatingRoomDto.getId())) {
return R.fail("" + name + "】已存在");
return R.fail(MessageUtils.message("his.or.name_exists", name));
}
// 判断房间号是否已存在(排除自己)
if (isExistBusNo(operatingRoomDto.getBusNo(), operatingRoomDto.getId())) {
return R.fail("房间号【" + operatingRoomDto.getBusNo() + "】已存在");
return R.fail(MessageUtils.message("his.or.room_no_exists", operatingRoomDto.getBusNo()));
}
OperatingRoom operatingRoom = new OperatingRoom();
@@ -224,9 +225,9 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
boolean result = operatingRoomService.updateById(operatingRoom);
if (result) {
return R.ok(null, "修改成功");
return R.ok(null, MessageUtils.message("msg.success"));
}
return R.fail("修改失败");
return R.fail(MessageUtils.message("msg.failure"));
}
/**
@@ -244,16 +245,16 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
try {
idList.add(Long.parseLong(idStr.trim()));
} catch (NumberFormatException e) {
return R.fail("ID格式错误");
return R.fail(MessageUtils.message("his.or.id_format_error"));
}
}
// 删除手术室
boolean result = operatingRoomService.removeByIds(idList);
if (result) {
return R.ok(null, "删除成功");
return R.ok(null, MessageUtils.message("msg.success"));
}
return R.fail("删除失败");
return R.fail(MessageUtils.message("msg.failure"));
}
/**
@@ -265,7 +266,7 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
@Override
public R<?> enableOperatingRoom(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return R.fail("请选择要启用的手术室");
return R.fail(MessageUtils.message("his.or.select_enable"));
}
// 批量更新状态为启用
@@ -276,9 +277,9 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
boolean result = operatingRoomService.updateBatchById(operatingRooms);
if (result) {
return R.ok("启用成功");
return R.ok(MessageUtils.message("his.or.enable_success"));
}
return R.fail("启用失败");
return R.fail(MessageUtils.message("his.or.enable_failed"));
}
/**
@@ -290,7 +291,7 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
@Override
public R<?> disableOperatingRoom(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return R.fail("请选择要停用的手术室");
return R.fail(MessageUtils.message("his.or.select_disable"));
}
// 批量更新状态为停用
@@ -301,9 +302,9 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
boolean result = operatingRoomService.updateBatchById(operatingRooms);
if (result) {
return R.ok("停用成功");
return R.ok(MessageUtils.message("his.or.disable_success"));
}
return R.fail("停用失败");
return R.fail(MessageUtils.message("his.or.disable_failed"));
}
/**

View File

@@ -147,7 +147,7 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
// Validate required fields before processing
if (orgLocQueryDto.getOrganizationId() == null) {
return R.fail("请选择执行科室");
return R.fail(MessageUtils.message("his.org_location.select_dept"));
}
OrganizationLocation orgLoc = new OrganizationLocation();
@@ -170,8 +170,9 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
orgLoc.getStartTime(), orgLoc.getEndTime())) {
Organization org = organizationService.getById(organizationLocation.getOrganizationId());
String organizationName = org != null ? org.getName() : ("科室[" + organizationLocation.getOrganizationId() + "]已删除");
return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime()
+ CommonConstants.Common.DASH + orgLoc.getEndTime() + "" + organizationName + "时间冲突");
return R.fail(MessageUtils.message("his.org_location.time_conflict",
activityName + CommonConstants.Common.DASH + orgLoc.getStartTime()
+ CommonConstants.Common.DASH + orgLoc.getEndTime() + "" + organizationName));
}
if (orgLocQueryDto.getId() != null) {

View File

@@ -90,7 +90,7 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
// 账号唯一性
long count = iBizUserService.count(new LambdaQueryWrapper<BizUser>().eq(BizUser::getUserName, userName));
if (count > 0L) {
return R.fail(null, "账号已存在");
return R.fail(null, MessageUtils.message("his.practitioner.account_exists"));
}
// 新增 sys_user
BizUser bizUser = new BizUser();
@@ -462,7 +462,7 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
@Override
public R<?> delUserPractitioner(Long userId) {
if (1L == userId) {
return R.fail(null, "admin不允许删除");
return R.fail(null, MessageUtils.message("his.practitioner.admin_no_delete"));
}
// iBizUserService.remove(new LambdaQueryWrapper<BizUser>().eq(BizUser::getUserId, userId));
practitionerAppAppMapper.delUser(userId);
@@ -471,7 +471,7 @@ public class PractitionerAppServiceImpl implements IPractitionerAppService {
List<Practitioner> practitionerList = iPractitionerService.list(new LambdaQueryWrapper<Practitioner>().eq(Practitioner::getUserId, userId));
Practitioner one = practitionerList != null && !practitionerList.isEmpty() ? practitionerList.get(0) : null;
if (one == null) {
return R.fail(null, "未找到对应的医生信息");
return R.fail(null, MessageUtils.message("his.practitioner.not_found"));
}
Long practitionerId = one.getId();// 参与者id
iPractitionerService.removeById(practitionerId);

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.basicmanage.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.basicmanage.domain.Bed;
import com.healthlink.his.basicmanage.service.IBedService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -37,20 +38,20 @@ public class BedController {
}
@PostMapping("/add")
public R<?> add(@RequestBody Bed bed) {
return bedService.save(bed) ? R.ok("新增成功") : R.fail("新增失败");
return bedService.save(bed) ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@PutMapping("/update")
public R<?> update(@RequestBody Bed bed) {
return bedService.updateById(bed) ? R.ok("修改成功") : R.fail("修改失败");
return bedService.updateById(bed) ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@DeleteMapping("/delete")
public R<?> delete(@RequestParam Long id) {
return bedService.removeById(id) ? R.ok("删除成功") : R.fail("删除失败");
return bedService.removeById(id) ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@PutMapping("/status")
public R<?> updateStatus(@RequestParam Long id, @RequestParam Integer status) {
Bed bed = new Bed(); bed.setId(id); bed.setStatus(status);
return bedService.updateById(bed) ? R.ok("状态更新成功") : R.fail("状态更新失败");
return bedService.updateById(bed) ? R.ok(MessageUtils.message("his.bed.status_update_success")) : R.fail(MessageUtils.message("his.bed.status_update_failed"));
}
/**
@@ -81,15 +82,15 @@ public class BedController {
@PutMapping("/assign")
public R<?> assignBed(@RequestParam Long bedId, @RequestParam Long patientId, @RequestParam Long deptId) {
Bed bed = bedService.getById(bedId);
if (bed == null) return R.fail("床位不存在");
if (bed.getStatus() != 0) return R.fail("该床位当前不可分配(状态: " +
java.util.Map.of(0, "空闲", 1, "占用", 2, "清洁中", 3, "维修中").getOrDefault(bed.getStatus(), "未知") + "");
if (bed == null) return R.fail(MessageUtils.message("his.bed.not_found"));
if (bed.getStatus() != 0) return R.fail(MessageUtils.message("his.bed.not_assignable",
java.util.Map.of(0, "空闲", 1, "占用", 2, "清洁中", 3, "维修中").getOrDefault(bed.getStatus(), "未知")));
if (bed.getDeptId() != null && !bed.getDeptId().equals(deptId)) {
return R.fail("床位所属科室与患者入院科室不匹配");
return R.fail(MessageUtils.message("his.bed.dept_mismatch"));
}
bed.setStatus(1);
bedService.updateById(bed);
return R.ok("分配成功");
return R.ok(MessageUtils.message("his.bed.assign_success"));
}
/**
@@ -98,10 +99,10 @@ public class BedController {
@PutMapping("/discharge")
public R<?> dischargeBed(@RequestParam Long bedId) {
Bed bed = bedService.getById(bedId);
if (bed == null) return R.fail("床位不存在");
if (bed == null) return R.fail(MessageUtils.message("his.bed.not_found"));
bed.setStatus(2); // 清洁中
bedService.updateById(bed);
return R.ok("已标记为清洁中");
return R.ok(MessageUtils.message("his.bed.marked_cleaning"));
}
}

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.basicmanage.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.administration.domain.InvoiceSegment;
import com.healthlink.his.administration.service.IInvoiceSegmentService;
@@ -83,6 +84,6 @@ public class InvoiceSegmentController {
@PostMapping("/delete")
public R<?> delete(@RequestBody InvoiceSegmentDeleteRequest request) {
int rows = invoiceSegmentService.deleteInvoiceSegmentByIds(request.getIds());
return rows > 0 ? R.ok("删除成功") : R.fail("删除失败");
return rows > 0 ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
}

View File

@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.annotation.Log;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.enums.BusinessType;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
@@ -68,7 +69,7 @@ public class OutpatientNoSegmentController {
if (StringUtils.isEmpty(outpatientNoSegment.getStartNo()) ||
StringUtils.isEmpty(outpatientNoSegment.getEndNo()) ||
StringUtils.isEmpty(outpatientNoSegment.getUsedNo())) {
return R.fail("起始号码、终止号码和使用号码不能为空");
return R.fail(MessageUtils.message("his.outpatient_no.numbers_required"));
}
// 校验号码段是否重复
@@ -76,7 +77,7 @@ public class OutpatientNoSegmentController {
outpatientNoSegment.getStartNo(),
outpatientNoSegment.getEndNo(),
null)) {
return R.fail("门诊号码设置重复");
return R.fail(MessageUtils.message("his.outpatient_no.duplicate"));
}
// 设置创建人信息
@@ -87,7 +88,7 @@ public class OutpatientNoSegmentController {
outpatientNoSegment.setCreateBy(SecurityUtils.getUsername());
int result = outpatientNoSegmentService.insertOutpatientNoSegment(outpatientNoSegment);
return result > 0 ? R.ok("保存成功") : R.fail("保存失败");
return result > 0 ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
/**
@@ -103,7 +104,7 @@ public class OutpatientNoSegmentController {
if (StringUtils.isEmpty(outpatientNoSegment.getStartNo()) ||
StringUtils.isEmpty(outpatientNoSegment.getEndNo()) ||
StringUtils.isEmpty(outpatientNoSegment.getUsedNo())) {
return R.fail("起始号码、终止号码和使用号码不能为空");
return R.fail(MessageUtils.message("his.outpatient_no.numbers_required"));
}
// 校验号码段是否重复(排除自身)
@@ -111,14 +112,14 @@ public class OutpatientNoSegmentController {
outpatientNoSegment.getStartNo(),
outpatientNoSegment.getEndNo(),
outpatientNoSegment.getId())) {
return R.fail("门诊号码设置重复");
return R.fail(MessageUtils.message("his.outpatient_no.duplicate"));
}
// 设置更新人信息
outpatientNoSegment.setUpdateBy(SecurityUtils.getUsername());
int result = outpatientNoSegmentService.updateOutpatientNoSegment(outpatientNoSegment);
return result > 0 ? R.ok("保存成功") : R.fail("保存失败");
return result > 0 ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
/**
@@ -136,7 +137,7 @@ public class OutpatientNoSegmentController {
log.info("删除请求 - 接收到的ids类型: " + (idsObj != null ? idsObj.getClass().getName() : "null"));
if (idsObj == null) {
return R.fail("请选择要删除的数据");
return R.fail(MessageUtils.message("his.outpatient_no.select_delete"));
}
// 转换为 Long[] 数组
@@ -162,24 +163,24 @@ public class OutpatientNoSegmentController {
}
} catch (NumberFormatException e) {
log.info("删除请求 - ID转换失败: " + idObj + ", 错误: " + e.getMessage());
return R.fail("无效的ID格式: " + idObj);
return R.fail(MessageUtils.message("his.outpatient_no.invalid_id_value", String.valueOf(idObj)));
}
} else if (idObj instanceof Number) {
ids[i] = ((Number) idObj).longValue();
} else {
return R.fail("无效的ID类型: " + (idObj != null ? idObj.getClass().getName() : "null"));
return R.fail(MessageUtils.message("his.outpatient_no.invalid_id_type", idObj != null ? idObj.getClass().getName() : "null"));
}
}
} else if (idsObj instanceof Long[]) {
ids = (Long[]) idsObj;
} else {
return R.fail("无效的ID数组格式");
return R.fail(MessageUtils.message("his.outpatient_no.invalid_id_format"));
}
log.info("删除请求 - 转换后的ids: " + java.util.Arrays.toString(ids));
if (ids == null || ids.length == 0) {
return R.fail("请选择要删除的数据");
return R.fail(MessageUtils.message("his.outpatient_no.select_delete"));
}
// 获取当前用户ID
@@ -194,7 +195,7 @@ public class OutpatientNoSegmentController {
if (segment == null) {
// 记录日志以便调试
log.info("删除失败记录不存在ID=" + id + ",可能已被软删除或不存在");
return R.fail("数据不存在ID: " + id);
return R.fail(MessageUtils.message("his.outpatient_no.data_not_found", String.valueOf(id)));
}
log.info("删除验证 - 找到记录: ID=" + segment.getId() + ", operatorId=" + segment.getOperatorId() + ", usedNo=" + segment.getUsedNo() + ", startNo=" + segment.getStartNo());
@@ -202,20 +203,20 @@ public class OutpatientNoSegmentController {
// 校验归属权
if (!segment.getOperatorId().equals(userId)) {
log.info("删除验证 - 权限检查失败: segment.operatorId=" + segment.getOperatorId() + ", userId=" + userId);
return R.fail("只能删除自己维护的门诊号码段");
return R.fail(MessageUtils.message("his.outpatient_no.only_own_delete"));
}
// 校验使用状态(使用号码=起始号码表示未使用)
if (!segment.getUsedNo().equals(segment.getStartNo())) {
log.info("删除验证 - 使用状态检查失败: usedNo=" + segment.getUsedNo() + ", startNo=" + segment.getStartNo());
return R.fail("已有门诊号码段已有使用的门诊号码,请核对!");
return R.fail(MessageUtils.message("his.outpatient_no.has_used_numbers"));
}
}
log.info("删除验证 - 所有检查通过,开始执行删除");
int rows = outpatientNoSegmentService.deleteOutpatientNoSegmentByIds(ids);
log.info("删除执行 - 影响行数: " + rows);
return rows > 0 ? R.ok("删除成功") : R.fail("删除失败");
return rows > 0 ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
}

View File

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.core.domain.model.LoginUser;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.common.core.domain.model.LoginUser;
import com.healthlink.his.infectious.domain.InfectiousAudit;
@@ -138,7 +139,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> batchAudit(BatchAuditDto batchAuditDto) {
if (batchAuditDto.getCardNos() == null || batchAuditDto.getCardNos().isEmpty()) {
return R.fail("请选择要审核的报卡");
return R.fail(MessageUtils.message("his.card.select_approve"));
}
String auditorId = SecurityUtils.getUserId().toString();
@@ -169,7 +170,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> batchReturn(BatchReturnDto batchReturnDto) {
if (batchReturnDto.getCardNos() == null || batchReturnDto.getCardNos().isEmpty()) {
return R.fail("请选择要退回的报卡");
return R.fail(MessageUtils.message("his.card.select_return"));
}
String auditorId = SecurityUtils.getUserId().toString();
@@ -202,7 +203,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
public R<?> auditPass(SingleAuditDto auditDto) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(auditDto.getCardNo());
if (card == null) {
return R.fail("报卡不存在");
return R.fail(MessageUtils.message("his.card.not_found"));
}
String auditorId = SecurityUtils.getUserId().toString();
@@ -218,7 +219,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
createAuditRecord(card.getCardNo(), oldStatus, 2, 2, auditDto.getAuditOpinion(),
null, auditorId, auditorName, false, 1);
return R.ok("审核通过");
return R.ok(MessageUtils.message("his.card.approve_success"));
}
@Override
@@ -226,7 +227,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
public R<?> auditReturn(SingleReturnDto returnDto) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(returnDto.getCardNo());
if (card == null) {
return R.fail("报卡不存在");
return R.fail(MessageUtils.message("his.card.not_found"));
}
String auditorId = SecurityUtils.getUserId().toString();
@@ -243,7 +244,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
createAuditRecord(card.getCardNo(), oldStatus, 5, 4, null,
returnDto.getReturnReason(), auditorId, auditorName, false, 1);
return R.ok("已退回");
return R.ok(MessageUtils.message("his.card.returned"));
}
@Override
@@ -421,19 +422,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
public R<?> submitCard(String cardNo) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo);
if (card == null) {
return R.fail("报卡不存在");
return R.fail(MessageUtils.message("his.card.not_found"));
}
// 验证权限:只能提交自己的报卡
Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return R.fail("无权操作此报卡");
return R.fail(MessageUtils.message("his.card.no_permission"));
}
// 狋证状态:只有暂存状态可以提交
if (!Integer.valueOf(0).equals(card.getStatus())) {
return R.fail("只能提交暂存状态的报卡");
return R.fail(MessageUtils.message("his.card.only_draft_submit"));
}
// 更新状态为已提交
@@ -441,7 +442,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card);
return R.ok("提交成功");
return R.ok(MessageUtils.message("msg.success"));
}
@Override
@@ -449,19 +450,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
public R<?> withdrawCard(String cardNo) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo);
if (card == null) {
return R.fail("报卡不存在");
return R.fail(MessageUtils.message("his.card.not_found"));
}
// 验证权限:只能撤回自己的报卡
Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return R.fail("无权操作此报卡");
return R.fail(MessageUtils.message("his.card.no_permission"));
}
// 狋证状态:只有已提交状态可以撤回
if (!Integer.valueOf(1).equals(card.getStatus())) {
return R.fail("只能撤回已提交状态的报卡");
return R.fail(MessageUtils.message("his.card.only_submitted_withdraw"));
}
// 更新状态为暂存
@@ -469,7 +470,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card);
return R.ok("撤回成功");
return R.ok(MessageUtils.message("his.card.withdraw_success"));
}
@Override
@@ -477,19 +478,19 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
public R<?> deleteCard(String cardNo) {
InfectiousCard card = infectiousCardMapper.selectByCardNo(cardNo);
if (card == null) {
return R.fail("报卡不存在");
return R.fail(MessageUtils.message("his.card.not_found"));
}
// 验证权限:只能删除自己的报卡
Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null || !practitioner.getId().equals(card.getDoctorId())) {
return R.fail("无权操作此报卡");
return R.fail(MessageUtils.message("his.card.no_permission"));
}
// 狋证状态:只有暂存状态可以删除
if (!Integer.valueOf(0).equals(card.getStatus())) {
return R.fail("只能删除暂存状态的报卡");
return R.fail(MessageUtils.message("his.card.only_draft_delete"));
}
// 更新状态为作废
@@ -497,20 +498,20 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
card.setUpdateTime(new Date());
infectiousCardMapper.updateById(card);
return R.ok("删除成功");
return R.ok(MessageUtils.message("msg.success"));
}
@Override
@Transactional(rollbackFor = Exception.class)
public R<?> batchSubmitCards(List<String> cardNos) {
if (cardNos == null || cardNos.isEmpty()) {
return R.fail("请选择要提交的报卡");
return R.fail(MessageUtils.message("his.card.select_submit"));
}
Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null) {
return R.fail("当前用户未关联医生信息");
return R.fail(MessageUtils.message("his.card.user_no_doctor"));
}
Long doctorId = practitioner.getId();
int successCount = 0;
@@ -533,7 +534,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
}
if (successCount == 0) {
return R.fail("没有可提交的报卡,只能提交暂存状态的报卡");
return R.fail(MessageUtils.message("his.card.no_submittable"));
}
return R.ok("批量提交成功,共提交" + successCount + "");
@@ -543,13 +544,13 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> batchDeleteCards(List<String> cardNos) {
if (cardNos == null || cardNos.isEmpty()) {
return R.fail("请选择要删除的报卡");
return R.fail(MessageUtils.message("his.card.select_delete"));
}
Long userId = SecurityUtils.getUserId();
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(userId);
if (practitioner == null) {
return R.fail("当前用户未关联医生信息");
return R.fail(MessageUtils.message("his.card.user_no_doctor"));
}
Long doctorId = practitioner.getId();
int successCount = 0;
@@ -572,7 +573,7 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
}
if (successCount == 0) {
return R.fail("没有可删除的报卡,只能删除暂存状态的报卡");
return R.fail(MessageUtils.message("his.card.no_deletable"));
}
return R.ok("批量删除成功,共删除" + successCount + "");
@@ -587,24 +588,24 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
// 通过 sys_user 表的 user_id 查询医生表 (adm_practitioner) 获取医生 ID
Practitioner practitioner = iPractitionerService.getPractitionerByUserId(currentUserId);
if (practitioner == null) {
return R.fail("当前用户未关联医生信息");
return R.fail(MessageUtils.message("his.card.user_no_doctor"));
}
Long doctorId = practitioner.getId();
// 查询报卡
InfectiousCard card = infectiousCardMapper.selectByCardNo(updateDto.getCardNo());
if (card == null) {
return R.fail("报卡不存在");
return R.fail(MessageUtils.message("his.card.not_found"));
}
// 验证是否当前医生的报卡 - 根据 doctorId 字段验证
if (!doctorId.equals(card.getDoctorId())) {
return R.fail("只能修改自己的报卡");
return R.fail(MessageUtils.message("his.card.only_own_edit"));
}
// 狋证状态是否允许修改(只能修改暂存状态的报卡)
if (!Integer.valueOf(0).equals(card.getStatus())) {
return R.fail("只能修改暂存状态的报卡");
return R.fail(MessageUtils.message("his.card.only_draft_edit"));
}
// 更新字段
@@ -621,9 +622,9 @@ public class CardManageAppServiceImpl implements ICardManageAppService {
int rows = infectiousCardMapper.updateById(card);
if (rows > 0) {
return R.ok("更新成功");
return R.ok(MessageUtils.message("msg.success"));
}
return R.fail("更新失败");
return R.fail(MessageUtils.message("msg.failure"));
}
@Override

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.cdss.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.cdss.domain.CdssAlert;
import com.healthlink.his.cdss.domain.CdssRule;
import com.healthlink.his.cdss.domain.CdssRuleExecution;
@@ -38,7 +39,7 @@ public class CdssAppServiceImpl implements ICdssAppService {
@Override
public R<?> evaluateRules(Long encounterId, Long patientId, String triggerType, Long departmentId) {
if (encounterId == null || patientId == null) {
return R.fail(400, "就诊ID和患者ID不能为空");
return R.fail(400, MessageUtils.message("his.cdss.encounter_patient_required"));
}
List<CdssRule> activeRules = cdssRuleService.findActiveRules(triggerType, departmentId);
List<CdssAlert> triggeredAlerts = new ArrayList<>();
@@ -86,7 +87,7 @@ public class CdssAppServiceImpl implements ICdssAppService {
@Override
public R<?> getAlerts(Long encounterId, Integer acknowledged) {
if (encounterId == null) {
return R.fail(400, "就诊ID不能为空");
return R.fail(400, MessageUtils.message("his.cdss.encounter_id_required"));
}
List<CdssAlert> alerts = cdssAlertService.findByEncounterId(encounterId);
if (acknowledged != null) {
@@ -100,13 +101,13 @@ public class CdssAppServiceImpl implements ICdssAppService {
@Override
public R<?> acknowledgeAlert(Long id, String remark) {
if (id == null) {
return R.fail(400, "告警ID不能为空");
return R.fail(400, MessageUtils.message("his.cdss.alert_id_required"));
}
boolean updated = cdssAlertService.acknowledgeAlert(id, null, remark);
if (!updated) {
return R.fail(404, "告警不存在或已确认");
return R.fail(404, MessageUtils.message("his.cdss.alert_not_found"));
}
return R.ok(null, "确认成功");
return R.ok(null, MessageUtils.message("his.cdss.confirm_success"));
}
@Override

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.charge.patientcardrenewal;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
@@ -40,13 +41,13 @@ public class PatientCardRenewalController {
if (success) {
log.info("患者换卡成功: 旧卡号={} -> 新卡号={}",
request.getOldCardNo(), request.getNewCardNo());
return R.ok("换卡成功");
return R.ok(MessageUtils.message("his.card_renewal.success"));
} else {
return R.fail("换卡失败");
return R.fail(MessageUtils.message("his.card_renewal.failed"));
}
} catch (Exception e) {
log.error("患者换卡异常: ", e);
return R.fail("换卡操作异常: " + e.getMessage());
return R.fail(MessageUtils.message("his.card_renewal.exception", e.getMessage()));
}
}
}

View File

@@ -35,9 +35,10 @@ public interface IOutpatientChargeAppService {
* 根据就诊id查询患者处方列表
*
* @param encounterId 就诊id
* @param statusEnum 收费状态过滤(可选,不传则返回全部状态)
* @return 患者处方列表
*/
List<EncounterPatientPrescriptionDto> getEncounterPatientPrescription(Long encounterId);
List<EncounterPatientPrescriptionDto> getEncounterPatientPrescription(Long encounterId, Integer statusEnum);
/**
* 根据就诊id查询患者处方列表并新增字段实收金额、应收金额、优惠金额、折扣率

View File

@@ -111,10 +111,11 @@ public class OutpatientChargeAppServiceImpl implements IOutpatientChargeAppServi
* 根据就诊id查询患者处方列表
*
* @param encounterId 就诊id
* @param statusEnum 收费状态过滤(可选,不传则返回全部状态)
* @return 患者处方列表
*/
@Override
public List<EncounterPatientPrescriptionDto> getEncounterPatientPrescription(Long encounterId) {
public List<EncounterPatientPrescriptionDto> getEncounterPatientPrescription(Long encounterId, Integer statusEnum) {
List<EncounterPatientPrescriptionDto> prescriptionDtoList
= outpatientChargeAppMapper.selectEncounterPatientPrescription(encounterId,
ChargeItemContext.ACTIVITY.getValue(), ChargeItemContext.MEDICATION.getValue(),
@@ -123,7 +124,7 @@ public class OutpatientChargeAppServiceImpl implements IOutpatientChargeAppServi
ChargeItemStatus.PLANNED.getValue(), ChargeItemStatus.BILLABLE.getValue(),
ChargeItemStatus.BILLED.getValue(), ChargeItemStatus.REFUNDING.getValue(),
ChargeItemStatus.REFUNDED.getValue(), ChargeItemStatus.PART_REFUND.getValue(),
CommonConstants.TableName.WOR_DEVICE_REQUEST);
CommonConstants.TableName.WOR_DEVICE_REQUEST, statusEnum);
prescriptionDtoList.forEach(e -> {
// 收费状态枚举
e.setStatusEnum_enumText(EnumUtils.getInfoByValue(ChargeItemStatus.class, e.getStatusEnum()));

View File

@@ -284,7 +284,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
// ==================== 走退药流程 (生成新单据) ====================
// 校验是否重复申请
if (medicationRequest.getRefundMedicineId() != null) {
throw new ServiceException("已申请退药,请勿重复申请");
throw new ServiceException(MessageUtils.message("charge.refund.drug.duplicate"));
}
MedicationRequest newRefundRequest = new MedicationRequest();
BeanUtils.copyProperties(medicationRequest, newRefundRequest);
@@ -329,7 +329,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
// 检查是否已经是退药状态
if (DispenseStatus.STOPPED.getValue().equals(medicationDispense.getStatusEnum())
&& NotPerformedReason.REFUND.getValue().equals(medicationDispense.getStatusEnum())) {
throw new ServiceException("已申请退药,请勿重复申请");
throw new ServiceException(MessageUtils.message("charge.refund.drug.duplicate"));
}
// 修改状态
medicationDispense.setStatusEnum(DispenseStatus.STOPPED.getValue())
@@ -373,7 +373,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
// ==================== 走退耗材流程 (生成新单据) ====================
// 校验是否重复申请
if (deviceRequest.getRefundDeviceId() != null) {
throw new ServiceException("已申请退耗材,请勿重复申请");
throw new ServiceException(MessageUtils.message("charge.refund.consumable.duplicate"));
}
DeviceRequest newRefundRequest = new DeviceRequest();
BeanUtils.copyProperties(deviceRequest, newRefundRequest);
@@ -418,7 +418,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
// 检查是否已经是退耗材状态
if (DispenseStatus.STOPPED.getValue().equals(deviceDispense.getStatusEnum())
&& NotPerformedReason.REFUND.getValue().equals(deviceDispense.getStatusEnum())) {
throw new ServiceException("已申请退耗材,请勿重复申请");
throw new ServiceException(MessageUtils.message("charge.refund.consumable.duplicate"));
}
// 修改状态
deviceDispense.setStatusEnum(DispenseStatus.STOPPED.getValue())
@@ -443,7 +443,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
// 诊疗项目需医技科室同意退费
if (RequestStatus.COMPLETED.getValue().equals(serviceRequest.getStatusEnum())) {
if (serviceRequest.getRefundServiceId() != null) {
throw new ServiceException("已申请退费,请勿重复申请");
throw new ServiceException(MessageUtils.message("charge.refund.service.duplicate"));
}
// 生成服务请求(取消服务)
serviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4)); // 服务请求编码
@@ -454,7 +454,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
serviceRequestService.save(serviceRequest);
} else {
if (RequestStatus.STOPPED.getValue().equals(serviceRequest.getStatusEnum())) {
throw new ServiceException("已申请退费,请勿重复申请");
throw new ServiceException(MessageUtils.message("charge.refund.service.duplicate"));
}
serReqUpdateList.add(serviceRequest.getId());
}
@@ -576,7 +576,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
if (!medicationRequestList.isEmpty()) {
if (medicationRequestList.stream().map(MedicationRequest::getStatusEnum)
.anyMatch(x -> x.equals(RequestStatus.CANCELLED.getValue()))) {
throw new ServiceException("请先退药后再退费");
throw new ServiceException(MessageUtils.message("charge.refund.drug.first"));
}
}
}
@@ -589,7 +589,7 @@ public class OutpatientRefundAppServiceImpl implements IOutpatientRefundAppServi
if (!deviceRequestList.isEmpty()) {
if (deviceRequestList.stream().map(DeviceRequest::getStatusEnum)
.anyMatch(x -> x.equals(RequestStatus.CANCELLED.getValue()))) {
throw new ServiceException("请先退耗材后再退费");
throw new ServiceException(MessageUtils.message("charge.refund.consumable.first"));
}
}
}

View File

@@ -292,14 +292,14 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
public R<?> returnRegister(CancelRegPaymentDto cancelRegPaymentDto) {
Encounter byId = iEncounterService.getById(cancelRegPaymentDto.getEncounterId());
if (byId == null) {
return R.fail(null, "就诊记录不存在");
return R.fail(null, MessageUtils.message("his.chargemanage.encounter_not_exist"));
}
if (EncounterStatus.CANCELLED.getValue().equals(byId.getStatusEnum())) {
return R.fail(null, "该患者已经退号,请勿重复退号");
return R.fail(null, MessageUtils.message("his.chargemanage.already_cancelled_registration"));
}
// 只有待诊状态才能退号
if (!EncounterStatus.PLANNED.getValue().equals(byId.getStatusEnum())) {
return R.fail(null, "该患者已开始就诊,不能退号!");
return R.fail(null, MessageUtils.message("his.chargemanage.consultation_started_no_cancel"));
}
// 诊前退号检查:病历、费用明细、班段时间
@@ -395,7 +395,7 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
)
));
if (emrCount > 0) {
return R.fail(null, "该患者已有病历记录,不能退号!");
return R.fail(null, MessageUtils.message("his.chargemanage.emr_exists_no_cancel"));
}
// 2. 检查是否有当日费用明细(除挂号费外的其他费用)
@@ -418,7 +418,7 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
)
));
if (chargeItemCount > 0) {
return R.fail(null, "该患者已产生诊疗费用,不能退号!");
return R.fail(null, MessageUtils.message("his.chargemanage.charge_exists_no_cancel"));
}
// 3. 检查是否当日就诊(防止隔日财务封账)
@@ -426,7 +426,7 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
LocalDate encounterDate = encounter.getCreateTime().toInstant()
.atZone(ZoneId.systemDefault()).toLocalDate();
if (encounterDate.isBefore(today)) {
return R.fail(null, "非当日就诊记录,不能退号!");
return R.fail(null, MessageUtils.message("his.chargemanage.not_today_encounter_no_cancel"));
}
}
@@ -490,7 +490,7 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
// 检查当前时间是否已过班段结束时间
LocalTime now = LocalTime.now();
if (now.isAfter(pool.getEndTime())) {
return R.fail(null, "当前班段已结束,不能退号!");
return R.fail(null, MessageUtils.message("his.chargemanage.shift_ended_no_cancel"));
}
return null;
@@ -610,7 +610,7 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
@Override
public R<?> cancelRegister(Long encounterId) {
iEncounterService.removeById(encounterId);
return R.ok("已取消挂号");
return R.ok(MessageUtils.message("his.chargemanage.registration_cancelled"));
}
/**
@@ -725,7 +725,7 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
public R<?> reprintRegistration(ReprintRegistrationDto reprintRegistrationDto) {
// 补打挂号只是重新打印,不需要修改数据库
// 可以在这里添加日志记录补打操作
return R.ok(null, "补打挂号成功");
return R.ok(null, MessageUtils.message("his.chargemanage.reprint_success"));
}
/**

View File

@@ -61,11 +61,13 @@ public class OutpatientChargeController {
* 根据就诊id查询患者处方列表
*
* @param encounterId 就诊id
* @param statusEnum 收费状态过滤(可选,不传则返回全部状态)
* @return 患者处方列表
*/
@GetMapping(value = "/patient-prescription")
public R<?> getEncounterPatientPrescription(@RequestParam Long encounterId) {
return R.ok(outpatientChargeAppService.getEncounterPatientPrescription(encounterId));
public R<?> getEncounterPatientPrescription(@RequestParam Long encounterId,
@RequestParam(required = false) Integer statusEnum) {
return R.ok(outpatientChargeAppService.getEncounterPatientPrescription(encounterId, statusEnum));
}
/**

View File

@@ -4,6 +4,7 @@
package com.healthlink.his.web.chargemanage.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.web.chargemanage.appservice.IOutpatientRefundAppService;
import com.healthlink.his.web.chargemanage.dto.EncounterPatientPageParam;
import com.healthlink.his.web.chargemanage.dto.RefundItemParam;
@@ -68,7 +69,7 @@ public class OutpatientRefundController {
@GetMapping(value = "/patient-payment")
public R<?> getEncounterPatientPayment(@RequestParam(required = false) Long encounterId) {
if (encounterId == null) {
return R.fail(null, "请先选择患者后再进行退费操作");
return R.fail(null, MessageUtils.message("his.refund.select_patient_first"));
}
return outpatientRefundAppService.getEncounterPatientPayment(encounterId);
}

View File

@@ -59,7 +59,8 @@ public interface OutpatientChargeAppMapper {
@Param("chinesePatentMedicine") Integer chinesePatentMedicine,
@Param("planned") Integer planned, @Param("billable") Integer billable,
@Param("billed") Integer billed, @Param("refunding") Integer refunding, @Param("refunded") Integer refunded,
@Param("partRefund") Integer partRefund, @Param("worDeviceRequest") String worDeviceRequest);
@Param("partRefund") Integer partRefund, @Param("worDeviceRequest") String worDeviceRequest,
@Param("filterStatus") Integer filterStatus);
/**
* 根据就诊id查询患者处方列表并新增字段应收金额实收金额优惠金额折扣率

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.check.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.CheckMethod;
import com.healthlink.his.check.domain.CheckPackage;
import com.healthlink.his.check.service.ICheckMethodService;
@@ -120,13 +121,13 @@ public class CheckMethodAppServiceImpl implements ICheckMethodAppService {
public R<?> addCheckMethod(CheckMethod checkMethod) {
//1.数据校验
if (ObjectUtil.isEmpty(checkMethod.getName())) {
return R.fail("检查方法名称不能为空!");
return R.fail(MessageUtils.message("his.check_method.name_required"));
}
if (ObjectUtil.isEmpty(checkMethod.getCode())) {
return R.fail("检查方法代码不能为空!");
return R.fail(MessageUtils.message("his.check_method.code_required"));
}
if (ObjectUtil.isEmpty(checkMethod.getCheckType())) {
return R.fail("检查方法的检查类型不能为空!");
return R.fail(MessageUtils.message("his.check_method.type_required"));
}
//2.保存
checkMethodService.save(checkMethod);
@@ -139,13 +140,13 @@ public class CheckMethodAppServiceImpl implements ICheckMethodAppService {
public R<?> updateCheckMethod(CheckMethod checkMethod) {
//1.数据校验
if (ObjectUtil.isEmpty(checkMethod.getName())) {
return R.fail("检查方法名称不能为空!");
return R.fail(MessageUtils.message("his.check_method.name_required"));
}
if (ObjectUtil.isEmpty(checkMethod.getCode())) {
return R.fail("检查方法代码不能为空!");
return R.fail(MessageUtils.message("his.check_method.code_required"));
}
if (ObjectUtil.isEmpty(checkMethod.getCheckType())) {
return R.fail("检查方法的检查类型不能为空!");
return R.fail(MessageUtils.message("his.check_method.type_required"));
}
//2.更新
boolean b = checkMethodService.updateById(checkMethod);

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.check.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.CheckPackage;
import com.healthlink.his.check.domain.CheckPackageDetail;
import com.healthlink.his.check.domain.CheckPart;
@@ -90,7 +91,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
return R.ok(list);
} catch (Exception e) {
log.error("获取检查套餐列表失败", e);
return R.fail("获取检查套餐列表失败");
return R.fail(MessageUtils.message("his.check.get_package_list_failed"));
}
}
@@ -99,7 +100,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
try {
CheckPackage checkPackage = checkPackageService.getById(id);
if (checkPackage == null) {
return R.fail("套餐不存在");
return R.fail(MessageUtils.message("his.check.package_not_found"));
}
// 获取套餐明细
@@ -124,7 +125,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
return R.ok(dto);
} catch (Exception e) {
log.error("获取检查套餐详情失败", e);
return R.fail("获取检查套餐详情失败");
return R.fail(MessageUtils.message("his.check.get_package_detail_failed"));
}
}
@@ -144,7 +145,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
// 保存套餐主表
boolean saveResult = checkPackageService.save(checkPackage);
if (!saveResult) {
return R.fail("保存套餐失败");
return R.fail(MessageUtils.message("his.check.save_package_failed"));
}
// 保存套餐明细
@@ -159,7 +160,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
// 同步更新引用此套餐的检查部位价格
syncCheckPartPrice(checkPackage.getPackageName(), checkPackage.getPackagePrice());
return R.ok(checkPackage.getId(), "保存成功");
return R.ok(checkPackage.getId(), MessageUtils.message("msg.success"));
} catch (Exception e) {
log.error("新增检查套餐失败", e);
@@ -175,11 +176,11 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
if (errorMessage.contains("check_package")) {
constraintInfo = "套餐名称或编码";
}
return R.fail("保存失败:数据重复," + constraintInfo + "已存在。详细错误:" + errorMessage);
return R.fail(MessageUtils.message("his.check.save_duplicate_failed", constraintInfo, errorMessage));
}
}
return R.fail("新增检查套餐失败:" + errorMessage);
return R.fail(MessageUtils.message("his.check.add_package_failed", errorMessage));
}
}
@@ -190,7 +191,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
// 检查套餐是否存在
CheckPackage existPackage = checkPackageService.getById(checkPackageDto.getId());
if (existPackage == null) {
return R.fail("套餐不存在");
return R.fail(MessageUtils.message("his.check.package_not_found"));
}
// 更新套餐主表数据
@@ -203,7 +204,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
boolean updateResult = checkPackageService.updateById(checkPackage);
if (!updateResult) {
return R.fail("更新套餐失败");
return R.fail(MessageUtils.message("his.check.update_package_failed"));
}
// 删除原有明细
@@ -221,10 +222,10 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
// 同步更新引用此套餐的检查部位价格
syncCheckPartPrice(existPackage.getPackageName(), checkPackage.getPackagePrice());
return R.ok("更新成功");
return R.ok(MessageUtils.message("msg.success"));
} catch (Exception e) {
log.error("更新检查套餐失败", e);
return R.fail("更新检查套餐失败:" + e.getMessage());
return R.fail(MessageUtils.message("his.check.update_package_error", e.getMessage()));
}
}
@@ -235,7 +236,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
// 检查套餐是否存在
CheckPackage existPackage = checkPackageService.getById(id);
if (existPackage == null) {
return R.fail("套餐不存在");
return R.fail(MessageUtils.message("his.check.package_not_found"));
}
// 删除套餐明细 - 先删除子表数据
@@ -250,14 +251,14 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService {
// 删除套餐主表
boolean deleteResult = checkPackageService.removeById(id);
if (!deleteResult) {
return R.fail("删除套餐失败");
return R.fail(MessageUtils.message("his.check.delete_package_failed"));
}
log.info("删除检查套餐成功,套餐 ID: {}", id);
return R.ok("删除成功");
return R.ok(MessageUtils.message("msg.success"));
} catch (Exception e) {
log.error("删除检查套餐失败", e);
return R.fail("删除检查套餐失败:" + e.getMessage());
return R.fail(MessageUtils.message("his.check.delete_package_error", e.getMessage()));
}
}
}

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.check.appservice.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.LisGroupInfo;
import com.healthlink.his.check.service.ILisGroupInfoService;
import com.healthlink.his.web.check.appservice.ILisGroupInfoAppService;
@@ -29,7 +30,7 @@ public class LisGroupInfoAppServiceImpl implements ILisGroupInfoAppService {
@Override
public R<?> add(LisGroupInfo lisGroupInfo) {
if (ObjectUtil.isEmpty(lisGroupInfo)) {
return R.fail("信息不能为空");
return R.fail(MessageUtils.message("his.lis.info_required"));
}
boolean save = lisGroupInfoService.save(lisGroupInfo);
return R.ok(save);
@@ -38,7 +39,7 @@ public class LisGroupInfoAppServiceImpl implements ILisGroupInfoAppService {
@Override
public R<?> update(LisGroupInfo lisGroupInfo) {
if (ObjectUtil.isEmpty(lisGroupInfo)) {
return R.fail("信息不能为空");
return R.fail(MessageUtils.message("his.lis.info_required"));
}
boolean update = lisGroupInfoService.updateById(lisGroupInfo);
return R.ok( update);

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.check.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.DicomPrintRecord;
import com.healthlink.his.check.domain.RadiologyImage;
import com.healthlink.his.check.domain.RadiologyImageReport;
@@ -82,7 +83,7 @@ public class RadiologyImageAppServiceImpl implements IRadiologyImageAppService {
public R<?> submitReport(Long id) {
RadiologyImageReport r = reportService.getById(id);
if (r == null) {
return R.fail("报告不存在");
return R.fail(MessageUtils.message("radiology.report.not.exist"));
}
r.setStatus("REPORTED");
r.setReportTime(new Date());
@@ -101,7 +102,7 @@ public class RadiologyImageAppServiceImpl implements IRadiologyImageAppService {
public R<?> verifyReport(Long id, String doctor) {
RadiologyImageReport r = reportService.getById(id);
if (r == null) {
return R.fail("报告不存在");
return R.fail(MessageUtils.message("radiology.report.not.exist"));
}
r.setStatus("VERIFIED");
r.setVerifyDoctor(doctor);

View File

@@ -7,6 +7,7 @@ import com.core.common.core.domain.AjaxResult;
import com.core.common.core.page.TableDataInfo;
import com.core.common.exception.ServiceException;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.administration.domain.Account;
import com.healthlink.his.administration.domain.ChargeItem;
@@ -307,7 +308,7 @@ public class ExamApplyController extends BaseController {
// 🔧 BugFix#385: 获取患者真实的自费账户预结算验证要求accountId必须真实存在
Account selfAccount = accountService.getSelfAccount(dto.getEncounterId());
if (selfAccount == null) {
throw new ServiceException("患者自费账户不存在无法创建检查收费项encounterId=" + dto.getEncounterId());
throw new ServiceException(MessageUtils.message("his.exam.self_account_not_found", dto.getEncounterId()));
}
chargeItem.setAccountId(selfAccount.getId());
// 🔧 BugFix#385: 使用 ItemType.ACTIVITY.getValue()=3 表示诊疗而不是硬编码的2
@@ -497,7 +498,7 @@ public class ExamApplyController extends BaseController {
// 🔧 BugFix#385: 获取患者真实的自费账户预结算验证要求accountId必须真实存在
Account selfAccount = accountService.getSelfAccount(dto.getEncounterId());
if (selfAccount == null) {
throw new ServiceException("患者自费账户不存在无法创建检查收费项encounterId=" + dto.getEncounterId());
throw new ServiceException(MessageUtils.message("his.exam.self_account_not_found", dto.getEncounterId()));
}
chargeItem.setAccountId(selfAccount.getId());
// 🔧 BugFix#385: 使用 ItemType.ACTIVITY.getValue()=3 表示诊疗

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.check.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.ExamAppointment;
import com.healthlink.his.check.service.IExamAppointmentService;
import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;
@@ -40,28 +41,28 @@ public class ExamAppointmentController {
@PreAuthorize("@ss.hasPermi('infection:check:edit')")
@Transactional(rollbackFor=Exception.class)
public R<?> checkin(@PathVariable Long id) {
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail("预约不存在");
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail(MessageUtils.message("his.exam.appointment_not_found"));
a.setStatus("CHECKED_IN"); appointmentService.updateById(a); return R.ok();
}
@PutMapping("/start/{id}")
@PreAuthorize("@ss.hasPermi('infection:check:edit')")
@Transactional(rollbackFor=Exception.class)
public R<?> startExam(@PathVariable Long id) {
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail("预约不存在");
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail(MessageUtils.message("his.exam.appointment_not_found"));
a.setStatus("EXAMINING"); appointmentService.updateById(a); return R.ok();
}
@PutMapping("/complete/{id}")
@PreAuthorize("@ss.hasPermi('infection:check:edit')")
@Transactional(rollbackFor=Exception.class)
public R<?> complete(@PathVariable Long id) {
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail("预约不存在");
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail(MessageUtils.message("his.exam.appointment_not_found"));
a.setStatus("COMPLETED"); appointmentService.updateById(a); return R.ok();
}
@PutMapping("/cancel/{id}")
@PreAuthorize("@ss.hasPermi('infection:check:edit')")
@Transactional(rollbackFor=Exception.class)
public R<?> cancel(@PathVariable Long id) {
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail("预约不存在");
ExamAppointment a = appointmentService.getById(id); if (a == null) return R.fail(MessageUtils.message("his.exam.appointment_not_found"));
a.setStatus("CANCELLED"); appointmentService.updateById(a); return R.ok();
}
@GetMapping("/queue")

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.check.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.*;
import com.healthlink.his.check.service.*;
import lombok.AllArgsConstructor;
@@ -54,7 +55,7 @@ public class RadiologyEnhancedController {
@Transactional(rollbackFor = Exception.class)
public R<?> notifyReport(@RequestParam Long id) {
RadiologyUrgentReport r = urgentReportService.getById(id);
if (r == null) return R.fail("报告不存在");
if (r == null) return R.fail(MessageUtils.message("his.radiology.report_not_found"));
r.setNotifyStatus(1);
r.setNotifyTime(new Date());
r.setUpdateTime(new Date());

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.check.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.check.domain.SpecimenBarcode;
import com.healthlink.his.check.service.ISpecimenBarcodeService;
import lombok.AllArgsConstructor;
@@ -76,7 +77,7 @@ public class SpecimenBarcodeController {
@Transactional(rollbackFor = Exception.class)
public R<?> scanConfirm(@PathVariable Long id, @RequestParam("confirmBy") String confirmBy) {
SpecimenBarcode barcode = barcodeService.getById(id);
if (barcode == null) return R.fail("条码不存在");
if (barcode == null) return R.fail(MessageUtils.message("his.specimen.barcode_not_found"));
barcode.setStatus("SCANNED");
barcode.setScanConfirmTime(LocalDateTime.now());
barcode.setScanConfirmBy(confirmBy);
@@ -88,7 +89,7 @@ public class SpecimenBarcodeController {
@Transactional(rollbackFor = Exception.class)
public R<?> reject(@PathVariable Long id) {
SpecimenBarcode barcode = barcodeService.getById(id);
if (barcode == null) return R.fail("条码不存在");
if (barcode == null) return R.fail(MessageUtils.message("his.specimen.barcode_not_found"));
barcode.setStatus("REJECTED");
barcodeService.updateById(barcode);
return R.ok(barcode);

View File

@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.AjaxResult;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.clinical.domain.*;
import com.healthlink.his.clinical.service.*;
import com.healthlink.his.web.clinical.appservice.IClinicalPathwayAppService;
@@ -42,7 +43,7 @@ public class ClinicalPathwayController {
public R<?> completePathway(@PathVariable Long id) {
LambdaQueryWrapper<ClinicalPathwayExecution> qw = new LambdaQueryWrapper<>();
qw.eq(ClinicalPathwayExecution::getPathwayId, id).eq(ClinicalPathwayExecution::getStatus, "IN_PATH").orderByDesc(ClinicalPathwayExecution::getCreateTime).last("LIMIT 1");
ClinicalPathwayExecution e = executionService.getOne(qw); if (e == null) return R.fail("执行记录不存在");
ClinicalPathwayExecution e = executionService.getOne(qw); if (e == null) return R.fail(MessageUtils.message("his.clinical.execution_not_found"));
e.setStatus("COMPLETED"); e.setCompleteDate(java.time.LocalDate.now());
executionService.updateById(e); return R.ok();
}
@@ -51,7 +52,7 @@ public class ClinicalPathwayController {
public R<?> varyPathway(@PathVariable Long id, @RequestParam("reason") String reason) {
LambdaQueryWrapper<ClinicalPathwayExecution> qw = new LambdaQueryWrapper<>();
qw.eq(ClinicalPathwayExecution::getPathwayId, id).eq(ClinicalPathwayExecution::getStatus, "IN_PATH").orderByDesc(ClinicalPathwayExecution::getCreateTime).last("LIMIT 1");
ClinicalPathwayExecution e = executionService.getOne(qw); if (e == null) return R.fail("执行记录不存在");
ClinicalPathwayExecution e = executionService.getOne(qw); if (e == null) return R.fail(MessageUtils.message("his.clinical.execution_not_found"));
e.setStatus("VARIATION"); e.setVariationReason(reason); executionService.updateById(e); return R.ok();
}
@PreAuthorize("@ss.hasPermi('inpatient:clinical:list')")

View File

@@ -214,7 +214,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 缓存中没有,从数据库查询
SurgeryDto surgeryDto = surgeryAppMapper.getSurgeryDetail(id);
if (surgeryDto == null) {
return R.fail("手术信息不存在");
return R.fail(MessageUtils.message("surgery.info.not.exist"));
}
// 从申请单中获取次要手术信息
@@ -257,24 +257,24 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 校验患者是否存在
Patient patient = patientService.getById(surgeryDto.getPatientId());
if (patient == null) {
return R.fail("患者信息不存在");
return R.fail(MessageUtils.message("surgery.patient.not.exist"));
}
// 校验就诊ID是否存在
if (surgeryDto.getEncounterId() == null) {
return R.fail("请选择就诊流水号");
return R.fail(MessageUtils.message("surgery.select.encounter"));
}
// 校验就诊记录是否存在
Encounter encounter = encounterService.getById(surgeryDto.getEncounterId());
if (encounter == null) {
return R.fail("就诊记录不存在");
return R.fail(MessageUtils.message("surgery.encounter.not.exist"));
}
// 获取患者的自费账户ID
Long accountId = accountService.getSelfPayAccount(surgeryDto.getEncounterId());
if (accountId == null) {
return R.fail("未找到患者的账户信息,请先完成挂号或住院登记");
return R.fail(MessageUtils.message("surgery.account.not.found"));
}
// 当前登录账号的科室id
@@ -443,7 +443,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
surgeryDto.getEncounterId(), surgeryDto.getPatientId(),
surgeryId, surgeryDto.getSurgeryName()));
return R.ok(surgeryId, "手术申请提交成功!");
return R.ok(surgeryId, MessageUtils.message("his.surgery.submit_success"));
}
/**
@@ -484,7 +484,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 校验手术是否存在
Surgery existSurgery = surgeryService.getById(surgeryDto.getId());
if (existSurgery == null) {
return R.fail("手术信息不存在");
return R.fail(MessageUtils.message("surgery.info.not.exist"));
}
// 转换为实体对象
@@ -522,7 +522,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 清除相关缓存
clearSurgeryAppCache(surgery);
return R.ok(null, "手术申请修改成功!");
return R.ok(null, MessageUtils.message("his.surgery.update_success"));
}
/**
@@ -537,12 +537,12 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 校验手术是否存在
Surgery existSurgery = surgeryService.getById(id);
if (existSurgery == null) {
return R.fail("手术信息不存在");
return R.fail(MessageUtils.message("surgery.info.not.exist"));
}
// 已完成的手术不能删除
if (existSurgery.getStatusEnum() == 3) {
return R.fail("已完成的手术不能删除");
return R.fail(MessageUtils.message("surgery.completed.cannot.delete"));
}
// 级联删除关联数据
@@ -587,7 +587,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 校验手术是否存在
Surgery existSurgery = surgeryService.getById(id);
if (existSurgery == null) {
return R.fail("手术信息不存在");
return R.fail(MessageUtils.message("surgery.info.not.exist"));
}
surgeryService.updateSurgeryStatus(id, statusEnum);
@@ -607,7 +607,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
@Override
public R<List<Encounter>> getEncounterListByPatientId(Long patientId) {
if (patientId == null) {
return R.fail("患者ID不能为空");
return R.fail(MessageUtils.message("surgery.patient.id.empty"));
}
// 查询该患者的所有就诊记录(进行中的优先)
@@ -620,7 +620,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
List<Encounter> encounterList = encounterService.list(wrapper);
if (encounterList == null || encounterList.isEmpty()) {
return R.fail("该患者暂无就诊记录,请先挂号或办理住院");
return R.fail(MessageUtils.message("surgery.no.encounter.record"));
}
return R.ok(encounterList);
@@ -861,7 +861,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
.ne(excludeId != null, Surgery::getId, excludeId);
long conflictCount = surgeryService.count(wrapper);
if (conflictCount > 0) {
return R.fail("该手术室在该时间段已有手术安排,请选择其他时间或手术室");
return R.fail(MessageUtils.message("surgery.room.time.conflict"));
}
return R.ok(false);
}

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.core.domain.model.LoginUser;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.administration.domain.Patient;
import com.healthlink.his.administration.service.IPatientService;
@@ -92,7 +93,7 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
public R<OpScheduleDto> getSurgeryScheduleDetail(Long scheduleId) {
OpScheduleDto opScheduleDto = surgicalScheduleAppMapper.getSurgeryScheduleDetail(scheduleId);
if (opScheduleDto == null) {
return R.fail("手术安排信息不存在");
return R.fail(MessageUtils.message("his.surgical_schedule.not_found"));
}
return R.ok(opScheduleDto);
}
@@ -110,7 +111,7 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
if (opCreateScheduleDto.getPatientId() != null) {
Patient patient = patientService.getById(opCreateScheduleDto.getPatientId());
if (patient == null) {
return R.fail("患者信息不存在");
return R.fail(MessageUtils.message("his.surgical_schedule.patient_not_found"));
}
}
@@ -125,7 +126,7 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
opCreateScheduleDto.getOperName()
);
if (existsDuplicate != null && existsDuplicate) {
return R.fail("该患者此手术单号已存在手术安排,请勿重复提交");
return R.fail(MessageUtils.message("his.surgical_schedule.duplicate_schedule"));
}
}
@@ -136,14 +137,14 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
if (startTime != null && endTime != null && roomCode != null && !roomCode.isEmpty()) {
Boolean scheduleConflict = surgicalScheduleAppMapper.isScheduleConflict(startTime, endTime, roomCode);
if (scheduleConflict != null && scheduleConflict) {
return R.fail("该时段内手术间被占用");
return R.fail(MessageUtils.message("his.surgical_schedule.room_occupied"));
}
}
// Bug #432 修复获取当前登录用户信息增加null校验防止NPE
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null) {
return R.fail("用户未登录或登录已过期");
return R.fail(MessageUtils.message("his.surgical_schedule.user_not_logged_in"));
}
// 当前登录用户ID
Long userId = loginUser.getUserId();
@@ -205,7 +206,7 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
// 保存手术安排
boolean saved = opScheduleService.save(opSchedule);
if (!saved) {
return R.fail("新增手术安排失败");
return R.fail(MessageUtils.message("his.surgical_schedule.add_failed"));
}
syncSurgeryIncisionLevel(opSchedule.getOperCode(), opCreateScheduleDto.getIncisionLevel());
@@ -255,7 +256,7 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
}
}
return R.ok("新增手术安排成功");
return R.ok(MessageUtils.message("his.surgical.add_success"));
}
/**
@@ -269,11 +270,11 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
public R<?> updateSurgerySchedule(OpScheduleDto opScheduleDto) {
// 校验手术安排是否存在
if (opScheduleDto.getScheduleId() == null) {
return R.fail("排程号不能为空");
return R.fail(MessageUtils.message("his.surgical_schedule.schedule_id_required"));
}
OpSchedule existSchedule = opScheduleService.getById(opScheduleDto.getScheduleId());
if (existSchedule == null) {
return R.fail("手术安排信息不存在");
return R.fail(MessageUtils.message("his.surgical_schedule.not_found"));
}
// 转换为实体对象
@@ -324,12 +325,12 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
// 更新手术安排
boolean updated = opScheduleService.updateById(opSchedule);
if (!updated) {
return R.fail("修改手术安排失败");
return R.fail(MessageUtils.message("his.surgical_schedule.update_failed"));
}
syncSurgeryIncisionLevel(opScheduleDto.getOperCode(), opScheduleDto.getIncisionLevel());
return R.ok("修改手术安排成功");
return R.ok(MessageUtils.message("his.surgical.update_success"));
}
/**
@@ -344,16 +345,16 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
// 校验手术安排是否存在
OpSchedule existSchedule = opScheduleService.getById(scheduleId);
if (existSchedule == null) {
return R.fail("手术安排信息不存在");
return R.fail(MessageUtils.message("his.surgical_schedule.not_found"));
}
// 逻辑删除手术安排
boolean deleted = opScheduleService.removeById(scheduleId);
if (!deleted) {
return R.fail("删除手术安排失败");
return R.fail(MessageUtils.message("his.surgical_schedule.delete_failed"));
}
return R.ok(null, "删除手术安排成功");
return R.ok(null, MessageUtils.message("his.surgical.delete_success"));
}
/**

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.clinicalmanage.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.common.enums.ActivityDefCategory;
import com.healthlink.his.web.clinicalmanage.appservice.ISurgicalScheduleAppService;
import com.healthlink.his.web.clinicalmanage.dto.OpCreateScheduleDto;
@@ -137,9 +138,9 @@ public class SurgicalScheduleController {
com.core.common.core.domain.model.LoginUser loginUser = com.core.common.utils.SecurityUtils.getLoginUser();
String encodedPassword = loginUser.getPassword();
if (com.core.common.utils.SecurityUtils.matchesPassword(password, encodedPassword)) {
return R.ok(true, "密码验证成功");
return R.ok(true, MessageUtils.message("his.surgical.password_verify_success"));
} else {
return R.fail(false, "账户密码错误,请重新输入");
return R.fail(false, MessageUtils.message("his.surgical.password_verify_failed"));
}
}

View File

@@ -12,6 +12,7 @@ import com.core.common.enums.DelFlag;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.StringUtils;
import com.core.common.utils.bean.BeanUtils;
import com.healthlink.his.administration.domain.Location;
@@ -311,7 +312,7 @@ public class CommonServiceImpl implements ICommonService {
// 医保编码和生产厂家校验
for (LocationInventoryDto dto : locationInventoryDtoList) {
if (StringUtils.isNotEmpty(dto.getYbNo()) && StringUtils.isEmpty(dto.getManufacturerText())) {
return R.fail("生产厂家不能为空,请到药品目录维护");
return R.fail(MessageUtils.message("common.manufacturer.required"));
}
}
return R.ok(locationInventoryDtoList);
@@ -521,9 +522,9 @@ public class CommonServiceImpl implements ICommonService {
}
}
// 方式 3如果仍然没有病区且 currentOrgId 为空,尝试获取所有病区
if (wardList.isEmpty() && currentOrgId == null) {
log.info("getPractitionerWard - 尝试获取所有病区");
// 方式 3如果仍然没有病区尝试获取所有活动病区
if (wardList.isEmpty()) {
log.info("getPractitionerWard - 未查到指定病区,获取所有病区");
List<Location> allWards = locationService.getWardList(null);
log.info("getPractitionerWard - 所有病区数:{}", allWards != null ? allWards.size() : 0);
if (allWards != null && !allWards.isEmpty()) {
@@ -700,7 +701,7 @@ public class CommonServiceImpl implements ICommonService {
List<InventoryDetailDto> inventoryDetailList = commonAppMapper
.selectMedicineInventoryDetail(medicationIdList, locationIdList, PublicationStatus.ACTIVE.getValue());
if (inventoryDetailList == null || inventoryDetailList.isEmpty()) {
return R.fail("发药单生成失败,请检查药品库存");
return R.fail(MessageUtils.message("common.drug.dispense.fail.check.stock"));
}
// 将库存信息根据药品id和库房id进行分组
Map<String, List<InventoryDetailDto>> inventoryDetailMap = inventoryDetailList.stream()
@@ -720,7 +721,7 @@ public class CommonServiceImpl implements ICommonService {
+ medicationDispense.getLocationId();
// 查询对应的库存信息
if (!inventoryDetailMap.containsKey(inventoryKey)) {
return R.fail("药品库存不存在药品ID: " + medicationDispense.getMedicationId());
return R.fail(MessageUtils.message("common.drug.stock.not.exist", medicationDispense.getMedicationId()));
}
List<InventoryDetailDto> inventoryList = inventoryDetailMap.get(inventoryKey);
@@ -788,13 +789,13 @@ public class CommonServiceImpl implements ICommonService {
// 校验药品库存
for (MedicationDispense medicationDispense : medicationDispenseList) {
if (medicationDispense.getLotNumber() == null) {
return R.fail("药品:" + medicationDispense.getMedicationId() + "库存不足,请检查药品库存");
return R.fail(MessageUtils.message("common.drug.stock.insufficient", medicationDispense.getMedicationId()));
}
}
// 新增或更新发药单
boolean result = medicationDispenseService.saveOrUpdateBatch(medicationDispenseList);
if (!result) {
return R.fail("发药单生成失败,请联系管理员");
return R.fail(MessageUtils.message("common.drug.dispense.fail.contact.admin"));
}
}
// 查询患者待发放的耗材信息
@@ -815,7 +816,7 @@ public class CommonServiceImpl implements ICommonService {
List<InventoryDetailDto> inventoryDetailList = commonAppMapper.selectDeviceInventoryDetail(deviceIdList,
locationIdList, PublicationStatus.ACTIVE.getValue());
if (inventoryDetailList == null || inventoryDetailList.isEmpty()) {
return R.fail("发耗材单生成失败,请检查耗材库存");
return R.fail(MessageUtils.message("common.device.dispense.fail.check.stock"));
}
// 将库存信息根据耗材id和库房id进行分组
Map<String, List<InventoryDetailDto>> inventoryDetailMap = inventoryDetailList.stream()
@@ -835,7 +836,7 @@ public class CommonServiceImpl implements ICommonService {
= deviceDispense.getDeviceDefId() + CommonConstants.Common.DASH + deviceDispense.getLocationId();
// 查询对应的库存信息
if (!inventoryDetailMap.containsKey(inventoryKey)) {
return R.fail("耗材库存不存在耗材ID: " + deviceDispense.getDeviceDefId());
return R.fail(MessageUtils.message("common.device.stock.not.exist", deviceDispense.getDeviceDefId()));
}
List<InventoryDetailDto> inventoryList = inventoryDetailMap.get(inventoryKey);
@@ -903,13 +904,13 @@ public class CommonServiceImpl implements ICommonService {
// 校验耗材库存
for (DeviceDispense deviceDispense : deviceDispenseList) {
if (deviceDispense.getLotNumber() == null) {
return R.fail("耗材:" + deviceDispense.getDeviceDefId() + "库存不足,请检查耗材库存");
return R.fail(MessageUtils.message("common.device.stock.insufficient", deviceDispense.getDeviceDefId()));
}
}
// 新增或更新发耗材单
boolean result = deviceDispenseService.saveOrUpdateBatch(deviceDispenseList);
if (!result) {
return R.fail("发耗材单生成失败,请联系管理员");
return R.fail(MessageUtils.message("common.device.dispense.fail.contact.admin"));
}
}
return R.ok();

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.consultation.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.web.consultation.appservice.IConsultationAppService;
import com.healthlink.his.web.consultation.dto.ConsultationActivityDto;
import com.healthlink.his.web.consultation.dto.ConsultationConfirmationDto;
@@ -46,7 +47,7 @@ public class ConsultationController {
return R.ok(list);
} catch (Exception e) {
log.error("获取会诊列表失败", e);
return R.fail("获取会诊列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_list_failed", e.getMessage()));
}
}
@@ -61,7 +62,7 @@ public class ConsultationController {
return R.ok(list);
} catch (Exception e) {
log.error("查询会诊申请列表失败", e);
return R.fail("查询会诊申请列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.query_list_failed", e.getMessage()));
}
}
@@ -81,7 +82,7 @@ public class ConsultationController {
return R.ok(page);
} catch (Exception e) {
log.error("分页查询会诊申请列表失败", e);
return R.fail("分页查询会诊申请列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.query_page_failed", e.getMessage()));
}
}
@@ -93,10 +94,10 @@ public class ConsultationController {
public R<String> saveConsultation(@RequestBody ConsultationRequestDto dto) {
try {
Boolean result = consultationAppService.saveConsultation(dto);
return result ? R.ok("保存成功") : R.fail("保存失败");
return result ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
} catch (Exception e) {
log.error("保存会诊申请失败", e);
return R.fail("保存会诊申请失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.save_failed", e.getMessage()));
}
}
@@ -109,10 +110,10 @@ public class ConsultationController {
@Parameter(description = "会诊申请单号") @RequestParam String consultationId) {
try {
Boolean result = consultationAppService.submitConsultation(consultationId);
return result ? R.ok("提交成功") : R.fail("提交失败");
return result ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
} catch (Exception e) {
log.error("提交会诊申请失败", e);
return R.fail("提交会诊申请失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.submit_failed", e.getMessage()));
}
}
@@ -126,10 +127,10 @@ public class ConsultationController {
@Parameter(description = "作废原因") @RequestParam(required = false) String cancelReason) {
try {
Boolean result = consultationAppService.cancelConsultation(consultationId, cancelReason);
return result ? R.ok("作废成功") : R.fail("作废失败");
return result ? R.ok(MessageUtils.message("his.consultation.void_success")) : R.fail(MessageUtils.message("his.consultation.void_failed"));
} catch (Exception e) {
log.error("作废会诊申请失败", e);
return R.fail("作废会诊申请失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.void_error", e.getMessage()));
}
}
@@ -142,10 +143,10 @@ public class ConsultationController {
@Parameter(description = "会诊申请单号") @RequestParam String consultationId) {
try {
Boolean result = consultationAppService.completeConsultation(consultationId);
return result ? R.ok("结束成功") : R.fail("结束失败");
return result ? R.ok(MessageUtils.message("his.consultation.complete_success")) : R.fail(MessageUtils.message("his.consultation.complete_failed"));
} catch (Exception e) {
log.error("结束会诊申请失败", e);
return R.fail("结束会诊申请失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.complete_error", e.getMessage()));
}
}
@@ -160,7 +161,7 @@ public class ConsultationController {
return R.ok(tree);
} catch (Exception e) {
log.error("获取科室医生树失败", e);
return R.fail("获取科室医生树失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_dept_tree_failed", e.getMessage()));
}
}
@@ -176,7 +177,7 @@ public class ConsultationController {
return R.ok(diagnosis);
} catch (Exception e) {
log.error("获取主诊断失败", e);
return R.fail("获取主诊断失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_diagnosis_failed", e.getMessage()));
}
}
@@ -191,7 +192,7 @@ public class ConsultationController {
return R.ok(list);
} catch (Exception e) {
log.error("获取我的会诊邀请失败", e);
return R.fail("获取我的会诊邀请失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_invitations_failed", e.getMessage()));
}
}
@@ -206,7 +207,7 @@ public class ConsultationController {
return R.ok(list);
} catch (Exception e) {
log.error("获取会诊项目列表失败", e);
return R.fail("获取会诊项目列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_activities_failed", e.getMessage()));
}
}
@@ -223,7 +224,7 @@ public class ConsultationController {
return R.ok(list);
} catch (Exception e) {
log.error("获取待确认会诊列表失败", e);
return R.fail("获取待确认会诊列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_pending_failed", e.getMessage()));
}
}
@@ -235,10 +236,10 @@ public class ConsultationController {
public R<String> confirmConsultation(@RequestBody ConsultationConfirmationDto dto) {
try {
Boolean result = consultationAppService.confirmConsultation(dto);
return result ? R.ok("确认成功") : R.fail("确认失败");
return result ? R.ok(MessageUtils.message("his.consultation.confirm_success")) : R.fail(MessageUtils.message("his.consultation.confirm_failed"));
} catch (Exception e) {
log.error("确认会诊失败", e);
return R.fail("确认会诊失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.confirm_error", e.getMessage()));
}
}
@@ -250,10 +251,10 @@ public class ConsultationController {
public R<String> cancelConfirmation(@Parameter(description = "会诊申请单号") @RequestParam String consultationId) {
try {
Boolean result = consultationAppService.cancelConfirmation(consultationId);
return result ? R.ok("取消确认成功") : R.fail("取消确认失败");
return result ? R.ok(MessageUtils.message("his.consultation.cancel_confirm_success")) : R.fail(MessageUtils.message("his.consultation.cancel_confirm_failed"));
} catch (Exception e) {
log.error("取消确认会诊失败", e);
return R.fail("取消确认会诊失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.cancel_confirm_error", e.getMessage()));
}
}
@@ -265,10 +266,10 @@ public class ConsultationController {
public R<String> signConsultation(@Parameter(description = "会诊申请单号") @RequestParam String consultationId) {
try {
Boolean result = consultationAppService.signConsultation(consultationId);
return result ? R.ok("签名成功") : R.fail("签名失败");
return result ? R.ok(MessageUtils.message("his.consultation.sign_success")) : R.fail(MessageUtils.message("his.consultation.sign_failed"));
} catch (Exception e) {
log.error("签名会诊失败", e);
return R.fail("签名会诊失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.sign_error", e.getMessage()));
}
}
@@ -284,7 +285,7 @@ public class ConsultationController {
return R.ok(detail);
} catch (Exception e) {
log.error("获取会诊确认详情失败", e);
return R.fail("获取会诊确认详情失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_detail_failed", e.getMessage()));
}
}
@@ -300,7 +301,7 @@ public class ConsultationController {
return R.ok(opinions);
} catch (Exception e) {
log.error("获取会诊意见列表失败", e);
return R.fail("获取会诊意见列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_opinions_failed", e.getMessage()));
}
}
@@ -316,7 +317,7 @@ public class ConsultationController {
return R.ok(detail);
} catch (Exception e) {
log.error("查询会诊申请详情失败", e);
return R.fail("查询会诊申请详情失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.query_detail_failed", e.getMessage()));
}
}
@@ -335,7 +336,7 @@ public class ConsultationController {
return R.ok(result);
} catch (Exception e) {
log.error("检查会诊时限失败", e);
return R.fail("检查会诊时限失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.check_time_limit_failed", e.getMessage()));
}
}
@@ -350,7 +351,7 @@ public class ConsultationController {
return R.ok(stats);
} catch (Exception e) {
log.error("获取会诊时限统计失败", e);
return R.fail("获取会诊时限统计失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.consultation.get_time_stats_failed", e.getMessage()));
}
}

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.cssd.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.cssd.domain.*;
import com.healthlink.his.cssd.service.*;
import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;
@@ -46,7 +47,7 @@ public class CssdController {
LambdaQueryWrapper<CssdTray> tw = new LambdaQueryWrapper<>();
tw.eq(CssdTray::getTrayCode, trayCode);
CssdTray tray = trayService.getOne(tw);
if (tray == null) return R.fail("器械包不存在: " + trayCode);
if (tray == null) return R.fail(MessageUtils.message("his.cssd.tray_not_found", trayCode));
// 更新器械包状态
Map<String, String> statusFlow = Map.of(
@@ -113,7 +114,7 @@ public class CssdController {
}
@PutMapping("/sterilize/complete/{id}") @Transactional(rollbackFor=Exception.class)
public R<?> completeBatch(@PathVariable Long id, @RequestBody Map<String, Object> params) {
CssdSterilizeBatch b = batchService.getById(id); if (b == null) return R.fail("批次不存在");
CssdSterilizeBatch b = batchService.getById(id); if (b == null) return R.fail(MessageUtils.message("his.cssd.batch_not_found"));
b.setEndTime(new Date());
b.setBiologicalResult((String) params.getOrDefault("biologicalResult", "PASS"));
b.setChemicalResult((String) params.getOrDefault("chemicalResult", "PASS"));
@@ -123,9 +124,9 @@ public class CssdController {
}
@PutMapping("/sterilize/release/{id}") @Transactional(rollbackFor=Exception.class)
public R<?> releaseBatch(@PathVariable Long id, @RequestParam("releaseBy") String releaseBy) {
CssdSterilizeBatch b = batchService.getById(id); if (b == null) return R.fail("批次不存在");
CssdSterilizeBatch b = batchService.getById(id); if (b == null) return R.fail(MessageUtils.message("his.cssd.batch_not_found"));
if (!"PASS".equals(b.getBiologicalResult()) || !"PASS".equals(b.getChemicalResult()) || !"PASS".equals(b.getPhysicalResult())) {
return R.fail("三项监测未全部合格,禁止释放");
return R.fail(MessageUtils.message("his.cssd.monitor_not_passed"));
}
b.setBatchStatus("RELEASED"); b.setReleaseBy(releaseBy); b.setReleaseTime(new Date());
batchService.updateById(b); return R.ok(b);

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.datacollection.appservice.impl;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.quality.service.IBusinessAnalyticsService;
import com.healthlink.his.quality.domain.BusinessAnalytics;
import com.healthlink.his.web.datacollection.appservice.IDataCollectionAppService;
@@ -43,7 +44,7 @@ public class DataCollectionAppServiceImpl implements IDataCollectionAppService {
log.error("临床数据采集失败", e);
result.put("status", "error");
result.put("message", "采集失败: " + e.getMessage());
return R.fail("采集失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.datacollect.collect_failed", e.getMessage()));
}
return R.ok(result);
}
@@ -71,7 +72,7 @@ public class DataCollectionAppServiceImpl implements IDataCollectionAppService {
log.error("运营数据采集失败", e);
result.put("status", "error");
result.put("message", "采集失败: " + e.getMessage());
return R.fail("采集失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.datacollect.collect_failed", e.getMessage()));
}
return R.ok(result);
}

View File

@@ -401,7 +401,7 @@ public class DeviceManageAppServiceImpl implements IDeviceManageAppService {
importDto.getRetailPrice(), importDto.getMaximumRetailPrice(), orgId,
CommonConstants.TableName.ADM_DEVICE_DEFINITION, deviceDefinition.getId());
}
return R.ok(null, "导入成功!");
return R.ok(null, MessageUtils.message("his.device.import_success"));
}
/**
@@ -427,12 +427,12 @@ public class DeviceManageAppServiceImpl implements IDeviceManageAppService {
if (!deviceRequestList.isEmpty()) {
if (deviceRequestList.stream()
.allMatch(x -> x.getStatusEnum().equals(RequestStatus.COMPLETED.getValue()))) {
return R.ok(1, "医生开过该耗材,不可编辑");
return R.ok(1, MessageUtils.message("his.device.used_by_doctor"));
} else {
// 校验是否可以编辑
boolean result = supplyRequestService.verifyAbleEdit(deviceId);
if (result) {
return R.ok(2, "该耗材已经入库过,不可编辑");
return R.ok(2, MessageUtils.message("his.device.already_in_stock"));
}
}
}
@@ -556,7 +556,7 @@ public class DeviceManageAppServiceImpl implements IDeviceManageAppService {
}
}
if (!fieldValidateMsgList.isEmpty()) {
return R.fail("导入失败!器材信息填写有误:" + String.join(" ", fieldValidateMsgList));
return R.fail(MessageUtils.message("import.fail.field.validate", "器材", String.join(" ", fieldValidateMsgList)));
}
// 重复校验(文件行重复)
List<String> lineRepeatedValidateMsgList = new ArrayList<>();
@@ -570,7 +570,7 @@ public class DeviceManageAppServiceImpl implements IDeviceManageAppService {
}
}
if (!lineRepeatedValidateMsgList.isEmpty()) {
return R.fail("导入失败!文件中存在重复器材:" + String.join(" ", lineRepeatedValidateMsgList));
return R.fail(MessageUtils.message("import.fail.line.duplicate", "器材", String.join(" ", lineRepeatedValidateMsgList)));
}
// 重复校验(文件与数据库重复)
List<String> dbRepeatedValidateMsgList = new ArrayList<>();
@@ -585,7 +585,7 @@ public class DeviceManageAppServiceImpl implements IDeviceManageAppService {
}
}
if (!dbRepeatedValidateMsgList.isEmpty()) {
return R.fail("导入失败!系统中存在重复器材:" + String.join(" ", dbRepeatedValidateMsgList));
return R.fail(MessageUtils.message("import.fail.db.duplicate", "器材", String.join(" ", dbRepeatedValidateMsgList)));
}
return R.ok();
}

View File

@@ -542,7 +542,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
.eq(ActivityDefinition::getBusNo, activityDefinition.getBusNo())
);
if (!existingDefinitions.isEmpty()) {
return R.fail(null, "诊疗编码已存在:" + activityDefinition.getBusNo());
return R.fail(null, MessageUtils.message("his.diag.code_exists", activityDefinition.getBusNo()));
}
if (activityDefinitionService.addDiagnosisTreatment(activityDefinition)) {
@@ -612,7 +612,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
importDto.getMaximumRetailPrice(), orgId, CommonConstants.TableName.WOR_ACTIVITY_DEFINITION,
activityDefinition.getId());
}
return R.ok(null, "导入成功!");
return R.ok(null, MessageUtils.message("his.diag.import_success"));
}
/**
@@ -639,7 +639,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
if (!serviceRequestList.isEmpty()) {
if (serviceRequestList.stream().anyMatch(
serviceRequest -> RequestStatus.COMPLETED.getValue().equals(serviceRequest.getStatusEnum()))) {
return R.ok(1, "医生开过该诊疗项目,不可编辑");
return R.ok(1, MessageUtils.message("his.diag.used_by_doctor"));
}
}
return R.ok();
@@ -655,7 +655,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
@Override
public R<?> updatePricingFlag(List<Long> ids, Integer pricingFlag) {
if (ids == null || ids.isEmpty()) {
return R.fail(null, "请选择要设置的诊疗项目");
return R.fail(null, MessageUtils.message("his.diag.select_items"));
}
List<ActivityDefinition> activityDefinitionList = new CopyOnWriteArrayList<>();
@@ -743,7 +743,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
}
}
if (!fieldValidateMsgList.isEmpty()) {
return R.fail("导入失败!诊疗信息填写有误:" + String.join(" ", fieldValidateMsgList));
return R.fail(MessageUtils.message("import.fail.field.validate", "诊疗", String.join(" ", fieldValidateMsgList)));
}
// 重复校验(文件行重复)
List<String> lineRepeatedValidateMsgList = new ArrayList<>();
@@ -758,7 +758,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
}
}
if (!lineRepeatedValidateMsgList.isEmpty()) {
return R.fail("导入失败!文件中存在重复诊疗:" + String.join(" ", lineRepeatedValidateMsgList));
return R.fail(MessageUtils.message("import.fail.line.duplicate", "诊疗", String.join(" ", lineRepeatedValidateMsgList)));
}
// 重复校验(文件与数据库重复)
List<String> dbRepeatedValidateMsgList = new ArrayList<>();
@@ -771,7 +771,7 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
}
}
if (!dbRepeatedValidateMsgList.isEmpty()) {
return R.fail("导入失败!系统中存在重复诊疗:" + String.join(" ", dbRepeatedValidateMsgList));
return R.fail(MessageUtils.message("import.fail.db.duplicate", "诊疗", String.join(" ", dbRepeatedValidateMsgList)));
}
return R.ok();
}

View File

@@ -496,7 +496,7 @@ public class MedicationManageAppServiceImpl implements IMedicationManageAppServi
importDto.getRetailPrice(), importDto.getMaximumRetailPrice(), orgId,
CommonConstants.TableName.MED_MEDICATION_DEFINITION, medicationDefinition.getId());
}
return R.ok(null, "导入成功!");
return R.ok(null, MessageUtils.message("his.medication.import_success"));
}
/**
@@ -523,12 +523,12 @@ public class MedicationManageAppServiceImpl implements IMedicationManageAppServi
if (!medicationRequestList.isEmpty()) {
if (medicationRequestList.stream()
.allMatch(x -> x.getStatusEnum().equals(RequestStatus.COMPLETED.getValue()))) {
return R.ok(1, "医生开过该药品,不可编辑");
return R.ok(1, MessageUtils.message("his.medication.used_by_doctor"));
} else {
// 校验是否可以编辑
boolean result = supplyRequestService.verifyAbleEdit(medicationId);
if (result) {
return R.ok(2, "该药品已经入库过,不可编辑");
return R.ok(2, MessageUtils.message("his.medication.already_in_stock"));
}
}
}
@@ -730,7 +730,7 @@ public class MedicationManageAppServiceImpl implements IMedicationManageAppServi
}
}
if (!fieldValidateMsgList.isEmpty()) {
return R.fail("导入失败!药品信息填写有误:" + String.join(" ", fieldValidateMsgList) + " ■ ※如遇到模板中不存在的字段,请重新下载模板");
return R.fail(MessageUtils.message("import.fail.field.validate", "药品", String.join(" ", fieldValidateMsgList) + " ■ ※如遇到模板中不存在的字段,请重新下载模板"));
}
// 重复校验(文件行重复)
List<String> lineRepeatedValidateMsgList = new ArrayList<>();
@@ -747,7 +747,7 @@ public class MedicationManageAppServiceImpl implements IMedicationManageAppServi
}
}
if (!lineRepeatedValidateMsgList.isEmpty()) {
return R.fail("导入失败!文件中存在重复药品:" + String.join(" ", lineRepeatedValidateMsgList));
return R.fail(MessageUtils.message("import.fail.line.duplicate", "药品", String.join(" ", lineRepeatedValidateMsgList)));
}
// 重复校验(文件与数据库重复)
List<String> dbRepeatedValidateMsgList = new ArrayList<>();
@@ -769,7 +769,7 @@ public class MedicationManageAppServiceImpl implements IMedicationManageAppServi
}
}
if (!dbRepeatedValidateMsgList.isEmpty()) {
return R.fail("导入失败!系统中存在重复药品:" + String.join(" ", dbRepeatedValidateMsgList));
return R.fail(MessageUtils.message("import.fail.db.duplicate", "药品", String.join(" ", dbRepeatedValidateMsgList)));
}
return R.ok();
}

View File

@@ -124,7 +124,7 @@ public class SupplierManagementAppServiceImpl implements ISupplierManagementAppS
List<Supplier> supplierList = supplierService.getsupplierList(supplierUpDto.getName(),
supplierUpDto.getAddress(), supplierUpDto.getTypeEnum());
if(!supplierList.isEmpty()){
throw new ServiceException("数据已添加,请勿重复添加");
throw new ServiceException(MessageUtils.message("data.duplicate.add"));
}
Supplier supplierInfo = new Supplier();

View File

@@ -244,7 +244,7 @@ public class DepartmentReceiptApprovalServiceImpl implements IDepartmentReceiptA
if (supplyItemDetailDto.getItemUnit().equals(supplyItemDetailDto.getUnitCode())) {
if (minQuantity.compareTo(supplyItemDetailDto.getItemQuantity()) < 0) {
// 库存数量不足
return R.fail(MessageUtils.createMessage("操作失败,库存数量不足", null));
return R.fail(MessageUtils.message("inventory.stock.insufficient"));
} else {
// 仓库库存-(退货数量*拆零比)
minQuantity = minQuantity.subtract(
@@ -253,7 +253,7 @@ public class DepartmentReceiptApprovalServiceImpl implements IDepartmentReceiptA
} else if (supplyItemDetailDto.getItemUnit().equals(supplyItemDetailDto.getMinUnitCode())) {
if (minQuantity.compareTo(supplyItemDetailDto.getItemQuantity()) < 0) {
// 库存数量不足
return R.fail(MessageUtils.createMessage("操作失败,库存数量不足", null));
return R.fail(MessageUtils.message("inventory.stock.insufficient"));
} else {
// 供应申请的物品计量单位与最小单位相同
// 仓库库存-退货数量
@@ -330,7 +330,7 @@ public class DepartmentReceiptApprovalServiceImpl implements IDepartmentReceiptA
// if (supplyItemDetailDto.getItemUnit().equals(supplyItemDetailDto.getUnitCode())) {
// if (minQuantitySource.compareTo(supplyItemDetailDto.getItemQuantity()) < 0) {
// // 库存数量不足
// return R.fail(MessageUtils.createMessage("操作失败,库存数量不足", null));
// return R.fail(MessageUtils.message("inventory.stock.insufficient"));
// } else {
// // 源仓库库存-(领用数量*拆零比)
// minQuantitySource = minQuantitySource.subtract(
@@ -339,7 +339,7 @@ public class DepartmentReceiptApprovalServiceImpl implements IDepartmentReceiptA
// } else if (supplyItemDetailDto.getItemUnit().equals(supplyItemDetailDto.getMinUnitCode())) {
// if (minQuantitySource.compareTo(supplyItemDetailDto.getItemQuantity()) < 0) {
// // 库存数量不足
// return R.fail(MessageUtils.createMessage("操作失败,库存数量不足", null));
// return R.fail(MessageUtils.message("inventory.stock.insufficient"));
// } else {
// // 供应申请的物品计量单位与最小单位相同
// // 源仓库库存-领用数量
@@ -687,7 +687,7 @@ public class DepartmentReceiptApprovalServiceImpl implements IDepartmentReceiptA
if (supplyItemDetailDto.getItemUnit().equals(supplyItemDetailDto.getUnitCode())) {
if (minQuantity.compareTo(supplyItemDetailDto.getItemQuantity()) < 0) {
// 库存数量不足
return R.fail(MessageUtils.createMessage("操作失败,库存数量不足", null));
return R.fail(MessageUtils.message("inventory.stock.insufficient"));
} else {
// 源仓库库存-(退库数量*拆零比)
minQuantity = minQuantity.subtract(
@@ -696,7 +696,7 @@ public class DepartmentReceiptApprovalServiceImpl implements IDepartmentReceiptA
} else if (supplyItemDetailDto.getItemUnit().equals(supplyItemDetailDto.getMinUnitCode())) {
if (minQuantity.compareTo(supplyItemDetailDto.getItemQuantity()) < 0) {
// 库存数量不足
return R.fail(MessageUtils.createMessage("操作失败,库存数量不足", null));
return R.fail(MessageUtils.message("inventory.stock.insufficient"));
} else {
// 供应申请的物品计量单位与最小单位相同
// 源仓库库存-退库数量

View File

@@ -232,7 +232,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 医嘱定价来源
String orderPricingSource = TenantOptionUtil.getOptionContent(TenantOptionDict.ORDER_PRICING_SOURCE);
if (StringUtils.isEmpty(orderPricingSource) && StringUtils.isEmpty(orderPricing)) {
throw new ServiceException("租户配置项【医嘱定价来源】未配置");
throw new ServiceException(MessageUtils.message("advice.tenant.config.not.configured"));
} else if (StringUtils.isNotEmpty(orderPricing)) {
orderPricingSource = orderPricing;
}
@@ -562,7 +562,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 🔧 BugFix#333/335/336: 参数非空校验
if (adviceSaveParam == null) {
log.error("BugFix#333: adviceSaveParam 为 null");
return R.fail(null, "请求参数为空,请刷新页面后重试");
return R.fail(null, MessageUtils.message("advice.param.empty"));
}
// 患者挂号对应的科室id
@@ -573,7 +573,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 🔧 BugFix#333: 医嘱列表非空校验
if (adviceSaveList == null || adviceSaveList.isEmpty()) {
log.error("BugFix#333: adviceSaveList 为 null 或空adviceOpType={}", adviceOpType);
return R.fail(null, "医嘱列表为空,请刷新页面后重试");
return R.fail(null, MessageUtils.message("advice.list.empty"));
}
// 🔍 Debug日志: 记录请求入口
@@ -631,7 +631,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (adviceSaveDto.getEncounterId() == null) {
log.error("encounterId为null无法保存医嘱, dbOpType={}, requestId={}, adviceType={}",
adviceSaveDto.getDbOpType(), adviceSaveDto.getRequestId(), adviceSaveDto.getAdviceType());
return R.fail(null, "就诊信息不完整,请重新选择患者后再试");
return R.fail(null, MessageUtils.message("advice.encounter.incomplete"));
}
// 如果patientId为null尝试从encounter获取
@@ -644,7 +644,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
adviceSaveDto.getEncounterId(), encounter.getPatientId());
} else {
log.error("无法获取patientId: encounterId={}", adviceSaveDto.getEncounterId());
return R.fail(null, "无法获取患者信息,请重新选择患者");
return R.fail(null, MessageUtils.message("advice.patient.not.found"));
}
}
@@ -662,7 +662,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
encounterCheck.getStatusEnum() != EncounterStatus.COMPLETED.getValue()) {
log.error("BugFix#338: 患者未接诊,禁止划价/保存医嘱encounterId={}, status={}",
adviceSaveDto.getEncounterId(), encounterCheck.getStatusEnum());
return R.fail(null, "患者尚未接诊,无法保存医嘱。请先完成接诊操作!");
return R.fail(null, MessageUtils.message("advice.encounter.not.started"));
}
}
}
@@ -1015,7 +1015,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (chargeItemList != null && !chargeItemList.isEmpty()) {
for (ChargeItem ci : chargeItemList) {
if (ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum())) {
throw new ServiceException("已收费的项目无法删除,请刷新页面后重试");
throw new ServiceException(MessageUtils.message("advice.charged.item.cannot.delete"));
}
}
}
@@ -1200,7 +1200,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (!existing.getEncounterId().equals(adviceSaveDto.getEncounterId())) {
log.error("Bug#643: 越权操作,医嘱 encounterId={} 与请求 encounterId={} 不匹配",
existing.getEncounterId(), adviceSaveDto.getEncounterId());
throw new ServiceException("无权操作此医嘱");
throw new ServiceException(MessageUtils.message("advice.no.permission.operate"));
}
if (RequestStatus.ACTIVE.getValue().equals(existing.getStatusEnum())) {
isRollback = true;
@@ -1528,7 +1528,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (chargeItemList != null && !chargeItemList.isEmpty()) {
for (ChargeItem ci : chargeItemList) {
if (ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum())) {
throw new ServiceException("已收费的项目无法删除,请刷新页面后重试");
throw new ServiceException(MessageUtils.message("advice.charged.item.cannot.delete"));
}
}
}
@@ -1706,7 +1706,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (!existingDevice.getEncounterId().equals(adviceSaveDto.getEncounterId())) {
log.error("Bug#643: 越权操作(耗材),医嘱 encounterId={} 与请求 encounterId={} 不匹配",
existingDevice.getEncounterId(), adviceSaveDto.getEncounterId());
throw new ServiceException("无权操作此医嘱");
throw new ServiceException(MessageUtils.message("advice.no.permission.operate"));
}
if (RequestStatus.ACTIVE.getValue().equals(existingDevice.getStatusEnum())) {
deviceIsRollback = true;
@@ -1920,7 +1920,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (chargeItemList != null && !chargeItemList.isEmpty()) {
for (ChargeItem ci : chargeItemList) {
if (ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum())) {
throw new ServiceException("已收费的项目无法删除,请刷新页面后重试");
throw new ServiceException(MessageUtils.message("advice.charged.item.cannot.delete"));
}
}
}
@@ -2080,7 +2080,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
&& !DbOpType.DELETE.getCode().equals(adviceSaveDto.getDbOpType())) {
Long effectiveOrgId = adviceSaveDto.getEffectiveOrgId();
if (effectiveOrgId == null) {
throw new ServiceException("诊疗项目必须选择执行科室");
throw new ServiceException(MessageUtils.message("advice.treatment.must.select.dept"));
}
}
serviceRequest = new ServiceRequest();
@@ -2361,7 +2361,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
if (chargeItemList != null && !chargeItemList.isEmpty()) {
for (ChargeItem chargeItem : chargeItemList) {
if (ChargeItemStatus.BILLED.getValue().equals(chargeItem.getStatusEnum())) {
throw new ServiceException("已收费的项目无法签退,请刷新页面后重试");
throw new ServiceException(MessageUtils.message("advice.charged.item.cannot.checkout"));
}
}

View File

@@ -140,8 +140,8 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
.setSourceEnum(ConditionDefinitionSource.TRADITIONAL_CHINESE_MEDICINE_SYNDROME_CATALOG.getValue());
QueryWrapper<ConditionDefinition> queryWrapper = HisQueryUtils.buildQueryWrapper(conditionDefinition, searchKey,
new HashSet<>(Arrays.asList("name", "py_str", "wb_str")), null);
// 设置排序
queryWrapper.orderByDesc("update_time");
// 设置排序(与诊断目录页保持一致,按编码升序,确保取到原始标准编码记录)
queryWrapper.orderByAsc("condition_code");
// 诊断信息
Page<ConditionDefinitionMetadata> conditionDefinitionMetadataPage = HisPageUtils
.selectPage(conditionDefinitionMapper, queryWrapper, pageNo, pageSize, ConditionDefinitionMetadata.class);
@@ -444,7 +444,7 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
if (chargeItemList != null && !chargeItemList.isEmpty()) {
for (ChargeItem ci : chargeItemList) {
if (ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum())) {
return R.fail("已收费的项目无法删除,请刷新页面后重试");
return R.fail(MessageUtils.message("advice.charged.item.cannot.delete"));
}
}
}
@@ -767,10 +767,10 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
// 诊断id集合
List<Long> conditionIds = doctorStationChineseMedicalAppMapper.getConditionIds(syndromeGroupNo);
if (conditionIds.isEmpty()) {
return R.fail("数据已被删除,请刷新页面");
return R.fail(MessageUtils.message("chinese.medical.data.deleted.refresh"));
}
if (doctorStationChineseMedicalAppMapper.getAdviceNumByConditionIds(conditionIds) > 0) {
return R.fail("所选诊断已经存在医嘱记录,不允许删除");
return R.fail(MessageUtils.message("chinese.medical.diagnosis.has.advice"));
}
for (Long conditionId : conditionIds) {
iConditionService.removeById(conditionId);

View File

@@ -493,7 +493,7 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
public R<?> delEncounterDiagnosis(Long conditionId) {
// 对应诊断开过医嘱不允许删除
if (doctorStationDiagnosisAppMapper.getAdviceNumByConditionId(conditionId) > 0) {
return R.fail("所选诊断已经存在医嘱记录,不允许删除");
return R.fail(MessageUtils.message("his.diagnosis.has_orders_no_delete"));
}
iConditionService.removeById(conditionId);
iEncounterDiagnosisService
@@ -589,14 +589,14 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
// 检查卡片编号唯一性(新增时检查,编辑时排除当前记录)
String cardNo = infectiousDiseaseReportDto.getCardNo();
if (cardNo == null || cardNo.trim().isEmpty()) {
return R.fail("卡片编号不能为空");
return R.fail(MessageUtils.message("his.diagnosis.card_no_required"));
}
cardNo = cardNo.trim();
LambdaQueryWrapper<InfectiousDiseaseReport> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(InfectiousDiseaseReport::getCardNo, cardNo);
long count = iInfectiousDiseaseReportService.count(queryWrapper);
if (count > 0) {
return R.fail("卡片编号已存在,请重新生成");
return R.fail(MessageUtils.message("his.diagnosis.card_no_exists"));
}
// 转换为实体

View File

@@ -467,7 +467,7 @@ public class DoctorStationElepPrescriptionServiceImpl extends
// 处方状态
item.setStatusEnum(RequestStatus.ACTIVE.getValue());
} else {
return R.fail("选择了不能签发的处方");
return R.fail(MessageUtils.message("his.elep_prescription.cannot_issue"));
}
}
// 签发处方

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.doctorstation.appservice.impl;
import com.core.common.core.domain.R;
import com.core.common.core.redis.RedisCache;
import com.core.common.enums.DelFlag;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.common.enums.DbOpType;
import com.healthlink.his.administration.service.IAccountService;
@@ -540,7 +541,7 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
if (inspectionLabApply == null) {
log.warn("未找到申请单号为 [{}] 的检验申请单", applyNo);
return R.fail("未找到对应的检验申请单");
return R.fail(MessageUtils.message("his.lab_apply.not_found"));
}
// 2. 获取当前登录用户和时间
@@ -572,7 +573,7 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
log.debug("成功删除申请单号为 [{}] 的检验申请单及相关数据,更新人:{},更新时间:{}",
applyNo, currentUsername, currentTime);
return R.ok("删除成功");
return R.ok(MessageUtils.message("msg.success"));
} catch (Exception e) {
log.error("删除检验申请单 [{}] 时发生异常,事务将回滚", applyNo, e);

View File

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.core.domain.model.LoginUser;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.administration.domain.Encounter;
import com.healthlink.his.administration.domain.EncounterParticipant;
@@ -156,13 +157,13 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
// 检查就诊记录是否存在
Encounter encounter = encounterMapper.selectById(encounterId);
if (encounter == null) {
return R.fail("就诊记录不存在");
return R.fail(MessageUtils.message("his.doctor_station.encounter_not_found"));
}
// 检查患者状态,防止重复接诊
Integer currentStatus = encounter.getStatusEnum();
if (EncounterStatus.IN_PROGRESS.getValue().equals(currentStatus)) {
return R.fail("已接诊,请勿重复点击,已为您刷新");
return R.fail(MessageUtils.message("his.doctor_station.already_admitted_refresh"));
}
// 允许从「待诊/暂离/诊毕」重新接诊(用于队列弹窗的完诊患者重新进入在诊)
@@ -184,9 +185,9 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
// 重新查询当前状态
encounter = encounterMapper.selectById(encounterId);
if (EncounterStatus.IN_PROGRESS.getValue().equals(encounter.getStatusEnum())) {
return R.fail("已接诊,请勿重复接诊");
return R.fail(MessageUtils.message("his.doctor_station.already_admitted"));
}
return R.fail("接诊失败,请刷新后重试");
return R.fail(MessageUtils.message("his.doctor_station.admit_failed_retry"));
}
// 先把之前的接诊记录更新为已完成
@@ -259,7 +260,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
// 1. 检查当前患者状态
Encounter encounter = encounterMapper.selectById(encounterId);
if (encounter == null) {
return R.fail("就诊记录不存在");
return R.fail(MessageUtils.message("his.doctor_station.encounter_not_found"));
}
// 检查患者状态,防止重复完诊
@@ -267,11 +268,11 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
if (EncounterStatus.DISCHARGED.getValue().equals(currentStatus) ||
EncounterStatus.COMPLETED.getValue().equals(currentStatus)) {
// 患者已完成就诊,返回特定提示
return R.fail("患者已完成就诊,已为您自动刷新患者列表");
return R.fail(MessageUtils.message("his.doctor_station.patient_already_completed"));
}
if (!EncounterStatus.IN_PROGRESS.getValue().equals(currentStatus)) {
return R.fail("非就诊中患者不能完诊");
return R.fail(MessageUtils.message("his.doctor_station.not_in_progress_complete"));
}
// 2. 查找队列项(限定当天,避免复诊患者匹配到历史队列记录)
@@ -382,7 +383,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
.set(Encounter::getFirstEnum, firstEnum) // 直接在此处更新字段
.set(Encounter::getUpdateTime, now));
if (update <= 0) return R.fail("完诊失败");
if (update <= 0) return R.fail(MessageUtils.message("his.doctor_station.complete_failed"));
// 5. 审计日志sys_oper_log
try {
@@ -405,7 +406,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
// 审计日志失败不影响主流程
}
return R.ok("就诊完成");
return R.ok(MessageUtils.message("his.doctor_station.visit_completed"));
}
/**
@@ -464,7 +465,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
boolean isEmpty = ObjectUtil.isAllEmpty(emrDetailResult, diagnosisResult, adviceResult, symptom, illness, tcmPrescriptionResult);
if (!isEmpty) {
return R.fail("该患者已产生业务数据(病历、诊断、处方等),无法直接取消接诊。请先删除相关数据后再操作。");
return R.fail(MessageUtils.message("his.doctor_station.cancel_admit_has_data"));
}
//2.取消接诊,患者重新回到患者队列待诊中
@@ -472,10 +473,10 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
.set(Encounter::getStatusEnum, EncounterStatus.PLANNED.getValue())
.set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.TRIAGED.getValue()));
return update > 0 ? R.ok("取消接诊成功") : R.fail("取消接诊失败,请刷新后重试");
return update > 0 ? R.ok(MessageUtils.message("his.doctor_station.cancel_admit_success")) : R.fail(MessageUtils.message("his.doctor_station.cancel_admit_failed_retry"));
} catch (Exception e) {
log.error("取消接诊时发生错误encounterId={}", encounterId, e);
return R.fail("取消接诊失败:" + e.getMessage());
return R.fail(MessageUtils.message("his.doctor_station.cancel_admit_error", e.getMessage()));
}
}
@@ -560,12 +561,12 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
// 1. 校验就诊记录是否存在
Encounter encounter = encounterMapper.selectById(encounterId);
if (encounter == null) {
return R.fail("就诊记录不存在");
return R.fail(MessageUtils.message("his.doctor_station.encounter_not_found"));
}
// 2. 校验状态仅「在诊IN_PROGRESS=2」可重排
if (!EncounterStatus.IN_PROGRESS.getValue().equals(encounter.getStatusEnum())) {
return R.fail("仅「在诊」状态的患者可执行过号重排");
return R.fail(MessageUtils.message("his.doctor_station.only_in_progress_reorder"));
}
// 3. 核心更新:改回待诊+更新missed_time
@@ -580,7 +581,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
.eq(Encounter::getStatusEnum, EncounterStatus.IN_PROGRESS.getValue())); // 防并发
if (updateCount == 0) {
return R.fail("过号重排失败:状态更新异常");
return R.fail(MessageUtils.message("his.doctor_station.reorder_failed"));
}
// 4. 同步更新接诊参与记录
@@ -589,7 +590,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
.eq(EncounterParticipant::getTypeCode, ParticipantType.ADMITTER.getCode())
.set(EncounterParticipant::getStatusEnum, EncounterActivityStatus.COMPLETED.getValue()));
return R.ok("过号重排成功");
return R.ok(MessageUtils.message("his.doctor_station.reorder_success"));
}
}

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.doctorstation.appservice.impl;
import com.core.common.core.domain.R;
import com.core.common.utils.DateUtils;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.common.enums.*;
import com.healthlink.his.common.utils.EnumUtils;
import com.healthlink.his.web.doctorstation.appservice.IDoctorStationPtDetailsAppService;
@@ -36,7 +37,7 @@ public class DoctorStationPtDetailsAppServiceImpl implements IDoctorStationPtDet
public R<?> getPtDetails(Long encounterId) {
// 检查参数
if (encounterId == null) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
// 收费状态List(1:待收费,2:待结算,5:已结算)
@@ -54,7 +55,7 @@ public class DoctorStationPtDetailsAppServiceImpl implements IDoctorStationPtDet
ParticipantType.ADMITTER.getCode(), statusList);
if (patientDetailsDto == null) {
return R.fail("未找到患者详情信息");
return R.fail(MessageUtils.message("his.doctor_station.patient_detail_not_found"));
}
// 住院的场合,获取现在时间,计算住院天数

View File

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.common.constant.CommonConstants;
import com.healthlink.his.common.enums.*;
@@ -245,19 +246,19 @@ public class TodayOutpatientServiceImpl implements ITodayOutpatientService {
public R<?> batchUpdatePatientStatus(List<Long> encounterIds, Integer targetStatus,
HttpServletRequest request) {
if (ObjectUtil.isEmpty(encounterIds)) {
return R.fail("就诊记录ID列表不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_ids_required"));
}
// 验证状态值
if (EncounterStatus.getByValue(targetStatus) == null) {
return R.fail("无效的状态值");
return R.fail(MessageUtils.message("his.doctor_station.invalid_status"));
}
// 执行批量更新
int updated = todayOutpatientMapper.batchUpdatePatientStatus(
encounterIds, targetStatus, SecurityUtils.getLoginUser().getUserId(), new Date());
return updated > 0 ? R.ok("更新成功") : R.fail("更新失败");
return updated > 0 ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@Override

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.doctorstation.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.common.enums.BindingType;
import com.healthlink.his.template.domain.DoctorPhrase;
import com.healthlink.his.web.doctorstation.appservice.IDoctorPhraseAppService;
@@ -29,7 +30,7 @@ public class DoctorPhraseController {
} catch (Exception e) {
// 系统异常使用error级别日志
log.error("获取医生常用语列表系统异常", e);
return R.fail("获取医生常用语列表失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.phrase.get_list_failed", e.getMessage()));
}
}
@@ -49,7 +50,7 @@ public class DoctorPhraseController {
} catch (Exception e) {
// 系统异常使用error级别日志
log.error("查询医生常用语系统异常", e);
return R.fail("查询医生常用语失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.phrase.query_failed", e.getMessage()));
}
}
@@ -64,9 +65,9 @@ public class DoctorPhraseController {
try {
Boolean result = doctorPhraseAppService.addDoctorPhrase(doctorPhrase);
if (result != null && result) {
return R.ok("新增成功");
return R.ok(MessageUtils.message("msg.success"));
} else {
return R.fail("新增失败");
return R.fail(MessageUtils.message("msg.failure"));
}
} catch (IllegalArgumentException e) {
// 参数错误异常使用warn级别日志
@@ -75,7 +76,7 @@ public class DoctorPhraseController {
} catch (Exception e) {
// 系统异常使用error级别日志
log.error("新增医生常用语系统异常", e);
return R.fail("新增失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.phrase.add_failed", e.getMessage()));
}
}
@@ -90,9 +91,9 @@ public class DoctorPhraseController {
try {
Boolean result = doctorPhraseAppService.updateDoctorPhrase(doctorPhrase);
if (result != null && result) {
return R.ok("更新成功");
return R.ok(MessageUtils.message("msg.success"));
} else {
return R.fail("更新失败");
return R.fail(MessageUtils.message("msg.failure"));
}
} catch (IllegalArgumentException e) {
// 参数错误异常使用warn级别日志
@@ -105,7 +106,7 @@ public class DoctorPhraseController {
} catch (Exception e) {
// 系统异常使用error级别日志
log.error("更新医生常用语系统异常", e);
return R.fail("更新失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.phrase.update_failed", e.getMessage()));
}
}
@@ -120,9 +121,9 @@ public class DoctorPhraseController {
try {
Boolean result = doctorPhraseAppService.deleteDoctorPhrase(DoctorPhraseId);
if (result != null && result) {
return R.ok("删除成功");
return R.ok(MessageUtils.message("msg.success"));
} else {
return R.fail("删除失败");
return R.fail(MessageUtils.message("msg.failure"));
}
} catch (IllegalArgumentException e) {
// 参数错误异常使用warn级别日志
@@ -135,7 +136,7 @@ public class DoctorPhraseController {
} catch (Exception e) {
// 系统异常使用error级别日志
log.error("删除医生常用语系统异常", e);
return R.fail("删除失败: " + e.getMessage());
return R.fail(MessageUtils.message("his.phrase.delete_failed", e.getMessage()));
}
}

View File

@@ -4,6 +4,7 @@
package com.healthlink.his.web.doctorstation.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.StringUtils;
import com.healthlink.his.common.enums.Whether;
import com.healthlink.his.web.doctorstation.appservice.IDoctorStationMainAppService;
@@ -65,13 +66,13 @@ public class DoctorStationMainController {
@GetMapping(value = "/receive-encounter")
public R<?> receiveEncounter(@RequestParam(value = "encounterId", required = false) String encounterId) {
if (encounterId == null || "undefined".equals(encounterId) || "null".equals(encounterId)) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
try {
Long id = Long.parseLong(encounterId);
return iDoctorStationMainAppService.receiveEncounter(id);
} catch (NumberFormatException e) {
return R.fail("就诊ID格式错误");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_format_error"));
}
}
@@ -84,13 +85,13 @@ public class DoctorStationMainController {
@GetMapping(value = "/leave-encounter")
public R<?> leaveEncounter(@RequestParam(value = "encounterId", required = false) String encounterId) {
if (encounterId == null || "undefined".equals(encounterId) || "null".equals(encounterId)) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
try {
Long id = Long.parseLong(encounterId);
return iDoctorStationMainAppService.leaveEncounter(id);
} catch (NumberFormatException e) {
return R.fail("就诊ID格式错误");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_format_error"));
}
}
@@ -107,10 +108,10 @@ public class DoctorStationMainController {
Object firstEnumObj = params.get("firstEnum");
if (encounterIdObj == null || StringUtils.isEmpty(encounterIdObj.toString())) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
if (firstEnumObj == null) {
return R.fail("初复诊状态不能为空");
return R.fail(MessageUtils.message("his.doctor_station.first_visit_required"));
}
try {
@@ -119,7 +120,7 @@ public class DoctorStationMainController {
// 调用 Service
return iDoctorStationMainAppService.completeEncounter(id, firstEnum);
} catch (NumberFormatException e) {
return R.fail("数据格式错误ID或初复诊状态非数字");
return R.fail(MessageUtils.message("his.doctor_station.data_format_error"));
}
}
@@ -132,13 +133,13 @@ public class DoctorStationMainController {
@GetMapping(value = "/cancel-encounter")
public R<?> cancelEncounter(@RequestParam(value = "encounterId", required = false) String encounterId) {
if (encounterId == null || "undefined".equals(encounterId) || "null".equals(encounterId)) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
try {
Long id = Long.parseLong(encounterId);
return iDoctorStationMainAppService.cancelEncounter(id);
} catch (NumberFormatException e) {
return R.fail("就诊ID格式错误");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_format_error"));
}
}
@@ -152,7 +153,7 @@ public class DoctorStationMainController {
public R<?> rearrangeMissedEncounter(@RequestParam(value = "encounterId", required = false) String encounterId) {
// 1. 空值校验(和现有接口保持一致)
if (encounterId == null || "undefined".equals(encounterId) || "null".equals(encounterId)) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
try {
// 2. 字符串转Long和现有接口保持一致
@@ -161,7 +162,7 @@ public class DoctorStationMainController {
return iDoctorStationMainAppService.rearrangeMissedEncounter(id);
} catch (NumberFormatException e) {
// 4. 格式错误处理(和现有接口保持一致)
return R.fail("就诊ID格式错误");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_format_error"));
}
}

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.doctorstation.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.web.doctorstation.appservice.ITodayOutpatientService;
import com.healthlink.his.web.doctorstation.dto.TodayOutpatientPatientDto;
@@ -99,7 +100,7 @@ public class TodayOutpatientController {
@PathVariable("encounterId") Long encounterId,
HttpServletRequest request) {
if (encounterId == null) {
return R.fail("就诊记录ID不能为空");
return R.fail(MessageUtils.message("his.doctor_station.encounter_id_required"));
}
TodayOutpatientPatientDto patient = todayOutpatientService.getPatientDetail(encounterId, request);
return R.ok(patient);

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.doctorstation.utils;
import com.core.common.exception.ServiceException;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.AgeCalculatorUtil;
import com.healthlink.his.administration.domain.Organization;
import com.healthlink.his.administration.domain.Patient;
@@ -62,32 +63,32 @@ public class DoctorStationSendApplyUtil {
ActivityDefinition activityDefinition =
activityDefinitionService.getById(adviceSaveDto.getAdviceDefinitionId());
if (activityDefinition == null) {
throw new ServiceException("发起LIS或PACS请求失败诊疗信息不存在");
throw new ServiceException(MessageUtils.message("his.doctor.activity_not_found"));
}
// 查询挂号科室
Organization organization = organizationService.getById(organizationId);
if (organization == null) {
throw new ServiceException("发起LIS或PACS请求失败挂号科室信息不存在");
throw new ServiceException(MessageUtils.message("his.doctor.org_not_found"));
}
// 查询服务请求
ServiceRequest serviceRequest = serviceRequestService.getById(adviceSaveDto.getRequestId());
if (serviceRequest == null) {
throw new ServiceException("发起LIS或PACS请求失败服务请求信息不存在");
throw new ServiceException(MessageUtils.message("his.doctor.service_request_not_found"));
}
// 查询患者
Patient patient = patientService.getById(adviceSaveDto.getPatientId());
if (patient == null) {
throw new ServiceException("发起LIS或PACS请求失败患者信息不存在");
throw new ServiceException(MessageUtils.message("his.doctor.patient_not_found"));
}
// 查询开方医生
Practitioner practitioner = practitionerService.getById(adviceSaveDto.getPractitionerId());
if (practitioner == null) {
throw new ServiceException("发起LIS或PACS请求失败开方医生信息不存在");
throw new ServiceException(MessageUtils.message("his.doctor.practitioner_not_found"));
}
// 查询执行科室
Organization organizationExec = organizationService.getById(adviceSaveDto.getPositionId());
if (organizationExec == null) {
throw new ServiceException("发起LIS或PACS请求失败执行科室信息不存在");
throw new ServiceException(MessageUtils.message("his.doctor.exec_dept_not_found"));
}
// 检验发送LIS申请

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.document.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.bean.BeanUtils;
import com.healthlink.his.common.enums.AssignSeqEnum;
@@ -49,18 +50,18 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
public R<?> addDefinition(DocDefinitionDto definitionDto) {
// 1. 基础参数校验(按必填优先级排序)
if (definitionDto.getName() == null || definitionDto.getName().trim().isEmpty()) {
return R.fail("新增文书定义失败:文书名称不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_name_required"));
}
if (definitionDto.getVersion() == null || definitionDto.getVersion().trim().isEmpty()) {
return R.fail("新增文书定义失败:文书版本号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_version_required"));
}
if (definitionDto.getVueRouter() == null || definitionDto.getVueRouter().trim().isEmpty()) {
return R.fail("新增文书定义失败:文书路由不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_router_required"));
}
if (definitionDto.getUseRangeEnum() != null
&& DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum())
&& definitionDto.getOrganizationIds() == null) {
return R.fail("新增文书定义失败:科室分配时,科室不能为空");
return R.fail(MessageUtils.message("his.doc.def_dept_required"));
}
// 2. 校验"名称+版本号"唯一性(避免重复创建)
@@ -69,7 +70,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
.eq(DocDefinition::getVersion, definitionDto.getVersion().trim()).count();
if (duplicateCount > 0) {
log.warn("新增文书定义失败:名称={}、版本号={}的文书已存在", definitionDto.getName(), definitionDto.getVersion());
return R.fail("新增文书定义失败:相同名称和版本号的文书已存在,请修改后重试");
return R.fail(MessageUtils.message("his.doc.def_duplicate"));
}
// 3. 补充默认值避免null字段插入数据库
@@ -85,7 +86,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
// 校验AssignSeqUtil是否注入避免空指针
if (assignSeqUtil == null) {
log.error("新增文书定义失败AssignSeqUtil工具类未注入无法生成业务编号");
return R.fail("新增文书定义失败:系统工具类异常,无法生成业务编号");
return R.fail(MessageUtils.message("his.doc.def_tool_error"));
}
// 获取当前登录用户的医院ID
@@ -117,7 +118,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
if (!saveSuccess) {
log.error("新增文书定义失败:数据库保存异常(名称={}, 版本号={}, 业务编号={}", definitionDto.getName(), definitionDto.getVersion(),
busNo);
return R.fail("新增文书定义失败:数据库保存操作异常");
return R.fail(MessageUtils.message("his.doc.def_save_failed"));
}
// 6. 科室分配(仅当使用范围为"科室级"时执行)
@@ -131,7 +132,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
return docDefinitionOrganizationAppService.add(orgDto);
}
return R.ok("新增文书定义成功");
return R.ok(MessageUtils.message("his.doc_def.add_success"));
}
/**
@@ -141,30 +142,30 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
public R<?> updateDefinition(DocDefinitionDto definitionDto) {
// 1. 基础参数校验(修改必传字段)
if (definitionDto.getId() == null) {
return R.fail("修改文书定义失败文书ID不能为空");
return R.fail(MessageUtils.message("his.doc.def_id_required"));
}
if (definitionDto.getName() == null || definitionDto.getName().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书名称不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_name_required"));
}
if (definitionDto.getVersion() == null || definitionDto.getVersion().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书版本号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_version_required"));
}
if (definitionDto.getVueRouter() == null || definitionDto.getVueRouter().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书路由不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_router_required"));
}
if (definitionDto.getBusNo() == null || definitionDto.getBusNo().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书业务编号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc.def_bus_no_required"));
}
if (definitionDto.getUseRangeEnum() != null
&& DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum())
&& definitionDto.getOrganizationIds() == null) {
return R.fail("修改文书定义失败:科室分配时,科室不能为空");
return R.fail(MessageUtils.message("his.doc.def_dept_required"));
}
// 2. 校验文书是否存在
DocDefinition existingDoc = docDefinitionService.getById(definitionDto.getId());
if (existingDoc == null) {
log.warn("修改文书定义失败未找到ID={}的文书记录", definitionDto.getId());
return R.fail("修改文书定义失败:待修改的文书记录不存在");
return R.fail(MessageUtils.message("his.doc.def_not_found"));
}
// 3. 版本号冲突处理(版本号不一致时,转为新增逻辑)
@@ -210,7 +211,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
boolean updateSuccess = docDefinitionService.updateById(existingDoc);
if (!updateSuccess) {
log.error("修改文书定义失败数据库更新异常ID={}, 业务编号={}", definitionDto.getId(), definitionDto.getBusNo());
return R.fail("修改文书定义失败:数据库更新操作异常");
return R.fail(MessageUtils.message("his.doc.def_update_failed"));
} else {
// 7. 更新科室分配(仅当使用范围为"科室级"时执行)
DocDefinitionOrganizationDto orgDto = new DocDefinitionOrganizationDto();
@@ -226,15 +227,15 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
public R<?> deleteDefinition(Long id) {
// 1. 参数校验
if (id == null) {
return R.fail("删除文书定义失败文书ID不能为空");
return R.fail(MessageUtils.message("his.doc.def_id_required"));
}
boolean result = docDefinitionService.removeById(id);
if (result) {
log.info("删除文书定义成功ID={}", id);
return R.ok("删除文书定义成功");
return R.ok(MessageUtils.message("his.doc_def.delete_success"));
} else {
log.error("删除文书定义失败数据库删除异常ID={})", id);
return R.fail("删除文书定义失败:数据库删除操作异常");
return R.fail(MessageUtils.message("his.doc.def_delete_failed"));
}
}
@@ -286,7 +287,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
log.info("获取文书定义树形列表成功医院ID={}, 暂无匹配的文书定义", hospitalId);
}
return R.ok(treeNodes, "获取文书定义树形列表成功");
return R.ok(treeNodes, MessageUtils.message("his.doc_def.get_tree_success"));
}
/**
@@ -296,18 +297,18 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
public R<?> getDefinitionDetailById(Long id) {
// 1. 参数校验
if (id == null) {
return R.fail("获取文书定义详情失败文书ID不能为空");
return R.fail(MessageUtils.message("his.doc.def_id_required"));
}
// 2. 调用私有方法获取详情含科室ID
DocDefinitionDto docDto = getDefinitionById(id);
if (docDto == null) {
log.warn("获取文书定义详情失败未找到ID={}的文书记录", id);
return R.fail("获取文书定义详情失败:未查询到对应的文书定义信息");
return R.fail(MessageUtils.message("his.doc.def_detail_not_found"));
}
log.info("获取文书定义详情成功ID={}, 名称={}, 业务编号={}", id, docDto.getName(), docDto.getBusNo());
return R.ok(docDto, "获取文书定义详情成功");
return R.ok(docDto, MessageUtils.message("his.doc_def.get_detail_success"));
}
/**
@@ -352,10 +353,10 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
Long hospitalId = SecurityUtils.getLoginUser().getHospitalId();
if (hospitalId == null) {
log.warn("获取文书定义树形列表失败当前登录用户未关联医院ID");
return R.fail("获取文书定义树形列表失败:当前用户未关联医院,请重新登录");
return R.fail(MessageUtils.message("his.doc.def_hospital_required"));
}
if (menuEnum == null) {
return R.fail("来源类型不能为空");
return R.fail(MessageUtils.message("his.doc.def_menu_enum_required"));
}
// 2. 数据库查询文书定义列表
LambdaQueryWrapper<DocDefinition> queryWrapper = new LambdaQueryWrapper<>();

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.document.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.document.domain.DocDefinitionOrganization;
import com.healthlink.his.document.service.IDocDefinitionOrganizationService;
import com.healthlink.his.web.document.appservice.IDocDefinitionOrganizationAppService;
@@ -28,16 +29,16 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
public R<?> add(DocDefinitionOrganizationDto definitionOrganizationDto) {
// 1. 参数校验(明确错误原因,避免模糊提示)
if (definitionOrganizationDto == null) {
return R.fail("文书科室分配失败:请求参数不能为空");
return R.fail(MessageUtils.message("his.doc_org.assign_failed"));
}
if (definitionOrganizationDto.getOrganizationIds() == null || definitionOrganizationDto.getOrganizationIds().isEmpty()) {
return R.fail("文书科室分配失败科室ID列表不能为空");
return R.fail(MessageUtils.message("his.doc_org.assign_failed"));
}
if (definitionOrganizationDto.getDefinitionId() == null || definitionOrganizationDto.getDefinitionId() == 0) {
return R.fail("文书科室分配失败文书定义ID不能为空或不能为0");
return R.fail(MessageUtils.message("his.doc_org.assign_failed"));
}
if (definitionOrganizationDto.getBusNo() == null || definitionOrganizationDto.getBusNo().trim().isEmpty()) {
return R.fail("文书科室分配失败:业务编号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc_org.assign_failed"));
}
// 2. DTO转实体批量封装科室分配关系
@@ -53,11 +54,11 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
// 3. 批量新增
boolean saveSuccess = docDefinitionOrganizationService.saveBatch(organizationList);
if (saveSuccess) {
return R.ok("文书科室分配成功");
return R.ok(MessageUtils.message("his.doc_org.assign_success"));
} else {
log.error("文书科室分配新增失败文书定义ID={}, 业务编号={}",
definitionOrganizationDto.getDefinitionId(), definitionOrganizationDto.getBusNo());
return R.fail("文书科室分配失败:数据库新增操作异常");
return R.fail(MessageUtils.message("his.doc_org.assign_failed"));
}
}
@@ -68,10 +69,10 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
public R<?> delete(Long definitionId, String busNo) {
// 1. 参数校验
if (definitionId == null || definitionId == 0) {
return R.fail("文书科室分配删除失败文书定义ID不能为空或不能为0");
return R.fail(MessageUtils.message("his.doc_org.delete_failed"));
}
if (busNo == null || busNo.trim().isEmpty()) {
return R.fail("文书科室分配删除失败:业务编号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc_org.delete_failed"));
}
// 2. 构建查询条件(精准匹配文书+业务编号)
@@ -82,11 +83,11 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
// 3. 执行删除
boolean deleteSuccess = docDefinitionOrganizationService.remove(queryWrapper);
if (deleteSuccess) {
return R.ok("文书科室分配删除成功");
return R.ok(MessageUtils.message("his.doc_org.delete_success"));
} else {
log.warn("文书科室分配删除失败未找到匹配的分配关系文书定义ID={}, 业务编号={}",
definitionId, busNo);
return R.fail("文书科室分配删除失败:未找到对应的科室分配记录");
return R.fail(MessageUtils.message("his.doc_org.delete_not_found"));
}
}
@@ -97,10 +98,10 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
public R<?> getOrganizationIdlist(Long definitionId, String busNo) {
// 1. 参数校验
if (definitionId == null || definitionId == 0) {
return R.fail("文书科室分配查询失败文书定义ID不能为空或不能为0");
return R.fail(MessageUtils.message("his.doc_org.query_failed"));
}
if (busNo == null || busNo.trim().isEmpty()) {
return R.fail("文书科室分配查询失败:业务编号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc_org.query_failed"));
}
// 2. 构建查询条件
@@ -117,7 +118,7 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
log.info("文书科室分配查询成功文书定义ID={}, 业务编号={}, 分配科室数量={}",
definitionId, busNo, orgIdList.size());
return R.ok(orgIdList, "文书科室分配查询成功");
return R.ok(orgIdList, MessageUtils.message("his.doc_org.query_success"));
}
/**
@@ -127,13 +128,13 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
public R<?> updateOrganization(DocDefinitionOrganizationDto definitionOrganizationDto) {
// 1. 参数校验与add方法保持一致的校验逻辑
if (definitionOrganizationDto == null) {
return R.fail("文书科室分配更新失败:请求参数不能为空");
return R.fail(MessageUtils.message("his.doc_org.update_failed"));
}
if (definitionOrganizationDto.getDefinitionId() == null || definitionOrganizationDto.getDefinitionId() == 0) {
return R.fail("文书科室分配更新失败文书定义ID不能为空或不能为0");
return R.fail(MessageUtils.message("his.doc_org.update_failed"));
}
if (definitionOrganizationDto.getBusNo() == null || definitionOrganizationDto.getBusNo().trim().isEmpty()) {
return R.fail("文书科室分配更新失败:业务编号不能为空(或不能为空白字符)");
return R.fail(MessageUtils.message("his.doc_org.update_failed"));
}
// 2. 先删除原有分配关系
@@ -146,11 +147,11 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
if (!deleteSuccess) {
log.error("文书科室分配更新失败删除原有分配记录异常文书定义ID={}, 业务编号={}",
definitionOrganizationDto.getDefinitionId(), definitionOrganizationDto.getBusNo());
return R.fail("文书科室分配更新失败:删除原有分配记录异常");
return R.fail(MessageUtils.message("his.doc_org.update_delete_failed"));
}
}
if (definitionOrganizationDto.getOrganizationIds() == null || definitionOrganizationDto.getOrganizationIds().isEmpty()) {
return R.ok("文书科室分配更新成功");
return R.ok(MessageUtils.message("his.doc_org.update_success"));
} else {
// 3. 再新增新的分配关系
List<DocDefinitionOrganization> newOrgList = new ArrayList<>();
@@ -163,11 +164,11 @@ public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOr
}
boolean saveSuccess = docDefinitionOrganizationService.saveBatch(newOrgList);
if (saveSuccess) {
return R.ok("文书科室分配更新成功");
return R.ok(MessageUtils.message("his.doc_org.update_success"));
} else {
log.error("文书科室分配更新失败新增新分配记录异常文书定义ID={}, 业务编号={}",
definitionOrganizationDto.getDefinitionId(), definitionOrganizationDto.getBusNo());
return R.fail("文书科室分配更新失败:新增新分配记录异常");
return R.fail(MessageUtils.message("his.doc_org.update_save_failed"));
}
}
}

View File

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
import com.core.common.utils.bean.BeanUtils;
@@ -214,14 +215,14 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
*/
private R<?> createOrUpdateStatistics(DocRecordDto docRecordDto) {
if (docRecordDto == null) {
return R.fail("插入文书统计数据失败:原始文书记录不能为空");
return R.fail(MessageUtils.message("doc.record.stats.param.empty"));
}
if (docRecordDto.getContentJson() == null) {
return R.fail("插入文书统计数据失败:原始文书记录内容不能为空");
return R.fail(MessageUtils.message("doc.record.stats.content.empty"));
}
List<DocStatisticsDto> list = convertToDocStatistics.convertToStatisticsDtoList(docRecordDto);
if (list == null || list.isEmpty()) {
return R.fail("插入文书统计数据失败:统计数据为空");
return R.fail(MessageUtils.message("doc.record.stats.data.empty"));
}
return docStatisticsAppService.createOrUpdte(list);
}
@@ -252,9 +253,9 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
if (saveSuccess) {
docRecordDto.setId(docRecord.getId());
createOrUpdateStatistics(docRecordDto);
return R.ok("新增患者文书记录成功");
return R.ok(MessageUtils.message("doc.record.add.success"));
} else {
return R.fail("新增患者文书记录失败");
return R.fail(MessageUtils.message("doc.record.add.fail"));
}
}
@@ -267,7 +268,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
public R<?> updateRecord(DocRecordDto docRecordDto) {
Integer printCount = docRecordDto.getPrintCount();
if (printCount > 0) {
return R.fail("已打印的文书记录,禁止修改");
return R.fail(MessageUtils.message("doc.record.printed.forbidden"));
}
List<String> sourceCodes = Arrays.stream(DocDefinitionEnum.values()).map(DocDefinitionEnum::getValue).toList();
if (!sourceCodes.contains(StringUtils.isBlank(docRecordDto.getSource()) ? "" : docRecordDto.getSource())) {
@@ -279,7 +280,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
// 1. 查询原文书记录
DocRecord docRecord = docRecordService.getById(docRecordDto.getId());
if (docRecord == null) {
return R.fail("修改患者文书记录失败:记录不存在");
return R.fail(MessageUtils.message("doc.record.update.not.found"));
}
// 2. 记录日志
// 深拷贝原数据用于日志
@@ -302,12 +303,12 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
// 插入操作日志
boolean logSuccess = insertLog(logDocRecord);
if (!logSuccess) {
return R.fail("修改患者文书记录成功,但插入文档操作日志失败");
return R.fail(MessageUtils.message("doc.record.update.log.fail"));
}
createOrUpdateStatistics(docRecordDto);
return R.ok("修改患者文书记录成功");
return R.ok(MessageUtils.message("doc.record.update.success"));
} else {
return R.fail("修改患者文书记录失败");
return R.fail(MessageUtils.message("doc.record.update.fail"));
}
}
@@ -319,13 +320,13 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
Integer pageSize, String searchKey, HttpServletRequest request) {
// 1. 参数校验
if (docRecordQueryParam == null) {
return R.fail("患者文书记录:查询参数不能为空");
return R.fail(MessageUtils.message("doc.record.query.param.empty"));
}
if (docRecordQueryParam.getPatientId() == null && docRecordQueryParam.getEncounterId() == null) {
return R.fail("患者文书记录患者ID和就诊ID不能同时为空");
return R.fail(MessageUtils.message("doc.record.query.ids.empty"));
}
if (docRecordQueryParam.getDefinitionId() == null) {
return R.fail("患者文书记录文书类型定义ID不能为空");
return R.fail(MessageUtils.message("doc.record.query.def.empty"));
}
// 2. 分页查询逻辑
@@ -334,7 +335,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
HisQueryUtils.buildQueryWrapper(docRecordQueryParam, null, null, request);
IPage<DocRecordDto> pageResult =
docRecordAppMapper.getRecordPageListByEncounterId(new Page<>(pageNo, pageSize), queryWrapper);
return R.ok(pageResult, "获取患者文书记录列表成功");
return R.ok(pageResult, MessageUtils.message("doc.record.get.list.success"));
}
// 3. 不分页查询逻辑
else {
@@ -366,7 +367,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
dto.setVersion(docDefinitionDto != null ? docDefinitionDto.getVersion() : "");
dtoList.add(dto);
}
return R.ok(dtoList, "获取患者文书记录列表成功");
return R.ok(dtoList, MessageUtils.message("doc.record.get.list.success"));
}
}
@@ -378,7 +379,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
List<Integer> primaryMenuEnumList, Integer pageNo, Integer pageSize, String searchKey,
HttpServletRequest request) {
if (docRecordPatientQueryParam == null) {
return R.fail("文书记录:查询参数不能为空");
return R.fail(MessageUtils.message("doc.record.list.query.param.empty"));
}
// 构建查询条件(支持患者姓名搜索)
@@ -409,7 +410,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
}
}
return R.ok(pageResult, "获取患者文书记录列表成功");
return R.ok(pageResult, MessageUtils.message("doc.record.get.list.success"));
}
/**
@@ -418,37 +419,37 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
@Override
public R<?> getRecordById(Long recordId) {
if (recordId == null) {
return R.fail("患者文书记录文书记录ID不能为空");
return R.fail(MessageUtils.message("doc.record.id.empty"));
}
DocRecord record = docRecordService.getById(recordId);
if (record == null) {
return R.fail("患者文书记录:对应记录不存在");
return R.fail(MessageUtils.message("doc.record.not.found"));
}
DocRecordDto dto = new DocRecordDto();
BeanUtils.copyProperties(record, dto);
return R.ok(dto, "获取患者文书记录成功");
return R.ok(dto, MessageUtils.message("doc.record.get.success"));
}
@Override
public R<?> setIsEdit(Long recordId) {
if (recordId == null) {
return R.fail("患者文书记录文书记录ID不能为空");
return R.fail(MessageUtils.message("doc.record.id.empty"));
}
DocRecord record = docRecordService.getById(recordId);
if (record == null) {
return R.fail("患者文书记录:对应记录不存在");
return R.fail(MessageUtils.message("doc.record.not.found"));
}
if (record.getIsEdit() != null && record.getIsEdit() == 1) {
return R.ok("患者文书记录:记录已处于编辑中状态,请勿重复 editing");
return R.ok(MessageUtils.message("doc.record.already.editing"));
}
record.setIsEdit(1);
boolean updateSuccess = docRecordService.updateById(record);
if (updateSuccess) {
return R.ok("设置患者文书记录为编辑中成功");
return R.ok(MessageUtils.message("doc.record.set.edit.success"));
} else {
return R.fail("设置患者文书记录为编辑中失败");
return R.fail(MessageUtils.message("doc.record.set.edit.fail"));
}
}
@@ -459,13 +460,13 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
public R<?> deleteRecord(List<Long> ids) {
// 1. 参数校验
if (ids == null || ids.isEmpty()) {
return R.fail("患者文书记录删除的记录ID列表不能为空");
return R.fail(MessageUtils.message("doc.record.delete.ids.empty"));
}
// 2. 校验记录是否存在
List<DocRecord> recordList = docRecordService.listByIds(ids);
if (recordList == null || recordList.isEmpty()) {
return R.fail("患者文书记录:待删除的记录不存在");
return R.fail(MessageUtils.message("doc.record.delete.not.found"));
}
// 3. 权限校验:仅允许删除自己创建的记录
@@ -473,7 +474,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
List<DocRecord> logRecordList = new ArrayList<>();
for (DocRecord record : recordList) {
if (!currentUsername.equals(record.getCreateBy())) {
return R.fail("患者文书记录无权限删除他人创建的记录记录ID" + record.getId() + "");
return R.fail(MessageUtils.message("doc.record.delete.no.permission", record.getId()));
}
// 拷贝原记录用于日志
DocRecord logRecord = new DocRecord();
@@ -488,11 +489,11 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
// 5. 批量插入删除日志
boolean logSuccess = insertBatchLog(logRecordList);
if (!logSuccess) {
return R.fail("删除患者文书记录成功,但插入文档操作日志失败");
return R.fail(MessageUtils.message("doc.record.delete.log.fail"));
}
return R.ok("删除患者文书记录成功");
return R.ok(MessageUtils.message("doc.record.delete.success"));
} else {
return R.fail("删除患者文书记录失败");
return R.fail(MessageUtils.message("doc.record.delete.fail"));
}
}
@@ -507,13 +508,13 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
public R<?> getRecordByEncounterIdAndTimeList(DocRecordQueryParam docRecordQueryParam, String recordTime) {
// 参数校验
if (docRecordQueryParam == null) {
return R.fail("患者文书记录:查询参数不能为空");
return R.fail(MessageUtils.message("doc.record.query.param.empty"));
}
if (docRecordQueryParam.getPatientId() == null && docRecordQueryParam.getEncounterId() == null) {
return R.fail("患者文书记录患者ID和就诊ID不能同时为空");
return R.fail(MessageUtils.message("doc.record.query.ids.empty"));
}
if (docRecordQueryParam.getDefinitionId() == null) {
return R.fail("患者文书记录文书类型定义ID不能为空");
return R.fail(MessageUtils.message("doc.record.query.def.empty"));
}
// 未传时间,按照当前时间
Date recordDate = StringUtils.isBlank(recordTime) ? new Date()
@@ -549,7 +550,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
dto.setVersion(docDefinitionDto != null ? docDefinitionDto.getVersion() : "");
dtoList.add(dto);
}
return R.ok(dtoList, "获取患者文书记录列表成功");
return R.ok(dtoList, MessageUtils.message("doc.record.get.list.success"));
}
@@ -597,19 +598,19 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
public R<?> temperatureChart(DocRecordQueryParam docRecordQueryParam) {
// 参数校验
if (docRecordQueryParam == null) {
return R.fail("患者文书记录:查询参数不能为空");
return R.fail(MessageUtils.message("doc.record.query.param.empty"));
}
Long encounterId = docRecordQueryParam.getEncounterId();
Long patientId = docRecordQueryParam.getPatientId();
Long tempId = docRecordQueryParam.getDefinitionId();
if (encounterId == null) {
return R.fail("患者文书记录就诊ID不能为空");
return R.fail(MessageUtils.message("doc.record.encounter.id.empty"));
}
if (patientId == null) {
return R.fail("患者文书记录患者ID不能为空");
return R.fail(MessageUtils.message("doc.record.patient.id.empty"));
}
if (tempId == null) {
return R.fail("患者文书记录文书类型定义ID不能为空");
return R.fail(MessageUtils.message("doc.record.query.def.empty"));
}
// 根据病历ID和患者ID获取住院、出院时间
Map<String, Date> dateMap = getDateByEncounterId(encounterId, patientId);
@@ -691,19 +692,19 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
public R<?> summaryNursingRecords(DocRecordQueryParam docRecordQueryParam, String startTime, String endTime) {
// 参数校验
if (docRecordQueryParam == null) {
return R.fail("患者文书记录:查询参数不能为空");
return R.fail(MessageUtils.message("doc.record.query.param.empty"));
}
Long encounterId = docRecordQueryParam.getEncounterId();
Long patientId = docRecordQueryParam.getPatientId();
Long definitionId = docRecordQueryParam.getDefinitionId();
if (encounterId == null) {
return R.fail("患者文书记录就诊ID不能为空");
return R.fail(MessageUtils.message("doc.record.encounter.id.empty"));
}
if (patientId == null) {
return R.fail("患者文书记录患者ID不能为空");
return R.fail(MessageUtils.message("doc.record.patient.id.empty"));
}
if (definitionId == null) {
return R.fail("患者文书记录文书类型定义ID不能为空");
return R.fail(MessageUtils.message("doc.record.query.def.empty"));
}
List<DocRecordDto> docRecordList = new ArrayList<>();
// 查询所有

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.bean.BeanUtils;
import com.healthlink.his.document.enums.DocDefinitionEnum;
@@ -71,7 +72,7 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
if (result) {
return R.ok();
} else {
return R.fail("新增或更新文档统计数据失败");
return R.fail(MessageUtils.message("his.doc.stats_save_failed"));
}
}
@@ -84,7 +85,7 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
if (update) {
return R.ok();
} else {
return R.fail("删除失败");
return R.fail(MessageUtils.message("his.doc.stats_delete_failed"));
}
}
@@ -127,7 +128,7 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
Page<DocStatisticsDto> recordPage =
HisPageUtils.selectPage(docStatisticsMapper, queryWrapper, pageNo, pageSize, DocStatisticsDto.class);
return R.ok(recordPage, "获取患者文书统计数据成功");
return R.ok(recordPage, MessageUtils.message("his.doc.get_statistics_success"));
}
// 2. 不分页查询逻辑
else {
@@ -156,7 +157,7 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
BeanUtils.copyProperties(statistics, dto);
dtoList.add(dto);
}
return R.ok(dtoList, "获取患者文书统计数据成功");
return R.ok(dtoList, MessageUtils.message("his.doc.get_statistics_success"));
}
}

View File

@@ -7,6 +7,7 @@ import com.core.common.constant.CacheConstants;
import com.core.common.core.domain.R;
import com.core.common.core.domain.entity.SysDictData;
import com.core.common.core.redis.RedisCache;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.bean.BeanUtils;
import com.healthlink.his.common.utils.HisPageUtils;
import com.healthlink.his.common.utils.HisQueryUtils;
@@ -45,16 +46,16 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
@Override
public R<?> createOrEdit(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
if (docStatisticsDefinitionDto == null) {
return R.fail("新增/编辑文档统计定义,参数不能为空");
return R.fail(MessageUtils.message("his.doc_stat.param_required"));
}
if (docStatisticsDefinitionDto.getName() == null || docStatisticsDefinitionDto.getName().trim().length() == 0) {
return R.fail("新增/编辑文档统计定义,名称不能为空");
return R.fail(MessageUtils.message("his.doc_stat.name_required"));
}
if (docStatisticsDefinitionDto.getTypeEnum() == null) {
return R.fail("新增/编辑文档统计定义,类型不能为空");
return R.fail(MessageUtils.message("his.doc_stat.type_required"));
}
if (docStatisticsDefinitionDto.getCode() == null) {
return R.fail("新增/编辑文档统计定义,代码不能为空");
return R.fail(MessageUtils.message("his.doc_stat.code_required"));
}
DocStatisticsDefinition docStatisticsDefinition = new DocStatisticsDefinition();
BeanUtils.copyProperties(docStatisticsDefinitionDto, docStatisticsDefinition);
@@ -64,7 +65,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
queryWrapper.eq(DocStatisticsDefinition::getCode, docStatisticsDefinitionDto.getCode());
docStatisticsDefinition = iDocStatisticsDefinitionService.getOne(queryWrapper);
if (docStatisticsDefinition != null) {
return R.fail("文档统计定义代码已存在,请更换代码");
return R.fail(MessageUtils.message("his.doc_stat.code_exists"));
}
}
// 区分新增/编辑逻辑
@@ -85,7 +86,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
queryWrapper.eq(DocStatisticsDefinition::getCode, docStatisticsDefinitionDto.getCode());
Long count = iDocStatisticsDefinitionService.count(queryWrapper);
if (count > 0) {
return R.fail("文档统计定义代码已存在,请更换代码");
return R.fail(MessageUtils.message("his.doc_stat.code_exists"));
}
}
// 赋值新增字段
@@ -103,9 +104,9 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
docStatisticsDefinition.setTypeCode(docStatisticsDefinitionDto.getTypeCode());
boolean saveResult = iDocStatisticsDefinitionService.save(docStatisticsDefinition);
if (saveResult) {
return R.ok("文档统计定义新增成功");
return R.ok(MessageUtils.message("his.doc_stat.add_success"));
} else {
return R.fail("文档统计定义新增失败");
return R.fail(MessageUtils.message("his.doc_stat.add_fail"));
}
}
@@ -120,7 +121,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
DocStatisticsDefinition existingData =
iDocStatisticsDefinitionService.getById(docStatisticsDefinitionDto.getId());
if (existingData == null) {
return R.fail("更新文档统计定义失败,目标数据不存在");
return R.fail(MessageUtils.message("his.doc_stat.update_not_found"));
}
// 赋值更新字段
existingData.setName(docStatisticsDefinitionDto.getName());
@@ -137,24 +138,24 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
boolean updateResult = iDocStatisticsDefinitionService.updateById(existingData);
if (updateResult) {
// 同步更新选项列表
return R.ok("文档统计定义更新成功");
return R.ok(MessageUtils.message("his.doc_stat.update_success"));
} else {
return R.fail("文档统计定义更新失败");
return R.fail(MessageUtils.message("his.doc_stat.update_fail"));
}
}
private String initCheck(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
if (docStatisticsDefinitionDto == null) {
return "新增/编辑文档统计定义,参数不能为空";
return MessageUtils.message("his.doc_stat.param_required");
}
if (docStatisticsDefinitionDto.getName() == null || docStatisticsDefinitionDto.getName().trim().length() == 0) {
return "新增/编辑文档统计定义,名称不能为空";
return MessageUtils.message("his.doc_stat.name_required");
}
if (docStatisticsDefinitionDto.getTypeEnum() == null) {
return "新增/编辑文档统计定义,类型不能为空";
return MessageUtils.message("his.doc_stat.type_required");
}
if (docStatisticsDefinitionDto.getCode() == null) {
return "新增/编辑文档统计定义,代码不能为空";
return MessageUtils.message("his.doc_stat.code_required");
}
return null;
@@ -180,7 +181,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
Page<DocStatisticsDefinitionDto> recordPage = HisPageUtils.selectPage(docStatisticsDefinitionMapper,
queryWrapper, pageNo, pageSize, DocStatisticsDefinitionDto.class);
// 转换为分页结果
return R.ok(recordPage, "文档统计定义列表获取成功");
return R.ok(recordPage, MessageUtils.message("his.doc_stat.list_success"));
}
/**
@@ -241,7 +242,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
// 2. 处理空数据场景
if (optionDtoList == null || optionDtoList.isEmpty()) {
return R.ok(new ArrayList<>(), "文档统计定义选项列表获取成功,查询结果为空");
return R.ok(new ArrayList<>(), MessageUtils.message("his.doc_stat.option_list_empty"));
}
// 3. 按code字段分组
@@ -289,19 +290,19 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
resultList.add(resultMap);
}
return R.ok(resultList, "文档统计定义选项列表获取成功");
return R.ok(resultList, MessageUtils.message("his.doc_stat.option_list_success"));
}
@Override
public R<?> deleteDocStatisticsDefinition(Long id) {
if (id == null) {
return R.fail("删除文档统计定义参数ID不能为空");
return R.fail(MessageUtils.message("his.doc_stat.delete_param_required"));
}
boolean deleteResult = iDocStatisticsDefinitionService.removeById(id);
if (deleteResult) {
return R.ok("文档统计定义删除成功");
return R.ok(MessageUtils.message("his.doc_stat.delete_success"));
} else {
return R.fail("文档统计定义删除失败");
return R.fail(MessageUtils.message("his.doc_stat.delete_fail"));
}
}

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.healthlink.his.document.enums.DocUseRangeEnum;
import com.healthlink.his.common.utils.HisPageUtils;
@@ -63,7 +64,7 @@ public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
docTemplate.setUseRange(docTemplateDto.getUseRange());
docTemplate.setRemark(docTemplateDto.getRemark());
docTemplateService.save(docTemplate);
return R.ok(" 添加成功");
return R.ok(MessageUtils.message("his.doc.add_success"));
}
private String initCheck(DocTemplateDto docTemplateDto) {
@@ -98,13 +99,13 @@ public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
@Override
public R<?> delete(Long id) {
if (id == null) {
return R.fail("模板ID不能为空");
return R.fail(MessageUtils.message("his.doc.template_id_required"));
}
boolean result = docTemplateService.removeById(id);
if (result) {
return R.ok("删除成功");
return R.ok(MessageUtils.message("his.doc.delete_success"));
}
return R.fail("模板不存在");
return R.fail(MessageUtils.message("his.doc.template_not_found"));
}
@Override
@@ -114,11 +115,11 @@ public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
return R.fail(msg);
}
if (docTemplateDto.getId() == null) {
return R.fail("模板ID不能为空");
return R.fail(MessageUtils.message("his.doc.template_id_required"));
}
DocTemplate docTemplate = docTemplateService.getById(docTemplateDto.getId());
if (docTemplate == null) {
return R.fail("模板不存在");
return R.fail(MessageUtils.message("his.doc.template_not_found"));
}
if (docTemplateDto.getUseRange() == DocUseRangeEnum.ALL_HOSPITAL_USE.getValue() || docTemplateDto.getUseRange() == DocUseRangeEnum.NO_IN_USE.getValue()) {
docTemplateDto.setOrganizationId(null);
@@ -141,13 +142,13 @@ public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
docTemplate.setUserId(docTemplateDto.getUserId());
docTemplate.setRemark(docTemplateDto.getRemark());
docTemplateService.updateById(docTemplate);
return R.ok("更新成功");
return R.ok(MessageUtils.message("his.doc.update_success"));
}
@Override
public R<?> getById(Long id) {
if (id == null) {
return R.fail("模板ID不能为空");
return R.fail(MessageUtils.message("his.doc.template_id_required"));
}
DocTemplateDto templateDto = new DocTemplateDto();
DocTemplate result = docTemplateService.getById(id);
@@ -158,7 +159,7 @@ public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
@Override
public R<?> getListByDefinitionId(Long definitionId) {
if (definitionId == null) {
return R.fail("模板定义ID不能为空");
return R.fail(MessageUtils.message("his.doc.definition_id_required"));
}
LambdaQueryWrapper<DocTemplate> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocTemplate::getDefinitionId, definitionId);
@@ -184,6 +185,6 @@ public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
Page<DocTemplateDto> page = HisPageUtils.selectPage(
docTemplateMapper, queryWrapper, pageNo, pageSize, DocTemplateDto.class);
// 转换为分页结果
return R.ok(page, "获取成功");
return R.ok(page, MessageUtils.message("his.doc.get_success"));
}
}

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.document.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.document.domain.InformedConsent;
import com.healthlink.his.document.service.IInformedConsentService;
import lombok.AllArgsConstructor;
@@ -54,7 +55,7 @@ public class InformedConsentController {
public R<?> getDetail(@RequestParam Long id) {
InformedConsent consent = consentService.getById(id);
if (consent == null) {
return R.fail("知情同意书不存在");
return R.fail(MessageUtils.message("his.consent.not_found"));
}
return R.ok(consent);
}
@@ -81,10 +82,10 @@ public class InformedConsentController {
public R<?> update(@RequestBody InformedConsent consent) {
InformedConsent existing = consentService.getById(consent.getId());
if (existing == null) {
return R.fail("知情同意书不存在");
return R.fail(MessageUtils.message("his.consent.not_found"));
}
if (existing.getStatus() != 0) {
return R.fail("只有草稿状态可以修改");
return R.fail(MessageUtils.message("his.consent.only_draft_edit"));
}
consent.setUpdateTime(new Date());
consentService.updateById(consent);
@@ -99,10 +100,10 @@ public class InformedConsentController {
public R<?> delete(@RequestParam Long id) {
InformedConsent consent = consentService.getById(id);
if (consent == null) {
return R.fail("知情同意书不存在");
return R.fail(MessageUtils.message("his.consent.not_found"));
}
if (consent.getStatus() != 0) {
return R.fail("只有草稿状态可以删除");
return R.fail(MessageUtils.message("his.consent.only_draft_delete"));
}
consentService.removeById(id);
return R.ok();
@@ -117,8 +118,8 @@ public class InformedConsentController {
Long id = Long.valueOf(params.get("id").toString());
String signImage = (String) params.get("signImage");
InformedConsent consent = consentService.getById(id);
if (consent == null) return R.fail("知情同意书不存在");
if (consent.getStatus() != 0) return R.fail("当前状态不允许签名");
if (consent == null) return R.fail(MessageUtils.message("his.consent.not_found"));
if (consent.getStatus() != 0) return R.fail(MessageUtils.message("his.consent.status_not_allow_sign"));
consent.setDoctorSignTime(new Date());
consent.setDoctorSignImage(signImage);
@@ -137,8 +138,8 @@ public class InformedConsentController {
Long id = Long.valueOf(params.get("id").toString());
String signImage = (String) params.get("signImage");
InformedConsent consent = consentService.getById(id);
if (consent == null) return R.fail("知情同意书不存在");
if (consent.getStatus() != 1) return R.fail("当前状态不接受患者签名");
if (consent == null) return R.fail(MessageUtils.message("his.consent.not_found"));
if (consent.getStatus() != 1) return R.fail(MessageUtils.message("his.consent.status_not_accept_patient_sign"));
consent.setPatientSignStatus(1); // 已签
consent.setPatientSignTime(new Date());
@@ -159,7 +160,7 @@ public class InformedConsentController {
String reason = (String) params.get("rejectReason");
String witness = (String) params.get("witnessName");
InformedConsent consent = consentService.getById(id);
if (consent == null) return R.fail("知情同意书不存在");
if (consent == null) return R.fail(MessageUtils.message("his.consent.not_found"));
consent.setPatientSignStatus(2); // 拒绝
consent.setRejectReason(reason);
@@ -177,8 +178,8 @@ public class InformedConsentController {
@Transactional(rollbackFor = Exception.class)
public R<?> archive(@RequestParam Long id) {
InformedConsent consent = consentService.getById(id);
if (consent == null) return R.fail("知情同意书不存在");
if (consent.getStatus() != 2) return R.fail("只有已完成状态可以归档");
if (consent == null) return R.fail(MessageUtils.message("his.consent.not_found"));
if (consent.getStatus() != 2) return R.fail(MessageUtils.message("his.consent.only_completed_archive"));
consent.setStatus(3); // 已归档
consent.setUpdateTime(new Date());
@@ -193,8 +194,8 @@ public class InformedConsentController {
@Transactional(rollbackFor = Exception.class)
public R<?> voidConsent(@RequestParam Long id, @RequestParam(required = false) String reason) {
InformedConsent consent = consentService.getById(id);
if (consent == null) return R.fail("知情同意书不存在");
if (consent.getStatus() >= 3) return R.fail("已归档/已作废的知情同意书不能再次作废");
if (consent == null) return R.fail(MessageUtils.message("his.consent.not_found"));
if (consent.getStatus() >= 3) return R.fail(MessageUtils.message("his.consent.archived_voided_no_void"));
consent.setStatus(4); // 已作废
consent.setOtherNotes(consent.getOtherNotes() != null ? consent.getOtherNotes() + "\n作废原因: " + reason : "作废原因: " + reason);

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.document.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.document.domain.ProgressNote;
import com.healthlink.his.document.domain.ProgressNoteReminder;
import com.healthlink.his.document.service.IProgressNoteReminderService;
@@ -75,7 +76,7 @@ public class ProgressNoteController {
@GetMapping("/detail")
public R<?> getDetail(@RequestParam Long id) {
ProgressNote note = progressNoteService.getById(id);
if (note == null) return R.fail("病程记录不存在");
if (note == null) return R.fail(MessageUtils.message("doc.progress.note.not.exist"));
return R.ok(note);
}
@@ -107,8 +108,8 @@ public class ProgressNoteController {
@Transactional(rollbackFor = Exception.class)
public R<?> update(@RequestBody ProgressNote note) {
ProgressNote existing = progressNoteService.getById(note.getId());
if (existing == null) return R.fail("病程记录不存在");
if (existing.getSignStatus() == 1) return R.fail("已签名的病程记录不能修改");
if (existing == null) return R.fail(MessageUtils.message("doc.progress.note.not.exist"));
if (existing.getSignStatus() == 1) return R.fail(MessageUtils.message("doc.progress.note.signed.cannot.modify"));
note.setVersion(existing.getVersion() + 1);
note.setUpdateTime(new Date());
progressNoteService.updateById(note);
@@ -122,8 +123,8 @@ public class ProgressNoteController {
@Transactional(rollbackFor = Exception.class)
public R<?> delete(@RequestParam Long id) {
ProgressNote note = progressNoteService.getById(id);
if (note == null) return R.fail("病程记录不存在");
if (note.getSignStatus() == 1) return R.fail("已签名的病程记录不能删除");
if (note == null) return R.fail(MessageUtils.message("doc.progress.note.not.exist"));
if (note.getSignStatus() == 1) return R.fail(MessageUtils.message("doc.progress.note.signed.cannot.delete"));
progressNoteService.removeById(id);
return R.ok();
}
@@ -136,8 +137,8 @@ public class ProgressNoteController {
public R<?> sign(@RequestBody Map<String, Object> params) {
Long id = Long.valueOf(params.get("id").toString());
ProgressNote note = progressNoteService.getById(id);
if (note == null) return R.fail("病程记录不存在");
if (note.getSignStatus() == 1) return R.fail("已签名");
if (note == null) return R.fail(MessageUtils.message("doc.progress.note.not.exist"));
if (note.getSignStatus() == 1) return R.fail(MessageUtils.message("doc.progress.note.signed"));
note.setSignStatus(1);
note.setSignTime(new Date());
note.setUpdateTime(new Date());
@@ -157,7 +158,7 @@ public class ProgressNoteController {
String reviewerName = (String) params.get("reviewUserName");
Long reviewerId = Long.valueOf(params.get("reviewUserId").toString());
ProgressNote note = progressNoteService.getById(id);
if (note == null) return R.fail("病程记录不存在");
if (note == null) return R.fail(MessageUtils.message("doc.progress.note.not.exist"));
note.setReviewUserId(reviewerId);
note.setReviewUserName(reviewerName);
note.setUpdateTime(new Date());

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.emergency.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.emergency.domain.*;
import com.healthlink.his.emergency.service.*;
import lombok.AllArgsConstructor;
@@ -175,7 +176,7 @@ public class EmergencyController {
}
// 校验patientId 必须存在(数据库 NOT NULL 约束)
if (rescue.getPatientId() == null) {
return R.fail("患者ID不能为空请提供患者ID或分诊ID");
return R.fail(MessageUtils.message("his.emergency.patient_id_required"));
}
rescue.setRescueStart(new Date());
rescue.setCreateTime(new Date());
@@ -317,7 +318,7 @@ public class EmergencyController {
@Transactional(rollbackFor = Exception.class)
public R<?> activateGreenChannel(@RequestBody EmergencyGreenChannel gc) {
if (gc.getPatientId() == null) {
return R.fail("患者ID不能为空请选择患者后再激活绿色通道");
return R.fail(MessageUtils.message("his.emergency.patient_id_for_green_channel"));
}
gc.setActivateTime(new Date());
gc.setCreateTime(new Date());

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.empi.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.empi.domain.*;
import com.healthlink.his.empi.service.*;
import lombok.AllArgsConstructor;
@@ -86,7 +87,7 @@ public class EmpiEnhancedController {
Long id = Long.valueOf(params.get("id").toString());
String reason = (String) params.get("undoReason");
EmpiMergeLog logEntry = mergeLogService.getById(id);
if (logEntry == null) return R.fail("日志不存在");
if (logEntry == null) return R.fail(MessageUtils.message("his.empi.log_not_found"));
logEntry.setStatus("UNDONE");
logEntry.setUndoTime(new Date());
logEntry.setUndoReason(reason);

View File

@@ -4,10 +4,10 @@ import com.healthlink.his.emr.domain.EmrCompletenessCheck;
import com.healthlink.his.emr.domain.EmrRevision;
import com.healthlink.his.emr.domain.EmrTimeliness;
import com.healthlink.his.emr.dto.RevisionHistoryDto;
import com.healthlink.his.emr.service.IEmrCompletenessCheckService;
import com.healthlink.his.emr.service.IEmrRevisionService;
import com.healthlink.his.emr.service.IEmrTimelinessService;
import com.healthlink.his.web.emr.appservice.IStructuredEmrAppService;
import com.healthlink.his.web.emr.appservice.IEmrCompletenessAppService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -23,10 +23,10 @@ public class StructuredEmrAppServiceImpl implements IStructuredEmrAppService {
private IEmrRevisionService emrRevisionService;
@Resource
private IEmrCompletenessCheckService emrCompletenessCheckService;
private IEmrTimelinessService emrTimelinessService;
@Resource
private IEmrTimelinessService emrTimelinessService;
private IEmrCompletenessAppService emrCompletenessAppService;
@Override
@Transactional
@@ -59,7 +59,10 @@ public class StructuredEmrAppServiceImpl implements IStructuredEmrAppService {
@Override
@Transactional
public List<EmrCompletenessCheck> executeCompletenessCheck(Long emrId, Long encounterId) {
return emrCompletenessCheckService.executeCheck(emrId, encounterId);
Map<String, Object> result = emrCompletenessAppService.checkCompleteness(emrId, encounterId);
@SuppressWarnings("unchecked")
List<EmrCompletenessCheck> checks = (List<EmrCompletenessCheck>) result.get("checks");
return checks != null ? checks : List.of();
}
@Override

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.emr.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.emr.domain.EmrArchiveRecord;
import com.healthlink.his.emr.service.IEmrArchiveRecordService;
import lombok.AllArgsConstructor;
@@ -57,7 +58,7 @@ public class EmrArchiveController {
@Transactional(rollbackFor = Exception.class)
public R<?> archive(@PathVariable Long id, @RequestParam("archivedBy") String archivedBy) {
EmrArchiveRecord record = archiveService.getById(id);
if (record == null) return R.fail("归档记录不存在");
if (record == null) return R.fail(MessageUtils.message("his.emr.archive_not_found"));
record.setArchiveStatus("ARCHIVED");
record.setArchiveTime(new Date());
record.setArchivedBy(archivedBy);
@@ -69,7 +70,7 @@ public class EmrArchiveController {
@Transactional(rollbackFor = Exception.class)
public R<?> reprint(@PathVariable Long id) {
EmrArchiveRecord record = archiveService.getById(id);
if (record == null) return R.fail("归档记录不存在");
if (record == null) return R.fail(MessageUtils.message("his.emr.archive_not_found"));
record.setPrintCount(record.getPrintCount() + 1);
archiveService.updateById(record);
return R.ok(record);

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.emr.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.emr.domain.EmrRevision;
import com.healthlink.his.emr.dto.EmrRevisionWithPatientDto;
import com.healthlink.his.emr.mapper.EmrRevisionMapper;
@@ -95,7 +96,7 @@ public class EmrRevisionController {
@RequestParam("revisionId2") Long id2) {
EmrRevision r1 = revisionService.getById(id1);
EmrRevision r2 = revisionService.getById(id2);
if (r1 == null || r2 == null) return R.fail("修订记录不存在");
if (r1 == null || r2 == null) return R.fail(MessageUtils.message("emr.revision.not.exist"));
return R.ok(Map.of("revision1", r1, "revision2", r2));
}
}

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.emr.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.core.common.core.domain.entity.SysUser;
import com.core.system.mapper.SysUserMapper;
import com.healthlink.his.administration.domain.Encounter;
@@ -84,7 +85,7 @@ public class EmrSyncController {
.orderByAsc(Emr::getCreateTime));
if (emrList.isEmpty()) {
return R.ok("没有病历数据需要同步");
return R.ok(MessageUtils.message("his.emr.no_data_to_sync"));
}
log.info("共找到 {} 条病历数据", emrList.size());

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.esbmanage.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.esb.domain.CdaDocument;
import com.healthlink.his.web.esbmanage.appservice.ICdaDocumentAppService;
import lombok.RequiredArgsConstructor;
@@ -32,7 +33,7 @@ public class CdaDocumentController {
String clinicalData = (String) params.get("clinicalData");
if (encounterId == null || documentType == null) {
return R.fail("encounterId和documentType不能为空");
return R.fail(MessageUtils.message("his.cda.params_required"));
}
CdaDocument doc = cdaDocumentAppService.generateCda(encounterId, patientId, documentType, documentTitle, clinicalData);
return R.ok(doc);

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.esbmanage.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.esb.domain.EsbMessage;
import com.healthlink.his.esb.service.IEsbMessageService;
import com.healthlink.his.esb.domain.EsbServiceRegistry;
@@ -39,16 +40,16 @@ public class EsbMessageController {
message.setStatus("待发送");
message.setRetryCount(0);
boolean result = esbMessageService.save(message);
return result ? R.ok("消息已提交") : R.fail("提交失败");
return result ? R.ok(MessageUtils.message("his.esb.message_submitted")) : R.fail(MessageUtils.message("msg.failure"));
}
@PutMapping("/retry/{id}")
public R<?> retryMessage(@PathVariable Long id) {
EsbMessage msg = esbMessageService.getById(id);
if (msg == null) return R.fail("消息不存在");
if (msg == null) return R.fail(MessageUtils.message("his.esb.message_not_found"));
msg.setStatus("重试中");
msg.setRetryCount(msg.getRetryCount() + 1);
esbMessageService.updateById(msg);
return R.ok("重试已提交");
return R.ok(MessageUtils.message("his.esb.retry_submitted"));
}
@GetMapping("/stats")
public R<?> getStats() {
@@ -70,9 +71,9 @@ public class EsbMessageController {
.eq(EsbServiceRegistry::getServiceStatus, "启用");
boolean exists = registryService.count(wrapper) > 0;
if (!exists) {
return R.fail("目标系统 '" + targetSystem + "' 未注册或已停用,无法路由消息");
return R.fail(MessageUtils.message("his.esb.target_not_registered", targetSystem));
}
return R.ok("路由校验通过");
return R.ok(MessageUtils.message("his.esb.route_check_passed"));
}
/**
@@ -92,13 +93,13 @@ public class EsbMessageController {
@PutMapping("/reset-dead-letter")
public R<?> resetDeadLetter(@RequestParam Long id) {
EsbMessage msg = esbMessageService.getById(id);
if (msg == null) return R.fail("消息不存在");
if (!"发送失败".equals(msg.getStatus())) return R.fail("只能重置失败消息");
if (msg == null) return R.fail(MessageUtils.message("his.esb.message_not_found"));
if (!"发送失败".equals(msg.getStatus())) return R.fail(MessageUtils.message("his.esb.only_reset_failed"));
msg.setStatus("待发送");
msg.setRetryCount(0);
msg.setErrorMessage(null);
esbMessageService.updateById(msg);
return R.ok("消息已重置为待发送");
return R.ok(MessageUtils.message("his.esb.message_reset"));
}
}

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.esbmanage.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.esb.domain.EsbDeadLetter;
import com.healthlink.his.esb.domain.EsbMessage;
import com.healthlink.his.esb.domain.EsbMonitorStats;
@@ -38,7 +39,7 @@ public class EsbReliabilityController {
LambdaQueryWrapper<EsbMessage> w = new LambdaQueryWrapper<>();
w.eq(EsbMessage::getMessageId, messageId);
EsbMessage msg = messageService.getOne(w);
if (msg == null) return R.fail("消息不存在");
if (msg == null) return R.fail(MessageUtils.message("his.esb.message_not_found"));
int retryCount = msg.getRetryCount() != null ? msg.getRetryCount() : 0;
if (retryCount >= 3) {
@@ -60,7 +61,7 @@ public class EsbReliabilityController {
msg.setStatus("死信");
messageService.updateById(msg);
return R.ok("消息已转入死信队列");
return R.ok(MessageUtils.message("his.esb.moved_to_dead_letter"));
}
msg.setRetryCount(retryCount + 1);
@@ -72,7 +73,7 @@ public class EsbReliabilityController {
msg.setAckTime(new Date());
messageService.updateById(msg);
return R.ok("重试成功(第" + (retryCount + 1) + "次)");
return R.ok(MessageUtils.message("his.esb.retry_success", retryCount + 1));
}
@PostMapping("/retry-all-failed")
@@ -91,7 +92,7 @@ public class EsbReliabilityController {
retried++;
}
}
return R.ok("已重试 " + retried + " 条失败消息");
return R.ok(MessageUtils.message("his.esb.retried_count", retried));
}
// ==================== 死信队列 ====================
@@ -113,7 +114,7 @@ public class EsbReliabilityController {
@Transactional(rollbackFor = Exception.class)
public R<?> resolveDeadLetter(@PathVariable Long id, @RequestParam("resolvedBy") String resolvedBy) {
EsbDeadLetter dl = deadLetterService.getById(id);
if (dl == null) return R.fail("死信记录不存在");
if (dl == null) return R.fail(MessageUtils.message("his.esb.dead_letter_not_found"));
dl.setStatus("RESOLVED");
dl.setResolvedBy(resolvedBy);
dl.setResolvedTime(new Date());
@@ -125,7 +126,7 @@ public class EsbReliabilityController {
@Transactional(rollbackFor = Exception.class)
public R<?> ignoreDeadLetter(@PathVariable Long id) {
EsbDeadLetter dl = deadLetterService.getById(id);
if (dl == null) return R.fail("死信记录不存在");
if (dl == null) return R.fail(MessageUtils.message("his.esb.dead_letter_not_found"));
dl.setStatus("IGNORED");
deadLetterService.updateById(dl);
return R.ok();

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.esbmanage.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.esb.domain.EsbServiceRegistry;
import com.healthlink.his.esb.service.IEsbServiceRegistryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -34,19 +35,19 @@ public class EsbServiceRegistryController {
@PostMapping("/add")
public R<?> add(@RequestBody EsbServiceRegistry registry) {
registry.setServiceStatus("启用");
return registryService.save(registry) ? R.ok("注册成功") : R.fail("注册失败");
return registryService.save(registry) ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@PutMapping("/update")
public R<?> update(@RequestBody EsbServiceRegistry registry) {
return registryService.updateById(registry) ? R.ok("修改成功") : R.fail("修改失败");
return registryService.updateById(registry) ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@DeleteMapping("/delete")
public R<?> delete(@RequestParam Long id) {
return registryService.removeById(id) ? R.ok("删除成功") : R.fail("删除失败");
return registryService.removeById(id) ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@PutMapping("/status")
public R<?> updateStatus(@RequestParam Long id, @RequestParam String status) {
EsbServiceRegistry reg = new EsbServiceRegistry(); reg.setId(id); reg.setServiceStatus(status);
return registryService.updateById(reg) ? R.ok("状态更新成功") : R.fail("状态更新失败");
return registryService.updateById(reg) ? R.ok(MessageUtils.message("his.esb.status_update_success")) : R.fail(MessageUtils.message("his.esb.status_update_failed"));
}
}

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.esbmanage.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.esb.domain.CdaDocument;
import com.healthlink.his.esb.domain.CodeMapping;
import com.healthlink.his.esb.domain.FhirResource;
@@ -59,7 +60,7 @@ public class FhirCdaController {
@Transactional(rollbackFor = Exception.class)
public R<?> updateFhirResource(@RequestBody FhirResource resource) {
FhirResource existing = fhirService.getById(resource.getId());
if (existing == null) return R.fail("资源不存在");
if (existing == null) return R.fail(MessageUtils.message("his.fhir.resource_not_found"));
resource.setVersionId(existing.getVersionId() + 1);
resource.setUpdateTime(new Date());
fhirService.updateById(resource);
@@ -115,7 +116,7 @@ public class FhirCdaController {
@Transactional(rollbackFor = Exception.class)
public R<?> publishCdaDocument(@RequestParam Long id) {
CdaDocument doc = cdaService.getById(id);
if (doc == null) return R.fail("文档不存在");
if (doc == null) return R.fail(MessageUtils.message("his.fhir.document_not_found"));
doc.setStatus("PUBLISHED");
doc.setUpdateTime(new Date());
cdaService.updateById(doc);
@@ -153,7 +154,7 @@ public class FhirCdaController {
.eq(CodeMapping::getSourceCode, params.get("sourceCode"))
.eq(CodeMapping::getMappingType, params.get("mappingType"));
CodeMapping mapping = mappingService.getOne(wrapper);
if (mapping == null) return R.fail("未找到映射关系");
if (mapping == null) return R.fail(MessageUtils.message("his.fhir.mapping_not_found"));
Map<String, String> result = new HashMap<>();
result.put("targetCode", mapping.getTargetCode());
result.put("targetSystem", mapping.getTargetSystem());

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.esbmanage.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.esb.domain.FhirResource;
import com.healthlink.his.web.esbmanage.appservice.IFhirConversionAppService;
import lombok.RequiredArgsConstructor;
@@ -28,7 +29,7 @@ public class FhirConversionController {
@SuppressWarnings("unchecked")
Map<String, Object> internalData = (Map<String, Object>) params.get("data");
if (resourceType == null || internalData == null) {
return R.fail("resourceType和data不能为空");
return R.fail(MessageUtils.message("his.fhir.params_required"));
}
FhirResource result = fhirConversionAppService.convertToFhir(internalData, resourceType);
return R.ok(result);
@@ -39,7 +40,7 @@ public class FhirConversionController {
public R<?> convertFromFhir(@RequestBody Map<String, String> params) {
String resourceJson = params.get("resourceJson");
if (resourceJson == null || resourceJson.isBlank()) {
return R.fail("resourceJson不能为空");
return R.fail(MessageUtils.message("his.fhir.resource_json_required"));
}
Map<String, Object> result = fhirConversionAppService.convertFromFhir(resourceJson);
return R.ok(result);

View File

@@ -4,6 +4,7 @@ import tools.jackson.databind.ObjectMapper;
import com.core.common.utils.JsonUtils;
import com.core.common.core.domain.R;
import com.core.common.enums.TenantOptionDict;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.TenantOptionUtil;
import com.healthlink.his.web.externalintegration.appservice.IBankPosCloudAppService;
import com.healthlink.his.web.externalintegration.dto.BpcTransactionRequestDto;
@@ -39,16 +40,16 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> processConsumerScan(String txnAmt, String merTradeNo, String scanCode, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
return R.fail(MessageUtils.message("his.bpc.txn_amt_required"));
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
if (StringUtils.isEmpty(scanCode)) {
return R.fail("二维码信息不能为空");
return R.fail(MessageUtils.message("his.bpc.scan_code_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -79,13 +80,13 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> createMerchantScanOrder(String txnAmt, String merTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
return R.fail(MessageUtils.message("his.bpc.txn_amt_required"));
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -114,13 +115,13 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> queryPaymentOrder(String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
// if (StringUtils.isEmpty(tradeNo)) {
// return R.fail("原交易订单号不能为空");
// return R.fail(MessageUtils.message("his.bpc.trade_no_required"));
// }
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -149,13 +150,13 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> closeOrder(String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
if (StringUtils.isEmpty(tradeNo)) {
return R.fail("原交易订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -186,19 +187,19 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> applyForRefund(String txnAmt, String vfTradeNo, String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
return R.fail(MessageUtils.message("his.bpc.txn_amt_required"));
}
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
return R.fail(MessageUtils.message("his.bpc.vf_trade_no_required"));
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
if (StringUtils.isEmpty(tradeNo)) {
return R.fail("原交易订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -231,10 +232,10 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> queryRefundOrder(String vfTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
return R.fail(MessageUtils.message("his.bpc.vf_trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -263,19 +264,19 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> reversePayment(String txnAmt, String vfTradeNo, String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
return R.fail(MessageUtils.message("his.bpc.txn_amt_required"));
}
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
return R.fail(MessageUtils.message("his.bpc.vf_trade_no_required"));
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
if (StringUtils.isEmpty(tradeNo)) {
return R.fail("原交易订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -308,10 +309,10 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> queryReversalOrder(String merTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
return R.fail(MessageUtils.message("his.bpc.mer_trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -339,16 +340,16 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
public R<?> processCardRefund(String txnAmt, String pan, String vfTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
return R.fail(MessageUtils.message("his.bpc.txn_amt_required"));
}
if (StringUtils.isEmpty(pan)) {
return R.fail("银行卡号不能为空");
return R.fail(MessageUtils.message("his.bpc.pan_required"));
}
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
return R.fail(MessageUtils.message("his.bpc.vf_trade_no_required"));
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
return R.fail(MessageUtils.message("his.bpc.pos_no_required"));
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
@@ -379,19 +380,19 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
// 验证租户配置
String mid = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_MID);
if (StringUtils.isEmpty(mid)) {
return R.fail("BPC商户号未配置");
return R.fail(MessageUtils.message("his.bpc.mid_not_configured"));
}
String tid = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_TID);
if (StringUtils.isEmpty(tid)) {
return R.fail("BPC终端号未配置");
return R.fail(MessageUtils.message("his.bpc.tid_not_configured"));
}
String md5SharedSecret = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_MD5_SHARED_SECRET);
if (StringUtils.isEmpty(md5SharedSecret)) {
return R.fail("BPCMD5签名密钥未配置");
return R.fail(MessageUtils.message("his.bpc.md5_secret_not_configured"));
}
String requestUrl = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_REQUEST_URL);
if (StringUtils.isEmpty(requestUrl)) {
return R.fail("BPC请求URL未配置");
return R.fail(MessageUtils.message("his.bpc.request_url_not_configured"));
}
// 生成终端流水号
String traceNo = BpcTraceNoGenerator.nextTraceNo();
@@ -415,10 +416,10 @@ public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
try {
responseDto = JsonUtils.parseObject(postResponse, BpcTransactionResponseDto.class);
if (StringUtils.isNotEmpty(responseDto.getTraceNo()) && !traceNo.equals(responseDto.getTraceNo())) {
return R.fail("终端流水号不一致,交易失败");
return R.fail(MessageUtils.message("his.bpc.trace_no_mismatch"));
}
} catch (Exception e) {
return R.fail("报文解析失败");
return R.fail(MessageUtils.message("his.bpc.response_parse_failed"));
}
// 返回响应结果
return R.ok(responseDto);

View File

@@ -2,6 +2,7 @@ package com.healthlink.his.web.externalintegration.appservice.impl;
import tools.jackson.databind.ObjectMapper;
import com.core.common.utils.JsonUtils;
import com.core.common.utils.MessageUtils;
import tools.jackson.databind.JsonNode;
import com.core.common.core.domain.R;
import com.core.common.enums.TenantOptionDict;
@@ -63,17 +64,17 @@ public class FoodborneAcquisitionAppServiceImpl implements IFoodborneAcquisition
// 判断食源性接口地址是否为空
String foodborneApiUrl = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_API_URL);
if (StringUtils.isEmpty(foodborneApiUrl)) {
return R.fail("【食源性判断接口】租户配置项「食源性接口地址」未配置");
return R.fail(MessageUtils.message("his.external.foodborne.api_url_not_configured"));
}
// 判断食源性医疗机构是否为空
String foodborneHospital = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_HOSPITAL);
if (StringUtils.isEmpty(foodborneHospital)) {
return R.fail("【食源性判断接口】租户配置项「食源性医疗机构」未配置");
return R.fail(MessageUtils.message("his.external.foodborne.hospital_not_configured"));
}
// 判断食源性登录账号是否为空
String foodborneUserName = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_USER_NAME);
if (StringUtils.isEmpty(foodborneUserName)) {
return R.fail("【食源性判断接口】租户配置项「食源性登录账号」未配置");
return R.fail(MessageUtils.message("his.external.foodborne.username_not_configured"));
}
// 定义诊断列表参数
List<String> diagnosisNameList = new ArrayList<>();
@@ -86,7 +87,7 @@ public class FoodborneAcquisitionAppServiceImpl implements IFoodborneAcquisition
diagnosisNameList.addAll(encounterDiagnosisConditionNameList);
// 判断诊断是否为空
if (diagnosisNameList.isEmpty()) {
return R.fail("【食源性判断接口】未找到有效诊断");
return R.fail(MessageUtils.message("his.external.foodborne.no_valid_diagnosis"));
}
// 设置超时时间
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000, java.util.concurrent.TimeUnit.MILLISECONDS).setConnectionRequestTimeout(3000, java.util.concurrent.TimeUnit.MILLISECONDS).setResponseTimeout(30000, java.util.concurrent.TimeUnit.MILLISECONDS).build();
@@ -134,7 +135,7 @@ public class FoodborneAcquisitionAppServiceImpl implements IFoodborneAcquisition
AdministrativeGender.FEMALE.getValue(), EncounterType.FOLLOW_UP.getValue(),
EncounterClass.IMP.getValue(), ParticipantType.ADMITTER.getCode());
if (simplediseaseAddNopwParam == null) {
return R.fail("【食源性判断接口】跳转参数查询失败");
return R.fail(MessageUtils.message("his.external.foodborne.param_query_failed"));
}
// 返回的标识字段 fillGuid
String fillGuid = String.valueOf(object.get("fillGuid"));
@@ -176,7 +177,7 @@ public class FoodborneAcquisitionAppServiceImpl implements IFoodborneAcquisition
return R.ok(jumpUrl);
} catch (Exception e) {
log.error(e.getMessage(), e);
return R.fail("【食源性判断接口】发生异常:" + e.getMessage());
return R.fail(MessageUtils.message("his.external.foodborne.request_exception", e.getMessage()));
} finally {
if (response != null) {
try {

View File

@@ -3,6 +3,7 @@ package com.healthlink.his.web.followup.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.followup.domain.*;
import com.healthlink.his.followup.service.*;
import com.healthlink.his.web.followup.appservice.IFollowupAppService;
@@ -326,7 +327,7 @@ public class FollowupController {
.le(endDate != null, SatisfactionSurvey::getSurveyDate, endDate);
List<SatisfactionSurvey> list = surveyService.list(w);
if (list.isEmpty()) {
return R.ok("暂无数据");
return R.ok(MessageUtils.message("his.followup.no_data"));
}
double avgOverall = list.stream().mapToInt(SatisfactionSurvey::getOverallScore).average().orElse(0);
double avgService = list.stream().mapToInt(SatisfactionSurvey::getServiceScore).average().orElse(0);

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.enums.DelFlag;
import com.core.common.exception.ServiceException;
import com.core.common.utils.*;
import com.core.common.utils.bean.BeanUtils;
@@ -87,6 +88,12 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
@Resource
private IChargeItemService iChargeItemService;
@Resource
private ILocationService iLocationService;
@Resource
private IOrganizationService iOrganizationService;
/**
* 门诊医生开住院申请
*
@@ -357,17 +364,38 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
*/
@Override
public List<LocationDto> getWardList(Long orgId) {
List<Location> wardList = inHospitalRegisterAppMapper.selectWardList(orgId, LocationForm.WARD.getValue(),
LocationStatus.ACTIVE.getValue());
// 2. 转换为 LocationDto逻辑与原代码完全一致
List<LocationDto> locationDtoList = new ArrayList<>();
for (Location location : wardList) {
LocationDto locationDto = new LocationDto();
BeanUtils.copyProperties(location, locationDto);
locationDtoList.add(locationDto);
Set<Long> orgIds = new LinkedHashSet<>();
if (orgId != null) {
orgIds.add(orgId);
// 通过 busNo 层级查找所有子孙科室busNo 用 "." 分隔层级,如 "1" → "1.1" → "1.1.1"
Organization org = iOrganizationService.getById(orgId);
if (org != null && StringUtils.isNotEmpty(org.getBusNo())) {
List<Organization> children = iOrganizationService.list(
new LambdaQueryWrapper<Organization>()
.likeRight(Organization::getBusNo, org.getBusNo() + ".")
.eq(Organization::getDeleteFlag, DelFlag.NO.getCode()));
for (Organization child : children) {
orgIds.add(child.getId());
}
}
}
// 查询所有关联科室下的病区
List<Location> wardList = new ArrayList<>();
for (Long id : orgIds) {
wardList.addAll(iLocationService.getWardList(id));
}
// 按 ID 去重
List<LocationDto> locationDtoList = new ArrayList<>();
Set<Long> seen = new HashSet<>();
for (Location location : wardList) {
if (seen.add(location.getId())) {
LocationDto dto = new LocationDto();
BeanUtils.copyProperties(location, dto);
locationDtoList.add(dto);
}
}
return locationDtoList;
}
@@ -381,15 +409,15 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
public R<?> updateRegistration(InHospitalInfoDto inHospitalInfoDto) {
Long encounterId = inHospitalInfoDto.getEncounterId();
if (encounterId == null) {
throw new ServiceException("就诊ID不能为空");
throw new ServiceException(MessageUtils.message("inpatient.register.encounter.id.empty"));
}
Encounter encounter = iEncounterService.getById(encounterId);
if (encounter == null) {
throw new ServiceException("未找到该住院登记记录");
throw new ServiceException(MessageUtils.message("inpatient.register.not.found"));
}
// 仅"待入科"状态可修改
if (!EncounterZyStatus.REGISTERED.getValue().equals(encounter.getStatusEnum())) {
throw new ServiceException("患者已入科接收,无法修改登记信息");
throw new ServiceException(MessageUtils.message("inpatient.register.already.admitted"));
}
// 更新就诊信息
@@ -501,15 +529,15 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
@Override
public R<?> voidRegistration(Long encounterId) {
if (encounterId == null) {
throw new ServiceException("就诊ID不能为空");
throw new ServiceException(MessageUtils.message("inpatient.register.encounter.id.empty"));
}
Encounter encounter = iEncounterService.getById(encounterId);
if (encounter == null) {
throw new ServiceException("未找到该住院登记记录");
throw new ServiceException(MessageUtils.message("inpatient.register.not.found"));
}
// 仅"待入科"状态可作废
if (!EncounterZyStatus.REGISTERED.getValue().equals(encounter.getStatusEnum())) {
throw new ServiceException("该患者已入科,请先通知护士站办理退科处理!");
throw new ServiceException(MessageUtils.message("inpatient.register.need.discharge"));
}
// 检查预交金余额
@@ -519,7 +547,7 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
.eq(Account::getTypeCode, AccountType.PERSONAL_CASH_ACCOUNT.getCode()));
if (cashAccount != null && cashAccount.getBalanceAmount() != null
&& cashAccount.getBalanceAmount().compareTo(BigDecimal.ZERO) > 0) {
throw new ServiceException("该患者存在未退清的预交金,请先前往预交金页面办理退款!");
throw new ServiceException(MessageUtils.message("inpatient.register.has.deposit"));
}
// 检查是否已产生计费
@@ -527,7 +555,7 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
new LambdaQueryWrapper<ChargeItem>()
.eq(ChargeItem::getEncounterId, encounterId));
if (chargeCount > 0) {
throw new ServiceException("该患者已产生计费记录,无法作废登记!");
throw new ServiceException(MessageUtils.message("inpatient.register.has.charges"));
}
// 设置状态为已作废
@@ -570,7 +598,7 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
if (admissionTime.before(requestTime)) {
log.error("BugFix#363: 入院时间早于申请时间 - 就诊 id={}, 申请时间={}, 入院时间={}",
inHospitalInfoDto.getAmbEncounterId(), requestTime, admissionTime);
throw new ServiceException("入院时间不能早于住院申请时间,请核对后重新提交");
throw new ServiceException(MessageUtils.message("inpatient.register.admit.time.invalid"));
}
}
}

View File

@@ -1,6 +1,7 @@
package com.healthlink.his.web.inhospitalmanage.controller;
import com.core.common.core.domain.R;
import com.core.common.utils.MessageUtils;
import com.healthlink.his.administration.domain.EncounterDiagnosis;
import com.healthlink.his.administration.service.IEncounterDiagnosisService;
import lombok.AllArgsConstructor;
@@ -28,18 +29,18 @@ public class InpatientDiagnosisController {
@PostMapping(value = "/add")
public R<?> addDiagnosis(@RequestBody EncounterDiagnosis diagnosis) {
boolean result = encounterDiagnosisService.save(diagnosis);
return result ? R.ok("新增成功") : R.fail("新增失败");
return result ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@PutMapping(value = "/update")
public R<?> updateDiagnosis(@RequestBody EncounterDiagnosis diagnosis) {
boolean result = encounterDiagnosisService.updateById(diagnosis);
return result ? R.ok("修改成功") : R.fail("修改失败");
return result ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
@DeleteMapping(value = "/delete")
public R<?> deleteDiagnosis(@RequestParam Long id) {
boolean result = encounterDiagnosisService.removeById(id);
return result ? R.ok("删除成功") : R.fail("删除失败");
return result ? R.ok(MessageUtils.message("msg.success")) : R.fail(MessageUtils.message("msg.failure"));
}
}

View File

@@ -10,6 +10,7 @@ import com.core.common.core.domain.R;
import com.core.common.enums.DelFlag;
import com.core.common.utils.AgeCalculatorUtil;
import com.core.common.utils.DateUtils;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
import com.healthlink.his.administration.domain.Encounter;
@@ -538,12 +539,12 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
} catch (Exception e) {
log.error("保存入院体征失败,但不影响参与者数据", e);
}
return R.ok("患者信息更新成功");
return R.ok(MessageUtils.message("atd.patient.update.success"));
}
// 新分配床位时,校验床位信息
if (targetBedId == null || admissionPatientInfoDto.getTargetHouseId() == null) {
return R.fail("床位分配失败,请选择有效的床位");
return R.fail(MessageUtils.message("atd.bed.allocate.invalid"));
}
// 判断患者是否已经在床
@@ -565,7 +566,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
Integer result = encounterLocationService.updateEncounterLocationStatus(encounterId, false);
Integer targetResult = encounterLocationService.updateEncounterLocationStatus(targetEncounterId, false);
if (result == 0 || targetResult == 0) {
return R.fail("换床失败,请联系管理员");
return R.fail(MessageUtils.message("atd.bed.transfer.admin.fail"));
}
// 保存住院位置(目标床位)
// 病房
@@ -590,7 +591,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
// 换床
Integer result = encounterLocationService.updateEncounterLocationStatus(encounterId, false);
if (result == 0) {
return R.fail("换床失败,请联系管理员");
return R.fail(MessageUtils.message("atd.bed.transfer.admin.fail"));
}
// 保存住院位置
// 病房
@@ -639,7 +640,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
Integer result
= encounterService.updateEncounterStatus(encounterId, EncounterZyStatus.ADMITTED_TO_THE_HOSPITAL.getValue());
if (result == 0) {
return R.fail("床位分配失败,请联系管理员");
return R.fail(MessageUtils.message("atd.bed.allocate.admin.fail"));
}
// 保存入院体征(在事务外执行,避免影响参与者数据保存)
try {
@@ -657,7 +658,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
stats.put("action", "admission");
stats.put("encounterId", encounterId);
eventPublisher.publishEvent(new StatisticsPushEvent(this, "ADMISSION", stats));
return R.ok("床位分配成功");
return R.ok(MessageUtils.message("atd.bed.allocate.success"));
}
/**
@@ -670,7 +671,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> transferDepartment(Long encounterId) {
if (encounterId == null) {
return R.fail("转科失败,请选择有效的患者");
return R.fail(MessageUtils.message("atd.transfer.invalid.patient"));
}
// 校验是否有未处理完的医嘱(药品/诊疗/耗材)
String blockingMsg = checkBlockingOrders(encounterId);
@@ -684,7 +685,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
DispenseStatus.PENDING_REFUND.getValue(), DispenseStatus.SUBMITTED.getValue())
.eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
if (!medicationDispenseList.isEmpty()) {
return R.fail("患者有待取的药品,请先取药");
return R.fail(MessageUtils.message("atd.transfer.pending.drugs"));
}
// 没有待取的药并且没有可以执行的医嘱才可以转科
Encounter encounter = encounterService.getById(encounterId);
@@ -694,7 +695,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
.eq(OrderProcess::getOriginalOrganizationId, encounter.getOrganizationId())
.orderByDesc(OrderProcess::getCreateTime));
if (orderProcessList.isEmpty()) {
return R.fail("转科失败,请检查转科信息");
return R.fail(MessageUtils.message("atd.transfer.check.info"));
}
OrderProcess orderProcess = orderProcessList.get(0);
@@ -702,7 +703,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
List<EncounterLocation> encounterLocationList = encounterLocationService.getEncounterLocationList(encounterId,
LocationForm.BED, EncounterActivityStatus.ACTIVE);
if (encounterLocationList == null || encounterLocationList.size() != 1) {
return R.fail("清床失败,请检查病床状态");
return R.fail(MessageUtils.message("atd.clean.bed.status.fail"));
}
locationService.updateStatusById(encounterLocationList.get(0).getLocationId(), LocationStatus.IDLE.getValue());
// 更新患者位置状态:已完成
@@ -716,7 +717,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
encounter.setOrganizationId(orderProcess.getTargetOrganizationId())
.setStatusEnum(EncounterZyStatus.REGISTERED.getValue());
encounterService.saveOrUpdateEncounter(encounter);
return R.ok("转科成功");
return R.ok(MessageUtils.message("atd.transfer.success"));
}
/**
@@ -729,7 +730,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> hospitalDischarge(Long encounterId) {
if (encounterId == null) {
return R.fail("出院失败,请选择有效的患者");
return R.fail(MessageUtils.message("atd.discharge.invalid.patient"));
}
// 校验是否有未处理完的医嘱(药品/诊疗/耗材)
String blockingMsg = checkBlockingOrders(encounterId);
@@ -743,7 +744,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
DispenseStatus.PENDING_REFUND.getValue(), DispenseStatus.SUBMITTED.getValue())
.eq(MedicationDispense::getDeleteFlag, DelFlag.NO.getCode()));
if (!medicationDispenseList.isEmpty()) {
return R.fail("患者有待取的药品,请先取药");
return R.fail(MessageUtils.message("atd.transfer.pending.drugs"));
}
int affectedRows
= encounterService.updateEncounterStatus(encounterId, EncounterZyStatus.DISCHARGED_FROM_HOSPITAL.getValue());
@@ -758,9 +759,9 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
stats.put("action", "discharge");
stats.put("encounterId", encounterId);
eventPublisher.publishEvent(new StatisticsPushEvent(this, "DISCHARGE", stats));
return R.ok("出院成功");
return R.ok(MessageUtils.message("atd.discharge.success"));
}
return R.fail("出院失败");
return R.fail(MessageUtils.message("atd.discharge.fail"));
}
/**
@@ -775,11 +776,11 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
if (EncounterZyStatus.ALREADY_SETTLED.getValue().equals(encounter.getStatusEnum())
|| EncounterZyStatus.REGISTERED.getValue().equals(encounter.getStatusEnum())) {
return R.fail("请等待出院结算完成后再清床");
return R.fail(MessageUtils.message("atd.clean.wait.settlement"));
}
// 待转科患者应使用转科功能,不允许直接清床
if (EncounterZyStatus.PENDING_TRANSFER.getValue().equals(encounter.getStatusEnum())) {
return R.fail("患者处于待转科状态,请使用转科功能");
return R.fail(MessageUtils.message("atd.clean.pending.transfer"));
}
// 校验是否有未处理完的医嘱(药品/诊疗/耗材)
String blockingMsg = checkBlockingOrders(encounterId);
@@ -794,10 +795,10 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
List<EncounterLocation> encounterLocationList = encounterLocationService.getEncounterLocationList(encounterId,
LocationForm.BED, EncounterActivityStatus.ACTIVE);
if (encounterLocationList == null || encounterLocationList.size() != 1) {
return R.fail("清床失败,请检查病床状态");
return R.fail(MessageUtils.message("atd.clean.bed.status.fail"));
}
locationService.updateStatusById(encounterLocationList.get(0).getLocationId(), LocationStatus.IDLE.getValue());
return R.ok("清床完成");
return R.ok(MessageUtils.message("atd.clean.complete"));
}
/**
@@ -892,7 +893,8 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
public R<?> getPendingMedication(Long encounterId) {
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
return R.ok(atdManageAppMapper.getPendingMedication(encounterId, DispenseStatus.EXECUTED.getValue(),
DispenseStatus.SUBMITTED.getValue(), RequestStatus.CANCELLED.getValue(), tenantId));
DispenseStatus.SUBMITTED.getValue(), RequestStatus.CANCELLED.getValue(),
DispenseStatus.PENDING_REFUND.getValue(), tenantId));
}
/**
@@ -1120,15 +1122,15 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> cancelBedAssignment(Long encounterId) {
if (encounterId == null) {
return R.fail("退床失败,请选择有效的就诊记录");
return R.fail(MessageUtils.message("atd.bed.release.fail.invalid"));
}
Encounter encounter = encounterService.getById(encounterId);
if (encounter == null) {
return R.fail("未找到该住院就诊记录");
return R.fail(MessageUtils.message("atd.bed.release.not.found"));
}
// 仅已入院状态允许退床
if (!EncounterZyStatus.ADMITTED_TO_THE_HOSPITAL.getValue().equals(encounter.getStatusEnum())) {
return R.fail("该患者未在科,无法办理退床");
return R.fail(MessageUtils.message("atd.bed.release.not.in.ward"));
}
// 校验是否产生了医嘱或计费
@@ -1138,7 +1140,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
.eq(MedicationRequest::getEncounterId, encounterId)
.eq(MedicationRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (medCount > 0) {
return R.fail("患者已产生医嘱或计费,无法直接退床");
return R.fail(MessageUtils.message("atd.bed.release.has.orders"));
}
// 2. 检查诊疗医嘱
@@ -1147,7 +1149,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
.eq(ServiceRequest::getEncounterId, encounterId)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (svcCount > 0) {
return R.fail("患者已产生医嘱或计费,无法直接退床");
return R.fail(MessageUtils.message("atd.bed.release.has.orders"));
}
// 3. 检查耗材医嘱
@@ -1156,7 +1158,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
.eq(DeviceRequest::getEncounterId, encounterId)
.eq(DeviceRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (devCount > 0) {
return R.fail("患者已产生医嘱或计费,无法直接退床");
return R.fail(MessageUtils.message("atd.bed.release.has.orders"));
}
// 4. 检查计费记录
@@ -1164,7 +1166,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
new LambdaQueryWrapper<ChargeItem>()
.eq(ChargeItem::getEncounterId, encounterId));
if (chargeCount > 0) {
return R.fail("患者已产生医嘱或计费,无法直接退床");
return R.fail(MessageUtils.message("atd.bed.release.has.orders"));
}
// 更新原病床状态为 空闲 (LocationStatus.IDLE)
@@ -1187,7 +1189,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
encounter.setStatusEnum(EncounterZyStatus.REGISTERED.getValue());
encounterService.saveOrUpdateEncounter(encounter);
return R.ok("退床成功");
return R.ok(MessageUtils.message("atd.bed.release.success"));
}
/**
@@ -1201,37 +1203,37 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> changeBedAssginment(Long encounterId, Long targetBedId) {
if (encounterId == null) {
return R.fail("换床失败,请选择有效的就诊记录");
return R.fail(MessageUtils.message("atd.bed.transfer.fail.invalid"));
}
if (targetBedId == null) {
return R.fail("换床失败,请选择目标床位");
return R.fail(MessageUtils.message("atd.bed.transfer.fail.no.target"));
}
Encounter encounter = encounterService.getById(encounterId);
if (encounter == null) {
return R.fail("未找到就诊记录");
return R.fail(MessageUtils.message("atd.bed.transfer.not.found"));
}
// 仅已入院状态允许换床
if (!EncounterZyStatus.ADMITTED_TO_THE_HOSPITAL.getValue().equals(encounter.getStatusEnum())) {
return R.fail("该患者未在科,无法办理换床");
return R.fail(MessageUtils.message("atd.bed.transfer.not.in.ward"));
}
// 查询目标床位
Location targetBed = locationService.getById(targetBedId);
if (targetBed == null) {
return R.fail("目标床位不存在");
return R.fail(MessageUtils.message("atd.bed.transfer.target.not.exist"));
}
if (!LocationForm.BED.getValue().equals(targetBed.getFormEnum())) {
return R.fail("所选位置不是床位");
return R.fail(MessageUtils.message("atd.bed.transfer.not.bed"));
}
// 根据目标床位的 busNo 获取其父级房间 (house)
String bedBusNo = targetBed.getBusNo();
if (bedBusNo == null || !bedBusNo.contains(".")) {
return R.fail("目标床位编码异常");
return R.fail(MessageUtils.message("atd.bed.transfer.code.error"));
}
String[] parts = bedBusNo.split("\\.");
if (parts.length < 2) {
return R.fail("目标床位编码层级异常");
return R.fail(MessageUtils.message("atd.bed.transfer.code.level.error"));
}
String houseBusNo = parts[0] + "." + parts[1];
Location targetHouse = locationService.lambdaQuery()
@@ -1240,7 +1242,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
.eq(Location::getDeleteFlag, "0")
.one();
if (targetHouse == null) {
return R.fail("未找到目标床位所属的病房");
return R.fail(MessageUtils.message("atd.bed.transfer.house.not.found"));
}
Date now = new Date();
@@ -1258,24 +1260,24 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
Long targetEncounterId = occupiedBedLocs.get(0).getEncounterId();
Encounter targetEncounter = encounterService.getById(targetEncounterId);
if (targetEncounter == null) {
return R.fail("目标床位占用患者就诊记录异常");
return R.fail(MessageUtils.message("atd.bed.transfer.occupied.record.error"));
}
if (!EncounterZyStatus.ADMITTED_TO_THE_HOSPITAL.getValue().equals(targetEncounter.getStatusEnum())) {
return R.fail("目标床位占用患者已不在科,无法办理换床");
return R.fail(MessageUtils.message("atd.bed.transfer.occupied.not.in.ward"));
}
// 获取当前患者的原床位和原病房
List<EncounterLocation> currentBedLocs = encounterLocationService.getEncounterLocationList(encounterId,
LocationForm.BED, EncounterActivityStatus.ACTIVE);
if (currentBedLocs == null || currentBedLocs.isEmpty()) {
return R.fail("当前患者未分配床位,无法进行换床互换");
return R.fail(MessageUtils.message("atd.bed.transfer.no.current.bed"));
}
Long currentBedId = currentBedLocs.get(0).getLocationId();
List<EncounterLocation> currentHouseLocs = encounterLocationService.getEncounterLocationList(encounterId,
LocationForm.HOUSE, EncounterActivityStatus.ACTIVE);
if (currentHouseLocs == null || currentHouseLocs.isEmpty()) {
return R.fail("当前患者原病房记录不存在");
return R.fail(MessageUtils.message("atd.bed.transfer.no.current.house"));
}
Long currentHouseId = currentHouseLocs.get(0).getLocationId();
@@ -1300,7 +1302,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
encounterLocationService.creatEncounterLocation(targetEncounterId, targetStartTime, currentHouseId, LocationForm.HOUSE.getValue());
encounterLocationService.creatEncounterLocation(targetEncounterId, targetStartTime, currentBedId, LocationForm.BED.getValue());
return R.ok("床位互换成功");
return R.ok(MessageUtils.message("atd.bed.swap.success"));
} else {
// Target bed is vacant! Normal bed change
// 获取当前患者原床位
@@ -1324,8 +1326,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
// 4. 将目标床位状态更新为占用 (LocationStatus.OCCUPY)
locationService.updateStatusById(targetBedId, LocationStatus.OCCUPY.getValue());
return R.ok("换床成功");
return R.ok(MessageUtils.message("atd.bed.transfer.success"));
}
}
}

View File

@@ -188,7 +188,6 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
inpatientAdviceParam.setRequestStatus(null);
// 提取deadline手动处理
// Bug #714修复截止时间过滤使用request_time限制检索范围
// Bug #763修复NULL-safe的end_time比较
String deadline = inpatientAdviceParam.getDeadline();
inpatientAdviceParam.setDeadline(null);
// 构建查询条件
@@ -218,15 +217,17 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
= Arrays.stream(encounterIds.split(CommonConstants.Common.COMMA)).map(Long::parseLong).toList();
queryWrapper.in(CommonConstants.FieldName.EncounterId, encounterIdList);
}
// 手动拼接截止时间条件:
// 1. request_time >= deadline只显示截止时间之后创建的医嘱Bug #714修复
// 默认值为当天00:00:00默认只加载当天数据避免加载过长周期的历史未核对数据
// 2. end_time IS NULL OR end_time <= deadlineNULL-safe终止时间比较Bug #763修复
// 手动拼接截止时间条件:当天00:00:00 <= request_time <= deadline
// 默认deadline为当天23:59:59既排除历史医嘱又保证护士可以校对当天医嘱。
if (deadline != null && !deadline.isEmpty()) {
Date deadlineTime = DateUtils.parseDate(deadline);
if (deadlineTime != null) {
queryWrapper.ge("request_time", deadlineTime);
queryWrapper.and(w -> w.isNull("end_time").or().le("end_time", deadlineTime));
Date dayStartTime = Date.from(deadlineTime.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate()
.atStartOfDay(ZoneId.systemDefault())
.toInstant());
queryWrapper.between("request_time", dayStartTime, deadlineTime);
} else {
log.warn("截止时间解析失败: {}", deadline);
}
@@ -268,15 +269,9 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
e.setSingleDose(doseStr + unitStr);
}
// 总量:剂量 × 数量 + 单位(仅药品医嘱)
if (e.getDose() != null && e.getQuantity() != null) {
BigDecimal total = e.getDose().multiply(BigDecimal.valueOf(e.getQuantity()));
String totalStr = total.stripTrailingZeros().toPlainString();
String unitStr = e.getUnitCode_dictText() != null ? e.getUnitCode_dictText() : "";
e.setTotalAmount(totalStr + unitStr);
} else if (e.getQuantity() != null) {
String unitStr = e.getUnitCode_dictText() != null ? e.getUnitCode_dictText() : "";
e.setTotalAmount(e.getQuantity() + unitStr);
// 总量:药品请求数量按最小单位存储时,折算回当前展示单位。
if (e.getQuantity() != null) {
e.setTotalAmount(normalizeTotalAmount(e));
}
// 频次/用法组合
@@ -407,6 +402,30 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
return R.ok(inpatientAdvicePage);
}
private String normalizeTotalAmount(InpatientAdviceDto advice) {
BigDecimal quantity = advice.getQuantity();
if (quantity == null) {
return null;
}
if (CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(advice.getAdviceTable())
&& advice.getPartPercent() != null
&& advice.getPartPercent().compareTo(BigDecimal.ZERO) > 0
&& advice.getUnitCode() != null
&& advice.getMinUnitCode() != null
&& !advice.getUnitCode().equals(advice.getMinUnitCode())) {
BigDecimal partPercent = advice.getPartPercent();
if (quantity.compareTo(partPercent) >= 0) {
BigDecimal[] divideResult = quantity.divideAndRemainder(partPercent);
if (BigDecimal.ZERO.compareTo(divideResult[1]) == 0) {
quantity = divideResult[0];
}
}
}
return quantity.stripTrailingZeros().toPlainString();
}
/**
* 医嘱校对通过
*
@@ -526,7 +545,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
deviceRequestService.updateCompletedStatusBatch(otherDevIds);
}
}
return R.ok(null, "校对成功");
return R.ok(null, MessageUtils.message("his.nurse.proofread_success"));
}
/**
@@ -566,7 +585,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
.collect(Collectors.toSet());
executedIds.removeAll(cancelledRefundIds);
if (!executedIds.isEmpty()) {
return R.fail("该医嘱已执行,请先取消执行后再退回");
return R.fail(MessageUtils.message("advice.process.executed.cannot.return"));
}
// 校验药品医嘱是否已发药,已发药的医嘱不允许退回
if (!medRequestList.isEmpty()) {
@@ -576,7 +595,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
.in(MedicationDispense::getMedReqId, medReqIds)
.eq(MedicationDispense::getStatusEnum, DispenseStatus.COMPLETED.getValue()));
if (!dispenseList.isEmpty()) {
return R.fail("该药品已由药房发放,请先执行退药处理,不可直接退回");
return R.fail(MessageUtils.message("advice.process.drug.dispensed.return.first"));
}
}
Long practitionerId = SecurityUtils.getPractitionerId();
@@ -602,7 +621,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
deviceRequestService.updateDraftStatusBatch(
deviceRequestList.stream().map(PerformInfoDto::getRequestId).toList());
}
return R.ok(null, "退回成功");
return R.ok(null, MessageUtils.message("his.nurse.return_success"));
}
/**
@@ -615,7 +634,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
@Transactional(rollbackFor = Exception.class)
public R<?> adviceCancelVerify(List<PerformInfoDto> performInfoList) {
if (performInfoList == null || performInfoList.isEmpty()) {
return R.fail("请先选择医嘱信息");
return R.fail(MessageUtils.message("advice.process.select.advice.first"));
}
// 分别创建列表来存储不同类型的请求
@@ -649,14 +668,14 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
.collect(Collectors.toSet());
executedIds.removeAll(cancelledRefundIds);
if (!executedIds.isEmpty()) {
return R.fail("该医嘱已执行,无法撤销校对,请先去医嘱执行模块取消执行");
return R.fail(MessageUtils.message("advice.process.executed.cannot.undo.verify"));
}
// 校验②:校验该医嘱是否已记账扣费。若已扣费,则不允许撤销校对。
List<ChargeItem> chargeItems = chargeItemService.getChargeItemInfoByReqId(allRequestIds);
boolean isBilled = chargeItems.stream().anyMatch(ci -> ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum()));
if (isBilled) {
return R.fail("该医嘱已记账收费,若需撤销请先进行退费/计账回滚");
return R.fail(MessageUtils.message("advice.process.billed.cannot.undo"));
}
// 校验③:若为药品医嘱,校验药房是否已发药(配药)。若已发药,则不允许撤销校对。
@@ -671,7 +690,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
DispenseStatus.PART_COMPLETED.getValue()
)));
if (!dispenseList.isEmpty()) {
return R.fail("药房已发药,请先进行退药申请");
return R.fail(MessageUtils.message("advice.process.drug.dispensed.return.apply"));
}
}
@@ -698,7 +717,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
.set(DeviceRequest::getCheckTime, null));
}
return R.ok(null, "撤销校对成功");
return R.ok(null, MessageUtils.message("his.nurse.undo_proofread_success"));
}
/**
@@ -946,7 +965,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
unitCode = medicationDefinition.get().getUnitCode();
}
if (minUnitCode == null || unitCode == null || partPercent == null) {
throw new ServiceException("药品信息有误,请联系管理员");
throw new ServiceException(MessageUtils.message("advice.process.drug.info.error"));
}
// 最小单位数量
BigDecimal minQuantity = BigDecimal.ZERO;
@@ -1018,7 +1037,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
SurgeryAppStatusEnum.VERIFIED.getCode());
}
}
return R.ok("取消执行成功,相关汇总领药单已重新生成");
return R.ok(MessageUtils.message("his.nurse.cancel_execute_success_regen"));
}
/**
@@ -1036,7 +1055,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
// 判断是否有空的pID
for (AdviceExecuteDetailParam adviceExecuteDetailParam : adviceExecuteDetailList) {
if (adviceExecuteDetailParam.getProcedureId() != null) {
return R.fail("执行失败");
return R.fail(MessageUtils.message("advice.process.execute.fail"));
}
}
@@ -1051,7 +1070,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
null, exeDate, notExeDate, adviceExecuteDetailParam.getGroupId(), null);
}
}
return R.ok("不执行成功");
return R.ok(MessageUtils.message("his.nurse.not_execute_success"));
}
/**

View File

@@ -88,7 +88,7 @@ public class EncounterAutoRollAppServiceImpl implements IEncounterAutoRollAppSer
long count = encounterAutoRollService.count(new LambdaQueryWrapper<EncounterAutoRoll>()
.eq(EncounterAutoRoll::getEncounterId, encounterId).eq(EncounterAutoRoll::getInstanceId, instanceId));
if (count > 0L) {
return R.fail("当前患者已经存在该信息,请勿重复绑定");
return R.fail(MessageUtils.message("his.encounter_roll.duplicate_bind"));
}
EncounterAutoRoll encounterAutoRoll = new EncounterAutoRoll();
encounterAutoRoll.setStatusEnum(PublicationStatus.ACTIVE.getValue()); // 状态

View File

@@ -202,7 +202,7 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
@Override
public R<?> medicineSummary(List<MedicineSummaryParam> medicineSummaryParamList) {
if (medicineSummaryParamList == null || medicineSummaryParamList.isEmpty()) {
throw new ServiceException("请至少选择一条待汇总的药品");
throw new ServiceException(MessageUtils.message("medicine.summary.select.at.least.one"));
}
// 领药人
Long receiverId = medicineSummaryParamList.get(0).getReceiverId();
@@ -217,11 +217,11 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
// 药品发放信息列表
List<MedicationDispense> medicationDispenseList = medicationDispenseService.listByIds(medDispenseIdList);
if (medicationDispenseList == null || medicationDispenseList.isEmpty()) {
throw new ServiceException("未找到药品发放信息");
throw new ServiceException(MessageUtils.message("medicine.summary.dispense.not.found"));
}
if (medicationDispenseList.stream().map(MedicationDispense::getStatusEnum)
.anyMatch(x -> x.equals(DispenseStatus.SUBMITTED.getValue()))) {
throw new ServiceException("药品已汇总,请勿重复汇总");
throw new ServiceException(MessageUtils.message("medicine.summary.already.summarized"));
}
// 查询药品信息
List<MedicationDefinition> medicationDefinitions = medicationDefinitionService
@@ -261,7 +261,7 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
unitCode = medicationDefinition.get().getUnitCode();
}
if (minUnitCode == null || unitCode == null || partPercent == null) {
throw new ServiceException("药品信息有误,请联系管理员");
throw new ServiceException(MessageUtils.message("advice.process.drug.info.error"));
}
// 最小单位数量
BigDecimal minQuantity = BigDecimal.ZERO;
@@ -296,14 +296,14 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
// 取消汇总申请(软删除)
List<Long> requestIdList = supplyRequestService.cancelSummarySupplyRequest(List.of(summaryNo));
if (requestIdList.isEmpty()) {
return R.fail("取消汇总申请失败");
return R.fail(MessageUtils.message("medicine.summary.cancel.fail"));
}
// 软删除汇总发放
supplyDeliveryService.deleteSupplyDeliveryByReqId(requestIdList);
// 取消药品汇总
boolean result = medicationDispenseService.cancelMedicationSummary(List.of(summaryNo));
if (!result) {
return R.fail("取消汇总申请失败");
return R.fail(MessageUtils.message("medicine.summary.cancel.fail"));
}
return R.ok(MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"取消"}));
}

View File

@@ -216,7 +216,7 @@ public class NurseBillingAppService implements INurseBillingAppService {
}
this.handleDel(deviceRequestIds, SERVICE_TABLE_DEVICE);
this.handleDel(activityRequestIds, SERVICE_TABLE_SERVICE);
return R.ok("删除成功");
return R.ok(MessageUtils.message("his.nurse.delete_success"));
}
/**
@@ -233,8 +233,9 @@ public class NurseBillingAppService implements INurseBillingAppService {
// 初始化查询参数
String encounterIds = inpatientAdviceParam.getEncounterIds();
inpatientAdviceParam.setEncounterIds(null);
Integer exeStatus = inpatientAdviceParam.getExeStatus();
inpatientAdviceParam.setExeStatus(null);
// 提取deadline手动处理防止自动拼接列名不存在的错误
String deadline = inpatientAdviceParam.getDeadline();
inpatientAdviceParam.setDeadline(null);
@@ -291,18 +292,18 @@ public class NurseBillingAppService implements INurseBillingAppService {
private R<?> checkNurseBillingParam(RegAdviceSaveParam regAdviceSaveParam) {
// 1. 整体参数非空校验请求体为null直接返回失败
if (regAdviceSaveParam == null) {
return R.fail("划价请求失败:未获取到有效请求数据,请重新提交");
return R.fail(MessageUtils.message("nurse.billing.param.invalid"));
}
// 2. 核心字段非空校验患者住院科室ID不能为空
if (regAdviceSaveParam.getOrganizationId() == null) {
return R.fail("划价请求失败:患者住院科室信息缺失,请确认患者科室后重试");
return R.fail(MessageUtils.message("nurse.billing.dept.missing"));
}
// 3. 医嘱列表非空校验:必须选择至少一个待划价项目
List<RegAdviceSaveDto> adviceList = regAdviceSaveParam.getRegAdviceSaveList();
if (adviceList == null || adviceList.isEmpty()) {
return R.fail("划价请求失败:未选择任何待划价项目,请添加医嘱后提交");
return R.fail(MessageUtils.message("nurse.billing.no.items"));
}
// 4. 库存校验:临时注释(当前需求:划价不校验库存,实际发放时校验)
@@ -316,7 +317,7 @@ public class NurseBillingAppService implements INurseBillingAppService {
String inventoryTip = adviceUtils.checkInventory(new ArrayList<>(needCheckInventoryList));
if (inventoryTip != null) {
return R.fail("划价失败:" + inventoryTip + ",请联系库房确认库存或调整申请数量");
return R.fail(MessageUtils.message("his.nurse.billing_inventory_tip", inventoryTip));
}
*/
// 所有校验通过
@@ -726,7 +727,7 @@ public class NurseBillingAppService implements INurseBillingAppService {
boolean hasBilledItem
= chargeItemList.stream().anyMatch(ci -> ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum()));
if (hasBilledItem) {
throw new ServiceException("删除失败:部分项目已完成收费(结算),不支持直接删除,请联系收费人员处理后重试");
throw new ServiceException(MessageUtils.message("nurse.billing.delete.fail.billed"));
}
}
@@ -776,7 +777,7 @@ public class NurseBillingAppService implements INurseBillingAppService {
HttpServletRequest request) {
List<Long> encounterIds = costDetailSearchParam.getEncounterIds();
if (encounterIds == null || encounterIds.isEmpty()) {
return R.fail("就诊ID不能为空");
return R.fail(MessageUtils.message("nurse.billing.encounter.id.empty"));
}
costDetailSearchParam.setEncounterIds(null);
QueryWrapper<CostDetailSearchParam> queryWrapper

Some files were not shown because too many files have changed in this diff Show More