feat:添加wps相关代码

This commit is contained in:
aguanleishen
2026-07-28 17:29:45 +08:00
parent b5246d4e58
commit 27b1c5543d
55 changed files with 2499 additions and 1 deletions

View File

@@ -43,7 +43,7 @@ public class Attachment implements Serializable {
* 附件大小(单位:B)
*/
@Schema(description = "附件大小(单位:B)")
private long size;
private Long size;
/**
* objectKey

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springblade</groupId>
<artifactId>blade-service-api</artifactId>
<version>${revision}</version>
</parent>
<artifactId>blade-open-api</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
</project>

View File

@@ -0,0 +1,40 @@
package org.springblade.openapi.common.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
* 分页参数
* @author bfhuange
* @since 2025/4/23
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Schema(description = "分页结果")
public class PageVO<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 查询数据列表
*/
@Schema(description = "查询数据列表")
protected List<T> records = Collections.emptyList();
/**
* 总数
*/
@Schema(description = "总数")
protected long total = 0;
/**
* 总页数
*/
@Schema(description = "总页数")
protected long pages = 0;
}

View File

@@ -0,0 +1,61 @@
package org.springblade.openapi.mk.api;
import org.springblade.core.tool.api.FR;
import org.springblade.openapi.mk.pojo.dto.Api4MKProcessApprovalDTO;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* 给mk回调的api
* @author bfhuange
* @date 2024/9/5
*/
public interface IApi4MK {
String API_PREFIX = "/openApi/mk";
String PROCESS_API_PREFIX = API_PREFIX + "/process";
String PROCESS_FINISH_CALLBACK = PROCESS_API_PREFIX + "/finishCallback";
String PROCESS_APPROVAL_CALLBACK = PROCESS_API_PREFIX + "/approvalCallback";
String PROCESS_REJECT_CALLBACK = PROCESS_API_PREFIX + "/rejectCallback";
String PROCESS_REVOKE_CALLBACK = PROCESS_API_PREFIX + "/revokeCallback";
String PROCESS_COMMON_CALLBACK = PROCESS_API_PREFIX + "/commonCallback";
/**
* 流程通用回调接口
* @param param
* @return
*/
@PostMapping(PROCESS_COMMON_CALLBACK)
FR<Boolean> processCommonCallback(@RequestBody Api4MKProcessApprovalDTO param);
/**
* 流程结束回调接口
* @param param
* @return
*/
@PostMapping(PROCESS_FINISH_CALLBACK)
FR<Boolean> processFinishCallback(@RequestBody Api4MKProcessApprovalDTO param);
/**
* 流程审批同意回调接口
* @param param
* @return
*/
@PostMapping(PROCESS_APPROVAL_CALLBACK)
FR<Boolean> processApprovalCallback(@RequestBody Api4MKProcessApprovalDTO param);
/**
* 流程审批拒绝回调接口
* @param param
* @return
*/
@PostMapping(PROCESS_REJECT_CALLBACK)
FR<Boolean> processRejectCallback(@RequestBody Api4MKProcessApprovalDTO param);
/**
* 流程撤销回调接口
* @param param
* @return
*/
@PostMapping(PROCESS_REVOKE_CALLBACK)
FR<Boolean> processRevokeCallback(@RequestBody Api4MKProcessApprovalDTO param);
}

View File

@@ -0,0 +1,8 @@
package org.springblade.openapi.mk.constant;
/**
* @author bfhuange
* @date 2024/9/12
*/
public class MKConstant {
}

View File

@@ -0,0 +1,81 @@
package org.springblade.openapi.mk.pojo.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* mk审批回调参数
* @author bfhuange
* @date 2024/9/5
*/
@Data
public class Api4MKProcessApprovalDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程实例id
*/
private String processInstanceId;
/**
* 表单实例id
*/
private String formInstanceId;
/**
* 模板id
*/
private String templateId;
/**
* 模板编码template_拼接 ProcessTypeEnum 的值
*/
private String templateCode;
/**
* 流程状态
*/
private String processStatus;
/**
* 申请人登录名
*/
private String applicantLoginName;
//===========================下面5个参数流程结束没有=========================
/**
* 驳回节点id N2 是起草节点
*/
private String rejectNodeId;
/**
* 当前节点id
*/
private String currentNodeId;
/**
* 当前节点编号
*/
private String currentNodeNumber;
/**
* 执行的操作
*/
private String operation;
/**
* 操作名称
*/
private String operationName;
/**
* 审批意见
*/
private String approvalOpinion;
/**
* 操作人登录名
*/
private String operatorLoginName;
//====================非mk回调参数回调接口设置参数===================
/**
* 是否流程已完成非mk回调参数回调接口设置参数
*/
private boolean complete;
/**
* 审批状态非mk回调参数回调接口设置参数
*/
private String approveStatus;
}

View File

@@ -0,0 +1,34 @@
package org.springblade.openapi.mk.pojo.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* mk审批结束回调参数
* @author bfhuange
* @date 2024/9/5
*/
@Data
public class ApiMKProcessFinishDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 流程实例id
*/
private String processInstanceId;
/**
* 表单实例id
*/
private String formInstanceId;
/**
* 模板编码template_拼接 ProcessTypeEnum 的值
*/
private String templateCode;
/**
* 流程状态
*/
private String processStatus;
}

View File

@@ -0,0 +1,40 @@
package org.springblade.openapi.mk.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProcessApprovalDTO implements Serializable {
/**
* 流程实例id
*/
@Schema(description = "流程实例id")
protected String flowInstId;
/**
* 表单实例id
*/
protected String formInstanceId;
/**
* 审批状态
*/
protected String approveStatus;
/**
* 下级审批人
*/
protected String nextApproveUser;
}

View File

