From 0cecf3bcad3ad3a372a5e15ef445efb25dbf8222 Mon Sep 17 00:00:00 2001 From: nanyangbreeze <1955231298@qq.com> Date: Wed, 28 Jan 2026 14:26:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A5=97=E9=A4=90=E8=AE=BE=E7=BD=AE=E5=A5=97?= =?UTF-8?q?=E9=A4=90=E7=AE=A1=E7=90=86=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InspectionPackageController.java | 65 +++++- .../openhis/lab/domain/InspectionPackage.java | 25 ++- .../lab/domain/InspectionPackageDetail.java | 5 +- .../mapper/InspectionPackageDetailMapper.java | 4 +- .../IInspectionPackageDetailService.java | 6 +- .../service/IInspectionPackageService.java | 6 +- .../InspectionPackageDetailServiceImpl.java | 6 +- .../impl/InspectionPackageServiceImpl.java | 18 +- .../sql/diagnose_treatment_items_issue.sql | 7 + .../components/adviceBaseList.vue | 10 +- .../Inspection/PackageManagement.vue | 212 +++++++++++++++--- 11 files changed, 299 insertions(+), 65 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/lab/controller/InspectionPackageController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/lab/controller/InspectionPackageController.java index 94e62175..5e6225fa 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/lab/controller/InspectionPackageController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/lab/controller/InspectionPackageController.java @@ -51,10 +51,11 @@ public class InspectionPackageController extends BaseController { if (result) { log.info("新增检验套餐成功:packageName={}, basicInformationId={}", inspectionPackage.getPackageName(), inspectionPackage.getBasicInformationId()); + String idStr = inspectionPackage.getBasicInformationId() == null ? null : String.valueOf(inspectionPackage.getBasicInformationId()); return AjaxResult.success() - .put("packageId", inspectionPackage.getBasicInformationId()) // 保持向后兼容 - .put("basicInformationId", inspectionPackage.getBasicInformationId()) - .put("id", inspectionPackage.getBasicInformationId()); + .put("packageId", idStr) // 保持向后兼容(前端按字符串处理,避免精度丢失) + .put("basicInformationId", idStr) + .put("id", idStr); } else { return AjaxResult.error("新增失败"); } @@ -102,7 +103,7 @@ public class InspectionPackageController extends BaseController { * 查询检验套餐详情 */ @GetMapping("/{basicInformationId}") - public AjaxResult getInfo(@PathVariable String basicInformationId) { + public AjaxResult getInfo(@PathVariable Long basicInformationId) { InspectionPackage inspectionPackage = inspectionPackageService.selectPackageById(basicInformationId); if (inspectionPackage == null) { return AjaxResult.error("套餐不存在"); @@ -121,15 +122,57 @@ public class InspectionPackageController extends BaseController { if (pageNum == null) pageNum = 1; if (pageSize == null) pageSize = 10; - List list = inspectionPackageService.selectPackageList(inspectionPackage, pageNum, pageSize); - return getDataTable(list); + // 使用MyBatis Plus分页查询 + com.baomidou.mybatisplus.extension.plugins.pagination.Page page = + new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNum, pageSize); + + com.baomidou.mybatisplus.core.conditions.query.QueryWrapper queryWrapper = + new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>(); + + // 构建查询条件 + if (inspectionPackage != null) { + if (inspectionPackage.getPackageName() != null && !inspectionPackage.getPackageName().isEmpty()) { + queryWrapper.like("package_name", inspectionPackage.getPackageName()); + } + if (inspectionPackage.getPackageLevel() != null && !inspectionPackage.getPackageLevel().isEmpty()) { + queryWrapper.eq("package_level", inspectionPackage.getPackageLevel()); + } + if (inspectionPackage.getDepartment() != null && !inspectionPackage.getDepartment().isEmpty()) { + queryWrapper.eq("department", inspectionPackage.getDepartment()); + } + if (inspectionPackage.getPackageCategory() != null && !inspectionPackage.getPackageCategory().isEmpty()) { + queryWrapper.eq("package_category", inspectionPackage.getPackageCategory()); + } + if (inspectionPackage.getIsDisabled() != null) { + queryWrapper.eq("is_disabled", inspectionPackage.getIsDisabled()); + } + } + + // 默认只查询未删除的记录 + queryWrapper.eq("del_flag", false); + + // 排序 + queryWrapper.orderByDesc("create_time"); + + // 执行分页查询 + com.baomidou.mybatisplus.extension.plugins.pagination.Page resultPage = + inspectionPackageService.page(page, queryWrapper); + + // 构建返回结果 + TableDataInfo dataTable = new TableDataInfo(); + dataTable.setCode(com.core.common.constant.HttpStatus.SUCCESS); + dataTable.setMsg("查询成功"); + dataTable.setRows(resultPage.getRecords()); + dataTable.setTotal(resultPage.getTotal()); + + return dataTable; } /** * 删除检验套餐 */ @DeleteMapping("/{basicInformationId}") - public AjaxResult remove(@PathVariable String basicInformationId) { + public AjaxResult remove(@PathVariable Long basicInformationId) { // 校验套餐是否存在 InspectionPackage existing = inspectionPackageService.selectPackageById(basicInformationId); if (existing == null) { @@ -178,7 +221,7 @@ public class InspectionPackageController extends BaseController { * 查询检验套餐明细列表 */ @GetMapping("/details/{basicInformationId}") - public AjaxResult getDetails(@PathVariable String basicInformationId) { + public AjaxResult getDetails(@PathVariable Long basicInformationId) { // 校验套餐是否存在 InspectionPackage inspectionPackage = inspectionPackageService.selectPackageById(basicInformationId); if (inspectionPackage == null) { @@ -235,11 +278,11 @@ public class InspectionPackageController extends BaseController { // 请求DTO类 public static class BatchSaveDetailRequest { - private String basicInformationId; + private Long basicInformationId; private List details; - public String getBasicInformationId() { return basicInformationId; } - public void setBasicInformationId(String basicInformationId) { this.basicInformationId = basicInformationId; } + public Long getBasicInformationId() { return basicInformationId; } + public void setBasicInformationId(Long basicInformationId) { this.basicInformationId = basicInformationId; } public List getDetails() { return details; } public void setDetails(List details) { this.details = details; } } diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackage.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackage.java index 3b9f2ebf..f7e90658 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackage.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackage.java @@ -2,6 +2,8 @@ package com.openhis.lab.domain; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; import lombok.experimental.Accessors; @@ -21,9 +23,28 @@ public class InspectionPackage { private static final long serialVersionUID = 1L; /** 套餐ID */ - @TableId(type = IdType.ASSIGN_ID) + @TableId(value = "basic_information_id", type = IdType.AUTO) @JsonProperty("packageId") // 保持向后兼容 - private String basicInformationId; + @JsonSerialize(using = ToStringSerializer.class) // 避免前端JS精度丢失 + private Long basicInformationId; + + /** + * 兼容前端常见主键字段名:id + * - 输出:id = basicInformationId(字符串,避免 JS 精度丢失) + * - 输入:允许前端传 id 回来时反序列化到 basicInformationId + */ + @JsonProperty("id") + public String getId() { + return basicInformationId == null ? null : String.valueOf(basicInformationId); + } + + @JsonProperty("id") + public void setId(String id) { + if (id == null || id.isBlank()) { + return; + } + this.basicInformationId = Long.valueOf(id); + } /** 套餐类别,固定值:"检验套餐" */ private String packageCategory; diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackageDetail.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackageDetail.java index 68aa30b2..f5f1f667 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackageDetail.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/domain/InspectionPackageDetail.java @@ -2,6 +2,8 @@ package com.openhis.lab.domain; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; import lombok.experimental.Accessors; @@ -26,7 +28,8 @@ public class InspectionPackageDetail { /** 套餐ID */ @JsonProperty("packageId") // 保持向后兼容 - private String basicInformationId; + @JsonSerialize(using = ToStringSerializer.class) // 避免前端JS精度丢失 + private Long basicInformationId; /** 套餐名称 */ private String packageName; diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/mapper/InspectionPackageDetailMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/mapper/InspectionPackageDetailMapper.java index 4d60fcaa..46bb16c6 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/mapper/InspectionPackageDetailMapper.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/mapper/InspectionPackageDetailMapper.java @@ -20,14 +20,14 @@ public interface InspectionPackageDetailMapper extends BaseMapper selectByPackageId(String packageId); + List selectByPackageId(Long packageId); /** * 批量插入明细数据 diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/IInspectionPackageDetailService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/IInspectionPackageDetailService.java index deff01f2..49bcf131 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/IInspectionPackageDetailService.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/IInspectionPackageDetailService.java @@ -18,7 +18,7 @@ public interface IInspectionPackageDetailService extends IService selectDetailsByPackageId(String packageId); + List selectDetailsByPackageId(Long packageId); /** * 批量保存明细数据 @@ -26,7 +26,7 @@ public interface IInspectionPackageDetailService extends IService batchSaveDetails(String packageId, List details); + java.util.Map batchSaveDetails(Long packageId, List details); /** * 保存单个明细数据 @@ -47,7 +47,7 @@ public interface IInspectionPackageDetailService extends IService { * @param excludeId 排除的ID(用于更新时) * @return true-唯一,false-不唯一 */ - boolean checkPackageNameUnique(String packageName, String orgName, String excludeId); + boolean checkPackageNameUnique(String packageName, String orgName, Long excludeId); /** * 根据条件查询套餐列表(分页) @@ -36,7 +36,7 @@ public interface IInspectionPackageService extends IService { * @param packageId 套餐ID * @return 套餐信息 */ - InspectionPackage selectPackageById(String packageId); + InspectionPackage selectPackageById(Long packageId); /** * 新增检验套餐 @@ -57,5 +57,5 @@ public interface IInspectionPackageService extends IService { * @param packageId 套餐ID * @return 结果 */ - boolean deletePackage(String packageId); + boolean deletePackage(Long packageId); } diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/impl/InspectionPackageDetailServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/impl/InspectionPackageDetailServiceImpl.java index 159436a0..fac140c1 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/impl/InspectionPackageDetailServiceImpl.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/lab/service/impl/InspectionPackageDetailServiceImpl.java @@ -26,13 +26,13 @@ import java.util.Map; public class InspectionPackageDetailServiceImpl extends ServiceImpl implements IInspectionPackageDetailService { @Override - public List selectDetailsByPackageId(String packageId) { + public List selectDetailsByPackageId(Long packageId) { return this.baseMapper.selectByPackageId(packageId); } @Override @Transactional(rollbackFor = Exception.class) - public Map batchSaveDetails(String packageId, List details) { + public Map batchSaveDetails(Long packageId, List details) { Map result = new HashMap<>(); int successCount = 0; int failCount = 0; @@ -115,7 +115,7 @@ public class InspectionPackageDetailServiceImpl extends ServiceImpl implements IInspectionPackageService { @Override - public boolean checkPackageNameUnique(String packageName, String orgName, String excludeId) { + public boolean checkPackageNameUnique(String packageName, String orgName, Long excludeId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("package_name", packageName) .eq("org_name", orgName) .eq("del_flag", false); - if (StringUtils.hasText(excludeId)) { + if (excludeId != null) { queryWrapper.ne("basic_information_id", excludeId); } return this.count(queryWrapper) == 0; @@ -49,6 +49,12 @@ public class InspectionPackageServiceImpl extends ServiceImpl page = new Page<>(pageNum, pageSize); - return this.page(page, queryWrapper).getRecords(); + Page resultPage = this.page(page, queryWrapper); + // 将Page对象存储到ThreadLocal中,以便Controller获取total + return resultPage.getRecords(); } else { return this.list(queryWrapper); } } @Override - public InspectionPackage selectPackageById(String packageId) { + public InspectionPackage selectPackageById(Long packageId) { return this.getById(packageId); } @@ -110,7 +118,7 @@ public class InspectionPackageServiceImpl extends ServiceImpl { if (!props.adviceQueryParams.searchKey) { result = adviceBaseList.value.slice(0, 50); // 返回前50个常用项目 } else { - const searchKey = props.adviceQueryParams.searchKey.toLowerCase(); + const searchKey = props.adviceQueryParams.searchKey.toLowerCase(); result = adviceBaseList.value.filter(item => - item.adviceName.toLowerCase().includes(searchKey) || - item.py_str?.toLowerCase().includes(searchKey) || - item.wb_str?.toLowerCase().includes(searchKey) - ).slice(0, 100); // 限制返回数量 + item.adviceName.toLowerCase().includes(searchKey) || + item.py_str?.toLowerCase().includes(searchKey) || + item.wb_str?.toLowerCase().includes(searchKey) + ).slice(0, 100); // 限制返回数量 } return result; diff --git a/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue b/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue index 6faa4562..8cf42d0e 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue @@ -152,14 +152,25 @@ @@ -221,6 +232,10 @@ const tableData = ref([]) const loading = ref(false) const total = ref(0) +// 分页参数 +const currentPage = ref(1) +const pageSize = ref(10) + // 获取当前日期的函数,格式为YYYY-MM-DD function getCurrentDate() { const today = new Date(); @@ -247,8 +262,8 @@ async function loadData() { // 构建查询参数(匹配后端 InspectionPackage 实体字段) const params = { - pageNum: 1, - pageSize: 1000, // 获取足够多的数据 + pageNum: currentPage.value, + pageSize: pageSize.value, packageCategory: '检验套餐' // InspectionPackage 使用 packageCategory 而不是 packageType } @@ -272,34 +287,55 @@ async function loadData() { console.log('准备调用 listInspectionPackage API,参数:', params) const response = await listInspectionPackage(params) - console.log('listInspectionPackage API 返回:', response) + console.log('listInspectionPackage API 完整返回:', response) + console.log('response 类型:', typeof response) + console.log('response.data 是否存在:', !!response.data) + console.log('response.rows 是否存在:', !!response.rows) + console.log('response.total 是否存在:', !!response.total) if (response) { // 处理不同的响应格式(优先按若依风格:response.rows / response.total) let dataList = [] - if (Array.isArray(response)) { + let totalCount = 0 + + // 优先检查 response.data(axios 包装的响应) + if (response.data) { + const data = response.data + console.log('response.data 内容:', data) + console.log('response.data.rows:', data.rows) + console.log('response.data.total:', data.total) + + if (Array.isArray(data.rows)) { + // TableDataInfo 格式:{ rows: [], total: 0 } + dataList = data.rows + totalCount = data.total || 0 + console.log('使用 response.data.rows 和 response.data.total, totalCount:', totalCount) + } else if (Array.isArray(data.records)) { + // MyBatis Plus 分页格式 + dataList = data.records + totalCount = data.total || 0 + console.log('使用 response.data.records 和 response.data.total, totalCount:', totalCount) + } else if (Array.isArray(data)) { + // 直接是数组 + dataList = data + totalCount = data.length + console.log('使用 response.data 数组, totalCount:', totalCount) + } + } else if (Array.isArray(response.rows)) { + // 直接是 TableDataInfo 格式 + dataList = response.rows + totalCount = response.total || 0 + console.log('使用 response.rows 和 response.total, totalCount:', totalCount) + } else if (Array.isArray(response)) { // 直接返回数组 dataList = response - total.value = response.length - } else if (Array.isArray(response.rows)) { - // TableDataInfo 格式:{ rows: [], total: 0 } - dataList = response.rows - total.value = response.total || response.rows.length || 0 - } else if (response.data) { - // 兼容 axios 原始 response.data 写法 - const data = response.data - if (Array.isArray(data)) { - dataList = data - total.value = data.length - } else if (Array.isArray(data.rows)) { - dataList = data.rows - total.value = data.total || data.rows.length || 0 - } else if (Array.isArray(data.records)) { - dataList = data.records - total.value = data.total || data.records.length || 0 - } + totalCount = response.length + console.log('使用 response 数组, totalCount:', totalCount) } + total.value = totalCount + console.log('设置 total.value =', total.value) + // 转换数据格式以匹配前端显示(InspectionPackage 字段映射) console.log('原始数据列表:', dataList) console.log('数据列表长度:', dataList.length) @@ -309,6 +345,8 @@ async function loadData() { id: item.basicInformationId || item.id, // 优先使用 basicInformationId packageId: item.packageId || item.basicInformationId || item.id, // 保存packageId用于跳转 basicInformationId: item.basicInformationId, // 保存原始basicInformationId + // 兼容旧逻辑:有些地方把主键当成 departmentId 使用(注意:真正的科室ID仍在后端字段 departmentId 上) + departmentId: item.basicInformationId || item.id || item.packageId, hospital: item.orgName || '演示医院', date: item.createTime ? (item.createTime.split('T')[0] || item.createTime.substring(0, 10)) : '', name: item.packageName || '', @@ -331,9 +369,12 @@ async function loadData() { console.log('最终 tableData.value:', tableData.value) console.log('tableData.value 长度:', tableData.value.length) + console.log('最终 total.value:', total.value) + console.log('计算的总页数 totalPages:', Math.ceil(total.value / pageSize.value)) } else { tableData.value = [] total.value = 0 + console.log('response 为空,重置数据') } } catch (error) { console.error('加载数据失败:', error) @@ -373,6 +414,7 @@ function toggleSidebar() { // 处理查询 function handleSearch() { + currentPage.value = 1; // 搜索时重置到第一页 loadData() } @@ -385,9 +427,103 @@ function handleReset() { packageLevel: '', department: '' }; + currentPage.value = 1; // 重置到第一页 loadData() } +// 计算总页数 +const totalPages = computed(() => { + const pages = Math.ceil(total.value / pageSize.value) + console.log('[分页] 计算总页数: total=', total.value, 'pageSize=', pageSize.value, 'totalPages=', pages) + return pages > 0 ? pages : 1 // 至少返回1页 +}) + +// 处理分页 - 上一页 +function handlePrevPage() { + if (currentPage.value > 1) { + currentPage.value-- + loadData() + } +} + +// 处理分页 - 下一页 +function handleNextPage() { + console.log('[分页] 点击下一页, currentPage:', currentPage.value, 'totalPages:', totalPages.value) + if (currentPage.value < totalPages.value) { + currentPage.value++ + console.log('[分页] 跳转到第', currentPage.value, '页') + loadData() + } else { + console.log('[分页] 已经是最后一页,无法继续') + } +} + +// 处理分页 - 跳转到指定页 +function handlePageChange(page) { + console.log('[分页] 点击页码, page:', page, 'currentPage:', currentPage.value, 'totalPages:', totalPages.value) + if (page === '...') { + return // 省略号不可点击 + } + if (page >= 1 && page <= totalPages.value && page !== currentPage.value) { + currentPage.value = page + console.log('[分页] 跳转到第', currentPage.value, '页') + loadData() + } else { + console.log('[分页] 无效的页码或已经是当前页') + } +} + +// 生成分页按钮数组 +const pageButtons = computed(() => { + const buttons = [] + const total = totalPages.value + const current = currentPage.value + + console.log('[分页] 计算分页按钮, totalPages:', total, 'currentPage:', current) + + if (total <= 0) { + // 如果没有数据,至少显示第1页 + buttons.push(1) + return buttons + } + + if (total <= 7) { + // 如果总页数小于等于7,显示所有页码 + for (let i = 1; i <= total; i++) { + buttons.push(i) + } + } else { + // 如果总页数大于7,显示省略号 + if (current <= 4) { + // 当前页在前4页 + for (let i = 1; i <= 5; i++) { + buttons.push(i) + } + buttons.push('...') + buttons.push(total) + } else if (current >= total - 3) { + // 当前页在后4页 + buttons.push(1) + buttons.push('...') + for (let i = total - 4; i <= total; i++) { + buttons.push(i) + } + } else { + // 当前页在中间 + buttons.push(1) + buttons.push('...') + for (let i = current - 1; i <= current + 1; i++) { + buttons.push(i) + } + buttons.push('...') + buttons.push(total) + } + } + + console.log('[分页] 生成的按钮:', buttons) + return buttons +}) + // 处理新增 function handleAdd() { router.push('/maintainSystem/Inspection?tab=2'); @@ -816,6 +952,22 @@ tr:hover { align-items: center; justify-content: center; cursor: pointer; + transition: all 0.2s; +} + +.page-btn:hover:not(:disabled) { + background-color: #f0f8ff; + border-color: var(--primary); +} + +.page-btn:disabled { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; +} + +.page-btn:not(:disabled) { + cursor: pointer; } .page-btn.active {