Sfoglia il codice sorgente

上传营养帅选配置

chenying2100 2 mesi fa
parent
commit
fc05fb1d53

+ 3 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/bo/EnteralNutritionBo.java

@@ -10,6 +10,7 @@ import org.dromara.web.domain.EnteralNutrition;
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 /**
  * 肠内营养业务对象 enteral_nutrition
@@ -143,4 +144,6 @@ public class EnteralNutritionBo extends BaseEntity {
      * 状态(0正常 1停用)
      */
     private String status;
+
+    private List<EnteralNutritionBo> products;
 }

+ 2 - 0
ruoyi-admin/src/main/java/org/dromara/web/domain/vo/EnteralNutritionQueryVo.java

@@ -40,6 +40,8 @@ public class EnteralNutritionQueryVo implements Serializable {
 
     private String chargeType;
 
+    private String chargeTypeMame;
+
     private String paymentStatus;
 
     private String createByName;

+ 150 - 77
ruoyi-admin/src/main/java/org/dromara/web/service/impl/EnteralNutritionServiceImpl.java

@@ -30,6 +30,7 @@ import org.dromara.web.domain.Settlement;
 import org.dromara.web.domain.SuppliesManage;
 import org.dromara.web.domain.TreatmentUser;
 import org.dromara.web.domain.bo.EnteralNutritionBo;
+import org.dromara.web.domain.bo.EnteralNutritionConsumableBo;
 import org.dromara.web.domain.bo.EnteralNutritionSaveBo;
 import org.dromara.web.domain.bo.SettlementBo;
 import org.dromara.web.domain.vo.EnteralNutritionConsumableVo;
@@ -106,6 +107,10 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
         if (CollUtil.isNotEmpty(nutritionList)) {
             queryVo.setProductNutritionMap(productNutritionMapper.selectByIds(nutritionList.stream().map(EnteralNutrition::getNutritionProductId).collect(Collectors.toSet()))
                 .stream().map(v -> MapstructUtils.convert(v, ProductNutritionVo.class)).collect(Collectors.toMap(k1 -> k1.getId(), k2 -> k2, (k1, k12) -> k1)));
+
+            queryVo.getNutritionList().forEach(nutrition -> {
+                nutrition.setMealTime(Arrays.stream(nutrition.getMealTime().split(",")).filter(StrUtil::isNotBlank).collect(Collectors.joining(",")));
+            });
         }
 
         return R.ok(queryVo);
@@ -118,15 +123,15 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
         List<Settlement> settlementList = settlementMapper.selectList(lqw);
 
         Map<String, List<SysDictDataVo>> dictMap = dataService.selectGroupByType(List.of(BizConst.PAYMENT_STATUS, BizConst.FEE_TYPE)).getData();
-        Map<String, String> paymentMap = dictMap.get(BizConst.PAYMENT_STATUS).stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2.getDictLabel(), (k1, k2) -> k1));
         Map<String, String> feeTypeMap = dictMap.get(BizConst.FEE_TYPE).stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2.getDictLabel(), (k1, k2) -> k1));
         List<EnteralNutritionQueryVo> nutritionQueryVoList = new ArrayList<>(settlementList.size());
         String today = DateUtil.today();
         settlementList.forEach(settlement -> {
             EnteralNutritionQueryVo queryVo = new EnteralNutritionQueryVo();
 
-            queryVo.setPaymentStatus(paymentMap.get(settlement.getPaymentStatus()));
-            queryVo.setChargeType(feeTypeMap.get(settlement.getChargeType()));
+            queryVo.setPaymentStatus(settlement.getPaymentStatus());
+            queryVo.setChargeType(settlement.getChargeType());
+            queryVo.setChargeTypeMame(feeTypeMap.get(settlement.getChargeType()));
             queryVo.setOrderTime(settlement.getOrderTime());
             queryVo.setSettlementId(settlement.getId());
             String stopDate = DateUtil.formatDate(settlement.getStopDate());
@@ -267,7 +272,20 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
         Map<String, String> specUnitMap = dictMap.get(BizConst.PRODUCT_SPEC_UNIT).stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2.getDictLabel(), (k1, k2) -> k1));
         Map<String, String> packageUnitMap = dictMap.get(BizConst.PRODUCT_PACKAGE_UNIT).stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2.getDictLabel(), (k1, k2) -> k1));
 