@@ -0,0 +1,101 @@
package org.springblade.openapi.mk.pojo.enums;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 流程回调类型
* @author bfhuange
* @since 2024/11/23
*/
@AllArgsConstructor
@Getter
public enum ProcessCallbackType {
/**
* 提交
*/
SUBMIT(ProcessOperationType.DRAFTER_SUBMIT),
/**
* 起草人撤回
*/
RETRACT(ProcessOperationType.DRAFTER_RETRACT),
/**
* 审批通过
*/
PASS(ProcessOperationType.HANDLER_PASS),
/**
* 审批驳回
*/
REJECT(ProcessOperationType.HANDLER_REJECT),
/**
* 废弃(起草人废弃、审批人废弃、超管废弃)
*/
ABANDON(ProcessOperationType.DRAFTER_ABANDON, ProcessOperationType.HANDLER_ABANDON, ProcessOperationType.ADMIN_ABANDON),
/**
* 修改当前处理人(超管修改当前处理人、审批人转办、审批人撤回、特权人前后跳转)
*/
CHANGE_CUR_HANDLER(ProcessOperationType.ADMIN_CHANGE_CUR_HANDLER, ProcessOperationType.HANDLER_TRANSFER, ProcessOperationType.HISTORY_HANDLER_RETRACT, ProcessOperationType.ADMIN_JUMP),
/**
* 流程结束
*/
FINISH(ProcessOperationType.PROCESS_FINISH),
;
/**
* 编码
*/
private final List<String> operationTypes;
ProcessCallbackType(ProcessOperationType... operationTypes) {
if (operationTypes.length == 0) {
throw new RuntimeException("流程操作类型不能为空");
}
this.operationTypes = Stream.of(operationTypes)
.map(ProcessOperationType::getCode)
.toList();
}
ProcessCallbackType(String... operationTypes) {
if (operationTypes.length == 0) {
throw new RuntimeException("流程操作类型不能为空");
}
this.operationTypes = Lists.newArrayList(operationTypes);
}
/**
* 流程操作类型对应的事件
*/
private static final Map<String, ProcessCallbackType> CALLBACK_MAP = initCallbackMap();
/**
* 初始化流程操作类型对应的事件
* @return
*/
private static Map<String, ProcessCallbackType> initCallbackMap() {
return Stream.of(values())
.flatMap(callbackType -> callbackType.getOperationTypes().stream()
.collect(Collectors.toMap(Function.identity(), type -> callbackType))
.entrySet()
.stream()
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {
throw new RuntimeException("流程操作类型不能重复");
}));
}
/**
* 根据流程操作类型,获取对应的回调
* @param operationType
* @return
*/
public static ProcessCallbackType getCallbackType(String operationType) {
return CALLBACK_MAP.get(operationType);
}
}

View File

@@ -0,0 +1,175 @@
package org.springblade.openapi.mk.pojo.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* 流程操作类型枚举
* @author bfhuange
* @since 2024/11/23
*/
@AllArgsConstructor
@Getter
public enum ProcessOperationType {
/**
* 起草人协同
*/
DRAFTER_COOPERATE("drafter_cooperate", "起草人协同"),
/**
* 起草人取消协同
*/
DRAFTER_CANCEL_DRAFT_COOPERATE("drafter_cancelDraftCooperate", "起草人取消协同"),
/**
* 协同接收人-回复协同
*/
HANDLER_REPLY_DRAFT_COOPERATE("handler_replyDraftCooperate", "协同接收人-回复协同"),
/**
* 起草人-提交
*/
DRAFTER_SUBMIT("drafter_submit", "起草人-提交"),
/**
* 起草人-废弃
*/
DRAFTER_ABANDON("drafter_abandon", "起草人-废弃"),
/**
* 起草人-撤回
*/
DRAFTER_RETRACT("drafter_retract", "起草人-撤回"),
/**
* 审批人-通过
*/
HANDLER_PASS("handler_pass", "审批人-通过"),
/**
* 审批人-驳回
*/
HANDLER_REJECT("handler_reject", "审批人-驳回"),
/**
* 审批人-废弃
*/
HANDLER_ABANDON("handler_abandon", "审批人-废弃"),
/**
* 审批人-撤回
*/
HISTORY_HANDLER_RETRACT("historyHandler_retract", "审批人-撤回"),
/**
* 审批人-签字
*/
HANDLER_SIGN("handler_sign", "审批人-签字"),
/**
* 审批人-转办
*/
HANDLER_TRANSFER("handler_transfer", "审批人-转办"),
/**
* 审批人-分发
*/
HANDLER_ASSIGN("handler_assign", "审批人-分发"),
/**
* 审批人-催办
*/
HISTORY_HANDLER_URGE("historyHandler_urge", "审批人-催办"),
/**
* 审批人-沟通
*/
HANDLER_COMMUNICATE("handler_communicate", "审批人-沟通"),
/**
* 审批人-回复沟通
*/
HANDLER_REPLY_COMMUNICATE("handler_replyCommunicate", "审批人-回复沟通"),
/**
* 审批人-取消沟通
*/
HANDLER_CANCEL_COMMUNICATE("handler_cancelCommunicate", "审批人-取消沟通"),
/**
* 审批人-补签
*/
HANDLER_APPEND_SIGN("handler_appendSign", "审批人-补签"),
/**
* 审批人-加签
*/
HANDLER_PREPEND_SIGN("handler_prependSign", "审批人-加签"),
/**
* 审批人(加签人)-取消加签
*/
HANDLER_PREPEND_SIGN_CANCEL("handler_prependSignCancel", "审批人(加签人)-取消加签"),
/**
* 审批人(被加签人)-退回加签
*/
HANDLER_PREPEND_SIGN_REFUSE("handler_prependSignRefuse", "审批人(被加签人)-退回加签"),
/**
* 审批人(被加签人)-通过加签
*/
HANDLER_PREPEND_SIGN_PASS("handler_prependSignPass", "审批人(被加签人)-通过加签"),
/**
* 审批人(被加签人)-审批人-传阅
*/
HANDLER_CIRCULATION("handler_circulation", "审批人(被加签人)-审批人-传阅"),
/**
* 特权人-前后跳转
*/
ADMIN_JUMP("admin_jump", "特权人-前后跳转"),
/**
* 特权人-流程暂停
*/
ADMIN_PROCESS_SUSPEND("admin_processSuspend", "特权人-流程暂停"),
/**
* 特权人-节点暂停
*/
ADMIN_NODE_SUSPEND("admin_nodeSuspend", "特权人-节点暂停"),
/**
* 审批人-节点唤醒
*/
HANDLER_NODE_RESUME("handler_nodeResume", "审批人-节点唤醒"),
/**
* 特权人-节点唤醒
*/
ADMIN_NODE_RESUME("admin_nodeResume", "特权人-节点唤醒"),
/**
* 特权人-流程唤醒
*/
ADMIN_PROCESS_RESUME("admin_processResume", "特权人-流程唤醒"),
/**
* 特权人-修改流程
*/
ADMIN_MODIFY_PROCESS("admin_modifyProcess", "特权人-修改流程"),
/**
* 特权人-修改当前处理人
*/
ADMIN_CHANGE_CUR_HANDLER("admin_changeCurHandler", "特权人-修改当前处理人"),
/**
* 特权人-终审通过
*/
ADMIN_END("admin_end", "特权人-终审通过"),
/**
* 特权人-直接废弃
*/
ADMIN_ABANDON("admin_abandon", "特权人-直接废弃"),
;
/**
* 编码
*/
private final String code;
/**
* 名称
*/
private final String name;
/**
* 流程结束mk没有这个操作但是有这个事件自定义一个操作类型统一管理
*/
public static final String PROCESS_FINISH = "erp_process_finish";
/**
* 根据操作编码获取名称
* @param code
* @return
*/
public static String getOperationName(String code) {
return Stream.of(values())
.filter(type -> type.getCode().equals(code))
.findFirst()
.map(ProcessOperationType::getName)
.orElse(null);
}
}

