Fix Bug #566: AI修复

This commit is contained in:
2026-05-27 03:19:57 +08:00
parent e4c6c57176
commit b1fb7b2d56
2 changed files with 203 additions and 24 deletions

View File

@@ -0,0 +1,154 @@
<template>
<div class="temperature-sheet-container">
<div class="chart-wrapper">
<div ref="chartRef" class="temperature-chart"></div>
</div>
<div class="table-wrapper">
<el-table :data="tableData" border stripe style="width: 100%" size="small">
<el-table-column prop="measureTime" label="测量时间" width="160" align="center" />
<el-table-column prop="temperature" label="体温(℃)" width="100" align="center">
<template #default="{ row }">{{ row.temperature ? row.temperature.toFixed(1) : '-' }}</template>
</el-table-column>
<el-table-column prop="pulse" label="脉搏(次/分)" width="110" align="center" />
<el-table-column prop="heartRate" label="心率(次/分)" width="110" align="center" />
</el-table>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import { getPatientVitals } from '@/api/inpatient/vitalsign';
const props = defineProps({
patientId: { type: [String, Number], required: true }
});
const chartRef = ref(null);
let chartInstance = null;
const tableData = ref([]);
// 初始化图表
const initChart = () => {
if (!chartRef.value) return;
chartInstance = echarts.init(chartRef.value);
window.addEventListener('resize', handleResize);
};
const handleResize = () => chartInstance?.resize();
// 核心修复:数据拉取与渲染逻辑
const refreshData = async () => {
try {
const res = await getPatientVitals({ patientId: props.patientId });
if (res.code === 200 && Array.isArray(res.data)) {
// 按时间升序排序
const sorted = res.data.sort((a, b) => new Date(a.measureTime) - new Date(b.measureTime));
tableData.value = sorted; // 同步表格区
renderChart(sorted);
}
} catch (err) {
console.error('[体温单] 数据加载失败:', err);
}
};
// 渲染图表(严格遵循医疗绘图规范)
const renderChart = (data) => {
if (!chartInstance) return;
const times = data.map(d => d.measureTime);
// 处理断点连线:缺失值映射为 null配合 connectNulls: false 实现自动断开
const mapSeries = (key) => data.map(d => (d[key] != null ? d[key] : null));
const option = {
tooltip: { trigger: 'axis', formatter: '{b}<br/>{a}: {c}' },
grid: { top: 30, bottom: 30, left: 40, right: 20, containLabel: true },
xAxis: {
type: 'category',
data: times,
axisLabel: { rotate: 30, fontSize: 11 }
},
yAxis: {
type: 'value',
min: 35,
max: 42,
splitNumber: 7,
axisLine: { show: false },
splitLine: { lineStyle: { type: 'dashed' } }
},
series: [
{
name: '体温',
type: 'line',
data: mapSeries('temperature'),
symbol: 'x',
symbolSize: 8,
lineStyle: { color: '#1890ff', width: 2 },
itemStyle: { color: '#1890ff' },
connectNulls: false // 医疗规范:数据缺失必须断开
},
{
name: '脉搏',
type: 'line',
data: mapSeries('pulse'),
symbol: 'circle', // ● 实心圆
symbolSize: 8,
lineStyle: { color: '#ff4d4f', width: 2 },
itemStyle: { color: '#ff4d4f' },
connectNulls: false
},
{
name: '心率',
type: 'line',
data: mapSeries('heartRate'),
symbol: 'emptyCircle', // ○ 空心圆
symbolSize: 8,
lineStyle: { color: '#ff4d4f', width: 2 },
itemStyle: { color: '#ff4d4f' },
connectNulls: false
}
]
};
// 重叠处理ECharts 默认按 series 顺序绘制,心率(空心)在脉搏(实心)之上,符合临床视觉习惯
chartInstance.setOption(option, true);
};
// 暴露方法供父组件/弹窗在保存成功后调用
defineExpose({ refreshData });
onMounted(() => {
initChart();
refreshData();
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
});
</script>
<style scoped>
.temperature-sheet-container {
display: flex;
flex-direction: column;
height: 100%;
padding: 10px;
background: #fff;
}
.chart-wrapper {
flex: 1;
min-height: 300px;
margin-bottom: 10px;
}
.temperature-chart {
width: 100%;
height: 100%;
}
.table-wrapper {
height: 200px;
overflow-y: auto;
}
</style>