Compare commits
28 Commits
9b35fec931
...
1212
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d85686b06 | |||
| b33cb6f9a1 | |||
| 072e71b025 | |||
| 47394de43c | |||
| f0f1dde6b6 | |||
| 1ab1165697 | |||
| a8f1b1fdfa | |||
| 3b94d19199 | |||
| db1139a14f | |||
|
|
bea74aeac2 | ||
|
|
634a1f45f9 | ||
| 8f1ad3307c | |||
| d8080fa22d | |||
|
|
e8783d9f8f | ||
| d8c4348341 | |||
|
|
8e61490005 | ||
| f5f4e3c48e | |||
| 0f013715b8 | |||
| fb9722d328 | |||
| 6f9192d30d | |||
| f2b5b90f34 | |||
| a2cbd5e583 | |||
| d3df46858b | |||
| 47a7a945bc | |||
| 0a56c0dcf0 | |||
| 15d32134e2 | |||
| eff98ea5eb | |||
| a47306825a |
104
check_display_order.sql
Normal file
104
check_display_order.sql
Normal file
@@ -0,0 +1,104 @@
|
||||
-- 检查流水号(display_order)是否按“科室+医生+当天”正确递增
|
||||
--
|
||||
-- 说明:
|
||||
-- 1. display_order 存的是纯数字(1, 2, 3...),不带时间戳前缀
|
||||
-- 2. 时间戳前缀(如 20260109)是在前端显示时加上的
|
||||
-- 3. 后端用 Redis key "ORG-{科室ID}-DOC-{医生ID}" 按天自增
|
||||
--
|
||||
-- 如何判断逻辑是否正确:
|
||||
-- 同一科室、同一医生、同一天的记录,display_order 应该递增(1, 2, 3...)
|
||||
-- 不同科室、不同医生、不同天的记录,可能都是 1(这是正常的)
|
||||
|
||||
-- ========================================
|
||||
-- 查询1:按“科室+医生+日期”分组,看每组内的 display_order 是否递增
|
||||
-- ========================================
|
||||
SELECT
|
||||
DATE(start_time) AS 日期,
|
||||
organization_id AS 科室ID,
|
||||
registrar_id AS 医生ID,
|
||||
COUNT(*) AS 该组记录数,
|
||||
MIN(display_order) AS 最小序号,
|
||||
MAX(display_order) AS 最大序号,
|
||||
STRING_AGG(display_order::text, ', ' ORDER BY start_time) AS 序号列表,
|
||||
STRING_AGG(id::text, ', ' ORDER BY start_time) AS 记录ID列表
|
||||
FROM adm_encounter
|
||||
WHERE delete_flag = '0'
|
||||
AND start_time >= CURRENT_DATE - INTERVAL '7 days' -- 只看最近7天
|
||||
AND display_order IS NOT NULL
|
||||
GROUP BY DATE(start_time), organization_id, registrar_id
|
||||
ORDER BY 日期 DESC, 科室ID, 医生ID;
|
||||
|
||||
-- ========================================
|
||||
-- 查询2:详细查看每条记录,看同组内的序号是否连续
|
||||
-- ========================================
|
||||
SELECT
|
||||
id AS 记录ID,
|
||||
DATE(start_time) AS 日期,
|
||||
organization_id AS 科室ID,
|
||||
registrar_id AS 医生ID,
|
||||
start_time AS 挂号时间,
|
||||
display_order AS 流水号,
|
||||
-- 计算:同组内的序号应该是 1, 2, 3...,看是否有重复或跳号
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(start_time), organization_id, registrar_id
|
||||
ORDER BY start_time
|
||||
) AS 应该是第几个,
|
||||
CASE
|
||||
WHEN display_order = ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(start_time), organization_id, registrar_id
|
||||
ORDER BY start_time
|
||||
) THEN '✓ 正常'
|
||||
ELSE '✗ 异常'
|
||||
END AS 是否正常
|
||||
FROM adm_encounter
|
||||
WHERE delete_flag = '0'
|
||||
AND start_time >= CURRENT_DATE - INTERVAL '7 days'
|
||||
AND display_order IS NOT NULL
|
||||
ORDER BY DATE(start_time) DESC, organization_id, registrar_id, start_time;
|
||||
|
||||
-- ========================================
|
||||
-- 查询3:只看今天的数据(最直观)
|
||||
-- ========================================
|
||||
SELECT
|
||||
id AS 记录ID,
|
||||
organization_id AS 科室ID,
|
||||
registrar_id AS 医生ID,
|
||||
start_time AS 挂号时间,
|
||||
display_order AS 流水号
|
||||
FROM adm_encounter
|
||||
WHERE delete_flag = '0'
|
||||
AND DATE(start_time) = CURRENT_DATE
|
||||
AND display_order IS NOT NULL
|
||||
ORDER BY organization_id, registrar_id, start_time;
|
||||
|
||||
-- ========================================
|
||||
-- 查询4:发现问题 - 找出同组内 display_order 重复的记录
|
||||
-- ========================================
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
id,
|
||||
DATE(start_time) AS reg_date,
|
||||
organization_id,
|
||||
registrar_id,
|
||||
start_time,
|
||||
display_order,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(start_time), organization_id, registrar_id
|
||||
ORDER BY start_time
|
||||
) AS should_be_order
|
||||
FROM adm_encounter
|
||||
WHERE delete_flag = '0'
|
||||
AND start_time >= CURRENT_DATE - INTERVAL '7 days'
|
||||
AND display_order IS NOT NULL
|
||||
)
|
||||
SELECT
|
||||
reg_date AS 日期,
|
||||
organization_id AS 科室ID,
|
||||
registrar_id AS 医生ID,
|
||||
COUNT(*) AS 重复数量,
|
||||
STRING_AGG(id::text || '->' || display_order::text, ', ') AS 问题记录
|
||||
FROM ranked
|
||||
WHERE display_order != should_be_order
|
||||
GROUP BY reg_date, organization_id, registrar_id
|
||||
ORDER BY reg_date DESC;
|
||||
|
||||
10
md/test.html
Normal file
10
md/test.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>测试合并11112</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,179 +0,0 @@
|
||||
# 中医诊断主诊断功能实现说明
|
||||
|
||||
## 问题描述
|
||||
中医诊断在添加时无法设置主诊断标记,导致保存后无法正确标识主诊断。
|
||||
|
||||
## 问题原因
|
||||
在 `addDiagnosisDialog.vue` 中保存中医诊断时,没有传递 `maindiseFlag`(主诊断标记)字段到后端。
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 前端修改
|
||||
|
||||
#### 1.1 添加主诊断UI(addDiagnosisDialog.vue)
|
||||
在诊断详情区域为每个中医诊断添加了主诊断复选框:
|
||||
|
||||
```vue
|
||||
<el-checkbox
|
||||
v-model="item.isMain"
|
||||
label="主诊断"
|
||||
:true-label="true"
|
||||
:false-label="false"
|
||||
border
|
||||
size="small"
|
||||
style="margin-right: 10px;"
|
||||
@change="(value) => handleMaindise(value, index)"
|
||||
/>
|
||||
```
|
||||
|
||||
#### 1.2 添加主诊断逻辑处理
|
||||
|
||||
**新增诊断时的默认行为:**
|
||||
- 第一个添加的中医诊断自动设置为主诊断
|
||||
- 后续添加的诊断默认不是主诊断
|
||||
|
||||
**主诊断唯一性校验:**
|
||||
```javascript
|
||||
function handleMaindise(value, index) {
|
||||
if (value) {
|
||||
// 检查是否已有其他主诊断
|
||||
let mainCount = 0;
|
||||
tcmDiagonsisList.value.forEach((item, idx) => {
|
||||
if (item.isMain && idx !== index) {
|
||||
mainCount++;
|
||||
}
|
||||
});
|
||||
|
||||
if (mainCount > 0) {
|
||||
// 取消当前选择
|
||||
tcmDiagonsisList.value[index].isMain = false;
|
||||
proxy.$modal.msgWarning('只能有一条主诊断');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新保存列表中的主诊断标记
|
||||
const syndromeGroupNo = tcmDiagonsisList.value[index].syndromeGroupNo;
|
||||
tcmDiagonsisSaveList.value.forEach((item, idx) => {
|
||||
if (item.syndromeGroupNo === syndromeGroupNo) {
|
||||
// 每个证候组有两条记录(病和证),只有第一条(病)设置主诊断标记
|
||||
if (idx % 2 === 0 || tcmDiagonsisSaveList.value[idx - 1]?.syndromeGroupNo !== syndromeGroupNo) {
|
||||
item.maindiseFlag = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 取消主诊断
|
||||
const syndromeGroupNo = tcmDiagonsisList.value[index].syndromeGroupNo;
|
||||
tcmDiagonsisSaveList.value.forEach((item) => {
|
||||
if (item.syndromeGroupNo === syndromeGroupNo) {
|
||||
item.maindiseFlag = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 保存时包含主诊断字段
|
||||
|
||||
**新增诊断时:**
|
||||
```javascript
|
||||
tcmDiagonsisSaveList.value.push({
|
||||
definitionId: row.id,
|
||||
ybNo: row.ybNo,
|
||||
syndromeGroupNo: timestamp.value,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: '11',
|
||||
maindiseFlag: isFirstDiagnosis ? 1 : 0, // 添加主诊断标记
|
||||
});
|
||||
```
|
||||
|
||||
**修改诊断时:**
|
||||
```javascript
|
||||
tcmDiagonsisSaveList.value.push({
|
||||
conditionId: item.conditionId,
|
||||
updateId: updateIds[0],
|
||||
definitionId: item.illnessDefinitionId,
|
||||
ybNo: item.ybNo,
|
||||
syndromeGroupNo: item.syndromeGroupNo,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: '11',
|
||||
diagSrtNo: item.diagSrtNo,
|
||||
maindiseFlag: isMain ? 1 : 0, // 保留原有的主诊断标记
|
||||
});
|
||||
```
|
||||
|
||||
#### 1.4 诊断列表显示(diagnosis.vue)
|
||||
|
||||
在获取中医诊断列表时,正确读取并显示主诊断标记:
|
||||
|
||||
```javascript
|
||||
form.value.diagnosisList.push({
|
||||
name: item.name + '-' + res.data.symptom[index].name,
|
||||
diagSrtNo: item.diagSrtNo,
|
||||
ybNo: item.ybNo,
|
||||
medTypeCode: item.medTypeCode,
|
||||
syndromeGroupNo: item.syndromeGroupNo,
|
||||
typeName: '中医诊断',
|
||||
conditionId: item.conditionId,
|
||||
symptomConditionId: res.data.symptom[index].conditionId,
|
||||
updateId: item.encounterDiagnosisId + '-' + res.data.symptom[index].encounterDiagnosisId,
|
||||
illnessDefinitionId: item.definitionId,
|
||||
symptomDefinitionId: res.data.symptom[index].definitionId,
|
||||
symptomYbNo: res.data.symptom[index].ybNo,
|
||||
maindiseFlag: item.maindiseFlag || 0, // 添加主诊断标记
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 后端支持
|
||||
|
||||
后端已经支持 `maindiseFlag` 字段的保存和读取:
|
||||
|
||||
**SaveDiagnosisChildParam.java:**
|
||||
```java
|
||||
/**
|
||||
* 主诊断标记 (1:是,0:否)
|
||||
*/
|
||||
private Integer maindiseFlag;
|
||||
```
|
||||
|
||||
**DoctorStationChineseMedicalAppServiceImpl.java:**
|
||||
```java
|
||||
encounterDiagnosis.setMaindiseFlag(saveDiagnosisChildParam.getMaindiseFlag());
|
||||
```
|
||||
|
||||
## 业务规则
|
||||
|
||||
1. **主诊断标记位置**:主诊断标记在"病"上(每个病-证组合的第一条记录)
|
||||
2. **主诊断唯一性**:中医诊断只能有一个主诊断
|
||||
3. **与西医诊断的关系**:中医诊断和西医诊断可以各有一个主诊断(互不冲突)
|
||||
4. **默认行为**:第一个添加的中医诊断自动设置为主诊断
|
||||
|
||||
## 修改文件清单
|
||||
|
||||
1. `openhis-ui-vue3/src/views/doctorstation/components/diagnosis/addDiagnosisDialog.vue`
|
||||
- 添加主诊断复选框UI
|
||||
- 添加主诊断逻辑处理函数
|
||||
- 修改保存数据时包含 maindiseFlag 字段
|
||||
|
||||
2. `openhis-ui-vue3/src/views/doctorstation/components/diagnosis/diagnosis.vue`
|
||||
- 修改获取中医诊断列表时读取 maindiseFlag 字段
|
||||
- 修改传递给对话框的数据包含 maindiseFlag 字段
|
||||
|
||||
## 测试要点
|
||||
|
||||
1. ✅ 新增中医诊断时,第一个诊断自动设置为主诊断
|
||||
2. ✅ 可以手动勾选/取消主诊断复选框
|
||||
3. ✅ 只能有一个主诊断(尝试勾选第二个时会提示错误)
|
||||
4. ✅ 保存后主诊断标记正确保存到数据库
|
||||
5. ✅ 刷新页面后主诊断标记正确显示
|
||||
6. ✅ 修改已有诊断时,主诊断标记正确回显
|
||||
7. ✅ 中医诊断和西医诊断的主诊断互不影响
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 中医诊断是"病-证"成对出现的,主诊断标记只设置在"病"上
|
||||
2. 证候记录的 maindiseFlag 始终为 0
|
||||
3. 主诊断唯一性校验只在中医诊断内部进行,不影响西医诊断
|
||||
|
||||
## 完成时间
|
||||
2026年1月9日
|
||||
178
md/公告通知弹窗功能说明.md
178
md/公告通知弹窗功能说明.md
@@ -1,178 +0,0 @@
|
||||
# 公告通知弹窗功能说明
|
||||
|
||||
## 功能概述
|
||||
用户登录后,系统会自动弹出公告通知窗口,显示未读的系统公告和通知。
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 1. 自动弹出
|
||||
- 登录后 1 秒自动加载公告列表
|
||||
- 如果有未读公告,自动弹出弹窗显示
|
||||
- 延迟加载避免影响页面初始渲染
|
||||
|
||||
### 2. 优先级显示
|
||||
- **高优先级**(1):红色背景 `#fff1f0`,红色文字 `#ff4d4f`
|
||||
- **中优先级**(2):橙色背景 `#fff7e6`,橙色文字 `#faad14`
|
||||
- **低优先级**(3):灰色背景 `#f0f2f5`,灰色文字 `#909399`
|
||||
|
||||
### 3. 排序规则
|
||||
- 按优先级升序排列(高 -> 中 -> 低)
|
||||
- 相同优先级按创建时间降序排列
|
||||
|
||||
### 4. 已读状态
|
||||
- 未读公告:黄色背景高亮显示
|
||||
- 已读公告:默认白色背景
|
||||
- 点击公告自动标记为已读
|
||||
|
||||
### 5. 分类显示
|
||||
- **通知**(1):蓝色图标
|
||||
- **紧急**(2):红色警告图标
|
||||
- **信息**(3):绿色信息图标
|
||||
- **成功**(4):紫色成功图标
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/
|
||||
│ ├── NoticePopup/
|
||||
│ │ └── index.vue # 登录后自动弹窗组件
|
||||
│ └── NoticePanel/
|
||||
│ └── index.vue # 手动打开的公告面板
|
||||
├── layout/
|
||||
│ └── index.vue # 主布局,引入 NoticePopup
|
||||
└── views/
|
||||
└── system/
|
||||
└── notice/
|
||||
└── index.vue # 公告管理页面
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 前端 API
|
||||
```javascript
|
||||
// 获取用户公告列表
|
||||
getUserNotices()
|
||||
|
||||
// 标记为已读
|
||||
markAsRead(noticeId)
|
||||
|
||||
// 全部标记为已读
|
||||
markAllAsRead(noticeIds)
|
||||
|
||||
// 获取未读数量
|
||||
getUnreadCount()
|
||||
```
|
||||
|
||||
### 后端接口
|
||||
```java
|
||||
// GET /system/notice/public/notice
|
||||
// 获取当前用户的公告列表(含已读状态)
|
||||
|
||||
// GET /system/notice/public/unread/count
|
||||
// 获取未读公告数量
|
||||
|
||||
// POST /system/notice/public/read/{noticeId}
|
||||
// 标记公告为已读
|
||||
|
||||
// POST /system/notice/public/read/all
|
||||
// 批量标记为已读
|
||||
```
|
||||
|
||||
## 数据库字段
|
||||
|
||||
### sys_notice 表新增字段
|
||||
```sql
|
||||
-- 优先级字段
|
||||
priority VARCHAR(1) DEFAULT '3'
|
||||
|
||||
-- 发布状态字段
|
||||
publish_status VARCHAR(1) DEFAULT '0'
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 1. 数据库迁移
|
||||
执行 SQL 脚本添加必要的字段:
|
||||
```bash
|
||||
# 添加优先级字段
|
||||
ALTER TABLE sys_notice ADD COLUMN priority VARCHAR(1) DEFAULT '3';
|
||||
|
||||
# 添加发布状态字段
|
||||
ALTER TABLE sys_notice ADD COLUMN publish_status VARCHAR(1) DEFAULT '0';
|
||||
```
|
||||
|
||||
### 2. 后台管理
|
||||
在 `系统管理 > 公告管理` 中:
|
||||
1. 点击"新增"创建公告
|
||||
2. 选择优先级:高/中/低
|
||||
3. 选择公告类型:通知/紧急/信息/成功
|
||||
4. 填写标题和内容
|
||||
5. 点击"发布"按钮
|
||||
|
||||
### 3. 用户端显示
|
||||
- 登录后自动弹出未读公告
|
||||
- 点击顶部导航栏铃铛图标可手动打开
|
||||
- 点击公告查看详情
|
||||
- 支持全部标记为已读
|
||||
|
||||
## 样式说明
|
||||
|
||||
### 弹窗样式
|
||||
- 宽度:800px
|
||||
- 高度:最大 600px
|
||||
- 标题栏:渐变紫色背景 `linear-gradient(135deg, #667eea 0%, #764ba2 100%)`
|
||||
- 左右分栏布局
|
||||
|
||||
### 列表样式
|
||||
- 列表宽度:380px
|
||||
- 滚动区域:最大高度 500px
|
||||
- 未读高亮:黄色背景 `#fffbe6`
|
||||
- 激活项:蓝色左边框 `#1890ff`
|
||||
|
||||
### 详情样式
|
||||
- 自适应宽度
|
||||
- 标题字号:18px
|
||||
- 内容字号:14px
|
||||
- 行高:1.8
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **权限控制**
|
||||
- 只有已发布的公告才会显示
|
||||
- 只有正常状态的公告才会显示
|
||||
|
||||
2. **性能优化**
|
||||
- 使用延迟加载(1秒)
|
||||
- 使用虚拟滚动(el-scrollbar)
|
||||
- 按需加载详情
|
||||
|
||||
3. **用户体验**
|
||||
- 支持点击空白处关闭
|
||||
- 支持ESC键关闭
|
||||
- 未读状态醒目标识
|
||||
- 优先级颜色区分明显
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 弹窗不显示
|
||||
1. 检查后端接口 `/system/notice/public/notice` 是否正常返回
|
||||
2. 检查是否有未读公告
|
||||
3. 检查浏览器控制台是否有错误
|
||||
4. 清除浏览器缓存重试
|
||||
|
||||
### 样式错乱
|
||||
1. 检查 Element Plus 版本是否兼容
|
||||
2. 检查样式是否被其他 CSS 覆盖
|
||||
3. 使用浏览器开发者工具检查样式
|
||||
|
||||
### 数据不更新
|
||||
1. 检查后端返回的数据格式
|
||||
2. 检查 API 调用是否成功
|
||||
3. 检查响应拦截器处理
|
||||
|
||||
## 版本信息
|
||||
- 创建日期:2025-12-30
|
||||
- 功能版本:v1.0
|
||||
- 前端框架:Vue 3 + Element Plus
|
||||
- 后端框架:Spring Boot + MyBatis Plus
|
||||
@@ -1,254 +0,0 @@
|
||||
# 手术人员字段不显示问题解决方案
|
||||
|
||||
## 问题描述
|
||||
主刀医生、麻醉医生、助手1、助手2、执行科这些字段在手术查看页面中没有显示数据。
|
||||
|
||||
## 问题原因
|
||||
这些字段在数据库中可能为 **null 或空值**,虽然保存了 ID(如 `main_surgeon_id`),但没有保存对应的姓名(如 `main_surgeon_name`)。
|
||||
|
||||
## 解决步骤
|
||||
|
||||
### 步骤 1:检查数据库中字段的实际值
|
||||
|
||||
执行以下 SQL 查看当前数据:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id,
|
||||
surgery_no,
|
||||
main_surgeon_id,
|
||||
main_surgeon_name,
|
||||
anesthetist_id,
|
||||
anesthetist_name,
|
||||
assistant_1_id,
|
||||
assistant_1_name,
|
||||
assistant_2_id,
|
||||
assistant_2_name,
|
||||
operating_room_id,
|
||||
operating_room_name,
|
||||
org_id,
|
||||
org_name
|
||||
FROM public.cli_surgery
|
||||
WHERE delete_flag = '0'
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
**请告诉我结果**:特别是 `main_surgeon_name`、`anesthetist_name`、`assistant_1_name`、`assistant_2_name`、`operating_room_name`、`org_name` 这些字段的值。
|
||||
|
||||
### 步骤 2:检查用户表结构
|
||||
|
||||
执行以下 SQL 查看用户表的结构:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
column_name,
|
||||
data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'sys_user'
|
||||
AND column_name IN ('user_id', 'nick_name', 'user_name', 'practitioner_id')
|
||||
ORDER BY column_name;
|
||||
```
|
||||
|
||||
**目的**:确定人员ID和姓名的对应关系。
|
||||
|
||||
### 步骤 3:填充人员姓名字段(推荐方法)
|
||||
|
||||
使用以下 SQL 脚本填充人员姓名:
|
||||
|
||||
```sql
|
||||
-- 填充主刀医生姓名
|
||||
UPDATE public.cli_surgery s
|
||||
SET main_surgeon_name = u.nick_name
|
||||
FROM public.sys_user u
|
||||
WHERE s.main_surgeon_id = u.user_id
|
||||
AND s.main_surgeon_name IS NULL
|
||||
AND s.delete_flag = '0';
|
||||
|
||||
-- 填充麻醉医生姓名
|
||||
UPDATE public.cli_surgery s
|
||||
SET anesthetist_name = u.nick_name
|
||||
FROM public.sys_user u
|
||||
WHERE s.anesthetist_id = u.user_id
|
||||
AND s.anesthetist_name IS NULL
|
||||
AND s.delete_flag = '0';
|
||||
|
||||
-- 填充助手1姓名
|
||||
UPDATE public.cli_surgery s
|
||||
SET assistant_1_name = u.nick_name
|
||||
FROM public.sys_user u
|
||||
WHERE s.assistant_1_id = u.user_id
|
||||
AND s.assistant_1_name IS NULL
|
||||
AND s.delete_flag = '0';
|
||||
|
||||
-- 填充助手2姓名
|
||||
UPDATE public.cli_surgery s
|
||||
SET assistant_2_name = u.nick_name
|
||||
FROM public.sys_user u
|
||||
WHERE s.assistant_2_id = u.user_id
|
||||
AND s.assistant_2_name IS NULL
|
||||
AND s.delete_flag = '0';
|
||||
|
||||
-- 填充手术室名称
|
||||
UPDATE public.cli_surgery s
|
||||
SET operating_room_name = r.name
|
||||
FROM public.cli_operating_room r
|
||||
WHERE s.operating_room_id = r.id
|
||||
AND s.operating_room_name IS NULL
|
||||
AND s.delete_flag = '0';
|
||||
|
||||
-- 填充执行科室名称
|
||||
UPDATE public.cli_surgery s
|
||||
SET org_name = o.name
|
||||
FROM public.adm_organization o
|
||||
WHERE s.org_id = o.id
|
||||
AND s.org_name IS NULL
|
||||
AND s.delete_flag = '0';
|
||||
```
|
||||
|
||||
### 步骤 4:验证更新结果
|
||||
|
||||
执行以下 SQL 验证是否更新成功:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id,
|
||||
surgery_no,
|
||||
main_surgeon_id,
|
||||
main_surgeon_name,
|
||||
anesthetist_id,
|
||||
anesthetist_name,
|
||||
assistant_1_id,
|
||||
assistant_1_name,
|
||||
assistant_2_id,
|
||||
assistant_2_name,
|
||||
operating_room_id,
|
||||
operating_room_name,
|
||||
org_id,
|
||||
org_name
|
||||
FROM public.cli_surgery
|
||||
WHERE delete_flag = '0'
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
**预期结果**:所有 `*_name` 字段都应该有值。
|
||||
|
||||
### 步骤 5:刷新前端页面
|
||||
|
||||
1. 刷新手术管理页面
|
||||
2. 点击某个手术记录的"查看"按钮
|
||||
3. 检查详情对话框中是否显示这些字段
|
||||
|
||||
## 前端代码检查
|
||||
|
||||
### 1. 检查详情对话框显示
|
||||
|
||||
打开 `surgerymanage/index.vue` 文件,查看详情对话框部分:
|
||||
|
||||
```vue
|
||||
<el-descriptions-item label="主刀医生">{{ viewData.mainSurgeonName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="麻醉医生">{{ viewData.anesthetistName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="助手1">{{ viewData.assistant1Name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="助手2">{{ viewData.assistant2Name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手术室">{{ viewData.operatingRoomName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="执行科室">{{ viewData.orgName }}</el-descriptions-item>
|
||||
```
|
||||
|
||||
**确认**:这些字段名是否正确(注意驼峰命名)。
|
||||
|
||||
### 2. 检查浏览器控制台
|
||||
|
||||
1. 打开浏览器开发者工具(F12)
|
||||
2. 切换到 Console 标签
|
||||
3. 点击"查看"按钮
|
||||
4. 查看是否有 JavaScript 错误
|
||||
|
||||
### 3. 检查 Network 响应
|
||||
|
||||
1. 切换到 Network 标签
|
||||
2. 点击"查看"按钮
|
||||
3. 找到 `/clinical-manage/surgery/surgery-detail` 请求
|
||||
4. 查看响应内容
|
||||
|
||||
**检查**:响应数据中是否包含这些字段,值是什么。
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 问题 1:UPDATE SQL 执行失败
|
||||
|
||||
**症状**:报错 "relation does not exist" 或 "column does not exist"
|
||||
|
||||
**解决**:
|
||||
1. 检查表名是否正确(sys_user 或 adm_practitioner)
|
||||
2. 检查字段名是否正确(user_id 或 practitioner_id)
|
||||
|
||||
### 问题 2:UPDATE 后字段仍为 null
|
||||
|
||||
**症状**:UPDATE 执行成功,但字段仍为 null
|
||||
|
||||
**原因**:关联表中没有对应的记录
|
||||
|
||||
**解决**:检查人员ID是否存在于人员表中
|
||||
|
||||
```sql
|
||||
-- 检查主刀医生ID是否存在
|
||||
SELECT s.main_surgeon_id, u.nick_name
|
||||
FROM public.cli_surgery s
|
||||
LEFT JOIN public.sys_user u ON s.main_surgeon_id = u.user_id
|
||||
WHERE s.main_surgeon_id IS NOT NULL
|
||||
AND u.user_id IS NULL
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
### 问题 3:前端仍然不显示
|
||||
|
||||
**症状**:数据库中有值,但前端不显示
|
||||
|
||||
**原因**:
|
||||
1. 前端字段名不匹配
|
||||
2. 前端数据绑定有问题
|
||||
|
||||
**解决**:
|
||||
1. 检查 MyBatis XML 映射是否正确
|
||||
2. 检查后端返回的 JSON 数据结构
|
||||
3. 检查前端变量名是否正确
|
||||
|
||||
## 后续改进建议
|
||||
|
||||
### 1. 保存时自动填充姓名
|
||||
|
||||
在前端或后端保存手术信息时,根据选择的医生ID自动查询并填充姓名字段。
|
||||
|
||||
### 2. 提供人员选择功能
|
||||
|
||||
在前端提供医生、科室等选择下拉框,而不是手动输入ID。
|
||||
|
||||
### 3. 添加数据完整性校验
|
||||
|
||||
在保存前检查:如果选择了人员ID,必须填充对应的姓名字段。
|
||||
|
||||
## 相关文件
|
||||
|
||||
1. **检查和填充脚本**:`e:/his/检查和填充手术人员字段.sql`
|
||||
2. **填充脚本**:`e:/his/填充手术人员字段姓名.sql`
|
||||
3. **MyBatis 映射**:`e:/his/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml`
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] 数据库查询显示字段为 null
|
||||
- [ ] 执行了填充 SQL 脚本
|
||||
- [ ] 验证更新后字段有值
|
||||
- [ ] 刷新前端页面
|
||||
- [ ] 详情对话框中正确显示
|
||||
|
||||
## 联系支持
|
||||
|
||||
如果以上步骤都无法解决问题,请提供:
|
||||
|
||||
1. **步骤 1 的查询结果**:当前数据库中这些字段的值
|
||||
2. **步骤 2 的查询结果**:sys_user 表的结构
|
||||
3. **UPDATE SQL 执行结果**:是否有错误,更新了多少条记录
|
||||
4. **步骤 4 的验证结果**:更新后的字段值
|
||||
5. **浏览器控制台错误**:是否有 JavaScript 错误
|
||||
6. **Network 响应数据**:后端返回的完整数据
|
||||
@@ -1,120 +0,0 @@
|
||||
# 手术和麻醉信息Redis缓存实现说明
|
||||
|
||||
## 概述
|
||||
为提高手术和麻醉信息的查询性能,已将手术信息缓存到Redis中。接口查询时先从Redis缓存获取,如果没有则从数据库查询并更新到Redis缓存。
|
||||
|
||||
## 实现细节
|
||||
|
||||
### 1. Redis缓存Key定义
|
||||
在 `openhis-common/src/main/java/com/openhis/common/utils/RedisKeys.java` 中定义了以下缓存Key:
|
||||
|
||||
```java
|
||||
// 单个手术信息缓存
|
||||
public static String getSurgeryKey(Long surgeryId)
|
||||
|
||||
// 按患者ID查询的手术列表缓存
|
||||
public static String getSurgeryListByPatientKey(Long patientId)
|
||||
|
||||
// 按就诊ID查询的手术列表缓存
|
||||
public static String getSurgeryListByEncounterKey(Long encounterId)
|
||||
```
|
||||
|
||||
### 2. 缓存实现
|
||||
|
||||
#### 2.1 SurgeryServiceImpl (Domain层)
|
||||
- **getSurgeryById(Long id)**: 根据手术ID查询单个手术信息
|
||||
- 先从Redis缓存获取
|
||||
- 缓存未命中则从数据库查询
|
||||
- 查询结果存入Redis缓存(30分钟过期)
|
||||
|
||||
- **getSurgeryListByPatientId(Long patientId)**: 根据患者ID查询手术列表
|
||||
- 先从Redis缓存获取
|
||||
- 缓存未命中则从数据库查询
|
||||
- 查询结果存入Redis缓存(30分钟过期)
|
||||
|
||||
- **getSurgeryListByEncounterId(Long encounterId)**: 根据就诊ID查询手术列表
|
||||
- 先从Redis缓存获取
|
||||
- 缓存未命中则从数据库查询
|
||||
- 查询结果存入Redis缓存(30分钟过期)
|
||||
|
||||
- **insertSurgery(Surgery surgery)**: 新增手术信息
|
||||
- 插入成功后清除相关缓存
|
||||
|
||||
- **updateSurgery(Surgery surgery)**: 更新手术信息
|
||||
- 更新成功后清除相关缓存
|
||||
|
||||
- **deleteSurgery(Long id)**: 删除手术信息
|
||||
- 删除成功后清除相关缓存
|
||||
|
||||
- **updateSurgeryStatus(Long id, Integer statusEnum)**: 更新手术状态
|
||||
- 更新成功后清除相关缓存
|
||||
|
||||
#### 2.2 SurgeryAppServiceImpl (Application层)
|
||||
- **getSurgeryDetail(Long id)**: 根据ID查询手术详情
|
||||
- 先从Redis缓存获取
|
||||
- 缓存未命中则从数据库查询
|
||||
- 查询结果存入Redis缓存(30分钟过期)
|
||||
|
||||
- **addSurgery(SurgeryDto surgeryDto)**: 新增手术信息
|
||||
- 插入成功后清除相关缓存
|
||||
|
||||
- **updateSurgery(SurgeryDto surgeryDto)**: 更新手术信息
|
||||
- 更新成功后清除相关缓存
|
||||
|
||||
- **deleteSurgery(Long id)**: 删除手术信息
|
||||
- 删除成功后清除相关缓存
|
||||
|
||||
- **updateSurgeryStatus(Long id, Integer statusEnum)**: 更新手术状态
|
||||
- 更新成功后清除相关缓存
|
||||
|
||||
### 3. 缓存清除策略
|
||||
当手术信息发生变化时(新增、更新、删除),会清除以下相关缓存:
|
||||
1. 单个手术信息缓存
|
||||
2. 患者手术列表缓存
|
||||
3. 就诊手术列表缓存
|
||||
|
||||
### 4. 缓存配置
|
||||
- **缓存时间**: 30分钟
|
||||
- **时间单位**: TimeUnit.MINUTES
|
||||
- **序列化**: 使用RedisTemplate默认序列化方式
|
||||
|
||||
## 关于麻醉信息
|
||||
当前项目中,麻醉信息是手术表(`cli_surgery`)中的字段,包括:
|
||||
- 麻醉医生ID (anesthetistId)
|
||||
- 麻醉医生姓名 (anesthetistName)
|
||||
- 麻醉方式编码 (anesthesiaTypeEnum)
|
||||
- 麻醉费用 (anesthesiaFee)
|
||||
|
||||
这些字段已经包含在手术实体的缓存中,无需单独实现麻醉信息的缓存。
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 查询手术信息(自动使用缓存)
|
||||
```java
|
||||
// 自动从缓存获取,未命中则查询数据库
|
||||
Surgery surgery = surgeryService.getSurgeryById(surgeryId);
|
||||
```
|
||||
|
||||
### 更新手术信息(自动清除缓存)
|
||||
```java
|
||||
// 更新数据库,同时清除相关缓存
|
||||
surgeryService.updateSurgery(surgery);
|
||||
```
|
||||
|
||||
### 手动清除缓存(如需要)
|
||||
```java
|
||||
String cacheKey = RedisKeys.getSurgeryKey(surgeryId);
|
||||
redisCache.deleteObject(cacheKey);
|
||||
```
|
||||
|
||||
## 性能优化建议
|
||||
1. 对于频繁访问的手术信息,缓存命中率高,可显著提升查询性能
|
||||
2. 对于不常访问的手术信息,30分钟缓存时间可避免占用过多Redis内存
|
||||
3. 如需调整缓存时间,可修改代码中的 `30, TimeUnit.MINUTES` 参数
|
||||
4. 如需更精细的缓存控制,可考虑使用不同的缓存时间策略(如根据手术状态设置不同过期时间)
|
||||
|
||||
## 监控建议
|
||||
建议监控以下指标:
|
||||
- Redis缓存命中率
|
||||
- Redis内存使用情况
|
||||
- 查询响应时间对比(缓存命中 vs 缓存未命中)
|
||||
@@ -1,256 +0,0 @@
|
||||
# 手术室管理添加类型和所属科室字段功能说明
|
||||
|
||||
## 概述
|
||||
|
||||
本次更新为手术室管理模块添加了"类型"和"所属科室"字段,优化了手术室信息的分类管理。
|
||||
|
||||
**数据库类型**:PostgreSQL
|
||||
|
||||
## 功能特点
|
||||
|
||||
### 1. 手术室类型
|
||||
|
||||
支持四种手术室类型:
|
||||
- **急诊手术室**:用于急诊手术的手术室
|
||||
- **择期手术室**:用于择期手术的手术室(默认类型)
|
||||
- **日间手术室**:用于日间手术的手术室
|
||||
- **复合手术室**:用于复合手术的手术室
|
||||
|
||||
### 2. 所属科室
|
||||
|
||||
每个手术室可以关联到具体的科室,便于科室级别的资源管理。
|
||||
|
||||
## 修改内容
|
||||
|
||||
### 前端修改(Vue3)
|
||||
|
||||
#### 1. 手术室列表页面 (`operatingroom/index.vue`)
|
||||
|
||||
**列表表格新增列**:
|
||||
- 类型列:显示手术室类型(急诊手术室、择期手术室等)
|
||||
- 所属科室列:显示手术室所属的科室名称
|
||||
|
||||
**新增/修改对话框新增字段**:
|
||||
- 类型选择器:下拉选择手术室类型
|
||||
- 所属科室选择器:可搜索的科室下拉框
|
||||
|
||||
**查询表单保持原样**:
|
||||
- 仍支持按手术室名称和状态查询
|
||||
|
||||
**查看对话框新增显示**:
|
||||
- 类型信息
|
||||
- 所属科室信息
|
||||
|
||||
#### 2. 表单数据结构
|
||||
|
||||
```javascript
|
||||
const form = ref({
|
||||
id: undefined,
|
||||
busNo: undefined,
|
||||
name: undefined,
|
||||
roomTypeEnum: undefined, // 新增:手术室类型
|
||||
organizationId: undefined, // 已有:所属科室ID
|
||||
organizationName: undefined, // 已有:所属科室名称
|
||||
locationDescription: undefined,
|
||||
equipmentConfig: undefined,
|
||||
capacity: 1,
|
||||
statusEnum: 1,
|
||||
displayOrder: 0,
|
||||
remark: undefined
|
||||
})
|
||||
```
|
||||
|
||||
#### 3. 类型选项配置
|
||||
|
||||
```javascript
|
||||
const roomTypeOptions = ref([
|
||||
{ value: 1, label: '急诊手术室' },
|
||||
{ value: 2, label: '择期手术室' },
|
||||
{ value: 3, label: '日间手术室' },
|
||||
{ value: 4, label: '复合手术室' }
|
||||
])
|
||||
```
|
||||
|
||||
### 后端修改(Java)
|
||||
|
||||
#### 1. 实体类 (`OperatingRoom.java`)
|
||||
|
||||
**新增字段**:
|
||||
```java
|
||||
/** 手术室类型 */
|
||||
@Dict(dictCode = "operating_room_type")
|
||||
private Integer roomTypeEnum;
|
||||
private String roomTypeEnum_dictText;
|
||||
|
||||
/** 所属机构ID */
|
||||
private Long organizationId;
|
||||
|
||||
/** 所属机构名称 */
|
||||
private String organizationName;
|
||||
```
|
||||
|
||||
#### 2. DTO类 (`OperatingRoomDto.java`)
|
||||
|
||||
**新增字段**:
|
||||
```java
|
||||
/** 手术室类型 */
|
||||
@Dict(dictCode = "operating_room_type")
|
||||
private Integer roomTypeEnum;
|
||||
private String roomTypeEnum_dictText;
|
||||
|
||||
/** 所属机构ID */
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long organizationId;
|
||||
|
||||
/** 机构名称 */
|
||||
private String organizationName;
|
||||
```
|
||||
|
||||
#### 3. Service实现类 (`OperatingRoomAppServiceImpl.java`)
|
||||
|
||||
**查询列表方法优化**:
|
||||
- 添加类型字段的枚举值转换逻辑
|
||||
- 根据类型编码设置对应的中文描述
|
||||
|
||||
**详情查询方法优化**:
|
||||
- 添加类型字段的枚举值转换
|
||||
- 查询所属科室的名称并回显
|
||||
|
||||
### 数据库修改
|
||||
|
||||
#### SQL脚本文件:`add_operating_room_type_fields.sql`(PostgreSQL版本)
|
||||
|
||||
**1. 添加字段**:
|
||||
```sql
|
||||
ALTER TABLE public.adm_operating_room
|
||||
ADD COLUMN room_type_enum INTEGER DEFAULT 2;
|
||||
|
||||
COMMENT ON COLUMN public.adm_operating_room.room_type_enum IS
|
||||
'手术室类型:1-急诊手术室,2-择期手术室,3-日间手术室,4-复合手术室';
|
||||
```
|
||||
|
||||
**2. 更新现有数据**:
|
||||
```sql
|
||||
UPDATE public.adm_operating_room
|
||||
SET room_type_enum = 2
|
||||
WHERE room_type_enum IS NULL;
|
||||
```
|
||||
|
||||
**3. 添加索引**:
|
||||
```sql
|
||||
CREATE INDEX idx_room_type ON public.adm_operating_room(room_type_enum);
|
||||
CREATE INDEX idx_org_id ON public.adm_operating_room(organization_id);
|
||||
```
|
||||
|
||||
**4. 字典数据**:
|
||||
- 新增字典类型:`operating_room_type`(手术室类型)
|
||||
- 新增字典项:
|
||||
- 急诊手术室(1)
|
||||
- 择期手术室(2)
|
||||
- 日间手术室(3)
|
||||
- 复合手术室(4)
|
||||
|
||||
**PostgreSQL特定语法说明**:
|
||||
- 使用 `public.adm_operating_room` 替代 `` `adm_operating_room` ``
|
||||
- 使用 `COMMENT ON COLUMN` 替代 `COMMENT` 在 `ALTER TABLE` 中
|
||||
- 使用 `nextval()` 和序列来生成字典类型ID
|
||||
- 使用 `information_schema.columns` 获取列信息
|
||||
- 使用 `CASE WHEN` 语句进行条件判断
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 数据库部署
|
||||
|
||||
执行SQL脚本(PostgreSQL):
|
||||
```bash
|
||||
psql -U postgres -d his_database -f add_operating_room_type_fields.sql
|
||||
```
|
||||
|
||||
或者使用 pgAdmin 等图形化工具执行SQL脚本。
|
||||
|
||||
### 2. 后端部署
|
||||
|
||||
重启后端服务,使新的代码生效。
|
||||
|
||||
### 3. 前端部署
|
||||
|
||||
重新编译并部署前端代码:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 新增手术室
|
||||
|
||||
1. 进入手术室管理页面
|
||||
2. 点击"新增手术室"按钮
|
||||
3. 填写手术室信息:
|
||||
- 手术室名称(必填)
|
||||
- 类型(可选,默认为择期手术室)
|
||||
- 所属科室(必填)
|
||||
- 位置描述
|
||||
- 设备配置
|
||||
- 容纳人数
|
||||
- 状态(默认为启用)
|
||||
- 显示顺序
|
||||
- 备注
|
||||
4. 点击"确定"保存
|
||||
|
||||
### 修改手术室
|
||||
|
||||
1. 在手术室列表中找到要修改的记录
|
||||
2. 点击"编辑"按钮
|
||||
3. 修改相关信息(包括类型和所属科室)
|
||||
4. 点击"确定"保存
|
||||
|
||||
### 查看手术室详情
|
||||
|
||||
1. 在手术室列表中点击"查看"按钮
|
||||
2. 查看完整的手术室信息,包括类型和所属科室
|
||||
|
||||
### 查询手术室
|
||||
|
||||
- 按手术室名称模糊查询
|
||||
- 按状态筛选(启用/停用)
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **数据迁移**:现有手术室的类型默认设置为"择期手术室"(2),可以根据实际需要调整。
|
||||
|
||||
2. **科室关联**:所属科室是必填字段,需要在科室管理中先配置好科室信息。
|
||||
|
||||
3. **类型字典**:手术室类型字典已自动创建,可以在系统字典管理中进行维护。
|
||||
|
||||
4. **索引优化**:已为类型和科室字段添加索引,提升查询性能。
|
||||
|
||||
5. **兼容性**:此次修改保持了向后兼容性,不影响现有功能。
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] 数据库字段添加成功
|
||||
- [ ] 字典数据创建成功
|
||||
- [ ] 前端列表正确显示类型和所属科室
|
||||
- [ ] 新增手术室时可选择类型和所属科室
|
||||
- [ ] 修改手术室时可更新类型和所属科室
|
||||
- [ ] 查看手术室详情时正确显示类型和所属科室
|
||||
- [ ] 类型下拉选项显示正确
|
||||
- [ ] 所属科室选择器可正常搜索和选择
|
||||
- [ ] 查询功能正常工作
|
||||
- [ ] 没有语法错误和运行时错误
|
||||
|
||||
## 回滚方案
|
||||
|
||||
如需撤销本次修改,请执行SQL脚本中的回滚语句(PostgreSQL):
|
||||
|
||||
```sql
|
||||
DROP INDEX idx_room_type ON public.adm_operating_room;
|
||||
DROP INDEX idx_org_id ON public.adm_operating_room;
|
||||
DELETE FROM public.sys_dict_data WHERE dict_type = 'operating_room_type';
|
||||
DELETE FROM public.sys_dict_type WHERE dict_type = 'operating_room_type';
|
||||
ALTER TABLE public.adm_operating_room DROP COLUMN room_type_enum;
|
||||
```
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题,请联系技术支持团队。
|
||||
@@ -1,215 +0,0 @@
|
||||
# 手术申请医生科室字段保存问题解决方案
|
||||
|
||||
## 问题确认
|
||||
数据库中只保存了 ID 字段(`apply_doctor_id`、`apply_dept_id`),但没有保存名称字段(`apply_doctor_name`、`apply_dept_name`)。
|
||||
|
||||
## 根本原因
|
||||
**数据库表中缺少 `apply_doctor_name` 和 `apply_dept_name` 这两个字段!**
|
||||
|
||||
虽然 MyBatis 映射文件和实体类都配置了这些字段,但如果数据库表中不存在这些列,MyBatis 在插入时会静默忽略这些字段(不会报错),导致只有 ID 被保存。
|
||||
|
||||
## 解决步骤
|
||||
|
||||
### 步骤 1:执行数据库迁移脚本(必须!)
|
||||
|
||||
使用 Navicat Premium 17 执行以下 SQL:
|
||||
|
||||
```sql
|
||||
-- 方法1:使用 IF NOT EXISTS 语法(推荐)
|
||||
ALTER TABLE public.cli_surgery ADD COLUMN IF NOT EXISTS apply_doctor_name VARCHAR(100);
|
||||
COMMENT ON COLUMN public.cli_surgery.apply_doctor_name IS '申请医生姓名';
|
||||
|
||||
ALTER TABLE public.cli_surgery ADD COLUMN IF NOT EXISTS apply_dept_name VARCHAR(100);
|
||||
COMMENT ON COLUMN public.cli_surgery.apply_dept_name IS '申请科室名称';
|
||||
|
||||
-- 验证字段是否添加成功
|
||||
SELECT column_name, data_type, character_maximum_length
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'cli_surgery'
|
||||
AND column_name IN ('apply_doctor_name', 'apply_dept_name');
|
||||
```
|
||||
|
||||
**预期结果**:
|
||||
```
|
||||
apply_doctor_name | character varying | 100
|
||||
apply_dept_name | character varying | 100
|
||||
```
|
||||
|
||||
### 步骤 2:重启后端服务
|
||||
|
||||
执行数据库迁移后,必须重启后端服务以重新加载表结构。
|
||||
|
||||
### 步骤 3:新增手术并查看日志
|
||||
|
||||
1. 打开后端控制台或日志文件
|
||||
2. 在前端新增一条手术记录
|
||||
3. 查看后端日志,应该能看到:
|
||||
|
||||
```
|
||||
设置申请医生信息 - doctorId: 123, doctorName: 张医生, deptId: 456, deptName: 普外科
|
||||
前端提交的数据 - applyDoctorId: 123, applyDoctorName: 张医生, applyDeptId: 456, applyDeptName: 普外科
|
||||
准备插入手术记录 - applyDoctorId: 123, applyDoctorName: 张医生, applyDeptId: 456, deptName: 普外科
|
||||
准备插入手术记录 - applyDoctorId: 123, applyDoctorName: 张医生, applyDeptId: 456, deptName: 普外科
|
||||
插入后查询结果 - applyDoctorId: 123, applyDoctorName: 张医生, applyDeptId: 456, deptName: 普外科
|
||||
手术记录插入成功 - surgeryId: 1234567890123456789, surgeryNo: OP202501051234
|
||||
```
|
||||
|
||||
**关键检查点**:
|
||||
- `准备插入手术记录` 这行日志中,`applyDoctorName` 和 `applyDeptName` 必须有值(不能为 null)
|
||||
- `插入后查询结果` 这行日志中,这两个字段也必须有值
|
||||
|
||||
### 步骤 4:验证数据库
|
||||
|
||||
执行以下 SQL 查询最新插入的记录:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id,
|
||||
surgery_no,
|
||||
apply_doctor_id,
|
||||
apply_doctor_name,
|
||||
apply_dept_id,
|
||||
apply_dept_name,
|
||||
surgery_name,
|
||||
create_time
|
||||
FROM public.cli_surgery
|
||||
WHERE delete_flag = '0'
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
||||
**预期结果**:
|
||||
- `apply_doctor_id`:有值(例如:123)
|
||||
- `apply_doctor_name`:有值(例如:张医生)
|
||||
- `apply_dept_id`:有值(例如:456)
|
||||
- `apply_dept_name`:有值(例如:普外科)
|
||||
|
||||
### 步骤 5:测试前端显示
|
||||
|
||||
1. 刷新手术管理页面
|
||||
2. 查看列表中是否显示申请医生和申请科室列
|
||||
3. 点击"查看"或"编辑"按钮,检查详情对话框是否显示这些信息
|
||||
|
||||
## 常见问题和解决
|
||||
|
||||
### 问题 1:执行 SQL 后报错 "column does not exist"
|
||||
|
||||
**原因**:数据库表结构可能不同,或者表名不是 `cli_surgery`
|
||||
|
||||
**解决**:先执行以下 SQL 检查表名:
|
||||
|
||||
```sql
|
||||
SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_name LIKE '%surgery%'
|
||||
AND table_schema = 'public';
|
||||
```
|
||||
|
||||
### 问题 2:执行 SQL 后字段仍然不存在
|
||||
|
||||
**原因**:可能是权限问题或 SQL 语法问题
|
||||
|
||||
**解决**:尝试使用更简单的方式:
|
||||
|
||||
```sql
|
||||
-- 先检查表结构
|
||||
\d public.cli_surgery
|
||||
|
||||
-- 手动添加字段(如果不存在)
|
||||
-- 注意:如果字段已存在,这个语句会报错,这是正常的
|
||||
ALTER TABLE public.cli_surgery ADD COLUMN apply_doctor_name VARCHAR(100);
|
||||
ALTER TABLE public.cli_surgery ADD COLUMN apply_dept_name VARCHAR(100);
|
||||
```
|
||||
|
||||
### 问题 3:字段添加成功,但插入时仍然为空
|
||||
|
||||
**原因**:MyBatis 或 MyBatis-Plus 配置问题
|
||||
|
||||
**解决**:
|
||||
1. 检查实体类字段是否有 `@TableField` 注解
|
||||
2. 检查字段名是否与数据库列名一致
|
||||
3. 查看后端日志中的 `插入后查询结果`
|
||||
|
||||
### 问题 4:后端日志显示字段为 null
|
||||
|
||||
**原因**:后端代码中 `applyDoctorName` 或 `applyDeptName` 被设置为 null
|
||||
|
||||
**解决**:
|
||||
1. 检查 `SecurityUtils.getLoginUser().getUser().getNickName()` 是否返回 null
|
||||
2. 检查 `SecurityUtils.getLoginUser().getOrgId()` 是否返回 null
|
||||
3. 检查 `organizationService.getById(orgId)` 是否返回 null
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] 数据库迁移脚本已执行
|
||||
- [ ] 数据库字段已添加(步骤 1 验证 SQL 有结果)
|
||||
- [ ] 后端服务已重启
|
||||
- [ ] 后端日志显示 `准备插入手术记录` 且字段有值
|
||||
- [ ] 后端日志显示 `插入后查询结果` 且字段有值
|
||||
- [ ] 数据库查询显示字段有值(步骤 4)
|
||||
- [ ] 前端列表正确显示
|
||||
- [ ] 前端详情正确显示
|
||||
|
||||
## 调试 SQL 脚本
|
||||
|
||||
如果需要手动测试插入功能,可以执行:
|
||||
|
||||
```sql
|
||||
-- 测试插入(确保字段存在)
|
||||
INSERT INTO public.cli_surgery (
|
||||
surgery_no,
|
||||
patient_id,
|
||||
encounter_id,
|
||||
apply_doctor_id,
|
||||
apply_doctor_name,
|
||||
apply_dept_id,
|
||||
apply_dept_name,
|
||||
surgery_name,
|
||||
status_enum,
|
||||
delete_flag,
|
||||
create_time,
|
||||
update_time
|
||||
) VALUES (
|
||||
'TEST202501050002',
|
||||
(SELECT id FROM public.adm_patient WHERE delete_flag = '0' LIMIT 1),
|
||||
(SELECT id FROM public.adm_encounter WHERE delete_flag = '0' LIMIT 1),
|
||||
999,
|
||||
'手动测试医生',
|
||||
999,
|
||||
'手动测试科室',
|
||||
'手动测试手术',
|
||||
0,
|
||||
'0',
|
||||
NOW(),
|
||||
NOW()
|
||||
);
|
||||
|
||||
-- 查询刚才插入的数据
|
||||
SELECT
|
||||
surgery_no,
|
||||
apply_doctor_id,
|
||||
apply_doctor_name,
|
||||
apply_dept_id,
|
||||
apply_dept_name,
|
||||
surgery_name
|
||||
FROM public.cli_surgery
|
||||
WHERE surgery_no = 'TEST202501050002';
|
||||
|
||||
-- 清理测试数据
|
||||
-- DELETE FROM public.cli_surgery WHERE surgery_no = 'TEST202501050002';
|
||||
```
|
||||
|
||||
## 联系支持
|
||||
|
||||
如果以上步骤都无法解决问题,请提供:
|
||||
|
||||
1. **数据库表结构查询结果**:
|
||||
```sql
|
||||
\d public.cli_surgery
|
||||
```
|
||||
|
||||
2. **后端日志**:特别是 `准备插入手术记录` 和 `插入后查询结果` 这两行
|
||||
|
||||
3. **数据库查询结果**:执行步骤 4 中的 SQL,告诉我结果
|
||||
|
||||
4. **错误信息**:如果有任何错误提示
|
||||
@@ -1,194 +0,0 @@
|
||||
# 手术申请医生科室数据保存问题排查指南
|
||||
|
||||
## 问题现象
|
||||
新增手术后,列表页面和编辑查看页面没有显示申请医生名称和科室名称。
|
||||
|
||||
## 排查步骤
|
||||
|
||||
### 步骤1:检查数据库字段是否存在
|
||||
执行以下 SQL 检查字段是否已添加:
|
||||
|
||||
```sql
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'cli_surgery'
|
||||
AND column_name IN ('apply_doctor_name', 'apply_dept_name');
|
||||
```
|
||||
|
||||
**预期结果**:应该返回两条记录
|
||||
```
|
||||
apply_doctor_name | character varying
|
||||
apply_dept_name | character varying
|
||||
```
|
||||
|
||||
**如果结果为空**:说明字段未添加,需要执行迁移脚本。
|
||||
|
||||
### 步骤2:检查数据库迁移脚本是否执行
|
||||
执行迁移脚本(如果未执行):
|
||||
|
||||
```sql
|
||||
-- 检查并添加申请医生姓名字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'cli_surgery'
|
||||
AND column_name = 'apply_doctor_name'
|
||||
) THEN
|
||||
ALTER TABLE public.cli_surgery ADD COLUMN apply_doctor_name VARCHAR(100);
|
||||
COMMENT ON COLUMN public.cli_surgery.apply_doctor_name IS '申请医生姓名';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 检查并添加申请科室名称字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'cli_surgery'
|
||||
AND column_name = 'apply_dept_name'
|
||||
) THEN
|
||||
ALTER TABLE public.cli_surgery ADD COLUMN apply_dept_name VARCHAR(100);
|
||||
COMMENT ON COLUMN public.cli_surgery.apply_dept_name IS '申请科室名称';
|
||||
END IF;
|
||||
END $$;
|
||||
```
|
||||
|
||||
### 步骤3:重启后端服务
|
||||
执行数据库迁移后,必须重启后端服务。
|
||||
|
||||
### 步骤4:新增手术并查看后端日志
|
||||
1. 打开后端控制台或日志文件
|
||||
2. 在前端新增一条手术记录
|
||||
3. 查看后端日志,应该能看到以下信息:
|
||||
|
||||
```
|
||||
设置申请医生信息 - doctorId: 123, doctorName: 张医生, deptId: 456, deptName: 普外科
|
||||
前端提交的数据 - applyDoctorId: 123, applyDoctorName: 张医生, applyDeptId: 456, applyDeptName: 普外科
|
||||
准备插入手术记录 - applyDoctorId: 123, applyDoctorName: 张医生, applyDeptId: 456, deptName: 普外科
|
||||
手术记录插入成功 - surgeryId: 1234567890123456789, surgeryNo: OP202501051234
|
||||
```
|
||||
|
||||
**如果看不到这些日志**:说明代码没有执行到这里,检查是否有异常抛出。
|
||||
|
||||
**如果看到 "前端提交的数据 - applyDoctorName: null"**:说明前端提交的数据为空,需要检查前端代码。
|
||||
|
||||
### 步骤5:检查数据库中是否保存成功
|
||||
执行以下 SQL 查询最新插入的记录:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
id,
|
||||
surgery_no,
|
||||
patient_id,
|
||||
apply_doctor_id,
|
||||
apply_doctor_name,
|
||||
apply_dept_id,
|
||||
apply_dept_name,
|
||||
surgery_name,
|
||||
status_enum,
|
||||
create_time
|
||||
FROM public.cli_surgery
|
||||
WHERE delete_flag = '0'
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
**如果 apply_doctor_name 和 apply_dept_name 字段为空**:说明数据没有保存成功。
|
||||
|
||||
**如果字段有值**:说明保存成功,问题出在前端显示。
|
||||
|
||||
### 步骤6:检查前端 API 响应
|
||||
1. 打开浏览器开发者工具(F12)
|
||||
2. 切换到 Network 标签
|
||||
3. 新增手术
|
||||
4. 找到 `/clinical-manage/surgery/surgery-page` 请求
|
||||
5. 点击查看响应内容
|
||||
|
||||
检查响应数据中是否包含 `applyDoctorName` 和 `applyDeptName` 字段。
|
||||
|
||||
**如果响应中没有这些字段**:说明 MyBatis 映射有问题,检查 XML 配置。
|
||||
|
||||
**如果响应中有这些字段但值为 null**:说明数据库中为空,回到步骤5。
|
||||
|
||||
### 步骤7:检查前端表格显示
|
||||
查看前端代码中的表格列配置:
|
||||
|
||||
```vue
|
||||
<el-table-column label="申请医生" align="center" prop="applyDoctorName" width="100" />
|
||||
<el-table-column label="申请科室" align="center" prop="applyDeptName" width="120" show-overflow-tooltip />
|
||||
```
|
||||
|
||||
确保 `prop` 属性与后端返回的字段名一致(注意大小写)。
|
||||
|
||||
## 常见问题和解决方案
|
||||
|
||||
### 问题1:数据库字段未添加
|
||||
**症状**:后端报错 "column apply_doctor_name does not exist"
|
||||
**解决**:执行数据库迁移脚本
|
||||
|
||||
### 问题2:后端日志显示 applyDoctorName 为 null
|
||||
**症状**:日志中 "前端提交的数据 - applyDoctorName: null"
|
||||
**原因**:前端提交数据时,disabled 字段没有被包含
|
||||
**解决**:检查前端 submitForm 函数,确保手动设置了这些字段
|
||||
|
||||
### 问题3:数据库中有值,但前端不显示
|
||||
**症状**:数据库查询有值,前端响应也有值,但表格不显示
|
||||
**原因**:
|
||||
1. 前端 prop 属性名与后端字段名不一致(大小写问题)
|
||||
2. 前端数据未正确绑定
|
||||
**解决**:
|
||||
1. 检查 prop 属性名,确保与后端返回的 JSON 字段名一致
|
||||
2. 检查浏览器控制台是否有 JavaScript 错误
|
||||
|
||||
### 问题4:MyBatis 映射未生效
|
||||
**症状**:后端保存成功,但查询时字段为 null
|
||||
**原因**:XML 映射文件未正确配置
|
||||
**解决**:
|
||||
1. 检查 SurgeryMapper.xml 中的 resultMap 配置
|
||||
2. 检查 SQL 查询中是否包含这些字段
|
||||
3. 重启后端服务
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [ ] 数据库迁移脚本已执行
|
||||
- [ ] 数据库字段已添加(步骤1)
|
||||
- [ ] 后端服务已重启
|
||||
- [ ] 后端日志显示申请医生信息(步骤4)
|
||||
- [ ] 数据库中已保存数据(步骤5)
|
||||
- [ ] 前端 API 响应包含这些字段(步骤6)
|
||||
- [ ] 前端表格正确显示(步骤7)
|
||||
|
||||
## 附加 SQL 脚本
|
||||
|
||||
### 查看统计信息
|
||||
```sql
|
||||
SELECT
|
||||
COUNT(*) as total_count,
|
||||
COUNT(apply_doctor_name) as has_doctor_name_count,
|
||||
COUNT(apply_dept_name) as has_dept_name_count
|
||||
FROM public.cli_surgery
|
||||
WHERE delete_flag = '0';
|
||||
```
|
||||
|
||||
### 手动更新测试数据
|
||||
如果需要手动更新已有的测试数据:
|
||||
|
||||
```sql
|
||||
UPDATE public.cli_surgery
|
||||
SET apply_doctor_name = '测试医生',
|
||||
apply_dept_name = '测试科室'
|
||||
WHERE apply_doctor_name IS NULL
|
||||
AND delete_flag = '0';
|
||||
```
|
||||
|
||||
## 联系支持
|
||||
|
||||
如果以上步骤都无法解决问题,请提供以下信息:
|
||||
1. 数据库字段查询结果(步骤1)
|
||||
2. 后端日志截图(步骤4)
|
||||
3. 数据库查询结果(步骤5)
|
||||
4. 浏览器 Network 响应截图(步骤6)
|
||||
5. 浏览器 Console 错误信息
|
||||
351
md/手术管理模块开发说明.md
351
md/手术管理模块开发说明.md
@@ -1,351 +0,0 @@
|
||||
# 手术管理模块开发说明
|
||||
|
||||
## 模块概述
|
||||
|
||||
手术管理模块是一个完整的医疗手术管理系统,涵盖从手术排期、执行到记录的全流程管理。本模块基于经典的Spring Boot + Vue3前后端分离架构开发。
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 1. 手术信息管理
|
||||
- 手术基本信息录入(手术名称、编码、类型、等级)
|
||||
- 患者信息关联
|
||||
- 就诊信息关联
|
||||
- 手术部位描述
|
||||
|
||||
### 2. 手术团队管理
|
||||
- 主刀医生选择
|
||||
- 麻醉医生选择
|
||||
- 助手1/助手2选择
|
||||
- 巡回护士选择
|
||||
- 麻醉方式选择
|
||||
|
||||
### 3. 手术状态管理
|
||||
- 待排期
|
||||
- 已排期
|
||||
- 手术中
|
||||
- 已完成
|
||||
- 已取消
|
||||
- 暂停
|
||||
|
||||
### 4. 手术时间管理
|
||||
- 计划手术时间
|
||||
- 实际开始时间
|
||||
- 实际结束时间
|
||||
|
||||
### 5. 诊断信息管理
|
||||
- 术前诊断
|
||||
- 术后诊断
|
||||
- 手术经过描述
|
||||
- 术后医嘱
|
||||
- 并发症描述
|
||||
|
||||
### 6. 手术费用管理
|
||||
- 手术费用
|
||||
- 麻醉费用
|
||||
- 总费用自动计算
|
||||
|
||||
### 7. 手术切口管理
|
||||
- 切口等级(I级、II级、III级、IV级)
|
||||
- 愈合等级(甲级、乙级、丙级)
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 后端技术栈
|
||||
- Spring Boot 2.x
|
||||
- MyBatis Plus
|
||||
- PostgreSQL 12+
|
||||
- JDK 1.8+
|
||||
|
||||
### 前端技术栈
|
||||
- Vue 3.x
|
||||
- Element Plus
|
||||
- Axios
|
||||
- Vite
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
openh-is/
|
||||
├── openhis-server-new/ # 后端项目
|
||||
│ ├── openhis-domain/ # 领域层
|
||||
│ │ └── src/main/java/com/openhis/
|
||||
│ │ ├── clinical/
|
||||
│ │ │ ├── domain/
|
||||
│ │ │ │ └── Surgery.java # 手术实体类
|
||||
│ │ │ ├── mapper/
|
||||
│ │ │ │ └── SurgeryMapper.java # 手术Mapper接口
|
||||
│ │ │ └── service/
|
||||
│ │ │ ├── ISurgeryService.java # 手术Service接口
|
||||
│ │ │ └── impl/
|
||||
│ │ │ └── SurgeryServiceImpl.java # 手术Service实现
|
||||
│ │ └── common/ # 公共模块
|
||||
│ │ └── src/main/java/com/openhis/common/
|
||||
│ │ └── enums/ # 枚举类
|
||||
│ │ ├── SurgeryTypeEnum.java # 手术类型枚举
|
||||
│ │ ├── SurgeryStatusEnum.java # 手术状态枚举
|
||||
│ │ ├── SurgeryLevelEnum.java # 手术等级枚举
|
||||
│ │ ├── AnesthesiaTypeEnum.java # 麻醉方式枚举
|
||||
│ │ ├── IncisionLevelEnum.java # 切口等级枚举
|
||||
│ │ └── HealingLevelEnum.java # 愈合等级枚举
|
||||
│ │
|
||||
│ ├── openhis-application/ # 应用层
|
||||
│ │ └── src/main/java/com/openhis/web/clinicalmanage/
|
||||
│ │ ├── controller/
|
||||
│ │ │ └── SurgeryController.java # 手术控制器
|
||||
│ │ ├── dto/
|
||||
│ │ │ └── SurgeryDto.java # 手术数据传输对象
|
||||
│ │ ├── appservice/
|
||||
│ │ │ ├── ISurgeryAppService.java # 手术应用服务接口
|
||||
│ │ │ └── impl/
|
||||
│ │ │ └── SurgeryAppServiceImpl.java # 手术应用服务实现
|
||||
│ │ └── mapper/
|
||||
│ │ └── SurgeryAppMapper.java # 手术应用Mapper
|
||||
│ │
|
||||
│ └── src/main/resources/mapper/
|
||||
│ ├── clinical/
|
||||
│ │ └── SurgeryMapper.xml # 手术Mapper XML
|
||||
│ └── clinicalmanage/
|
||||
│ └── SurgeryMapper.xml # 手术应用Mapper XML
|
||||
│
|
||||
├── openhis-ui-vue3/ # 前端项目
|
||||
│ └── src/
|
||||
│ ├── api/
|
||||
│ │ └── surgerymanage.js # 手术API接口
|
||||
│ └── views/
|
||||
│ └── surgerymanage/
|
||||
│ └── index.vue # 手术管理页面
|
||||
│
|
||||
└── surgery_manage_init.sql # 数据库初始化脚本
|
||||
```
|
||||
|
||||
## 数据库设计
|
||||
|
||||
### 主表:cli_surgery(手术管理表)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | bigint | 主键ID |
|
||||
| surgery_no | varchar(50) | 手术编号(唯一) |
|
||||
| patient_id | bigint | 患者ID |
|
||||
| patient_name | varchar(100) | 患者姓名 |
|
||||
| encounter_id | bigint | 就诊ID |
|
||||
| surgery_name | varchar(200) | 手术名称 |
|
||||
| surgery_code | varchar(100) | 手术编码 |
|
||||
| surgery_type_enum | int2 | 手术类型 |
|
||||
| surgery_level | int2 | 手术等级 |
|
||||
| status_enum | int2 | 手术状态 |
|
||||
| planned_time | timestamp | 计划手术时间 |
|
||||
| actual_start_time | timestamp | 实际开始时间 |
|
||||
| actual_end_time | timestamp | 实际结束时间 |
|
||||
| main_surgeon_id | bigint | 主刀医生ID |
|
||||
| main_surgeon_name | varchar(100) | 主刀医生姓名 |
|
||||
| anesthetist_id | bigint | 麻醉医生ID |
|
||||
| anesthetist_name | varchar(100) | 麻醉医生姓名 |
|
||||
| anesthesia_type_enum | int2 | 麻醉方式 |
|
||||
| body_site | varchar(200) | 手术部位 |
|
||||
| preoperative_diagnosis | text | 术前诊断 |
|
||||
| postoperative_diagnosis | text | 术后诊断 |
|
||||
| surgery_fee | numeric(10,2) | 手术费用 |
|
||||
| anesthesia_fee | numeric(10,2) | 麻醉费用 |
|
||||
| total_fee | numeric(10,2) | 总费用 |
|
||||
|
||||
### 字典表
|
||||
|
||||
手术管理模块包含以下字典类型:
|
||||
- surgery_status(手术状态)
|
||||
- surgery_type(手术类型)
|
||||
- surgery_level(手术等级)
|
||||
- anesthesia_type(麻醉方式)
|
||||
- incision_level(切口等级)
|
||||
- healing_level(愈合等级)
|
||||
|
||||
## 安装部署
|
||||
|
||||
### 1. 数据库初始化
|
||||
|
||||
执行SQL脚本初始化数据库表和字典数据:
|
||||
|
||||
```bash
|
||||
psql -U postgres -d his_database -f surgery_manage_init.sql
|
||||
```
|
||||
|
||||
或者使用psql客户端执行:
|
||||
|
||||
```sql
|
||||
\i /path/to/surgery_manage_init.sql
|
||||
```
|
||||
|
||||
### 2. 后端配置
|
||||
|
||||
1. 将后端代码复制到对应目录
|
||||
2. 修改数据库连接配置(application.yml)
|
||||
3. 启动Spring Boot应用
|
||||
|
||||
### 3. 前端配置
|
||||
|
||||
1. 将前端代码复制到对应目录
|
||||
2. 配置API接口地址(.env.development)
|
||||
3. 启动前端开发服务器
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## API接口说明
|
||||
|
||||
### 1. 分页查询手术列表
|
||||
|
||||
**接口地址:** `GET /clinical-manage/surgery/surgery-page`
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"pageNo": 1,
|
||||
"pageSize": 10,
|
||||
"surgeryNo": "SS20251230001",
|
||||
"surgeryName": "阑尾切除术",
|
||||
"patientName": "张三",
|
||||
"statusEnum": 1,
|
||||
"surgeryTypeEnum": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 查询手术详情
|
||||
|
||||
**接口地址:** `GET /clinical-manage/surgery/surgery-detail`
|
||||
|
||||
**请求参数:**
|
||||
```
|
||||
id: 手术ID
|
||||
```
|
||||
|
||||
### 3. 新增手术
|
||||
|
||||
**接口地址:** `POST /clinical-manage/surgery/surgery`
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"patientId": 1,
|
||||
"surgeryName": "阑尾切除术",
|
||||
"surgeryCode": "ICD-9-CM:47.09",
|
||||
"surgeryTypeEnum": 2,
|
||||
"surgeryLevel": 2,
|
||||
"plannedTime": "2025-12-31 09:00:00",
|
||||
"mainSurgeonId": 10,
|
||||
"anesthetistId": 11,
|
||||
"anesthesiaTypeEnum": 3,
|
||||
"bodySite": "腹部"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 修改手术
|
||||
|
||||
**接口地址:** `PUT /clinical-manage/surgery/surgery`
|
||||
|
||||
**请求参数:** 同新增手术,需包含id
|
||||
|
||||
### 5. 删除手术
|
||||
|
||||
**接口地址:** `DELETE /clinical-manage/surgery/surgery`
|
||||
|
||||
**请求参数:**
|
||||
```
|
||||
id: 手术ID
|
||||
```
|
||||
|
||||
### 6. 更新手术状态
|
||||
|
||||
**接口地址:** `PUT /clinical-manage/surgery/surgery-status`
|
||||
|
||||
**请求参数:**
|
||||
```
|
||||
id: 手术ID
|
||||
statusEnum: 状态值
|
||||
```
|
||||
|
||||
## 前端页面功能
|
||||
|
||||
### 1. 查询功能
|
||||
- 支持按手术编号、手术名称、患者姓名模糊查询
|
||||
- 支持按手术状态、手术类型精确查询
|
||||
- 支持按计划时间范围查询
|
||||
|
||||
### 2. 新增功能
|
||||
- 完整的手术信息录入表单
|
||||
- 患者下拉选择
|
||||
- 医生/护士下拉选择
|
||||
- 费用自动计算
|
||||
|
||||
### 3. 编辑功能
|
||||
- 仅待排期和已排期状态的手术可编辑
|
||||
- 手术中或已完成的手术不可编辑
|
||||
|
||||
### 4. 状态流转
|
||||
- 已排期 → 手术中
|
||||
- 手术中 → 已完成
|
||||
- 待排期/已排期 → 已取消
|
||||
|
||||
### 5. 删除功能
|
||||
- 仅待排期和已排期状态的手术可删除
|
||||
- 已完成的手术不能删除
|
||||
|
||||
## 扩展开发建议
|
||||
|
||||
### 1. 手术排期管理
|
||||
- 可增加手术排期日历视图
|
||||
- 手术室资源冲突检测
|
||||
- 手术排队优先级管理
|
||||
|
||||
### 2. 手术统计报表
|
||||
- 手术量统计
|
||||
- 手术类型分布
|
||||
- 手术成功率统计
|
||||
- 手术费用统计
|
||||
|
||||
### 3. 手术文档管理
|
||||
- 手术知情同意书
|
||||
- 手术安全核查表
|
||||
- 手术记录单
|
||||
- 麻醉记录单
|
||||
|
||||
### 4. 手术质控管理
|
||||
- 手术质量评估
|
||||
- 并发症统计
|
||||
- 术后恢复跟踪
|
||||
- 手术质量指标管理
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **手术编号生成**:手术编号采用自动生成机制,格式为SS + 10位数字
|
||||
2. **权限控制**:需要配置相应的菜单权限和操作权限
|
||||
3. **数据校验**:新增手术时必须选择患者和主刀医生
|
||||
4. **状态流转**:手术状态的流转需要符合业务逻辑
|
||||
5. **费用计算**:总费用自动计算,不允许手动修改
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 手术编号重复怎么办?
|
||||
A: 手术编号是系统自动生成的唯一编号,不会重复。如果需要自定义编号,需要修改SurgeryServiceImpl中的生成逻辑。
|
||||
|
||||
### Q2: 如何添加新的手术类型?
|
||||
A: 在数据库sys_dict_data表中添加新的surgery_type字典数据即可。
|
||||
|
||||
### Q3: 手术开始后还能修改信息吗?
|
||||
A: 根据业务规则,手术开始后不允许修改基本信息,但可以补充术后诊断等信息。
|
||||
|
||||
### Q4: 如何实现手术室资源管理?
|
||||
A: 可以新增手术室管理模块,建立手术排期与手术室的关联关系,实现资源冲突检测。
|
||||
|
||||
## 版本历史
|
||||
|
||||
- v1.0.0 (2025-12-30)
|
||||
- 初始版本发布
|
||||
- 实现手术基本管理功能
|
||||
- 实现手术状态流转
|
||||
- 实现手术团队管理
|
||||
|
||||
## 联系方式
|
||||
|
||||
如有问题或建议,请联系开发团队。
|
||||
@@ -1,160 +0,0 @@
|
||||
# 门诊就诊记录SQL查询优化建议
|
||||
|
||||
## 当前查询分析
|
||||
|
||||
### 主要查询表
|
||||
```sql
|
||||
SELECT
|
||||
enc.id as encounterId,
|
||||
pt.name,
|
||||
pt.id_card,
|
||||
pt.bus_no as patientBusNo,
|
||||
enc.bus_no as encounterBusNo,
|
||||
pt.gender_enum,
|
||||
pt.phone,
|
||||
enc.create_time as encounterTime,
|
||||
enc.status_enum as subjectStatusEnum,
|
||||
org.name as organizationName,
|
||||
prac.name as doctorName
|
||||
FROM adm_encounter AS enc
|
||||
LEFT JOIN adm_organization AS org ON enc.organization_id = org.ID AND org.delete_flag = '0'
|
||||
LEFT JOIN adm_encounter_participant AS ep
|
||||
ON enc.ID = ep.encounter_id AND ep.type_code = #{participantType} AND ep.delete_flag = '0'
|
||||
LEFT JOIN adm_practitioner AS prac ON ep.practitioner_id = prac.ID AND prac.delete_flag = '0'
|
||||
LEFT JOIN adm_patient AS pt ON enc.patient_id = pt.ID AND pt.delete_flag = '0'
|
||||
```
|
||||
|
||||
### 常见查询条件
|
||||
1. `enc.delete_flag = '0'`
|
||||
2. `enc.tenant_id = ?`
|
||||
3. `pt.name LIKE ?`
|
||||
4. `pt.id_card LIKE ?`
|
||||
5. `pt.bus_no LIKE ?`
|
||||
6. `enc.bus_no LIKE ?`
|
||||
7. `pt.gender_enum = ?`
|
||||
8. `enc.status_enum = ?`
|
||||
9. `prac.name LIKE ?`
|
||||
10. `pt.phone LIKE ?`
|
||||
11. `enc.create_time BETWEEN ? AND ?`
|
||||
|
||||
## 索引优化建议
|
||||
|
||||
### 1. adm_encounter 表索引
|
||||
```sql
|
||||
-- 复合索引:提高查询性能
|
||||
CREATE INDEX idx_encounter_tenant_delete_status ON adm_encounter(tenant_id, delete_flag, status_enum);
|
||||
|
||||
-- 时间范围查询索引
|
||||
CREATE INDEX idx_encounter_create_time ON adm_encounter(create_time);
|
||||
|
||||
-- 业务编号查询索引
|
||||
CREATE INDEX idx_encounter_bus_no ON adm_encounter(bus_no);
|
||||
|
||||
-- 患者ID关联索引
|
||||
CREATE INDEX idx_encounter_patient_id ON adm_encounter(patient_id);
|
||||
```
|
||||
|
||||
### 2. adm_patient 表索引
|
||||
```sql
|
||||
-- 姓名模糊查询索引
|
||||
CREATE INDEX idx_patient_name ON adm_patient(name);
|
||||
|
||||
-- 身份证号查询索引
|
||||
CREATE INDEX idx_patient_id_card ON adm_patient(id_card);
|
||||
|
||||
-- 业务编号查询索引
|
||||
CREATE INDEX idx_patient_bus_no ON adm_patient(bus_no);
|
||||
|
||||
-- 电话查询索引
|
||||
CREATE INDEX idx_patient_phone ON adm_patient(phone);
|
||||
|
||||
-- 复合索引:常用查询条件
|
||||
CREATE INDEX idx_patient_delete_gender ON adm_patient(delete_flag, gender_enum);
|
||||
```
|
||||
|
||||
### 3. adm_encounter_participant 表索引
|
||||
```sql
|
||||
-- 复合索引:提高连接性能
|
||||
CREATE INDEX idx_ep_encounter_type ON adm_encounter_participant(encounter_id, type_code, delete_flag);
|
||||
|
||||
-- 参与者ID索引
|
||||
CREATE INDEX idx_ep_practitioner ON adm_encounter_participant(practitioner_id);
|
||||
```
|
||||
|
||||
### 4. adm_practitioner 表索引
|
||||
```sql
|
||||
-- 姓名查询索引
|
||||
CREATE INDEX idx_practitioner_name ON adm_practitioner(name);
|
||||
|
||||
-- 复合索引:常用查询条件
|
||||
CREATE INDEX idx_practitioner_delete_tenant ON adm_practitioner(delete_flag, tenant_id);
|
||||
```
|
||||
|
||||
### 5. adm_organization 表索引
|
||||
```sql
|
||||
-- 主键关联索引
|
||||
CREATE INDEX idx_organization_id_delete ON adm_organization(id, delete_flag);
|
||||
```
|
||||
|
||||
## 查询优化建议
|
||||
|
||||
### 1. 添加查询统计信息收集
|
||||
```sql
|
||||
-- 定期分析表统计信息
|
||||
ANALYZE TABLE adm_encounter;
|
||||
ANALYZE TABLE adm_patient;
|
||||
ANALYZE TABLE adm_encounter_participant;
|
||||
ANALYZE TABLE adm_practitioner;
|
||||
ANALYZE TABLE adm_organization;
|
||||
```
|
||||
|
||||
### 2. 考虑分区表(针对大数据量)
|
||||
如果 `adm_encounter` 表数据量超过100万条,考虑按时间分区:
|
||||
```sql
|
||||
-- 按月分区
|
||||
PARTITION BY RANGE (YEAR(create_time) * 100 + MONTH(create_time))
|
||||
(
|
||||
PARTITION p202501 VALUES LESS THAN (202501),
|
||||
PARTITION p202502 VALUES LESS THAN (202502),
|
||||
-- ... 更多分区
|
||||
);
|
||||
```
|
||||
|
||||
### 3. 添加覆盖索引(Covering Index)
|
||||
对于常用查询字段,创建覆盖索引避免回表:
|
||||
```sql
|
||||
CREATE INDEX idx_encounter_cover ON adm_encounter(
|
||||
tenant_id, delete_flag, create_time,
|
||||
status_enum, bus_no, patient_id
|
||||
) INCLUDE (organization_id);
|
||||
```
|
||||
|
||||
## 执行计划检查
|
||||
|
||||
建议定期检查查询执行计划:
|
||||
```sql
|
||||
EXPLAIN ANALYZE
|
||||
SELECT -- 完整查询语句
|
||||
FROM adm_encounter AS enc
|
||||
-- ... 连接条件
|
||||
WHERE enc.delete_flag = '0'
|
||||
AND enc.tenant_id = 1
|
||||
-- ... 其他条件
|
||||
ORDER BY enc.create_time DESC;
|
||||
```
|
||||
|
||||
## 监控建议
|
||||
|
||||
1. **慢查询监控**:监控执行时间超过1秒的查询
|
||||
2. **索引使用监控**:定期检查未使用的索引
|
||||
3. **表空间监控**:监控表增长和碎片情况
|
||||
4. **连接性能监控**:监控JOIN操作的性能
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 在测试环境创建建议的索引
|
||||
2. 执行查询性能测试
|
||||
3. 分析执行计划,确认索引有效性
|
||||
4. 在生产环境非高峰期创建索引
|
||||
5. 监控生产环境性能变化
|
||||
6. 定期维护和优化索引
|
||||
287
md/需求/94-手术室维护界面_2026-1-9.md
Normal file
287
md/需求/94-手术室维护界面_2026-1-9.md
Normal file
@@ -0,0 +1,287 @@
|
||||
## 手术室维护界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:手术室维护界面
|
||||
**页面目标**:提供手术室基础数据的维护功能,包括新增、编辑、启用/停用手术室信息,为手术安排提供基础数据支持
|
||||
**适用场景**:医院管理员需要新增、修改、启用/停用手术室信息时使用
|
||||
**页面类型**:列表页+表单页(含模态框)
|
||||
|
||||
**原型图地址:**https://static.pm-ai.cn/prototype/20260104/ee5d222231effefcb39624d1646a2e20/index.html
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 手术室列表展示与查询
|
||||
2. 新增手术室信息
|
||||
3. 编辑现有手术室信息
|
||||
4. 启用/停用手术室状态
|
||||
5. 数据有效性校验
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 管理员可集中管理所有手术室基础信息
|
||||
- 确保手术安排时能获取准确的手术室数据
|
||||
- 通过状态管理控制手术室可用性
|
||||
|
||||
**流程图:**
|
||||
|
||||

|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[手术室维护界面] --> B[手术室列表展示]
|
||||
|
||||
B --> C[新增手术室]
|
||||
|
||||
B --> D[编辑手术室]
|
||||
|
||||
B --> E[启用/停用手术室]
|
||||
|
||||
B --> F[查询手术室]
|
||||
|
||||
C --> G[点击新增按钮]
|
||||
|
||||
G --> H[打开新增模态框]
|
||||
|
||||
H --> I[填写表单字段]
|
||||
|
||||
I --> J{必填字段校验}
|
||||
|
||||
J -->|通过| K[提交数据]
|
||||
|
||||
J -->|不通过| L[提示请填写所有必填项]
|
||||
|
||||
K --> M[表格新增数据行]
|
||||
|
||||
D --> N[点击修改按钮]
|
||||
|
||||
N --> O[打开编辑模态框]
|
||||
|
||||
O --> P[修改表单字段]
|
||||
|
||||
P --> Q{必填字段校验}
|
||||
|
||||
Q -->|通过| R[保存数据]
|
||||
|
||||
Q -->|不通过| S[提示请填写所有必填项]
|
||||
|
||||
R --> T[更新表格对应行]
|
||||
|
||||
E --> U[点击启用/停用按钮]
|
||||
|
||||
U --> V{二次确认}
|
||||
|
||||
V -->|确认| W[切换状态标签]
|
||||
|
||||
V -->|取消| X[取消操作]
|
||||
|
||||
W --> Y[更新按钮状态]
|
||||
|
||||
F --> Z[输入查询条件]
|
||||
|
||||
Z --> AA[筛选表格数据]
|
||||
|
||||
K --> AB{房间号重复校验}
|
||||
|
||||
AB -->|不重复| AC[提示房间号已存在]
|
||||
|
||||
AB -->|重复| AD[更新按钮状态]
|
||||
```
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. 页头区域(15%高度)
|
||||
2. 表格展示区(85%高度)
|
||||
**布局特点**:上下布局,表格采用固定表头+滚动内容区设计
|
||||
**响应式要求**:移动端适配时改为纵向堆叠布局,操作按钮组变为纵向排列
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 页头区域
|
||||
|
||||
**区域位置**:页面顶部
|
||||
**区域尺寸**:高度60px,宽度100%
|
||||
**区域功能**:展示标题和主要操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **标题文本**
|
||||
- 元素类型:H1标题
|
||||
- 显示内容:"手术室列表"
|
||||
- 样式特征:1.75rem/600字重,深灰色(#333)
|
||||
- **新增按钮**
|
||||
- 元素类型:主要操作按钮
|
||||
- 显示内容:"新增"(带+图标)
|
||||
- 交互行为:点击触发新增模态框
|
||||
- 样式特征:蓝色背景(#5a7cff),白色文字,8px圆角,悬停上浮1px
|
||||
|
||||
#### 2. 表格展示区(手术室列表表格)
|
||||
|
||||
**区域位置**:页头下方
|
||||
**区域尺寸**:高度自适应,宽度100%
|
||||
**区域功能**:展示手术室数据并支持行级操作
|
||||
**包含元素**:
|
||||
|
||||
- **数据表格**
|
||||
- 展示方式:固定表头表格
|
||||
- 数据字段:
|
||||
- 房间号:文本 - OR01 - 不可操作
|
||||
- 手术室名称:文本 - 第一手术室 - 不可操作
|
||||
- 类型:文本 - 普通/日间/复合 - 不可操作
|
||||
- 所属科室:文本 - 外科 - 不可操作
|
||||
- 状态:标签 - 有效/无效 - 通过操作按钮切换
|
||||
- 操作功能:每行包含"修改"和"状态切换(停用-黄色/启用-绿色)"按钮
|
||||
- **表格样式**:
|
||||
- 表头:浅灰色背景(#f8f9fa),大写字母,14px字号
|
||||
- 行悬停:浅灰色背景(#f8f9fa)
|
||||
- 状态标签:
|
||||
- 有效:绿色背景+文字(#28a745)
|
||||
- 无效:灰色背景+文字(#6c757d)
|
||||
|
||||
#### 3. 新增手术室弹窗
|
||||
|
||||
**区域位置**:页面居中模态弹窗
|
||||
**区域功能**:收集新增手术室所需信息
|
||||
**包含元素**:
|
||||
|
||||
- 表单字段:
|
||||
1. 房间号输入框
|
||||
2. 类型:文本输入
|
||||
3. 必填:是
|
||||
4. 示例值:OR04
|
||||
5. 校验规则:非空校验
|
||||
6. 手术室名称输入框
|
||||
- 类型:文本输入
|
||||
- 必填:是
|
||||
- 示例值:第四手术室
|
||||
1. 手术室类型下拉框
|
||||
- 类型:单选下拉
|
||||
- 选项:普通/日间/复合/特殊
|
||||
- 默认值:普通
|
||||
1. 所属科室下拉框
|
||||
- 类型:单选下拉
|
||||
- 必填:是
|
||||
- 选项:外科/妇产科等8个科室
|
||||
- 默认提示:"请选择科室"
|
||||
- 操作按钮:
|
||||
- 取消按钮(灰色边框)
|
||||
- 确认按钮(蓝色填充)
|
||||
- 校验逻辑:必填字段非空校验
|
||||
- 成功反馈:提示"手术室添加成功"
|
||||
- 失败反馈:提示"请填写所有必填项"
|
||||
|
||||
#### 4. 编辑手术室弹窗
|
||||
|
||||
**区域位置**:页面居中模态弹窗
|
||||
**区域功能**:修改现有手术室信息
|
||||
**包含元素**:
|
||||
|
||||
- 表单字段(同新增弹窗,带初始值)
|
||||
- 操作按钮:
|
||||
- 取消按钮
|
||||
- 保存按钮
|
||||
- 校验逻辑:同新增弹窗
|
||||
- 成功反馈:提示"手术室信息已更新"
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 新增手术室
|
||||
|
||||
**功能描述**:添加新的手术室记录
|
||||
**触发条件**:点击页头"新增"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 打开新增模态框
|
||||
2. 填写必填字段(房间号、名称、科室)
|
||||
3. 点击确认提交(插入his_or_room表)
|
||||
4. 表格末尾新增数据行
|
||||
**异常处理**:
|
||||
- 必填项为空时弹出"请填写所有必填项"提示
|
||||
- 房间号重复需在后端校验并提示
|
||||
|
||||
#### 2. 编辑手术室
|
||||
|
||||
**功能描述**:修改现有手术室信息
|
||||
**触发条件**:点击行内"修改"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 打开编辑模态框(自动填充当前行数据)
|
||||
2. 用户修改数据
|
||||
3. 点击"保存"时校验并更新对应行数据
|
||||
**状态保持**:记录当前编辑行索引确保数据更新准确
|
||||
|
||||
#### 3. 状态切换
|
||||
|
||||
**功能描述**:启用/停用手术室
|
||||
**触发条件**:点击"停用"或"启用"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 弹出二次确认对话框
|
||||
2. 用户确认后切换状态标签
|
||||
3. 按钮变为相反操作(停用↔启用)
|
||||
4. 、停用手术室
|
||||
- **步骤**:
|
||||
1. 查询需要停用的手术室记录。
|
||||
2. 将 valid_flag 设置为 0(无效)。
|
||||
- **示例**:
|
||||
|
||||
UPDATE his_or_room
|
||||
|
||||
SET valid_flag = '0'
|
||||
|
||||
WHERE room_code = 'OR06';
|
||||
|
||||
5\. 启用手术室
|
||||
|
||||
**步骤**:
|
||||
|
||||
1. 查询需要启用的手术室记录。
|
||||
1. 将 valid_flag 设置为 1(有效)。
|
||||
- **示例**:
|
||||
|
||||
UPDATE his_or_room
|
||||
|
||||
SET valid_flag = '1'
|
||||
|
||||
WHERE room_code = 'OR06';
|
||||
|
||||
**防误操作**:所有状态变更需二次确认
|
||||
|
||||
### 五、数据结构说明(HIS_OR_ROOM手术室字典表)
|
||||
|
||||
| **字段名称** | **数据类型** | **是否为空** | **说明/典型值** | **外键/来源** |
|
||||
|--------------|--------------|--------------|-----------------|-------------------------------|
|
||||
| room_id | VARCHAR(10) | N | 主键 | 自增主键 |
|
||||
| room_code | VARCHAR(10) | N | 手术室房间号 | 自定义编码,如 OR01、OR02 |
|
||||
| room_name | VARCHAR(100) | N | 手术室名称 | 如 "第一手术室"、"第二手术室" |
|
||||
| room_type | VARCHAR(10) | N | 手术室类型 | 普通、日间、复合 |
|
||||
| dept_code | VARCHAR(10) | N | 所属科室 | FK → 科室管理的科室代码 |
|
||||
| valid_flag | CHAR(1) | N | 是否有效 | 1有效,0无效 |
|
||||
| created_time | DATETIME | N | 创建时间 | 默认当前时间 |
|
||||
| updated_time | DATETIME | N | 更新时间 | 默认当前时间,自动更新 |
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- 主色调:#5a7cff(按钮/交互元素)
|
||||
- 辅助色:#7b8a8b(次要文本)
|
||||
- 字体:
|
||||
- 标题:1.75rem/600字重
|
||||
- 正文:0.875rem/400字重
|
||||
- 间距系统:
|
||||
- 卡片内边距:24px
|
||||
- 表单字段间距:16px
|
||||
|
||||
**技术要求**:
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 数据安全:
|
||||
- 所有变更操作需记录操作日志
|
||||
- 停用状态的手术室需在前端标记不可预约
|
||||
2. 性能优化:
|
||||
- 表格数据分页加载
|
||||
- 模态框使用懒加载
|
||||
@@ -64,6 +64,11 @@
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
</dependency>
|
||||
<!-- rabbitMQ -->
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.AssignSeqUtil;
|
||||
import com.core.common.utils.ChineseConvertUtils;
|
||||
import com.core.common.utils.DictUtils;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.openhis.administration.domain.OperatingRoom;
|
||||
import com.openhis.administration.mapper.OperatingRoomMapper;
|
||||
@@ -78,23 +79,12 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
e.setStatusEnum_dictText(e.getStatusEnum() != null && e.getStatusEnum() == 1 ? "启用" : "停用");
|
||||
// 类型
|
||||
if (e.getRoomTypeEnum() != null) {
|
||||
switch (e.getRoomTypeEnum()) {
|
||||
case 1:
|
||||
e.setRoomTypeEnum_dictText("急诊手术室");
|
||||
break;
|
||||
case 2:
|
||||
e.setRoomTypeEnum_dictText("择期手术室");
|
||||
break;
|
||||
case 3:
|
||||
e.setRoomTypeEnum_dictText("日间手术室");
|
||||
break;
|
||||
case 4:
|
||||
e.setRoomTypeEnum_dictText("复合手术室");
|
||||
break;
|
||||
default:
|
||||
e.setRoomTypeEnum_dictText("未知");
|
||||
break;
|
||||
}
|
||||
e.setRoomTypeEnum_dictText(DictUtils.getDictLabel("operating_room_type", String.valueOf(e.getRoomTypeEnum())));
|
||||
}
|
||||
// 如果有机构ID,查询机构名称
|
||||
if (e.getOrganizationId() != null) {
|
||||
String orgName = commonService.getOrgNameById(e.getOrganizationId());
|
||||
e.setOrganizationName(orgName);
|
||||
}
|
||||
// 拼音码
|
||||
e.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(e.getName()));
|
||||
@@ -127,23 +117,7 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
|
||||
// 类型描述
|
||||
if (operatingRoom.getRoomTypeEnum() != null) {
|
||||
switch (operatingRoom.getRoomTypeEnum()) {
|
||||
case 1:
|
||||
operatingRoomDto.setRoomTypeEnum_dictText("急诊手术室");
|
||||
break;
|
||||
case 2:
|
||||
operatingRoomDto.setRoomTypeEnum_dictText("择期手术室");
|
||||
break;
|
||||
case 3:
|
||||
operatingRoomDto.setRoomTypeEnum_dictText("日间手术室");
|
||||
break;
|
||||
case 4:
|
||||
operatingRoomDto.setRoomTypeEnum_dictText("复合手术室");
|
||||
break;
|
||||
default:
|
||||
operatingRoomDto.setRoomTypeEnum_dictText("未知");
|
||||
break;
|
||||
}
|
||||
operatingRoomDto.setRoomTypeEnum_dictText(DictUtils.getDictLabel("operating_room_type", String.valueOf(operatingRoom.getRoomTypeEnum())));
|
||||
}
|
||||
|
||||
// 如果有机构ID,查询机构名称
|
||||
@@ -168,6 +142,11 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
return R.fail("手术室名称不能为空");
|
||||
}
|
||||
|
||||
// 校验房间号不能为空
|
||||
if (StringUtils.isEmpty(operatingRoomDto.getBusNo())) {
|
||||
return R.fail("房间号不能为空");
|
||||
}
|
||||
|
||||
// 去除空格
|
||||
String name = operatingRoomDto.getName().replaceAll("[ ]", "");
|
||||
operatingRoomDto.setName(name);
|
||||
@@ -177,13 +156,14 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
return R.fail("【" + name + "】已存在");
|
||||
}
|
||||
|
||||
// 判断房间号是否已存在
|
||||
if (isExistBusNo(operatingRoomDto.getBusNo(), null)) {
|
||||
return R.fail("房间号【" + operatingRoomDto.getBusNo() + "】已存在");
|
||||
}
|
||||
|
||||
OperatingRoom operatingRoom = new OperatingRoom();
|
||||
BeanUtils.copyProperties(operatingRoomDto, operatingRoom);
|
||||
|
||||
// 生成编码
|
||||
String code = assignSeqUtil.getSeq(AssignSeqEnum.OPERATING_ROOM_BUS_NO.getPrefix(), 3);
|
||||
operatingRoom.setBusNo(code);
|
||||
|
||||
// 拼音码
|
||||
operatingRoom.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(operatingRoomDto.getName()));
|
||||
// 五笔码
|
||||
@@ -215,6 +195,11 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
return R.fail("手术室名称不能为空");
|
||||
}
|
||||
|
||||
// 校验房间号不能为空
|
||||
if (StringUtils.isEmpty(operatingRoomDto.getBusNo())) {
|
||||
return R.fail("房间号不能为空");
|
||||
}
|
||||
|
||||
// 去除空格
|
||||
String name = operatingRoomDto.getName().replaceAll("[ ]", "");
|
||||
operatingRoomDto.setName(name);
|
||||
@@ -224,6 +209,11 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
return R.fail("【" + name + "】已存在");
|
||||
}
|
||||
|
||||
// 判断房间号是否已存在(排除自己)
|
||||
if (isExistBusNo(operatingRoomDto.getBusNo(), operatingRoomDto.getId())) {
|
||||
return R.fail("房间号【" + operatingRoomDto.getBusNo() + "】已存在");
|
||||
}
|
||||
|
||||
OperatingRoom operatingRoom = new OperatingRoom();
|
||||
BeanUtils.copyProperties(operatingRoomDto, operatingRoom);
|
||||
|
||||
@@ -331,4 +321,20 @@ public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService {
|
||||
}
|
||||
return operatingRoomService.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断房间号是否已存在
|
||||
*
|
||||
* @param busNo 房间号
|
||||
* @param excludeId 排除的ID
|
||||
* @return 是否存在
|
||||
*/
|
||||
private boolean isExistBusNo(String busNo, Long excludeId) {
|
||||
LambdaQueryWrapper<OperatingRoom> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(OperatingRoom::getBusNo, busNo);
|
||||
if (excludeId != null) {
|
||||
queryWrapper.ne(OperatingRoom::getId, excludeId);
|
||||
}
|
||||
return operatingRoomService.count(queryWrapper) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,4 +141,9 @@ public class CurrentDayEncounterDto {
|
||||
*/
|
||||
private String identifierNo;
|
||||
|
||||
/**
|
||||
* 流水号(就诊当日序号)
|
||||
*/
|
||||
private Integer displayOrder;
|
||||
|
||||
}
|
||||
|
||||
@@ -69,12 +69,3 @@ public class ReprintRegistrationDto {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.core.common.core.domain.R;
|
||||
import com.openhis.check.domain.LisGroupInfo;
|
||||
|
||||
public interface ILisGroupInfoAppService {
|
||||
R<?> getLisGroupInfoList();
|
||||
R<?> getLisGroupInfoList(Integer pageNum, Integer pageSize);
|
||||
|
||||
R<?> add(LisGroupInfo lisGroupInfo);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.openhis.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.openhis.check.domain.LisGroupInfo;
|
||||
import com.openhis.check.service.ILisGroupInfoService;
|
||||
@@ -17,11 +18,14 @@ public class LisGroupInfoAppServiceImpl implements ILisGroupInfoAppService {
|
||||
@Resource
|
||||
private ILisGroupInfoService lisGroupInfoService;
|
||||
@Override
|
||||
public R<?> getLisGroupInfoList() {
|
||||
List<LisGroupInfo> list = lisGroupInfoService.list();
|
||||
public R<?> getLisGroupInfoList(Integer pageNum, Integer pageSize) {
|
||||
Page<LisGroupInfo> page = new Page<>(pageNum, pageSize);
|
||||
Page<LisGroupInfo> list = lisGroupInfoService.page(page);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public R<?> add(LisGroupInfo lisGroupInfo) {
|
||||
if (ObjectUtil.isEmpty(lisGroupInfo)) {
|
||||
|
||||
@@ -19,8 +19,8 @@ public class LisGroupInfoController {
|
||||
*
|
||||
* */
|
||||
@GetMapping("/list")
|
||||
public R<?> getLisGroupInfoList(){
|
||||
return R.ok(lisGroupInfoAppService.getLisGroupInfoList());
|
||||
public R<?> getLisGroupInfoList(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize){
|
||||
return R.ok(lisGroupInfoAppService.getLisGroupInfoList(pageNum, pageSize));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -401,6 +401,20 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
|
||||
// 删除
|
||||
List<AdviceSaveDto> deleteList = medicineList.stream()
|
||||
.filter(e -> DbOpType.DELETE.getCode().equals(e.getDbOpType())).collect(Collectors.toList());
|
||||
|
||||
// 校验删除的医嘱是否已经收费
|
||||
List<Long> delRequestIdList = deleteList.stream().map(AdviceSaveDto::getRequestId).collect(Collectors.toList());
|
||||
if (!delRequestIdList.isEmpty()) {
|
||||
List<ChargeItem> chargeItemList = iChargeItemService.getChargeItemInfoByReqId(delRequestIdList);
|
||||
if (chargeItemList != null && !chargeItemList.isEmpty()) {
|
||||
for (ChargeItem ci : chargeItemList) {
|
||||
if (ChargeItemStatus.BILLED.getValue().equals(ci.getStatusEnum())) {
|
||||
return R.fail("已收费的项目无法删除,请刷新页面后重试");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||
iMedicationRequestService.removeById(adviceSaveDto.getRequestId());
|
||||
// 删除已经产生的药品发放信息
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.openhis.web.doctorstation.dto.PrescriptionInfoBaseDto;
|
||||
import com.openhis.web.doctorstation.dto.PrescriptionInfoDetailDto;
|
||||
import com.openhis.web.doctorstation.dto.ReceptionStatisticsDto;
|
||||
import com.openhis.web.doctorstation.mapper.DoctorStationMainAppMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -32,6 +33,7 @@ import java.util.stream.Collectors;
|
||||
/**
|
||||
* 医生站-主页面 应用实现类
|
||||
*/
|
||||
//@Slf4j
|
||||
@Service
|
||||
public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppService {
|
||||
|
||||
@@ -95,6 +97,9 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
|
||||
ParticipantType.REGISTRATION_DOCTOR.getCode(), ParticipantType.ADMITTER.getCode(), userId,
|
||||
currentUserOrganizationId, pricingFlag, EncounterStatus.PLANNED.getValue(),
|
||||
EncounterActivityStatus.ACTIVE.getValue(), queryWrapper);
|
||||
//日志输出就诊患者信息,patientInfo
|
||||
// log.debug("就诊患者信息: 总数={}, 记录数={}, 数据={}",
|
||||
// patientInfo.getTotal(), patientInfo.getRecords().size(), patientInfo.getRecords());
|
||||
patientInfo.getRecords().forEach(e -> {
|
||||
// 性别
|
||||
e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum()));
|
||||
|
||||
@@ -123,4 +123,8 @@ public class PatientInfoDto {
|
||||
* 病历号
|
||||
*/
|
||||
private String busNo;
|
||||
/**
|
||||
* 就诊卡号
|
||||
*/
|
||||
private String identifierNo;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,13 @@ public interface IEleInvoiceService {
|
||||
*/
|
||||
R<?> invoiceWriteoff(Long paymentId, String reason);
|
||||
|
||||
/**
|
||||
* 获取发票HTML
|
||||
* @param busNo 业务流水号
|
||||
* @return HTML字符串
|
||||
*/
|
||||
String getInvoiceHtml(String busNo);
|
||||
|
||||
/**
|
||||
* 查询已开发票
|
||||
* @param invoiceId 主键id
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.openhis.financial.domain.PaymentRecDetail;
|
||||
import com.openhis.financial.domain.PaymentReconciliation;
|
||||
import com.openhis.financial.service.IPaymentRecDetailService;
|
||||
import com.openhis.financial.service.IPaymentReconciliationService;
|
||||
import com.openhis.web.paymentmanage.appservice.IChargeBillService;
|
||||
import com.openhis.web.paymentmanage.appservice.IEleInvoiceService;
|
||||
import com.openhis.web.paymentmanage.dto.*;
|
||||
import com.openhis.web.paymentmanage.mapper.EleInvoiceMapper;
|
||||
@@ -38,6 +39,11 @@ import com.openhis.yb.service.IClinicSettleService;
|
||||
import com.openhis.yb.service.IRegService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
import org.apache.velocity.runtime.RuntimeConstants;
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
@@ -56,6 +62,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -64,6 +71,7 @@ import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -97,153 +105,180 @@ public class EleInvoiceServiceImpl implements IEleInvoiceService {
|
||||
@Resource
|
||||
IEncounterService encounterService;
|
||||
@Resource
|
||||
IChargeBillService chargeBillService;
|
||||
@Resource
|
||||
private AssignSeqUtil assignSeqUtil;
|
||||
@Autowired
|
||||
private HttpConfig httpConfig;
|
||||
|
||||
public static JSONObject PreInvoicePostForward(JSONObject bill, String endpoint) {
|
||||
String resultString = "";
|
||||
// JSONObject result = new JSONObject();
|
||||
// 获取当前租户的option信息
|
||||
static {
|
||||
Properties p = new Properties();
|
||||
p.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
|
||||
p.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
|
||||
p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
|
||||
Velocity.init(p);
|
||||
}
|
||||
|
||||
private static final Map<String, JSONObject> invoiceDataMap = new ConcurrentHashMap<>();
|
||||
|
||||
private JSONObject internalRegistration(JSONObject bill) {
|
||||
return createInternalSuccessResponse(bill, "REG");
|
||||
}
|
||||
|
||||
private JSONObject internalOutpatient(JSONObject bill) {
|
||||
return createInternalSuccessResponse(bill, "OUT");
|
||||
}
|
||||
|
||||
private JSONObject internalHospitalized(JSONObject bill) {
|
||||
return createInternalSuccessResponse(bill, "HOS");
|
||||
}
|
||||
|
||||
private JSONObject internalWriteOff(JSONObject bill) {
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("eScarletBillBatchCode", "SC" + System.currentTimeMillis());
|
||||
message.put("eScarletBillNo", UUID.randomUUID().toString().substring(0, 8));
|
||||
message.put("eScarletRandom", "666888");
|
||||
message.put("createTime", "20251101143028");
|
||||
message.put("billQRCode", "QR_DATA_SCARLET");
|
||||
|
||||
JSONObject optionJson = SecurityUtils.getLoginUser().getOptionJson();
|
||||
String baseUrl = optionJson.getString(CommonConstants.Option.URL);
|
||||
String appID = optionJson.getString(CommonConstants.Option.APP_ID);
|
||||
String appKey = optionJson.getString(CommonConstants.Option.KEY);
|
||||
message.put("pictureUrl", baseUrl + "/invoice/view?busNo=scarlet");
|
||||
message.put("pictureNetUrl", baseUrl + "/invoice/view?busNo=scarlet");
|
||||
|
||||
EleInvioceBillDto eleInvioceBillDto = new EleInvioceBillDto();
|
||||
eleInvioceBillDto.setBaseUrl(baseUrl);
|
||||
eleInvioceBillDto.setEndpoint(endpoint);
|
||||
eleInvioceBillDto.setAppKey(appKey);
|
||||
eleInvioceBillDto.setAppID(appID);
|
||||
eleInvioceBillDto.setJsonObject(bill);
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("result", "S0000");
|
||||
result.put("message", Base64.getEncoder().encodeToString(message.toJSONString().getBytes(StandardCharsets.UTF_8)));
|
||||
return result;
|
||||
}
|
||||
|
||||
// 创建Http请求
|
||||
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000)
|
||||
.setSocketTimeout(30000).build();
|
||||
CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
|
||||
CloseableHttpResponse response = null;
|
||||
// 发送请求
|
||||
try {
|
||||
HttpPost httpPost = new HttpPost(optionJson.getString("invoiceUrl") + "/eleInvoice/forward");
|
||||
System.out.println(optionJson.getString("invoiceUrl") + "/eleInvoice/forward");
|
||||
StringEntity stringEntity = new StringEntity(com.alibaba.fastjson2.JSON.toJSONString(eleInvioceBillDto),
|
||||
ContentType.APPLICATION_JSON);
|
||||
httpPost.setEntity(stringEntity);
|
||||
// 执行http请求
|
||||
response = httpClient.execute(httpPost);
|
||||
if (response == null) {
|
||||
throw new ServiceException("Http请求异常,未接受返回参数");
|
||||
private JSONObject createInternalSuccessResponse(JSONObject bill, String prefix) {
|
||||
String busNo = bill.getString("busNo");
|
||||
JSONObject optionJson = SecurityUtils.getLoginUser().getOptionJson();
|
||||
String baseUrl = optionJson.getString(CommonConstants.Option.URL);
|
||||
|
||||
JSONObject message = new JSONObject();
|
||||
message.put("billBatchCode", prefix + "BC" + System.currentTimeMillis());
|
||||
message.put("billNo", UUID.randomUUID().toString().substring(0, 8));
|
||||
message.put("random", "123456");
|
||||
message.put("createTime", new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));
|
||||
message.put("billQRCode", "QR_" + busNo);
|
||||
message.put("pictureUrl", baseUrl + "/invoice/view?busNo=" + busNo);
|
||||
message.put("pictureNetUrl", baseUrl + "/invoice/view?busNo=" + busNo);
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("result", "S0000");
|
||||
result.put("message", Base64.getEncoder().encodeToString(message.toJSONString().getBytes(StandardCharsets.UTF_8)));
|
||||
return result;
|
||||
}
|
||||
|
||||
private JSONObject createInternalErrorResponse(String msg) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("result", "E0001");
|
||||
result.put("message", Base64.getEncoder().encodeToString(msg.getBytes(StandardCharsets.UTF_8)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInvoiceHtml(String busNo) {
|
||||
JSONObject bill = invoiceDataMap.get(busNo);
|
||||
if (bill == null) {
|
||||
return "<html><body><h2>未找到流水号为 " + busNo + " 的发票数据</h2></body></html>";
|
||||
}
|
||||
|
||||
JSONObject receiptData = bill.getJSONObject("receiptData");
|
||||
|
||||
VelocityContext context = new VelocityContext();
|
||||
context.put("hospitalName", receiptData != null ? receiptData.getString("fixmedinsName") : "HIS 医疗机构");
|
||||
context.put("patientName", bill.getString("payer"));
|
||||
context.put("outpatientNo", receiptData != null ? receiptData.getString("regNo") : bill.getString("busNo"));
|
||||
context.put("idCard", bill.getString("cardNo"));
|
||||
context.put("tel", bill.getString("tel"));
|
||||
context.put("deptName", bill.getString("patientCategory"));
|
||||
context.put("doctorName", receiptData != null ? receiptData.getString("doctor") : "-");
|
||||
context.put("appointmentTime", bill.getString("consultationDate"));
|
||||
context.put("totalAmt", bill.getString("totalAmt"));
|
||||
context.put("busNo", busNo);
|
||||
context.put("printTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
|
||||
List<Map<String, Object>> items = new ArrayList<>();
|
||||
if (receiptData != null && receiptData.containsKey("chargeItem")) {
|
||||
com.alibaba.fastjson2.JSONArray chargeItems = receiptData.getJSONArray("chargeItem");
|
||||
for (int i = 0; i < chargeItems.size(); i++) {
|
||||
JSONObject item = chargeItems.getJSONObject(i);
|
||||
Map<String, Object> itemMap = new HashMap<>();
|
||||
itemMap.put("chargeItemName", item.getString("chargeItemName"));
|
||||
itemMap.put("quantityValue", item.getString("quantityValue"));
|
||||
itemMap.put("totalPrice", item.getString("totalPrice"));
|
||||
items.add(itemMap);
|
||||
}
|
||||
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
|
||||
} else {
|
||||
Map<String, Object> itemMap = new HashMap<>();
|
||||
itemMap.put("chargeItemName", "挂号费");
|
||||
itemMap.put("quantityValue", "1");
|
||||
itemMap.put("totalPrice", bill.getString("totalAmt"));
|
||||
items.add(itemMap);
|
||||
}
|
||||
context.put("items", items);
|
||||
|
||||
try {
|
||||
Template template = Velocity.getTemplate("vm/invoice/invoice.vm");
|
||||
StringWriter writer = new StringWriter();
|
||||
template.merge(context, writer);
|
||||
return writer.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new ServiceException("Http请求异常,请稍后再试。");
|
||||
} finally {
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
// logger.error("关闭响应异常", e);
|
||||
throw new ServiceException("未关闭系统资源:" + e.getStackTrace());
|
||||
}
|
||||
log.error("渲染发票模板失败", e);
|
||||
return "<html><body><h2>渲染发票凭条失败:" + e.getMessage() + "</h2></body></html>";
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject PreInvoicePostForward(JSONObject bill, String endpoint) {
|
||||
// 参考补打小票逻辑,动态获取小票详细信息
|
||||
Long paymentId = bill.getLong("paymentId");
|
||||
if (paymentId != null) {
|
||||
try {
|
||||
Map<String, Object> receiptDetail = chargeBillService.getDetail(paymentId);
|
||||
bill.put("receiptData", receiptDetail);
|
||||
log.info("已成功获取并注入小票动态数据,paymentId: {}", paymentId);
|
||||
} catch (Exception e) {
|
||||
log.error("获取小票数据失败,paymentId: {}", paymentId, e);
|
||||
}
|
||||
}
|
||||
return JSONObject.parseObject(resultString);
|
||||
|
||||
// 内部调用逻辑:不再使用 Http 客户端,直接分发到本地逻辑
|
||||
String busNo = bill.getString("busNo");
|
||||
if (busNo != null) {
|
||||
invoiceDataMap.put(busNo, bill);
|
||||
}
|
||||
|
||||
JSONObject internalResult;
|
||||
if (endpoint.contains("invEBillRegistration")) {
|
||||
internalResult = internalRegistration(bill);
|
||||
} else if (endpoint.contains("invoiceEBillOutpatient")) {
|
||||
internalResult = internalOutpatient(bill);
|
||||
} else if (endpoint.contains("invEBillHospitalized")) {
|
||||
internalResult = internalHospitalized(bill);
|
||||
} else if (endpoint.contains("writeOffEBill")) {
|
||||
internalResult = internalWriteOff(bill);
|
||||
} else {
|
||||
internalResult = createInternalErrorResponse("未知接口: " + endpoint);
|
||||
}
|
||||
|
||||
JSONObject finalResponse = new JSONObject();
|
||||
finalResponse.put("success", true);
|
||||
finalResponse.put("result", internalResult);
|
||||
return finalResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
* 发送请求 (内部调用版本)
|
||||
*
|
||||
* @param bill 请求参数
|
||||
* @param endpoint 请求后缀url
|
||||
* @return 返回值
|
||||
*/
|
||||
public static JSONObject PreInvoicePost(JSONObject bill, String endpoint) {
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
// 获取当前租户的option信息
|
||||
JSONObject optionJson = SecurityUtils.getLoginUser().getOptionJson();
|
||||
|
||||
String baseUrl = optionJson.getString(CommonConstants.Option.URL);
|
||||
// 拼接成完整 URL(作为路径)
|
||||
String cleanUrl = baseUrl + "/" + endpoint; // 确保用 "/" 分隔
|
||||
String url = cleanUrl.trim().replaceAll("^\"|\"$", "") // 去除首尾引号
|
||||
.replaceAll("\\s+", "")// 去除首尾引号
|
||||
.replaceAll("\"", ""); // 去除中间引号
|
||||
|
||||
String appID = optionJson.getString(CommonConstants.Option.APP_ID);
|
||||
String appKey = optionJson.getString(CommonConstants.Option.KEY);
|
||||
String data = bill.toJSONString();
|
||||
String version = "1.0";
|
||||
// 请求随机标识 noise
|
||||
String noise = UUID.randomUUID().toString();
|
||||
|
||||
data = Base64.getEncoder().encodeToString(data.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("appid=").append(appID);
|
||||
str.append("&data=").append(data);
|
||||
str.append("&noise=").append(noise);
|
||||
str.append("&key=").append(appKey);
|
||||
str.append("&version=").append(version);
|
||||
String sign = DigestUtils.md5Hex(str.toString().getBytes(Charset.forName("UTF-8"))).toUpperCase();
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("appid", appID);
|
||||
map.put("data", data);
|
||||
map.put("noise", noise);
|
||||
map.put("sign", sign);
|
||||
map.put("version", version);
|
||||
|
||||
try {
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
CloseableHttpClient client = HttpClients.createDefault();
|
||||
String respContent = null;
|
||||
// 请求参数转JOSN字符串
|
||||
StringEntity entity = new StringEntity(new ObjectMapper().writeValueAsString(map), "utf-8");
|
||||
entity.setContentEncoding("UTF-8");
|
||||
entity.setContentType("application/json");
|
||||
httpPost.setEntity(entity);
|
||||
HttpResponse resp = client.execute(httpPost);
|
||||
|
||||
if (resp.getStatusLine().getStatusCode() == 200) {
|
||||
String rev = EntityUtils.toString(resp.getEntity());
|
||||
// System.out.println("返回串--》"+rev);
|
||||
Map resultData = new ObjectMapper().readValue(rev, Map.class);
|
||||
String rdata = resultData.get("data").toString();
|
||||
String rnoise = resultData.get("noise").toString();
|
||||
// 1、拼接返回验签参数
|
||||
StringBuilder str1 = new StringBuilder();
|
||||
str1.append("appid=").append(appID);
|
||||
str1.append("&data=").append(rdata);
|
||||
str1.append("&noise=").append(rnoise);
|
||||
str1.append("&key=").append(appKey);
|
||||
str1.append("&version=").append(version);
|
||||
// 3.MD5加密 生成sign
|
||||
String rmd5 = DigestUtils.md5Hex(str1.toString().getBytes(Charset.forName("UTF-8"))).toUpperCase();
|
||||
String rsign = resultData.get("sign").toString();
|
||||
System.out.println("验签-》" + (StringUtils.equals(rsign, rmd5)));
|
||||
String busData
|
||||
= new String(Base64.getDecoder().decode(resultData.get("data").toString()), StandardCharsets.UTF_8);
|
||||
System.out.println("返回业务数据--》" + busData);
|
||||
Map busDataMap = new ObjectMapper().readValue(busData, Map.class);
|
||||
System.out
|
||||
.println("业务信息解密--》" + new String(Base64.getDecoder().decode(busDataMap.get("message").toString()),
|
||||
StandardCharsets.UTF_8));
|
||||
|
||||
JSONObject resobj = JSONObject.parseObject(busData);
|
||||
result.put("success", true);
|
||||
result.put("result", resobj);
|
||||
} else {
|
||||
result.put("msg", "web响应失败!");
|
||||
result.put("success", false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.put("msg", e.getMessage());
|
||||
result.put("success", false);
|
||||
}
|
||||
return result;
|
||||
|
||||
public JSONObject PreInvoicePost(JSONObject bill, String endpoint) {
|
||||
return PreInvoicePostForward(bill, endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -339,6 +374,7 @@ public class EleInvoiceServiceImpl implements IEleInvoiceService {
|
||||
|
||||
// --------------------请求业务参数 data--------------------START
|
||||
JSONObject bill = commomSet(patientInfo, paymentInfo, clinicSettle);
|
||||
bill.put("paymentId", paymentId);
|
||||
|
||||
// ------票据信息------
|
||||
// busType 业务标识 String 20 是 06,标识挂号
|
||||
@@ -580,6 +616,7 @@ public class EleInvoiceServiceImpl implements IEleInvoiceService {
|
||||
|
||||
// --------------------请求业务参数 data--------------------START
|
||||
JSONObject bill = commomSet(patientInfo, paymentInfo, clinicSettle);
|
||||
bill.put("paymentId", paymentId);
|
||||
|
||||
// ------票据信息------
|
||||
// busType 业务标识 String 20 是 直接填写业务系统内部编码值,由医疗平台配置对照,例如:附录5 业务标识列表
|
||||
@@ -890,6 +927,7 @@ public class EleInvoiceServiceImpl implements IEleInvoiceService {
|
||||
|
||||
// --------------------请求业务参数 data--------------------START
|
||||
JSONObject bill = commomSet(patientInfo, paymentInfo, clinicSettle);
|
||||
bill.put("paymentId", paymentId);
|
||||
|
||||
// ------票据信息------
|
||||
// busType 业务标识 String 20 是 直接填写业务系统内部编码值,由医疗平台配置对照,例如:附录5 业务标识列表
|
||||
|
||||
@@ -1818,6 +1818,10 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
||||
// 保存就诊信息
|
||||
Encounter encounter = new Encounter();
|
||||
BeanUtils.copyProperties(encounterFormData, encounter);
|
||||
// 将挂号医生ID提前塞入 encounter 的 registrarId,便于生成“科室+医生+当日”序号
|
||||
if (encounterParticipantFormData.getPractitionerId() != null) {
|
||||
encounter.setRegistrarId(encounterParticipantFormData.getPractitionerId());
|
||||
}
|
||||
encounter.setBusNo(outpatientRegistrationSettleParam.getBusNo());
|
||||
// 就诊ID
|
||||
Long encounterId = iEncounterService.saveEncounterByRegister(encounter);
|
||||
|
||||
@@ -41,22 +41,23 @@ public class EleInvoiceController {
|
||||
public R<?> invoiceReissue(@RequestBody MakeInvoiceDto makeInvoiceDto) {
|
||||
// 付款成功后,开具发票
|
||||
R<?> result = eleInvoiceService.invoiceReissue(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
R<?> eleResult = null;
|
||||
if (result.getCode() == 200) {
|
||||
if (result.getData() == YbEncounterClass.REG.getValue()) {
|
||||
// 付款成功后,开具发票
|
||||
R<?> eleResult = eleInvoiceService.invoiceRegMake(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
eleResult = eleInvoiceService.invoiceRegMake(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
if (eleResult.getCode() != 200) {
|
||||
return R.ok(" 挂号电子发票开具失败 :" + eleResult.getMsg());
|
||||
}
|
||||
} else if (result.getData() == YbEncounterClass.AMB.getValue()) {
|
||||
// 付款成功后,开具发票
|
||||
R<?> eleResult = eleInvoiceService.invoiceMZMake(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
eleResult = eleInvoiceService.invoiceMZMake(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
if (eleResult.getCode() != 200) {
|
||||
return R.ok(" 门诊电子发票开具失败 :" + eleResult.getMsg());
|
||||
}
|
||||
} else if (result.getData() == YbEncounterClass.IMP.getValue()) {
|
||||
// 付款成功后,开具发票
|
||||
R<?> eleResult = eleInvoiceService.invoiceZYMake(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
eleResult = eleInvoiceService.invoiceZYMake(makeInvoiceDto.getPaymentId(), makeInvoiceDto.getEncounterId());
|
||||
if (eleResult.getCode() != 200) {
|
||||
return R.ok(" 住院电子发票开具失败 :" + eleResult.getMsg());
|
||||
}
|
||||
@@ -64,7 +65,11 @@ public class EleInvoiceController {
|
||||
return R.ok("电子发票类型不明确!");
|
||||
}
|
||||
}
|
||||
Map detail = iChargeBillService.getDetail(makeInvoiceDto.getPaymentId());
|
||||
Map<String, Object> detail = iChargeBillService.getDetail(makeInvoiceDto.getPaymentId());
|
||||
if (eleResult != null && eleResult.getCode() == 200 && eleResult.getData() instanceof Invoice) {
|
||||
Invoice invoice = (Invoice) eleResult.getData();
|
||||
detail.put("pictureUrl", invoice.getPictureUrl());
|
||||
}
|
||||
return R.ok(detail);
|
||||
}
|
||||
|
||||
@@ -95,10 +100,18 @@ public class EleInvoiceController {
|
||||
public R<?> invoiceOpen(@RequestParam("invoiceId") String invoiceId) {
|
||||
// 退款成功后,开具发票
|
||||
Invoice invoice = eleInvoiceService.getInvoiceById(Long.parseLong(invoiceId));
|
||||
if(invoice ==null){
|
||||
if (invoice == null) {
|
||||
throw new ServiceException("未查询到发票信息");
|
||||
}
|
||||
return R.ok(invoice.getPictureUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取发票HTML凭条预览
|
||||
*/
|
||||
@GetMapping(value = "/view", produces = "text/html;charset=UTF-8")
|
||||
@ResponseBody
|
||||
public String viewInvoice(@RequestParam("busNo") String busNo) {
|
||||
return eleInvoiceService.getInvoiceHtml(busNo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package com.openhis.web.paymentmanage.controller;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.enums.TenantOptionDict;
|
||||
import com.core.web.util.TenantOptionUtil;
|
||||
import com.openhis.administration.domain.Invoice;
|
||||
import com.openhis.financial.domain.PaymentReconciliation;
|
||||
import com.openhis.web.chargemanage.dto.OutpatientRegistrationAddParam;
|
||||
import com.openhis.web.chargemanage.dto.OutpatientRegistrationSettleParam;
|
||||
@@ -92,10 +93,12 @@ public class PaymentReconciliationController {
|
||||
if (eleResult.getCode() != 200) {
|
||||
// 因收费成功前端需要关闭弹窗,此处信息仅用于提示所以返回ok
|
||||
return R.ok(detail, " 收费成功,电子发票开具失败 :" + eleResult.getMsg());
|
||||
} else if (eleResult.getData() instanceof Invoice) {
|
||||
Invoice invoice = (Invoice) eleResult.getData();
|
||||
detail.put("pictureUrl", invoice.getPictureUrl());
|
||||
}
|
||||
return R.ok(detail);
|
||||
}
|
||||
|
||||
// Map detail = iChargeBillService.getDetail(paymentRecon.getId());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -194,7 +197,11 @@ public class PaymentReconciliationController {
|
||||
if (eleResult.getCode() != 200) {
|
||||
// 因收费成功前端需要关闭弹窗,此处信息仅用于提示所以返回ok
|
||||
return R.ok(detail, " 收费成功,电子发票开具失败 :" + eleResult.getMsg());
|
||||
} else if (eleResult.getData() instanceof Invoice) {
|
||||
Invoice invoice = (Invoice) eleResult.getData();
|
||||
detail.put("pictureUrl", invoice.getPictureUrl());
|
||||
}
|
||||
return R.ok(detail);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -233,6 +240,9 @@ public class PaymentReconciliationController {
|
||||
if (eleResult.getCode() != 200) {
|
||||
// 因收费成功前端需要关闭弹窗,此处信息仅用于提示所以返回ok
|
||||
return R.ok(detail, " 收费成功,电子发票开具失败 :" + eleResult.getMsg());
|
||||
} else if (eleResult.getData() instanceof Invoice) {
|
||||
Invoice invoice = (Invoice) eleResult.getData();
|
||||
detail.put("pictureUrl", invoice.getPictureUrl());
|
||||
}
|
||||
return R.ok(detail);
|
||||
}
|
||||
@@ -260,8 +270,9 @@ public class PaymentReconciliationController {
|
||||
// 因取消付款成功前端需要关闭弹窗,此处信息仅用于提示所以返回ok
|
||||
return R.ok(null, " 取消付款成功,电子发票开具失败 :" + eleResult.getMsg());
|
||||
}
|
||||
return R.ok("取消结算成功");
|
||||
}
|
||||
return R.ok("取消结算失败,请确认");
|
||||
return R.fail("取消结算失败,请确认");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<select id="getCurrentDayEncounter" resultType="com.openhis.web.chargemanage.dto.CurrentDayEncounterDto">
|
||||
SELECT T9.tenant_id AS tenantId,
|
||||
T9.encounter_id AS encounterId,
|
||||
T9.display_order AS displayOrder,
|
||||
T9.organization_id AS organizationId,
|
||||
T9.organization_name AS organizationName,
|
||||
T9.healthcare_name AS healthcareName,
|
||||
@@ -66,10 +67,11 @@
|
||||
T9.payment_id AS paymentId,
|
||||
T9.picture_url AS pictureUrl,
|
||||
T9.birth_date AS birthDate,
|
||||
T9.identifier_no AS identifierNo
|
||||
COALESCE(T9.identifier_no, T9.patient_bus_no, '') AS identifierNo
|
||||
from (
|
||||
SELECT T1.tenant_id AS tenant_id,
|
||||
T1.id AS encounter_id,
|
||||
T1.display_order AS display_order,
|
||||
T1.organization_id AS organization_id,
|
||||
T2.NAME AS organization_name,
|
||||
T3.NAME AS healthcare_name,
|
||||
@@ -90,6 +92,7 @@
|
||||
T13.id AS payment_id,
|
||||
ai.picture_url AS picture_url,
|
||||
T8.birth_date AS birth_date,
|
||||
T8.bus_no AS patient_bus_no,
|
||||
T18.identifier_no AS identifier_no
|
||||
FROM adm_encounter AS T1
|
||||
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
|
||||
@@ -129,6 +132,8 @@
|
||||
ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY create_time ASC) AS rn
|
||||
FROM adm_patient_identifier
|
||||
WHERE delete_flag = '0'
|
||||
AND identifier_no IS NOT NULL
|
||||
AND identifier_no != ''
|
||||
) t
|
||||
WHERE rn = 1
|
||||
) AS T18 ON T8.id = T18.patient_id
|
||||
|
||||
@@ -43,207 +43,247 @@
|
||||
abi.restricted_scope,
|
||||
abi.dosage_instruction,
|
||||
abi.chrgitm_lv
|
||||
from (
|
||||
<if test="adviceTypes == null or adviceTypes.contains(1)">
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
1 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
T1.pharmacology_category_code AS pharmacology_category_code,
|
||||
T1.part_percent AS part_percent,
|
||||
T1.unit_conversion_ratio AS unit_conversion_ratio,
|
||||
T1.part_attribute_enum AS part_attribute_enum,
|
||||
T1.tho_part_attribute_enum AS tho_part_attribute_enum,
|
||||
T1.skin_test_flag AS skin_test_flag,
|
||||
T1.inject_flag AS inject_flag,
|
||||
T1.ID AS advice_definition_id,
|
||||
T1.NAME AS advice_name,
|
||||
T1.bus_no AS advice_bus_no,
|
||||
T1.py_str AS py_str,
|
||||
T1.wb_str AS wb_str,
|
||||
T1.yb_no AS yb_no,
|
||||
T1.merchandise_name AS product_name,
|
||||
0 AS activity_type,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.min_unit_code AS min_unit_code,
|
||||
T2.total_volume AS volume,
|
||||
T2.method_code AS method_code,
|
||||
T2.rate_code AS rate_code,
|
||||
T2.org_id AS org_id,
|
||||
T2.location_id AS location_id,
|
||||
CAST(T2.dose AS TEXT) AS dose,
|
||||
T2.dose_unit_code AS dose_unit_code,
|
||||
T3.NAME AS supplier,
|
||||
T3.id AS supplier_id,
|
||||
T1.manufacturer_text AS manufacturer,
|
||||
T5.id AS charge_item_definition_id,
|
||||
T5.instance_table AS advice_table_name,
|
||||
T6.def_location_id AS position_id,
|
||||
t1.restricted_flag AS restricted_flag,
|
||||
t1.restricted_scope AS restricted_scope,
|
||||
T1.dosage_instruction AS dosage_instruction,
|
||||
T1.chrgitm_lv as chrgitm_lv
|
||||
FROM med_medication_definition AS t1
|
||||
INNER JOIN med_medication AS T2 ON T2.medication_def_id = T1.ID
|
||||
AND T2.delete_flag = '0' AND T2.status_enum = #{statusEnum}
|
||||
LEFT JOIN adm_supplier AS T3
|
||||
ON T3.ID = T1.supply_id
|
||||
AND T3.delete_flag = '0'
|
||||
LEFT JOIN adm_charge_item_definition AS T5 ON T5.instance_id = T1.ID
|
||||
AND T5.delete_flag = '0' AND T5.status_enum = #{statusEnum}
|
||||
LEFT JOIN adm_organization_location AS T6
|
||||
ON T6.distribution_category_code = T1.category_code
|
||||
AND T6.delete_flag = '0' AND T6.item_code = '1' AND T6.organization_id = #{organizationId} AND
|
||||
(CURRENT_TIME :: time (6) BETWEEN T6.start_time AND T6.end_time)
|
||||
WHERE T1.delete_flag = '0'
|
||||
AND T2.status_enum = #{statusEnum}
|
||||
<if test="pricingFlag ==1">
|
||||
AND 1 = 2
|
||||
FROM (
|
||||
<!-- 确保至少有一个查询被执行以避免语法错误 -->
|
||||
<if test="adviceTypes != null and !adviceTypes.isEmpty() and (adviceTypes.contains(1) or adviceTypes.contains(2) or adviceTypes.contains(3))">
|
||||
<!-- 如果有有效的adviceTypes,则执行对应的查询 -->
|
||||
<if test="adviceTypes.contains(1)">
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
1 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
T1.pharmacology_category_code AS pharmacology_category_code,
|
||||
T1.part_percent AS part_percent,
|
||||
T1.unit_conversion_ratio AS unit_conversion_ratio,
|
||||
T1.part_attribute_enum AS part_attribute_enum,
|
||||
T1.tho_part_attribute_enum AS tho_part_attribute_enum,
|
||||
T1.skin_test_flag AS skin_test_flag,
|
||||
T1.inject_flag AS inject_flag,
|
||||
T1.ID AS advice_definition_id,
|
||||
T1.NAME AS advice_name,
|
||||
T1.bus_no AS advice_bus_no,
|
||||
T1.py_str AS py_str,
|
||||
T1.wb_str AS wb_str,
|
||||
T1.yb_no AS yb_no,
|
||||
T1.merchandise_name AS product_name,
|
||||
0 AS activity_type,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.min_unit_code AS min_unit_code,
|
||||
T2.total_volume AS volume,
|
||||
T2.method_code AS method_code,
|
||||
T2.rate_code AS rate_code,
|
||||
T2.org_id AS org_id,
|
||||
T2.location_id AS location_id,
|
||||
CAST(T2.dose AS TEXT) AS dose,
|
||||
T2.dose_unit_code AS dose_unit_code,
|
||||
T3.NAME AS supplier,
|
||||
T3.id AS supplier_id,
|
||||
T1.manufacturer_text AS manufacturer,
|
||||
T5.id AS charge_item_definition_id,
|
||||
T5.instance_table AS advice_table_name,
|
||||
T6.def_location_id AS position_id,
|
||||
t1.restricted_flag AS restricted_flag,
|
||||
t1.restricted_scope AS restricted_scope,
|
||||
T1.dosage_instruction AS dosage_instruction,
|
||||
T1.chrgitm_lv as chrgitm_lv
|
||||
FROM med_medication_definition AS t1
|
||||
INNER JOIN med_medication AS T2 ON T2.medication_def_id = T1.ID
|
||||
AND T2.delete_flag = '0' AND T2.status_enum = #{statusEnum}
|
||||
LEFT JOIN adm_supplier AS T3
|
||||
ON T3.ID = T1.supply_id
|
||||
AND T3.delete_flag = '0'
|
||||
LEFT JOIN adm_charge_item_definition AS T5 ON T5.instance_id = T1.ID
|
||||
AND T5.delete_flag = '0' AND T5.status_enum = #{statusEnum}
|
||||
LEFT JOIN adm_organization_location AS T6
|
||||
ON T6.distribution_category_code = T1.category_code
|
||||
AND T6.delete_flag = '0' AND T6.item_code = '1' AND T6.organization_id = #{organizationId} AND
|
||||
(CURRENT_TIME :: time (6) BETWEEN T6.start_time AND T6.end_time)
|
||||
WHERE T1.delete_flag = '0'
|
||||
AND T2.status_enum = #{statusEnum}
|
||||
<if test="pricingFlag ==1">
|
||||
AND 1 = 2
|
||||
</if>
|
||||
<if test="adviceDefinitionIdParamList != null and !adviceDefinitionIdParamList.isEmpty()">
|
||||
AND T1.id IN
|
||||
<foreach collection="adviceDefinitionIdParamList" item="itemId" open="(" separator="," close=")">
|
||||
#{itemId}
|
||||
</foreach>
|
||||
</if>
|
||||
AND T5.instance_table = #{medicationTableName}
|
||||
)
|
||||
<if test="adviceTypes.contains(2) or adviceTypes.contains(3)">UNION ALL</if>
|
||||
</if>
|
||||
<if test="adviceDefinitionIdParamList != null and !adviceDefinitionIdParamList.isEmpty()">
|
||||
AND T1.id IN
|
||||
<foreach collection="adviceDefinitionIdParamList" item="itemId" open="(" separator="," close=")">
|
||||
#{itemId}
|
||||
</foreach>
|
||||
|
||||
<if test="adviceTypes.contains(2)">
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
2 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
'' AS pharmacology_category_code,
|
||||
T1.part_percent AS part_percent,
|
||||
0 AS unit_conversion_ratio,
|
||||
null AS part_attribute_enum,
|
||||
null AS tho_part_attribute_enum,
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
T1.ID AS advice_definition_id,
|
||||
T1.NAME AS advice_name,
|
||||
T1.bus_no AS advice_bus_no,
|
||||
T1.py_str AS py_str,
|
||||
T1.wb_str AS wb_str,
|
||||
T1.yb_no AS yb_no,
|
||||
'' AS product_name,
|
||||
0 AS activity_type,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.min_unit_code AS min_unit_code,
|
||||
T1.SIZE AS volume,
|
||||
'' AS method_code,
|
||||
'' AS rate_code,
|
||||
T1.org_id AS org_id,
|
||||
T1.location_id AS location_id,
|
||||
'' AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T2.NAME AS supplier,
|
||||
T2.id AS supplier_id,
|
||||
T1.manufacturer_text AS manufacturer,
|
||||
T4.id AS charge_item_definition_id,
|
||||
T4.instance_table AS advice_table_name,
|
||||
T5.def_location_id AS position_id,
|
||||
0 AS restricted_flag,
|
||||
'' AS restricted_scope,
|
||||
'' AS dosage_instruction,
|
||||
T1.chrgitm_lv as chrgitm_lv
|
||||
FROM adm_device_definition AS T1
|
||||
LEFT JOIN adm_supplier AS T2
|
||||
ON T2.ID = T1.supply_id
|
||||
AND T2.delete_flag = '0'
|
||||
LEFT JOIN adm_charge_item_definition AS T4 ON T4.instance_id = T1.ID
|
||||
AND T4.delete_flag = '0' AND T4.status_enum = #{statusEnum}
|
||||
LEFT JOIN adm_organization_location AS T5 ON T5.distribution_category_code = T1.category_code
|
||||
AND T5.delete_flag = '0' AND T5.item_code = '2' AND T5.organization_id = #{organizationId} AND
|
||||
(CURRENT_TIME :: time (6) BETWEEN T5.start_time AND T5.end_time)
|
||||
WHERE T1.delete_flag = '0'
|
||||
<if test="adviceDefinitionIdParamList != null and !adviceDefinitionIdParamList.isEmpty()">
|
||||
AND T1.id IN
|
||||
<foreach collection="adviceDefinitionIdParamList" item="itemId" open="(" separator="," close=")">
|
||||
#{itemId}
|
||||
</foreach>
|
||||
</if>
|
||||
AND T4.instance_table = #{deviceTableName}
|
||||
AND T1.status_enum = #{statusEnum}
|
||||
)
|
||||
<if test="adviceTypes.contains(3)">UNION ALL</if>
|
||||
</if>
|
||||
|
||||
<if test="adviceTypes.contains(3)">
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
3 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
'' AS pharmacology_category_code,
|
||||
1 AS part_percent,
|
||||
0 AS unit_conversion_ratio,
|
||||
null AS part_attribute_enum,
|
||||
null AS tho_part_attribute_enum,
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
T1.ID AS advice_definition_id,
|
||||
T1.NAME AS advice_name,
|
||||
T1.bus_no AS advice_bus_no,
|
||||
T1.py_str AS py_str,
|
||||
T1.wb_str AS wb_str,
|
||||
T1.yb_no AS yb_no,
|
||||
'' AS product_name,
|
||||
T1.type_enum AS activity_type,
|
||||
'' AS unit_code,
|
||||
'' AS min_unit_code,
|
||||
'' AS volume,
|
||||
'' AS method_code,
|
||||
'' AS rate_code,
|
||||
T1.org_id AS org_id,
|
||||
T1.location_id AS location_id,
|
||||
'' AS dose,
|
||||
'' AS dose_unit_code,
|
||||
'' AS supplier,
|
||||
null AS supplier_id,
|
||||
'' AS manufacturer,
|
||||
T2.ID AS charge_item_definition_id,
|
||||
T2.instance_table AS advice_table_name,
|
||||
T3.organization_id AS position_id,
|
||||
0 AS restricted_flag,
|
||||
'' AS restricted_scope,
|
||||
'' AS dosage_instruction,
|
||||
T1.chrgitm_lv as chrgitm_lv
|
||||
FROM wor_activity_definition AS T1
|
||||
LEFT JOIN adm_charge_item_definition AS T2
|
||||
ON T2.instance_id = T1.ID
|
||||
AND T2.delete_flag = '0' AND T2.status_enum = #{statusEnum}
|
||||
AND T2.instance_table = #{activityTableName}
|
||||
LEFT JOIN adm_organization_location AS T3 ON T3.activity_definition_id = T1.ID
|
||||
AND T3.delete_flag = '0' AND (CURRENT_TIME :: time (6) BETWEEN T3.start_time AND T3.end_time)
|
||||
WHERE T1.delete_flag = '0'
|
||||
<if test="pricingFlag ==1">
|
||||
AND (T1.pricing_flag = #{pricingFlag} OR T1.pricing_flag IS NULL)
|
||||
</if>
|
||||
<if test="adviceDefinitionIdParamList != null and !adviceDefinitionIdParamList.isEmpty()">
|
||||
AND T1.id IN
|
||||
<foreach collection="adviceDefinitionIdParamList" item="itemId" open="(" separator="," close=")">
|
||||
#{itemId}
|
||||
</foreach>
|
||||
</if>
|
||||
AND T1.status_enum = #{statusEnum}
|
||||
)
|
||||
</if>
|
||||
AND T5.instance_table = #{medicationTableName}
|
||||
)
|
||||
</if>
|
||||
|
||||
|
||||
<if test="adviceTypes == null or adviceTypes.contains(1)">
|
||||
<if test="adviceTypes == null or adviceTypes.contains(2) or adviceTypes.contains(3)">UNION ALL</if>
|
||||
</if>
|
||||
|
||||
<if test="adviceTypes == null or adviceTypes.contains(2)">
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
2 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
'' AS pharmacology_category_code,
|
||||
T1.part_percent AS part_percent,
|
||||
0 AS unit_conversion_ratio,
|
||||
null AS part_attribute_enum,
|
||||
null AS tho_part_attribute_enum,
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
T1.ID AS advice_definition_id,
|
||||
T1.NAME AS advice_name,
|
||||
T1.bus_no AS advice_bus_no,
|
||||
T1.py_str AS py_str,
|
||||
T1.wb_str AS wb_str,
|
||||
T1.yb_no AS yb_no,
|
||||
'' AS product_name,
|
||||
0 AS activity_type,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.min_unit_code AS min_unit_code,
|
||||
T1.SIZE AS volume,
|
||||
'' AS method_code,
|
||||
'' AS rate_code,
|
||||
T1.org_id AS org_id,
|
||||
T1.location_id AS location_id,
|
||||
'' AS dose,
|
||||
'' AS dose_unit_code,
|
||||
T2.NAME AS supplier,
|
||||
T2.id AS supplier_id,
|
||||
T1.manufacturer_text AS manufacturer,
|
||||
T4.id AS charge_item_definition_id,
|
||||
T4.instance_table AS advice_table_name,
|
||||
T5.def_location_id AS position_id,
|
||||
0 AS restricted_flag,
|
||||
'' AS restricted_scope,
|
||||
'' AS dosage_instruction,
|
||||
T1.chrgitm_lv as chrgitm_lv
|
||||
FROM adm_device_definition AS T1
|
||||
LEFT JOIN adm_supplier AS T2
|
||||
ON T2.ID = T1.supply_id
|
||||
AND T2.delete_flag = '0'
|
||||
LEFT JOIN adm_charge_item_definition AS T4 ON T4.instance_id = T1.ID
|
||||
AND T4.delete_flag = '0' AND T4.status_enum = #{statusEnum}
|
||||
LEFT JOIN adm_organization_location AS T5 ON T5.distribution_category_code = T1.category_code
|
||||
AND T5.delete_flag = '0' AND T5.item_code = '2' AND T5.organization_id = #{organizationId} AND
|
||||
(CURRENT_TIME :: time (6) BETWEEN T5.start_time AND T5.end_time)
|
||||
WHERE T1.delete_flag = '0'
|
||||
<if test="adviceDefinitionIdParamList != null and !adviceDefinitionIdParamList.isEmpty()">
|
||||
AND T1.id IN
|
||||
<foreach collection="adviceDefinitionIdParamList" item="itemId" open="(" separator="," close=")">
|
||||
#{itemId}
|
||||
</foreach>
|
||||
</if>
|
||||
AND T4.instance_table = #{deviceTableName}
|
||||
AND T1.status_enum = #{statusEnum}
|
||||
)
|
||||
</if>
|
||||
|
||||
|
||||
<if test="adviceTypes == null or adviceTypes.contains(2)">
|
||||
<if test="adviceTypes == null or adviceTypes.contains(3)">UNION ALL</if>
|
||||
</if>
|
||||
|
||||
<if test="adviceTypes == null or adviceTypes.contains(3)">
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
3 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
'' AS pharmacology_category_code,
|
||||
1 AS part_percent,
|
||||
0 AS unit_conversion_ratio,
|
||||
null AS part_attribute_enum,
|
||||
null AS tho_part_attribute_enum,
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
T1.ID AS advice_definition_id,
|
||||
T1.NAME AS advice_name,
|
||||
T1.bus_no AS advice_bus_no,
|
||||
T1.py_str AS py_str,
|
||||
T1.wb_str AS wb_str,
|
||||
T1.yb_no AS yb_no,
|
||||
'' AS product_name,
|
||||
T1.type_enum AS activity_type,
|
||||
'' AS unit_code,
|
||||
'' AS min_unit_code,
|
||||
'' AS volume,
|
||||
'' AS method_code,
|
||||
'' AS rate_code,
|
||||
T1.org_id AS org_id,
|
||||
T1.location_id AS location_id,
|
||||
'' AS dose,
|
||||
'' AS dose_unit_code,
|
||||
'' AS supplier,
|
||||
null AS supplier_id,
|
||||
'' AS manufacturer,
|
||||
T2.ID AS charge_item_definition_id,
|
||||
T2.instance_table AS advice_table_name,
|
||||
T3.organization_id AS position_id,
|
||||
0 AS restricted_flag,
|
||||
'' AS restricted_scope,
|
||||
'' AS dosage_instruction,
|
||||
T1.chrgitm_lv as chrgitm_lv
|
||||
FROM wor_activity_definition AS T1
|
||||
LEFT JOIN adm_charge_item_definition AS T2
|
||||
ON T2.instance_id = T1.ID
|
||||
AND T2.delete_flag = '0' AND T2.status_enum = #{statusEnum}
|
||||
AND T2.instance_table = #{activityTableName}
|
||||
LEFT JOIN adm_organization_location AS T3 ON T3.activity_definition_id = T1.ID
|
||||
AND T3.delete_flag = '0' AND (CURRENT_TIME :: time (6) BETWEEN T3.start_time AND T3.end_time)
|
||||
WHERE T1.delete_flag = '0'
|
||||
<if test="pricingFlag ==1">
|
||||
AND (T1.pricing_flag = #{pricingFlag} OR T1.pricing_flag IS NULL)
|
||||
</if>
|
||||
<if test="adviceDefinitionIdParamList != null and !adviceDefinitionIdParamList.isEmpty()">
|
||||
AND T1.id IN
|
||||
<foreach collection="adviceDefinitionIdParamList" item="itemId" open="(" separator="," close=")">
|
||||
#{itemId}
|
||||
</foreach>
|
||||
</if>
|
||||
AND T1.status_enum = #{statusEnum}
|
||||
)
|
||||
<!-- 如果没有有效的adviceTypes,提供一个空的默认查询以避免语法错误 -->
|
||||
<if test="adviceTypes == null or adviceTypes.isEmpty() or (!adviceTypes.contains(1) and !adviceTypes.contains(2) and !adviceTypes.contains(3))">
|
||||
SELECT
|
||||
mmd.tenant_id,
|
||||
CAST(0 AS INTEGER) AS advice_type,
|
||||
CAST('' AS VARCHAR) AS bus_no,
|
||||
CAST('' AS VARCHAR) AS category_code,
|
||||
CAST('' AS VARCHAR) AS pharmacology_category_code,
|
||||
CAST(0 AS NUMERIC) AS part_percent,
|
||||
CAST(0 AS NUMERIC) AS unit_conversion_ratio,
|
||||
CAST(0 AS INTEGER) AS part_attribute_enum,
|
||||
CAST(0 AS INTEGER) AS tho_part_attribute_enum,
|
||||
CAST(0 AS INTEGER) AS skin_test_flag,
|
||||
CAST(0 AS INTEGER) AS inject_flag,
|
||||
CAST(0 AS BIGINT) AS advice_definition_id,
|
||||
CAST('' AS VARCHAR) AS advice_name,
|
||||
CAST('' AS VARCHAR) AS advice_bus_no,
|
||||
CAST('' AS VARCHAR) AS py_str,
|
||||
CAST('' AS VARCHAR) AS wb_str,
|
||||
CAST('' AS VARCHAR) AS yb_no,
|
||||
CAST('' AS VARCHAR) AS product_name,
|
||||
CAST(0 AS INTEGER) AS activity_type,
|
||||
CAST('' AS VARCHAR) AS unit_code,
|
||||
CAST('' AS VARCHAR) AS min_unit_code,
|
||||
CAST(0 AS NUMERIC) AS volume,
|
||||
CAST('' AS VARCHAR) AS method_code,
|
||||
CAST('' AS VARCHAR) AS rate_code,
|
||||
CAST(0 AS BIGINT) AS org_id,
|
||||
CAST(0 AS BIGINT) AS location_id,
|
||||
CAST('' AS VARCHAR) AS dose,
|
||||
CAST('' AS VARCHAR) AS dose_unit_code,
|
||||
CAST('' AS VARCHAR) AS supplier,
|
||||
CAST(0 AS BIGINT) AS supplier_id,
|
||||
CAST('' AS VARCHAR) AS manufacturer,
|
||||
CAST(0 AS BIGINT) AS charge_item_definition_id,
|
||||
CAST('' AS VARCHAR) AS advice_table_name,
|
||||
CAST(0 AS BIGINT) AS position_id,
|
||||
CAST(0 AS INTEGER) AS restricted_flag,
|
||||
CAST('' AS VARCHAR) AS restricted_scope,
|
||||
CAST('' AS VARCHAR) AS dosage_instruction,
|
||||
CAST(0 AS INTEGER) AS chrgitm_lv
|
||||
FROM med_medication_definition mmd
|
||||
WHERE 1 = 0 -- 仍然确保不返回任何行,但使用真实表确保类型正确
|
||||
</if>
|
||||
) AS abi
|
||||
${ew.customSqlSegment}
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
T10.reception_time,
|
||||
T10.practitioner_user_id,
|
||||
T10.jz_practitioner_user_id,
|
||||
T10.bus_no
|
||||
T10.bus_no,
|
||||
T10.identifier_no
|
||||
from
|
||||
(
|
||||
SELECT T1.tenant_id AS tenant_id,
|
||||
@@ -48,7 +49,8 @@
|
||||
T1.create_time AS register_time,
|
||||
T1.reception_time AS reception_time,
|
||||
T1.organization_id AS org_id,
|
||||
T8.bus_no AS bus_no
|
||||
T8.bus_no AS bus_no,
|
||||
T9.identifier_no AS identifier_no
|
||||
FROM adm_encounter AS T1
|
||||
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
|
||||
LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0'
|
||||
@@ -67,6 +69,20 @@
|
||||
LEFT JOIN adm_account AS T6 ON T1.ID = T6.encounter_id AND T6.delete_flag = '0' and T6.encounter_flag = '1'
|
||||
LEFT JOIN fin_contract AS T7 ON T6.contract_no = T7.bus_no AND T7.delete_flag = '0'
|
||||
LEFT JOIN adm_patient AS T8 ON T1.patient_id = T8.ID AND T8.delete_flag = '0'
|
||||
LEFT JOIN (
|
||||
SELECT patient_id,
|
||||
identifier_no
|
||||
FROM (
|
||||
SELECT patient_id,
|
||||
identifier_no,
|
||||
ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY create_time ASC) AS rn
|
||||
FROM adm_patient_identifier
|
||||
WHERE delete_flag = '0'
|
||||
AND identifier_no IS NOT NULL
|
||||
AND identifier_no != ''
|
||||
) t
|
||||
WHERE rn = 1
|
||||
) AS T9 ON T8.id = T9.patient_id
|
||||
WHERE
|
||||
T1.delete_flag = '0'
|
||||
<!-- 当前登录账号ID 和 当前登录账号所属的科室ID 用于控制数据权限 -->
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body { font-family: 'Microsoft YaHei', sans-serif; width: 350px; margin: 0 auto; padding: 20px; border: 1px solid #ccc; background: #fff; }
|
||||
.header { text-align: center; }
|
||||
.hospital-name { font-size: 20px; font-weight: bold; margin-bottom: 5px; }
|
||||
.title { font-size: 16px; margin-bottom: 10px; }
|
||||
.time { font-size: 12px; color: #666; margin-bottom: 15px; }
|
||||
.section { border-top: 1px solid #000; padding-top: 10px; margin-top: 10px; }
|
||||
.section-title { font-weight: bold; text-decoration: underline; margin-bottom: 10px; font-size: 14px; }
|
||||
.item { display: flex; font-size: 13px; margin-bottom: 5px; }
|
||||
.label { width: 90px; color: #333; }
|
||||
.value { flex: 1; font-weight: 500; }
|
||||
table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 13px; }
|
||||
th { text-align: left; border-bottom: 1px dashed #ccc; padding-bottom: 5px; color: #666; }
|
||||
td { padding: 5px 0; }
|
||||
.total { text-align: right; font-weight: bold; border-top: 1px solid #000; padding-top: 10px; margin-top: 10px; font-size: 15px; }
|
||||
.footer { margin-top: 20px; font-size: 11px; color: #666; line-height: 1.5; }
|
||||
.qr-code { text-align: center; margin-top: 15px; }
|
||||
.serial-no { text-align: left; margin-top: 10px; font-size: 12px; font-weight: bold; border-top: 1px dashed #ccc; padding-top: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='header'>
|
||||
<div class='hospital-name'>$hospitalName</div>
|
||||
<div class='title'>门诊预约挂号凭条</div>
|
||||
<div class='time'>打印时间:$printTime</div>
|
||||
</div>
|
||||
<div class='section'>
|
||||
<div class='section-title'>患者基本信息</div>
|
||||
<div class='item'><div class='label'>患者姓名:</div><div class='value'>$patientName</div></div>
|
||||
<div class='item'><div class='label'>门诊号:</div><div class='value'>$outpatientNo</div></div>
|
||||
<div class='item'><div class='label'>身份证号:</div><div class='value'>#if($idCard)$idCard#else-#end</div></div>
|
||||
<div class='item'><div class='label'>联系电话:</div><div class='value'>#if($tel)$tel#else-#end</div></div>
|
||||
</div>
|
||||
<div class='section'>
|
||||
<div class='section-title'>预约详情</div>
|
||||
<div class='item'><div class='label'>就诊科室:</div><div class='value'>#if($deptName)$deptName#else-#end</div></div>
|
||||
<div class='item'><div class='label'>医生姓名:</div><div class='value'>$doctorName</div></div>
|
||||
<div class='item'><div class='label'>预约时间:</div><div class='value'>#if($appointmentTime)$appointmentTime#else-#end</div></div>
|
||||
<div class='item'><div class='label'>就诊地点:</div><div class='value'>门诊大楼内</div></div>
|
||||
<div class='item'><div class='label'>预约状态:</div><div class='value'><span style='color:green;'>☑ 已 预</span></div></div>
|
||||
</div>
|
||||
<div class='section'>
|
||||
<div class='section-title'>费用信息</div>
|
||||
<table>
|
||||
<tr><th>项目</th><th>数量</th><th>单价</th><th>金额</th></tr>
|
||||
#foreach($item in $items)
|
||||
<tr>
|
||||
<td>$item.chargeItemName</td>
|
||||
<td>$item.quantityValue</td>
|
||||
<td>¥$item.totalPrice</td>
|
||||
<td>¥$item.totalPrice</td>
|
||||
</tr>
|
||||
#end
|
||||
</table>
|
||||
<div class='total'>合计:¥$totalAmt</div>
|
||||
<div class='item' style='margin-top:10px;'><div class='label'>支付方式:</div><div class='value'>线上支付 (已支付)</div></div>
|
||||
</div>
|
||||
<div class='footer'>
|
||||
温馨提示:请至少提前30分钟到达取号,过时自动取消。服务时间:8:00-17:00
|
||||
</div>
|
||||
<div class='qr-code'>
|
||||
<img src='https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=$busNo' width='100' height='100' />
|
||||
</div>
|
||||
<div class='serial-no'>流水号:$busNo</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.openhis.administration.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
@@ -33,14 +34,16 @@ public class OperatingRoom extends HisBaseEntity {
|
||||
private String name;
|
||||
|
||||
/** 手术室类型 */
|
||||
@Dict(dictCode = "operating_room_type")
|
||||
private Integer roomTypeEnum;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String roomTypeEnum_dictText;
|
||||
|
||||
/** 所属机构ID */
|
||||
private Long organizationId;
|
||||
|
||||
/** 所属机构名称 */
|
||||
@TableField(exist = false)
|
||||
private String organizationName;
|
||||
|
||||
/** 位置描述 */
|
||||
@@ -64,6 +67,9 @@ public class OperatingRoom extends HisBaseEntity {
|
||||
/** 五笔码 */
|
||||
private String wbStr;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
public OperatingRoom() {
|
||||
this.statusEnum = LocationStatus.ACTIVE.getValue();
|
||||
}
|
||||
|
||||
@@ -44,8 +44,16 @@ public class EncounterServiceImpl extends ServiceImpl<EncounterMapper, Encounter
|
||||
// 生成就诊编码 医保挂号时是先生成码后生成实体
|
||||
encounter.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.ENCOUNTER_NUM.getPrefix(), 4));
|
||||
}
|
||||
// 生成就诊序号 (患者ID + 科室ID 作为当日就诊号的唯一标识)
|
||||
String preFix = encounter.getPatientId() + String.valueOf(encounter.getOrganizationId());
|
||||
// 生成就诊序号:
|
||||
// 1) 若挂号医生已传入(registrarId 充当挂号医生 ID),按“科室+医生+当日”递增
|
||||
// Key 示例:ORG-123-DOC-456 -> 1、2、3...
|
||||
// 2) 否则按“科室+当日”递增
|
||||
String preFix;
|
||||
if (encounter.getRegistrarId() != null) {
|
||||
preFix = "ORG-" + encounter.getOrganizationId() + "-DOC-" + encounter.getRegistrarId();
|
||||
} else {
|
||||
preFix = "ORG-" + encounter.getOrganizationId();
|
||||
}
|
||||
encounter.setDisplayOrder(assignSeqUtil.getSeqNoByDay(preFix));
|
||||
// 患者ID
|
||||
Long patientId = encounter.getPatientId();
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>openhis-server</artifactId>
|
||||
<groupId>com.openhis</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>openhis-einvoiceapp</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 领域-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.openhis</groupId>-->
|
||||
<!-- <artifactId>openhis-domain</artifactId>-->
|
||||
<!-- <version>0.0.1-SNAPSHOT</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<!-- 共通-->
|
||||
<dependency>
|
||||
<groupId>com.openhis</groupId>
|
||||
<artifactId>openhis-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- liteflow-->
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>kernel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- pdf依赖-->
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itextpdf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itext-asian</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!-- <build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <fork>true</fork> <!– 如果没有该配置,devtools不会生效 –>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>repackage</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-war-plugin</artifactId>-->
|
||||
<!-- <version>${maven-war-plugin.version}</version>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <failOnMissingWebXml>false</failOnMissingWebXml>-->
|
||||
<!-- <warName>${project.artifactId}</warName>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!-- <finalName>${project.artifactId}</finalName>-->
|
||||
<!-- </build>-->
|
||||
|
||||
</project>
|
||||
18
openhis-ui-vue3/package-lock.json
generated
18
openhis-ui-vue3/package-lock.json
generated
@@ -1637,6 +1637,7 @@
|
||||
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
|
||||
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
@@ -1647,6 +1648,7 @@
|
||||
"integrity": "sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
@@ -3333,6 +3335,7 @@
|
||||
"resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -5575,13 +5578,15 @@
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash-unified": {
|
||||
"version": "1.0.3",
|
||||
@@ -6534,6 +6539,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -6774,6 +6780,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -6786,6 +6793,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
||||
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.0"
|
||||
@@ -7037,6 +7045,7 @@
|
||||
"integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
@@ -7215,6 +7224,7 @@
|
||||
"integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
@@ -7247,6 +7257,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/segmentit/-/segmentit-2.0.3.tgz",
|
||||
"integrity": "sha512-7mn2XL3OdTUQ+AhHz7SbgyxLTaQRzTWQNVwiK+UlTO8aePGbSwvKUzTwE4238+OUY9MoR6ksAg35zl8sfTunQQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"preval.macro": "^4.0.0"
|
||||
}
|
||||
@@ -8446,6 +8457,7 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -8807,6 +8819,7 @@
|
||||
"integrity": "sha512-RzAr8LSvM8lmhB4tQ5OPcBhpjOZRZjuxv9zO5UcxeoY2bd3kP3Ticd40Qma9/BqZ8JS96Ll/jeBX9u+LJZrhVg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.19.3",
|
||||
"postcss": "^8.4.31",
|
||||
@@ -8911,6 +8924,7 @@
|
||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.25.tgz",
|
||||
"integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.25",
|
||||
"@vue/compiler-sfc": "3.5.25",
|
||||
|
||||
@@ -11,7 +11,7 @@ export default {
|
||||
inDiagName: '急性上呼吸道感染',
|
||||
name: '于浩',
|
||||
officeName: '住院科室',
|
||||
title: '长春市朝阳区中医院',
|
||||
title: '',
|
||||
operaDays: null,
|
||||
outdate: null,
|
||||
sex: '女',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="recordBill">
|
||||
<div :id="'exeSheetTitle' + printData.id" class="printView_header">
|
||||
<div style="text-align: center; height: 60px">
|
||||
长春市朝阳区中医院医嘱执行单
|
||||
{{ userStore.hospitalName }}医嘱执行单
|
||||
</div>
|
||||
<div>
|
||||
<span style="display: inline-block; width: 100px">床号:{{ printData.patientInfo.encounterLocationName }}</span>
|
||||
@@ -87,8 +87,13 @@
|
||||
</template>
|
||||
<script>
|
||||
import {getLodop} from '../../../plugins/print/LodopFuncs'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const userStore = useUserStore();
|
||||
return { userStore };
|
||||
},
|
||||
props: {
|
||||
printData: {
|
||||
type: Object,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="recordBill">
|
||||
<div id="div1" class="printView_header">
|
||||
<div style="text-align: center; font-size: 20px; height: 40px">
|
||||
长春市朝阳区中医院输液执行单
|
||||
{{ userStore.hospitalName }}输液执行单
|
||||
</div>
|
||||
<div>
|
||||
<span>座位:{{ printData.patientInfo.encounterLocationName }}</span>
|
||||
@@ -61,8 +61,13 @@
|
||||
</template>
|
||||
<script>
|
||||
import {getLodop} from '../../../plugins/print/LodopFuncs'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const userStore = useUserStore();
|
||||
return { userStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
printData: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="printTicket">
|
||||
<p>长春市朝阳区中医院</p>
|
||||
<p>{{ userStore.hospitalName }}</p>
|
||||
<div>
|
||||
<span>姓名:</span>
|
||||
<span>{{ printData.patientName }}</span>
|
||||
@@ -26,9 +26,14 @@
|
||||
</template>
|
||||
<script>
|
||||
import JsBarcode from 'jsbarcode';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
export default {
|
||||
name: 'TriageTicket',
|
||||
setup() {
|
||||
const userStore = useUserStore();
|
||||
return { userStore };
|
||||
},
|
||||
props: {
|
||||
printData: {
|
||||
type: Object,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 15,
|
||||
"height": 16.5,
|
||||
"width": 792,
|
||||
"title": "长春市朝阳区中医院预交金收据",
|
||||
"title": "{{HOSPITAL_NAME}}预交金收据",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontWeight": "bold",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 38,
|
||||
"height": 19.5,
|
||||
"width": 255,
|
||||
"title": "中药长春市朝阳区中医院",
|
||||
"title": "中药{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 11.25,
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
"top": 58.5,
|
||||
"height": 13.5,
|
||||
"width": 145.5,
|
||||
"title": "机构名称:长春市朝阳区中医院",
|
||||
"title": "机构名称:{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 9,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 22.5,
|
||||
"height": 19.5,
|
||||
"width": 420,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 20.25,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"top": 39.5,
|
||||
"height": 19.5,
|
||||
"width": 255,
|
||||
"title": "中药长春市朝阳区中医院",
|
||||
"title": "中药{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 11.25,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 22.5,
|
||||
"height": 19.5,
|
||||
"width": 595.5,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 20.25,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 22.5,
|
||||
"height": 19.5,
|
||||
"width": 420,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 20.25,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 22.5,
|
||||
"height": 19.5,
|
||||
"width": 595.5,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 20.25,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 15,
|
||||
"height": 16.5,
|
||||
"width": 225,
|
||||
"title": "长春市朝阳区中医院门诊收费结算单",
|
||||
"title": "{{HOSPITAL_NAME}}门诊收费结算单",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontWeight": "bold",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"top": 22.5,
|
||||
"height": 19.5,
|
||||
"width": 595.5,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 20.25,
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"top": 15,
|
||||
"height": 16.5,
|
||||
"width": 226.5,
|
||||
"title": "长春市朝阳区中医院挂号收费明细",
|
||||
"title": "{{HOSPITAL_NAME}}挂号收费明细",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontWeight": "bold",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"top": 20,
|
||||
"height": 19.5,
|
||||
"width": 228,
|
||||
"title": "中药长春市朝阳区中医院",
|
||||
"title": "中药{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 11.25,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 20,
|
||||
"height": 19.5,
|
||||
"width": 420,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 11.25,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"top": 38,
|
||||
"height": 19.5,
|
||||
"width": 255,
|
||||
"title": "中药长春市朝阳区中医院",
|
||||
"title": "中药{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 11.25,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"top": 22.5,
|
||||
"height": 19.5,
|
||||
"width": 420,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 20.25,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createWebHistory, createRouter } from 'vue-router'
|
||||
import {createWebHistory, createRouter} from 'vue-router'
|
||||
/* Layout */
|
||||
import Layout from '@/layout'
|
||||
|
||||
@@ -16,366 +16,86 @@ import Layout from '@/layout'
|
||||
* roles: ['admin', 'common'] // 访问路由的角色权限
|
||||
* permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
|
||||
* meta : {
|
||||
noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
|
||||
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
|
||||
icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
|
||||
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
|
||||
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
|
||||
}
|
||||
noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
|
||||
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
|
||||
icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
|
||||
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
|
||||
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
|
||||
}
|
||||
*/
|
||||
|
||||
// 公共路由
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/redirect',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
component: () => import('@/views/redirect/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/views/login'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
component: () => import('@/views/register'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/401',
|
||||
component: () => import('@/views/error/401'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: Layout,
|
||||
redirect: '/index',
|
||||
children: [
|
||||
{
|
||||
path: '/index',
|
||||
component: () => import('@/views/index'),
|
||||
name: 'Index',
|
||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/user',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
redirect: 'noredirect',
|
||||
children: [
|
||||
{
|
||||
path: 'profile',
|
||||
component: () => import('@/views/system/user/profile/index'),
|
||||
name: 'Profile',
|
||||
meta: { title: '个人中心', icon: 'user' }
|
||||
}
|
||||
]
|
||||
},
|
||||
// 添加套餐管理相关路由到公共路由,确保始终可用
|
||||
{
|
||||
path: '/maintainSystem/Inspection/PackageManagement',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
{
|
||||
path: '/redirect',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
component: () => import('@/views/redirect/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/views/login'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
component: () => import('@/views/register'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/401',
|
||||
component: () => import('@/views/error/401'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/maintainSystem/Inspection/PackageManagement.vue'),
|
||||
name: 'DirectPackageManagement',
|
||||
meta: { title: '套餐管理' }
|
||||
}
|
||||
]
|
||||
}
|
||||
component: Layout,
|
||||
redirect: '/index',
|
||||
children: [
|
||||
{
|
||||
path: '/index',
|
||||
component: () => import('@/views/index'),
|
||||
name: 'Index',
|
||||
meta: {title: '首页', icon: 'dashboard', affix: true}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/user',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
redirect: 'noredirect',
|
||||
children: [
|
||||
{
|
||||
path: 'profile',
|
||||
component: () => import('@/views/system/user/profile/index'),
|
||||
name: 'Profile',
|
||||
meta: {title: '个人中心', icon: 'user'}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
// 动态路由,基于用户权限动态去加载
|
||||
export const dynamicRoutes = [
|
||||
export const dynamicRoutes = [
|
||||
{
|
||||
path: '/basicmanage',
|
||||
component: Layout,
|
||||
redirect: '/basicmanage/invoice-management',
|
||||
name: 'BasicManage',
|
||||
meta: { title: '基础管理', icon: 'component' },
|
||||
children: [
|
||||
{
|
||||
path: 'invoice-management',
|
||||
component: () => import('@/views/basicmanage/InvoiceManagement/index.vue'),
|
||||
name: 'invoice-management',
|
||||
meta: { title: '发票管理' }
|
||||
}
|
||||
]
|
||||
path: '/help-center',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/helpcenter/index.vue'),
|
||||
name: 'HelpCenter',
|
||||
meta: {title: '帮助中心'},
|
||||
},
|
||||
],
|
||||
},
|
||||
// 兼容系统业务管理路径
|
||||
// {
|
||||
// path: '/system/ywgz',
|
||||
// component: Layout,
|
||||
// redirect: '/system/ywgz/InvoiceManagement',
|
||||
// hidden: true,
|
||||
// children: [
|
||||
// {
|
||||
// path: 'InvoiceManagement',
|
||||
// component: () => import('@/views/basicmanage/InvoiceManagement/index.vue'),
|
||||
// name: 'SystemInvoiceManagement',
|
||||
// meta: { title: '发票管理' }
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// path: '/maintainSystem',
|
||||
// component: Layout,
|
||||
// redirect: '/maintainSystem/chargeConfig',
|
||||
// name: 'MaintainSystem',
|
||||
// meta: { title: '维护系统', icon: 'system' },
|
||||
// children: [
|
||||
// {
|
||||
// path: '',
|
||||
// redirect: 'chargeConfig'
|
||||
// },
|
||||
// {
|
||||
// path: 'chargeConfig',
|
||||
// component: () => import('@/views/maintainSystem/chargeConfig/index.vue'),
|
||||
// name: 'ChargeConfig',
|
||||
// meta: { title: '挂号收费系统参数维护', icon: 'config', permissions: ['maintainSystem:chargeConfig:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'Inspection',
|
||||
// component: () => import('@/views/maintainSystem/Inspection/index.vue'),
|
||||
// name: 'Inspection',
|
||||
// meta: { title: '检验管理', icon: 'inspection' },
|
||||
// children: [
|
||||
// {
|
||||
// path: 'PackageManagement',
|
||||
// component: () => import('@/views/maintainSystem/Inspection/PackageManagement.vue'),
|
||||
// name: 'PackageManagement',
|
||||
// meta: { title: '套餐管理' }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// path: '/system',
|
||||
// component: Layout,
|
||||
// redirect: '/system/user',
|
||||
// name: 'System',
|
||||
// meta: { title: '系统管理', icon: 'system' },
|
||||
// children: [
|
||||
// {
|
||||
// path: 'user',
|
||||
// component: () => import('@/views/system/user/index.vue'),
|
||||
// name: 'User',
|
||||
// meta: { title: '用户管理', icon: 'user', permissions: ['system:user:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'role',
|
||||
// component: () => import('@/views/system/role/index.vue'),
|
||||
// name: 'Role',
|
||||
// meta: { title: '角色管理', icon: 'role', permissions: ['system:role:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'menu',
|
||||
// component: () => import('@/views/system/menu/index.vue'),
|
||||
// name: 'Menu',
|
||||
// meta: { title: '菜单管理', icon: 'menu', permissions: ['system:menu:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'dept',
|
||||
// component: () => import('@/views/system/dept/index.vue'),
|
||||
// name: 'Dept',
|
||||
// meta: { title: '部门管理', icon: 'dept', permissions: ['system:dept:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'post',
|
||||
// component: () => import('@/views/system/post/index.vue'),
|
||||
// name: 'Post',
|
||||
// meta: { title: '岗位管理', icon: 'post', permissions: ['system:post:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'dict',
|
||||
// component: () => import('@/views/system/dict/index.vue'),
|
||||
// name: 'Dict',
|
||||
// meta: { title: '字典管理', icon: 'dict', permissions: ['system:dict:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'config',
|
||||
// component: () => import('@/views/system/config/index.vue'),
|
||||
// name: 'Config',
|
||||
// meta: { title: '参数配置', icon: 'config', permissions: ['system:config:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'notice',
|
||||
// component: () => import('@/views/system/notice/index.vue'),
|
||||
// name: 'Notice',
|
||||
// meta: { title: '通知公告', icon: 'notice', permissions: ['system:notice:list'] }
|
||||
// },
|
||||
// {
|
||||
// path: 'tenant',
|
||||
// component: () => import('@/views/system/tenant/index.vue'),
|
||||
// name: 'Tenant',
|
||||
// meta: { title: '租户管理', icon: 'tenant', permissions: ['system:tenant:list'] }
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
path: '/system/tenant-user',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['*:*:*'],
|
||||
children: [
|
||||
{
|
||||
path: 'set/:tenantId(\\d+)',
|
||||
component: () => import('@/views/system/tenant/setUser'),
|
||||
name: 'SetUser',
|
||||
meta: { title: '所属用户', activeMenu: '/system/tenant' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/system/tenant-contract',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['*:*:*'],
|
||||
children: [
|
||||
{
|
||||
path: 'set/:tenantId(\\d+)',
|
||||
component: () => import('@/views/system/tenant/setContract'),
|
||||
name: 'SetContract',
|
||||
meta: { title: '合同管理', activeMenu: '/system/tenant' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/system/user-auth',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['system:user:edit'],
|
||||
children: [
|
||||
{
|
||||
path: 'role/:userId(\\d+)',
|
||||
component: () => import('@/views/system/user/authRole'),
|
||||
name: 'AuthRole',
|
||||
meta: { title: '分配角色', activeMenu: '/system/user' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/system/role-auth',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['system:role:edit'],
|
||||
children: [
|
||||
{
|
||||
path: 'user/:roleId(\\d+)',
|
||||
component: () => import('@/views/system/role/authUser'),
|
||||
name: 'AuthUser',
|
||||
meta: { title: '分配用户', activeMenu: '/system/role' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/system/dict-data',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['system:dict:list'],
|
||||
children: [
|
||||
{
|
||||
path: 'index/:dictId(\\d+)',
|
||||
component: () => import('@/views/system/dict/data'),
|
||||
name: 'Data',
|
||||
meta: { title: '字典数据', activeMenu: '/system/dict' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/monitor',
|
||||
component: Layout,
|
||||
redirect: '/monitor/operlog',
|
||||
name: 'Monitor',
|
||||
meta: { title: '系统监控', icon: 'monitor' },
|
||||
children: [
|
||||
{
|
||||
path: 'operlog',
|
||||
component: () => import('@/views/monitor/operlog/index.vue'),
|
||||
name: 'Operlog',
|
||||
meta: { title: '操作日志', icon: 'operlog', permissions: ['monitor:operlog:list'] }
|
||||
},
|
||||
{
|
||||
path: 'logininfor',
|
||||
component: () => import('@/views/monitor/logininfor/index.vue'),
|
||||
name: 'Logininfor',
|
||||
meta: { title: '登录日志', icon: 'logininfor', permissions: ['monitor:logininfor:list'] }
|
||||
},
|
||||
{
|
||||
path: 'job',
|
||||
component: () => import('@/views/monitor/job/index.vue'),
|
||||
name: 'Job',
|
||||
meta: { title: '定时任务', icon: 'job', permissions: ['monitor:job:list'] }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/tool',
|
||||
component: Layout,
|
||||
redirect: '/tool/gen',
|
||||
name: 'Tool',
|
||||
meta: { title: '系统工具', icon: 'tool' },
|
||||
children: [
|
||||
{
|
||||
path: 'gen',
|
||||
component: () => import('@/views/tool/gen/index.vue'),
|
||||
name: 'Gen',
|
||||
meta: { title: '代码生成', icon: 'gen', permissions: ['tool:gen:list'] }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/monitor/job-log',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['monitor:job:list'],
|
||||
children: [
|
||||
{
|
||||
path: 'index/:jobId(\\d+)',
|
||||
component: () => import('@/views/monitor/job/log'),
|
||||
name: 'JobLog',
|
||||
meta: { title: '调度日志', activeMenu: '/monitor/job' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/tool/gen-edit',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['tool:gen:edit'],
|
||||
children: [
|
||||
{
|
||||
path: 'index/:tableId(\\d+)',
|
||||
component: () => import('@/views/tool/gen/editTable'),
|
||||
name: 'GenEdit',
|
||||
meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/help-center',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/helpcenter/index.vue'),
|
||||
name: 'HelpCenter',
|
||||
meta: { title: '帮助中心'},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// 合并常量路由和动态路由,确保所有路由都能被访问
|
||||
@@ -383,21 +103,21 @@ const allRoutes = [...constantRoutes, ...dynamicRoutes];
|
||||
|
||||
// 添加404路由到所有路由的最后
|
||||
allRoutes.push({
|
||||
path: "/:pathMatch(.*)*",
|
||||
component: () => import('@/views/error/404'),
|
||||
hidden: true
|
||||
path: "/:pathMatch(.*)*",
|
||||
component: () => import('@/views/error/404'),
|
||||
hidden: true
|
||||
});
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: allRoutes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
} else {
|
||||
return { top: 0 }
|
||||
}
|
||||
},
|
||||
history: createWebHistory(),
|
||||
routes: allRoutes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
} else {
|
||||
return {top: 0}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,96 +1,99 @@
|
||||
import { login, logout, getInfo } from '@/api/login'
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
import {getInfo, login, logout} from '@/api/login'
|
||||
import {getToken, removeToken, setToken} from '@/utils/auth'
|
||||
import defAva from '@/assets/images/user.png'
|
||||
import { defineStore } from 'pinia'
|
||||
import {defineStore} from 'pinia'
|
||||
|
||||
const useUserStore = defineStore(
|
||||
'user',
|
||||
{
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
id: '',
|
||||
name: '',
|
||||
avatar: '',
|
||||
orgId: '',
|
||||
practitionerId: '',
|
||||
orgName: '',
|
||||
nickName: '',
|
||||
fixmedinsCode: '', // 医疗机构编码
|
||||
roles: [],
|
||||
permissions: [],
|
||||
tenantId: '',
|
||||
hospitalName:''
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
login(userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
const password = userInfo.password
|
||||
const code = userInfo.code
|
||||
const uuid = userInfo.uuid
|
||||
const tenantId = userInfo.tenantId
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, uuid ,tenantId).then(res => {
|
||||
setToken(res.token)
|
||||
this.token = res.token
|
||||
this.tenantId = tenantId
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
'user',
|
||||
{
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
id: '',
|
||||
name: '',
|
||||
avatar: '',
|
||||
orgId: '',
|
||||
practitionerId: '',
|
||||
orgName: '',
|
||||
nickName: '',
|
||||
fixmedinsCode: '', // 医疗机构编码
|
||||
roles: [],
|
||||
permissions: [],
|
||||
tenantId: '',
|
||||
tenantName: '', // 租户名称
|
||||
hospitalName:'',
|
||||
optionMap: {} // 租户配置项Map(从sys_tenant_option表读取)
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
login(userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
const password = userInfo.password
|
||||
const code = userInfo.code
|
||||
const uuid = userInfo.uuid
|
||||
const tenantId = userInfo.tenantId
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, uuid ,tenantId).then(res => {
|
||||
setToken(res.token)
|
||||
this.token = res.token
|
||||
this.tenantId = tenantId
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取用户信息
|
||||
getInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo().then(res => {
|
||||
const user = res.user
|
||||
const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
|
||||
},
|
||||
// 获取用户信息
|
||||
getInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo().then(res => {
|
||||
const user = res.user
|
||||
const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
|
||||
|
||||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
this.roles = res.roles
|
||||
this.permissions = res.permissions
|
||||
} else {
|
||||
this.roles = ['ROLE_DEFAULT']
|
||||
}
|
||||
// console.log('user info:', user);
|
||||
this.id = user.userId
|
||||
this.name = user.userName // 用户账号(对应数据库的user_name字段,如'admin')
|
||||
this.orgId = user.orgId
|
||||
this.orgName = user.orgName
|
||||
this.nickName = user.nickName
|
||||
this.practitionerId = res.practitionerId
|
||||
this.fixmedinsCode = res.optionJson.fixmedinsCode
|
||||
this.avatar = avatar
|
||||
this.hospitalName = res.optionJson.hospitalName
|
||||
// 获取tenantId,优先从res.user获取,否则从res获取
|
||||
this.tenantId = user.tenantId || res.tenantId || this.tenantId
|
||||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
this.roles = res.roles
|
||||
this.permissions = res.permissions
|
||||
} else {
|
||||
this.roles = ['ROLE_DEFAULT']
|
||||
}
|
||||
// console.log('user info:', user);
|
||||
this.id = user.userId
|
||||
this.name = user.userName // 用户账号(对应数据库的user_name字段,如'admin')
|
||||
this.orgId = user.orgId
|
||||
this.orgName = user.orgName
|
||||
this.nickName = user.nickName
|
||||
this.practitionerId = res.practitionerId
|
||||
this.fixmedinsCode = res.optionJson.fixmedinsCode
|
||||
this.avatar = avatar
|
||||
this.optionMap = res.optionMap || {}
|
||||
// 优先从optionMap获取配置,如果没有则从optionJson获取
|
||||
this.hospitalName = this.optionMap.hospitalName || res.optionJson.hospitalName || ''
|
||||
this.tenantName = res.tenantName || ''
|
||||
|
||||
resolve(res)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
resolve(res)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
// 退出系统
|
||||
logOut() {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout(this.token).then(() => {
|
||||
this.token = ''
|
||||
this.roles = []
|
||||
this.permissions = []
|
||||
this.tenantId = ''
|
||||
removeToken()
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
},
|
||||
// 退出系统
|
||||
logOut() {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout(this.token).then(() => {
|
||||
this.token = ''
|
||||
this.roles = []
|
||||
this.permissions = []
|
||||
this.tenantId = ''
|
||||
removeToken()
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
removeRoles(){
|
||||
this.roles = []
|
||||
},
|
||||
removeRoles(){
|
||||
this.roles = []
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
export default useUserStore
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
patient?.busNo || '未知'
|
||||
}}
|
||||
</div>
|
||||
<h2 style="text-align: center">长春市朝阳区中医院</h2>
|
||||
<h2 style="text-align: center">{{ userStore.hospitalName }}</h2>
|
||||
<h2 style="text-align: center">出院诊断病历</h2>
|
||||
|
||||
<!-- 滚动内容区域 -->
|
||||
@@ -143,6 +143,9 @@ import {nextTick, onMounted, reactive, ref} from 'vue';
|
||||
import {ElMessage} from 'element-plus';
|
||||
import {previewPrint} from '../utils/printUtils';
|
||||
import DisDiagnMedicalRecord from '../views/hospitalRecord/components/disDiagnMedicalRecord.vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
defineOptions({
|
||||
name: 'DischargeDiagnosisCertificate',
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import {ref} from 'vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 1. 基础信息(复用已有变量,补充一致性格式)
|
||||
const patientInfo = ref({
|
||||
@@ -117,8 +120,8 @@ defineExpose({ patientInfo, firstRecordTime, firstRecordIntro, caseFeatures, chi
|
||||
<div class="medical-record">
|
||||
<!-- 1. 医院头部(每一页PDF均包含,复用已有样式) -->
|
||||
<div class="hospital-header">
|
||||
<img src="./imgs/logo.png" alt="长春市朝阳区中医院Logo" class="header-logo" />
|
||||
<h1 class="hospital-name">长春市朝阳区中医院</h1>
|
||||
<img src="./imgs/logo.png" :alt="userStore.hospitalName + 'Logo'" class="header-logo" />
|
||||
<h1 class="hospital-name">{{ userStore.hospitalName }}</h1>
|
||||
</div>
|
||||
|
||||
<!-- 2. 患者信息栏(每一页PDF均包含,下划线样式) -->
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<!-- 医院头部 -->
|
||||
<div class="hospital-header">
|
||||
<h1 class="hospital-name">
|
||||
<span class="hospital-text">长春市朝阳区中医院</span>
|
||||
<span class="hospital-text">{{ userStore.hospitalName }}</span>
|
||||
</h1>
|
||||
</div>
|
||||
<!-- 页面标题 -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="medical-form">
|
||||
<h2 style="text-align: center">
|
||||
{{ userStore.hospitalName || '长春市朝阳区中医院' }} -入院记录
|
||||
{{ userStore.hospitalName }} -入院记录
|
||||
</h2>
|
||||
|
||||
<!-- 滚动内容区域 -->
|
||||
|
||||
@@ -232,23 +232,13 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from 'vue';
|
||||
import intOperRecordSheet from '../views/hospitalRecord/components/intOperRecordSheet.vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDatePicker,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElMessage,
|
||||
ElMessageBox,
|
||||
ElOption,
|
||||
ElSelect,
|
||||
} from 'element-plus';
|
||||
import {previewPrint} from '../utils/printUtils';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const isShowprintDom = ref(false);
|
||||
const recordPrintRef = ref();
|
||||
// 医院名称
|
||||
const hospitalName = '长春市朝阳区中医院';
|
||||
const hospitalName = userStore.hospitalName;
|
||||
defineOptions({
|
||||
name: 'iInHospitalSurgicalRecord',
|
||||
});
|
||||
|
||||
@@ -213,20 +213,11 @@
|
||||
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from 'vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDatePicker,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElMessage,
|
||||
ElMessageBox,
|
||||
ElOption,
|
||||
ElSelect,
|
||||
} from 'element-plus';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 医院名称
|
||||
const hospitalName = '长春市朝阳区中医院';
|
||||
const hospitalName = userStore.hospitalName;
|
||||
defineOptions({
|
||||
name: 'InHospitalCommunicate',
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h2 class="title">长春市朝阳区中医院</h2>
|
||||
<h2 class="title">{{ userStore.hospitalName }}</h2>
|
||||
<h3 class="subtitle">患者护理记录单</h3>
|
||||
</div>
|
||||
|
||||
@@ -234,8 +234,10 @@
|
||||
defineOptions({
|
||||
name: 'NursingRecordSheet',
|
||||
});
|
||||
import {getCurrentInstance, onBeforeMount, onMounted} from 'vue';
|
||||
import {getCurrentInstance, onBeforeMount, onMounted, ref} from 'vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const emits = defineEmits([]);
|
||||
const props = defineProps({
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
patient?.busNo || '未知'
|
||||
}}
|
||||
</div>
|
||||
<h2 style="text-align: center">{{ userStore.hospitalName || '长春市朝阳区中医院' }}</h2>
|
||||
<h2 style="text-align: center">{{ userStore.hospitalName }}</h2>
|
||||
|
||||
<h2 style="text-align: center">门诊病历</h2>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="surgicalPatientHandover-container">
|
||||
<div class="handover-form">
|
||||
<div class="form-header">
|
||||
<h1 class="hospital-name">长春市朝阳区中医院</h1>
|
||||
<h1 class="hospital-name">{{ userStore.hospitalName }}</h1>
|
||||
<h2 class="form-title">手术患者交接单</h2>
|
||||
</div>
|
||||
|
||||
@@ -562,6 +562,9 @@ defineOptions({
|
||||
});
|
||||
import {getCurrentInstance, onBeforeMount, onMounted, reactive} from 'vue';
|
||||
import useOptionsList from './useOptionsList';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
// import { A } from '../../dist/assets/api-DmiMW8YF';
|
||||
const { statisticsOptionList, getStatisticsOptionList } = useOptionsList();
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
@@ -228,7 +228,11 @@ export function executePrint(data, template, printerName, options = {}, business
|
||||
throw new Error('打印插件未加载');
|
||||
}
|
||||
|
||||
const hiprintTemplate = new window.hiprint.PrintTemplate({ template });
|
||||
const userStore = useUserStore();
|
||||
const processedTemplate = JSON.parse(
|
||||
JSON.stringify(template).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
const hiprintTemplate = new window.hiprint.PrintTemplate({ template: processedTemplate });
|
||||
const printOptions = {
|
||||
title: '打印标题',
|
||||
height: 210,
|
||||
|
||||
@@ -299,236 +299,236 @@ async function printReceipt(param) {
|
||||
|
||||
// 金额大于0时显示金额和单位,等于0时不显示单位
|
||||
YB_FUND_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 100000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 100000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 基金支付总额
|
||||
SELF_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 200000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 200000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人负担总金额
|
||||
OTHER_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 其他(如医院负担金额)
|
||||
|
||||
// 基本医保统筹基金支出
|
||||
YB_TC_FUND_AMOUNT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 110000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 110000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 基本医保统筹基金支出
|
||||
YB_BC_FUND_AMOUNT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 120000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 补充医疗保险基金支出
|
||||
YB_JZ_FUND_AMOUNT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 130000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 130000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医疗救助基金支出
|
||||
YB_OTHER_AMOUNT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 140000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 140000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 其他支出
|
||||
|
||||
// 职工基本医疗保险
|
||||
YB_TC_ZG_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 110100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 110100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 职工基本医疗保险
|
||||
YB_TC_JM_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 110200)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 110200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 居民基本医疗保险
|
||||
|
||||
// 补充医疗保险基金支出细分
|
||||
YB_BC_JM_DB_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 120100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 全体参保人的居民大病保险
|
||||
YB_BC_DE_BZ_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 120200)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 大额医疗费用补助
|
||||
YB_BC_ZG_DE_BZ_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 120300)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 企业职工大额医疗费用补助
|
||||
YB_BC_GWY_BZ_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 120400)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 120400)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 公务员医疗补助
|
||||
|
||||
// 其他支出细分
|
||||
OTHER_PAY_DD_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300001)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300001)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 兜底基金支出
|
||||
OTHER_PAY_YW_SH_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300002)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300002)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 意外伤害基金支出
|
||||
OTHER_PAY_LX_YL_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300003)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300003)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 离休人员医疗保障金支出
|
||||
OTHER_PAY_LX_YH_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300004)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300004)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 离休人员优惠金支出
|
||||
OTHER_PAY_CZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300005)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300005)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 财政基金支出
|
||||
OTHER_PAY_CZ_YZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300006)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300006)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 财政预支支出
|
||||
OTHER_PAY_ZG_DB_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300007)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300007)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 职工大病基金支出
|
||||
OTHER_PAY_EY_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300008)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300008)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 二乙基金支出
|
||||
OTHER_PAY_QX_JZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300009)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300009)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 倾斜救助支出
|
||||
OTHER_PAY_YL_JZ_FUND_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300010)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300010)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医疗救助再救助基金
|
||||
HOSP_PART_AMT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 300011)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 300011)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医院负担金额
|
||||
|
||||
// 医保结算返回值
|
||||
FULAMT_OWNPAY_AMT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 1)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 1)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 全自费金额
|
||||
OVERLMT_SELFPAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 3)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 3)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 超限价自费费用
|
||||
PRESELFPAY_AMT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 4)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 4)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 先行自付金额
|
||||
INSCP_SCP_AMT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 5)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 5)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 符合政策范围金额
|
||||
ACT_PAY_DEDC: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 6)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 6)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 实际支付起付线
|
||||
POOL_PROP_SELFPAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 7)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 7)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 基本医疗保险统筹基金支付比例
|
||||
BALC: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 8)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 8)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 余额
|
||||
|
||||
// 特殊支付方式
|
||||
SELF_YB_ZH_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 210000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 210000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人医保账户支付
|
||||
SELF_YB_ZH_GJ_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 210100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 210100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 账户共济支付金额
|
||||
SELF_CASH_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 220000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额
|
||||
SELF_VX_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 230000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 230000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 微信支付金额
|
||||
SELF_ALI_PAY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 240000)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 240000)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 阿里支付金额
|
||||
|
||||
// 现金支付细分
|
||||
SELF_CASH_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(现金)
|
||||
SELF_CASH_VX_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(微信)
|
||||
SELF_CASH_ALI_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(支付宝)
|
||||
SELF_CASH_UNION_VALUE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 个人现金支付金额(银联)
|
||||
|
||||
// 基金类型(扩展)
|
||||
BIRTH_FUND: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 510100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 510100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 生育基金
|
||||
RETIREE_MEDICAL: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 340100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 340100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 离休人员医疗保障基金
|
||||
URBAN_BASIC_MEDICAL: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 390100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 城乡居民基本医疗保险基金
|
||||
URBAN_SERIOUS_ILLNESS: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 390200)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390200)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 城乡居民大病医疗保险基金
|
||||
MEDICAL_ASSISTANCE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 610100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 610100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医疗救助基金
|
||||
GOVERNMENT_SUBSIDY: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 640100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 640100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 政府兜底基金
|
||||
ACCIDENT_INSURANCE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 390400)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390400)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 意外伤害基金
|
||||
CARE_INSURANCE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 620100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 620100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 照护保险基金
|
||||
FINANCIAL_FUND: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 360100)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 360100)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 财政基金
|
||||
HOSPITAL_ADVANCE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 999900)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 999900)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 医院垫付
|
||||
SUPPLEMENTARY_INSURANCE: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 390300)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 390300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 城乡居民大病补充保险基金
|
||||
HEALTHCARE_PREPAYMENT: (() => {
|
||||
const amount = param.detail.find((t) => t.payEnum === 360300)?.amount ?? 0;
|
||||
const amount = param.detail?.find((t) => t.payEnum === 360300)?.amount ?? 0;
|
||||
return amount > 0 ? amount + ' 元' : amount;
|
||||
})(), // 保健预支基金
|
||||
//微信刷卡支付
|
||||
SELF_CASH_VX_VALUE: (() => {
|
||||
// const cashValue = param.detail.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
const vxValue = param.detail.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
const unionValue = param.detail.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
const aliValue = param.detail.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return vxValue + unionValue + aliValue + ' 元';
|
||||
// const cashValue = param.detail?.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
const vxValue = param.detail?.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
const unionValue = param.detail?.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
const aliValue = param.detail?.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return (Number(vxValue) + Number(unionValue) + Number(aliValue)).toFixed(2) + ' 元';
|
||||
})(),
|
||||
|
||||
Mr_QR_Code: param.regNo,
|
||||
@@ -674,7 +674,9 @@ async function print() {
|
||||
};
|
||||
console.log(result, '==result.data==');
|
||||
|
||||
const printElements = templateJson;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(templateJson).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
const printerList = hiprintTemplate.getPrinterList();
|
||||
console.log(hiprintTemplate, '打印机列表');
|
||||
|
||||
@@ -287,7 +287,7 @@ function getPatientList() {
|
||||
queryParams.value.receptionTimeETime = undefined;
|
||||
}
|
||||
getList(queryParams.value).then((res) => {
|
||||
patientList.value = res.data.data.records;
|
||||
patientList.value = res.data?.data?.records || [];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -363,17 +363,17 @@ function confirmCharge() {
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
chargeItemIds: chargeItemIdList.value,
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
if (res.code == 200 && res.data) {
|
||||
// totalAmount.value = res.data.psnCashPay;
|
||||
paymentId.value = res.data.paymentId;
|
||||
chrgBchnoList.value = res.data.chrgBchnoList;
|
||||
totalAmount.value = res.data.details.find((item) => item.payEnum == 220000).amount;
|
||||
details.value = res.data.details.filter((item) => {
|
||||
totalAmount.value = res.data.details?.find((item) => item.payEnum == 220000)?.amount ?? 0;
|
||||
details.value = res.data.details?.filter((item) => {
|
||||
return item.amount > 0;
|
||||
});
|
||||
}) || [];
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg);
|
||||
proxy.$modal.msgError(res?.msg || '预结算失败');
|
||||
}
|
||||
});
|
||||
// console.log(patientInfo)
|
||||
@@ -517,11 +517,11 @@ async function handleReadCard(value) {
|
||||
ybMdtrtCertType: userCardInfo.psnCertType,
|
||||
busiCardInfo: userCardInfo.busiCardInfo,
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
if (res.code == 200 && res.data) {
|
||||
// totalAmount.value = res.data.psnCashPay;
|
||||
paymentId.value = res.data.paymentId;
|
||||
totalAmount.value = res.data.details.find((item) => item.payEnum == 220000).amount;
|
||||
details.value = res.data.details;
|
||||
totalAmount.value = res.data.details?.find((item) => item.payEnum == 220000)?.amount ?? 0;
|
||||
details.value = res.data.details || [];
|
||||
// chrgBchnoList.value = res.data.chrgBchnoList;
|
||||
chargeItemIdList.value = selectRows.map((item) => {
|
||||
return item.id;
|
||||
@@ -537,7 +537,7 @@ async function handleReadCard(value) {
|
||||
});
|
||||
openDialog.value = true;
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg);
|
||||
proxy.$modal.msgError(res?.msg || '预结算失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -648,9 +648,9 @@ function printCharge(row) {
|
||||
getChargeInfo({ paymentId: row.paymentId }).then((res) => {
|
||||
// 设置实收金额
|
||||
if (res.data && res.data.detail) {
|
||||
const amountDetail = res.data.detail.find((item) => item.payEnum == 220000);
|
||||
const amountDetail = res.data.detail?.find((item) => item.payEnum == 220000);
|
||||
if (amountDetail) {
|
||||
totalAmount.value = amountDetail.amount;
|
||||
totalAmount.value = amountDetail.amount || 0;
|
||||
|
||||
// 为合并的行设置金额相关字段值
|
||||
rows.forEach((item) => {
|
||||
|
||||
@@ -302,14 +302,14 @@ function handleRefund(row) {
|
||||
// return new Decimal(accumulator).add(new Decimal(currentRow.totalPrice || 0));
|
||||
// }, 0);
|
||||
getReturnDetail({ id: row.paymentId }).then((res) => {
|
||||
if (res.data.length > 0) {
|
||||
if (res.data?.length > 0) {
|
||||
totalAmount.value =
|
||||
res.data.find((item) => item.payEnum === 220000).amount -
|
||||
(res.data.find((item) => item.payEnum === 220500)?.amount || 0);
|
||||
(res.data.find((item) => item.payEnum === 220000)?.amount ?? 0) -
|
||||
(res.data.find((item) => item.payEnum === 220500)?.amount ?? 0);
|
||||
}
|
||||
details.value = res.data.filter((item) => {
|
||||
details.value = res.data?.filter((item) => {
|
||||
return item.amount > 0;
|
||||
});
|
||||
}) || [];
|
||||
});
|
||||
paymentId.value = row.paymentId;
|
||||
patientInfo.value.patientId = row.patientId;
|
||||
|
||||
@@ -128,7 +128,7 @@ const getFeeTypeText = computed(() => {
|
||||
}
|
||||
// 如果只有一个选项,直接返回第一个选项的文本
|
||||
if (props.medfee_paymtd_code.length === 1) {
|
||||
return props.medfee_paymtd_code[0].label || '';
|
||||
return props.medfee_paymtd_code[0]?.label || '';
|
||||
}
|
||||
return '';
|
||||
});
|
||||
@@ -214,38 +214,38 @@ async function printReceipt(param) {
|
||||
{
|
||||
...param,
|
||||
// 基础支付类型
|
||||
YB_FUND_PAY: param.detail.find((t) => t.payEnum === 100000)?.amount ?? 0, // 基金支付总额
|
||||
SELF_PAY: param.detail.find((t) => t.payEnum === 200000)?.amount ?? 0, // 个人负担总金额
|
||||
OTHER_PAY: param.detail.find((t) => t.payEnum === 300000)?.amount ?? 0, // 其他(如医院负担金额)
|
||||
YB_FUND_PAY: param.detail?.find((t) => t.payEnum === 100000)?.amount ?? 0, // 基金支付总额
|
||||
SELF_PAY: param.detail?.find((t) => t.payEnum === 200000)?.amount ?? 0, // 个人负担总金额
|
||||
OTHER_PAY: param.detail?.find((t) => t.payEnum === 300000)?.amount ?? 0, // 其他(如医院负担金额)
|
||||
|
||||
// 基本医保统筹基金支出
|
||||
YB_TC_FUND_AMOUNT: param.detail.find((t) => t.payEnum === 110000)?.amount ?? 0, // 基本医保统筹基金支出
|
||||
YB_BC_FUND_AMOUNT: param.detail.find((t) => t.payEnum === 120000)?.amount ?? 0, // 补充医疗保险基金支出
|
||||
YB_JZ_FUND_AMOUNT: param.detail.find((t) => t.payEnum === 130000)?.amount ?? 0, // 医疗救助基金支出
|
||||
YB_OTHER_AMOUNT: param.detail.find((t) => t.payEnum === 140000)?.amount ?? 0, // 其他支出
|
||||
YB_TC_FUND_AMOUNT: param.detail?.find((t) => t.payEnum === 110000)?.amount ?? 0, // 基本医保统筹基金支出
|
||||
YB_BC_FUND_AMOUNT: param.detail?.find((t) => t.payEnum === 120000)?.amount ?? 0, // 补充医疗保险基金支出
|
||||
YB_JZ_FUND_AMOUNT: param.detail?.find((t) => t.payEnum === 130000)?.amount ?? 0, // 医疗救助基金支出
|
||||
YB_OTHER_AMOUNT: param.detail?.find((t) => t.payEnum === 140000)?.amount ?? 0, // 其他支出
|
||||
|
||||
// 职工基本医疗保险
|
||||
YB_TC_ZG_FUND_VALUE: param.detail.find((t) => t.payEnum === 110100)?.amount ?? 0, // 职工基本医疗保险
|
||||
YB_TC_JM_FUND_VALUE: param.detail.find((t) => t.payEnum === 110200)?.amount ?? 0, // 居民基本医疗保险
|
||||
YB_TC_ZG_FUND_VALUE: param.detail?.find((t) => t.payEnum === 110100)?.amount ?? 0, // 职工基本医疗保险
|
||||
YB_TC_JM_FUND_VALUE: param.detail?.find((t) => t.payEnum === 110200)?.amount ?? 0, // 居民基本医疗保险
|
||||
|
||||
// 补充医疗保险基金支出细分
|
||||
YB_BC_JM_DB_VALUE: param.detail.find((t) => t.payEnum === 120100)?.amount ?? 0, // 全体参保人的居民大病保险
|
||||
YB_BC_DE_BZ_VALUE: param.detail.find((t) => t.payEnum === 120200)?.amount ?? 0, // 大额医疗费用补助
|
||||
YB_BC_ZG_DE_BZ_VALUE: param.detail.find((t) => t.payEnum === 120300)?.amount ?? 0, // 企业职工大额医疗费用补助
|
||||
YB_BC_GWY_BZ_VALUE: param.detail.find((t) => t.payEnum === 120400)?.amount ?? 0, // 公务员医疗补助
|
||||
YB_BC_JM_DB_VALUE: param.detail?.find((t) => t.payEnum === 120100)?.amount ?? 0, // 全体参保人的居民大病保险
|
||||
YB_BC_DE_BZ_VALUE: param.detail?.find((t) => t.payEnum === 120200)?.amount ?? 0, // 大额医疗费用补助
|
||||
YB_BC_ZG_DE_BZ_VALUE: param.detail?.find((t) => t.payEnum === 120300)?.amount ?? 0, // 企业职工大额医疗费用补助
|
||||
YB_BC_GWY_BZ_VALUE: param.detail?.find((t) => t.payEnum === 120400)?.amount ?? 0, // 公务员医疗补助
|
||||
|
||||
// 其他支出细分
|
||||
OTHER_PAY_DD_FUND_VALUE: param.detail.find((t) => t.payEnum === 300001)?.amount ?? 0, // 兜底基金支出
|
||||
OTHER_PAY_YW_SH_FUND_VALUE: param.detail.find((t) => t.payEnum === 300002)?.amount ?? 0, // 意外伤害基金支出
|
||||
OTHER_PAY_LX_YL_FUND_VALUE: param.detail.find((t) => t.payEnum === 300003)?.amount ?? 0, // 离休人员医疗保障金支出
|
||||
OTHER_PAY_LX_YH_FUND_VALUE: param.detail.find((t) => t.payEnum === 300004)?.amount ?? 0, // 离休人员优惠金支出
|
||||
OTHER_PAY_CZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300005)?.amount ?? 0, // 财政基金支出
|
||||
OTHER_PAY_CZ_YZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300006)?.amount ?? 0, // 财政预支支出
|
||||
OTHER_PAY_ZG_DB_FUND_VALUE: param.detail.find((t) => t.payEnum === 300007)?.amount ?? 0, // 职工大病基金支出
|
||||
OTHER_PAY_EY_FUND_VALUE: param.detail.find((t) => t.payEnum === 300008)?.amount ?? 0, // 二乙基金支出
|
||||
OTHER_PAY_QX_JZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300009)?.amount ?? 0, // 倾斜救助支出
|
||||
OTHER_PAY_YL_JZ_FUND_VALUE: param.detail.find((t) => t.payEnum === 300010)?.amount ?? 0, // 医疗救助再救助基金
|
||||
HOSP_PART_AMT: param.detail.find((t) => t.payEnum === 300011)?.amount ?? 0, // 医院负担金额
|
||||
OTHER_PAY_DD_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300001)?.amount ?? 0, // 兜底基金支出
|
||||
OTHER_PAY_YW_SH_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300002)?.amount ?? 0, // 意外伤害基金支出
|
||||
OTHER_PAY_LX_YL_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300003)?.amount ?? 0, // 离休人员医疗保障金支出
|
||||
OTHER_PAY_LX_YH_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300004)?.amount ?? 0, // 离休人员优惠金支出
|
||||
OTHER_PAY_CZ_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300005)?.amount ?? 0, // 财政基金支出
|
||||
OTHER_PAY_CZ_YZ_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300006)?.amount ?? 0, // 财政预支支出
|
||||
OTHER_PAY_ZG_DB_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300007)?.amount ?? 0, // 职工大病基金支出
|
||||
OTHER_PAY_EY_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300008)?.amount ?? 0, // 二乙基金支出
|
||||
OTHER_PAY_QX_JZ_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300009)?.amount ?? 0, // 倾斜救助支出
|
||||
OTHER_PAY_YL_JZ_FUND_VALUE: param.detail?.find((t) => t.payEnum === 300010)?.amount ?? 0, // 医疗救助再救助基金
|
||||
HOSP_PART_AMT: param.detail?.find((t) => t.payEnum === 300011)?.amount ?? 0, // 医院负担金额
|
||||
|
||||
// 医保结算返回值 - 修复运算符优先级问题,添加括号确保正确拼接'元'
|
||||
FULAMT_OWNPAY_AMT: (param.detail?.find((t) => t.payEnum === 1)?.amount ?? 0) + '元', // 全自费金额
|
||||
@@ -347,11 +347,11 @@ async function printReceipt(param) {
|
||||
: '', // 保健预支基金
|
||||
//微信刷卡支付
|
||||
SELF_CASH_VX_VALUE: (() => {
|
||||
// const cashValue = param.detail.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
const vxValue = param.detail.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
const unionValue = param.detail.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
const aliValue = param.detail.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return vxValue + unionValue + aliValue + '元';
|
||||
// const cashValue = param.detail?.find((t) => t.payEnum === 220400)?.amount ?? 0;
|
||||
const vxValue = param.detail?.find((t) => t.payEnum === 220100)?.amount ?? 0;
|
||||
const unionValue = param.detail?.find((t) => t.payEnum === 220300)?.amount ?? 0;
|
||||
const aliValue = param.detail?.find((t) => t.payEnum === 220200)?.amount ?? 0;
|
||||
return (Number(vxValue) + Number(unionValue) + Number(aliValue)).toFixed(2) + '元';
|
||||
})(),
|
||||
|
||||
// 患者信息
|
||||
|
||||
@@ -196,7 +196,7 @@ watch(
|
||||
// 计算应退金额并更新表单数据
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
const sum = res.data
|
||||
.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce((total, item) => total + (Number(item.amount) || 0), 0);
|
||||
if (sum > 0) {
|
||||
formData.totalAmount = sum;
|
||||
@@ -313,9 +313,9 @@ const displayAmount = computed(() => {
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
const sum = preCancelData.value
|
||||
.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce((sum, item) => sum + (Number(item.amount) || 0), 0);
|
||||
return sum.toFixed(2);
|
||||
return sum?.toFixed(2) ?? '0.00';
|
||||
});
|
||||
|
||||
const returnedAmount = computed(() => {
|
||||
@@ -334,7 +334,7 @@ const calculatedTotalAmount = computed(() => {
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
// 应退金额 = (amount - returnAmount) 的总和,即剩余应退金额
|
||||
const sum = preCancelData.value
|
||||
.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce(
|
||||
(total, item) => total + ((Number(item.amount) || 0) - (Number(item.returnAmount) || 0)),
|
||||
0
|
||||
@@ -348,7 +348,7 @@ const calculatedReturnAmount = computed(() => {
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
const sum = preCancelData.value
|
||||
.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
?.filter((item) => targetPayEnums.includes(item.payEnum))
|
||||
.reduce((total, item) => total + (Number(item.returnAmount) || 0), 0);
|
||||
return sum || 0;
|
||||
});
|
||||
@@ -359,12 +359,12 @@ const refundMethodsFromApi = computed(() => {
|
||||
return [];
|
||||
}
|
||||
const targetPayEnums = [220500, 220400, 220100, 220200, 220300];
|
||||
return preCancelData.value.filter(
|
||||
return preCancelData.value?.filter(
|
||||
(item) =>
|
||||
targetPayEnums.includes(item.payEnum) &&
|
||||
item.payEnum_dictText &&
|
||||
item.payEnum_dictText.trim() !== ''
|
||||
);
|
||||
) || [];
|
||||
});
|
||||
|
||||
// 根据 payEnum 获取支付方式标签
|
||||
@@ -380,7 +380,7 @@ const getPayMethodLabel = (payEnum) => {
|
||||
|
||||
// 计算所有退费方式的总和
|
||||
const totalRefundAmount = computed(() => {
|
||||
return refundMethodsFromApi.value.reduce((sum, item) => sum + (Number(item.amount) || 0), 0);
|
||||
return refundMethodsFromApi.value?.reduce((sum, item) => sum + (Number(item.amount) || 0), 0) ?? 0;
|
||||
});
|
||||
|
||||
// 计算剩余可输入金额(应退金额 - 已输入的退费金额总和)
|
||||
|
||||
@@ -151,10 +151,6 @@
|
||||
<span class="label">患者姓名:</span>
|
||||
<span class="value">{{ form.name || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">门诊号:</span>
|
||||
<span class="value">{{ form.serialNo || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">就诊卡号:</span>
|
||||
<span class="value">{{ form.cardNo || '-' }}</span>
|
||||
@@ -233,6 +229,12 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 流水号显示在左下角 -->
|
||||
<div class="serial-number-bottom-left">
|
||||
<span class="serial-label">流水号:</span>
|
||||
<span class="serial-value">{{ form.serialNo || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="print-footer">
|
||||
<div class="reminder">温馨提示: 请妥善保管此凭条,就诊时请携带。</div>
|
||||
</div>
|
||||
@@ -545,29 +547,21 @@ function formatDateTime(date) {
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
// 计算流水号(与 fillForm 中的逻辑一致)
|
||||
// 计算流水号:直接使用挂号记录表的主键ID(encounterId)
|
||||
function calculateSerialNo(row) {
|
||||
if (!row) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
// 优先使用已有的 serialNo(如果存在)
|
||||
if (row.serialNo) {
|
||||
return row.serialNo;
|
||||
|
||||
// 直接使用主键ID作为流水号
|
||||
if (row.encounterId != null && row.encounterId !== undefined) {
|
||||
return String(row.encounterId);
|
||||
} else if (row.id != null && row.id !== undefined) {
|
||||
// 兼容其他可能的ID字段名
|
||||
return String(row.id);
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
|
||||
// 使用 encounterId 的后3位计算流水号
|
||||
if (row.encounterId) {
|
||||
const idStr = String(row.encounterId);
|
||||
const lastThree = idStr.slice(-3);
|
||||
const num = parseInt(lastThree) || 0;
|
||||
return String((num % 999) + 1).padStart(3, '0');
|
||||
}
|
||||
|
||||
// 如果 encounterId 为空,生成一个001-999的序列号
|
||||
const timestamp = Date.now();
|
||||
const serial = (timestamp % 999) + 1;
|
||||
return String(serial).padStart(3, '0');
|
||||
}
|
||||
|
||||
// 提交补打挂号
|
||||
@@ -835,6 +829,26 @@ function handleBrowserPrint() {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
.serial-number-bottom-left {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.serial-number-bottom-left .serial-label {
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.serial-number-bottom-left .serial-value {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.print-content {
|
||||
position: relative;
|
||||
min-height: 500px;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
.print-footer {
|
||||
margin-top: 20px;
|
||||
font-size: 12px;
|
||||
@@ -1052,6 +1066,31 @@ async function handleConfirmSelect() {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* 流水号显示在左下角,加粗 */
|
||||
.serial-number-bottom-left {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.serial-number-bottom-left .serial-label {
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.serial-number-bottom-left .serial-value {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.print-content {
|
||||
position: relative;
|
||||
min-height: 500px;
|
||||
padding-bottom: 60px; /* 为左下角流水号留出空间 */
|
||||
}
|
||||
|
||||
.print-footer {
|
||||
margin-top: 20px;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -801,10 +801,10 @@ const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
/** 根据contractNo获取费用性质名称 */
|
||||
function getFeeTypeName(contractNo) {
|
||||
if (!contractNo || !medfee_paymtd_code || !Array.isArray(medfee_paymtd_code)) {
|
||||
if (!contractNo || !medfee_paymtd_code?.value || !Array.isArray(medfee_paymtd_code.value)) {
|
||||
return '';
|
||||
}
|
||||
const dictItem = medfee_paymtd_code.find(item => item.value === contractNo);
|
||||
const dictItem = medfee_paymtd_code.value.find(item => item.value === contractNo);
|
||||
return dictItem ? dictItem.label : '';
|
||||
}
|
||||
|
||||
@@ -1185,7 +1185,7 @@ function filterDoctorsByHealthcare() {
|
||||
}
|
||||
|
||||
// 获取选中的挂号类型信息
|
||||
const selectedHealthcare = healthcareList.value.find(
|
||||
const selectedHealthcare = healthcareList.value?.find(
|
||||
(healthcare) => healthcare.id === form.value.serviceTypeId
|
||||
);
|
||||
|
||||
@@ -1349,7 +1349,7 @@ function handleAdd() {
|
||||
genderEnum_enumText: form.value.genderEnum_enumText,
|
||||
age: form.value.age,
|
||||
contractName: form.value.contractNo
|
||||
? contractList.value.find((item) => item.busNo === form.value.contractNo)?.contractName ||
|
||||
? contractList.value?.find((item) => item.busNo === form.value.contractNo)?.contractName ||
|
||||
'自费'
|
||||
: '自费',
|
||||
idCard: form.value.idCard,
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"top": 57,
|
||||
"height": 13.5,
|
||||
"width": 145.5,
|
||||
"title": "机构名称:长春市朝阳区中医院",
|
||||
"title": "机构名称:{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 9,
|
||||
|
||||
@@ -356,7 +356,7 @@ async function print() {
|
||||
...reportValue.value, // 将 reportValue.value 中的所有属性展开到 result 中
|
||||
nickName: userStore.nickName,
|
||||
orgName: userStore.orgName,
|
||||
fixmedinsName: '长春市朝阳区中医院医院',
|
||||
fixmedinsName: userStore.hospitalName,
|
||||
queryTime: queryTime.value[0] + '~' + queryTime.value[1],
|
||||
zfAmount: new Decimal(reportValue.value.zhSum || 0).add(reportValue.value.fundSum || 0),
|
||||
feeAmount: new Decimal(reportValue.value.DIAGNOSTIC_FEE || 0)
|
||||
|
||||
@@ -514,7 +514,9 @@ async function print() {
|
||||
};
|
||||
console.log(result, '==result.data==');
|
||||
|
||||
const printElements = templateJson;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(templateJson).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
const printerList = hiprintTemplate.getPrinterList();
|
||||
console.log(hiprintTemplate, '打印机列表');
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"top": 22.5,
|
||||
"height": 12,
|
||||
"width": 420,
|
||||
"title": "长春市朝阳区中医院",
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 13.5,
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"top": 16.5,
|
||||
"height": 22.5,
|
||||
"width": 120,
|
||||
"title": "长春市朝阳区中医院医院",
|
||||
"title": "{{HOSPITAL_NAME}}医院",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontFamily": "Microsoft YaHei",
|
||||
|
||||
@@ -660,7 +660,9 @@ function printPrescription() {
|
||||
// 将对象转换为 JSON 字符串
|
||||
console.log(result, 'result');
|
||||
// 模板对象获取
|
||||
const printElements = prescriptionTemplate;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(prescriptionTemplate).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
hiprintTemplate.print2(result, {
|
||||
title: '打印标题',
|
||||
@@ -695,7 +697,9 @@ function printDisposal() {
|
||||
.join(',');
|
||||
advicePrint({ requestIds: requestIds }).then((res) => {
|
||||
const result = res.data;
|
||||
const printElements = disposalTemplate;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(disposalTemplate).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
hiprintTemplate.print2(result, {
|
||||
height: 210,
|
||||
@@ -735,7 +739,9 @@ function printBloodBarcode() {
|
||||
} else {
|
||||
printBloodCode({ requestId: selectedRows[0].requestId }).then((res) => {
|
||||
const result = res.data;
|
||||
const printElements = bloodTemplate;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(bloodTemplate).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
hiprintTemplate.print2(result, {
|
||||
height: 210,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<span>CF0000000001</span>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<h2>长春市朝阳区中医院医院</h2>
|
||||
<h2>{{ userStore.hospitalName }}</h2>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<h3>处方单</h3>
|
||||
@@ -130,7 +130,9 @@
|
||||
|
||||
<script setup name="historicalPrescriptionDetail">
|
||||
import {getPrescriptionDetail} from './api';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -197,7 +197,10 @@ watch(
|
||||
|
||||
// 直接更新查询参数
|
||||
queryParams.value.searchKey = newValue.searchKey || '';
|
||||
|
||||
|
||||
// 更新categoryCode
|
||||
queryParams.value.categoryCode = newValue.categoryCode || '';
|
||||
|
||||
// 处理类型筛选
|
||||
if (newValue.adviceType !== undefined && newValue.adviceType !== null && newValue.adviceType !== '') {
|
||||
// 单个类型
|
||||
@@ -215,8 +218,18 @@ getList();
|
||||
// 从priceList列表中获取价格
|
||||
function getPriceFromInventory(row) {
|
||||
if (row.priceList && row.priceList.length > 0) {
|
||||
const price = row.priceList[0].price || 0;
|
||||
return Number(price).toFixed(2) + ' 元';
|
||||
const price = row.priceList[0].price;
|
||||
// 检查价格是否为有效数字
|
||||
if (price !== undefined && price !== null && !isNaN(price) && isFinite(price)) {
|
||||
return Number(price).toFixed(2) + ' 元';
|
||||
}
|
||||
// 如果价格无效,尝试从其他可能的字段获取价格
|
||||
if (row.totalPrice !== undefined && row.totalPrice !== null && !isNaN(row.totalPrice) && isFinite(row.totalPrice)) {
|
||||
return Number(row.totalPrice).toFixed(2) + ' 元';
|
||||
}
|
||||
if (row.price !== undefined && row.price !== null && !isNaN(row.price) && isFinite(row.price)) {
|
||||
return Number(row.price).toFixed(2) + ' 元';
|
||||
}
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@
|
||||
<div style="display:flex;flex-direction:column;align-items:center;gap:5px;">
|
||||
<el-checkbox
|
||||
label="主诊断"
|
||||
:trueLabel="1"
|
||||
:falseLabel="0"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
v-model="scope.row.maindiseFlag"
|
||||
border
|
||||
size="small"
|
||||
@@ -409,10 +409,10 @@ function getTree() {
|
||||
function handleAddDiagnosis() {
|
||||
proxy.$refs.formRef.validate((valid) => {
|
||||
if (valid) {
|
||||
// if (!allowAdd.value) {
|
||||
// proxy.$modal.msgWarning('请先填写病历');
|
||||
// return;
|
||||
// }
|
||||
const maxSortNo = form.value.diagnosisList.length > 0
|
||||
? Math.max(...form.value.diagnosisList.map(item => item.diagSrtNo || 0))
|
||||
: 0;
|
||||
|
||||
form.value.diagnosisList.push({
|
||||
showPopover: false,
|
||||
name: undefined,
|
||||
@@ -491,6 +491,7 @@ function handleSaveDiagnosis() {
|
||||
return false;
|
||||
} else if (!form.value.diagnosisList.some((diagnosis) => diagnosis.maindiseFlag === 1)) {
|
||||
proxy.$modal.msgWarning('至少添加一条主诊断');
|
||||
return false;
|
||||
} else {
|
||||
// 保存前按排序号排序
|
||||
form.value.diagnosisList.sort((a, b) => (a.diagSrtNo || 0) - (b.diagSrtNo || 0));
|
||||
|
||||
@@ -38,7 +38,7 @@ watch(
|
||||
queryParams.value.searchKey = newValue;
|
||||
getList();
|
||||
},
|
||||
{ immdiate: true }
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
getList();
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--检验信息-->
|
||||
<el-table
|
||||
ref="inspectionTableRef"
|
||||
:data="inspectionList"
|
||||
@@ -79,7 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 下方:申请单和检验项目选择器 -->
|
||||
<!-- 下方:申请单和检验项目选择器 -->
|
||||
<div style="display: flex; gap: 20px">
|
||||
<!-- 左侧:申请单和检验信息 -->
|
||||
<div style="width: 55%">
|
||||
@@ -88,18 +88,18 @@
|
||||
<div class="application-form" style="padding: 20px; height: 700px; overflow-y: auto; border: 1px solid #e4e7ed; border-radius: 4px; margin: 10px;">
|
||||
<div style="margin-bottom: 20px">
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请单号</label>
|
||||
<el-input v-model="formData.applicationNo" disabled size="small" />
|
||||
<el-input v-model="formData.applicationNo" readonly size="small" />
|
||||
</div>
|
||||
|
||||
<!-- 患者信息行 -->
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">姓名</label>
|
||||
<el-input v-model="formData.patientName" disabled size="small" />
|
||||
<el-input v-model="formData.patientName" readonly size="small" />
|
||||
</div>
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">就诊卡号</label>
|
||||
<el-input v-model="formData.cardNo" disabled size="small" />
|
||||
<el-input v-model="formData.identifierNo" readonly size="small" />
|
||||
</div>
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">费用性质</label>
|
||||
@@ -115,6 +115,7 @@
|
||||
|
||||
<!-- 申请信息行 -->
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||||
<!--申请日期-->
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请日期</label>
|
||||
<el-date-picker
|
||||
@@ -127,6 +128,7 @@
|
||||
style="width: 100%"
|
||||
/>
|
||||
</div>
|
||||
<!--申请科室-->
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请科室</label>
|
||||
<el-select v-model="formData.departmentName" placeholder="请选择申请科室" size="small" style="width: 100%" disabled>
|
||||
@@ -135,9 +137,11 @@
|
||||
<el-option label="儿科" value="pediatrics" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!--申请医生-->
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">申请医生</label>
|
||||
<el-select v-model="formData.doctorName" placeholder="请选择申请医生" size="small" style="width: 100%" disabled>
|
||||
<el-select v-model="formData.doctorName" placeholder="请选择申请医生" size="small" style="width: 100%">
|
||||
<el-option label="张医生" value="doctor_zhang" />
|
||||
<el-option label="李医生" value="doctor_li" />
|
||||
<el-option label="王医生" value="doctor_wang" />
|
||||
@@ -164,7 +168,7 @@
|
||||
<div v-if="validationErrors.executeDepartment" class="error-message">请选择执行科室</div>
|
||||
</div>
|
||||
|
||||
<!-- 诊断相关字段 -->
|
||||
<!-- 诊断描述 -->
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||||
<div :class="{ 'form-item-error': validationErrors.diagnosisDesc }">
|
||||
<label style="display: block; margin-bottom: 5px; font-weight: bold">诊断描述 <span style="color: #f56c6c">*</span></label>
|
||||
@@ -248,7 +252,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="检验信息" name="inspectionInfo">
|
||||
<div style="padding: 20px; height: 700px; overflow-y: auto; border: 1px solid #e4e7ed; border-radius: 4px; margin: 10px;">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px">
|
||||
@@ -458,7 +461,7 @@ const formData = reactive({
|
||||
applicationId: null,
|
||||
applicationNo: '202511210001',
|
||||
patientName: '',
|
||||
cardNo: '',
|
||||
identifierNo: '',
|
||||
feeType: 'self',
|
||||
applicationDate: new Date(),
|
||||
departmentName: '',
|
||||
@@ -579,11 +582,11 @@ const getFilteredItems = (categoryKey) => {
|
||||
|
||||
// 初始化数据
|
||||
function initData() {
|
||||
console.log('检验组件初始化,patientInfo:', props.patientInfo)
|
||||
// console.log('检验组件初始化,patientInfo:', props.patientInfo)
|
||||
if (props.patientInfo) {
|
||||
queryParams.encounterId = props.patientInfo.encounterId
|
||||
formData.patientName = props.patientInfo.patientName || ''
|
||||
formData.cardNo = props.patientInfo.cardNo || ''
|
||||
formData.identifierNo = props.patientInfo.identifierNo || ''
|
||||
formData.departmentName = props.patientInfo.departmentName || ''
|
||||
formData.doctorName = props.patientInfo.doctorName || ''
|
||||
}
|
||||
@@ -597,26 +600,26 @@ function initData() {
|
||||
function getInspectionList() {
|
||||
// 如果没有encounterId,不调用接口
|
||||
if (!queryParams.encounterId) {
|
||||
console.warn('【检验】encounterId为空,不调用接口')
|
||||
// console.warn('【检验】encounterId为空,不调用接口')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
|
||||
// 调用真实的API,只传递 encounterId 参数
|
||||
console.log('【检验】调用API,encounterId:', queryParams.encounterId)
|
||||
// console.log('【检验】调用API,encounterId:', queryParams.encounterId)
|
||||
getInspectionApplicationList({ encounterId: queryParams.encounterId }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
inspectionList.value = res.data || []
|
||||
total.value = res.data?.length || 0
|
||||
console.log('【检验】获取数据成功,数量:', inspectionList.value.length)
|
||||
// console.log('【检验】获取数据成功,数量:', inspectionList.value.length)
|
||||
} else {
|
||||
inspectionList.value = []
|
||||
total.value = 0
|
||||
ElMessage.error('获取检验申请单列表失败')
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('获取检验申请单列表异常:', error)
|
||||
// console.error('获取检验申请单列表异常:', error)
|
||||
inspectionList.value = []
|
||||
total.value = 0
|
||||
ElMessage.error('获取检验申请单列表异常')
|
||||
@@ -627,7 +630,7 @@ function getInspectionList() {
|
||||
|
||||
// 新增申请单
|
||||
function handleNewApplication() {
|
||||
console.log('点击新增按钮')
|
||||
// console.log('点击新增按钮')
|
||||
resetForm()
|
||||
// 生成申请单号
|
||||
formData.applicationNo = generateApplicationNo()
|
||||
@@ -737,7 +740,7 @@ function handleSave() {
|
||||
totalAmount: selectedInspectionItems.value.reduce((sum, item) => sum + item.price + (item.serviceFee || 0), 0)
|
||||
}
|
||||
|
||||
console.log('保存检验申请单数据:', saveData)
|
||||
// console.log('保存检验申请单数据:', saveData)
|
||||
|
||||
// 调用真实的API保存
|
||||
saveInspectionApplication(saveData).then((res) => {
|
||||
@@ -751,7 +754,7 @@ function handleSave() {
|
||||
ElMessage.error(res.message || '保存失败')
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('保存检验申请单异常:', error)
|
||||
// console.error('保存检验申请单异常:', error)
|
||||
ElMessage.error('保存异常')
|
||||
})
|
||||
}
|
||||
@@ -761,7 +764,7 @@ function handleFormSave() {
|
||||
formRef.value?.validate((valid) => {
|
||||
if (valid) {
|
||||
formData.inspectionItems = selectedInspectionItems.value.map(item => item.id)
|
||||
console.log('保存检验申请单表单数据:', formData)
|
||||
// console.log('保存检验申请单表单数据:', formData)
|
||||
ElMessage.success('保存成功')
|
||||
showForm.value = false
|
||||
getInspectionList()
|
||||
@@ -771,7 +774,7 @@ function handleFormSave() {
|
||||
|
||||
// 查看详情
|
||||
function handleView(row) {
|
||||
console.log('点击查看按钮,数据:', row)
|
||||
// console.log('点击查看按钮,数据:', row)
|
||||
// 加载表单数据
|
||||
Object.assign(formData, row)
|
||||
|
||||
@@ -811,7 +814,7 @@ function switchCategory(category) {
|
||||
// 处理搜索
|
||||
function handleSearch() {
|
||||
// 搜索逻辑已在getFilteredItems中实现,这里可以添加额外的搜索逻辑
|
||||
console.log('搜索关键词:', searchKeyword.value)
|
||||
// console.log('搜索关键词:', searchKeyword.value)
|
||||
}
|
||||
|
||||
// 处理项目项点击(排除勾选框点击)
|
||||
@@ -866,7 +869,7 @@ function handleSelectionChange(selection) {
|
||||
|
||||
// 打印申请单
|
||||
function handlePrint(row) {
|
||||
console.log('打印申请单:', row)
|
||||
// console.log('打印申请单:', row)
|
||||
|
||||
// 切换到申请单TAB
|
||||
leftActiveTab.value = 'application'
|
||||
@@ -949,7 +952,7 @@ function handleDelete(row) {
|
||||
confirmButtonClass: 'el-button--danger'
|
||||
}
|
||||
).then(() => {
|
||||
console.log('删除申请单:', row)
|
||||
// console.log('删除申请单:', row)
|
||||
// 调用真实的API删除
|
||||
deleteInspectionApplication(row.applicationId).then((res) => {
|
||||
if (res.code === 200) {
|
||||
@@ -960,7 +963,7 @@ function handleDelete(row) {
|
||||
ElMessage.error(res.message || '删除失败')
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('删除检验申请单异常:', error)
|
||||
// console.error('删除检验申请单异常:', error)
|
||||
ElMessage.error('删除异常')
|
||||
})
|
||||
}).catch(() => {
|
||||
@@ -987,10 +990,11 @@ watch(() => props.activeTab, (newVal) => {
|
||||
|
||||
// 监听patientInfo变化,确保encounterId及时更新
|
||||
watch(() => props.patientInfo, (newVal) => {
|
||||
console.log('【检验】patientInfo变化:', newVal)
|
||||
// console.log('【检验】patientInfo变化:', newVal)
|
||||
console.log('【检验】接收到的完整patientInfo:', JSON.stringify(newVal, null, 2))
|
||||
if (newVal && newVal.encounterId) {
|
||||
queryParams.encounterId = newVal.encounterId
|
||||
console.log('【检验】更新encounterId:', queryParams.encounterId)
|
||||
// console.log('【检验】更新encounterId:', queryParams.encounterId)
|
||||
}
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<span>{{ item.prescriptionNo }}</span>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<h2>长春市朝阳区中医院医院</h2>
|
||||
<h2>{{ userStore.hospitalName }}</h2>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<h3>处方单</h3>
|
||||
@@ -144,6 +144,9 @@
|
||||
import {formatDateStr} from '@/utils/index';
|
||||
//高精度库
|
||||
import Decimal from 'decimal.js';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const props = defineProps({
|
||||
open: {
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
' ' +
|
||||
scope.row.volume +
|
||||
' [' +
|
||||
Number(scope.row.unitPrice).toFixed(2) +
|
||||
(scope.row.unitPrice !== undefined && scope.row.unitPrice !== null && !isNaN(scope.row.unitPrice) && isFinite(scope.row.unitPrice) ? Number(scope.row.unitPrice).toFixed(2) : '-') +
|
||||
' 元' +
|
||||
'/' +
|
||||
scope.row.unitCode_dictText +
|
||||
@@ -145,7 +145,7 @@
|
||||
<span class="medicine-info"> 注射药品:{{ scope.row.injectFlag_enumText }} </span>
|
||||
<span class="total-amount">
|
||||
总金额:{{
|
||||
scope.row.totalPrice
|
||||
(scope.row.totalPrice !== undefined && scope.row.totalPrice !== null && !isNaN(scope.row.totalPrice) && isFinite(scope.row.totalPrice))
|
||||
? Number(scope.row.totalPrice).toFixed(2) + ' 元'
|
||||
: '0.00 元'
|
||||
}}
|
||||
@@ -631,7 +631,7 @@
|
||||
" " +
|
||||
scope.row.volume +
|
||||
" [" +
|
||||
Number(scope.row.unitPrice).toFixed(2) +
|
||||
(scope.row.unitPrice !== undefined && scope.row.unitPrice !== null && !isNaN(scope.row.unitPrice) && isFinite(scope.row.unitPrice) ? Number(scope.row.unitPrice).toFixed(2) : '-') +
|
||||
" 元" +
|
||||
"/" +
|
||||
scope.row.unitCode_dictText +
|
||||
@@ -687,7 +687,7 @@
|
||||
</el-form-item>
|
||||
<span class="total-amount">
|
||||
总金额:{{
|
||||
scope.row.totalPrice
|
||||
(scope.row.totalPrice !== undefined && scope.row.totalPrice !== null && !isNaN(scope.row.totalPrice) && isFinite(scope.row.totalPrice))
|
||||
? Number(scope.row.totalPrice).toFixed(2) + ' 元'
|
||||
: '0.00 元'
|
||||
}}
|
||||
@@ -702,7 +702,7 @@
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{ scope.row.adviceName }}
|
||||
{{
|
||||
scope.row.unitPrice
|
||||
(scope.row.unitPrice !== undefined && scope.row.unitPrice !== null && !isNaN(scope.row.unitPrice) && isFinite(scope.row.unitPrice))
|
||||
? Number(scope.row.unitPrice).toFixed(2) + '/次'
|
||||
: '-' + '元'
|
||||
}}
|
||||
@@ -748,7 +748,7 @@
|
||||
<span class="total-amount">
|
||||
总金额:
|
||||
{{
|
||||
scope.row.totalPrice
|
||||
(scope.row.totalPrice !== undefined && scope.row.totalPrice !== null && !isNaN(scope.row.totalPrice) && isFinite(scope.row.totalPrice))
|
||||
? Number(scope.row.totalPrice).toFixed(2) + ' 元'
|
||||
: '0.00 元'
|
||||
}}
|
||||
@@ -782,6 +782,19 @@
|
||||
// 当医嘱类型改变时,清空当前选择的项目名称,因为不同类型项目的数据结构可能不兼容
|
||||
prescriptionList[scope.$index].adviceName = undefined;
|
||||
adviceQueryParams.adviceType = value;
|
||||
|
||||
// 根据选择的类型设置categoryCode,用于药品分类筛选
|
||||
if (value == 1) { // 西药
|
||||
adviceQueryParams.categoryCode = '2';
|
||||
} else if (value == 2) { // 中成药
|
||||
adviceQueryParams.categoryCode = '1';
|
||||
} else if (value == 3) { // 耗材
|
||||
adviceQueryParams.categoryCode = ''; // 耗材不需要categoryCode筛选
|
||||
} else if (value == 4) { // 诊疗
|
||||
adviceQueryParams.categoryCode = ''; // 诊疗不需要categoryCode筛选
|
||||
} else {
|
||||
adviceQueryParams.categoryCode = ''; // 全部类型
|
||||
}
|
||||
}
|
||||
"
|
||||
@clear="
|
||||
@@ -907,7 +920,7 @@
|
||||
<el-table-column label="总金额" align="right" prop="" header-align="center" width="100">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isEdit" style="text-align: right">
|
||||
{{ scope.row.totalPrice ? Number(scope.row.totalPrice).toFixed(2) + ' 元' : '-' }}
|
||||
{{ (scope.row.totalPrice !== undefined && scope.row.totalPrice !== null && !isNaN(scope.row.totalPrice) && isFinite(scope.row.totalPrice)) ? Number(scope.row.totalPrice).toFixed(2) + ' 元' : '-' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -2472,8 +2485,8 @@ function setValue(row) {
|
||||
? (typeof row.skinTestFlag === 'number' ? row.skinTestFlag : (row.skinTestFlag ? 1 : 0))
|
||||
: 0;
|
||||
|
||||
prescriptionList.value[targetIndex] = {
|
||||
...prescriptionList.value[targetIndex],
|
||||
prescriptionList.value[rowIndex.value] = {
|
||||
...prescriptionList.value[rowIndex.value],
|
||||
...JSON.parse(JSON.stringify(row)),
|
||||
// 确保adviceType为数字类型,避免类型不匹配导致的显示问题
|
||||
adviceType: Number(row.adviceType),
|
||||
@@ -2852,12 +2865,25 @@ function getGroupMarkers() {
|
||||
function calculateTotalPrice(row, index) {
|
||||
nextTick(() => {
|
||||
if (row.adviceType == 3) {
|
||||
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
|
||||
// 检查价格是否为有效数字
|
||||
if (row.unitPrice !== undefined && row.unitPrice !== null && !isNaN(row.unitPrice) && isFinite(row.unitPrice)) {
|
||||
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
|
||||
} else {
|
||||
row.totalPrice = '0.000000'; // 或者设置为 0
|
||||
}
|
||||
} else {
|
||||
if (row.unitCode == row.minUnitCode) {
|
||||
row.totalPrice = (row.minUnitPrice * row.quantity).toFixed(6);
|
||||
if (row.minUnitPrice !== undefined && row.minUnitPrice !== null && !isNaN(row.minUnitPrice) && isFinite(row.minUnitPrice)) {
|
||||
row.totalPrice = (row.minUnitPrice * row.quantity).toFixed(6);
|
||||
} else {
|
||||
row.totalPrice = '0.000000';
|
||||
}
|
||||
} else {
|
||||
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
|
||||
if (row.unitPrice !== undefined && row.unitPrice !== null && !isNaN(row.unitPrice) && isFinite(row.unitPrice)) {
|
||||
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
|
||||
} else {
|
||||
row.totalPrice = '0.000000';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -775,6 +775,19 @@ function deletePrescription(prescription) {
|
||||
|
||||
const index = tcmPrescriptionList.value.findIndex((p) => p.id === prescription.id);
|
||||
if (index !== -1) {
|
||||
const prescriptionData = tcmPrescriptionList.value[index];
|
||||
|
||||
if (prescriptionData.prescriptionList && prescriptionData.prescriptionList.length > 0) {
|
||||
proxy.$modal.msgWarning('该处方单还有药品,请先删除所有药品后再删除处方单');
|
||||
return;
|
||||
}
|
||||
|
||||
const hasChargedItems = prescriptionData.prescriptionList && prescriptionData.prescriptionList.some(item => item.statusEnum === 2);
|
||||
if (hasChargedItems) {
|
||||
proxy.$modal.msgWarning('该处方单已收费,不能删除');
|
||||
return;
|
||||
}
|
||||
|
||||
tcmPrescriptionList.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,10 @@ getPatientList();
|
||||
function getPatientList() {
|
||||
queryParams.value.statusEnum = 2;
|
||||
getList(queryParams.value).then((res) => {
|
||||
// console.log('API返回的完整数据:', res); // 添加这行来查看完整返回
|
||||
// console.log('API返回的数据记录:', res.data.records); // 查看具体数据记录
|
||||
patientList.value = res.data.records.map((item) => {
|
||||
// console.log('处理的单个患者数据:', item); // 查看处理的单个患者数据
|
||||
return {
|
||||
...item,
|
||||
active: currentEncounterId.value ? item.encounterId == currentEncounterId.value : false,
|
||||
@@ -431,7 +434,7 @@ function handleClick(tab) {
|
||||
// 查看本次就诊处方单(从医嘱Tab页获取已开立的处方单信息)
|
||||
function getEnPrescription(encounterId) {
|
||||
getEnPrescriptionInfo({ encounterId: encounterId }).then((res) => {
|
||||
console.log('处方单 res', res);
|
||||
// console.log('处方单 res', res);
|
||||
let dataArr = res.data.records || [];
|
||||
if (dataArr.length <= 0) {
|
||||
ElMessage({
|
||||
@@ -461,6 +464,7 @@ function handleCardClick(item, index) {
|
||||
patient.active = patient.encounterId === item.encounterId;
|
||||
});
|
||||
patientInfo.value = item;
|
||||
// console.log('patientInfo.value.cardNo:', patientInfo.value.cardNo)
|
||||
// 将患者信息保存到store中,供hospitalizationEmr组件使用
|
||||
updatePatientInfo(item);
|
||||
activeTab.value = 'hospitalizationEmr';
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"top": 16.5,
|
||||
"height": 22.5,
|
||||
"width": 120,
|
||||
"title": "长春市朝阳区中医院医院",
|
||||
"title": "{{HOSPITAL_NAME}}医院",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontFamily": "Microsoft YaHei",
|
||||
|
||||
@@ -291,10 +291,13 @@ import {advicePrint, getAdjustPriceSwitchState, lotNumberMatch} from '@/api/publ
|
||||
import {debounce} from 'lodash-es';
|
||||
import TraceNoDialog from '@/components/OpenHis/TraceNoDialog/index.vue';
|
||||
import {hiprint} from 'vue-plugin-hiprint';
|
||||
// import templateJson from './components/templateJson.json';
|
||||
// import disposalTemplate from './components/disposalTemplate.json';
|
||||
import templateJson from './templateJson.json';
|
||||
import disposalTemplate from './disposalTemplate.json';
|
||||
import {formatInventory} from '@/utils/his.js';
|
||||
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const showSearch = ref(true);
|
||||
const total = ref(0);
|
||||
@@ -444,7 +447,9 @@ async function printPrescription() {
|
||||
}).then((res) => {
|
||||
if (projectTypeCode.value == '3') {
|
||||
const result = res.data;
|
||||
const printElements = disposalTemplate;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(disposalTemplate).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
hiprintTemplate.print2(result, {
|
||||
height: 210,
|
||||
@@ -474,7 +479,9 @@ async function printPrescription() {
|
||||
prescriptionList: item,
|
||||
});
|
||||
});
|
||||
const printElements = templateJson;
|
||||
const printElements = JSON.parse(
|
||||
JSON.stringify(templateJson).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
|
||||
);
|
||||
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
|
||||
hiprintTemplate.print2(result, {
|
||||
height: 210,
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
{
|
||||
"panels": [
|
||||
{
|
||||
"index": 0,
|
||||
"name": 1,
|
||||
"paperType": "A5",
|
||||
"height": 210,
|
||||
"width": 148,
|
||||
"paperHeader": 0,
|
||||
"paperFooter": 592.4409448818898,
|
||||
"paperNumberDisabled": true,
|
||||
"paperNumberContinue": true,
|
||||
"expandCss": "",
|
||||
"overPrintOptions": {
|
||||
"content": "",
|
||||
"opacity": 0.7,
|
||||
"type": 1
|
||||
},
|
||||
"watermarkOptions": {
|
||||
"content": "",
|
||||
"fillStyle": "rgba(184, 184, 184, 0.3)",
|
||||
"fontSize": "14px",
|
||||
"rotate": 25,
|
||||
"width": 200,
|
||||
"height": 200,
|
||||
"timestamp": false,
|
||||
"format": "YYYY-MM-DD HH:mm"
|
||||
},
|
||||
"panelLayoutOptions": {},
|
||||
"printElements": [
|
||||
{
|
||||
"options": {
|
||||
"left": 0,
|
||||
"top": 22.5,
|
||||
"height": 12,
|
||||
"width": 420,
|
||||
"title": "{{HOSPITAL_NAME}}",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 13.5,
|
||||
"qrCodeLevel": 0,
|
||||
"textAlign": "center"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 0,
|
||||
"top": 45,
|
||||
"height": 9.75,
|
||||
"width": 420,
|
||||
"title": "处置单",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 11.25,
|
||||
"qrCodeLevel": 0,
|
||||
"textAlign": "center"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 22.5,
|
||||
"top": 67.5,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "姓名",
|
||||
"field": "patientName",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 157.5,
|
||||
"top": 67.5,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "年龄",
|
||||
"field": "age",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 300,
|
||||
"top": 67.5,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "性别",
|
||||
"field": "genderEnum_enumText",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 22.5,
|
||||
"top": 94.5,
|
||||
"height": 9.75,
|
||||
"width": 96,
|
||||
"title": "科室",
|
||||
"field": "departmentName",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 156,
|
||||
"top": 94.5,
|
||||
"height": 9.75,
|
||||
"width": 118.5,
|
||||
"title": "费用性质",
|
||||
"field": "contractName",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 300,
|
||||
"top": 94.5,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "日期",
|
||||
"field": "reqTime",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 22.5,
|
||||
"top": 121.5,
|
||||
"height": 9.75,
|
||||
"width": 123,
|
||||
"title": "门诊号",
|
||||
"field": "encounterNo",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 156,
|
||||
"top": 121.5,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "开单医生",
|
||||
"field": "doctorName",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 18,
|
||||
"top": 141,
|
||||
"height": 9,
|
||||
"width": 393,
|
||||
"borderWidth": "1.5",
|
||||
"title": "undefined+beforeDragIn",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "横线",
|
||||
"type": "hline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 22.5,
|
||||
"top": 156,
|
||||
"height": 9.75,
|
||||
"width": 24,
|
||||
"title": "Rp",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 12,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 22.5,
|
||||
"top": 177,
|
||||
"height": 36,
|
||||
"width": 387,
|
||||
"title": "undefined+beforeDragIn",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"field": "adviceItemList",
|
||||
"columns": [
|
||||
[
|
||||
{
|
||||
"title": "项目名",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 180.11284430829235,
|
||||
"field": "itemName",
|
||||
"checked": true,
|
||||
"columnId": "itemName",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "单价",
|
||||
"titleSync": false,
|
||||
"align": "right",
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"formatter2": "function(value,row,index,options,rowIndex,column){ return value + ' 元'; }",
|
||||
"width": 65.15543233883191,
|
||||
"field": "unitPrice",
|
||||
"checked": true,
|
||||
"columnId": "unitPrice",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "数量",
|
||||
"titleSync": false,
|
||||
"align": "right",
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"formatter2": "function(value,row,index,options,rowIndex,column){ return value + ' ' + row.unitCode_dictText; }",
|
||||
"width": 61.720533008519084,
|
||||
"field": "quantity",
|
||||
"checked": true,
|
||||
"columnId": "quantity",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "执行次数",
|
||||
"titleSync": false,
|
||||
"align": "right",
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 80.01119034435662,
|
||||
"field": "quantity",
|
||||
"checked": true,
|
||||
"columnId": "quantity",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "表格",
|
||||
"type": "table",
|
||||
"editable": true,
|
||||
"columnDisplayEditable": true,
|
||||
"columnDisplayIndexEditable": true,
|
||||
"columnTitleEditable": true,
|
||||
"columnResizable": true,
|
||||
"columnAlignEditable": true,
|
||||
"isEnableEditField": true,
|
||||
"isEnableContextMenu": true,
|
||||
"isEnableInsertRow": true,
|
||||
"isEnableDeleteRow": true,
|
||||
"isEnableInsertColumn": true,
|
||||
"isEnableDeleteColumn": true,
|
||||
"isEnableMergeCell": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
{
|
||||
"panels": [
|
||||
{
|
||||
"index": 0,
|
||||
"name": 1,
|
||||
"paperType": "自定义",
|
||||
"height": 130,
|
||||
"width": 210,
|
||||
"paperNumberDisabled": true,
|
||||
"paperNumberContinue": true,
|
||||
"overPrintOptions": {
|
||||
"content": "",
|
||||
"opacity": 0.7,
|
||||
"type": 1
|
||||
},
|
||||
"watermarkOptions": {
|
||||
"content": "",
|
||||
"fillStyle": "rgba(184, 184, 184, 0.3)",
|
||||
"fontSize": "14px",
|
||||
"rotate": 25,
|
||||
"width": 200,
|
||||
"height": 200,
|
||||
"timestamp": false,
|
||||
"format": "YYYY-MM-DD HH:mm"
|
||||
},
|
||||
"panelLayoutOptions": {},
|
||||
"paperHeader": 0,
|
||||
"paperFooter": 841.8897637795277,
|
||||
"printElements": [
|
||||
{
|
||||
"options": {
|
||||
"left": 252,
|
||||
"top": 13.5,
|
||||
"height": 12,
|
||||
"width": 75,
|
||||
"title": "{{HOSPITAL_NAME}}医院",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"fontSize": 12,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 19.5,
|
||||
"top": 33,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "日期",
|
||||
"field": "occurrenceTime",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 222,
|
||||
"top": 33,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "单据号",
|
||||
"field": "busNo",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 465,
|
||||
"top": 33,
|
||||
"height": 9.75,
|
||||
"width": 120,
|
||||
"title": "机构:{{HOSPITAL_NAME}}医院",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 19.5,
|
||||
"top": 57,
|
||||
"height": 9.75,
|
||||
"width": 322.5,
|
||||
"title": "供应商",
|
||||
"field": "supplierName",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 19.5,
|
||||
"top": 84,
|
||||
"height": 36,
|
||||
"width": 570,
|
||||
"title": "undefined+beforeDragIn",
|
||||
"field": "purchaseinventoryList",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"columns": [
|
||||
[
|
||||
{
|
||||
"title": "项目名",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 53.52877835374887,
|
||||
"field": "name",
|
||||
"checked": true,
|
||||
"columnId": "name",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "规格",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 50.3056193642802,
|
||||
"field": "volume",
|
||||
"checked": true,
|
||||
"columnId": "volume",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "厂家/产地",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 84.09807741407441,
|
||||
"field": "manufacturerText",
|
||||
"checked": true,
|
||||
"columnId": "manufacturerText",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "数量",
|
||||
"titleSync": false,
|
||||
"align": "right",
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"formatter2": "function(value,row,index,options,rowIndex,column){ return value + ' ' + row.unitCode_dictText; }",
|
||||
"width": 37.02194283284556,
|
||||
"field": "itemQuantity",
|
||||
"checked": true,
|
||||
"columnId": "itemQuantity",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "采购单价",
|
||||
"titleSync": false,
|
||||
"align": "right",
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"formatter2": "function(value,row,index,options,rowIndex,column){ return value + ' 元'; }",
|
||||
"width": 45.05495152300426,
|
||||
"field": "price",
|
||||
"checked": true,
|
||||
"columnId": "price",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "金额",
|
||||
"titleSync": false,
|
||||
"align": "right",
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"formatter2": "function(value,row,index,options,rowIndex,column){ return value + ' 元'; }",
|
||||
"width": 39.04544357631049,
|
||||
"field": "totalPrice",
|
||||
"checked": true,
|
||||
"columnId": "totalPrice",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "仓库",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 40.041954542099724,
|
||||
"field": "purposeLocationName",
|
||||
"checked": true,
|
||||
"columnId": "purposeLocationName",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "产品批号",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 47.05067091842349,
|
||||
"field": "lotNumber",
|
||||
"checked": true,
|
||||
"columnId": "lotNumber",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "生产日期",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 63.089377997062755,
|
||||
"field": "startTime",
|
||||
"checked": true,
|
||||
"columnId": "startTime",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "有效期至",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 59.05673483929025,
|
||||
"field": "endTime",
|
||||
"checked": true,
|
||||
"columnId": "endTime",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
},
|
||||
{
|
||||
"title": "发票号",
|
||||
"titleSync": false,
|
||||
"halign": "center",
|
||||
"tableQRCodeLevel": 0,
|
||||
"tableSummaryTitle": true,
|
||||
"tableSummary": "",
|
||||
"width": 51.706448638859854,
|
||||
"field": "invoiceNo",
|
||||
"checked": true,
|
||||
"columnId": "invoiceNo",
|
||||
"fixed": false,
|
||||
"rowspan": 1,
|
||||
"colspan": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "表格",
|
||||
"type": "table",
|
||||
"editable": true,
|
||||
"columnDisplayEditable": true,
|
||||
"columnDisplayIndexEditable": true,
|
||||
"columnTitleEditable": true,
|
||||
"columnResizable": true,
|
||||
"columnAlignEditable": true,
|
||||
"isEnableEditField": true,
|
||||
"isEnableContextMenu": true,
|
||||
"isEnableInsertRow": true,
|
||||
"isEnableDeleteRow": true,
|
||||
"isEnableInsertColumn": true,
|
||||
"isEnableDeleteColumn": true,
|
||||
"isEnableMergeCell": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"left": 480,
|
||||
"top": 130.5,
|
||||
"height": 12,
|
||||
"width": 109.5,
|
||||
"title": "合计",
|
||||
"field": "totalAmount",
|
||||
"coordinateSync": false,
|
||||
"widthHeightSync": false,
|
||||
"qrCodeLevel": 0,
|
||||
"formatter": "function(title,value,options,templateData,target,paperNo){\n return value + ' 元'\n}"
|
||||
},
|
||||
"printElementType": {
|
||||
"title": "文本",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<div style="padding: 20px; max-width: 1200px; margin: 0 auto" ref="bodyRef">
|
||||
<!-- 标题区域 - 居中加粗,增加层次感 -->
|
||||
<div style="text-align: center; margin-bottom: 30px">
|
||||
<div style="font-size: 22px; color: #333; letter-spacing: 1px">长春市朝阳区中医院</div>
|
||||
<div style="font-size: 22px; color: #333; letter-spacing: 1px">{{ userStore.hospitalName }}</div>
|
||||
<div
|
||||
style="
|
||||
font-size: 32px;
|
||||
@@ -614,7 +614,7 @@
|
||||
border-top: 1px solid #eee;
|
||||
"
|
||||
>
|
||||
本记录由长春市朝阳区中医院医师根据患者病情如实记录,仅供临床诊疗参考 |
|
||||
本记录由{{ userStore.hospitalName }}医师根据患者病情如实记录,仅供临床诊疗参考 |
|
||||
地址:长春市朝阳区XX街XX号 | 联系电话:0431-XXXXXXX
|
||||
</div>
|
||||
|
||||
@@ -629,7 +629,9 @@
|
||||
|
||||
<script setup>
|
||||
import {reactive, ref} from 'vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const bodyRef = ref();
|
||||
|
||||
// 响应式表单数据
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
margin-bottom: 8px;
|
||||
"
|
||||
>
|
||||
长春市朝阳区中医院
|
||||
{{ userStore.hospitalName }}
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
@@ -500,7 +500,9 @@
|
||||
|
||||
<script setup>
|
||||
import {reactive, ref} from 'vue'; // 补充缺失的reactive导入
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const bodyRef = ref(null);
|
||||
const showPrintPreview = ref(false); // 控制弹窗显隐
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
word-wrap: break-word;
|
||||
"
|
||||
>
|
||||
长春市朝阳区中医院
|
||||
{{ userStore.hospitalName }}
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
@@ -721,7 +721,7 @@
|
||||
word-wrap: break-word;
|
||||
"
|
||||
>
|
||||
长春市朝阳区中医院
|
||||
{{ userStore.hospitalName }}
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
@@ -1346,8 +1346,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {reactive, ref} from 'vue';
|
||||
import {computed, reactive, ref} from 'vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const bodyRef = ref();
|
||||
const printContentRef = ref(); // 新增打印内容的ref
|
||||
const showPrintPreview = ref(false); // 控制打印预览弹窗显示
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- 标题区域 - 强化正式感 -->
|
||||
<div
|
||||
style="text-align: center; margin-bottom: 30px; padding: 20px; background: #fff; border-radius: 12px; box-shadow: 0 2px 6px rgba(0,0,0,0.03);">
|
||||
<div style="font-size: 22px; color: #2d3748; letter-spacing: 1px;">长春市朝阳区中医院</div>
|
||||
<div style="font-size: 22px; color: #2d3748; letter-spacing: 1px;">{{ userStore.hospitalName }}</div>
|
||||
<div
|
||||
style="font-size: 28px; font-weight: 700; margin: 12px 0; padding: 8px 0; border-bottom: 2px solid #e8f4f8; display: inline-block;">
|
||||
住院患者入院沟通记录单</div>
|
||||
@@ -343,5 +343,7 @@
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
</script>
|
||||
@@ -11,7 +11,7 @@
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.03);
|
||||
"
|
||||
>
|
||||
<div style="font-size: 22px; color: #2d3748; letter-spacing: 1px">长春市朝阳区中医院</div>
|
||||
<div style="font-size: 22px; color: #2d3748; letter-spacing: 1px">{{ userStore.hospitalName }}</div>
|
||||
<div
|
||||
style="
|
||||
font-size: 28px;
|
||||
@@ -823,7 +823,9 @@
|
||||
|
||||
<script setup>
|
||||
import {reactive, ref} from 'vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const bodyRef = ref();
|
||||
// 响应式表单数据
|
||||
const formData = reactive({
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
<div
|
||||
style="display: flex; flex-direction: column; justify-content: center; align-items: center"
|
||||
>
|
||||
<div style="font-size: 20px">长春市朝阳区中医院</div>
|
||||
<div style="font-size: 20px">{{ userStore.hospitalName }}</div>
|
||||
<div style="font-size: 30px; font-weight: bold; padding-top: 10px">住院病案首页</div>
|
||||
</div>
|
||||
<!-- 线 -->
|
||||
@@ -1754,7 +1754,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from 'vue';
|
||||
import {ref, reactive, getCurrentInstance} from 'vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { proxy } = getCurrentInstance();
|
||||
import formDataJs from '../../doctorstation/components/store/medicalpage';
|
||||
import {patientInfo} from '../../inpatientDoctor/home/store/patient';
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user