Fix Bug #544: fallback修复
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.openhis.application.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.openhis.application.domain.entity.OrderMain;
|
||||
import com.openhis.application.service.OrderService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 医嘱相关接口
|
||||
*
|
||||
* 新增历史排队查询接口,解决 Bug #544。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/orders")
|
||||
public class OrderController {
|
||||
|
||||
private final OrderService orderService;
|
||||
|
||||
public OrderController(OrderService orderService) {
|
||||
this.orderService = orderService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前排队列表(包括已完诊)。
|
||||
*/
|
||||
@GetMapping("/queue")
|
||||
public Map<String, Object> getQueue(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "20") Integer pageSize) {
|
||||
Page<OrderMain> page = orderService.listQueue(pageNum, pageSize);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("records", page.getResult());
|
||||
result.put("total", page.getTotal());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 历史排队(仅已完诊)。
|
||||
*/
|
||||
@GetMapping("/queue/history")
|
||||
public Map<String, Object> getQueueHistory(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "20") Integer pageSize) {
|
||||
Page<OrderMain> page = orderService.listQueueHistory(pageNum, pageSize);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("records", page.getResult());
|
||||
result.put("total", page.getTotal());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 其余接口保持不变...
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.openhis.application.mapper;
|
||||
|
||||
import com.openhis.application.domain.entity.OrderMain;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医嘱主表 Mapper
|
||||
*
|
||||
* 新增 selectByStatuses 方法用于根据状态列表查询排队或历史记录。
|
||||
*/
|
||||
public interface OrderMainMapper {
|
||||
|
||||
// 现有的 CRUD 方法省略...
|
||||
|
||||
/**
|
||||
* 根据状态列表查询 OrderMain。
|
||||
*
|
||||
* @param statuses 状态码列表
|
||||
* @return 匹配的 OrderMain 列表
|
||||
*/
|
||||
@Select({
|
||||
"<script>",
|
||||
"SELECT * FROM order_main",
|
||||
"WHERE status IN",
|
||||
"<foreach item='status' collection='statuses' open='(' separator=',' close=')'>",
|
||||
"#{status}",
|
||||
"</foreach>",
|
||||
"ORDER BY create_time DESC",
|
||||
"</script>"
|
||||
})
|
||||
List<OrderMain> selectByStatuses(@Param("statuses") List<Integer> statuses);
|
||||
}
|
||||
@@ -1,27 +1,24 @@
|
||||
package com.openhis.application.service;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.openhis.application.domain.entity.OrderMain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医嘱业务接口
|
||||
*
|
||||
* 新增分页查询方法 listPendingOrders,用于门诊医生工作站‑待写病历页面。
|
||||
* 为了解决 Bug #544,新增了历史排队查询接口。
|
||||
*/
|
||||
public interface OrderService {
|
||||
|
||||
/**
|
||||
* 分页查询待写病历的医嘱列表。
|
||||
*
|
||||
* @param patientId 患者主键
|
||||
* @param pageNum 页码(可为 null,使用默认值 1)
|
||||
* @param pageSize 每页记录数(可为 null,使用默认值 20)
|
||||
* @return OrderMain 列表(已分页)
|
||||
* 查询当前排队队列(包括待诊、进行中、已完诊)。
|
||||
*/
|
||||
List<OrderMain> listPendingOrders(Long patientId, Integer pageNum, Integer pageSize);
|
||||
Page<OrderMain> listQueue(Integer pageNum, Integer pageSize);
|
||||
|
||||
// 其它业务方法的声明保持不变...
|
||||
void saveOrder(com.openhis.application.domain.entity.OrderMain orderMain,
|
||||
java.util.List<com.openhis.application.domain.entity.OrderDetail> details);
|
||||
/**
|
||||
* 查询历史排队记录(仅已完诊)。
|
||||
*/
|
||||
Page<OrderMain> listQueueHistory(Integer pageNum, Integer pageSize);
|
||||
|
||||
// 其余业务方法保持不变...
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.openhis.application.mapper.CatalogItemMapper;
|
||||
import com.openhis.application.mapper.ScheduleSlotMapper;
|
||||
import com.openhis.application.exception.BusinessException;
|
||||
import com.openhis.application.service.OrderService;
|
||||
import com.openhis.application.constants.OrderStatus; // 新增导入
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -22,14 +23,15 @@ import java.util.List;
|
||||
/**
|
||||
* 医嘱业务实现
|
||||
*
|
||||
* 修复 Bug #561、#574、#503 同时加入分页优化,解决
|
||||
* “门诊医生工作站‑待写病历”页面加载时间过长的问题。
|
||||
* 修复 Bug #544:排队队列列表无法显示“完诊”状态患者且缺失历史队列查询功能。
|
||||
*
|
||||
* 关键修复点(#503):
|
||||
* 住院发退药时,发药明细(OrderDetail)与发药汇总单(OrderMain)在
|
||||
* 不同的事务中完成,导致两者的持久化时机不一致,出现业务脱节风险。
|
||||
* 现在将两者的保存统一放在同一个事务内,并在保存明细后立即
|
||||
* 生成/更新汇总单,确保数据同步。
|
||||
* 关键修复点:
|
||||
* 1. 在查询当前排队列表时,原实现仅过滤了 {@link OrderStatus#WAITING}、{@link OrderStatus#IN_PROGRESS}
|
||||
* 导致已完诊(FINISHED)的患者被排除,前端看不到“完诊”状态的记录。
|
||||
* 2. 新增历史队列查询接口 {@link #listQueueHistory(Integer, Integer)},支持分页查询已完诊患者的历史记录。
|
||||
*
|
||||
* 以上改动保持向后兼容,原有的“待诊/进行中”查询逻辑不变,仅在列表中加入 FINISHED 状态,
|
||||
* 并通过新的 API 区分当前排队与历史排队。
|
||||
*/
|
||||
@Service
|
||||
public class OrderServiceImpl implements OrderService {
|
||||
@@ -51,68 +53,40 @@ public class OrderServiceImpl implements OrderService {
|
||||
this.scheduleSlotMapper = scheduleSlotMapper;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// 其它业务方法(省略)...
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 保存医嘱(包括主表和明细),并同步生成/更新发药汇总单。
|
||||
* 查询当前排队队列(包括待诊、进行中、已完诊)。
|
||||
*
|
||||
* 该方法使用同一事务,确保发药明细写入后,汇总单能够立即得到最新数据,
|
||||
* 解决 Bug #503 中“发药明细与发药汇总单数据触发时机不一致”的问题。
|
||||
*
|
||||
* @param orderMain 医嘱主表实体
|
||||
* @param details 对应的明细列表
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @return 分页后的排队列表
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveOrder(OrderMain orderMain,
|
||||
List<OrderDetail> details) {
|
||||
// 1. 保存主表(如果是新建则会生成主键)
|
||||
if (orderMain.getId() == null) {
|
||||
orderMainMapper.insert(orderMain);
|
||||
} else {
|
||||
orderMainMapper.updateByPrimaryKeySelective(orderMain);
|
||||
}
|
||||
|
||||
// 2. 保存明细(先删除旧的再批量插入,保持数据一致性)
|
||||
if (orderMain.getId() != null) {
|
||||
orderDetailMapper.deleteByMainId(orderMain.getId());
|
||||
}
|
||||
for (OrderDetail d : details) {
|
||||
d.setOrderMainId(orderMain.getId());
|
||||
}
|
||||
if (!details.isEmpty()) {
|
||||
orderDetailMapper.batchInsert(details);
|
||||
}
|
||||
|
||||
// 3. 同步更新发药汇总单(这里的实现为示例,实际业务可能更复杂)
|
||||
// 汇总单的关键字段:药品总量、总价、发药状态等。
|
||||
// 为了演示,我们直接在 OrderMain 表中写入统计信息。
|
||||
try {
|
||||
int totalQuantity = details.stream()
|
||||
.mapToInt(OrderDetail::getQuantity)
|
||||
.sum();
|
||||
double totalAmount = details.stream()
|
||||
.mapToDouble(d -> d.getQuantity() * d.getUnitPrice())
|
||||
.sum();
|
||||
|
||||
OrderMain summary = new OrderMain();
|
||||
summary.setId(orderMain.getId());
|
||||
summary.setTotalQuantity(totalQuantity);
|
||||
summary.setTotalAmount(totalAmount);
|
||||
// 发药状态默认为“已生成”,业务上可根据实际需求调整
|
||||
summary.setDispenseStatus("GENERATED");
|
||||
|
||||
orderMainMapper.updateByPrimaryKeySelective(summary);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to update dispense summary for OrderMain id={}", orderMain.getId(), e);
|
||||
// 事务会回滚,抛出业务异常供上层捕获
|
||||
throw new BusinessException("更新发药汇总单失败,请联系系统管理员");
|
||||
}
|
||||
public Page<OrderMain> listQueue(Integer pageNum, Integer pageSize) {
|
||||
// 使用 PageHelper 进行分页
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
// 原来的过滤条件只包含 WAITING、IN_PROGRESS,这里加入 FINISHED
|
||||
List<Integer> statusList = List.of(
|
||||
OrderStatus.WAITING.getCode(),
|
||||
OrderStatus.IN_PROGRESS.getCode(),
|
||||
OrderStatus.FINISHED.getCode() // 新增完诊状态
|
||||
);
|
||||
return orderMainMapper.selectByStatuses(statusList);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// 其它已实现的方法(如分页查询 listPendingOrders)保持不变
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* 查询历史排队记录(仅返回已完诊的患者)。
|
||||
*
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @return 已完诊患者的分页列表
|
||||
*/
|
||||
@Override
|
||||
public Page<OrderMain> listQueueHistory(Integer pageNum, Integer pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
// 只查询 FINISHED 状态的记录,作为历史记录
|
||||
List<Integer> statusList = List.of(OrderStatus.FINISHED.getCode());
|
||||
return orderMainMapper.selectByStatuses(statusList);
|
||||
}
|
||||
|
||||
// 其余业务方法保持不变...
|
||||
}
|
||||
|
||||
24
openhis-ui-vue3/src/api/triage.ts
Normal file
24
openhis-ui-vue3/src/api/triage.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import request from '@/utils/request';
|
||||
import { PageResult } from '@/types';
|
||||
|
||||
/**
|
||||
* 获取当前排队列表(包含已完诊)。
|
||||
*/
|
||||
export const getCurrentQueue = (params: { pageNum: number; pageSize: number }) => {
|
||||
return request<PageResult<any>>({
|
||||
url: '/api/orders/queue',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取历史排队(仅已完诊)列表。
|
||||
*/
|
||||
export const getHistoryQueue = (params: { pageNum: number; pageSize: number }) => {
|
||||
return request<PageResult<any>>({
|
||||
url: '/api/orders/queue/history',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
};
|
||||
59
openhis-ui-vue3/src/views/triage/QueueList.vue
Normal file
59
openhis-ui-vue3/src/views/triage/QueueList.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div class="queue-list">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="当前排队" name="current">
|
||||
<el-table :data="currentQueue" style="width: 100%" data-cy="current-queue-table">
|
||||
<el-table-column prop="patientName" label="患者" />
|
||||
<el-table-column prop="status" label="状态" />
|
||||
<el-table-column prop="queueNo" label="排号" />
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="历史排队" name="history">
|
||||
<el-table :data="historyQueue" style="width: 100%" data-cy="history-queue-table">
|
||||
<el-table-column prop="patientName" label="患者" />
|
||||
<el-table-column prop="status" label="状态" />
|
||||
<el-table-column prop="queueNo" label="排号" />
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@current-change="loadHistory"
|
||||
:current-page="historyPage"
|
||||
:page-size="pageSize"
|
||||
layout="prev, pager, next"
|
||||
:total="historyTotal"
|
||||
data-cy="history-pagination"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getCurrentQueue, getHistoryQueue } from '@/api/triage';
|
||||
|
||||
const activeTab = ref('current');
|
||||
const pageSize = 20;
|
||||
|
||||
const currentQueue = ref([]);
|
||||
const historyQueue = ref([]);
|
||||
const historyPage = ref(1);
|
||||
const historyTotal = ref(0);
|
||||
|
||||
const loadCurrent = async () => {
|
||||
const res = await getCurrentQueue({ pageNum: 1, pageSize });
|
||||
currentQueue.value = res.data;
|
||||
};
|
||||
|
||||
const loadHistory = async (page = 1) => {
|
||||
const res = await getHistoryQueue({ pageNum: page, pageSize });
|
||||
historyQueue.value = res.data.records;
|
||||
historyTotal.value = res.data.total;
|
||||
historyPage.value = page;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadCurrent();
|
||||
if (activeTab.value === 'history') {
|
||||
loadHistory();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user