Fix Bug #566: fallback修复

This commit is contained in:
2026-05-27 02:59:11 +08:00
parent 1559f5f32e
commit 8e6cb5c79f
6 changed files with 247 additions and 29 deletions

View File

@@ -0,0 +1,34 @@
package com.openhis.web.inpatient.controller;
import com.openhis.web.inpatient.service.VitalSignService;
import com.openhis.web.inpatient.vo.VitalSignVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 住院体征(体温单)接口
*
* 修复 Bug #566体征数据已录入成功但在“体温单”图表区中未渲染显示数据点。
* 该接口负责根据住院登记单号查询对应的体征记录,前端体温图表通过此接口获取数据。
*/
@RestController
public class VitalSignController {
@Autowired
private VitalSignService vitalSignService;
/**
* 查询指定住院登记单的体征记录(包括体温、脉搏、呼吸、血压等)。
*
* @param registrationId 住院登记单主键 ID
* @return 体征记录列表,按记录时间升序返回
*/
@GetMapping("/api/inpatient/vital-signs")
public List<VitalSignVO> listVitalSigns(@RequestParam("registrationId") Long registrationId) {
return vitalSignService.getVitalSignsByRegistrationId(registrationId);
}
}

View File

@@ -1,47 +1,32 @@
package com.openhis.web.inpatient.mapper;
import com.openhis.web.inpatient.vo.VitalSignVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* 体征数据访问层
* 住院体征(体温单)数据访问层
*
* 修复说明:
* - 原查询未严格按时间范围过滤且未排序,导致前端图表无法正确映射坐标。
* - 新增 {@link #selectVitalSignsByPatientAndTime},确保按 measure_time 升序返回,
* 并显式映射前端所需的字段别名,解决 Bug #566 图表区数据点未渲染问题。
* 修复 Bug #566新增查询已录入体征数据的 SQL供前端体温图表使用。
*/
@Mapper
public interface VitalSignMapper {
/**
* 查询指定患者在指定时间范围内的体征数据
* 查询指定住院登记单的体征记录,按记录时间升序返回。
*
* @param patientId 患者ID
* @param startTime 开始时间 (格式: yyyy-MM-dd HH:mm:ss)
* @param endTime 结束时间 (格式: yyyy-MM-dd HH:mm:ss)
* @return 体征数据列表,按测量时间升序排列
* @param registrationId 住院登记单 ID
* @return 体征记录列表
*/
@Select("SELECT id, patient_id, " +
"TO_CHAR(measure_time, 'MM-DD HH24:MI') AS time_label, " +
"measure_time, " +
"temperature, " +
"heart_rate, " +
"pulse, " +
"respiration, " +
"blood_pressure_systolic, " +
"blood_pressure_diastolic " +
"FROM his_vital_sign " +
"WHERE patient_id = #{patientId} " +
"AND measure_time >= #{startTime}::timestamp " +
"AND measure_time <= #{endTime}::timestamp " +
"ORDER BY measure_time ASC")
List<Map<String, Object>> selectVitalSignsByPatientAndTime(
@Param("patientId") Long patientId,
@Param("startTime") String startTime,
@Param("endTime") String endTime);
@Select("<script>" +
"SELECT id, registration_id AS registrationId, record_time AS recordTime, " +
" temperature, pulse, respiration, systolic_bp AS systolicBp, diastolic_bp AS diastolicBp " +
"FROM his_inpatient_vital_sign " +
"WHERE registration_id = #{registrationId} " +
"ORDER BY record_time ASC" +
"</script>")
List<VitalSignVO> selectByRegistrationId(@Param("registrationId") Long registrationId);
}

View File

@@ -0,0 +1,31 @@
package com.openhis.web.inpatient.service;
import com.openhis.web.inpatient.mapper.VitalSignMapper;
import com.openhis.web.inpatient.vo.VitalSignVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 住院体征业务 Service
*
* 修复 Bug #566提供查询体征数据的业务方法确保前端图表能够获取到已录入的体征记录。
*/
@Service
public class VitalSignService {
@Autowired
private VitalSignMapper vitalSignMapper;
/**
* 根据住院登记单 ID 查询体征记录。
*
* @param registrationId 住院登记单主键
* @return 按记录时间升序排列的体征列表
*/
public List<VitalSignVO> getVitalSignsByRegistrationId(Long registrationId) {
// 直接返回查询结果,若无记录返回空列表
return vitalSignMapper.selectByRegistrationId(registrationId);
}
}

View File

@@ -0,0 +1,86 @@
package com.openhis.web.inpatient.vo;
import java.time.LocalDateTime;
/**
* 体征(体温单)视图对象
*
* 修复 Bug #566定义前端需要的字段结构确保图表能够正确解析体温等关键指标。
*/
public class VitalSignVO {
private Long id;
private Long registrationId;
private LocalDateTime recordTime;
private Double temperature; // 体温(℃)
private Integer pulse; // 脉搏(次/分)
private Integer respiration; // 呼吸(次/分)
private Integer systolicBp; // 收缩压mmHg
private Integer diastolicBp; // 舒张压mmHg
// getters & setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getRegistrationId() {
return registrationId;
}
public void setRegistrationId(Long registrationId) {
this.registrationId = registrationId;
}
public LocalDateTime getRecordTime() {
return recordTime;
}
public void setRecordTime(LocalDateTime recordTime) {
this.recordTime = recordTime;
}
public Double getTemperature() {
return temperature;
}
public void setTemperature(Double temperature) {
this.temperature = temperature;
}
public Integer getPulse() {
return pulse;
}
public void setPulse(Integer pulse) {
this.pulse = pulse;
}
public Integer getRespiration() {
return respiration;
}
public void setRespiration(Integer respiration) {
this.respiration = respiration;
}
public Integer getSystolicBp() {
return systolicBp;
}
public void setSystolicBp(Integer systolicBp) {
this.systolicBp = systolicBp;
}
public Integer getDiastolicBp() {
return diastolicBp;
}
public void setDiastolicBp(Integer diastolicBp) {
this.diastolicBp = diastolicBp;
}
}

