From 2a3c80a8bd6eea76a14be03929f65dfebf117f95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BA=84=E9=94=90=E6=B3=A2?=
<10549902+zhuangruibo@user.noreply.gitee.com>
Date: Tue, 14 Apr 2026 16:10:12 +0800
Subject: [PATCH 1/6] =?UTF-8?q?=E9=80=81=E7=A0=81=E5=85=A5=E4=BC=81?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../enterprisePubQrcodeList.html | 415 +++++++
.../EnterprisePubQrcodeController.java | 317 +++++
.../zdxt/code/domain/EnterprisePubQrcode.java | 310 +++++
.../mapper/EnterprisePubQrcodeMapper.java | 90 ++
.../impl/EnterprisePubQrcodeServiceImpl.java | 1043 +++++++++++++++++
.../java/com/zdxt/code/utils/QRCodeUtil.java | 83 ++
.../mapper/EnterprisePubQrcodeMapper.xml | 189 +++
7 files changed, 2447 insertions(+)
create mode 100644 lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/project/code/enterprise_pub_qrcode/enterprisePubQrcodeList.html
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/controller/EnterprisePubQrcodeController.java
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/domain/EnterprisePubQrcode.java
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/mapper/EnterprisePubQrcodeMapper.java
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/EnterprisePubQrcodeServiceImpl.java
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/mapper/EnterprisePubQrcodeMapper.xml
diff --git a/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/project/code/enterprise_pub_qrcode/enterprisePubQrcodeList.html b/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/project/code/enterprise_pub_qrcode/enterprisePubQrcodeList.html
new file mode 100644
index 00000000..627874f6
--- /dev/null
+++ b/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/project/code/enterprise_pub_qrcode/enterprisePubQrcodeList.html
@@ -0,0 +1,415 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/controller/EnterprisePubQrcodeController.java b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/controller/EnterprisePubQrcodeController.java
new file mode 100644
index 00000000..f95aab55
--- /dev/null
+++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/controller/EnterprisePubQrcodeController.java
@@ -0,0 +1,317 @@
+package com.zdxt.code.controller;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.zdxt.common.ZDResponse;
+import com.zdxt.common.controller.BaseController;
+import com.zdxt.common.util.TableDataInfo;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.zdxt.code.domain.EnterprisePubQrcode;
+import com.zdxt.code.service.IEnterprisePubQrcodeService;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 送码入企信息Controller
+ *
+ * @author chenrui
+ * @date 2026-04-10
+ */
+@Controller
+@RequestMapping("/code/enterprisePubQrcode")
+public class EnterprisePubQrcodeController extends BaseController
+{
+ private static final Logger log = LoggerFactory.getLogger(EnterprisePubQrcodeController.class);
+
+ private String prefix = "project/code/enterprise_pub_qrcode";
+
+ @Autowired
+ private IEnterprisePubQrcodeService enterprisePubQrcodeService;
+
+ @RequiresPermissions("code:pubQrcode:view")
+ @GetMapping()
+ public String pubQrcode()
+ {
+ return prefix + "/enterprisePubQrcodeList";
+ }
+
+ /**
+ * 查询送码入企信息列表
+ */
+ @RequiresPermissions("code:pubQrcode:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ startPage();
+ List list = enterprisePubQrcodeService.selectEnterprisePubQrcodeList(enterprisePubQrcode);
+ return getDataTable(list);
+ }
+
+ /**
+ * 查询送码入企信息列表
+ */
+ @GetMapping("/queryList")
+ @ResponseBody
+ public ZDResponse queryList(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ startPage();
+ List list = enterprisePubQrcodeService.selectEnterprisePubQrcodeList(enterprisePubQrcode);
+ return ZDResponse.success("查询成功", list);
+ }
+
+ /**
+ * 新增送码入企信息
+ */
+ @GetMapping("/add")
+ public String add()
+ {
+ return prefix + "/add";
+ }
+
+ /**
+ * 新增保存送码入企信息
+ */
+ @RequiresPermissions("code:pubQrcode:add")
+ @PostMapping("/add")
+ @ResponseBody
+ public ZDResponse addSave(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ return enterprisePubQrcodeService.insertEnterprisePubQrcode(enterprisePubQrcode) > 0
+ ? ZDResponse.success("新增成功") : ZDResponse.error("新增失败");
+ }
+
+ /**
+ * 修改送码入企信息
+ */
+ @GetMapping("/edit/{id}")
+ public String edit(@PathVariable("id") String id, ModelMap mmap)
+ {
+ EnterprisePubQrcode enterprisePubQrcode = enterprisePubQrcodeService.selectEnterprisePubQrcodeById(id);
+ mmap.put("enterprisePubQrcode", enterprisePubQrcode);
+ return prefix + "/edit";
+ }
+
+ /**
+ * 修改保存送码入企信息
+ */
+ @RequiresPermissions("code:pubQrcode:edit")
+ @PostMapping("/edit")
+ @ResponseBody
+ public ZDResponse editSave(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ return enterprisePubQrcodeService.updateEnterprisePubQrcode(enterprisePubQrcode) > 0
+ ? ZDResponse.success("修改成功") : ZDResponse.error("修改失败");
+ }
+
+ /**
+ * 删除送码入企信息
+ */
+ @RequiresPermissions("code:pubQrcode:remove")
+ @PostMapping("/remove")
+ @ResponseBody
+ public ZDResponse remove(String ids)
+ {
+ return enterprisePubQrcodeService.deleteEnterprisePubQrcodeByIds(ids) > 0
+ ? ZDResponse.success("删除成功") : ZDResponse.error("删除失败");
+ }
+
+ /**
+ * 获取送码入企信息详情
+ */
+ @RequiresPermissions("code:pubQrcode:detail")
+ @GetMapping("/detail")
+ @ResponseBody
+ public ZDResponse detail(String id)
+ {
+ return ZDResponse.success("查询成功",
+ enterprisePubQrcodeService.selectEnterprisePubQrcodeById(id));
+ }
+
+ /**
+ * 下载导入模板
+ */
+ @GetMapping("/importTemplate")
+ public void importTemplate(HttpServletResponse response)
+ {
+ try
+ {
+ // 创建模板Excel
+ Workbook workbook = new XSSFWorkbook();
+ Sheet sheet = workbook.createSheet("送码入企数据");
+ // 创建表头
+ Row headerRow = sheet.createRow(0);
+ headerRow.createCell(0).setCellValue("序号");
+ headerRow.createCell(1).setCellValue("企业名称");
+ headerRow.createCell(2).setCellValue("统一社会信用代码");
+ headerRow.createCell(3).setCellValue("归属区域");
+ headerRow.createCell(4).setCellValue("归属街道");
+ // 设置列宽
+ sheet.setColumnWidth(0, 2000);
+ sheet.setColumnWidth(1, 8000);
+ sheet.setColumnWidth(2, 6000);
+ sheet.setColumnWidth(3, 5000);
+ sheet.setColumnWidth(4, 5000);
+
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ response.setHeader("Content-Disposition", "attachment;filename=enterprise_pub_qrcode_template.xlsx");
+ workbook.write(response.getOutputStream());
+ workbook.close();
+ }
+ catch (Exception e)
+ {
+ log.error("下载导入模板失败", e);
+ }
+ }
+
+ /**
+ * 导入送码入企数据
+ */
+ @RequiresPermissions("code:pubQrcode:add")
+ @PostMapping("/importData")
+ @ResponseBody
+ public ZDResponse importData(MultipartFile file)
+ {
+ try
+ {
+ String message = enterprisePubQrcodeService.importEnterprisePubQrcode(file);
+ return ZDResponse.success(message);
+ }
+ catch (Exception e)
+ {
+ log.error("导入送码入企数据失败", e);
+ return ZDResponse.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 批量匹配送码入企数据
+ */
+ @RequiresPermissions("code:pubQrcode:edit")
+ @PostMapping("/matchSelectEnterprise")
+ @ResponseBody
+ public ZDResponse matchSelectEnterprise(String ids)
+ {
+ try
+ {
+ String message = enterprisePubQrcodeService.matchSelectEnterprise(ids);
+ return ZDResponse.success(message);
+ }
+ catch (Exception e)
+ {
+ log.error("批量匹配送码入企数据失败", e);
+ return ZDResponse.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 强制匹配送码入企数据
+ */
+ @RequiresPermissions("code:pubQrcode:edit")
+ @PostMapping("/forceMatch")
+ @ResponseBody
+ public ZDResponse forceMatch(String id)
+ {
+ try
+ {
+ String message = enterprisePubQrcodeService.forceMatch(id);
+ return ZDResponse.success(message);
+ }
+ catch (Exception e)
+ {
+ log.error("强制匹配失败", e);
+ return ZDResponse.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 下载送码入企PDF
+ */
+ @RequiresPermissions("code:pubQrcode:edit")
+ @GetMapping("/download")
+ public void download(String ids, HttpServletResponse response)
+ {
+ try
+ {
+ enterprisePubQrcodeService.downloadPdf(ids, response);
+ }
+ catch (Exception e)
+ {
+ log.error("下载PDF失败", e);
+ if (response.isCommitted())
+ {
+ log.warn("响应已提交,无法输出错误页面,客户端可能已断开连接");
+ return;
+ }
+ try
+ {
+ response.reset();
+ response.setContentType("text/html;charset=utf-8");
+ response.getOutputStream().write(
+ ("").getBytes("utf-8"));
+ response.getOutputStream().flush();
+ }
+ catch (IOException ex)
+ {
+ log.warn("输出错误响应失败,客户端可能已断开连接: {}", ex.getMessage());
+ }
+ catch (Exception ex)
+ {
+ log.error("输出错误响应失败", ex);
+ }
+ }
+ }
+
+ /**
+ * 生成送码入企PDF文件(落盘后返回下载地址)
+ */
+ @RequiresPermissions("code:pubQrcode:edit")
+ @PostMapping("/generatePdf")
+ @ResponseBody
+ public ZDResponse generatePdf(String ids)
+ {
+ try
+ {
+ String downloadUrl = enterprisePubQrcodeService.generatePdfFile(ids);
+ return ZDResponse.success("生成完成", downloadUrl);
+ }
+ catch (Exception e)
+ {
+ log.error("生成PDF失败", e);
+ return ZDResponse.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 批量设置下载状态
+ */
+ @RequiresPermissions("code:pubQrcode:edit")
+ @PostMapping("/batchUpdateDownloadStatus")
+ @ResponseBody
+ public ZDResponse batchUpdateDownloadStatus(String ids, String downloadStatus, String remark)
+ {
+ try
+ {
+ int rows = enterprisePubQrcodeService.batchUpdateDownloadStatus(ids, downloadStatus, remark);
+ return rows > 0 ? ZDResponse.success("更新成功,共更新" + rows + "条记录") : ZDResponse.error("更新失败");
+ }
+ catch (Exception e)
+ {
+ log.error("批量设置下载状态失败", e);
+ return ZDResponse.error(e.getMessage());
+ }
+ }
+}
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/domain/EnterprisePubQrcode.java b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/domain/EnterprisePubQrcode.java
new file mode 100644
index 00000000..80876d8e
--- /dev/null
+++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/domain/EnterprisePubQrcode.java
@@ -0,0 +1,310 @@
+package com.zdxt.code.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zdxt.common.BaseDomain;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 送码入企信息对象 enterprise_pub_qrcode
+ *
+ * @author chenrui
+ * @date 2026-04-10
+ */
+public class EnterprisePubQrcode extends BaseDomain
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 主键ID */
+ private String id;
+
+ /** 企业名称 */
+ private String enterpriseName;
+
+ /** 企业纳税识别号 */
+ private String enterpriseNumber;
+
+ /** 归属区域名称 */
+ private String areaName;
+
+ /** 归属区域id */
+ private String areaId;
+
+ /** 归属街道名称 */
+ private String streetName;
+
+ /** 归属街道id */
+ private String streetId;
+
+ /** 匹配状态 */
+ private String matchingStatus;
+
+ /** 匹配消息 */
+ private String matchingMessage;
+
+ /** 下载情况 */
+ private String downloadStatus;
+
+ /** 上传单位名称 */
+ private String deptName;
+
+ /** 上传用户名称 */
+ private String userName;
+
+ /** 二维码存储路径 */
+ private String qrCodePath;
+
+ /** 上一次二维码生成时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date lastQrCodeTime;
+
+ /** 导入序号 */
+ private Integer importRowNum;
+
+ /** 导入文件名 */
+ private String importFileName;
+
+ /** 导入文件id */
+ private String importFileId;
+
+ /** 备注 */
+ private String remark;
+
+ /** 匹配到的目标类型 */
+ private String matchingToType;
+
+ /** 匹配到的目标id */
+ private String matchingToId;
+
+ public void setId(String id)
+ {
+ this.id = id;
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public void setEnterpriseName(String enterpriseName)
+ {
+ this.enterpriseName = enterpriseName;
+ }
+
+ public String getEnterpriseName()
+ {
+ return enterpriseName;
+ }
+
+ public void setEnterpriseNumber(String enterpriseNumber)
+ {
+ this.enterpriseNumber = enterpriseNumber;
+ }
+
+ public String getEnterpriseNumber()
+ {
+ return enterpriseNumber;
+ }
+
+ public void setAreaName(String areaName)
+ {
+ this.areaName = areaName;
+ }
+
+ public String getAreaName()
+ {
+ return areaName;
+ }
+
+ public void setAreaId(String areaId)
+ {
+ this.areaId = areaId;
+ }
+
+ public String getAreaId()
+ {
+ return areaId;
+ }
+
+ public void setStreetName(String streetName)
+ {
+ this.streetName = streetName;
+ }
+
+ public String getStreetName()
+ {
+ return streetName;
+ }
+
+ public void setStreetId(String streetId)
+ {
+ this.streetId = streetId;
+ }
+
+ public String getStreetId()
+ {
+ return streetId;
+ }
+
+ public void setMatchingStatus(String matchingStatus)
+ {
+ this.matchingStatus = matchingStatus;
+ }
+
+ public String getMatchingStatus()
+ {
+ return matchingStatus;
+ }
+
+ public void setMatchingMessage(String matchingMessage)
+ {
+ this.matchingMessage = matchingMessage;
+ }
+
+ public String getMatchingMessage()
+ {
+ return matchingMessage;
+ }
+
+ public void setDownloadStatus(String downloadStatus)
+ {
+ this.downloadStatus = downloadStatus;
+ }
+
+ public String getDownloadStatus()
+ {
+ return downloadStatus;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setUserName(String userName)
+ {
+ this.userName = userName;
+ }
+
+ public String getUserName()
+ {
+ return userName;
+ }
+
+ public void setQrCodePath(String qrCodePath)
+ {
+ this.qrCodePath = qrCodePath;
+ }
+
+ public String getQrCodePath()
+ {
+ return qrCodePath;
+ }
+
+ public void setLastQrCodeTime(Date lastQrCodeTime)
+ {
+ this.lastQrCodeTime = lastQrCodeTime;
+ }
+
+ public Date getLastQrCodeTime()
+ {
+ return lastQrCodeTime;
+ }
+
+ public void setImportRowNum(Integer importRowNum)
+ {
+ this.importRowNum = importRowNum;
+ }
+
+ public Integer getImportRowNum()
+ {
+ return importRowNum;
+ }
+
+ public void setImportFileName(String importFileName)
+ {
+ this.importFileName = importFileName;
+ }
+
+ public String getImportFileName()
+ {
+ return importFileName;
+ }
+
+ public void setImportFileId(String importFileId)
+ {
+ this.importFileId = importFileId;
+ }
+
+ public String getImportFileId()
+ {
+ return importFileId;
+ }
+
+ public void setRemark(String remark)
+ {
+ this.remark = remark;
+ }
+
+ public String getRemark()
+ {
+ return remark;
+ }
+
+ public void setMatchingToType(String matchingToType)
+ {
+ this.matchingToType = matchingToType;
+ }
+
+ public String getMatchingToType()
+ {
+ return matchingToType;
+ }
+
+ public void setMatchingToId(String matchingToId)
+ {
+ this.matchingToId = matchingToId;
+ }
+
+ public String getMatchingToId()
+ {
+ return matchingToId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+ .append("id", getId())
+ .append("enterpriseName", getEnterpriseName())
+ .append("enterpriseNumber", getEnterpriseNumber())
+ .append("areaName", getAreaName())
+ .append("areaId", getAreaId())
+ .append("streetName", getStreetName())
+ .append("streetId", getStreetId())
+ .append("matchingStatus", getMatchingStatus())
+ .append("matchingMessage", getMatchingMessage())
+ .append("downloadStatus", getDownloadStatus())
+ .append("deptName", getDeptName())
+ .append("deptId", getDeptId())
+ .append("userName", getUserName())
+ .append("userId", getUserId())
+ .append("createTime", getCreateTime())
+ .append("createBy", getCreateBy())
+ .append("qrCodePath", getQrCodePath())
+ .append("lastQrCodeTime", getLastQrCodeTime())
+ .append("importRowNum", getImportRowNum())
+ .append("importFileName", getImportFileName())
+ .append("importFileId", getImportFileId())
+ .append("remark", getRemark())
+ .append("matchingToType", getMatchingToType())
+ .append("matchingToId", getMatchingToId())
+ .toString();
+ }
+}
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/mapper/EnterprisePubQrcodeMapper.java b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/mapper/EnterprisePubQrcodeMapper.java
new file mode 100644
index 00000000..97ab8e77
--- /dev/null
+++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/mapper/EnterprisePubQrcodeMapper.java
@@ -0,0 +1,90 @@
+package com.zdxt.code.mapper;
+
+import com.zdxt.code.domain.EnterprisePubQrcode;
+
+import java.util.List;
+
+/**
+ * 送码入企信息Mapper接口
+ *
+ * @author chenrui
+ * @date 2026-04-10
+ */
+public interface EnterprisePubQrcodeMapper
+{
+ /**
+ * 查询送码入企信息
+ *
+ * @param id 送码入企信息ID
+ * @return 送码入企信息
+ */
+ EnterprisePubQrcode selectEnterprisePubQrcodeById(String id);
+
+ /**
+ * 查询送码入企信息列表
+ *
+ * @param enterprisePubQrcode 送码入企信息
+ * @return 送码入企信息集合
+ */
+ List selectEnterprisePubQrcodeList(EnterprisePubQrcode enterprisePubQrcode);
+
+ /**
+ * 新增送码入企信息
+ *
+ * @param enterprisePubQrcode 送码入企信息
+ * @return 结果
+ */
+ int insertEnterprisePubQrcode(EnterprisePubQrcode enterprisePubQrcode);
+
+ /**
+ * 修改送码入企信息
+ *
+ * @param enterprisePubQrcode 送码入企信息
+ * @return 结果
+ */
+ int updateEnterprisePubQrcode(EnterprisePubQrcode enterprisePubQrcode);
+
+ /**
+ * 删除送码入企信息
+ *
+ * @param id 送码入企信息ID
+ * @return 结果
+ */
+ int deleteEnterprisePubQrcodeById(String id);
+
+ /**
+ * 批量删除送码入企信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ int deleteEnterprisePubQrcodeByIds(String[] ids);
+
+ /**
+ * 根据统一社会信用代码查询送码入企信息
+ *
+ * @param enterpriseNumber 统一社会信用代码
+ * @return 送码入企信息
+ */
+ EnterprisePubQrcode selectEnterprisePubQrcodeByEnterpriseNumber(String enterpriseNumber);
+
+ /**
+ * 根据ID数组批量查询送码入企信息
+ *
+ * @param ids ID数组
+ * @return 送码入企信息集合
+ */
+ List selectEnterprisePubQrcodeByIds(String[] ids);
+
+ /**
+ * 批量更新下载状态和备注
+ *
+ * @param ids 需要更新的ID数组
+ * @param downloadStatus 下载状态
+ * @param remark 备注
+ * @return 结果
+ */
+ int batchUpdateDownloadStatus(@org.apache.ibatis.annotations.Param("ids") String[] ids,
+ @org.apache.ibatis.annotations.Param("downloadStatus") String downloadStatus,
+ @org.apache.ibatis.annotations.Param("remark") String remark);
+}
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/EnterprisePubQrcodeServiceImpl.java b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/EnterprisePubQrcodeServiceImpl.java
new file mode 100644
index 00000000..d1be1f3d
--- /dev/null
+++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/EnterprisePubQrcodeServiceImpl.java
@@ -0,0 +1,1043 @@
+package com.zdxt.code.service.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Pattern;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletResponse;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.lowagie.text.Document;
+import com.lowagie.text.Element;
+import com.lowagie.text.Image;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.PdfAction;
+import com.lowagie.text.pdf.PdfDestination;
+import com.lowagie.text.pdf.PdfOutline;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfWriter;
+import com.zdxt.auth.dto.UserBean;
+import com.zdxt.auth.feign.FileUploadApi;
+import com.zdxt.auth.feign.UserApi;
+import com.zdxt.auth.project.system.dept.service.IDeptService;
+import com.zdxt.code.domain.EnterpriseInformation;
+import com.zdxt.code.mapper.EnterpriseInformationMapper;
+import com.zdxt.code.service.ISsztJbxx110497Service;
+import com.zdxt.code.service.IQrCodeGenerateHistoryService;
+import com.zdxt.code.domain.QrCodeGenerateHistory;
+import com.zdxt.common.config.RuoYiConfig;
+import com.zdxt.common.util.Constants;
+import com.zdxt.common.util.DateUtils;
+import com.zdxt.common.util.StringUtils;
+import com.zdxt.domain.auth.Dept;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import com.zdxt.code.mapper.EnterprisePubQrcodeMapper;
+import com.zdxt.code.domain.EnterprisePubQrcode;
+import com.zdxt.code.service.IEnterprisePubQrcodeService;
+import com.zdxt.code.utils.PasswordTools;
+import com.zdxt.code.utils.QRCodeUtil;
+
+/**
+ * 送码入企信息Service业务层处理
+ *
+ * @author chenrui
+ * @date 2026-04-10
+ */
+@Service
+public class EnterprisePubQrcodeServiceImpl implements IEnterprisePubQrcodeService
+{
+ private static final Logger log = LoggerFactory.getLogger(EnterprisePubQrcodeServiceImpl.class);
+
+ /** 统一社会信用代码正则:18位,由数字和大写字母组成(不含 I、O、Z、S、V) */
+ private static final Pattern CREDIT_CODE_PATTERN = Pattern.compile("^[0-9A-HJ-NP-RTUW-Y]{2}\\d{6}[0-9A-HJ-NP-RTUW-Y]{10}$");
+
+ /** 企业名称正则:2-100个字符,允许中文、英文、数字、括号、破折号等 */
+ private static final Pattern ENTERPRISE_NAME_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5a-zA-Z0-9()()\\-·]{2,100}$");
+
+ /** 背景图片classpath路径 */
+ private static final String BG_IMAGE_PATH = "images/enterprise_pub_qrcode_bg.jpg";
+
+ private static final String AES_KEY = "zdxt-ec-enterprise-qrcd!";
+
+ @Autowired
+ private UserApi userApi;
+
+ @Autowired
+ private EnterprisePubQrcodeMapper enterprisePubQrcodeMapper;
+
+ @Autowired
+ private IDeptService deptService;
+
+ @Autowired
+ private ISsztJbxx110497Service ssztJbxx110497Service;
+
+ @Autowired
+ private EnterpriseInformationMapper enterpriseInformationMapper;
+
+ @Autowired
+ private IQrCodeGenerateHistoryService iQrCodeGenerateHistoryService;
+
+ @Autowired
+ private FileUploadApi fileUploadApi;
+
+ @Value("${ruoyi.profile}")
+ private String filePath;
+
+ public static String symmetricRQValidateCodeEncrypt(String content) {
+ try {
+ javax.crypto.spec.SecretKeySpec secretKey = new javax.crypto.spec.SecretKeySpec(AES_KEY.getBytes(), "AES");
+ javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
+ cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey);
+ byte[] encrypted = cipher.doFinal(content.getBytes(java.nio.charset.StandardCharsets.UTF_8));
+ return java.util.Base64.getEncoder().encodeToString(encrypted);
+ } catch (Exception e) {
+ throw new RuntimeException("AES加密失败", e);
+ }
+ //return SecureUtil.aes(AES_KEY.getBytes()).encryptBase64(content);
+ }
+
+ /**
+ * 查询送码入企信息
+ *
+ * @param id 送码入企信息ID
+ * @return 送码入企信息
+ */
+ @Override
+ public EnterprisePubQrcode selectEnterprisePubQrcodeById(String id)
+ {
+ return enterprisePubQrcodeMapper.selectEnterprisePubQrcodeById(id);
+ }
+
+ /**
+ * 查询送码入企信息列表
+ *
+ * @param enterprisePubQrcode 送码入企信息
+ * @return 送码入企信息
+ */
+ @Override
+ public List selectEnterprisePubQrcodeList(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ return enterprisePubQrcodeMapper.selectEnterprisePubQrcodeList(enterprisePubQrcode);
+ }
+
+ /**
+ * 新增送码入企信息
+ *
+ * @param enterprisePubQrcode 送码入企信息
+ * @return 结果
+ */
+ @Override
+ public int insertEnterprisePubQrcode(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ enterprisePubQrcode.setCreateTime(DateUtils.getNowDate());
+ return enterprisePubQrcodeMapper.insertEnterprisePubQrcode(enterprisePubQrcode);
+ }
+
+ /**
+ * 修改送码入企信息
+ *
+ * @param enterprisePubQrcode 送码入企信息
+ * @return 结果
+ */
+ @Override
+ public int updateEnterprisePubQrcode(EnterprisePubQrcode enterprisePubQrcode)
+ {
+ return enterprisePubQrcodeMapper.updateEnterprisePubQrcode(enterprisePubQrcode);
+ }
+
+ /**
+ * 删除送码入企信息对象
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ @Override
+ public int deleteEnterprisePubQrcodeByIds(String ids)
+ {
+ return enterprisePubQrcodeMapper.deleteEnterprisePubQrcodeByIds(Convert.toStrArray(ids));
+ }
+
+ /**
+ * 删除送码入企信息信息
+ *
+ * @param id 送码入企信息ID
+ * @return 结果
+ */
+ @Override
+ public int deleteEnterprisePubQrcodeById(String id)
+ {
+ return enterprisePubQrcodeMapper.deleteEnterprisePubQrcodeById(id);
+ }
+
+ /**
+ * 导入送码入企信息Excel
+ *
+ * @param file Excel文件
+ * @return 导入结果消息
+ * @throws Exception 异常
+ */
+ @Override
+ public String importEnterprisePubQrcode(MultipartFile file) throws Exception
+ {
+ UserBean currentUser = userApi.getCurrentUser();
+ // 1.解析Excel文件
+ List dataList = parseExcelToList(file);
+ if (dataList == null || dataList.isEmpty())
+ {
+ throw new Exception("导入数据不能为空!");
+ }
+
+ // 2.验证数据
+ StringBuilder errorMsg = new StringBuilder();
+ String importFileId = UUID.randomUUID().toString().replace("-", "");
+ String importFileName = file.getOriginalFilename();
+
+ for (int i = 0; i < dataList.size(); i++)
+ {
+ EnterprisePubQrcode item = dataList.get(i);
+ int rowNum = i + 2; // Excel行号(第1行为表头,数据从第2行开始)
+
+ // 验证企业名称
+ if (StrUtil.isBlank(item.getEnterpriseName()))
+ {
+ errorMsg.append("第").append(rowNum).append("行,企业名称不能为空;");
+ }
+ else if (!ENTERPRISE_NAME_PATTERN.matcher(item.getEnterpriseName().trim()).matches())
+ {
+ errorMsg.append("第").append(rowNum).append("行,企业名称格式不正确(应为2-100个中英文、数字或括号组合);");
+ }
+
+ // 验证统一社会信用代码
+ if (StrUtil.isBlank(item.getEnterpriseNumber()))
+ {
+ errorMsg.append("第").append(rowNum).append("行,统一社会信用代码不能为空;");
+ }
+ else if (!CREDIT_CODE_PATTERN.matcher(item.getEnterpriseNumber().trim().toUpperCase()).matches())
+ {
+ errorMsg.append("第").append(rowNum).append("行,统一社会信用代码格式不正确(应为18位数字和大写字母组合);");
+ }
+
+ // 验证归属区域
+ if (StrUtil.isBlank(item.getAreaName()))
+ {
+ errorMsg.append("第").append(rowNum).append("行,归属区域不能为空;");
+ }
+ else
+ {
+ Dept areaDept=deptService.selectDeptByDeptName2(item.getAreaName().trim());
+ if (areaDept == null)
+ {
+ errorMsg.append("第").append(rowNum).append("行,归属区域\"").append(item.getAreaName()).append("\"在系统中未找到;");
+ }
+ else
+ {
+ item.setAreaId(areaDept.getDeptId());
+ }
+ }
+
+ // 验证归属街道
+ if (StrUtil.isBlank(item.getStreetName()))
+ {
+ errorMsg.append("第").append(rowNum).append("行,归属街道不能为空;");
+ }
+ else
+ {
+ List deptList=deptService.selectDeptByDeptName(item.getStreetName().trim());
+ if (deptList == null || deptList.isEmpty())
+ {
+ errorMsg.append("第").append(rowNum).append("行,归属街道\"").append(item.getStreetName()).append("\"在系统中未找到;");
+ }
+ else
+ {
+ Dept streetDept = deptList.get(0);
+ item.setStreetId(streetDept.getDeptId());
+ }
+ }
+
+ // 设置导入相关信息
+ item.setImportFileName(importFileName);
+ item.setImportFileId(importFileId);
+ }
+
+ // 3.如果有错误,取消导入
+ if (errorMsg.length() > 0)
+ {
+ throw new Exception("导入失败:" + errorMsg.toString());
+ }
+
+ // 4.批量导入数据(根据EnterpriseNumber判断新增或更新)
+ int insertCount = 0;
+ int updateCount = 0;
+ for (EnterprisePubQrcode item : dataList)
+ {
+ EnterprisePubQrcode existing = enterprisePubQrcodeMapper.selectEnterprisePubQrcodeByEnterpriseNumber(item.getEnterpriseNumber().trim());
+ if (existing != null)
+ {
+ // 已存在,更新记录并重置状态
+ existing.setEnterpriseName(item.getEnterpriseName());
+ existing.setEnterpriseNumber(item.getEnterpriseNumber());
+ existing.setAreaName(item.getAreaName());
+ existing.setAreaId(item.getAreaId());
+ existing.setStreetName(item.getStreetName());
+ existing.setStreetId(item.getStreetId());
+ existing.setImportRowNum(item.getImportRowNum());
+ existing.setImportFileName(item.getImportFileName());
+ existing.setImportFileId(item.getImportFileId());
+ // 重置匹配状态、匹配消息、下载情况
+ existing.setMatchingStatus("未匹配");
+ existing.setMatchingMessage("");
+ existing.setDownloadStatus("未下载");
+ enterprisePubQrcodeMapper.updateEnterprisePubQrcode(existing);
+ updateCount++;
+ }
+ else
+ {
+ // 不存在,新增记录
+ item.setId(UUID.randomUUID().toString().replace("-", ""));
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ item.setCreateTime(cal.getTime());
+ item.setMatchingStatus("未匹配");
+ item.setDownloadStatus("未下载");
+
+ item.setUserName(currentUser.getUserName());
+ item.setUserId(currentUser.getUserId());
+ item.setCreateBy(currentUser.getUserName());
+ item.setDeptName(currentUser.getDeptName());
+ item.setDeptId(currentUser.getDeptId());
+ enterprisePubQrcodeMapper.insertEnterprisePubQrcode(item);
+ insertCount++;
+ }
+ }
+
+ return "成功导入" + dataList.size() + "条数据,其中新增" + insertCount + "条,更新" + updateCount + "条";
+ }
+
+ /**
+ * 批量匹配送码入企信息
+ *
+ * @param ids 选中的记录ID,逗号分隔
+ * @return 匹配结果消息
+ * @throws Exception 异常
+ */
+ @Override
+ public String matchSelectEnterprise(String ids) throws Exception
+ {
+ String[] idArray = Convert.toStrArray(ids);
+ int matchedCount = 0;
+ int failedCount = 0;
+ int insertedCount = 0;
+
+ for (String id : idArray)
+ {
+ EnterprisePubQrcode record = enterprisePubQrcodeMapper.selectEnterprisePubQrcodeById(id);
+ if (record == null)
+ {
+ continue;
+ }
+
+ String enterpriseNumber = record.getEnterpriseNumber();
+ // 同时检索两个数据源
+ EnterpriseInformation existingInfo = enterpriseInformationMapper.selectEnterpriseInformationByNum(enterpriseNumber);
+ EnterpriseInformation sjInfo = ssztJbxx110497Service.selectSsztJbxx110497ByCode(enterpriseNumber);
+
+ if (existingInfo != null)
+ {
+ // 深i企存在该企业,优先使用深i企数据
+ if (record.getEnterpriseName().equals(existingInfo.getEnterpriseName()))
+ {
+ // 企业名称一致
+ record.setMatchingStatus("已匹配");
+ }
+ else
+ {
+ // 企业名称不一致,以深i企为准
+ record.setMatchingStatus("已匹配");
+ record.setMatchingMessage("企业名称与本地的数据源不一致,以本地库的为准,导入名称为" + record.getEnterpriseName() + ",本地库企业名称为:" + existingInfo.getEnterpriseName() + ",本地库的数据源主要来源为深i企");
+ record.setEnterpriseName(existingInfo.getEnterpriseName());
+ }
+ // 生成并存储蓝色二维码
+ try
+ {
+ generateAndStoreBlueQrCode(record, existingInfo);
+ }
+ catch (Exception e)
+ {
+ log.error("生成二维码失败,企业:" + record.getEnterpriseName(), e);
+ }
+
+ record.setMatchingToType("本地数据源");
+ record.setMatchingToId(existingInfo.getId());
+ enterprisePubQrcodeMapper.updateEnterprisePubQrcode(record);
+ matchedCount++;
+ }
+ else if (sjInfo != null)
+ {
+ // 深i企不存在,使用市监数据
+ if (record.getEnterpriseName().equals(sjInfo.getEnterpriseName()))
+ {
+ // 企业名称一致
+ record.setMatchingStatus("已匹配");
+ }
+ else
+ {
+ // 企业名称不一致,以市监为准
+ record.setMatchingStatus("已匹配");
+ record.setMatchingMessage("企业名称于市监的数据源不一致,以市监的为准,导入名称为" + record.getEnterpriseName() + ",市监企业名为:" + sjInfo.getEnterpriseName());
+ record.setEnterpriseName(sjInfo.getEnterpriseName());
+ }
+ // 市监匹配成功且深i企不存在,先写入enterprise_information表
+ sjInfo.setId(IdUtil.simpleUUID());
+ String salt = PasswordTools.encrypt(enterpriseNumber);
+ sjInfo.setSalt(salt);
+ sjInfo.setIsUnsubscribe(0);
+ sjInfo.setIsDelete(0);
+ sjInfo.setCreateTime(DateUtils.getNowDate());
+ sjInfo.setEnterpriseType("送码入企");
+ enterpriseInformationMapper.insertEnterpriseInformation(sjInfo);
+ insertedCount++;
+
+ // 生成并存储蓝色二维码
+ try
+ {
+ generateAndStoreBlueQrCode(record, sjInfo);
+ }
+ catch (Exception e)
+ {
+ log.error("生成二维码失败,企业:" + record.getEnterpriseName(), e);
+ }
+
+ record.setMatchingToType("市监数据源");
+ record.setMatchingToId(sjInfo.getId());
+ enterprisePubQrcodeMapper.updateEnterprisePubQrcode(record);
+ matchedCount++;
+ }
+ else
+ {
+ // 两个数据源都不存在该企业
+ record.setMatchingStatus("匹配失败");
+ record.setMatchingMessage("市监与本地的数据源中不存在该信用代码的企业");
+ enterprisePubQrcodeMapper.updateEnterprisePubQrcode(record);
+ failedCount++;
+ }
+ }
+
+ return "匹配完成,共" + idArray.length + "条记录,已匹配" + matchedCount + "条,匹配失败" + failedCount + "条,新增企业信息" + insertedCount + "条";
+ }
+
+ /**
+ * 强制匹配送码入企信息
+ *
+ * @param id 记录ID
+ * @return 匹配结果消息
+ * @throws Exception 异常
+ */
+ @Override
+ public String forceMatch(String id) throws Exception
+ {
+ EnterprisePubQrcode record = enterprisePubQrcodeMapper.selectEnterprisePubQrcodeById(id);
+ if (record == null)
+ {
+ throw new Exception("记录不存在");
+ }
+
+ // 设置状态为强制匹配
+ record.setMatchingStatus("强制匹配");
+ String enterpriseNumber = record.getEnterpriseNumber();
+ EnterpriseInformation existingInfo = enterpriseInformationMapper.selectEnterpriseInformationByNum(enterpriseNumber);
+ EnterpriseInformation targetInfo;
+ String resultMsg;
+
+ if (existingInfo == null)
+ {
+ // 不存在则插入企业数据
+ EnterpriseInformation newInfo = new EnterpriseInformation();
+ newInfo.setId(IdUtil.simpleUUID());
+ newInfo.setEnterpriseName(record.getEnterpriseName());
+ newInfo.setEnterpriseNumber(enterpriseNumber);
+ String salt = PasswordTools.encrypt(enterpriseNumber);
+ newInfo.setSalt(salt);
+ newInfo.setIsUnsubscribe(0);
+ newInfo.setIsDelete(0);
+ newInfo.setCreateTime(DateUtils.getNowDate());
+ newInfo.setEnterpriseType("送码入企");
+ enterpriseInformationMapper.insertEnterpriseInformation(newInfo);
+ targetInfo = newInfo;
+ resultMsg = "强制匹配成功,已新增企业信息";
+ }
+ else
+ {
+ targetInfo = existingInfo;
+ resultMsg = "强制匹配成功";
+ }
+
+ // 生成并存储蓝色二维码
+ try
+ {
+ generateAndStoreBlueQrCode(record, targetInfo);
+ }
+ catch (Exception e)
+ {
+ log.error("生成二维码失败,企业:" + record.getEnterpriseName(), e);
+ }
+
+ record.setMatchingToType("本地数据源");
+ record.setMatchingToId(targetInfo.getId());
+ enterprisePubQrcodeMapper.updateEnterprisePubQrcode(record);
+ return resultMsg;
+ }
+
+ /**
+ * 解析Excel文件为List
+ *
+ * @param file Excel文件
+ * @return 数据列表
+ * @throws Exception 异常
+ */
+ private List parseExcelToList(MultipartFile file) throws Exception
+ {
+ String fileName = file.getOriginalFilename();
+ if (fileName == null || (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")))
+ {
+ throw new Exception("文件格式不正确,仅支持xls和xlsx格式!");
+ }
+
+ InputStream is = file.getInputStream();
+ Workbook workbook;
+ if (fileName.endsWith(".xlsx"))
+ {
+ workbook = new XSSFWorkbook(is);
+ }
+ else
+ {
+ workbook = new HSSFWorkbook(is);
+ }
+
+ Sheet sheet = workbook.getSheetAt(0);
+ if (sheet == null)
+ {
+ workbook.close();
+ throw new Exception("Excel文件中没有工作表!");
+ }
+
+ // 验证表头(第一行)
+ Row headerRow = sheet.getRow(0);
+ if (headerRow == null)
+ {
+ workbook.close();
+ throw new Exception("Excel表头不能为空!");
+ }
+
+ // 解析数据行
+ List dataList = new ArrayList<>();
+ int lastRowNum = sheet.getLastRowNum();
+ for (int i = 1; i <= lastRowNum; i++)
+ {
+ Row row = sheet.getRow(i);
+ if (row == null)
+ {
+ continue;
+ }
+
+ // 判断是否为空行
+ boolean isEmptyRow = true;
+ for (int j = 0; j < 5; j++)
+ {
+ String cellValue = getCellStringValue(row.getCell(j));
+ if (StrUtil.isNotBlank(cellValue))
+ {
+ isEmptyRow = false;
+ break;
+ }
+ }
+ if (isEmptyRow)
+ {
+ continue;
+ }
+
+ EnterprisePubQrcode item = new EnterprisePubQrcode();
+ // 序号(第1列,必须为正整数)
+ String seqNo = getCellStringValue(row.getCell(0));
+ if (StrUtil.isBlank(seqNo) || !seqNo.matches("^[1-9]\\d*$"))
+ {
+ throw new Exception("第" + (i + 1) + "行,序号必须为正整数!");
+ }
+ item.setImportRowNum(Integer.valueOf(seqNo));
+ // 企业名称(第2列)
+ item.setEnterpriseName(getCellStringValue(row.getCell(1)));
+ // 统一社会信用代码(第3列)
+ item.setEnterpriseNumber(getCellStringValue(row.getCell(2)));
+ // 归属区域(第4列)
+ item.setAreaName(getCellStringValue(row.getCell(3)));
+ // 归属街道(第5列)
+ item.setStreetName(getCellStringValue(row.getCell(4)));
+
+ dataList.add(item);
+ }
+
+ workbook.close();
+ // 按序号升序排序
+ dataList.sort((a, b) -> a.getImportRowNum().compareTo(b.getImportRowNum()));
+ return dataList;
+ }
+
+ /**
+ * 获取单元格字符串值
+ *
+ * @param cell 单元格
+ * @return 字符串值
+ */
+ private String getCellStringValue(Cell cell)
+ {
+ if (cell == null)
+ {
+ return "";
+ }
+ cell.setCellType(CellType.STRING);
+ return cell.getStringCellValue().trim();
+ }
+
+ /**
+ * 下载送码入企PDF(生成蓝色二维码并嵌入PDF)
+ * PDF结构:汇总信息页(含成功/失败分表) -> 各企业二维码页(含PDF书签导航)
+ *
+ * @param ids 记录ID,逗号分隔
+ * @param response HTTP响应
+ * @throws Exception 异常
+ */
+ @Override
+ public void downloadPdf(String ids, HttpServletResponse response) throws Exception
+ {
+ byte[] pdfBytes = buildPdfBytes(ids);
+
+ String fileName = "执法监督码_批量下载.pdf";
+ String[] idArray = Convert.toStrArray(ids);
+ if (idArray.length == 1)
+ {
+ EnterprisePubQrcode singleRecord = enterprisePubQrcodeMapper.selectEnterprisePubQrcodeById(idArray[0]);
+ if (singleRecord != null && ("已匹配".equals(singleRecord.getMatchingStatus()) || "强制匹配".equals(singleRecord.getMatchingStatus())))
+ {
+ fileName = singleRecord.getEnterpriseName() + "_执法监督码.pdf";
+ }
+ }
+
+ response.setContentType("application/pdf");
+ response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
+ response.setContentLength(pdfBytes.length);
+ response.getOutputStream().write(pdfBytes);
+ response.getOutputStream().flush();
+ }
+
+ @Override
+ public String generatePdfFile(String ids) throws Exception
+ {
+ byte[] pdfBytes = buildPdfBytes(ids);
+
+ String datePath = DateUtils.datePath();
+ String pdfDir = RuoYiConfig.getProfile() + "/pdf/" + datePath;
+ java.io.File dir = new java.io.File(pdfDir);
+ if (!dir.exists())
+ {
+ dir.mkdirs();
+ }
+
+ String pdfFileName = IdUtil.simpleUUID() + ".pdf";
+ java.io.File pdfFile = new java.io.File(pdfDir, pdfFileName);
+ try (java.io.FileOutputStream fos = new java.io.FileOutputStream(pdfFile))
+ {
+ fos.write(pdfBytes);
+ fos.flush();
+ }
+
+ return Constants.RESOURCE_PREFIX + "/pdf/" + datePath + "/" + pdfFileName;
+ }
+
+ /**
+ * 生成PDF字节内容(公共逻辑)
+ */
+ private byte[] buildPdfBytes(String ids) throws Exception
+ {
+ String[] idArray = Convert.toStrArray(ids);
+
+ // 1. 一次性批量查询所有选中记录
+ List allRecords = enterprisePubQrcodeMapper.selectEnterprisePubQrcodeByIds(idArray);
+ if (allRecords == null || allRecords.isEmpty())
+ {
+ throw new Exception("未找到对应的记录");
+ }
+
+ // 2. 分类记录:匹配成功和匹配失败
+ List matchedRecords = new ArrayList<>();
+ List unmatchedRecords = new ArrayList<>();
+ for (EnterprisePubQrcode record : allRecords)
+ {
+ if ("已匹配".equals(record.getMatchingStatus()) || "强制匹配".equals(record.getMatchingStatus()))
+ {
+ matchedRecords.add(record);
+ }
+ else
+ {
+ unmatchedRecords.add(record);
+ }
+ }
+
+ // 3. 加载中文字体
+ BaseFont bfChinese = loadChineseBaseFont();
+ com.lowagie.text.Font titleFont = new com.lowagie.text.Font(bfChinese, 18, com.lowagie.text.Font.BOLD);
+ com.lowagie.text.Font subTitleFont = new com.lowagie.text.Font(bfChinese, 14, com.lowagie.text.Font.BOLD);
+ com.lowagie.text.Font normalFont = new com.lowagie.text.Font(bfChinese, 12, com.lowagie.text.Font.NORMAL);
+ com.lowagie.text.Font tableHeaderFont = new com.lowagie.text.Font(bfChinese, 10, com.lowagie.text.Font.BOLD);
+ com.lowagie.text.Font tableCellFont = new com.lowagie.text.Font(bfChinese, 9, com.lowagie.text.Font.NORMAL);
+
+ // 4. 创建PDF文档(带边距,用于汇总页)
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Document document = new Document(PageSize.A4, 36, 36, 36, 36);
+ PdfWriter writer = PdfWriter.getInstance(document, baos);
+ document.open();
+
+ // === 第一部分:批量生成信息汇总页 ===
+ Paragraph title = new Paragraph("批量生成信息汇总", titleFont);
+ title.setAlignment(Element.ALIGN_CENTER);
+ title.setSpacingAfter(20);
+ document.add(title);
+
+ Paragraph summaryText = new Paragraph(
+ "本次共选择 " + allRecords.size() + " 家企业,成功生成 " + matchedRecords.size() + " 家,失败 " + unmatchedRecords.size() + " 家",
+ normalFont);
+ summaryText.setSpacingAfter(15);
+ document.add(summaryText);
+
+ // 表格列头
+ String[] headers = {"导入序号", "企业名称", "区名称", "街道名称", "信用代码", "匹配状态"};
+
+ // --- 生成成功企业表格 ---
+ Paragraph successTitle = new Paragraph("生成成功企业(" + matchedRecords.size() + " 家)", subTitleFont);
+ successTitle.setSpacingAfter(10);
+ document.add(successTitle);
+
+ PdfPTable successTable = new PdfPTable(6);
+ successTable.setWidthPercentage(100);
+ successTable.setWidths(new float[]{8, 25, 12, 12, 25, 10});
+ addTableHeaders(successTable, headers, tableHeaderFont);
+ for (EnterprisePubQrcode record : matchedRecords)
+ {
+ addRecordRow(successTable, record, tableCellFont);
+ }
+ document.add(successTable);
+
+ // --- 生成失败企业表格 ---
+ if (!unmatchedRecords.isEmpty())
+ {
+ Paragraph failTitle = new Paragraph("生成失败企业(" + unmatchedRecords.size() + " 家)", subTitleFont);
+ failTitle.setSpacingBefore(15);
+ failTitle.setSpacingAfter(10);
+ document.add(failTitle);
+
+ PdfPTable failTable = new PdfPTable(6);
+ failTable.setWidthPercentage(100);
+ failTable.setWidths(new float[]{8, 25, 12, 12, 25, 10});
+ addTableHeaders(failTable, headers, tableHeaderFont);
+ for (EnterprisePubQrcode record : unmatchedRecords)
+ {
+ addRecordRow(failTable, record, tableCellFont);
+ }
+ document.add(failTable);
+ }
+
+ // 获取PDF书签根节点
+ PdfOutline rootOutline = writer.getDirectContent().getRootOutline();
+
+ // 书签:0.首页 -> 指向第一页
+ new PdfOutline(rootOutline, PdfAction.gotoLocalPage(1, new PdfDestination(PdfDestination.FITH), writer), "0.首页");
+
+ // === 第三部分:各企业二维码页(仅当有匹配成功的记录时) ===
+ if (!matchedRecords.isEmpty())
+ {
+ // 读取背景图片模板
+ InputStream bgStream = EnterprisePubQrcodeServiceImpl.class.getClassLoader()
+ .getResourceAsStream(BG_IMAGE_PATH);
+ if (bgStream == null)
+ {
+ throw new Exception("背景图片不存在");
+ }
+ BufferedImage bgTemplate = ImageIO.read(bgStream);
+ bgStream.close();
+
+ // 加载AWT中文字体(用于图片上绘制文字)
+ java.awt.Font chineseAwtFont = loadChineseAwtFont();
+
+ // 预创建可复用的合成画布,避免每次循环重新分配内存
+ BufferedImage compositeImage = new BufferedImage(
+ bgTemplate.getWidth(), bgTemplate.getHeight(), BufferedImage.TYPE_INT_RGB);
+
+ // 预获取JPEG写入器(循环外复用)
+ javax.imageio.ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
+ javax.imageio.ImageWriteParam jpgParam = jpgWriter.getDefaultWriteParam();
+ jpgParam.setCompressionMode(javax.imageio.ImageWriteParam.MODE_EXPLICIT);
+ jpgParam.setCompressionQuality(0.95f);
+
+ for (int i = 0; i < matchedRecords.size(); i++)
+ {
+ EnterprisePubQrcode record = matchedRecords.get(i);
+
+ // 切换为无边距并新建页面
+ document.setMargins(0, 0, 0, 0);
+ document.newPage();
+
+ // 添加PDF书签导航
+ String bookmarkTitle = (i + 1) + ". " + record.getEnterpriseName();
+ new PdfOutline(rootOutline, new PdfDestination(PdfDestination.FITH), bookmarkTitle);
+
+ // 优先使用匹配阶段预生成的蓝色二维码
+ BufferedImage qrImage = null;
+ if (StrUtil.isNotBlank(record.getQrCodePath()))
+ {
+ // 将Web路径转换为物理路径:/profile/xxx -> {ruoyi.profile}/xxx
+ String physicalPath = record.getQrCodePath().replaceFirst(Constants.RESOURCE_PREFIX, RuoYiConfig.getProfile());
+ java.io.File qrFile = new java.io.File(physicalPath);
+ if (qrFile.exists())
+ {
+ qrImage = ImageIO.read(qrFile);
+ }
+ }
+
+ if (qrImage == null){
+ throw new Exception("二维码不存在");
+ }
+
+ // 在复用画布上合成(先绘制背景覆盖上一次内容)
+ Graphics2D g2d = compositeImage.createGraphics();
+ g2d.drawImage(bgTemplate, 0, 0, null);
+ g2d.drawImage(qrImage, 266, 645, null);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2d.setColor(new java.awt.Color(0x333333));
+ g2d.setFont(chineseAwtFont);
+ java.awt.FontMetrics fm = g2d.getFontMetrics();
+ int textWidth = fm.stringWidth(record.getEnterpriseName());
+ int textX = (bgTemplate.getWidth() - textWidth) / 2;
+ g2d.drawString(record.getEnterpriseName(), textX, 1240);
+ g2d.dispose();
+
+ // 使用JPEG 95%质量代替PNG:编码更快,体积更小
+ ByteArrayOutputStream imageBytes = new ByteArrayOutputStream();
+ javax.imageio.stream.ImageOutputStream ios = ImageIO.createImageOutputStream(imageBytes);
+ jpgWriter.setOutput(ios);
+ jpgWriter.write(null, new javax.imageio.IIOImage(compositeImage, null, null), jpgParam);
+ ios.close();
+
+ // 添加合成图片到PDF,缩放适配A4页面
+ Image pdfImage = Image.getInstance(imageBytes.toByteArray());
+ pdfImage.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());
+ pdfImage.setAlignment(Image.ALIGN_CENTER);
+ document.add(pdfImage);
+ }
+
+ jpgWriter.dispose();
+ }
+
+ document.close();
+ writer.close();
+
+ return baos.toByteArray();
+ }
+
+ /**
+ * 批量设置下载状态和备注
+ *
+ * @param ids 记录ID,逗号分隔
+ * @param downloadStatus 下载状态
+ * @param remark 备注
+ * @return 更新结果
+ */
+ @Override
+ public int batchUpdateDownloadStatus(String ids, String downloadStatus, String remark)
+ {
+ String[] idArray = Convert.toStrArray(ids);
+ return enterprisePubQrcodeMapper.batchUpdateDownloadStatus(idArray, downloadStatus, remark);
+ }
+
+ /**
+ * 生成并存储蓝色二维码(带LOGO),同时写入qr_code_generate_history表
+ *
+ * @param record 送码入企记录(生成后会设置qrCodePath和lastQrCodeTime)
+ * @param enterpriseInfo 企业信息(包含salt和id)
+ */
+ private void generateAndStoreBlueQrCode(EnterprisePubQrcode record, EnterpriseInformation enterpriseInfo) throws Exception
+ {
+ String enterpriseNumber = record.getEnterpriseNumber();
+
+ // 检查qr_code_generate_history表中是否已存在该企业由送码入企生成的有效二维码记录
+ QrCodeGenerateHistory existingHistory = iQrCodeGenerateHistoryService.selectQrCodeGenerateHistoryByNewest(enterpriseNumber);
+ if (existingHistory != null && existingHistory.getStatus() != null && existingHistory.getStatus() == 0
+ && "送码入企".equals(existingHistory.getReasonsChange()))
+ {
+ // 已有送码入企生成的有效记录,复用已有二维码路径
+ record.setQrCodePath(existingHistory.getQrCodeUrl());
+ record.setLastQrCodeTime(existingHistory.getGenerateTime());
+ return;
+ }
+
+ String salt = enterpriseInfo.getSalt();
+ String enterpriseId = enterpriseInfo.getId();
+
+ String codeId = IdUtil.simpleUUID();
+ Map jsonMap = new HashMap<>();
+ jsonMap.put("salt", salt);
+ jsonMap.put("codeId", codeId);
+ jsonMap.put("type", "zfjd");
+ jsonMap.put("enterpriseId", enterpriseId);
+ jsonMap.put("enterpriseNumber", enterpriseNumber);
+ jsonMap.put("vaCode", symmetricRQValidateCodeEncrypt(enterpriseNumber));
+ jsonMap.put("formModule","EntPubQrcodeService");
+ jsonMap.put("createDate", DateUtils.getTime());
+ jsonMap.put("eprqId",record.getId());
+ String qrContent = JSON.toJSONString(jsonMap);
+
+ BufferedImage qrImage = QRCodeUtil.createBlueQrCodeWithLogo(qrContent, 460);
+
+ // 将BufferedImage写入临时文件,再通过fileUploadApi上传
+ java.io.File tempFile = java.io.File.createTempFile("qrcode_" + codeId, ".png");
+ tempFile.deleteOnExit();
+ ImageIO.write(qrImage, "PNG", tempFile);
+ MultipartFile multipartFile = QRCodeUtil.getMultipartFile(tempFile);
+ String upload = fileUploadApi.upload(multipartFile);
+ tempFile.delete();
+
+ QrCodeGenerateHistory history = new QrCodeGenerateHistory();
+ history.setId(codeId);
+ history.setGenerateTime(DateUtils.getNowDate());
+ history.setQrCodeUrl(upload);
+ history.setEnterpriseNumber(enterpriseNumber);
+ history.setEnterpriseName(record.getEnterpriseName());
+ history.setReasonsChange("送码入企");
+ iQrCodeGenerateHistoryService.insertQrCodeGenerateHistory(history);
+
+ record.setQrCodePath(upload);
+ record.setLastQrCodeTime(DateUtils.getNowDate());
+ }
+
+ /**
+ * 加载中文BaseFont(用于PDF文本元素)
+ */
+ private BaseFont loadChineseBaseFont() throws Exception
+ {
+ if (!StringUtils.isWindows())
+ {
+ return BaseFont.createFont("/home/zdxt/font/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+ }
+ else
+ {
+ InputStream fontStream = EnterprisePubQrcodeServiceImpl.class.getClassLoader()
+ .getResourceAsStream("font/simsun.ttc");
+ if (fontStream != null)
+ {
+ java.io.File tempFile = java.io.File.createTempFile("simsun", ".ttc");
+ tempFile.deleteOnExit();
+ java.nio.file.Files.copy(fontStream, tempFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
+ fontStream.close();
+ return BaseFont.createFont(tempFile.getAbsolutePath() + ",0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+ }
+ else
+ {
+ return BaseFont.createFont("C:/Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+ }
+ }
+ }
+
+ /**
+ * 加载中文AWT字体(用于图片上绘制文字)
+ */
+ private java.awt.Font loadChineseAwtFont() throws Exception
+ {
+ if (!StringUtils.isWindows())
+ {
+ return java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT,
+ new java.io.File("/home/zdxt/font/simsun.ttc"))
+ .deriveFont(java.awt.Font.BOLD, 28f);
+ }
+ else
+ {
+ InputStream fontStream = EnterprisePubQrcodeServiceImpl.class.getClassLoader()
+ .getResourceAsStream("font/simsun.ttc");
+ if (fontStream != null)
+ {
+ java.awt.Font font = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, fontStream)
+ .deriveFont(java.awt.Font.BOLD, 28f);
+ fontStream.close();
+ return font;
+ }
+ else
+ {
+ return new java.awt.Font("SimSun", java.awt.Font.BOLD, 28);
+ }
+ }
+ }
+
+ /**
+ * 向PDF表格添加列头
+ */
+ private void addTableHeaders(PdfPTable table, String[] headers, com.lowagie.text.Font font)
+ {
+ for (String header : headers)
+ {
+ PdfPCell cell = new PdfPCell(new Phrase(header, font));
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ cell.setBackgroundColor(new java.awt.Color(0xDD, 0xDD, 0xDD));
+ cell.setPadding(5);
+ table.addCell(cell);
+ }
+ }
+
+ /**
+ * 向PDF表格添加一行企业记录
+ */
+ private void addRecordRow(PdfPTable table, EnterprisePubQrcode record, com.lowagie.text.Font font)
+ {
+ addTableCell(table, record.getImportRowNum() != null ? String.valueOf(record.getImportRowNum()) : "", font, Element.ALIGN_CENTER);
+ addTableCell(table, record.getEnterpriseName() != null ? record.getEnterpriseName() : "", font, Element.ALIGN_LEFT);
+ addTableCell(table, record.getAreaName() != null ? record.getAreaName() : "", font, Element.ALIGN_CENTER);
+ addTableCell(table, record.getStreetName() != null ? record.getStreetName() : "", font, Element.ALIGN_CENTER);
+ addTableCell(table, record.getEnterpriseNumber() != null ? record.getEnterpriseNumber() : "", font, Element.ALIGN_LEFT);
+ addTableCell(table, record.getMatchingStatus() != null ? record.getMatchingStatus() : "", font, Element.ALIGN_CENTER);
+ }
+
+ /**
+ * 向PDF表格添加单元格
+ */
+ private void addTableCell(PdfPTable table, String text, com.lowagie.text.Font font, int alignment)
+ {
+ PdfPCell cell = new PdfPCell(new Phrase(text, font));
+ cell.setHorizontalAlignment(alignment);
+ cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ cell.setPadding(4);
+ table.addCell(cell);
+ }
+}
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/utils/QRCodeUtil.java b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/utils/QRCodeUtil.java
index fbced049..346bf01a 100644
--- a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/utils/QRCodeUtil.java
+++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/utils/QRCodeUtil.java
@@ -386,6 +386,89 @@ public class QRCodeUtil {
return image;
}
+ // 蓝色二维码前景色
+ private static final int BLUE_FOREGROUND_COLOR = 0xFF003399;
+
+ // classpath中的LOGO图片路径
+ private static final String EMBEDDED_LOGO_PATH = "images/enterprise_pub_qrcode_logo.jpg";
+
+ /**
+ * 生成蓝色二维码并在中间插入自定义图片,返回BufferedImage
+ *
+ * @param content 二维码内容
+ * @param imgPath 中间图片地址(为空则不插入图片)
+ * @param needCompress 是否压缩中间图片
+ * @return BufferedImage
+ * @throws Exception
+ */
+ public static BufferedImage createBlueQrCode(String content, String imgPath,
+ boolean needCompress) throws Exception {
+ Hashtable hints = new Hashtable();
+ hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+ hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+ hints.put(EncodeHintType.MARGIN, 1);
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
+ BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
+ int width = bitMatrix.getWidth();
+ int height = bitMatrix.getHeight();
+ BufferedImage image = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ image.setRGB(x, y, bitMatrix.get(x, y) ? BLUE_FOREGROUND_COLOR
+ : 0xFFFFFFFF);
+ }
+ }
+ if (imgPath != null && !"".equals(imgPath)) {
+ insertImage(image, imgPath, needCompress);
+ }
+ return image;
+ }
+
+ /**
+ * 生成蓝色二维码并在中间插入classpath中的LOGO图片,返回BufferedImage
+ *
+ * @param content 二维码内容
+ * @return BufferedImage
+ * @throws Exception
+ */
+ public static BufferedImage createBlueQrCodeWithLogo(String content,int size) throws Exception {
+ Hashtable hints = new Hashtable();
+ hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+ hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+ hints.put(EncodeHintType.MARGIN, 1);
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
+ BarcodeFormat.QR_CODE, size, size, hints);
+ int width = bitMatrix.getWidth();
+ int height = bitMatrix.getHeight();
+ BufferedImage image = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ image.setRGB(x, y, bitMatrix.get(x, y) ? BLUE_FOREGROUND_COLOR
+ : 0xFFFFFFFF);
+ }
+ }
+ // 从classpath读取LOGO图片并插入二维码中间
+ InputStream logoStream = QRCodeUtil.class.getClassLoader().getResourceAsStream(EMBEDDED_LOGO_PATH);
+ if (logoStream != null) {
+ Image logo = ImageIO.read(logoStream);
+ logoStream.close();
+ int logoWidth = Math.min(logo.getWidth(null), 100);
+ int logoHeight = Math.min(logo.getHeight(null), 100);
+ Image scaledLogo = logo.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
+ Graphics2D graph = image.createGraphics();
+ int x = (size - logoWidth) / 2;
+ int y = (size - logoHeight) / 2;
+ graph.drawImage(scaledLogo, x, y, logoWidth, logoHeight, null);
+ Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 6, 6);
+ graph.setStroke(new BasicStroke(3f));
+ graph.draw(shape);
+ graph.dispose();
+ }
+ return image;
+ }
+
public static MultipartFile getMultipartFile(File file) {
FileItem item = new DiskFileItemFactory().createItem("file"
, MediaType.MULTIPART_FORM_DATA_VALUE
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/mapper/EnterprisePubQrcodeMapper.xml b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/mapper/EnterprisePubQrcodeMapper.xml
new file mode 100644
index 00000000..7b59b3d1
--- /dev/null
+++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/mapper/EnterprisePubQrcodeMapper.xml
@@ -0,0 +1,189 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select id, enterprise_name, enterprise_number, area_name, area_id, street_name, street_id,
+ matching_status, matching_message, download_status, dept_name, dept_id, user_name, user_id,
+ create_time, create_by, qr_code_path, last_qr_code_time,
+ import_row_num, import_file_name, import_file_id, remark,
+ matching_to_type, matching_to_id
+ from enterprise_pub_qrcode
+
+
+
+
+
+
+
+
+
+
+
+ insert into enterprise_pub_qrcode
+
+ id,
+ enterprise_name,
+ enterprise_number,
+ area_name,
+ area_id,
+ street_name,
+ street_id,
+ matching_status,
+ matching_message,
+ download_status,
+ dept_name,
+ dept_id,
+ user_name,
+ user_id,
+ create_time,
+ create_by,
+ qr_code_path,
+ last_qr_code_time,
+ import_row_num,
+ import_file_name,
+ import_file_id,
+ remark,
+ matching_to_type,
+ matching_to_id,
+
+
+ #{id},
+ #{enterpriseName},
+ #{enterpriseNumber},
+ #{areaName},
+ #{areaId},
+ #{streetName},
+ #{streetId},
+ #{matchingStatus},
+ #{matchingMessage},
+ #{downloadStatus},
+ #{deptName},
+ #{deptId},
+ #{userName},
+ #{userId},
+ #{createTime},
+ #{createBy},
+ #{qrCodePath},
+ #{lastQrCodeTime},
+ #{importRowNum},
+ #{importFileName},
+ #{importFileId},
+ #{remark},
+ #{matchingToType},
+ #{matchingToId},
+
+
+
+
+ update enterprise_pub_qrcode
+
+ enterprise_name = #{enterpriseName},
+ enterprise_number = #{enterpriseNumber},
+ area_name = #{areaName},
+ area_id = #{areaId},
+ street_name = #{streetName},
+ street_id = #{streetId},
+ matching_status = #{matchingStatus},
+ matching_message = #{matchingMessage},
+ download_status = #{downloadStatus},
+ dept_name = #{deptName},
+ dept_id = #{deptId},
+ user_name = #{userName},
+ user_id = #{userId},
+ create_time = #{createTime},
+ create_by = #{createBy},
+ qr_code_path = #{qrCodePath},
+ last_qr_code_time = #{lastQrCodeTime},
+ import_row_num = #{importRowNum},
+ import_file_name = #{importFileName},
+ import_file_id = #{importFileId},
+ remark = #{remark},
+ matching_to_type = #{matchingToType},
+ matching_to_id = #{matchingToId},
+
+ where id = #{id}
+
+
+
+ delete from enterprise_pub_qrcode where id = #{id}
+
+
+
+ delete from enterprise_pub_qrcode where id in
+
+ #{id}
+
+
+
+
+ update enterprise_pub_qrcode
+ set download_status = #{downloadStatus},
+ remark = #{remark}
+ where id in
+
+ #{id}
+
+
+
From bacbb1c0a1b4c38bb862771520f9e39400462b6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BA=84=E9=94=90=E6=B3=A2?=
<10549902+zhuangruibo@user.noreply.gitee.com>
Date: Tue, 14 Apr 2026 16:13:22 +0800
Subject: [PATCH 2/6] =?UTF-8?q?=E9=80=81=E7=A0=81=E5=85=A5=E4=BC=81?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../images/enterprise_pub_qrcode_bg.jpg | Bin 0 -> 306288 bytes
.../images/enterprise_pub_qrcode_logo.jpg | Bin 0 -> 11087 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/images/enterprise_pub_qrcode_bg.jpg
create mode 100644 lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/images/enterprise_pub_qrcode_logo.jpg
diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/images/enterprise_pub_qrcode_bg.jpg b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/resources/images/enterprise_pub_qrcode_bg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ffe4cf8f9929c2c0fa753f5607b05700c6e05f02
GIT binary patch
literal 306288
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