Explorar el Código

出入管理 WEB端页面 接口代码调整

zhulu hace 4 días
padre
commit
c8e7ab5fcd
Se han modificado 18 ficheros con 1068 adiciones y 24 borrados
  1. 1 1
      project_data/sql/1.0.14/soc/soc.sql
  2. 1 1
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/domain/CoreIntroduceLetterOutInRequestUser.java
  3. 3 9
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/dto/CoreOutInRequestDto.java
  4. 7 1
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/vo/CoreIntroduceLetterOutInRequestVo.java
  5. 39 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/controller/CoreIntroduceLetterController.java
  6. 176 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/CoreIntroduceLetterOutInRequestExcelVo.java
  7. 42 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/IdTypeConverter.java
  8. 157 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/IntroduceLetterOutInRequestMergeHandler.java
  9. 39 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/LetterTypeConverter.java
  10. 224 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/MultiImageWriteHandler.java
  11. 50 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/OutInRequestStatusConverter.java
  12. 6 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/mapper/CoreIntroduceLetterMapper.java
  13. 3 5
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/mapper/CoreOutInRecordMapper.java
  14. 5 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/ICoreIntroduceLetterService.java
  15. 3 3
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/ICoreOutInRecordService.java
  16. 195 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/impl/CoreIntroduceLetterServiceImpl.java
  17. 3 3
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/impl/CoreOutInRecordServiceImpl.java
  18. 114 1
      soc-modules/soc-modules-core/src/main/resources/mapper/letter/CoreIntroduceLetterMapper.xml

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
project_data/sql/1.0.14/soc/soc.sql


+ 1 - 1
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/domain/CoreIntroduceLetterOutInRequestUser.java

@@ -30,7 +30,7 @@ public class CoreIntroduceLetterOutInRequestUser
 
     /** 出入人员名称 */
     @ApiModelProperty(value = "人员名称")
-    private String userName;
+private String userName;
 
     /** 出入人员单位名称 */
     @ApiModelProperty(value = "单位名称")

+ 3 - 9
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/dto/CoreOutInRecordRequestDto.java → soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/dto/CoreOutInRequestDto.java

@@ -1,15 +1,8 @@
 package com.xunmei.common.core.domain.letter.dto;
 
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
 import com.xunmei.common.core.web.domain.BaseEntity;
-import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
 
 import java.util.Date;
 
@@ -20,7 +13,7 @@ import java.util.Date;
  * @date 2023-11-10
  */
 @Data
