diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPackageAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPackageAppService.java new file mode 100644 index 00000000..1edad70b --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPackageAppService.java @@ -0,0 +1,48 @@ +package com.openhis.web.check.appservice; + +import com.core.common.core.domain.R; +import com.openhis.web.check.dto.CheckPackageDto; + +/** + * 检查套餐AppService接口 + * + * @author system + * @date 2025-11-26 + */ +public interface ICheckPackageAppService { + + /** + * 获取检查套餐列表 + * @return 检查套餐列表 + */ + R getCheckPackageList(); + + /** + * 根据ID获取检查套餐详情 + * @param id 套餐ID + * @return 套餐详情 + */ + R getCheckPackageById(Long id); + + /** + * 新增检查套餐 + * @param checkPackageDto 套餐信息 + * @return 新增结果 + */ + R addCheckPackage(CheckPackageDto checkPackageDto); + + /** + * 更新检查套餐 + * @param checkPackageDto 套餐信息 + * @return 更新结果 + */ + R updateCheckPackage(CheckPackageDto checkPackageDto); + + /** + * 删除检查套餐 + * @param id 套餐ID + * @return 删除结果 + */ + R deleteCheckPackage(Long id); +} + diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java new file mode 100644 index 00000000..60221610 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java @@ -0,0 +1,206 @@ +package com.openhis.web.check.appservice.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.core.common.core.domain.R; +import com.openhis.check.domain.CheckPackage; +import com.openhis.check.domain.CheckPackageDetail; +import com.openhis.check.service.ICheckPackageDetailService; +import com.openhis.check.service.ICheckPackageService; +import com.openhis.web.check.appservice.ICheckPackageAppService; +import com.openhis.web.check.dto.CheckPackageDetailDto; +import com.openhis.web.check.dto.CheckPackageDto; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 检查套餐AppService实现 + * + * @author system + * @date 2025-11-26 + */ +@Slf4j +@Service +@AllArgsConstructor +public class CheckPackageAppServiceImpl implements ICheckPackageAppService { + + private final ICheckPackageService checkPackageService; + private final ICheckPackageDetailService checkPackageDetailService; + + @Override + public R getCheckPackageList() { + try { + List list = checkPackageService.list(); + return R.ok(list); + } catch (Exception e) { + log.error("获取检查套餐列表失败", e); + return R.fail("获取检查套餐列表失败"); + } + } + + @Override + public R getCheckPackageById(Long id) { + try { + CheckPackage checkPackage = checkPackageService.getById(id); + if (checkPackage == null) { + return R.fail("套餐不存在"); + } + + // 获取套餐明细 + List details = checkPackageDetailService.list( + new LambdaQueryWrapper() + .eq(CheckPackageDetail::getPackageId, id) + .orderByAsc(CheckPackageDetail::getOrderNum) + ); + + // 转换为DTO + CheckPackageDto dto = new CheckPackageDto(); + BeanUtils.copyProperties(checkPackage, dto); + + List detailDtos = details.stream().map(detail -> { + CheckPackageDetailDto detailDto = new CheckPackageDetailDto(); + BeanUtils.copyProperties(detail, detailDto); + return detailDto; + }).collect(Collectors.toList()); + + dto.setItems(detailDtos); + + return R.ok(dto); + } catch (Exception e) { + log.error("获取检查套餐详情失败", e); + return R.fail("获取检查套餐详情失败"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public R addCheckPackage(CheckPackageDto checkPackageDto) { + try { + // 创建套餐主表数据 + CheckPackage checkPackage = new CheckPackage(); + BeanUtils.copyProperties(checkPackageDto, checkPackage); + + // 设置套餐维护日期为当前系统日期 + checkPackage.setMaintainDate(LocalDate.now()); + checkPackage.setCreateTime(LocalDateTime.now()); + checkPackage.setUpdateTime(LocalDateTime.now()); + + // 保存套餐主表 + boolean saveResult = checkPackageService.save(checkPackage); + if (!saveResult) { + return R.fail("保存套餐失败"); + } + + // 保存套餐明细 + if (checkPackageDto.getItems() != null && !checkPackageDto.getItems().isEmpty()) { + List details = new ArrayList<>(); + int orderNum = 1; + for (CheckPackageDetailDto detailDto : checkPackageDto.getItems()) { + CheckPackageDetail detail = new CheckPackageDetail(); + BeanUtils.copyProperties(detailDto, detail); + detail.setPackageId(checkPackage.getId()); + detail.setOrderNum(orderNum++); + detail.setCreateTime(LocalDateTime.now()); + detail.setUpdateTime(LocalDateTime.now()); + details.add(detail); + } + checkPackageDetailService.saveBatch(details); + } + + return R.ok(checkPackage.getId(), "保存成功"); + } catch (Exception e) { + log.error("新增检查套餐失败", e); + return R.fail("新增检查套餐失败: " + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public R updateCheckPackage(CheckPackageDto checkPackageDto) { + try { + // 检查套餐是否存在 + CheckPackage existPackage = checkPackageService.getById(checkPackageDto.getId()); + if (existPackage == null) { + return R.fail("套餐不存在"); + } + + // 更新套餐主表数据 + CheckPackage checkPackage = new CheckPackage(); + BeanUtils.copyProperties(checkPackageDto, checkPackage); + + // 更新套餐维护日期为当前系统日期 + checkPackage.setMaintainDate(LocalDate.now()); + checkPackage.setUpdateTime(LocalDateTime.now()); + + boolean updateResult = checkPackageService.updateById(checkPackage); + if (!updateResult) { + return R.fail("更新套餐失败"); + } + + // 删除原有明细 + checkPackageDetailService.remove( + new LambdaQueryWrapper() + .eq(CheckPackageDetail::getPackageId, checkPackage.getId()) + ); + + // 保存新的套餐明细 + if (checkPackageDto.getItems() != null && !checkPackageDto.getItems().isEmpty()) { + List details = new ArrayList<>(); + int orderNum = 1; + for (CheckPackageDetailDto detailDto : checkPackageDto.getItems()) { + CheckPackageDetail detail = new CheckPackageDetail(); + BeanUtils.copyProperties(detailDto, detail); + detail.setPackageId(checkPackage.getId()); + detail.setOrderNum(orderNum++); + detail.setCreateTime(LocalDateTime.now()); + detail.setUpdateTime(LocalDateTime.now()); + details.add(detail); + } + checkPackageDetailService.saveBatch(details); + } + + return R.ok("更新成功"); + } catch (Exception e) { + log.error("更新检查套餐失败", e); + return R.fail("更新检查套餐失败: " + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public R deleteCheckPackage(Long id) { + try { + // 检查套餐是否存在 + CheckPackage existPackage = checkPackageService.getById(id); + if (existPackage == null) { + return R.fail("套餐不存在"); + } + + // 删除套餐明细 + checkPackageDetailService.remove( + new LambdaQueryWrapper() + .eq(CheckPackageDetail::getPackageId, id) + ); + + // 删除套餐主表 + boolean deleteResult = checkPackageService.removeById(id); + if (!deleteResult) { + return R.fail("删除套餐失败"); + } + + return R.ok("删除成功"); + } catch (Exception e) { + log.error("删除检查套餐失败", e); + return R.fail("删除检查套餐失败: " + e.getMessage()); + } + } +} + diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java index c36aec56..a061b3d9 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/CheckTypeController.java @@ -1,6 +1,9 @@ package com.openhis.web.check.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.core.common.core.controller.BaseController; +import com.core.common.core.domain.AjaxResult; +import com.core.common.core.domain.R; import com.openhis.check.domain.CheckMethod; import com.openhis.check.domain.CheckPackage; import com.openhis.check.domain.CheckPart; @@ -9,12 +12,13 @@ import com.openhis.check.service.ICheckMethodService; import com.openhis.check.service.ICheckPackageService; import com.openhis.check.service.ICheckPartService; import com.openhis.check.service.ICheckTypeService; +import com.openhis.web.check.appservice.ICheckPackageAppService; +import com.openhis.web.check.dto.CheckPackageDto; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; -import com.core.common.core.controller.BaseController; -import com.core.common.core.domain.AjaxResult; +import javax.validation.Valid; import java.util.List; /** @@ -22,6 +26,7 @@ import java.util.List; * * @author system * @date 2025-07-22 + * @updated 2025-11-26 - 增加套餐设置相关接口 */ @RestController @RequestMapping({"/system/check-type", "/system"}) @@ -33,6 +38,7 @@ public class CheckTypeController extends BaseController { private final ICheckMethodService checkMethodService; private final ICheckPartService checkPartService; private final ICheckPackageService checkPackageService; + private final ICheckPackageAppService checkPackageAppService; /** * 获取检查类型列表 @@ -93,4 +99,36 @@ public class CheckTypeController extends BaseController { public AjaxResult remove(@PathVariable Long checkTypeId) { return toAjax(checkTypeService.removeById(checkTypeId)); } + + /** + * 根据ID获取检查套餐详情 + */ + @GetMapping({"/package/{id}", "/check-package/{id}"}) + public R getCheckPackageById(@PathVariable Long id) { + return checkPackageAppService.getCheckPackageById(id); + } + + /** + * 新增检查套餐 + */ + @PostMapping({"/package", "/check-package"}) + public R addCheckPackage(@Valid @RequestBody CheckPackageDto checkPackageDto) { + return checkPackageAppService.addCheckPackage(checkPackageDto); + } + + /** + * 更新检查套餐 + */ + @PutMapping({"/package", "/check-package"}) + public R updateCheckPackage(@Valid @RequestBody CheckPackageDto checkPackageDto) { + return checkPackageAppService.updateCheckPackage(checkPackageDto); + } + + /** + * 删除检查套餐 + */ + @DeleteMapping({"/package/{id}", "/check-package/{id}"}) + public R deleteCheckPackage(@PathVariable Long id) { + return checkPackageAppService.deleteCheckPackage(id); + } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/dto/CheckPackageDetailDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/dto/CheckPackageDetailDto.java new file mode 100644 index 00000000..f3d1e442 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/dto/CheckPackageDetailDto.java @@ -0,0 +1,71 @@ +package com.openhis.web.check.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * 检查套餐明细DTO + * + * @author system + * @date 2025-11-26 + */ +@Data +@Accessors(chain = true) +public class CheckPackageDetailDto { + + /** 套餐明细ID */ + private Long id; + + /** 套餐ID */ + private Long packageId; + + /** 项目编号 */ + private String itemCode; + + /** 项目名称/规格 */ + @NotBlank(message = "项目名称不能为空") + private String itemName; + + /** 检查项目ID(诊疗项目ID) */ + private Long checkItemId; + + /** 剂量 */ + private String dose; + + /** 途径 */ + private String method; + + /** 频次 */ + private String frequency; + + /** 天数 */ + private String days; + + /** 数量 */ + @NotNull(message = "数量不能为空") + private Integer quantity; + + /** 单价 */ + @NotNull(message = "单价不能为空") + private BigDecimal unitPrice; + + /** 金额 */ + private BigDecimal amount; + + /** 服务费 */ + private BigDecimal serviceCharge; + + /** 总金额 */ + private BigDecimal total; + + /** 产地 */ + private String origin; + + /** 序号 */ + private Integer orderNum; +} + diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/dto/CheckPackageDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/dto/CheckPackageDto.java new file mode 100644 index 00000000..a3017bab --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/dto/CheckPackageDto.java @@ -0,0 +1,86 @@ +package com.openhis.web.check.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +/** + * 检查套餐DTO + * + * @author system + * @date 2025-11-26 + */ +@Data +@Accessors(chain = true) +public class CheckPackageDto { + + /** 检查套餐ID */ + private Long id; + + /** 套餐名称 */ + @NotBlank(message = "套餐名称不能为空") + private String packageName; + + /** 套餐编码 */ + private String code; + + /** 套餐类别 */ + @NotBlank(message = "套餐类别不能为空") + private String packageType; + + /** 套餐级别 */ + @NotBlank(message = "套餐级别不能为空") + private String packageLevel; + + /** 适用科室 */ + private String department; + + /** 适用用户 */ + private String user; + + /** 卫生机构 */ + private String organization; + + /** 套餐金额 */ + private BigDecimal packagePrice; + + /** 折扣 */ + private BigDecimal discount; + + /** 制单人 */ + private String creator; + + /** 是否停用 */ + private Integer isDisabled; + + /** 显示套餐名 */ + private Integer showPackageName; + + /** 生成服务费 */ + private Integer generateServiceFee; + + /** 套餐价格启用状态 */ + private Integer packagePriceEnabled; + + /** 服务费 */ + private BigDecimal serviceFee; + + /** 备注 */ + private String remark; + + /** 描述 */ + private String description; + + /** 套餐维护日期 */ + private LocalDate createDate; + + /** 套餐明细列表 */ + @NotNull(message = "套餐明细不能为空") + private List items; +} + diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackage.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackage.java index 17ab3af0..5a79de77 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackage.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackage.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import lombok.experimental.Accessors; +import java.math.BigDecimal; +import java.time.LocalDate; import java.time.LocalDateTime; /** @@ -15,6 +17,7 @@ import java.time.LocalDateTime; * * @author system * @date 2025-07-22 + * @updated 2025-11-26 - 扩展字段以支持套餐设置PRD需求 */ @Data @Accessors(chain = true) @@ -27,22 +30,76 @@ public class CheckPackage { private Long id; /** 套餐名称 */ - private String name; + @TableField("name") + private String packageName; /** 套餐编码 */ private String code; + /** 套餐类别 */ + @TableField("package_type") + private String packageType; + + /** 套餐级别 (1:全院套餐 2:科室套餐 3:个人套餐) */ + @TableField("package_level") + private String packageLevel; + + /** 适用科室 (当套餐级别为科室套餐时必填) */ + @TableField(value = "department", exist = false) + private String department; + + /** 适用用户 (当套餐级别为个人套餐时必填) */ + @TableField(value = "user", exist = false) + private String user; + + /** 卫生机构 */ + @TableField(value = "organization", exist = false) + private String organization; + + /** 套餐金额 */ + @TableField("price") + private BigDecimal packagePrice; + + /** 折扣 (百分比) */ + @TableField(value = "discount", exist = false) + private BigDecimal discount; + + /** 制单人 */ + @TableField(value = "creator", exist = false) + private String creator; + + /** 是否停用 (0:启用 1:停用) */ + @TableField(value = "is_disabled", exist = false) + private Integer isDisabled; + + /** 显示套餐名 (0:否 1:是) */ + @TableField(value = "show_package_name", exist = false) + private Integer showPackageName; + + /** 生成服务费 (0:否 1:是) */ + @TableField(value = "generate_service_fee", exist = false) + private Integer generateServiceFee; + + /** 套餐价格启用状态 (0:不启用 1:启用) */ + @TableField(value = "package_price_enabled", exist = false) + private Integer packagePriceEnabled; + + /** 服务费 */ + @TableField(value = "service_fee", exist = false) + private BigDecimal serviceFee; + + /** 备注 */ + private String remark; + /** 描述 */ private String description; - /** 价格 */ - private Double price; - /** 序号 */ private Integer number; - /** 备注 */ - private String remark; + /** 套餐维护日期 (系统自动生成) */ + @TableField(value = "maintain_date", exist = false) + private LocalDate maintainDate; /** 创建时间 */ private LocalDateTime createTime; diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackageDetail.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackageDetail.java new file mode 100644 index 00000000..98569618 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/domain/CheckPackageDetail.java @@ -0,0 +1,95 @@ +package com.openhis.check.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 检查套餐明细表 + * + * @author system + * @date 2025-11-26 + */ +@Data +@Accessors(chain = true) +@TableName(value = "check_package_detail", autoResultMap = true) +public class CheckPackageDetail { + private static final long serialVersionUID = 1L; + + /** 套餐明细ID */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 套餐ID */ + private Long packageId; + + /** 项目编号 */ + private String itemCode; + + /** 项目名称/规格 */ + private String itemName; + + /** 检查项目ID(诊疗项目ID) */ + private Long checkItemId; + + /** 剂量 */ + private String dose; + + /** 途径 */ + private String method; + + /** 频次 */ + private String frequency; + + /** 天数 */ + private String days; + + /** 数量 */ + private Integer quantity; + + /** 单价 */ + private BigDecimal unitPrice; + + /** 金额 */ + private BigDecimal amount; + + /** 服务费 */ + private BigDecimal serviceCharge; + + /** 总金额 */ + private BigDecimal total; + + /** 产地 */ + private String origin; + + /** 序号 */ + private Integer orderNum; + + /** 创建时间 */ + private LocalDateTime createTime; + + /** 更新时间 */ + private LocalDateTime updateTime; + + /** + * 禁用MyBatis Plus自动添加的字段 + */ + @TableField(exist = false) + private String createBy; + + @TableField(exist = false) + private String updateBy; + + @TableField(exist = false) + private Integer tenantId; + + @TableField(exist = false) + private String deleteFlag; +} + diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/mapper/CheckPackageDetailMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/mapper/CheckPackageDetailMapper.java new file mode 100644 index 00000000..b6d2fd1e --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/mapper/CheckPackageDetailMapper.java @@ -0,0 +1,16 @@ +package com.openhis.check.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.openhis.check.domain.CheckPackageDetail; +import org.apache.ibatis.annotations.Mapper; + +/** + * 检查套餐明细Mapper接口 + * + * @author system + * @date 2025-11-26 + */ +@Mapper +public interface CheckPackageDetailMapper extends BaseMapper { +} + diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/service/ICheckPackageDetailService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/service/ICheckPackageDetailService.java new file mode 100644 index 00000000..9c77098b --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/service/ICheckPackageDetailService.java @@ -0,0 +1,14 @@ +package com.openhis.check.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.openhis.check.domain.CheckPackageDetail; + +/** + * 检查套餐明细Service接口 + * + * @author system + * @date 2025-11-26 + */ +public interface ICheckPackageDetailService extends IService { +} + diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/service/impl/CheckPackageDetailServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/service/impl/CheckPackageDetailServiceImpl.java new file mode 100644 index 00000000..2d7a308b --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/check/service/impl/CheckPackageDetailServiceImpl.java @@ -0,0 +1,19 @@ +package com.openhis.check.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.openhis.check.domain.CheckPackageDetail; +import com.openhis.check.mapper.CheckPackageDetailMapper; +import com.openhis.check.service.ICheckPackageDetailService; +import org.springframework.stereotype.Service; + +/** + * 检查套餐明细Service实现 + * + * @author system + * @date 2025-11-26 + */ +@Service +public class CheckPackageDetailServiceImpl extends ServiceImpl + implements ICheckPackageDetailService { +} + diff --git a/openhis-ui-vue3/src/api/system/checkType.js b/openhis-ui-vue3/src/api/system/checkType.js index 42c32295..0fd1ba42 100644 --- a/openhis-ui-vue3/src/api/system/checkType.js +++ b/openhis-ui-vue3/src/api/system/checkType.js @@ -68,4 +68,38 @@ export function listCheckPackage(query) { method: 'get', params: query }) +} + +// 根据ID查询检查套餐详情 +export function getCheckPackage(id) { + return request({ + url: `/system/check-package/${id}`, + method: 'get' + }) +} + +// 新增检查套餐 +export function addCheckPackage(data) { + return request({ + url: '/system/check-package', + method: 'post', + data: data + }) +} + +// 修改检查套餐 +export function updateCheckPackage(data) { + return request({ + url: '/system/check-package', + method: 'put', + data: data + }) +} + +// 删除检查套餐 +export function delCheckPackage(id) { + return request({ + url: `/system/check-package/${id}`, + method: 'delete' + }) } \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue index 00a6b070..6b3dcb4e 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue @@ -3,12 +3,14 @@
套餐管理 - 刷新 + + 刷新 ({{ diagnosisTreatmentList.length }}) + 保存
-
+

基本信息

- + @@ -190,27 +196,61 @@ - + @@ -226,9 +266,14 @@ {{ row.frequency || '-' }} - + @@ -335,7 +380,7 @@ import { ElMessage, ElMessageBox } from 'element-plus' import { getDicts } from '@/api/system/dict/data' import { addCheckPackage, updateCheckPackage } from '@/api/system/checkType' import { getDiagnosisTreatmentList } from '@/views/catalog/diagnosistreatment/components/diagnosistreatment' -import { useUserStore } from '@/store/modules/user' +import useUserStore from '@/store/modules/user' const userStore = useUserStore() @@ -372,13 +417,7 @@ const formRules = { { required: true, message: '请选择套餐级别', trigger: 'change' } ], packageName: [ - { required: true, message: '请输入套餐名称', trigger: 'blur' } - ], - department: [ - { required: true, message: '请选择科室', trigger: 'change' } - ], - user: [ - { required: true, message: '请选择用户', trigger: 'change' } + { required: true, message: '请输入套餐名称', trigger: 'blur', type: 'string' } ] } @@ -388,21 +427,28 @@ const packageLevelOptions = ref([]) const departments = ref([]) // 诊疗项目列表 const diagnosisTreatmentList = ref([]) +// 过滤后的诊疗项目列表(用于搜索) +const filteredDiagnosisList = ref([]) +// 加载状态 +const loading = ref(false) // 明细数据 const detailData = ref([]) // 初始化数据 onMounted(async () => { + console.log('=== PackageSettings 组件开始初始化 ===') + try { // 获取套餐级别字典 try { const levelResponse = await getDicts('examination_item_package_level') if (levelResponse && levelResponse.data) { packageLevelOptions.value = levelResponse.data + console.log('✓ 套餐级别数据加载成功:', packageLevelOptions.value.length) } } catch (error) { - console.error('获取套餐级别字典失败:', error) + console.error('✗ 获取套餐级别字典失败:', error) } // 获取科室字典 @@ -410,33 +456,97 @@ onMounted(async () => { const deptResponse = await getDicts('dept') if (deptResponse && deptResponse.data) { departments.value = deptResponse.data + console.log('✓ 科室数据加载成功:', departments.value.length) } } catch (error) { - console.error('获取科室字典失败:', error) + console.error('✗ 获取科室字典失败:', error) } - // 获取诊疗项目列表 + // 获取诊疗项目列表 - 使用分批加载策略 + loading.value = true try { - const treatmentResponse = await getDiagnosisTreatmentList({ - pageNo: 1, - pageSize: 1000 - }) - if (treatmentResponse && treatmentResponse.data && treatmentResponse.data.records) { - diagnosisTreatmentList.value = treatmentResponse.data.records + console.log('开始获取诊疗项目列表...') + + // 分批加载数据,避免一次性加载过多导致超时 + let allItems = [] + const maxBatches = 3 // 最多加载3批 + const batchSize = 50 // 每批50条 + + for (let page = 1; page <= maxBatches; page++) { + try { + const treatmentResponse = await getDiagnosisTreatmentList({ + pageNo: page, + pageSize: batchSize + }) + + console.log(`第${page}批API响应:`, treatmentResponse) + + // 处理不同的响应格式 + let batchData = [] + if (treatmentResponse) { + if (treatmentResponse.data && treatmentResponse.data.records) { + batchData = treatmentResponse.data.records + } else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) { + batchData = treatmentResponse.data + } else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) { + batchData = treatmentResponse.records + } + } + + if (batchData.length > 0) { + allItems = allItems.concat(batchData) + console.log(`✓ 第${page}批加载成功: ${batchData.length}条,累计: ${allItems.length}条`) + + // 如果这批数据少于pageSize,说明已经是最后一批了 + if (batchData.length < batchSize) { + break + } + } else { + break // 没有更多数据了 + } + } catch (batchError) { + console.error(`第${page}批加载失败:`, batchError) + break // 出错就停止继续加载 + } } + + if (allItems.length > 0) { + diagnosisTreatmentList.value = allItems + console.log(`✓ 诊疗项目加载完成,共${allItems.length}条`) + ElMessage.success(`成功加载${allItems.length}个诊疗项目`) + } else { + console.warn('未获取到任何诊疗项目数据') + ElMessage.warning({ + message: '未获取到诊疗项目数据。请先在【系统管理-目录管理-诊疗项目】中添加数据', + duration: 6000, + showClose: true + }) + } + } catch (error) { console.error('获取诊疗项目列表失败:', error) + ElMessage.error({ + message: '获取诊疗项目列表失败,请检查网络连接或联系管理员', + duration: 6000, + showClose: true + }) + } finally { + loading.value = false } // 初始化一行空数据 handleAddRow() + + console.log('=== PackageSettings 组件初始化完成 ===') + console.log('最终诊疗项目列表:', diagnosisTreatmentList.value) } catch (error) { - console.error('初始化数据失败:', error) + console.error('✗ 初始化数据失败:', error) } }) // 套餐级别变更处理 function handlePackageLevelChange(value) { + console.log('套餐级别变更:', value) // 重置关联字段 if (value !== '2') { formData.department = '' @@ -444,6 +554,21 @@ function handlePackageLevelChange(value) { if (value !== '3') { formData.user = '' } + + // 动态更新验证规则 + if (value === '2') { + // 科室套餐,科室必填 + formRules.department = [{ required: true, message: '请选择科室', trigger: 'change' }] + formRules.user = [] + } else if (value === '3') { + // 个人套餐,用户必填 + formRules.user = [{ required: true, message: '请选择用户', trigger: 'change' }] + formRules.department = [] + } else { + // 全院套餐,都不必填 + formRules.department = [] + formRules.user = [] + } } // 添加行 @@ -462,7 +587,8 @@ function handleAddRow() { serviceCharge: 0, total: 0, origin: '', - editing: true + editing: true, + filteredList: diagnosisTreatmentList.value // 初始化过滤列表 }) } @@ -499,13 +625,21 @@ function handleDeleteRow(index) { // 项目选择处理 function handleItemSelect(row) { + console.log('选择项目ID:', row.itemId) + console.log('诊疗项目列表:', diagnosisTreatmentList.value) + const item = diagnosisTreatmentList.value.find(i => i.id === row.itemId) + console.log('找到的项目:', item) + if (item) { - row.itemName = item.name || '' - row.code = item.busNo || '' - // 获取单价,使用retailPrice - row.unitPrice = item.retailPrice || 0 + row.itemName = item.name || item.itemName || '' + row.code = item.busNo || item.code || item.itemCode || '' + // 获取单价,尝试多个可能的字段名 + row.unitPrice = item.retailPrice || item.unitPrice || item.price || 0 + console.log('设置单价:', row.unitPrice) calculateAmount(row) + } else { + ElMessage.warning('未找到该项目信息') } } @@ -532,22 +666,100 @@ function handlePackageManagement() { ElMessage.info('即将进入套餐管理界面') } -// 刷新 -function handleRefresh() { - ElMessageBox.confirm('确定要刷新页面吗?未保存的数据将丢失', '提示', { - confirmButtonText: '确定', - cancelButtonText: '取消', - type: 'warning' - }).then(() => { - location.reload() - }).catch(() => {}) +// 刷新 - 重新加载诊疗项目数据 +async function handleRefresh() { + try { + loading.value = true + console.log('开始刷新诊疗项目数据...') + + // 分批加载数据,避免一次性加载过多导致超时 + let allItems = [] + const maxBatches = 3 // 最多加载3批 + const batchSize = 50 // 每批50条 + + for (let page = 1; page <= maxBatches; page++) { + try { + const treatmentResponse = await getDiagnosisTreatmentList({ + pageNo: page, + pageSize: batchSize + }) + + console.log(`第${page}批API响应:`, treatmentResponse) + + let batchData = [] + if (treatmentResponse) { + if (treatmentResponse.data && treatmentResponse.data.records) { + batchData = treatmentResponse.data.records + } else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) { + batchData = treatmentResponse.data + } else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) { + batchData = treatmentResponse.records + } + } + + if (batchData.length > 0) { + allItems = allItems.concat(batchData) + console.log(`✓ 第${page}批加载成功: ${batchData.length}条,累计: ${allItems.length}条`) + + // 如果这批数据少于pageSize,说明已经是最后一批了 + if (batchData.length < batchSize) { + break + } + } else { + break // 没有更多数据了 + } + } catch (batchError) { + console.error(`第${page}批加载失败:`, batchError) + break // 出错就停止继续加载 + } + } + + if (allItems.length > 0) { + diagnosisTreatmentList.value = allItems + ElMessage.success('刷新成功,共加载 ' + allItems.length + ' 个项目') + } else { + ElMessage.warning('未获取到项目数据,请先在【系统管理-目录管理-诊疗项目】中添加数据') + } + } catch (error) { + console.error('刷新失败:', error) + ElMessage.error('刷新失败,请检查网络连接或联系管理员') + } finally { + loading.value = false + } +} + +// 数字输入验证 - 用于表单字段 +function validateNumberInput(value, field) { + // 只允许数字和小数点 + const regex = /^\d*\.?\d*$/ + if (!regex.test(value)) { + formData[field] = value.replace(/[^\d.]/g, '') + } +} + +// 数字输入验证 - 用于表格字段 +function validateTableNumberInput(value, row, field) { + // 只允许数字和小数点 + const regex = /^\d*\.?\d*$/ + if (!regex.test(value)) { + row[field] = value.replace(/[^\d.]/g, '') + } } // 保存 async function handleSave() { try { + console.log('开始保存,当前表单数据:', JSON.parse(JSON.stringify(formData))) + // 验证基本信息 - await basicFormRef.value.validate() + try { + await basicFormRef.value.validate() + console.log('✓ 基本信息验证通过') + } catch (validationError) { + console.error('✗ 表单验证失败:', validationError) + ElMessage.error('请完善必填项:' + Object.keys(validationError).join(', ')) + return + } // 验证明细数据 if (detailData.value.length === 0) { @@ -555,27 +767,38 @@ async function handleSave() { return } + console.log('明细数据条数:', detailData.value.length) + // 检查是否有未确认的编辑行 const hasEditingRow = detailData.value.some(row => row.editing) if (hasEditingRow) { ElMessage.warning('请先确认所有正在编辑的行') return } + console.log('✓ 所有行已确认') // 检查明细数据完整性 const hasEmptyItem = detailData.value.some(row => !row.itemName || !row.quantity) if (hasEmptyItem) { - ElMessage.warning('请完善所有明细项目信息') + console.error('✗ 存在空项目:', detailData.value.filter(row => !row.itemName || !row.quantity)) + ElMessage.warning('请完善所有明细项目信息(项目名称和数量为必填项)') return } + console.log('✓ 明细数据完整性验证通过') // 更新创建日期为当前系统时间 formData.createDate = new Date().toISOString().split('T')[0] + // 验证折扣范围 + if (formData.discount && (parseFloat(formData.discount) < 0 || parseFloat(formData.discount) > 100)) { + ElMessage.warning('折扣必须在0-100之间') + return + } + // 构建保存数据 const saveData = { id: formData.id, - packageName: formData.packageName, + packageName: String(formData.packageName || ''), code: formData.code || '', description: formData.description || '', packageType: formData.packageType, @@ -583,49 +806,69 @@ async function handleSave() { department: formData.department || '', user: formData.user || '', organization: formData.organization, - packagePrice: formData.packagePrice, + packagePrice: parseFloat(formData.packagePrice) || 0, discount: formData.discount ? parseFloat(formData.discount) : null, creator: formData.creator, isDisabled: formData.isDisabled, showPackageName: formData.showPackageName, generateServiceFee: formData.generateServiceFee, packagePriceEnabled: formData.packagePriceEnabled, - serviceFee: formData.serviceFee || 0, + serviceFee: parseFloat(formData.serviceFee) || 0, remark: formData.remark || '', createDate: formData.createDate, - items: detailData.value.map(item => ({ + items: detailData.value.map((item, index) => ({ itemCode: item.code || '', itemName: item.itemName || '', - checkItemId: item.itemId || null, // 诊疗项目ID + checkItemId: item.itemId || null, dose: item.dose || '', method: item.method || '', frequency: item.frequency || '', days: item.days || '', - quantity: item.quantity || 1, - unitPrice: item.unitPrice || 0, - amount: item.amount || 0, - serviceCharge: item.serviceCharge || 0, - total: item.total || 0, - origin: item.origin || '' + quantity: parseInt(item.quantity) || 1, + unitPrice: parseFloat(item.unitPrice) || 0, + amount: parseFloat(item.amount) || 0, + serviceCharge: parseFloat(item.serviceCharge) || 0, + total: parseFloat(item.total) || 0, + origin: item.origin || '', + orderNum: index + 1 })) } - - // 调用API保存 - const response = await addCheckPackage(saveData) - if (response && response.code === 200) { - ElMessage.success('套餐数据已保存') - // 如果有返回ID,更新formData.id以便后续更新 - if (response.data) { - formData.id = response.data + console.log('构建的保存数据:', JSON.parse(JSON.stringify(saveData))) + + // 调用API保存 - 根据是否有ID判断新增还是更新 + let response + try { + if (formData.id) { + console.log('执行更新操作...') + response = await updateCheckPackage(saveData) + } else { + console.log('执行新增操作...') + response = await addCheckPackage(saveData) } - } else { - ElMessage.error(response?.msg || '保存失败,请检查表单数据') + + console.log('API响应:', response) + + if (response && (response.code === 200 || response.code === 0)) { + ElMessage.success('套餐数据已保存') + // 如果有返回ID,更新formData.id以便后续更新 + if (response.data && !formData.id) { + formData.id = response.data + console.log('新增成功,套餐ID:', formData.id) + } + } else { + console.error('保存失败,响应:', response) + ElMessage.error(response?.msg || response?.message || '保存失败,请检查表单数据') + } + } catch (apiError) { + console.error('API调用失败:', apiError) + throw apiError } } catch (error) { - console.error('保存失败:', error) + console.error('保存过程出错:', error) if (error !== 'cancel') { - ElMessage.error('保存失败,请检查表单数据') + const errorMsg = error.response?.data?.msg || error.message || '保存失败,请检查表单数据' + ElMessage.error('保存失败: ' + errorMsg) } } }