已修改7个文件
已添加1个文件
514 ■■■■■ 文件已修改
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/AmountUtils.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-gzdz.yml 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -398,12 +398,15 @@
            }
            for (CustomerTransactionsVo vo : records) {
                BigDecimal outboundAmount = shippedAmountMap.getOrDefault(vo.getCustomerId(), BigDecimal.ZERO);
                vo.setShippedAmount(outboundAmount);
                BigDecimal contractAmounts = vo.getContractAmounts() == null ? BigDecimal.ZERO : vo.getContractAmounts();
                BigDecimal unshippedAmount = contractAmounts.subtract(outboundAmount);
                BigDecimal contractAmounts = AmountUtils.scaleMoney(vo.getContractAmounts());
                // å·²å‡ºåº“金额按分(2位小数)处理,避免按含税单价累计出库金额产生误差导致全部发货后仍有未出库零头
                BigDecimal shippedAmount = AmountUtils.scaleMoney(outboundAmount);
                BigDecimal unshippedAmount = contractAmounts.subtract(shippedAmount);
                if (unshippedAmount.compareTo(BigDecimal.ZERO) < 0) {
                    unshippedAmount = BigDecimal.ZERO;
                }
                vo.setContractAmounts(contractAmounts);
                vo.setShippedAmount(shippedAmount);
                vo.setUnshippedAmount(unshippedAmount);
                AmountUtils.normalizeCustomerTransaction(vo);
            }
@@ -426,12 +429,15 @@
            }
            for (CustomerTransactionsDetailsVo vo : records) {
                BigDecimal outboundAmount = shippedAmountMap.getOrDefault(vo.getSalesLedgerId(), BigDecimal.ZERO);
                vo.setShippedAmount(outboundAmount);
                BigDecimal contractAmount = vo.getContractAmount() == null ? BigDecimal.ZERO : vo.getContractAmount();
                BigDecimal unshippedAmount = contractAmount.subtract(outboundAmount);
                BigDecimal contractAmount = AmountUtils.scaleMoney(vo.getContractAmount());
                // å·²å‡ºåº“金额按分(2位小数)处理,避免按含税单价累计出库金额产生误差导致全部发货后仍有未出库零头
                BigDecimal shippedAmount = AmountUtils.scaleMoney(outboundAmount);
                BigDecimal unshippedAmount = contractAmount.subtract(shippedAmount);
                if (unshippedAmount.compareTo(BigDecimal.ZERO) < 0) {
                    unshippedAmount = BigDecimal.ZERO;
                }
                vo.setContractAmount(contractAmount);
                vo.setShippedAmount(shippedAmount);
                vo.setUnshippedAmount(unshippedAmount);
                AmountUtils.normalizeCustomerTransactionDetail(vo);
            }
