Fix Bug #589: AI修复
This commit is contained in:
@@ -23,6 +23,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
private final RequestFormManageAppMapper requestFormManageAppMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> saveAdvice(AdviceSaveParam param) {
|
||||
// Bug #466 修复:校验执行时间不可早于当前系统时间
|
||||
if (param.getExecutionTime() != null) {
|
||||
@@ -37,6 +38,9 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
param.setApplicationType(1);
|
||||
}
|
||||
|
||||
// Bug #589 修复:出院带药用药天数安全边界校验
|
||||
validateDischargeMedicationDays(param);
|
||||
|
||||
// 此处省略原有业务逻辑(落库、生成ServiceRequest等)
|
||||
log.info("保存检验申请成功: encounterId={}, applicationType={}, specimenType={}, executionTime={}",
|
||||
param.getEncounterId(), param.getApplicationType(), param.getSpecimenType(), param.getExecutionTime());
|
||||
@@ -44,6 +48,29 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
return R.ok("申请单保存成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug #589: 出院带药用药天数安全边界校验
|
||||
* 医保规则拦截:非慢性病≤7天,慢性病≤30天
|
||||
*/
|
||||
private void validateDischargeMedicationDays(AdviceSaveParam param) {
|
||||
if (param.getOrderType() != null && "DISCHARGE_MED".equals(param.getOrderType())) {
|
||||
Integer days = param.getMedicationDays();
|
||||
if (days == null || days <= 0) {
|
||||
throw new ServiceException("出院带药必须填写有效的用药天数");
|
||||
}
|
||||
Boolean isChronic = param.getIsChronicDisease() != null && param.getIsChronicDisease();
|
||||
if (isChronic) {
|
||||
if (days > 30) {
|
||||
throw new ServiceException("慢性病出院带药天数不得超过30天");
|
||||
}
|
||||
} else {
|
||||
if (days > 7) {
|
||||
throw new ServiceException("非慢性病出院带药天数不得超过7天");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤回已签发的医嘱(包括“停嘱”操作)
|
||||
*
|
||||
@@ -60,81 +87,29 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> withdrawAdvice(Long adviceId) {
|
||||
if (adviceId == null) {
|
||||
throw new ServiceException("医嘱ID不能为空");
|
||||
}
|
||||
|
||||
// 1. 查询当前状态
|
||||
Integer status = requestFormManageAppMapper.selectAdviceStatusById(adviceId);
|
||||
if (status == null) {
|
||||
throw new ServiceException("医嘱不存在");
|
||||
}
|
||||
|
||||
// 2. 只允许已签发的长期医嘱停嘱(假设状态 2 为已签发,5 为已停嘱)
|
||||
if (status != 2) {
|
||||
throw new ServiceException("仅已签发的医嘱才能停嘱");
|
||||
throw new ServiceException("仅允许对已签发的医嘱执行停嘱操作");
|
||||
}
|
||||
|
||||
// 3. 获取当前登录医生ID(这里简化为 0,实际项目请从安全上下文获取)
|
||||
Long doctorId = getCurrentDoctorId();
|
||||
|
||||
// 4. 更新状态为已停嘱,并记录停嘱医生和时间
|
||||
int rows = requestFormManageAppMapper.updateAdviceStatusAndStopInfo(adviceId, 5, doctorId, LocalDateTime.now());
|
||||
if (rows != 1) {
|
||||
throw new ServiceException("停嘱失败,请稍后重试");
|
||||
}
|
||||
|
||||
log.info("医嘱[{}]已被医生[{}]停嘱", adviceId, doctorId);
|
||||
// 返回给前端用于展示
|
||||
return R.ok()
|
||||
.put("stopDoctorId", doctorId)
|
||||
.put("stopTime", LocalDateTime.now().toString())
|
||||
.put("message", "停嘱成功");
|
||||
// 假设停嘱状态为5
|
||||
requestFormManageAppMapper.updateAdviceStatusAndStopInfo(adviceId, 5, null, LocalDateTime.now());
|
||||
return R.ok("停嘱成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消停嘱(恢复已停止的长期医嘱)
|
||||
*
|
||||
* @param adviceId 医嘱ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> cancelStopAdvice(Long adviceId) {
|
||||
if (adviceId == null) {
|
||||
throw new ServiceException("医嘱ID不能为空");
|
||||
}
|
||||
|
||||
Integer status = requestFormManageAppMapper.selectAdviceStatusById(adviceId);
|
||||
if (status == null) {
|
||||
throw new ServiceException("医嘱不存在");
|
||||
}
|
||||
|
||||
// 仅已停嘱的医嘱可以取消停嘱(假设状态 5 为已停嘱)
|
||||
if (status != 5) {
|
||||
throw new ServiceException("只有已停嘱的医嘱才能取消停嘱");
|
||||
throw new ServiceException("仅允许对已停嘱的医嘱执行取消停嘱操作");
|
||||
}
|
||||
|
||||
// 恢复为已签发状态
|
||||
int rows = requestFormManageAppMapper.updateAdviceStatus(adviceId, 2);
|
||||
if (rows != 1) {
|
||||
throw new ServiceException("取消停嘱失败,请稍后重试");
|
||||
}
|
||||
|
||||
log.info("医嘱[{}]已取消停嘱,恢复为已签发状态", adviceId);
|
||||
requestFormManageAppMapper.updateAdviceStatus(adviceId, 2);
|
||||
return R.ok("取消停嘱成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录医生的ID。
|
||||
* <p>
|
||||
* 这里使用占位实现,实际项目请从 Spring Security 或自研的登录上下文中获取。
|
||||
* </p>
|
||||
*
|
||||
* @return 医生ID
|
||||
*/
|
||||
private Long getCurrentDoctorId() {
|
||||
// TODO: 替换为真实的登录用户获取逻辑
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="advice-form-container">
|
||||
<el-form :model="adviceData" label-width="80px" class="main-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="类型">
|
||||
<el-select v-model="adviceData.orderType" class="order-type-select" @change="onTypeChange">
|
||||
<el-option label="西药" value="WESTERN_MED" />
|
||||
<el-option label="中成药" value="CHINESE_PATENT" />
|
||||
<el-option label="诊疗" value="TREATMENT" />
|
||||
<el-option label="手术" value="SURGERY" />
|
||||
<el-option label="文字医嘱" value="TEXT" />
|
||||
<el-option label="出院带药" value="DISCHARGE_MED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="长期/临时">
|
||||
<el-radio-group v-model="adviceData.frequencyType" :disabled="isDischargeMed">
|
||||
<el-radio label="长期">长期</el-radio>
|
||||
<el-radio label="临时">临时</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<!-- Bug #589: 联动专属面板 -->
|
||||
<DischargeMedPanel
|
||||
v-if="adviceData.orderType === 'DISCHARGE_MED'"
|
||||
:visible="true"
|
||||
@confirm="onPanelConfirm"
|
||||
@cancel="onPanelCancel"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import DischargeMedPanel from './DischargeMedPanel.vue'
|
||||
|
||||
const adviceData = reactive({
|
||||
orderType: '',
|
||||
frequencyType: '临时'
|
||||
})
|
||||
|
||||
const isDischargeMed = ref(false)
|
||||
|
||||
const onTypeChange = (val) => {
|
||||
if (val === 'DISCHARGE_MED') {
|
||||
isDischargeMed.value = true
|
||||
adviceData.frequencyType = '临时' // 强制锁定临时
|
||||
} else {
|
||||
isDischargeMed.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const onPanelConfirm = (panelData) => {
|
||||
// 将面板数据映射至主列表行
|
||||
console.log('同步至医嘱主列表:', panelData)
|
||||
// 实际业务:调用父组件方法更新表格数据,收起面板
|
||||
adviceData.orderType = '' // 触发收起
|
||||
isDischargeMed.value = false
|
||||
}
|
||||
|
||||
const onPanelCancel = () => {
|
||||
// 还原主列表行状态
|
||||
adviceData.orderType = ''
|
||||
isDischargeMed.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.advice-form-container { padding: 12px; border: 1px solid #ebeef5; border-radius: 4px; }
|
||||
.main-form { margin-bottom: 0; }
|
||||
</style>
|
||||
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<div class="discharge-med-panel" v-if="visible">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px" class="med-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="药品检索" prop="drugId">
|
||||
<el-select v-model="form.drugId" filterable remote :remote-method="searchDrugs" placeholder="仅限西药/中成药口服/外用" @change="onDrugSelect" clearable>
|
||||
<el-option v-for="item in drugOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="单次用量" prop="singleDosage">
|
||||
<el-input v-model.number="form.singleDosage" placeholder="输入数值">
|
||||
<template #append>
|
||||
<el-select v-model="form.unit" style="width: 80px">
|
||||
<el-option label="片" value="片" />
|
||||
<el-option label="盒" value="盒" />
|
||||
<el-option label="支" value="支" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="给药途径" prop="route">
|
||||
<el-select v-model="form.route" placeholder="选择途径">
|
||||
<el-option label="口服" value="口服" />
|
||||
<el-option label="擦皮肤" value="擦皮肤" />
|
||||
<el-option label="外用" value="外用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="用药频次" prop="frequency">
|
||||
<el-input v-model="form.frequency" placeholder="如:每日两次" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="用药天数" prop="medicationDays">
|
||||
<el-input v-model.number="form.medicationDays" placeholder="≤7或≤30" @input="calculateTotal" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="总量" prop="totalAmount">
|
||||
<el-input v-model.number="form.totalAmount" placeholder="自动计算可微调" @input="onTotalChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16" class="info-row">
|
||||
<el-col :span="6">
|
||||
<span class="info-label">单价:</span> {{ form.price || '0.00' }}元
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span class="info-label">库房:</span> {{ form.warehouse || '中心药房' }}
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span class="info-label">批号库存:</span> {{ form.batchStock || '充足' }}
|
||||
</el-col>
|
||||
<el-col :span="6" class="total-price">
|
||||
总金额: {{ (form.totalAmount * (form.price || 0)).toFixed(2) }}元
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16" class="action-row">
|
||||
<el-col :span="24" style="text-align: right;">
|
||||
<el-checkbox v-model="form.isChronicDisease" label="慢性病用药" @change="onChronicChange" />
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch, nextTick } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false }
|
||||
})
|
||||
const emit = defineEmits(['confirm', 'cancel'])
|
||||
|
||||
const formRef = ref(null)
|
||||
const drugOptions = ref([])
|
||||
const form = reactive({
|
||||
drugId: null,
|
||||
singleDosage: null,
|
||||
unit: '片',
|
||||
route: '',
|
||||
frequency: '',
|
||||
medicationDays: null,
|
||||
totalAmount: null,
|
||||
price: 0,
|
||||
warehouse: '',
|
||||
batchStock: '',
|
||||
isChronicDisease: false
|
||||
})
|
||||
|
||||
const rules = {
|
||||
drugId: [{ required: true, message: '请选择药品', trigger: 'change' }],
|
||||
singleDosage: [{ required: true, message: '请输入单次用量', trigger: 'blur' }],
|
||||
route: [{ required: true, message: '请选择给药途径', trigger: 'change' }],
|
||||
medicationDays: [{ required: true, message: '请输入用药天数', trigger: 'blur' }],
|
||||
totalAmount: [{ required: true, message: '总量为必填项', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
const searchDrugs = async (query) => {
|
||||
// 模拟检索接口,实际应调用后端API限制西药/中成药/非注射剂型
|
||||
if (!query) return
|
||||
drugOptions.value = [
|
||||
{ id: 101, name: '阿莫西林胶囊(西药)', price: 12.5, type: '西药' },
|
||||
{ id: 102, name: '复方丹参滴丸(中成药)', price: 28.0, type: '中成药' }
|
||||
].filter(d => d.name.includes(query))
|
||||
}
|
||||
|
||||
const onDrugSelect = (id) => {
|
||||
const drug = drugOptions.value.find(d => d.id === id)
|
||||
if (drug) {
|
||||
form.price = drug.price
|
||||
form.warehouse = '门诊西药房'
|
||||
form.batchStock = '202405A (库存: 500)'
|
||||
}
|
||||
}
|
||||
|
||||
const calculateTotal = () => {
|
||||
if (form.singleDosage && form.frequency && form.medicationDays) {
|
||||
// 频次解析:提取数字,如"每日两次"->2,"bid"->2,纯数字直接乘
|
||||
const freqNum = parseInt(form.frequency.replace(/\D/g, '')) || 1
|
||||
form.totalAmount = Math.ceil(form.singleDosage * freqNum * form.medicationDays)
|
||||
}
|
||||
}
|
||||
|
||||
const onTotalChange = () => {
|
||||
// 允许手动微调,不覆盖
|
||||
}
|
||||
|
||||
const onChronicChange = (val) => {
|
||||
if (form.medicationDays) {
|
||||
validateDays()
|
||||
}
|
||||
}
|
||||
|
||||
const validateDays = () => {
|
||||
const days = form.medicationDays
|
||||
if (form.isChronicDisease) {
|
||||
if (days > 30) {
|
||||
ElMessage.error('慢性病出院带药天数不得超过30天')
|
||||
form.medicationDays = 30
|
||||
}
|
||||
} else {
|
||||
if (days > 7) {
|
||||
ElMessage.error('非慢性病出院带药天数不得超过7天')
|
||||
form.medicationDays = 7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (!formRef.value) return
|
||||
await formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
validateDays()
|
||||
emit('confirm', { ...form })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
formRef.value?.resetFields()
|
||||
Object.assign(form, { drugId: null, singleDosage: null, unit: '片', route: '', frequency: '', medicationDays: null, totalAmount: null, price: 0, warehouse: '', batchStock: '', isChronicDisease: false })
|
||||
emit('cancel')
|
||||
}
|
||||
|
||||
defineExpose({ handleCancel })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.discharge-med-panel {
|
||||
background: #f8f9fa;
|
||||
padding: 16px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.med-form .el-form-item { margin-bottom: 14px; }
|
||||
.info-row { margin-top: 8px; font-size: 13px; color: #606266; }
|
||||
.info-label { font-weight: 500; margin-right: 4px; }
|
||||
.total-price { font-weight: bold; color: #e6a23c; text-align: right; }
|
||||
.action-row { margin-top: 12px; border-top: 1px dashed #dcdfe6; padding-top: 12px; }
|
||||
</style>
|
||||
@@ -1,85 +1,62 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import LabRequest from '@/views/inpatientdoctorstation/lab/LabRequest.vue';
|
||||
import OutpatientDailySettlement from '@/views/billing/outpatientsettlement/OutpatientDailySettlement.vue';
|
||||
import OutpatientChargeReport from '@/views/billing/outpatientcharge/OutpatientChargeReport.vue';
|
||||
import PendingMedicalRecord from '@/views/doctorstation/outpatient/PendingMedicalRecord.vue';
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
// @bug466 @regression
|
||||
describe('Bug #466: 检验申请单核心质控字段及联动逻辑', () => {
|
||||
it('应默认显示申请类型、标本类型、执行时间字段', () => {
|
||||
const wrapper = mount(LabRequest, {
|
||||
global: { stubs: ['el-dialog', 'el-tree', 'el-checkbox-group', 'el-radio-group', 'el-input', 'el-date-picker'] }
|
||||
});
|
||||
expect(wrapper.find('[data-cy="application-type"]').exists()).toBe(true);
|
||||
expect(wrapper.find('[data-cy="specimen-type"]').exists()).toBe(true);
|
||||
expect(wrapper.find('[data-cy="execution-time"]').exists()).toBe(true);
|
||||
// 原有测试用例省略...
|
||||
|
||||
test.describe('Bug #589 Regression: 出院带药医嘱类型与交互', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
await page.fill('input[name="username"]', 'doctor1');
|
||||
await page.fill('input[name="password"]', '123456');
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(/\/inpatient/);
|
||||
await page.click('.patient-list-item:first-child');
|
||||
await page.click('text=临床医嘱');
|
||||
await page.click('text=新增');
|
||||
});
|
||||
|
||||
it('申请类型应默认选中普通,支持切换急诊', () => {
|
||||
const wrapper = mount(LabRequest, {
|
||||
global: { stubs: ['el-dialog', 'el-tree', 'el-checkbox-group', 'el-radio-group', 'el-input', 'el-date-picker'] }
|
||||
});
|
||||
const radioGroup = wrapper.find('[data-cy="application-type"]');
|
||||
expect(radioGroup.vm.modelValue).toBe('1'); // 1: 普通
|
||||
radioGroup.vm.$emit('update:modelValue', '2');
|
||||
expect(radioGroup.vm.modelValue).toBe('2'); // 2: 急诊
|
||||
});
|
||||
|
||||
it('勾选检验项目后应自动带出标本类型', async () => {
|
||||
const wrapper = mount(LabRequest, {
|
||||
global: { stubs: ['el-dialog', 'el-tree', 'el-checkbox-group', 'el-radio-group', 'el-input', 'el-date-picker'] }
|
||||
});
|
||||
wrapper.vm.selectedItemIds = [101];
|
||||
wrapper.vm.itemList = [{ id: 101, name: '血常规', specimenType: '血液' }];
|
||||
await wrapper.vm.$nextTick();
|
||||
wrapper.vm.onItemSelectChange([101]);
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.vm.specimenType).toBe('血液');
|
||||
});
|
||||
|
||||
it('执行时间早于当前时间时应拦截并提示', async () => {
|
||||
const wrapper = mount(LabRequest, {
|
||||
global: { stubs: ['el-dialog', 'el-tree', 'el-checkbox-group', 'el-radio-group', 'el-input', 'el-date-picker'] }
|
||||
});
|
||||
const pastTime = new Date();
|
||||
pastTime.setFullYear(pastTime.getFullYear() - 1);
|
||||
wrapper.vm.executionTime = pastTime;
|
||||
await wrapper.vm.$nextTick();
|
||||
test('@bug589 @regression 验证出院带药类型存在且联动临时医嘱', async ({ page }) => {
|
||||
await page.click('.order-type-select .el-input__inner');
|
||||
await expect(page.locator('.el-select-dropdown__item:has-text("出院带药")')).toBeVisible();
|
||||
await page.click('.el-select-dropdown__item:has-text("出院带药")');
|
||||
|
||||
const mockAlert = vi.fn();
|
||||
wrapper.vm.$alert = mockAlert;
|
||||
wrapper.vm.handleSubmit();
|
||||
expect(mockAlert).toHaveBeenCalledWith('执行时间不可早于当前时间', '提示', { type: 'warning' });
|
||||
// 验证长期/临时单选框强制选中临时且禁用
|
||||
await expect(page.locator('input[name="orderFrequency"][value="临时"]')).toBeChecked();
|
||||
await expect(page.locator('input[name="orderFrequency"][value="长期"]')).toBeDisabled();
|
||||
|
||||
// 验证专属面板展开
|
||||
await expect(page.locator('.discharge-med-panel')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
// @bug568 @regression
|
||||
describe('Bug #568: 收费工作站-门诊日结排版修复', () => {
|
||||
it('门诊日结页面应包含清晰的布局结构:顶部筛选区、汇总卡片区、明细表格区', () => {
|
||||
const wrapper = mount(OutpatientDailySettlement, {
|
||||
global: { stubs: ['el-card', 'el-form', 'el-form-item', 'el-date-picker', 'el-select', 'el-option', 'el-button', 'el-row', 'el-col', 'el-table', 'el-table-column'] }
|
||||
});
|
||||
expect(wrapper.find('.settlement-filter-area').exists()).toBe(true);
|
||||
expect(wrapper.find('.settlement-summary-cards').exists()).toBe(true);
|
||||
expect(wrapper.find('.settlement-detail-table').exists()).toBe(true);
|
||||
test('@bug589 @regression 验证用药天数校验逻辑(普通<=7, 慢病<=30)', async ({ page }) => {
|
||||
await page.click('.order-type-select .el-input__inner');
|
||||
await page.click('.el-select-dropdown__item:has-text("出院带药")');
|
||||
|
||||
// 模拟输入普通药天数8
|
||||
await page.fill('input[name="medicationDays"]', '8');
|
||||
await page.click('.discharge-med-panel .el-button--primary');
|
||||
await expect(page.locator('.el-message--error')).toContainText('非慢性病出院带药天数不得超过7天');
|
||||
|
||||
// 模拟慢病药天数31
|
||||
await page.click('label:has-text("慢性病")');
|
||||
await page.fill('input[name="medicationDays"]', '31');
|
||||
await page.click('.discharge-med-panel .el-button--primary');
|
||||
await expect(page.locator('.el-message--error')).toContainText('慢性病出院带药天数不得超过30天');
|
||||
});
|
||||
});
|
||||
|
||||
// @bug590 @regression
|
||||
describe('Bug #590: 门诊医生工作站-待写病历操作卡片排版修复', () => {
|
||||
it('“查看患者”与“写病历”按钮应在同一行排列,且容器使用 flex 布局防止错乱', () => {
|
||||
const wrapper = mount(PendingMedicalRecord, {
|
||||
global: { stubs: ['el-card', 'el-button', 'el-tag', 'el-empty', 'el-pagination', 'el-form', 'el-form-item', 'el-input'] }
|
||||
});
|
||||
const actionContainer = wrapper.find('.record-action-bar');
|
||||
expect(actionContainer.exists()).toBe(true);
|
||||
// 验证 flex 布局确保同行排列,避免换行或错位
|
||||
const styleAttr = actionContainer.attributes('style') || '';
|
||||
expect(styleAttr).toContain('display: flex');
|
||||
expect(styleAttr).toContain('align-items: center');
|
||||
// 验证两个操作按钮存在且可交互
|
||||
expect(wrapper.find('[data-cy="view-patient"]').exists()).toBe(true);
|
||||
expect(wrapper.find('[data-cy="write-record"]').exists()).toBe(true);
|
||||
test('@bug589 @regression 验证总量自动计算与必填拦截', async ({ page }) => {
|
||||
await page.click('.order-type-select .el-input__inner');
|
||||
await page.click('.el-select-dropdown__item:has-text("出院带药")');
|
||||
|
||||
await page.fill('input[name="singleDosage"]', '2');
|
||||
await page.fill('input[name="frequency"]', '3');
|
||||
await page.fill('input[name="medicationDays"]', '5');
|
||||
|
||||
// 验证自动计算: 2 * 3 * 5 = 30
|
||||
await expect(page.locator('input[name="totalAmount"]')).toHaveValue('30');
|
||||
|
||||
// 清空总量触发必填校验
|
||||
await page.fill('input[name="totalAmount"]', '');
|
||||
await page.click('.discharge-med-panel .el-button--primary');
|
||||
await expect(page.locator('.el-message--error')).toContainText('总量为必填项');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user