-        Set<Long> idList = bo.getNutritionList().stream().map(EnteralNutritionBo::getNutritionProductId).collect(Collectors.toSet());
+        Set<Long> idList = CollUtil.newHashSet();
+        bo.getNutritionList().forEach(nutritionBo -> {
+            if (FeeType.PRE_PACKAGED_PRESCRIPTION.getCode().equalsIgnoreCase(bo.getChargeType())) {
+                idList.add(nutritionBo.getNutritionProductId());
+            } else {
+                if (CollUtil.isEmpty(nutritionBo.getProducts())) {
+                    throw new ServiceException("营养产品不能为空");
+                }
+                nutritionBo.getProducts().forEach(nutritionProductBo -> {
+                    idList.add(nutritionProductBo.getNutritionProductId());
+                });
+            }
+        });
+
         Map<Long, ProductNutrition> nutritionMap = productNutritionMapper.selectByIds(idList)
             .stream().collect(Collectors.toMap(k1 -> k1.getId(), k2 -> k2, (k1, k2) -> k1));
         BigDecimal total = BigDecimal.ZERO;
@@ -282,45 +300,16 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
             if (StrUtil.isBlank(nutritionBo.getMealTime())) {
                 throw new ServiceException("餐次时间不能为空");
             }
-            if (ObjUtil.isNull(nutritionBo.getDosePerTime())) {
-                throw new ServiceException("用量/次不能为空");
-            }
-            if (StrUtil.isBlank(nutritionBo.getGroupNo())) {
-                throw new ServiceException("组号不能为空");
-            }
-            Set<String> mealTimeSet = Arrays.stream(nutritionBo.getMealTime().split(",")).map(String::trim).filter(StrUtil::isNotBlank).collect(Collectors.toSet());
-            nutritionBo.setMealTime(StrUtil.join(",", mealTimeSet));
-            nutritionBo.setFrequency(Long.valueOf(mealTimeSet.size()));
-            groupNoMap.put(nutritionBo.getGroupNo(), nutritionBo);
-
-            ProductNutrition nutrition = nutritionMap.get(nutritionBo.getNutritionProductId());
-            nutritionBo.setNutritionProduct(nutrition.getProductName());
-            if (ObjUtil.isNull(nutrition)) {
-                continue;
-            }
-            if (FeeType.CONFIGURE_PRESCRIPTION.getCode().equalsIgnoreCase(nutritionBo.getPrescriptionType())) {
-                if (ObjUtil.isNull(nutrition.getConfigSalePrice())) {
-                    throw new ServiceException("配置销售价格不能为空");
-                }
-                if (ObjUtil.isNull(nutritionBo.getUsageDays())) {
-                    throw new ServiceException("使用天数不能为空");
-                }
-                if (ObjUtil.isNull(nutritionBo.getFirstDay())) {
-                    throw new ServiceException("首日不能为空");
-                }
-                nutritionBo.setAmount(BigDecimal.valueOf(nutrition.getConfigSalePrice() *
-                        (nutritionBo.getFrequency() * (nutritionBo.getUsageDays() - 1) + nutritionBo.getFirstDay()))
-                    .multiply(nutritionBo.getDosePerTime()));
-
-                nutritionBo.setDailyCalories(BigDecimal.valueOf(nutrition.getCalorie() * nutritionBo.getFrequency() / 100.0)
-                    .multiply(nutritionBo.getDosePerTime()));
 
-                nutritionBo.setTotalDose(BigDecimal.valueOf((nutritionBo.getFrequency() * (nutritionBo.getUsageDays() - 1) + nutritionBo.getFirstDay()))
-                    .multiply(nutritionBo.getDosePerTime()));
+            Set<String> mealTimeSet = Arrays.stream(nutritionBo.getMealTime().split(","))
+                .map(String::trim).filter(StrUtil::isNotBlank).collect(Collectors.toSet());
+            nutritionBo.setFrequency(Long.valueOf(mealTimeSet.size()));
 
-                settlement.setStopDate(DateUtil.offsetDay(nutritionBo.getPrescriptionDate(), nutritionBo.getUsageDays().intValue() - 1));
+            if (FeeType.PRE_PACKAGED_PRESCRIPTION.getCode().equalsIgnoreCase(bo.getChargeType())) {
+                nutritionBo.setPrescriptionType(bo.getChargeType());
 
-            } else if (FeeType.PRE_PACKAGED_PRESCRIPTION.getCode().equalsIgnoreCase(nutritionBo.getPrescriptionType())) {
+                ProductNutrition nutrition = nutritionMap.get(nutritionBo.getNutritionProductId());
+                nutrition.setCalorie(ObjUtil.isNull(nutrition.getCalorie()) ? 0L : nutrition.getCalorie());
                 if (ObjUtil.isNull(nutrition.getPackagePrice())) {
                     throw new ServiceException("预包装销售价不能为空");
                 }
@@ -338,44 +327,91 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
                     .multiply(nutritionBo.getDosePerTime()));
 
                 settlement.setStopDate(DateUtil.offsetDay(nutritionBo.getPrescriptionDate(), nutritionBo.getUsageDays().intValue() - 1));
+                nutritionBo.setStopDate(settlement.getStopDate());
+                continue;
+            }
 
-            } else if (FeeType.LONG_TERM_PRESCRIPTION.getCode().equalsIgnoreCase(nutritionBo.getPrescriptionType())) {
-                if (ObjUtil.isNull(nutritionBo.getStopDate())) {
-                    throw new ServiceException("停嘱日期不能为空");
-                }
-                if (ObjUtil.isNull(nutritionBo.getStopDate())) {
-                    throw new ServiceException("停嘱日期不能为空");
+
+            for (EnteralNutritionBo product : nutritionBo.getProducts()) {
+                if (ObjUtil.isNull(product.getDosePerTime())) {
+                    throw new ServiceException("用量/次不能为空");
                 }
-                if (ObjUtil.isNull(nutritionBo.getFirstDay())) {
-                    throw new ServiceException("首日不能为空");
+                if (StrUtil.isBlank(product.getGroupNo())) {
+                    throw new ServiceException("组号不能为空");
                 }
-                if (ObjUtil.isNull(nutrition.getConfigSalePrice())) {
-                    throw new ServiceException("配置销售价格不能为空");
+                groupNoMap.put(product.getGroupNo(), nutritionBo);
+
+                ProductNutrition nutrition = nutritionMap.get(product.getNutritionProductId());
+                nutrition.setCalorie(ObjUtil.isNull(nutrition.getCalorie()) ? 0L : nutrition.getCalorie());
+                product.setNutritionProduct(nutrition.getProductName());
+                if (ObjUtil.isNull(nutrition)) {
+                    continue;
                 }
-                long days = DateUtil.between(nutritionBo.getPrescriptionDate(), nutritionBo.getStopDate(), DateUnit.DAY);
-                nutritionBo.setUsageDays(days);
 
-                nutritionBo.setAmount(BigDecimal.valueOf(((days - 1) * nutritionBo.getFrequency() + nutritionBo.getFirstDay()) * nutrition.getConfigSalePrice())
-                    .multiply(nutritionBo.getDosePerTime()));
+                product.setFrequency(nutritionBo.getFrequency());
+                product.setUsageDays(nutritionBo.getUsageDays());
+                product.setFirstDay(nutritionBo.getFirstDay());
+                product.setPrescriptionDate(nutritionBo.getPrescriptionDate());
+                product.setPrescriptionType(bo.getChargeType());
+                product.setMealTime(nutritionBo.getMealTime());
+                product.setStopDate(nutritionBo.getStopDate());
+
+                if (FeeType.CONFIGURE_PRESCRIPTION.getCode().equalsIgnoreCase(bo.getChargeType())) {
+                    if (ObjUtil.isNull(nutrition.getConfigSalePrice())) {
+                        throw new ServiceException("配置销售价格不能为空");
+                    }
+                    if (ObjUtil.isNull(nutritionBo.getUsageDays())) {
+                        throw new ServiceException("使用天数不能为空");
+                    }
+                    if (ObjUtil.isNull(nutritionBo.getFirstDay())) {
+                        throw new ServiceException("首日不能为空");
+                    }
 
-                nutritionBo.setDailyCalories(BigDecimal.valueOf(nutrition.getCalorie() * nutritionBo.getFrequency() / 100.0)
-                    .multiply(nutritionBo.getDosePerTime()));
+                    product.setAmount(BigDecimal.valueOf(nutrition.getConfigSalePrice() *
+                            (nutritionBo.getFrequency() * (nutritionBo.getUsageDays() - 1) + nutritionBo.getFirstDay()))
+                        .multiply(product.getDosePerTime()));
+                    product.setAmount(BigDecimal.ZERO.compareTo(product.getAmount()) > 0 ? BigDecimal.ZERO : product.getAmount());
 
-                settlement.setStopDate(nutritionBo.getStopDate());
-            }
-            nutritionBo.setDosePerDay(BigDecimal.valueOf(nutritionBo.getFrequency()).multiply(nutritionBo.getDosePerTime()));
+                    product.setDailyCalories(BigDecimal.valueOf(nutrition.getCalorie() * nutritionBo.getFrequency() / 100.0)
+                        .multiply(product.getDosePerTime()));
 
-            String packageUnit = StrUtil.emptyToDefault(packageUnitMap.get(nutrition.getPackageUnit()), StrUtil.EMPTY);
-            String productSpecUnit = StrUtil.emptyToDefault(specUnitMap.get(nutrition.getProductSpecUnit()), StrUtil.EMPTY);
-            nutritionBo.setSpecification(nutrition.getProductSpec() + productSpecUnit + "/" + packageUnit);
-            total = total.add(nutritionBo.getAmount());
-        }
-        settlement.setReceivableAmount(total);
+                    product.setTotalDose(BigDecimal.valueOf((nutritionBo.getFrequency() * (nutritionBo.getUsageDays() - 1) + nutritionBo.getFirstDay()))
+                        .multiply(product.getDosePerTime()));
 
-        if (ObjUtil.isNull(settlement.getId())) {
-            settlementMapper.insert(settlement);
-        } else {
-            settlementMapper.updateById(settlement);
+                    settlement.setStopDate(DateUtil.offsetDay(nutritionBo.getPrescriptionDate(), product.getUsageDays().intValue() - 1));
+                    product.setStopDate(settlement.getStopDate());
+                } else if (FeeType.LONG_TERM_PRESCRIPTION.getCode().equalsIgnoreCase(bo.getChargeType())) {
+                    if (ObjUtil.isNull(product.getStopDate())) {
+                        throw new ServiceException("停嘱日期不能为空");
+                    }
+                    if (ObjUtil.isNull(product.getStopDate())) {
+                        throw new ServiceException("停嘱日期不能为空");
+                    }
+                    if (ObjUtil.isNull(product.getFirstDay())) {
+                        throw new ServiceException("首日不能为空");
+                    }
+                    if (ObjUtil.isNull(nutrition.getConfigSalePrice())) {
+                        throw new ServiceException("配置销售价格不能为空");
+                    }
+                    long days = DateUtil.between(nutritionBo.getPrescriptionDate(), product.getStopDate(), DateUnit.DAY) + 1;
+                    product.setUsageDays(days);
+
+                    product.setAmount(BigDecimal.valueOf(((days - 1) * nutritionBo.getFrequency() + nutritionBo.getFirstDay()) * nutrition.getConfigSalePrice())
+                        .multiply(product.getDosePerTime()));
+                    product.setAmount(BigDecimal.ZERO.compareTo(product.getAmount()) > 0 ? BigDecimal.ZERO : product.getAmount());
+
+                    product.setDailyCalories(BigDecimal.valueOf(nutrition.getCalorie() * nutritionBo.getFrequency() / 100.0)
+                        .multiply(product.getDosePerTime()));
+
+                    settlement.setStopDate(product.getStopDate());
+                }
+                product.setDosePerDay(BigDecimal.valueOf(nutritionBo.getFrequency()).multiply(product.getDosePerTime()));
+
+                String packageUnit = StrUtil.emptyToDefault(packageUnitMap.get(nutrition.getPackageUnit()), StrUtil.EMPTY);
+                String productSpecUnit = StrUtil.emptyToDefault(specUnitMap.get(nutrition.getProductSpecUnit()), StrUtil.EMPTY);
+                product.setSpecification(nutrition.getProductSpec() + productSpecUnit + "/" + packageUnit);
+                total = total.add(product.getAmount());
+            }
         }
 
         if (CollUtil.isNotEmpty(bo.getConsumableList())) {
@@ -387,8 +423,6 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
                 if (ObjUtil.isNull(v.getQuantity())) {
                     throw new ServiceException("耗材[数量]不能为空");
                 }
-
-                v.setSettlementId(settlement.getId());
                 consumableIds.add(v.getConsumableId());
             });
 
@@ -406,13 +440,14 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
                     long days = 0L;
 
                     if (FeeType.LONG_TERM_PRESCRIPTION.getCode().equalsIgnoreCase(nutritionBo.getPrescriptionType())) {
-                        days = DateUtil.between(nutritionBo.getPrescriptionDate(), nutritionBo.getStopDate(), DateUnit.DAY);
+                        days = DateUtil.between(nutritionBo.getPrescriptionDate(), nutritionBo.getStopDate(), DateUnit.DAY) + 1;
                     } else {
                         days = nutritionBo.getUsageDays();
                     }
 
-                    v.setQuantity(BigDecimal.valueOf(days - 1).multiply(v.getDosePerDay())
-                        .add(v.getDosePerTime().multiply(BigDecimal.valueOf(v.getFirstDay()))).longValue());
+                    v.setQuantity(BigDecimal.valueOf(days - 1).multiply(BigDecimal.valueOf(v.getFrequency()))
+                        .add(BigDecimal.valueOf(v.getFirstDay())).multiply(v.getDosePerTime()).longValue());
+                    v.setQuantity(Math.max(v.getQuantity(), 0L));
                 }
 
                 if (ObjUtil.isNotNull(suppliesManage)) {
@@ -430,12 +465,47 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
                 }
 
             });
+        }
+
+
+        if (CollUtil.isNotEmpty(bo.getConsumableList())) {
+            total = total.add(BigDecimal.valueOf(bo.getConsumableList().size()));
+            for (EnteralNutritionConsumableBo enteralNutritionConsumableBo : bo.getConsumableList()) {
+                total = total.add(enteralNutritionConsumableBo.getAmount());
+            }
+        }
+        settlement.setReceivableAmount(total);
+        if (ObjUtil.isNull(settlement.getId())) {
+            settlementMapper.insert(settlement);
+        } else {
+            settlementMapper.updateById(settlement);
+        }
+
+        if (CollUtil.isNotEmpty(bo.getConsumableList())) {
+            bo.getConsumableList().forEach(v -> {
+                v.setSettlementId(settlement.getId());
+            });
             consumableMapper.insertBatch(MapstructUtils.convert(bo.getConsumableList(), EnteralNutritionConsumable.class));
         }
 
         bo.setSettlementId(settlement.getId());
-        bo.getNutritionList().forEach(v -> v.setSettlementId(settlement.getId()));
-        baseMapper.insertBatch(MapstructUtils.convert(bo.getNutritionList(), EnteralNutrition.class));
+
+        if (FeeType.PRE_PACKAGED_PRESCRIPTION.getCode().equalsIgnoreCase(bo.getChargeType())) {
+            bo.getNutritionList().forEach(v -> {
+                v.setSettlementId(settlement.getId());
+            });
+            baseMapper.insertBatch(MapstructUtils.convert(bo.getNutritionList(), EnteralNutrition.class));
+        } else {
+            List<EnteralNutritionBo> productList = CollUtil.newArrayList();
+            bo.getNutritionList().forEach(v -> {
+                v.getProducts().forEach(p -> {
+                    productList.add(p);
+                    p.setSettlementId(settlement.getId());
+                });
+            });
+
+            baseMapper.insertBatch(MapstructUtils.convert(productList, EnteralNutrition.class));
+        }
     }
 
 
