liding
2025-05-12 0578cb68bcd2933fd638f94a7cc7c53f21588b48
通用文件上传
已修改6个文件
已添加7个文件
408 ■■■■ 文件已修改
src/main/java/com/ruoyi/RuoYiApplication.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/controller/TempFileController.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/mapper/TempFileMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/pojo/TempFile.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/service/TempFileService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerFileMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerFile.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 179 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-druid.yml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/RuoYiApplication.java
@@ -3,12 +3,15 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
 * å¯åŠ¨ç¨‹åº
 * 
 * @author ruoyi
 */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableScheduling
public class RuoYiApplication
{
    public static void main(String[] args)
src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java
@@ -25,6 +25,8 @@
        IGNORE_TABLES.add("sys_logininfor");
        IGNORE_TABLES.add("sys_post");
        IGNORE_TABLES.add("sys_user_post");
        IGNORE_TABLES.add("sales_ledger_file");
        IGNORE_TABLES.add("temp_file");
    }
}
src/main/java/com/ruoyi/other/controller/TempFileController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.ruoyi.other.controller;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.service.TempFileService;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/file")
@AllArgsConstructor
public class TempFileController {
    private TempFileService tempFileService;
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) {
        try {
            return AjaxResult.success(tempFileService.uploadFile(file));
        }catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }
}
src/main/java/com/ruoyi/other/mapper/TempFileMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
package com.ruoyi.other.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.other.pojo.TempFile;
public interface TempFileMapper extends BaseMapper<TempFile> {
}
src/main/java/com/ruoyi/other/pojo/TempFile.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.ruoyi.other.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("temp_file")
public class TempFile {
    private String tempId;         // ä¸´æ—¶æ–‡ä»¶ID(UUID)
    private String originalName;   // åŽŸå§‹æ–‡ä»¶å
    private String tempPath;       // ä¸´æ—¶å­˜å‚¨è·¯å¾„
    private LocalDateTime expireTime; // è¿‡æœŸæ—¶é—´
}
src/main/java/com/ruoyi/other/service/TempFileService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
package com.ruoyi.other.service;
import com.ruoyi.other.pojo.TempFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public interface TempFileService {
    TempFile uploadFile(MultipartFile file) throws IOException;
}
src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.other.service.TempFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
@Service
@Slf4j
public class TempFileServiceImpl extends ServiceImpl<TempFileMapper, TempFile> implements TempFileService {
    @Autowired
    private TempFileMapper tempFileMapper;
    @Value("${file.temp-dir}")
    private String tempDir;
    // ä¸Šä¼ åˆ°ä¸´æ—¶ç›®å½•
    @Override
    public TempFile uploadFile(MultipartFile file) throws IOException {
        // 1. ç”Ÿæˆä¸´æ—¶æ–‡ä»¶ID和路径
        String tempId = UUID.randomUUID().toString();
        Path tempFilePath = Paths.get(tempDir, tempId + "_" + file.getOriginalFilename());
        // 2. ç¡®ä¿ç›®å½•存在
        Path parentDir = tempFilePath.getParent();
        if (parentDir != null) {
            Files.createDirectories(parentDir); // é€’归创建目录
        }
        // 3. ä¿å­˜æ–‡ä»¶åˆ°ä¸´æ—¶ç›®å½•
        file.transferTo(tempFilePath.toFile());
        // 4. ä¿å­˜ä¸´æ—¶æ–‡ä»¶è®°å½•
        TempFile tempFileRecord = new TempFile();
        tempFileRecord.setTempId(tempId);
        tempFileRecord.setOriginalName(file.getOriginalFilename());
        tempFileRecord.setTempPath(tempFilePath.toString());
        tempFileRecord.setExpireTime(LocalDateTime.now().plusHours(2)); // 2小时后过期
        tempFileMapper.insert(tempFileRecord);
        return tempFileRecord;
    }
    @Scheduled(cron = "0 0 3 * * ?") // æ¯å¤©å‡Œæ™¨3点执行
    public void cleanupExpiredTempFiles() {
        LambdaQueryWrapper<TempFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(TempFile::getExpireTime, LocalDateTime.now()); // expireTime < å½“前时间
        List<TempFile> expiredFiles = tempFileMapper.selectList(wrapper);
        for (TempFile file : expiredFiles) {
            try {
                // åˆ é™¤ç‰©ç†æ–‡ä»¶
                Files.deleteIfExists(Paths.get(file.getTempPath()));
                // åˆ é™¤æ•°æ®åº“记录
                tempFileMapper.deleteById(file);
                log.info("已清理过期临时文件: {}", file.getTempPath());
            } catch (IOException e) {
                log.error("删除文件失败: {}", file.getTempPath(), e);
                // å¯é€‰æ‹©è®°å½•失败日志或重试
            }
        }
        log.info("过期临时文件清理完成,共清理 {} ä¸ªæ–‡ä»¶", expiredFiles.size());
    }
}
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -1,6 +1,6 @@
package com.ruoyi.sales.controller;
import java.util.List;
import java.util.*;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -8,12 +8,7 @@
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.service.ISalesLedgerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
@@ -22,14 +17,13 @@
/**
 * é”€å”®å°è´¦Controller
 *
 *
 * @author ruoyi
 * @date 2025-05-08
 */
