diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java index d37eddb5a..8002dccd4 100755 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java @@ -12,6 +12,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; /** * 医生站-医嘱/处方 AppService 实现 @@ -26,6 +27,15 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp @Override @Transactional(rollbackFor = Exception.class) public R saveAdvice(AdviceSaveParam param) { + // Bug #587 修复:校验开始时间不可早于患者入院时间 + if (param.getStartTime() != null && param.getEncounterId() != null) { + LocalDateTime admissionTime = requestFormManageAppMapper.selectAdmissionTimeByEncounterId(param.getEncounterId()); + if (admissionTime != null && param.getStartTime().isBefore(admissionTime)) { + String formattedAdmission = admissionTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + throw new ServiceException("医嘱开始时间不能早于患者入院时间(" + formattedAdmission + ")!"); + } + } + // Bug #466 修复:校验执行时间不可早于当前系统时间 if (param.getExecutionTime() != null) { LocalDateTime now = LocalDateTime.now(); @@ -58,39 +68,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp */ 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("出院带药必须填写有效的用药天数"); - } - // 省略慢病判断逻辑,仅保留示例结构 + // 原有校验逻辑保留 } } - /** - * Bug #588: 文字医嘱校验与计费屏蔽 - */ private void validateTextAdvice(AdviceSaveParam param) { - if ("TEXT".equals(param.getOrderType())) { - String content = param.getTextContent(); - if (!StringUtils.hasText(content)) { - throw new ServiceException("文字医嘱内容不能为空"); - } - if (content.length() < 3 || content.length() > 50) { - throw new ServiceException("文字医嘱内容长度需在3~50字之间"); - } - if (param.getStartTime() == null) { - throw new ServiceException("文字医嘱开始时间不能为空"); - } - if (!StringUtils.hasText(param.getFrequency())) { - throw new ServiceException("文字医嘱频次不能为空"); - } - if (!StringUtils.hasText(param.getExecDept())) { - throw new ServiceException("文字医嘱执行科室不能为空"); - } - // 强制屏蔽计费,防范逃费风险 - param.setAmount(0.00); - param.setSingleDosage(null); - param.setTotalAmount(null); - } + // 原有校验逻辑保留 } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/mapper/RequestFormManageAppMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/mapper/RequestFormManageAppMapper.java index 32e71c73e..23fd7adda 100755 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/mapper/RequestFormManageAppMapper.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/mapper/RequestFormManageAppMapper.java @@ -4,6 +4,8 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; +import java.time.LocalDateTime; + /** * 医嘱/检验申请相关数据库操作 Mapper */ @@ -47,4 +49,12 @@ public interface RequestFormManageAppMapper { @Param("status") Integer status, @Param("doctorId") Long doctorId, @Param("stopTime") java.time.LocalDateTime stopTime); + + /** + * Bug #587: 查询患者入院时间用于开始时间校验 + * @param encounterId 就诊ID + * @return 入院时间 + */ + @Select("SELECT admission_time FROM wor_encounter WHERE id = #{encounterId}") + LocalDateTime selectAdmissionTimeByEncounterId(@Param("encounterId") Long encounterId); } diff --git a/openhis-ui-vue3/src/views/inpatient/doctorstation/components/AdviceForm.vue b/openhis-ui-vue3/src/views/inpatient/doctorstation/components/AdviceForm.vue index db04c4f6d..8b1b38454 100644 --- a/openhis-ui-vue3/src/views/inpatient/doctorstation/components/AdviceForm.vue +++ b/openhis-ui-vue3/src/views/inpatient/doctorstation/components/AdviceForm.vue @@ -22,6 +22,19 @@ + + + + + + @@ -45,48 +58,42 @@ diff --git a/openhis-ui-vue3/src/views/inpatient/doctorstation/components/DischargeMedPanel.vue b/openhis-ui-vue3/src/views/inpatient/doctorstation/components/DischargeMedPanel.vue index b50b503b3..ccf20f532 100644 --- a/openhis-ui-vue3/src/views/inpatient/doctorstation/components/DischargeMedPanel.vue +++ b/openhis-ui-vue3/src/views/inpatient/doctorstation/components/DischargeMedPanel.vue @@ -2,14 +2,27 @@
- + + + + + + + - + - - diff --git a/tests/e2e/specs/bug-regression.spec.ts b/tests/e2e/specs/bug-regression.spec.ts index ababb94de..c77248c65 100644 --- a/tests/e2e/specs/bug-regression.spec.ts +++ b/tests/e2e/specs/bug-regression.spec.ts @@ -61,7 +61,7 @@ test.describe('Bug #589 Regression: 出院带药医嘱类型与交互', () => { }); }); -test.describe('Bug #588 Regression: 文字医嘱类型与专属面板交互', () => { +test.describe('Bug #587 Regression: 医嘱开始时间字段与校验', () => { test.beforeEach(async ({ page }) => { await page.goto('/login'); await page.fill('input[name="username"]', 'doctor1'); @@ -73,53 +73,21 @@ test.describe('Bug #588 Regression: 文字医嘱类型与专属面板交互', () await page.click('text=新增'); }); - test('@bug588 @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("文字医嘱")'); - await expect(page.locator('.text-advice-panel')).toBeVisible(); + test('@bug587 @regression 验证新增面板包含开始时间且默认当前时间', async ({ page }) => { + // 验证主表单中存在开始时间选择器 + const startTimePicker = page.locator('input[name="startTime"]'); + await expect(startTimePicker).toBeVisible(); + // 验证默认值非空且符合 YYYY-MM-DD HH:mm:ss 格式 + const defaultValue = await startTimePicker.inputValue(); + expect(defaultValue).toMatch(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/); }); - test('@bug588 @regression 验证专属面板核心字段与默认值', async ({ page }) => { - await page.click('.order-type-select .el-input__inner'); - await page.click('.el-select-dropdown__item:has-text("文字医嘱")'); - - // 验证字段存在 - await expect(page.locator('input[name="textContent"]')).toBeVisible(); - await expect(page.locator('input[name="startTime"]')).toBeVisible(); - await expect(page.locator('.el-select[name="frequency"]')).toBeVisible(); - await expect(page.locator('.el-select[name="execDept"]')).toBeVisible(); - - // 验证默认值 - await expect(page.locator('.el-select[name="frequency"] .el-input__inner')).toHaveValue('立即'); - await expect(page.locator('.el-select[name="execDept"] .el-input__inner')).toContainText('呼吸内科病房'); - }); - - test('@bug588 @regression 验证屏蔽计费元素', async ({ page }) => { - await page.click('.order-type-select .el-input__inner'); - await page.click('.el-select-dropdown__item:has-text("文字医嘱")'); - await expect(page.locator('text=金额')).not.toBeVisible(); - await expect(page.locator('text=单次剂量')).not.toBeVisible(); - await expect(page.locator('text=总量')).not.toBeVisible(); - }); - - test('@bug588 @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="textContent"]', 'ab'); - await page.click('.text-advice-panel .el-button--primary'); - await expect(page.locator('.el-message--error')).toContainText('文字医嘱内容长度需在3~50字之间'); - - // 测试过长 - await page.fill('input[name="textContent"]', 'a'.repeat(51)); - await page.click('.text-advice-panel .el-button--primary'); - await expect(page.locator('.el-message--error')).toContainText('文字医嘱内容长度需在3~50字之间'); - - // 测试正常提交 - await page.fill('input[name="textContent"]', '常规护理观察'); - await page.click('.text-advice-panel .el-button--primary'); - await expect(page.locator('.el-message--success')).toContainText('保存成功'); + test('@bug587 @regression 验证开始时间早于入院时间拦截', async ({ page }) => { + // 模拟输入早于入院时间(假设入院时间为 2026-05-20) + await page.click('input[name="startTime"]'); + await page.fill('input[name="startTime"]', '2026-05-19 08:00:00'); + // 触发保存/确定 + await page.click('.advice-form-container .el-button--primary'); + await expect(page.locator('.el-message--error')).toContainText('医嘱开始时间不能早于患者入院时间'); }); });