检查项目设置-套餐设置
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<CheckPackage> 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<CheckPackageDetail> details = checkPackageDetailService.list(
|
||||||
|
new LambdaQueryWrapper<CheckPackageDetail>()
|
||||||
|
.eq(CheckPackageDetail::getPackageId, id)
|
||||||
|
.orderByAsc(CheckPackageDetail::getOrderNum)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 转换为DTO
|
||||||
|
CheckPackageDto dto = new CheckPackageDto();
|
||||||
|
BeanUtils.copyProperties(checkPackage, dto);
|
||||||
|
|
||||||
|
List<CheckPackageDetailDto> 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<CheckPackageDetail> 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<CheckPackageDetail>()
|
||||||
|
.eq(CheckPackageDetail::getPackageId, checkPackage.getId())
|
||||||
|
);
|
||||||
|
|
||||||
|
// 保存新的套餐明细
|
||||||
|
if (checkPackageDto.getItems() != null && !checkPackageDto.getItems().isEmpty()) {
|
||||||
|
List<CheckPackageDetail> 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<CheckPackageDetail>()
|
||||||
|
.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.openhis.web.check.controller;
|
package com.openhis.web.check.controller;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
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.CheckMethod;
|
||||||
import com.openhis.check.domain.CheckPackage;
|
import com.openhis.check.domain.CheckPackage;
|
||||||
import com.openhis.check.domain.CheckPart;
|
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.ICheckPackageService;
|
||||||
import com.openhis.check.service.ICheckPartService;
|
import com.openhis.check.service.ICheckPartService;
|
||||||
import com.openhis.check.service.ICheckTypeService;
|
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.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,6 +26,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author system
|
* @author system
|
||||||
* @date 2025-07-22
|
* @date 2025-07-22
|
||||||
|
* @updated 2025-11-26 - 增加套餐设置相关接口
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping({"/system/check-type", "/system"})
|
@RequestMapping({"/system/check-type", "/system"})
|
||||||
@@ -33,6 +38,7 @@ public class CheckTypeController extends BaseController {
|
|||||||
private final ICheckMethodService checkMethodService;
|
private final ICheckMethodService checkMethodService;
|
||||||
private final ICheckPartService checkPartService;
|
private final ICheckPartService checkPartService;
|
||||||
private final ICheckPackageService checkPackageService;
|
private final ICheckPackageService checkPackageService;
|
||||||
|
private final ICheckPackageAppService checkPackageAppService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取检查类型列表
|
* 获取检查类型列表
|
||||||
@@ -93,4 +99,36 @@ public class CheckTypeController extends BaseController {
|
|||||||
public AjaxResult remove(@PathVariable Long checkTypeId) {
|
public AjaxResult remove(@PathVariable Long checkTypeId) {
|
||||||
return toAjax(checkTypeService.removeById(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<CheckPackageDetailDto> items;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,6 +17,7 @@ import java.time.LocalDateTime;
|
|||||||
*
|
*
|
||||||
* @author system
|
* @author system
|
||||||
* @date 2025-07-22
|
* @date 2025-07-22
|
||||||
|
* @updated 2025-11-26 - 扩展字段以支持套餐设置PRD需求
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@@ -27,22 +30,76 @@ public class CheckPackage {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 套餐名称 */
|
/** 套餐名称 */
|
||||||
private String name;
|
@TableField("name")
|
||||||
|
private String packageName;
|
||||||
|
|
||||||
/** 套餐编码 */
|
/** 套餐编码 */
|
||||||
private String code;
|
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 String description;
|
||||||
|
|
||||||
/** 价格 */
|
|
||||||
private Double price;
|
|
||||||
|
|
||||||
/** 序号 */
|
/** 序号 */
|
||||||
private Integer number;
|
private Integer number;
|
||||||
|
|
||||||
/** 备注 */
|
/** 套餐维护日期 (系统自动生成) */
|
||||||
private String remark;
|
@TableField(value = "maintain_date", exist = false)
|
||||||
|
private LocalDate maintainDate;
|
||||||
|
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<CheckPackageDetail> {
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<CheckPackageDetail> {
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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<CheckPackageDetailMapper, CheckPackageDetail>
|
||||||
|
implements ICheckPackageDetailService {
|
||||||
|
}
|
||||||
|
|
||||||
@@ -69,3 +69,37 @@ export function listCheckPackage(query) {
|
|||||||
params: query
|
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'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
<!-- 顶部操作按钮区 -->
|
<!-- 顶部操作按钮区 -->
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<el-button type="primary" @click="handlePackageManagement">套餐管理</el-button>
|
<el-button type="primary" @click="handlePackageManagement">套餐管理</el-button>
|
||||||
<el-button @click="handleRefresh">刷新</el-button>
|
<el-button @click="handleRefresh" :loading="loading">
|
||||||
|
刷新 ({{ diagnosisTreatmentList.length }})
|
||||||
|
</el-button>
|
||||||
<el-button type="success" @click="handleSave">保存</el-button>
|
<el-button type="success" @click="handleSave">保存</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 基本信息表单区 -->
|
<!-- 基本信息表单区 -->
|
||||||
<div class="basic-info-section">
|
<div class="basic-info-section" v-loading="loading" element-loading-text="正在加载诊疗项目数据...">
|
||||||
<h3 class="section-title">基本信息</h3>
|
<h3 class="section-title">基本信息</h3>
|
||||||
<el-form
|
<el-form
|
||||||
ref="basicFormRef"
|
ref="basicFormRef"
|
||||||
@@ -89,7 +91,11 @@
|
|||||||
|
|
||||||
<el-col :xs="24" :sm="12" :md="8" :lg="6">
|
<el-col :xs="24" :sm="12" :md="8" :lg="6">
|
||||||
<el-form-item label="折扣">
|
<el-form-item label="折扣">
|
||||||
<el-input v-model="formData.discount" placeholder="请输入折扣">
|
<el-input
|
||||||
|
v-model="formData.discount"
|
||||||
|
placeholder="请输入折扣"
|
||||||
|
@input="validateNumberInput($event, 'discount')"
|
||||||
|
>
|
||||||
<template #append>%</template>
|
<template #append>%</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -190,27 +196,61 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="itemName" label="项目名称/规格" min-width="200">
|
<el-table-column prop="itemName" label="项目名称/规格" min-width="200">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-select
|
<div v-if="row.editing">
|
||||||
v-if="row.editing"
|
<el-select
|
||||||
v-model="row.itemId"
|
v-model="row.itemId"
|
||||||
placeholder="请选择项目"
|
placeholder="输入名称/首字母/编号搜索"
|
||||||
filterable
|
filterable
|
||||||
style="width: 100%"
|
remote
|
||||||
@change="handleItemSelect(row)"
|
:remote-method="(query) => handleProjectSearch(query, row)"
|
||||||
>
|
style="width: 100%"
|
||||||
<el-option
|
@change="handleItemSelect(row)"
|
||||||
v-for="item in diagnosisTreatmentList"
|
@focus="initializeSearchList(row)"
|
||||||
:key="item.id"
|
:loading="diagnosisTreatmentList.length === 0"
|
||||||
:label="item.name"
|
clearable
|
||||||
:value="item.id"
|
>
|
||||||
/>
|
<el-option
|
||||||
</el-select>
|
v-for="item in (row.filteredList || diagnosisTreatmentList)"
|
||||||
|
:key="item.id"
|
||||||
|
:label="(item.name || item.itemName || '未命名') + (item.busNo ? ' [' + item.busNo + ']' : '')"
|
||||||
|
:value="item.id"
|
||||||
|
>
|
||||||
|
<span style="float: left">{{ item.name || item.itemName }}</span>
|
||||||
|
<span style="float: right; color: #8492a6; font-size: 13px">
|
||||||
|
{{ item.busNo || item.code }}
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
|
<template #empty>
|
||||||
|
<div style="padding: 10px; text-align: center; color: #999;">
|
||||||
|
<div v-if="diagnosisTreatmentList.length === 0">
|
||||||
|
暂无项目数据<br/>
|
||||||
|
<small>请先在【系统管理-目录管理-诊疗项目】中添加项目</small>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
无匹配项目<br/>
|
||||||
|
<small>支持:名称模糊搜索、首字母搜索、编号搜索</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
<div style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||||
|
共 {{ diagnosisTreatmentList.length }} 个可选项目
|
||||||
|
<span v-if="row.filteredList && row.filteredList.length < diagnosisTreatmentList.length">
|
||||||
|
(搜索结果: {{ row.filteredList.length }} 个)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<span v-else>{{ row.itemName }}</span>
|
<span v-else>{{ row.itemName }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="dose" label="剂量" width="80" align="center">
|
<el-table-column prop="dose" label="剂量" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-input v-if="row.editing" v-model="row.dose" placeholder="-" />
|
<el-input
|
||||||
|
v-if="row.editing"
|
||||||
|
v-model="row.dose"
|
||||||
|
placeholder="-"
|
||||||
|
@input="validateTableNumberInput($event, row, 'dose')"
|
||||||
|
/>
|
||||||
<span v-else>{{ row.dose || '-' }}</span>
|
<span v-else>{{ row.dose || '-' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -226,9 +266,14 @@
|
|||||||
<span v-else>{{ row.frequency || '-' }}</span>
|
<span v-else>{{ row.frequency || '-' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="days" label="天数" width="80" align="center">
|
<el-table-column prop="days" label="天数" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-input v-if="row.editing" v-model="row.days" placeholder="-" />
|
<el-input
|
||||||
|
v-if="row.editing"
|
||||||
|
v-model="row.days"
|
||||||
|
placeholder="-"
|
||||||
|
@input="validateTableNumberInput($event, row, 'days')"
|
||||||
|
/>
|
||||||
<span v-else>{{ row.days || '-' }}</span>
|
<span v-else>{{ row.days || '-' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -335,7 +380,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
|||||||
import { getDicts } from '@/api/system/dict/data'
|
import { getDicts } from '@/api/system/dict/data'
|
||||||
import { addCheckPackage, updateCheckPackage } from '@/api/system/checkType'
|
import { addCheckPackage, updateCheckPackage } from '@/api/system/checkType'
|
||||||
import { getDiagnosisTreatmentList } from '@/views/catalog/diagnosistreatment/components/diagnosistreatment'
|
import { getDiagnosisTreatmentList } from '@/views/catalog/diagnosistreatment/components/diagnosistreatment'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
@@ -372,13 +417,7 @@ const formRules = {
|
|||||||
{ required: true, message: '请选择套餐级别', trigger: 'change' }
|
{ required: true, message: '请选择套餐级别', trigger: 'change' }
|
||||||
],
|
],
|
||||||
packageName: [
|
packageName: [
|
||||||
{ required: true, message: '请输入套餐名称', trigger: 'blur' }
|
{ required: true, message: '请输入套餐名称', trigger: 'blur', type: 'string' }
|
||||||
],
|
|
||||||
department: [
|
|
||||||
{ required: true, message: '请选择科室', trigger: 'change' }
|
|
||||||
],
|
|
||||||
user: [
|
|
||||||
{ required: true, message: '请选择用户', trigger: 'change' }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,21 +427,28 @@ const packageLevelOptions = ref([])
|
|||||||
const departments = ref([])
|
const departments = ref([])
|
||||||
// 诊疗项目列表
|
// 诊疗项目列表
|
||||||
const diagnosisTreatmentList = ref([])
|
const diagnosisTreatmentList = ref([])
|
||||||
|
// 过滤后的诊疗项目列表(用于搜索)
|
||||||
|
const filteredDiagnosisList = ref([])
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
// 明细数据
|
// 明细数据
|
||||||
const detailData = ref([])
|
const detailData = ref([])
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
console.log('=== PackageSettings 组件开始初始化 ===')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取套餐级别字典
|
// 获取套餐级别字典
|
||||||
try {
|
try {
|
||||||
const levelResponse = await getDicts('examination_item_package_level')
|
const levelResponse = await getDicts('examination_item_package_level')
|
||||||
if (levelResponse && levelResponse.data) {
|
if (levelResponse && levelResponse.data) {
|
||||||
packageLevelOptions.value = levelResponse.data
|
packageLevelOptions.value = levelResponse.data
|
||||||
|
console.log('✓ 套餐级别数据加载成功:', packageLevelOptions.value.length)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取套餐级别字典失败:', error)
|
console.error('✗ 获取套餐级别字典失败:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取科室字典
|
// 获取科室字典
|
||||||
@@ -410,33 +456,97 @@ onMounted(async () => {
|
|||||||
const deptResponse = await getDicts('dept')
|
const deptResponse = await getDicts('dept')
|
||||||
if (deptResponse && deptResponse.data) {
|
if (deptResponse && deptResponse.data) {
|
||||||
departments.value = deptResponse.data
|
departments.value = deptResponse.data
|
||||||
|
console.log('✓ 科室数据加载成功:', departments.value.length)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取科室字典失败:', error)
|
console.error('✗ 获取科室字典失败:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取诊疗项目列表
|
// 获取诊疗项目列表 - 使用分批加载策略
|
||||||
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const treatmentResponse = await getDiagnosisTreatmentList({
|
console.log('开始获取诊疗项目列表...')
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 1000
|
// 分批加载数据,避免一次性加载过多导致超时
|
||||||
})
|
let allItems = []
|
||||||
if (treatmentResponse && treatmentResponse.data && treatmentResponse.data.records) {
|
const maxBatches = 3 // 最多加载3批
|
||||||
diagnosisTreatmentList.value = treatmentResponse.data.records
|
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) {
|
} catch (error) {
|
||||||
console.error('获取诊疗项目列表失败:', error)
|
console.error('获取诊疗项目列表失败:', error)
|
||||||
|
ElMessage.error({
|
||||||
|
message: '获取诊疗项目列表失败,请检查网络连接或联系管理员',
|
||||||
|
duration: 6000,
|
||||||
|
showClose: true
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化一行空数据
|
// 初始化一行空数据
|
||||||
handleAddRow()
|
handleAddRow()
|
||||||
|
|
||||||
|
console.log('=== PackageSettings 组件初始化完成 ===')
|
||||||
|
console.log('最终诊疗项目列表:', diagnosisTreatmentList.value)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化数据失败:', error)
|
console.error('✗ 初始化数据失败:', error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 套餐级别变更处理
|
// 套餐级别变更处理
|
||||||
function handlePackageLevelChange(value) {
|
function handlePackageLevelChange(value) {
|
||||||
|
console.log('套餐级别变更:', value)
|
||||||
// 重置关联字段
|
// 重置关联字段
|
||||||
if (value !== '2') {
|
if (value !== '2') {
|
||||||
formData.department = ''
|
formData.department = ''
|
||||||
@@ -444,6 +554,21 @@ function handlePackageLevelChange(value) {
|
|||||||
if (value !== '3') {
|
if (value !== '3') {
|
||||||
formData.user = ''
|
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,
|
serviceCharge: 0,
|
||||||
total: 0,
|
total: 0,
|
||||||
origin: '',
|
origin: '',
|
||||||
editing: true
|
editing: true,
|
||||||
|
filteredList: diagnosisTreatmentList.value // 初始化过滤列表
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,13 +625,21 @@ function handleDeleteRow(index) {
|
|||||||
|
|
||||||
// 项目选择处理
|
// 项目选择处理
|
||||||
function handleItemSelect(row) {
|
function handleItemSelect(row) {
|
||||||
|
console.log('选择项目ID:', row.itemId)
|
||||||
|
console.log('诊疗项目列表:', diagnosisTreatmentList.value)
|
||||||
|
|
||||||
const item = diagnosisTreatmentList.value.find(i => i.id === row.itemId)
|
const item = diagnosisTreatmentList.value.find(i => i.id === row.itemId)
|
||||||
|
console.log('找到的项目:', item)
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
row.itemName = item.name || ''
|
row.itemName = item.name || item.itemName || ''
|
||||||
row.code = item.busNo || ''
|
row.code = item.busNo || item.code || item.itemCode || ''
|
||||||
// 获取单价,使用retailPrice
|
// 获取单价,尝试多个可能的字段名
|
||||||
row.unitPrice = item.retailPrice || 0
|
row.unitPrice = item.retailPrice || item.unitPrice || item.price || 0
|
||||||
|
console.log('设置单价:', row.unitPrice)
|
||||||
calculateAmount(row)
|
calculateAmount(row)
|
||||||
|
} else {
|
||||||
|
ElMessage.warning('未找到该项目信息')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,22 +666,100 @@ function handlePackageManagement() {
|
|||||||
ElMessage.info('即将进入套餐管理界面')
|
ElMessage.info('即将进入套餐管理界面')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新
|
// 刷新 - 重新加载诊疗项目数据
|
||||||
function handleRefresh() {
|
async function handleRefresh() {
|
||||||
ElMessageBox.confirm('确定要刷新页面吗?未保存的数据将丢失', '提示', {
|
try {
|
||||||
confirmButtonText: '确定',
|
loading.value = true
|
||||||
cancelButtonText: '取消',
|
console.log('开始刷新诊疗项目数据...')
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
// 分批加载数据,避免一次性加载过多导致超时
|
||||||
location.reload()
|
let allItems = []
|
||||||
}).catch(() => {})
|
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() {
|
async function handleSave() {
|
||||||
try {
|
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) {
|
if (detailData.value.length === 0) {
|
||||||
@@ -555,27 +767,38 @@ async function handleSave() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('明细数据条数:', detailData.value.length)
|
||||||
|
|
||||||
// 检查是否有未确认的编辑行
|
// 检查是否有未确认的编辑行
|
||||||
const hasEditingRow = detailData.value.some(row => row.editing)
|
const hasEditingRow = detailData.value.some(row => row.editing)
|
||||||
if (hasEditingRow) {
|
if (hasEditingRow) {
|
||||||
ElMessage.warning('请先确认所有正在编辑的行')
|
ElMessage.warning('请先确认所有正在编辑的行')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
console.log('✓ 所有行已确认')
|
||||||
|
|
||||||
// 检查明细数据完整性
|
// 检查明细数据完整性
|
||||||
const hasEmptyItem = detailData.value.some(row => !row.itemName || !row.quantity)
|
const hasEmptyItem = detailData.value.some(row => !row.itemName || !row.quantity)
|
||||||
if (hasEmptyItem) {
|
if (hasEmptyItem) {
|
||||||
ElMessage.warning('请完善所有明细项目信息')
|
console.error('✗ 存在空项目:', detailData.value.filter(row => !row.itemName || !row.quantity))
|
||||||
|
ElMessage.warning('请完善所有明细项目信息(项目名称和数量为必填项)')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
console.log('✓ 明细数据完整性验证通过')
|
||||||
|
|
||||||
// 更新创建日期为当前系统时间
|
// 更新创建日期为当前系统时间
|
||||||
formData.createDate = new Date().toISOString().split('T')[0]
|
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 = {
|
const saveData = {
|
||||||
id: formData.id,
|
id: formData.id,
|
||||||
packageName: formData.packageName,
|
packageName: String(formData.packageName || ''),
|
||||||
code: formData.code || '',
|
code: formData.code || '',
|
||||||
description: formData.description || '',
|
description: formData.description || '',
|
||||||
packageType: formData.packageType,
|
packageType: formData.packageType,
|
||||||
@@ -583,49 +806,69 @@ async function handleSave() {
|
|||||||
department: formData.department || '',
|
department: formData.department || '',
|
||||||
user: formData.user || '',
|
user: formData.user || '',
|
||||||
organization: formData.organization,
|
organization: formData.organization,
|
||||||
packagePrice: formData.packagePrice,
|
packagePrice: parseFloat(formData.packagePrice) || 0,
|
||||||
discount: formData.discount ? parseFloat(formData.discount) : null,
|
discount: formData.discount ? parseFloat(formData.discount) : null,
|
||||||
creator: formData.creator,
|
creator: formData.creator,
|
||||||
isDisabled: formData.isDisabled,
|
isDisabled: formData.isDisabled,
|
||||||
showPackageName: formData.showPackageName,
|
showPackageName: formData.showPackageName,
|
||||||
generateServiceFee: formData.generateServiceFee,
|
generateServiceFee: formData.generateServiceFee,
|
||||||
packagePriceEnabled: formData.packagePriceEnabled,
|
packagePriceEnabled: formData.packagePriceEnabled,
|
||||||
serviceFee: formData.serviceFee || 0,
|
serviceFee: parseFloat(formData.serviceFee) || 0,
|
||||||
remark: formData.remark || '',
|
remark: formData.remark || '',
|
||||||
createDate: formData.createDate,
|
createDate: formData.createDate,
|
||||||
items: detailData.value.map(item => ({
|
items: detailData.value.map((item, index) => ({
|
||||||
itemCode: item.code || '',
|
itemCode: item.code || '',
|
||||||
itemName: item.itemName || '',
|
itemName: item.itemName || '',
|
||||||
checkItemId: item.itemId || null, // 诊疗项目ID
|
checkItemId: item.itemId || null,
|
||||||
dose: item.dose || '',
|
dose: item.dose || '',
|
||||||
method: item.method || '',
|
method: item.method || '',
|
||||||
frequency: item.frequency || '',
|
frequency: item.frequency || '',
|
||||||
days: item.days || '',
|
days: item.days || '',
|
||||||
quantity: item.quantity || 1,
|
quantity: parseInt(item.quantity) || 1,
|
||||||
unitPrice: item.unitPrice || 0,
|
unitPrice: parseFloat(item.unitPrice) || 0,
|
||||||
amount: item.amount || 0,
|
amount: parseFloat(item.amount) || 0,
|
||||||
serviceCharge: item.serviceCharge || 0,
|
serviceCharge: parseFloat(item.serviceCharge) || 0,
|
||||||
total: item.total || 0,
|
total: parseFloat(item.total) || 0,
|
||||||
origin: item.origin || ''
|
origin: item.origin || '',
|
||||||
|
orderNum: index + 1
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用API保存
|
console.log('构建的保存数据:', JSON.parse(JSON.stringify(saveData)))
|
||||||
const response = await addCheckPackage(saveData)
|
|
||||||
|
|
||||||
if (response && response.code === 200) {
|
// 调用API保存 - 根据是否有ID判断新增还是更新
|
||||||
ElMessage.success('套餐数据已保存')
|
let response
|
||||||
// 如果有返回ID,更新formData.id以便后续更新
|
try {
|
||||||
if (response.data) {
|
if (formData.id) {
|
||||||
formData.id = response.data
|
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) {
|
} catch (error) {
|
||||||
console.error('保存失败:', error)
|
console.error('保存过程出错:', error)
|
||||||
if (error !== 'cancel') {
|
if (error !== 'cancel') {
|
||||||
ElMessage.error('保存失败,请检查表单数据')
|
const errorMsg = error.response?.data?.msg || error.message || '保存失败,请检查表单数据'
|
||||||
|
ElMessage.error('保存失败: ' + errorMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user