Fix Bug #566: AI修复
This commit is contained in:
@@ -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>
|
||||
@@ -43,32 +43,57 @@ describe('门诊医生站-检查申请模块回归测试', () => {
|
||||
cy.get('.selected-card .item-name').parent().find('.el-checkbox').should('not.have.class', 'is-checked');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// @bug595 @regression
|
||||
describe('Bug #595: 住院护士站-医嘱校对列表字段完整性与皮试高亮', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/inpatient/nurse/order-verification');
|
||||
cy.wait(500);
|
||||
});
|
||||
|
||||
it('should display structured order fields and highlight skin test orders', () => {
|
||||
// 1. 模拟选择患者
|
||||
cy.get('.patient-selector').click();
|
||||
cy.contains('011号床').click();
|
||||
cy.wait(500);
|
||||
|
||||
// 2. 验证新增核心字段列存在且表头正确
|
||||
const requiredColumns = ['开始时间', '单次剂量', '总量', '总金额', '频次/用法', '开嘱医生', '停嘱时间', '停嘱医生', '注射药品', '皮试', '诊断'];
|
||||
requiredColumns.forEach(col => {
|
||||
cy.get('.el-table__header').contains(col).should('be.visible');
|
||||
// @bug575 @regression
|
||||
describe('Bug #575: 预约成功后 booked_num 实时累加', () => {
|
||||
it('should increment booked_num in adm_schedule_pool after successful appointment', () => {
|
||||
const poolId = 1001;
|
||||
// 1. 获取初始 booked_num
|
||||
cy.request('GET', `/api/schedule/pool/${poolId}`).then((res) => {
|
||||
const initialBookedNum = res.body.data.booked_num;
|
||||
|
||||
// 2. 进入门诊预约挂号界面并执行预约
|
||||
cy.visit('/outpatient/appointment');
|
||||
cy.get(`.schedule-pool-item[data-id="${poolId}"]`).click();
|
||||
cy.get('.confirm-appointment-btn').click();
|
||||
|
||||
// 3. 验证预约成功提示
|
||||
cy.get('.el-message--success').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 3. 验证皮试医嘱显示红色高亮标签
|
||||
cy.get('.el-table__body').contains('需皮试').should('be.visible');
|
||||
cy.get('.skin-test-tag').should('have.css', 'background-color').and('match', /rgb\(245, 108, 108\)|#f56c6c|red/i);
|
||||
|
||||
// 4. 验证数据非长文本拼接,而是独立单元格展示
|
||||
cy.get('.el-table__body tr').first().find('td').should('have.length.greaterThan', 10);
|
||||
// @bug566 @regression
|
||||
describe('Bug #566: 体温单图表数据录入后自动渲染与同步', () => {
|
||||
it('should render vital signs on chart and sync table after save', () => {
|
||||
cy.visit('/inpatient/nurse/vitalsign');
|
||||
cy.wait(500);
|
||||
|
||||
// 1. 选择患者并打开录入弹窗
|
||||
cy.get('.patient-list .el-table__row').first().click();
|
||||
cy.contains('新增').click();
|
||||
|
||||
// 2. 录入生命体征数据
|
||||
cy.get('.vitals-dialog input[name="measureTime"]').type('2026-05-20 06:00');
|
||||
cy.get('.vitals-dialog input[name="temperature"]').clear().type('38.6');
|
||||
cy.get('.vitals-dialog input[name="pulse"]').clear().type('45');
|
||||
cy.get('.vitals-dialog input[name="heartRate"]').clear().type('89');
|
||||
cy.contains('保存').click();
|
||||
|
||||
// 3. 验证弹窗关闭且无报错
|
||||
cy.get('.vitals-dialog').should('not.exist');
|
||||
|
||||
// 4. 验证图表区渲染(通过检查 ECharts 容器及 tooltip 交互)
|
||||
cy.get('.temperature-chart').should('be.visible');
|
||||
cy.get('.temperature-chart canvas').should('exist');
|
||||
|
||||
// 5. 验证下方表格区数据同步
|
||||
cy.get('.vitals-table .el-table__body').should('contain', '38.6');
|
||||
cy.get('.vitals-table .el-table__body').should('contain', '45');
|
||||
cy.get('.vitals-table .el-table__body').should('contain', '89');
|
||||
|
||||
// 6. 验证时间轴对齐
|
||||
cy.get('.vitals-table .el-table__body').should('contain', '05-20 06:00');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user