View File

@@ -0,0 +1,36 @@
package org.springblade.openapi.ocr.api;
import org.springblade.core.tool.api.FR;
import org.springblade.openapi.common.vo.PageVO;
import org.springblade.openapi.ocr.pojo.dto.Api4OCRProjectDTO;
import org.springblade.openapi.ocr.pojo.dto.Api4OCRResultDTO;
import org.springblade.openapi.ocr.pojo.vo.Api4OCRProjectVO;
import org.springblade.openapi.ocr.pojo.vo.Api4OCRResultVO;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* @author bfhuange
* @since 2025/04/22
*/
public interface IApi4OCR {
String API_PREFIX = "/openApi/ocr";
String PROJECT_LIST = API_PREFIX + "/queryProjectList";
String OCR_RESULT_LIST = API_PREFIX + "/queryOCRResultList";
/**
* 查询项目列表
* @param param
* @return
*/
@PostMapping(PROJECT_LIST)
FR<PageVO<Api4OCRProjectVO>> queryProjectList(@RequestBody(required = false) Api4OCRProjectDTO param);
/**
* 查询凭证ocr识别结果列表
* @param param
* @return
*/
@PostMapping(OCR_RESULT_LIST)
FR<PageVO<Api4OCRResultVO>> queryOCRResultList(@RequestBody(required = false) Api4OCRResultDTO param);
}

View File

@@ -0,0 +1,24 @@
package org.springblade.openapi.ocr.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* @author bfhuange
* @since 2025/4/22
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "提供给ocr的项目信息")
public class Api4OCRProjectDTO extends PageQuery {
@Serial
private static final long serialVersionUID = 1L;
/**
* 关键字,项目名称或简称模糊查询
*/
@Schema(description = "关键字,项目名称或简称模糊查询")
private String keyword;
}

View File

@@ -0,0 +1,62 @@
package org.springblade.openapi.ocr.pojo.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.util.Date;
/**
* @author bfhuange
* @since 2025/4/22
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "凭证ocr结果查询参数")
public class Api4OCRResultDTO extends PageQuery {
@Serial
private static final long serialVersionUID = 1L;
/**
* 项目id
*/
@Schema(description = "项目id项目id、凭证批次号、凭证号至少一个不为空")
private Long projectId;
/**
* 凭证批次号
*/
@Schema(description = "凭证批次号项目id、凭证批次号、凭证号至少一个不为空")
private String batchCode;
/**
* 凭证号
*/
@Schema(description = "凭证号项目id、凭证批次号、凭证号至少一个不为空")
private String detailCode;
/**
* 是否类型错误1 否 2 是)
*/
@Schema(description = "是否类型错误1 否 2 是)")
private Integer isTypeError;
/**
* 是否数据错误1 否 2 是)
*/
@Schema(description = "是否数据错误1 否 2 是)")
private Integer isDataError;
/**
* 创建时间始
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME, timezone = "GMT+8")
@Schema(description = "创建时间始格式yyyy-MM-dd HH:mm:ss")
private Date createTimeStart;
/**
* 创建时间至
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME, timezone = "GMT+8")
@Schema(description = "创建时间至格式yyyy-MM-dd HH:mm:ss")
private Date createTimeEnd;
}

View File

@@ -0,0 +1,41 @@
package org.springblade.openapi.ocr.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 分页查询参数
* @author bfhuange
* @since 2025/4/22
*/
@Data
@Schema(description = "分页查询参数")
public class PageQuery implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 每页最大数量 200
*/
public static final int MAX_SIZE = 200;
/**
* 当前页
*/
@Schema(description = "当前页默认1")
protected Integer current = 1;
/**
* 每页的数量
*/
@Schema(description = "每页的数量默认10超过200会修改为200")
protected Integer size = 10;
public void setSize(Integer size) {
if (size != null && size > MAX_SIZE) {
size = MAX_SIZE;
}
this.size = size;
}
}

View File

@@ -0,0 +1,56 @@
package org.springblade.openapi.ocr.pojo.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author bfhuange
* @since 2025/4/22
*/
@Data
@Schema(description = "提供给ocr的项目信息")
public class Api4OCRProjectVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 项目id
*/
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "项目id")
private Long id;
/**
* 项目名称
*/
@Schema(description = "项目名称")
private String name;
/**
* 项目简称
*/
@Schema(description = "项目简称")
private String abbreviation;
/**
* 创建时间
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "创建时间")
private Date createTime;
/**
* 更新时间
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "更新时间")
private Date updateTime;
}

View File

@@ -0,0 +1,103 @@
package org.springblade.openapi.ocr.pojo.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.openapi.ocr.pojo.vo.result.AttachmentType;
import org.springblade.openapi.ocr.pojo.vo.result.ErrorAttachmentType;
import org.springblade.openapi.ocr.pojo.vo.result.ErrorField;
import org.springblade.openapi.ocr.pojo.vo.result.TransportCertificateBatchDetailData;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author bfhuange
* @since 2025/4/22
*/
@Data
@Schema(description = "凭证ocr结果")
public class Api4OCRResultVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@JsonSerialize(using = ToStringSerializer.class, nullsUsing = NullSerializer.class)
@Schema(description = "主键")
private Long id;
/**
* 凭证号
*/
@Schema(description = "凭证号")
private String code;
/**
* 识别类型batch 批量识别mixed 单张识别合并)
*/
@Schema(description = "识别类型batch 批量识别mixed 单张识别合并)")
private String identifyType;
/**
* 是否类型错误1 否 2 是)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "是否类型错误1 否 2 是)")
private Integer isTypeError;
/**
* 是否数据错误1 否 2 是)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "是否数据错误1 否 2 是)")
private Integer isDataError;
/**
* 附件类型列表
*/
@Schema(description = "附件类型列表")
private List<AttachmentType> attachmentTypeList;
/**
* 数据
*/
@Schema(description = "数据")
private TransportCertificateBatchDetailData data;
/**
* 错误类型列表
*/
@Schema(description = "错误类型列表")
private List<ErrorAttachmentType> errorTypeList;
/**
* 错误字段列表
*/
@Schema(description = "错误字段列表")
private List<ErrorField> errorFieldList;
/**
* 错误字段列表
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "创建时间")
private Date createTime;
/**
* 更新时间
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
@Schema(description = "更新时间")
private Date updateTime;
}

View File

@@ -0,0 +1,40 @@
package org.springblade.openapi.ocr.pojo.vo.result;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 附件类型
* @author bfhuange
* @since 2025/4/18
*/
@Data
@Schema(description = "附件类型")
public class AttachmentType implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 附件id
*/
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "附件id")
private Long attachmentId;
/**
* ocr附件类型
*/
@Schema(description = "ocr附件类型")
private String ocrType;
/**
* 附件url
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Schema(description = "附件url")
private String url;
}

View File

@@ -0,0 +1,25 @@
package org.springblade.openapi.ocr.pojo.vo.result;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 错误附件类型
* @author bfhuange
* @since 2025/4/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "错误附件类型")
public class ErrorAttachmentType extends AttachmentType {
@Serial
private static final long serialVersionUID = 1L;
/**
* erp附件类型
*/
@Schema(description = "erp附件类型")
private String erpType;
}