@@ -477,6 +547,9 @@ public class EnteralNutritionServiceImpl implements IEnteralNutritionService {
         if (isValid) {
             //TODO 做一些业务上的校验,判断是否需要校验
         }
-        return baseMapper.deleteByIds(ids) > 0;
+        int cnt = settlementMapper.update(Wrappers.lambdaUpdate(Settlement.class)
+            .set(Settlement::getDelFlag, DelFlag.YES.getCode())
+            .in(Settlement::getId, ids));
+        return cnt > 0;
     }
 }

+ 8 - 0
ruoyi-admin/src/main/java/org/dromara/web/service/impl/ProductNutritionServiceImpl.java

@@ -32,6 +32,7 @@ import org.dromara.web.domain.bo.BatchProductNuyritionBo;
 import org.dromara.web.domain.bo.ProductNutritionBo;
 import org.dromara.web.domain.vo.ProductCategoryVo;
 import org.dromara.web.domain.vo.ProductNutritionVo;
+import org.dromara.web.mapper.ProductCategoryMapper;
 import org.dromara.web.mapper.ProductNutritionMapper;
 import org.dromara.web.service.IProductCategoryService;
 import org.dromara.web.service.IProductNutritionService;
@@ -61,6 +62,8 @@ public class ProductNutritionServiceImpl implements IProductNutritionService {
 
     private final IProductCategoryService categoryService;
 
+    private final ProductCategoryMapper productCategoryMapper;
+
     private final ISysDiseaseLabelService diseaseLabelService;
 
     private final ISysDictDataService dataService;
@@ -187,6 +190,11 @@ public class ProductNutritionServiceImpl implements IProductNutritionService {
             Map<String, String> specUnitMap = dictMap.get(BizConst.PRODUCT_SPEC_UNIT).stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2.getDictLabel(), (k1, k2) -> k1));
             Map<String, String> packageUnitMap = dictMap.get(BizConst.PRODUCT_PACKAGE_UNIT).stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2.getDictLabel(), (k1, k2) -> k1));
 
