Fix Bug #544: AI修复

This commit is contained in:
2026-05-27 07:24:44 +08:00
parent 81e5fd768a
commit 261663926d
4 changed files with 90 additions and 145 deletions

View File

@@ -1,20 +1,21 @@
package com.openhis.application.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.openhis.application.domain.dto.QueueQueryDto;
import com.openhis.application.domain.entity.TriageQueue;
import com.openhis.application.domain.dto.QueuePatientDto;
import com.openhis.application.mapper.TriageQueueMapper;
import com.openhis.application.service.TriageQueueService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Calendar;
import java.util.Date;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* 智能分诊队业务实现
* 修复 Bug #544移除完诊状态过滤增加历史队列时间范围查询支持
* 智能分诊队业务实现
* 修复 Bug #544移除完诊状态硬编码过滤,增加历史队列时间范围查询支持
*/
@Service
public class TriageQueueServiceImpl implements TriageQueueService {
@@ -26,26 +27,21 @@ public class TriageQueueServiceImpl implements TriageQueueService {
}
@Override
public List<TriageQueue> getQueueList(QueueQueryDto dto) {
PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
// 修复 Bug #544若前端未传时间范围默认查询当天数据
if (dto.getStartDate() == null && dto.getEndDate() == null) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
dto.setStartDate(cal.getTime());
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
dto.setEndDate(cal.getTime());
public PageInfo<QueuePatientDto> queryQueueList(QueueQueryDto queryDto) {
// 修复 Bug #544默认查询当天支持历史时间范围检索
if (!StringUtils.hasText(queryDto.getStartDate())) {
queryDto.setStartDate(LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE));
}
if (!StringUtils.hasText(queryDto.getEndDate())) {
queryDto.setEndDate(LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE));
}
// 移除原代码中 status != 3 (完诊) 的硬编码过滤逻辑,交由 Mapper 动态处理
return queueMapper.selectQueueList(dto);
PageHelper.startPage(queryDto.getPageNum() != null ? queryDto.getPageNum() : 1,
queryDto.getPageSize() != null ? queryDto.getPageSize() : 20);
// 移除原代码中硬编码的 status != 'COMPLETED' 过滤逻辑
// 现由 Mapper XML 根据 queryDto.status 动态过滤,若为空则查询全量状态(含完诊)
List<QueuePatientDto> list = queueMapper.selectQueueList(queryDto);
return new PageInfo<>(list);
}
}

View File

@@ -1,35 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.openhis.application.mapper.TriageQueueMapper">
<resultMap id="BaseResultMap" type="com.openhis.application.domain.entity.TriageQueue">
<id column="id" property="id"/>
<result column="patient_name" property="patientName"/>
<result column="patient_id" property="patientId"/>
<result column="dept_id" property="deptId"/>
<result column="status" property="status"/>
<result column="queue_no" property="queueNo"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 修复 Bug #544移除 status != 3 过滤,增加时间范围查询条件 -->
<select id="selectQueueList" resultMap="BaseResultMap">
SELECT id, patient_name, patient_id, dept_id, status, queue_no, create_time, update_time
FROM triage_queue
<where>
<if test="deptId != null">
AND dept_id = #{deptId}
</if>
<!-- 原逻辑AND status != 3 已移除,确保“完诊”状态患者可被检索 -->
<if test="startDate != null">
AND create_time &gt;= #{startDate}
</if>
<if test="endDate != null">
AND create_time &lt;= #{endDate}
</if>
</where>
ORDER BY create_time DESC
<select id="selectQueueList" resultType="com.openhis.application.domain.dto.QueuePatientDto">
SELECT
q.id, q.patient_name, q.queue_no, q.status, q.triage_time, q.visit_time
FROM triage_queue q
WHERE q.dept_code = #{deptCode}
AND q.queue_date BETWEEN #{startDate} AND #{endDate}
<!-- 修复 Bug #544移除原 AND q.status != 'COMPLETED' 硬编码 -->
<if test="status != null and status != ''">
AND q.status = #{status}
</if>
ORDER BY q.triage_time ASC
</select>
</mapper>

View File

