wangxin hai 1 ano
pai
achega
c125e2a2a4

+ 21 - 0
pom.xml

@@ -343,6 +343,27 @@
 <!--            <artifactId>snms-spring-boot-starter</artifactId>-->
 <!--            <version>0.0.2</version>-->
 <!--        </dependency>-->
+        <!--  Spring-Cloud-Feign  -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+            <version>3.1.3</version>
+        </dependency>
+        <!--  pdf输出中文要用的jar  -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.xhtmlrenderer</groupId>
+            <artifactId>flying-saucer-pdf-itext5</artifactId>
+            <version>9.1.20</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>html2pdf</artifactId>
+            <version>4.0.3</version>
+        </dependency>
     </dependencies>
 
 	<build>

+ 89 - 0
src/main/java/cn/ezhizao/common/utils/PdfUtil.java

@@ -0,0 +1,89 @@
+package cn.ezhizao.common.utils;
+
+import com.itextpdf.html2pdf.ConverterProperties;
+import com.itextpdf.html2pdf.HtmlConverter;
+import com.itextpdf.kernel.geom.PageSize;
+import com.itextpdf.kernel.pdf.PdfDocument;
+import com.itextpdf.kernel.pdf.PdfWriter;
+import com.itextpdf.layout.font.FontProvider;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.*;
+import java.util.Map;
+
+public class PdfUtil {
+
+    /**
+     * 获取模板内容
+     * @param templateDirectory 模板文件夹
+     * @param templateName      模板文件名
+     * @param paramMap          模板参数
+     * @return
+     * @throws Exception
+     */
+    public static String getTemplateContent(String templateDirectory, String templateName, Map<String, Object> paramMap) throws Exception {
+        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+        try {
+            configuration.setDirectoryForTemplateLoading(new File(templateDirectory));
+        } catch (Exception e) {
+            System.out.println("-- exception --");
+        }
+
+        Writer out = new StringWriter();
+        Template template = configuration.getTemplate(templateName,"UTF-8");
+        template.process(paramMap, out);
+        out.flush();
+        out.close();
+        return out.toString();
+    }
+    /**
+     * HTML 转 PDF
+     * @param content html内容
+     * @param outPath           输出pdf路径
+     * @return 是否创建成功
+     */
+    public static boolean html2Pdf(String content, String outPath) {
+        try {
+            ConverterProperties converterProperties = new ConverterProperties();
+            converterProperties.setCharset("UTF-8");
+            FontProvider fontProvider = new FontProvider();
+            fontProvider.addSystemFonts();
+            converterProperties.setFontProvider(fontProvider);
+            HtmlConverter.convertToPdf(content, new FileOutputStream(outPath), converterProperties);
+        } catch (Exception e) {
+            System.out.println("生成模板内容失败,{}"+e);
+            return false;
+        }
+        return true;
+    }
+    /**
+     * HTML 转 PDF
+     * @param content html内容
+     * @return PDF字节数组
+     */
+    public static byte[] html2Pdf(String content) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        try {
+            ConverterProperties converterProperties = new ConverterProperties();
+            converterProperties.setCharset("UTF-8");
+            FontProvider fontProvider = new FontProvider();
+            fontProvider.addSystemFonts();
+            converterProperties.setFontProvider(fontProvider);
+            //设置pdf纸张
+            PdfWriter writer = new PdfWriter(outputStream);
+            PdfDocument pdf = new PdfDocument(writer);
+            pdf.setTagged();
+            //设置纸张的大小,并且设置默认的pdf大小
+            PageSize pageSize = new PageSize(241f / 72 * 25.4f, 140f / 72 * 25.4f);
+//            PageSize pageSize = new PageSize(241f,140f);
+
+            pdf.setDefaultPageSize(pageSize);
+            HtmlConverter.convertToPdf(content,pdf,converterProperties);
+        } catch (Exception e) {
+            System.out.print("生成 PDF 失败,{}"+e);
+        }
+        return outputStream.toByteArray();
+    }
+}

+ 196 - 13
src/main/java/cn/ezhizao/project/business/controller/BizOutsourcedOrderController.java

@@ -1,34 +1,36 @@
 package cn.ezhizao.project.business.controller;
 
 import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.StringTokenizer;
+import java.util.*;
 import java.util.stream.Collectors;
 import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 
+import cn.ezhizao.common.utils.PdfUtil;
 import cn.ezhizao.framework.redis.RedisCache;
 import cn.ezhizao.project.business.domain.*;
 import cn.ezhizao.project.business.service.*;
 
+import cn.hutool.extra.template.TemplateException;
+import freemarker.template.Template;
+import io.swagger.annotations.ApiOperation;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-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 cn.ezhizao.framework.aspectj.lang.annotation.Log;
 import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
 import cn.ezhizao.framework.web.controller.BaseController;
 import cn.ezhizao.framework.web.domain.AjaxResult;
 
 import cn.ezhizao.framework.web.page.TableDataInfo;
+import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
 
 /**
  * 外协单主
@@ -37,6 +39,7 @@ import cn.ezhizao.framework.web.page.TableDataInfo;
  * @author 庄德政
  * date    2024-04-26
  */
+@Data
 @RestController
 @RequestMapping("/business/outsource")
 public class BizOutsourcedOrderController extends BaseController {
@@ -61,6 +64,12 @@ public class BizOutsourcedOrderController extends BaseController {
     @Resource
     private IBizDayworkCarrierService iBizDayworkCarrierService;
 
+    /**
+     * 生成pdf
+     */
+    @Autowired
+    private FreeMarkerConfigurer freeMarkerConfigurer;
+
     @Resource
     private IBizCarrierRejectService iBizCarrierRejectService;
 
@@ -84,7 +93,7 @@ public class BizOutsourcedOrderController extends BaseController {
      * 导出外协单主 带箱方式,是整单的。如果换新箱子,明细中,都需要更换箱子列表
      */
 //    @PreAuthorize("@ss.hasPermi('business:outsource:export')")
-    @Log(title = "外协单主带箱方式,是整单的。如果换新箱子,明细中,都需要更换箱子", businessType = BusinessType.EXPORT)
+    @Log(title = "外协单导出", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response,  BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException, IOException {
         bizOutsourcedOrder = bizOutsourcedOrderService.getById(bizOutsourcedOrder);
@@ -95,6 +104,180 @@ public class BizOutsourcedOrderController extends BaseController {
         bizOutsourcedOrderService.exportTemplateProvinceAreaData(response, bizOutsourcedOrder);
     }
 
+    @Log(title = "外协打印", businessType = BusinessType.EXPORT)
+    @PostMapping("/printDetailPdf")
+    public void SocialSecurityPdf(BizOutsourcedOrder bizOutsourcedOrder, HttpServletResponse response) throws IOException, TemplateException, freemarker.template.TemplateException {
+
+        /** 按照产品进行区分 **/
+        bizOutsourcedOrder = bizOutsourcedOrderService.getById(bizOutsourcedOrder);
+        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
+        bizOutsourcedOrderDetail.setMasterId(bizOutsourcedOrder.getId());
+
+        //该发出单所有明细
+        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
+        // 创建SimpleDateFormat对象,并设置日期格式
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        bizOutsourcedOrder.setStringDate(dateFormat.format(bizOutsourcedOrder.getFormDate()));
+
+        List<List<BizOutsourcedOrderDetail> > list = new ArrayList<>();
+
+        //打印数据时每页14条
+        if(outsourcedOrderDetails.size() > 14){
+            // 用于临时存储每组数据的列表
+            List<BizOutsourcedOrderDetail> group = new ArrayList<>();
+            // 遍历 outsourcedOrderDetails 列表
+            for (BizOutsourcedOrderDetail detail : outsourcedOrderDetails) {
+                group.add(detail);
+                // 每添加 14 个元素后,将其添加到 list 中,并重置 group
+                if (group.size() == 14) {
+                    // 使用流过滤出 productNum 不为空的元素,并对其 productNum 值求和
+                    Integer sum = group.stream()
+                            .filter(item -> item.getProductNum() != null) // 过滤出 productNum 不为空的元素
+                            .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
+                            .sum(); // 计算总和
+                    // 然后,给每个对象的 sum 属性赋值
+                    for (BizOutsourcedOrderDetail item : group) {
+                        detail.setSum(sum);
+                        detail.setOriginalCarrierCount(item.getNewCarrierCount()==null?item.getOriginalCarrierCount():item.getNewCarrierCount());
+                    }
+                    list.add(new ArrayList<>(group));
+                    group = new ArrayList<>();
+                }
+            }
+            // 如果最后一组不足 14 个元素,也将其添加到 list 中
+            if (!group.isEmpty()) {
+                BizOutsourcedOrderDetail orderDetail=new BizOutsourcedOrderDetail();
+                while (group.size() < 14) {
+                    group.add(orderDetail); // 添加默认元素直到总数为14
+                }
+                list.add(group);
+            }
+        }else{
+            BizOutsourcedOrderDetail orderDetail=new BizOutsourcedOrderDetail();
+            while (outsourcedOrderDetails.size() < 14) {
+                outsourcedOrderDetails.add(orderDetail); // 添加默认元素直到总数为14
+            }
+            // 使用流过滤出 productNum 不为空的元素,并对其 productNum 值求和
+            Integer sum = outsourcedOrderDetails.stream()
+                    .filter(detail -> detail.getProductNum() != null) // 过滤出 productNum 不为空的元素
+                    .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
+                    .sum(); // 计算总和
+            // 然后,给每个对象的 sum 属性赋值
+            for (BizOutsourcedOrderDetail detail : outsourcedOrderDetails) {
+                detail.setSum(sum);
+                detail.setOriginalCarrierCount(detail.getNewCarrierCount()==null?detail.getOriginalCarrierCount():detail.getNewCarrierCount());
+            }
+
+            list.add(outsourcedOrderDetails);
+        }
+        bizOutsourcedOrder.setDetailLists(list);
+
+
+        Map<String, Object> paramMap = new HashMap<>();
+        paramMap.put("outsourcedOrder" , bizOutsourcedOrder);
+        Writer out = new StringWriter();
+        //获取模板地址
+        Template template = freeMarkerConfigurer.getConfiguration().getTemplate("outSourcedPdf.html");
+        template.process(paramMap, out);
+        out.flush();
+        out.close();
+        String templateContent = out.toString();
+        response.setCharacterEncoding("UTF-8");
+        response.setContentType("application/pdf");
+        String fileName ="外协发出明细";
+        response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes()));
+        byte[] resources = PdfUtil.html2Pdf(templateContent);
+        ServletOutputStream outputStream = response.getOutputStream();
+        outputStream.write(resources);
+        outputStream.close();
+    }
+
+//    @Log(title = "外协打印", businessType = BusinessType.EXPORT)
+//    @PostMapping("/printDetailPdf")
+//    public void SocialSecurityPdf(BizOutsourcedOrder bizOutsourcedOrder, HttpServletResponse response) throws IOException, TemplateException, freemarker.template.TemplateException {
+//
+//        /** 正常打印 **/
+//        bizOutsourcedOrder = bizOutsourcedOrderService.getById(bizOutsourcedOrder);
+//        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
+//        bizOutsourcedOrderDetail.setMasterId(bizOutsourcedOrder.getId());
+//        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
+//        // 创建SimpleDateFormat对象,并设置日期格式
+//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+//        bizOutsourcedOrder.setStringDate(dateFormat.format(bizOutsourcedOrder.getFormDate()));
+//
+//        List<List<BizOutsourcedOrderDetail> > list = new ArrayList<>();
+//
+//        //打印数据时每页14条
+//        if(outsourcedOrderDetails.size() > 14){
+//            // 用于临时存储每组数据的列表
+//            List<BizOutsourcedOrderDetail> group = new ArrayList<>();
+//            // 遍历 outsourcedOrderDetails 列表
+//            for (BizOutsourcedOrderDetail detail : outsourcedOrderDetails) {
+//                group.add(detail);
+//                // 每添加 14 个元素后,将其添加到 list 中,并重置 group
+//                if (group.size() == 14) {
+//                    // 使用流过滤出 productNum 不为空的元素,并对其 productNum 值求和
+//                    Integer sum = group.stream()
+//                            .filter(item -> item.getProductNum() != null) // 过滤出 productNum 不为空的元素
+//                            .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
+//                            .sum(); // 计算总和
+//                    // 然后,给每个对象的 sum 属性赋值
+//                    for (BizOutsourcedOrderDetail item : group) {
+//                        detail.setSum(sum);
+//                        detail.setOriginalCarrierCount(item.getNewCarrierCount()==null?item.getOriginalCarrierCount():item.getNewCarrierCount());
+//                    }
+//                    list.add(new ArrayList<>(group));
+//                    group = new ArrayList<>();
+//                }
+//            }
+//            // 如果最后一组不足 14 个元素,也将其添加到 list 中
+//            if (!group.isEmpty()) {
+//                BizOutsourcedOrderDetail orderDetail=new BizOutsourcedOrderDetail();
+//                while (group.size() < 14) {
+//                    group.add(orderDetail); // 添加默认元素直到总数为14
+//                }
+//                list.add(group);
+//            }
+//        }else{
+//            BizOutsourcedOrderDetail orderDetail=new BizOutsourcedOrderDetail();
+//            while (outsourcedOrderDetails.size() < 14) {
+//                outsourcedOrderDetails.add(orderDetail); // 添加默认元素直到总数为14
+//            }
+//            // 使用流过滤出 productNum 不为空的元素,并对其 productNum 值求和
+//            Integer sum = outsourcedOrderDetails.stream()
+//                    .filter(detail -> detail.getProductNum() != null) // 过滤出 productNum 不为空的元素
+//                    .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
+//                    .sum(); // 计算总和
+//            // 然后,给每个对象的 sum 属性赋值
+//            for (BizOutsourcedOrderDetail detail : outsourcedOrderDetails) {
+//                detail.setSum(sum);
+//                detail.setOriginalCarrierCount(detail.getNewCarrierCount()==null?detail.getOriginalCarrierCount():detail.getNewCarrierCount());
+//            }
+//
+//            list.add(outsourcedOrderDetails);
+//        }
+//        bizOutsourcedOrder.setDetailLists(list);
+//
+//
+//        Map<String, Object> paramMap = new HashMap<>();
+//        paramMap.put("outsourcedOrder" , bizOutsourcedOrder);
+//        Writer out = new StringWriter();
+//        //获取模板地址
+//        Template template = freeMarkerConfigurer.getConfiguration().getTemplate("outSourcedPdf.html");
+//        template.process(paramMap, out);
+//        out.flush();
+//        out.close();
+//        String templateContent = out.toString();
+//        response.setCharacterEncoding("UTF-8");
+//        response.setContentType("application/pdf");
+//        String fileName ="外协发出明细";
+//        response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes()));
+//        byte[] resources = PdfUtil.html2Pdf(templateContent);
+//        ServletOutputStream outputStream = response.getOutputStream();
+//        outputStream.write(resources);
+//        outputStream.close();
+//    }
+//
 
     /**
      * 获取外协单主

+ 7 - 0
src/main/java/cn/ezhizao/project/business/domain/BizOutsourcedOrder.java

@@ -88,5 +88,12 @@ public class BizOutsourcedOrder extends BaseEntity
     @TableField(exist = false)
     private Integer productNum;
 
+    /** 打印使用 **/
+    @TableField(exist = false)
+    private List<List<BizOutsourcedOrderDetail>> detailLists;
+
+    @TableField(exist = false)
+    private String stringDate;
+
 
 }

+ 4 - 0
src/main/java/cn/ezhizao/project/business/domain/BizOutsourcedOrderDetail.java

@@ -162,4 +162,8 @@ public class BizOutsourcedOrderDetail extends BaseEntity
     private String remark;
     @TableField(exist = false)
     private List<BizReturnReceiptDetail> returnReceiptDetailList;
+
+    //发出总数量 只在打印时用到
+    @TableField(exist = false)
+    private Integer sum;
 }

+ 4 - 0
src/main/java/cn/ezhizao/project/business/service/impl/BizOutsourcedOrderServiceImpl.java

@@ -16,12 +16,14 @@ import com.alibaba.excel.ExcelWriter;
 import com.alibaba.excel.write.metadata.WriteSheet;
 import com.alibaba.excel.write.metadata.fill.FillConfig;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import cn.ezhizao.project.business.mapper.BizOutsourcedOrderMapper;
 import cn.ezhizao.project.business.domain.BizOutsourcedOrder;
 import cn.ezhizao.project.business.service.IBizOutsourcedOrderService;
 
+
 /**
  * 外协单主
 带箱方式,是整单的。如果换新箱子,明细中,都需要更换箱子Service业务层处理
@@ -41,6 +43,8 @@ public class BizOutsourcedOrderServiceImpl  extends ServiceImpl<BizOutsourcedOrd
     @Value("${file.excelTemplate.url}")
     private  String templatePath;
 
+
+
     /**
      * 查询外协单主
 带箱方式,是整单的。如果换新箱子,明细中,都需要更换箱子列表

+ 168 - 0
src/main/resources/templates/outSourcedPdf.html

@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="zh">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <style>
+        @page {
+            margin: 15px 40px 20px 10px;
+            size: 211mm 140mm;
+        }
+
+        body {
+
+            font-family: Arial, sans-serif;
+        }
+
+        table {
+            width: 100%;
+            border-collapse: collapse;
+            /*margin-bottom: 300px;*/
+            font-size: 10px;
+        }
+
+        th, td {
+            text-align: center;
+            padding: 5px;
+            border: 1px solid black;
+        }
+
+        .border {
+            border: 1px solid black !important;
+        }
+
+        .total-row {
+            font-weight: bold;
+            /*background-color: lightgray;*/
+            text-align: center;
+        }
+
+        /* 用于模拟13列布局 */
+        .col-1 {
+
+        }
+        .right-align { text-align: right; }
+        .center-align { text-align: center; }
+        .left-align { text-align: left; }
+        .title-row {
+            font-size: 13px ;
+            display: flex;
+            justify-content: space-between; /* 元素之间的间距均匀分布 */
+            align-items: center; /* 垂直居中对齐 */
+            width: 100%; /* 确保标题行占满整个容器宽度 */
+            /*margin-bottom: 10px; !* 根据需要调整间距 *!*/
+        }
+
+        .title-row div {
+            margin: 0; /* 移除默认的外边距 */
+        }
+    </style>
+</head>
+<#list outsourcedOrder.detailLists as detail>
+<body>
+
+<!-- 标题行 -->
+<div class="title-row">
+    <div class="right-align" style=" font-size: 12px ; margin-left: 5px;padding-right: 150px ">外协单位:${outsourcedOrder.supplierName}</div>
+    <div class="center-align"  style="font-size: 13px ;padding-right: 90px">大连德迈仕精密科技股份有限公司</div>
+    <div class="left-align"  style=" font-size: 12px ;margin-right: 5px">单据号:${outsourcedOrder.formCode}</div>
+</div>
+<!-- 标题行 -->
+<div class="title-row" style="margin-top: 5px ; font-size: 12px ;">
+    <div class="right-align" style="margin-left: 5px; padding-right:180px;" >单据日期:${outsourcedOrder.stringDate}</div>
+    <div class="center-align" style="font-size: 13px ; padding-right: 185px">外协发出明细表</div>
+    <div class="left-align" style="margin-right: 5px">第${detail_index+1}页 共 ${outsourcedOrder.detailLists?size}页</div>
+</div>
+<table>
+
+
+    <!-- 第三行 -->
+    <tr class="header border">
+        <td class="col-0" align="center" valign="middle" style="width: 13px;">序号</td>
+        <td class="col-1" align="center" valign="middle">产品描述</td>
+        <td class="col-1" align="center" valign="middle" style="width: 60px;">批号</td>
+        <td class="col-1" align="center" valign="middle">工序名称</td>
+        <td class="col-1" align="center" valign="middle" style="width: 30px;">发出量</td>
+        <td class="col-1" align="center" valign="middle" style="width: 13px;">箱数</td>
+        <td class="col-1" align="center" valign="middle" style="width: 100px;"> 发出箱号</td>
+        <td class="col-1" align="center" valign="middle" style="width: 15px;">备注</td>
+    </tr>
+
+    <!-- 动态数据行 -->
+    <#list detail as item>
+    <tr class=" border">
+        <td class="col-1" align="center">${ item_index + 1 }</td>
+        <td class="col-1" style="text-align: left;">
+            <#if item.productDescription??>
+            ${ item.productDescription}
+            <#else>
+
+            </#if>
+        </td>
+        <td class="col-1" style="text-align: left;" >
+            <#if item.lotCode??>
+            ${ item.lotCode }
+            <#else>
+
+        </#if>
+        </td>
+        <td class="col-1" style="text-align: left;" >
+            <#if item.processNames??>
+            ${ item.processNames }
+            <#else>
+
+        </#if>
+        </td>
+        <td class="col-1" style=" text-align: right;" >
+            <#if item.productNum??>
+            ${ item.productNum }
+            <#else>
+
+        </#if>
+           </td>
+        <td class="col-1" >
+            <#if item.originalCarrierCount??>
+            ${ item.originalCarrierCount }
+            <#else>
+
+        </#if>
+            </td>
+        <td class="col-1" style="text-align: left;">
+            <#if item.newCarrier??>
+            ${ item.newCarrier }
+            <#else>
+
+        </#if>
+       </td>
+        <td class="col-1" style="text-align: left;" >
+            <#if item.remark??>
+            ${ item.remark }
+            <#else>
+
+        </#if>
+        </td>
+
+    </tr>
+    </#list>
+<!--小计行-->
+<tr class="total-row border">
+    <td class="col-1" align="center" colspan="1"></td>
+    <td class="col-1" align="center" colspan="1">小计</td>
+    <!-- 这里根据实际计算结果填充 -->
+    <td class="col-1" align="center" colspan="1"></td>
+    <td class="col-1" align="center" colspan="1"></td>
+    <td class="col-1" align="center" colspan="1"></td>
+    <td class="col-1" align="center" colspan="1"></td>
+    <td class="col-1" align="center" colspan="1"></td>
+    <td class="col-1" align="center" colspan="1"></td>
+    <!-- ... 类似地填充剩余单元格 -->
+</tr>
+</table>
+<div class="title-row" >
+    <div class="center-align"  style="margin-left: 60px;padding-right: 90px">发出人:</div>
+    <div class="center-align"  style="margin-left: 60px;padding-right: 120px">外协接收人:</div>
+    <div class="left-align" style="margin-right: 15px">白-存根, 粉-生产, 黄-外协</div>
+</div>
+</body>
+</#list>
+</html>