From ae727d0fddd860c12ed8f687fdef094664a31aa8 Mon Sep 17 00:00:00 2001 From: jiangpeng Date: Thu, 23 Apr 2026 02:00:18 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E8=AE=A2=E5=8D=95=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E9=80=9A=E8=BF=87=E6=97=B6=E7=94=9F=E6=88=90=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E4=BF=A1=E6=81=AFpdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-sip/pom.xml | 5 + .../impl/ProjectOrderInfoServiceImpl.java | 444 ++++++++++++++++++ .../mapper/sip/ProjectOrderFileLogMapper.xml | 6 +- .../resources/static/img/companyLogoHD.jpg | Bin 0 -> 8769 bytes 4 files changed, 454 insertions(+), 1 deletion(-) create mode 100644 ruoyi-sip/src/main/resources/static/img/companyLogoHD.jpg diff --git a/ruoyi-sip/pom.xml b/ruoyi-sip/pom.xml index c4ddd953..08f22703 100644 --- a/ruoyi-sip/pom.xml +++ b/ruoyi-sip/pom.xml @@ -53,6 +53,11 @@ javax.mail 1.5.6 + + com.github.librepdf + openpdf + 1.3.23 + diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java index 600fa0c8..029130ff 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java @@ -19,6 +19,22 @@ import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.lowagie.text.Document; +import com.lowagie.text.DocumentException; +import com.lowagie.text.Element; +import com.lowagie.text.Chunk; +import com.lowagie.text.Image; +import com.lowagie.text.PageSize; +import com.lowagie.text.Paragraph; +import com.lowagie.text.Phrase; +import com.lowagie.text.Rectangle; +import com.lowagie.text.pdf.BaseFont; +import com.lowagie.text.pdf.ColumnText; +import com.lowagie.text.pdf.PdfPCell; +import com.lowagie.text.pdf.PdfPageEventHelper; +import com.lowagie.text.pdf.PdfPTable; +import com.lowagie.text.pdf.PdfWriter; +import com.lowagie.text.pdf.draw.LineSeparator; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; @@ -35,7 +51,9 @@ import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.sip.domain.*; import com.ruoyi.sip.dto.ApiDataQueryDto; import com.ruoyi.sip.flowable.domain.Todo; @@ -69,9 +87,11 @@ import org.springframework.stereotype.Service; import com.ruoyi.sip.mapper.ProjectOrderInfoMapper; import com.ruoyi.common.core.text.Convert; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.*; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import static com.ruoyi.common.utils.ShiroUtils.getSysUser; @@ -119,6 +139,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To private static final List N_VIDIA_LIST = Arrays.asList("0504A14F", "0504A14G", "0504A1JX"); private Boolean useMcpExportExcelFormat = Boolean.TRUE; private static final List FILE_INFO_LIST = Arrays.asList( "(请上传商务折扣审批邮件信息).pdf/.jpg/.png","(请上传未盖章合同信息).pdf/.jpg/.png", "(补充附件).zip/.rar/.jpg/.png","(请上传已盖章合同信息).pdf/.jpg/.png"); + private static final String ORDER_CONTENT_FILE_SORT = "5"; @Autowired private TaskService taskService; @@ -1741,6 +1762,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To handleApproveOrder(businessKey); // 订单审批通过时推送项目信息到CRM projectInfoService.scheduleOpportunityUpdateByProjectId(dbProjectOrderInfo.getProjectId()); + saveOrderContentPdf(dbProjectOrderInfo.getId()); } @Override @@ -1839,6 +1861,428 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To } } + private void saveOrderContentPdf(Long orderId) { + ProjectOrderInfo orderInfo = selectProjectOrderInfoById(orderId); + if (orderInfo == null) { + throw new ServiceException("订单不存在,无法生成订单内容PDF"); + } + try { + deleteExistingOrderContentPdf(orderId, orderInfo.getVersionCode()); + byte[] pdfBytes = buildOrderContentPdf(orderInfo); + String fileName = buildOrderContentFileName(orderInfo); + String filePath = uploadGeneratedPdf(fileName, pdfBytes); + + ProjectOrderFileLog fileLog = new ProjectOrderFileLog(); + fileLog.setOrderId(orderId); + fileLog.setFileName(fileName); + fileLog.setFilePath(filePath); + fileLog.setFileType(ProjectOrderFileLog.FileTypeEnum.CONTRACT_BAK.getCode()); + fileLog.setFileSort(ORDER_CONTENT_FILE_SORT); + fileLog.setFileVersionCode(orderInfo.getVersionCode()); + fileLog.setUploadTime(DateUtils.getNowDate()); + fileLog.setUploadUser(resolveCurrentUserId()); + fileLog.setUploadUserName(resolveCurrentUserName()); + fileLogService.insertProjectOrderFileLog(fileLog); + } catch (Exception e) { + log.error("生成订单内容PDF失败,订单ID:{}", orderId, e); + throw new ServiceException("生成订单内容PDF失败: " + e.getMessage()); + } + } + + private void deleteExistingOrderContentPdf(Long orderId, String versionCode) { + ProjectOrderFileLog query = new ProjectOrderFileLog(); + query.setOrderId(orderId); + query.setFileType(ProjectOrderFileLog.FileTypeEnum.CONTRACT_BAK.getCode()); + query.setFileVersionCode(versionCode); + query.setFileSort(ORDER_CONTENT_FILE_SORT); + List existList = fileLogService.selectProjectOrderFileLogList(query); + if (CollUtil.isNotEmpty(existList)) { + String ids = existList.stream().map(v -> String.valueOf(v.getId())).collect(Collectors.joining(",")); + fileLogService.deleteProjectOrderFileLogByIds(ids); + } + } + + private String buildOrderContentFileName(ProjectOrderInfo orderInfo) { + String safeProjectName = StringUtils.isEmpty(orderInfo.getProjectName()) ? "订单内容" + : orderInfo.getProjectName().replaceAll("[\\\\/:*?\"<>|]", "_"); + return safeProjectName + "_Rev." + safeText(orderInfo.getVersionCode()) + "_订单内容.pdf"; + } + + private String uploadGeneratedPdf(String fileName, byte[] pdfBytes) throws IOException { + MultipartFile multipartFile = new ByteArrayMultipartFile(fileName, fileName, "application/pdf", pdfBytes); + return FileUploadUtils.upload(multipartFile); + } + + private byte[] buildOrderContentPdf(ProjectOrderInfo orderInfo) throws Exception { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Rectangle pageSize = PageSize.A4.rotate(); + Document document = new Document(pageSize, 22, 22, 20, 20); + BaseFont baseFont = createPdfBaseFont(); + PdfWriter writer = PdfWriter.getInstance(document, outputStream); + writer.setPageEvent(new OrderContentPdfPageEvent(baseFont, buildPdfFooter(orderInfo))); + document.open(); + addPdfHeader(document, baseFont, orderInfo); + + addOrderInfoSection(document, baseFont, orderInfo); + + document.close(); + return outputStream.toByteArray(); + } + + private String buildPdfFooter(ProjectOrderInfo orderInfo) { + return safeEmpty(orderInfo.getProjectCode()) + "-" + + safeEmpty(orderInfo.getOrderCode()) + "-Rev." + + safeEmpty(orderInfo.getVersionCode()); + } + + private BaseFont createPdfBaseFont() throws Exception { + List embeddedFontCandidates = Arrays.asList( + "C:\\Windows\\Fonts\\msyh.ttc,0", + "C:\\Windows\\Fonts\\simsun.ttc,0", + "C:\\Windows\\Fonts\\simhei.ttf" + ); + for (String fontPath : embeddedFontCandidates) { + String actualPath = fontPath.contains(",") ? fontPath.substring(0, fontPath.indexOf(',')) : fontPath; + if (Files.exists(Paths.get(actualPath))) { + return BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED); + } + } + return BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + } + + private void addPdfHeader(Document document, BaseFont baseFont, ProjectOrderInfo orderInfo) throws DocumentException { + PdfPTable headerTable = new PdfPTable(2); + headerTable.setWidthPercentage(100); + headerTable.setWidths(new float[]{4.5f, 1.5f}); + headerTable.setSpacingAfter(4); + headerTable.getDefaultCell().setBorder(Rectangle.NO_BORDER); + + PdfPCell companyCell = createBorderlessCell("紫光汇智信息技术有限公司", baseFont, 13, Element.ALIGN_LEFT, + new java.awt.Color(125, 125, 125), true); + companyCell.setVerticalAlignment(Element.ALIGN_MIDDLE); + companyCell.setPaddingTop(4); + headerTable.addCell(companyCell); + + Image logoImage = loadOrderPdfLogo(); + if (logoImage != null) { + logoImage.scaleToFit(110f, 30f); + PdfPCell logoCell = new PdfPCell(logoImage, false); + logoCell.setBorder(Rectangle.NO_BORDER); + logoCell.setHorizontalAlignment(Element.ALIGN_RIGHT); + logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE); + logoCell.setPadding(0); + headerTable.addCell(logoCell); + } else { + PdfPCell brandCell = createBorderlessCell("紫光汇智 UNIS SENSE", baseFont, 10, Element.ALIGN_RIGHT, + new java.awt.Color(118, 38, 137), true); + brandCell.setVerticalAlignment(Element.ALIGN_MIDDLE); + brandCell.setPaddingTop(4); + headerTable.addCell(brandCell); + } + document.add(headerTable); + + LineSeparator separator = new LineSeparator(); + separator.setLineWidth(0.6f); + separator.setLineColor(new java.awt.Color(200, 200, 200)); + document.add(new Chunk(separator)); + + Paragraph subTitle = new Paragraph(buildPdfSubtitle(orderInfo), + new com.lowagie.text.Font(baseFont, 11, com.lowagie.text.Font.BOLD, new java.awt.Color(85, 85, 85))); + subTitle.setAlignment(Element.ALIGN_CENTER); + subTitle.setSpacingBefore(3); + subTitle.setSpacingAfter(8); + document.add(subTitle); + } + + private Image loadOrderPdfLogo() { + try (InputStream inputStream = SpringUtils.getResource("classpath:static/img/companyLogoHD.jpg").getInputStream()) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; + int length; + while ((length = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, length); + } + return Image.getInstance(outputStream.toByteArray()); + } catch (Exception e) { + log.warn("读取订单PDF Logo失败", e); + return null; + } + } + + private String buildPdfSubtitle(ProjectOrderInfo orderInfo) { + return safeEmpty(orderInfo.getProjectName()) + "Rev." + safeEmpty(orderInfo.getVersionCode()); + } + + private static class OrderContentPdfPageEvent extends PdfPageEventHelper { + private final BaseFont baseFont; + private final String footerText; + + private OrderContentPdfPageEvent(BaseFont baseFont, String footerText) { + this.baseFont = baseFont; + this.footerText = footerText; + } + + @Override + public void onEndPage(PdfWriter writer, Document document) { + com.lowagie.text.Font footerFont = new com.lowagie.text.Font(baseFont, 9, + com.lowagie.text.Font.NORMAL, new java.awt.Color(120, 120, 120)); + float y = document.bottom() - 10; + ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, + new Phrase(footerText, footerFont), document.left(), y, 0); + ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_RIGHT, + new Phrase("第" + writer.getPageNumber() + "页", footerFont), document.right(), y, 0); + } + } + + private void addOrderInfoSection(Document document, BaseFont baseFont, ProjectOrderInfo orderInfo) throws DocumentException { + Paragraph sectionTitle = new Paragraph("订单信息", + new com.lowagie.text.Font(baseFont, 14, com.lowagie.text.Font.BOLD, new java.awt.Color(32, 126, 214))); + sectionTitle.setSpacingAfter(5); + document.add(sectionTitle); + + PdfPTable table = new PdfPTable(6); + table.setWidthPercentage(100); + table.setWidths(new float[]{1.3f, 2.5f, 1.3f, 2.5f, 1.4f, 2.5f}); + table.setSpacingAfter(6); + + addSixColumnRow(table, baseFont, "项目名称", orderInfo.getProjectName(), 3, "版本号", orderInfo.getVersionCode(), 1); + addSixColumnRow(table, baseFont, "项目编号", orderInfo.getProjectCode(), 1, "最终客户", orderInfo.getCustomerName(), 3); + addSixColumnRow(table, baseFont, "BG", + firstNonEmpty(orderInfo.getBgPropertyDesc(), DictUtils.getDictLabel(BG_TYPE_DICT_TYPE, orderInfo.getBgProperty())), 1, + "行业", firstNonEmpty(orderInfo.getIndustryTypeDesc(), + DictUtils.getDictLabel("YYS".equals(orderInfo.getBgProperty()) ? "bg_yys" : "bg_hysy", orderInfo.getIndustryType())), 1, + "代表处", orderInfo.getAgentName(), 1); + addSixColumnRow(table, baseFont, "进货商接口人", orderInfo.getBusinessPerson(), 1, "Email", orderInfo.getBusinessEmail(), 1, + "联系方式", orderInfo.getBusinessPhone(), 1); + addSixColumnRow(table, baseFont, "合同编号", orderInfo.getOrderCode(), 1, "执行单有效截止时间", formatDate(orderInfo.getOrderEndTime()), 3); + addSixColumnRow(table, baseFont, "币种", DictUtils.getDictLabel("currency_type", orderInfo.getCurrencyType()), 1, + "总代出货金额", formatMoney(orderInfo.getShipmentAmount()), 3); + addSixColumnRow(table, baseFont, "要求到货时间", formatDate(orderInfo.getDeliveryTime()), 1, + "公司直发", firstNonEmpty(orderInfo.getCompanyDeliveryDesc(), DictUtils.getDictLabel("company_delivery", orderInfo.getCompanyDelivery())), 3); + addSixColumnRow(table, baseFont, "下单通路", firstNonEmpty(orderInfo.getOrderChannelDesc(), resolveOrderChannel(orderInfo.getOrderChannel())), 1, + "供货商", orderInfo.getSupplier(), 3); + addSixColumnRow(table, baseFont, "汇智责任人", orderInfo.getDutyName(), 1, "Email", orderInfo.getDutyEmail(), 1, + "联系方式", orderInfo.getDutyPhone(), 1); + addSixColumnRow(table, baseFont, "进货商", orderInfo.getPartnerName(), 3, "进货商类型", + firstNonEmpty(orderInfo.getLevelDesc(), DictUtils.getDictLabel("identify_level", orderInfo.getLevel())), 1); + addSixColumnRow(table, baseFont, "进货商联系人", orderInfo.getPartnerUserName(), 1, "Email", orderInfo.getPartnerEmail(), 1, + "联系方式", orderInfo.getPartnerPhone(), 1); + addSingleFieldRow(table, baseFont, "其他特别说明", orderInfo.getRemark()); + + document.add(table); + } + + private void addSixColumnRow(PdfPTable table, BaseFont baseFont, String label1, String value1, int value1Colspan, + String label2, String value2, int value2Colspan) { + table.addCell(createLabelCell(label1, baseFont)); + PdfPCell valueCell1 = createValueCell(value1, baseFont); + valueCell1.setColspan(value1Colspan); + table.addCell(valueCell1); + table.addCell(createLabelCell(label2, baseFont)); + PdfPCell valueCell2 = createValueCell(value2, baseFont); + valueCell2.setColspan(value2Colspan); + table.addCell(valueCell2); + } + + private void addSixColumnRow(PdfPTable table, BaseFont baseFont, String label1, String value1, int value1Colspan, + String label2, String value2, int value2Colspan, + String label3, String value3, int value3Colspan) { + table.addCell(createLabelCell(label1, baseFont)); + PdfPCell valueCell1 = createValueCell(value1, baseFont); + valueCell1.setColspan(value1Colspan); + table.addCell(valueCell1); + table.addCell(createLabelCell(label2, baseFont)); + PdfPCell valueCell2 = createValueCell(value2, baseFont); + valueCell2.setColspan(value2Colspan); + table.addCell(valueCell2); + table.addCell(createLabelCell(label3, baseFont)); + PdfPCell valueCell3 = createValueCell(value3, baseFont); + valueCell3.setColspan(value3Colspan); + table.addCell(valueCell3); + } + + private void addSingleFieldRow(PdfPTable table, BaseFont baseFont, String label, String value) { + table.addCell(createLabelCell(label, baseFont)); + PdfPCell valueCell = createValueCell(value, baseFont); + valueCell.setColspan(5); + table.addCell(valueCell); + } + + private PdfPCell createLabelCell(String value, BaseFont baseFont) { + return createTableCell(value, baseFont, 10, Element.ALIGN_LEFT, new java.awt.Color(248, 248, 248), true, false); + } + + private PdfPCell createValueCell(String value, BaseFont baseFont) { + return createTableCell(value, baseFont, 10, Element.ALIGN_LEFT, java.awt.Color.WHITE, false, true); + } + + private PdfPCell createTableCell(String value, BaseFont baseFont, int fontSize, int alignment, java.awt.Color backgroundColor, + boolean bold, boolean emptyAsBlank) { + com.lowagie.text.Font font = new com.lowagie.text.Font(baseFont, fontSize, + bold ? com.lowagie.text.Font.BOLD : com.lowagie.text.Font.NORMAL); + String displayValue = emptyAsBlank ? safeEmptyValue(value) : safeText(value); + PdfPCell cell = new PdfPCell(new Phrase(displayValue, font)); + cell.setHorizontalAlignment(alignment); + cell.setVerticalAlignment(Element.ALIGN_MIDDLE); + cell.setPadding(4); + cell.setMinimumHeight(26f); + cell.setBackgroundColor(backgroundColor); + cell.setBorderColor(new java.awt.Color(220, 220, 220)); + cell.setBorderWidth(0.7f); + return cell; + } + + private PdfPCell createBorderlessCell(String value, BaseFont baseFont, int fontSize, int alignment, + java.awt.Color fontColor, boolean bold) { + com.lowagie.text.Font font = new com.lowagie.text.Font(baseFont, fontSize, + bold ? com.lowagie.text.Font.BOLD : com.lowagie.text.Font.NORMAL, fontColor); + PdfPCell cell = new PdfPCell(new Phrase(safeText(value), font)); + cell.setHorizontalAlignment(alignment); + cell.setVerticalAlignment(Element.ALIGN_MIDDLE); + cell.setBorder(Rectangle.NO_BORDER); + cell.setPadding(0); + return cell; + } + + private String resolveOrderChannel(String orderChannel) { + if (ProjectOrderInfo.OrderChannelEnum.TOTAL_GENERATION.getCode().equals(orderChannel)) { + return "总代"; + } + if (ProjectOrderInfo.OrderChannelEnum.DIRECT_SIGNING.getCode().equals(orderChannel)) { + return "直签"; + } + return ""; + } + + private String resolvePaymentMethodLabel(ProjectOrderInfo orderInfo) { + if (StringUtils.isEmpty(orderInfo.getPaymentMethod())) { + return ""; + } + if (ProjectOrderInfo.OrderChannelEnum.TOTAL_GENERATION.getCode().equals(orderInfo.getOrderChannel())) { + if ("1-1".equals(orderInfo.getPaymentMethod())) { + return "全款支付,无需预付款"; + } + if ("1-2".equals(orderInfo.getPaymentMethod())) { + return "全款支付,需单独备货生产,预付订单总货款百分比"; + } + } + if (ProjectOrderInfo.OrderChannelEnum.DIRECT_SIGNING.getCode().equals(orderInfo.getOrderChannel())) { + if ("2-1".equals(orderInfo.getPaymentMethod())) { + return "全款支付"; + } + if ("2-2".equals(orderInfo.getPaymentMethod())) { + return "全款支付,需单独备货生产,预付订单总货款百分比"; + } + if ("2-3".equals(orderInfo.getPaymentMethod())) { + return "商业汇票支付,预付订单总货款百分比"; + } + } + return orderInfo.getPaymentMethod(); + } + + private String resolveCurrentUserId() { + try { + Long userId = ShiroUtils.getUserId(); + return userId == null ? "" : String.valueOf(userId); + } catch (Exception e) { + return ""; + } + } + + private String resolveCurrentUserName() { + try { + SysUser sysUser = getSysUser(); + return sysUser == null ? "" : sysUser.getUserName(); + } catch (Exception e) { + return ""; + } + } + + private String formatMoney(BigDecimal value) { + if (value == null) { + return ""; + } + return new DecimalFormat("#,##0.00").format(value); + } + + private String formatDate(Date date) { + return date == null ? "-" : DateUtil.format(date, "yyyy-MM-dd"); + } + + private String safeText(Object value) { + if (value == null) { + return "-"; + } + String text = String.valueOf(value).trim(); + return StringUtils.isEmpty(text) ? "-" : text; + } + + private String firstNonEmpty(String first, String second) { + return StringUtils.isNotEmpty(first) ? first : second; + } + + private String safeEmpty(String value) { + return value == null ? "" : value.trim(); + } + + private String safeEmptyValue(String value) { + return value == null ? "" : value.trim(); + } + + private static class ByteArrayMultipartFile implements MultipartFile { + private final String name; + private final String originalFilename; + private final String contentType; + private final byte[] content; + + private ByteArrayMultipartFile(String name, String originalFilename, String contentType, byte[] content) { + this.name = name; + this.originalFilename = originalFilename; + this.contentType = contentType; + this.content = content == null ? new byte[0] : content; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getOriginalFilename() { + return originalFilename; + } + + @Override + public String getContentType() { + return contentType; + } + + @Override + public boolean isEmpty() { + return content.length == 0; + } + + @Override + public long getSize() { + return content.length; + } + + @Override + public byte[] getBytes() { + return content; + } + + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(content); + } + + @Override + public void transferTo(File dest) throws IOException { + Files.write(dest.toPath(), content); + } + } + @Override public byte[] exportContractTemplate( ProjectOrderInfo orderInfo) { try { diff --git a/ruoyi-sip/src/main/resources/mapper/sip/ProjectOrderFileLogMapper.xml b/ruoyi-sip/src/main/resources/mapper/sip/ProjectOrderFileLogMapper.xml index e5d628aa..34e400b6 100644 --- a/ruoyi-sip/src/main/resources/mapper/sip/ProjectOrderFileLogMapper.xml +++ b/ruoyi-sip/src/main/resources/mapper/sip/ProjectOrderFileLogMapper.xml @@ -12,6 +12,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -30,6 +32,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" andt1. upload_time = #{uploadTime} and t1.file_path = #{filePath} and t1.file_type = #{fileType} + and t1.file_sort = #{fileSort} + and t1.file_version_code = #{fileVersionCode} order by t1.id @@ -116,4 +120,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - \ No newline at end of file + diff --git a/ruoyi-sip/src/main/resources/static/img/companyLogoHD.jpg b/ruoyi-sip/src/main/resources/static/img/companyLogoHD.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbb173529b12bf972f1c6c5fb6fcddbac03a07fb GIT binary patch literal 8769 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 literal 0 HcmV?d00001