车车 3 месяцев назад
Родитель
Сommit
d265101e32

+ 21 - 11
yudao-module-iscs/src/main/java/cn/iocoder/yudao/module/iscs/controller/admin/workflow/WorkflowModeController.java

@@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.iscs.controller.admin.workflow;
 
 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModePageReqVO;
 import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModeRespVO;
 import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModeSaveReqVO;
 import cn.iocoder.yudao.module.iscs.service.workflow.WorkflowModeService;
+import cn.iocoder.yudao.module.iscs.service.workflow.WorkflowStepService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -20,7 +19,14 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.IOException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.FileNotFoundException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@@ -34,6 +40,8 @@ public class WorkflowModeController {
 
     @Resource
     private WorkflowModeService workflowModeService;
+    @Resource
+    private WorkflowStepService workflowStepService;
 
     @PostMapping("/insertWorkflowMode")
     @Operation(summary = "创建工作流模式")
@@ -76,16 +84,18 @@ public class WorkflowModeController {
         return success(BeanUtils.toBean(pageResult, WorkflowModeRespVO.class));
     }
 
-    @GetMapping("/exportWorkflowModeExcel")
-    @Operation(summary = "导出工作流模式 Excel")
+    @GetMapping("/exportWorkflowMode")
+    @Operation(summary = "导出工作流模式")
     @PreAuthorize("@ss.hasPermission('iscs:workflow-mode:export')")
     @ApiAccessLog(operateType = EXPORT)
-    public void exportWorkflowModeExcel(@Valid WorkflowModePageReqVO pageReqVO,
-              HttpServletResponse response) throws IOException {
-        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<WorkflowModeRespVO> list = workflowModeService.getWorkflowModePage(pageReqVO).getList();
-        // 导出 Excel
-        ExcelUtils.write(response, "工作流模式.xls", "数据", WorkflowModeRespVO.class, list);
+    public void exportWorkflowMode(
+              HttpServletResponse response) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, FileNotFoundException {
+        ArrayList<Long> objects = new ArrayList<>();
+        objects.add(1L);
+        objects.add(2L);
+        workflowModeService.exportWorkflowMode(response, objects);
+
+
     }
 
 }

+ 36 - 0
yudao-module-iscs/src/main/java/cn/iocoder/yudao/module/iscs/controller/admin/workflow/vo/WorkflowModeExportVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 工作流模式分页 Request VO")
+@Data
+public class WorkflowModeExportVO {
+
+    @Schema(description = "id")
+    private Long id;
+
+    @Schema(description = "编码")
+    private String modeCode;
+
+    @Schema(description = "是否预置")
+    private Boolean isPreset;
+
+    @Schema(description = "名称", example = "李四")
+    private String modeName;
+
+    @Schema(description = "标题")
+    private String modeTitle;
+
+    @Schema(description = "描述信息", example = "你猜")
+    private String modeDescription;
+
+    @Schema(description = "是否支持共锁")
+    private Boolean isColockSupport;
+
+    @Schema(description = "模式详细步骤")
+    private List<WorkflowStepExportVO> stepList;
+
+}

+ 110 - 0
yudao-module-iscs/src/main/java/cn/iocoder/yudao/module/iscs/controller/admin/workflow/vo/WorkflowStepExportVO.java

@@ -0,0 +1,110 @@
+package cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 工作流步骤 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class WorkflowStepExportVO {
+
+    @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1064")
+    @ExcelProperty("ID")
+    private Long Id;
+
+    @Schema(description = "工作流模式ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31144")
+    @ExcelProperty("工作流模式ID")
+    private Long modeId;
+
+    @Schema(description = "步骤模版ID", example = "4626")
+    @ExcelProperty("步骤模版ID")
+    private Long stepTemplateId;
+
+    @Schema(description = "步骤序号", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("步骤序号")
+    private Integer stepIndex;
+
+    @Schema(description = "名称", example = "赵六")
+    @ExcelProperty("名称")
+    private String stepName;
+
+    @Schema(description = "图标", example = "HTTP://1212131")
+    private String stepIcon;
+
+    @Schema(description = "标题")
+    @ExcelProperty("标题")
+    private String stepTitle;
+
+    @Schema(description = "短标题")
+    @ExcelProperty("短标题")
+    private String stepTitleShort;
+
+    @Schema(description = "描述信息", example = "你说的对")
+    @ExcelProperty("描述信息")
+    private String stepDescription;
+
+    @Schema(description = "是否自动执行", example = "1")
+    @ExcelProperty("是否自动执行")
+    private Integer confirmType;
+
+    @Schema(description = "确认角色编码")
+    @ExcelProperty("确认角色编码")
+    private String confirmRoleCode;
+
+    @Schema(description = "确认人员")
+    @ExcelProperty("确认人员")
+    private Long confirmUser;
+
+    @Schema(description = "开启取消作业")
+    @ExcelProperty("开启取消作业")
+    private Boolean enableCancelJob;
+
+    @Schema(description = "开启设置锁定人")
+    @ExcelProperty("开启设置锁定人")
+    private Boolean enableSetLocker;
+
+    @Schema(description = "开启设置共锁人")
+    @ExcelProperty("开启设置共锁人")
+    private Boolean enableSetColocker;
+
+    @Schema(description = "开启添加共锁人")
+    @ExcelProperty("开启添加共锁人")
+    private Boolean enableAddColocker;
+
+    @Schema(description = "添加共锁人后跳转步骤")
+    @ExcelProperty("添加共锁人后跳转步骤")
+    private Integer gotoStepAfterAddingColocker;
+
+    @Schema(description = "开启减少共锁人")
+    @ExcelProperty("开启减少共锁人")
+    private Boolean enableReduceColocker;
+
+    @Schema(description = "开启上锁")
+    @ExcelProperty("开启上锁")
+    private Boolean enableLock;
+
+    @Schema(description = "开启共锁")
+    @ExcelProperty("开启共锁")
+    private Boolean enableColock;
+
+    @Schema(description = "开启解除共锁")
+    @ExcelProperty("开启解除共锁")
+    private Boolean enableReleaseColock;
+
+    @Schema(description = "开启解锁")
+    @ExcelProperty("开启解锁")
+    private Boolean enableUnlock;
+
+    @Schema(description = "开启结束作业")
+    @ExcelProperty("开启结束作业")
+    private Boolean enableEndJob;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 11 - 0
yudao-module-iscs/src/main/java/cn/iocoder/yudao/module/iscs/service/workflow/WorkflowModeService.java

@@ -6,8 +6,16 @@ import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModeRes
 import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModeSaveReqVO;
 import cn.iocoder.yudao.module.iscs.dal.dataobject.workflow.WorkflowModeDO;
 import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.Valid;
 
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.FileNotFoundException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
 import java.util.List;
 
 /**
@@ -62,4 +70,7 @@ public interface WorkflowModeService extends IService<WorkflowModeDO> {
      */
     PageResult<WorkflowModeRespVO> getWorkflowModePage(WorkflowModePageReqVO pageReqVO);
 
+    void exportWorkflowMode(HttpServletResponse response, List<Long> ids) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, FileNotFoundException;
+
+
 }

+ 123 - 5
yudao-module-iscs/src/main/java/cn/iocoder/yudao/module/iscs/service/workflow/WorkflowModeServiceImpl.java

@@ -2,28 +2,37 @@ package cn.iocoder.yudao.module.iscs.service.workflow;
 
 import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
+import cn.iocoder.yudao.framework.common.util.io.FileDriveLetterUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModePageReqVO;
-import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModeRespVO;
-import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowModeSaveReqVO;
-import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.WorkflowStepRespVO;
+import cn.iocoder.yudao.module.iscs.controller.admin.workflow.vo.*;
 import cn.iocoder.yudao.module.iscs.dal.dataobject.workflow.WorkflowModeDO;
 import cn.iocoder.yudao.module.iscs.dal.dataobject.workflow.WorkflowStepDO;
 import cn.iocoder.yudao.module.iscs.dal.mysql.workflow.WorkflowModeMapper;
+import cn.iocoder.yudao.module.iscs.utils.AES256Utils;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.*;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
-
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 /**
  * 工作流模式 Service 实现类
  *
@@ -135,4 +144,113 @@ public class WorkflowModeServiceImpl extends ServiceImpl<WorkflowModeMapper, Wor
         return bean;
     }
 
+    @Override
+    public void exportWorkflowMode(HttpServletResponse response, List<Long> ids) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
+        Assert.isFalse(ids.isEmpty(), "导出的数据不可为空!");
+        // 开始查询数据
+        List<WorkflowModeDO> workflowModeDOS = listByIds(ids);
+        List<WorkflowStepDO> stepDOList = workflowStepService.list(Wrappers.<WorkflowStepDO>lambdaQuery()
+                .in(WorkflowStepDO::getModeId, ids));
+        // 开始构建数据
+        List<WorkflowModeExportVO> modeExportVOS = BeanUtils.toBean(workflowModeDOS, WorkflowModeExportVO.class);
+        for (WorkflowModeExportVO modeExportVO : modeExportVOS) {
+            List<WorkflowStepDO> list = stepDOList.stream().filter(o -> o.getModeId().equals(modeExportVO.getId())).toList();
+            List<WorkflowStepExportVO> stepExportVOS = BeanUtils.toBean(list, WorkflowStepExportVO.class);
+            modeExportVO.setStepList(stepExportVOS);
+        }
+        // 开始加密
+        String s = AES256Utils.AES256DECRYPT(modeExportVOS.toString());
+        // 时间戳
+        long currentTimestamp = System.currentTimeMillis();
+        // 开始写入dat文件
+        String url = getPath() + currentTimestamp + ".dat";
+        try (FileOutputStream fos = new FileOutputStream(url)) {
+            fos.write(s.getBytes()); // 写入字节数组
+            System.out.println("数据已成功写入" + currentTimestamp + ".dat");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        // 开始写入.sha文件
+        String url1 = getPath() + currentTimestamp + ".sha";
+        try (FileOutputStream fos = new FileOutputStream(url1)) {
+            fos.write(s.getBytes()); // 写入字节数组
+            System.out.println("数据已成功写入" + currentTimestamp + ".sha");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        // 开始压缩
+        List<String> filesToZip = List.of(url, url1);
+        String outputZip = getPath() + currentTimestamp + ".zip";
+
+        try {
+            zipFiles(filesToZip, outputZip);
+            System.out.println("成功创建ZIP文件:" + outputZip);
+        } catch (IOException e) {
+            System.err.println("创建ZIP文件失败!");
+            e.printStackTrace();
+        }
+
+        // 2. 设置 HTTP 响应头
+        response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(currentTimestamp + ".zip"));
+        response.setContentType("application/zip");
+    }
+
+
+    private String getPath() {
+        // D:
+        String driveLetter = FileDriveLetterUtils.getDriveLetter();
+        // 获取临时文件地址
+        String path = driveLetter + "/home/flow/temp/";
+        return path;
+    }
+
+    /**
+     * 将多个文件压缩到指定的ZIP文件中
+     *
+     * @param filePaths   待压缩的文件路径列表
+     * @param zipFilePath 目标ZIP文件路径
+     * @throws IOException 如果发生I/O错误
+     */
+    public static void zipFiles(List<String> filePaths, String zipFilePath) throws IOException {
+        // 创建ZIP输出流
+        try (FileOutputStream fos = new FileOutputStream(zipFilePath);
+             ZipOutputStream zos = new ZipOutputStream(fos)) {
+
+            for (String filePath : filePaths) {
+                File file = new File(filePath);
+                if (!file.exists() || !file.isFile()) {
+                    System.out.println("警告:文件 " + filePath + " 不存在或不是文件,已跳过");
+                    continue;
+                }
+
+                // 添加文件到ZIP
+                try (FileInputStream fis = new FileInputStream(file);
+                     BufferedInputStream bis = new BufferedInputStream(fis)) {
+
+                    // 创建ZIP条目(保留文件名)
+                    ZipEntry zipEntry = new ZipEntry(file.getName());
+                    zos.putNextEntry(zipEntry);
+
+                    // 设置压缩级别(可选)
+                    zipEntry.setMethod(ZipEntry.DEFLATED); // 默认压缩方式
+
+                    // 写入文件数据
+                    byte[] buffer = new byte[4096];
+                    int bytesRead;
+                    while ((bytesRead = bis.read(buffer)) != -1) {
+                        zos.write(buffer, 0, bytesRead);
+                    }
+
+                    // 关闭当前ZIP条目
+                    zos.closeEntry();
+                } catch (IOException e) {
+                    System.err.println("错误:无法压缩文件 " + filePath);
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
 }

+ 98 - 0
yudao-module-iscs/src/main/java/cn/iocoder/yudao/module/iscs/utils/AES256Utils.java

@@ -0,0 +1,98 @@
+package cn.iocoder.yudao.module.iscs.utils;
+
+import lombok.val;
+import org.apache.commons.codec.binary.Hex;
+
+import javax.crypto.*;
+import javax.crypto.spec.IvParameterSpec;
+import java.security.*;
+import java.util.Base64;
+
+/**
+ * 时间工具类
+ *
+ * @author ruoyi
+ */
+public class AES256Utils {
+
+    /**
+     * 输入1-7获取包括当日的下一个周几的日期
+     */
+    public static String AES256DECRYPT(String plaintext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
+        // 1. 生成256位密钥(需确保JCE无限制政策已安装)
+        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
+        keyGen.init(128, new SecureRandom()); // 使用安全随机数
+        SecretKey secretKey = keyGen.generateKey();
+
+        // 2. 创建Cipher实例(推荐使用CBC模式+PKCS5Padding)
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+
+        // 3. 初始化向量(IV)
+        byte[] ivBytes = new byte[16];
+        SecureRandom random = new SecureRandom();
+        random.nextBytes(ivBytes);
+        IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+        // 4. 加密过程
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
+        byte[] encrypted = cipher.doFinal(plaintext.getBytes());
+        byte[] data = new byte[16 + encrypted.length];
+        System.arraycopy(ivBytes, 0, data, 0, 16);
+        System.arraycopy(encrypted, 0, data, 16, encrypted.length);
+        String hexStr = Hex.encodeHexString(data);
+        System.out.println("hexStr: " + hexStr);
+        return hexStr;
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        // 1. 生成256位密钥(需确保JCE无限制政策已安装)
+        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
+        keyGen.init(128, new SecureRandom()); // 使用安全随机数
+        SecretKey secretKey = keyGen.generateKey();
+
+        // 2. 创建Cipher实例(推荐使用CBC模式+PKCS5Padding)
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+
+        // 3. 初始化向量(IV)
+        byte[] ivBytes = new byte[16];
+        SecureRandom random = new SecureRandom();
+        random.nextBytes(ivBytes);
+        IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+        // 4. 加密过程
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
+        String plaintext = "Hello, AES-256!";
+        byte[] encrypted = cipher.doFinal(plaintext.getBytes());
+
+        // 5. 解密过程
+        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
+        byte[] decrypted = cipher.doFinal(encrypted);
+
+        // 6. 输出结果
+        System.out.println("Plaintext: " + plaintext);
+        System.out.println("Encrypted (Base64): " + Base64.getEncoder().encodeToString(encrypted));
+        System.out.println("Decrypted: " + new String(decrypted));
+
+        byte[] data = new byte[16 + encrypted.length];
+        System.arraycopy(ivBytes, 0, data, 0, 16);
+        System.arraycopy(encrypted, 0, data, 16, encrypted.length);
+        String hexStr = Hex.encodeHexString(data);
+        System.out.println("hexStr: " + hexStr);
+        // .dat
+
+        byte[] ivdatanew = new byte[16];
+        System.arraycopy(data, 0, ivdatanew, 0, 16);
+        IvParameterSpec ivdata = new IvParameterSpec(ivdatanew);
+        byte[] databyte = new byte[data.length - 16];
+        System.arraycopy(data, 16, databyte, 0, databyte.length);
+        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivdata);
+        byte[] decrypted21 = cipher.doFinal(databyte);
+        System.out.println("Decrypted: " + new String(decrypted21));
+
+        val digest = MessageDigest.getInstance("SHA-256");
+        // String hexStr1 = Hex.encodeHexString(digest.digest(fileBytes));
+        // .sha
+    }
+
+}