View File

@@ -0,0 +1,45 @@
package org.springblade.openapi.ocr.pojo.vo.result;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 错误字段
* @author bfhuange
* @since 2025/4/21
*/
@Data
@Schema(description = "错误字段")
public class ErrorField implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 字段名
*/
@Schema(description = "字段名")
private String filed;
/**
* ocr类型
*/
@Schema(description = "ocr类型")
private String ocrType;
/**
* ocr字段值
*/
@Schema(description = "ocr字段值")
private String ocrValue;
/**
* erp字段值
*/
@Schema(description = "erp字段值")
private String erpValue;
/**
* 附件列表
*/
@Schema(description = "附件列表")
private List<AttachmentType> attachmentList;
}

View File

@@ -0,0 +1,94 @@
package org.springblade.openapi.ocr.pojo.vo.result;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springblade.core.tool.utils.DateUtil;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 车辆运输凭证批次明细表 实体类
*
* @author BladeX
* @since 2024-10-23
*/
@Data
@Schema(description = "凭证数据对象")
public class TransportCertificateBatchDetailData implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 磅单车牌号
*/
@Schema(description = "磅单车牌号")
private String poundPlateNo;
/**
* 行驶证上的车牌号
*/
@Schema(description = "行驶证上的车牌号")
private String drivingPlateNo;
/**
* 车头车牌号
*/
@Schema(description = "车头车牌号")
private String carFrontPlateNo;
/**
* 到货日期
*/
@JsonFormat(pattern = DateUtil.PATTERN_DATE, timezone = "GMT+8")
@Schema(description = "到货日期")
private Date supplyMaterialDate;
/**
* 货物名称
*/
@Schema(description = "货物名称")
private String productName;
/**
* 规格料型
*/
@Schema(description = "规格料型")
private String specificationMaterial;
/**
* 毛重(吨)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "毛重(吨)")
private BigDecimal grossWeight;
/**
* 皮重(吨)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "皮重(吨)")
private BigDecimal skinWeight;
/**
* 净重(吨)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "净重(吨)")
private BigDecimal netWeight;
/**
* 扣杂(吨)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "扣杂(吨)")
private BigDecimal miscellaneousWeight;
/**
* 实收(吨)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "实收(吨)")
private BigDecimal realityWeight;
/**
* 驾驶证是否有效1 否 2 是)
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
@Schema(description = "驾驶证是否有效1 否 2 是)")
private Integer isDriverLicenseValid;
}

View File

@@ -0,0 +1,40 @@
package org.springblade.openapi.track.api;
import org.springblade.openapi.track.pojo.dto.Api4TrackWaybillDTO;
import org.springblade.openapi.track.pojo.vo.Api4TrackResultVO;
import org.springblade.openapi.track.pojo.vo.Api4TrackWaybillVO;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* @author bfhuange
* @since 2024/12/16
*/
public interface IApi4Track {
String API_PREFIX = "/openApi/gj";
String WAYBILL_LIST = API_PREFIX + "/mycode/zhcx/getZhcx";
String WAYBILL_TRACK_UPDATE = API_PREFIX + "/mycode/zhcx/callback";
/**
* 轨迹查询运单信息
*
* @param param@return
*/
@PostMapping(WAYBILL_LIST)
Api4TrackResultVO<List<Api4TrackWaybillVO>> queryWaybillList(@RequestBody Api4TrackWaybillDTO param);
/**
* 轨迹更新运单轨迹url和状态
* @param waybillId
* @param trajectoryId
* @param trajectoryStatus
* @return
*/
@PostMapping(WAYBILL_TRACK_UPDATE)
Api4TrackResultVO<Void> updateWaybillTrack(@RequestParam(name = "zhcxId", required = false) String waybillId,
@RequestParam(name = "diTuUrl", required = false) String trajectoryId,
@RequestParam(name = "guiJiZhuangTai", required = false) String trajectoryStatus);
}

View File

@@ -0,0 +1,17 @@
package org.springblade.openapi.track.constant;
/**
* 轨迹常量
* @author bfhuange
* @since 2024/12/16
*/
public class TrackConstant {
/**
* 响应成功状态码
*/
public static final Integer SUCCESS_CODE = 200;
/**
* 响应失败状态码
*/
public static final Integer FAIL_CODE = 500;
}

View File

@@ -0,0 +1,22 @@
package org.springblade.openapi.track.pojo.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author bfhuange
* @since 2024/12/16
*/
@Data
public class Api4TrackWaybillDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 运单id列表
*/
private List<String> ids;
}

View File

@@ -0,0 +1,33 @@
package org.springblade.openapi.track.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author bfhuange
* @since 2024/12/16
*/
@Data
public class Api4TrackWaybillUpdateDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 运单id
*/
@JsonProperty("zhcxId")
private String waybillId;
/**
* 轨迹id
*/
@JsonProperty("diTuUrl")
private String trajectoryId;
/**
* 轨迹状态
*/
@JsonProperty("guiJiZhuangTai")
private String trajectoryStatus;
}

View File

@@ -0,0 +1,50 @@
package org.springblade.openapi.track.pojo.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springblade.openapi.track.constant.TrackConstant;
import java.io.Serial;
import java.io.Serializable;
/**
* @author bfhuange
* @since 2024/12/16
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Api4TrackResultVO<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 响应代码。200为正确
*/
private Integer state;
/**
* 对应的提示信息
*/
private String message;
/**
* 数据
*/
private T data;
public Api4TrackResultVO(Integer state, T data) {
this.state = state;
this.data = data;
}
public static <T> Api4TrackResultVO<T> success() {
return Api4TrackResultVO.success(null);
}
public static <T> Api4TrackResultVO<T> fail(String message) {
return new Api4TrackResultVO<>(TrackConstant.FAIL_CODE, message, null);
}
public static <T> Api4TrackResultVO<T> success(T data) {
return new Api4TrackResultVO<>(TrackConstant.SUCCESS_CODE, data);
}
}

View File