src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
@@ -226,11 +226,9 @@
                List<StockInRecord> currentDirectRecords = directInboundRecords.stream().filter(s -> s.getRecordId().equals(ledgerId)).toList();
                for (StockInRecord sir : currentDirectRecords) {
                    List<SalesLedgerProduct> currentProducts = salesLedgerProducts.stream().filter(s -> s.getSalesLedgerId().equals(ledgerId)).toList();
                    for (SalesLedgerProduct slp : currentProducts) {
                        if (sir.getStockInNum() != null && slp.getTaxInclusiveUnitPrice() != null) {
                            shippedAmount = shippedAmount.add(sir.getStockInNum().multiply(slp.getTaxInclusiveUnitPrice()));
                        }
                    BigDecimal unitPrice = getPurchaseInboundUnitPrice(salesLedgerProducts, ledgerId, sir);
                    if (sir.getStockInNum() != null && unitPrice != null) {
                        shippedAmount = shippedAmount.add(sir.getStockInNum().multiply(unitPrice));
                    }
                }
@@ -323,11 +321,9 @@
            List<StockInRecord> currentDirectRecords = directInboundRecords.stream().filter(s -> s.getRecordId().equals(vo.getPurchaseLedgerId())).toList();
            for (StockInRecord sir : currentDirectRecords) {
                List<SalesLedgerProduct> currentProducts = salesLedgerProducts.stream().filter(s -> s.getSalesLedgerId().equals(vo.getPurchaseLedgerId())).toList();
                for (SalesLedgerProduct slp : currentProducts) {
                    if (sir.getStockInNum() != null && slp.getTaxInclusiveUnitPrice() != null) {
                        shippedAmount = shippedAmount.add(sir.getStockInNum().multiply(slp.getTaxInclusiveUnitPrice()));
                    }
                BigDecimal unitPrice = getPurchaseInboundUnitPrice(salesLedgerProducts, vo.getPurchaseLedgerId(), sir);
                if (sir.getStockInNum() != null && unitPrice != null) {
                    shippedAmount = shippedAmount.add(sir.getStockInNum().multiply(unitPrice));
                }
            }
@@ -373,4 +369,29 @@
                .min(BigDecimal::compareTo)
                .orElse(null);
    }
    /**
     * ç›´æŽ¥å…¥åº“记录(7)的含税单价:批次号格式为“采购合同号-采购产品行ID”,按对应产品行取价
     */
    private BigDecimal getPurchaseInboundUnitPrice(List<SalesLedgerProduct> allSlp, Long salesLedgerId, StockInRecord record) {
        String batchNo = record.getBatchNo();
        int separatorIndex = batchNo == null ? -1 : batchNo.lastIndexOf('-');
        if (separatorIndex > -1) {
            try {
                Long productId = Long.valueOf(batchNo.substring(separatorIndex + 1));
                BigDecimal unitPrice = allSlp.stream()
                        .filter(s -> s.getId().equals(productId))
                        .map(SalesLedgerProduct::getTaxInclusiveUnitPrice)
                        .filter(java.util.Objects::nonNull)
                        .findFirst()
                        .orElse(null);
                if (unitPrice != null) {
                    return unitPrice;
                }
            } catch (NumberFormatException ignored) {
                // æ‰¹æ¬¡å·ä¸ç¬¦åˆçº¦å®šæ ¼å¼ï¼Œå›žé€€æŒ‰äº§å“è§„格匹配
            }
        }
        return getMinTaxInclusiveUnitPrice(allSlp, salesLedgerId, record.getProductModelId());
    }
}
src/main/java/com/ruoyi/common/utils/AmountUtils.java
@@ -13,12 +13,15 @@
import java.util.List;
/**
 * é‡‘额精度工具:统一保留 6 ä½å°æ•°
 * é‡‘额精度工具:默认统一保留 6 ä½å°æ•°ï¼Œé‡‘额(元)保留 2 ä½å°æ•°
 */