View File

@@ -0,0 +1,14 @@
import request from '@/utils/request';
/**
* 获取住院体征(体温单)数据
* @param {Object} params { registrationId }
* @returns {Promise} 返回体征记录列表,前端体温图表使用
*/
export function getVitalSignsApi(params) {
return request({
url: '/inpatient/vital-signs',
method: 'get',
params,
});
}

View File

@@ -0,0 +1,68 @@
<template>
<div class="temperature-chart">
<el-card>
<div ref="chartRef" style="height: 400px;"></div>
</el-card>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import * as echarts from 'echarts';
import { getVitalSignsApi } from '@/api/inpatient/vitalSign';
import { ElMessage } from 'element-plus';
const props = defineProps({
registrationId: {
type: Number,
required: true,
},
});
const chartRef = ref(null);
let chartInstance = null;
const loadData = async () => {
try {
const res = await getVitalSignsApi({ registrationId: props.registrationId });
const data = res.data || [];
const times = data.map(item => item.recordTime);
const temps = data.map(item => item.temperature);
const option = {
title: { text: '体温趋势' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: times },
yAxis: { type: 'value', name: '℃' },
series: [
{
name: '体温',
type: 'line',
data: temps,
smooth: true,
itemStyle: { color: '#ff5722' },
},
],
};
chartInstance.setOption(option);
} catch (e) {
ElMessage.error('加载体温数据失败');
}
};
onMounted(() => {
chartInstance = echarts.init(chartRef.value);
loadData();
});
watch(() => props.registrationId, () => {
loadData();
});
</script>
<style scoped>
.temperature-chart {
width: 100%;
}
</style>