@@ -0,0 +1,86 @@
package org.springblade.openapi.track.pojo.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.springblade.core.tool.utils.DateUtil;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author bfhuange
* @since 2024/12/16
*/
@Data
public class Api4TrackWaybillVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 运单id
*/
private String id;
/**
* 收货日期
*/
@DateTimeFormat(pattern = DateUtil.PATTERN_DATE)
@JsonFormat(pattern = DateUtil.PATTERN_DATE)
@JsonProperty("shouHuoRiQi")
private Date enterDate;
/**
* 车牌号
*/
@JsonProperty("chePaiHao")
private String plateNo;
/**
* 钢厂简称
*/
@JsonProperty("gangChangJianCheng")
private String customerAbbreviation;
/**
* 钢厂合同编号
*/
@JsonIgnore
private String contractGcCode;
//===========================设置默认值的参数==========================
/**
* 托运人
*/
@JsonProperty("tuoYunRen")
private String shipper = "托运人";
/**
* 收货人
*/
@JsonProperty("shouHuoRen")
private String consignee = "收货人";
/**
* 收货地址
*/
@JsonProperty("shouHuoDiZhi")
private String address = "收货地址";
/**
* 投送人
*/
@JsonProperty("touSongRen")
private String delivery = "投送人";
/**
* 货物名称
*/
@JsonProperty("huoWuMingCheng")
private String goodsName = "货物名称";
/**
* 重量
*/
@JsonProperty("zhongLiang")
private BigDecimal weight = BigDecimal.ZERO;
/**
* 事业部
*/
@JsonProperty("shiYeBu")
private String division = "事业部";
}

View File

@@ -0,0 +1,50 @@
package org.springblade.openapi.wps.api;
import org.springblade.openapi.wps.pojo.dto.Api4WpsFileInfoDTO;
import org.springblade.openapi.wps.pojo.vo.Api4WpsFileInfoVO;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
/**
* 给wps回调的api
* @author bfhuange
* @date 2024/10/30
*/
public interface IApi4Wps {
String API_PREFIX = "/openApi/wps";
String VERSION = "/v1";
String FILE_INFO = API_PREFIX + VERSION + "/3rd/file/info";
String FILE_SAVE = API_PREFIX + VERSION + "/3rd/file/save";
/**
* wps回调查询文件信息
*
* @param fileId 文件id必填
* @param token 非必填
* @param param 在获取预览链接时按需求传入的所有自定义参数
* @return
*/
@GetMapping(FILE_INFO)
Api4WpsFileInfoVO getFileInfo(@RequestHeader("X-Weboffice-File-Id") String fileId,
@RequestHeader(value = "X-Wps-Weboffice-Token", required = false) String token,
@SpringQueryMap Api4WpsFileInfoDTO param);
/**
* wps回调-上传文件新版本
*
* @param fileId 文件id必填
* @param token 非必填
* @param param 在获取预览链接时按需求传入的所有自定义参数
* @return
*/
@PostMapping(FILE_SAVE)
Api4WpsFileInfoVO getFileSave(@RequestHeader("X-Weboffice-File-Id") String fileId,
@RequestHeader(value = "X-Weboffice-Save-Type") String saveType,
@RequestHeader(value = "X-Wps-Weboffice-Token", required = false) String token,
@RequestPart("file") MultipartFile file,
@SpringQueryMap Api4WpsFileInfoDTO param);
}

View File

@@ -0,0 +1,21 @@
package org.springblade.openapi.wps.constant;
/**
* wps常量类
* @author bfhuange
* @date 2024/10/30
*/
public class WpsConstant {
/**
* 是
*/
public static final Integer YES = 1;
/**
* 否
*/
public static final Integer NO = 0;
/**
* 文件信息查询默认缓存时间 120 秒
*/
public static final String FILE_INFO_DEFAULT_CACHE_TIME = "120";
}

View File

@@ -0,0 +1,17 @@
package org.springblade.openapi.wps.pojo.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wps文件信息查询参数
* @author bfhuange
* @date 2024/10/30
*/
@Data
public class Api4WpsFileInfoDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,60 @@
package org.springblade.openapi.wps.pojo.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* wps 回调接口错误枚举
* @author bfhuange
* @since 2024/11/26
*/
@AllArgsConstructor
@Getter
public enum Api4WpsError {
/**
* 服务处理正常
*/
OK(0, "OK"),
/**
* token过期
*/
SESSION_EXPIRED(40002, "SessionExpired"),
/**
* 用户无权限访问
*/
PERMISSION_DENIED(40003, "PermissionDenied"),
/**
* 资源不存在
*/
NOT_EXISTS(40004, "NotExists"),
/**
* 参数错误
*/
INVALID_ARGUMENT(40005, "InvalidArgument"),
/**
* 保存空间已满
*/
SPACE_FULL(40006, "SpaceFull"),
/**
* 自定义错误提示前端页面将显示此错误内容在回调错误响应中的hint字段中自定义错误提示该错误提示不支持多语言
*/
CUSTOM_MSG(40007, "CustomMsg"),
/**
* 文件重命名冲突
*/
FNAME_CONFLICT(40008, "FnameConflict"),
/**
* 对接系统错误
*/
SERVER_ERROR(50001, "ServerError"),
;
/**
* 错误码
*/
private final Integer code;
/**
* 信息
*/
private final String message;
}

View File

@@ -0,0 +1,27 @@
package org.springblade.openapi.wps.pojo.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* wps附加参数
* @author bfhuange
* @date 2024/10/30
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Api4WpsAttrsVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 单位秒取值范围为1-300超过300秒不会缓存回调信息此字段需服务端全局配置开启缓存且需要使用token访问预览链接非必填
*/
@JsonProperty("cachetime")
private String cacheTime;
}

View File

@@ -0,0 +1,41 @@
package org.springblade.openapi.wps.pojo.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* wps回调接口错误
* @author bfhuange
* @since 2024/11/26
*/
@NoArgsConstructor
@Data
public class Api4WpsErrorVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误提示详细信息
*/
private String details;
/**
* 自定义错误信息当code为40007错误码时必填
*/
private String hint;
public Api4WpsErrorVO(Integer code, String message, String hint) {
this.code = code;
this.message = message;
this.hint = hint;
}
}

View File

@@ -0,0 +1,34 @@
package org.springblade.openapi.wps.pojo.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wps文件信息查询结果
* @author bfhuange
* @date 2024/10/30
*/
@Data
public class Api4WpsFileInfoVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 文件信息,必填
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
private Api4WpsFileVO file;
/**
* 用户信息,必填
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
private Api4WpsUserVO user;
/**
* 附加参数v6.0.2209.20220920新增
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
private Api4WpsAttrsVO attrs;
}

View File

@@ -0,0 +1,83 @@
package org.springblade.openapi.wps.pojo.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wps文件结果
* @author bfhuange
* @date 2024/10/30
*/
@Data
public class Api4WpsFileVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 文件id,字符串长度不超过64位必填
*/
private String id;
/**
* 文件名必须带后缀,必填
*/
private String name;
/**
* 文档版本号从1开始累加位数小于11必填
*/
private Integer version = 1;
/**
* 文档大小,单位为字节;此处需传文件真实大小,否则会出现异常,必填
*/
private Integer size;
/**
* readonly默认为false
* true开启表格筛选支持对EXCEL表格文档筛选但不支持对EXCEL表格文档开启多人同步筛选该预览特性见常见问题
* false关闭表格筛选20220707新增非必填
*/
private Boolean readonly = true;
/**
* 创建者id字符串长度不超过32位。与user里的id一致必填
*/
private String creator;
/**
* 创建时间,时间戳,单位为秒,必填
*/
@JsonProperty("create_time")
private Integer createTime;
/**
* 修改者id字符串长度不超过32位必填
*/
private String modifier;
/**
* 最近修改时间,时间戳,单位为秒,必填
*/
@JsonProperty("modify_time")
private Integer modifyTime;
/**
* 文档下载地址,必填
*/
@JsonProperty("download_url")
private String downloadUrl;
/**
* 普通预览模式下可限制预览页数不超过5000
* previewPages 默认值为 0不限制预览页数
* previewPages >= 1 时,限制生效,限制的页数为 previewpages 字段的值,必填
*/
@JsonProperty("preview_pages")
private Integer previewPages = 0;
/**
* 用户权限,非必填
*/
@JsonProperty("user_acl")
@JsonSerialize(nullsUsing = NullSerializer.class)
private Api4WpsUserAclVO userAcl;
/**
* 水印参数,非必填
*/
@JsonSerialize(nullsUsing = NullSerializer.class)
private Api4WpsWatermarkVO watermark;
}

View File

@@ -0,0 +1,37 @@
package org.springblade.openapi.wps.pojo.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wps用户权限
* @author bfhuange
* @date 2024/10/30
*/
@Data
public class Api4WpsUserAclVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 重命名权限1为打开该权限0为关闭该权限默认为0非必填
*/
private Integer rename;
/**
* 历史文件打开权限1为打开该权限0为关闭该权限默认为1非必填
*/
private Integer history;
/**
* 复制权限1为打开该权限0为关闭该权限默认为1非必填
*/
private Integer copy;
/**
* 导出权限1为打开该权限0为关闭该权限默认为1非必填
*/
private Integer export;
/**
* 打印权限1为打开该权限0为关闭该权限默认为1非必填
*/
private Integer print;
}

View File

@@ -0,0 +1,36 @@
package org.springblade.openapi.wps.pojo.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* wps用户信息
* @author bfhuange
* @date 2024/10/30
*/
@NoArgsConstructor
@Data
public class Api4WpsUserVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户id长度不超过32位与creator、modifier一致必填
*/
private String id;
/**
* 用户名称,必填
*/
private String name;
/**
* 用户操作权限预览固定为read必填
*/
private String permission = "write";
public Api4WpsUserVO(String id, String name) {
this.id = id;
this.name = name;
}
}

View File

@@ -0,0 +1,48 @@
package org.springblade.openapi.wps.pojo.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wps水印参数
* @author bfhuange
* @date 2024/10/30
*/
@Data
public class Api4WpsWatermarkVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 水印类型, 0为无水印 1为文字水印非必填
*/
private Integer type;
/**
* 文字水印的文字,支持通过\r\n换行支持emoji表情
* 当type为1时此字段必选
*/
private String value;
/**
* 水印的颜色含透明度非必选有默认值。格式为rgba( 192, 192, 192, 0.6 )
*/
@JsonProperty("fillstyle")
private String fillStyle;
/**
* 水印的字体非必选有默认值格式为bold 20px Serif非必填
*/
private String font;
/**
* 水印的旋转度(弧度),非必选,有默认值,默认为-0.7853982,非必填
*/
private Float rotate;
/**
* 水印水平间距非必选有默认值默认为50非必填
*/
private Integer horizontal;
/**
* 水印垂直间距非必选有默认值默认为100非必填
*/
private Integer vertical;
}

View File

@@ -24,6 +24,7 @@
<module>blade-user-api</module>
<module>blade-record-api</module>
<module>blade-file-api</module>
<module>blade-open-api</module>
</modules>
<dependencies>

View File

