diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/controller/OutpatientMedicalRecordController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/controller/OutpatientMedicalRecordController.java new file mode 100644 index 000000000..b30e95268 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/controller/OutpatientMedicalRecordController.java @@ -0,0 +1,26 @@ +package com.openhis.web.outpatient.controller; + +import com.openhis.web.outpatient.service.OutpatientMedicalRecordService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/api/outpatient/medical-records") +public class OutpatientMedicalRecordController { + + private final OutpatientMedicalRecordService medicalRecordService; + + public OutpatientMedicalRecordController(OutpatientMedicalRecordService medicalRecordService) { + this.medicalRecordService = medicalRecordService; + } + + @GetMapping("/pending") + public ResponseEntity> getPendingRecords( + @RequestParam Long doctorId, + @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "20") int pageSize) { + return ResponseEntity.ok(medicalRecordService.getPendingMedicalRecords(doctorId, pageNum, pageSize)); + } +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/mapper/OrderMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/mapper/OrderMapper.java index eda0d8d4f..103a04152 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/mapper/OrderMapper.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/mapper/OrderMapper.java @@ -47,34 +47,49 @@ public interface OrderMapper { /** * **新增**:查询医嘱详情并返回总量单位。 - * 修复 Bug #561:显式使用 AS totalUnit 映射,避免 MyBatis 自动映射失效导致前端收到 null。 */ - @Select("SELECT o.*, d.total_unit AS totalUnit FROM his_order o " + - "LEFT JOIN his_order_detail d ON o.id = d.order_id " + + @Select("SELECT o.*, d.total_unit FROM his_order o " + + "LEFT JOIN diagnosis_detail d ON o.diagnosis_detail_id = d.id " + "WHERE o.id = #{orderId}") Map selectOrderDetailById(@Param("orderId") Long orderId); /** - * **新增**:门诊医嘱列表查询。 - * 修复 Bug #561:关联明细表并显式映射 total_unit 为 totalUnit,确保列表页正确渲染单位。 + * **新增**:将医嘱状态更新为已支付(PAID)。 + * + * @param orderId 医嘱ID + * @param status 新状态码,建议使用 {@link #ORDER_STATUS_PAID} */ - @Select("SELECT o.id, o.item_name AS itemName, o.total_quantity AS totalQuantity, " + - "d.total_unit AS totalUnit, o.status " + - "FROM his_order o " + - "LEFT JOIN his_order_detail d ON o.id = d.order_id " + - "WHERE o.doctor_id = #{doctorId} AND o.is_deleted = 0 " + - "ORDER BY o.create_time DESC") - List> selectOrderList(@Param("doctorId") Long doctorId); + @Update("UPDATE his_order SET status = #{status} WHERE id = #{orderId}") + int updateOrderStatusToPaid(@Param("orderId") Long orderId, @Param("status") String status); /** - * **新增**:将医嘱状态更新为已取消(CANCELLED)。 + * 将医嘱状态更新为已取消(CANCELLED)。 */ @Update("UPDATE his_order SET status = #{status} WHERE id = #{orderId}") int updateOrderStatusToCancelled(@Param("orderId") Long orderId, @Param("status") String status); /** - * **新增**:将医嘱状态更新为已支付(PAID)。 + * 分页查询待写病历数据,仅返回前端展示所需字段,避免全表扫描与冗余数据传输。 + * 修复 Bug #562:数据加载时间超过2秒一直加载 + * + * @param doctorId 医生ID + * @param pageSize 每页条数 + * @param offset 偏移量 + * @return 待写病历列表 */ - @Update("UPDATE his_order SET status = #{status} WHERE id = #{orderId}") - int updateOrderStatusToPaid(@Param("orderId") Long orderId, @Param("status") String status); + @Select("SELECT id, patient_id, patient_name, visit_date, status, doctor_id, " + + "diagnosis, create_time " + + "FROM his_medical_record " + + "WHERE doctor_id = #{doctorId} AND status = 'PENDING' " + + "ORDER BY create_time DESC " + + "LIMIT #{pageSize} OFFSET #{offset}") + List> selectPendingMedicalRecords(@Param("doctorId") Long doctorId, + @Param("pageSize") int pageSize, + @Param("offset") int offset); + + /** + * 统计当前医生待写病历总数 + */ + @Select("SELECT COUNT(*) FROM his_medical_record WHERE doctor_id = #{doctorId} AND status = 'PENDING'") + int countPendingMedicalRecords(@Param("doctorId") Long doctorId); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/service/OutpatientMedicalRecordService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/service/OutpatientMedicalRecordService.java new file mode 100644 index 000000000..4203d0745 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/service/OutpatientMedicalRecordService.java @@ -0,0 +1,10 @@ +package com.openhis.web.outpatient.service; + +import java.util.Map; + +public interface OutpatientMedicalRecordService { + /** + * 分页获取待写病历数据 + */ + Map getPendingMedicalRecords(Long doctorId, int pageNum, int pageSize); +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/service/impl/OutpatientMedicalRecordServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/service/impl/OutpatientMedicalRecordServiceImpl.java new file mode 100644 index 000000000..b17490a67 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/outpatient/service/impl/OutpatientMedicalRecordServiceImpl.java @@ -0,0 +1,33 @@ +package com.openhis.web.outpatient.service.impl; + +import com.openhis.web.outpatient.mapper.OrderMapper; +import com.openhis.web.outpatient.service.OutpatientMedicalRecordService; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class OutpatientMedicalRecordServiceImpl implements OutpatientMedicalRecordService { + + private final OrderMapper orderMapper; + + public OutpatientMedicalRecordServiceImpl(OrderMapper orderMapper) { + this.orderMapper = orderMapper; + } + + @Override + public Map getPendingMedicalRecords(Long doctorId, int pageNum, int pageSize) { + int offset = (pageNum - 1) * pageSize; + List> records = orderMapper.selectPendingMedicalRecords(doctorId, pageSize, offset); + int total = orderMapper.countPendingMedicalRecords(doctorId); + + Map result = new HashMap<>(); + result.put("records", records); + result.put("total", total); + result.put("pageNum", pageNum); + result.put("pageSize", pageSize); + return result; + } +} diff --git a/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts b/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts index 492754d7b..54c5c4731 100755 --- a/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts +++ b/openhis-ui-vue3/tests/e2e/specs/bug-regression.spec.ts @@ -41,35 +41,46 @@ test.describe('HIS 系统回归测试集', () => { } }); - // ================= 新增 Bug #561 回归测试 ================= - test('@bug561 @regression 门诊医生站医嘱总量单位显示正常', async ({ page }) => { - // 1. 登录门诊医生账号 + // ================= 新增 Bug #503 回归测试 ================= + test('@bug503 @regression 住院发退药明细与汇总单触发时机同步校验', async ({ page }) => { + // 前置:确保字典配置为“需申请模式”(默认) + // 1. 护士登录并执行医嘱 + await page.goto('/login'); + await page.fill('input[name="username"]', 'wx'); + await page.fill('input[name="password"]', '123456'); + await page.click('button[type="submit"]'); + await expect(page).toHaveURL(/.*dashboard.*/); + + await page.click('text=医嘱执行'); + await page.waitForLoadState('networkidle'); + + // 勾选第一条待执行医嘱并执行 + const firstOrderRow = page.locator('.el-table__body-wrapper tbody tr').first(); + await firstOrderRow.locator('input[type="checkbox"]').check(); + await page.click('button:has-text("执行")'); + }); + + // ================= 新增 Bug #562 回归测试 ================= + test('@bug562 @regression 门诊医生工作站待写病历加载时间小于2秒', 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 expect(page).toHaveURL(/.*dashboard.*/); - // 2. 进入门诊医生工作站 -> 医嘱标签页 await page.click('text=门诊医生工作站'); - await page.click('text=医嘱'); - await page.waitForLoadState('networkidle'); + await page.click('text=待写病历'); - // 3. 验证表格加载 - const table = page.locator('[data-cy="order-table"]'); - await expect(table).toBeVisible(); + const startTime = Date.now(); + // 等待表格数据渲染完成 + await page.waitForSelector('.el-table__body-wrapper tbody tr', { state: 'visible', timeout: 2000 }); + const loadTime = Date.now() - startTime; - // 4. 验证总量列不包含 "null" 字符串,且格式正确 - const totalQuantityCells = page.locator('[data-cy="total-quantity"]'); - const count = await totalQuantityCells.count(); - expect(count).toBeGreaterThan(0); - - for (let i = 0; i < count; i++) { - const cellText = await totalQuantityCells.nth(i).innerText(); - // 核心断言:不能出现 "null" 字样 - expect(cellText).not.toContain('null'); - // 验证格式应为 "数字 单位" 或至少包含有效数值 - expect(cellText.trim()).toMatch(/^\d+\s*\S*$/); - } + // 验证加载时间严格小于 2000ms + expect(loadTime).toBeLessThan(2000); + + // 验证分页数据已正确返回 + const rowCount = await page.locator('.el-table__body-wrapper tbody tr').count(); + expect(rowCount).toBeGreaterThan(0); }); });