public final class AmountUtils {
    public static final int AMOUNT_SCALE = 6;
    public static final RoundingMode AMOUNT_ROUNDING = RoundingMode.HALF_UP;
    /** é‡‘额(元)保留小数位数(分) */
    public static final int MONEY_SCALE = 2;
    private AmountUtils() {
    }
@@ -28,6 +31,17 @@
            return BigDecimal.ZERO.setScale(AMOUNT_SCALE, AMOUNT_ROUNDING);
        }
        return value.setScale(AMOUNT_SCALE, AMOUNT_ROUNDING);
    }
    /**
     * é‡‘额(元)精度处理:四舍五入保留 2 ä½å°æ•°ï¼Œ
     * é¿å…æŒ‰å«ç¨Žå•价累计出库金额时产生误差,全部发货后仍显示未出库零头
     */
    public static BigDecimal scaleMoney(BigDecimal value) {
        if (value == null) {
            return BigDecimal.ZERO.setScale(MONEY_SCALE, AMOUNT_ROUNDING);
        }
        return value.setScale(MONEY_SCALE, AMOUNT_ROUNDING);
    }
    public static BigDecimal calcTaxExclusiveTotalPrice(BigDecimal taxInclusiveTotalPrice, BigDecimal taxRate) {
@@ -92,18 +106,18 @@
        if (vo == null) {
            return;
        }
        vo.setContractAmounts(scaleAmount(vo.getContractAmounts()));
        vo.setShippedAmount(scaleAmount(vo.getShippedAmount()));
        vo.setUnshippedAmount(scaleAmount(vo.getUnshippedAmount()));
        vo.setContractAmounts(scaleMoney(vo.getContractAmounts()));
        vo.setShippedAmount(scaleMoney(vo.getShippedAmount()));
        vo.setUnshippedAmount(scaleMoney(vo.getUnshippedAmount()));
    }
    public static void normalizeCustomerTransactionDetail(CustomerTransactionsDetailsVo vo) {
        if (vo == null) {
            return;
        }
        vo.setContractAmount(scaleAmount(vo.getContractAmount()));
        vo.setShippedAmount(scaleAmount(vo.getShippedAmount()));
        vo.setUnshippedAmount(scaleAmount(vo.getUnshippedAmount()));
        vo.setContractAmount(scaleMoney(vo.getContractAmount()));
        vo.setShippedAmount(scaleMoney(vo.getShippedAmount()));
        vo.setUnshippedAmount(scaleMoney(vo.getUnshippedAmount()));
    }
    public static void normalizeProcurementBusinessSummary(ProcurementBusinessSummaryDto dto) {
src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -845,8 +845,17 @@
                // éåŽ†å¤„ç†æ•°æ®å¹¶ç»„è£…ç»“æžœ
                : workOrderPage.getRecords().stream()
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(ProductionOperationTaskVo::getId, Comparator.nullsLast(Comparator.naturalOrder())))
                .toList();
        if (!workOrderList.isEmpty()) {
            // å·¥åºè¿›åº¦éœ€è¦æŒ‰å·¥è‰ºè·¯çº¿å·¥åºé¡ºåºï¼ˆdrag_sort å‡åºï¼‰ä»Žå·¦åˆ°å³å±•示,任务 id ä»…作为兜底排序
            Map<Long, Integer> routingOperationDragSortMap = loadRoutingOperationDragSortMap(workOrderList);
            Comparator<ProductionOperationTaskVo> workOrderComparator = Comparator
                    .comparing((ProductionOperationTaskVo task) -> routingOperationDragSortMap.get(task.getProductionOrderRoutingOperationId()),
                            Comparator.nullsLast(Comparator.<Integer>naturalOrder()))
                    .thenComparing(ProductionOperationTaskVo::getId,
                            Comparator.nullsLast(Comparator.<Long>naturalOrder()));
            workOrderList = workOrderList.stream().sorted(workOrderComparator).toList();
        }
        if (workOrderList.isEmpty()) {
            detailVo.setWorkOrderList(Collections.emptyList());
            return detailVo;
@@ -995,6 +1004,23 @@
        return detailVo;
    }
    /**
     * æŸ¥è¯¢å·¥å•对应工艺路线工序的拖动排序,用于按工序先后顺序展示工序进度
     */
    private Map<Long, Integer> loadRoutingOperationDragSortMap(List<ProductionOperationTaskVo> workOrderList) {
        Set<Long> routingOperationIds = workOrderList.stream()
                .map(ProductionOperationTaskVo::getProductionOrderRoutingOperationId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        if (routingOperationIds.isEmpty()) {
            return Collections.emptyMap();
        }
        return productionOrderRoutingOperationMapper.selectBatchIds(routingOperationIds).stream()
                .filter(Objects::nonNull)
                .filter(operation -> operation.getId() != null && operation.getDragSort() != null)
                .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, ProductionOrderRoutingOperation::getDragSort, (a, b) -> a));
    }
    private Long resolveProductionOrderId(ProductionOrderDto dto) {
        // ä»Žå…¥å‚中解析生产订单ID并校验
        if (dto == null) {
src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
@@ -123,9 +123,9 @@
        if (assignedQuantity == null || assignedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("下发失败,下发数量必须大于0");
        }
        if (assignedQuantity.compareTo(totalRequiredQuantity) > 0) {
            throw new ServiceException("下发失败,下发数量不能大于计划剩余需求总量");
        }
//        if (assignedQuantity.compareTo(totalRequiredQuantity) > 0) {
//            throw new ServiceException("下发失败,下发数量不能大于计划剩余需求总量");
//        }
        // æŒ‰è®¡åˆ’顺序分摊下发数量,收集实际参与下发的计划 ID
        BigDecimal remainingForOrderBind = assignedQuantity;
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -592,9 +592,9 @@
                    salesLedgerProduct.setApproveStatus(0);
                    // æ˜¯å¦è´¨æ£€åˆ¤æ–­
                    salesLedgerProduct.setIsChecked(salesLedgerProductImportDto.getIsChecked() == 1);
                    if(salesLedgerProductImportDto.getIsChecked() == 1){
                        addQualityInspect(salesLedger, salesLedgerProduct);
                    }
                    //if(salesLedgerProductImportDto.getIsChecked() == 1){
                    //    addQualityInspect(salesLedger, salesLedgerProduct);
                    //}
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                }
                // é‡‡è´­å®¡æ ¸
src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
@@ -20,10 +20,14 @@
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@@ -123,32 +127,59 @@
        if (technologyRouting.getBomId() == null) {
            return;
        }
        List<TechnologyBomStructure> bomStructures = technologyBomStructureMapper.selectList(
                Wrappers.<TechnologyBomStructure>lambdaQuery()
                        .eq(TechnologyBomStructure::getBomId, technologyRouting.getBomId())
                        .isNotNull(TechnologyBomStructure::getOperationId)
                        .orderByDesc(TechnologyBomStructure::getId)
                        .orderByAsc(TechnologyBomStructure::getId)
        );
        if (bomStructures.isEmpty()) {
            throw new ServiceException("bom产品结构为空!");
        }
        // åŒä¸€ä¸ª BOM ä¸­å¯èƒ½é‡å¤å¼•用相同工序,按照上一层的父节点的产品是否相同和工序是否相同
        Map<Long, TechnologyBomStructure> structureById = new HashMap<>();
        Map<Long, List<TechnologyBomStructure>> childrenByParentId = new LinkedHashMap<>();
        List<TechnologyBomStructure> rootList = new ArrayList<>();
        for (TechnologyBomStructure bomStructure : bomStructures) {
            if (bomStructure != null && bomStructure.getId() != null) {
            if (bomStructure == null) {
                continue;
            }
            if (bomStructure.getId() != null) {
                structureById.put(bomStructure.getId(), bomStructure);
            }
            if (bomStructure.getParentId() == null || bomStructure.getParentId() == 0L) {
                rootList.add(bomStructure);
            } else {
                childrenByParentId.computeIfAbsent(bomStructure.getParentId(), key -> new ArrayList<>()).add(bomStructure);
            }
        }
        Map<String, TechnologyBomStructure> uniqueOperationMap = new LinkedHashMap<>();
        for (TechnologyBomStructure bomStructure : bomStructures) {
            Long outputProductModelId = resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId());
            uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure);
        // åŽåºéåކBOM
        List<TechnologyBomStructure> orderedOperationNodes = new ArrayList<>();
        Set<Long> visitingIds = new HashSet<>();
        for (TechnologyBomStructure rootNode : rootList) {
            collectOperationNodePostOrder(rootNode, childrenByParentId, orderedOperationNodes, visitingIds);
        }
        if (orderedOperationNodes.isEmpty()) {
            throw new ServiceException("bom产品结构未配置消耗工序!");
        }
        // åŒä¸€å±‚级(同一父节点)内相同工序合并为一道工序,例如同层的多个压接件合并成一道压接;
        // åˆå¹¶åŽçš„位置取该工序最后一次出现的位置,确保其全部输入物料的工序都在它之前
        Map<String, Integer> lastPositionByKey = new HashMap<>();
        Map<String, TechnologyBomStructure> operationNodeByKey = new LinkedHashMap<>();
        for (int i = 0; i < orderedOperationNodes.size(); i++) {
            TechnologyBomStructure bomStructure = orderedOperationNodes.get(i);
            String dedupKey = buildBomOperationDedupKey(bomStructure);
            lastPositionByKey.put(dedupKey, i);
            operationNodeByKey.putIfAbsent(dedupKey, bomStructure);
        }
        List<String> sortedDedupKeys = new ArrayList<>(operationNodeByKey.keySet());
        sortedDedupKeys.sort(Comparator.comparingInt(lastPositionByKey::get));
        int dragSort = 1;
        for (TechnologyBomStructure bomStructure : uniqueOperationMap.values()) {
        for (String dedupKey : sortedDedupKeys) {
            TechnologyBomStructure bomStructure = operationNodeByKey.get(dedupKey);
            TechnologyRoutingOperation routingOperation = new TechnologyRoutingOperation();
            routingOperation.setTechnologyRoutingId(technologyRouting.getId());
            routingOperation.setProductModelId(resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId()));
@@ -163,42 +194,61 @@
        }
    }
    private String buildBomOperationDedupKey(TechnologyBomStructure bomStructure, Long outputProductModelId) {
        Long operationId = bomStructure == null ? null : bomStructure.getOperationId();
        Long parentId = bomStructure == null ? null : bomStructure.getParentId();
        return operationId + "#"
                + outputProductModelId + "#"
                + parentId;
    /**
     * åŽåºéåކ BOM
     */
    private void collectOperationNodePostOrder(TechnologyBomStructure node,
                                               Map<Long, List<TechnologyBomStructure>> childrenByParentId,
                                               List<TechnologyBomStructure> orderedOperationNodes,
                                               Set<Long> visitingIds) {
        if (node == null || node.getId() == null) {
            return;
        }
        if (!visitingIds.add(node.getId())) {
            return;
        }
        List<TechnologyBomStructure> children = childrenByParentId.get(node.getId());
        if (children != null && !children.isEmpty()) {
            for (TechnologyBomStructure child : children) {
                collectOperationNodePostOrder(child, childrenByParentId, orderedOperationNodes, visitingIds);
            }
        }
        visitingIds.remove(node.getId());
        if (node.getOperationId() != null) {
            orderedOperationNodes.add(node);
        }
    }
    /**
     * åŽ»é‡é”®ï¼šåŒä¸€çˆ¶èŠ‚ç‚¹ + ç›¸åŒå·¥åºï¼ˆåªåœ¨åŒä¸€å±‚级内合并,不同层级、不同分支的相同工序不会合并)。
     */
    private String buildBomOperationDedupKey(TechnologyBomStructure bomStructure) {
        Long operationId = bomStructure == null ? null : bomStructure.getOperationId();
        Long parentId = bomStructure == null ? null : bomStructure.getParentId();
        return operationId + "#" + (parentId == null ? "root" : String.valueOf(parentId));
    }
    /**
     * å·¥åºäº§å‡ºäº§å“ = çˆ¶èŠ‚ç‚¹çš„äº§å“ï¼ˆæœ¬è¡Œç‰©æ–™ç”±çˆ¶èŠ‚ç‚¹å±‚çº§çš„æ¶ˆè€—å·¥åºæ¶ˆè€—ï¼Œäº§å‡ºçš„æ˜¯ä¸Šä¸€å±‚äº§å“ï¼Œ
     * è€Œä¸æ˜¯æœ¬è¡Œç‰©æ–™è‡ªèº«ï¼‰ï¼›ä»…当父节点缺失或父节点没有产品时,才回退到本节点自身产品、再回退到工艺路线产品。
     */
    private Long resolveOutputProductModelId(TechnologyBomStructure bomStructure,
                                             Map<Long, TechnologyBomStructure> structureById,
                                             Long routingProductModelId) {
        if (bomStructure == null) {
            return routingProductModelId;
        }
        if (hasChildren(bomStructure, structureById)) {
            return bomStructure.getProductModelId() != null
                    ? bomStructure.getProductModelId() : routingProductModelId;
        }
        Long parentId = bomStructure.getParentId();
        if (parentId == null) {
            return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
        if (parentId != null && parentId != 0L && structureById != null) {
            TechnologyBomStructure parent = structureById.get(parentId);
            if (parent != null && parent.getProductModelId() != null) {
                return parent.getProductModelId();
            }
        }
        TechnologyBomStructure parent = structureById.get(parentId);
        if (parent != null && parent.getProductModelId() != null) {
            return parent.getProductModelId();
        if (bomStructure.getProductModelId() != null) {
            return bomStructure.getProductModelId();
        }
        return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
    }
    private boolean hasChildren(TechnologyBomStructure bomStructure,
                                Map<Long, TechnologyBomStructure> structureById) {
        if (bomStructure == null || bomStructure.getId() == null || structureById == null) {
            return false;
        }
        return structureById.values().stream()
                .anyMatch(child -> child != null && java.util.Objects.equals(child.getParentId(), bomStructure.getId()));
        return routingProductModelId;
    }
    private void syncRoutingOperationParams(Long technologyRoutingOperationId, Long technologyOperationId) {
src/main/resources/application-gzdz.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,269 @@
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  # åç§°
  name: RuoYi
  # ç‰ˆæœ¬
  version: 3.8.9
  # ç‰ˆæƒå¹´ä»½
  copyrightYear: 2025
  # æ–‡ä»¶è·¯å¾„ ç¤ºä¾‹ï¼ˆ Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: /data/javaWork/product-inventory-management/file
  # èŽ·å–ip地址开关
  addressEnabled: false
  # éªŒè¯ç ç±»åž‹ math æ•°å­—计算 char å­—符验证
  captchaType: math
  # ååŒå®¡æ‰¹ç¼–号前缀(配置文件后缀命名)
  approvalNumberPrefix: NEW
  # ä¸ªæŽ¨ Unipush é…ç½®
  getui:
    appId: PfjyAAE0FK64FaO1w2CMb1
    appKey: zTMb831OEL6J4GK1uE3Ob4
    masterSecret: K1GFtsv42v61tXGnF7SGE5
    domain: https://restapi.getui.cn/v2/
    # ç¦»çº¿æŽ¨é€ä½¿ç”¨çš„包名/组件名
    intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
# å¼€å‘环境配置
server:
  # æœåŠ¡å™¨çš„HTTP端口,默认为8080
  port: 9002
  servlet:
    # åº”用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # è¿žæŽ¥æ•°æ»¡åŽçš„æŽ’队数,默认为100
    accept-count: 1000
    max-swallow-size: -1          # -1 è¡¨ç¤ºä¸é™åˆ¶
    max-http-form-post-size: -1   # POST è¯·æ±‚体不限制
    connection-timeout: 60000     # è¿žæŽ¥è¶…æ—¶æ—¶é—´(毫秒)
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# æ—¥å¿—配置
logging:
  level:
    com.ruoyi: warn
    org.springframework: warn
minio:
  endpoint: http://114.132.189.42/
  port: 7019
  secure: false
  accessKey: admin
  secretKey: 12345678
  preview-expiry: 24 # é¢„览地址默认24小时
  default-bucket: uploadPath
# ç”¨æˆ·é…ç½®
user:
  password:
    # å¯†ç æœ€å¤§é”™è¯¯æ¬¡æ•°
    maxRetryCount: 5
    # å¯†ç é”å®šæ—¶é—´ï¼ˆé»˜è®¤10分钟)
    lockTime: 10
# Spring配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # ä¸»åº“数据源
      master:
        url: jdbc:mysql://36.134.158.166:83/product-inventory-management-gzdz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: gzdz@123456..
      # ä»Žåº“数据源
      slave:
        # ä»Žæ•°æ®æºå¼€å…³/默认关闭
        enabled: false
        url:
        username:
        password:
      # åˆå§‹è¿žæŽ¥æ•°
      initialSize: 5
      # æœ€å°è¿žæŽ¥æ± æ•°é‡
      minIdle: 10
      # æœ€å¤§è¿žæŽ¥æ± æ•°é‡
      maxActive: 20
      # é…ç½®èŽ·å–è¿žæŽ¥ç­‰å¾…è¶…æ—¶çš„æ—¶é—´
      maxWait: 60000
      # é…ç½®è¿žæŽ¥è¶…æ—¶æ—¶é—´
      connectTimeout: 30000
      # é…ç½®ç½‘络超时时间
      socketTimeout: 60000
      # é…ç½®é—´éš”多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å°ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
      minEvictableIdleTimeMillis: 300000
      # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å¤§ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # é…ç½®æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # è®¾ç½®ç™½åå•,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # æŽ§åˆ¶å°ç®¡ç†ç”¨æˆ·åå’Œå¯†ç 
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # æ…¢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
  # èµ„源信息
  messages:
    # å›½é™…化资源文件路径
    basename: i18n/messages
  # æ–‡ä»¶ä¸Šä¼ 
  servlet:
    multipart:
      # å•个文件大小
      max-file-size: 1GB
      # è®¾ç½®æ€»ä¸Šä¼ çš„æ–‡ä»¶å¤§å°
      max-request-size: 2GB
  # æœåŠ¡æ¨¡å—
  devtools:
    restart:
      # çƒ­éƒ¨ç½²å¼€å…³
      enabled: false
  data:
    # redis é…ç½®
    redis:
      # åœ°å€
      #      host: localhost
      host: 172.17.0.1
      # ç«¯å£ï¼Œé»˜è®¤ä¸º6379
      port: 6379
      # æ•°æ®åº“索引
      database: 0
      # å¯†ç 
      #    password: root2022!
      password:
      # è¿žæŽ¥è¶…æ—¶æ—¶é—´
      timeout: 10s
      lettuce:
        pool:
          # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
          min-idle: 0
          # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
          max-idle: 8
          # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
          max-active: 8
          # #连接池最大阻塞等待时间(使用负值表示没有限制)
          max-wait: -1ms
  # Quartz定时任务配置(新增部分)
  quartz:
    job-store-type: jdbc  # ä½¿ç”¨æ•°æ®åº“存储
    jdbc:
      initialize-schema: never  # é¦–次运行时自动创建表结构,成功后改为never
      schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql  # MySQL表结构脚本
    properties:
      org:
        quartz:
          scheduler:
            instanceName: RuoYiScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # MySQL适配
            tablePrefix: qrtz_  # è¡¨åå‰ç¼€ï¼Œä¸Žè„šæœ¬ä¸€è‡´
            isClustered: false  # å•节点模式(集群需改为true)
            clusterCheckinInterval: 10000
            txIsolationLevelSerializable: true
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10  # çº¿ç¨‹æ± å¤§å°
            threadPriority: 5
            makeThreadsDaemons: true
          updateCheck: false  # å…³é—­ç‰ˆæœ¬æ£€æŸ¥
# token配置
token:
  # ä»¤ç‰Œè‡ªå®šä¹‰æ ‡è¯†
  header: Authorization
  # ä»¤ç‰Œå¯†é’¥
  secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ
  # ä»¤ç‰Œæœ‰æ•ˆæœŸï¼ˆé»˜è®¤30分钟)
  expireTime: 450
# MyBatis Plus配置
mybatis-plus:
  # æœç´¢æŒ‡å®šåŒ…别名   æ ¹æ®è‡ªå·±çš„项目来
  typeAliasesPackage: com.ruoyi.**.pojo
  # é…ç½®mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # åŠ è½½å…¨å±€çš„é…ç½®æ–‡ä»¶
  configLocation: classpath:mybatis/mybatis-config.xml
  global-config:
    enable-sql-runner: true
    db-config:
      id-type: auto
# PageHelper分页插件
pagehelper:
  helperDialect: mysql
  supportMethodsArguments: true
  params: count=countSql
# Swagger配置
swagger:
  # æ˜¯å¦å¼€å¯swagger
  enabled: true
  # è¯·æ±‚前缀
  pathMapping: /dev-api
# é˜²æ­¢XSS攻击
xss:
  # è¿‡æ»¤å¼€å…³
  enabled: true
  # æŽ’除链接(多个用逗号分隔)
  excludes: /system/notice
  # åŒ¹é…é“¾æŽ¥
  urlPatterns: /system/*,/monitor/*,/tool/*
# ä»£ç ç”Ÿæˆ
gen:
  # ä½œè€…
  author: ruoyi
  # é»˜è®¤ç”ŸæˆåŒ…路径 system éœ€æ”¹æˆè‡ªå·±çš„æ¨¡å—名称 å¦‚ system monitor tool
  packageName: com.ruoyi.project.system
  # è‡ªåŠ¨åŽ»é™¤è¡¨å‰ç¼€ï¼Œé»˜è®¤æ˜¯true
  autoRemovePre: false
  # è¡¨å‰ç¼€ï¼ˆç”Ÿæˆç±»åä¸ä¼šåŒ…含表前缀,多个用逗号分隔)
  tablePrefix: sys_
  # æ˜¯å¦å…è®¸ç”Ÿæˆæ–‡ä»¶è¦†ç›–到本地(自定义路径),默认不允许
  allowOverwrite: false
# æ–‡ä»¶ä¸Šä¼ é…ç½®
file:
  temp-dir: /data/javaWork/product-inventory-management/file/temp/uploads   # ä¸´æ—¶ç›®å½• åŽæœŸåˆ é™¤
  upload-dir: /data/javaWork/product-inventory-management/file/prod/uploads # æ­£å¼ç›®å½• åŽæœŸåˆ é™¤
  path: /data/javaWork/product-inventory-management/file/path/uploads # ä¸Šä¼ ç›®å½•
  urlPrefix: /prod-api/common # é“¾æŽ¥å‰ç¼€
  domain: http://36.134.158.166:81 # åŸŸåå‰ç¼€
  expired: 120 # è¿‡æœŸæ—¶é—´(单位:分钟)
  useLimit: 10 # ä½¿ç”¨æ¬¡æ•°
  compress: true # æ˜¯å¦åŽ‹ç¼©
  needCompressSize: 10MB # åŽ‹ç¼©é˜ˆå€¼
  compressQuality: 0.5 # åŽ‹ç¼©è´¨é‡(0.0-1.0)
knowledge:
  one: D:\新疆大罗素企业产品体系说明文档.md