@RestController
@RequestMapping("/sales/ledger")
public class SalesLedgerController extends BaseController
{
public class SalesLedgerController extends BaseController {
    @Autowired
    private ISalesLedgerService salesLedgerService;
@@ -37,8 +31,7 @@
     * æŸ¥è¯¢é”€å”®å°è´¦åˆ—表
     */
    @GetMapping("/list")
    public TableDataInfo list(SalesLedgerDto salesLedgerDto)
    {
    public TableDataInfo list(SalesLedgerDto salesLedgerDto) {
        startPage();
        List<SalesLedger> list = salesLedgerService.selectSalesLedgerList(salesLedgerDto);
        return getDataTable(list);
@@ -48,8 +41,8 @@
     * æŸ¥è¯¢é”€å”®å°è´¦å’Œäº§å“çˆ¶å­åˆ—表
     */
    @GetMapping("/getSalesLedgerWithProducts")
    public SalesLedgerDto getSalesLedgerWithProducts(SalesLedgerDto salesLedgerDto){
        return  salesLedgerService.getSalesLedgerWithProducts(salesLedgerDto);
    public SalesLedgerDto getSalesLedgerWithProducts(SalesLedgerDto salesLedgerDto) {
        return salesLedgerService.getSalesLedgerWithProducts(salesLedgerDto);
    }
    /**
@@ -57,8 +50,7 @@
     */
    @Log(title = "销售台账", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SalesLedgerDto salesLedgerDto)
    {
    public void export(HttpServletResponse response, SalesLedgerDto salesLedgerDto) {
        List<SalesLedger> list = salesLedgerService.selectSalesLedgerList(salesLedgerDto);
        ExcelUtil<SalesLedger> util = new ExcelUtil<SalesLedger>(SalesLedger.class);
        util.exportExcel(response, list, "销售台账数据");
@@ -68,9 +60,8 @@
     * æ–°å¢žä¿®æ”¹é”€å”®å°è´¦
     */
    @Log(title = "销售台账", businessType = BusinessType.INSERT)
    @PostMapping ("/addOrUpdateSalesLedger")
    public AjaxResult add(@RequestBody SalesLedgerDto salesLedgerDto)
    {
    @PostMapping("/addOrUpdateSalesLedger")
    public AjaxResult add(@RequestBody SalesLedgerDto salesLedgerDto) {
        return toAjax(salesLedgerService.addOrUpdateSalesLedger(salesLedgerDto));
    }
@@ -78,9 +69,8 @@
     * åˆ é™¤é”€å”®å°è´¦
     */
    @Log(title = "销售台账", businessType = BusinessType.DELETE)
    @DeleteMapping("/delLedger")
    public AjaxResult remove(@RequestBody Long[] ids)
    {
    @DeleteMapping("/delLedger")
    public AjaxResult remove(@RequestBody Long[] ids) {
        if (ids == null || ids.length == 0) {
            return AjaxResult.error("请传入要删除的ID");
        }
src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
@@ -23,4 +23,6 @@
    private String attachmentMaterials;
    private Boolean hasChildren = false;
    private List<SalesLedgerProduct> productData;
    private List<String> tempFileIds;
}
src/main/java/com/ruoyi/sales/mapper/SalesLedgerFileMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
package com.ruoyi.sales.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.sales.pojo.SalesLedgerFile;
public interface SalesLedgerFileMapper extends BaseMapper<SalesLedgerFile> {
}
src/main/java/com/ruoyi/sales/pojo/SalesLedgerFile.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.ruoyi.sales.pojo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sales_ledger_file")
public class SalesLedgerFile {
    @TableId(type = IdType.AUTO)
    private Long id;
    /** é”€å”®å°è´¦ID */
    private Long ledgerId;
    /** æ–‡ä»¶åç§° */
    private String fileName;
    /** æ–‡ä»¶è·¯å¾„ */
    private String filePath;
    /** åˆ›å»ºæ—¶é—´ */
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    /** æ›´æ–°æ—¶é—´ */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -8,22 +8,33 @@
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.mapper.SalesLedgerFileMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerFile;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerService;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.file.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -37,14 +48,22 @@
 * @date 2025-05-08
 */
@Service
@AllArgsConstructor
@RequiredArgsConstructor
@Slf4j
public class SalesLedgerServiceImpl extends ServiceImpl<SalesLedgerMapper, SalesLedger> implements ISalesLedgerService {
    private SalesLedgerMapper salesLedgerMapper;
    private final  SalesLedgerMapper salesLedgerMapper;
    private CustomerMapper customerMapper;
    private final  CustomerMapper customerMapper;
    private SalesLedgerProductMapper salesLedgerProductMapper;
    private final  SalesLedgerProductMapper salesLedgerProductMapper;
    private final SalesLedgerFileMapper salesLedgerFileMapper;
    private final TempFileMapper tempFileMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
    private static final String LOCK_PREFIX = "contract_no_lock:";
    private static final long LOCK_WAIT_TIMEOUT = 10; // é”ç­‰å¾…超时时间(秒)
@@ -102,46 +121,126 @@
        return salesLedgerMapper.deleteBatchIds(idList);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto) {
        // 1. æ ¡éªŒå®¢æˆ·ä¿¡æ¯
        Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId());
        if (customer == null) {
            throw new BaseException("客户不存在");
        try {
            // 1. æ ¡éªŒå®¢æˆ·ä¿¡æ¯
            Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId());
            if (customer == null) {
                throw new BaseException("客户不存在");
            }
            // 2. DTO转Entity
            SalesLedger salesLedger = convertToEntity(salesLedgerDto);
            salesLedger.setCustomerName(customer.getCustomerName());
            salesLedger.setTenantId(customer.getTenantId());
            // 3. æ–°å¢žæˆ–更新主表
            if (salesLedger.getId() == null) {
                String contractNo = generateSalesContractNo();
                salesLedger.setSalesContractNo(contractNo);
                salesLedgerMapper.insert(salesLedger);
            } else {
                salesLedgerMapper.updateById(salesLedger);
            }
            // 4. å¤„理子表数据
            List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
            if (productList != null && !productList.isEmpty()) {
                handleSalesLedgerProducts(salesLedger.getId(), productList);
                updateMainContractAmount(
                        salesLedger.getId(),
                        productList,
                        SalesLedgerProduct::getTaxInclusiveTotalPrice,
                        salesLedgerMapper,
                        SalesLedger.class
                );
            }
            // 5. è¿ç§»ä¸´æ—¶æ–‡ä»¶åˆ°æ­£å¼ç›®å½•
            if (salesLedgerDto.getTempFileIds() != null && !salesLedgerDto.getTempFileIds().isEmpty()) {
                migrateTempFilesToFormal(salesLedger.getId(), salesLedgerDto.getTempFileIds());
            }
            return 1;
        } catch (IOException e) {
            throw new BaseException("文件迁移失败: " + e.getMessage());
        }
        // 2. DTO转Entity
        SalesLedger salesLedger = convertToEntity(salesLedgerDto);
        salesLedger.setCustomerName(customer.getCustomerName());
        salesLedger.setTenantId(customer.getTenantId());
        // 3. æ–°å¢žæˆ–更新主表
        if (salesLedger.getId() == null) {
            // ç”ŸæˆåˆåŒç¼–号
            String contractNo = generateSalesContractNo();
            salesLedger.setSalesContractNo(contractNo);
            salesLedgerMapper.insert(salesLedger);
        } else {
            salesLedgerMapper.updateById(salesLedger);
        }
        // 4. å¤„理子表数据
        List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
        if (productList != null && !productList.isEmpty()) {
            handleSalesLedgerProducts(salesLedger.getId(), productList);
            // âœ… è°ƒç”¨é€šç”¨æ–¹æ³•更新主表金额
            updateMainContractAmount(
                    salesLedger.getId(),
                    productList,
                    SalesLedgerProduct::getTaxInclusiveTotalPrice,
                    salesLedgerMapper,
                    SalesLedger.class
            );
        }
        return 1; // æ“ä½œæˆåŠŸè¿”å›ž1
    }
    // æ–‡ä»¶è¿ç§»æ–¹æ³•
    /**
     * å°†ä¸´æ—¶æ–‡ä»¶è¿ç§»åˆ°æ­£å¼ç›®å½•
     *
     * @param businessId  ä¸šåŠ¡ID(销售台账ID)
     * @param tempFileIds ä¸´æ—¶æ–‡ä»¶ID列表
     * @throws IOException æ–‡ä»¶æ“ä½œå¼‚常
     */
    private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException {
        if (CollectionUtils.isEmpty(tempFileIds)) {
            return;
        }
        // æž„建正式目录路径(按业务类型和日期分组)
        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
        Path formalDirPath = Paths.get(formalDir);
        // ç¡®ä¿æ­£å¼ç›®å½•存在(递归创建)
        if (!Files.exists(formalDirPath)) {
            Files.createDirectories(formalDirPath);
        }
        for (String tempFileId : tempFileIds) {
            // æŸ¥è¯¢ä¸´æ—¶æ–‡ä»¶è®°å½•
            TempFile tempFile = tempFileMapper.selectById(tempFileId);
            if (tempFile == null) {
                throw new FileNotFoundException("临时文件不存在: " + tempFileId);
            }
            // æž„建正式文件名(包含业务ID和时间戳,避免冲突)
            String originalFilename = tempFile.getOriginalName();
            String fileExtension = FilenameUtils.getExtension(originalFilename);
            String formalFilename = businessId + "_" +
                    System.currentTimeMillis() + "_" +
                    UUID.randomUUID().toString().substring(0, 8) +
                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
            Path formalFilePath = formalDirPath.resolve(formalFilename);
            try {
                // æ‰§è¡Œæ–‡ä»¶è¿ç§»ï¼ˆä½¿ç”¨åŽŸå­æ“ä½œç¡®ä¿å®‰å…¨æ€§ï¼‰
                Files.move(
                        Paths.get(tempFile.getTempPath()),
                        formalFilePath,
                        StandardCopyOption.REPLACE_EXISTING,
                        StandardCopyOption.ATOMIC_MOVE
                );
                log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath);
                // æ›´æ–°æ–‡ä»¶è®°å½•(关联到业务ID)
                SalesLedgerFile fileRecord = new SalesLedgerFile();
                fileRecord.setLedgerId(businessId);
                fileRecord.setFileName(originalFilename);
                fileRecord.setFilePath(formalFilePath.toString());
                fileRecord.setCreateTime(LocalDateTime.now());
                salesLedgerFileMapper.insert(fileRecord);
                // åˆ é™¤ä¸´æ—¶æ–‡ä»¶è®°å½•
                tempFileMapper.deleteById(tempFile);
                log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath);
            } catch (IOException e) {
                log.error("文件迁移失败: {}", tempFile.getTempPath(), e);
                // å¯é€‰æ‹©å›žæ»šäº‹åŠ¡æˆ–è®°å½•å¤±è´¥æ–‡ä»¶
                throw new IOException("文件迁移异常", e);
            }
        }
    }
    private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products) {
        // æŒ‰ID分组,区分新增和更新的记录
        Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
src/main/resources/application-druid.yml
@@ -6,7 +6,8 @@
        druid:
            # ä¸»åº“数据源
            master:
                url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#                url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                url: jdbc:mysql://114.132.189.42:9004/product-inventory-management?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: 123456
            # ä»Žåº“数据源
@@ -59,3 +60,7 @@
                wall:
                    config:
                        multi-statement-allow: true
file:
    temp-dir: D:/ruoyi/temp/uploads   # ä¸´æ—¶ç›®å½•
    upload-dir: D:/ruoyi/prod/uploads # æ­£å¼ç›®å½•