15815213711
2025-07-30 00400fe72f8e30cf7df08771f69b8ad8b80e9f1a
修改ID,修改加密方式
7个文件已修改
4个文件已添加
271 ■■■■■ 已修改文件
admin/config/test/application-custom.yml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/main/resources/simhei.ttf 补丁 | 查看 | 原始文档 | blame | 历史
service/pom.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/controller/DispatchOrderController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/service/IDispatchOrderService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/service/impl/DispatchOrderServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/utils/MultiPagePdfWithImageUtils.java 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/java/com/ruoyi/cwgl/utils/simhei.ttf 补丁 | 查看 | 原始文档 | blame | 历史
service/src/main/resources/simhei.ttf 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/api/cwgl/dispatchOrder.ts 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ui/admin-ui3/src/views/cwgl/dispatchOrder/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/config/test/application-custom.yml
@@ -55,11 +55,11 @@
      log-slow-sql: true  # 慢SQL记录
  #redis 相关配置
  redis:
    host: 127.0.0.1 #访问地址
    port: 6379 #端口
    password: 123456 #密码
    host: 61.143.42.70 #访问地址
    port: 7007 #端口
    password: rd@123 #密码
    timeout: 10s #超时时间
    keyprefix: cwgl_test #存储key前缀,避免多套环境key相同
    keyprefix: cwgl:test #存储key前缀,避免多套环境key相同
  #swagger相关配置
  swagger:
    enabled: true #是否开启
admin/src/main/resources/simhei.ttf
Binary files differ
service/pom.xml
@@ -25,7 +25,11 @@
        <artifactId>common</artifactId>
        <version>${project.version}</version>
    </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
    <!--持久化层模块-->
    <dependency>
service/src/main/java/com/ruoyi/cwgl/controller/DispatchOrderController.java
@@ -2,8 +2,12 @@
import java.util.List;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.cwgl.domain.vo.DispatchOrderAttachmentVo;
import com.ruoyi.cwgl.domain.vo.DispatchOrderItemVo;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -23,6 +27,8 @@
import com.ruoyi.cwgl.service.IDispatchOrderService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import javax.servlet.http.HttpServletResponse;
/**
 * 调度单Controller
@@ -73,6 +79,15 @@
        return getDataTable(list);
    }
    @PreAuthorize("@ss.hasPermi('cwgl:dispatchOrder:attachment')")
    @GetMapping("/downAttachment")
    public void downAttachment(String no, HttpServletResponse response) throws Exception {
        String filePath = dispatchOrderService.downAttachment(no);
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        FileUtils.setAttachmentResponseHeader(response, FileUtils.getName(filePath));
        FileUtils.writeBytes(filePath, response.getOutputStream());
    }
    /**
     * 导出调度单列表
     * @param dispatchOrder 查询条件对象
@@ -100,6 +115,7 @@
    /**
     * 获取调度单详细信息
     */