-public class CoreOutInRecordRequestDto extends BaseEntity {
+public class CoreOutInRequestDto extends BaseEntity {
     private static final long serialVersionUID = 1L;
 
     /**
@@ -68,5 +61,6 @@ public class CoreOutInRecordRequestDto extends BaseEntity {
 
     private Date endTime;
 
-    private Integer approveStatus;
+    @ApiModelProperty(value = "出入状态 :0待审批 1 待登记 2 已完成 3 已拒绝 4 已过期 5已补登")
+    private Integer status;
 }

+ 7 - 1
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/letter/vo/CoreIntroduceLetterOutInRequestVo.java

@@ -100,7 +100,7 @@ public class CoreIntroduceLetterOutInRequestVo {
     @ApiModelProperty(value = "出入状态 :0待审批 1 待登记 2 已完成 3 已拒绝 4 已过期 5已补登")
     private Integer status;
 
-    @ApiModelProperty(value = "类型:1 职能部门出入, 2 临时出入,3 紧急出入")
+    @ApiModelProperty(value = "类型:2 普通出入,3 紧急出入")
     private Integer letterType;
 
 //    @ApiModelProperty(value = "描述")
@@ -150,4 +150,10 @@ public class CoreIntroduceLetterOutInRequestVo {
 
     private String remarkImage;
 
+    @ApiModelProperty(value = "地区")
+    private String affiliatedArea;
+
+    @ApiModelProperty(value = "行社名称")
+    private String affiliatedBank;
+
 }

+ 39 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/controller/CoreIntroduceLetterController.java

@@ -19,6 +19,7 @@ import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 import java.util.Date;
 
 /**
@@ -232,4 +233,42 @@ public class CoreIntroduceLetterController extends BaseController {
         }
         return coreIntroduceLetterService.selectOntInRequestListPage(requestDto);
     }
+
+    @ApiOperation(value = "导出出入申请列表")
+    @RequiresPermissions("core:outinrequest:list")
+    @PostMapping("/outinrequest/export")
+    public void exportOutInRequestExcel(CoreOutInRequestDto requestDto, HttpServletResponse response) {
+        if(ObjectUtil.isNull(requestDto))
+        {
+            throw new RuntimeException("请求参数不能为空");
+        }
+        if(ObjectUtil.isEmpty( requestDto.getOrgId()))
+        {
+            requestDto.setOrgId(SecurityUtils.getLoginUser().getOrgId());
+        }
+        if(ObjectUtil.isNull(requestDto.getOrgId()))
+        {
+            throw new RuntimeException("请求参数机构编码不能为空");
+        }
+        coreIntroduceLetterService.webExportOntInRequestExcel(requestDto,response);
+    }
+
+    @ApiOperation(value = "查询出入申请列表")
+    @RequiresPermissions("core:outinrequest:list")
+    @GetMapping("/outinrequest/web/list")
+    public TableDataInfo<CoreIntroduceLetterOutInRequestVo> webOutInRequestList(CoreOutInRequestDto requestDto) {
+        if(ObjectUtil.isNull(requestDto))
+        {
+            throw new RuntimeException("请求参数不能为空");
+        }
+        if(ObjectUtil.isEmpty( requestDto.getOrgId()))
+        {
+            requestDto.setOrgId(SecurityUtils.getLoginUser().getOrgId());
+        }
+        if(ObjectUtil.isNull(requestDto.getOrgId()))
+        {
+            throw new RuntimeException("请求参数机构编码不能为空");
+        }
+        return coreIntroduceLetterService.selectWebOntInRequestListPage(requestDto);
+    }
 }

+ 176 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/CoreIntroduceLetterOutInRequestExcelVo.java

@@ -0,0 +1,176 @@
+package com.xunmei.core.letter.export;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xunmei.core.safetyCheck.vo.SafeStatusConverter;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 介绍信对象 core_introduce_letter
+ *
+ * @author xunmei
+ * @date 2023-10-12
+ */
+@Data
+@ColumnWidth(15) //列宽,最大值为255
+@HeadRowHeight(16) //表头行高
+@ContentRowHeight(16) //数据行高
+public class CoreIntroduceLetterOutInRequestExcelVo {
+    private static final long serialVersionUID = 1L;
+
+    @ExcelIgnore
+    private Long outInRequestId;
+
+    @ExcelProperty(index = 0,value = {"${cellWriterValue}","序号"})
+    private Integer no;
+
+    @ExcelProperty(index = 1,value = {"${cellWriterValue}","地区"})
+    private String affiliatedArea;
+
+    @ExcelProperty(value = {"${cellWriterValue}","行社"})
+    private String affiliatedBank;
+
+    @ExcelProperty(value = {"${cellWriterValue}","单位名称"})
+    private String orgName;
+
+    /**
+     * 介绍信编号
+     */
+    @ExcelProperty(value = {"${cellWriterValue}","介绍信编号"})
+    private String letterNo;
+
+    /**
+     * 出入类型
+     */
+    @ExcelProperty(value = {"${cellWriterValue}","出入类型"},converter = LetterTypeConverter.class)
+    private String letterType;
+
+    /**
+     * 有效开始时间
+     */
+    @ExcelProperty(value = {"${cellWriterValue}","有效开始时间"})
+    @ApiModelProperty(value = "有效开始时间")
+    @JsonFormat(pattern = "yyyy年MM月dd日", timezone = "GMT+8")
+    private Date startTime;
+
+    /**
+     * 有效结束时间
+     */
+    @ExcelProperty(value = {"${cellWriterValue}","有效结束时间"})
+    @ApiModelProperty(value = "有效结束时间")
+    @JsonFormat(pattern = "yyyy年MM月dd日", timezone = "GMT+8")
+    private Date endTime;
+
+    @ExcelProperty(value = {"${cellWriterValue}","有效天数"})
+    @ApiModelProperty(value = "有效天数")
+    private Integer effectiveDays;
+
+    /**
+     * 来访事由
+     */
+    @ExcelProperty(value = {"${cellWriterValue}","来访事由"})
+    @ApiModelProperty(value = "来访事由")
+    private String letterReasons;
+
+    /**
+     * 介绍信文件
+     */
+
+//    @ExcelProperty(value = {"${cellWriterValue}","介绍信照片"})
+    @ExcelIgnore
+    private List<String> letterFile;
+    @ExcelIgnore
+    private String letterFileStr;
+
+    @ExcelProperty(value = {"${cellWriterValue}","核验人"})
+    private String createBy;
+
+    /**
+     * 申请时间
+     */
+    @ExcelProperty(value = {"${cellWriterValue}","申请时间"})
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+
+
+//    @ExcelProperty(value = {"${cellWriterValue}","核验人签名"})
+//    private String checkSign;
+
+    @ExcelProperty(value = {"${cellWriterValue}","审批人"})
+    @ApiModelProperty(value = "审批人")
+    private String approveUser;
+
+    /**
+     * 审核时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ExcelProperty(value = {"${cellWriterValue}","审批时间"})
+    @ApiModelProperty(value = "审批时间")
+    private Date approveTime;
+
+
+
+    @ApiModelProperty(value = "审批说明")
+    @ExcelProperty(value = {"${cellWriterValue}","审批说明"})
+    private String approveRemark;
+
+//    @ApiModelProperty(value = "审批人签名")
+//    @ExcelProperty(value = {"${cellWriterValue}","审批人签名"})
+//    private String approveSignImg;
+
+    @ApiModelProperty(value = "出入状态 :0待审批 1 待登记 2 已完成 3 已拒绝 4 已过期 5已补登")
+    @ExcelProperty(value = {"${cellWriterValue}","出入状态"},converter = OutInRequestStatusConverter.class)
+    private String status;
+
+    @ExcelProperty(value = {"${cellWriterValue}","陪同人员"})
+    private String accompanyingPerson;
+
+    @ExcelProperty(value = {"${cellWriterValue}","备注"})
+    private String remark;
+
+//    @ExcelProperty(value = {"${cellWriterValue}","备注图片"})
+//    private String remarkImage;
+
+    @ApiModelProperty(value = "人员名称")
+    @ExcelProperty(value = {"${cellWriterValue}","人员名称"})
+    private String userName;
+
+    /** 出入人员单位名称 */
+    @ApiModelProperty(value = "单位名称")
+    @ExcelProperty(value = {"${cellWriterValue}","单位名称"})
+    private String companyName;
+
+    /** 证件类型 */
+    @ExcelProperty(value = {"${cellWriterValue}","证件类型"},converter = IdTypeConverter.class)
+    private String idType;
+
+    /** 介绍信证件号 */
+    @ExcelProperty(value = {"${cellWriterValue}","证件号"})
+    private String idCard;
+
+    /** 证件照片 */
+//    @ExcelProperty(value = {"${cellWriterValue}","证件照片"})
+    @ExcelIgnore
+    private List<String> imgFileList;
+
+//    @ExcelProperty(value = {"${cellWriterValue}","证件照片"})
+    @ExcelIgnore
+    private String imgFileStr;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ExcelProperty(value = {"${cellWriterValue}","到达时间"})
+    private Date arrivalTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ExcelProperty(value = {"${cellWriterValue}","离开时间"})
+    private Date departureTime;
+}

+ 42 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/IdTypeConverter.java

@@ -0,0 +1,42 @@
+package com.xunmei.core.letter.export;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+
+public class IdTypeConverter implements Converter<String> {
+
+
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return null;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(String status, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+
+        if ("0".equals(status)) {
+            return new CellData("身份证");
+        }
+        if ("1".equals(status)) {
+            return new CellData("工作证");
+        }
+        if ("2".equals(status)) {
+            return new CellData("其他");
+        }
+        return new CellData("其他");
+    }
+}

+ 157 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/IntroduceLetterOutInRequestMergeHandler.java

@@ -0,0 +1,157 @@
+package com.xunmei.core.letter.export;
+
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+public class IntroduceLetterOutInRequestMergeHandler implements CellWriteHandler {
+
+    // 不参与合并的字段名(即:每个人不同的字段)
+    private static final Set<String> EXCLUDE_MERGE_FIELDS = new HashSet<>(Arrays.asList(
+            "userName",
+            "companyName",
+            "idType",
+            "idCard",
+            "imgFile",
+            "arrivalTime",
+            "departureTime"
+    ));
+
+    // 缓存所有数据用于判断合并
+    private List<Object> allData;
+    private Map<String, Field> fieldMap;
+
+    public IntroduceLetterOutInRequestMergeHandler(List<?> data) {
+        this.allData = new ArrayList<>(data);
+        buildFieldMap();
+    }
+
+    private void buildFieldMap() {
+        fieldMap = new HashMap<>();
+        Class<?> clazz = CoreIntroduceLetterOutInRequestExcelVo.class;
+        while (clazz != null) {
+            for (Field field : clazz.getDeclaredFields()) {
+                field.setAccessible(true);
+                fieldMap.put(field.getName(), field);
+            }
+            clazz = clazz.getSuperclass();
+        }
+    }
+
+    private Long getFieldValue(Object obj, String fieldName) throws Exception {
+        Field field = fieldMap.get(fieldName);
+        if (field != null) {
+            Object value = field.get(obj);
+            if (value instanceof Long) {
+                return (Long) value;
+            } else if (value != null) {
+                return Long.valueOf(value.toString());
+            }
+        }
+        return null;
+    }
+
+    // 找到本次合并的起始行
+    private int findMergeStartRow(int currentRow, Long requestId) {
+        for (int i = currentRow; i >= 0; i--) {
+            try {
+                Object obj = allData.get(i);
+                Long id = getFieldValue(obj, "outInRequestId");
+                if (!requestId.equals(id)) {
+                    return i + 1;
+                }
+            } catch (Exception e) {
+                return currentRow;
+            }
+        }
+        return 0;
+    }
+
+    // 移除指定列在某行区间内的已有合并
+    private void removeMergedRegion(Sheet sheet, int startRow, int endRow, int col) {
+        for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) {
+            CellRangeAddress region = sheet.getMergedRegion(i);
+            if (region.getFirstColumn() == col && region.getLastColumn() == col &&
+                    region.getFirstRow() >= startRow && region.getLastRow() <= endRow) {
+                sheet.removeMergedRegion(i);
+            }
+        }
+    }
+
+    @Override
+    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
+        if (isHead || relativeRowIndex == null || relativeRowIndex < 0) {
+            return;
+        }
+
+        int rowIndex = relativeRowIndex;
+        Sheet sheet = writeSheetHolder.getSheet();
+
+        // 获取当前行和上一行的数据对象
+        if (rowIndex >= allData.size()) return;
+
+        Object currentObj = allData.get(rowIndex);
+        Object prevObj = rowIndex > 0 ? allData.get(rowIndex - 1) : null;
+
+        try {
+            Long currentRequestId = getFieldValue(currentObj, "outInRequestId");
+            Long prevRequestId = prevObj != null ? getFieldValue(prevObj, "outInRequestId") : null;
+
+            String fieldName = head.getFieldName();
+
+            // 只对需要合并的字段处理
+            if (!EXCLUDE_MERGE_FIELDS.contains(fieldName)) {
+                if (currentRequestId != null && currentRequestId.equals(prevRequestId)) {
+                    // 当前记录与上一条属于同一申请,尝试合并
+
+                    int mergeStartRow = findMergeStartRow(rowIndex, currentRequestId);
+                    int currentCol = cell.getColumnIndex();
+
+                    // 跳过表头行
+                    mergeStartRow+=2;
+                    rowIndex+=2;
+                    // 移除已存在的合并区域(防止重复)
+                    removeMergedRegion(sheet, mergeStartRow, rowIndex - 1, currentCol);
+
+                    // 添加新的合并区域
+                    CellRangeAddress region = new CellRangeAddress(mergeStartRow, rowIndex, currentCol, currentCol);
+                    sheet.addMergedRegion(region);
+
+                    // 居中垂直对齐(可选)
+                    Row firstRow = sheet.getRow(mergeStartRow);
+                    if (firstRow != null) {
+                        Cell firstCell = firstRow.getCell(currentCol);
+                        if (firstCell != null) {
+                            CellStyle style = firstCell.getCellStyle();
+                            style.setVerticalAlignment(VerticalAlignment.CENTER);
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 39 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/LetterTypeConverter.java

@@ -0,0 +1,39 @@
+package com.xunmei.core.letter.export;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+
+public class LetterTypeConverter implements Converter<String> {
+
+
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return null;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(String status, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+
+        if ("2".equals(status)) {
+            return new CellData("普通");
+        }
+        if ("3".equals(status)) {
+            return new CellData("紧急");
+        }
+        return new CellData("其他");
+    }
+}

+ 224 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/MultiImageWriteHandler.java

@@ -0,0 +1,224 @@
+package com.xunmei.core.letter.export;
+
+
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.*;
+import org.apache.poi.util.IOUtils;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+
+
+/**
+ * @ClassName MultiImageWriteHandler
+ * @Description: 类描述
+ * @Author: LuZhu
+ * @CreateDate: 2025/10/28 17:01
+ */
+public class MultiImageWriteHandler implements CellWriteHandler {
+
+//    private final int imageColumnIndex; // 图片所在列(从0开始)
+    private final int maxImageHeightInPoints; // 每张图最大高度(单位:points)
+    private final int maxImageWidthInPixels; // 每张图最大宽度(像素)
+    private List<Object> allData;
+    private String imageFieldName;
+
+    private String headFieldName;
+    private Map<String, Field> fieldMap;
+
+    public MultiImageWriteHandler(int imageColumnIndex,String fieldName,String headFieldName,List<?> data) {
+        this(imageColumnIndex, 80, 120); // 默认高度80pt,宽度120px
+        this.allData = new ArrayList<>(data);
+        this.imageFieldName = fieldName;
+        this.headFieldName = headFieldName;
+        buildFieldMap();
+    }
+
+    public MultiImageWriteHandler(int imageColumnIndex, int maxHeight, int maxWidth) {
+//        this.imageColumnIndex = imageColumnIndex;
+        this.maxImageHeightInPoints = maxHeight;
+        this.maxImageWidthInPixels = maxWidth;
+    }
+
+    private void buildFieldMap() {
+        fieldMap = new HashMap<>();
+        Class<?> clazz = CoreIntroduceLetterOutInRequestExcelVo.class;
+        while (clazz != null) {
+            for (Field field : clazz.getDeclaredFields()) {
+                field.setAccessible(true);
+                fieldMap.put(field.getName(), field);
+            }
+            clazz = clazz.getSuperclass();
+        }
+    }
+
+    private int determinePictureType(String filePath) {
+        if (filePath.toLowerCase().endsWith(".png"))
+        {
+            return Workbook.PICTURE_TYPE_PNG;
+        }
+
+        if (filePath.toLowerCase().endsWith(".jpeg") || filePath.toLowerCase().endsWith(".jpg"))
+            return Workbook.PICTURE_TYPE_JPEG;
+        return Workbook.PICTURE_TYPE_JPEG;
+    }
+
+    @Override
+    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {
+
+    }
+
+    @Override
+    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head,  Integer relativeRowIndex, Boolean isHead) {
+        if (isHead || relativeRowIndex == null)
+            return;
+
+        int currentCol = cell.getColumnIndex();
+
+        String fieldName = head.getFieldName();
+
+        if(!headFieldName.equals(fieldName))
+        {
+            return;
+        }
+
+        // 获取当前行和上一行的数据对象
+        if (relativeRowIndex >= allData.size())
+            return;
+
+        // 获取当前行的数据对象
+        Object data =   allData.get(relativeRowIndex);
+        if (!(data instanceof CoreIntroduceLetterOutInRequestExcelVo))
+            return;
+
+        CoreIntroduceLetterOutInRequestExcelVo vo = (CoreIntroduceLetterOutInRequestExcelVo) data;
+
+        List<String> photoPaths = null;
+        try {
+            photoPaths = getFieldValue(data, imageFieldName);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        if (photoPaths == null || photoPaths.isEmpty()) return;
+
+        Sheet sheet = writeSheetHolder.getSheet();
+        Workbook workbook = sheet.getWorkbook();
+
+        // ✅ 使用通用 Drawing 接口,避免强转异常
+        Drawing<?> drawing = sheet.createDrawingPatriarch();
+
+        int absoluteRowIndex = cell.getRowIndex(); // 获取当前行在Excel中的绝对行索引,即第几行,从0开始计数, absoluteRowIndex
+        int currentRow = absoluteRowIndex;
+        int totalHeight = 0;
+
+        for (int i = 0; i < photoPaths.size(); i++) {
+            String photoPath = photoPaths.get(i);
+            try (FileInputStream fis = new FileInputStream(photoPath)) {
+//                byte[] imageBytes = IOUtils.toByteArray(fis);
+//                int pictureIdx = workbook.addPicture(imageBytes, determinePictureType(photoPath));
+//
+//                XSSFClientAnchor anchor = new XSSFClientAnchor();
+//                anchor.setCol1(currentCol);
+//                anchor.setCol2(currentCol + 1);
+//                anchor.setRow1(currentRow);
+//                anchor.setRow2(currentRow + 1);
+//
+//                XSSFPicture picture = drawing.createPicture(anchor, pictureIdx);
+//                picture.resize(maxImageWidthInPixels / 96f, 1); // 宽度缩放,高度由行高控制
+
+                byte[] bytes = org.apache.poi.util.IOUtils.toByteArray(fis);
+                int pictureIdx = workbook.addPicture(bytes, determinePictureType(photoPath));
+
+                // ✅ 使用通用 ClientAnchor
+                ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
+                anchor.setCol1(currentCol);
+                anchor.setCol2(currentCol + 1);
+                anchor.setRow1(currentRow + i);
+                anchor.setRow2(currentRow + i + 1);
+
+                drawing.createPicture(anchor, pictureIdx);
+
+                // 设置行高
+                Row row = sheet.getRow(currentRow + i);
+                if (row == null) row = sheet.createRow(currentRow + i);
+                row.setHeightInPoints(maxImageHeightInPoints);
+
+//                totalHeight += maxImageHeightInPoints;
+//                currentRow++;
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        // 合并文本列(姓名、身份证号)
+        for (int col = 0; col < currentCol; col++) {
+            sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(
+                    absoluteRowIndex,
+                    absoluteRowIndex + photoPaths.size() - 1,
+                    col, col));
+        }
+
+        // 设置每行高度
+        for (int i = 0; i < photoPaths.size(); i++) {
+            Row row = sheet.getRow(absoluteRowIndex + i);
+            if (row == null) row = sheet.createRow(absoluteRowIndex + i);
+            row.setHeightInPoints(maxImageHeightInPoints);
+        }
+    }
+
+    private List<String> getFieldValue(Object obj, String fieldName) throws Exception {
+        Field field = fieldMap.get(fieldName);
+        if (field != null) {
+            Object value = field.get(obj);
+            if (value == null) {
+                return Collections.emptyList();
+            }
+
+            // JDK 8 写法:if-else 判断类型
+            if (value instanceof String) {
+                String str = (String) value;
+                String[] parts = str.split("\\s*,\\s*"); // 按逗号分割,忽略前后空格
+                return Arrays.asList(parts);
+
+            } else if (value instanceof Collection) {
+                Collection<?> coll = (Collection<?>) value;
+                List<String> result = new ArrayList<>();
+                for (Object item : coll) {
+                    result.add(item != null ? item.toString() : "");
+                }
+                return result;
+
+            } else if (value.getClass().isArray()) {
+                int length = java.lang.reflect.Array.getLength(value);
+                List<String> result = new ArrayList<>();
+                for (int i = 0; i < length; i++) {
+                    Object item = java.lang.reflect.Array.get(value, i);
+                    result.add(item != null ? item.toString() : "");
+                }
+                return result;
+
+            } else {
+                // 其他类型:Integer, Long, File, URL 等
+                return Arrays.asList(value.toString());
+            }
+        }
+        return null;
+    }
+}

+ 50 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/export/OutInRequestStatusConverter.java

@@ -0,0 +1,50 @@
+package com.xunmei.core.letter.export;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+
+public class OutInRequestStatusConverter implements Converter<String> {
+
+
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return null;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(String status, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if ("0".equals(status)) {
+            return new CellData("待审批");
+        }
+        if ("1".equals(status)) {
+            return new CellData("待登记");
+        }
+        if ("2".equals(status)) {
+            return new CellData("已完成");
+        }
+        if ("3".equals(status)) {
+            return new CellData("已拒绝");
+        }
+        if ("4".equals(status)) {
+            return new CellData("已逾期");
+        }
+        if ("5".equals(status)) {
+            return new CellData("已补登");
+        }
+        return new CellData("未知");
+    }
+}

+ 6 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/mapper/CoreIntroduceLetterMapper.java

@@ -6,8 +6,10 @@ import com.xunmei.common.core.domain.letter.domain.*;
 import com.xunmei.common.core.domain.letter.dto.CoreIntroduceLetterApproveRequestDto;
 import com.xunmei.common.core.domain.letter.dto.CoreIntroduceLetterRequestDto;
 import com.xunmei.common.core.domain.letter.dto.CoreIntroduceLetterUserAddDto;
+import com.xunmei.common.core.domain.letter.dto.CoreOutInRequestDto;
 import com.xunmei.common.core.domain.letter.vo.*;
 import com.xunmei.common.core.domain.panel.vo.PanelListVo;
+import com.xunmei.core.letter.export.CoreIntroduceLetterOutInRequestExcelVo;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -126,4 +128,8 @@ public interface CoreIntroduceLetterMapper extends BaseMapper<CoreIntroduceLette
 
     List<CoreIntroduceLetterOutInRequestVo> selectOutInRequestByLetterIds(@Param("letterIds") List<Long> letterIds,@Param("status") Integer status,@Param("orgId") Long orgId);
 
+    Page<CoreIntroduceLetterOutInRequestVo> selectWebOutInRequestPageList(@Param("page") Page<CoreIntroduceLetterOutInRequestVo> page, @Param("request") CoreOutInRequestDto requestDto);
+
+    List<CoreIntroduceLetterOutInRequestExcelVo> selectWebOutInRequestExportList(@Param("request") CoreOutInRequestDto requestDto);
+
 }

+ 3 - 5
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/mapper/CoreOutInRecordMapper.java

@@ -3,9 +3,7 @@ package com.xunmei.core.letter.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.xunmei.common.core.domain.letter.domain.CoreOutInRecord;
-import com.xunmei.common.core.domain.letter.dto.CoreIntroduceLetterRequestDto;
-import com.xunmei.common.core.domain.letter.dto.CoreOutInRecordRequestDto;
-import com.xunmei.common.core.domain.letter.vo.CoreIntroduceLetterVo;
+import com.xunmei.common.core.domain.letter.dto.CoreOutInRequestDto;
 import com.xunmei.common.core.domain.letter.vo.CoreOutInRecordVo;
 import org.apache.ibatis.annotations.Param;
 
@@ -34,9 +32,9 @@ public interface CoreOutInRecordMapper extends BaseMapper<CoreOutInRecord> {
      */
 //    List<CoreOutInRecord> selectCoreOutInRecordPageList(CoreOutInRecord coreOutInRecord);
 
-    Page<CoreOutInRecordVo> selectCoreOutInRecordPageList(@Param("page") Page<CoreOutInRecordVo> page, @Param("request") CoreOutInRecordRequestDto coreOutInRecord);
+    Page<CoreOutInRecordVo> selectCoreOutInRecordPageList(@Param("page") Page<CoreOutInRecordVo> page, @Param("request") CoreOutInRequestDto coreOutInRecord);
 
-    List<CoreOutInRecordVo> selectRecordList(@Param("request") CoreOutInRecordRequestDto request);
+    List<CoreOutInRecordVo> selectRecordList(@Param("request") CoreOutInRequestDto request);
 
     /**
      * 新增人员出入登记

+ 5 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/ICoreIntroduceLetterService.java

@@ -1,6 +1,7 @@
 package com.xunmei.core.letter.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.xunmei.common.core.domain.edu.dto.CoreEduTrainingTaskReportDto;
 import com.xunmei.common.core.domain.letter.domain.CoreIntroduceLetter;
 import com.xunmei.common.core.domain.letter.domain.CoreIntroduceLetterOutInRequest;
 import com.xunmei.common.core.domain.letter.dto.*;
@@ -10,6 +11,7 @@ import com.xunmei.common.core.domain.panel.vo.PanelListVo;
 import com.xunmei.common.core.domain.panel.vo.WebPanelResult;
 import com.xunmei.common.core.web.page.TableDataInfo;
 
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -87,6 +89,9 @@ public interface ICoreIntroduceLetterService extends IService<CoreIntroduceLette
 
     TableDataInfo<CoreIntroduceLetterOutInRequestVo> selectOntInRequestListPage(CoreIntroduceLetterApproveRequestDto requestDto);
 
+    TableDataInfo<CoreIntroduceLetterOutInRequestVo> selectWebOntInRequestListPage(CoreOutInRequestDto requestDto);
+    void webExportOntInRequestExcel(CoreOutInRequestDto requestDto, HttpServletResponse response);
+
     List<CoreIntroduceLetterCheckLogVo> auditAllList(Long id);
 
     List<CoreIntroduceLetterApprovedPersonVo> getOutInApprovedPersonList(CoreIntroduceLetterApproveRequestDto requestDto);

+ 3 - 3
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/ICoreOutInRecordService.java

@@ -2,7 +2,7 @@ package com.xunmei.core.letter.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.xunmei.common.core.domain.letter.domain.CoreOutInRecord;
-import com.xunmei.common.core.domain.letter.dto.CoreOutInRecordRequestDto;
+import com.xunmei.common.core.domain.letter.dto.CoreOutInRequestDto;
 import com.xunmei.common.core.domain.letter.vo.CoreOutInRecordVo;
 import com.xunmei.common.core.web.domain.AjaxResult;
 import com.xunmei.common.core.web.page.TableDataInfo;
@@ -70,9 +70,9 @@ public interface ICoreOutInRecordService extends IService<CoreOutInRecord> {
      * @param coreOutInRecord 查询条件对象
      * @return Page
      */
-    TableDataInfo<CoreOutInRecordVo> selectPage(CoreOutInRecordRequestDto coreOutInRecord);
+    TableDataInfo<CoreOutInRecordVo> selectPage(CoreOutInRequestDto coreOutInRecord);
 
     AjaxResult buildOutInRecordPdf(Long id);
 
-    int batchReBuildPdf(CoreOutInRecordRequestDto requestDto);
+    int batchReBuildPdf(CoreOutInRequestDto requestDto);
 }

+ 195 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/impl/CoreIntroduceLetterServiceImpl.java

@@ -2,6 +2,8 @@ package com.xunmei.core.letter.service.impl;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
 import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -13,6 +15,7 @@ import com.xunmei.common.core.constant.CacheConstants;
 import com.xunmei.common.core.constant.DictConstants;
 import com.xunmei.common.core.constant.ErrorMsgConstants;
 import com.xunmei.common.core.constant.SecurityConstants;
+import com.xunmei.common.core.domain.edu.vo.CoreEduTrainingTaskReportVo;
 import com.xunmei.common.core.domain.letter.domain.*;
 import com.xunmei.common.core.domain.letter.dto.*;
 import com.xunmei.common.core.domain.letter.vo.*;
@@ -21,12 +24,18 @@ import com.xunmei.common.core.domain.panel.enums.PanelTypeEnums;
 import com.xunmei.common.core.domain.panel.vo.PanelListVo;
 import com.xunmei.common.core.domain.panel.vo.WebPanelResult;
 import com.xunmei.common.core.enums.OrgTypeEnum;
+import com.xunmei.common.core.exception.SystemException;
 import com.xunmei.common.core.util.BeanHelper;
 import com.xunmei.common.core.utils.DateUtils;
+import com.xunmei.common.core.utils.StringUtils;
 import com.xunmei.common.core.web.page.TableDataInfo;
 import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.common.security.utils.DictUtils;
 import com.xunmei.common.security.utils.SecurityUtils;
+import com.xunmei.core.edu.service.impl.ValueCellWriteHandler;
+import com.xunmei.core.letter.export.CoreIntroduceLetterOutInRequestExcelVo;
+import com.xunmei.core.letter.export.IntroduceLetterOutInRequestMergeHandler;
+import com.xunmei.core.letter.export.MultiImageWriteHandler;
 import com.xunmei.core.letter.mapper.CoreIntroduceLetterOutInRequestMapper;
 import com.xunmei.core.letter.mapper.CoreIntroduceLetterMapper;
 import com.xunmei.core.letter.mapper.CoreIntroduceLetterOutInRequestUserMapper;
@@ -34,6 +43,7 @@ import com.xunmei.core.letter.mapper.CoreOutInRecordMapper;
 import com.xunmei.core.letter.service.ICoreIntroduceLetterOutInHistoryUserService;
 import com.xunmei.core.letter.service.ICoreIntroduceLetterOutInRequestUserService;
 import com.xunmei.core.letter.service.ICoreIntroduceLetterService;
+import com.xunmei.system.api.RemoteFileService;
 import com.xunmei.system.api.RemoteOrgService;
 import com.xunmei.system.api.RemoteRoleService;
 import com.xunmei.system.api.RemoteUserService;
@@ -48,6 +58,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URLEncoder;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -82,6 +94,9 @@ public class CoreIntroduceLetterServiceImpl extends ServiceImpl<CoreIntroduceLet
     private RemoteRoleService roleService;
     @Autowired
     private RemoteUserService userService;
+
+    @Resource
+    private RemoteFileService fileService;
     @Resource
     private RemoteOrgService orgService;
 
@@ -227,6 +242,168 @@ public class CoreIntroduceLetterServiceImpl extends ServiceImpl<CoreIntroduceLet
     }
 
     @Override
+    public TableDataInfo<CoreIntroduceLetterOutInRequestVo> selectWebOntInRequestListPage(CoreOutInRequestDto requestDto) {
+        Page<CoreIntroduceLetterOutInRequestVo> page;
+        //分页
+        if (requestDto.getPageNum() != null && requestDto.getPageSize() != null) {
+            page = new Page<>(requestDto.getPageNum(), requestDto.getPageSize());
+        } else {
+            page = new Page<>();
+        }
+        if (ObjectUtil.isNotEmpty(requestDto.getRange())) {
+            requestDto.setStartTime(DateUtil.beginOfDay(requestDto.getRange()[0]));
+            requestDto.setEndTime(DateUtil.endOfDay(requestDto.getRange()[1]));
+        }
+        if (Boolean.TRUE.equals(requestDto.getCheckSub())) {
+            SysOrg org = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.selectOrgById(requestDto.getOrgId(), SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
+            requestDto.setOrgPath(org.getPath());
+        }
+        //获取数据
+        page = coreIntroduceLetterMapper.selectWebOutInRequestPageList(page, requestDto);
+
+        if (CollectionUtils.isNotEmpty(page.getRecords())) {
+            //获取人员信息
+            final LambdaQueryWrapper<CoreIntroduceLetterOutInRequestUser> oqw = new LambdaQueryWrapper<CoreIntroduceLetterOutInRequestUser>();
+            oqw.in(CoreIntroduceLetterOutInRequestUser::getOutInRequestId, page.getRecords().stream().map(x->x.getId()).collect(Collectors.toList()));
+            List<CoreIntroduceLetterOutInRequestUser> userList =  outInRequestUserMapper.selectList(oqw);
+            Map<Long, List<CoreIntroduceLetterOutInRequestUser>> userListMap = userList.stream().collect(Collectors.groupingBy(CoreIntroduceLetterOutInRequestUser::getOutInRequestId));
+
+
+            page.getRecords().stream().forEach(vo -> {
+                vo.setLetterFile(ObjectUtil.isNotEmpty(vo.getLetterFileStr()) ? JSON.parseArray(vo.getLetterFileStr(), String.class) : null);
+
+                if (CollectionUtils.isNotEmpty(userListMap) && userListMap.containsKey(vo.getId())) {
+                    vo.setUserInfos(userListMap.get(vo.getId()));
+
+                    List<String> names = userListMap.get(vo.getId()).stream().map(CoreIntroduceLetterOutInRequestUser::getUserName).filter(name -> name != null && !name.trim().isEmpty()).collect(Collectors.toList());
+                    if(names.size()>0)
+                    {
+                        if(names.size() ==vo.getUserInfos().size())
+                        {
+                            vo.setUserNames(names.stream().collect(Collectors.joining(",")));
+                        }
+                        else if  (names.size()>0 && names.size()<vo.getUserInfos().size()){
+                            vo.setUserNames(names.stream().collect(Collectors.joining(",")) + " 等"+vo.getUserInfos().size()+"人");
+                        }
+                    }
+                    else
+                    {
+                        vo.setUserNames("待登记后显示");
+                    }
+                }
+            });
+        }
+
+        //抓换为TableDataInfo适配前端
+        return TableDataInfo.build(page);
+    }
+
+    @Override
+    public void webExportOntInRequestExcel(CoreOutInRequestDto requestDto, HttpServletResponse response) {
+        if (ObjectUtil.isNotEmpty(requestDto.getRange())) {
+            requestDto.setStartTime(DateUtil.beginOfDay(requestDto.getRange()[0]));
+            requestDto.setEndTime(DateUtil.endOfDay(requestDto.getRange()[1]));
+        }
+        if (Boolean.TRUE.equals(requestDto.getCheckSub())) {
+            SysOrg org = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.selectOrgById(requestDto.getOrgId(), SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
+            requestDto.setOrgPath(org.getPath());
+        }
+        final List<CoreIntroduceLetterOutInRequestExcelVo> list = coreIntroduceLetterMapper.selectWebOutInRequestExportList(requestDto);
+        if (ObjectUtil.isEmpty(list)) {
+            throw new SystemException("未获取到数据");
+        }
+        String prefixPath = RemoteCallHandlerExecutor.executeRemoteCall(() -> fileService.getLocalPathPrefix(), ErrorMsgConstants.QUERY_FILE_PATH_ERROR).getData();
+        String staticsPath = RemoteCallHandlerExecutor.executeRemoteCall(() -> fileService.getStaticPathPrefix(), ErrorMsgConstants.QUERY_FILE_PATH_ERROR).getData();
+
+
+        for (int i = 0; i < list.size(); i++) {
+            CoreIntroduceLetterOutInRequestExcelVo outInRequestVo = list.get(i);
+
+            outInRequestVo.setNo(i + 1);
+            // 处理签名图片
+//            if (ObjectUtil.isNotEmpty(outInRequestVo.getCheckSign())) {
+//                outInRequestVo.setCheckSign(getFileRealPath(outInRequestVo.getCheckSign(), prefixPath, staticsPath));
+//            }
+//            // 处理签名图片
+//            if (ObjectUtil.isNotEmpty(outInRequestVo.getApproveSignImg())) {
+//                outInRequestVo.setApproveSignImg(getFileRealPath(outInRequestVo.getApproveSignImg(), prefixPath, staticsPath));
+//            }
+            // 处理证件照片(逗号分隔)
+            if (ObjectUtil.isNotEmpty(outInRequestVo.getImgFileStr())) {
+                outInRequestVo.setImgFileList(getFileRealPath(Arrays.asList(outInRequestVo.getImgFileStr().split(",")), prefixPath, staticsPath));
+            }
+            // 处理介绍信文件(JSON 数组)
+            if (ObjectUtil.isNotEmpty(outInRequestVo.getLetterFileStr())) {
+
+                final List<String> letterFileList = JSON.parseArray(outInRequestVo.getLetterFileStr(), String.class);
+                List<String> strings = new ArrayList<>();
+                for (String json : letterFileList) {
+                    final Map map = JSON.parseObject(json, Map.class);
+                    final String url = (String) map.get("imgPath");
+                    if (ObjectUtil.isNotEmpty(url)) {
+                        strings.add(url);
+                    } else {
+                        strings.add((String) map.get("url"));
+                    }
+                }
+                outInRequestVo.setLetterFile(getFileRealPath(strings, prefixPath, staticsPath));
+            }
+
+        }
+        try {
+            String baseHeaderName = "出入情况表";
+            // 设置响应头
+            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(baseHeaderName, "utf-8"));
+            response.setContentType("application/octet-stream;charset=UTF-8");
+            response.setCharacterEncoding("utf-8");
+
+            String header = baseHeaderName + "(" + DateUtil.format(requestDto.getStartTime(), "yyyy-MM-dd") + "至" + DateUtil.format(requestDto.getEndTime(), "yyyy-MM-dd") + ")";
+            // 数据导出
+            EasyExcel.write(response.getOutputStream(), CoreIntroduceLetterOutInRequestExcelVo.class)
+                    .registerWriteHandler(new IntroduceLetterOutInRequestMergeHandler(list)) // 注册合并处理器
+                    .registerWriteHandler(new MultiImageWriteHandler(0,"checkSign","checkSign",list)) // 注册图片处理器
+
+                    .registerWriteHandler(new ValueCellWriteHandler(header))
+                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                    .sheet(baseHeaderName).doWrite(list);
+        } catch (Exception e) {
+            // 重置response
+            response.reset();
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+        }
+    }
+
+    private List<String> getFileRealPath(List<String> fileList, String prefixPath, String staticsPath) {
+        List<String> list = new ArrayList<>();
+        if (ObjectUtil.isEmpty(fileList)) {
+            return list;
+        }
+        for (String path : fileList) {
+            if (path.contains(staticsPath)) {
+                //删除 /statics 前缀路径
+                path = path.replace(staticsPath, StringUtil.EMPTY_STRING);
+            }
+            list.add(prefixPath + path);
+        }
+        return list;
+    }
+
+    private String getFileRealPath(String file, String prefixPath, String staticsPath) {
+
+        if (ObjectUtil.isEmpty(file)) {
+            return StringUtil.EMPTY_STRING;
+        }
+
+        if (file.contains(staticsPath)) {
+            //删除 /statics 前缀路径
+            file = file.replace(staticsPath, StringUtil.EMPTY_STRING);
+        }
+        return prefixPath + file;
+
+    }
+
+    @Override
     public List<CoreIntroduceLetterCheckLogVo> auditAllList(Long id) {
         return coreIntroduceLetterMapper.auditAllList(id);
     }
@@ -547,9 +724,27 @@ public class CoreIntroduceLetterServiceImpl extends ServiceImpl<CoreIntroduceLet
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateCoreIntroduceLetterStatus(CoreIntroduceLetterUpdateStatusDto letterDto) {
         CoreIntroduceLetter coreIntroduceLetter = coreIntroduceLetterMapper.selectById(letterDto.getId());
         coreIntroduceLetter.setStatus(letterDto.getStatus());
+        //下发时 出入人员进入 创建机构历史人员库
+        if (ObjectUtil.equal(letterDto.getStatus(), 1)) {
+
+            CoreIntroduceLetterInfoVo coreIntroduceLetterVo = coreIntroduceLetterMapper.selectOneById(letterDto.getId());
+            List<CoreIntroduceLetterInfoVo> list = new ArrayList<>();
+            list.add(coreIntroduceLetterVo);
+            List<CoreIntroduceLetterUserAddDto> letterUserList = coreIntroduceLetterMapper.findUserList(list);
+
+            letterUserList =letterUserList.stream().filter(item ->
+                    ObjectUtil.isNotEmpty(item.getUserName())
+                    && ObjectUtil.isNotEmpty(item.getCompanyName())
+                    && ObjectUtil.isNotEmpty(item.getIdCard())
+            ).collect(Collectors.toList());
+
+            //进入 历史人员库
+            outInHistoryUserService.batchInboundOutInHistory(letterUserList,coreIntroduceLetter.getOrgId(),null);
+        }
         coreIntroduceLetterMapper.updateById(coreIntroduceLetter);
     }
 

+ 3 - 3
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/letter/service/impl/CoreOutInRecordServiceImpl.java

@@ -17,7 +17,7 @@ import com.xunmei.common.core.domain.R;
 import com.xunmei.common.core.domain.letter.domain.CoreIntroduceLetterOutInRequest;
 import com.xunmei.common.core.domain.letter.domain.CoreIntroduceLetterOutInRequestUser;
 import com.xunmei.common.core.domain.letter.domain.CoreOutInRecord;
-import com.xunmei.common.core.domain.letter.dto.CoreOutInRecordRequestDto;
+import com.xunmei.common.core.domain.letter.dto.CoreOutInRequestDto;
 import com.xunmei.common.core.domain.letter.vo.CoreOutInRecordVo;
 import com.xunmei.common.core.domain.registerbook.domain.CoreRegisterBookPdf;
 import com.xunmei.common.core.enums.RegisterBookType;
@@ -86,7 +86,7 @@ public class CoreOutInRecordServiceImpl extends ServiceImpl<CoreOutInRecordMappe
     private ThreadPoolTaskExecutor threadPoolTaskExecutor;
 
     @Override
-    public TableDataInfo<CoreOutInRecordVo> selectPage(CoreOutInRecordRequestDto request) {
+    public TableDataInfo<CoreOutInRecordVo> selectPage(CoreOutInRequestDto request) {
         //未删除
         Page<CoreOutInRecordVo> page;
         //分页
@@ -277,7 +277,7 @@ public class CoreOutInRecordServiceImpl extends ServiceImpl<CoreOutInRecordMappe
     }
 
     @Override
-    public int batchReBuildPdf(CoreOutInRecordRequestDto requestDto) {
+    public int batchReBuildPdf(CoreOutInRequestDto requestDto) {
         final List<CoreOutInRecordVo> coreOutInRecordVos = coreOutInRecordMapper.selectRecordList(requestDto);
         if(ObjectUtil.isNotEmpty(coreOutInRecordVos))
         {

+ 114 - 1
soc-modules/soc-modules-core/src/main/resources/mapper/letter/CoreIntroduceLetterMapper.xml

@@ -515,7 +515,13 @@
     </insert>
 
     <select id="selectOneOutInRequestById" resultType="com.xunmei.common.core.domain.letter.vo.CoreIntroduceLetterOutInRequestVo">
-        select a.*,a.letter_file as letterFileStr from core_introduce_letter_out_in_request a where a.id =#{id}
+        select a.*,
+               a.letter_file as letterFileStr,
+               o.short_name as orgName
+        from
+            core_introduce_letter_out_in_request a
+            INNER JOIN sys_org o ON a.org_id=o.id
+        where a.id =#{id}
     </select>
 
     <resultMap id="OutInRequestResultMap" type="com.xunmei.common.core.domain.letter.vo.CoreIntroduceLetterOutInRequestVo">
@@ -567,4 +573,111 @@
         ) s INNER JOIN core_introduce_letter_out_in_request_user u ON s.id = u.out_in_request_id
         ORDER BY r.create_time DESC;
     </select>
+
+    <select id="selectWebOutInRequestPageList" resultType="com.xunmei.common.core.domain.letter.vo.CoreIntroduceLetterOutInRequestVo">
+        SELECT
+        DISTINCT
+        l.*,
+        l.letter_file as letterFileStr,
+        o.short_name as orgName,
+        o.affiliated_area,
+        o.affiliated_bank
+        FROM
+        core_introduce_letter_out_in_request l
+        INNER JOIN sys_org o ON l.org_id=o.id
+        INNER JOIN core_introduce_letter_out_in_request_user u ON l.id = u.out_in_request_id
+        <where>
+            <choose>
+                <when test="request.checkSub==true">
+                    o.path like concat(#{request.orgPath}, '%')
+                </when>
+                <otherwise>
+                    l.org_id = #{request.orgId}
+                </otherwise>
+            </choose>
+            <if test="request.userName != null  and request.userName != ''">
+                and (u.user_name like concat('%', #{request.userName}, '%')  OR u.id_card like concat('%', #{request.userName}, '%'))
+            </if>
+            <if test="request.companyName != null  and request.companyName != ''">
+                and u.company_name like concat('%', #{request.companyName}, '%')
+            </if>
+            <if test="request.startTime != null and request.endTime != null">
+<!--                and (-->
+<!--                (-->
+<!--                #{request.startTime}   <![CDATA[<=]]> u.arrival_time-->
+<!--                and #{request.endTime}     <![CDATA[>=]]> u.arrival_time-->
+<!--                )-->
+<!--                or-->
+<!--                (-->
+<!--                #{request.startTime}   <![CDATA[<=]]> u.departure_time-->
+<!--                and #{request.endTime}     <![CDATA[>=]]> u.departure_time-->
+<!--                )-->
+<!--                or (-->
+<!--                #{request.startTime}   <![CDATA[>=]]> u.arrival_time-->
+<!--                and #{request.endTime}     <![CDATA[<=]]> u.departure_time-->
+<!--                )-->
+<!--                )-->
+                and #{request.startTime}   <![CDATA[<=]]> u.create_time
+                and #{request.endTime}     <![CDATA[>=]]> u.create_time
+                </if>
+                <if test="request.type != null  and request.type != ''">
+                    and l.letter_type = #{request.type}
+                </if>
+                <if test="request.status != null">
+                    and l.status = #{request.status}
+                </if>
+
+            </where>
+            order by l.create_time DESC
+    </select>
+
+    <select id="selectWebOutInRequestExportList" resultType="com.xunmei.core.letter.export.CoreIntroduceLetterOutInRequestExcelVo">
+        SELECT
+        l.*,
+        l.id as outInRequestId,
+        l.letter_file as letterFileStr,
+        o.short_name as orgName,
+        o.affiliated_area,
+        o.affiliated_bank,
+        u.user_name,
+        u.company_name,
+        u.id_card,
+        u.id_type,
+        u.img_file AS imgFileStr,
+        u.arrival_time,
+        u.departure_time
+        FROM
+        core_introduce_letter_out_in_request l
+        INNER JOIN sys_org o ON l.org_id=o.id
+        INNER JOIN core_introduce_letter_out_in_request_user u ON l.id = u.out_in_request_id
+        <where>
+            <choose>
+                <when test="request.checkSub==true">
+                    o.path like concat(#{request.orgPath}, '%')
+                </when>
+                <otherwise>
+                    l.org_id = #{request.orgId}
+                </otherwise>
+            </choose>
+            <if test="request.userName != null  and request.userName != ''">
+                and (u.user_name like concat('%', #{request.userName}, '%')  OR u.id_card like concat('%', #{request.userName}, '%'))
+            </if>
+            <if test="request.companyName != null  and request.companyName != ''">
+                and u.company_name like concat('%', #{request.companyName}, '%')
+            </if>
+            <if test="request.startTime != null and request.endTime != null">
+                and #{request.startTime}   <![CDATA[<=]]> u.create_time
+                and #{request.endTime}     <![CDATA[>=]]> u.create_time
+            </if>
+            <if test="request.type != null  and request.type != ''">
+                and l.letter_type = #{request.type}
+            </if>
+            <if test="request.status != null">
+                and l.status = #{request.status}
+            </if>
+
+        </where>
+        order by l.create_time DESC,u.arrival_time DESC
+    </select>
+
 </mapper>

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio