diff --git a/jeecg-module-miniapp/pom.xml b/jeecg-module-miniapp/pom.xml index 26bb0cb..1844f4a 100644 --- a/jeecg-module-miniapp/pom.xml +++ b/jeecg-module-miniapp/pom.xml @@ -38,15 +38,13 @@ com.itextpdf - itext-core + itext7-core 8.0.3 pom - - com.itextpdf - forms - 8.0.3 + org.springframework + spring-test diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/dict/controller/DictController.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/dict/controller/DictController.java new file mode 100644 index 0000000..243db1b --- /dev/null +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/dict/controller/DictController.java @@ -0,0 +1,44 @@ +package org.jeecg.modules.miniapp.dict.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.api.CommonAPI; +import org.jeecg.common.system.vo.DictModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author tanzs + * @date 2025/2/23 17:21 + */ +@Api(tags="字典查询") +@RestController +@RequestMapping("/miniapp/dict") +@Slf4j +public class DictController { + + @Lazy + @Resource + private CommonAPI commonApi; + + /** + * 获取数据字典 + * @param code + * @return + */ + @ApiOperation(value="字典code查询", notes="字典code查询") + @GetMapping("/queryDictItemsByCode") + @ApiImplicitParam(name = "code", value = "字典 code", required = true, dataType = "String", paramType = "query") + List queryDictItemsByCode(@RequestParam("code") String code){ + return commonApi.queryDictItemsByCode(code); + } +} diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/controller/OrderController.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/controller/OrderController.java index 262de33..13c926c 100644 --- a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/controller/OrderController.java +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/controller/OrderController.java @@ -15,9 +15,11 @@ import org.jeecg.common.aspect.annotation.AutoLog; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryRuleEnum; import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.common.system.vo.MLoginUser; import org.jeecg.common.util.oConvertUtils; import org.jeecg.modules.miniapp.order.service.OrderService; import org.jeecg.modules.miniapp.order.service.impl.OrderServiceImpl; +import org.jeecg.modules.miniapp.utils.UserInfoUtil; import org.jeecg.modules.sysMiniapp.order.entity.AppOrder; import org.jeecg.modules.sysMiniapp.order.entity.AppOrderCar; import org.jeecg.modules.sysMiniapp.order.entity.AppOrderFinance; @@ -66,6 +68,8 @@ public class OrderController { private IAppOrderFinanceService appOrderFinanceService; @Autowired private OrderService orderService; + @Autowired + private UserInfoUtil userInfoUtil; /** * 分页列表查询 @@ -83,6 +87,8 @@ public class OrderController { @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) { + // 获取当前用户信息,只能查询当前账号订单 + MLoginUser userInfo = userInfoUtil.getUserInfo(); // 自定义查询规则 Map customeRuleMap = new HashMap<>(); // 自定义多选的查询规则为:LIKE_WITH_OR @@ -90,6 +96,7 @@ public class OrderController { customeRuleMap.put("custType", QueryRuleEnum.LIKE_WITH_OR); customeRuleMap.put("status", QueryRuleEnum.LIKE_WITH_OR); QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(appOrder, req.getParameterMap(),customeRuleMap); + queryWrapper.eq("create_by",userInfo.getNickName()); Page page = new Page(pageNo, pageSize); IPage pageList = appOrderService.page(page, queryWrapper); return Result.OK(pageList); @@ -124,7 +131,13 @@ public class OrderController { @ApiImplicitParam(name = "orderId", value = "订单id", required = true, dataType = "String", paramType = "query"), }) public Result addContract(@RequestParam(value = "orderId")String orderId) { - AppOrder appOrderEntity = appOrderService.getById(orderId); + // 获取当前用户信息,只能生成当前账号订单 + MLoginUser userInfo = userInfoUtil.getUserInfo(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("create_by", userInfo.getNickName()); + queryWrapper.eq("id",orderId); + queryWrapper.eq("status",0); // 未生效的订单才可以生成 + AppOrder appOrderEntity = appOrderService.getOne(queryWrapper); if(appOrderEntity==null) { return Result.error("未找到对应数据"); } @@ -132,6 +145,32 @@ public class OrderController { return Result.OK(url); } + /** + * 生成合同 + * @param orderId 订单 id + * @return + */ + @AutoLog(value = "合同订单表-取消合同") + @ApiOperation(value="合同订单表-取消合同", notes="合同订单表-取消合同") + @GetMapping(value = "/canelContract") + @ApiImplicitParams({ + @ApiImplicitParam(name = "orderId", value = "订单id", required = true, dataType = "String", paramType = "query"), + }) + public Result canelContract(@RequestParam(value = "orderId")String orderId) { + // 获取当前用户信息,只能生成当前账号订单 + MLoginUser userInfo = userInfoUtil.getUserInfo(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("create_by", userInfo.getNickName()); + queryWrapper.eq("id",orderId); + queryWrapper.eq("status",1); // 未生效的订单才可以生成 + AppOrder appOrderEntity = appOrderService.getOne(queryWrapper); + if(appOrderEntity==null) { + return Result.error("未找到对应数据"); + } + orderService.canelOrderContract(appOrderEntity); + return Result.OK("取消成功"); + } + /** * 编辑 * diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/entity/OrderInfo.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/entity/OrderInfo.java index b5bef27..b72251d 100644 --- a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/entity/OrderInfo.java +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/entity/OrderInfo.java @@ -1,5 +1,6 @@ package org.jeecg.modules.miniapp.order.entity; +import com.alibaba.fastjson.annotation.JSONField; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.jeecg.common.aspect.annotation.Dict; @@ -60,8 +61,7 @@ public class OrderInfo implements Serializable { /**营业执照*/ private java.lang.String busLicense; /**创建日期*/ - @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") - @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") private java.util.Date createTime; /**订单状态*/ @Dict(dicCode = "order_status") @@ -71,8 +71,7 @@ public class OrderInfo implements Serializable { /**收款方*/ private java.lang.String payee; /**收款时间*/ - @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") - @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") private java.util.Date payeeTime; /**支付凭证*/ private java.lang.String payVoucherUrl; @@ -98,8 +97,7 @@ public class OrderInfo implements Serializable { /**里程*/ private java.lang.String mileage; /**购车时间*/ - @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") - @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") private java.util.Date buyTime; /**车辆购置价*/ private java.math.BigDecimal buyMoney; @@ -122,13 +120,11 @@ public class OrderInfo implements Serializable { /**服务费*/ private java.math.BigDecimal serviceMoney; /**生效时间*/ - @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") - @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd") private java.util.Date effectiveTime; /**失效时间*/ - @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") - @DateTimeFormat(pattern="yyyy-MM-dd") + @JSONField(format = "yyyy-MM-dd") private java.util.Date endTime; /**服务年限*/ private java.lang.String serviceYear; @@ -150,8 +146,7 @@ public class OrderInfo implements Serializable { private java.lang.String assigneeCardNo; /**支付时间*/ - @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") - @DateTimeFormat(pattern="yyyy-MM-dd") + @JSONField(format = "yyyy-MM-dd") private java.util.Date payTime; /**经销商地址*/ private java.lang.String dealerAddress; diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/OrderService.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/OrderService.java index 5c0916a..d18794a 100644 --- a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/OrderService.java +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/OrderService.java @@ -28,4 +28,11 @@ public interface OrderService { * @return */ String addOrderContract(AppOrder appOrder); + + /** + * 取消订单合同 + * @param appOrder + * @return + */ + void canelOrderContract(AppOrder appOrder); } diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/impl/OrderServiceImpl.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/impl/OrderServiceImpl.java index fdd19c9..59b30af 100644 --- a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/impl/OrderServiceImpl.java +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/order/service/impl/OrderServiceImpl.java @@ -7,8 +7,10 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.system.vo.MLoginUser; +import org.jeecg.common.util.CommonUtils; import org.jeecg.modules.miniapp.order.entity.OrderInfo; import org.jeecg.modules.miniapp.order.service.OrderService; +import org.jeecg.modules.miniapp.utils.PdfFormUtils; import org.jeecg.modules.miniapp.utils.UserInfoUtil; import org.jeecg.modules.sysMiniapp.order.entity.AppOrder; import org.jeecg.modules.sysMiniapp.order.entity.AppOrderCar; @@ -20,15 +22,22 @@ import org.jeecg.modules.sysMiniapp.order.mapper.AppOrderMapper; import org.jeecg.modules.sysMiniapp.order.mapper.AppOrderVoucherMapper; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.lang.reflect.Field; import java.text.MessageFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; import static org.jeecg.modules.miniapp.utils.PdfFormUtils.*; @@ -50,6 +59,11 @@ public class OrderServiceImpl implements OrderService { private AppOrderFinanceMapper appOrderFinanceMapper; @Autowired private UserInfoUtil userInfoUtil; + @Autowired + private PdfFormUtils pdfFormUtils; + + @Value(value="${jeecg.uploadType}") + private String uploadType; /** @@ -66,19 +80,20 @@ public class OrderServiceImpl implements OrderService { MLoginUser user =userInfoUtil.getUserInfo(); // 生成唯一订单号 appOrder.setOrderNum( - MessageFormat.format("{0}{1}{3}", + MessageFormat.format("{0}{1}{2}", "CXSC", - DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN), - String.valueOf(new Snowflake(1, 1).nextId())) - ); + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN), + String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000)))); appOrder.setStatus(0); // 默认未生效 // 当前登录用户 appOrder.setCreateBy(user.getNickName()); + appOrder.setCreateTime(new Date()); appOrderMapper.insert(appOrder); if(appOrderCarList!=null && appOrderCarList.size()>0) { for(AppOrderCar entity:appOrderCarList) { //外键设置 entity.setOrderFkId(appOrder.getId()); + entity.setCreateBy(user.getNickName()); appOrderCarMapper.insert(entity); } } @@ -86,6 +101,7 @@ public class OrderServiceImpl implements OrderService { for(AppOrderVoucher entity:appOrderVoucherList) { //外键设置 entity.setOrderFkId(appOrder.getId()); + entity.setCreateBy(user.getNickName()); appOrderVoucherMapper.insert(entity); } } @@ -93,6 +109,7 @@ public class OrderServiceImpl implements OrderService { for(AppOrderFinance entity:appOrderFinanceList) { //外键设置 entity.setOrderFkId(appOrder.getId()); + entity.setCreateBy(user.getNickName()); appOrderFinanceMapper.insert(entity); } } @@ -121,15 +138,24 @@ public class OrderServiceImpl implements OrderService { String contractUrl = null; // pdf 文件表单填充 // 1.定义输出临时路径 - String outputPath = "/Users/tanzs/Downloads/" + appOrder.getOrderNum() +".pdf"; + String outputPath = System.getProperty("java.io.tmpdir") + "/" + appOrder.getOrderNum() +".pdf"; // 2.转换实体类到 Map try { Map formData = jsonToMap(JSONObject.toJSONString(orderInfo)); - log.info("FormData: " + JSONObject.toJSONString(formData)); + log.debug("FormData: " + JSONObject.toJSONString(formData)); //3. 拼接 pdf - fillPdfFormFromUrl(appOrder.getProductContractTemp(),outputPath,formData,6.5f); + pdfFormUtils.fillPdfFormFromUrl(appOrder.getProductContractTemp(),outputPath,formData,6.5f); //4. 调用合同上传 oss - + File pdfFile = new File(outputPath); + contractUrl = CommonUtils.upload(convertFileToMultipartFile(pdfFile), "contract", uploadType); + // 5. 更新订单表 + appOrder.setStatus(1); // 更改订单状态 + appOrder.setContractUrl(contractUrl); + appOrder.setUpdateBy(userInfoUtil.getUserInfo().getNickName()); + appOrder.setUpdateTime(new Date()); + appOrderMapper.updateById(appOrder); + // 删除临时文件 + pdfFile.delete(); } catch (Exception e) { log.error("合同生成失败,订单编号:{}",appOrder.getOrderNum()); throw new RuntimeException(e); @@ -137,6 +163,27 @@ public class OrderServiceImpl implements OrderService { return contractUrl; } + @Override + public void canelOrderContract(AppOrder appOrder) { + MLoginUser userInfo = userInfoUtil.getUserInfo(); + appOrder.setUpdateBy(userInfo.getNickName()); + appOrder.setStatus(0); + appOrderMapper.updateById(appOrder); + } + + private MultipartFile convertFileToMultipartFile(File file) throws IOException { + FileInputStream inputStream = new FileInputStream(file); + return new MockMultipartFile(file.getName(), file.getName(), "application/octet-stream", inputStream); + } + + // 订单号生成 + public static void main(String[] args) { + System.err.println(MessageFormat.format("{0}{1}{2}", + "CXSC", + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN), + String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000)))); + } + } diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/product/controller/MProductController.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/product/controller/MProductController.java index fde880a..b820edb 100644 --- a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/product/controller/MProductController.java +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/product/controller/MProductController.java @@ -53,7 +53,6 @@ public class MProductController { @ApiOperation(value="产品管理-查询所有产品服务", notes="产品管理-查询所有产品服务") @GetMapping(value = "/categories") - @IgnoreAuth public Result> query(@RequestParam(name = "name",required = false)String name) { return mProductService.getAllCateGoryProduct(name); } diff --git a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/utils/PdfFormUtils.java b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/utils/PdfFormUtils.java index df79c83..a57ac1d 100644 --- a/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/utils/PdfFormUtils.java +++ b/jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/utils/PdfFormUtils.java @@ -4,28 +4,54 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.itextpdf.forms.PdfAcroForm; import com.itextpdf.forms.fields.PdfFormField; +import com.itextpdf.io.font.FontProgram; +import com.itextpdf.io.font.FontProgramFactory; +import com.itextpdf.io.font.PdfEncodings; +import com.itextpdf.io.font.TrueTypeCollection; +import com.itextpdf.kernel.font.PdfFont; +import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfName; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.PdfWriter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import java.awt.*; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Type; +import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; +import static com.itextpdf.kernel.pdf.PdfName.BaseFont; + /** * @author Tanzs * @date 2025/2/19 下午3:29 * @description PDF表单填充工具类 */ +@Component +@Slf4j public class PdfFormUtils { private static final Gson gson = new Gson(); + // 本地使用调试字体路径 + private static final String TEST_FONT_PATH = "/Users/tanzs/Documents/fonts/simsun.ttc,0"; + + // TODO 环境变量获取文字路径,重新部署需要复制 resource 下的字体文件到指定路径 + @Value(value = "${jeecg.path.fonts}") + private String DEFAULT_FONT_PATH; + + + + /** * 通过 pdf 文本域拼接 PDF 表单 @@ -42,19 +68,26 @@ public class PdfFormUtils { // 获取表单 PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); - // 填写表单字段 + // 打印所有字段名称 Map fields = form.getAllFormFields(); for (String fieldName : fields.keySet()) { System.out.println("Field name: " + fieldName); } + // 创建字体 + PdfFont baseFont = PdfFontFactory.createFont(TEST_FONT_PATH, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); + + // 填写表单字段 for (Map.Entry entry : formData.entrySet()) { String fieldName = entry.getKey(); String fieldValue = entry.getValue(); - // 确保字段存在并填写值 - if (fields.containsKey(fieldName)) { - fields.get(fieldName).setValue(fieldValue); - fields.get(fieldName).setFontSize(fontSize); // 设置字体大小 + PdfFormField field = fields.get(fieldName); + if (field != null && field.getFormType() == PdfName.Tx) { // 检查是否为文本字段 + field.setValue(fieldValue); + field.setFont(baseFont); + field.setFontSize(fontSize); + } else { + System.out.println("Field not found or not a text field: " + fieldName); } } @@ -70,34 +103,39 @@ public class PdfFormUtils { /** * 通过 pdf 文本域拼接 PDF 表单 * @param templateUrl PDF 表单文件 URL,例如 "https://example.com/template.pdf" - * @param outputPath 填充后的 PDF 文件路径 + * @param outputFilePath 填充后的 PDF 文件路径 * @param formData 填充的数据,键为表单字段名称,值为填充的值 * @param fontSize 字体大小 */ - public static void fillPdfFormFromUrl(String templateUrl, String outputPath, Map formData, float fontSize) { + public void fillPdfFormFromUrl(String templateUrl, String outputFilePath, Map formData, float fontSize) { try { // 从 URL 获取输入流 URL url = new URL(templateUrl); try (InputStream templateInputStream = url.openStream(); - PdfWriter writer = new PdfWriter(outputPath); + PdfWriter writer = new PdfWriter(outputFilePath); PdfDocument pdfDoc = new PdfDocument(new PdfReader(templateInputStream), writer)) { // 获取表单 PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); - // 填写表单字段 + // 打印所有字段名称 Map fields = form.getAllFormFields(); for (String fieldName : fields.keySet()) { - System.out.println("Field name: " + fieldName); + log.debug("Field name: " + fieldName); } + // 创建字体 + PdfFont baseFont = PdfFontFactory.createFont(DEFAULT_FONT_PATH, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); + + // 填写表单字段 for (Map.Entry entry : formData.entrySet()) { String fieldName = entry.getKey(); String fieldValue = entry.getValue(); - // 确保字段存在并填写值 - if (fields.containsKey(fieldName)) { - fields.get(fieldName).setValue(fieldValue); - fields.get(fieldName).setFontSize(fontSize); // 设置字体大小 + PdfFormField field = fields.get(fieldName); + if (field != null && field.getFormType() == PdfName.Tx) { // 检查是否为文本字段 + field.setValue(fieldValue); + field.setFont(baseFont); + field.setFontSize(fontSize); } } @@ -106,20 +144,28 @@ public class PdfFormUtils { } catch (IOException e) { e.printStackTrace(); + throw new RuntimeException("pdf合同生成失败,请稍后重试!"); } } catch (IOException e) { e.printStackTrace(); + throw new RuntimeException("pdf合同生成失败,请稍后重试!"); } } - - public static void fillPdfFormFromUrl2(String templateUrl, String outputPath, Map formData, float fontSize) { + /** + * 通过 pdf 文本域拼接 PDF 表单 + * @param templateUrl PDF 表单文件 URL,例如 "https://example.com/template.pdf" + * @param outputFilePath 填充后的 PDF 文件路径 + * @param formData 填充的数据,键为表单字段名称,值为填充的值 + * @param fontSize 字体大小 + */ + public static void fillPdfFormFromUrlLocal(String templateUrl, String outputFilePath, Map formData, float fontSize) { try { // 从 URL 获取输入流 URL url = new URL(templateUrl); try (InputStream templateInputStream = url.openStream(); - PdfWriter writer = new PdfWriter(outputPath); + PdfWriter writer = new PdfWriter(outputFilePath); PdfDocument pdfDoc = new PdfDocument(new PdfReader(templateInputStream), writer)) { // 获取表单 @@ -130,6 +176,8 @@ public class PdfFormUtils { for (String fieldName : fields.keySet()) { System.out.println("Field name: " + fieldName); } + // 创建字体 + PdfFont baseFont = PdfFontFactory.createFont(TEST_FONT_PATH, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); // 填写表单字段 for (Map.Entry entry : formData.entrySet()) { @@ -139,6 +187,7 @@ public class PdfFormUtils { PdfFormField field = fields.get(fieldName); if (field != null && field.getFormType() == PdfName.Tx) { // 检查是否为文本字段 field.setValue(fieldValue); + field.setFont(baseFont); field.setFontSize(fontSize); } else { System.out.println("Field not found or not a text field: " + fieldName); @@ -158,6 +207,8 @@ public class PdfFormUtils { } + + /** * 实体类转换成Map * @param obj @@ -189,21 +240,21 @@ public class PdfFormUtils { // 示例:调用此工具类 public static void main(String[] args) { - String templatePath = "/Users/tanzs/Downloads/carT.pdf"; -// String templateUrl = "https://jf.sh.189.cn/minio/gov-miniapp/order_pdf/carT.pdf"; +// String templatePath = "/Users/tanzs/Downloads/carT.pdf"; + String templateUrl = "https://img.augcl.com/temp/carT_1740226107035.pdf"; String outputPath = "/Users/tanzs/Downloads/carR.pdf"; float fontSize = 6.5f; // 设置字体大小 // 填写的数据 Map formData = new HashMap(); - formData.put("cust_name", "张三"); - formData.put("cust_phone", "123213"); + formData.put("custName", "张三"); + formData.put("custPhone", "123213"); formData.put("carNo", "京A12345"); - formData.put("cust_address", "测试地址"); + formData.put("custAddress", "测试地址"); // 调用工具类进行表单填写 - fillPdfForm(templatePath, outputPath, formData, fontSize); -// fillPdfFormFromUrl(templateUrl, outputPath, formData, fontSize); +// fillPdfForm(templatePath, outputPath, formData, fontSize); + fillPdfFormFromUrlLocal(templateUrl, outputPath, formData, fontSize); } } diff --git a/jeecg-module-system/jeecg-system-start/pom.xml b/jeecg-module-system/jeecg-system-start/pom.xml index 744e9d6..ce33b9f 100644 --- a/jeecg-module-system/jeecg-system-start/pom.xml +++ b/jeecg-module-system/jeecg-system-start/pom.xml @@ -93,7 +93,7 @@ ${project.build.directory}/lib - runtime + false false diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml index fe77909..025a586 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml @@ -227,6 +227,8 @@ jeecg: upload: /opt/upFiles #webapp文件路径 webapp: /opt/webapp + # 字体路径 + fonts: "/Users/tanzs/Documents/fonts/simsun.ttc,0" shiro: excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/** #阿里云oss存储和大鱼短信秘钥配置 diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml index 104c7aa..f2876f5 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml @@ -227,6 +227,8 @@ jeecg: upload: /opt/jeecg-boot/upload #webapp文件路径 webapp: /opt/jeecg-boot/webapp + # 字体路径 + fonts: "/opt/fonts/simsun.ttc,0" shiro: excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/api/getUserInfo #阿里云oss存储和大鱼短信秘钥配置 diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml b/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml index 39833aa..cd31d6a 100644 --- a/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml +++ b/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml @@ -227,6 +227,8 @@ jeecg: upload: /opt/upFiles #webapp文件路径 webapp: /opt/webapp + # 字体路径 + fonts: "/opt/fonts/simsun.ttc,0" shiro: excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/** #阿里云oss存储和大鱼短信秘钥配置 diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/fonts/STKAITI.TTF b/jeecg-module-system/jeecg-system-start/src/main/resources/fonts/STKAITI.TTF new file mode 100644 index 0000000..5044116 Binary files /dev/null and b/jeecg-module-system/jeecg-system-start/src/main/resources/fonts/STKAITI.TTF differ diff --git a/jeecg-module-system/jeecg-system-start/src/main/resources/fonts/simsun.ttc b/jeecg-module-system/jeecg-system-start/src/main/resources/fonts/simsun.ttc new file mode 100644 index 0000000..40e9693 Binary files /dev/null and b/jeecg-module-system/jeecg-system-start/src/main/resources/fonts/simsun.ttc differ