Merge remote-tracking branch 'ztcloud/test' into dev
# Conflicts: # zt-framework/zt-spring-boot-starter-biz-data-permission/src/main/java/com/zt/plat/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java
This commit is contained in:
514
docs/iWork用印流程集成开发文档.md
Normal file
514
docs/iWork用印流程集成开发文档.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,19 @@
|
||||
-- iWork 流程创建日志表(达梦数据库)
|
||||
-- iWork 流程日志表(达梦数据库)
|
||||
-- 合并了流程创建日志和回调日志
|
||||
CREATE TABLE system_iwork_workflow_log (
|
||||
id BIGINT NOT NULL,
|
||||
request_id VARCHAR(64) NOT NULL,
|
||||
request_id VARCHAR(128) NOT NULL,
|
||||
workflow_id BIGINT,
|
||||
business_code VARCHAR(128),
|
||||
biz_callback_key VARCHAR(255),
|
||||
raw_request VARCHAR(2000),
|
||||
status VARCHAR(32),
|
||||
callback_status INTEGER,
|
||||
retry_count INTEGER DEFAULT 0,
|
||||
max_retry INTEGER,
|
||||
last_error_message VARCHAR(512),
|
||||
raw_callback VARCHAR(2000),
|
||||
last_callback_time TIMESTAMP,
|
||||
creator VARCHAR(64) DEFAULT '',
|
||||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updater VARCHAR(64) DEFAULT '',
|
||||
@@ -17,14 +24,20 @@ CREATE TABLE system_iwork_workflow_log (
|
||||
);
|
||||
|
||||
-- 添加注释
|
||||
COMMENT ON TABLE system_iwork_workflow_log IS 'iWork 流程创建日志';
|
||||
COMMENT ON TABLE system_iwork_workflow_log IS 'iWork 流程日志';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.id IS '主键';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.request_id IS 'iWork 返回的请求编号';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.request_id IS 'iWork 请求编号';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.workflow_id IS '流程模板 ID';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.business_code IS '业务编码';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.biz_callback_key IS '业务回调标识';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.raw_request IS '创建请求原始参数';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.raw_request IS '创建请求原文';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.status IS '流程状态';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.callback_status IS '回调处理状态';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.retry_count IS '已重试次数';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.max_retry IS '最大重试次数';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.last_error_message IS '最后错误信息';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.raw_callback IS '回调原文';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.last_callback_time IS '最近回调时间';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.creator IS '创建者';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.updater IS '更新者';
|
||||
@@ -33,6 +46,8 @@ COMMENT ON COLUMN system_iwork_workflow_log.deleted IS '是否删除';
|
||||
COMMENT ON COLUMN system_iwork_workflow_log.tenant_id IS '租户编号';
|
||||
|
||||
-- 创建唯一索引
|
||||
CREATE UNIQUE INDEX uk_request_id ON system_iwork_workflow_log(request_id);
|
||||
|
||||
CREATE UNIQUE INDEX uk_iwork_workflow_log_request_id ON system_iwork_workflow_log(request_id);
|
||||
|
||||
-- 创建普通索引
|
||||
-- CREATE INDEX idx_iwork_workflow_log_business_code ON system_iwork_workflow_log(business_code);
|
||||
-- CREATE INDEX idx_iwork_workflow_log_biz_callback_key ON system_iwork_workflow_log(biz_callback_key);
|
||||
@@ -1,43 +0,0 @@
|
||||
-- iWork 用印回调日志(DM8)
|
||||
-- 表:system_iwork_seal_log
|
||||
-- 序列:system_iwork_seal_log_seq
|
||||
|
||||
-- 清理旧对象(若存在)
|
||||
DROP TABLE IF EXISTS system_iwork_seal_log;
|
||||
|
||||
CREATE TABLE system_iwork_seal_log (
|
||||
id BIGINT NOT NULL,
|
||||
request_id VARCHAR(128) NOT NULL,
|
||||
business_code VARCHAR(128),
|
||||
biz_callback_key VARCHAR(255),
|
||||
status INTEGER,
|
||||
retry_count INTEGER DEFAULT 0,
|
||||
max_retry INTEGER,
|
||||
last_error_message VARCHAR(512),
|
||||
raw_callback VARCHAR(2000),
|
||||
last_callback_time DATETIME,
|
||||
creator VARCHAR(64),
|
||||
create_time DATETIME DEFAULT SYSDATE,
|
||||
updater VARCHAR(64),
|
||||
update_time DATETIME DEFAULT SYSDATE,
|
||||
deleted SMALLINT DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (request_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE system_iwork_seal_log IS 'iWork 用印回调日志';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.id IS '主键';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.request_id IS 'iWork requestId 唯一标识';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.business_code IS '业务单号';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.biz_callback_key IS '业务回调标识';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.status IS '状态枚举';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.retry_count IS '已重试次数';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.max_retry IS '最大重试次数快照';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.last_error_message IS '最后错误信息';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.raw_callback IS '回调原文截断';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.last_callback_time IS '最近回调时间';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.creator IS '创建者';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.updater IS '更新者';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.update_time IS '最后更新时间';
|
||||
COMMENT ON COLUMN system_iwork_seal_log.deleted IS '是否删除';
|
||||
@@ -14,6 +14,7 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.util.List;
|
||||
@@ -45,6 +46,7 @@ public class ZtDataPermissionAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MenuDataPermissionHandler menuDataPermissionHandler(MybatisPlusInterceptor interceptor) {
|
||||
// 创建菜单数据权限处理器
|
||||
MenuDataPermissionHandler handler = new MenuDataPermissionHandler();
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionIntercepto
|
||||
import com.zt.plat.framework.datapermission.core.menudatapermission.handler.MenuDataPermissionHandler;
|
||||
import com.zt.plat.framework.mybatis.core.util.MyBatisUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -20,6 +21,7 @@ public class MenuDataPermissionConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(MybatisPlusInterceptor.class)
|
||||
@ConditionalOnMissingBean
|
||||
public MenuDataPermissionHandler menuDataPermissionHandler(MybatisPlusInterceptor interceptor) {
|
||||
// 创建菜单数据权限处理器
|
||||
MenuDataPermissionHandler handler = new MenuDataPermissionHandler();
|
||||
|
||||
@@ -96,7 +96,6 @@ public class DeptDataPermissionRule implements DataPermissionRule {
|
||||
/**
|
||||
* 基于用户的表字段配置
|
||||
* 一般情况下,每个表的部门编号字段是 dept_id,通过该配置自定义。
|
||||
* key:表名
|
||||
* value:字段名
|
||||
*/
|
||||
private final Map<String, String> userColumns = new HashMap<>();
|
||||
@@ -262,7 +261,11 @@ public class DeptDataPermissionRule implements DataPermissionRule {
|
||||
if (Boolean.FALSE.equals(self)) {
|
||||
return null;
|
||||
}
|
||||
String columnName = userColumns.get(tableName);
|
||||
String userColumnsKey = tableName;
|
||||
if (StrUtil.isNotBlank(workCode)) {
|
||||
userColumnsKey = userColumnsKey + "_work_code";
|
||||
}
|
||||
String columnName = userColumns.get(userColumnsKey);
|
||||
if (StrUtil.isEmpty(columnName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,12 @@ public class DbSqlSessionFactory implements SessionFactory {
|
||||
// 当前系统适配 dm,如果存在 schema 为空的情况,从 connection 获取
|
||||
try {
|
||||
if (getDatabaseSchema() == null || getDatabaseSchema().length() == 0){
|
||||
setDatabaseSchema(dbSqlSession.getSqlSession().getConnection().getSchema());
|
||||
String schemaFromUrl = extractSchemaFromJdbcUrl(dbSqlSession.getSqlSession().getConnection());
|
||||
if (schemaFromUrl != null && schemaFromUrl.length() > 0) {
|
||||
setDatabaseSchema(schemaFromUrl);
|
||||
} else {
|
||||
setDatabaseSchema(dbSqlSession.getSqlSession().getConnection().getSchema());
|
||||
}
|
||||
}
|
||||
dbSqlSession.getSqlSession().getConnection().getSchema();
|
||||
} catch (SQLException e) {
|
||||
@@ -351,4 +356,39 @@ public class DbSqlSessionFactory implements SessionFactory {
|
||||
public void setUsePrefixId(boolean usePrefixId) {
|
||||
this.usePrefixId = usePrefixId;
|
||||
}
|
||||
|
||||
private String extractSchemaFromJdbcUrl(java.sql.Connection connection) {
|
||||
if (connection == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String url = connection.getMetaData().getURL();
|
||||
if (url == null || url.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
int queryIndex = url.indexOf('?');
|
||||
if (queryIndex < 0 || queryIndex == url.length() - 1) {
|
||||
return null;
|
||||
}
|
||||
String query = url.substring(queryIndex + 1);
|
||||
String[] parts = query.split("[&;]");
|
||||
for (String part : parts) {
|
||||
int eqIndex = part.indexOf('=');
|
||||
if (eqIndex <= 0 || eqIndex == part.length() - 1) {
|
||||
continue;
|
||||
}
|
||||
String key = part.substring(0, eqIndex).trim().toLowerCase(Locale.ROOT);
|
||||
if ("schema".equals(key) || "currentschema".equals(key) || "current_schema".equals(key)) {
|
||||
String value = part.substring(eqIndex + 1).trim();
|
||||
if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
|
||||
value = value.substring(1, value.length() - 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch (SQLException ignored) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.error;
|
||||
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||
import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static com.zt.plat.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;
|
||||
@@ -52,13 +53,13 @@ public class FileController {
|
||||
private FileService fileService;
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获取文件预览地址", description = "根据 fileId 返回文件预览 url(kkfile),支持加密文件预览,需要传递验证码 code,加密文件预览地址默认5分钟内有效,可在配置文件中添加zt.file.preview-expire-seconds配置")
|
||||
@Operation(summary = "获取文件预览地址", description = "根据 fileId 返回文件预览 url(kkfile),支持加密文件预览,加密文件预览地址默认5分钟内有效,可在配置文件中添加zt.file.preview-expire-seconds配置有效时间")
|
||||
public CommonResult<FileRespVO> getPreviewUrl(@RequestParam("fileId") Long fileId,
|
||||
@RequestParam(value = "code", required = false) String code,
|
||||
HttpServletRequest request) throws Exception {
|
||||
FileDO fileDO = fileService.getActiveFileById(fileId);
|
||||
if (fileDO == null) {
|
||||
return CommonResult.error(HttpStatus.NOT_FOUND.value(), "文件不存在");
|
||||
return error(HttpStatus.NOT_FOUND.value(), "文件不存在");
|
||||
}
|
||||
|
||||
// 统计下载次数
|
||||
@@ -68,26 +69,24 @@ public class FileController {
|
||||
FileRespVO fileRespVO = BeanUtils.toBean(fileDO, FileRespVO.class);
|
||||
|
||||
// 加密文件:塞入“临时解密预览 URL”
|
||||
if (Boolean.TRUE.equals(fileRespVO.getIsEncrypted())) { // FileDO 通过 aesIv 判断加密
|
||||
if (Boolean.TRUE.equals(fileRespVO.getIsEncrypted()) // FileDO 通过 aesIv 判断加密
|
||||
&& cn.hutool.core.util.StrUtil.isNotBlank(code)) { // 预览文件会调用两次该接口,只有code不为空时候才塞url
|
||||
|
||||
if (cn.hutool.core.util.StrUtil.isBlank(code)) {
|
||||
/*if (cn.hutool.core.util.StrUtil.isBlank(code)) {
|
||||
return CommonResult.error(HttpStatus.BAD_REQUEST.value(), "加密文件预览需要验证码 code");
|
||||
}
|
||||
}*/
|
||||
|
||||
// 验证通过:发放给 kkfile 用的短期 token(kkfile 不带登录态)
|
||||
Long userId = getLoginUserId();
|
||||
boolean flag = fileService.verifyCode(fileId, userId, code);
|
||||
if(!flag){
|
||||
return CommonResult.customize(null, HttpStatus.INTERNAL_SERVER_ERROR.value(), "验证码错误");
|
||||
return error(HttpStatus.BAD_REQUEST.value(), "验证码错误");
|
||||
}
|
||||
|
||||
String token = fileService.generatePreviewToken(fileId, userId);
|
||||
|
||||
String baseUrl = buildPublicBaseUrl(request); // 见下方函数
|
||||
|
||||
String fullfilename = java.net.URLEncoder
|
||||
.encode(fileDO.getName(), java.nio.charset.StandardCharsets.UTF_8)
|
||||
.replace("+", "%20");
|
||||
|
||||
String decryptUrl = baseUrl + "/admin-api/infra/file/preview-decrypt"
|
||||
+ "?fileId=" + fileId
|
||||
+ "&token=" + token
|
||||
@@ -215,14 +214,14 @@ public class FileController {
|
||||
try {
|
||||
sendTypeEnum = VerifyCodeSendType.valueOf(sendType.trim().toUpperCase());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return CommonResult.error(HttpStatus.BAD_REQUEST.value(),
|
||||
return error(HttpStatus.BAD_REQUEST.value(),
|
||||
"sendType 参数不合法,可选:SMS / E_OFFICE");
|
||||
}
|
||||
}
|
||||
|
||||
FileDO activeFileById = fileService.getActiveFileById(fileId);
|
||||
if (activeFileById == null) {
|
||||
return CommonResult.error(HttpStatus.NOT_FOUND.value(), "文件不存在");
|
||||
return error(HttpStatus.NOT_FOUND.value(), "文件不存在");
|
||||
}
|
||||
|
||||
FileRespVO fileRespVO = BeanUtils.toBean(activeFileById, FileRespVO.class);
|
||||
|
||||
@@ -229,7 +229,6 @@ zt:
|
||||
- system_seq_dtl
|
||||
- system_seq_rcd
|
||||
- system_sync_log
|
||||
- system_iwork_seal_log
|
||||
ignore-caches:
|
||||
- user_role_ids
|
||||
- permission_menu_ids
|
||||
|
||||
@@ -3,10 +3,11 @@ package com.zt.plat.module.system.controller.admin.integration.iwork;
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.framework.tenant.core.aop.TenantIgnore;
|
||||
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.*;
|
||||
import com.zt.plat.module.system.service.integration.iwork.IWorkCallbackLogService;
|
||||
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
|
||||
import com.zt.plat.module.system.service.integration.iwork.IWorkOrgRestService;
|
||||
import com.zt.plat.module.system.service.integration.iwork.IWorkSyncService;
|
||||
import com.zt.plat.module.system.service.integration.iwork.IWorkWorkflowLogService;
|
||||
import com.zt.plat.module.system.dal.dataobject.iwork.IWorkWorkflowLogDO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -37,7 +38,7 @@ public class IWorkIntegrationController {
|
||||
private final IWorkIntegrationService integrationService;
|
||||
private final IWorkOrgRestService orgRestService;
|
||||
private final IWorkSyncService syncService;
|
||||
private final IWorkCallbackLogService callbackLogService;
|
||||
private final IWorkWorkflowLogService workflowLogService;
|
||||
|
||||
@PostMapping("/auth/register")
|
||||
@Operation(summary = "注册 iWork 凭证,获取服务端公钥与 secret")
|
||||
@@ -99,17 +100,17 @@ public class IWorkIntegrationController {
|
||||
|
||||
@PreAuthorize("@ss.hasPermission('system:iwork:log:query')")
|
||||
@PostMapping("/log/page")
|
||||
@Operation(summary = "iWork 回调日志分页查询")
|
||||
@Operation(summary = "iWork 流程日志分页查询")
|
||||
public CommonResult<com.zt.plat.framework.common.pojo.PageResult<IWorkCallbackLogRespVO>> pageLogs(@Valid @RequestBody IWorkCallbackLogPageReqVO reqVO) {
|
||||
com.zt.plat.framework.common.pojo.PageResult<com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO> page = callbackLogService.page(reqVO);
|
||||
com.zt.plat.framework.common.pojo.PageResult<IWorkWorkflowLogDO> page = workflowLogService.page(reqVO);
|
||||
java.util.List<IWorkCallbackLogRespVO> mapped = new java.util.ArrayList<>();
|
||||
for (com.zt.plat.module.system.dal.dataobject.iwork.IWorkSealLogDO log : page.getList()) {
|
||||
for (IWorkWorkflowLogDO log : page.getList()) {
|
||||
IWorkCallbackLogRespVO vo = new IWorkCallbackLogRespVO();
|
||||
vo.setId(log.getId());
|
||||
vo.setRequestId(log.getRequestId());
|
||||
vo.setBusinessCode(log.getBusinessCode());
|
||||
vo.setBizCallbackKey(log.getBizCallbackKey());
|
||||
vo.setStatus(log.getStatus());
|
||||
vo.setStatus(log.getCallbackStatus());
|
||||
vo.setRetryCount(log.getRetryCount());
|
||||
vo.setMaxRetry(log.getMaxRetry());
|
||||
vo.setLastErrorMessage(log.getLastErrorMessage());
|
||||
@@ -126,7 +127,7 @@ public class IWorkIntegrationController {
|
||||
@PostMapping("/log/retry")
|
||||
@Operation(summary = "iWork 回调手工重试")
|
||||
public CommonResult<Boolean> retry(@Valid @RequestBody IWorkWorkflowVoidReqVO reqVO) {
|
||||
callbackLogService.resetAndDispatch(reqVO.getRequestId());
|
||||
workflowLogService.resetAndDispatch(reqVO.getRequestId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user