service/src/main/java/com/ruoyi/cwgl/service/IDispatchOrderService.java
@@ -1,5 +1,6 @@
package com.ruoyi.cwgl.service;
import java.io.FileNotFoundException;
import java.util.List;
import com.ruoyi.cwgl.domain.DispatchOrder;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -118,4 +119,6 @@
     * @return
     */
    List<DispatchOrderAttachmentVo> selectDispatchOrderAttachment(String no);
    String downAttachment(String no) throws Exception;
}
service/src/main/java/com/ruoyi/cwgl/service/impl/DispatchOrderServiceImpl.java
@@ -1,6 +1,10 @@
package com.ruoyi.cwgl.service.impl;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.math.BigDecimal;
@@ -12,7 +16,13 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.PageUtil;
import com.github.pagehelper.Page;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import javax.annotation.Resource;
@@ -23,6 +33,7 @@
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.cwgl.domain.vo.DispatchOrderVo;
import com.ruoyi.cwgl.enums.FeeTypeEnums;
import com.ruoyi.cwgl.utils.MultiPagePdfWithImageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.cwgl.domain.DispatchOrderItem;
@@ -476,4 +487,15 @@
    public List<DispatchOrderAttachmentVo> selectDispatchOrderAttachment(String no) {
        return dispatchOrderMapper.selectDispatchOrderAttachment(no);
    }
    @DataSource(DataSourceType.CWSJ)
    @Override
    public String  downAttachment(String no) throws Exception {
        List<DispatchOrderAttachmentVo> dispatchOrderAttachmentVos = selectDispatchOrderAttachment(no);
        return MultiPagePdfWithImageUtils.createPdf(dispatchOrderAttachmentVos, no);
    }
}
service/src/main/java/com/ruoyi/cwgl/utils/MultiPagePdfWithImageUtils.java
New file
@@ -0,0 +1,186 @@
package com.ruoyi.cwgl.utils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.cwgl.domain.vo.DispatchOrderAttachmentVo;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public class MultiPagePdfWithImageUtils {
    public static String createPdf(List<DispatchOrderAttachmentVo> dispatchOrderAttachmentVos, String no) throws Exception {
        String fileName = no+ "_凭证_"+ UUID.randomUUID() +".pdf";
        String path = RuoYiConfig.getDownloadPath() + fileName;
        Document document = new Document(PageSize.A4, 36, 36, 36, 36);
        PdfWriter writer = PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(path)));
        document.open();
        BaseFont baseFont = BaseFont.createFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        Font font = new Font(baseFont, 11, Font.NORMAL);
        int totalPages = dispatchOrderAttachmentVos.size();
        for (int i = 0; i < totalPages; i++) {
            if (i > 0) document.newPage();
            DispatchOrderAttachmentVo dispatchOrderAttachmentVo = dispatchOrderAttachmentVos.get(i);
            String currency = Optional.ofNullable(dispatchOrderAttachmentVo.getCurrency()).orElse("人民币");
            String currentStr;
            if ("人民币".equals(currency)){
                currentStr = "总金额:港币 0;人民币:"+dispatchOrderAttachmentVo.getAccount()+";";
            }else{
                currentStr = "总金额:港币 "+dispatchOrderAttachmentVo.getAccount()+";人民币:0;";
            }
            PdfPTable wrapperTable = new PdfPTable(1);
            wrapperTable.setWidthPercentage(100);
            wrapperTable.setKeepTogether(true);
            // ▶ 页眉表格
            PdfPTable headerTable = new PdfPTable(2);
            headerTable.setWidthPercentage(100);
            headerTable.setWidths(new int[]{3, 2});
            headerTable.addCell(createCell("调度单号:"+no, font));
            headerTable.addCell(createCell(currentStr, font));
            PdfPCell headerCell = new PdfPCell(headerTable);
            headerCell.setBorder(Rectangle.BOX);
            wrapperTable.addCell(headerCell);
            // ▶ 图片
            Image image = Image.getInstance(new URL(dispatchOrderAttachmentVo.getImageUrl()));
            // 限制图片最大尺寸
            float maxImgWidth = 500f;
            float maxImgHeight = 700f;
            image.scaleToFit(maxImgWidth, maxImgHeight);
            image.setAlignment(Image.ALIGN_CENTER);
            // 创建图片单元格并设置固定高度(确保整体表格不分页)
            PdfPCell imageCell = new PdfPCell();
            imageCell.setPadding(10);
            imageCell.setBorder(Rectangle.BOX);
            imageCell.setFixedHeight(maxImgHeight + 20); // 加一点 padding 空间
            imageCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            imageCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            imageCell.addElement(image);
            wrapperTable.addCell(imageCell);
            // ▶ 页脚表格
            PdfPTable footerTable = new PdfPTable(4);
            footerTable.setWidthPercentage(100);
            footerTable.setWidths(new int[]{3, 2, 2, 3});
            footerTable.addCell(createCell("费用类:"+dispatchOrderAttachmentVo.getFeeItem(), font));
            footerTable.addCell(createCell("金额:"+dispatchOrderAttachmentVo.getAccount(), font));
            footerTable.addCell(createCell("币制:"+dispatchOrderAttachmentVo.getCurrency(), font));
            footerTable.addCell(createCell("第 " + (i + 1) + " 页 / 共 " + totalPages + " 页", font));
            PdfPCell footerCell = new PdfPCell(footerTable);
            footerCell.setBorder(Rectangle.BOX);
            wrapperTable.addCell(footerCell);
            // 添加总表格
            document.add(wrapperTable);
        }
        document.close();
        writer.close();
        System.out.println("PDF 生成成功!");
        return path;
    }
    public static void main(String[] args) throws Exception {
        Document document = new Document(PageSize.A4, 36, 36, 36, 36);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("bordered_receipt.pdf"));
        document.open();
        BaseFont baseFont = BaseFont.createFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        Font font = new Font(baseFont, 11, Font.NORMAL);
        List<String> imageUrls = Arrays.asList(
                "https://xiongbenda-shengzheng.oss-cn-shenzhen.aliyuncs.com/cz/ImageViewServlet%20%281%29.gif",
                "https://xiongbenda-shengzheng.oss-cn-shenzhen.aliyuncs.com/cz/ImageViewServlet.gif"
        );
        int totalPages = imageUrls.size();
        for (int i = 0; i < totalPages; i++) {
            if (i > 0) document.newPage();
            // ▶ 构造一个总表格(3行,1列),包住所有内容,控制边框与分页
            PdfPTable wrapperTable = new PdfPTable(1);
            wrapperTable.setWidthPercentage(100);
            wrapperTable.setKeepTogether(true);
            // ▶ 页眉表格
            PdfPTable headerTable = new PdfPTable(2);
            headerTable.setWidthPercentage(100);
            headerTable.setWidths(new int[]{3, 2});
            headerTable.addCell(createCell("调度单号:LD2507260028", font));
            headerTable.addCell(createCell("总金额:港币 280;人民币:0", font));
            PdfPCell headerCell = new PdfPCell(headerTable);
            headerCell.setBorder(Rectangle.BOX);
            wrapperTable.addCell(headerCell);
            // ▶ 图片
            Image image = Image.getInstance(new URL(imageUrls.get(i)));
// 限制图片最大尺寸
            float maxImgWidth = 500f;
            float maxImgHeight = 700f;
            image.scaleToFit(maxImgWidth, maxImgHeight);
            image.setAlignment(Image.ALIGN_CENTER);
// 创建图片单元格并设置固定高度(确保整体表格不分页)
            PdfPCell imageCell = new PdfPCell();
            imageCell.setPadding(10);
            imageCell.setBorder(Rectangle.BOX);
            imageCell.setFixedHeight(maxImgHeight + 20); // 加一点 padding 空间
            imageCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            imageCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            imageCell.addElement(image);
            wrapperTable.addCell(imageCell);
            // ▶ 页脚表格
            PdfPTable footerTable = new PdfPTable(4);
            footerTable.setWidthPercentage(100);
            footerTable.setWidths(new int[]{3, 2, 2, 3});
            footerTable.addCell(createCell("费用类:登记费 HKD", font));
            footerTable.addCell(createCell("金额:250.00", font));
            footerTable.addCell(createCell("币制:港币", font));
            footerTable.addCell(createCell("第 " + (i + 1) + " 页 / 共 " + totalPages + " 页", font));
            PdfPCell footerCell = new PdfPCell(footerTable);
            footerCell.setBorder(Rectangle.BOX);
            wrapperTable.addCell(footerCell);
            // 添加总表格
            document.add(wrapperTable);
        }
        document.close();
        writer.close();
        System.out.println("PDF 生成成功!");
    }
    // 默认左对齐、含内边距、含边框
    private static PdfPCell createCell(String text, Font font) {
        PdfPCell cell = new PdfPCell(new Phrase(text, font));
        cell.setPadding(6);
        cell.setHorizontalAlignment(Element.ALIGN_LEFT);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        return cell;
    }
}
service/src/main/java/com/ruoyi/cwgl/utils/simhei.ttf
Binary files differ
service/src/main/resources/simhei.ttf
Binary files differ
ui/admin-ui3/src/api/cwgl/dispatchOrder.ts
@@ -70,7 +70,14 @@
        download('/cwgl/dispatchOrder/export2',query);
    })
}
export const downloadFJ:requestType = (query) => {
    return request({
        url: '/cwgl/dispatchOrder/downAttachment',
        method:'get',
        params:query,
        responseType: 'blob'
    })
}
/**
 * 查询查看费用
 */
