Merge branch 'dev' into 'test'

重写手动针对用户以及组织的单条同步逻辑

See merge request jygk/dsc!29
This commit is contained in:
朝锦 杨
2026-02-02 08:36:22 +00:00
8 changed files with 580 additions and 19 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -77,8 +77,13 @@ public class DbSqlSessionFactory implements SessionFactory {
// 当前系统适配 dm,如果存在 schema 为空的情况,从 connection 获取
try {
if (getDatabaseSchema() == null || getDatabaseSchema().length() == 0){
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) {
throw new RuntimeException(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;
}
}

View File

@@ -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 返回文件预览 urlkkfile支持加密文件预览需要传递验证码 code加密文件预览地址默认5分钟内有效可在配置文件中添加zt.file.preview-expire-seconds配置")
@Operation(summary = "获取文件预览地址", description = "根据 fileId 返回文件预览 urlkkfile支持加密文件预览加密文件预览地址默认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 用的短期 tokenkkfile 不带登录态)
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);

View File

@@ -24,6 +24,7 @@ public class DataPermissionConfiguration {
rule.addDeptColumn(DeptDO.class, "id");
// user
rule.addUserColumn(AdminUserDO.class, "id");
rule.addUserColumn("system_users_work_code", "workcode");
};
}

View File

@@ -47,14 +47,14 @@ spring:
primary: master
datasource:
master:
url: jdbc:dm://172.16.46.247:1050?schema=RUOYI-VUE-PRO
url: jdbc:dm://172.17.11.98:20870?schema=JYGK_TEST
username: SYSDBA
password: pgbsci6ddJ6Sqj@e
password: P@ssword25
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度
url: jdbc:dm://172.16.46.247:1050?schema=RUOYI-VUE-PRO
url: jdbc:dm://172.17.11.98:20870?schema=JYGK_TEST
username: SYSDBA
password: pgbsci6ddJ6Sqj@e
password: P@ssword25
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data: