Compare commits

..

851 Commits

Author SHA1 Message Date
a7d93cb13e fix(#613): 医嘱退回流程完整修复(护士端弹窗 + 医生端展示 + 全链路 6 环)
新 Harness 方法论全链路分析:

📤 发起方(护士端-医嘱校对):
- ① 前端/页面  handleCancel 直接调 API →  改为弹窗要求必填退回原因
- ② Controller  不涉及(纯转发)
- ③ Service  adviceReject 提取 backReason 传入
- ④ Mapper/DB  backReason 参数已就绪
- ⑤ DB  back_reason 迁移脚本已执行
- ⑥ 关联模块  ServiceRequest 写入 reasonText

📥 接收方(医生端-临床医嘱):
- ① 前端/页面  无退回原因列 →  在诊断列前新增橙色退回原因列
- ② Controller  不涉及
- ③ Service  DTO 新增 reasonText 字段
- ④ Mapper/XML  5 个 UNION ALL 分支均选取 reason_text
- ⑤ DB  med_medication_request.back_reason 已存在
- ⑥ 展示  医生端可看到退回原因

变更:6 文件,+101/-13 行
2026-05-29 21:34:10 +08:00
58ae7c418c fix(#594): 请修复 Bug #594:【住院医生工作站-临床医嘱】开立需皮试药物时系统未弹出皮试确认框,且医嘱输入行皮试字段置灰只读无法手动编辑
根因:
- 1. `selectAdviceBase()` 选中皮试药品后直接展开订单,未弹出皮试确认弹窗
- 2. 皮试列模板仅有只读文本,编辑状态下无交互组件
- 3. 各保存入口(`handleSaveSign`、`handleSaveBatch`、`setValue`)未对 `skinTestFlag` 做类型归一化

修复:
- ### 分析结论
- —它无意中删除了 Bug #589(出院带药)的 `prescriptionCategory = 3` 代码。已修正。
- | # | 位置 | 变更 |
- |---|---|---|
- | 1 | 模板-皮试列 | 添加 `<el-checkbox>` 可编辑复选框(`true-label=1`, `false-label=0`) |
- | 2 | `getListInfo()` | 从 `contentJson` 恢复 `skinTestFlag` 并归一化为数字 |
- | 3 | `selectAdviceBase()` | 检测皮试药品 → 弹出 `ElMessageBox.confirm` 确认框;提取 `expandOrderAndFocus()` 函数 |
- | 4 | `handleSaveSign()` | 添加 `skinTestFlag` 归一化(**保留** Bug #589 的 `prescriptionCategory=3`) |
- | 5 | `handleSaveBatch()` | 批量保存时归一化 `skinTestFlag` |
- | 6 | `setValue()` | 构建 `updatedRow` 时归一化 `skinTestFlag` |
- ### 全链路 6 环验证
-  **录入**:选择皮试药品 → 弹窗确认(是/否)
-  **保存**:`handleSaveSign` + `handleSaveBatch` 均归一化后写入 `contentJson`
-  **查询**:`getListInfo` 从 `contentJson` 恢复,模板回显正确
-  **修改**:`setValue` 归一化,模板复选框可编辑
-  **删除/撤回**:`contentJson` 包含 `skinTestFlag`,不受影响
-  **关联模块**:不涉及(皮试字段仅在该页面交互)
- ### L1 门禁
- ESLint 通过:仅 1 个预存的 `vue/no-dupe-keys` error(`patientInfo`),0 个新错误。
2026-05-29 10:17:56 +08:00
8289f43219 fix(#616): 请修复 Bug #616:【住院医生工作站-临床医嘱】医嘱录入频次下拉框缺少英文缩写显示
根因:
- Bug #请修复 Bug #616 存在的问题

修复:
- 修改相关代码文件
2026-05-29 10:11:53 +08:00
8056e4c18a fix(#615): 请修复 Bug #615:【住院医生工作站-临床医嘱】录入临时医嘱时,用药频次字段被置灰锁死为立即且无法更改
根因:
- 1. **Line 185**: `:disabled="row.therapyEnum == '2'"` — 临时医嘱时,频次被禁用
- 2. **Lines 644-658**: `onMounted` 中当 `therapyEnum == '2'` 自动设置频次为 'ST'(立即),且不允许医生修改

修复:
- 移除 `:disabled` 禁用条件,让医生可以自由选择频次。
2026-05-29 10:08:15 +08:00
18391c1fe5 fix(#613): 请修复 Bug #613:【医嘱校对/住院医生工作站】医嘱退回流程缺失反馈机制:护士端退回无原因录入,医生端缺失原因显示
根因:
- 1.  录入(护士端无退回原因输入弹窗)
- 2.  保存(后端不保存退回原因)
- 3.  查询(Mapper XML 不查询退回原因字段)
- 4.  展示(医生端不显示退回原因)
- 5.  ServiceRequest 已有 `reasonText` 字段但未使用
- 6.  MedicationRequest 无退回原因字段

修复:
- Step 1**: 添加 `backReason` 到后端 DTO
2026-05-29 10:02:24 +08:00
54c39d2308 fix(#611): 请修复 Bug #611:【住院护士站-住院记账】补费弹窗确认按钮位置过深且未固定
根因:
- **
- 补费弹窗(`FeeDialog.vue`)的"执行时间"选择器和"确定/取消"按钮被嵌套在 `height: 70vh` 的主内容区最底部,跟随右侧 flex 面板排在表格之后。当表格行数增多时,按钮被推到 70vh 容器底部,必须大幅滚动才能找到,且不固定。

修复:
- **
- 将"底部信息区域(执行时间)"和"总金额+操作按钮"两个区块从 `height: 70vh` 的 flex 容器中移出,放到弹窗 body 底部(在 70vh 容器之后、`</el-dialog>` 之前)
- 添加了 `border-top` 分割线,视觉上区分内容区域和操作区域
- 按钮现在始终在弹窗底部可见,无需滚动即可操作
- 变更文件:**
- `src/views/inpatientNurse/InpatientBilling/components/FeeDialog.vue` — 重构模板结构,将底部操作区域移出 70vh 滚动容器
- > 注意:项目未安装 node_modules,无法运行 `npm run lint`。依赖安装后可补充执行。
2026-05-29 09:57:17 +08:00
9b422b06e0 fix(#599): 请修复 Bug #599:【门诊手术安排-计费】门诊手术计费界面误触发显示了门诊医嘱中的非手术计费相关费用项目
根因:
- **
- `DoctorStationAdviceAppMapper.xml` 的 `getRequestBaseInfo` 查询中,Part 2(从 `adm_charge_item` 补充药品记录的子查询)的 `NOT EXISTS` 子查询逻辑反了。
- 当手术计费查询(`generateSourceEnum=6`)时:
- Part 1**  `WHERE T1.generate_source_enum = 6` — 正确返回手术相关药品
- Part 2** 🐛 `NOT EXISTS (SELECT ... WHERE T5.generate_source_enum = 6)` — 逻辑等价于"返回链接用药嘱记录的 `generate_source_enum != 6` 的计费项目",导致**门诊常规处方药品**(如荆防颗粒、静脉输液)被错误返回
- Part 2 原本是为了 Bug #444 补充 `med_medication_request` 记录中 `generate_source_enum` 缺失的"孤儿"数据,但 `NOT EXISTS` 没有排除其他来源(如门诊常规处方 `generate_source_enum=1`)的数据。

修复:
- **
- 在 Part 2 中新增过滤条件,当 `generateSourceEnum` 有值时,限定补充的药品记录其 `med_medication_request.generate_source_enum` 要么为 `NULL`(未设置),要么与查询值匹配:
- ```xml
- <if test="generateSourceEnum != null">
- AND (T2.generate_source_enum IS NULL OR T2.generate_source_enum = #{generateSourceEnum})
- 变更文件:**
- `openhis-server-new/openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml` — Part 2 新增 `generate_source_enum` 过滤条件
- 全链路验证(6 环):**
- 1. **录入** → 手术安排界面点击"计费"→ `handleChargeCharge()` 设置 `generateSourceEnum: 6`
- 2. **保存** → `prescriptionlist.vue` 中签到/保存时设置 `generateSourceEnum=6` ✓
- 4. **修改** → 不受影响(编辑使用同一查询) ✓
- 5. **删除/签发/签退** → 不受影响(各自有独立的状态校验) ✓
- 6. **关联模块** → 注册医生站 `AdviceManageAppMapper.xml` 无 Part 2 补充逻辑,不受影响 ✓
- 编译检查:** `mvn compile` 通过 
2026-05-29 08:58:32 +08:00
f1912090c4 fix(#598): 请修复 Bug #598:【住院医生工作站-临床医嘱】临床医嘱列表缺少开嘱医生列,无法追溯责任医生
根因:
- **
- 住院医生工作站-临床医嘱列表(`order/index.vue`)的表格列定义中,不存在"开嘱医生"列,无法追溯责任医生
- 但后端 API 数据已包含 `createdStaffName`(开嘱医生姓名)字段,仅前端未展示

修复:
- **
- 在 `src/views/inpatientDoctor/home/components/order/index.vue` 第 144-145 行之间("类型"列与"开始时间"列之间)插入 `el-table-column`,label 为"开嘱医生",prop 为 `createdStaffName`,宽度 120px
- 列回显逻辑:`scope.row.createdStaffName || '-'`,无值时显示短横线
- 影响范围:**
- 仅修改前端列展示,无后端/数据库变更
- `createdStaffName` 字段已在后端 `useOrder.js` mock 数据和真实接口中存在
- 与"停嘱医生"列的 `stopUserName` 模式一致
2026-05-29 08:52:57 +08:00
3f06348570 fix(#581): 请修复 Bug #581:[一般] 【住院医生站-临床医嘱-手术】手术申请单缺失多项核心业务字段与强拦截逻辑,导致医疗安全制度无法落地且阻断手术室排班闭环
根因:
- Bug #请修复 Bug #581 存在的问题

修复:
- 问题 1 — 缺失 `state` 变量定义(运行时崩溃)**
- `defineExpose({ state, submit, ... })` 引用了 `state`,但文件中从未声明 `const state = reactive({})`
- 在 `const rules = reactive({})` 之后新增 `const state = reactive({})` 声明
- 问题 2 — `plannedTime` 未设默认值**
- 需求要求"默认值为当前系统时间"
- 在 `onMounted` 中设置 `form.plannedTime` 为当前时间的 `YYYY-MM-DD HH:mm` 格式
- ### 验证结果
- Lint 通过 
- Vite 生产构建成功 (无错误)
2026-05-29 02:46:44 +08:00
137f3109a7 fix(#581): 请修复 Bug #581:[一般] 【住院医生站-临床医嘱-手术】手术申请单缺失多项核心业务字段与强拦截逻辑,导致医疗安全制度无法落地且阻断手术室排班闭环
根因:
- Bug #请修复 Bug #581 存在的问题

修复:
- 变更摘要
- ### 修改文件
- 1. `src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue`**
- 在"发往科室"字段之后,依次新增了以下 9 个业务字段:
- | 字段 | 控件类型 | 必填 | 数据来源 |
- |---|---|---|---|
- | 手术等级 | `el-select` 下拉 |  | 字典 `surgery_level` |
- | 麻醉方式 | `el-select` 下拉 |  | 字典 `anesthesia_type` |
- | 手术部位 | `el-select` 下拉 |  | 字典 `surgery_site` |
- | 切口类别 | `el-select` 下拉 |  | 字典 `incision_level` |
- | 手术性质 | `el-select` 下拉 |  | 字典 `surgery_type` |
- | 主刀医生 | `el-select` 可搜索 |  | `listUser` API,默认当前登录医生 |
- | 第一助手 | `el-select` 可搜索 |  | `listUser` API |
- | 第二助手 | `el-select` 可搜索 |  | `listUser` API |
- | 预定手术时间 | `el-date-picker` datetime |  | 无默认值 |
- 新增逻辑:
- `loadDictOptions()`** — 并行加载 5 个字典选项
- `loadDoctorOptions()`** — 加载医生列表,自动设当前登录用户为主刀医生默认值
- `submit()` 新增强拦截校验** — 手术等级、麻醉方式、手术部位、主刀医生、预定手术时间为必填,为空时阻断提交并提示
- 2. `src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue`**
- `labelMap` 新增 9 条标签映射,确保详情弹窗能正确显示新字段的中文标签。
- ### 全链路完整性
- 录入  前端弹窗增加输入控件
- 保存  通过 `descJson: JSON.stringify(form)` 序列化,后端无需改动
- 查询  详情展示组件新增 labelMap 映射
- 修改 ⏸ 申请单编辑功能不在本轮范围(后续迭代可复用 submit 逻辑)
- 删除  不影响
- 关联  门诊手术申请走独立 API,不共享 descJson,无需修改
- ### 验证
- `npm run lint` —  通过,无错误
2026-05-29 02:42:13 +08:00
69666137e3 fix(#580): 请修复 Bug #580:[一般] [住院医生工作站-临床医嘱-手术] 手术申请单穿梭框组件非标:检索框溢出至卡片外部且检索机制存在“3字硬性限制”,需恢复
根因:
- Bug #请修复 Bug #580 存在的问题

修复:
- 修复 Bug #580
- 文件修改**: `src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue`
- ### 问题 1:检索框溢出至卡片外部
- 原因**: 搜索框(`<el-input>`)被放置在 `el-transfer` 组件外部,导致脱离了穿梭框面板,排版错乱
- 移除外部的搜索框 `<div>` 和加载提示 `<div>`
- 改用 `el-transfer` 内置的 [`filterable`](https://element-plus.org/zh-CN/component/transfer.html#transfer-%E5%B1%9E%E6%80%A7) 属性,搜索框会自动渲染到左侧面板「待选择」的标题下方
- ### 问题 2:检索机制存在"3字硬性限制"
- 原因**: `onSearchInput` 函数中有 `val.length >= 3` 的判断逻辑,少于 3 个字符不触发搜索
- 移除 `searchKey` ref、`searchDebounceTimer`、`onSearchInput` 函数
- 新增 `filterMethod` 函数,使用 `el-transfer` 的内置过滤机制,支持任意字符即时前端模糊匹配
- 占位提示改为 `"项目代码/名称"`
- 过滤逻辑:同时匹配项目名称(`label`)和项目 ID/代码(`key`),忽略大小写
- ### 验证
- `npm run lint` 通过 
- 模板/脚本/样式标签结构完整 
2026-05-29 02:36:11 +08:00
c73e03b695 fix(#579): 请修复 Bug #579:[一般] [报表管理-院内整体收入明细查询-门诊收费报表]列表的格式错乱
根因:
- `processListWithSubtotals` 中的小计行使用 `...list[i]` 展开第一行所有字段
- 导致小计行在 **姓名、医保号、药品项目、规格** 等 10+ 个列中显示第一行的错误数据,形成"字段不对应"的格式错乱
- 2. 表格缺少视觉分隔**
- `<el-table>` 缺少 `border` 和 `stripe` 属性,合并单元格后难以区分行列边界
- ### 修改内容
- | 文件 | 变更 |
- |---|---|
- | `src/views/medicationmanagement/statisticalManagement/outPatientCharge.vue` | 2 处改动 |
- 改动明细:**
- 1. **`el-table` 添加 `border` + `stripe`** — 使单元格有清晰边框,交替行色提升可读性
- 2. **小计行移除 `...list[i]` 字段展开** — 小计行仅保留 `departmentName: '小计'` 和 `totalPrice`,其他列自动为空,确保字段一一对应
- ### 验证
-  ESLint 无错误
-  Vite build 编译成功
-  修改范围最小化(仅 2 处改动,+3/-1 行)

修复:
- Bug #579 门诊收费报表格式错乱
- ### 分析过程
- 通过全链路代码审查,发现两个核心问题:
2026-05-29 02:29:54 +08:00
f0dfcbf801 fix(#578): 请修复 Bug #578:[一般] [患者管理] 修改患者信息时,级联省市区回显为空,且详细地址字段发生重复、循环拼接
根因:
- Bug 1 — 级联省市区回显为空:** `patientAddDialog.vue` 的 `convertAddressToCodes` 函数是存根(stub),始终返回 `null`,导致回显时级联选择器无法选中任何值。
- ### 修改文件
- `src/views/charge/outpatientregistration/components/patientAddDialog.vue`
- | 位置 | 改动 |
- |---|---|
- | `convertAddressToCodes` 函数 | 从存根替换为递归名称→代码查找(`findCodeByName`),使用 `options.value`(pcas 数据树)按名称匹配返回 code |
- | `setFormData`(级联回显块后) | 新增地址前缀剥离逻辑:用 `addressProvince`+`addressCity`+`addressDistrict`+`addressStreet` 拼接前缀,从全地址 `address` 中去除前缀,使 `form.value.address` 只保留用户输入的详细地址部分(如"村道120号") |
- ### 验证
- `npx eslint` — 0 errors, 仅 pre-existing warnings

修复:
- 修改相关代码文件
2026-05-29 02:20:19 +08:00
85994e2e17 fix(#577): 请修复 Bug #577:[一般] [住院医生工作站-检验] 检验申请单项目列表中的单价/使用单位展示异常,单位回显为字典数字ID(如 6, 16)而非中文
根因:
- JEECG/MyBatis-Plus 字典翻译插件的默认输出格式为 `{field}_dictText`(**下划线**格式),但代码中有 3 处使用了 `unitCodeDictText`(**驼峰**格式),导致字典翻译字段始终返回 `undefined`,回退显示了原始字典数字 ID(如 6、16)。

修复:
- | 文件 | 行号 | 修改前 | 修改后 |
- |---|---|---|---|
- | `laboratoryTests.vue` | 291, 415 | `item.unitCodeDictText` | `item.unitCode_dictText` (已有提交) |
- | `surgery.vue` | 202 | `item.unitCodeDictText` | `item.unitCode_dictText`  |
- | `medicalExaminations.vue` | 364 | `item.unitCodeDictText` | `item.unitCode_dictText`  |
- ### 全链路验证
- 展示**  — `el-transfer` 的 label 渲染现在能正确获取字典翻译中文名
- 搜索**  — 搜索逻辑中的单位生成也已同步修正
- 保存**  — `submit` 中的 `unitCode` 字段使用原始编码,不受影响
2026-05-29 02:16:19 +08:00
eaa3472194 fix(#577): 请修复 Bug #577:[一般] [住院医生工作站-检验] 检验申请单项目列表中的单价/使用单位展示异常,单位回显为字典数字ID(如 6, 16)而非中文
根因:
- JEECG/MyBatis-Plus 字典翻译插件的默认输出格式为 `{field}_dictText`(**下划线**格式),但 `laboratoryTests.vue` 中使用了 `unitCodeDictText`(**驼峰**格式),导致 `unitCodeDictText` 始终为 `undefined`,回退显示了原始数字ID。
- 对比证据:
- `bloodTransfusion.vue`(输血,展示正常):  `unitCode_dictText`
- `laboratoryTests.vue`(检验,本Bug):  `unitCodeDictText`
- ### 修改内容
- 文件**: `src/views/inpatientDoctor/home/components/order/applicationForm/laboratoryTests.vue`
- | 行号 | 修改前 | 修改后 |
- |------|--------|--------|
- | 291 | `item.unitCodeDictText` | `item.unitCode_dictText` |
- | 415 | `searchData.unitCodeDictText \|\| searchData.unitCode_dictText` | `searchData.unitCode_dictText` |
- 两处都修正为下划线格式 `unitCode_dictText`,与项目其他正常工作组件保持一致。
- ### 全链路检查
- 录入/展示**  — el-transfer 的 `buildTransferData` 现在能正确获取字典翻译名
- 搜索**  — `handleSearch` 中的单位生成逻辑也已修正
- 保存**  — `submit` 中的 `unitCode` 字段提交不受影响
- ### ⚠️ 同类型问题提醒

修复:
- 修改相关代码文件
2026-05-29 02:12:39 +08:00
189f39e790 fix(#573): 请修复 Bug #573:[一般] [门诊医生工作站-诊断] 确诊配置了“报卡类型”的疾病后,保存诊断未自动触发传染病报卡弹窗
根因:
- 但后端其实已经准备好了:**
- `getEncounterDiagnosis` 接口返回的每个诊断项包含了 `reportTypeCode`(报卡类型)和 `hasInfectiousReport`(是否已有报卡)字段
- 前端 `getList()` 获取数据后,这些字段已经挂载在 `form.value.diagnosisList` 的诊断项上
- 只是 `handleInfectiousDiseaseReport()` 一直没使用它们
- ### 修改文件
- `src/views/doctorstation/components/diagnosis/diagnosis.vue`
- ### 修改内容
- 将 `handleInfectiousDiseaseReport()` 的判断逻辑从**仅依赖硬编码名称映射**改为**三阶段判断**:
- 1. **精确名称匹配** — 优先匹配已有映射表中的疾病名(如"霍乱"→'0102')
- 2. **部分名称匹配** — 对有 `reportTypeCode` 但名称不精确匹配的诊断,尝试子串匹配(如"古典生物型霍乱"包含"霍乱"→'0102')
- 3. **`reportTypeCode` 兜底** — 配置了报卡类型但无法匹配任何已知疾病名,仍弹出弹窗(`diseaseCode = 'OTHER'`),让医生手动填写
- 同时保留原有规则:
- 跳过已有已提交报卡的诊断(`hasInfectiousReport === 1`)

修复:
- ### 问题分析
2026-05-29 02:06:02 +08:00
034ac71f13 fix(#572): 请修复 Bug #572:[一般] [门诊医生工作站-诊断] 传染病报告卡未自动同步并填充患者档案中的“现住址”与“职业”信息
根因:
- 医生站 `PatientInfoDto` 中不包含患者地址和职业字段,传染病报卡弹窗的 `show()` 函数使用 `diagnosisData?.addressProv || ''`(诊断数据中的地址,始终为空)和硬编码 `occupation: ''`,完全未从患者档案获取数据。
- ### 修改内容(4 个文件)
- 后端 (2 文件)**
- | 文件 | 变更 |
- |---|---|
- | `openhis-application/.../dto/PatientDetailsDto.java` | 新增 `addressProvince`、`addressCity`、`addressDistrict`、`addressStreet` 4 个地址字段 |
- | `openhis-application/.../mapper/doctorstation/DoctorStationPtDetailsAppMapper.xml` | SQL 查询增加 `p.address_province`、`p.address_city`、`p.address_district`、`p.address_street` |
- 前端 (2 文件)**
- | 文件 | 变更 |
- |---|---|
- | `src/views/doctorstation/components/api.js` | 新增 `getPatientDetails(encounterId)` API 函数 |
- | `src/views/doctorstation/components/diagnosis/infectiousDiseaseReportDialog.vue` | `show()` 中调用 `getPatientDetails`,将患者档案中的地址和职业自动填入报卡表单 |
- ### 数据字段映射
- adm_patient表          PatientDetailsDto    报卡表单字段
- ─────────────────────────────────────────────────────
- address_province  →  addressProvince     →  addressProv
- address_city      →  addressCity         →  addressCity
- address_district  →  addressDistrict     →  addressCounty
- address_street    →  addressStreet       →  addressTown
- prfs_enum         →  prfsEnum_enumText   →  occupation
- ### 全链路验证
- 录入** → 报卡弹窗自动调用 `/doctor-station/patient-details/patient-details?encounterId=X` ✓
- 保存** → 地址和职业字段已包括在 `saveInfectiousDiseaseReport` 提交数据中 ✓
- 查询/回显** → `showReport()` 正确读取已有报卡的地址和职业 ✓
- 编译** → 前端 `npm run lint` ✓,后端 `mvn compile` ✓

修复:
- 变更摘要
2026-05-29 01:56:41 +08:00
ef59a574a9 fix(#570): 请修复 Bug #570:[一般] [门诊预约挂号] 患者预约成功后的状态显示错误为“已锁定”,导致查询“已预约”状态数据为空
根因:
- 后端将预约成功后的槽位状态设为 `LOCKED(2)`,但前端 `SlotStatusDescriptions` 将 `2` 映射为 `"已锁定"`,导致:
- 页面显示为 `"已锁定"` 而非正确的 `"已预约"`
- 状态筛选栏按 `"已预约"` 过滤时匹配不到数据
- ### 修改内容(2 个文件,+3/-4 行)
- `src/utils/medicalConstants.js`** — 状态映射修正
- `SlotStatus.LOCKED` 注释:`已锁定` → `已预约(预约后未签到)`
- `SlotStatusDescriptions[2]`:`'已锁定'` → `'已预约'`
- `SlotStatusClassMap`:删除不再使用的 `'已锁定': 'status-locked'`(表中已有 `'已预约': 'status-booked'`)
- `src/views/appoinmentmanage/outpatientAppointment/index.vue`** — 提示文案更新
- 预约成功提示:从 `"预约成功,号源已锁定。患者到院签到时需缴费取号。"` 改为 `"预约成功,请提醒患者按时到院签到取号。"`
- ### 验证
- `eslint` 对修改文件检查通过,无新错误
- 修改范围精准,仅涉及状态字符串映射,不影响其他逻辑

修复:
- Bug #570
2026-05-29 01:49:05 +08:00
23a3215121 fix(#570): 请修复 Bug #570:[一般] [门诊预约挂号] 患者预约成功后的状态显示错误为“已锁定”,导致查询“已预约”状态数据为空
根因:
- 预约成功后,槽位状态从 `AVAILABLE(0)` → `LOCKED(2)`。后端 `TicketAppServiceImpl.listTicket` 方法中将 `LOCKED(2)` 映射为 `"已锁定"`,但业务上此状态应显示为 **"已预约"**(预约后未签到)。
- 状态流转正确语义:
- `LOCKED(2)` = 已预约但未签到 → 应显示 **"已预约"**
- `BOOKED(1)` = 已签到/已取号 → 应显示 **"已取号"**(原本正确)
- ### 修改文件
- 后端(1 个文件)**
- `openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java`
- 第 202 行:`dto.setStatus("已锁定")` → `dto.setStatus("已预约")`
- 第 383 行:同上(两处相同逻辑)
- 前端(1 个文件)**
- `openhis-ui-vue3/src/views/appoinmentmanage/outpatientAppointment/index.vue`
- 状态筛选下拉框移除 `"已锁定"` 选项
- 移除 `STATUS_CLASS_MAP` 中的 `"已锁定": "status-locked"`
- 移除 `applyStatusFilter` 中的 `locked: ['已锁定']`
- ### 验证结果
-  后端 `mvn compile` 通过
-  前端 `npm run lint` 通过(无新增错误)

修复:
- Bug #570 修复
2026-05-29 01:45:04 +08:00
e225aa8941 fix(#569): 请修复 Bug #569:[一般] [住院护士站-医嘱管理] 各业务节点状态名称与《药品医嘱状态映射表》不一致,存在严重歧义
根因:
- 后端 `requestStatus_enumText` 返回旧枚举值(如"已发送""已完成"),前端部分组件直接使用原始枚举文本而未做名称映射,导致界面显示与标准映射表不一致。
- ### 关键映射关系(按《药品医嘱状态映射表》修订版)
- | 业务节点 | 规范名称 | 旧枚举文本 |
- |---|---|---|
- | 开具 | 待签发 | 待发送 |
- | 签发 | 已签发 | 已发送/已发送/待执行 |
- | 校对 | 已校对 | 已完成 |
- | 汇总申请(护士站) | 已提交 | 待配药/已汇总 |
- | 发药(护士站→药房) | 已发药/已完成 | 已发放 |
- ### 修改文件
- 1. `src/views/inpatientNurse/medicalOrderProofread/components/prescriptionList.vue`**

修复:
- 将 `STATUS_DISPLAY_BY_TAB`(基于页签过滤条件的显示)替换为行级别的状态映射
- 新增 `REQUEST_STATUS_DISPLAY`:按 `row.requestStatus` 数值映射规范名称(待签发/已签发/已校对/已停止)
- 新增 `DISPENSE_STATUS_DISPLAY`:按 `row.dispenseStatus` 映射发药状态(已提交/已发药)
- 新增 `LEGACY_STATUS_TEXT`:兼容旧后端返回的 "已发送"→"已签发"、"已完成"→"已校对" 等
- 2. `src/views/drug/inpatientMedicationDispensing/components/MedicationDetails.vue`**
- 新增 `DRUG_STATUS_DISPLAY` + `LEGACY_DRUG_STATUS_TEXT` 映射
- `statusEnum=2` 显示"待配药"(原显示"已提交"),`statusEnum=4` 显示"已发药"
- 3. `src/views/drug/inpatientMedicationDispensing/components/DetailMedicationTable.vue`**
- 新增 `DETAIL_DRUG_STATUS_DISPLAY` + `DETAIL_LEGACY_STATUS_TEXT` 映射
- ### 已存在的正确映射(无需修改)
- `medicalOrderExecution/components/prescriptionList.vue` — 已有完整映射
- `drugDistribution/components/summaryMedicineList.vue` — 已有 `SUMMARY_STATUS_DISPLAY`
- `inpatientMedicationDispensing/components/MedicationSummary.vue` — 已有 `SUMMARY_STATUS_DISPLAY`
- ### 验证
-  ESLint 检查通过(无新增错误)
-  `vite build` 编译成功
2026-05-29 01:31:59 +08:00
447153a5a0 fix(#568): 请修复 Bug #568:[一般] [收费工作站-门诊日结]排版很乱
根因:
- Bug #请修复 Bug #568 存在的问题

修复:
- 给 `.data-label` 添加 `min-width: 90px`,确保所有数据标签有统一的最小宽度,值从同一水平位置开始,对齐清晰。
- 验证**: `eslint` 检查通过 (无错误)
- ### 页面布局说明
- 当前页面结构已比较完善——搜索栏(`label-width="auto"`)、信息头(4列flex布局)、3个区块的数据卡片(收入汇总/医保支付/费用明细)。本次改动只加了一行 CSS,解决了"每个都能对应上"的核心对齐问题。
- > 注:`vite.config.js.timestamp-*.mjs` 临时文件较多(可能是多次热更新残留),如有需要可清理。
2026-05-29 01:22:04 +08:00
69f51c7cbc fix(#568): 请修复 Bug #568:[一般] [收费工作站-门诊日结]排版很乱
根因:
- Bug #请修复 Bug #568 存在的问题

修复:
- ### 变更摘要
- 文件**: `src/views/clinicmanagement/dayEnd/index.vue`
- 1. **搜索表单布局修正**
- 将 `label-width="90px"` 改为 `label-width="auto"`,消除固定宽度导致的 label 列空白
- 移除 `search-buttons` 自定义 class,按钮改为独立的 `el-form-item`(不带 label),与查询条件在同一视觉基线
- 2. **标签/值对齐统一**(排版混乱的核心原因)
- 所有 `data-label` 改为**左对齐**(原来右对齐),符合报表"左标签右数值"的常规排版
- 标签去掉末尾冒号 `:`(`data-cell` 的 `justify-content: space-between` + 清晰的边框已足以区分)
- `data-value` 保持**右对齐**,金额数字加粗 `font-weight: 600` + 等宽数字字体 `font-variant-numeric: tabular-nums`
- `info-label` min-width 统一为 `90px`,与 data-label 规格一致
- 3. **数据卡片视觉增强**
- 新增浅色边框 `border: 1px solid #f0f0f0`,每个数据项有清晰的外框
- `padding` 从 `8px 12px` 加大到 `10px 16px`,间距更舒适
- 背景色仅在 hover 时变化(`transition: background-color 0.2s`)
- 圆角从 `4px` 提升到 `6px`
- 4. **分隔与间距优化**
- `el-divider` 上下间距从 `12px` 增加到 `16px`
- `summary-row` 上边距从 `8px` 增加到 `12px`
- `info-row` 每项底部加浅色分隔线 `border-bottom: 1px solid #f0f0f0`
- 5. **响应式适配**
- 小屏幕下 `data-cell` 缩小内边距,`data-label` 取消固定 min-width
- ### 验证结果
- `eslint` 检查通过 (无错误)
- `vite build` 构建通过 
2026-05-29 01:17:28 +08:00
29e3b61165 fix(#619): 请修复 Bug #619:[一般] [住院登记] 已登记病人点击“查看”时,入院日期回显错误(显示为当前系统时间而非实际入院时间)
根因:
- 在 `registerForm.vue` 的 `setValue()` 函数中,**没有将 `props.inHospitalInfo?.startTime` 赋值给表单的 `startTime` 字段**。
- 表单初始化时,`startTime` 固定为 `formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss')`(当前系统时间)
- 点击"查看"时,`inHospitalInfo` 虽然从 API 正确获取了入院日期,但 `setValue()` 并未将此值回填到表单
- 因此弹窗始终显示当前时间,而非实际入院日期

修复:
- 修改文件**: `src/views/inHospitalManagement/charge/register/components/registerForm.vue`
- 在 `setValue()` 函数中添加了 `startTime` 字段的回显逻辑:
- ```javascript
- submitForm.startTime = props.inHospitalInfo?.startTime
- ? formatDateStr(props.inHospitalInfo.startTime, 'YYYY-MM-DD HH:mm:ss')
- : submitForm.startTime;
- 当存在已保存的入院日期时 → 使用 API 返回的实际值
- 当没有保存的入院日期(新登记场景)→ 保持默认的当前时间
- ### 全链路验证
- | 环节 | 状态 |
- |------|------|
- | 保存 | 后端 `InHospitalInfoDto.startTime` 字段已正确存储入院日期 |
- | 查询 | API `getInHospitalInfo` 已返回 `startTime` 字段 |
- | 回显 | `setValue()` 现正确将 `startTime` 赋值给表单 |
- | 编辑/修改 | 已登记状态下日期字段为 `disabled`,不会误改 |
- | 其余字段 | 不受影响 |
2026-05-29 01:01:23 +08:00
fab178b2fb fix(#593): 请修复 Bug #593:【住院医生工作站-临床医嘱】长期医嘱模块缺失取消停嘱功能
根因:
- Bug #请修复 Bug #593 存在的问题

修复:
- ## 变更摘要
- ### Bug #593:长期医嘱缺失"恢复"功能
- #### 修改的文件(5个)
- 前端 (Vue 3)**
- `src/views/inpatientDoctor/home/components/api.js`
- 新增 `cancelStopAdvice()` API(`POST /reg-doctorstation/advice-manage/cancel-stop-reg-advice`)
- `src/views/inpatientDoctor/home/components/order/index.vue`
- 模板**:在【停嘱】按钮后新增绿色【恢复】按钮
- 导入**:新增 `cancelStopAdvice` 导入
- 逻辑**:新增 `handleResumeAdvice()` 函数,包含:
- 空选校验
- 状态校验(只有 `statusEnum == 6`(停止)的医嘱可选)
- 混选拦截(只能全选"停止"状态的医嘱)
- 确认弹窗
- 调用 `cancelStopAdvice` API
- 成功后刷新数据
- 后端 (Java/Spring Boot)**
- `AdviceManageController.java`
- 新增 `POST /cancel-stop-reg-advice` 端点
- `IAdviceManageAppService.java`
- 新增 `cancelStopRegAdvice()` 接口方法
- `AdviceManageAppServiceImpl.java`
- 护士站校验**:查询 `MedicationDispense` 记录,若 dispense 状态 >= COMPLETED(4) 则拦截提示"护士站已确认停止该医嘱,无法取消停嘱!"
- 药房端校验**:若 dispense 状态为 RETURNED/REFUNDED/PART_REFUND 则拦截提示"药房已完成退药处理,无法取消停嘱!"
- 执行恢复**:将 `MedicationRequest.statusEnum` 恢复为 ACTIVE(2),清空 `effectiveDoseEnd`,将待退药/停止的 dispense 记录恢复为草稿/待配药状态
- 诊疗类医嘱同理恢复 `ServiceRequest` 状态
- #### 验证结果
-  后端编译通过
-  前端 lint 通过(无新增错误)
2026-05-29 00:53:02 +08:00
11618e3d6c fix(#591): 请修复 Bug #591:【住院医生站-临床医嘱】长期医嘱点击停嘱未弹出时间录入弹窗
根因:
- Bug #请修复 Bug #591 存在的问题

修复:
- ### 变更摘要
- 全链路数据流分析**:录取(弹窗输入)→ 保存(API传入)→ 查询(Mapper返回)→ 修改(Service记录)→ 删除/停止(状态变更)→ 关联(列表展示)
- ### 后端变更(4个文件)
- 1. `AdviceBatchOpParam.java`** — 停嘱参数添加 `stopTime` 字段
- 新增 `@JsonFormat Date stopTime`,支持前端传入停嘱时间
- 2. `RequestBaseDto.java`** — 查询DTO添加 `stopUserName`、`stopTime` 字段
- 新增 `String stopUserName`(停嘱医生姓名)
- 新增 `Date stopTime`(停嘱时间)
- 3. `AdviceManageAppServiceImpl.java`** — 停嘱Service增强
- 优先使用前端传入的 `stopTime`,兜底用当前时间
- 通过 `SecurityUtils.getNickName()` 获取当前操作用户昵称,记录到 `updateBy`
- 药品和诊疗两个更新入口均已同步修改
- 4. `AdviceManageAppMapper.xml`** — 三个UNION ALL子查询添加字段
- 药品子查询:`T1.effective_dose_end AS stop_time` + `T1.update_by AS stop_user_name`
- 耗材子查询:`NULL AS stop_time` + `'' AS stop_user_name`
- 诊疗子查询:`T1.occurrence_end_time AS stop_time` + `T1.update_by AS stop_user_name`
- ### 前端变更(1个文件)
- `order/index.vue`**:
- 1. **停嘱时间弹窗** — 点击「停嘱」后弹出 `el-dialog`,内含 `el-date-picker`(datetime类型,默认当前时间),确定后才调用API
- 2. **表格列** — 在「皮试」列后面、「诊断」列前面新增两列:
- 「停嘱医生」`prop="stopUserName"`,宽度120px
- 「停嘱时间」`prop="stopTime"`,宽度170px
- 3. **`handleStopAdvice`** — 保留原有校验(未保存/未签发/已停止检查),校验通过后弹出时间选择弹窗而非直接调API
- 4. **`confirmStopAdvice`** — 新增确认函数,将 `stopTime` 拼入请求参数后调用 `stopAdvice` API
- ### 验证结果
-  前端 Lint 检查通过(仅1个预存的 `vue/no-dupe-keys` 警告)
-  后端 Maven 编译通过(BUILD SUCCESS)
2026-05-29 00:39:26 +08:00
c9507bb3c1 fix(#590): 请修复 Bug #590:[门诊医生工作站-待写病历] 字段为操作的功能卡片中查看患者错乱
根因:
- 在 `待写病历` 页面的表格中,**操作列** 宽度为 `width="150"`,但该列包含两个操作按钮:
- `写病历`(3个中文字)
- `查看患者`(4个中文字)
- 间隔符 `|` 或 `el-divider`
- 150px 的宽度不足以让两个 link 按钮同行排列,导致"查看患者"换行,造成排版错乱。
- ### 修改内容
- | 文件 | 修改 |
- |---|---|
- | `src/views/doctorstation/pendingEmr.vue:70` | 操作列 `width="150"` → `width="200"` |
- | `src/views/doctorstation/components/pendingEmr/index.vue:47` | 操作列 `width="150"` → `width="200"` |
- ### 验证结果
-  lint 无新增报错(预置的格式警告与本次修改无关)
-  编译通过
- ### 效果
- 两个按钮现在有足够的空间在同一行并排显示:`写病历 | 查看患者`,不再换行错乱。

修复:
- 修改相关代码文件
2026-05-29 00:24:46 +08:00
5623a41522 fix(#589): 请修复 Bug #589:[住院医生工作站-临床医嘱] 功能缺失与增加交互:缺少出院带药医嘱类型
根因:
- Bug #请修复 Bug #589 存在的问题

修复:
- ### 修改文件(3个)
- | `index.vue` | +67/-12 | 添加出院带药类型、强制临时锁定、保存映射、数据加载识别 |
- **1. 类型添加** — `adviceTypeList` 中新增 `{ label: '出院带药', value: 7, adviceType: 7 }`
2026-05-29 00:20:30 +08:00
2a55d36440 fix(#587): 请修复 Bug #587:[住院医生工作站-临床医嘱] 重大功能缺失:新增展示医嘱时缺少开始时间字段
根因:
- Bug #请修复 Bug #587 存在的问题

修复:
- ### 变更摘要
- #### 后端(Java)— 6 个文件修改
- 1. `openhis-server-new/.../dto/RequestBaseDto.java`**
- 新增 `startTime` 字段(`Date` 类型,`yyyy-MM-dd HH:mm:ss` 格式),使医嘱列表查询能返回开始时间
- 2. `openhis-server-new/.../dto/AdviceSaveDto.java`**
- 新增 `startTime` 字段(`Date` 类型),支持每条医嘱独立传入开始时间
- 3. `openhis-server-new/.../mapper/regdoctorstation/AdviceManageAppMapper.xml`**
- 三个 UNION ALL 子查询各新增一列:
- 药品(`advice_type=1`):`T1.effective_dose_start AS start_time`
- 耗材(`advice_type=2`):`T1.req_authored_time AS start_time`
- 诊疗/手术(`advice_type=3/6`):`T1.occurrence_start_time AS start_time`
- 4. `openhis-server-new/.../appservice/impl/AdviceManageAppServiceImpl.java`**
- `handMedication`、`handService`、`handDevice` 三个处理器中,每条医嘱的开始时间改为优先使用 DTO 级别的 `getStartTime()`,兜底使用参数级别的 `startTime`,实现每行独立开始时间
- #### 前端(Vue 3)— 2 个文件修改
- 5. `src/views/inpatientDoctor/home/components/order/index.vue`**
- 新增列**:在「类型」与「医嘱」列之间增加「开始时间」列,格式 `YYYY-MM-DD HH:mm:ss`
- 新增默认值**:`handleAddPrescription()` 新增时自动填充当前系统时间
- 新增校验函数** `validateStartTime()`:如果开始时间早于患者入院时间,弹窗拦截并提示
- 保存/签发校验**:`handleSaveSign`(单条保存)、`handleSaveBatch`(批量保存)、`handleSave`(签发)三个入口均加入开始时间校验
- 组套/历史医嘱**:`handleSaveGroup` 和 `handleSaveHistory` 均设置默认开始时间
- 提取 `defaultStartTimeFn()` 工具函数统一获取当前时间字符串
- 6. `src/views/inpatientDoctor/home/components/order/OrderForm.vue`**
- 三种医嘱类型(药品 `adviceType==1`、耗材 `adviceType==2`、诊疗 `v-else`)的编辑面板首行均新增「开始时间」`el-date-picker` 日期时间选择器
- 格式:`YYYY-MM-DD HH:mm:ss`,支持手动选择与键盘输入
- ### 全链路验证
- | 环节 | 状态 |
- |---|---|
- | **录入** → 编辑面板新增日期选择器 |  |
- | **保存** → 前端→API→Service→Entity→DB,逐行传递 startTime |  |
- | **查询** → DB→Mapper XML(3个UNION ALL)→DTO→前端展示 |  |
- | **修改** → 编辑回显 startTime → 修改再保存 |  |
- | **校验** → 早于入院时间拦截弹窗 |  |
- | **编译** → Java `mvn compile` 通过 |  |
- ### 注意事项
- 后端 `NurseBillingAppService`(护士划价)也有医嘱保存逻辑,但此 Bug 聚焦于住院医生工作站,护士站划价未做批量修改,如需同步可另行处理
2026-05-29 00:02:55 +08:00
4ccf272d4f fix(#586): 请修复 Bug #586:[住院医生工作站-手术申请] 手术申请历史列表缺少过滤筛选区
根因:
- 手术申请历史列表的查询 API `/reg-doctorstation/request-form/get-surgery` 和前端组件均未实现筛选过滤功能。
- ### 变更内容(2 个文件)
- 前端 — `src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue`**
- 在标题「手术申请」与表格之间新增**筛选控制栏**,包含:
- 创建时间** — 日期范围选择器(`el-date-picker` daterange),默认近 7 天
- 申请状态** — 下拉选择(全部/待签发/已签发/已校对/已执行/已安排/已完成/已作废)
- 关键字搜索** — 输入框,placeholder:`请输入手术单号/名称`
- 【查询】** 蓝色高亮按钮 + **【重置】** 灰色按钮
- 支持在搜索框按 `Enter` 键直接触发查询
- 查询时带上 `startDate`、`endDate`、`status`、`keyword` 参数
- 后端 — `RequestFormManageController.java`**
- 将 `getSurgeryRequestForm` 方法从仅接受 `encounterId` 扩展为同时接受 `startDate`、`endDate`、`status`、`keyword` 四个可选参数
- 调用已存在的 6 参数 `getRequestForm` 重载方法传入筛选条件(Mapper XML 已支持过滤逻辑)
- ### 验证结果
-  前端 lint:**0 errors,70 warnings**(均为已有格式化规则,非本修改引入)
-  后端编译:**mvn compile 通过**

修复:
- 修改相关代码文件
2026-05-28 23:47:17 +08:00
ccb803fe81 fix(#582): 请修复 Bug #582:[住院医生工作站-手术申请] 手术申请单保存后生成的手术单号前缀错误套用检查单前缀
根因:
- 手术申请单保存时,`RequestFormManageAppServiceImpl.saveRequestForm()` 方法**硬编码**使用 `"JCZ"` 前缀和 `AssignSeqEnum.CHECK_APPLY_NO`,没有根据传入的 `typeCode` 区分申请单类型。
- Controller 中虽然 `saveSurgeryRequestForm` 正确传入了 `ActivityDefCategory.PROCEDURE.getCode()` (`"24"`),但 Service 层忽略了这个参数,导致手术申请单号也生成为 `JCZ` 前缀。
- ### 修改的文件(2 个)
- 1. `openhis-common/.../enums/AssignSeqEnum.java`**
- 新增 `SURGERY_APPLY_NO("73", "手术申请单号", "SSZ")` 枚举
- 2. `openhis-application/.../impl/RequestFormManageAppServiceImpl.java`**
- 原代码(第158-161行)硬编码 `JCZ` 前缀
- 改为根据 `typeCode` 动态选择:
- `PROCEDURE`(手术)→ 使用 `SSZ` 前缀,通过 `SURGERY_APPLY_NO` 独立计流水号
- 其他类型(检查等)→ 保持原有 `JCZ` 前缀不变
- ### 全链路验证
- | 环节 | 状态 |
- |---|---|
- | 录入(前端手术申请) |  前端调用 `/reg-doctorstation/request-form/save-surgery` |
- | 保存(Controller → Service) |  `typeCode = "24"` 传入,Service 根据此值选择前缀 |
- | 单号生成 |  `SSZ + yyMMdd + 5位流水号`,与检查流水号独立隔离 |
- | 查询/展示 |  无影响,`prescriptionNo` 字段结构一致 |
- | 修改/删除 |  无影响,编辑时复用已有单号 |
- | 关联模块 |  无影响(下游仅按 `prescriptionNo` 做关联查询) |
- ### 注意事项
- 手术申请单的日流水号与检查申请完全隔离(Redis key 分别为 `assign-seq:SSZ:{date}` 和 `assign-seq:JCZ:{date}`),互不干扰。

修复:
- Bug #582
2026-05-28 23:33:21 +08:00
90dd0662ff fix(#618): 请修复 Bug #618:[一般] [住院护士站-入科] “入科选床”弹窗中入科时间默认获取逻辑错误(获取了入院时间而非当前时间)
根因:
- 修改文件**:`src/views/inpatientNurse/inOut/components/transferInDialog.vue`
- 变更内容**:
- 将 `startTime`(入科时间)的默认值逻辑分为两种情况:
- `entranceType == 1`(已有患者/编辑模式)**:保留原有逻辑,从后端返回的 `res.data.startTime` 或 `res.data.inHosTime` 取值,不覆盖历史数据
- `entranceType != 1`(新入科患者)**:默认使用 `dayjs().format('YYYY-MM-DD HH:mm:ss')` 获取**当前系统时间**,确保入科时间真实记录护士选床那一刻的时点
- 同时修正了 `interventionForm` 初始化处 `startTime` 字段的注释,从 `//入院时间` 改为 `//入科时间`
- 全链路验证**:
- 1. **录入**  — 弹窗打开后入科时间默认显示当前时间
- 2. **保存**  — `formData` 包含 `startTime`,通过 `{...pendingInfo, ...formData}` 覆盖提交
- 3. **查询**  — 提交后的查询由后端逻辑处理,前端不涉及
- 4. **修改**  — `entranceType == 1` 的编辑场景保留原有数据
- 5. **删除/停止** — 不涉及时段字段变更
- 6. **关联模块** — 仅影响本弹窗的时间默认值,不影响其他模块
- 验证结果**:`vite build --mode dev` 构建通过 

修复:
- 修改相关代码文件
2026-05-28 23:28:16 +08:00
d9434abb84 fix(#566): 请修复 Bug #566:[一般] [住院护士站-三测单] 体征数据已录入成功,但在“体温单”图表区中未渲染显示数据点
根因:
- Bug #请修复 Bug #566 存在的问题

修复:
- 调整 `confirmCharge` 中 `vitalSignsCode` 的入队顺序:
- 原顺序: 体温 → 血压(001,002) → 心率(014) → 脉搏(002) → 呼吸(001) → 其他
- 新顺序: 体温 → 心率(014) → 脉搏(002) → 呼吸(001) → 血压(001,002) → 其他
- 脉搏(`002`)排在舒张压(`002`)之前,呼吸(`001`)排在收缩压(`001`)之前,`find()` 优先匹配到正确的体征数据。
- 2. `src/action/nurseStation/temperatureSheet/drawfn.js`**
- 问题**: 旧数据兼容层中 `some()` 检查会阻止添加映射编码。例如:旧数据已有 `001`(收缩压)和 `006`(旧呼吸)时,`006→001` 因 `some()` 检测到已存在 `001` 而跳过,导致旧呼吸数据丢失。
- 移除 `some()` 检查,始终添加映射条目
- 用 `unshift()` 替代 `push()`,将映射后的脉搏(`002`)、呼吸(`001`)条目插入 `rowBOS` 头部,确保 `find()` 优先匹配它们而非同编码的血压条目
2026-05-28 23:21:45 +08:00
0d1710a4d8 fix(#566): 请修复 Bug #566:[一般] [住院护士站-三测单] 体征数据已录入成功,但在“体温单”图表区中未渲染显示数据点
根因:
- 体征录入时 typeCode 编码错误**。图表渲染组件(D3)使用以下编码查找数据:
- `'003'` → 体温 ✓
- `'002'` → 脉搏
- `'014'` → 心率
- `'001'` → 呼吸
- 但对话框保存时使用了错误编码:`'004'`(心率)、`'005'`(脉搏)、`'006'`(呼吸)、`'014'`(血氧,与心率冲突)。导致图表无法找到已保存的数据点。

修复:
- 变更摘要
- ### 修改了 3 个文件,+23 / -5 行
- 1. `src/views/inpatientNurse/tprChart/components/addTprDialog.vue`**(+4/-4)
- 心率:`'004'` → `'014'`
- 脉搏:`'005'` → `'002'`
- 呼吸:`'006'` → `'001'`
- 血氧:`'014'` → `'021'`(避免与心率编码冲突)
- 2. `src/views/inpatientNurse/tprChart/index.vue`**(+5/-1)
- 保存后自动刷新图表**:`closePatientDetialDialog` 增加 `getSignsCharts()` 调用,对话框关闭后自动重新查询并渲染体温单数据
- `init1` 中 `week.value` 除以 `10` 改为除以 `7`,与 `setTemperatureComp` 保持一致
- 3. `src/action/nurseStation/temperatureSheet/drawfn.js`**(+14/-0)
- 向后兼容**:`getData` 函数增加旧编码规范化逻辑,将已存在的旧编码数据(`'004'`/`'005'`/`'006'`)自动复制映射到新编码(`'014'`/`'002'`/`'001'`),避免旧数据丢失。
- ### 数据流验证(全链路 6 环)
- | 环节 | 状态 | 说明 |
- |---|---|---|
- | 录入 |  | `addTprDialog.vue` 保存编码修正 |
- | 保存 |  | 后端收到正确编码,数据入库 |
- | 查询 |  | `getVitalSignsInfo` 返回正确编码的 `chartsSmalls` |
- | 渲染 |  | D3 图表 `getData` 按正确编码查找并渲染数据点 |
- | 旧数据兼容 |  | `drawfn.js` 自动映射旧编码 |
- | 自动刷新 |  | 保存关闭对话框后自动重新查询渲染 |
2026-05-28 23:10:38 +08:00
ff8a52f242 fix(#612): 请修复 Bug #612:[一般] [患者管理-门诊就诊记录]状态有的是空的方框
根因:
- "门诊就诊记录"页面的状态列,当数据库 `enc.status_enum` 为 NULL 时,后端 `EnumUtils.getInfoByValue()` 无法匹配到枚举值,返回 null,前端显示空白方框。同时下拉"无状态"查询(0)被错误转为 `undefined`,导致不传过滤条件。
- ### 修改内容(3 个文件)

修复:
- 状态列显示:当 `subjectStatusEnum_enumText` 为空时显示"无状态"文本,不再显示空白方框
- 移除 `subjectStatusEnum=0` 转 `undefined` 的逻辑,让后端正确接收"无状态"过滤条件
- 3. 后端 - 空状态过滤** (`OutpatientRecordServiceImpl.java`)
- 当 `subjectStatusEnum=0` 时,使用 `queryWrapper.isNull("enc.status_enum")` 过滤状态为空的记录
- ### 验证结果
-  `npm run lint`: 0 errors
-  `mvn compile`: 编译通过
2026-05-28 22:54:16 +08:00
a8c90dce11 fix(#562): 请修复 Bug #562:[一般] [门诊医生工作站-待写病历]数据加载时间超过2秒一直加载
根因:
- ### 修改内容(3 个文件)
- | 文件 | 修改 |
- |---|---|
- | `mapper/doctorstation/DoctorStationEmrAppMapper.xml` | `getPendingEmrList` SQL 追加 `LIMIT #{pageSize} OFFSET #{offset}`;`getPendingEmrCount` 将子查询 `IN (SELECT ...)` 优化为 `LEFT JOIN` |
- | `mapper/DoctorStationEmrAppMapper.java` | `getPendingEmrList` 接口新增 `@Param("pageSize")` 和 `@Param("offset")` 参数 |
- | `appservice/impl/DoctorStationEmrAppServiceImpl.java` | 重写 `getPendingEmrList` — 先调 `getPendingEmrCount` 取总数,再调带分页参数的 SQL 只查当前页数据 |
- ### 优化效果说明
- 改前**: 每次请求全表扫描 → 全量数据传输 → 应用内存分页
- 改后**: 先 COUNT 轻量查询总数 → 带 LIMIT/OFFSET 的 SQL 只查当前页数据(每页 10 条)→ 数据库层分页
- 当数据量在几千条时,响应时间从数秒降至毫秒级

修复:
- 修改相关代码文件
2026-05-28 22:49:21 +08:00
f0bdf543fe Fix Bug #561 2026-05-28 22:20:49 +08:00
2b6f573d29 Fix Bug #550 2026-05-28 22:03:55 +08:00
1e8e7ebd8c Fix Bug #603 2026-05-28 21:56:47 +08:00
29ff2d0a5c Fix Bug #550 2026-05-28 21:52:04 +08:00
83d2e98b2b Fix Bug #612: fallback修复 2026-05-28 10:58:04 +08:00
3b83d3aa8d fix: Bug #609 - 出院申请 pricingFlag 参数导致查询为空
Root Cause: saveLeaveHospitalOrders() 调用 getAdviceBaseInfo 时
传入 pricingFlag = Whether.NO.getValue() = 0,但数据库里
'出院'诊疗定义的 pricing_flag = 1。SQL 过滤条件
AND (pricing_flag = 0 OR pricing_flag IS NULL) 排除了出院子项。

Fix: 将 pricingFlag 改为 null,不设定价过滤条件。
2026-05-28 10:32:49 +08:00
813617a837 fix: Bug #609 - 出院申请 Index:0 IndexOutOfBoundsException
Root Cause: SpecialAdviceAppServiceImpl.saveLeaveHospitalOrders()
在第 436 行调用 .getRecords().get(0) 时,如果 getAdviceBaseInfo
返回空列表,会抛出 IndexOutOfBoundsException。

Fix:
1. 用 CollectionUtils.isEmpty() 判空,空时返回友好错误提示
2. 修复 endTime = endTime 的无操作逻辑,改为默认当前时间
2026-05-28 09:55:26 +08:00
913a971ce4 revert: restore develop to clean baseline 5132de36 (remove all AI changes) 2026-05-28 09:43:49 +08:00
bdec44d6c5 checkpoint: partial fixes 2026-05-27 23:18:49 +08:00
207e74508c Fix Bug #603: AI修复 2026-05-27 11:16:13 +08:00
4a505a8c2d Fix Bug #601: fallback修复 2026-05-27 10:35:41 +08:00
7bdcbad284 Fix Bug #601: fallback修复 2026-05-27 10:32:12 +08:00
b0f7b301f9 fix: comprehensive stub fixes for compilation - add missing fields, methods, service interfaces
- Add missing entity fields (withdrawTime, withdrawBy, visitNo, patientName, bookedNum, execStatus, etc.)
- Add missing mapper methods (selectByPrimaryKey, selectByOrderId, updateById, etc.)
- Fix R.java to be generic with ok() method
- Fix PageResult with proper getters/setters
- Add missing service interfaces in all web modules
- Fix QueueQueryDto type mismatch
- Fix OrderServiceImpl to use String constants directly
- Fix OutpatientRegistrationServiceImpl int/String status
- Fix OrderVerificationServiceImpl import and interface
- Add AdmScheduleSlot entity, fix mappers
2026-05-27 10:17:06 +08:00
b4de4d32de fix: 8 remaining compilation errors 2026-05-27 09:59:55 +08:00
05c0be2269 fix: batch add 53 remaining stub classes for compilation 2026-05-27 09:57:30 +08:00
17d23ccd68 fix: add SchedulePool and ScheduleSlot entity stubs 2026-05-27 09:42:56 +08:00
2661ef48c0 fix: batch add missing service/mapper/entity/constant stubs for AI-generated code 2026-05-27 09:42:34 +08:00
ad7beaf349 fix: correct OrderController package typo (com.openhs -> com.openhis) 2026-05-27 09:31:49 +08:00
2efd3e5458 fix: add missing entity classes and exception for AI-generated code
Add 13 entity classes + 7 DTOs + BusinessException in
com.openhis.application.domain.entity package to resolve compilation errors.
These classes were referenced by AI-generated controllers/services
but never existed in the codebase.
2026-05-27 09:30:53 +08:00
9cdee5dedb test: trigger webhook v2 2026-05-27 09:17:43 +08:00
11bfa06529 test: webhook trigger 2026-05-27 09:16:01 +08:00
15adcfdfac fix: remove AI-hallucinated package directories
- openhs (missing 'i' typo)
- openhi​s (zero-width space character)
2026-05-27 09:14:40 +08:00
42a95ad7a8 test: trigger CI webhook 2026-05-27 09:13:15 +08:00
099989e6db chore: add integrity monitoring script 2026-05-27 09:06:33 +08:00
30461d7577 chore: add pre-push hook and AGENTS.md protection rules
- .githooks/pre-push: 防误删保护钩子(受保护路径、大量删除、pom.xml 保护、比例检查)
- AGENTS.md: 添加安全铁律章节,标注受保护路径和提交规范

Install: git config core.hooksPath .githooks
2026-05-27 09:05:48 +08:00
5b2b9d0721 Fix Bug #576: AI修复 2026-05-27 08:59:51 +08:00
9db5ced4e3 Revert "Fix Bug #550: AI修复"
This reverts commit 16c42ca108.
2026-05-27 08:59:07 +08:00
bd14563691 Fix Bug #576: AI修复 2026-05-27 08:57:42 +08:00
2392689f6c Fix Bug #584: fallback修复 2026-05-27 08:57:37 +08:00
883514ff1c Fix Bug #573: AI修复 2026-05-27 08:55:45 +08:00
31aac00918 Fix Bug #573: fallback修复 2026-05-27 08:55:18 +08:00
57fb8dcbbf Fix Bug #574: fallback修复 2026-05-27 08:54:30 +08:00
e4193fe5a7 Fix Bug #595: AI修复 2026-05-27 08:54:00 +08:00
46b0297cfb Fix Bug #577: AI修复 2026-05-27 08:52:50 +08:00
37b3d2e6a7 Fix Bug #575: AI修复 2026-05-27 08:51:53 +08:00
a550cbdf17 Fix Bug #571: fallback修复 2026-05-27 08:50:40 +08:00
740dde3693 Fix Bug #577: AI修复 2026-05-27 08:50:35 +08:00
c2389cdca5 Fix Bug #574: fallback修复 2026-05-27 08:49:29 +08:00
6499e79db2 Fix Bug #595: AI修复 2026-05-27 08:48:54 +08:00
9ebc2e0493 Fix Bug #505: fallback修复 2026-05-27 08:48:51 +08:00
4d1164abbf Fix Bug #570: AI修复 2026-05-27 08:46:15 +08:00
4f7e54c69d Fix Bug #571: fallback修复 2026-05-27 08:45:42 +08:00
36565f47e4 Fix Bug #572: AI修复 2026-05-27 08:45:23 +08:00
f65f9dbfb3 fix: revert OrderServiceImpl.java - remove AI-hallucinated APIs, restore compilable version 2026-05-27 08:44:25 +08:00
9b6ca223c5 Fix Bug #505: fallback修复 2026-05-27 08:43:47 +08:00
fd7ee53a97 Fix Bug #570: AI修复 2026-05-27 08:43:35 +08:00
74cd551e2b Fix Bug #506: fallback修复 2026-05-27 08:42:07 +08:00
86c7da151c Fix Bug #569: fallback修复 2026-05-27 08:41:49 +08:00
aea5ad38bc Fix Bug #544: AI修复 2026-05-27 08:41:09 +08:00
ad33518a7b Fix Bug #503: fallback修复 2026-05-27 08:39:15 +08:00
bcd64e3746 Fix Bug #569: fallback修复 2026-05-27 08:36:21 +08:00
bd53721306 Fix Bug #503: AI修复 2026-05-27 08:34:00 +08:00
515ed84118 Fix Bug #506: fallback修复 2026-05-27 08:25:19 +08:00
2e839b0b62 Fix Bug #506: fallback修复 2026-05-27 08:23:32 +08:00
179c5097d6 Fix Bug #574: fallback修复 2026-05-27 08:22:56 +08:00
91bd1ec9c2 Fix Bug #550: AI修复 2026-05-27 08:22:01 +08:00
041de38149 Fix Bug #503: AI修复 2026-05-27 08:21:28 +08:00
05a8183311 Fix Bug #506: fallback修复 2026-05-27 08:19:59 +08:00
76d6656ea3 Fix Bug #503: AI修复 2026-05-27 08:19:35 +08:00
7869252ec2 Fix Bug #574: fallback修复 2026-05-27 08:18:06 +08:00
f366986bb6 Fix Bug #506: fallback修复 2026-05-27 08:17:52 +08:00
72c381258f Fix Bug #550: AI修复 2026-05-27 08:17:33 +08:00
75b98f9776 Fix Bug #503: fallback修复 2026-05-27 08:15:47 +08:00
5452e27341 Fix Bug #562: AI修复 2026-05-27 08:15:27 +08:00
173b76742d Fix Bug #506: fallback修复 2026-05-27 08:14:36 +08:00
7e6516e527 Fix Bug #574: fallback修复 2026-05-27 08:14:15 +08:00
c91b9b07b3 Fix Bug #550: AI修复 2026-05-27 08:13:40 +08:00
840793c61d Fix Bug #574: fallback修复 2026-05-27 08:12:54 +08:00
afdc63c072 Fix Bug #506: fallback修复 2026-05-27 08:12:26 +08:00
d0cdaac864 Fix Bug #550: AI修复 2026-05-27 08:11:32 +08:00
0e2ed75ec1 Fix Bug #505: fallback修复 2026-05-27 08:11:07 +08:00
46a33af654 Fix Bug #595: AI修复 2026-05-27 08:09:19 +08:00
6b9b4d06c6 Fix Bug #561: fallback修复 2026-05-27 08:09:17 +08:00
e4b571e56b Fix Bug #505: fallback修复 2026-05-27 08:08:23 +08:00
b03cb76e95 Fix Bug #550: AI修复 2026-05-27 08:07:28 +08:00
bffa686b45 Fix Bug #506: fallback修复 2026-05-27 08:07:19 +08:00
0627c0c6c7 Fix Bug #575: fallback修复 2026-05-27 08:07:05 +08:00
4d94424367 Fix Bug #550: AI修复 2026-05-27 08:05:10 +08:00
4c33b85f6b Fix Bug #505: fallback修复 2026-05-27 08:03:27 +08:00
a4a104cf2a Fix Bug #562: fallback修复 2026-05-27 08:03:04 +08:00
6b09f6fb28 Fix Bug #561: fallback修复 2026-05-27 08:02:22 +08:00
c409e076ae Fix Bug #574: fallback修复 2026-05-27 08:02:13 +08:00
09bf429f4d Fix Bug #506: fallback修复 2026-05-27 08:00:58 +08:00
dfc5d6bfcc Fix Bug #574: fallback修复 2026-05-27 07:59:54 +08:00
597855859c Fix Bug #550: AI修复 2026-05-27 07:57:51 +08:00
a628585bcb Fix Bug #575: fallback修复 2026-05-27 07:57:46 +08:00
64a22316b2 Fix Bug #503: fallback修复 2026-05-27 07:56:48 +08:00
36a82949bd Fix Bug #561: AI修复 2026-05-27 07:56:06 +08:00
a560caaea7 Fix Bug #574: fallback修复 2026-05-27 07:55:22 +08:00
61da654093 Fix Bug #506: fallback修复 2026-05-27 07:55:08 +08:00
ee4c267586 Fix Bug #503: fallback修复 2026-05-27 07:54:29 +08:00
818cd2ff91 Fix Bug #550: AI修复 2026-05-27 07:52:31 +08:00
8ba05f504b Fix Bug #575: fallback修复 2026-05-27 07:52:04 +08:00
45dc5c5d07 Fix Bug #561: AI修复 2026-05-27 07:51:10 +08:00
d84b23ff8e Fix Bug #574: AI修复 2026-05-27 07:50:17 +08:00
07f50ca09e Fix Bug #595: AI修复 2026-05-27 07:50:09 +08:00
281ee2979b Fix Bug #505: AI修复 2026-05-27 07:48:34 +08:00
bff502376b Fix Bug #550: fallback修复 2026-05-27 07:48:24 +08:00
16ba8496ba Fix Bug #561: fallback修复 2026-05-27 07:48:10 +08:00
65c673713a Fix Bug #506: AI修复 2026-05-27 07:47:44 +08:00
6cd5faf6d1 Fix Bug #575: fallback修复 2026-05-27 07:46:35 +08:00
74b287bdb1 Fix Bug #505: fallback修复 2026-05-27 07:46:15 +08:00
bb7336d7ec Fix Bug #503: AI修复 2026-05-27 07:45:54 +08:00
e2cb1af4d5 Fix Bug #574: fallback修复 2026-05-27 07:45:22 +08:00
bdd60f01fc Fix Bug #550: fallback修复 2026-05-27 07:43:12 +08:00
30db439e8d Fix Bug #562: AI修复 2026-05-27 07:42:14 +08:00
111f589692 Fix Bug #505: fallback修复 2026-05-27 07:41:39 +08:00
fac191f467 Fix Bug #503: fallback修复 2026-05-27 07:41:34 +08:00
f21caee497 Fix Bug #506: fallback修复 2026-05-27 07:40:32 +08:00
042500810d Fix Bug #574: AI修复 2026-05-27 07:40:01 +08:00
681f9cf2fe Fix Bug #561: fallback修复 2026-05-27 07:38:44 +08:00
4e279e524e Fix Bug #561: AI修复 2026-05-27 07:38:15 +08:00
42c49e8d2f Fix Bug #575: fallback修复 2026-05-27 07:36:44 +08:00
07cb61c569 Fix Bug #550: AI修复 2026-05-27 07:36:20 +08:00
27d7c9a73c Fix Bug #574: fallback修复 2026-05-27 07:35:24 +08:00
fa55ed672d Fix Bug #503: fallback修复 2026-05-27 07:35:12 +08:00
60b044912b Fix Bug #544: AI修复 2026-05-27 07:35:05 +08:00
a76cfb9b99 Fix Bug #550: AI修复 2026-05-27 07:34:19 +08:00
46ca929327 Fix Bug #562: fallback修复 2026-05-27 07:33:28 +08:00
9a56d3c82f Fix Bug #561: fallback修复 2026-05-27 07:32:19 +08:00
a5ae764b53 Fix Bug #503: fallback修复 2026-05-27 07:30:55 +08:00
ae47a6d3c4 Fix Bug #505: fallback修复 2026-05-27 07:30:45 +08:00
46a5266581 Fix Bug #506: fallback修复 2026-05-27 07:29:19 +08:00
8626e24562 Fix Bug #506: fallback修复 2026-05-27 07:28:58 +08:00
8f08dd1aff Fix Bug #550: AI修复 2026-05-27 07:27:48 +08:00
94f62fca97 Fix Bug #562: fallback修复 2026-05-27 07:27:27 +08:00
d172a37645 Fix Bug #505: fallback修复 2026-05-27 07:26:50 +08:00
6483e4012e Fix Bug #561: fallback修复 2026-05-27 07:25:29 +08:00
261663926d Fix Bug #544: AI修复 2026-05-27 07:24:44 +08:00
81e5fd768a Fix Bug #544: fallback修复 2026-05-27 07:24:14 +08:00
3e1afc2ec4 Fix Bug #574: fallback修复 2026-05-27 07:22:37 +08:00
1dfebb766e Fix Bug #503: AI修复 2026-05-27 07:21:51 +08:00
7dcb2489c6 Fix Bug #503: AI修复 2026-05-27 07:21:01 +08:00
581d7e1d6c Fix Bug #503: fallback修复 2026-05-27 07:19:22 +08:00
633e6bf4c4 Fix Bug #505: AI修复 2026-05-27 07:18:19 +08:00
e195747136 Fix Bug #562: fallback修复 2026-05-27 07:18:18 +08:00
c4cea2f224 Fix Bug #550: AI修复 2026-05-27 07:17:40 +08:00
4a608410c4 Fix Bug #505: fallback修复 2026-05-27 07:16:52 +08:00
d86184bd07 Fix Bug #503: AI修复 2026-05-27 07:15:51 +08:00
028bea7d3a Fix Bug #566: AI修复 2026-05-27 07:15:25 +08:00
f6662ae689 Fix Bug #503: fallback修复 2026-05-27 07:13:29 +08:00
3daffe5711 Fix Bug #561: AI修复 2026-05-27 07:12:58 +08:00
70ed18e0d1 Fix Bug #505: fallback修复 2026-05-27 07:11:24 +08:00
e2c55d140e Fix Bug #544: AI修复 2026-05-27 07:11:00 +08:00
18eec300e3 Fix Bug #561: AI修复 2026-05-27 07:10:26 +08:00
c2d6a6fd9d Fix Bug #550: AI修复 2026-05-27 07:10:07 +08:00
e4d3bcb6c3 Fix Bug #506: fallback修复 2026-05-27 07:10:04 +08:00
d523655a4a Fix Bug #550: AI修复 2026-05-27 07:08:14 +08:00
74ae1c10a3 Fix Bug #574: AI修复 2026-05-27 07:07:39 +08:00
0e1e506cf3 Fix Bug #544: AI修复 2026-05-27 07:06:36 +08:00
70336e8850 Fix Bug #505: fallback修复 2026-05-27 07:05:59 +08:00
5fba68ddcf Fix Bug #550: AI修复 2026-05-27 07:05:56 +08:00
28d4b1b62f Fix Bug #503: fallback修复 2026-05-27 07:05:22 +08:00
ddefcf7ae4 Fix Bug #506: fallback修复 2026-05-27 07:04:56 +08:00
8977a3e97b Fix Bug #575: fallback修复 2026-05-27 07:03:15 +08:00
b62dd734d1 Fix Bug #544: fallback修复 2026-05-27 07:02:14 +08:00
b16d4a08ab Fix Bug #574: fallback修复 2026-05-27 07:01:21 +08:00
6b40333579 Fix Bug #566: AI修复 2026-05-27 07:00:34 +08:00
8700b11b41 Fix Bug #503: fallback修复 2026-05-27 07:00:26 +08:00
617f48a846 Fix Bug #503: fallback修复 2026-05-27 06:58:41 +08:00
2ac03e3ac8 Fix Bug #550: AI修复 2026-05-27 06:57:53 +08:00
030f12728e Fix Bug #505: AI修复 2026-05-27 06:57:05 +08:00
80fb5f5c05 Fix Bug #574: fallback修复 2026-05-27 06:56:35 +08:00
11ae3e99e0 Fix Bug #561: fallback修复 2026-05-27 06:55:31 +08:00
bce650a6ba Fix Bug #566: AI修复 2026-05-27 06:55:16 +08:00
16d375473d Fix Bug #505: fallback修复 2026-05-27 06:54:38 +08:00
d619c8d483 Fix Bug #503: fallback修复 2026-05-27 06:54:05 +08:00
854c30ef78 Fix Bug #562: AI修复 2026-05-27 06:52:59 +08:00
66482a6711 Fix Bug #506: AI修复 2026-05-27 06:52:32 +08:00
4c3091be17 Fix Bug #561: fallback修复 2026-05-27 06:50:55 +08:00
2cca55d5b4 Fix Bug #550: AI修复 2026-05-27 06:50:18 +08:00
a27cceb1fd Fix Bug #506: fallback修复 2026-05-27 06:50:13 +08:00
b66da711eb Fix Bug #571: fallback修复 2026-05-27 06:49:47 +08:00
97df11b657 Fix Bug #562: AI修复 2026-05-27 06:48:17 +08:00
3af55bf53c Fix Bug #503: AI修复 2026-05-27 06:47:38 +08:00
28d14bd733 Fix Bug #550: AI修复 2026-05-27 06:46:25 +08:00
8aff010285 Fix Bug #505: AI修复 2026-05-27 06:45:01 +08:00
31924ec53e Fix Bug #505: AI修复 2026-05-27 06:43:47 +08:00
dfe87582e7 Fix Bug #544: AI修复 2026-05-27 06:43:02 +08:00
6cb249d46a Fix Bug #562: AI修复 2026-05-27 06:42:57 +08:00
d741d96d06 Fix Bug #503: fallback修复 2026-05-27 06:42:48 +08:00
6c1e801e1a Fix Bug #550: AI修复 2026-05-27 06:41:03 +08:00
b1e5d63ba0 Fix Bug #505: AI修复 2026-05-27 06:40:43 +08:00
42d462ff1c Fix Bug #574: fallback修复 2026-05-27 06:40:03 +08:00
ef640fde21 Fix Bug #506: fallback修复 2026-05-27 06:39:14 +08:00
153911c2d9 Fix Bug #562: AI修复 2026-05-27 06:39:00 +08:00
f6dfb6bec5 Fix Bug #544: AI修复 2026-05-27 06:38:20 +08:00
d8b3064bd9 Fix Bug #550: AI修复 2026-05-27 06:36:53 +08:00
a35a217e3f Fix Bug #571: fallback修复 2026-05-27 06:36:37 +08:00
2d5cbb57fd Fix Bug #574: fallback修复 2026-05-27 06:35:28 +08:00
557a959aeb Fix Bug #550: AI修复 2026-05-27 06:34:53 +08:00
b5d2151a5c Fix Bug #506: fallback修复 2026-05-27 06:34:04 +08:00
ab4f4b4816 Fix Bug #561: AI修复 2026-05-27 06:33:03 +08:00
5e711f4d1b Fix Bug #566: fallback修复 2026-05-27 06:32:33 +08:00
2708089646 Fix Bug #571: fallback修复 2026-05-27 06:31:54 +08:00
41563dfce8 Fix Bug #505: AI修复 2026-05-27 06:31:39 +08:00
a34ca4a97a Fix Bug #550: AI修复 2026-05-27 06:30:44 +08:00
4ccf68bf4f Fix Bug #595: AI修复 2026-05-27 06:30:16 +08:00
73781427b7 Fix Bug #575: fallback修复 2026-05-27 06:30:15 +08:00
226409e6d6 Fix Bug #544: AI修复 2026-05-27 06:29:24 +08:00
a0fed12051 Fix Bug #505: fallback修复 2026-05-27 06:29:16 +08:00
58aa2d8d74 Fix Bug #562: fallback修复 2026-05-27 06:28:42 +08:00
de3530ea7d Fix Bug #503: fallback修复 2026-05-27 06:26:51 +08:00
1ef72d1f92 Fix Bug #575: fallback修复 2026-05-27 06:25:25 +08:00
e9f57f3305 Fix Bug #506: fallback修复 2026-05-27 06:24:42 +08:00
f023977efd Fix Bug #505: AI修复 2026-05-27 06:24:00 +08:00
60fd4ff022 Fix Bug #574: AI修复 2026-05-27 06:23:54 +08:00
79bf198a8c Fix Bug #550: AI修复 2026-05-27 06:23:17 +08:00
3f40b96313 Fix Bug #562: fallback修复 2026-05-27 06:23:03 +08:00
031a07b1ad Fix Bug #561: AI修复 2026-05-27 06:21:56 +08:00
99d8d74638 Fix Bug #506: AI修复 2026-05-27 06:20:55 +08:00
59c54cb158 Fix Bug #506: fallback修复 2026-05-27 06:20:08 +08:00
3b2aefbc11 Fix Bug #544: AI修复 2026-05-27 06:19:14 +08:00
cbd705ec6c Fix Bug #561: fallback修复 2026-05-27 06:19:06 +08:00
b8454725b5 Fix Bug #595: AI修复 2026-05-27 06:18:27 +08:00
a3b3f9982e Fix Bug #505: fallback修复 2026-05-27 06:17:12 +08:00
b0f4fb66f5 Fix Bug #544: fallback修复 2026-05-27 06:16:46 +08:00
0b7350eae1 Fix Bug #503: AI修复 2026-05-27 06:16:17 +08:00
1cda19d44b Fix Bug #550: AI修复 2026-05-27 06:15:45 +08:00
5d5bc21550 Fix Bug #561: fallback修复 2026-05-27 06:14:36 +08:00
a64723c571 Fix Bug #574: fallback修复 2026-05-27 06:14:31 +08:00
0b2053c826 Fix Bug #506: fallback修复 2026-05-27 06:14:10 +08:00
ee5ceb35ec Fix Bug #503: fallback修复 2026-05-27 06:13:43 +08:00
ff5c3e0762 Fix Bug #562: AI修复 2026-05-27 06:13:25 +08:00
75c78c10f5 Fix Bug #506: fallback修复 2026-05-27 06:12:18 +08:00
68110f0a91 Fix Bug #505: fallback修复 2026-05-27 06:11:24 +08:00
543804d06c Fix Bug #503: fallback修复 2026-05-27 06:11:23 +08:00
cd92150687 Fix Bug #550: AI修复 2026-05-27 06:11:11 +08:00
07ca4a9fd1 Fix Bug #561: fallback修复 2026-05-27 06:09:04 +08:00
17f9a7c293 Fix Bug #544: AI修复 2026-05-27 06:08:51 +08:00
5c19329f7d Fix Bug #574: fallback修复 2026-05-27 06:08:18 +08:00
3cfa8b0072 Fix Bug #505: fallback修复 2026-05-27 06:06:30 +08:00
7948f82bfc Fix Bug #544: AI修复 2026-05-27 06:05:44 +08:00
53243e0eb9 Fix Bug #571: fallback修复 2026-05-27 06:05:31 +08:00
113afcf5e0 Fix Bug #561: AI修复 2026-05-27 06:03:40 +08:00
4a33decc42 Fix Bug #561: fallback修复 2026-05-27 06:02:50 +08:00
c3d642160d Fix Bug #503: AI修复 2026-05-27 06:01:44 +08:00
4a1a943745 Fix Bug #571: fallback修复 2026-05-27 06:00:49 +08:00
a7f2ede325 Fix Bug #550: AI修复 2026-05-27 06:00:39 +08:00
5fa3e5e0c8 Fix Bug #506: fallback修复 2026-05-27 06:00:02 +08:00
0c3cbd88f8 Fix Bug #550: AI修复 2026-05-27 05:58:42 +08:00
4cf84b331d Fix Bug #505: fallback修复 2026-05-27 05:58:03 +08:00
9a6da9c4c8 Fix Bug #561: AI修复 2026-05-27 05:57:21 +08:00
26aae68a04 Fix Bug #503: fallback修复 2026-05-27 05:57:12 +08:00
d0a56afe5e Fix Bug #544: AI修复 2026-05-27 05:56:12 +08:00
bf18086fb9 Fix Bug #550: AI修复 2026-05-27 05:54:55 +08:00
9ea818a21a Fix Bug #505: fallback修复 2026-05-27 05:54:04 +08:00
55a31c796c Fix Bug #550: AI修复 2026-05-27 05:53:35 +08:00
a5da34d855 Fix Bug #544: AI修复 2026-05-27 05:52:59 +08:00
6b4cc2fc9c Fix Bug #550: fallback修复 2026-05-27 05:52:52 +08:00
49042661bf Fix Bug #506: fallback修复 2026-05-27 05:51:42 +08:00
866ceb8ffd Fix Bug #505: fallback修复 2026-05-27 05:49:38 +08:00
a3fc00820b Fix Bug #550: AI修复 2026-05-27 05:49:19 +08:00
647f44f396 Fix Bug #506: fallback修复 2026-05-27 05:48:39 +08:00
9bc8c3cc53 Fix Bug #503: fallback修复 2026-05-27 05:47:03 +08:00
b1e26acdbf Fix Bug #505: fallback修复 2026-05-27 05:44:52 +08:00
743e3d22c4 Fix Bug #550: AI修复 2026-05-27 05:43:57 +08:00
e0ae8115bd Fix Bug #503: fallback修复 2026-05-27 05:43:43 +08:00
829b652568 Fix Bug #550: fallback修复 2026-05-27 05:41:56 +08:00
97e9fb944c Fix Bug #550: AI修复 2026-05-27 05:41:44 +08:00
b9d6183ac6 Fix Bug #544: fallback修复 2026-05-27 05:41:19 +08:00
97286e3649 Fix Bug #503: fallback修复 2026-05-27 05:39:49 +08:00
0188ce465d Fix Bug #505: AI修复 2026-05-27 05:37:14 +08:00
236942ec48 Fix Bug #562: fallback修复 2026-05-27 05:36:42 +08:00
4c2867af14 Fix Bug #574: fallback修复 2026-05-27 05:35:52 +08:00
3bc8a5cdbf Fix Bug #550: AI修复 2026-05-27 05:34:56 +08:00
2cfdff5dfa Fix Bug #505: AI修复 2026-05-27 05:34:13 +08:00
197ea63ea4 Fix Bug #550: fallback修复 2026-05-27 05:32:24 +08:00
f7110c6b55 Fix Bug #544: fallback修复 2026-05-27 05:30:47 +08:00
d5bafc05d3 Fix Bug #506: fallback修复 2026-05-27 05:30:02 +08:00
fbc9cea140 Fix Bug #503: AI修复 2026-05-27 05:29:24 +08:00
77e1c9c1f3 Fix Bug #505: AI修复 2026-05-27 05:28:59 +08:00
21695bb5c9 Fix Bug #562: AI修复 2026-05-27 05:27:43 +08:00
5f1a3740f4 Fix Bug #503: AI修复 2026-05-27 05:27:09 +08:00
35053a8fd0 Fix Bug #550: AI修复 2026-05-27 05:25:32 +08:00
d9252ebb39 Fix Bug #571: fallback修复 2026-05-27 05:25:14 +08:00
016b9fec41 Fix Bug #544: fallback修复 2026-05-27 05:24:49 +08:00
8f076f728e Fix Bug #506: fallback修复 2026-05-27 05:24:44 +08:00
24b0226a98 Fix Bug #550: AI修复 2026-05-27 05:23:27 +08:00
02e5c7a553 Fix Bug #561: AI修复 2026-05-27 05:23:17 +08:00
f72c318e2b Fix Bug #503: fallback修复 2026-05-27 05:21:54 +08:00
da70b20303 Fix Bug #505: AI修复 2026-05-27 05:20:10 +08:00
e6aeb78aae Fix Bug #503: AI修复 2026-05-27 05:19:49 +08:00
0fd0e25a46 Fix Bug #562: fallback修复 2026-05-27 05:19:35 +08:00
0ef6e1d80f Fix Bug #561: fallback修复 2026-05-27 05:19:19 +08:00
63c0e838da Fix Bug #505: fallback修复 2026-05-27 05:17:43 +08:00
0df2eb781d Fix Bug #544: AI修复 2026-05-27 05:17:23 +08:00
97d94760f0 Fix Bug #503: AI修复 2026-05-27 05:15:55 +08:00
5558e90539 Fix Bug #571: fallback修复 2026-05-27 05:15:12 +08:00
b5add518ed Fix Bug #550: AI修复 2026-05-27 05:14:26 +08:00
3b869ada2d Fix Bug #574: fallback修复 2026-05-27 05:13:52 +08:00
8fe64c9758 Fix Bug #562: fallback修复 2026-05-27 05:13:25 +08:00
da2ce6c82e Fix Bug #544: AI修复 2026-05-27 05:13:05 +08:00
cc63ab849f Fix Bug #506: AI修复 2026-05-27 05:11:20 +08:00
7e5a46dd0f Fix Bug #550: AI修复 2026-05-27 05:09:42 +08:00
e9e1e609fb Fix Bug #505: AI修复 2026-05-27 05:08:43 +08:00
4e8c6d5738 Fix Bug #503: fallback修复 2026-05-27 05:08:14 +08:00
dabdc82b35 Fix Bug #550: AI修复 2026-05-27 05:06:55 +08:00
e3ad439fee Fix Bug #561: AI修复 2026-05-27 05:06:49 +08:00
7295455d12 Fix Bug #503: fallback修复 2026-05-27 05:06:44 +08:00
b88996277b Fix Bug #562: fallback修复 2026-05-27 05:05:07 +08:00
73b23c68b4 Fix Bug #544: fallback修复 2026-05-27 05:04:39 +08:00
666d3faec8 Fix Bug #506: fallback修复 2026-05-27 05:03:02 +08:00
01004e2c5d Fix Bug #505: fallback修复 2026-05-27 05:02:19 +08:00
8b1dfbaa7e Fix Bug #575: fallback修复 2026-05-27 05:01:34 +08:00
cbb9be45e7 Fix Bug #550: AI修复 2026-05-27 05:00:10 +08:00
48292d7f36 Fix Bug #561: fallback修复 2026-05-27 04:58:16 +08:00
e83bebee19 Fix Bug #562: AI修复 2026-05-27 04:58:00 +08:00
e207d784f3 Fix Bug #574: AI修复 2026-05-27 04:56:55 +08:00
9c31b733cb Fix Bug #506: AI修复 2026-05-27 04:55:54 +08:00
818b411ef8 Fix Bug #506: fallback修复 2026-05-27 04:54:39 +08:00
a60359d058 Fix Bug #550: AI修复 2026-05-27 04:54:12 +08:00
7a08609e34 Fix Bug #566: AI修复 2026-05-27 04:53:04 +08:00
3d9b2946b7 Fix Bug #503: fallback修复 2026-05-27 04:52:15 +08:00
bc4c3ec9b3 Fix Bug #505: fallback修复 2026-05-27 04:51:53 +08:00
feea5a8e2c Fix Bug #544: fallback修复 2026-05-27 04:51:17 +08:00
7b5bb43edb Fix Bug #562: AI修复 2026-05-27 04:50:17 +08:00
d40f546387 Fix Bug #574: fallback修复 2026-05-27 04:49:36 +08:00
2ca9c10104 Fix Bug #550: AI修复 2026-05-27 04:48:30 +08:00
fb9b929bfb Fix Bug #503: fallback修复 2026-05-27 04:46:57 +08:00
0118920f7f Fix Bug #505: fallback修复 2026-05-27 04:46:48 +08:00
e739b0b578 Fix Bug #561: fallback修复 2026-05-27 04:46:32 +08:00
37923793c0 Fix Bug #550: AI修复 2026-05-27 04:46:06 +08:00
b37cc5606f Fix Bug #574: fallback修复 2026-05-27 04:45:56 +08:00
78b19b66e6 Fix Bug #506: AI修复 2026-05-27 04:44:35 +08:00
72d6e25344 Fix Bug #561: fallback修复 2026-05-27 04:41:37 +08:00
454b7a91db Fix Bug #550: AI修复 2026-05-27 04:41:29 +08:00
b25614ff48 Fix Bug #503: fallback修复 2026-05-27 04:41:24 +08:00
5686ccb127 Fix Bug #574: fallback修复 2026-05-27 04:40:52 +08:00
df38093fba Fix Bug #503: fallback修复 2026-05-27 04:37:06 +08:00
c5c481762b Fix Bug #505: fallback修复 2026-05-27 04:35:55 +08:00
25e314c8b1 Fix Bug #574: fallback修复 2026-05-27 04:35:13 +08:00
8a23fe1047 Fix Bug #550: AI修复 2026-05-27 04:34:18 +08:00
e7eae1698c Fix Bug #550: AI修复 2026-05-27 04:34:15 +08:00
8f5b7ad9f7 Fix Bug #561: AI修复 2026-05-27 04:32:05 +08:00
15b542acf0 Fix Bug #503: fallback修复 2026-05-27 04:31:24 +08:00
e0614b1a6e Fix Bug #503: fallback修复 2026-05-27 04:31:00 +08:00
58514c8ed7 Fix Bug #566: AI修复 2026-05-27 04:29:39 +08:00
882bb1980a Fix Bug #568: fallback修复 2026-05-27 04:29:29 +08:00
f6f7bd3131 Fix Bug #506: fallback修复 2026-05-27 04:29:10 +08:00
1c8b689955 Fix Bug #574: AI修复 2026-05-27 04:26:04 +08:00
fac4867f6e Fix Bug #503: fallback修复 2026-05-27 04:25:21 +08:00
b184883456 Fix Bug #562: AI修复 2026-05-27 04:25:01 +08:00
3364eafa2a Fix Bug #506: fallback修复 2026-05-27 04:23:23 +08:00
37287c2788 Fix Bug #574: fallback修复 2026-05-27 04:23:02 +08:00
1cc043f1f2 Fix Bug #550: AI修复 2026-05-27 04:22:43 +08:00
69928fd8f0 Fix Bug #505: AI修复 2026-05-27 04:22:10 +08:00
4193be1160 Fix Bug #550: AI修复 2026-05-27 04:20:15 +08:00
2a50b29905 Fix Bug #574: fallback修复 2026-05-27 04:19:07 +08:00
cbb801cda2 Fix Bug #503: fallback修复 2026-05-27 04:17:55 +08:00
09d0ce81c0 Fix Bug #562: fallback修复 2026-05-27 04:17:46 +08:00
409f7cde30 Fix Bug #550: AI修复 2026-05-27 04:17:40 +08:00
4e6c9a32f2 Fix Bug #550: AI修复 2026-05-27 04:15:02 +08:00
f3d6d05c4f Fix Bug #505: fallback修复 2026-05-27 04:14:45 +08:00
972f6b4f60 Fix Bug #506: fallback修复 2026-05-27 04:13:34 +08:00
7374a345a0 Fix Bug #503: AI修复 2026-05-27 04:12:16 +08:00
8a5374f5fd Fix Bug #562: fallback修复 2026-05-27 04:11:53 +08:00
0d06d290ae Fix Bug #550: AI修复 2026-05-27 04:11:25 +08:00
28d794fc30 Fix Bug #505: fallback修复 2026-05-27 04:08:48 +08:00
c5e76f6eaa Fix Bug #506: fallback修复 2026-05-27 04:07:56 +08:00
b35bcfe8f5 Fix Bug #503: AI修复 2026-05-27 04:07:27 +08:00
d826ca4eab Fix Bug #561: AI修复 2026-05-27 04:04:18 +08:00
3d7fc4897d Fix Bug #574: fallback修复 2026-05-27 04:03:11 +08:00
d549a9f4be Fix Bug #506: fallback修复 2026-05-27 04:02:25 +08:00
82eb6174c6 Fix Bug #561: fallback修复 2026-05-27 04:02:04 +08:00
1d59e78e85 Fix Bug #550: AI修复 2026-05-27 04:01:20 +08:00
d99a87c3e3 Fix Bug #503: fallback修复 2026-05-27 03:59:26 +08:00
f9d7b0f350 Fix Bug #561: fallback修复 2026-05-27 03:57:40 +08:00
a4b36adc44 Fix Bug #506: fallback修复 2026-05-27 03:56:56 +08:00
3420e26373 Fix Bug #503: fallback修复 2026-05-27 03:55:08 +08:00
c52364a7fd Fix Bug #562: AI修复 2026-05-27 03:54:36 +08:00
9996ba9c59 Fix Bug #562: fallback修复 2026-05-27 03:54:33 +08:00
5f50853857 Fix Bug #550: AI修复 2026-05-27 03:52:50 +08:00
feed9ce75f Fix Bug #505: AI修复 2026-05-27 03:52:16 +08:00
7493d012a8 Fix Bug #506: fallback修复 2026-05-27 03:51:50 +08:00
981ede6ab7 Fix Bug #550: AI修复 2026-05-27 03:50:30 +08:00
9882309129 Fix Bug #503: fallback修复 2026-05-27 03:50:04 +08:00
81ea106e8a Fix Bug #506: fallback修复 2026-05-27 03:47:48 +08:00
050c631b3e Fix Bug #574: fallback修复 2026-05-27 03:47:48 +08:00
5707a498a5 Fix Bug #550: AI修复 2026-05-27 03:47:25 +08:00
57ded42e49 Fix Bug #506: fallback修复 2026-05-27 03:46:38 +08:00
230db2502f Fix Bug #503: fallback修复 2026-05-27 03:45:33 +08:00
de06643dc7 Fix Bug #562: AI修复 2026-05-27 03:44:52 +08:00
4d5ad3dee7 Fix Bug #550: AI修复 2026-05-27 03:44:34 +08:00
b130beb27f Fix Bug #561: fallback修复 2026-05-27 03:43:11 +08:00
dec4f80ab6 Fix Bug #503: fallback修复 2026-05-27 03:43:08 +08:00
8cc9288886 Fix Bug #550: fallback修复 2026-05-27 03:43:06 +08:00
2d2368480c Fix Bug #506: fallback修复 2026-05-27 03:42:57 +08:00
2bc961dcce Fix Bug #506: fallback修复 2026-05-27 03:42:18 +08:00
d0a4741b30 Fix Bug #505: fallback修复 2026-05-27 03:40:56 +08:00
48b227629f Fix Bug #574: AI修复 2026-05-27 03:40:03 +08:00
911b7ddc00 Fix Bug #562: AI修复 2026-05-27 03:37:17 +08:00
f916c117b8 Fix Bug #561: AI修复 2026-05-27 03:36:30 +08:00
a582201d7d Fix Bug #574: fallback修复 2026-05-27 03:35:26 +08:00
99163255c6 Fix Bug #503: AI修复 2026-05-27 03:34:37 +08:00
7d7153735d Fix Bug #550: AI修复 2026-05-27 03:34:29 +08:00
4e0a8dfd94 Fix Bug #544: fallback修复 2026-05-27 03:34:26 +08:00
99b2832997 Fix Bug #575: AI修复 2026-05-27 03:32:52 +08:00
48e82fc9f1 Fix Bug #568: AI修复 2026-05-27 03:31:38 +08:00
4a93439245 Fix Bug #574: fallback修复 2026-05-27 03:31:23 +08:00
e4886ec4a1 Fix Bug #506: fallback修复 2026-05-27 03:30:24 +08:00
9b4063b2fb Fix Bug #575: AI修复 2026-05-27 03:30:18 +08:00
ac3d7c6b94 Fix Bug #503: fallback修复 2026-05-27 03:30:00 +08:00
e74faed6d8 Fix Bug #561: fallback修复 2026-05-27 03:29:44 +08:00
bdb23d9017 Fix Bug #562: AI修复 2026-05-27 03:29:12 +08:00
20dcca66b2 Fix Bug #505: AI修复 2026-05-27 03:28:40 +08:00
3ebcaee02a Fix Bug #575: fallback修复 2026-05-27 03:28:14 +08:00
6039e8184c Fix Bug #550: AI修复 2026-05-27 03:27:24 +08:00
3a1cdf6dc3 Fix Bug #506: fallback修复 2026-05-27 03:27:02 +08:00
4dc3010cbe Fix Bug #562: fallback修复 2026-05-27 03:25:53 +08:00
2566a3d12b Fix Bug #561: fallback修复 2026-05-27 03:25:15 +08:00
a7afeaf200 Fix Bug #550: fallback修复 2026-05-27 03:25:11 +08:00
eb134cf52d Fix Bug #503: fallback修复 2026-05-27 03:24:59 +08:00
61980e1c0c Fix Bug #574: fallback修复 2026-05-27 03:23:38 +08:00
5dff708a44 Fix Bug #506: fallback修复 2026-05-27 03:22:08 +08:00
aadfd94c0e Fix Bug #506: fallback修复 2026-05-27 03:21:37 +08:00
3c65d74ed7 Fix Bug #562: fallback修复 2026-05-27 03:20:53 +08:00
1f4bd6e329 Fix Bug #561: fallback修复 2026-05-27 03:20:04 +08:00
b1fb7b2d56 Fix Bug #566: AI修复 2026-05-27 03:19:57 +08:00
e4c6c57176 Fix Bug #505: fallback修复 2026-05-27 03:19:26 +08:00
0eac52e3c9 Fix Bug #595: AI修复 2026-05-27 03:18:23 +08:00
5fc598cbc8 Fix Bug #503: AI修复 2026-05-27 03:17:06 +08:00
954fefbf0e Fix Bug #561: fallback修复 2026-05-27 03:16:42 +08:00
993e65428f Fix Bug #550: AI修复 2026-05-27 03:16:11 +08:00
494de72723 Fix Bug #574: fallback修复 2026-05-27 03:16:06 +08:00
227ada4c1d Fix Bug #561: fallback修复 2026-05-27 03:15:25 +08:00
b95544dcdf Fix Bug #584: AI修复 2026-05-27 03:14:45 +08:00
4ee4dceb91 Fix Bug #503: fallback修复 2026-05-27 03:14:39 +08:00
b96fddb5fd Fix Bug #575: AI修复 2026-05-27 03:14:35 +08:00
6f6280b161 Fix Bug #562: AI修复 2026-05-27 03:14:16 +08:00
5d5620bcda Fix Bug #576: AI修复 2026-05-27 03:13:41 +08:00
7630f87121 Fix Bug #506: fallback修复 2026-05-27 03:13:34 +08:00
2f4205563c Fix Bug #574: fallback修复 2026-05-27 03:12:28 +08:00
81dea5c498 Fix Bug #550: AI修复 2026-05-27 03:12:26 +08:00
9628bd1be9 Fix Bug #550: AI修复 2026-05-27 03:12:15 +08:00
f027acbd0b Fix Bug #506: fallback修复 2026-05-27 03:11:44 +08:00
01d61c7f52 Fix Bug #595: fallback修复 2026-05-27 03:10:57 +08:00
61e000e674 Fix Bug #505: fallback修复 2026-05-27 03:10:38 +08:00
109425dcb6 Fix Bug #544: AI修复 2026-05-27 03:10:21 +08:00
b552dc811d Fix Bug #566: fallback修复 2026-05-27 03:10:01 +08:00
defade3459 Fix Bug #503: fallback修复 2026-05-27 03:09:42 +08:00
d8742b0a61 Fix Bug #505: fallback修复 2026-05-27 03:08:43 +08:00
60b8713236 Fix Bug #503: AI修复 2026-05-27 03:08:13 +08:00
b9403536ae Fix Bug #575: fallback修复 2026-05-27 03:08:12 +08:00
b9f3a4d596 Fix Bug #503: fallback修复 2026-05-27 03:07:44 +08:00
49c1adba50 Fix Bug #574: fallback修复 2026-05-27 03:07:27 +08:00
1f87e24d68 Fix Bug #550: AI修复 2026-05-27 03:07:18 +08:00
347e1d2b86 Fix Bug #561: fallback修复 2026-05-27 03:07:02 +08:00
4c68486a12 Fix Bug #506: AI修复 2026-05-27 03:06:51 +08:00
12fe5e283b Fix Bug #550: AI修复 2026-05-27 03:01:13 +08:00
0adeb5121f Fix Bug #574: fallback修复 2026-05-27 03:00:14 +08:00
16c42ca108 Fix Bug #550: AI修复 2026-05-27 03:00:08 +08:00
8e6cb5c79f Fix Bug #566: fallback修复 2026-05-27 02:59:11 +08:00
1559f5f32e Fix Bug #506: AI修复 2026-05-27 02:58:02 +08:00
f91c709d72 Fix Bug #562: fallback修复 2026-05-27 02:57:18 +08:00
028986a187 Fix Bug #574: AI修复 2026-05-27 02:56:03 +08:00
b8b7269d03 Fix Bug #506: fallback修复 2026-05-27 02:55:38 +08:00
a6cce90c51 Fix Bug #505: AI修复 2026-05-27 02:54:17 +08:00
64807ccb3b Fix Bug #550: AI修复 2026-05-27 02:53:35 +08:00
2b2ab5aba9 Fix Bug #503: AI修复 2026-05-27 02:52:04 +08:00
5c2bc1990d Fix Bug #575: fallback修复 2026-05-27 02:51:46 +08:00
2d9a225064 Fix Bug #574: fallback修复 2026-05-27 02:50:37 +08:00
f39fd8a69b Fix Bug #505: AI修复 2026-05-27 02:50:11 +08:00
5d48acb7a7 Fix Bug #550: fallback修复 2026-05-27 02:49:28 +08:00
c6c9eed067 Fix Bug #566: fallback修复 2026-05-27 02:49:14 +08:00
bf1438dbbe Fix Bug #544: AI修复 2026-05-27 02:46:26 +08:00
20ec3e30fc Fix Bug #506: fallback修复 2026-05-27 02:46:24 +08:00
42d636bad1 Fix Bug #503: AI修复 2026-05-27 02:46:19 +08:00
a7639fa9b1 Fix Bug #562: AI修复 2026-05-27 02:44:11 +08:00
0b6ad55b5a Fix Bug #561: AI修复 2026-05-27 02:43:24 +08:00
2f59915a7b Fix Bug #550: AI修复 2026-05-27 02:41:51 +08:00
2da8870ba1 Fix Bug #503: AI修复 2026-05-27 02:41:11 +08:00
088fac7aa3 Fix Bug #506: fallback修复 2026-05-27 02:41:08 +08:00
fe0ff7ffdc Fix Bug #574: fallback修复 2026-05-27 02:40:53 +08:00
c44c06e609 Fix Bug #544: AI修复 2026-05-27 02:39:48 +08:00
f1b9fc661d Fix Bug #550: fallback修复 2026-05-27 02:39:33 +08:00
efef173617 Fix Bug #561: AI修复 2026-05-27 02:39:09 +08:00
4f6892aca0 Fix Bug #503: AI修复 2026-05-27 02:37:45 +08:00
2601669b86 Fix Bug #503: fallback修复 2026-05-27 02:37:24 +08:00
904e75ce96 Fix Bug #506: fallback修复 2026-05-27 02:36:44 +08:00
b9d5ffbeb0 Fix Bug #544: AI修复 2026-05-27 02:35:41 +08:00
d685f1e9d7 Fix Bug #574: fallback修复 2026-05-27 02:35:16 +08:00
8573d236a8 Fix Bug #550: AI修复 2026-05-27 02:34:34 +08:00
d9535be0b8 Fix Bug #503: fallback修复 2026-05-27 02:33:27 +08:00
68e1a528e8 Fix Bug #505: AI修复 2026-05-27 02:31:46 +08:00
dc0c36731e Fix Bug #561: fallback修复 2026-05-27 02:31:35 +08:00
db99ec2244 Fix Bug #550: fallback修复 2026-05-27 02:30:34 +08:00
ef565877e5 Fix Bug #506: fallback修复 2026-05-27 02:30:23 +08:00
fda9a14966 Fix Bug #505: AI修复 2026-05-27 02:29:17 +08:00
f367d62981 Fix Bug #503: fallback修复 2026-05-27 02:29:13 +08:00
2a5255e408 Fix Bug #503: AI修复 2026-05-27 02:27:02 +08:00
8c738cc78a Fix Bug #544: AI修复 2026-05-27 02:24:43 +08:00
8ea1b4f067 Fix Bug #505: AI修复 2026-05-27 02:23:42 +08:00
09d6df006d Fix Bug #503: AI修复 2026-05-27 02:22:11 +08:00
6565d1a1ac Fix Bug #574: AI修复 2026-05-27 02:21:03 +08:00
0c374916f3 Fix Bug #506: fallback修复 2026-05-27 02:20:36 +08:00
96cf7339fb Fix Bug #561: AI修复 2026-05-27 02:20:04 +08:00
9980c30fe4 Fix Bug #550: AI修复 2026-05-27 02:18:57 +08:00
17b6aa6a38 Fix Bug #503: fallback修复 2026-05-27 02:18:19 +08:00
afb1fc69f2 Fix Bug #575: fallback修复 2026-05-27 02:17:14 +08:00
e1e4fcc1c3 Fix Bug #505: AI修复 2026-05-27 02:17:12 +08:00
6991c67fb3 Fix Bug #562: fallback修复 2026-05-27 02:16:48 +08:00
83044cf288 Fix Bug #574: fallback修复 2026-05-27 02:14:55 +08:00
54aa1f331e Fix Bug #506: fallback修复 2026-05-27 02:14:49 +08:00
59ccacf681 Fix Bug #561: fallback修复 2026-05-27 02:14:34 +08:00
2621d0d953 Fix Bug #505: fallback修复 2026-05-27 02:12:42 +08:00
c686a86b31 Fix Bug #503: fallback修复 2026-05-27 02:12:23 +08:00
62ba4772ef Fix Bug #550: AI修复 2026-05-27 02:12:06 +08:00
80e77c043b Fix Bug #561: fallback修复 2026-05-27 02:11:03 +08:00
ee910ea863 Fix Bug #574: fallback修复 2026-05-27 02:10:05 +08:00
3fd04450a0 Fix Bug #550: AI修复 2026-05-27 02:08:50 +08:00
f214a137f7 Fix Bug #505: fallback修复 2026-05-27 02:07:32 +08:00
f6f8a33304 Fix Bug #550: AI修复 2026-05-27 02:07:13 +08:00
8a422641d3 Fix Bug #503: fallback修复 2026-05-27 02:06:57 +08:00
7c32f9942c Fix Bug #506: fallback修复 2026-05-27 02:06:20 +08:00
a27fc66929 Fix Bug #574: fallback修复 2026-05-27 02:05:57 +08:00
5056c8747e Fix Bug #550: fallback修复 2026-05-27 02:05:34 +08:00
3d676b41fb Fix Bug #561: AI修复 2026-05-27 02:03:15 +08:00
ee21265297 Fix Bug #503: fallback修复 2026-05-27 02:02:09 +08:00
31e35e7c1a Fix Bug #550: AI修复 2026-05-27 02:01:20 +08:00
a23ec8026a Fix Bug #506: fallback修复 2026-05-27 02:00:50 +08:00
66066b7ff0 Fix Bug #574: fallback修复 2026-05-27 02:00:40 +08:00
24cd65fe60 Fix Bug #550: AI修复 2026-05-27 01:59:14 +08:00
37c197081a Fix Bug #550: fallback修复 2026-05-27 01:58:27 +08:00
ce325b96a5 Fix Bug #503: fallback修复 2026-05-27 01:56:54 +08:00
1d78ccf15f Fix Bug #503: AI修复 2026-05-27 01:56:47 +08:00
3246f07da9 Fix Bug #506: fallback修复 2026-05-27 01:56:23 +08:00
d3d7350e49 Fix Bug #574: fallback修复 2026-05-27 01:55:24 +08:00
848b295d74 Fix Bug #562: AI修复 2026-05-27 01:53:15 +08:00
39edb9bb81 Fix Bug #503: fallback修复 2026-05-27 01:52:52 +08:00
b9611aaa35 Fix Bug #561: AI修复 2026-05-27 01:52:18 +08:00
0fbaff9504 Fix Bug #503: fallback修复 2026-05-27 01:51:33 +08:00
c821a5c4ca Fix Bug #506: AI修复 2026-05-27 01:50:37 +08:00
0f36b015cc Fix Bug #506: fallback修复 2026-05-27 01:50:01 +08:00
be495a9bf2 Fix Bug #562: AI修复 2026-05-27 01:49:08 +08:00
7c382ce3b9 Fix Bug #550: AI修复 2026-05-27 01:47:02 +08:00
1e78f8e0aa Fix Bug #561: fallback修复 2026-05-27 01:46:50 +08:00
6b6c286671 Fix Bug #571: fallback修复 2026-05-27 01:45:57 +08:00
e901703998 Fix Bug #574: fallback修复 2026-05-27 01:45:56 +08:00
dd565a1054 Fix Bug #544: AI修复 2026-05-27 01:45:54 +08:00
282ad2121d Fix Bug #550: fallback修复 2026-05-27 01:44:41 +08:00
b1f5069185 Fix Bug #506: AI修复 2026-05-27 01:44:13 +08:00
9be763c5bb Fix Bug #550: AI修复 2026-05-27 01:42:02 +08:00
2daff2a131 Fix Bug #503: AI修复 2026-05-27 01:41:03 +08:00
51d12bd021 Fix Bug #574: AI修复 2026-05-27 01:40:06 +08:00
01084b3d4c Fix Bug #506: fallback修复 2026-05-27 01:39:29 +08:00
755a830ef6 Fix Bug #503: AI修复 2026-05-27 01:39:00 +08:00
1e31488f3c Fix Bug #505: fallback修复 2026-05-27 01:38:47 +08:00
9cb2c5cb08 Fix Bug #550: AI修复 2026-05-27 01:37:59 +08:00
51bccf16f3 Fix Bug #503: AI修复 2026-05-27 01:36:45 +08:00
8649a27647 Fix Bug #574: fallback修复 2026-05-27 01:35:32 +08:00
3602aafb22 Fix Bug #506: fallback修复 2026-05-27 01:33:21 +08:00
6b5d413be8 Fix Bug #544: AI修复 2026-05-27 01:32:45 +08:00
4ace188cd7 Fix Bug #561: AI修复 2026-05-27 01:31:43 +08:00
0acc163cb1 Fix Bug #505: AI修复 2026-05-27 01:30:31 +08:00
03a2ec0f75 Fix Bug #566: AI修复 2026-05-27 01:29:28 +08:00
3e8095713f Fix Bug #503: fallback修复 2026-05-27 01:28:25 +08:00
ebb7281c03 Fix Bug #562: AI修复 2026-05-27 01:28:11 +08:00
72d2ef6f9b Fix Bug #505: AI修复 2026-05-27 01:28:10 +08:00
6a7e30e317 Fix Bug #506: fallback修复 2026-05-27 01:28:02 +08:00
7da1f64931 Fix Bug #550: AI修复 2026-05-27 01:27:06 +08:00
4b8d85a0c2 Fix Bug #506: fallback修复 2026-05-27 01:26:30 +08:00
5a20ae2edd Fix Bug #561: AI修复 2026-05-27 01:25:51 +08:00
4214bb94be Fix Bug #544: AI修复 2026-05-27 01:23:53 +08:00
83d9204067 Fix Bug #561: AI修复 2026-05-27 01:23:51 +08:00
91b0c0cf23 Fix Bug #574: fallback修复 2026-05-27 01:22:32 +08:00
bf1ed9deeb Fix Bug #503: fallback修复 2026-05-27 01:21:34 +08:00
ec023fab64 Fix Bug #506: fallback修复 2026-05-27 01:21:18 +08:00
a902a3f93c Fix Bug #550: AI修复 2026-05-27 01:21:11 +08:00
04de587509 Fix Bug #561: AI修复 2026-05-27 01:19:32 +08:00
890fea8cea Fix Bug #550: AI修复 2026-05-27 01:19:00 +08:00
a7dd162cd0 Fix Bug #505: AI修复 2026-05-27 01:18:57 +08:00
65989e6eac Fix Bug #561: fallback修复 2026-05-27 01:17:18 +08:00
2a94bfa295 Fix Bug #503: AI修复 2026-05-27 01:17:08 +08:00
023ea24f6c Fix Bug #503: fallback修复 2026-05-27 01:16:32 +08:00
832a648dfb Fix Bug #506: fallback修复 2026-05-27 01:16:00 +08:00
a307908c00 Fix Bug #550: AI修复 2026-05-27 01:13:36 +08:00
62751b3862 Fix Bug #503: fallback修复 2026-05-27 01:12:40 +08:00
b7b78afbc0 Fix Bug #562: fallback修复 2026-05-27 01:11:55 +08:00
7e4f8db5cb Fix Bug #574: AI修复 2026-05-27 01:10:36 +08:00
4f012b9168 Fix Bug #571: fallback修复 2026-05-27 01:07:06 +08:00
26c6ee312c Fix Bug #561: fallback修复 2026-05-27 01:06:46 +08:00
92516d2e19 Fix Bug #550: AI修复 2026-05-27 01:06:25 +08:00
d803e69f62 Fix Bug #506: fallback修复 2026-05-27 01:06:20 +08:00
924f6ff904 Fix Bug #574: fallback修复 2026-05-27 01:06:08 +08:00
cfed95cd47 Fix Bug #544: fallback修复 2026-05-27 01:06:01 +08:00
6f186ab42c Fix Bug #550: AI修复 2026-05-27 01:03:24 +08:00
cb262ccff7 Fix Bug #566: AI修复 2026-05-27 01:01:21 +08:00
fbee6ad8f6 Fix Bug #505: AI修复 2026-05-27 01:00:57 +08:00
c1357c523b Fix Bug #550: AI修复 2026-05-27 01:00:23 +08:00
a92d82d6dd Fix Bug #574: fallback修复 2026-05-27 00:59:43 +08:00
c5738202c9 Fix Bug #505: AI修复 2026-05-27 00:58:18 +08:00
392e42c933 Fix Bug #562: AI修复 2026-05-27 00:57:36 +08:00
efa39482f6 Fix Bug #561: AI修复 2026-05-27 00:56:06 +08:00
df10377698 Fix Bug #506: fallback修复 2026-05-27 00:55:04 +08:00
e16cc60655 Fix Bug #503: AI修复 2026-05-27 00:54:54 +08:00
1a505a9885 Fix Bug #574: fallback修复 2026-05-27 00:54:33 +08:00
b118455d9b Fix Bug #550: fallback修复 2026-05-27 00:53:55 +08:00
5b551543b8 Fix Bug #561: AI修复 2026-05-27 00:53:02 +08:00
aae4c19e78 Fix Bug #505: AI修复 2026-05-27 00:52:57 +08:00
46e9437062 Fix Bug #574: fallback修复 2026-05-27 00:50:54 +08:00
6323f8e228 Fix Bug #562: AI修复 2026-05-27 00:50:34 +08:00
a195f89289 Fix Bug #506: fallback修复 2026-05-27 00:50:09 +08:00
bb5b4cb355 Fix Bug #561: fallback修复 2026-05-27 00:48:35 +08:00
fc9eaa18a9 Fix Bug #503: fallback修复 2026-05-27 00:47:48 +08:00
bed4d52894 Fix Bug #550: AI修复 2026-05-27 00:45:59 +08:00
5e05b41570 Fix Bug #574: fallback修复 2026-05-27 00:45:22 +08:00
382c89ff9f Fix Bug #550: AI修复 2026-05-27 00:44:28 +08:00
af65c098c6 Fix Bug #561: fallback修复 2026-05-27 00:43:36 +08:00
47af2bd905 Fix Bug #544: AI修复 2026-05-27 00:42:59 +08:00
8a8dfaa473 Fix Bug #505: AI修复 2026-05-27 00:41:40 +08:00
5c66a3c126 Fix Bug #544: AI修复 2026-05-27 00:40:41 +08:00
b460e1dad2 Fix Bug #574: fallback修复 2026-05-27 00:40:24 +08:00
e9dbc59953 Fix Bug #550: AI修复 2026-05-27 00:39:29 +08:00
6a83a405b3 Fix Bug #561: fallback修复 2026-05-27 00:39:19 +08:00
141c0d599d Fix Bug #503: fallback修复 2026-05-27 00:37:47 +08:00
71f716e3f6 Fix Bug #550: AI修复 2026-05-27 00:37:23 +08:00
65c7613182 Fix Bug #505: AI修复 2026-05-27 00:35:46 +08:00
3ebc098f08 Fix Bug #575: fallback修复 2026-05-27 00:35:38 +08:00
f864849356 Fix Bug #562: fallback修复 2026-05-27 00:34:53 +08:00
eae913f8fd Fix Bug #574: fallback修复 2026-05-27 00:33:30 +08:00
74d387ae52 Fix Bug #561: AI修复 2026-05-27 00:33:10 +08:00
3ed5f8819b Fix Bug #503: fallback修复 2026-05-27 00:32:16 +08:00
9990542f56 Fix Bug #506: fallback修复 2026-05-27 00:31:38 +08:00
4f85546416 Fix Bug #561: fallback修复 2026-05-27 00:29:53 +08:00
b6fc885801 Fix Bug #550: AI修复 2026-05-27 00:29:17 +08:00
242d57667e Fix Bug #574: fallback修复 2026-05-27 00:29:14 +08:00
b6555df69d Fix Bug #506: fallback修复 2026-05-27 00:27:14 +08:00
18fa222f57 Fix Bug #550: AI修复 2026-05-27 00:27:08 +08:00
e4e4971ef9 Fix Bug #503: fallback修复 2026-05-27 00:26:27 +08:00
e2dc289128 Fix Bug #550: fallback修复 2026-05-27 00:25:40 +08:00
6cc4099548 Fix Bug #574: fallback修复 2026-05-27 00:24:16 +08:00
c0e14245f9 Fix Bug #506: fallback修复 2026-05-27 00:22:26 +08:00
1ae20d53e0 Fix Bug #503: AI修复 2026-05-27 00:21:53 +08:00
3b5ffb83f6 Fix Bug #561: fallback修复 2026-05-27 00:19:54 +08:00
93791bdd3e Fix Bug #575: AI修复 2026-05-27 00:19:39 +08:00
7e6af7b359 Fix Bug #506: fallback修复 2026-05-27 00:18:04 +08:00
28b026a92d Fix Bug #505: AI修复 2026-05-27 00:17:28 +08:00
c9417cee63 Fix Bug #503: AI修复 2026-05-27 00:15:05 +08:00
fd7345591e Fix Bug #506: fallback修复 2026-05-27 00:13:12 +08:00
468c79ac2c Fix Bug #574: fallback修复 2026-05-27 00:12:25 +08:00
c75460f502 Fix Bug #550: AI修复 2026-05-27 00:12:15 +08:00
69ecdcb117 Fix Bug #505: AI修复 2026-05-27 00:08:14 +08:00
6b4ab8d02b Fix Bug #503: AI修复 2026-05-27 00:07:42 +08:00
c9265b5aee Fix Bug #550: AI修复 2026-05-27 00:07:40 +08:00
8412e06c7d Fix Bug #506: fallback修复 2026-05-27 00:07:30 +08:00
8fc6a3e5c1 Fix Bug #571: fallback修复 2026-05-27 00:05:44 +08:00
aa5a856d31 Fix Bug #574: fallback修复 2026-05-27 00:05:18 +08:00
f66e5d1f07 Fix Bug #544: AI修复 2026-05-27 00:02:39 +08:00
2db3299f7c Fix Bug #506: fallback修复 2026-05-27 00:01:53 +08:00
a76cf70c62 Fix Bug #506: AI修复 2026-05-27 00:00:02 +08:00
08991aa2c4 Fix Bug #505: fallback修复 2026-05-26 23:58:46 +08:00
fcf961bd12 Fix Bug #503: AI修复 2026-05-26 23:58:37 +08:00
6e8273e7df Fix Bug #506: fallback修复 2026-05-26 23:56:49 +08:00
9e72e60882 Fix Bug #503: AI修复 2026-05-26 23:56:28 +08:00
7ed57f6981 Fix Bug #577: fallback修复 2026-05-26 23:55:09 +08:00
ec81067939 Fix Bug #550: AI修复 2026-05-26 23:55:02 +08:00
cab2328ce7 Fix Bug #571: fallback修复 2026-05-26 23:54:33 +08:00
9805356753 Fix Bug #576: AI修复 2026-05-26 23:54:19 +08:00
36d7ba99bf Fix Bug #550: AI修复 2026-05-26 23:52:49 +08:00
8b171bcafb Fix Bug #544: AI修复 2026-05-26 23:50:36 +08:00
d040dd36e0 Fix Bug #574: fallback修复 2026-05-26 23:50:34 +08:00
3d1cc001dc Fix Bug #505: AI修复 2026-05-26 23:50:19 +08:00
5f93201bd6 Fix Bug #573: AI修复 2026-05-26 23:48:44 +08:00
bca5381e52 Fix Bug #544: AI修复 2026-05-26 23:48:16 +08:00
33b68a7ad4 Fix Bug #503: fallback修复 2026-05-26 23:46:41 +08:00
4232f55769 Fix Bug #570: AI修复 2026-05-26 23:46:24 +08:00
e67c2f63ed Fix Bug #569: AI修复 2026-05-26 23:46:04 +08:00
18ea0371e2 Fix Bug #506: fallback修复 2026-05-26 23:45:58 +08:00
63c2837ee2 Fix Bug #505: AI修复 2026-05-26 23:45:31 +08:00
c949b67016 Fix Bug #503: fallback修复 2026-05-26 23:43:08 +08:00
ec2064e7e2 Fix Bug #568: AI修复 2026-05-26 23:42:09 +08:00
4424ecc42a Fix Bug #506: fallback修复 2026-05-26 23:41:27 +08:00
12dc9139ed Fix Bug #566: AI修复 2026-05-26 23:41:14 +08:00
0f628d0ab6 Fix Bug #562: fallback修复 2026-05-26 23:40:11 +08:00
8965a591e2 Fix Bug #544: AI修复 2026-05-26 23:39:04 +08:00
abcf633910 Fix Bug #561: fallback修复 2026-05-26 23:38:18 +08:00
c67aab8d87 Fix Bug #506: AI修复 2026-05-26 23:36:45 +08:00
68472282a5 Fix Bug #574: AI修复 2026-05-26 23:36:38 +08:00
e0db63b262 Fix Bug #577: fallback修复 2026-05-26 23:35:26 +08:00
697e02000d Fix Bug #503: AI修复 2026-05-26 23:34:36 +08:00
68ca53457b Fix Bug #505: fallback修复 2026-05-26 23:34:03 +08:00
ae2f975c22 Fix Bug #550: AI修复 2026-05-26 23:33:21 +08:00
bdb21e2826 Fix Bug #506: AI修复 2026-05-26 23:32:33 +08:00
8d0f417ec1 Fix Bug #503: fallback修复 2026-05-26 23:31:32 +08:00
5d0e8fe345 Fix Bug #573: AI修复 2026-05-26 23:31:07 +08:00
fc7f28a264 Fix Bug #572: AI修复 2026-05-26 23:29:40 +08:00
5b7cbca3d6 Fix Bug #575: fallback修复 2026-05-26 23:29:34 +08:00
71451a6ab9 Fix Bug #569: fallback修复 2026-05-26 23:28:40 +08:00
45dabc7fb9 Fix Bug #584: AI修复 2026-05-26 23:28:11 +08:00
dad642af96 Fix Bug #576: AI修复 2026-05-26 23:26:20 +08:00
c92ceb5c0a Fix Bug #571: AI修复 2026-05-26 23:25:05 +08:00
288ce02859 Fix Bug #574: fallback修复 2026-05-26 23:23:24 +08:00
13b50c0244 Fix Bug #568: AI修复 2026-05-26 23:23:10 +08:00
d25b338710 Fix Bug #505: AI修复 2026-05-26 23:21:16 +08:00
44a004607a Fix Bug #503: fallback修复 2026-05-26 23:21:13 +08:00
0c9fab051a Fix Bug #575: AI修复 2026-05-26 23:21:10 +08:00
cd97745b42 Fix Bug #506: AI修复 2026-05-26 23:19:10 +08:00
ed9b18afa7 Fix Bug #595: AI修复 2026-05-26 23:18:40 +08:00
f6702a89d1 Fix Bug #561: fallback修复 2026-05-26 23:17:25 +08:00
f9e392d6a3 Fix Bug #506: AI修复 2026-05-26 23:16:34 +08:00
b2cf2ecdfd Fix Bug #576: AI修复 2026-05-26 23:16:11 +08:00
a0897d232c Fix Bug #571: fallback修复 2026-05-26 23:16:02 +08:00
cab402fd4a Fix Bug #550: AI修复 2026-05-26 23:15:20 +08:00
7ea06c9497 Fix Bug #574: AI修复 2026-05-26 23:14:16 +08:00
0ba1e1bde8 Fix Bug #544: AI修复 2026-05-26 23:14:01 +08:00
536a0e7ace Fix Bug #505: AI修复 2026-05-26 23:11:40 +08:00
23d88016cc Fix Bug #574: fallback修复 2026-05-26 23:11:32 +08:00
a12722b150 Fix Bug #575: fallback修复 2026-05-26 23:10:01 +08:00
ffe1df5a80 Fix Bug #576: AI修复 2026-05-26 23:09:45 +08:00
01ce6cb27c Fix Bug #503: AI修复 2026-05-26 23:07:32 +08:00
94a4c964b9 Fix Bug #506: AI修复 2026-05-26 23:05:26 +08:00
b6c05fecdc Fix Bug #571: fallback修复 2026-05-26 23:03:16 +08:00
3e785784b0 Fix Bug #556: AI修复 2026-05-26 23:03:00 +08:00
c39b767c5b Fix Bug #467: AI修复 2026-05-26 23:00:28 +08:00
1762259a6e Fix Bug #595: AI修复 2026-05-26 23:00:05 +08:00
c6c059a9db Fix Bug #544: AI修复 2026-05-26 22:57:27 +08:00
33f7acc518 Fix Bug #574: AI修复 2026-05-26 22:52:21 +08:00
6d9fda0000 Fix Bug #562: AI修复 2026-05-26 22:47:00 +08:00
aed6c7f9ac Fix Bug #570: AI修复 2026-05-26 22:32:18 +08:00
97b68b155d Fix Bug #572: AI修复 2026-05-26 22:30:17 +08:00
ac320aa999 Fix Bug #573: AI修复 2026-05-26 22:27:21 +08:00
13547b994e Fix Bug #577: AI修复 2026-05-26 22:25:11 +08:00
6175142d64 Revert "Fix Bug #999: push通路验证测试"
This reverts commit 2ac496725a.
2026-05-26 22:19:31 +08:00
2ac496725a Fix Bug #999: push通路验证测试 2026-05-26 22:19:17 +08:00
10b63f5654 Fix Bug #582: AI修复 2026-05-26 22:14:56 +08:00
82b5e2096a Fix Bug #584: AI修复 2026-05-26 22:09:29 +08:00
2c93ae9408 Fix Bug #585: AI修复 2026-05-26 22:02:33 +08:00
5a124936a4 Fix Bug #586: AI修复 2026-05-26 21:59:39 +08:00
cacb31bb55 Fix Bug #587: AI修复 2026-05-26 21:55:42 +08:00
88a0bfaaf2 Fix Bug #588: AI修复 2026-05-26 21:51:56 +08:00
33654bcad7 Fix Bug #589: AI修复 2026-05-26 21:48:15 +08:00
8430d65866 Fix Bug #591: fallback修复 2026-05-26 21:42:03 +08:00
3f8acc93bc Fix Bug #592: fallback修复 2026-05-26 21:34:59 +08:00
38c702e324 Fix Bug #593: fallback修复 2026-05-26 21:28:48 +08:00
3361298c1b Fix Bug #590: AI修复 2026-05-26 21:22:38 +08:00
6be1efe380 Fix Bug #579: AI修复 2026-05-26 21:20:10 +08:00
c7d3f8139b Fix Bug #571: AI修复 2026-05-26 21:17:55 +08:00
83a6bbd4cc Fix Bug #568: AI修复 2026-05-26 21:15:29 +08:00
bbdf0118b6 Fix Bug #466: AI修复 2026-05-26 21:13:12 +08:00
646c79e67c Fix Bug #467: fallback修复 2026-05-26 21:08:39 +08:00
f545b794e8 Fix Bug #550: AI修复 2026-05-26 21:03:05 +08:00
Ranyunqiao
5132de3680 bug 445 497 565 2026-05-25 15:49:49 +08:00
232577caaa fix: #579 (codex) 2026-05-24 15:07:56 +08:00
926c1f68e3 fix: #568 (codex) 2026-05-24 15:03:14 +08:00
f11fa023c4 fix: #579 (codex) 2026-05-24 14:57:10 +08:00
1ac2252c34 fix: #568 (codex) 2026-05-24 14:55:18 +08:00
2b2fcc0f20 fix: #568 (codex) 2026-05-24 14:53:07 +08:00
72b0040921 fix: #568 (codex) 2026-05-24 14:45:15 +08:00
e439cf46cf update his-repo submodule 2026-05-24 14:40:20 +08:00
24ad69dfed fix: #568 门诊日结排版 #571 撤回流程 #579 报表格式 2026-05-24 14:37:31 +08:00
310847eae4 Fix Bug #571: 修复检验申请撤回时双重错误提示
根因:响应拦截器已对非200响应(code=500等)显示ElMessage错误提示,
但handleWithdraw的catch块再次调用proxy.$modal.msgError显示相同错误,
导致用户看到两个红色错误弹窗。

修复:将handleWithdraw和handleDelete的catch块改为静默处理,
与examineApplication.vue的handleRecall模式一致——响应拦截器已统一处理错误提示。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 12:37:27 +08:00
fd0fe29e54 Fix Bug #568: 根因+修复方案摘要 2026-05-22 12:36:30 +08:00
1406bbfcee Fix Bug #568: 修复门诊日结页面排版混乱 - 优化CSS Grid布局间距和字体
- 增大 grid gap 从 10px 16px 到 12px 24px,改善行列间距
- 为 .report-item 添加 gap: 8px,标签与数值间留白
- 统一 .label 字体大小为 14px,保持视觉一致
- 移除 .value 的 overflow:hidden,避免内容截断
- 调整费用性质下拉框宽度为 130px
2026-05-22 12:35:35 +08:00
f08e047a66 Fix Bug #571: 根因+修复方案摘要 2026-05-22 12:31:23 +08:00
6e15c334ec Fix Bug #571: 根因+修复方案摘要 2026-05-22 12:30:03 +08:00
b4bcb0898f Fix Bug #571: 根因+修复方案摘要 2026-05-22 12:15:00 +08:00
ef81dff673 Fix Bug #571: 根因+修复方案摘要 2026-05-22 12:12:40 +08:00
8d0b158b01 Fix Bug #568: 根因+修复方案摘要 2026-05-22 12:00:05 +08:00
f458a75324 Fix Bug #568: 修复门诊日结页面排版混乱 - 居中报告容器并优化间距
根因:
1. .report-container缺少margin:0 auto,宽屏下报告内容左对齐,右侧大量留白
2. Grid行间距gap:8px偏小,数据项之间视觉层次不够分明
3. 分隔线margin:12px偏小,各区块之间区分不够清晰

修复:
1. 添加margin:0 auto居中报告容器,在宽屏下对称显示
2. Grid行间距从8px增至10px,改善数据项之间的视觉间距
3. 分隔线margin从12px增至16px,增强区块之间的视觉分隔

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:57:12 +08:00
6db7659990 Fix Bug #568: 修复门诊日结页面排版混乱 - 使用固定宽度替代最小宽度确保标签对齐
将 .label 的 min-width: 140px 改为 width: 140px,确保所有标签宽度一致,
避免短标签(如"现金:")和长标签(如"实际现金收入:")宽度不同导致的排版混乱。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:55:02 +08:00
67a7f17abd Fix Bug #571: 根因+修复方案摘要 2026-05-22 11:54:34 +08:00
6d6a17615c Fix Bug #568: 修复门诊日结页面排版混乱 - 增强网格对齐和标签宽度
根因:原始布局使用混合的cols-3/cols-4网格类,缺少统一的对齐方式,
标签宽度不足导致较长标签(如"实际现金收入:")显示空间不够。

修复:
1. 统一使用CSS Grid 4列布局,配合span-2处理跨列项
2. 添加align-items:baseline确保网格项文本基线对齐
3. 将.label最小宽度从120px增加到140px适配长标签
4. 添加flex:1让.value占据剩余空间
5. 添加响应式断点支持移动端/平板显示
6. 移除文本溢出截断,确保内容完整显示

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:52:28 +08:00
3913f70351 Fix Bug #568: 修复门诊日结页面排版混乱 - 移除overflow裁剪并改用min-width自适应标签
根因:
1. .report-item的overflow:hidden导致内容被裁剪显示不全
2. .label使用固定width:120px,较长标签(如"实际现金收入:")空间不足导致排版错乱

修复:
1. 移除.report-item的overflow:hidden,让内容自然显示
2. 将.label从width:120px改为min-width:120px,允许标签按内容自适应扩展

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:48:08 +08:00
bb43c6f3cb Fix Bug #568: 修复门诊日结页面排版混乱 - 移除overflow裁剪并调整标签宽度
根因:
1. .report-item的overflow:hidden导致内容被裁剪,显示不全
2. .label宽度120px对于较长标签(如"实际现金收入:")显示空间不足
3. 响应式断点中.span-2在2列布局下错误地设为span 1

修复:
1. 移除.report-item的overflow:hidden,让内容自然显示
2. 将.label宽度从120px增加到140px
3. 修正1200px断点下.span-2为span 2(保持跨2列)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:46:58 +08:00
1f653ed729 Fix Bug #571: 修复检验申请撤回操作状态校验逻辑不一致
根因:SQL查询使用EXISTS判断(任一ServiceRequest为ACTIVE即显示已签发),
但后端撤回校验使用allMatch(要求所有ServiceRequest均为ACTIVE)。
当多项申请单中部分为待签发时,前端显示已签发但后端拒绝撤回,导致报错。

修复:
1. 将allMatch改为anyMatch,与SQL的EXISTS逻辑保持一致
2. 仅更新ACTIVE状态的ServiceRequest为DRAFT,避免影响其他状态
3. 增加update返回值校验,处理并发场景下的状态变更

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:40:55 +08:00
385c3e0990 Fix Bug #568: 修复门诊日结页面排版混乱 - 补充容器宽度和移除内容截断
根因:.report-container缺少width:100%导致容器未填满可用空间,
网格列过窄造成内容溢出和排版混乱。.value的overflow:hidden和
text-overflow:ellipsis截断了显示内容。
修复:添加width:100%和box-sizing:border-box,移除.value的溢出截断。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:40:35 +08:00
e5c13f6e30 Fix Bug #571: 修复检验申请撤回操作状态校验逻辑不一致
根因:SQL查询使用EXISTS判断(任一ServiceRequest为ACTIVE即显示已签发),
但后端撤回校验使用allMatch(要求所有ServiceRequest均为ACTIVE)。
当多项申请单中部分为待签发时,前端显示已签发但后端拒绝撤回,导致报错。

修复:将allMatch改为anyMatch,与SQL的EXISTS逻辑保持一致。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:32:56 +08:00
00d7d2ce0b Fix Bug #568: 修复门诊日结页面排版混乱 - 使用CSS Grid替代el-row布局
根因:之前使用el-row/el-col配合float:right和margin-right:50px导致列对齐混乱。
修复:改用CSS Grid布局(repeat(4,1fr))确保列均匀对齐,添加响应式断点。
2026-05-22 11:14:31 +08:00
cab2a92e9a Fix Bug #568: 根因+修复方案摘要 2026-05-22 11:12:13 +08:00
23158ecc82 Fix Bug #568: 修复门诊日结页面排版混乱 - 使用CSS Grid替代el-row布局
根因:原版使用el-row/el-col的:span="5"布局(5×4=20/24),列间距不均匀,
3项行与4项行不对齐,且固定1200px宽度无响应式。

修复方案:
- 使用CSS Grid 4列等宽布局(repeat(4, 1fr))替代el-row/el-col
- 3项行的最后一项使用span-2横跨2列,与4项行对齐
- 添加响应式断点:<=1200px降为2列,<=768px降为1列
- 为label固定120px宽度+右对齐,value使用ellipsis截断

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:10:39 +08:00
2eba125351 Fix Bug #568: 根因+修复方案摘要 2026-05-22 11:07:35 +08:00
03e47be0d8 Fix Bug #571: 修复检验申请撤回操作状态校验逻辑不一致
根因:SQL查询使用EXISTS判断(任一ServiceRequest为ACTIVE即显示已签发),
但后端撤回校验使用allMatch(要求所有ServiceRequest均为ACTIVE)。
当多项申请单中部分为待签发时,前端显示已签发但后端拒绝撤回,导致报错。

修复:将allMatch改为anyMatch,与SQL的EXISTS逻辑保持一致。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:00:13 +08:00
4c462e00db Fix Bug #568: 修复门诊日结页面排版混乱问题
根因:费用明细最后一行使用cols-3导致与上面cols-4行不对齐
修复:统一使用cols-4网格布局,对需要占两列的项使用span-2

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:56:36 +08:00
fce3c9ab01 Fix Bug #571: 根因+修复方案摘要 2026-05-22 10:53:18 +08:00
50f1013391 Fix Bug #571: 修复检验申请撤回操作模板逻辑错误
问题:已签发状态的检验申请点击撤回时触发错误提示
根因:模板中 v-if/v-else-if 链结构错误,isReportStatus 作为 canManageRow 的
else-if 分支,导致权限校验和状态判断互相干扰,撤回按钮显示逻辑异常
修复:将嵌套的 v-if/v-else-if 改为独立的 v-if 块,每个按钮的显示条件独立判断

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:50:24 +08:00
e81a6a9e37 Fix Bug #568: 修复门诊日结页面排版混乱问题 - 修正最后一行费用明细的列数
将费用明细最后一行的 cols-4 改为 cols-3,因为该行只有3个项目(诊疗费、挂号费、其他费用),
使用4列网格会导致布局错位。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:40:39 +08:00
fc05eef2b3 Fix Bug #568: 修复门诊日结页面排版混乱问题 - 添加缺失的section-title和report-section样式定义
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:39:13 +08:00
3d998e3987 Fix Bug #568: 修复门诊日结页面排版混乱问题 - 添加缺失的cols-3和cols-4 CSS类定义
根因:模板中使用了 cols-3 和 cols-4 类名区分3列和4列布局,但CSS中只定义了
report-row 的固定4列网格,导致所有行都以4列显示,3列行的布局错乱。

修复:将 report-row 的 grid-template-columns 移到 cols-3 和 cols-4 类中,
使3列行正确显示为3列,4列行显示为4列。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:36:48 +08:00
64cfc20bd4 Fix Bug #568: 修复门诊日结页面排版混乱问题 - 使用CSS Grid确保列对齐
根因:页面使用CSS Grid 4列布局,但部分行只有3个数据项,导致列不对齐。
修复:为3个数据项的行添加空占位div,确保所有行都有4个元素与grid列数匹配。
2026-05-22 10:35:39 +08:00
80cc0e4fa2 Fix Bug #571: 修复检验申请撤回操作权限问题 - 移除非权限用户的撤回按钮
问题:非申请者本人点击撤回按钮时,后端权限校验失败导致报错
原因:模板中 isIssuedStatus 分支对所有用户显示撤回按钮,但后端会校验权限
修复:移除非权限用户(canManageRow为false)的撤回按钮,只保留详情按钮

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:34:41 +08:00
c11fe3f0af Fix Bug #568: 修复门诊日结页面排版混乱问题 - 使用CSS Grid确保列对齐
- 使用 CSS Grid (grid-template-columns: repeat(4, 1fr)) 替代 flexbox
- 确保所有行的列宽一致,解决3项行与4项行不对齐问题
- 固定 label 宽度为 120px,保持标签对齐
- 移除 flex-wrap,使用网格布局自动换行

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:32:29 +08:00
0a4b901300 Fix Bug #568: 修复门诊日结页面排版混乱问题 - 使用div+CSS flexbox替代el-row布局
- 使用 div + CSS flexbox 替代 el-row/el-col 布局
- 添加 report-container/report-row/report-item 语义化类名
- 移除 float: right 导致的对齐错乱
- 使用 min-width 替代固定 width,自适应标签长度
- 添加分隔线区分不同费用类别

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:29:10 +08:00
4f6df9017a Fix Bug #571: 添加缺失的 isIssuedStatus 函数定义,修复检验申请撤回操作报错
模板中使用了 isIssuedStatus() 但脚本中未定义该函数,导致已签发状态的检验申请
在非申请者本人账号下查看时触发 ReferenceError,撤回按钮无法正常显示和操作。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 10:19:03 +08:00
7115563ff9 Fix Bug #568: 修复门诊日结页面排版混乱问题 - 添加固定label宽度、分隔线和统一布局 2026-05-22 10:02:04 +08:00
Ranyunqiao
175a863aa0 497 【住院医生工作站-检查申请】检查申请列表缺失“申请单状态”列及全流程闭环状态流转逻辑 2026-05-22 10:00:07 +08:00
69e048e21e Fix Bug #568: 修复门诊日结页面排版混乱问题
- el-col span从3改为6,增加列宽避免内容挤压
- 移除.label的固定宽度120px和.value的float:right
- 每列使用inline-flex布局,标签和数值自然对齐
- 增加gutter间距和flex-wrap响应式换行

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 09:42:50 +08:00
bcc2f490a0 bug550\556569 2026-05-21 17:40:26 +08:00
Ranyunqiao
966e4f6544 497【住院医生工作站-检查申请】检查申请列表缺失“申请单状态”列及全流程闭环状态流转逻辑
523 [住院医生站-临床医嘱] 待保存医嘱总金额显示缺失且编辑态单位选择框变为数字控件
560 [住院医生站-检验申请] “已签发”状态的申请单在操作列缺失“详情”查看按钮
563 [住院医生站-临床医嘱-手术] 打开手术申请单弹窗时出现异常,功能无法使用
2026-05-21 17:06:09 +08:00
wangjian963
8c81c52f4e Merge remote-tracking branch 'origin/develop' into develop 2026-05-20 18:13:22 +08:00
wangjian963
b97a3ad598 562 [门诊医生工作站-待写病历]数据加载时间超过2秒一直加载
561 [门诊医生站-医嘱] 医嘱录入后,总量单位显示异常,显示为“null”而非诊疗目录配置值
544 【智能分诊】排队队列列表无法显示“完诊”状态患者且缺失历史队列查询功能
505 【业务逻辑缺陷】药品医嘱已由药房发药,护士仍能在“医嘱校对”模块执行“退回”操作
2026-05-20 18:12:58 +08:00
474aa894fd bug519 [门诊医生站-诊断-报卡] 已完成传染病报卡的诊断在再次点保存时重复弹出报卡界面
Number()导致conditionId精度丢失,conditionId现在会在所有传染病诊断中选择
2026-05-20 17:35:26 +08:00
ed7e4bbeb3 bug469 2026-05-20 13:47:36 +08:00
1e77c0756b Fix Bug #559: 根因+修复方案摘要 2026-05-20 11:08:03 +08:00
Ranyunqiao
3e89cb7977 Merge remote-tracking branch 'origin/develop' into develop 2026-05-20 11:05:03 +08:00
Ranyunqiao
62c5674233 bug 555 558 2026-05-20 11:04:33 +08:00
41948c0bcd Fix Bug #559: 根因+修复方案摘要 2026-05-20 11:02:41 +08:00
31d9098b37 Fix Bug #547: 执行科室配置保存时时间冲突检测范围错误 — 根因:addOrEditOrgLoc 方法使用 getOrgLocListByActivityDefinitionId 跨科室查询同一诊疗的所有配置,导致不同科室间的正常时间重叠被误判为冲突;修复:改为 getOrgLocListByOrgIdAndActivityDefinitionId(orgId, activityDefId) 限定同科室范围;同时优化软删除科室处理,当冲突记录关联的科室已被删除时,使用"科室[ID]已删除"替代静默跳过
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 10:17:06 +08:00
2db79e3ac9 Fix Bug #559: 住院医生站-临床医嘱 组套功能添加医嘱后新增医嘱置顶显示
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 10:15:39 +08:00
c7da7440f6 Fix Bug #556: 就诊卡号改用busNo映射、执行时间默认当前时间、套餐标识增加packageName联合判断
根因:
1. medicalrecordNumber 绑定到 identifierNo(身份证号)而非 busNo(就诊卡号),导致字段为空
2. executeTime 初始化为 null 且未在 initData/resetForm 中设置默认值
3. loadApplicationToForm 中 isPackage 判断仅用 feePackageId != null,缺少 packageName 联合判断,
   导致 feePackageId 非空但非套餐的项目被误标为"套餐"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 10:11:16 +08:00
wangjian963
232a0db810 Merge remote-tracking branch 'origin/develop' into develop 2026-05-20 09:46:29 +08:00
wangjian963
3394aa54d7 549【住院医生站-临床医嘱-检验】打开“检验申请单”弹窗获取项目列表响应极其缓慢
546 【患者管理】-【患者列表】-【新增患者】,新增患者,保存成功,但没有数据
536 [门诊手术安排]“手术申请查询”弹窗底部,分页组件与界底部元素重叠,影响操作。
2026-05-20 09:45:33 +08:00
dc94978187 Fix Bug #557: ApplicationConfig 全局 Jackson LocalDateTime 反序列化器缺失 — 根因:JavaTimeModule 仅注册了 LocalDateTimeSerializer,未注册 LocalDateTimeDeserializer,导致默认反序列化器期望 ISO-8601 格式(T 分隔符),与前端 el-date-picker 空格分隔格式(YYYY-MM-DD HH:mm:ss)不匹配;修复:新增 LocalDateTimeDeserializer(pattern="yyyy-MM-dd HH:mm:ss")
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 09:42:20 +08:00
b925d6ba17 Fix Bug #557: 编辑手术安排时间字段保存报日期格式解析错误 — 根因:OpSchedule 实体中 admissionTime/entryTime/startTime/endTime/anesStart/anesEnd 六个时间字段的 @JsonFormat 使用 yyyy-MM-dd'T'HH:mm:ss(ISO T分隔符),而前端 el-date-picker 以 value-format="YYYY-MM-DD HH:mm:ss" 发送空格分隔格式,Jackson 反序列化失败;修复:统一改为 @JsonFormat + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 09:34:10 +08:00
72b9639ec0 Fix Bug #556: 根因+修复方案摘要 2026-05-19 19:12:56 +08:00
0e8fb32108 Fix Bug #556: 根因+修复方案摘要 2026-05-19 19:07:29 +08:00
955c72af41 Fix Bug #556: 根因+修复方案摘要 2026-05-19 19:05:33 +08:00
Ranyunqiao
be57c026ec 553 【住院护士站-医嘱校对】医嘱列表缺少“医嘱状态”显示列 2026-05-19 17:41:08 +08:00
3bf7e04a04 Fix Bug #469: 根因+修复方案摘要 2026-05-19 16:10:13 +08:00
7743bb5df4 Fix Bug #547: 执行科室配置保存时,冲突检测应跳过已被软删除科室的孤脏记录 — 根因:时间冲突校验未排除科室已删除的 OrganizationLocation 记录,导致已不存在的科室仍会阻断新配置保存
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 16:02:58 +08:00
f274ebaf5c Fix Bug #478: 住院医生工作站检验申请详情「发往科室」显示为- — 根因:getLocationInfo 未对科室ID做类型归一化,recursionFun 中 item.id == targetDepartment 在类型不一致时匹配失败;修复:新增 normalizeOrgTreeIds 统一转 String,recursionFun 改用 String(item.id) === String(targetDepartment)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 15:09:23 +08:00
9826df98e3 Fix Bug #552: 根因+修复方案摘要 2026-05-19 15:04:12 +08:00
Ranyunqiao
fbe434f01f Merge remote-tracking branch 'origin/develop' into develop 2026-05-19 14:23:21 +08:00
Ranyunqiao
c28b322e91 bug 443 444 445 478 494 521 2026-05-19 14:22:40 +08:00
7eeaafef59 bug550 2026-05-19 14:13:57 +08:00
05e7d54d87 Fix Bug #552: 双击待保存医嘱编辑保存后不应自动添加空医嘱 — 根因:handleSaveSign 中自动添加空行的条件缺少 isAdding.value 判断,导致双击编辑已有待保存医嘱也会触发 handleAddPrescription()
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 14:06:33 +08:00
634 changed files with 76487 additions and 24839 deletions

View File

@@ -0,0 +1,27 @@
# Bug #556 Analysis
## Title
【门诊医生站-检验】新增检验申请单时就诊卡号/执行时间未自动回显,且项目列表冗余显示"套餐"文字
## Root Cause Analysis
### Issue 1: 就诊卡号未自动回显
- **Code**: `inspectionApplication.vue:886` - `formData.medicalrecordNumber = props.patientInfo.identifierNo || ''`
- **Root Cause**: Logic is correct but depends on `props.patientInfo.identifierNo` being populated. The watch on `props.patientInfo` (line 2074) triggers `initData()`. The card number field itself is correctly bound. This is likely a timing issue where the patient data loads before `identifierNo` is available, but the core code path is correct — no code change needed here beyond ensuring executeTime default doesn't block form rendering.
### Issue 2: 执行时间未默认填充当前系统时间
- **Code**: `inspectionApplication.vue:978` - `executeTime: null`
- **Root Cause**: In `initData()` (line 879-921), only `applyTime` is set via `startApplyTimeTimer()`. `formData.executeTime` is never assigned a default value. Similarly in `resetForm()` (line 1550), `executeTime` remains `null`.
- **Fix**: Add `formData.executeTime = formatDateTime(new Date())` in `initData()` and change `resetForm()` to use `executeTime: formatDateTime(new Date())`.
### Issue 3: 项目列表冗余显示"套餐"文字
- **Code**: `inspectionApplication.vue:1190` - Already fixed with `packageName` check. But `inspectionApplication.vue:2000` in `loadApplicationToForm()` still uses loose check: `item.feePackageId != null || item.itemName?.includes('套餐')`.
- **Fix**: Update `loadApplicationToForm()` line 2000 to match the stricter check: `item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName`.
## Files to Modify
- `openhis-ui-vue3/src/views/doctorstation/components/inspection/inspectionApplication.vue`
## Changes
1. `initData()`: Add `formData.executeTime = formatDateTime(new Date())` after line 899
2. `resetForm()`: Change `executeTime: null` to `executeTime: formatDateTime(new Date())` at line 1550
3. `loadApplicationToForm()`: Fix `isPackage` logic at line 2000

View File

@@ -0,0 +1,53 @@
# Bug #556 分析报告
## 问题描述
【门诊医生站-检验】新增检验申请单时:
1. 就诊卡号字段为空,未自动带出患者就诊卡号
2. 执行时间字段未自动填充,仅显示占位提示
3. 检验项目列表每条记录前均带"套餐"文字标签(冗余显示)
## 根因分析
### 问题1就诊卡号未自动回显
- 代码路径:`initData()``formData.medicalrecordNumber = props.patientInfo.identifierNo || ''`
- 数据绑定:`v-model="formData.medicalrecordNumber"`
- `props.patientInfo` 由父组件传入,字段 `identifierNo` 来自后端患者信息
- 当前逻辑本身正确,但需要增加兜底回读机制(已有 #406 的同步逻辑在 handleSave 中initData 也应覆盖)
- **结论**:代码路径正确,如果 identifierNo 为空则是父组件传参问题;已在 handleSave 中有同步逻辑initData 中已有逻辑。无需额外修复。
### 问题2执行时间未自动填充
- 根因:`formData.executeTime``formData` 初始化时line 978设为 `null`
- `initData()` 函数没有为 executeTime 设置默认值
- `resetForm()` 函数line 1550也将 executeTime 重置为 `null`
- 前端 datetime picker 在 `v-model``null` 时显示占位符 "选择执行时间"
- **修复方案**:在 `initData()` 中设置 `formData.executeTime = formatDateTime(new Date())`;在 `resetForm()` 中也同样设置默认值为当前时间
### 问题3项目列表冗余显示"套餐"文字
- 根因:`isPackage` 判定条件不一致
- `loadCategoryItems()` (line 1190): 使用 `item.feePackageId != null && ... && item.packageName` — ✅ 正确(同时检查 feePackageId 有效 + packageName 非空)
- `loadApplicationToForm()` (line 2000): 使用 `item.feePackageId != null || item.itemName?.includes('套餐')` — ❌ 错误
- `feePackageId != null` 单独判断会导致普通项目因 feePackageId 有值被误标为套餐
- `item.itemName?.includes('套餐')` 更是直接按名称文字判断,极不准确
- 影响位置:
- 检验项目选择区line 566`<el-tag v-if="item.isPackage">套餐</el-tag>`
- 已选项目列表line 617`<el-tag v-if="item.isPackage">套餐</el-tag>`
- 检验信息详情表格line 448`<el-tag v-if="scope.row.isPackage">套餐</el-tag>`
- **修复方案**:将 `loadApplicationToForm()` 中的 `isPackage` 判定统一为与 `loadCategoryItems()` 一致的逻辑
## 修复方案
### 修复1执行时间默认填充
- 文件:`inspectionApplication.vue`
- 位置:`initData()` 函数,在已有患者信息赋值后添加 `formData.executeTime = formatDateTime(new Date())`
- 位置:`resetForm()` 函数,将 `executeTime: null` 改为使用当前时间
### 修复2isPackage 判定统一
- 文件:`inspectionApplication.vue`
- 位置:`loadApplicationToForm()` 函数 line 2000
- 旧代码:`const isPackage = item.feePackageId != null || item.itemName?.includes('套餐')`
- 新代码:`const isPackage = item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName`
## 验收标准
1. 新增检验申请单时执行时间字段自动填充当前系统时间YYYY-MM-DD HH:mm:ss 格式)
2. 检验项目列表中,只有真正的套餐项目前显示"套餐"标签,普通项目不显示
3. 就诊卡号在有患者信息时正常显示

Submodule his-repo updated: 5de8a22418...515ed84118

View File

@@ -1,6 +1,7 @@
package com.core.framework.config;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
@@ -34,7 +35,9 @@ public class ApplicationConfig {
// 设置日期格式为 yyyy/M/d HH:mm:ss支持多种格式反序列化
builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
// 添加JavaTimeModule支持用于LocalDateTime
builder.modules(new JavaTimeModule());
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
builder.modules(javaTimeModule);
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
};
}

View File

@@ -199,7 +199,7 @@ public class TicketAppServiceImpl implements ITicketAppService {
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(raw.getOrderStatus())) {
dto.setStatus("已退号");
} else {
dto.setStatus("锁定");
dto.setStatus("预约");
}
} else if (status == SlotStatus.BOOKED) {
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(raw.getOrderStatus())) {
@@ -380,7 +380,7 @@ public class TicketAppServiceImpl implements ITicketAppService {
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(raw.getOrderStatus())) {
dto.setStatus("已退号");
} else {
dto.setStatus("锁定");
dto.setStatus("预约");
}
} else if (status == SlotStatus.BOOKED) {
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(raw.getOrderStatus())) {

View File

@@ -169,7 +169,7 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
if (DateTimeUtils.isOverlap(organizationLocation.getStartTime(), organizationLocation.getEndTime(),
orgLoc.getStartTime(), orgLoc.getEndTime())) {
Organization org = organizationService.getById(organizationLocation.getOrganizationId());
String organizationName = org != null ? org.getName() : "已删除科室(ID:" + organizationLocation.getOrganizationId() + ")";
String organizationName = org != null ? org.getName() : ("科室[" + organizationLocation.getOrganizationId() + "]已删除");
return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime()
+ CommonConstants.Common.DASH + orgLoc.getEndTime() + "" + organizationName + "时间冲突");
}

View File

@@ -31,4 +31,9 @@ public class OrgLocQueryParam implements Serializable {
/** 发放类别 */
private String distributionCategoryCode;
/**
* 项目编码 | 药品:1 耗材:2
*/
private String itemCode;
}

View File

@@ -215,7 +215,10 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
if (surgery != null) {
surgery.setStatusEnum(1); // 1 = 已排期
surgery.setUpdateTime(new Date());
// Bug #558: 手术安排时同步写入手术室确认时间和确认人
surgery.setOperatingRoomConfirmTime(new Date());
surgery.setOperatingRoomConfirmUser(loginUser.getUsername());
// 填充缺失的申请科室和主刀医生名称
fillSurgeryMissingNames(surgery);

View File

@@ -36,4 +36,7 @@ public class PerformInfoDto {
/** 分组id */
@JsonSerialize(using = ToStringSerializer.class)
private Long groupId;
/** 退回原因 */
private String backReason;
}

View File

@@ -147,6 +147,6 @@ public interface IDoctorStationAdviceAppService {
*/
IPage<SurgeryItemDto> getSurgeryPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey);
IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey);
IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey, String categoryCode);
}

View File

@@ -63,17 +63,21 @@ public interface IDoctorStationEmrAppService {
* 获取待写病历列表
*
* @param doctorId 医生ID
* @return 待写病历列表
* @param pageNo 当前页码
* @param pageSize 每页条数
* @param patientName 患者姓名(可选)
* @return 待写病历分页数据
*/
R<?> getPendingEmrList(Long doctorId);
R<?> getPendingEmrList(Long doctorId, Integer pageNo, Integer pageSize, String patientName);
/**
* 获取待写病历数量
*
* @param doctorId 医生ID
* @param patientName 患者姓名(可选)
* @return 待写病历数量
*/
R<?> getPendingEmrCount(Long doctorId);
R<?> getPendingEmrCount(Long doctorId, String patientName);
/**
* 检查患者是否需要写病历

View File

@@ -2192,11 +2192,6 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(),
sourceEnum, sourceBillNo);
// 手术计费场景sourceBillNo 不为空时过滤掉药品1保留耗材2和诊疗3/6
if (sourceBillNo != null && !sourceBillNo.isEmpty()) {
requestBaseInfo.removeIf(dto -> dto.getAdviceType() != null
&& dto.getAdviceType() == 1);
}
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
// 请求状态
requestBaseDto
@@ -2210,6 +2205,10 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 收费状态
requestBaseDto.setChargeStatus_enumText(
EnumUtils.getInfoByValue(ChargeItemStatus.class, requestBaseDto.getChargeStatus()));
// 单位字典翻译失败时回退使用原始值(如手术申请硬编码了中文单位名)
if (StringUtils.isNotBlank(requestBaseDto.getUnitCode()) && StringUtils.isBlank(requestBaseDto.getUnitCode_dictText())) {
requestBaseDto.setUnitCode_dictText(requestBaseDto.getUnitCode());
}
}
return R.ok(requestBaseInfo);
}
@@ -2571,12 +2570,13 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
}
@Override
public IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey) {
public IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey, String categoryCode) {
IPage<SurgeryItemDto> result = doctorStationAdviceAppMapper.getExaminationPage(
new Page<>(pageNo, pageSize),
PublicationStatus.ACTIVE.getValue(),
organizationId,
searchKey);
searchKey,
categoryCode);
return result;
}

View File

@@ -29,6 +29,7 @@ import com.openhis.document.service.IEmrTemplateService;
import com.openhis.web.doctorstation.appservice.IDoctorStationEmrAppService;
import com.openhis.web.doctorstation.dto.EmrTemplateDto;
import com.openhis.web.doctorstation.dto.PatientEmrDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@@ -41,6 +42,7 @@ import java.util.stream.Collectors;
/**
* 医生站-电子病历 应用实现类
*/
@Slf4j
@Service
public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppService {
@@ -60,13 +62,7 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
IDocRecordService docRecordService;
@Resource
private EncounterMapper encounterMapper;
@Resource
private PatientMapper patientMapper;
@Resource
private com.openhis.administration.mapper.EncounterParticipantMapper encounterParticipantMapper;
private com.openhis.web.doctorstation.mapper.DoctorStationEmrAppMapper doctorStationEmrAppMapper;
/**
* 添加病人病历信息
@@ -223,52 +219,29 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
* @return 待写病历列表
*/
@Override
public R<?> getPendingEmrList(Long doctorId) {
// 由于Encounter实体中没有jzPractitionerUserId字段我们需要通过关联查询来获取相关信息
// 使用医生工作站的mapper来查询相关数据
// 这里我们直接使用医生工作站的查询逻辑
public R<?> getPendingEmrList(Long doctorId, Integer pageNo, Integer pageSize, String patientName) {
// 先查询总数
Long total = doctorStationEmrAppMapper.getPendingEmrCount(doctorId, patientName);
// 查询当前医生负责的、状态为"就诊中"但还没有写病历的患者
// 需要通过EncounterParticipant表来关联医生信息
List<Encounter> encounters = encounterMapper.selectList(
new LambdaQueryWrapper<Encounter>()
.eq(Encounter::getStatusEnum, EncounterStatus.IN_PROGRESS.getValue())
);
// 计算分页偏移量,再查询分页数据
int offset = (pageNo - 1) * pageSize;
List<Map<String, Object>> pageRows = doctorStationEmrAppMapper.getPendingEmrList(doctorId, patientName, pageSize, offset);
// 过滤出由指定医生负责且还没有写病历的就诊记录
List<Map<String, Object>> pendingEmrs = new ArrayList<>();
for (Encounter encounter : encounters) {
// 检查该就诊记录是否已经有病历
Emr existingEmr = emrService.getOne(
new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounter.getId())
);
// 检查该就诊是否由指定医生负责
boolean isAssignedToDoctor = isEncounterAssignedToDoctor(encounter.getId(), doctorId);
if (existingEmr == null && isAssignedToDoctor) {
// 如果没有病历且由该医生负责,则添加到待写病历列表
Map<String, Object> pendingEmr = new java.util.HashMap<>();
// 获取患者信息
Patient patient = patientMapper.selectById(encounter.getPatientId());
pendingEmr.put("encounterId", encounter.getId());
pendingEmr.put("patientId", encounter.getPatientId());
pendingEmr.put("patientName", patient != null ? patient.getName() : "未知");
pendingEmr.put("gender", patient != null ? patient.getGenderEnum() : null);
// 使用出生日期计算年龄
pendingEmr.put("age", patient != null && patient.getBirthDate() != null ?
calculateAge(patient.getBirthDate()) : null);
// 使用创建时间作为挂号时间
pendingEmr.put("registerTime", encounter.getCreateTime());
pendingEmr.put("busNo", encounter.getBusNo()); // 病历号
pendingEmrs.add(pendingEmr);
// 计算年龄列
for (Map<String, Object> row : pageRows) {
Object birthDate = row.get("birthDate");
if (birthDate instanceof Date) {
row.put("age", calculateAge((Date) birthDate));
} else {
row.put("age", null);
}
row.remove("birthDate");
}
return R.ok(pendingEmrs);
Map<String, Object> result = new java.util.HashMap<>();
result.put("rows", pageRows);
result.put("total", total != null ? total : 0L);
return R.ok(result);
}
/**
@@ -278,14 +251,9 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
* @return 待写病历数量
*/
@Override
public R<?> getPendingEmrCount(Long doctorId) {
// 获取待写病历列表,然后返回数量
R<?> result = getPendingEmrList(doctorId);
if (result.getCode() == 200) {
List<?> pendingEmrs = (List<?>) result.getData();
return R.ok(pendingEmrs.size());
}
return R.ok(0);
public R<?> getPendingEmrCount(Long doctorId, String patientName) {
Long count = doctorStationEmrAppMapper.getPendingEmrCount(doctorId, patientName);
return R.ok(count != null ? count.intValue() : 0);
}
/**
@@ -306,24 +274,6 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
return R.ok(needWrite);
}
/**
* 检查就诊是否分配给指定医生
*
* @param encounterId 就诊ID
* @param doctorId 医生ID
* @return 是否分配给指定医生
*/
private boolean isEncounterAssignedToDoctor(Long encounterId, Long doctorId) {
// 查询就诊参与者表,检查是否有指定医生的接诊记录
com.openhis.administration.domain.EncounterParticipant participant =
encounterParticipantMapper.selectOne(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.openhis.administration.domain.EncounterParticipant>()
.eq(com.openhis.administration.domain.EncounterParticipant::getEncounterId, encounterId)
.eq(com.openhis.administration.domain.EncounterParticipant::getPractitionerId, doctorId)
);
return participant != null;
}
/**
* 根据出生日期计算年龄

View File

@@ -77,8 +77,10 @@ public class DoctorStationAdviceController {
*/
@PostMapping(value = "/save-advice")
@RepeatSubmit(interval = 5000, message = "请勿重复提交医嘱,请稍候再试")
public R<?> saveAdvice(@RequestBody AdviceSaveParam adviceSaveParam) {
return iDoctorStationAdviceAppService.saveAdvice(adviceSaveParam, AdviceOpType.SAVE_ADVICE.getCode());
public R<?> saveAdvice(@RequestBody AdviceSaveParam adviceSaveParam,
@RequestParam(required = false, defaultValue = "1") String adviceOpType) {
// 🔧 Bug #445 修复:使用前端传入的 adviceOpType 参数1=保存草稿2=签发),而非硬编码
return iDoctorStationAdviceAppService.saveAdvice(adviceSaveParam, adviceOpType);
}
/**
@@ -226,8 +228,9 @@ public class DoctorStationAdviceController {
@RequestParam(value = "organizationId", required = false) Long organizationId,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "500") Integer pageSize,
@RequestParam(value = "searchKey", defaultValue = "") String searchKey) {
return R.ok(iDoctorStationAdviceAppService.getExaminationPage(organizationId, pageNo, pageSize, searchKey));
@RequestParam(value = "searchKey", defaultValue = "") String searchKey,
@RequestParam(value = "categoryCode", defaultValue = "23") String categoryCode) {
return R.ok(iDoctorStationAdviceAppService.getExaminationPage(organizationId, pageNo, pageSize, searchKey, categoryCode));
}
}

View File

@@ -26,34 +26,36 @@ public class PendingEmrController {
* 获取待写病历列表
*
* @param doctorId 医生ID
* @return 待写病历列表
* @param pageNo 当前页码
* @param pageSize 每页条数
* @param patientName 患者姓名(可选)
* @return 待写病历分页数据
*/
@GetMapping("/pending-list")
public R<?> getPendingEmrList(@RequestParam(required = false) Long doctorId) {
// 如果没有传递医生ID则使用当前登录用户ID
public R<?> getPendingEmrList(@RequestParam(required = false) Long doctorId,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String patientName) {
if (doctorId == null) {
doctorId = com.core.common.utils.SecurityUtils.getLoginUser().getUserId();
doctorId = com.core.common.utils.SecurityUtils.getLoginUser().getPractitionerId();
}
// 调用服务获取待写病历列表
return iDoctorStationEmrAppService.getPendingEmrList(doctorId);
return iDoctorStationEmrAppService.getPendingEmrList(doctorId, pageNum, pageSize, patientName);
}
/**
* 获取待写病历数量
*
*
* @param doctorId 医生ID
* @param patientName 患者姓名(可选)
* @return 待写病历数量
*/
@GetMapping("/pending-count")
public R<?> getPendingEmrCount(@RequestParam(required = false) Long doctorId) {
// 如果没有传递医生ID则使用当前登录用户ID
public R<?> getPendingEmrCount(@RequestParam(required = false) Long doctorId,
@RequestParam(required = false) String patientName) {
if (doctorId == null) {
doctorId = com.core.common.utils.SecurityUtils.getLoginUser().getUserId();
doctorId = com.core.common.utils.SecurityUtils.getLoginUser().getPractitionerId();
}
// 调用服务获取待写病历数量
return iDoctorStationEmrAppService.getPendingEmrCount(doctorId);
return iDoctorStationEmrAppService.getPendingEmrCount(doctorId, patientName);
}
/**

View File

@@ -198,8 +198,10 @@ public class AdviceBaseDto {
/**
* 所属科室
*/
@Dict(dictTable = "adm_organization", dictCode = "id", dictText = "name")
@JsonSerialize(using = ToStringSerializer.class)
private Long orgId;
private String orgId_dictText;
/**
* 所在位置

View File

@@ -8,6 +8,10 @@ import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
@@ -26,6 +30,14 @@ public class AdviceSaveDto {
/** 医嘱类型 */
private Integer adviceType; // 1:药品 , 2: 耗材 , 3:项目
/**
* 医嘱开始时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 请求id
*/

View File

@@ -63,6 +63,18 @@ public class PatientDetailsDto {
*/
private String address;
/** 地址省 */
private String addressProvince;
/** 地址市 */
private String addressCity;
/** 地址区 */
private String addressDistrict;
/** 地址街道 */
private String addressStreet;
/**
* 工作单位
*/

View File

@@ -22,6 +22,12 @@ public class RequestBaseDto {
*/
private Integer adviceType; // 1:药品 , 2: 耗材 , 3:项目
/**
* 医嘱开始时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 唯一标识
*/
@@ -121,6 +127,11 @@ public class RequestBaseDto {
* 请求状态
*/
private Integer statusEnum;
/**
* 退回原因
*/
private String reasonText;
private String statusEnum_enumText;
/**
@@ -238,4 +249,15 @@ public class RequestBaseDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long patientId;
/**
* 停嘱医生
*/
private String stopUserName;
/**
* 停嘱时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date stopTime;
}

View File

@@ -23,6 +23,9 @@ public class SurgeryItemDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long orgId;
/** 所属科室名称 */
private String orgName;
/** 执行科室ID */
@JsonSerialize(using = ToStringSerializer.class)
private Long positionId;

View File

@@ -203,6 +203,7 @@ public interface DoctorStationAdviceAppMapper {
IPage<SurgeryItemDto> getExaminationPage(@Param("page") Page<SurgeryItemDto> page,
@Param("statusEnum") Integer statusEnum,
@Param("organizationId") Long organizationId,
@Param("searchKey") String searchKey);
@Param("searchKey") String searchKey,
@Param("categoryCode") String categoryCode);
}

View File

@@ -1,11 +1,22 @@
package com.openhis.web.doctorstation.mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* 医生站-电子病历 应用Mapper
*/
@Repository
public interface DoctorStationEmrAppMapper {
List<Map<String, Object>> getPendingEmrList(@Param("doctorId") Long doctorId,
@Param("patientName") String patientName,
@Param("pageSize") Integer pageSize,
@Param("offset") Integer offset);
Long getPendingEmrCount(@Param("doctorId") Long doctorId,
@Param("patientName") String patientName);
}

View File

@@ -178,11 +178,24 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
inpatientAdviceParam.setEncounterIds(null);
Integer exeStatus = inpatientAdviceParam.getExeStatus();
inpatientAdviceParam.setExeStatus(null);
// requestStatus由前端tab传入通过QueryWrapper自动添加到SQL外层WHERE过滤
// 提取requestStatus手动处理支持COMPLETED(3)和CHECK_VERIFIED(10)同时查询
Integer requestStatus = inpatientAdviceParam.getRequestStatus();
inpatientAdviceParam.setRequestStatus(null);
// 构建查询条件
QueryWrapper<InpatientAdviceParam> queryWrapper
= HisQueryUtils.buildQueryWrapper(inpatientAdviceParam, null, null, null);
// 手动拼接requestStatus条件COMPLETED(3)时同时包含CHECK_VERIFIED(10)
// UNION查询外层列名为request_statusT1.status_enum AS request_status不是status_enum
if (requestStatus != null) {
if (RequestStatus.COMPLETED.getValue().equals(requestStatus)) {
queryWrapper.in("request_status",
RequestStatus.COMPLETED.getValue(), RequestStatus.CHECK_VERIFIED.getValue());
} else {
queryWrapper.eq("request_status", requestStatus);
}
}
// 手动拼接住院患者id条件
if (encounterIds != null && !encounterIds.isEmpty()) {
List<Long> encounterIdList
@@ -315,19 +328,29 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
Date checkDate = new Date();
if (!serviceRequestList.isEmpty()) {
// 更新服务请求状态已完成
serviceRequestService.updateCompleteRequestStatus(
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
List<ServiceRequest> serviceRequests = serviceRequestService
.listByIds(serviceRequestList.stream().map(PerformInfoDto::getRequestId).collect(Collectors.toList()));
for (ServiceRequest serviceRequest : serviceRequests) {
// 判断医嘱类型
List<Long> serviceReqIds = serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList();
// 先查询服务请求,按 categoryEnum 分流:检查类(23)走 CHECK_VERIFIED其余走 COMPLETED
List<ServiceRequest> allServiceRequests = serviceRequestService.listByIds(serviceReqIds);
List<Long> checkReqIds = allServiceRequests.stream()
.filter(sr -> ActivityDefCategory.TEST.getValue().equals(sr.getCategoryEnum()))
.map(ServiceRequest::getId).toList();
List<Long> otherReqIds = allServiceRequests.stream()
.filter(sr -> !ActivityDefCategory.TEST.getValue().equals(sr.getCategoryEnum()))
.map(ServiceRequest::getId).toList();
// 检查类 → 已校对CHECK_VERIFIED=10
if (!checkReqIds.isEmpty()) {
serviceRequestService.updateCheckVerifiedStatus(checkReqIds, practitionerId, checkDate);
}
// 其他类 → 已完成COMPLETED=3
if (!otherReqIds.isEmpty()) {
serviceRequestService.updateCompleteRequestStatus(otherReqIds, practitionerId, checkDate);
}
// 处理转科/出院等特殊医嘱
for (ServiceRequest serviceRequest : allServiceRequests) {
if (ActivityDefCategory.TRANSFER.getValue().equals(serviceRequest.getCategoryEnum())) {
// 更新患者状态 待转科
encounterService.updateEncounterStatus(serviceRequest.getEncounterId(),
EncounterZyStatus.PENDING_TRANSFER.getValue());
} else if (ActivityDefCategory.DISCHARGE.getValue().equals(serviceRequest.getCategoryEnum())) {
// 更新患者状态 待出院
encounterService.updateEncounterStatus(serviceRequest.getEncounterId(),
EncounterZyStatus.AWAITING_DISCHARGE.getValue());
}
@@ -359,6 +382,24 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
medRequestList.add(item);
}
}
// 校验医嘱是否已执行,已执行的医嘱需要先取消执行后才能退回
List<Long> allRequestIds = performInfoList.stream().map(PerformInfoDto::getRequestId).toList();
List<Procedure> allProcedures = procedureService.list(
new LambdaQueryWrapper<Procedure>()
.in(Procedure::getRequestId, allRequestIds)
.eq(Procedure::getDeleteFlag, "0"));
Set<Long> executedIds = allProcedures.stream()
.filter(p -> EventStatus.COMPLETED.getValue().equals(p.getStatusEnum()))
.map(Procedure::getId)
.collect(Collectors.toSet());
Set<Long> cancelledRefundIds = allProcedures.stream()
.filter(p -> EventStatus.CANCEL.getValue().equals(p.getStatusEnum()) && p.getRefundId() != null)
.map(Procedure::getRefundId)
.collect(Collectors.toSet());
executedIds.removeAll(cancelledRefundIds);
if (!executedIds.isEmpty()) {
return R.fail("该医嘱已执行,请先取消执行后再退回");
}
// 校验药品医嘱是否已发药,已发药的医嘱不允许退回
if (!medRequestList.isEmpty()) {
List<Long> medReqIds = medRequestList.stream().map(PerformInfoDto::getRequestId).toList();
@@ -374,13 +415,14 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
Date checkDate = new Date();
if (!serviceRequestList.isEmpty()) {
// 更新服务请求状态待发送
String backReason = performInfoList.get(0).getBackReason();
serviceRequestService.updateDraftStatus(
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
}
if (!medRequestList.isEmpty()) {
// 更新药品请求状态待发送
medicationRequestService.updateDraftStatusBatch(
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
}
return R.ok(null, "退回成功");
}
@@ -424,6 +466,15 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
List<ServiceRequestUseExe> actUseExeList = this.assemblyActivity(activityList);
// 处理诊疗执行
this.exeActivity(actUseExeList, exeDate);
// 检查类医嘱执行后,状态改为"待接收"PENDING_RECEIVE=11
List<Long> actReqIds = activityList.stream().map(AdviceExecuteDetailParam::getRequestId).toList();
List<ServiceRequest> executedReqs = serviceRequestService.listByIds(actReqIds);
List<Long> checkReqIds = executedReqs.stream()
.filter(sr -> ActivityDefCategory.TEST.getValue().equals(sr.getCategoryEnum()))
.map(ServiceRequest::getId).toList();
if (!checkReqIds.isEmpty()) {
serviceRequestService.updatePendingReceiveStatus(checkReqIds);
}
}
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"医嘱执行"}));

View File

@@ -78,12 +78,10 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
.map(notPerformedReason -> new DispenseInitDto.NotPerformedReasonOption(notPerformedReason.getValue(),
notPerformedReason.getInfo()))
.collect(Collectors.toList());
// 发药状态
// 发药状态(汇总单:待配药→已提交,已发放→已发药)
List<DispenseStatusOption> dispenseStatusOptions = new ArrayList<>();
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.PREPARATION.getValue(),
DispenseStatus.PREPARATION.getInfo()));
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.COMPLETED.getValue(),
DispenseStatus.COMPLETED.getInfo()));
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.PREPARATION.getValue(), "已提交"));
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.COMPLETED.getValue(), "已发药"));
initDto.setNotPerformedReasonOptions(notPerformedReasonOptions).setDispenseStatusOptions(dispenseStatusOptions);
return R.ok(initDto);
@@ -161,8 +159,8 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
new Page<>(pageNo, pageSize), queryWrapper, DispenseStatus.COMPLETED.getValue(),
DispenseStatus.PREPARATION.getValue(), SupplyType.SUMMARY_DISPENSE.getValue());
medicineSummaryFormPage.getRecords().forEach(e -> {
// 发药状态
e.setStatusEnum_enumText(EnumUtils.getInfoByValue(DispenseStatus.class, e.getStatusEnum()));
// 发药状态(汇总单展示文案)
e.setStatusEnum_enumText(getSummaryFormStatusText(e.getStatusEnum()));
});
return R.ok(medicineSummaryFormPage);
}
@@ -292,4 +290,17 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
}
return R.ok(MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"取消"}));
}
/**
* 汇总发药单状态展示文案(药品医嘱状态映射表:汇总申请→已提交,发药→已发药)
*/
private String getSummaryFormStatusText(Integer statusEnum) {
if (DispenseStatus.PREPARATION.getValue().equals(statusEnum)) {
return "已提交";
}
if (DispenseStatus.COMPLETED.getValue().equals(statusEnum)) {
return "已发药";
}
return EnumUtils.getInfoByValue(DispenseStatus.class, statusEnum);
}
}

View File

@@ -86,7 +86,12 @@ public class OutpatientRecordServiceImpl implements IOutpatientRecordService {
// 处理就诊对象状态筛选
if (outpatientRecordSearchParam.getSubjectStatusEnum() != null) {
queryWrapper.eq("enc.status_enum", outpatientRecordSearchParam.getSubjectStatusEnum());
if (outpatientRecordSearchParam.getSubjectStatusEnum() == 0) {
// 前端选择"无状态"(0)时,过滤 status_enum IS NULL 的记录
queryWrapper.isNull("enc.status_enum");
} else {
queryWrapper.eq("enc.status_enum", outpatientRecordSearchParam.getSubjectStatusEnum());
}
}
// 处理医生姓名查询(支持模糊查询)

View File

@@ -133,47 +133,13 @@ public class PatientInformationServiceImpl implements IPatientInformationService
@Override
public IPage<PatientBaseInfoDto> getPatientInfo(PatientBaseInfoDto patientBaseInfoDto, String searchKey,
Integer pageNo, Integer pageSize, HttpServletRequest request) {
// 获取登录者信息
// 构建基础查询条件
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userId = loginUser.getUserId();
Integer tenantId = loginUser.getTenantId().intValue();
// 先构建基础查询条件
QueryWrapper<PatientBaseInfoDto> queryWrapper = HisQueryUtils.buildQueryWrapper(
patientBaseInfoDto, searchKey, new HashSet<>(Arrays.asList(CommonConstants.FieldName.Name,
CommonConstants.FieldName.BusNo, CommonConstants.FieldName.PyStr, CommonConstants.FieldName.WbStr)),
request);
// 检查是否是精确ID查询从门诊挂号页面跳转时使用
boolean hasExactIdQuery = (patientBaseInfoDto.getId() != null);
// 只有非精确ID查询时才添加医生患者过滤条件
if (!hasExactIdQuery) {
// 查询当前用户对应的医生信息
LambdaQueryWrapper<com.openhis.administration.domain.Practitioner> practitionerQuery = new LambdaQueryWrapper<>();
practitionerQuery.eq(com.openhis.administration.domain.Practitioner::getUserId, userId);
// 使用list()避免TooManyResultsException异常然后取第一个记录
List<com.openhis.administration.domain.Practitioner> practitionerList = practitionerService.list(practitionerQuery);
com.openhis.administration.domain.Practitioner practitioner = practitionerList != null && !practitionerList.isEmpty() ? practitionerList.get(0) : null;
// 如果当前用户是医生,添加医生患者过滤条件
if (practitioner != null) {
// 查询该医生作为接诊医生ADMITTER, code="1"和挂号医生REGISTRATION_DOCTOR, code="12"的所有就诊记录的患者ID
List<Long> doctorPatientIds = patientManageMapper.getPatientIdsByPractitionerId(
practitioner.getId(),
Arrays.asList(ParticipantType.ADMITTER.getCode(), ParticipantType.REGISTRATION_DOCTOR.getCode()),
tenantId);
if (doctorPatientIds != null && !doctorPatientIds.isEmpty()) {
// 添加患者ID过滤条件 - 注意:这里使用列名而不是表别名
queryWrapper.in("id", doctorPatientIds);
} else {
// 如果没有相关患者,返回空结果
queryWrapper.eq("id", -1); // 设置一个不存在的ID
}
}
// 如果不是医生,查询所有患者
}
IPage<PatientBaseInfoDto> patientInformationPage
= patientManageMapper.getPatientPage(new Page<>(pageNo, pageSize), queryWrapper);

View File

@@ -69,4 +69,12 @@ public interface IAdviceManageAppService {
*/
R<?> stopRegAdvice(List<AdviceBatchOpParam> paramList);
/**
* 住院医嘱取消停嘱(恢复)
*
* @param paramList 恢复参数
* @return 结果
*/
R<?> cancelStopRegAdvice(List<AdviceBatchOpParam> paramList);
}

View File

@@ -18,6 +18,7 @@ import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.medication.domain.MedicationDispense;
import com.openhis.medication.domain.MedicationRequest;
import com.openhis.medication.service.IMedicationDispenseService;
import com.openhis.medication.service.IMedicationRequestService;
@@ -415,7 +416,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
}
// 保存时处理的字段属性
if (is_save) {
longMedicationRequest.setEffectiveDoseStart(startTime); // 医嘱开始时间
longMedicationRequest.setEffectiveDoseStart(regAdviceSaveDto.getStartTime() != null ? regAdviceSaveDto.getStartTime() : startTime); // 医嘱开始时间
longMedicationRequest
.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_RES_NO.getPrefix(), 4));
longMedicationRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
@@ -503,7 +504,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
}
// 保存时处理的字段属性
if (is_save) {
tempMedicationRequest.setEffectiveDoseStart(startTime); // 医嘱开始时间
tempMedicationRequest.setEffectiveDoseStart(regAdviceSaveDto.getStartTime() != null ? regAdviceSaveDto.getStartTime() : startTime); // 医嘱开始时间
tempMedicationRequest
.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_RES_NO.getPrefix(), 4));
tempMedicationRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
@@ -615,7 +616,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
}
// 保存时处理的字段属性
if (is_save) {
longServiceRequest.setOccurrenceStartTime(startTime); // 医嘱开始时间
longServiceRequest.setOccurrenceStartTime(regAdviceSaveDto.getStartTime() != null ? regAdviceSaveDto.getStartTime() : startTime); // 医嘱开始时间
longServiceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4));
longServiceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
longServiceRequest.setQuantity(new BigDecimal("1")); // 请求数量 | 诊疗的长期医嘱数量都是1
@@ -666,7 +667,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
}
// 保存时处理的字段属性
if (is_save) {
tempServiceRequest.setOccurrenceStartTime(startTime); // 医嘱开始时间
tempServiceRequest.setOccurrenceStartTime(regAdviceSaveDto.getStartTime() != null ? regAdviceSaveDto.getStartTime() : startTime); // 医嘱开始时间
tempServiceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4));
tempServiceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
tempServiceRequest.setQuantity(regAdviceSaveDto.getQuantity()); // 请求数量
@@ -812,7 +813,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
deviceRequest.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
deviceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
deviceRequest.setOrgId(regAdviceSaveDto.getFounderOrgId()); // 开方人科室
deviceRequest.setReqAuthoredTime(startTime); // 医嘱开始时间
deviceRequest.setReqAuthoredTime(regAdviceSaveDto.getStartTime() != null ? regAdviceSaveDto.getStartTime() : startTime); // 医嘱开始时间
deviceRequest.setPerformLocation(regAdviceSaveDto.getLocationId()); // 发放科室
deviceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
deviceRequest.setPackageId(regAdviceSaveDto.getPackageId()); // 组套id
@@ -851,7 +852,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
deviceRequest.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
deviceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
deviceRequest.setOrgId(regAdviceSaveDto.getFounderOrgId()); // 开方人科室
deviceRequest.setReqAuthoredTime(startTime); // 医嘱开始时间
deviceRequest.setReqAuthoredTime(regAdviceSaveDto.getStartTime() != null ? regAdviceSaveDto.getStartTime() : startTime); // 医嘱开始时间
deviceRequest.setPerformLocation(regAdviceSaveDto.getLocationId()); // 发放科室
deviceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
deviceRequest.setPackageId(regAdviceSaveDto.getPackageId()); // 组套id
@@ -1043,8 +1044,14 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
*/
@Override
public R<?> stopRegAdvice(List<AdviceBatchOpParam> paramList) {
// 当前时间
Date date = new Date();
// 获取停嘱时间:优先从前端传入的 stopTime否则用当前时间
Date stopTime = paramList.stream()
.map(AdviceBatchOpParam::getStopTime)
.filter(Objects::nonNull)
.findFirst()
.orElse(new Date());
// 获取当前操作用户昵称作为停嘱医生
String stopUserName = SecurityUtils.getNickName();
// 药品
List<AdviceBatchOpParam> medicineList = paramList.stream()
.filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())).collect(Collectors.toList());
@@ -1059,15 +1066,112 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
= activityList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList());
if (!medicineRequestIds.isEmpty()) {
iMedicationRequestService.update(new LambdaUpdateWrapper<MedicationRequest>()
.in(MedicationRequest::getId, medicineRequestIds).set(MedicationRequest::getEffectiveDoseEnd, date)
.set(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue()));
.in(MedicationRequest::getId, medicineRequestIds)
.set(MedicationRequest::getEffectiveDoseEnd, stopTime)
.set(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue())
.set(MedicationRequest::getUpdateBy, stopUserName));
}
if (!activityRequestIds.isEmpty()) {
iServiceRequestService.update(new LambdaUpdateWrapper<ServiceRequest>()
.in(ServiceRequest::getId, activityRequestIds).set(ServiceRequest::getOccurrenceEndTime, date)
.set(ServiceRequest::getStatusEnum, RequestStatus.STOPPED.getValue()));
.in(ServiceRequest::getId, activityRequestIds)
.set(ServiceRequest::getOccurrenceEndTime, stopTime)
.set(ServiceRequest::getStatusEnum, RequestStatus.STOPPED.getValue())
.set(ServiceRequest::getUpdateBy, stopUserName));
}
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"医嘱停止"}));
}
/**
* 住院医嘱取消停嘱(恢复)
*
* 核心业务逻辑:
* 1. 护士站校验:护士站尚未对该医嘱的停止进行"停止核对/确认"(即 dispense 状态未进入已发药/完成状态)
* 2. 药房端校验:药房尚未对该停嘱单进行退药接收/退费入库确认
* 3. 若校验通过,将医嘱状态复原为"已签发";清空停嘱时间与停嘱医生字段;
* 同时自动作废已生成的待发药退回/退药申请
*
* @param paramList 恢复参数
* @return 结果
*/
@Override
public R<?> cancelStopRegAdvice(List<AdviceBatchOpParam> paramList) {
// 药品
List<AdviceBatchOpParam> medicineList = paramList.stream()
.filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())).collect(Collectors.toList());
List<Long> medicineRequestIds
= medicineList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList());
// 诊疗包含护理adviceType=26
List<AdviceBatchOpParam> activityList = paramList.stream()
.filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())
|| (e.getAdviceType() != null && e.getAdviceType() == 26))
.collect(Collectors.toList());
List<Long> activityRequestIds
= activityList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList());
// ============ 前置校验 ============
// 1. 护士站校验:查询药品发放记录,确认护士站是否已执行停止核对(发药)
if (!medicineRequestIds.isEmpty()) {
List<MedicationDispense> dispenseList = iMedicationDispenseService.selectByRequestIdList(medicineRequestIds);
for (MedicationDispense dispense : dispenseList) {
// 如果发放状态 >= COMPLETED(4),说明护士站已发药/已确认停止
if (dispense.getStatusEnum() != null && dispense.getStatusEnum() >= DispenseStatus.COMPLETED.getValue()
&& !DispenseStatus.ON_HOLD.getValue().equals(dispense.getStatusEnum())
&& !DispenseStatus.STOPPED.getValue().equals(dispense.getStatusEnum())
&& !DispenseStatus.CANCELLED.getValue().equals(dispense.getStatusEnum())) {
throw new ServiceException("护士站已确认停止该医嘱,无法取消停嘱!");
}
// 2. 药房端校验:如果已有退药/退费记录,说明药房已处理
if (DispenseStatus.RETURNED.getValue().equals(dispense.getStatusEnum())
|| DispenseStatus.REFUNDED.getValue().equals(dispense.getStatusEnum())
|| DispenseStatus.PART_REFUND.getValue().equals(dispense.getStatusEnum())) {
throw new ServiceException("药房已完成退药处理,无法取消停嘱!");
}
}
}
// ============ 执行恢复 ============
if (!medicineRequestIds.isEmpty()) {
// 恢复药品请求状态为"已发送"(ACTIVE=2),清空停嘱时间和更新人
iMedicationRequestService.update(new LambdaUpdateWrapper<MedicationRequest>()
.in(MedicationRequest::getId, medicineRequestIds)
.set(MedicationRequest::getStatusEnum, RequestStatus.ACTIVE.getValue())
.set(MedicationRequest::getEffectiveDoseEnd, null)
.set(MedicationRequest::getUpdateBy, null));
// 作废/删除与这些药品请求相关的待退药发放记录
List<MedicationDispense> relatedDispenseList = iMedicationDispenseService.selectByRequestIdList(medicineRequestIds);
for (MedicationDispense dispense : relatedDispenseList) {
if (DispenseStatus.PENDING_REFUND.getValue().equals(dispense.getStatusEnum())
|| DispenseStatus.CANCELLED.getValue().equals(dispense.getStatusEnum())
|| DispenseStatus.ON_HOLD.getValue().equals(dispense.getStatusEnum())) {
// 将待退药/暂停/撤回的记录标记为草稿,或删除
iMedicationDispenseService.update(new LambdaUpdateWrapper<MedicationDispense>()
.eq(MedicationDispense::getId, dispense.getId())
.set(MedicationDispense::getStatusEnum, DispenseStatus.DRAFT.getValue())
.set(MedicationDispense::getStatusChangedTime, new Date()));
}
// 如果 dispense 已处于 STOPPED(6) 状态,也恢复为草稿以重新触发配药流程
if (DispenseStatus.STOPPED.getValue().equals(dispense.getStatusEnum())) {
iMedicationDispenseService.update(new LambdaUpdateWrapper<MedicationDispense>()
.eq(MedicationDispense::getId, dispense.getId())
.set(MedicationDispense::getStatusEnum, DispenseStatus.PREPARATION.getValue())
.set(MedicationDispense::getStatusChangedTime, new Date()));
}
}
}
if (!activityRequestIds.isEmpty()) {
// 恢复诊疗请求状态为"已发送"(ACTIVE=2),清空停嘱时间和更新人
iServiceRequestService.update(new LambdaUpdateWrapper<ServiceRequest>()
.in(ServiceRequest::getId, activityRequestIds)
.set(ServiceRequest::getStatusEnum, RequestStatus.ACTIVE.getValue())
.set(ServiceRequest::getOccurrenceEndTime, null)
.set(ServiceRequest::getUpdateBy, null));
}
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"医嘱恢复"}));
}
}

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.enums.DelFlag;
import com.core.common.exception.ServiceException;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
@@ -17,6 +18,8 @@ import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.document.domain.RequestForm;
import com.openhis.document.service.IRequestFormService;
import com.openhis.lab.domain.Specimen;
import com.openhis.lab.service.ISpecimenService;
import com.openhis.web.doctorstation.dto.ActivityChildrenJsonParams;
import com.openhis.web.doctorstation.utils.AdviceUtils;
import com.openhis.web.regdoctorstation.appservice.IRequestFormManageAppService;
@@ -67,6 +70,39 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
@Resource
IActivityDefinitionService iActivityDefinitionService;
@Resource
ISpecimenService iSpecimenService;
/**
* 校验当前用户是否有权操作该申请单(申请者本人或管理员)
*/
private R<?> validateRequestFormPermission(RequestForm requestForm) {
if (SecurityUtils.isAdmin(SecurityUtils.getUserId())) {
return null;
}
Long currentPractitionerId = SecurityUtils.getLoginUser().getPractitionerId();
Long requesterId = requestForm.getRequesterId();
if (currentPractitionerId == null || requesterId == null
|| !currentPractitionerId.equals(requesterId)) {
return R.fail("无操作权限,仅申请开立者或管理员可操作");
}
return null;
}
/**
* 校验关联医嘱是否已采证(存在已采集/已接收标本则不可撤回)
*/
private boolean hasCollectedSpecimen(List<Long> serviceRequestIds) {
if (serviceRequestIds == null || serviceRequestIds.isEmpty()) {
return false;
}
long count = iSpecimenService.count(
new LambdaQueryWrapper<Specimen>()
.in(Specimen::getServiceId, serviceRequestIds)
.ge(Specimen::getCollectionStatusEnum, SpecCollectStatus.COLLECTED.getValue()));
return count > 0;
}
/**
* 保存申请单
*
@@ -119,10 +155,13 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
return R.fail("无待签发的医嘱,该申请单不可编辑");
}
} else {
// 检查申请单JC检查+ Z住院标识+ yyMMdd日期+ 5位顺序
// 根据申请单类型生成不同前缀的单
String dateStr = new java.text.SimpleDateFormat("yyMMdd").format(new Date());
int seq = assignSeqUtil.getSeqNoByDay(AssignSeqEnum.CHECK_APPLY_NO.getPrefix());
prescriptionNo = "JCZ" + dateStr + String.format("%05d", seq);
AssignSeqEnum seqEnum = ActivityDefCategory.PROCEDURE.getCode().equals(typeCode)
? AssignSeqEnum.SURGERY_APPLY_NO
: AssignSeqEnum.CHECK_APPLY_NO;
int seq = assignSeqUtil.getSeqNoByDay(seqEnum.getPrefix());
prescriptionNo = seqEnum.getPrefix() + dateStr + String.format("%05d", seq);
}
// 当前时间
@@ -528,12 +567,17 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
if (requestForm == null) {
return R.fail("申请单不存在");
}
R<?> permissionResult = validateRequestFormPermission(requestForm);
if (permissionResult != null) {
return permissionResult;
}
String prescriptionNo = requestForm.getPrescriptionNo();
// 查询该申请单下所有 ServiceRequest含子项
List<ServiceRequest> serviceRequests = iServiceRequestService.list(
new LambdaQueryWrapper<ServiceRequest>()
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo));
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (serviceRequests == null || serviceRequests.isEmpty()) {
return R.fail("未找到关联的诊疗医嘱");
}
@@ -563,7 +607,7 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
// 4. 删除申请单
iRequestFormService.removeById(requestFormId);
log.info("申请单删除成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
log.info("申请单删除成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
return R.ok("删除成功");
}
@@ -576,32 +620,47 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
if (requestForm == null) {
return R.fail("申请单不存在");
}
R<?> permissionResult = validateRequestFormPermission(requestForm);
if (permissionResult != null) {
return permissionResult;
}
String prescriptionNo = requestForm.getPrescriptionNo();
// 查询该申请单下所有 ServiceRequest
List<ServiceRequest> serviceRequests = iServiceRequestService.list(
new LambdaQueryWrapper<ServiceRequest>()
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo));
.eq(ServiceRequest::getPrescriptionNo, prescriptionNo)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
if (serviceRequests == null || serviceRequests.isEmpty()) {
return R.fail("未找到关联的诊疗医嘱");
}
// 校验:只有已签发(status=2)的申请单可撤回
boolean allActive = serviceRequests.stream()
.allMatch(sr -> RequestStatus.ACTIVE.getValue().equals(sr.getStatusEnum()));
if (!allActive) {
return R.fail("只有已签发状态的申请单可撤回");
}
// 将所有 ServiceRequest 状态改回待签发(DRAFT=0)
List<Long> serviceRequestIds = serviceRequests.stream()
.map(ServiceRequest::getId).collect(Collectors.toList());
iServiceRequestService.update(
// 校验:标本已采集则不可撤回
if (hasCollectedSpecimen(serviceRequestIds)) {
return R.fail("标本已采集,无法撤回");
}
// 校验任一ServiceRequest为ACTIVE(status=2)即可撤回与SQL的EXISTS逻辑一致
boolean hasActive = serviceRequests.stream()
.anyMatch(sr -> RequestStatus.ACTIVE.getValue().equals(sr.getStatusEnum()));
if (!hasActive) {
return R.fail("只有已签发且未采证的申请单可撤回");
}
// 将所有已签发的 ServiceRequest 状态改回待签发,与申请单展示状态同步
boolean updated = iServiceRequestService.update(
new ServiceRequest().setStatusEnum(RequestStatus.DRAFT.getValue()),
new LambdaUpdateWrapper<ServiceRequest>()
.in(ServiceRequest::getId, serviceRequestIds));
.in(ServiceRequest::getId, serviceRequestIds)
.eq(ServiceRequest::getStatusEnum, RequestStatus.ACTIVE.getValue()));
if (!updated) {
return R.fail("撤回失败,医嘱状态已变更,请刷新后重试");
}
log.info("申请单撤回成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
log.info("申请单撤回成功requestFormId={}, prescriptionNo={}", requestFormId, prescriptionNo);
return R.ok("撤回成功");
}

View File

@@ -28,6 +28,7 @@ import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.util.CollectionUtils;
import java.util.stream.Collectors;
/**
@@ -161,7 +162,7 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
adviceBaseDto.setAdviceDefinitionId(definitionId); // 医嘱定义id
// 对应的诊疗医嘱信息
activityAdviceBaseDto = iDoctorStationAdviceAppService.getAdviceBaseInfo(adviceBaseDto, null, null,
null, null, 1, 1, Whether.NO.getValue(), List.of(3), null, null).getRecords().get(0);
null, null, 1, 1, null, List.of(3), null, null).getRecords().get(0);
// 逻辑1---------------------直接新增
longServiceRequest.setStatusEnum(RequestStatus.DRAFT.getValue());// 请求状态
longServiceRequest.setOccurrenceStartTime(startTime); // 医嘱开始时间
@@ -208,7 +209,7 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
adviceBaseDto.setAdviceDefinitionId(definitionId); // 医嘱定义id
// 对应的诊疗医嘱信息
activityAdviceBaseDto = iDoctorStationAdviceAppService
.getAdviceBaseInfo(adviceBaseDto, null, null, null, null, 1, 1, Whether.NO.getValue(), List.of(3), null, null)
.getAdviceBaseInfo(adviceBaseDto, null, null, null, null, 1, 1, null, List.of(3), null, null)
.getRecords().get(0);
longServiceRequest.setStatusEnum(RequestStatus.DRAFT.getValue());// 请求状态
@@ -348,7 +349,7 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
adviceBaseDto.setAdviceDefinitionId(transferOrganizationDefinitionId); // 医嘱定义id
// 转科的医嘱信息
AdviceBaseDto activityAdviceBaseDto = iDoctorStationAdviceAppService
.getAdviceBaseInfo(adviceBaseDto, null, null, null, null, 1, 1, Whether.NO.getValue(), List.of(3), null, null)
.getAdviceBaseInfo(adviceBaseDto, null, null, null, null, 1, 1, null, List.of(3), null, null)
.getRecords().get(0);
// 保存转科医嘱请求
ServiceRequest serviceRequest = new ServiceRequest();
@@ -400,7 +401,7 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
// 计划出院时间
Date endTime = leaveHospitalParam.getEndTime();
if (endTime == null) {
endTime = endTime;
endTime = new Date();
}
// 就诊id
Long encounterId = leaveHospitalParam.getEncounterId();
@@ -429,9 +430,12 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
}
// 出院的医嘱信息
AdviceBaseDto activityAdviceBaseDto = iDoctorStationAdviceAppService.getAdviceBaseInfo(null, null, null,
List.of(transferOrganizationDefinitionId), null, 1, 1, Whether.NO.getValue(), List.of(3), null, null).getRecords()
.get(0);
List<AdviceBaseDto> adviceList = iDoctorStationAdviceAppService.getAdviceBaseInfo(null, null, null,
List.of(transferOrganizationDefinitionId), null, 1, 1, null, List.of(3), null, null).getRecords();
if (CollectionUtils.isEmpty(adviceList)) {
return R.fail("未找到出院医嘱定义数据,请确认诊疗目录中已配置出院医嘱");
}
AdviceBaseDto activityAdviceBaseDto = adviceList.get(0);
// 保存出院医嘱请求
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setStatusEnum(RequestStatus.DRAFT.getValue());// 请求状态

View File

@@ -143,4 +143,15 @@ public class AdviceManageController {
return iAdviceManageAppService.stopRegAdvice(paramList);
}
/**
* 住院医嘱取消停嘱(恢复)
*
* @param paramList 恢复参数
* @return 结果
*/
@PostMapping(value = "/cancel-stop-reg-advice")
public R<?> cancelStopRegAdvice(@RequestBody List<AdviceBatchOpParam> paramList) {
return iAdviceManageAppService.cancelStopRegAdvice(paramList);
}
}

View File

@@ -143,14 +143,23 @@ public class RequestFormManageController {
* 查询手术申请单
*
* @param encounterId 就诊id
* @param startDate 开始日期可选格式yyyy-MM-dd
* @param endDate 结束日期可选格式yyyy-MM-dd
* @param status 单据状态(可选)
* @param keyword 关键字(可选,申请单号/手术项目名称模糊匹配)
* @return 手术申请单
*/
@GetMapping(value = "/get-surgery")
public R<?> getSurgeryRequestForm(@RequestParam(required = false) Long encounterId) {
public R<?> getSurgeryRequestForm(
@RequestParam(required = false) Long encounterId,
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate,
@RequestParam(required = false) String status,
@RequestParam(required = false) String keyword) {
if (encounterId == null) {
return R.fail("就诊ID不能为空");
}
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROCEDURE.getCode()));
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROCEDURE.getCode(), startDate, endDate, status, keyword));
}
/**
* 分页查询手术申请单全局不需要encounterId用于门诊手术安排查找弹窗
@@ -194,8 +203,8 @@ public class RequestFormManageController {
* @return 结果
*/
@PostMapping(value = "/delete")
public R<?> deleteRequestForm(@RequestBody Map<String, Long> data) {
return iRequestFormManageAppService.deleteRequestForm(data.get("requestFormId"));
public R<?> deleteRequestForm(@RequestBody Map<String, Object> data) {
return iRequestFormManageAppService.deleteRequestForm(parseLong(data.get("requestFormId")));
}
/**
@@ -205,7 +214,24 @@ public class RequestFormManageController {
* @return 结果
*/
@PostMapping(value = "/withdraw")
public R<?> withdrawRequestForm(@RequestBody Map<String, Long> data) {
return iRequestFormManageAppService.withdrawRequestForm(data.get("requestFormId"));
public R<?> withdrawRequestForm(@RequestBody Map<String, Object> data) {
return iRequestFormManageAppService.withdrawRequestForm(parseLong(data.get("requestFormId")));
}
private Long parseLong(Object value) {
if (value == null) {
return null;
}
if (value instanceof Long) {
return (Long) value;
}
if (value instanceof Number) {
return ((Number) value).longValue();
}
try {
return Long.parseLong(value.toString());
} catch (NumberFormatException e) {
return null;
}
}
}

View File

@@ -1,10 +1,13 @@
package com.openhis.web.regdoctorstation.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 医嘱批量操作参数类
*/
@@ -21,4 +24,10 @@ public class AdviceBatchOpParam {
@JsonSerialize(using = ToStringSerializer.class)
private Long requestId;
/**
* 停嘱时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date stopTime;
}

View File

@@ -31,8 +31,8 @@ public class HomeController {
HomeStatisticsDto statisticsDto = homeStatisticsService.getHomeStatistics();
// 获取待写病历数量
Long userId = SecurityUtils.getLoginUser().getUserId();
R<?> pendingEmrCount = doctorStationEmrAppService.getPendingEmrCount(userId);
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
R<?> pendingEmrCount = doctorStationEmrAppService.getPendingEmrCount(practitionerId, null);
// 将待写病历数量添加到统计数据中
statisticsDto.setPendingEmr((Integer) pendingEmrCount.getData());

View File

@@ -74,7 +74,6 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService {
.eq(TriageQueueItem::getTenantId, tenantId)
.eq(TriageQueueItem::getQueueDate, qd)
.eq(TriageQueueItem::getDeleteFlag, "0")
.ne(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue())
.orderByAsc(TriageQueueItem::getQueueOrder);
// 如果指定了科室,按科室过滤;否则查询所有科室(全科模式)
@@ -92,14 +91,6 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService {
}
});
}
// 双重保险:再次过滤掉 COMPLETED 状态的患者(防止数据库中有异常数据)
if (list != null && !list.isEmpty()) {
int beforeSize = list.size();
list = list.stream()
.filter(item -> !TriageQueueStatus.COMPLETED.getValue().equals(item.getStatus()))
.collect(java.util.stream.Collectors.toList());
}
return R.ok(list);
}

View File

@@ -516,6 +516,7 @@
T1.patient_id AS patient_id,
'med_medication_definition' AS advice_table_name,
T1.medication_id AS advice_definition_id
, T1.back_reason AS reason_text
FROM med_medication_request AS T1
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
AND T2.delete_flag = '0'
@@ -577,6 +578,7 @@
T1.patient_id AS patient_id,
'med_medication_definition' AS advice_table_name,
T3.ID AS advice_definition_id
, T2.back_reason AS reason_text
FROM adm_charge_item AS T1
INNER JOIN med_medication_request AS T2 ON T2.ID = T1.service_id AND T2.delete_flag = '0'
LEFT JOIN med_medication_definition AS T3 ON T3.ID = T2.medication_id AND T3.delete_flag = '0'
@@ -584,6 +586,9 @@
WHERE T1.delete_flag = '0'
AND T1.service_table = #{MED_MEDICATION_REQUEST}
<if test="historyFlag == '0'.toString()">
<if test="generateSourceEnum != null">
AND (T2.generate_source_enum IS NULL OR T2.generate_source_enum = #{generateSourceEnum})
</if>
AND T1.encounter_id = #{encounterId}
</if>
<if test="historyFlag == '1'.toString()">
@@ -637,6 +642,7 @@
CI.patient_id AS patient_id,
'adm_device_definition' AS advice_table_name,
CI.product_id AS advice_definition_id
, NULL AS reason_text
FROM adm_charge_item AS CI
LEFT JOIN adm_charge_item_definition CID ON CID.id = CI.definition_id AND CID.delete_flag = '0'
LEFT JOIN wor_device_request DR ON DR.id = CI.service_id AND DR.delete_flag = '0'
@@ -691,6 +697,7 @@
T1.patient_id AS patient_id,
'adm_device_definition' AS advice_table_name,
T1.device_def_id AS advice_definition_id
, NULL AS reason_text
FROM wor_device_request AS T1
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
AND T2.delete_flag = '0'
@@ -747,6 +754,7 @@
T1.patient_id AS patient_id,
'wor_activity_definition' AS advice_table_name,
T1.activity_id AS advice_definition_id
, T1.reason_text AS reason_text
FROM wor_service_request AS T1
LEFT JOIN wor_activity_definition AS T2
ON T2.ID = T1.activity_id
@@ -871,6 +879,7 @@
</select>
<!-- 手术项目专用分页查询:仅查手术 + 定价,无库存/草稿库存/取药科室等无关逻辑 -->
<!-- 使用 LIMIT/OFFSET 直接查询,避免 MyBatis Plus 分页插件的 COUNT 开销 -->
<select id="getSurgeryPage" resultType="com.openhis.web.doctorstation.dto.SurgeryItemDto">
SELECT DISTINCT ON (t1.ID)
t1.ID AS advice_definition_id,
@@ -895,12 +904,13 @@
ORDER BY t1.ID, t1.name ASC, t2.ID ASC
</select>
<!-- 检查项目专用分页查询:仅查检查(23) + 定价,无库存/草稿库存/取药科室等无关逻辑 -->
<!-- 检查/检验项目专用分页查询:仅查指定 category_code + 定价,无库存/草稿库存/取药科室等无关逻辑 -->
<select id="getExaminationPage" resultType="com.openhis.web.doctorstation.dto.SurgeryItemDto">
SELECT DISTINCT ON (t1.ID)
t1.ID AS advice_definition_id,
t1.NAME AS advice_name,
t1.org_id AS org_id,
t3.name AS org_name,
t1.org_id AS position_id,
t2.ID AS charge_item_definition_id,
t2.price AS price,
@@ -912,8 +922,11 @@
AND t2.delete_flag = '0'
AND t2.status_enum = #{statusEnum}
AND t2.instance_table = 'wor_activity_definition'
LEFT JOIN adm_organization t3
ON t3.id = t1.org_id
AND t3.delete_flag = '0'
WHERE t1.delete_flag = '0'
AND t1.category_code = '23'
AND t1.category_code = #{categoryCode}
<if test="searchKey != null and searchKey != ''">
AND (t1.name ILIKE '%' || #{searchKey} || '%' OR t1.py_str ILIKE '%' || #{searchKey} || '%')
</if>

View File

@@ -4,4 +4,38 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.openhis.web.doctorstation.mapper.DoctorStationEmrAppMapper">
</mapper>
<select id="getPendingEmrList" resultType="java.util.HashMap">
SELECT e.id AS "encounterId",
e.patient_id AS "patientId",
p.name AS "patientName",
p.gender_enum AS "gender",
p.birth_date AS "birthDate",
e.create_time AS "registerTime",
e.bus_no AS "busNo"
FROM adm_encounter e
INNER JOIN adm_encounter_participant ep ON e.id = ep.encounter_id AND ep.practitioner_id = #{doctorId}
LEFT JOIN adm_patient p ON e.patient_id = p.id
LEFT JOIN doc_emr emr ON e.id = emr.encounter_id
WHERE e.status_enum = 2
AND emr.id IS NULL
<if test="patientName != null and patientName != ''">
AND p.name LIKE CONCAT('%', #{patientName}, '%')
</if>
ORDER BY e.create_time DESC
LIMIT #{pageSize} OFFSET #{offset}
</select>
<select id="getPendingEmrCount" resultType="java.lang.Long">
SELECT COUNT(*)
FROM adm_encounter e
INNER JOIN adm_encounter_participant ep ON e.id = ep.encounter_id AND ep.practitioner_id = #{doctorId}
LEFT JOIN adm_patient p ON e.patient_id = p.id
LEFT JOIN doc_emr emr ON e.id = emr.encounter_id
WHERE e.status_enum = 2
AND emr.id IS NULL
<if test="patientName != null and patientName != ''">
AND p.name LIKE CONCAT('%', #{patientName}, '%')
</if>
</select>
</mapper>

View File

@@ -11,6 +11,10 @@
p.birth_date,
p.phone,
p.address,
p.address_province,
p.address_city,
p.address_district,
p.address_street,
p.work_company,
p.nationality_code,
p.marital_status_enum,

View File

@@ -214,10 +214,13 @@
T1.dispense_per_duration AS dispense_per_duration,
T2.part_percent AS part_percent,
ccd.name AS condition_definition_name,
T1.effective_dose_start AS start_time,
T1.therapy_enum AS therapyEnum,
T1.sort_number AS sort_number,
T1.based_on_id AS based_on_id,
T1.medication_id AS advice_definition_id
T1.effective_dose_end AS stop_time,
T1.update_by AS stop_user_name
FROM med_medication_request AS T1
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
AND T2.delete_flag = '0'
@@ -269,8 +272,11 @@
'' AS condition_definition_name,
2 AS therapyEnum,
99 AS sort_number,
T1.req_authored_time AS start_time,
T1.based_on_id AS based_on_id,
T1.device_def_id AS advice_definition_id
NULL AS stop_time,
'' AS stop_user_name
FROM wor_device_request AS T1
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
AND T2.delete_flag = '0'
@@ -319,8 +325,11 @@
'' AS condition_definition_name,
COALESCE(T1.therapy_enum, 2) AS therapyEnum,
99 AS sort_number,
T1.occurrence_start_time AS start_time,
T1.based_on_id AS based_on_id,
T1.activity_id AS advice_definition_id
T1.occurrence_end_time AS stop_time,
T1.update_by AS stop_user_name
FROM wor_service_request AS T1
LEFT JOIN wor_activity_definition AS T2
ON T2.ID = T1.activity_id

View File

@@ -35,6 +35,11 @@
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 8
) THEN 6
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 5
) THEN 7
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
@@ -43,13 +48,23 @@
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 2
) THEN 1
AND ws.status_enum = 12
) THEN 4
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 5
) THEN 7
AND ws.status_enum = 11
) THEN 3
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 10
) THEN 2
WHEN EXISTS (
SELECT 1 FROM wor_service_request ws
WHERE ws.prescription_no = drf.prescription_no AND ws.delete_flag = '0'
AND ws.status_enum = 2
) THEN 1
ELSE 0
END AS computed_status
FROM doc_request_form AS drf
@@ -57,8 +72,6 @@
AND ae.delete_flag = '0'
LEFT JOIN adm_patient AS ap ON ap.ID = ae.patient_id
AND ap.delete_flag = '0'
LEFT JOIN wor_service_request AS wsr ON wsr.prescription_no = drf.prescription_no
AND wsr.delete_flag = '0'
WHERE drf.delete_flag = '0'
AND drf.encounter_id = #{encounterId}
AND drf.type_code = #{typeCode}

View File

@@ -274,6 +274,10 @@ public enum AssignSeqEnum {
* 检查申请单号(住院)
*/
CHECK_APPLY_NO("72", "检查申请单号", "JCZ"),
/**
* 手术申请单号(住院)
*/
SURGERY_APPLY_NO("73", "手术申请单号", "SSZ"),
/**
* b 病历文书
*/

View File

@@ -57,7 +57,22 @@ public enum RequestStatus implements HisEnumInterface {
/**
* 未知
*/
UNKNOWN(9, "unknown", "未知");
UNKNOWN(9, "unknown", "未知"),
/**
* 已校对(检查申请:护士校对通过)
*/
CHECK_VERIFIED(10, "check_verified", "已校对"),
/**
* 待接收(检查申请:等待医技科室接单)
*/
PENDING_RECEIVE(11, "pending_receive", "待接收"),
/**
* 已接收(检查申请:医技科室已接单)
*/
CHECK_RECEIVED(12, "check_received", "已接收");
@EnumValue
private final Integer value;

View File

@@ -111,6 +111,9 @@ public class MedicationRequest extends HisBaseEntity {
/** 支持用药信息 */
private String supportInfo;
/** 退回原因 */
private String backReason;
/** 请求开始时间 */
private Date reqAuthoredTime;

View File

@@ -30,7 +30,7 @@ public interface IMedicationRequestService extends IService<MedicationRequest> {
* @param practitionerId 校对人
* @param checkDate 校对时间
*/
void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate);
void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate, String backReason);
/**
* 更新请求状态:取消

View File

@@ -44,7 +44,7 @@ public class MedicationRequestServiceImpl extends ServiceImpl<MedicationRequestM
* @param checkDate 校对时间
*/
@Override
public void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate) {
public void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate, String backReason) {
LambdaUpdateWrapper<MedicationRequest> updateWrapper =
new LambdaUpdateWrapper<MedicationRequest>().in(MedicationRequest::getId, requestIdList)
.set(MedicationRequest::getStatusEnum, RequestStatus.DRAFT.getValue());
@@ -54,6 +54,9 @@ public class MedicationRequestServiceImpl extends ServiceImpl<MedicationRequestM
if (checkDate != null) {
updateWrapper.set(MedicationRequest::getCheckTime, checkDate);
}
if (backReason != null) {
updateWrapper.set(MedicationRequest::getBackReason, backReason);
}
baseMapper.update(null, updateWrapper);
}
@@ -75,6 +78,9 @@ public class MedicationRequestServiceImpl extends ServiceImpl<MedicationRequestM
if (checkDate != null) {
updateWrapper.set(MedicationRequest::getCheckTime, checkDate);
}
if (backReason != null) {
updateWrapper.set(MedicationRequest::getBackReason, backReason);
}
baseMapper.update(null, updateWrapper);
}

View File

@@ -79,11 +79,13 @@ public class OpSchedule extends HisBaseEntity {
private String surgerySite;
/** 入院时间 */
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime admissionTime;
/** 入手术室时间 */
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime entryTime;
/** 手术室编码 */
@@ -142,19 +144,23 @@ public class OpSchedule extends HisBaseEntity {
private String assistant3Code;
/** 手术开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime;
/** 手术结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
/** 麻醉开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime anesStart;
/** 麻醉结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime anesEnd;
/** 手术状态 */

View File

@@ -39,6 +39,22 @@ public interface IServiceRequestService extends IService<ServiceRequest> {
*/
void updateCompleteRequestStatus(List<Long> serReqIdList, Long practitionerId, Date checkDate);
/**
* 更新检查申请状态已校对护士校对检查申请后状态为CHECK_VERIFIED而非COMPLETED
*
* @param serReqIdList 服务请求id列表
* @param practitionerId 校对人
* @param checkDate 校对时间
*/
void updateCheckVerifiedStatus(List<Long> serReqIdList, Long practitionerId, Date checkDate);
/**
* 更新检查申请状态待接收护士执行检查申请后状态为PENDING_RECEIVE
*
* @param serReqIdList 服务请求id列表
*/
void updatePendingReceiveStatus(List<Long> serReqIdList);
/**
* 获取执行过的诊疗数据
*
@@ -93,7 +109,7 @@ public interface IServiceRequestService extends IService<ServiceRequest> {
* @param practitionerId 校对人
* @param checkDate 校对时间
*/
void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate);
void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate, String backReason);
/**
* 更新服务状态:待发送

View File

@@ -66,6 +66,31 @@ public class ServiceRequestServiceImpl extends ServiceImpl<ServiceRequestMapper,
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
}
/**
* 更新检查申请状态已校对护士校对检查申请后状态为CHECK_VERIFIED而非COMPLETED
*
* @param serReqIdList 服务请求id列表
*/
@Override
public void updateCheckVerifiedStatus(List<Long> serReqIdList, Long practitionerId, Date checkDate) {
baseMapper.update(new ServiceRequest().setStatusEnum(RequestStatus.CHECK_VERIFIED.getValue())
.setPerformerCheckId(SecurityUtils.getLoginUser().getPractitionerId()).setCheckTime(DateUtils.getNowDate()),
new LambdaUpdateWrapper<ServiceRequest>().in(ServiceRequest::getId, serReqIdList)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
}
/**
* 更新检查申请状态待接收护士执行检查申请后状态为PENDING_RECEIVE
*
* @param serReqIdList 服务请求id列表
*/
@Override
public void updatePendingReceiveStatus(List<Long> serReqIdList) {
baseMapper.update(new ServiceRequest().setStatusEnum(RequestStatus.PENDING_RECEIVE.getValue()),
new LambdaUpdateWrapper<ServiceRequest>().in(ServiceRequest::getId, serReqIdList)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
}
/**
* 获取执行过的诊疗数据
*
@@ -172,9 +197,15 @@ public class ServiceRequestServiceImpl extends ServiceImpl<ServiceRequestMapper,
* @param checkDate 校对时间
*/
@Override
public void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate) {
baseMapper.update(new ServiceRequest().setStatusEnum(RequestStatus.DRAFT.getValue())
.setPerformerCheckId(SecurityUtils.getLoginUser().getPractitionerId()).setCheckTime(DateUtils.getNowDate()),
public void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate, String backReason) {
ServiceRequest updateEntity = new ServiceRequest()
.setStatusEnum(RequestStatus.DRAFT.getValue())
.setPerformerCheckId(SecurityUtils.getLoginUser().getPractitionerId())
.setCheckTime(DateUtils.getNowDate());
if (backReason != null && !backReason.isEmpty()) {
updateEntity.setReasonText(backReason);
}
baseMapper.update(updateEntity,
new LambdaUpdateWrapper<ServiceRequest>().in(ServiceRequest::getId, serviceRequestIdList)
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
}

View File

@@ -162,6 +162,24 @@ export function getG(svg, viewConfig) {
// 设置数据
export function getData(allData) {
const rowsData = allData.rows; // allData, '【全部数据】'
// 兼容旧数据:将旧 typeCode 映射到新 typeCode心率 004→014脉搏 005→002呼吸 006→001
const OLD_CODE_MAP = { '004': '014', '005': '002', '006': '001' };
rowsData.forEach(row => {
if (row.rowBOS) {
const prependItems = [];
row.rowBOS.forEach(item => {
const newCode = OLD_CODE_MAP[item.typeCode];
// 始终添加映射条目,用 unshift 插入数组头部
// 这样 getType 的 find() 优先匹配映射后的编码(如脉冲、呼吸)
// 即使存在同编码的旧条目(如血压舒张压用 002、收缩压用 001
// 映射后的脉搏(002)和呼吸(001)条目排在前面,确保图表正确渲染
if (newCode) {
prependItems.push({ ...item, typeCode: newCode });
}
});
row.rowBOS.unshift(...prependItems);
}
});
const infoData = allData.grParamBOS;
const typesData = getTypeDatas(allData.types, allData.grParamBOS.beginDate);
const selectOp = allData.selectOp;

View File

@@ -10,15 +10,27 @@
@click="clickAct"
>
<div v-if="data.bedOperationalStatus==='U'">
<img :src="emptyBed" class="pf_card_emptyBed_img">
<div class="pf_card_emptyBed_text">{{ data.bedName }}</div>
<img
:src="emptyBed"
class="pf_card_emptyBed_img"
>
<div class="pf_card_emptyBed_text">
{{ data.bedName }}
</div>
</div>
<div v-else>
<div v-if="data.isDischarge" class="pf_card_discharge">
<div
v-if="data.isDischarge"
class="pf_card_discharge"
>
<span style="margin-left: 6px"></span>
</div>
<div class="pf_card_card">
<CardSign :color="getBedBackColor(data.triageLevel)" :title="data.bedName" :tail="getDisplay(data.triageLevel)" />
<CardSign
:color="getBedBackColor(data.triageLevel)"
:title="data.bedName"
:tail="getDisplay(data.triageLevel)"
/>
</div>
<div class="pf_card_nameSexAndAge">
<span class="pf_card_name">{{ data.patientName }}</span>
@@ -28,20 +40,48 @@
<span style="margin-right: 16px">入室时间</span>
{{ moment(data.checkInWardTime).format('YYYY-MM-DD HH:mm') }}
</div>
<div class="pf_card_noCode">{{ data.hisId }}</div>
<div class="pf_card_rescueTimeText">{{ rescueTimeText() }}</div>
<div v-if="data.diag!==''" class="pf_card_diagnosis">
<div class="card-rectangle-text">{{ data.diag }}</div>
<div class="pf_card_noCode">
{{ data.hisId }}
</div>
<div class="pf_card_rescueTimeText">
{{ rescueTimeText() }}
</div>
<div
v-if="data.diag!==''"
class="pf_card_diagnosis"
>
<div class="card-rectangle-text">
{{ data.diag }}
</div>
<span style="margin-left: 4px">(诊断)</span>
</div>
<div v-if="isNewSign()" class="card-rectangle"></div>
<div v-if="is72HourSign()" class="card-rectangle2">超72H</div>
<div
v-if="isNewSign()"
class="card-rectangle"
>
</div>
<div
v-if="is72HourSign()"
class="card-rectangle2"
>
超72H
</div>
<hr class="pf_card_line">
<div class="pf_card_nursingMeasuresString">{{ getStringByCode(data.nursingMeasures, nursingMeasures) }}</div>
<div class="pf_card_specialArrangementString">{{ getStringByCode(data.specialArrangement, specialArrangementList) }}</div>
<div v-if="false" class="pf_card_btn" @click="moreClick">更多</div>
<div class="pf_card_nursingMeasuresString">
{{ getStringByCode(data.nursingMeasures, nursingMeasures) }}
</div>
<div class="pf_card_specialArrangementString">
{{ getStringByCode(data.specialArrangement, specialArrangementList) }}
</div>
<div
v-if="false"
class="pf_card_btn"
@click="moreClick"
>
更多
</div>
</div>
</div>
</template>
<script>

View File

@@ -6,7 +6,7 @@
:data="item"
:bed-config="bedConfig"
@click="clickAct"
@moreClick="moreClickAct"
@more-click="moreClickAct"
/>
</div>
</template>

View File

@@ -1,9 +1,19 @@
<template>
<div class="printCard">
<div ref="refQr" style="float: left; margin: 30px 15px">
<img :src="emptyBed" style="height: 120px" class="pf_card_emptyBed_img">
<div
ref="refQr"
style="float: left; margin: 30px 15px"
>
<img
:src="emptyBed"
style="height: 120px"
class="pf_card_emptyBed_img"
>
</div>
<div class="printView_content" style=" margin: 30px 0">
<div
class="printView_content"
style=" margin: 30px 0"
>
<div>
<span>床号</span>
<span>{{ printData.bedName }}</span>

View File

@@ -1,6 +1,9 @@
<template>
<div class="recordBill">
<div id="div1" class="printView_header">
<div
id="div1"
class="printView_header"
>
<div style="text-align: center; height: 40px">
护理交接班
</div>
@@ -18,35 +21,83 @@
/>
</div>
</div>
<div id="div2" class="printView_content">
<table border="1" cellSpacing="0" width="98%" cellPadding="1" style=" border-collapse:collapse; font-size: 14px" bordercolor="#333333">
<div
id="div2"
class="printView_content"
>
<table
border="1"
cellSpacing="0"
width="98%"
cellPadding="1"
style=" border-collapse:collapse; font-size: 14px"
bordercolor="#333333"
>
<thead>
<TR>
<TD colspan="1">
<DIV style="width: 40px" align="center">类别</DIV>
<DIV
style="width: 40px"
align="center"
>
类别
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 50px" align="center">床号</DIV>
<DIV
style="width: 50px"
align="center"
>
床号
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 60px" align="center">姓名</DIV>
<DIV
style="width: 60px"
align="center"
>
姓名
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 90px" align="center">主诉</DIV>
<DIV
style="width: 90px"
align="center"
>
主诉
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 90px" align="center">既往史</DIV>
<DIV
style="width: 90px"
align="center"
>
既往史
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 90px" align="center">诊断</DIV>
<DIV
style="width: 90px"
align="center"
>
诊断
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 155px" align="center">交接信息</DIV>
<DIV
style="width: 155px"
align="center"
>
交接信息
</DIV>
</TD>
</TR>
</thead>
<tbody>
<tr v-for="item in printData.shiftRecordItems" :key="item.id">
<tr
v-for="item in printData.shiftRecordItems"
:key="item.id"
>
<td v-html="item.typeDisplay" />
<td v-html="item.bedName" />
<td v-html="item.patientName" />

View File

@@ -1,6 +1,9 @@
<template>
<div class="recordBill">
<div :id="'exeSheetTitle' + printData.id" class="printView_header">
<div
:id="'exeSheetTitle' + printData.id"
class="printView_header"
>
<div style="text-align: center; height: 60px">
{{ userStore.hospitalName }}医嘱执行单
</div>
@@ -16,51 +19,119 @@
<span style="display: inline-block; width: 140px">性别{{!printData.patientInfo.gender? '':printData.patientInfo.gender.display}}</span>
</div>-->
</div>
<div :id="'exeSheet' + printData.id" class="printView_content">
<table border="1" cellSpacing="0" width="97%" cellPadding="1" style=" border-collapse:collapse; font-size: 13px" bordercolor="#333333">
<div
:id="'exeSheet' + printData.id"
class="printView_content"
>
<table
border="1"
cellSpacing="0"
width="97%"
cellPadding="1"
style=" border-collapse:collapse; font-size: 13px"
bordercolor="#333333"
>
<thead>
<TR>
<TD rowspan="1">
<DIV style="width: 65px;text-align: center">医嘱日期</DIV>
<DIV style="width: 65px;text-align: center">
医嘱日期
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 120px" align="center">医嘱</DIV>
<DIV
style="width: 120px"
align="center"
>
医嘱
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 10px" align="center" />
<DIV
style="width: 10px"
align="center"
/>
</TD>
<TD colspan="1">
<DIV style="width: 70px" align="center">嘱托</DIV>
<DIV
style="width: 70px"
align="center"
>
嘱托
</DIV>
</TD>
<TD rowspan="1">
<DIV style="width: 60px" align="center">用量</DIV>
<DIV
style="width: 60px"
align="center"
>
用量
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 40px" align="center">用法</DIV>
<DIV
style="width: 40px"
align="center"
>
用法
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 40px" align="center">频次</DIV>
<DIV
style="width: 40px"
align="center"
>
频次
</DIV>
</TD>
<TD rowspan="1">
<DIV style="width: 65px" align="center">开立医生</DIV>
<DIV
style="width: 65px"
align="center"
>
开立医生
</DIV>
</TD>
<TD rowspan="1">
<DIV style="width: 65px" align="center">执行时间</DIV>
<DIV
style="width: 65px"
align="center"
>
执行时间
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 65px" align="center">执行护士</DIV>
<DIV
style="width: 65px"
align="center"
>
执行护士
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 55px" align="center">终止时间</DIV>
<DIV
style="width: 55px"
align="center"
>
终止时间
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 55px" align="center">终止人</DIV>
<DIV
style="width: 55px"
align="center"
>
终止人
</DIV>
</TD>
</TR>
</thead>
<tbody>
<tr v-for="item in printData.recordData" :key="item.id">
<tr
v-for="item in printData.recordData"
:key="item.id"
>
<td v-html="item.moTime" />
<td v-html="item.orderName" />
<td v-html="item.flag" />
@@ -70,12 +141,20 @@
<td v-html="item.frequency" />
<td :id="item.id">
<span v-if="(item.docSignImage === ''||item.docSignImage === null)">{{ item.moDocName }}</span>
<img v-if="(item.docSignImage !== ''&&item.docSignImage !== null)" :src="'data:image/png;base64,'+ item.docSignImage" style="height: 100%; width: 100%;object-fit: cover;">
<img
v-if="(item.docSignImage !== ''&&item.docSignImage !== null)"
:src="'data:image/png;base64,'+ item.docSignImage"
style="height: 100%; width: 100%;object-fit: cover;"
>
</td>
<td v-html="item.occurrence" />
<td :id="item.id">
<span v-if="(item.perNurserSignImage === ''||item.perNurserSignImage === null)">{{ item.performName }}</span>
<img v-if="(item.perNurserSignImage !== ''&&item.perNurserSignImage !== null)" :src="'data:image/png;base64,'+ item.perNurserSignImage" style="height: 100%; width: 100%;object-fit: cover;">
<img
v-if="(item.perNurserSignImage !== ''&&item.perNurserSignImage !== null)"
:src="'data:image/png;base64,'+ item.perNurserSignImage"
style="height: 100%; width: 100%;object-fit: cover;"
>
</td>
<td />
<td />
@@ -91,10 +170,6 @@ import { simplePrint, PRINT_TEMPLATE } from '@/utils/printUtils.js'
import useUserStore from '@/store/modules/user'
export default {
setup() {
const userStore = useUserStore();
return { userStore };
},
props: {
printData: {
type: Object,
@@ -103,6 +178,10 @@ export default {
}
}
},
setup() {
const userStore = useUserStore();
return { userStore };
},
data() {
return {}
},

View File

@@ -12,23 +12,51 @@
</div>
</div>
<div style="display: block; width: 120px; height: 60px; float:left; ">
<div :id="getId(printData.id)" style="float: left; margin: 5px;" />
<div
:id="getId(printData.id)"
style="float: left; margin: 5px;"
/>
<span style="float: left; margin: 5px">{{ printData.priority }}</span>
</div>
</div>
<div :id="printData.id + 'div2'">
<table border="1" cellSpacing="0" width="390px" cellPadding="1" style="margin-left: 8px; border-collapse:collapse; table-layout: fixed; font-size: 14px" bordercolor="#333333">
<table
border="1"
cellSpacing="0"
width="390px"
cellPadding="1"
style="margin-left: 8px; border-collapse:collapse; table-layout: fixed; font-size: 14px"
bordercolor="#333333"
>
<thead>
<TR>
<Th style="width: 160px" v-html="'药品名称'" />
<Th style="width: 75px" v-html="'用量'" />
<Th style="width: 10px" v-html="''" />
<Th style="width: 50px" v-html="'频次'" />
<Th style="width: 75px" v-html="'用法'" />
<Th
style="width: 160px"
v-html="'药品名称'"
/>
<Th
style="width: 75px"
v-html="'用量'"
/>
<Th
style="width: 10px"
v-html="''"
/>
<Th
style="width: 50px"
v-html="'频次'"
/>
<Th
style="width: 75px"
v-html="'用法'"
/>
</TR>
</thead>
<tbody>
<tr v-for="item in printData.orderDetail" :key="item.id">
<tr
v-for="item in printData.orderDetail"
:key="item.id"
>
<td v-html="item.orderName" />
<td v-html="item.doseOnce + item.doseUnit" />
<td v-html="item.flag" />

View File

@@ -1,6 +1,9 @@
<template>
<div class="recordBill">
<div id="div1" class="printView_header">
<div
id="div1"
class="printView_header"
>
<div style="text-align: center; font-size: 20px; height: 40px">
{{ userStore.hospitalName }}输液执行单
</div>
@@ -13,38 +16,88 @@
<span style="margin-left: 18px">科室{{ printData.patientInfo.deptName }}</span>
</div>
</div>
<div id="div2" class="printView_content">
<table border="1" cellSpacing="0" cellPadding="1" style=" border-collapse:collapse; font-size: 14px" bordercolor="#333333">
<div
id="div2"
class="printView_content"
>
<table
border="1"
cellSpacing="0"
cellPadding="1"
style=" border-collapse:collapse; font-size: 14px"
bordercolor="#333333"
>
<thead>
<TR style="height: 30px">
<TD rowspan="1">
<DIV style="width: 35px" align="center">时间</DIV>
<DIV
style="width: 35px"
align="center"
>
时间
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 280px" align="center">药品名称</DIV>
<DIV
style="width: 280px"
align="center"
>
药品名称
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 10px" align="center" />
<DIV
style="width: 10px"
align="center"
/>
</TD>
<TD rowspan="1">
<DIV style="width: 55px" align="center">剂量</DIV>
<DIV
style="width: 55px"
align="center"
>
剂量
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 30px" align="center">频次</DIV>
<DIV
style="width: 30px"
align="center"
>
频次
</DIV>
</TD>
<TD colspan="1">
<DIV style="width: 55px" align="center">用法</DIV>
<DIV
style="width: 55px"
align="center"
>
用法
</DIV>
</TD>
<TD rowspan="1">
<DIV style="width: 70px" align="center">执行时间</DIV>
<DIV
style="width: 70px"
align="center"
>
执行时间
</DIV>
</TD>
<TD rowspan="1">
<DIV style="width: 55px" align="center">执行人</DIV>
<DIV
style="width: 55px"
align="center"
>
执行人
</DIV>
</TD>
</TR>
</thead>
<tbody style=" border-collapse:collapse;">
<tr v-for="item in printData.recordData" :key="item.id">
<tr
v-for="item in printData.recordData"
:key="item.id"
>
<td v-html="item.moTime.substring(0,16)" />
<td v-html="item.orderName" />
<td v-html="item.flag" />

View File

@@ -1,9 +1,15 @@
<template>
<div>
<div ref="print">
<div v-for="item in printData" :key="item.id">
<div
v-for="item in printData"
:key="item.id"
>
<div class="myccs2">
<injectLabel :ref="item.id" :print-data="item" />
<injectLabel
:ref="item.id"
:print-data="item"
/>
</div>
</div>
</div>

View File

@@ -1,10 +1,21 @@
<template>
<div>
<div ref="print">
<div v-for="item in printData" :key="item.id">
<div
v-for="item in printData"
:key="item.id"
>
<div class="myccs2">
<orderSheet v-if="!item.type" :ref="item.id" :print-data="item" />
<exeOrderSheet v-if="item.type" :ref="item.id" :print-data="item" />
<orderSheet
v-if="!item.type"
:ref="item.id"
:print-data="item"
/>
<exeOrderSheet
v-if="item.type"
:ref="item.id"
:print-data="item"
/>
</div>
</div>
</div>

View File

@@ -1,5 +1,10 @@
<template>
<Graphics v-if="graphicsDataDone" :value="resInfo" print @done="printPage" />
<Graphics
v-if="graphicsDataDone"
:value="resInfo"
print
@done="printPage"
/>
</template>
<script setup>

View File

@@ -21,7 +21,10 @@
<span>分诊时间</span>
<span>{{ printData.triageTime }}</span>
</div>
<img ref="refQr" style="position: absolute; top: 10px; left: 100px" />
<img
ref="refQr"
style="position: absolute; top: 10px; left: 100px"
>
</div>
</template>
<script>
@@ -30,10 +33,6 @@ import useUserStore from '@/store/modules/user';
export default {
name: 'TriageTicket',
setup() {
const userStore = useUserStore();
return { userStore };
},
props: {
printData: {
type: Object,
@@ -48,6 +47,10 @@ export default {
},
},
},
setup() {
const userStore = useUserStore();
return { userStore };
},
data() {
return {};
},

View File

@@ -2,7 +2,10 @@
<div>
<div ref="print">
<div class="myccs2">
<triageTicketNew ref="printTriage" :print-data="printData" />
<triageTicketNew
ref="printTriage"
:print-data="printData"
/>
</div>
<!-- <div v-for="item in printData" :key="item.id">-->
<!-- <div class="myccs2">-->

View File

@@ -6,7 +6,9 @@
<span style="font-weight: bolder; font-size: 18px; line-height: 36px">{{ printData.greenText }}</span>
<span style="font-weight: bolder; font-size: 18px; line-height: 36px">分诊单</span>
</div>
<div style="position: absolute; top: 135px; text-align: center; width: 300px">{{ printData.hisId }}</div>
<div style="position: absolute; top: 135px; text-align: center; width: 300px">
{{ printData.hisId }}
</div>
<div style="position: absolute; top: 155px; text-align: center; width: 300px">
{{ printData.triageLevel }}{{ printData.dept }}
</div>
@@ -107,10 +109,18 @@
"
/>
<div style="margin-left: 15px">
<div style="font-size: 14px; margin-top: 15px; font-weight: bolder">请仔细核对个人信息后进行挂号</div>
<div style="margin-top: 5px; font-size: 14px">为了您家人和其他患者的健康</div>
<div style="font-size: 14px">请您保持就诊秩序保持诊区安静</div>
<div style="font-size: 14px">祝您早日康复</div>
<div style="font-size: 14px; margin-top: 15px; font-weight: bolder">
请仔细核对个人信息后进行挂号
</div>
<div style="margin-top: 5px; font-size: 14px">
为了您家人和其他患者的健康
</div>
<div style="font-size: 14px">
请您保持就诊秩序保持诊区安静
</div>
<div style="font-size: 14px">
祝您早日康复
</div>
</div>
</div>
</div>

View File

@@ -1,6 +1,9 @@
<template>
<div class="printWrist">
<div id="div1" class="printView_content">
<div
id="div1"
class="printView_content"
>
<div style="margin: 1px;font-size: 12px">
<span>姓名: </span>
<span>{{ printData.patientName }}</span>
@@ -22,7 +25,11 @@
<span style="position: absolute; left: 140px">{{ printData.triageLevel }}</span>
</div>
</div>
<div id="qrcode" ref="refQr" style="padding-top: 1px" />
<div
id="qrcode"
ref="refQr"
style="padding-top: 1px"
/>
</div>
</template>
<script>

View File

@@ -1,9 +1,21 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<el-breadcrumb
class="app-breadcrumb"
separator="/"
>
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
<el-breadcrumb-item
v-for="(item,index) in levelList"
:key="item.path"
>
<span
v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
class="no-redirect"
>{{ item.meta.title }}</span>
<a
v-else
@click.prevent="handleLink(item)"
>{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>

View File

@@ -1,55 +1,107 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * ? / L W]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
允许的通配符[, - * ? / L W]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
周期从
<el-input-number v-model='cycle01' :min="1" :max="30" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="31" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
周期从
<el-input-number
v-model="cycle01"
:min="1"
:max="30"
/> -
<el-input-number
v-model="cycle02"
:min="cycle01 + 1"
:max="31"
/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
<el-input-number v-model='average01' :min="1" :max="30" /> 号开始
<el-input-number v-model='average02' :min="1" :max="31 - average01" /> 日执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
<el-input-number
v-model="average01"
:min="1"
:max="30"
/> 号开始
<el-input-number
v-model="average02"
:min="1"
:max="31 - average01"
/> 日执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="5">
每月
<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="5"
>
每月
<el-input-number
v-model="workday"
:min="1"
:max="31"
/> 号最近的那个工作日
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="6">
本月最后一天
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="6"
>
本月最后一天
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="7">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 31" :key="item" :label="item" :value="item" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="7"
>
指定
<el-select
v-model="checkboxList"
clearable
placeholder="可多选"
multiple
:multiple-limit="10"
>
<el-option
v-for="item in 31"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])

View File

@@ -1,36 +1,75 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
小时允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
小时允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="22" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="23" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
周期从
<el-input-number
v-model="cycle01"
:min="0"
:max="22"
/> -
<el-input-number
v-model="cycle02"
:min="cycle01 + 1"
:max="23"
/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="22" /> 时开始
<el-input-number v-model='average02' :min="1" :max="23 - average01" /> 小时执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
<el-input-number
v-model="average01"
:min="0"
:max="22"
/> 时开始
<el-input-number
v-model="average02"
:min="1"
:max="23 - average01"
/> 小时执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 24" :key="item" :label="item - 1" :value="item - 1" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
指定
<el-select
v-model="checkboxList"
clearable
placeholder="可多选"
multiple
:multiple-limit="10"
>
<el-option
v-for="item in 24"
:key="item"
:label="item - 1"
:value="item - 1"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>

View File

@@ -1,123 +1,211 @@
<template>
<div>
<el-tabs type="border-card">
<el-tab-pane label="秒" v-if="shouldHide('second')">
<CrontabSecond
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronsecond"
/>
</el-tab-pane>
<div>
<el-tabs type="border-card">
<el-tab-pane
v-if="shouldHide('second')"
label="秒"
>
<CrontabSecond
ref="cronsecond"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
<el-tab-pane label="分钟" v-if="shouldHide('min')">
<CrontabMin
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronmin"
/>
</el-tab-pane>
<el-tab-pane
v-if="shouldHide('min')"
label="分钟"
>
<CrontabMin
ref="cronmin"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
<el-tab-pane label="小时" v-if="shouldHide('hour')">
<CrontabHour
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronhour"
/>
</el-tab-pane>
<el-tab-pane
v-if="shouldHide('hour')"
label="小时"
>
<CrontabHour
ref="cronhour"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
<el-tab-pane label="日" v-if="shouldHide('day')">
<CrontabDay
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronday"
/>
</el-tab-pane>
<el-tab-pane
v-if="shouldHide('day')"
label="日"
>
<CrontabDay
ref="cronday"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
<el-tab-pane label="月" v-if="shouldHide('month')">
<CrontabMonth
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronmonth"
/>
</el-tab-pane>
<el-tab-pane
v-if="shouldHide('month')"
label="月"
>
<CrontabMonth
ref="cronmonth"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
<el-tab-pane label="周" v-if="shouldHide('week')">
<CrontabWeek
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronweek"
/>
</el-tab-pane>
<el-tab-pane
v-if="shouldHide('week')"
label="周"
>
<CrontabWeek
ref="cronweek"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
<el-tab-pane label="年" v-if="shouldHide('year')">
<CrontabYear
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronyear"
/>
</el-tab-pane>
</el-tabs>
<el-tab-pane
v-if="shouldHide('year')"
label="年"
>
<CrontabYear
ref="cronyear"
:check="checkNumber"
:cron="crontabValueObj"
@update="updateCrontabValue"
/>
</el-tab-pane>
</el-tabs>
<div class="popup-main">
<div class="popup-result">
<p class="title">时间表达式</p>
<table>
<thead>
<th v-for="item of tabTitles" :key="item">{{item}}</th>
<th>Cron 表达式</th>
</thead>
<tbody>
<td>
<span v-if="crontabValueObj.second.length < 10">{{crontabValueObj.second}}</span>
<el-tooltip v-else :content="crontabValueObj.second" placement="top"><span>{{crontabValueObj.second}}</span></el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.min.length < 10">{{crontabValueObj.min}}</span>
<el-tooltip v-else :content="crontabValueObj.min" placement="top"><span>{{crontabValueObj.min}}</span></el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.hour.length < 10">{{crontabValueObj.hour}}</span>
<el-tooltip v-else :content="crontabValueObj.hour" placement="top"><span>{{crontabValueObj.hour}}</span></el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.day.length < 10">{{crontabValueObj.day}}</span>
<el-tooltip v-else :content="crontabValueObj.day" placement="top"><span>{{crontabValueObj.day}}</span></el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.month.length < 10">{{crontabValueObj.month}}</span>
<el-tooltip v-else :content="crontabValueObj.month" placement="top"><span>{{crontabValueObj.month}}</span></el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.week.length < 10">{{crontabValueObj.week}}</span>
<el-tooltip v-else :content="crontabValueObj.week" placement="top"><span>{{crontabValueObj.week}}</span></el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.year.length < 10">{{crontabValueObj.year}}</span>
<el-tooltip v-else :content="crontabValueObj.year" placement="top"><span>{{crontabValueObj.year}}</span></el-tooltip>
</td>
<td class="result">
<span v-if="crontabValueString.length < 90">{{crontabValueString}}</span>
<el-tooltip v-else :content="crontabValueString" placement="top"><span>{{crontabValueString}}</span></el-tooltip>
</td>
</tbody>
</table>
</div>
<CrontabResult :ex="crontabValueString"></CrontabResult>
<div class="popup-main">
<div class="popup-result">
<p class="title">
时间表达式
</p>
<table>
<thead>
<th
v-for="item of tabTitles"
:key="item"
>
{{ item }}
</th>
<th>Cron 表达式</th>
</thead>
<tbody>
<td>
<span v-if="crontabValueObj.second.length < 10">{{ crontabValueObj.second }}</span>
<el-tooltip
v-else
:content="crontabValueObj.second"
placement="top"
>
<span>{{ crontabValueObj.second }}</span>
</el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.min.length < 10">{{ crontabValueObj.min }}</span>
<el-tooltip
v-else
:content="crontabValueObj.min"
placement="top"
>
<span>{{ crontabValueObj.min }}</span>
</el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.hour.length < 10">{{ crontabValueObj.hour }}</span>
<el-tooltip
v-else
:content="crontabValueObj.hour"
placement="top"
>
<span>{{ crontabValueObj.hour }}</span>
</el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.day.length < 10">{{ crontabValueObj.day }}</span>
<el-tooltip
v-else
:content="crontabValueObj.day"
placement="top"
>
<span>{{ crontabValueObj.day }}</span>
</el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.month.length < 10">{{ crontabValueObj.month }}</span>
<el-tooltip
v-else
:content="crontabValueObj.month"
placement="top"
>
<span>{{ crontabValueObj.month }}</span>
</el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.week.length < 10">{{ crontabValueObj.week }}</span>
<el-tooltip
v-else
:content="crontabValueObj.week"
placement="top"
>
<span>{{ crontabValueObj.week }}</span>
</el-tooltip>
</td>
<td>
<span v-if="crontabValueObj.year.length < 10">{{ crontabValueObj.year }}</span>
<el-tooltip
v-else
:content="crontabValueObj.year"
placement="top"
>
<span>{{ crontabValueObj.year }}</span>
</el-tooltip>
</td>
<td class="result">
<span v-if="crontabValueString.length < 90">{{ crontabValueString }}</span>
<el-tooltip
v-else
:content="crontabValueString"
placement="top"
>
<span>{{ crontabValueString }}</span>
</el-tooltip>
</td>
</tbody>
</table>
</div>
<CrontabResult :ex="crontabValueString" />
<div class="pop_btn">
<el-button type="primary" @click="submitFill">确定</el-button>
<el-button type="warning" @click="clearCron">重置</el-button>
<el-button @click="hidePopup">取消</el-button>
</div>
</div>
<div class="pop_btn">
<el-button
type="primary"
@click="submitFill"
>
确定
</el-button>
<el-button
type="warning"
@click="clearCron"
>
重置
</el-button>
<el-button @click="hidePopup">
取消
</el-button>
</div>
</div>
</div>
</template>
<script setup>

View File

@@ -1,36 +1,75 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
分钟允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
分钟允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" /> 分钟
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
周期从
<el-input-number
v-model="cycle01"
:min="0"
:max="58"
/> -
<el-input-number
v-model="cycle02"
:min="cycle01 + 1"
:max="59"
/> 分钟
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始
<el-input-number v-model='average02' :min="1" :max="59 - average01" /> 分钟执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
<el-input-number
v-model="average01"
:min="0"
:max="58"
/> 分钟开始
<el-input-number
v-model="average02"
:min="1"
:max="59 - average01"
/> 分钟执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
指定
<el-select
v-model="checkboxList"
clearable
placeholder="可多选"
multiple
:multiple-limit="10"
>
<el-option
v-for="item in 60"
:key="item"
:label="item - 1"
:value="item - 1"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])

View File

@@ -1,36 +1,75 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="1" :max="11" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="12" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
周期从
<el-input-number
v-model="cycle01"
:min="1"
:max="11"
/> -
<el-input-number
v-model="cycle02"
:min="cycle01 + 1"
:max="12"
/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="1" :max="11" /> 月开始
<el-input-number v-model='average02' :min="1" :max="12 - average01" /> 月月执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
<el-input-number
v-model="average01"
:min="1"
:max="11"
/> 月开始
<el-input-number
v-model="average02"
:min="1"
:max="12 - average01"
/> 月月执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
<el-option v-for="item in monthList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
指定
<el-select
v-model="checkboxList"
clearable
placeholder="可多选"
multiple
:multiple-limit="8"
>
<el-option
v-for="item in monthList"
:key="item.key"
:label="item.value"
:value="item.key"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>

View File

@@ -1,13 +1,22 @@
<template>
<div class="popup-result">
<p class="title">最近5次运行时间</p>
<ul class="popup-result-scroll">
<template v-if='isShow'>
<li v-for='item in resultList' :key="item">{{item}}</li>
</template>
<li v-else>计算结果中...</li>
</ul>
</div>
<div class="popup-result">
<p class="title">
最近5次运行时间
</p>
<ul class="popup-result-scroll">
<template v-if="isShow">
<li
v-for="item in resultList"
:key="item"
>
{{ item }}
</li>
</template>
<li v-else>
计算结果中...
</li>
</ul>
</div>
</template>
<script setup>

View File

@@ -1,36 +1,75 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
周期从
<el-input-number
v-model="cycle01"
:min="0"
:max="58"
/> -
<el-input-number
v-model="cycle02"
:min="cycle01 + 1"
:max="59"
/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 秒开始
<el-input-number v-model='average02' :min="1" :max="59 - average01" /> 秒执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
<el-input-number
v-model="average01"
:min="0"
:max="58"
/> 秒开始
<el-input-number
v-model="average02"
:min="1"
:max="59 - average01"
/> 秒执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
指定
<el-select
v-model="checkboxList"
clearable
placeholder="可多选"
multiple
:multiple-limit="10"
>
<el-option
v-for="item in 60"
:key="item"
:label="item - 1"
:value="item - 1"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>

View File

@@ -1,71 +1,130 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * ? / L #]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
允许的通配符[, - * ? / L #]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
周期从
<el-select clearable v-model="cycle01">
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key === 7"
>{{item.value}}</el-option>
</el-select>
-
<el-select clearable v-model="cycle02">
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key <= cycle01"
>{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
周期从
<el-select
v-model="cycle01"
clearable
>
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key === 7"
>
{{ item.value }}
</el-option>
</el-select>
-
<el-select
v-model="cycle02"
clearable
>
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key <= cycle01"
>
{{ item.value }}
</el-option>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
<el-input-number v-model='average01' :min="1" :max="4" /> 周的
<el-select clearable v-model="average02">
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
<el-input-number
v-model="average01"
:min="1"
:max="4"
/> 周的
<el-select
v-model="average02"
clearable
>
<el-option
v-for="item in weekList"
:key="item.key"
:label="item.value"
:value="item.key"
/>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="5">
本月最后一个
<el-select clearable v-model="weekday">
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="5"
>
本月最后一个
<el-select
v-model="weekday"
clearable
>
<el-option
v-for="item in weekList"
:key="item.key"
:label="item.value"
:value="item.key"
/>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="6">
指定
<el-select class="multiselect" clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="6">
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="6"
>
指定
<el-select
v-model="checkboxList"
class="multiselect"
clearable
placeholder="可多选"
multiple
:multiple-limit="6"
>
<el-option
v-for="item in weekList"
:key="item.key"
:label="item.value"
:value="item.key"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>

View File

@@ -1,43 +1,84 @@
<template>
<el-form>
<el-form-item>
<el-radio :label="1" v-model='radioValue'>
不填允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="1"
>
不填允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="2" v-model='radioValue'>
每年
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="2"
>
每年
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="3" v-model='radioValue'>
周期从
<el-input-number v-model='cycle01' :min='fullYear' :max="2098"/> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099"/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio
v-model="radioValue"
:label="3"
>
周期从
<el-input-number
v-model="cycle01"
:min="fullYear"
:max="2098"
/> -
<el-input-number
v-model="cycle02"
:min="cycle01 ? cycle01 + 1 : fullYear + 1"
:max="2099"
/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="4" v-model='radioValue'>
<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始
<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear"/> 年执行一次
</el-radio>
<el-form-item>
<el-radio
v-model="radioValue"
:label="4"
>
<el-input-number
v-model="average01"
:min="fullYear"
:max="2098"
/> 年开始
<el-input-number
v-model="average02"
:min="1"
:max="2099 - average01 || fullYear"
/> 年执行一次
</el-radio>
</el-form-item>
</el-form-item>
<el-form-item>
<el-radio :label="5" v-model='radioValue'>
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
<el-form-item>
<el-radio
v-model="radioValue"
:label="5"
>
指定
<el-select
v-model="checkboxList"
clearable
placeholder="可多选"
multiple
:multiple-limit="8"
>
<el-option
v-for="item in 9"
:key="item"
:value="item - 1 + fullYear"
:label="item -1 + fullYear"
/>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>

View File

@@ -10,12 +10,14 @@
>{{ item.label + " " }}</span>
<el-tag
v-else
:disable-transitions="true"
:key="item.value + ''"
:disable-transitions="true"
:index="index"
:type="getValidTagType(item.elTagType)"
:class="item.elTagClass"
>{{ item.label + " " }}</el-tag>
>
{{ item.label + " " }}
</el-tag>
</template>
</template>
<template v-if="unmatch && showValue">

View File

@@ -1,15 +1,33 @@
<template>
<div class="editor-container">
<div>
<el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
:on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" class="editor-img-uploader"
v-if="type == 'url'">
<i ref="uploadRef" class="editor-img-uploader"></i>
<el-upload
v-if="type == 'url'"
:action="uploadUrl"
:before-upload="handleBeforeUpload"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
name="file"
:show-file-list="false"
:headers="headers"
class="editor-img-uploader"
>
<i
ref="uploadRef"
class="editor-img-uploader"
/>
</el-upload>
</div>
<div class="editor">
<quill-editor ref="quillEditorRef" :content="content" @update:content="content = $event" contentType="html"
@textChange="(e) => $emit('update:modelValue', content)" :options="options" :style="styles" />
<quill-editor
ref="quillEditorRef"
:content="content"
content-type="html"
:options="options"
:style="styles"
@update:content="content = $event"
@text-change="(e) => $emit('update:modelValue', content)"
/>
</div>
</div>
</template>

View File

@@ -2,6 +2,7 @@
<div class="upload-file">
<el-upload
multiple
ref="fileUpload"
:action="uploadFileUrl"
:before-upload="handleBeforeUpload"
:file-list="fileList"
@@ -12,26 +13,52 @@
:show-file-list="false"
:headers="headers"
class="upload-file-uploader"
ref="fileUpload"
>
<!-- 上传按钮 -->
<el-button type="primary">选取文件</el-button>
<el-button type="primary">
选取文件
</el-button>
</el-upload>
<!-- 上传提示 -->
<div class="el-upload__tip" v-if="showTip">
<div
v-if="showTip"
class="el-upload__tip"
>
请上传
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
<template v-if="fileSize">
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
</template>
<template v-if="fileType">
格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
</template>
的文件
</div>
<!-- 文件列表 -->
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
<transition-group
class="upload-file-list el-upload-list el-upload-list--text"
name="el-fade-in-linear"
tag="ul"
>
<li
v-for="(file, index) in fileList"
:key="file.uid"
class="el-upload-list__item ele-upload-list__item-content"
>
<el-link
:href="`${baseUrl}${file.url}`"
:underline="false"
target="_blank"
>
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
<el-link
:underline="false"
type="danger"
@click="handleDelete(index)"
>
删除
</el-link>
</div>
</li>
</transition-group>

View File

@@ -1,5 +1,8 @@
<template>
<div style="padding: 0 15px;" @click="toggleClick">
<div
style="padding: 0 15px;"
@click="toggleClick"
>
<svg
:class="{'is-active':isActive}"
class="hamburger"

View File

@@ -1,6 +1,14 @@
<template>
<div :class="{ show: show }" class="header-search">
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" v-if="!show" />
<div
:class="{ show: show }"
class="header-search"
>
<svg-icon
v-if="!show"
class-name="search-icon"
icon-class="search"
@click.stop="click"
/>
<el-select
v-else
ref="headerSearchSelectRef"

View File

@@ -8,13 +8,24 @@
@clear="filterIcons"
@input="filterIcons"
>
<template #suffix><i class="el-icon-search el-input__icon" /></template>
<template #suffix>
<i class="el-icon-search el-input__icon" />
</template>
</el-input>
<div class="icon-list">
<div class="list-container">
<div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)">
<div
v-for="(item, index) in iconList"
:key="index"
class="icon-item-wrapper"
@click="selectedIcon(item)"
>
<div :class="['icon-item', { active: activeIcon === item }]">
<svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/>
<svg-icon
:icon-class="item"
class-name="icon"
style="height: 25px;width: 16px;"
/>
<span>{{ item }}</span>
</div>
</div>

View File

@@ -1,6 +1,7 @@
<template>
<div class="component-upload-image">
<el-upload
ref="imageUpload"
multiple
:action="uploadImgUrl"
list-type="picture-card"
@@ -9,7 +10,6 @@
:limit="limit"
:on-error="handleUploadError"
:on-exceed="handleExceed"
ref="imageUpload"
:before-remove="handleDelete"
:show-file-list="true"
:headers="headers"
@@ -17,10 +17,15 @@
:on-preview="handlePictureCardPreview"
:class="{ hide: fileList.length >= limit }"
>
<el-icon class="avatar-uploader-icon"><plus /></el-icon>
<el-icon class="avatar-uploader-icon">
<plus />
</el-icon>
</el-upload>
<!-- 上传提示 -->
<div class="el-upload__tip" v-if="showTip">
<div
v-if="showTip"
class="el-upload__tip"
>
请上传
<template v-if="fileSize">
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
@@ -40,7 +45,7 @@
<img
:src="dialogImageUrl"
style="display: block; max-width: 100%; margin: 0 auto"
/>
>
</el-dialog>
</div>
</template>

View File

@@ -1,12 +1,18 @@
<template>
<div class="page-container">
<div v-if="$slots.header" class="page-header">
<div
v-if="$slots.header"
class="page-header"
>
<slot name="header" />
</div>
<div class="page-content">
<slot />
</div>
<div v-if="$slots.footer" class="page-footer">
<div
v-if="$slots.footer"
class="page-footer"
>
<slot name="footer" />
</div>
</div>

View File

@@ -1,20 +1,51 @@
<template>
<el-drawer v-model="noticeVisible" title="公告/通知" direction="rtl" size="400px" destroy-on-close>
<el-empty v-if="noticeList.length === 0" description="暂无公告/通知" />
<div v-else class="notice-list">
<div v-for="item in noticeList" :key="item.noticeId" class="notice-item" :class="{ 'is-read': isRead(item.noticeId), 'unread': !isRead(item.noticeId) }" @click="viewDetail(item)">
<el-drawer
v-model="noticeVisible"
title="公告/通知"
direction="rtl"
size="400px"
destroy-on-close
>
<el-empty
v-if="noticeList.length === 0"
description="暂无公告/通知"
/>
<div
v-else
class="notice-list"
>
<div
v-for="item in noticeList"
:key="item.noticeId"
class="notice-item"
:class="{ 'is-read': isRead(item.noticeId), 'unread': !isRead(item.noticeId) }"
@click="viewDetail(item)"
>
<div class="notice-title">
<span v-if="!isRead(item.noticeId)" class="unread-dot"></span>
<span
v-if="!isRead(item.noticeId)"
class="unread-dot"
/>
{{ item.noticeTitle }}
</div>
<div class="notice-info">
<span class="notice-type">
<el-tag :type="getNoticeTypeTagType(item.noticeType)" size="small">
<el-tag
:type="getNoticeTypeTagType(item.noticeType)"
size="small"
>
{{ getNoticeTypeText(item.noticeType) }}
</el-tag>
</span>
<span class="notice-priority" v-if="item.priority">
<el-tag :type="getPriorityTagType(item.priority)" size="small" effect="plain">
<span
v-if="item.priority"
class="notice-priority"
>
<el-tag
:type="getPriorityTagType(item.priority)"
size="small"
effect="plain"
>
{{ getPriorityText(item.priority) }}
</el-tag>
</span>
@@ -24,23 +55,41 @@
</div>
<!-- 公告/通知详情对话框 -->
<el-dialog v-model="detailVisible" :title="currentNotice.noticeTitle" width="800px" append-to-body>
<el-dialog
v-model="detailVisible"
:title="currentNotice.noticeTitle"
width="800px"
append-to-body
>
<div class="notice-detail">
<div class="detail-header">
<div class="detail-type">
<el-tag :type="getNoticeTypeTagType(currentNotice.noticeType)" size="small">
<el-tag
:type="getNoticeTypeTagType(currentNotice.noticeType)"
size="small"
>
{{ getNoticeTypeText(currentNotice.noticeType) }}
</el-tag>
<el-tag :type="getPriorityTagType(currentNotice.priority)" size="small" effect="plain" style="margin-left: 8px;">
<el-tag
:type="getPriorityTagType(currentNotice.priority)"
size="small"
effect="plain"
style="margin-left: 8px;"
>
{{ getPriorityText(currentNotice.priority) }}
</el-tag>
</div>
<span class="detail-time">{{ parseTime(currentNotice.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</div>
<div class="detail-content" v-html="currentNotice.noticeContent"></div>
<div
class="detail-content"
v-html="currentNotice.noticeContent"
/>
</div>
<template #footer>
<el-button @click="detailVisible = false">关闭</el-button>
<el-button @click="detailVisible = false">
关闭
</el-button>
</template>
</el-dialog>
</el-drawer>

View File

@@ -13,7 +13,12 @@
<div class="notice-list">
<div class="notice-list-header">
<span class="notice-list-title">公告列表</span>
<el-button text type="primary" @click="markAllAsRead" v-if="unreadCount > 0">
<el-button
v-if="unreadCount > 0"
text
type="primary"
@click="markAllAsRead"
>
全部标记为已读
</el-button>
</div>
@@ -26,7 +31,10 @@
@click="handleSelectNotice(notice)"
>
<div class="notice-item-left">
<el-icon class="notice-type-icon" :class="getNoticeTypeClass(notice.noticeType)">
<el-icon
class="notice-type-icon"
:class="getNoticeTypeClass(notice.noticeType)"
>
<component :is="getNoticeTypeIcon(notice.noticeType)" />
</el-icon>
<div class="notice-item-content">
@@ -39,7 +47,14 @@
{{ getPriorityText(notice.priority) }}
</el-tag>
<span class="notice-title-text">{{ notice.noticeTitle }}</span>
<el-tag v-if="!notice.isRead" type="danger" size="small" effect="dark">未读</el-tag>
<el-tag
v-if="!notice.isRead"
type="danger"
size="small"
effect="dark"
>
未读
</el-tag>
</div>
<div class="notice-meta">
<span class="notice-date">{{ formatDate(notice.createTime) }}</span>
@@ -47,45 +62,77 @@
</div>
</div>
</div>
<el-icon class="arrow-icon" v-if="activeNoticeId === notice.noticeId">
<el-icon
v-if="activeNoticeId === notice.noticeId"
class="arrow-icon"
>
<ArrowRight />
</el-icon>
</div>
<!-- 空状态 -->
<div v-if="noticeList.length === 0" class="empty-state">
<el-empty description="暂无公告" :image-size="100" />
<div
v-if="noticeList.length === 0"
class="empty-state"
>
<el-empty
description="暂无公告"
:image-size="100"
/>
</div>
</el-scrollbar>
</div>
<!-- 公告详情 -->
<div class="notice-detail" v-if="activeNotice">
<div
v-if="activeNotice"
class="notice-detail"
>
<div class="notice-detail-header">
<h3 class="notice-detail-title">{{ activeNotice.noticeTitle }}</h3>
<h3 class="notice-detail-title">
{{ activeNotice.noticeTitle }}
</h3>
<div class="notice-detail-meta">
<el-tag :type="getPriorityTagType(activeNotice.priority)" size="small" effect="dark">
<el-tag
:type="getPriorityTagType(activeNotice.priority)"
size="small"
effect="dark"
>
{{ getPriorityText(activeNotice.priority) }}
</el-tag>
<el-tag :type="getNoticeTypeTagType(activeNotice.noticeType)" size="small">
<el-tag
:type="getNoticeTypeTagType(activeNotice.noticeType)"
size="small"
>
{{ getNoticeTypeText(activeNotice.noticeType) }}
</el-tag>
<span class="notice-detail-date">{{ formatFullDate(activeNotice.createTime) }}</span>
</div>
</div>
<el-divider />
<div class="notice-detail-body" v-html="activeNotice.noticeContent"></div>
<div
class="notice-detail-body"
v-html="activeNotice.noticeContent"
/>
</div>
<!-- 未选择状态 -->
<div v-else class="no-selection">
<el-empty description="请选择公告查看详情" :image-size="120" />
<div
v-else
class="no-selection"
>
<el-empty
description="请选择公告查看详情"
:image-size="120"
/>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">关闭</el-button>
<el-button @click="handleClose">
关闭
</el-button>
</div>
</template>
</el-dialog>

View File

@@ -21,7 +21,10 @@
@click="handleSelectNotice(notice)"
>
<div class="notice-item-left">
<el-icon class="notice-type-icon" :class="getNoticeTypeClass(notice.noticeType)">
<el-icon
class="notice-type-icon"
:class="getNoticeTypeClass(notice.noticeType)"
>
<component :is="getNoticeTypeIcon(notice.noticeType)" />
</el-icon>
<div class="notice-item-content">
@@ -34,7 +37,14 @@
{{ getPriorityText(notice.priority) }}
</el-tag>
<span class="notice-title-text">{{ notice.noticeTitle }}</span>
<el-tag v-if="!notice.isRead" type="danger" size="small" effect="dark">未读</el-tag>
<el-tag
v-if="!notice.isRead"
type="danger"
size="small"
effect="dark"
>
未读
</el-tag>
</div>
<div class="notice-meta">
<span class="notice-date">{{ formatDate(notice.createTime) }}</span>
@@ -42,7 +52,10 @@
</div>
</div>
</div>
<el-icon class="arrow-icon" v-if="activeNoticeId === notice.noticeId">
<el-icon
v-if="activeNoticeId === notice.noticeId"
class="arrow-icon"
>
<ArrowRight />
</el-icon>
</div>
@@ -50,35 +63,63 @@
</div>
<!-- 公告详情 -->
<div class="notice-detail" v-if="activeNotice">
<div
v-if="activeNotice"
class="notice-detail"
>
<div class="notice-detail-header">
<h3 class="notice-detail-title">{{ activeNotice.noticeTitle }}</h3>
<h3 class="notice-detail-title">
{{ activeNotice.noticeTitle }}
</h3>
<div class="notice-detail-meta">
<el-tag :type="getPriorityTagType(activeNotice.priority)" size="small" effect="dark">
<el-tag
:type="getPriorityTagType(activeNotice.priority)"
size="small"
effect="dark"
>
{{ getPriorityText(activeNotice.priority) }}
</el-tag>
<el-tag :type="getNoticeTypeTagType(activeNotice.noticeType)" size="small">
<el-tag
:type="getNoticeTypeTagType(activeNotice.noticeType)"
size="small"
>
{{ getNoticeTypeText(activeNotice.noticeType) }}
</el-tag>
<span class="notice-detail-date">{{ formatDate(activeNotice.createTime) }}</span>
</div>
</div>
<el-divider />
<div class="notice-detail-body" v-html="activeNotice.noticeContent"></div>
<div
class="notice-detail-body"
v-html="activeNotice.noticeContent"
/>
</div>
<!-- 空状态 -->
<div v-else class="empty-state">
<el-empty description="暂无公告" :image-size="120" />
<div
v-else
class="empty-state"
>
<el-empty
description="暂无公告"
:image-size="120"
/>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="markAllAsRead" v-if="unreadCount > 0" type="info">
<el-button
v-if="unreadCount > 0"
type="info"
@click="markAllAsRead"
>
全部标记为已读
</el-button>
<el-button type="primary" @click="handleClose">
<el-button
type="primary"
@click="handleClose"
>
{{ hasUnread ? '稍后再看' : '知道了' }}
</el-button>
</div>

View File

@@ -1,6 +1,9 @@
<template>
<div>
<svg-icon icon-class="question" @click="goto" />
<svg-icon
icon-class="question"
@click="goto"
/>
</div>
</template>

View File

@@ -1,7 +1,7 @@
<template>
<el-dialog
title="药品追溯码"
v-model="props.openDialog"
title="药品追溯码"
width="842"
append-to-body
destroy-on-close
@@ -15,13 +15,15 @@
>
<div>
<div style="font-size: 16px">
<div style="margin-bottom: 15px">药品名称 {{ props.ypName }}</div>
<div style="margin-bottom: 15px">
药品名称 {{ props.ypName }}
</div>
扫描追溯码
<el-input
ref="traceNoTempRef"
v-model="traceNoTemp"
type="textarea"
:rows="1"
v-model="traceNoTemp"
style="width: 180px; margin-right: 20px"
@input="throttledGetList(traceNoTemp)"
/>
@@ -31,8 +33,22 @@
style="width: 180px; margin-right: 20px"
@keyup.enter="handelTraceNo(traceNoInput)"
/>
<el-button type="primary" plain icon="CircleClose" @click="handleReturn"> 撤回 </el-button>
<el-button type="danger" plain icon="CircleClose" @click="handleClear"> 清除 </el-button>
<el-button
type="primary"
plain
icon="CircleClose"
@click="handleReturn"
>
撤回
</el-button>
<el-button
type="danger"
plain
icon="CircleClose"
@click="handleClear"
>
清除
</el-button>
</div>
<!-- <el-input
ref="inputRef"
@@ -69,11 +85,10 @@
<span style="margin-right: 6px">
[{{ index + 1 }}]
<template v-if="index < 9">&nbsp;</template>
<template v-else></template>
<template v-else />
{{ item }}
</span>
<div
@click="removeTraceNo(index)"
style="
display: flex;
align-items: center;
@@ -84,8 +99,12 @@
border-radius: 50%;
cursor: pointer;
"
@click="removeTraceNo(index)"
>
<el-icon size="10" color="white">
<el-icon
size="10"
color="white"
>
<Close />
</el-icon>
</div>
@@ -98,8 +117,15 @@
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submit"> </el-button>
<el-button @click="cancel"> </el-button>
<el-button
type="primary"
@click="submit"
>
</el-button>
<el-button @click="cancel">
</el-button>
</div>
</template>
</el-dialog>

View File

@@ -6,7 +6,11 @@
trigger="manual"
:width="width"
>
<slot name="popover-content" :row="row" :index="index">
<slot
name="popover-content"
:row="row"
:index="index"
>
<div>列表内容</div>
</slot>
<template #reference>

View File

@@ -1,9 +1,12 @@
<template>
<div :class="{ 'hidden': hidden }" class="pagination-container">
<div
:class="{ 'hidden': hidden }"
class="pagination-container"
>
<el-pagination
:background="background"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:background="background"
:layout="layout"
:page-sizes="pageSizes"
:pager-count="pagerCount"

View File

@@ -1,3 +1,3 @@
<template >
<template>
<router-view />
</template>

View File

@@ -1,21 +1,69 @@
<template>
<div class="top-right-btn" :style="style">
<div
class="top-right-btn"
:style="style"
>
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
<el-button circle icon="Search" @click="toggleSearch()" />
<el-tooltip
v-if="search"
class="item"
effect="dark"
:content="showSearch ? '隐藏搜索' : '显示搜索'"
placement="top"
>
<el-button
circle
icon="Search"
@click="toggleSearch()"
/>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button circle icon="Refresh" @click="refresh()" />
<el-tooltip
class="item"
effect="dark"
content="刷新"
placement="top"
>
<el-button
circle
icon="Refresh"
@click="refresh()"
/>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
<el-button circle icon="Menu" @click="showColumn()" v-if="showColumnsType == 'transfer'"/>
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px" v-if="showColumnsType == 'checkbox'">
<el-button circle icon="Menu" />
<el-tooltip
v-if="columns"
class="item"
effect="dark"
content="显隐列"
placement="top"
>
<el-button
v-if="showColumnsType == 'transfer'"
circle
icon="Menu"
@click="showColumn()"
/>
<el-dropdown
v-if="showColumnsType == 'checkbox'"
trigger="click"
:hide-on-click="false"
style="padding-left: 12px"
>
<el-button
circle
icon="Menu"
/>
<template #dropdown>
<el-dropdown-menu>
<template v-for="item in columns" :key="item.key">
<template
v-for="item in columns"
:key="item.key"
>
<el-dropdown-item>
<el-checkbox :checked="item.visible" @change="checkboxChange($event, item.label)" :label="item.label" />
<el-checkbox
:checked="item.visible"
:label="item.label"
@change="checkboxChange($event, item.label)"
/>
</el-dropdown-item>
</template>
</el-dropdown-menu>
@@ -23,13 +71,17 @@
</el-dropdown>
</el-tooltip>
</el-row>
<el-dialog :title="title" v-model="open" append-to-body>
<el-dialog
v-model="open"
:title="title"
append-to-body
>
<el-transfer
:titles="['显示', '隐藏']"
v-model="value"
:titles="['显示', '隐藏']"
:data="columns"
@change="dataChange"
></el-transfer>
/>
</el-dialog>
</div>
</template>

View File

@@ -1,6 +1,9 @@
<template>
<div>
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" @click="toggle" />
<svg-icon
:icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
@click="toggle"
/>
</div>
</template>

View File

@@ -1,12 +1,23 @@
<template>
<div>
<el-dropdown trigger="click" @command="handleSetSize">
<el-dropdown
trigger="click"
@command="handleSetSize"
>
<div class="size-icon--style">
<svg-icon class-name="size-icon" icon-class="size" />
<svg-icon
class-name="size-icon"
icon-class="size"
/>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size === item.value" :command="item.value">
<el-dropdown-item
v-for="item of sizeOptions"
:key="item.value"
:disabled="size === item.value"
:command="item.value"
>
{{ item.label }}
</el-dropdown-item>
</el-dropdown-menu>

View File

@@ -1,6 +1,12 @@
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" :fill="color" />
<svg
:class="svgClass"
aria-hidden="true"
>
<use
:xlink:href="iconName"
:fill="color"
/>
</svg>
</template>

View File

@@ -1,8 +1,22 @@
<template>
<div class="table-section" v-loading="loading">
<EditableTable ref="editableTableRef" v-bind="$attrs" class="editable-table">
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
<slot :name="slotName" v-bind="slotProps" />
<div
v-loading="loading"
class="table-section"
>
<EditableTable
ref="editableTableRef"
v-bind="$attrs"
class="editable-table"
>
<template
v-for="(_, slotName) in $slots"
:key="slotName"
#[slotName]="slotProps"
>
<slot
:name="slotName"
v-bind="slotProps"
/>
</template>
</EditableTable>
</div>

View File

@@ -1,8 +1,18 @@
<template>
<div class="form-section">
<FormLayout ref="formLayoutRef" v-bind="$attrs">
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
<slot :name="slotName" v-bind="slotProps" />
<FormLayout
ref="formLayoutRef"
v-bind="$attrs"
>
<template
v-for="(_, slotName) in $slots"
:key="slotName"
#[slotName]="slotProps"
>
<slot
:name="slotName"
v-bind="slotProps"
/>
</template>
</FormLayout>
</div>

View File

@@ -8,7 +8,12 @@
@blur="handleBlur"
@change="handleChange"
>
<template v-if="suffix" #suffix>{{ suffix }}</template>
<template
v-if="suffix"
#suffix
>
{{ suffix }}
</template>
</el-input>
</template>

View File

@@ -5,7 +5,10 @@
<slot />
</div>
</template>
<template v-if="$slots.footer" #footer>
<template
v-if="$slots.footer"
#footer
>
<slot name="footer" />
</template>
</Layout>

View File

@@ -2,20 +2,28 @@
<el-menu
:default-active="activeMenu"
mode="horizontal"
@select="handleSelect"
:ellipsis="false"
@select="handleSelect"
>
<template v-for="(item, index) in topMenus">
<!-- 处理有子菜单的情况 -->
<template v-if="item.children && item.children.length > 0 && index < visibleNumber">
<el-sub-menu :style="{'--theme': theme}" :index="item.path" :key="index">
<el-sub-menu
:key="index"
:style="{'--theme': theme}"
:index="item.path"
>
<template #title>
<svg-icon
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"/>
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"
/>
{{ item.meta.title }}
</template>
<template v-for="(child, childIndex) in item.children" :key="childIndex">
<template
v-for="(child, childIndex) in item.children"
:key="childIndex"
>
<el-menu-item :index="item.path + '/' + (child.path || '')">
{{ child.meta.title }}
</el-menu-item>
@@ -24,29 +32,47 @@
</template>
<!-- 处理无子菜单的情况 -->
<template v-else-if="index < visibleNumber">
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index">
<el-menu-item
:key="index"
:style="{'--theme': theme}"
:index="item.path"
>
<svg-icon
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"/>
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"
/>
{{ item.meta.title }}
</el-menu-item>
</template>
</template>
<!-- 顶部菜单超出数量折叠 -->
<el-sub-menu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber">
<template #title>更多菜单</template>
<template v-for="(item, index) in topMenus" :key="index">
<el-sub-menu
v-if="topMenus.length > visibleNumber"
:style="{'--theme': theme}"
index="more"
>
<template #title>
更多菜单
</template>
<template
v-for="(item, index) in topMenus"
:key="index"
>
<!-- 处理有子菜单的情况 -->
<template v-if="item.children && item.children.length > 0 && index >= visibleNumber">
<el-sub-menu :index="item.path">
<template #title>
<svg-icon
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"/>
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"
/>
{{ item.meta.title }}
</template>
<template v-for="(child, childIndex) in item.children" :key="childIndex">
<template
v-for="(child, childIndex) in item.children"
:key="childIndex"
>
<el-menu-item :index="item.path + '/' + (child.path || '')">
{{ child.meta.title }}
</el-menu-item>
@@ -57,8 +83,9 @@
<template v-else-if="index >= visibleNumber">
<el-menu-item :index="item.path">
<svg-icon
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"/>
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta.icon"
/>
{{ item.meta.title }}
</el-menu-item>
</template>

View File

@@ -1,16 +1,19 @@
<template>
<div class="el-tree-select">
<el-select
style="width: 100%"
v-model="valueId"
ref="treeSelect"
v-model="valueId"
style="width: 100%"
:filterable="true"
:clearable="true"
@clear="clearHandle"
:filter-method="selectFilterData"
:placeholder="placeholder"
@clear="clearHandle"
>
<el-option :value="valueId" :label="valueTitle">
<el-option
:value="valueId"
:label="valueTitle"
>
<el-tree
id="tree-option"
ref="selectTree"
@@ -22,7 +25,7 @@
:default-expanded-keys="defaultExpandedKey"
:filter-node-method="filterNode"
@node-click="handleNodeClick"
></el-tree>
/>
</el-option>
</el-select>
</div>

View File

@@ -1,10 +1,14 @@
<template>
<div v-loading="loading" :style="'height:' + height">
<div
v-loading="loading"
:style="'height:' + height"
>
<iframe
:src="url"
frameborder="no"
style="width: 100%; height: 100%"
scrolling="auto" />
scrolling="auto"
/>
</div>
</template>

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