@@ -0,0 +1,138 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.file.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdmin;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.file.pojo.entity.Attachment;
import org.springblade.file.service.IAttachmentService;
import org.springframework.web.bind.annotation.*;
/**
* 附件表 控制器
*
* @author Chill
*/
@NonDS
@RestController
@AllArgsConstructor
//@IsAdmin
@RequestMapping("/attachment")
@Tag(name = "附件", description = "附件")
public class AttachmentController extends BladeController {
private final IAttachmentService attachmentService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入attach")
public R<Attachment> detail(Attachment attach) {
Attachment detail = attachmentService.getOne(Condition.getQueryWrapper(attach));
return R.data(detail);
}
/**
* 分页 附件表
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入attach")
public R<IPage<Attachment>> list(Attachment attach, Query query) {
attach.setSize(null);
query.setDescs("create_time");
IPage<Attachment> pages = attachmentService.page(Condition.getPage(query), Condition.getQueryWrapper(attach));
return R.data(pages);
}
// /**
// * 自定义分页 附件表
// */
// @GetMapping("/page")
// @ApiOperationSupport(order = 3)
// @Operation(summary = "分页", description = "传入attach")
// public R<IPage<Attachment>> page(Attachment attach, Query query) {
// IPage<Attachment> pages = attachmentService.selectAttachPage(Condition.getPage(query), attach);
// return R.data(pages);
// }
/**
* 新增 附件表
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入attach")
public R save(@Valid @RequestBody Attachment attach) {
return R.status(attachmentService.save(attach));
}
/**
* 修改 附件表
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入attach")
public R update(@Valid @RequestBody Attachment attach) {
return R.status(attachmentService.updateById(attach));
}
/**
* 新增或修改 附件表
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入attach")
public R submit(@Valid @RequestBody Attachment attach) {
return R.status(attachmentService.saveOrUpdate(attach));
}
/**
* 删除 附件表
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(attachmentService.removeByIds(Func.toLongList(ids)));
}
}

View File

@@ -0,0 +1,19 @@
FROM bladex/alpine-java:openjdk17_cn_slim
ARG ACTIVE
LABEL maintainer="bladejava@qq.com"
# 设置时区为上海
ENV TZ=Asia/Shanghai
# 设置时区信息
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY ./target/blade-openapi.jar /opt/app.jar
WORKDIR /opt
EXPOSE 8108
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/logs", "-XX:ErrorFile=/opt/logs/hs_err_pid%p.log", "-Xlog:gc*:file=/opt/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=50M", "-XX:MaxDirectMemorySize=512m", "-Xms1024m", "-Xmx4096m", "-jar", "app.jar"]
CMD ["--spring.profiles.active=${ACTIVE}","--logging.path=/opt/logs"]

View File

@@ -0,0 +1,17 @@
#FROM 10.38.16.129/bladex/alpine-java:openjdk17_cn_slim
#FROM registry.cn-hangzhou.aliyuncs.com/vic_person/alpine-java:openjdk17_cn_slim
FROM 10.38.16.129:80/bladex/alpine-java:openjdk17_cn_slim
ARG ACTIVE
LABEL maintainer="bladejava@qq.com"
# 设置时区为上海
ENV TZ=Asia/Shanghai
# 设置时区信息
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY ./target/*.jar /opt/app.jar
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/opt/app.jar"]
CMD ["--spring.profiles.active=${ACTIVE}"]

View File

@@ -0,0 +1,19 @@
FROM bladex/alpine-java:openjdk17_cn_slim
ARG ACTIVE
LABEL maintainer="bladejava@qq.com"
# 设置时区为上海
ENV TZ=Asia/Shanghai
# 设置时区信息
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY ./target/blade-openapi.jar /opt/app.jar
WORKDIR /opt
EXPOSE 8108
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/logs", "-XX:ErrorFile=/opt/logs/hs_err_pid%p.log", "-Xlog:gc*:file=/opt/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=50M", "-XX:MaxDirectMemorySize=512m", "-Xms1024m", "-Xmx1024m", "-jar", "app.jar"]
CMD ["--spring.profiles.active=${ACTIVE}","--logging.path=/opt/logs"]

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>blade-service</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<artifactId>blade-openapi</artifactId>
<properties>
<!-- 其他依赖版本 -->
<lombok.version>1.18.30</lombok.version>
<org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-threadpool</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-open-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-file-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-mk-api</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<skip>${docker.fabric.skip}</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,50 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.openapi;
import org.dromara.dynamictp.core.spring.EnableDynamicTp;
import org.springblade.core.cloud.client.BladeCloudApplication;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.launch.constant.AppConstant;
import org.springframework.context.annotation.ComponentScan;
/**
* Desk启动器
*
* @author Chill
*/
@EnableDynamicTp
@BladeCloudApplication
@ComponentScan({"org.springblade.openapi", "org.springblade.**.feign"})
public class OpenApiApplication {
public static void main(String[] args) {
BladeApplication.run(AppConstant.APPLICATION_OPENAPI_NAME, OpenApiApplication.class, args);
}
}

View File

@@ -0,0 +1,53 @@
package org.springblade.openapi.resultcode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springblade.core.tool.api.IResultCode;
/**
*
* 业务自定义返回码
* 定义规则:
* 统一格式:[2位服务码][2位模块码][2位功能码][3位错误码]
* <p>
* xx xx xx xx
* |__服务码 |__模块 |__功能 |___错误码
* 业务自定义返回码
* * 定义规则:
* * 统一格式:[2位服务码][2位模块码][2位功能码][3位错误码]
* * <p>
* * xx xx xx xx
* * |__服务码 |__模块 |__功能 |___错误码
* *
服务码:
业务基础服务 10
订单服务 20
仓储服务 30
首页/通告服务 40
系统管理服务 50
开放接口服务 60
* @author vic
* @date 2024/9/12 2:09PM
* @description OrderResultCode
*/
@Getter
@AllArgsConstructor
public enum OpenApiResultCode implements IResultCode {
;
/**
* code编码
*/
final int code;
/**
* 中文信息描述
*/
final String message;
}

View File

@@ -0,0 +1,134 @@
package org.springblade.openapi.wps;
import com.alibaba.fastjson2.JSON;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.ObsUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.file.feign.IFileClient;
import org.springblade.file.pojo.vo.AttachmentDetailVO;
import org.springblade.openapi.wps.convert.WpsFileConvert;
import org.springblade.openapi.wps.api.IApi4Wps;
import org.springblade.openapi.wps.constant.WpsConstant;
import org.springblade.openapi.wps.exception.Api4WpsException;
import org.springblade.openapi.wps.pojo.dto.Api4WpsFileInfoDTO;
import org.springblade.openapi.wps.pojo.enums.Api4WpsError;
import org.springblade.openapi.wps.util.TokenUtils;
import org.springblade.openapi.wps.pojo.vo.*;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Locale;
/**
* @author bfhuange
* @date 2024/10/30
*/
@Slf4j
@Hidden
@AllArgsConstructor
@RestController
public class Api4Wps implements IApi4Wps {
/**
* 图片扩展名列表
*/
private static final List<String> IMAGE_EXT = List.of("bmp", "jpeg", "jpg", "png", "gif");
private final IFileClient fileClient;
private final WpsFileConvert convert;
@Override
public Api4WpsFileInfoVO getFileInfo(String fileId, String token, Api4WpsFileInfoDTO param) {
log.info("wps回调查询文件信息 参数 fileId{} token{} param{}", fileId, token, JSON.toJSONString(param));
long id = Func.toLong(fileId);
if (id <= 0L) {
throw new Api4WpsException(Api4WpsError.NOT_EXISTS);
}
if (token == null) {
throw new Api4WpsException(Api4WpsError.PERMISSION_DENIED);
}
R<AttachmentDetailVO> result = fileClient.getAttachmentDetail(id);
if (result == null || !result.isSuccess() || result.getData() == null || result.getData().getId() == null) {
log.warn("wps回调查询文件信息 查询附件失败 {}", JSON.toJSONString(result));
throw new Api4WpsException(Api4WpsError.NOT_EXISTS);
}
// 附件
AttachmentDetailVO attachment = result.getData();
Api4WpsFileVO fileVO = convert.attachment2file(attachment);
// 用户信息
Api4WpsUserVO user = TokenUtils.getWpsUser(token);
if (user == null) {
// 用户信息为空token过期了
throw new Api4WpsException(Api4WpsError.SESSION_EXPIRED);
}
// 用户不为空,添加水印
boolean isImage = isImage(attachment.getAttachmentName());
log.info("附件名:{} 是否图片:{}", attachment.getAttachmentName(), isImage);
if (!isImage) {
// 不是图片才加水印
Api4WpsWatermarkVO watermark = new Api4WpsWatermarkVO();
watermark.setType(WpsConstant.YES);
watermark.setValue(user.getName());
watermark.setHorizontal(100);
watermark.setVertical(200);
fileVO.setWatermark(watermark);
}
Api4WpsFileInfoVO fileInfoVO = new Api4WpsFileInfoVO();
fileInfoVO.setUser(user);
fileInfoVO.setFile(fileVO);
// 缓存时间
fileInfoVO.setAttrs(new Api4WpsAttrsVO(WpsConstant.FILE_INFO_DEFAULT_CACHE_TIME));
log.info("wps回调查询文件信息 返回结果:{}", JSON.toJSONString(fileInfoVO));
return fileInfoVO;
}
@Override
public Api4WpsFileInfoVO getFileSave(String fileId, String saveType, String token, MultipartFile file, Api4WpsFileInfoDTO param) {
try {
log.info("wps回调-上传文件新版本 参数 fileId{} token{} param{}", fileId, token, JSON.toJSONString(param));
long id = Func.toLong(fileId);
if (id == 0L) {
return null;
}
R<AttachmentDetailVO> result = fileClient.getAttachmentDetail(id);
if (result == null || !result.isSuccess()) {
log.warn("wps回调-上传文件新版本 查询附件失败 {}", JSON.toJSONString(result));
return null;
}
// 附件
AttachmentDetailVO attachment = result.getData();
Api4WpsFileVO fileVO = convert.attachment2file(attachment);
fileVO.setVersion(2);
ObsUtil.putObject(attachment.getObjectKey(), file.getInputStream());
Api4WpsFileInfoVO fileInfoVO = new Api4WpsFileInfoVO();
fileInfoVO.setFile(fileVO);
return fileInfoVO;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 是否图片类型
* @param fileName
* @return
*/
public boolean isImage(String fileName) {
if (fileName == null) {
return false;
}
int index = fileName.lastIndexOf(".");
if (index < 0 || index +1 >= fileName.length() ) {
return false;
}
String extName = fileName.substring(index + 1).toLowerCase(Locale.getDefault());
return IMAGE_EXT.contains(extName);
}
}

View File

@@ -0,0 +1,37 @@
package org.springblade.openapi.wps.convert;
import org.mapstruct.*;
import org.springblade.openapi.wps.pojo.vo.Api4WpsFileVO;
import org.springblade.file.pojo.vo.AttachmentDetailVO;
import java.util.Date;
/**
* @author bfhuange
* @date 2024/10/30
*/
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface WpsFileConvert {
@Mapping(source = "attachmentName", target = "name")
@Mapping(source = "url", target = "downloadUrl")
@Mapping(source = "size", target = "size", qualifiedByName = "long2int")
@Mapping(source = "createUser", target = "creator")
@Mapping(source = "createTime", target = "createTime", qualifiedByName = "date2int")
@Mapping(source = "updateUser", target = "modifier")
@Mapping(source = "updateTime", target = "modifyTime", qualifiedByName = "date2int")
Api4WpsFileVO attachment2file(AttachmentDetailVO attachment);
@Named("date2int")
default Integer date2int(Date date) {
if (date == null) {
return null;
}
return Math.toIntExact(date.getTime() / 1000);
}
@Named("long2int")
default Integer long2int(long size) {
return Math.toIntExact(size);
}
}

View File

@@ -0,0 +1,34 @@
package org.springblade.openapi.wps.exception;
import lombok.Getter;
import org.springblade.openapi.wps.pojo.enums.Api4WpsError;
/**
* wps回调接口异常
* @author bfhuange
* @since 2024/11/26
*/
@Getter
public class Api4WpsException extends RuntimeException {
/**
* 错误枚举
*/
private final Api4WpsError error;
/**
* 消息
*/
private final String message;
public Api4WpsException(Api4WpsError error) {
super(error.getMessage());
this.error = error;
this.message = error.getMessage();
}
public Api4WpsException(Api4WpsError error, String message) {
super(message);
this.error = error;
this.message = message;
}
}

View File

@@ -0,0 +1,27 @@
package org.springblade.openapi.wps.exception;
import lombok.extern.slf4j.Slf4j;
import org.springblade.openapi.wps.pojo.enums.Api4WpsError;
import org.springblade.openapi.wps.pojo.vo.Api4WpsErrorVO;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* wps 回调接口异常处理
* @author bfhuange
* @since 2024/11/26
*/
@Slf4j
@RestControllerAdvice
public class Api4WpsExceptionHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(Api4WpsException.class)
public Api4WpsErrorVO handleException(Api4WpsException exception) {
log.error("wps 回调接口异常:{}", exception.getMessage(), exception);
Api4WpsError error = exception.getError();
return new Api4WpsErrorVO(error.getCode(), error.getMessage(), exception.getMessage());
}
}

View File

@@ -0,0 +1,33 @@
package org.springblade.openapi.wps.util;
import io.jsonwebtoken.Claims;
import org.springblade.core.launch.constant.TokenConstant;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.openapi.wps.pojo.vo.Api4WpsUserVO;
/**
* @author bfhuange
* @date 2024/10/30
*/
public class TokenUtils {
/**
* 获取wps需要的用户信息
* @param token
* @return
*/
public static Api4WpsUserVO getWpsUser(String token) {
if (StringUtil.isBlank(token)) {
return null;
}
Claims claims = AuthUtil.parseJWT(token);
if (claims == null) {
return null;
}
String userId = Func.toStr(claims.get(TokenConstant.USER_ID));
String nickName = Func.toStr(claims.get(TokenConstant.NICK_NAME));
return new Api4WpsUserVO(userId, nickName);
}
}

View File

@@ -0,0 +1,6 @@
#spring:
# cloud:
# nacos:
# username: nacos
# password: ${NACOS_PASSWORD:gr30wIs5%Hi7keQj}
# server-addr: ${NACOS_ADDR:10.38.16.127:8848}

View File

@@ -0,0 +1,6 @@
#spring:
# cloud:
# nacos:
# username: nacos
# password: rWrMrVTWyf%ekjuw
# server-addr: ${NACOS_ADDR:192.168.0.242:8848}

View File

@@ -0,0 +1,8 @@
#server:
# port: 38108
#spring:
# cloud:
# nacos:
# username: nacos
# password: gr30wIs5%Hi7keQj
# server-addr: ${NACOS_ADDR:10.38.16.127:8848}

View File

@@ -0,0 +1,34 @@
server:
port: 8108
#数据源配置
spring:
datasource:
url: ${blade.datasource.dev.url}
username: ${blade.datasource.dev.username}
password: ${blade.datasource.dev.password}
#spring:
# application:
# name: blade-openapi
# cloud:
# nacos:
# discovery:
# namespace: ${spring.profiles.active}
# # 不注册到nacos
# #registerEnabled: false
# config:
# # 文件后缀名
# file-extension: yaml
# namespace: ${spring.profiles.active}
# shared-configs:
# - data-id: blade.yaml
# refresh: true
# - data-id: blade-${spring.profiles.active}.yaml
# refresh: true
# - data-id: third-party-api.yaml
# refresh: true
# extension-configs:
# - data-id: ${spring.application.name}-dynamictp.yaml
# group: DEFAULT_GROUP
# refresh: true # 必须配置,负责自动刷新不生效

View File

@@ -20,6 +20,7 @@
<module>blade-desk</module>
<module>blade-system</module>
<module>blade-file</module>
<module>blade-openapi</module>
</modules>
<dependencies>