+            dataList.stream().map(ProductNutritionVo::getProductCategory).collect(Collectors.toSet());
+            productCategoryMapper.selectList(Wrappers.lambdaQuery(ProductCategory.class)
+                .select(ProductCategory::getCategoryName, ProductCategory::getCategoryId)
+                .in(ProductCategory::getCategoryId, dataList.stream().map(ProductNutritionVo::getProductCategory).collect(Collectors.toSet())));
+
             dataList.forEach(v -> {
                 String packageUnit = StrUtil.emptyToDefault(packageUnitMap.get(v.getPackageUnit()), StrUtil.EMPTY);
                 String productSpecUnit = StrUtil.emptyToDefault(specUnitMap.get(v.getProductSpecUnit()), StrUtil.EMPTY);

+ 1 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -1,7 +1,7 @@
 # 开发环境配置
 server:
   # 服务器的HTTP端口,默认为8080
-  port: 8080
+  port: 8081
   servlet:
     # 应用的访问路径
     context-path: /

+ 2 - 1
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/biz/PaymentStatus.java

@@ -10,7 +10,8 @@ import lombok.Getter;
 public enum PaymentStatus {
     UNPAID("0", "未支付"),
     PAID("1", "已支付"),
-    REFUNDED("2", "已退款");
+    REFUNDED("2", "已退款"),
+    EXPIRED("3", "已失效");
 
     private String code;
     private String remark;

+ 19 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysScreeningAssessmentConfigController.java

@@ -2,6 +2,7 @@ package org.dromara.system.controller.system;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.util.ObjUtil;
+import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
@@ -28,7 +29,9 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -114,6 +117,15 @@ public class SysScreeningAssessmentConfigController extends BaseController {
         return toAjax(sysScreeningAssessmentConfigService.updateByBo(bo));
     }
 
+
+    @SaCheckPermission("system:screeningAssessmentConfig:edit")
+    @Log(title = "筛查/评估配置", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PostMapping("/editConclusion")
+    public R<Void> editConclusion(@RequestBody SysScreeningAssessmentConfigBo bo) {
+        return toAjax(sysScreeningAssessmentConfigService.editConclusion(bo));
+    }
+
     /**
      * 删除筛查/评估配置
      *
@@ -126,4 +138,11 @@ public class SysScreeningAssessmentConfigController extends BaseController {
                           @PathVariable Long[] configIds) {
         return toAjax(sysScreeningAssessmentConfigService.deleteWithValidByIds(List.of(configIds), true));
     }
+
+
+    @SaCheckPermission("system:diseaseLabel:import")
+    @RequestMapping(value = "/importFile", method = RequestMethod.POST)
+    public R<?> importExcel(MultipartFile file, HttpServletRequest request) throws Exception {
+        return sysScreeningAssessmentConfigService.importFile(file, request.getParameter("type"));
+    }
 }

+ 13 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysScreeningAssessmentConfig.java

@@ -57,6 +57,19 @@ public class SysScreeningAssessmentConfig extends TenantEntity {
      */
     private String remark;
 
+    /**
+     * 结论
+     */
+    private String conclusion;
+    /**
+     * 来源
+     */
+    private String source;
+    /**
+     * 目的
+     */
+    private String purpose;
+
     /**
      * 状态(0正常 1停用)
      */

+ 13 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysScreeningAssessmentConfigBo.java

@@ -60,6 +60,19 @@ public class SysScreeningAssessmentConfigBo extends BaseEntity {
      */
     private String remark;
 
+    /**
+     * 结论
+     */
+    private String conclusion;
+    /**
+     * 来源
+     */
+    private String source;
+    /**
+     * 目的
+     */
+    private String purpose;
+
     /**
      * 状态(0正常 1停用)
      */

+ 5 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysScreeningAssessmentQuestionBo.java

@@ -30,6 +30,11 @@ public class SysScreeningAssessmentQuestionBo extends BaseEntity {
     @NotNull(message = "主键ID不能为空", groups = {EditGroup.class})
     private Long questionId;
 
+    /**
+     * 导入数据使用
+     */
+    private String qId;
+
     /**
      * 主键ID
      */

+ 15 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysScreeningAssessmentConfigVo.java

@@ -73,6 +73,21 @@ public class SysScreeningAssessmentConfigVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+
+    /**
+     * 结论
+     */
+    private String conclusion;
+    /**
+     * 来源
+     */
+    private String source;
+    /**
+     * 目的
+     */
+    private String purpose;
+
+
     /**
      * 状态(0正常 1停用)
      */

+ 7 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysScreeningAssessmentConfigService.java

@@ -1,9 +1,11 @@
 package org.dromara.system.service;
 
+import org.dromara.common.core.domain.R;
 import org.dromara.system.domain.vo.SysScreeningAssessmentConfigVo;
 import org.dromara.system.domain.bo.SysScreeningAssessmentConfigBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.Collection;
 import java.util.List;
@@ -16,6 +18,7 @@ import java.util.List;
  */
 public interface ISysScreeningAssessmentConfigService {
     int updateConfigStatus(List<Long> configIdIds, String status);
+
     /**
      * 查询筛查/评估配置
      *
@@ -57,6 +60,8 @@ public interface ISysScreeningAssessmentConfigService {
      */
     Boolean updateByBo(SysScreeningAssessmentConfigBo bo);
 
+    Boolean editConclusion(SysScreeningAssessmentConfigBo bo);
+
     /**
      * 校验并批量删除筛查/评估配置信息
      *
@@ -65,4 +70,6 @@ public interface ISysScreeningAssessmentConfigService {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    R<?> importFile(MultipartFile file, String configType) throws Exception;
 }

+ 140 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysScreeningAssessmentConfigServiceImpl.java

@@ -1,14 +1,22 @@
 package org.dromara.system.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.aspectj.weaver.ast.Or;
 import org.dromara.common.core.constant.BizConst;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.enums.biz.QuestionsList;
 import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StreamUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -34,7 +42,10 @@ import org.dromara.system.domain.SysScreeningAssessmentConfig;
 import org.dromara.system.mapper.SysScreeningAssessmentConfigMapper;
 import org.dromara.system.service.ISysScreeningAssessmentConfigService;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Collection;
@@ -152,7 +163,7 @@ public class SysScreeningAssessmentConfigServiceImpl implements ISysScreeningAss
     private LambdaQueryWrapper<SysScreeningAssessmentConfig> buildQueryWrapper(SysScreeningAssessmentConfigBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<SysScreeningAssessmentConfig> lqw = Wrappers.lambdaQuery();
-        lqw.orderByAsc(SysScreeningAssessmentConfig::getConfigId);
+        lqw.orderByDesc(SysScreeningAssessmentConfig::getConfigId);
         lqw.eq(StringUtils.isNotBlank(bo.getType()), SysScreeningAssessmentConfig::getType, bo.getType());
         lqw.eq(StringUtils.isNotBlank(bo.getGender()), SysScreeningAssessmentConfig::getGender, bo.getGender());
         lqw.eq(StringUtils.isNotBlank(bo.getAge()), SysScreeningAssessmentConfig::getAge, bo.getAge());
@@ -198,6 +209,13 @@ public class SysScreeningAssessmentConfigServiceImpl implements ISysScreeningAss
         return flag;
     }
 
+    @Override
+    public Boolean editConclusion(SysScreeningAssessmentConfigBo bo) {
+        SysScreeningAssessmentConfig update = MapstructUtils.convert(bo, SysScreeningAssessmentConfig.class);
+        boolean flag = baseMapper.updateById(update) > 0;
+        return flag;
+    }
+
     /**
      * 修改筛查/评估配置
      *
@@ -258,4 +276,125 @@ public class SysScreeningAssessmentConfigServiceImpl implements ISysScreeningAss
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    private void setQId(SysScreeningAssessmentQuestionBo questionBo, JSONObject question) {
+        if (question.containsKey("id")) {
+            questionBo.setQId(question.getString("id"));
+        } else if (question.containsKey("questionId")) {
+            questionBo.setQId(question.getString("questionId"));
+        } else if (question.containsKey("question_id")) {
+            questionBo.setQId(question.getString("question_id"));
+        } else if (question.containsKey("question_id")) {
+            questionBo.setQId(question.getString("question_id"));
+        }
+    }
+
+    @Override
+    public R<?> importFile(MultipartFile file, String configType) throws Exception {
+        if (ObjUtil.isNull(file)) {
+            return R.fail("请选择文件!");
+        }
+
+        String content = IoUtil.read(file.getInputStream(), StandardCharsets.UTF_8);
+        JSONObject jsonObject = JSON.parseObject(content);
+
+        SysScreeningAssessmentConfigBo config = new SysScreeningAssessmentConfigBo();
+        config.setName(jsonObject.getString("title"));
+        config.setPurpose(jsonObject.getString("purpose"));
+        config.setSource(jsonObject.getString("source"));
+        config.setType(configType);
+
+        if (jsonObject.containsKey("scoring")) {
+            config.setConclusion(JSON.toJSONString(jsonObject.getJSONObject("scoring")));
+        } else if (jsonObject.containsKey("scoring_rules")) {
+            config.setConclusion(JSON.toJSONString(jsonObject.getJSONObject("scoring_rules")));
+        } else if (jsonObject.containsKey("scoringRules")) {
+            config.setConclusion(JSON.toJSONString(jsonObject.getJSONObject("scoringRules")));
+        }
+
+        JSONArray questions = jsonObject.getJSONArray("questions");
+        List<SysScreeningAssessmentQuestionBo> otherInfo = new ArrayList<>(questions.size());
+        config.setOtherInfo(otherInfo);
+
+        for (int i = 0, len = questions.size(); i < len; i++) {
+            JSONObject question = questions.getJSONObject(i);
+            String type = question.getString("type");
+            if ("单选".equals(type) || "多选".equals(type)) {
+                SysScreeningAssessmentQuestionBo questionBo = new SysScreeningAssessmentQuestionBo();
+                otherInfo.add(questionBo);
+
+                questionBo.setTitle(question.getString("text"));
+                setQId(questionBo, question);
+                questionBo.setArrangement("2");
+                if ("单选".equals(type)) {
+                    questionBo.setQuestionType(QuestionsList.QUESTION_TYPE_SELECTION.getCode());
+                    questionBo.setQuestionChildType(QuestionsList.SINGLE_CHOICE.getCode());
+                } else if ("多选".equals(type)) {
+                    questionBo.setQuestionType(QuestionsList.QUESTION_TYPE_SELECTION.getCode());
+                    questionBo.setQuestionChildType(QuestionsList.MULTIPLE_CHOICE.getCode());
+                }
+                questionBo.setRequired(Boolean.TRUE);
+
+                JSONArray options = question.getJSONArray("options");
+                List<SysScreeningAssessmentQuestionBo.QuestionAttrBo> contentList = CollUtil.newArrayList();
+                for (int j = 0, len2 = options.size(); j < len2; j++) {
+                    SysScreeningAssessmentQuestionBo.QuestionAttrBo questionAttrBo = new SysScreeningAssessmentQuestionBo.QuestionAttrBo();
+                    JSONObject op = options.getJSONObject(j);
+                    questionAttrBo.setLabel(StrUtil.emptyToDefault(op.getString("text"), op.getString("input_tex")));
+                    questionAttrBo.setScore(op.getString("score"));
+                    if ("单选".equals(type)) {
+                        questionAttrBo.setNameEn("single" + j);
+                    } else if ("多选".equals(type)) {
+                        questionAttrBo.setNameEn("multiple" + j);
+                    }
+                    questionAttrBo.setAllowFillBlank(Boolean.FALSE);
+                    contentList.add(questionAttrBo);
+                }
+                questionBo.setContentList(contentList);
+                questionBo.setContent(JSON.toJSONString(contentList));
+            } else if ("是/否".equals(type)) {
+                SysScreeningAssessmentQuestionBo questionBo = new SysScreeningAssessmentQuestionBo();
+                otherInfo.add(questionBo);
+
+                questionBo.setTitle(question.getString("text"));
+                questionBo.setArrangement("2");
+                setQId(questionBo, question);
+                questionBo.setQuestionType(QuestionsList.QUESTION_TYPE_SELECTION.getCode());
+                questionBo.setQuestionChildType(QuestionsList.SINGLE_CHOICE.getCode());
+                questionBo.setRequired(Boolean.TRUE);
+                JSONArray options = question.getJSONArray("options");
+                List<SysScreeningAssessmentQuestionBo.QuestionAttrBo> contentList = CollUtil.newArrayList();
+
+                if (CollUtil.isNotEmpty(options)) {
+                    for (int j = 0, len2 = options.size(); j < len2; j++) {
+                        SysScreeningAssessmentQuestionBo.QuestionAttrBo questionAttrBo = new SysScreeningAssessmentQuestionBo.QuestionAttrBo();
+                        JSONObject op = options.getJSONObject(j);
+                        questionAttrBo.setLabel(StrUtil.emptyToDefault(op.getString("text"), op.getString("input_tex")));
+                        questionAttrBo.setScore(op.getString("score"));
+                        questionAttrBo.setNameEn("single" + j);
+                        questionAttrBo.setAllowFillBlank(Boolean.FALSE);
+                        contentList.add(questionAttrBo);
+                    }
+                } else {
+                    SysScreeningAssessmentQuestionBo.QuestionAttrBo questionAttrBo = new SysScreeningAssessmentQuestionBo.QuestionAttrBo();
+                    questionAttrBo.setLabel("是");
+                    questionAttrBo.setScore("0");
+                    questionAttrBo.setNameEn("single1");
+                    questionAttrBo.setAllowFillBlank(Boolean.FALSE);
+                    contentList.add(questionAttrBo);
+                    questionAttrBo = new SysScreeningAssessmentQuestionBo.QuestionAttrBo();
+                    questionAttrBo.setLabel("否");
+                    questionAttrBo.setScore("0");
+                    questionAttrBo.setNameEn("single0");
+                    questionAttrBo.setAllowFillBlank(Boolean.FALSE);
+                    contentList.add(questionAttrBo);
+                }
+                questionBo.setContentList(contentList);
+                questionBo.setContent(JSON.toJSONString(contentList));
+            }
+        }
+
+        insertByBo(config);
+        return R.ok("导入成功");
+    }
 }

+ 4 - 0
script/sql/biz/create.sql

@@ -198,6 +198,10 @@ CREATE TABLE sys_screening_assessment_config (
     description   VARCHAR(300) DEFAULT NULL COMMENT '量表说明',
     remark        text DEFAULT NULL COMMENT '备注',
 
+    conclusion  text DEFAULT NULL COMMENT '结论',
+    source  VARCHAR(300) DEFAULT NULL COMMENT '来源',
+    purpose  VARCHAR(300) DEFAULT NULL COMMENT '目的',
+
     -- 系统字段
     status CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)',
     del_flag char default '0' null comment '删除标志(0代表存在 1代表删除)',