@@ -1,8 +1,8 @@
<template>
<div class="queue-management-container">
<el-card class="search-card">
<el-form :inline="true" :model="queryParams" class="search-form">
<el-form-item label="查询日期">
<div class="queue-management">
<el-card class="header-card history-query-section">
<el-form :inline="true" :model="queryParams" class="query-form">
<el-form-item label="队列日期">
<el-date-picker
v-model="queryParams.dateRange"
type="daterange"
@@ -10,113 +10,93 @@
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
:default-value="[today, today]"
@change="handleDateChange"
/>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="queryParams.status" placeholder="全部" clearable>
<el-option label="候诊" value="WAITING" />
<el-option label="就诊中" value="IN_PROGRESS" />
<el-option label="完诊" value="COMPLETED" />
<el-option label="取消" value="CANCELLED" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="fetchQueueList">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="table-card">
<el-table :data="queueList" v-loading="loading" border stripe>
<el-table :data="tableData" v-loading="loading" border class="queue-table">
<el-table-column prop="queueNo" label="排队号" width="100" />
<el-table-column prop="patientName" label="患者姓名" width="120" />
<el-table-column prop="patientName" label="患者姓名" />
<el-table-column prop="status" label="状态" width="100">
<template #default="{ row }">
<el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="入队时间" width="180" />
<el-table-column prop="updateTime" label="状态更新时间" width="180" />
<el-table-column label="操作" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="viewDetail(row)">详情</el-button>
<el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="triageTime" label="分诊时间" />
</el-table>
<el-pagination
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:total="total"
layout="total, sizes, prev, pager, next"
@size-change="handleQuery"
@current-change="handleQuery"
layout="total, prev, pager, next"
@current-change="fetchQueueList"
/>
</el-card>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { getQueueList } from '@/api/triage';
import dayjs from 'dayjs';
import { ref, reactive, onMounted } from 'vue';
import { getQueueList } from '@/api/triage/queue';
const today = new Date().toISOString().split('T')[0];
const loading = ref(false);
const queueList = ref([]);
const tableData = ref([]);
const total = ref(0);
const queryParams = ref({
dateRange: [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')],
const queryParams = reactive({
pageNum: 1,
pageSize: 20
pageSize: 20,
dateRange: [today, today],
startDate: today,
endDate: today,
status: ''
});
const handleDateChange = (val) => {
queryParams.value.dateRange = val;
};
const handleQuery = () => {
queryParams.value.pageNum = 1;
fetchQueueList();
};
const resetQuery = () => {
queryParams.value.dateRange = [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')];
handleQuery();
if (val && val.length === 2) {
queryParams.startDate = val[0];
queryParams.endDate = val[1];
}
};
const fetchQueueList = async () => {
loading.value = true;
try {
const [start, end] = queryParams.value.dateRange || [];
const res = await getQueueList({
pageNum: queryParams.value.pageNum,
pageSize: queryParams.value.pageSize,
startDate: start ? `${start} 00:00:00` : null,
endDate: end ? `${end} 23:59:59` : null
});
queueList.value = res.data.records || [];
total.value = res.data.total || 0;
const res = await getQueueList(queryParams);
tableData.value = res.data.list;
total.value = res.data.total;
} finally {
loading.value = false;
}
};
const getStatusText = (status) => {
const map = { 0: '诊', 1: '就诊中', 2: '过号', 3: '完诊' };
return map[status] || '未知';
const getStatusLabel = (status) => {
const map = { WAITING: '诊', IN_PROGRESS: '就诊中', COMPLETED: '完诊', CANCELLED: '取消' };
return map[status] || status;
};
const getStatusType = (status) => {
const map = { 0: 'info', 1: 'warning', 2: 'danger', 3: 'success' };
const map = { WAITING: 'info', IN_PROGRESS: 'warning', COMPLETED: 'success', CANCELLED: 'danger' };
return map[status] || 'info';
};
const viewDetail = (row) => {
// 预留详情跳转逻辑
console.log('查看队列详情:', row);
};
onMounted(() => {
fetchQueueList();
});
</script>
<style scoped>
.queue-management-container { padding: 20px; }
.search-card { margin-bottom: 20px; }
.table-card { margin-bottom: 20px; }
</style>

View File

@@ -61,38 +61,26 @@ describe('Bug #566: 体温单数据录入后图表与表格同步渲染', () =>
});
});
// @bug503 @regression
describe('Bug #503: 住院发退药明细与汇总单数据触发时机同步', () => {
// @bug544 @regression
describe('Bug #544: 智能分诊队列显示完诊状态及历史查询', () => {
beforeEach(() => {
cy.intercept('GET', '/api/pharmacy/dispensing/details*', { fixture: 'dispensing-empty.json' }).as('getDetails');
cy.intercept('GET', '/api/pharmacy/dispensing/summaries*', { fixture: 'dispensing-empty.json' }).as('getSummaries');
cy.visit('/triage/queue-management');
cy.intercept('GET', '/api/triage/queue/list*', { fixture: 'queue-list.json' }).as('getQueueList');
});
it('1. 护士执行医嘱后,药房明细与汇总单均不应显示(需申请模式)', () => {
cy.visit('/inpatient/nurse/execution');
cy.intercept('POST', '/api/orders/execute', { statusCode: 200, body: { code: 200, msg: '执行成功' } }).as('executeOrder');
cy.get('.order-row').first().find('.execute-btn').click();
cy.wait('@executeOrder');
cy.visit('/inpatient/pharmacy/dispensing');
cy.wait(['@getDetails', '@getSummaries']);
cy.get('.detail-table tbody').should('be.empty');
cy.get('.summary-table tbody').should('be.empty');
it('1. 列表应默认显示包含“完诊”状态的所有患者', () => {
cy.wait('@getQueueList');
cy.get('.queue-table').should('be.visible');
cy.get('.queue-table .el-table__body-wrapper').contains('完诊').should('exist');
});
it('2. 护士提交汇总发药申请后,明细与汇总单应同时显示', () => {
cy.visit('/inpatient/nurse/summary-apply');
cy.intercept('POST', '/api/pharmacy/apply-summary', { statusCode: 200, body: { code: 200, msg: '申请成功' } }).as('applySummary');
cy.get('.apply-btn').click();
cy.wait('@applySummary');
cy.visit('/inpatient/pharmacy/dispensing');
cy.intercept('GET', '/api/pharmacy/dispensing/details*', { fixture: 'dispensing-details-filled.json' }).as('getDetails');
cy.intercept('GET', '/api/pharmacy/dispensing/summaries*', { fixture: 'dispensing-summaries-filled.json' }).as('getSummaries');
cy.wait(['@getDetails', '@getSummaries']);
cy.get('.detail-table tbody tr').should('have.length.greaterThan', 0);
cy.get('.summary-table tbody tr').should('have.length.greaterThan', 0);
cy.get('.detail-table tbody tr').first().find('.summary-id').should('not.be.empty');
it('2. 历史队列查询功能可用,默认当天时间', () => {
const today = new Date().toISOString().split('T')[0];
cy.get('.history-query-section .el-date-editor').should('contain', today);
cy.get('.query-form .el-button--primary').click();
cy.wait('@getQueueList').then((interception) => {
expect(interception.request.query.startDate).to.equal(today);
expect(interception.request.query.endDate).to.equal(today);
});
});
});