ui/admin-ui3/src/views/cwgl/dispatchOrder/index.vue
@@ -39,6 +39,11 @@
            class="attachment-image" />
        </template>
      </avue-crud>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" v-if="itemTableData2.length>0" @click="downPZ">下载凭证</el-button>
        </div>
      </template>
    </el-dialog>
  </basicContainer>
@@ -52,13 +57,15 @@
  exportDispatchOrder,
  getDispatchOrder,
  listDispatchOrder,
  updateDispatchOrder, cwglDispatchOrderItem, cwglDispatchOrderattAchment, exportDispatchOrder2
  updateDispatchOrder, cwglDispatchOrderItem, cwglDispatchOrderattAchment, exportDispatchOrder2, downloadFJ
} from "@/api/cwgl/dispatchOrder";
import useCurrentInstance from "@/utils/useCurrentInstance";
import { computed, reactive, ref, toRefs } from "vue";
import { PagesInterface, PageQueryInterface } from "@/utils/globalInterface";
import { usePagePlus } from "@/hooks/usePagePlus";
import { hasPermission } from "@/utils/permissionUtils";
import {blobValidate} from "@/utils/ruoyi";
import {saveAs} from "file-saver";
const { proxy } = useCurrentInstance();
const crudRef = ref();
@@ -378,6 +385,18 @@
  queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.actualArrivalTimeRange, 'actualArrivalTime') || {};
  exportDispatchOrder2(queryParams.value);
}
const downPZ =()=>{
  downloadFJ({no:pageAttachment.value.no}).then(res=>{
    console.log(res)
      const blob = new Blob([res])
    console.log(blob)
      saveAs(blob, decodeURI(pageAttachment.value.no+"凭证.pdf"))
  })
}
</script>
<style lang="scss" scoped>
.avue-dialog .el-dialog__body {