【v3.8.3版本发布】

Merge remote-tracking branch 'origin/springboot3' into springboot3_sas

# Conflicts:
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/CommonAPI.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/LoginUser.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/filters/JwtFilter.java
#	jeecg-boot/jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java
#	jeecg-boot/jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/api/controller/SystemApiController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysLogController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTenantController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserAgentController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysDataLog.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantPackServiceImpl.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserDepartServiceImpl.java
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-docker.yml
#	jeecg-boot/pom.xml
This commit is contained in:
JEECG
2025-09-24 18:24:19 +08:00
336 changed files with 12900 additions and 84893 deletions

View File

@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.8.2</version>
<groupId>org.jeecgframework.boot3</groupId>
<version>3.8.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,6 +2,7 @@ package org.jeecg.common.system.api;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
@ -681,7 +682,7 @@ public interface ISysBaseAPI extends CommonAPI {
* @return
*/
@GetMapping("/sys/api/getRoleCode")
String getRoleCodeById(String id);
String getRoleCodeById(@RequestParam(name = "id") String id);
/**
* 根据roleCode查询角色信息可逗号分隔多个
@ -709,7 +710,7 @@ public interface ISysBaseAPI extends CommonAPI {
* @return JSONObject
*/
@GetMapping("/sys/api/queryUserById")
JSONObject queryUserById(String id);
JSONObject queryUserById(@RequestParam(name="id") String id);
/**
@ -770,7 +771,7 @@ public interface ISysBaseAPI extends CommonAPI {
* @return
*/
@GetMapping("/sys/api/queryUserIdsByPositionIds")
List<String> queryUserIdsByPositionIds(List<String> positionIds);
List<String> queryUserIdsByPositionIds(@RequestParam("positionIds") List<String> positionIds);
/**
* 根据部门和子部门下的所有用户账号
@ -815,6 +816,59 @@ public interface ISysBaseAPI extends CommonAPI {
@RequestParam(value = "currentUserName") String currentUserName
);
/**
* 根据部门编码查询公司信息
* @param orgCode 部门编码
* @return
* @author chenrui
* @date 2025/8/12 14:45
*/
@GetMapping(value = "/sys/api/queryCompByOrgCode")
SysDepartModel queryCompByOrgCode(@RequestParam(name = "sysCode") String orgCode);
/**
* 根据部门编码和层次查询上级公司
*
* @param orgCode 部门编码
* @param level 可以传空 默认为1级 最小值为1
* @return
*/
@GetMapping(value = "/sys/api/queryCompByOrgCodeAndLevel")
SysDepartModel queryCompByOrgCodeAndLevel(@RequestParam("orgCode") String orgCode, @RequestParam("level") Integer level);
/**
* 16 运行AIRag流程
* for [QQYUN-13634]在baseapi里面封装方法方便其他模块调用
*
* @param airagFlowDTO
* @return 流程执行结果,可能是String或者Map
* @author chenrui
* @date 2025/9/2 11:43
*/
@PostMapping(value = "/sys/api/runAiragFlow")
Object runAiragFlow(@RequestBody AiragFlowDTO airagFlowDTO);
/**
* 根据部门code或部门id获取部门名称(当前和上级部门)
*
* @param orgCode 部门编码
* @param depId 部门id
* @return String 部门名称
*/
@GetMapping("/getDepartPathNameByOrgCode")
String getDepartPathNameByOrgCode(@RequestParam(name = "orgCode", required = false) String orgCode, @RequestParam(name = "depId", required = false) String depId);
/**
* 根据部门ID查询部门及其子部门下用户ID <br/>
* @param deptIds
* @return
* @author chenrui
* @date 2025/09/08 15:28
*/
@GetMapping("/sys/api/queryUserIdsByCascadeDeptIds")
List<String> queryUserIdsByCascadeDeptIds(@RequestParam("deptIds") List<String> deptIds);
@GetMapping("/sys/api/getUserByPhone")
public LoginUser getUserByPhone(@RequestParam("phone") String phone);

View File

@ -3,6 +3,7 @@ package org.jeecg.common.system.api.fallback;
import com.alibaba.fastjson.JSONObject;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
@ -475,6 +476,31 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
}
@Override
public SysDepartModel queryCompByOrgCode(String orgCode) {
return null;
}
@Override
public SysDepartModel queryCompByOrgCodeAndLevel(String orgCode, Integer level) {
return null;
}
@Override
public Object runAiragFlow(AiragFlowDTO airagFlowDTO) {
return null;
}
@Override
public String getDepartPathNameByOrgCode(String orgCode, String depId) {
return "";
}
@Override
public List<String> queryUserIdsByCascadeDeptIds(List<String> deptIds) {
return null;
}
@Override
public LoginUser getUserByPhone(String phone) {
return null;

View File

@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.8.2</version>
<groupId>org.jeecgframework.boot3</groupId>
<version>3.8.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,12 +2,14 @@ package org.jeecg.common.system.api;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
import org.jeecg.common.constant.enums.DySmsEnum;
import org.jeecg.common.constant.enums.EmailTemplateEnum;
import org.jeecg.common.system.vo.*;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.Map;
@ -504,6 +506,14 @@ public interface ISysBaseAPI extends CommonAPI {
* @return
*/
List<String> queryUserIdsByDeptIds(List<String> deptIds);
/**
* 根据部门ID查询部门及其子部门下用户ID <br/>
* @param deptIds
* @return
*/
List<String> queryUserIdsByCascadeDeptIds(List<String> deptIds);
/**
* 根据部门ID查询用户账号
@ -557,4 +567,42 @@ public interface ISysBaseAPI extends CommonAPI {
* @param currentUserName
*/
void announcementAutoRelease(String dataId, String currentUserName);
/**
* 根据部门编码查询公司信息
* @param orgCode 部门编码
* @return
* @author chenrui
* @date 2025/8/12 14:53
*/
SysDepartModel queryCompByOrgCode(@RequestParam(name = "sysCode") String orgCode);
/**
* 根据部门编码和层次查询上级公司
*
* @param orgCode 部门编码
* @param level 可以传空 默认为1级 最小值为1
* @return
*/
SysDepartModel queryCompByOrgCodeAndLevel(String orgCode, Integer level);
/**
* 16 运行AIRag流程
* for [QQYUN-13634]在baseapi里面封装方法方便其他模块调用
*
* @param airagFlowDTO
* @return 流程执行结果,可能是String或者Map
* @author chenrui
* @date 2025/9/2 11:43
*/
Object runAiragFlow(AiragFlowDTO airagFlowDTO);
/**
* 根据部门code或部门id获取部门名称(当前和上级部门)
*
* @param orgCode 部门编码
* @param depId 部门id
* @return String 部门名称
*/
String getDepartPathNameByOrgCode(String orgCode, String depId);
}

View File

@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jeecg-module-system</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.8.2</version>
<groupId>org.jeecgframework.boot3</groupId>
<version>3.8.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
</dependencies>

View File

@ -2,9 +2,9 @@
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">
<parent>
<groupId>org.jeecgframework.boot</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-module-system</artifactId>
<version>3.8.2</version>
<version>3.8.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -12,7 +12,7 @@
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-system-local-api</artifactId>
</dependency>
<dependency>
@ -26,7 +26,7 @@
<!-- AI大模型管理 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-boot-module-airag</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
@ -69,7 +69,7 @@
</dependency>
<!-- AI大模型管理 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jeecg-boot-module-airag</artifactId>
<version>${jeecgboot.version}</version>
</dependency>

View File

@ -0,0 +1,30 @@
package org.jeecg.config.init;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* Shiro缓存清理
* 在应用启动时清除所有的Shiro授权缓存
* 主要用于解决重启项目,用户未重新登录,按钮权限不生效的问题
*/
@Slf4j
@Component
public class ShiroCacheClearRunner implements ApplicationRunner {
@Autowired
private RedisUtil redisUtil;
@Override
public void run(ApplicationArguments args) {
// 清空所有授权redis缓存
log.info("——— Service restart, clearing all user shiro authorization cache ——— ");
redisUtil.removeAll(CommonConstant.PREFIX_USER_SHIRO_CACHE);
}
}

View File

@ -1,33 +1,33 @@
//package org.jeecg.config.init;
//
//import org.apache.catalina.Context;
//import org.apache.tomcat.util.scan.StandardJarScanner;
//import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
///**
// * @Description: TomcatFactoryConfig
// * @author: scott
// * @date: 2021年01月25日 11:40
// */
//@Configuration
//public class TomcatFactoryConfig {
// /**
// * tomcat-embed-jasper引用后提示jar找不到的问题
// */
// @Bean
// public TomcatServletWebServerFactory tomcatFactory() {
// TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
// @Override
// protected void postProcessContext(Context context) {
// ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
// }
// };
// factory.addConnectorCustomizers(connector -> {
// connector.setProperty("relaxedPathChars", "[]{}");
// connector.setProperty("relaxedQueryChars", "[]{}");
// });
// return factory;
// }
//}
package org.jeecg.config.init;
import org.apache.catalina.Context;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: TomcatFactoryConfig
* @author: scott
* @date: 2021年01月25日 11:40
*/
@Configuration
public class TomcatFactoryConfig {
/**
* tomcat-embed-jasper引用后提示jar找不到的问题
*/
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
}
};
factory.addConnectorCustomizers(connector -> {
connector.setProperty("relaxedPathChars", "[]{}");
connector.setProperty("relaxedQueryChars", "[]{}");
});
return factory;
}
}

View File

@ -1,48 +1,48 @@
package org.jeecg.config.init;
import io.undertow.UndertowOptions;
import io.undertow.server.DefaultByteBufferPool;
import io.undertow.server.handlers.BlockingHandler;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.jeecg.modules.monitor.actuator.undertow.CustomUndertowMetricsHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
/**
* Undertow配置
*
* 解决启动提示: WARN io.undertow.websockets.jsr:68 - UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used
*/
@Configuration
public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
/**
* 自定义undertow监控指标工具类
* for [QQYUN-11902]tomcat 替换undertow 这里的功能还没修改
*/
@Autowired
private CustomUndertowMetricsHandler customUndertowMetricsHandler;
@Override
public void customize(UndertowServletWebServerFactory factory) {
// 设置 Undertow 服务器参数(底层网络配置)
factory.addBuilderCustomizers(builder -> {
builder.setServerOption(UndertowOptions.MAX_HEADER_SIZE, 65536); // header 最大64KB
builder.setServerOption(UndertowOptions.MAX_PARAMETERS, 10000); // 最大参数数
});
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
// 设置合理的参数
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 8192));
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
// 添加自定义 监控 handler
deploymentInfo.addInitialHandlerChainWrapper(next -> new BlockingHandler(customUndertowMetricsHandler.wrap(next)));
});
}
}
//package org.jeecg.config.init;
//
//import io.undertow.UndertowOptions;
//import io.undertow.server.DefaultByteBufferPool;
//import io.undertow.server.handlers.BlockingHandler;
//import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
//import org.jeecg.modules.monitor.actuator.undertow.CustomUndertowMetricsHandler;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
//import org.springframework.boot.web.server.WebServerFactoryCustomizer;
//import org.springframework.context.annotation.Configuration;
//
///**
// * Undertow配置
// *
// * 解决启动提示: WARN io.undertow.websockets.jsr:68 - UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used
// */
//@Configuration
//public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
//
// /**
// * 自定义undertow监控指标工具类
// * for [QQYUN-11902]tomcat 替换undertow 这里的功能还没修改
// */
// @Autowired
// private CustomUndertowMetricsHandler customUndertowMetricsHandler;
//
// @Override
// public void customize(UndertowServletWebServerFactory factory) {
// // 设置 Undertow 服务器参数(底层网络配置)
// factory.addBuilderCustomizers(builder -> {
// builder.setServerOption(UndertowOptions.MAX_HEADER_SIZE, 65536); // header 最大64KB
// builder.setServerOption(UndertowOptions.MAX_PARAMETERS, 10000); // 最大参数数
// });
// factory.addDeploymentInfoCustomizers(deploymentInfo -> {
//
// WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
//
// // 设置合理的参数
// webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 8192));
//
// deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
//
// // 添加自定义 监控 handler
// deploymentInfo.addInitialHandlerChainWrapper(next -> new BlockingHandler(customUndertowMetricsHandler.wrap(next)));
// });
// }
//}

View File

@ -0,0 +1,258 @@
package org.jeecg.modules.airag;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import dev.langchain4j.agent.tool.JsonSchemaProperty;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.service.tool.ToolExecutor;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.airag.llm.handler.JeecgToolsProvider;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.controller.SysUserController;
import org.jeecg.modules.system.entity.SysRole;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* for [QQYUN-13565]【AI助手】新增创建用户和查询用户的工具扩展
* @Description: jeecg llm工具提供者
* @Author: chenrui
* @Date: 2025/8/26 18:06
*/
@Component
public class JeecgBizToolsProvider implements JeecgToolsProvider {
@Autowired
SysUserController sysUserController;
@Autowired
SysUserMapper userMapper;
@Autowired
private BaseCommonService baseCommonService;
@Autowired
private org.jeecg.modules.system.service.ISysRoleService sysRoleService;
@Autowired
private org.jeecg.modules.system.service.ISysUserRoleService sysUserRoleService;
@Autowired
private org.jeecg.modules.system.service.ISysUserService sysUserService;
public Map<ToolSpecification, ToolExecutor> getDefaultTools(){
Map<ToolSpecification, ToolExecutor> tools = new HashMap<>();
JeecgLlmTools userTool = queryUserTool();
tools.put(userTool.getToolSpecification(), userTool.getToolExecutor());
JeecgLlmTools addUser = addUserTool();
tools.put(addUser.getToolSpecification(), addUser.getToolExecutor());
// 新增:查询所有角色
JeecgLlmTools queryRoles = queryAllRolesTool();
tools.put(queryRoles.getToolSpecification(), queryRoles.getToolExecutor());
// 新增:给用户授予角色
JeecgLlmTools grantRoles = grantUserRolesTool();
tools.put(grantRoles.getToolSpecification(), grantRoles.getToolExecutor());
return tools;
}
/**
* 添加用户
* @return
* @author chenrui
* @date 2025/8/27 09:51
*/
private JeecgLlmTools addUserTool(){
ToolSpecification toolSpecification = ToolSpecification.builder()
.name("add_user")
.description("添加用户,返回添加结果;" +
"\n\n - 缺少必要字段时,请向用户索要." +
"\n\n - 你应该提前判断用户的输入是否合法,比如用户名是否符合规范,手机号和邮箱是否正确等." +
"\n\n - 提前使用用户名查询用户是否存在,如果存在则不能添加." +
"\n\n - 添加成功后返回成功消息,如果失败则返回失败原因." +
"\n\n - 用户名,工号,邮箱,手机号均要求唯一,提前通过查询用户工具确认唯一性." )
.addParameter("username", JsonSchemaProperty.STRING, JsonSchemaProperty.description("用户名,必填,只允许使用字母、数字、下划线,且必须以字母开头,唯一"))
.addParameter("password", JsonSchemaProperty.STRING, JsonSchemaProperty.description("用户密码,必填"))
.addParameter("realname", JsonSchemaProperty.STRING, JsonSchemaProperty.description("真实姓名,必填"))
.addParameter("workNo", JsonSchemaProperty.STRING, JsonSchemaProperty.description("工号,必填,唯一"))
.addParameter("email", JsonSchemaProperty.STRING, JsonSchemaProperty.description("邮箱,必填,唯一"))
.addParameter("phone", JsonSchemaProperty.STRING, JsonSchemaProperty.description("手机号,必填,唯一"))
.build();
ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> {
JSONObject arguments = JSONObject.parseObject(toolExecutionRequest.arguments());
arguments.put("confirmPassword",arguments.get("password"));
arguments.put("userIdentity",1);
arguments.put("activitiSync",1);
arguments.put("departIds","");
String selectedRoles = arguments.getString("selectedroles");
String selectedDeparts = arguments.getString("selecteddeparts");
String msg = "添加用户失败";
try {
SysUser user = JSON.parseObject(arguments.toJSONString(), SysUser.class);
user.setCreateTime(new Date());//设置创建时间
String salt = oConvertUtils.randomGen(8);
user.setSalt(salt);
String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt);
user.setPassword(passwordEncode);
user.setStatus(1);
user.setDelFlag(CommonConstant.DEL_FLAG_0);
//用户表字段org_code不能在这里设置他的值
user.setOrgCode(null);
// 保存用户走一个service 保证事务
//获取租户ids
String relTenantIds = arguments.getString("relTenantIds");
sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds, false);
baseCommonService.addLog("添加用户username " +user.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
msg = "添加用户成功";
// 用户变更,触发同步工作流
} catch (Exception e) {
msg = "添加用户失败";
}
return msg;
};
return new JeecgLlmTools(toolSpecification,toolExecutor);
}
/**
* 查询用户信息
*
* @return 用户列表JSON字符串
* @author chenrui
* @date 2025/8/26 18:52
*/
private JeecgLlmTools queryUserTool() {
ToolSpecification toolSpecification = ToolSpecification.builder()
.name("query_user_by_name")
.description("查询用户详细信息返回json数组。支持用户名、真实姓名、邮箱、手机号、工号多字段组合查询用户名、真实姓名、邮箱、手机号均为模糊查询工号为精确查询。无条件则返回全部用户。")
.addParameter("username", JsonSchemaProperty.STRING, JsonSchemaProperty.description("用户名"))
.addParameter("realname", JsonSchemaProperty.STRING, JsonSchemaProperty.description("真实姓名"))
.addParameter("email", JsonSchemaProperty.STRING, JsonSchemaProperty.description("电子邮件"))
.addParameter("phone", JsonSchemaProperty.STRING, JsonSchemaProperty.description("手机号"))
.addParameter("workNo", JsonSchemaProperty.STRING, JsonSchemaProperty.description("工号"))
.build();
ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> {
SysUser args = JSONObject.parseObject(toolExecutionRequest.arguments(), SysUser.class);
QueryWrapper<SysUser> qw = new QueryWrapper<>();
if (StringUtils.isNotBlank(args.getUsername())) {
qw.like("username", args.getUsername());
}
if (StringUtils.isNotBlank(args.getRealname())) {
qw.like("realname", args.getRealname());
}
if (StringUtils.isNotBlank(args.getEmail())) {
qw.like("email", args.getEmail());
}
if (StringUtils.isNotBlank(args.getPhone())) {
qw.like("phone", args.getPhone());
}
if (StringUtils.isNotBlank(args.getWorkNo())) {
qw.eq("work_no", args.getWorkNo());
}
qw.eq("del_flag", 0);
List<SysUser> users = userMapper.selectList(qw);
users.forEach(u -> { u.setPassword(null); u.setSalt(null); });
return JSONObject.toJSONString(users);
};
return new JeecgLlmTools(toolSpecification, toolExecutor);
}
/**
* 查询所有角色
* @return
* @author chenrui
* @date 2025/8/27 09:52
*/
private JeecgLlmTools queryAllRolesTool() {
ToolSpecification spec = ToolSpecification.builder()
.name("query_all_roles")
.description("查询所有角色返回json数组。包含字段id、roleName、roleCode默认按创建时间/排序号规则由后端决定。")
.addParameter("roleName", JsonSchemaProperty.STRING, JsonSchemaProperty.description("角色姓名"))
.addParameter("roleCode", JsonSchemaProperty.STRING, JsonSchemaProperty.description("角色编码"))
.build();
ToolExecutor exec = (toolExecutionRequest, memoryId) -> {
// 做租户隔离查询(若开启)
SysRole sysRole = JSONObject.parseObject(toolExecutionRequest.arguments(), SysRole.class);
QueryWrapper<SysRole> qw = Wrappers.query();
if (StringUtils.isNotBlank(sysRole.getRoleName())) {
qw.like("role_name", sysRole.getRoleName());
}
if (StringUtils.isNotBlank(sysRole.getRoleCode())) {
qw.like("role_code", sysRole.getRoleCode());
}
// 未删除
List<org.jeecg.modules.system.entity.SysRole> roles = sysRoleService.list(qw);
// 仅返回核心字段
JSONArray arr = new JSONArray();
for (org.jeecg.modules.system.entity.SysRole r : roles) {
JSONObject o = new JSONObject();
o.put("id", r.getId());
o.put("roleName", r.getRoleName());
o.put("roleCode", r.getRoleCode());
arr.add(o);
}
return arr.toJSONString();
};
return new JeecgLlmTools(spec, exec);
}
/**
* 给用户授予角色
* @return
* @author chenrui
* @date 2025/8/27 09:52
*/
private JeecgLlmTools grantUserRolesTool() {
ToolSpecification spec = ToolSpecification.builder()
.name("grant_user_roles")
.description("给用户授予角色,支持一次授予多个角色;如果关系已存在则跳过。返回授予结果统计。")
.addParameter("userId", JsonSchemaProperty.STRING, JsonSchemaProperty.description("用户ID必填"))
.addParameter("roleIds", JsonSchemaProperty.STRING, JsonSchemaProperty.description("角色ID列表必填使用英文逗号分隔"))
.build();
ToolExecutor exec = (toolExecutionRequest, memoryId) -> {
JSONObject args = JSONObject.parseObject(toolExecutionRequest.arguments());
String userId = args.getString("userId");
String roleIdsStr = args.getString("roleIds");
if (org.apache.commons.lang3.StringUtils.isAnyBlank(userId, roleIdsStr)) {
return "参数缺失userId 或 roleIds";
}
org.jeecg.modules.system.entity.SysUser user = sysUserService.getById(userId);
if (user == null) {
return "用户不存在:" + userId;
}
String[] roleIds = roleIdsStr.split(",");
int added = 0, existed = 0, invalid = 0;
for (String roleId : roleIds) {
roleId = roleId.trim();
if (roleId.isEmpty()) continue;
org.jeecg.modules.system.entity.SysRole role = sysRoleService.getById(roleId);
if (role == null) { invalid++; continue; }
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<org.jeecg.modules.system.entity.SysUserRole> q = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
q.eq("role_id", roleId).eq("user_id", userId);
org.jeecg.modules.system.entity.SysUserRole one = sysUserRoleService.getOne(q);
if (one == null) {
org.jeecg.modules.system.entity.SysUserRole rel = new org.jeecg.modules.system.entity.SysUserRole(userId, roleId);
boolean ok = sysUserRoleService.save(rel);
if (ok) { added++; } else { invalid++; }
} else {
existed++;
}
}
return String.format("授予完成:新增%d已存在%d无效/失败%d", added, existed, invalid);
};
return new JeecgLlmTools(spec, exec);
}
}

View File

@ -2,6 +2,7 @@ package org.jeecg.modules.api.controller;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
@ -1038,5 +1039,63 @@ public class SystemApiController {
public JSONObject setLoginTenant(@RequestParam("username") String username) {
return sysBaseApi.setLoginTenant(username);
}
/**
* 根据部门编码查询公司信息
* @param orgCode 部门编码
* @return
* @author chenrui
* @date 2025/8/12 14:45
*/
@GetMapping(value = "/queryCompByOrgCode")
SysDepartModel queryCompByOrgCode(@RequestParam(name = "sysCode") String orgCode) {
return sysBaseApi.queryCompByOrgCode(orgCode);
}
/**
* 根据部门编码和层次查询上级公司
*
* @param orgCode 部门编码
* @param level 可以传空 默认为1级 最小值为1
* @return
*/
@GetMapping(value = "/queryCompByOrgCodeAndLevel")
SysDepartModel queryCompByOrgCodeAndLevel(@RequestParam("orgCode") String orgCode, @RequestParam("level") Integer level){
return sysBaseApi.queryCompByOrgCodeAndLevel(orgCode,level);
}
/**
* 运行AIRag流程
* for [QQYUN-13634]在baseapi里面封装方法方便其他模块调用
* @param airagFlowDTO
* @return 流程执行结果,可能是String或者Map
* @return
*/
@PostMapping(value = "/runAiragFlow")
Object runAiragFlow(@RequestBody AiragFlowDTO airagFlowDTO) {
return sysBaseApi.runAiragFlow(airagFlowDTO);
}
/**
* 根据部门code或部门id获取部门名称(当前和上级部门)
*
* @param orgCode 部门编码
* @param depId 部门id
* @return String 部门名称
*/
@GetMapping(value = "/getDepartPathNameByOrgCode")
String getDepartPathNameByOrgCode(@RequestParam(name = "orgCode", required = false) String orgCode, @RequestParam(name = "depId", required = false) String depId) {
return sysBaseApi.getDepartPathNameByOrgCode(orgCode, depId);
}
/**
* 根据部门ID查询用户ID
* @param deptIds
* @return
*/
@GetMapping("/queryUserIdsByCascadeDeptIds")
public List<String> queryUserIdsByCascadeDeptIds(@RequestParam("deptIds") List<String> deptIds){
return sysBaseApi.queryUserIdsByCascadeDeptIds(deptIds);
}
}

View File

@ -1,90 +1,88 @@
package org.jeecg.modules.monitor.actuator.undertow;
import io.micrometer.core.instrument.MeterRegistry;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.session.*;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
/**
* 自定义undertow监控指标工具类
* for [QQYUN-11902]tomcat 替换undertow 这里的功能还没修改
* @author chenrui
* @date 2025/4/8 19:06
*/
@Component("jeecgCustomUndertowMetricsHandler")
public class CustomUndertowMetricsHandler {
// 用于统计已创建的 session 数量
private final LongAdder sessionsCreated = new LongAdder();
// 用于统计已销毁的 session 数量
private final LongAdder sessionsExpired = new LongAdder();
// 当前活跃的 session 数量
private final AtomicInteger activeSessions = new AtomicInteger();
// 历史最大活跃 session 数
private final AtomicInteger maxActiveSessions = new AtomicInteger();
// Undertow 内存 session 管理器(用于创建与管理 session
private final InMemorySessionManager sessionManager = new InMemorySessionManager("undertow-session-manager");
// 使用 Cookie 存储 session ID
private final SessionConfig sessionConfig = new SessionCookieConfig();
/**
* 构造函数
* @param meterRegistry
* @author chenrui
* @date 2025/4/8 19:07
*/
public CustomUndertowMetricsHandler(MeterRegistry meterRegistry) {
// 注册 Micrometer 指标
meterRegistry.gauge("undertow.sessions.created", sessionsCreated, LongAdder::longValue);
meterRegistry.gauge("undertow.sessions.expired", sessionsExpired, LongAdder::longValue);
meterRegistry.gauge("undertow.sessions.active.current", activeSessions, AtomicInteger::get);
meterRegistry.gauge("undertow.sessions.active.max", maxActiveSessions, AtomicInteger::get);
// 添加 session 生命周期监听器,统计 session 创建与销毁
sessionManager.registerSessionListener(new SessionListener() {
@Override
public void sessionCreated(Session session, HttpServerExchange exchange) {
sessionsCreated.increment();
int now = activeSessions.incrementAndGet();
maxActiveSessions.getAndUpdate(max -> Math.max(max, now));
}
@Override
public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
sessionsExpired.increment();
activeSessions.decrementAndGet();
}
});
}
/**
* 包装 Undertow 的 HttpHandler实现 session 自动创建逻辑
* @param next
* @return
* @author chenrui
* @date 2025/4/8 19:07
*/
public HttpHandler wrap(HttpHandler next) {
return exchange -> {
// 获取当前 session如果不存在则创建
Session session = sessionManager.getSession(exchange, sessionConfig);
if (session == null) {
try {
sessionManager.createSession(exchange, sessionConfig);
} catch (Exception e) {}
}
// 执行下一个 Handler
next.handleRequest(exchange);
};
}
}
//package org.jeecg.modules.monitor.actuator.undertow;
//
//import io.micrometer.core.instrument.MeterRegistry;
//import io.undertow.server.HttpHandler;
//import io.undertow.server.HttpServerExchange;
//import io.undertow.server.session.*;
//import org.springframework.stereotype.Component;
//
//import java.util.concurrent.atomic.AtomicInteger;
//import java.util.concurrent.atomic.LongAdder;
//
///**
// * 自定义undertow监控指标工具类
// * for [QQYUN-11902]tomcat 替换undertow 这里的功能还没修改
// * @author chenrui
// * @date 2025/4/8 19:06
// */
//@Component("jeecgCustomUndertowMetricsHandler")
//public class CustomUndertowMetricsHandler {
//
// // 用于统计已创建的 session 数量
// private final LongAdder sessionsCreated = new LongAdder();
//
// // 用于统计已销毁的 session 数量
// private final LongAdder sessionsExpired = new LongAdder();
//
// // 当前活跃的 session 数量
// private final AtomicInteger activeSessions = new AtomicInteger();
//
// // 历史最大活跃 session 数
// private final AtomicInteger maxActiveSessions = new AtomicInteger();
//
// // Undertow 内存 session 管理器(用于创建与管理 session
// private final InMemorySessionManager sessionManager = new InMemorySessionManager("undertow-session-manager");
//
// // 使用 Cookie 存储 session ID
// private final SessionConfig sessionConfig = new SessionCookieConfig();
//
// /**
// * 构造函数
// * @param meterRegistry
// * @author chenrui
// * @date 2025/4/8 19:07
// */
// public CustomUndertowMetricsHandler(MeterRegistry meterRegistry) {
// // 注册 Micrometer 指标
// meterRegistry.gauge("undertow.sessions.created", sessionsCreated, LongAdder::longValue);
// meterRegistry.gauge("undertow.sessions.expired", sessionsExpired, LongAdder::longValue);
// meterRegistry.gauge("undertow.sessions.active.current", activeSessions, AtomicInteger::get);
// meterRegistry.gauge("undertow.sessions.active.max", maxActiveSessions, AtomicInteger::get);
//
// // 添加 session 生命周期监听器,统计 session 创建与销毁
// sessionManager.registerSessionListener(new SessionListener() {
// @Override
// public void sessionCreated(Session session, HttpServerExchange exchange) {
// sessionsCreated.increment();
// int now = activeSessions.incrementAndGet();
// maxActiveSessions.getAndUpdate(max -> Math.max(max, now));
// }
//
// @Override
// public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
// sessionsExpired.increment();
// activeSessions.decrementAndGet();
// }
// });
// }
//
// /**
// * 包装 Undertow 的 HttpHandler实现 session 自动创建逻辑
// * @param next
// * @return
// * @author chenrui
// * @date 2025/4/8 19:07
// */
// public HttpHandler wrap(HttpHandler next) {
// return exchange -> {
// // 获取当前 session如果不存在则创建
// Session session = sessionManager.getSession(exchange, sessionConfig);
// if (session == null) {
// sessionManager.createSession(exchange, sessionConfig);
// }
//
// // 执行下一个 Handler
// next.handleRequest(exchange);
// };
// }
//}

View File

@ -382,7 +382,7 @@ public class OpenApiController extends JeecgController<OpenApi, OpenApiService>
SwaggerInfo info = new SwaggerInfo();
info.setDescription("OpenAPI 接口列表");
info.setVersion("3.8.2");
info.setVersion("3.8.3");
info.setTitle("OpenAPI 接口列表");
info.setTermsOfService("https://jeecg.com");

View File

@ -13,7 +13,10 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
@ -213,9 +216,7 @@ public class CommonController {
if(oConvertUtils.isEmpty(imgPath) || CommonConstant.STRING_NULL.equals(imgPath)){
return;
}
// 其余处理略
InputStream inputStream = null;
OutputStream outputStream = null;
try {
imgPath = imgPath.replace("..", "").replace("../","");
if (imgPath.endsWith(SymbolConstant.COMMA)) {
@ -236,33 +237,21 @@ public class CommonController {
// 设置强制下载不打开
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
inputStream = new BufferedInputStream(new FileInputStream(filePath));
outputStream = response.getOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
// 结合 StreamingResponseBody 的流式写法
try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
OutputStream outputStream = response.getOutputStream()) {
byte[] buf = new byte[8192];
int len;
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.flush();
}
response.flushBuffer();
} catch (IOException e) {
log.error("预览文件失败" + e.getMessage());
response.setStatus(404);
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}

View File

@ -51,6 +51,9 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -86,6 +89,11 @@ public class LoginController {
private CacheManager cacheManager;
private final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
/**
* 线程池用于异步发送纪要
*/
public static ExecutorService cachedThreadPool = new ShiroThreadPoolExecutor(0, 1024, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
/**
* 使用spring authorization server提供的各类登录接口
@ -212,31 +220,37 @@ public class LoginController {
String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username);
if(sysUser!=null) {
//update-begin--Author:wangshuai Date:20200714 for登出日志没有记录人员
baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null,sysUser);
//update-end--Author:wangshuai Date:20200714 for登出日志没有记录人员
log.info(" 用户名: "+sysUser.getRealname()+",退出成功! ");
//清空用户登录Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
//清空用户登录Shiro权限缓存
redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
//清空用户的缓存信息包括部门信息例如sys:cache:user::<username>
redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
//调用shiro的logout
// SecurityUtils.getSubject().logout();
OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN);
// 清空用户信息
cacheManager.getCache("user_details").evict(authorization.getPrincipalName());
// 清空access token
authorizationService.remove(authorization);
return Result.ok("退出登录成功!");
asyncClearLogoutCache(token, sysUser); // 异步清理
OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN);
// 清空用户信息
cacheManager.getCache("user_details").evict(authorization.getPrincipalName());
// 清空access token
authorizationService.remove(authorization);
return Result.ok("退出登录成功!");
}else {
return Result.error("Token无效!");
}
}
/**
* 清理用户缓存
*
* @param token
* @param sysUser
*/
private void asyncClearLogoutCache(String token, LoginUser sysUser) {
cachedThreadPool.execute(()->{
//清空用户登录Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
//清空用户登录Shiro权限缓存
redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
//清空用户的缓存信息包括部门信息例如sys:cache:user::<username>
redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null, sysUser);
log.info("【退出成功操作】异步处理,退出后,清理用户缓存: "+sysUser.getRealname());
});
}
/**
* 获取访问量

View File

@ -323,7 +323,7 @@ public class SysAnnouncementController {
try {
// 同步企业微信、钉钉的消息通知
Response<String> dtResponse = dingtalkService.sendActionCardMessage(sysAnnouncement, null, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, null,true);
if (dtResponse != null && dtResponse.isSuccess()) {
String taskId = dtResponse.getResult();
@ -727,6 +727,18 @@ public class SysAnnouncementController {
return Result.ok("公告消息访问次数+1次");
}
/**
* 批量下载文件
* @param id
* @param request
* @param response
*/
@GetMapping("/downLoadFiles")
public void downLoadFiles(@RequestParam(name="id") String id,
HttpServletRequest request,
HttpServletResponse response){
sysAnnouncementService.downLoadFiles(id,request,response);
}
/**
* 根据异常信息确定友好的错误提示
*/

View File

@ -21,12 +21,14 @@ import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.excelstyle.ExcelExportSysUserStyle;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysUserDepartService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.vo.SysDepartExportVo;
import org.jeecg.modules.system.vo.SysPositionSelectTreeVo;
import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
@ -150,6 +152,32 @@ public class SysDepartController {
return result;
}
/**
* 异步查询部门和岗位list
* @param parentId 父节点 异步加载时传递
* @param ids 前端回显是传递
* @param primaryKey 主键字段id或者orgCode
* @return
*/
@RequestMapping(value = "/queryDepartAndPostTreeSync", method = RequestMethod.GET)
public Result<List<SysDepartTreeModel>> queryDepartAndPostTreeSync(@RequestParam(name = "pid", required = false) String parentId,
@RequestParam(name = "ids", required = false) String ids,
@RequestParam(name = "primaryKey", required = false) String primaryKey,
@RequestParam(name = "departIds", required = false) String departIds,
@RequestParam(name = "name", required = false) String orgName) {
Result<List<SysDepartTreeModel>> result = new Result<>();
try {
List<SysDepartTreeModel> list = sysDepartService.queryDepartAndPostTreeSync(parentId,ids, primaryKey, departIds, orgName);
result.setResult(list);
result.setSuccess(true);
} catch (Exception e) {
log.error(e.getMessage(),e);
result.setSuccess(false);
result.setMessage("查询失败");
}
return result;
}
/**
* 获取某个部门的所有父级部门的ID
*
@ -323,7 +351,10 @@ public class SysDepartController {
* @return
*/
@RequestMapping(value = "/searchBy", method = RequestMethod.GET)
public Result<List<SysDepartTreeModel>> searchBy(@RequestParam(name = "keyWord", required = true) String keyWord,@RequestParam(name = "myDeptSearch", required = false) String myDeptSearch) {
public Result<List<SysDepartTreeModel>> searchBy(@RequestParam(name = "keyWord", required = true) String keyWord,
@RequestParam(name = "myDeptSearch", required = false) String myDeptSearch,
@RequestParam(name = "orgCategory", required = false) String orgCategory,
@RequestParam(name = "departIds", required = false) String depIds) {
Result<List<SysDepartTreeModel>> result = new Result<List<SysDepartTreeModel>>();
//部门查询myDeptSearch为1时为我的部门查询登录用户为上级时查只查负责部门下数据
LoginUser user = SecureUtil.currentUser();
@ -331,7 +362,7 @@ public class SysDepartController {
if(oConvertUtils.isNotEmpty(user.getUserIdentity()) && user.getUserIdentity().equals( CommonConstant.USER_IDENTITY_2 )){
departIds = user.getDepartIds();
}
List<SysDepartTreeModel> treeList = this.sysDepartService.searchByKeyWord(keyWord,myDeptSearch,departIds);
List<SysDepartTreeModel> treeList = this.sysDepartService.searchByKeyWord(keyWord,myDeptSearch,departIds,orgCategory,depIds);
if (treeList == null || treeList.size() == 0) {
result.setSuccess(false);
result.setMessage("未查询匹配数据!");
@ -384,11 +415,14 @@ public class SysDepartController {
mv.addObject(NormalExcelConstants.FILE_NAME, "部门列表");
mv.addObject(NormalExcelConstants.CLASS, SysDepartExportVo.class);
LoginUser user = SecureUtil.currentUser();
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("导入规则:\n" +
"1、标题为第三行部门路径和部门名称的标题不允许修改否则会匹配失败第四行为数据填写范围;\n" +
"2、部门路径用英文字符/分割,部门名称为部门路径的最后一位;\n" +
"3、部门从一级名称开始创建如果有同级就需要多添加一行如研发部/研发一部;研发部/研发二部;\n" +
"4、自定义的部门编码需要满足规则才能导入。如一级部门编码为A01,那么子部门为A01A01,同级子部门为A01A02,编码固定为三位首字母为A-Z,后两位为数字0-99依次递增;", "导出人:"+user.getRealname(), "导出信息"));
ExportParams exportParams = new ExportParams("导入规则:\n" +
"1、标题为第三行部门路径和部门名称的标题不允许修改否则会匹配失败第四行为数据填写范围;\n" +
"2、部门路径用英文字符/分割,部门名称为部门路径的最后一位;\n" +
"3、部门从一级名称开始创建如果有同级就需要多添加一行如研发部/研发一部;研发部/研发二部;\n" +
"4、自定义的部门编码需要满足规则才能导入。如一级部门编码为A01,那么子部门为A01A01,同级子部门为A01A02,编码固定为三位首字母为A-Z,后两位为数字0-99依次递增;", "导出人:" + user.getRealname(), "导出信息");
exportParams.setTitleHeight((short)70);
exportParams.setStyle(ExcelExportSysUserStyle.class);
mv.addObject(NormalExcelConstants.PARAMS, exportParams);
mv.addObject(NormalExcelConstants.DATA_LIST, sysDepartExportVos);
//update-end---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
@ -582,6 +616,11 @@ public class SysDepartController {
String[] ids = deptIds.split(",");
Collection<String> idList = Arrays.asList(ids);
Collection<SysDepart> deptList = sysDepartService.listByIds(idList);
// 设置部门路径名称
for (SysDepart depart : deptList) {
String departPathName = sysDepartService.getDepartPathNameByOrgCode(depart.getOrgCode(),null);
depart.setDepartPathName(departPathName);
}
result.setSuccess(true);
result.setResult(deptList);
return result;
@ -687,5 +726,40 @@ public class SysDepartController {
}
return Result.error("文件导入失败!");
}
/**
* 根据部门id和职级id获取岗位信息
*/
@GetMapping("/getPositionByDepartId")
public Result<List<SysPositionSelectTreeVo>> getPositionByDepartId(@RequestParam(name = "parentId") String parentId,
@RequestParam(name = "departId",required = false) String departId,
@RequestParam(name = "positionId") String positionId){
List<SysPositionSelectTreeVo> positionByDepartId = sysDepartService.getPositionByDepartId(parentId, departId, positionId);
return Result.OK(positionByDepartId);
}
/**
* 获取职级关系
* @param departId
* @return
*/
@GetMapping("/getRankRelation")
public Result<List<SysPositionSelectTreeVo>> getRankRelation(@RequestParam(name = "departId") String departId){
List<SysPositionSelectTreeVo> list = sysDepartService.getRankRelation(departId);
return Result.ok(list);
}
/**
* 根据部门code获取当前和上级部门名称
*
* @param orgCode
* @param depId
* @return String 部门名称
*/
@GetMapping("/getDepartPathNameByOrgCode")
public Result<String> getDepartPathNameByOrgCode(@RequestParam(name = "orgCode", required = false) String orgCode,
@RequestParam(name = "depId", required = false) String depId) {
String departName = sysDepartService.getDepartPathNameByOrgCode(orgCode, depId);
return Result.OK(departName);
}
}

View File

@ -6,6 +6,7 @@ import java.util.Arrays;
import jakarta.servlet.http.HttpServletRequest;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysLog;
@ -22,6 +23,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.ModelAndView;
/**
* <p>
@ -34,7 +36,7 @@ import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/sys/log")
@Slf4j
public class SysLogController {
public class SysLogController extends JeecgController<SysLog, ISysLogService> {
@Autowired
private ISysLogService sysLogService;
@ -120,6 +122,17 @@ public class SysLogController {
}
return result;
}
/**
* 导出excel
* for [QQYUN-13431]【jeecg】日志管理中添加大数据导出功能
* @param request
* @param syslog
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, SysLog syslog) {
return super.exportXlsForBigData(request, syslog, SysLog.class, "syslog", 10000);
}
}

View File

@ -91,6 +91,8 @@ public class SysPositionController {
}
//------------------------------------------------------------------------------------------------
QueryWrapper<SysPosition> queryWrapper = QueryGenerator.initQueryWrapper(sysPosition, req.getParameterMap());
queryWrapper.orderByAsc("post_level");
queryWrapper.orderByDesc("create_time");
Page<SysPosition> page = new Page<SysPosition>(pageNo, pageSize);
IPage<SysPosition> pageList = sysPositionService.page(page, queryWrapper);
result.setSuccess(true);

View File

@ -415,8 +415,11 @@ public class SysTenantController {
*/
@PutMapping("/invitationUserJoin")
@PreAuthorize("@jps.requiresPermissions('system:tenant:invitation:user')")
public Result<String> invitationUserJoin(@RequestParam("ids") String ids,@RequestParam("phone") String phone){
sysTenantService.invitationUserJoin(ids,phone);
public Result<String> invitationUserJoin(@RequestParam("ids") String ids,@RequestParam(value = "phone", required = false) String phone, @RequestParam(value = "username", required = false) String username){
if(oConvertUtils.isEmpty(phone) && oConvertUtils.isEmpty(username)){
return Result.error("手机号和用户账号不能同时为空!");
}
sysTenantService.invitationUserJoin(ids,phone,username);
return Result.ok("邀请用户成功");
}
@ -1001,4 +1004,26 @@ public class SysTenantController {
sysTenantService.deleteUser(sysUser, tenantId);
return Result.ok("删除用户成功");
}
/**
* 根据租户id和用户id获取用户的产品包列表和当前用户下的产品包id
*
* @param tenantId
* @param request
* @return
*/
@GetMapping("/listPackByTenantUserId")
public Result<Map<String, Object>> listPackByTenantUserId(@RequestParam("tenantId") String tenantId,
@RequestParam("userId") String userId,
HttpServletRequest request) {
if (null == tenantId) {
return null;
}
List<SysTenantPack> list = sysTenantPackService.getPackListByTenantId(tenantId);
List<String> userPackIdList = sysTenantPackService.getPackIdByUserIdAndTenantId(userId, oConvertUtils.getInt(tenantId));
Map<String, Object> map = new HashMap<>(5);
map.put("packList", list);
map.put("userPackIdList", userPackIdList);
return Result.ok(map);
}
}

View File

@ -1,265 +0,0 @@
package org.jeecg.modules.system.controller;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.system.entity.SysUserAgent;
import org.jeecg.modules.system.service.ISysUserAgentService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
/**
* @Title: Controller
* @Description: 用户代理人设置
* @Author: jeecg-boot
* @Date: 2019-04-17
* @Version: V1.0
*/
@RestController
@RequestMapping("/sys/sysUserAgent")
@Slf4j
public class SysUserAgentController {
@Autowired
private ISysUserAgentService sysUserAgentService;
@Value("${jeecg.path.upload}")
private String upLoadPath;
/**
* 分页列表查询
* @param sysUserAgent
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<IPage<SysUserAgent>> queryPageList(SysUserAgent sysUserAgent,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
Result<IPage<SysUserAgent>> result = new Result<IPage<SysUserAgent>>();
QueryWrapper<SysUserAgent> queryWrapper = QueryGenerator.initQueryWrapper(sysUserAgent, req.getParameterMap());
Page<SysUserAgent> page = new Page<SysUserAgent>(pageNo, pageSize);
IPage<SysUserAgent> pageList = sysUserAgentService.page(page, queryWrapper);
result.setSuccess(true);
result.setResult(pageList);
return result;
}
/**
* 添加
* @param sysUserAgent
* @return
*/
@PostMapping(value = "/add")
public Result<SysUserAgent> add(@RequestBody SysUserAgent sysUserAgent) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
try {
sysUserAgentService.save(sysUserAgent);
result.success("代理人设置成功!");
} catch (Exception e) {
log.error(e.getMessage(),e);
result.error500("操作失败");
}
return result;
}
/**
* 编辑
* @param sysUserAgent
* @return
*/
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysUserAgent> edit(@RequestBody SysUserAgent sysUserAgent) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
SysUserAgent sysUserAgentEntity = sysUserAgentService.getById(sysUserAgent.getId());
if(sysUserAgentEntity==null) {
result.error500("未找到对应实体");
}else {
boolean ok = sysUserAgentService.updateById(sysUserAgent);
//TODO 返回false说明什么
if(ok) {
result.success("代理人设置成功!");
}
}
return result;
}
/**
* 通过id删除
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<SysUserAgent> delete(@RequestParam(name="id",required=true) String id) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
SysUserAgent sysUserAgent = sysUserAgentService.getById(id);
if(sysUserAgent==null) {
result.error500("未找到对应实体");
}else {
boolean ok = sysUserAgentService.removeById(id);
if(ok) {
result.success("删除成功!");
}
}
return result;
}
/**
* 批量删除
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<SysUserAgent> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
if(ids==null || "".equals(ids.trim())) {
result.error500("参数不识别!");
}else {
this.sysUserAgentService.removeByIds(Arrays.asList(ids.split(",")));
result.success("删除成功!");
}
return result;
}
/**
* 通过id查询
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<SysUserAgent> queryById(@RequestParam(name="id",required=true) String id) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
SysUserAgent sysUserAgent = sysUserAgentService.getById(id);
if(sysUserAgent==null) {
result.error500("未找到对应实体");
}else {
result.setResult(sysUserAgent);
result.setSuccess(true);
}
return result;
}
/**
* 通过userName查询
* @param userName
* @return
*/
@GetMapping(value = "/queryByUserName")
public Result<SysUserAgent> queryByUserName(@RequestParam(name="userName",required=true) String userName) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
LambdaQueryWrapper<SysUserAgent> queryWrapper = new LambdaQueryWrapper<SysUserAgent>();
queryWrapper.eq(SysUserAgent::getUserName, userName);
SysUserAgent sysUserAgent = sysUserAgentService.getOne(queryWrapper);
if(sysUserAgent==null) {
result.error500("未找到对应实体");
}else {
result.setResult(sysUserAgent);
result.setSuccess(true);
}
return result;
}
/**
* 导出excel
*
* @param sysUserAgent
* @param request
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(SysUserAgent sysUserAgent,HttpServletRequest request) {
// Step.1 组装查询条件
QueryWrapper<SysUserAgent> queryWrapper = QueryGenerator.initQueryWrapper(sysUserAgent, request.getParameterMap());
//Step.2 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
List<SysUserAgent> pageList = sysUserAgentService.list(queryWrapper);
//导出文件名称
mv.addObject(NormalExcelConstants.FILE_NAME, "用户代理人设置列表");
mv.addObject(NormalExcelConstants.CLASS, SysUserAgent.class);
LoginUser user = SecureUtil.currentUser();
ExportParams exportParams = new ExportParams("用户代理人设置列表数据", "导出人:"+user.getRealname(), "导出信息");
exportParams.setImageBasePath(upLoadPath);
mv.addObject(NormalExcelConstants.PARAMS, exportParams);
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
return mv;
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
// 获取上传文件对象
MultipartFile file = entity.getValue();
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<SysUserAgent> listSysUserAgents = ExcelImportUtil.importExcel(file.getInputStream(), SysUserAgent.class, params);
for (SysUserAgent sysUserAgentExcel : listSysUserAgents) {
sysUserAgentService.save(sysUserAgentExcel);
}
return Result.ok("文件导入成功!数据行数:" + listSysUserAgents.size());
} catch (Exception e) {
log.error(e.getMessage(),e);
return Result.error("文件导入失败!");
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.error("文件导入失败!");
}
}

View File

@ -3,7 +3,6 @@ package org.jeecg.modules.system.controller;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -13,7 +12,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
@ -28,10 +26,14 @@ import org.jeecg.common.util.*;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.excelstyle.ExcelExportSysUserStyle;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysUserSysDepPostModel;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.util.ImportSysUserCache;
import org.jeecg.modules.system.vo.SysDepartUsersVO;
import org.jeecg.modules.system.vo.SysUserExportVo;
import org.jeecg.modules.system.vo.SysUserRoleVO;
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
import org.jeecg.modules.system.vo.lowapp.UpdateDepartInfo;
@ -94,9 +96,6 @@ public class SysUserController {
@Autowired
private BaseCommonService baseCommonService;
@Autowired
private ISysUserAgentService sysUserAgentService;
@Autowired
private ISysPositionService sysPositionService;
@ -171,7 +170,7 @@ public class SysUserController {
// 保存用户走一个service 保证事务
//获取租户ids
String relTenantIds = jsonObject.getString("relTenantIds");
sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds);
sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds, false);
baseCommonService.addLog("添加用户username " +user.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
result.success("添加成功!");
} catch (Exception e) {
@ -485,15 +484,25 @@ public class SysUserController {
}
//update-end--Author:kangxiaolin Date:20180825 for[03]用户导出,如果选择数据则只导出相关数据----------------------
List<SysUser> pageList = sysUserService.list(queryWrapper);
List<SysUserExportVo> list = sysUserService.getDepartAndRoleExportMsg(pageList);
//导出文件名称
mv.addObject(NormalExcelConstants.FILE_NAME, "用户列表");
mv.addObject(NormalExcelConstants.CLASS, SysUser.class);
LoginUser user = SecureUtil.currentUser();
ExportParams exportParams = new ExportParams("用户列表数据", "导出人:"+user.getRealname(), "导出信息");
mv.addObject(NormalExcelConstants.CLASS, SysUserExportVo.class);
LoginUser user = SecureUtil.currentUser();
ExportParams exportParams = new ExportParams("导入规则:\n" +
"1. 用户名为必填项,仅支持新增数据导入;\n" +
"2. 多个部门、角色或负责部门请用英文分号 ; 分隔,如:财务部;研发部;\n" +
"3. 部门层级请用英文斜杠 / 分隔,如:北京公司/财务部/财务一部;\n" +
"4. 部门类型需与部门层级一致,也用 / 分隔,如:公司/部门/部门 或 1/3/3多个类型用 ; 分隔。机构类型编码:公司(1),子公司(4),部门(3)\n" +
"5. 部门根据用户名匹配,若存在多个则关联最新创建的部门,不存在时自动新增;\n" +
"6. 负责部门与所属部门导入规则一致,若所属部门不包含负责部门,则不关联负责部门;\n" +
"7. 用户主岗位导入时会在部门下自动创建新岗位,职级为空时默认不与岗位建立关联。", "导出人:" + user.getRealname(), "导出信息");
exportParams.setTitleHeight((short)70);
exportParams.setStyle(ExcelExportSysUserStyle.class);
exportParams.setImageBasePath(upLoadPath);
mv.addObject(NormalExcelConstants.PARAMS, exportParams);
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
mv.addObject(NormalExcelConstants.DATA_LIST, list);
return mv;
}
@ -507,78 +516,8 @@ public class SysUserController {
@PreAuthorize("@jps.requiresPermissions('system:user:import')")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response)throws IOException {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
// 错误信息
List<String> errorMessage = new ArrayList<>();
int successLines = 0, errorLines = 0;
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
MultipartFile file = entity.getValue();// 获取上传文件对象
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<SysUser> listSysUsers = ExcelImportUtil.importExcel(file.getInputStream(), SysUser.class, params);
for (int i = 0; i < listSysUsers.size(); i++) {
SysUser sysUserExcel = listSysUsers.get(i);
if (StringUtils.isBlank(sysUserExcel.getPassword())) {
// 密码默认为 “123456”
sysUserExcel.setPassword("123456");
}
// 密码加密加盐
String salt = oConvertUtils.randomGen(8);
sysUserExcel.setSalt(salt);
String passwordEncode = PasswordUtil.encrypt(sysUserExcel.getUsername(), sysUserExcel.getPassword(), salt);
sysUserExcel.setPassword(passwordEncode);
try {
sysUserService.save(sysUserExcel);
successLines++;
} catch (Exception e) {
errorLines++;
String message = e.getMessage().toLowerCase();
int lineNumber = i + 1;
// 通过索引名判断出错信息
if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_USERNAME)) {
errorMessage.add("" + lineNumber + " 行:用户名已经存在,忽略导入。");
} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_WORK_NO)) {
errorMessage.add("" + lineNumber + " 行:工号已经存在,忽略导入。");
} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_PHONE)) {
errorMessage.add("" + lineNumber + " 行:手机号已经存在,忽略导入。");
} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_EMAIL)) {
errorMessage.add("" + lineNumber + " 行:电子邮件已经存在,忽略导入。");
} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER)) {
errorMessage.add("" + lineNumber + " 行:违反表唯一性约束。");
} else {
errorMessage.add("" + lineNumber + " 行:未知错误,忽略导入");
log.error(e.getMessage(), e);
}
}
// 批量将部门和用户信息建立关联关系
String departIds = sysUserExcel.getDepartIds();
if (StringUtils.isNotBlank(departIds)) {
String userId = sysUserExcel.getId();
String[] departIdArray = departIds.split(",");
List<SysUserDepart> userDepartList = new ArrayList<>(departIdArray.length);
for (String departId : departIdArray) {
userDepartList.add(new SysUserDepart(userId, departId));
}
sysUserDepartService.saveBatch(userDepartList);
}
}
} catch (Exception e) {
errorMessage.add("发生异常:" + e.getMessage());
log.error(e.getMessage(), e);
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
return ImportExcelUtil.imporReturnRes(errorLines,successLines,errorMessage);
//return ImportOldUserUtil.importOldSysUser(request);
return sysUserService.importSysUser(request);
}
/**
@ -615,6 +554,17 @@ public class SysUserController {
return result;
}
/**
* @功能根据userName查询用户以及部门信息
* @param userName
* @return
*/
@RequestMapping(value = "/queryUserAndDeptByName", method = RequestMethod.GET)
public Result<Map<String,String>> queryUserAndDeptByName(@RequestParam(name = "userName") String userName) {
Map<String,String> userInfo= sysUserService.queryUserAndDeptByName(userName);
return Result.ok(userInfo);
}
/**
* 首页用户重置密码
*/
@ -647,7 +597,8 @@ public class SysUserController {
Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
String roleId = req.getParameter("roleId");
String username = req.getParameter("username");
IPage<SysUser> pageList = sysUserService.getUserByRoleId(page,roleId,username);
String realname = req.getParameter("realname");
IPage<SysUser> pageList = sysUserService.getUserByRoleId(page,roleId,username,realname);
result.setSuccess(true);
result.setResult(pageList);
return result;
@ -812,38 +763,8 @@ public class SysUserController {
SysUser userParams
) {
IPage page = new Page(pageNo, pageSize);
IPage<SysUserSysDepartModel> pageList = sysUserService.queryUserByOrgCode(orgCode, userParams, page);
List<SysUserSysDepartModel> list = pageList.getRecords();
// 记录所有出现过的 user, key = userId
Map<String, JSONObject> hasUser = new HashMap<>(list.size());
JSONArray resultJson = new JSONArray(list.size());
for (SysUserSysDepartModel item : list) {
String userId = item.getId();
// userId
JSONObject getModel = hasUser.get(userId);
// 之前已存在过该用户,直接合并数据
if (getModel != null) {
String departName = getModel.get("departName").toString();
getModel.put("departName", (departName + " | " + item.getDepartName()));
} else {
// 将用户对象转换为json格式并将部门信息合并到 json 中
JSONObject json = JSON.parseObject(JSON.toJSONString(item));
json.remove("id");
json.put("userId", userId);
json.put("departId", item.getDepartId());
json.put("departName", item.getDepartName());
// json.put("avatar", item.getSysUser().getAvatar());
resultJson.add(json);
hasUser.put(userId, json);
}
}
IPage<JSONObject> result = new Page<>(pageNo, pageSize, pageList.getTotal());
result.setRecords(resultJson.toJavaList(JSONObject.class));
return Result.ok(result);
IPage<SysUserSysDepPostModel> pageList = sysUserService.queryDepartPostUserByOrgCode(orgCode, userParams, page);
return Result.ok(pageList);
}
/**
@ -1228,6 +1149,14 @@ public class SysUserController {
map.put("sysUserName", sysUser.getRealname()); // 当前登录用户真实名称
map.put("sysOrgCode", sysUser.getOrgCode()); // 当前登录用户部门编号
// 【QQYUN-12930】设置部门名称
if (oConvertUtils.isNotEmpty(sysUser.getOrgCode())) {
SysDepart sysDepart = sysDepartService.lambdaQuery().select(SysDepart::getDepartName).eq(SysDepart::getOrgCode, sysUser.getOrgCode()).one();
if (sysDepart != null) {
map.put("sysOrgName", sysDepart.getDepartName()); // 当前登录用户部门名称
}
}
log.debug(" ------ 通过令牌获取部分用户信息,已获取的用户信息: " + map);
return Result.ok(map);
@ -1619,23 +1548,7 @@ public class SysUserController {
IPage<SysUser> pageList = sysUserDepartService.getUserInformation(tenantId, departId,roleId, keyword, pageSize, pageNo,excludeUserIdList);
return Result.OK(pageList);
}
/**
* 用户离职(新增代理人和用户状态变更操作)【低代码应用专用接口】
* @param sysUserAgent
* @return
*/
@PutMapping("/userQuitAgent")
public Result<String> userQuitAgent(@RequestBody SysUserAgent sysUserAgent){
//判断id是否为空
if(oConvertUtils.isNotEmpty(sysUserAgent.getId())){
sysUserAgentService.updateById(sysUserAgent);
}else{
sysUserAgentService.save(sysUserAgent);
}
sysUserService.userQuit(sysUserAgent.getUserName());
return Result.ok("离职成功");
}
/**
* 获取被逻辑删除的用户列表,无分页【低代码应用专用接口】
@ -1657,29 +1570,6 @@ public class SysUserController {
return Result.ok(quitList);
}
/**
* 更新刪除状态和离职状态【低代码应用专用接口】
* @param jsonObject
* @return Result<String>
*/
@PutMapping("/putCancelQuit")
public Result<String> putCancelQuit(@RequestBody JSONObject jsonObject, HttpServletRequest request){
String userIds = jsonObject.getString("userIds");
String usernames = jsonObject.getString("usernames");
Integer tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request),0);
//将状态改成未删除
if (StringUtils.isNotBlank(userIds)) {
userTenantService.putCancelQuit(Arrays.asList(userIds.split(SymbolConstant.COMMA)),tenantId);
}
if(StringUtils.isNotEmpty(usernames)){
//根据用户名删除代理人
LambdaQueryWrapper<SysUserAgent> query = new LambdaQueryWrapper<>();
query.in(SysUserAgent::getUserName,Arrays.asList(usernames.split(SymbolConstant.COMMA)));
sysUserAgentService.remove(query);
}
return Result.ok("取消离职成功");
}
/**
* 获取用户信息(vue3用户设置专用)【低代码应用专用接口】
* @return
@ -1757,7 +1647,7 @@ public class SysUserController {
}
return result;
}
/**
* 根据关键词搜索部门和用户【low-app】
* @param keyword
@ -1877,7 +1767,7 @@ public class SysUserController {
public Result<?> importAppUser(HttpServletRequest request, HttpServletResponse response)throws IOException {
return sysUserService.importAppUser(request);
}
/**
* 更改手机号(敲敲云个人设置专用)
*
@ -1891,7 +1781,7 @@ public class SysUserController {
sysUserService.changePhone(json,username);
return Result.ok("修改手机号成功!");
}
/**
* 发送短信验证码接口(修改手机号)
*
@ -1930,4 +1820,53 @@ public class SysUserController {
result.setMessage("发送验证码成功!");
return result;
}
/**
* 没有绑定手机号 直接修改密码
* @param oldPassword
* @param password
* @return
*/
@PutMapping("/updatePasswordNotBindPhone")
public Result<String> updatePasswordNotBindPhone(@RequestParam(value="oldPassword") String oldPassword,
@RequestParam(value="password") String password,
@RequestParam(value="username") String username){
sysUserService.updatePasswordNotBindPhone(oldPassword, password, username);
return Result.OK("修改密码成功!");
}
/**
* 根据部门岗位选择用户【部门岗位选择用户专用】
* @return
*/
@GetMapping("/queryDepartPostUserPageList")
public Result<IPage<SysUser>> queryDepartPostUserPageList( @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
@RequestParam(name = "departId", required = false) String departId,
@RequestParam(name="realname",required=false) String realname,
@RequestParam(name="username",required=false) String username,
@RequestParam(name="isMultiTranslate",required=false) String isMultiTranslate,
@RequestParam(name="id",required = false) String id){
String[] arr = new String[]{departId, realname, username, id};
SqlInjectionUtil.filterContent(arr, SymbolConstant.SINGLE_QUOTATION_MARK);
IPage<SysUser> pageList = sysUserDepartService.queryDepartPostUserPageList(departId, username, realname, pageSize, pageNo,id,isMultiTranslate);
return Result.OK(pageList);
}
/**
* 获取上传文件的进度
*
* @param fileKey
* @param type
* @return
*/
@GetMapping("/getUploadFileProgress")
public Result<Double> getUploadFileProgress(@RequestParam(name = "fileKey") String fileKey,
@RequestParam("type") String type){
Double progress = ImportSysUserCache.getImportSysUserMap(fileKey, type);
if(progress == 100){
ImportSysUserCache.removeImportLowAppMap(fileKey);
}
return Result.ok(progress);
}
}

View File

@ -8,10 +8,13 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.config.security.utils.SecureUtil;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.util.Date;
@ -98,7 +101,13 @@ public class SysDataLog implements Serializable {
LoginUser sysUser = SecureUtil.currentUser();
this.setCreateName(sysUser.getRealname());
} catch (Exception e) {
log.warn("SecurityUtils.getSubject() 获取用户信息异常:" + e.getMessage());
// QQYUN-13669 进一步优化:解决某些异步场景下获取用户信息为空的问题
String token = UserTokenContext.getToken();
if (StringUtils.hasText(token)) {
this.setCreateName(JwtUtil.getUsername(token));
} else {
log.warn("SecurityUtils.getSubject() 获取用户信息异常:" + e.getMessage());
}
}
}

View File

@ -35,6 +35,9 @@ public class SysDepart implements Serializable {
/**机构/部门名称*/
@Excel(name="机构/部门名称",width=15)
private String departName;
/**机构/部门路径名称(非持久化字段)*/
@TableField(exist = false)
private String departPathName;
/**英文名*/
@Excel(name="英文名",width=15)
private String departNameEn;
@ -46,7 +49,7 @@ public class SysDepart implements Serializable {
/**描述*/
@Excel(name="描述",width=15)
private String description;
/**机构类别 1=公司2=组织机构3=岗位*/
/**机构类别 1=公司2=组织机构3=岗位 4=子公司*/
@Excel(name="机构类别",width=15,dicCode="org_category")
private String orgCategory;
/**机构类型*/
@ -102,7 +105,21 @@ public class SysDepart implements Serializable {
@TableField(exist = false)
private String oldDirectorUserIds;
//update-end---author:wangshuai ---date:20200308 for[JTC-119]新增字段负责人ids和旧的负责人ids
/**
* 职级id
*/
@Excel(name="职级",width=15,dictTable = "sys_position", dicCode = "id", dicText = "name")
@Dict(dictTable = "sys_position", dicCode = "id", dicText = "name")
private String positionId;
/**
* 部门岗位id
*/
@Excel(name="上级岗位",width=15,dictTable = "sys_depart", dicCode = "id", dicText = "depart_name")
@Dict(dictTable = "sys_depart", dicCode = "id", dicText = "depart_name")
private String depPostParentId;
/**
* 重写equals方法
*/

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.system.entity;
import java.util.Date;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
@ -41,6 +42,7 @@ public class SysLog implements Serializable {
/**
* 创建时间
*/
@Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ -58,11 +60,13 @@ public class SysLog implements Serializable {
/**
* 耗时
*/
@Excel(name = "耗时(毫秒)", width = 15)
private Long costTime;
/**
* IP
*/
@Excel(name = "IP", width = 15)
private String ip;
/**
@ -91,10 +95,12 @@ public class SysLog implements Serializable {
/**
* 操作人用户账户
*/
@Excel(name = "操作人", width = 15)
private String userid;
/**
* 操作详细日志
*/
@Excel(name = "日志内容", width = 50)
private String logContent;
/**
@ -112,6 +118,7 @@ public class SysLog implements Serializable {
/**
* 客户终端类型 pc:电脑端 app:手机端 h5:移动网页端
*/
@Excel(name = "客户端类型", width = 15, dicCode = "client_type")
@Dict(dicCode = "client_type")
private String clientType;

View File

@ -14,7 +14,7 @@ import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
/**
* @Description: 职务
* @Description: 职务级别
* @Author: jeecg-boot
* @Date: 2019-09-19
* @Version: V1.0
@ -23,7 +23,7 @@ import org.springframework.format.annotation.DateTimeFormat;
@TableName("sys_position")
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Schema(description="职务表")
@Schema(description="职务级别")
public class SysPosition {
/**
@ -39,18 +39,17 @@ public class SysPosition {
@Schema(description = "职务编码")
private java.lang.String code;
/**
* 职务名称
* 职务级别名称
*/
@Excel(name = "职务名称", width = 15)
@Schema(description = "职务名称")
@Excel(name = "职务级别名称", width = 15)
@Schema(description = "职务级别名称")
private java.lang.String name;
/**
* 职级
*/
//@Excel(name = "职级", width = 15,dicCode ="position_rank")
@Schema(description = "职级")
@Dict(dicCode = "position_rank")
private java.lang.String postRank;
@Schema(description = "务等")
private java.lang.Integer postLevel;
/**
* 公司id
*/

View File

@ -67,6 +67,13 @@ public class SysTenantPack implements Serializable {
@Excel(name = "产品包类型", width = 15)
@Schema(description = "产品包类型")
private String packType;
/**
* 是否自动分配给用户(0 否 1是)
*/
@Excel(name = "是否自动分配给用户(0 否 1是)", width = 15)
@Schema(description = "是否自动分配给用户")
private String izSysn;
/**菜单id 临时字段用于新增编辑菜单id传递*/
@TableField(exist = false)

View File

@ -211,4 +211,36 @@ public class SysUser implements Serializable {
*/
@TableField(exist = false)
private boolean izBindThird;
/**
* 个性签名
*/
private String sign;
/**
* 是否开启个性签名
*/
private Integer signEnable;
/**
* 主岗位
*/
@Excel(name="主岗位",width = 15,dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
@Dict(dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
private String mainDepPostId;
/**
* 兼职岗位
*/
@Excel(name="兼职岗位",width = 15,dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
@Dict(dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
@TableField(exist = false)
private String otherDepPostId;
/**
* 职务(字典)
*/
@Excel(name = "职务", width = 15, dicCode = "position_type")
@Dict(dicCode = "position_type")
private String positionType;
}

View File

@ -1,74 +0,0 @@
package org.jeecg.modules.system.entity;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
/**
* @Description: 用户代理人设置
* @Author: jeecg-boot
* @Date: 2019-04-17
* @Version: V1.0
*/
@Data
@TableName("sys_user_agent")
public class SysUserAgent implements Serializable {
private static final long serialVersionUID = 1L;
/**序号*/
@TableId(type = IdType.ASSIGN_ID)
private java.lang.String id;
/**用户名*/
@Excel(name = "用户名", width = 15)
private java.lang.String userName;
/**代理人用户名*/
@Excel(name = "代理人用户名", width = 15)
private java.lang.String agentUserName;
/**代理开始时间*/
@Excel(name = "代理开始时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.util.Date startTime;
/**代理结束时间*/
@Excel(name = "代理结束时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.util.Date endTime;
/**状态0无效1有效*/
@Excel(name = "状态0无效1有效", width = 15)
private java.lang.String status;
/**创建人名称*/
@Excel(name = "创建人名称", width = 15)
private java.lang.String createName;
/**创建人登录名称*/
@Excel(name = "创建人登录名称", width = 15)
private java.lang.String createBy;
/**创建日期*/
@Excel(name = "创建日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.util.Date createTime;
/**更新人名称*/
@Excel(name = "更新人名称", width = 15)
private java.lang.String updateName;
/**更新人登录名称*/
@Excel(name = "更新人登录名称", width = 15)
private java.lang.String updateBy;
/**更新日期*/
@Excel(name = "更新日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.util.Date updateTime;
/**所属部门*/
@Excel(name = "所属部门", width = 15)
private java.lang.String sysOrgCode;
/**所属公司*/
@Excel(name = "所属公司", width = 15)
private java.lang.String sysCompanyCode;
}

View File

@ -0,0 +1,85 @@
package org.jeecg.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 部门岗位用户
* @author: wangshuai
* @date: 2025/9/5 11:45
*/
@Data
@TableName("sys_user_dep_post")
public class SysUserDepPost implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键id")
private String id;
/**
* 用户id
*/
@Schema(description = "用户id")
private String userId;
/**
* 部门岗位id
*/
@Schema(description = "部门岗位id")
private String depId;
/**
* 创建人
*/
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建时间")
private Date createTime;
/**
* 更新人
*/
@Schema(description = "更新人")
private String updateBy;
/**
* 更新时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "更新时间")
private Date updateTime;
/**
* 机构编码
*/
@Excel(name = "机构编码", width = 15)
@Schema(description = "机构编码")
private String orgCode;
public SysUserDepPost(String id, String userId, String depId) {
super();
this.id = id;
this.userId = userId;
this.depId = depId;
}
public SysUserDepPost(String userId, String departId) {
this.userId = userId;
this.depId = departId;
}
}

View File

@ -0,0 +1,34 @@
package org.jeecg.modules.system.excelstyle;
import org.apache.poi.ss.usermodel.*;
import org.jeecgframework.poi.excel.export.styler.ExcelExportStylerDefaultImpl;
/**
* @Description: 导入用户获取标题头部样式 覆盖默认样式
*
* @author: wangshuai
* @date: 2025/8/28 14:05
*/
public class ExcelExportSysUserStyle extends ExcelExportStylerDefaultImpl {
public ExcelExportSysUserStyle(Workbook workbook) {
super(workbook);
}
/**
* 获取标题样式
*
* @param color
* @return
*/
public CellStyle getHeaderStyle(short color) {
CellStyle titleStyle = this.workbook.createCellStyle();
Font font = this.workbook.createFont();
font.setFontHeightInPoints((short)12);
titleStyle.setFont(font);
titleStyle.setAlignment(HorizontalAlignment.LEFT);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
titleStyle.setWrapText(true);
return titleStyle;
}
}

View File

@ -7,9 +7,8 @@ import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.model.TreeModel;
import org.jeecg.modules.system.vo.SysDepartExportVo;
import org.jeecg.modules.system.vo.SysDepartPositionVo;
import org.jeecg.modules.system.vo.SysUserDepVo;
import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
import org.springframework.data.repository.query.Param;
@ -195,4 +194,61 @@ public interface SysDepartMapper extends BaseMapper<SysDepart> {
*/
@InterceptorIgnore(tenantLine = "true")
List<SysUserDepVo> getUserDepartByUserId(@Param("userList")List<SysUser> userList);
/**
* 根据父级id/职级/部门id获取部门岗位信息
*
* @param parentId
* @param postLevel
* @param departId
*/
List<SysDepart> getDepartPositionByParentId(@Param("parentId") String parentId, @Param("postLevel") Integer postLevel, @Param("departId") String departId);
/**
* 根据父级id获取部门中的数据
* @param parentId
* @return
*/
@Select("select id, depart_name, parent_id, iz_leaf, org_category, org_code from sys_depart where parent_id = #{parentId} order by depart_order,create_time desc")
List<SysDepart> getDepartByParentId(@Param("parentId") String parentId);
/**
* 根据部门id查询部门信息
* @param departId
* @return 部门岗位信息
*/
SysDepartPositionVo getDepartPostByDepartId(@Param("departId") String departId);
/**
* 根据父级部门id查询部门信息
* @param orgCode
* @return 部门岗位信息
*/
List<SysDepartPositionVo> getDepartPostByOrgCode(@Param("orgCode") String orgCode);
/**
* 根据部门id获取部门code
* @param idList
* @return
*/
List<String> getDepCodeByDepIds(@Param("idList") List<String> idList);
/**
* 根据父级部门id和职务名称查找部门id
*
* @param parentId
* @param postName
* @return
*/
String getDepIdByDepIdAndPostName(@Param("parentId") String parentId, @Param("postName") String postName);
/**
* 根据部门id 获取职级名称
*
* @param depId
* @return
*/
String getPostNameByPostId(@Param("depId") String depId);
}

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.system.entity.SysTenantPack;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@ -20,4 +21,12 @@ public interface SysTenantPackMapper extends BaseMapper<SysTenantPack> {
* @param tenantIdList
*/
void deletePackByTenantIds(@Param("tenantIdList") List<Integer> tenantIdList);
/**
* 根据租户id和产品包的code获取租户套餐id
*
* @param tenantId
*/
@Select("select id from sys_tenant_pack where tenant_id = #{tenantId} and (pack_code not in('superAdmin','accountAdmin','appAdmin') or pack_code is null) and iz_sysn = '1'")
List<String> getPackIdByPackCodeAndTenantId(@Param("tenantId") Integer tenantId);
}

View File

@ -3,6 +3,8 @@ package org.jeecg.modules.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.system.entity.SysTenantPack;
import org.jeecg.modules.system.entity.SysTenantPackUser;
import java.util.List;
@ -44,4 +46,23 @@ public interface SysTenantPackUserMapper extends BaseMapper<SysTenantPackUser> {
* @param
*/
void deletePackUserByTenantIds(@Param("tenantIds") List<Integer> tenantIds);
/**
* 根据用户id和租户id获取当前租户用户下的产品包id
*
* @param tenantId
* @param userId
* @return
*/
@Select("select pack_id from sys_tenant_pack_user where tenant_id = #{tenantId} and user_id = #{userId}")
List<String> getPackIdByTenantIdAndUserId(@Param("tenantId") Integer tenantId, @Param("userId") String userId);
/**
* 根据租户id获取用户的产品包列表
*
* @param tenantId
* @return
*/
@Select("select id,pack_name,pack_code,pack_type from sys_tenant_pack where tenant_id = #{tenantId}")
List<SysTenantPack> getPackListByTenantId(@Param("tenantId") Integer tenantId);
}

View File

@ -1,17 +0,0 @@
package org.jeecg.modules.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.system.entity.SysUserAgent;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: 用户代理人设置
* @Author: jeecg-boot
* @Date: 2019-04-17
* @Version: V1.0
*/
public interface SysUserAgentMapper extends BaseMapper<SysUserAgent> {
}

View File

@ -0,0 +1,25 @@
package org.jeecg.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.system.entity.SysUserDepPost;
import java.util.List;
/**
* @Description: 部门岗位用户关联表 Mapper
* @author: wangshuai
* @date: 2025/9/5 12:01
*/
public interface SysUserDepPostMapper extends BaseMapper<SysUserDepPost> {
/**
* 通过用户id查询部门岗位用户
*
* @param userId
* @return
*/
@Select("select dep_id from sys_user_dep_post where user_id = #{userId}")
List<String> getDepPostByUserId(@Param("userId") String userId);
}

View File

@ -8,6 +8,7 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.system.entity.SysUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.system.model.SysUserSysDepPostModel;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
import org.jeecg.modules.system.vo.SysUserDepVo;
@ -74,9 +75,10 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
* @param page
* @param roleId 角色id
* @param username 用户登录账户
* @param realname 用户姓名
* @return
*/
IPage<SysUser> getUserByRoleId(Page page, @Param("roleId") String roleId, @Param("username") String username);
IPage<SysUser> getUserByRoleId(Page page, @Param("roleId") String roleId, @Param("username") String username, @Param("realname") String realname);
/**
* 根据用户名设置部门ID
@ -222,4 +224,34 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
*/
@Select("select id,phone from sys_user where phone = #{phone} and username = #{username}")
SysUser getUserByNameAndPhone(@Param("phone") String phone, @Param("username") String username);
/**
* 查询部门、岗位下的用户 包括子部门下的用户
*
* @param page
* @param orgCode
* @param userParams
* @return
*/
List<SysUserSysDepPostModel> queryDepartPostUserByOrgCode(@Param("page") IPage page, @Param("orgCode") String orgCode, @Param("userParams") SysUser userParams);
/**
* 根据部门id和用户名获取部门岗位用户分页列表
*
* @param page
* @param userIdList
* @return
*/
IPage<SysUser> getDepPostListByIdUserName(@Param("page") Page<SysUser> page, @Param("userIdList") List<String> userIdList, @Param("userId") String userId, @Param("userName") String userName, @Param("userNameList") List<String> userNameList);
/**
* 根据部门id、用户名和真实姓名获取部门岗位用户分页列表
*
* @param page
* @param username
* @param realname
* @param orgCode
* @return
*/
IPage<SysUser> getDepartPostListByIdUserRealName(@Param("page") Page<SysUser> page, @Param("username") String username, @Param("realname") String realname, @Param("orgCode") String orgCode);
}

View File

@ -170,7 +170,7 @@
<!--系统后台导出根据父级id和租户id查询部门数据-->
<select id="getSysDepartList" resultType="org.jeecg.modules.system.vo.SysDepartExportVo">
SELECT id,depart_name,parent_id,depart_name_en,depart_order,description,org_category,org_code,mobile,fax,address,memo FROM sys_depart
SELECT id,depart_name,parent_id,depart_name_en,depart_order,description,org_category,org_code,mobile,fax,address,memo, position_id FROM sys_depart
WHERE
1=1
<if test="null != tenantId and 0 != tenantId">
@ -209,7 +209,7 @@
<!--根据用户id获取部门信息-->
<select id="getUserDepartByUserId" resultType="org.jeecg.modules.system.vo.SysUserDepVo">
SELECT sd.depart_name, sud.user_id, sd.id as deptId, sd.parent_id
SELECT sd.depart_name, sud.user_id, sd.id as deptId, sd.parent_id, sd.org_category
FROM sys_depart sd
RIGHT JOIN sys_user_depart sud on sd.id = sud.dep_id and sd.del_flag = 0
WHERE sud.user_id IN
@ -218,4 +218,54 @@
</foreach>
order by sd.org_code;
</select>
<!--根据父级id/职级/部门id获取部门岗位信息-->
<select id="getDepartPositionByParentId" resultType="org.jeecg.modules.system.entity.SysDepart">
select sd.depart_name, sd.id, sd.iz_leaf, sd.org_category, sd.parent_id, sd.org_code from sys_depart sd left join sys_position sp on sd.position_id = sp.id
where sd.parent_id = #{parentId}
and sd.org_category = '3'
<if test="postLevel != null">
and sp.post_level <![CDATA[ < ]]> #{postLevel}
</if>
<if test="departId != null and departId != ''">
and sd.id != #{departId}
</if>
order by sd.depart_order,sd.create_time desc
</select>
<!--根据部门id获取部门信息-->
<select id="getDepartPostByDepartId" resultType="org.jeecg.modules.system.vo.SysDepartPositionVo">
select depart_name as positionName,id,iz_leaf,parent_id,org_category,org_code, dep_post_parent_id from sys_depart
where id = #{departId}
</select>
<!--根据部门编码查询部门信息-->
<select id="getDepartPostByOrgCode" resultType="org.jeecg.modules.system.vo.SysDepartPositionVo">
select depart_name as positionName,id,iz_leaf,parent_id,org_category,org_code, dep_post_parent_id from sys_depart
where org_code like #{orgCode}
and org_category = '3'
order by depart_order,create_time desc
</select>
<!--根据部门id获取部门编码-->
<select id="getDepCodeByDepIds" resultType="java.lang.String">
SELECT org_code
FROM sys_depart
WHERE id IN
<foreach collection="idList" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<!-- 根据父级部门id和职务名称查找部门id -->
<select id="getDepIdByDepIdAndPostName" resultType="java.lang.String">
SELECT id FROM sys_depart
WHERE parent_id = #{parentId} and depart_name = #{postName}
</select>
<!--根据部门id获取职级名称-->
<select id="getPostNameByPostId" resultType="java.lang.String">
select sp.name from sys_depart sd join sys_position sp on sd.position_id = sp.id
where sd.id = #{depId}
</select>
</mapper>

View File

@ -28,15 +28,16 @@
,icon
,is_leaf
FROM sys_permission
WHERE 1=1
<choose>
<when test="parentId != null and parentId != ''">
AND parent_id = #{parentId,jdbcType=VARCHAR}
</when>
<otherwise>
AND parent_id is null
</otherwise>
</choose>
<where>
<choose>
<when test="parentId != null and parentId != ''">
parent_id = #{parentId,jdbcType=VARCHAR}
</when>
<otherwise>
parent_id is null
</otherwise>
</choose>
</where>
</select>
<!-- 获取登录用户拥有的权限 -->
@ -212,7 +213,7 @@
</select>
<!--根据用户名称和test角色id查询权限-->
<select id="queryPermissionByTestRoleId" resultType="org.jeecg.modules.system.entity.SysPermission">
<select id="queryPermissionByTestRoleId" resultMap="SysPermission">
SELECT p.*
FROM sys_permission p
WHERE exists(

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.system.mapper.SysUserAgentMapper">
</mapper>

View File

@ -57,6 +57,9 @@
<if test="username!=null and username!=''">
and username = #{username}
</if>
<if test="realname!=null and realname!=''">
and realname LIKE concat(concat('%',#{realname}),'%')
</if>
</select>
<!-- 修改用户部门code -->
@ -298,4 +301,125 @@
and sut.tenant_id=#{tenantId}
and sut.status = '1'
</select>
<!-- SQL片段getDepPostListByIdUserName WHERE 部分 -->
<sql id="getDepPostListByIdUserNameSql">
WHERE
su.status = 1
and su.del_flag = 0
and username <![CDATA[ != ]]> '_reserve_user_external'
<if test="userId!= null and userId != ''">
and su.id = #{userId}
</if>
<if test="userName!= null and userName != ''">
<bind name="bindUserName" value="userName+'%'"/>
and su.username like #{bindUserName}
</if>
<if test="userIdList != null and userIdList.size() > 0">
<foreach item="idItem" index="index" collection="userIdList" open=" and su.id IN (" separator="," close=")">
#{idItem}
</foreach>
</if>
<if test="userNameList != null and userNameList.size() > 0">
<foreach item="usernameItem" index="index" collection="userNameList" open=" and su.username IN (" separator="," close=")">
#{usernameItem}
</foreach>
</if>
</sql>
<!-- 根据部门id和用户名获取部门岗位用户分页列表 -->
<select id="getDepPostListByIdUserName" resultType="org.jeecg.modules.system.entity.SysUser">
SELECT su.* from
(
SELECT su.create_time,su.realname,su.username,su.phone FROM sys_user su
<include refid="getDepPostListByIdUserNameSql"/>
union
select DISTINCT su.create_time,su.realname,su.username,su.phone FROM sys_user su
JOIN sys_user_dep_post sudp ON su.id = sudp.user_id
<include refid="getDepPostListByIdUserNameSql"/>
) su
order by su.create_time desc
</select>
<!-- SQL片段getDepartPostListByIdUserRealName WHERE部分 -->
<sql id="getDepartPostListByIdUserRealNameSql">
WHERE
su.status = 1
and su.del_flag = 0
and username <![CDATA[ != ]]> '_reserve_user_external'
<if test="realname!= null and realname != ''">
<bind name="bindRealname" value="realname+'%'"/>
and su.id like #{bindRealname}
</if>
<if test="username!= null and username != ''">
<bind name="bindUserName" value="username+'%'"/>
and su.username like #{bindUserName}
</if>
<if test="orgCode!= null and orgCode != ''">
<bind name="bindOrgCode" value="orgCode+'%'"/>
and sd.org_code like #{bindOrgCode}
</if>
</sql>
<!-- 根据部门id、用户名和真实姓名获取部门岗位用户分页列表 -->
<select id="getDepartPostListByIdUserRealName" resultType="org.jeecg.modules.system.entity.SysUser">
SELECT su.* from
(
SELECT su.create_time,su.realname,su.username,su.phone FROM sys_user su
join sys_depart sd on su.main_dep_post_id = sd.id
<include refid="getDepartPostListByIdUserRealNameSql"/>
union
SELECT DISTINCT su.create_time,su.realname,su.username,su.phone FROM sys_user su
join sys_depart sd on su.main_dep_post_id = sd.id
join sys_user_dep_post sudp on su.id = sudp.user_id
<include refid="getDepartPostListByIdUserRealNameSql"/>
) su
order by su.create_time desc
</select>
<!-- SQL片段queryDepartPostUserByOrgCode WHERE部分 -->
<sql id="queryDepartPostUserByOrgCodeSql">
WHERE
<if test="orgCode == null">
<bind name="bindOrgCode" value="'%'"/>
</if>
<if test="orgCode != null">
<bind name="bindOrgCode" value="orgCode+'%'"/>
</if>
su.del_flag = 0 AND sd.org_code LIKE #{bindOrgCode}
<if test="userParams != null">
<if test="userParams.realname != null and userParams.realname != ''">
<bind name="bindRealname" value="'%'+ userParams.realname +'%'"/>
AND su.realname LIKE bindRealname
</if>
<if test="userParams.workNo != null and userParams.workNo != ''">
<bind name="bindWorkNo" value="'%'+ userParams.workNo +'%'"/>
AND su.work_no LIKE bindWorkNo
</if>
</if>
</sql>
<!-- 查询部门、岗位下的用户 包括子部门下的用户 -->
<select id="queryDepartPostUserByOrgCode" resultType="org.jeecg.modules.system.model.SysUserSysDepPostModel">
SELECT su.* from
(
SELECT su.id, su.create_time, su.realname, su.username, su.phone, su.avatar, su.birthday, su.sex, su.email,
su.status, su.del_flag, su.telephone, su.activiti_sync, su.user_identity, su.depart_ids, su.main_dep_post_id
FROM sys_user su join sys_user_depart sud on su.id = sud.user_id
join sys_depart sd on sud.dep_id = sd.id
<include refid="queryDepartPostUserByOrgCodeSql"/>
union
SELECT su.id, su.create_time, su.realname, su.username, su.phone, su.avatar, su.birthday, su.sex, su.email,
su.status, su.del_flag, su.telephone, su.activiti_sync, su.user_identity, su.depart_ids, su.main_dep_post_id
FROM sys_user su join sys_depart sd on su.main_dep_post_id = sd.id
<include refid="queryDepartPostUserByOrgCodeSql"/>
union
SELECT su.id, su.create_time, su.realname, su.username, su.phone, su.avatar, su.birthday, su.sex, su.email,
su.status, su.del_flag, su.telephone, su.activiti_sync, su.user_identity, su.depart_ids, su.main_dep_post_id
FROM sys_user su join sys_user_dep_post sudp on su.id = sudp.user_id
join sys_depart sd on sd.id = sudp.dep_id
<include refid="queryDepartPostUserByOrgCodeSql"/>
) su
order by su.create_time desc
</select>
</mapper>

View File

@ -70,7 +70,7 @@
<!--联查用户和租户审核状态-->
<select id="getUserTenantPageList" resultType="org.jeecg.modules.system.vo.SysUserTenantVo">
SELECT su.id,su.realname,su.username,su.email,su.phone,su.avatar,su.work_no,su.org_code,sut.status,st.create_by
SELECT su.id,su.realname,su.username,su.email,su.phone,su.avatar,su.work_no,su.org_code,sut.status,su.create_time,st.create_by
FROM sys_user_tenant sut
RIGHT JOIN sys_user su on sut.user_id = su.id and su.del_flag = 0
JOIN sys_tenant st ON sut.tenant_id = st.id

View File

@ -28,6 +28,10 @@ public class DepartIdModel implements Serializable {
* 主键ID
*/
private String value;
/**
* 部门编码
*/
private String code;
/**
* 部门名称
@ -56,6 +60,7 @@ public class DepartIdModel implements Serializable {
public DepartIdModel convertByUserDepart(SysDepart sysDepart) {
this.key = sysDepart.getId();
this.value = sysDepart.getId();
this.code = sysDepart.getOrgCode();
this.title = sysDepart.getDepartName();
return this;
}
@ -95,4 +100,12 @@ public class DepartIdModel implements Serializable {
public void setTitle(String title) {
this.title = title;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@ -80,6 +80,12 @@ public class SysDepartTreeModel implements Serializable{
private String directorUserIds;
//update-end---author:wangshuai ---date:20200308 for[JTC-119]在部门管理菜单下设置部门负责人新增字段部门负责人ids
/**职务*/
private String positionId;
/**上级岗位id*/
private String depPostParentId;
private List<SysDepartTreeModel> children = new ArrayList<>();
@ -113,6 +119,8 @@ public class SysDepartTreeModel implements Serializable{
this.updateBy = sysDepart.getUpdateBy();
this.updateTime = sysDepart.getUpdateTime();
this.directorUserIds = sysDepart.getDirectorUserIds();
this.positionId = sysDepart.getPositionId();
this.depPostParentId = sysDepart.getDepPostParentId();
if(0 == sysDepart.getIzLeaf()){
this.isLeaf = false;
}else{
@ -351,6 +359,22 @@ public class SysDepartTreeModel implements Serializable{
this.directorUserIds = directorUserIds;
}
public String getPositionId() {
return positionId;
}
public void setPositionId(String positionId) {
this.positionId = positionId;
}
public String getDepPostParentId() {
return depPostParentId;
}
public void setDepPostParentId(String depPostParentId) {
this.depPostParentId = depPostParentId;
}
/**
* 重写equals方法
*/
@ -385,6 +409,8 @@ public class SysDepartTreeModel implements Serializable{
Objects.equals(updateBy, model.updateBy) &&
Objects.equals(updateTime, model.updateTime) &&
Objects.equals(directorUserIds, model.directorUserIds) &&
Objects.equals(positionId, model.positionId) &&
Objects.equals(depPostParentId, model.depPostParentId) &&
Objects.equals(children, model.children);
}
@ -397,7 +423,7 @@ public class SysDepartTreeModel implements Serializable{
return Objects.hash(id, parentId, departName, departNameEn, departNameAbbr,
departOrder, description, orgCategory, orgType, orgCode, mobile, fax, address,
memo, status, delFlag, qywxIdentifier, createBy, createTime, updateBy, updateTime,
children,directorUserIds);
children,directorUserIds, positionId, depPostParentId);
}
}

View File

@ -0,0 +1,139 @@
package org.jeecg.modules.system.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @Description: 部门用户和部门岗位用户的Model
* @author: wangshuai
* @date: 2025/9/5 16:43
*/
@Data
public class SysUserSysDepPostModel {
/**
* 用户ID
*/
private String id;
/* 真实姓名 */
private String realname;
/**
* 头像
*/
@Excel(name = "头像", width = 15, type = 2)
private String avatar;
/**
* 生日
*/
@Excel(name = "生日", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
/**
* 性别1男 2
*/
@Excel(name = "性别", width = 15, dicCode = "sex")
@Dict(dicCode = "sex")
private Integer sex;
/**
* 电子邮件
*/
@Excel(name = "电子邮件", width = 15)
private String email;
/**
* 电话
*/
@Excel(name = "电话", width = 15)
private String phone;
/**
* 状态(1正常 2冻结
*/
@Excel(name = "状态", width = 15, dicCode = "user_status")
@Dict(dicCode = "user_status")
private Integer status;
/**
* 删除状态0正常1已删除
*/
@Excel(name = "删除状态", width = 15, dicCode = "del_flag")
@TableLogic
private Integer delFlag;
/**
* 座机号
*/
@Excel(name = "座机号", width = 15)
private String telephone;
/**
* 身份0 普通成员 1 上级)
*/
@Excel(name = "1普通成员 2上级", width = 15)
private Integer userIdentity;
/**
* 负责部门
*/
@Excel(name = "负责部门", width = 15, dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
@Dict(dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
private String departIds;
/**
* 多租户ids临时用不持久化数据库(数据库字段不存在)
*/
private String relTenantIds;
/**
* 同步工作流引擎(1-同步 0-不同步)
*/
private String activitiSync;
/**
* 主岗位
*/
@Excel(name = "主岗位", width = 15, dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
@Dict(dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
private String mainDepPostId;
/**
* 兼职岗位
*/
@Excel(name = "兼职岗位", width = 15, dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
@Dict(dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
@TableField(exist = false)
private String otherDepPostId;
/**
* 部门名称
*/
private String departName;
/**
* 主岗位
*/
private String postName;
/**
* 兼职岗位
*/
private String otherPostName;
/**
* 部门text
*/
private String orgCodeTxt;
/**
* 职务
*/
private String post;
}

View File

@ -22,7 +22,7 @@ public class TreeModel implements Serializable {
private String slotTitle;
private boolean isLeaf;
private Boolean isLeaf;
private String icon;
@ -54,11 +54,11 @@ public class TreeModel implements Serializable {
this.title = title;
}
public boolean getIsLeaf() {
public Boolean getIsLeaf() {
return isLeaf;
}
public void setIsLeaf(boolean isLeaf) {
public void setIsLeaf(Boolean isLeaf) {
this.isLeaf = isLeaf;
}

View File

@ -2,6 +2,8 @@ package org.jeecg.modules.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.modules.system.entity.SysAnnouncement;
import java.util.Date;
@ -98,4 +100,12 @@ public interface ISysAnnouncementService extends IService<SysAnnouncement> {
* @param count
*/
void updateVisitsNum(String id, int count);
/**
* 批量下载文件
* @param id
* @param request
* @param response
*/
void downLoadFiles(String id, HttpServletRequest request, HttpServletResponse response);
}

View File

@ -5,10 +5,10 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUserDepart;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.vo.SysDepartExportVo;
import org.jeecg.modules.system.vo.SysPositionSelectTreeVo;
import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
import jakarta.servlet.http.HttpServletRequest;
@ -75,12 +75,15 @@ public interface ISysDepartService extends IService<SysDepart>{
/**
* 根据关键字搜索相关的部门数据
*
* @param keyWord
* @param myDeptSearch
* @param departIds 多个部门id
* @param departIds 多个部门id
* @param orgCategory
* @param depIds
* @return
*/
List<SysDepartTreeModel> searchByKeyWord(String keyWord,String myDeptSearch,String departIds);
List<SysDepartTreeModel> searchByKeyWord(String keyWord, String myDeptSearch, String departIds, String orgCategory, String depIds);
/**
* 根据部门id删除并删除其可能存在的子级部门
@ -240,4 +243,40 @@ public interface ISysDepartService extends IService<SysDepart>{
* @param errorMessageList
*/
void importSysDepart(List<SysDepartExportVo> listSysDeparts, List<String> errorMessageList);
/**
* 根据部门id和职级id获取岗位信息
*
* @param parentId
* @param departId
* @param positionId
*/
List<SysPositionSelectTreeVo> getPositionByDepartId(String parentId, String departId, String positionId);
/**
* 获取职级关系
* @param departId
* @return
*/
List<SysPositionSelectTreeVo> getRankRelation(String departId);
/**
* 异步查询部门和岗位接口
*
* @param parentId
* @param ids
* @param primaryKey
* @param departIds
* @return
*/
List<SysDepartTreeModel> queryDepartAndPostTreeSync(String parentId, String ids, String primaryKey, String departIds,String orgName);
/**
* 根据部门code获取当前和上级部门名称
*
* @param orgCode
* @param depId
* @return
*/
String getDepartPathNameByOrgCode(String orgCode, String depId);
}

View File

@ -87,4 +87,21 @@ public interface ISysTenantPackService extends IService<SysTenantPack> {
* @date 2025/2/5 19:08
*/
void syncDefaultPack(Integer tenantId);
/**
* 根据用户id和当前的租户id获取产品包的id
*
* @param userId
* @param tenantId
* @return
*/
List<String> getPackIdByUserIdAndTenantId(String userId, Integer tenantId);
/**
* 根据租户id获取用户的产品包列表
*
* @param tenantId
* @return
*/
List<SysTenantPack> getPackListByTenantId(String tenantId);
}

View File

@ -49,8 +49,9 @@ public interface ISysTenantService extends IService<SysTenant> {
* 邀请用户加入租户,通过手机号
* @param ids
* @param phone
* @param username
*/
void invitationUserJoin(String ids, String phone);
void invitationUserJoin(String ids, String phone,String username);
/**
* 请离用户(租户)
@ -239,4 +240,11 @@ public interface ISysTenantService extends IService<SysTenant> {
* @param tenantId
*/
void deleteUser(SysUser sysUser, Integer tenantId);
/**
* 为用户添加租户下所有套餐
* @param userId
* @param tenantId
*/
void addPackUser(String userId, String tenantId);
}

View File

@ -1,14 +0,0 @@
package org.jeecg.modules.system.service;
import org.jeecg.modules.system.entity.SysUserAgent;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: 用户代理人设置
* @Author: jeecg-boot
* @Date: 2019-04-17
* @Version: V1.0
*/
public interface ISysUserAgentService extends IService<SysUserAgent> {
}

View File

@ -0,0 +1,13 @@
package org.jeecg.modules.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.entity.SysUserDepPost;
/**
* @Description: 部门岗位用户表
* @author: wangshuai
* @date: 2025/9/5 11:45
*/
public interface ISysUserDepPostService extends IService<SysUserDepPost> {
}

View File

@ -86,4 +86,18 @@ public interface ISysUserDepartService extends IService<SysUserDepart> {
* @return
*/
List<SysUser> getUsersByDepartTenantId(String departId,Integer tenantId);
/**
* 查询部门岗位下的用户
*
* @param departId
* @param username
* @param realname
* @param pageSize
* @param pageNo
* @param id
* @param isMultiTranslate
* @return
*/
IPage<SysUser> queryDepartPostUserPageList(String departId, String username, String realname, Integer pageSize, Integer pageNo, String id, String isMultiTranslate);
}

View File

@ -11,6 +11,7 @@ import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.modules.system.entity.SysRoleIndex;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.model.SysUserSysDepPostModel;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
import org.jeecg.modules.system.vo.SysUserExportVo;
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
@ -175,10 +176,11 @@ public interface ISysUserService extends IService<SysUser> {
* 根据角色Id查询
* @param page
* @param roleId 角色id
* @param username 用户账户名称
* @param username 用户账户
* @param realname 用户姓名
* @return
*/
public IPage<SysUser> getUserByRoleId(Page<SysUser> page,String roleId, String username);
public IPage<SysUser> getUserByRoleId(Page<SysUser> page,String roleId, String username, String realname);
/**
* 通过用户名获取用户角色集合
@ -298,13 +300,15 @@ public interface ISysUserService extends IService<SysUser> {
List<SysUser> queryByDepIds(List<String> departIds, String username);
/**
* 保存用户
* @param user 用户
* @param selectedRoles 选择的角色id多个以逗号隔开
* @param selectedDeparts 选择的部门id多个以逗号隔开
* @param relTenantIds 多个租户id
*/
void saveUser(SysUser user, String selectedRoles, String selectedDeparts, String relTenantIds);
* 保存用户
*
* @param user 用户
* @param selectedRoles 选择的角色id多个以逗号隔开
* @param selectedDeparts 选择的部门id多个以逗号隔开
* @param relTenantIds 多个租户id
* @param izSyncPack 是否需要同步租户套餐包
*/
void saveUser(SysUser user, String selectedRoles, String selectedDeparts, String relTenantIds, boolean izSyncPack);
/**
* 编辑用户
@ -481,4 +485,22 @@ public interface ISysUserService extends IService<SysUser> {
* @param username
*/
void updatePasswordNotBindPhone(String oldPassword, String password, String username);
/**
* 根据用户名称查询用户和部门信息
* @param userName
* @return
*/
Map<String, String> queryUserAndDeptByName(String userName);
/**
* 查询部门、岗位下的用户 包括子部门下的用户
*
* @param orgCode
* @param userParams
* @param page
* @return
*/
IPage<SysUserSysDepPostModel> queryDepartPostUserByOrgCode(String orgCode, SysUser userParams, IPage page);
}

View File

@ -1,14 +1,21 @@
package org.jeecg.modules.system.service.impl;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.FileDownloadUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.system.entity.SysAnnouncement;
@ -19,11 +26,12 @@ import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.service.ISysAnnouncementSendService;
import org.jeecg.modules.system.service.ISysAnnouncementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.io.*;
import java.net.URLEncoder;
import jakarta.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
@ -53,7 +61,9 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
@Autowired
private ISysAnnouncementSendService sysAnnouncementSendService;
@Autowired
private JeecgBaseConfig jeecgBaseConfig;
@Transactional(rollbackFor = Exception.class)
@Override
public void saveAnnouncement(SysAnnouncement sysAnnouncement) {
@ -253,4 +263,64 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
}
}
/**
* 批量下载文件
* @param id
* @param request
* @param response
*/
@Override
public void downLoadFiles(String id, HttpServletRequest request, HttpServletResponse response) {
// 参数校验
if (oConvertUtils.isEmpty(id)) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
// 获取文章信息
SysAnnouncement sysAnnouncement = this.baseMapper.selectById(id);
if (oConvertUtils.isEmpty(sysAnnouncement)) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
//设置HTTP响应头准备文件下载
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("application/force-download");
ZipArchiveOutputStream zous = null;
try {
// 生成ZIP文件名使用文章标题+时间戳避免重名
String title = sysAnnouncement.getTitile() + new Date().getTime();
String zipName = URLEncoder.encode( title + ".zip", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + zipName);
// 创建ZIP输出流直接输出到HTTP响应流
zous = new ZipArchiveOutputStream(response.getOutputStream());
zous.setUseZip64(Zip64Mode.AsNeeded);// 支持大文件
// 批量下载文件
String[] fileUrls = sysAnnouncement.getFiles().split(",");
// 遍历所有文件URL
for (int i = 0; i < fileUrls.length; i++) {
String fileUrl = fileUrls[i].trim();
if (oConvertUtils.isEmpty(fileUrl)) {
continue;
}
// 生成ZIP内文件名避免重名添加序号
String fileName = FileDownloadUtils.generateFileName(fileUrl, i, fileUrls.length);
String uploadUrl = jeecgBaseConfig.getPath().getUpload();
// 下载单个文件并添加到ZIP
FileDownloadUtils.downLoadSingleFile(fileUrl,fileName,uploadUrl, zous);
}
// 完成ZIP写入
zous.finish();
// 刷新缓冲区确保数据发送
response.flushBuffer();
} catch (IOException e) {
log.error("文件下载失败"+e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
// 确保流关闭,防止资源泄漏
IoUtil.close(zous);
}
}
}

View File

@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Joiner;
import com.jeecg.dingtalk.api.core.response.Response;
@ -19,6 +20,8 @@ import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
@ -32,13 +35,14 @@ import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryCondition;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.*;
import org.jeecg.common.util.*;
import org.jeecg.common.util.dynamic.db.FreemarkerParseFactory;
import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.airag.flow.service.IAiragFlowService;
import org.jeecg.modules.airag.flow.vo.api.FlowRunParams;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import org.jeecg.modules.message.handle.impl.DdSendMsgHandle;
import org.jeecg.modules.message.handle.impl.EmailSendMsgHandle;
@ -141,6 +145,9 @@ public class SysBaseApiImpl implements ISysBaseAPI {
@Autowired
private ISysAnnouncementService sysAnnouncementService;
@Autowired
IAiragFlowService airagFlowService;
@Override
//@SensitiveDecode
public LoginUser getUserByName(String username) {
@ -456,7 +463,8 @@ public class SysBaseApiImpl implements ISysBaseAPI {
message.getContent(),
message.getCategory(),
message.getBusType(),
message.getBusId());
message.getBusId(),
message.getNoticeType());
try {
// 同步发送第三方APP消息
wechatEnterpriseService.sendMessage(message, true);
@ -536,7 +544,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
try {
// 同步企业微信、钉钉的消息通知
dingtalkService.sendActionCardMessage(announcement, mobileOpenUrl, true);
wechatEnterpriseService.sendTextCardMessage(announcement, true);
wechatEnterpriseService.sendTextCardMessage(announcement, mobileOpenUrl, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
@ -589,7 +597,17 @@ public class SysBaseApiImpl implements ISysBaseAPI {
if(tmplateParam!=null && oConvertUtils.isNotEmpty(tmplateParam.get(CommonConstant.MSG_HREF_URL))){
mobileOpenUrl = tmplateParam.get(CommonConstant.MSG_HREF_URL);
}
// 如果传递扩展json说明是个性化业务有意见remark则设置为通知内容
if(oConvertUtils.isJson(announcement.getMsgAbstract())) {
// 获取announcement.getMsgAbstract()的字段remark
JSONObject jsonObject = JSON.parseObject(announcement.getMsgAbstract());
String remark = jsonObject.containsKey("remark")? jsonObject.getString("remark"): null;
if(oConvertUtils.isNotEmpty(remark)){
announcement.setMsgContent(remark);
}
}
announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
announcement.setBusId(busId);
@ -624,7 +642,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
// 钉钉的消息通知
dingtalkService.sendActionCardMessage(announcement, mobileOpenUrl, true);
// 企业微信通知
wechatEnterpriseService.sendTextCardMessage(announcement, true);
wechatEnterpriseService.sendTextCardMessage(announcement, mobileOpenUrl, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
@ -778,7 +796,6 @@ public class SysBaseApiImpl implements ISysBaseAPI {
return json;
}
@Override
public List<ComboModel> queryAllRole() {
List<ComboModel> list = new ArrayList<ComboModel>();
List<SysRole> roleList = roleMapper.selectList(new QueryWrapper<SysRole>());
@ -1372,8 +1389,9 @@ public class SysBaseApiImpl implements ISysBaseAPI {
* @param setMsgCategory
* @param busType
* @param busId
* @param noticeType 消息类型,for [JHHB-136]【vue3】协同工作系统消息需要添加一个类型
*/
private void sendBusAnnouncement(String fromUser, String toUser, String title, String msgContent, String setMsgCategory, String busType, String busId) {
private void sendBusAnnouncement(String fromUser, String toUser, String title, String msgContent, String setMsgCategory, String busType, String busId, String noticeType) {
SysAnnouncement announcement = new SysAnnouncement();
announcement.setTitile(title);
announcement.setMsgContent(msgContent);
@ -1388,7 +1406,12 @@ public class SysBaseApiImpl implements ISysBaseAPI {
announcement.setBusType(busType);
announcement.setOpenType(SysAnnmentTypeEnum.getByType(busType).getOpenType());
announcement.setOpenPage(SysAnnmentTypeEnum.getByType(busType).getOpenPage());
announcement.setNoticeType(NoticeTypeEnum.NOTICE_TYPE_FLOW.getValue());
//update-begin---author:chenrui ---date:20250807 for[JHHB-136]【vue3】协同工作系统消息需要添加一个类型------------
if(oConvertUtils.isEmpty(noticeType)){
noticeType = NoticeTypeEnum.NOTICE_TYPE_FLOW.getValue();
}
announcement.setNoticeType(noticeType);
//update-end---author:chenrui ---date:20250807 for[JHHB-136]【vue3】协同工作系统消息需要添加一个类型------------
//update-begin-author:liusq---date:2025-07-01--for: [QQYUN-12999]系统通知,系统通知时间更新,但是排到下面了
announcement.setIzTop(CommonConstant.IZ_TOP_0);
//update-end-author:liusq---date:2025-07-01--for: [QQYUN-12999]系统通知,系统通知时间更新,但是排到下面了
@ -1800,8 +1823,23 @@ public class SysBaseApiImpl implements ISysBaseAPI {
queryWrapper.lambda().select(SysUserDepart::getUserId).in(true,SysUserDepart::getDepId,deptIds);
return sysUserDepartService.listObjs(queryWrapper,e->e.toString());
}
@Override
@Override
public List<String> queryUserIdsByCascadeDeptIds(List<String> deptIds) {
Set<String> userIds = new HashSet<>();
List<SysDepart> departs = sysDepartService.list(Wrappers.lambdaQuery(SysDepart.class)
.select(SysDepart::getOrgCode)
.in(SysDepart::getId, deptIds));
departs.forEach(depart -> {
List<SysUser> sysUsers = sysUserDepartService.queryUserByDepCode(depart.getOrgCode(), null);
if(oConvertUtils.isObjectNotEmpty(sysUsers)){
userIds.addAll(sysUsers.stream().map(SysUser::getId).collect(Collectors.toSet()));
}
});
return new ArrayList<>(userIds);
}
@Override
public List<String> queryUserAccountsByDeptIds(List<String> deptIds) {
return departMapper.queryUserAccountByDepartIds(deptIds);
}
@ -1956,7 +1994,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
try {
// 同步企业微信、钉钉的消息通知
Response<String> dtResponse = dingtalkService.sendActionCardMessage(sysAnnouncement, null, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, null,true);
if (dtResponse != null && dtResponse.isSuccess()) {
String taskId = dtResponse.getResult();
@ -1969,6 +2007,131 @@ public class SysBaseApiImpl implements ISysBaseAPI {
}
}
@Override
public SysDepartModel queryCompByOrgCode(String orgCode) {
AssertUtils.assertNotEmpty("请输入部门编码",orgCode);
SysDepart comp = sysDepartService.queryCompByOrgCode(orgCode);
if(comp == null) {
log.error("未查询到对应的公司信息");
return null;
}
SysDepartModel respData = new SysDepartModel();
BeanUtils.copyProperties(comp, respData);
return respData;
}
/**
* 根据部门编码和层次查询上级公司
*
* @param orgCode 部门编码
* @param level 可以传空 默认为1 最小值为1
* @return
*/
@Override
public SysDepartModel queryCompByOrgCodeAndLevel(String orgCode, Integer level) {
if (null == level || 0 == level) {
level = 1;
}
int codeNum = YouBianCodeUtil.ZHANWEI_LENGTH;
//先判断父级code
String parendCode = "";
if (orgCode.length() > codeNum) {
parendCode = orgCode.substring(0, codeNum);
} else {
return null;
}
//根据部门编码查询公司和子公司的数据
List<String> categoryList = new ArrayList<>();
categoryList.add(DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue());
categoryList.add(DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue());
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
query.like(SysDepart::getOrgCode, parendCode);
query.in(SysDepart::getOrgCategory, categoryList);
query.orderByAsc(SysDepart::getOrgType);
List<SysDepart> sysDepartList = sysDepartService.list(query);
if (!CollectionUtils.isEmpty(sysDepartList)) {
//获取上级公司
SysDepart depart = getParentCompanyByOrgCode(orgCode, sysDepartList, level, 1);
if(depart == null){
depart = sysDepartList.get(0);
}
SysDepartModel respData = new SysDepartModel();
BeanUtils.copyProperties(depart, respData);
return respData;
}
return null;
}
@Override
public Object runAiragFlow(AiragFlowDTO airagFlowDTO) {
if(oConvertUtils.isEmpty(airagFlowDTO.getFlowId())) {
throw new JeecgBootException("流程ID不能为空");
}
FlowRunParams params = new FlowRunParams();
params.setFlowId(airagFlowDTO.getFlowId());
params.setInputParams(airagFlowDTO.getInputParams());
params.setResponseMode("blocking");
Result<Object> o = (Result<Object>)airagFlowService.runFlow(params);
return o.getResult();
}
/**
* 根据orgCode找上级
*
* @param orgCode
* @param sysDepartList
* @param level 指定那第几级 从下往上
* @param nowLevel
* @return
*/
public SysDepart getParentCompanyByOrgCode(String orgCode,List<SysDepart> sysDepartList, int level, int nowLevel) {
//获取上一级公司的编码
String code = this.getPrefix(orgCode);
if(oConvertUtils.isEmpty(code)) {
return null;
}
List<SysDepart> list = sysDepartList.stream().filter(sysDepart -> sysDepart.getOrgCode().equals(code)).toList();
//判断去上级的级别
if(!CollectionUtils.isEmpty(list) && nowLevel == level) {
return list.get(0);
} else {
if(!CollectionUtils.isEmpty(list)) {
nowLevel++;
}
return getParentCompanyByOrgCode(code, sysDepartList, level, nowLevel);
}
}
/**
* 根据指定值获取编码前缀每级固定YouBianCodeUtil.ZHANWEI_LENGTH位
*
* @param fullCode 完整编码(如"A01A01A01"
* @return 提取后的前缀编码(如"A01A01"
*/
private String getPrefix(String fullCode) {
if(fullCode.length() < YouBianCodeUtil.ZHANWEI_LENGTH){
return "";
}
// 计算总层级数,根据ZHANWEI_LENGTH
int totalLevels = fullCode.length() / YouBianCodeUtil.ZHANWEI_LENGTH;
int keepLevels = totalLevels - 1;
// 计算需要截取的长度(保留层级数 × YouBianCodeUtil.ZHANWEI_LENGTH
int prefixLength = keepLevels * YouBianCodeUtil.ZHANWEI_LENGTH;
return prefixLength == 0 ? "" : fullCode.substring(0, prefixLength);
}
/**
* 根据部门code或部门id获取部门名称(当前和上级部门)
*
* @param orgCode 部门编码
* @param depId 部门id
* @return String 部门名称
*/
@Override
public String getDepartPathNameByOrgCode(String orgCode, String depId) {
return sysDepartService.getDepartPathNameByOrgCode(orgCode, depId);
}
@Override
public JSONObject setLoginTenant(String username) {
JSONObject obj = new JSONObject(new LinkedHashMap<>());

View File

@ -17,11 +17,10 @@ import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.FillRuleConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.DepartCategoryEnum;
import org.jeecg.common.exception.JeecgBootBizTipException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.common.util.YouBianCodeUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.*;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.system.entity.*;
@ -31,12 +30,15 @@ import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.util.FindsDepartsChildrenUtil;
import org.jeecg.modules.system.vo.SysDepartExportVo;
import org.jeecg.modules.system.vo.SysDepartPositionVo;
import org.jeecg.modules.system.vo.SysPositionSelectTreeVo;
import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.function.Consumer;
@ -67,7 +69,11 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
private SysUserMapper sysUserMapper;
@Autowired
private SysDepartMapper departMapper;
@Autowired
private SysPositionMapper sysPositionMapper;
@Autowired
private RedisUtil redisUtil;
@Override
public List<SysDepartTreeModel> queryMyDeptTreeList(String departIds) {
//根据部门id获取所负责部门
@ -82,7 +88,7 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
query.or().likeRight(SysDepart::getOrgCode,codeArr[i]);
}
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
query.ne(SysDepart::getOrgCategory,DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
//------------------------------------------------------------------------------------------------
//是否开启系统管理模块的 SASS 控制
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
@ -119,6 +125,9 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
}
//------------------------------------------------------------------------------------------------
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
//update-begin---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
query.ne(SysDepart::getOrgCategory, DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
//update-end---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
query.orderByAsc(SysDepart::getDepartOrder);
List<SysDepart> list = this.list(query);
//update-begin---author:wangshuai ---date:20220307 for[JTC-119]在部门管理菜单下设置部门负责人 创建用户的时候不需要处理
@ -138,6 +147,9 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
List<SysDepartTreeModel> listResult=new ArrayList<>();
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
//update-begin---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
query.ne(SysDepart::getOrgCategory,DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
//update-end---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
if(oConvertUtils.isNotEmpty(ids)){
query.in(true,SysDepart::getId,ids.split(","));
}
@ -313,6 +325,8 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
if (sysDepart != null && username != null) {
sysDepart.setUpdateTime(new Date());
sysDepart.setUpdateBy(username);
//验证部门类型
this.verifyOrgCategory(sysDepart);
this.updateById(sysDepart);
//update-begin---author:wangshuai ---date:20220307 for[JTC-119]在部门管理菜单下设置部门负责人 创建用户的时候不需要处理
//修改部门管理的时候,修改负责部门
@ -324,8 +338,46 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
}
}
@Override
/**
* 验证部门类型
*
* @param sysDepart
*/
private void verifyOrgCategory(SysDepart sysDepart) {
//update-begin---author:wangshuai---date:2025-08-21---for: 当部门类型为岗位的时候,需要查看是否存在下级,存在下级无法变更为岗位---
//如果是岗位的情况下,不能存在子级
if (oConvertUtils.isNotEmpty(sysDepart.getOrgCategory()) && DepartCategoryEnum.DEPART_CATEGORY_POST.getValue().equals(sysDepart.getOrgCategory())) {
long count = this.count(new QueryWrapper<SysDepart>().lambda().eq(SysDepart::getParentId, sysDepart.getId()));
if (count > 0) {
throw new JeecgBootBizTipException("当前子公司/部门下存在子级,无法变更为岗位!");
}
}
//如果是子公司的情况下,则上级不能为部门或者岗位
if (oConvertUtils.isNotEmpty(sysDepart.getOrgCategory()) && DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue().equals(sysDepart.getOrgCategory())
&& oConvertUtils.isNotEmpty(sysDepart.getParentId())) {
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDepart::getId, sysDepart.getParentId());
queryWrapper.in(SysDepart::getOrgCategory, DepartCategoryEnum.DEPART_CATEGORY_POST.getValue(), DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue());
long count = this.count(queryWrapper);
if (count > 0) {
throw new JeecgBootBizTipException("当前父级为部门或岗位,无法变更为子公司!");
}
}
//如果是部门的情况下,下级不能为子公司或者公司
if (oConvertUtils.isNotEmpty(sysDepart.getOrgCategory()) && DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue().equals(sysDepart.getOrgCategory())) {
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDepart::getParentId, sysDepart.getId());
queryWrapper.in(SysDepart::getOrgCategory, DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue(), DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue());
long count = this.count(queryWrapper);
if (count > 0) {
throw new JeecgBootBizTipException("当前子级存在子公司,无法变更为部门!");
}
}
//update-end---author:wangshuai---date:2025-08-21---for: 当部门类型为岗位的时候,需要查看是否存在下级,存在下级无法变更为岗位---
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteBatchWithChildren(List<String> ids) {
//存放子级的id
@ -393,7 +445,7 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
* </p>
*/
@Override
public List<SysDepartTreeModel> searchByKeyWord(String keyWord,String myDeptSearch,String departIds) {
public List<SysDepartTreeModel> searchByKeyWord(String keyWord, String myDeptSearch, String departIds, String orgCategory, String depIds) {
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
List<SysDepartTreeModel> newList = new ArrayList<>();
//myDeptSearch不为空时为我的部门搜索只搜索所负责部门
@ -416,7 +468,26 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
}
query.like(SysDepart::getDepartName, keyWord);
//update-begin--Author:huangzhilin Date:20140417 for[bugfree号]组织机构搜索回显优化--------------------
//update-begin---author:wangshuai---date:2025-08-20---for:【QQYUN-13428】增加岗位选择组件---
//需要根据部门类型进行数据筛选
if(oConvertUtils.isNotEmpty(orgCategory)){
query.in(SysDepart::getOrgCategory, Arrays.asList(orgCategory.split(SymbolConstant.COMMA)));
}else{
query.ne(SysDepart::getOrgCategory,DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
}
//如果前端传过来的部门id不为空的时候说明是系统用户根据所属部门选择主岗位或者兼职岗位需要进行数据过滤
if(oConvertUtils.isNotEmpty(depIds)){
List<String> codeList = baseMapper.getDepCodeByDepIds(Arrays.asList(depIds.split(SymbolConstant.COMMA)));
if(CollectionUtil.isNotEmpty(codeList)){
query.and(i -> {
for (String code : codeList) {
i.or().likeRight(SysDepart::getOrgCode,code);
}
});
}
}
//update-end---author:wangshuai---date:2025-08-20---for:【QQYUN-13428】增加岗位选择组件---
//update-begin--Author:huangzhilin Date:20140417 for[bugfree号]组织机构搜索回显优化--------------------
SysDepartTreeModel model = new SysDepartTreeModel();
List<SysDepart> departList = this.list(query);
if(departList.size() > 0) {
@ -625,6 +696,9 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
}
//------------------------------------------------------------------------------------------------
lqw.eq(true,SysDepart::getDelFlag,CommonConstant.DEL_FLAG_0.toString());
//update-begin---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
lqw.ne(SysDepart::getOrgCategory,DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
//update-end---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
lqw.func(square);
//update-begin---author:wangshuai ---date:20220527 for[VUEN-1143]排序不对vue3和2应该都有问题应该按照升序排------------
lqw.orderByAsc(SysDepart::getDepartOrder);
@ -637,6 +711,12 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
List<SysDepartTreeModel> records = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
SysDepart depart = list.get(i);
//update-begin---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
long count = getNoDepartPostCount(depart.getId());
if(count == 0){
depart.setIzLeaf(CommonConstant.IS_LEAF);
}
//update-end---author:wangshuai---date:2025-08-18---for:【QQYUN-13427】部门选择组件修改:需要过滤掉岗位 只保留 公司 子公司 部门---
SysDepartTreeModel treeModel = new SysDepartTreeModel(depart);
//TODO 异步树加载key拼接__+时间戳,以便于每次展开节点会刷新数据
//treeModel.setKey(treeModel.getKey()+"__"+System.currentTimeMillis());
@ -645,6 +725,85 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
return records;
}
/**
* 获取部门数量
* @param departId
* @return
*/
private long getNoDepartPostCount(String departId) {
LambdaQueryWrapper<SysDepart> queryNoPosition = new LambdaQueryWrapper<>();
queryNoPosition.ne(SysDepart::getOrgCategory,DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
queryNoPosition.eq(SysDepart::getParentId,departId);
return this.count(queryNoPosition);
}
/**
* 部门管理异步树
*
* @param parentId
* @param ids
* @param primaryKey
* @param departIds
* @return
*/
@Override
public List<SysDepartTreeModel> queryDepartAndPostTreeSync(String parentId, String ids, String primaryKey,
String departIds, String orgName) {
Consumer<LambdaQueryWrapper<SysDepart>> square = i -> {
if (oConvertUtils.isNotEmpty(ids)) {
if (CommonConstant.DEPART_KEY_ORG_CODE.equals(primaryKey)) {
i.in(SysDepart::getOrgCode, ids.split(SymbolConstant.COMMA));
} else {
i.in(SysDepart::getId, ids.split(SymbolConstant.COMMA));
}
} else {
if(oConvertUtils.isEmpty(parentId)){
//update-begin---author:wangshuai---date:2025-08-20---for:如果前端传过来的部门id不为空的时候说明是系统用户根据所属部门选择主岗位或者兼职岗位---
if(oConvertUtils.isNotEmpty(departIds)){
i.in(SysDepart::getId,Arrays.asList(departIds.split(SymbolConstant.COMMA)));
}else{
if(oConvertUtils.isEmpty(orgName)){
i.and(q->q.isNull(true,SysDepart::getParentId).or().eq(true,SysDepart::getParentId,""));
}else{
i.like(SysDepart::getDepartName, orgName);
}
}
//update-end---author:wangshuai---date:2025-08-20---for:如果前端传过来的部门id不为空的时候说明是系统用户根据所属部门选择主岗位或者兼职岗位---
}else{
i.eq(true,SysDepart::getParentId,parentId);
}
}
};
LambdaQueryWrapper<SysDepart> lqw=new LambdaQueryWrapper<>();
//是否开启系统管理模块的 SASS 控制
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
lqw.eq(SysDepart::getTenantId, oConvertUtils.getInt(TenantContext.getTenant(), 0));
}
lqw.eq(true,SysDepart::getDelFlag,CommonConstant.DEL_FLAG_0.toString());
lqw.func(square);
lqw.orderByAsc(SysDepart::getDepartOrder);
List<SysDepart> list = list(lqw);
//设置用户id,让前台显示
this.setUserIdsByDepList(list);
List<String> departIdList = new ArrayList<>();
//如果前端传过来的部门id不为空的时候说明是系统用户根据所属部门选择主岗位或者兼职岗位
if(oConvertUtils.isNotEmpty(departIds) && oConvertUtils.isEmpty(parentId)){
departIdList = list.stream().map(SysDepart::getId).toList();
}
List<SysDepartTreeModel> records = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
SysDepart depart = list.get(i);
//如果部门id和父级部门id再同一列的时候不用添加到树结构里面去了
if(oConvertUtils.isNotEmpty(departIds) && oConvertUtils.isEmpty(parentId)
&& departIdList.contains(depart.getParentId())){
continue;
}
SysDepartTreeModel treeModel = new SysDepartTreeModel(depart);
records.add(treeModel);
}
return records;
}
@Override
public JSONObject queryAllParentIdByDepartId(String departId) {
JSONObject result = new JSONObject();
@ -1342,6 +1501,7 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
sysDepart.setFax(departExportVo.getFax());
sysDepart.setAddress(departExportVo.getAddress());
sysDepart.setMemo(departExportVo.getMemo());
sysDepart.setPositionId(departExportVo.getPositionId());
ImportExcelUtil.importDateSaveOne(sysDepart, ISysDepartService.class, errorMessageList, num, CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE);
departMap.put(departExportVo.getDepartNameUrl(),sysDepart);
}
@ -1388,4 +1548,348 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
}
}
//========================end 系统下部门与人员导入 ==================================================================
//=========================begin 部门岗位改造 ==================================================================
@Override
public List<SysPositionSelectTreeVo> getPositionByDepartId(String parentId, String departId, String positionId) {
//step1 根据职级获取当前岗位的级别
SysPosition sysPosition = sysPositionMapper.selectById(positionId);
if(null == sysPosition){
return null;
}
Integer postLevel = sysPosition.getPostLevel();
//先获取上级部门的信息
SysDepart sysDepart = baseMapper.getDepartById(parentId);
//step2 如果是总公司 即数据为空的时候,则说明没有上级领导了
if (null == sysDepart) {
return null;
}
//可能是老数据
if(null == postLevel){
throw new JeecgBootBizTipException("当前选择职级的职务等级为空,请前往职务管理进行修改!");
}
//step3 查看是否为董事长
if (1 == postLevel) {
//step4 如果是董事长查询上级子公司或者总公司下部门的所有的岗位
return this.getChairmanDepartPosition(sysDepart, departId);
} else {
//step5 如果不是董事长组查询当前父级部门、公司和子公司的岗位 和当前部门下的岗位,但是必须比当前职务的级别高
return this.getNotChairmanDepartPosition(sysDepart, postLevel, departId);
}
}
/**
* 获取董事长职位
*
* @param sysDepart
* @param id
* @return
*/
private List<SysPositionSelectTreeVo> getChairmanDepartPosition(SysDepart sysDepart, String id) {
//step1 先递归获取为子公司或者总共司的id
String departId = getCompanyDepartId(sysDepart.getParentId());
if (oConvertUtils.isNotEmpty(departId)) {
SysDepart depart = baseMapper.getDepartById(departId);
//如果当前上级部门就是子公司或者总公司的情况下
if (DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue().equals(sysDepart.getOrgCategory()) || DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue().equals(sysDepart.getOrgCategory())) {
depart.setParentId(departId);
List<SysPositionSelectTreeVo> departPosition = getDepartPosition(depart, null, id);
if (CollectionUtil.isNotEmpty(departPosition)) {
if (CollectionUtil.isNotEmpty(departPosition)) {
//父级id不为空并且当前部门不是子公司或者总公司则需要寻上顶级公司
return getSuperiorCompany(departPosition);
}
}
return departPosition;
} else {
//step2 获取上一个子公司或者总公司下的岗位
String parentId = getCompanyDepartId(depart.getParentId());
if (oConvertUtils.isNotEmpty(departId)) {
depart = baseMapper.getDepartById(parentId);
if (null != depart) {
depart.setParentId(parentId);
List<SysPositionSelectTreeVo> departPosition = getDepartPosition(depart, null, id);
//step3 获取上级部门信息,一直获取到子公司或者总公司为止
if (CollectionUtil.isNotEmpty(departPosition)) {
//父级id不为空并且当前部门不是子公司或者总公司则需要寻上顶级公司
return getSuperiorCompany(departPosition);
}
return departPosition;
}
}
}
}
return null;
}
/*
* 获取不是董事长的数据
*
* @param sysDepart
* @param postLevel
* @param id
* @return
*/
private List<SysPositionSelectTreeVo> getNotChairmanDepartPosition(SysDepart sysDepart, Integer postLevel, String id) {
//step1 先获取上级部门下的数据
List<SysPositionSelectTreeVo> departPosition = getDepartPosition(sysDepart, postLevel, id);
//step2 获取上级部门信息,一直获取到子公司或者总公司为止
if (CollectionUtil.isNotEmpty(departPosition)) {
if (CollectionUtil.isNotEmpty(departPosition)) {
//父级id不为空并且当前部门不是子公司或者总公司则需要寻上顶级公司
return getSuperiorCompany(departPosition);
}
return departPosition;
}
return departPosition;
}
/**
* 获取上级公司
*
* @param departPosition
*/
private List<SysPositionSelectTreeVo> getSuperiorCompany(List<SysPositionSelectTreeVo> departPosition) {
String parentId = departPosition.get(0).getParentId();
SysDepart depart = baseMapper.getDepartById(parentId);
if (null == depart) {
return departPosition;
}
List<SysPositionSelectTreeVo> childrenList = new ArrayList<>();
SysPositionSelectTreeVo childrenTreeModel = new SysPositionSelectTreeVo(depart);
childrenTreeModel.setChildren(departPosition);
childrenList.add(childrenTreeModel);
if (DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue().equals(depart.getOrgCategory()) || DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue().equals(depart.getOrgCategory())) {
return childrenList;
} else {
return this.getSuperiorCompany(childrenList);
}
}
/**
* 获取部门职务
*
* @param sysDepart
* @param postLevel
*/
private List<SysPositionSelectTreeVo> getDepartPosition(SysDepart sysDepart, Integer postLevel, String id) {
//step1 获取部门下的所有部门
String parentId = sysDepart.getParentId();
List<SysDepart> departList = baseMapper.getDepartByParentId(parentId);
List<SysPositionSelectTreeVo> treeModels = new ArrayList<>();
for (int i = 0; i < departList.size(); i++) {
SysDepart depart = departList.get(i);
//如果是叶子节点说明没有岗位直接跳出循环
if (depart.getIzLeaf() == 1) {
if (DepartCategoryEnum.DEPART_CATEGORY_POST.getValue().equals(depart.getOrgCategory())) {
SysPositionSelectTreeVo sysDepartTreeModel = new SysPositionSelectTreeVo(depart);
treeModels.add(sysDepartTreeModel);
}
continue;
}
//step2 查找子部门下大于当前职别的数据
List<SysDepart> departParentPosition = baseMapper.getDepartPositionByParentId(depart.getId(), postLevel, id);
if (CollectionUtil.isNotEmpty(departParentPosition)) {
List<SysPositionSelectTreeVo> sysDepartTreeModels = sysDepartToTreeModel(departParentPosition);
SysPositionSelectTreeVo parentDepartTree = new SysPositionSelectTreeVo(depart);
parentDepartTree.setChildren(sysDepartTreeModels);
treeModels.add(parentDepartTree);
}
}
return treeModels;
}
/**
* 将SysDepart中的属性转到SysDepartTreeModel中
*
* @return
*/
private List<SysPositionSelectTreeVo> sysDepartToTreeModel(List<SysDepart> sysDeparts) {
List<SysPositionSelectTreeVo> records = new ArrayList<>();
for (int i = 0; i < sysDeparts.size(); i++) {
SysDepart depart = sysDeparts.get(i);
SysPositionSelectTreeVo treeModel = new SysPositionSelectTreeVo(depart);
records.add(treeModel);
}
return records;
}
/**
* 获取公司或者子公司的id
*
* @param parentDepartId
* @return
*/
private String getCompanyDepartId(String parentDepartId) {
SysDepart sysDepart = baseMapper.getDepartById(parentDepartId);
if (sysDepart != null) {
if (DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue().equals(sysDepart.getOrgCategory()) || DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue().equals(sysDepart.getOrgCategory())) {
return sysDepart.getId();
}
//如果不是公司或者子公司的时候,需要递归查询
if (oConvertUtils.isNotEmpty(sysDepart.getParentId())) {
return getCompanyDepartId(sysDepart.getParentId());
} else {
return parentDepartId;
}
} else {
return "";
}
}
@Override
public List<SysPositionSelectTreeVo> getRankRelation(String departId) {
//记录当前部门 key为部门id,value为部门名称
Map<String, String> departNameMap = new HashMap<>(5);
//step1 根据id查询部门信息
SysDepartPositionVo sysDepartPosition = baseMapper.getDepartPostByDepartId(departId);
if (null == sysDepartPosition) {
throw new JeecgBootBizTipException("当前所选部门数据为空");
}
List<SysPositionSelectTreeVo> selectTreeVos = new ArrayList<>();
//step2 查看是否有子级部门,存在递归查询职位
if (!CommonConstant.IS_LEAF.equals(sysDepartPosition.getIzLeaf())) {
//获取子级职位根据部门编码
this.getChildrenDepartPositionByOrgCode(selectTreeVos, departNameMap, sysDepartPosition);
return buildTree(selectTreeVos);
}
return new ArrayList<>();
}
/**
* 获取子级职位根据部门编码
*
* @param selectTreeVos
* @param departNameMap
* @param sysDepartPosition
*/
private void getChildrenDepartPositionByOrgCode(List<SysPositionSelectTreeVo> selectTreeVos, Map<String, String> departNameMap, SysDepartPositionVo sysDepartPosition) {
String orgCode = sysDepartPosition.getOrgCode();
//step1 根据父级id获取子级部门信息
List<SysDepartPositionVo> positionList = baseMapper.getDepartPostByOrgCode(orgCode + "%");
if (CollectionUtil.isNotEmpty(positionList)) {
for (SysDepartPositionVo position : positionList) {
//初始化map
if (departNameMap == null) {
departNameMap = new HashMap<>(5);
}
SysDepart depart = baseMapper.getDepartById(position.getParentId());
if(null != depart){
position.setDepartName(depart.getDepartName());
}
if(oConvertUtils.isNotEmpty(position.getDepPostParentId())){
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
query.eq(SysDepart::getId,position.getDepPostParentId());
query.likeRight(SysDepart::getOrgCode,orgCode);
Long count = baseMapper.selectCount(query);
if(null== count || count == 0){
position.setDepPostParentId(null);
}
}
departNameMap.put(position.getParentId(), position.getPositionName());
//查看是否为部门岗位,不是则不需要处理
SysPositionSelectTreeVo treeVo = new SysPositionSelectTreeVo(position);
selectTreeVos.add(treeVo);
}
}
}
/**
* 构建树形结构,只返回没有父级的一级节点
*/
public static List<SysPositionSelectTreeVo> buildTree(List<SysPositionSelectTreeVo> nodes) {
// 存储一级节点(没有父级的节点)
List<SysPositionSelectTreeVo> rootNodes = new ArrayList<>();
// 先找出所有一级节点parentId为null或空
for (SysPositionSelectTreeVo node : nodes) {
if (node.getParentId() == null || node.getParentId().trim().isEmpty()) {
rootNodes.add(node);
}
}
// 为每个一级节点递归设置子节点
for (SysPositionSelectTreeVo root : rootNodes) {
setChildren(root, nodes);
}
return rootNodes;
}
/**
* 递归为节点设置子节点
*/
private static void setChildren(SysPositionSelectTreeVo parentNode, List<SysPositionSelectTreeVo> allNodes) {
for (SysPositionSelectTreeVo node : allNodes) {
// 如果当前节点的父ID等于父节点的ID则是子节点
if (parentNode.getId().equals(node.getParentId())) {
// 递归为子节点设置它的子节点
setChildren(node, allNodes);
// 将子节点添加到父节点的子节点列表
parentNode.getChildren().add(node);
}
}
}
//=========================end 部门岗位改造 ==================================================================
@Override
public String getDepartPathNameByOrgCode(String orgCode, String depId) {
//部门id为空需要查询当前部门下的编码
if(oConvertUtils.isNotEmpty(depId)){
SysDepart departById = baseMapper.getDepartById(depId);
if(null != departById){
orgCode = departById.getOrgCode();
}
}
if(oConvertUtils.isEmpty(orgCode)){
return "";
}
//从redis 获取不为空直接返回
Object departName = redisUtil.get(CommonConstant.DEPART_NAME_REDIS_KEY_PRE + orgCode);
if(null != departName){
return String.valueOf(departName);
}
//获取长度
int codeNum = YouBianCodeUtil.ZHANWEI_LENGTH;
List<String> list = this.getCodeHierarchy(orgCode, codeNum);
//根据部门编码查询公司和子公司的数据
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
query.in(SysDepart::getOrgCode, list);
query.orderByAsc(SysDepart::getOrgCode);
List<SysDepart> sysDepartList = departMapper.selectList(query);
if(!CollectionUtils.isEmpty(sysDepartList)){
//获取部门名称拼接返回给前台
List<String> departNameList = sysDepartList.stream().map(SysDepart::getDepartName).toList();
String departNames = String.join("/", departNameList);
redisUtil.set(CommonConstant.DEPART_NAME_REDIS_KEY_PRE + orgCode,departNames);
return departNames;
}
return "";
}
/**
* 获取编码及其所有上级编码
*
* @param code 完整编码,如 "A01A01A01"
* @param fixedLength 固定位数,如 3
* @return 包含所有上级编码的列表,如 ['A01','A01A01','A01A01A01']
*/
public List<String> getCodeHierarchy(String code, int fixedLength) {
List<String> hierarchy = new ArrayList<>();
if (code == null || code.isEmpty() || fixedLength <= 0) {
return hierarchy;
}
// 检查编码长度是否能被固定位数整除
if (code.length() % fixedLength != 0) {
throw new IllegalArgumentException("编码长度必须能被固定位数整除");
}
// 按固定位数分割并生成所有上级编码
for (int i = fixedLength; i <= code.length(); i += fixedLength) {
hierarchy.add(code.substring(0, i));
}
return hierarchy;
}
}

View File

@ -56,7 +56,7 @@ public class SysRoleIndexServiceImpl extends ServiceImpl<SysRoleIndexMapper, Sys
entity.setUrl(url);
entity.setComponent(component);
entity.setRoute(isRoute);
entity.setRelationType(CommonConstant.HOME_RELATION_ROLE);
entity.setRelationType(CommonConstant.HOME_RELATION_DEFAULT);
success = super.updateById(entity);
}
// 4. 清理缓存
@ -84,7 +84,7 @@ public class SysRoleIndexServiceImpl extends ServiceImpl<SysRoleIndexMapper, Sys
entity.setComponent(indexComponent);
entity.setRoute(isRoute);
entity.setStatus(CommonConstant.STATUS_1);
entity.setRelationType(CommonConstant.HOME_RELATION_ROLE);
entity.setRelationType(CommonConstant.HOME_RELATION_DEFAULT);
return entity;
}

View File

@ -1,7 +1,11 @@
package org.jeecg.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.TenantConstant;
import org.jeecg.common.system.vo.LoginUser;
@ -10,13 +14,10 @@ import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.aop.TenantLog;
import org.jeecg.modules.system.entity.SysPackPermission;
import org.jeecg.modules.system.entity.SysTenant;
import org.jeecg.modules.system.entity.SysTenantPack;
import org.jeecg.modules.system.entity.SysTenantPackUser;
import org.jeecg.modules.system.mapper.SysPackPermissionMapper;
import org.jeecg.modules.system.mapper.SysRoleMapper;
import org.jeecg.modules.system.mapper.SysTenantPackMapper;
import org.jeecg.modules.system.mapper.SysTenantPackUserMapper;
import org.jeecg.modules.system.entity.SysUserTenant;
import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.service.ISysTenantPackService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -54,8 +55,16 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
@Autowired
private SysRoleMapper sysRoleMapper;
@Autowired
private SysUserTenantMapper sysUserTenantMapper;
@Override
public void addPackPermission(SysTenantPack sysTenantPack) {
//如果是默认租户套餐包则需要设置code编码再编辑默认套餐找自定义套餐的时候用到
if(CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())){
String packCode = CommonConstant.TENANT_PACK_DEFAULT + RandomUtil.randomNumbers(4).toLowerCase();
sysTenantPack.setPackCode(packCode);
}
sysTenantPackMapper.insert(sysTenantPack);
String permissionIds = sysTenantPack.getPermissionIds();
if (oConvertUtils.isNotEmpty(permissionIds)) {
@ -66,6 +75,48 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
}
}
//如果是自定义套餐包的情况下再将新增套餐和用户关系
if(!CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())) {
//如果需要自动分配给用户时候再去添加用户与套餐的关系数据
if(oConvertUtils.isNotEmpty(sysTenantPack.getIzSysn()) && CommonConstant.STATUS_1.equals(sysTenantPack.getIzSysn())) {
//根据租户id和套餐id添加用户与套餐关系数据
this.addPackUserByPackTenantId(sysTenantPack.getTenantId(), sysTenantPack.getId());
}
}
}
/**
* 根据租户id和套餐id添加用户与套餐关系数据
*
* @param tenantId
* @param packId
*/
private void addPackUserByPackTenantId(Integer tenantId, String packId) {
if (null != tenantId && tenantId != 0) {
List<String> userIds = sysUserTenantMapper.getUserIdsByTenantId(tenantId);
if (CollectionUtil.isNotEmpty(userIds)) {
//update-begin---author:wangshuai---date:2025-09-03---for: 编辑时需要查看有没有未分配的用户---
// 查询已存在的用户
LambdaQueryWrapper<SysTenantPackUser> query = new LambdaQueryWrapper<>();
query.eq(SysTenantPackUser::getTenantId, tenantId);
query.eq(SysTenantPackUser::getPackId, packId);
query.in(SysTenantPackUser::getUserId, userIds);
List<SysTenantPackUser> existingUsers = sysTenantPackUserMapper.selectList(query);
// 提取已存在的用户ID
List<String> existingUserIds = existingUsers.stream()
.map(SysTenantPackUser::getUserId)
.toList();
// 过滤出需要新增的用户ID
List<String> newUserIds = userIds.stream()
.filter(userId -> !existingUserIds.contains(userId))
.toList();
for (String userId : newUserIds) {
//update-end---author:wangshuai---date:2025-09-03---for: 编辑时需要查看有没有未分配的用户---
SysTenantPackUser tenantPackUser = new SysTenantPackUser(tenantId, packId, userId);
sysTenantPackUserMapper.insert(tenantPackUser);
}
}
}
}
@Override
@ -89,9 +140,17 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
//如果传过来的菜单id为空那么就删除数据库中所有菜单
if (oConvertUtils.isEmpty(permissionIds)) {
this.deletePackPermission(sysTenantPack.getId(), null);
//如果是默认套餐包,需要删除其他关联默认产品包下的角色与菜单的关系
if(CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())){
this.deleteDefaultPackPermission(sysTenantPack.getPackCode(), null);
}
} else if (oConvertUtils.isNotEmpty(permissionIds) && oConvertUtils.isEmpty(oldPermissionIds)) {
//如果传过来的菜单id不为空但是数据库的菜单id为空那么就新增
this.addPermission(sysTenantPack.getId(), permissionIds);
//如果是默认套餐包,需要新增其他关联默认产品包下的角色与菜单的关系
if(CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())){
this.addDefaultPackPermission(sysTenantPack.getPackCode(), permissionIds);
}
} else {
//都不为空,需要比较,进行添加或删除
if (oConvertUtils.isNotEmpty(oldPermissionIds)) {
@ -100,6 +159,10 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
if (permissionList.size() > 0) {
for (String permission : permissionList) {
this.deletePackPermission(sysTenantPack.getId(), permission);
//如果是默认套餐包,需要删除其他关联默认产品包下的角色与菜单的关系
if(CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())){
this.deleteDefaultPackPermission(sysTenantPack.getPackCode(), permission);
}
}
}
@ -108,11 +171,29 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
if (permissionAddList.size() > 0) {
for (String permission : permissionAddList) {
this.addPermission(sysTenantPack.getId(), permission);
//如果是默认套餐包,需要新增其他关联默认产品包下的角色与菜单的关系
if(CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())){
this.addDefaultPackPermission(sysTenantPack.getPackCode(), permission);
}
}
}
}
}
sysTenantPackMapper.updateById(sysTenantPack);
//如果是默认套餐包,则更新和当前匹配默认套餐包匹配的数据
if(CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())){
//同步同 packCode 下的相关套餐包数据
this.syncRelatedPackDataByDefaultPack(sysTenantPack);
}
//如果是自定义套餐包的情况下再将新增套餐和用户关系
if(!CommonConstant.TENANT_PACK_DEFAULT.equals(sysTenantPack.getPackType())) {
//如果需要自动分配给用户时候再去添加用户与套餐的关系数据
if(oConvertUtils.isNotEmpty(sysTenantPack.getIzSysn()) && CommonConstant.STATUS_1.equals(sysTenantPack.getIzSysn())) {
//根据租户id和套餐id添加用户与套餐关系数据
this.addPackUserByPackTenantId(sysTenantPack.getTenantId(), sysTenantPack.getId());
}
}
}
@Override
@ -137,7 +218,7 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
ISysTenantPackService currentService = SpringContextUtils.getApplicationContext().getBean(ISysTenantPackService.class);
// 创建租户超级管理员
SysTenantPack superAdminPack = new SysTenantPack(tenantId, "超级管理员", TenantConstant.SUPER_ADMIN);
superAdminPack.setIzSysn(CommonConstant.STATUS_0);
//step.1 创建租户套餐包(超级管理员)
LambdaQueryWrapper<SysTenantPack> query = new LambdaQueryWrapper<>();
query.eq(SysTenantPack::getTenantId,tenantId);
@ -163,6 +244,7 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
if(null == sysTenantPackAccountAdmin){
// 创建超级管理员
SysTenantPack accountAdminPack = new SysTenantPack(tenantId, "组织账户管理员", TenantConstant.ACCOUNT_ADMIN);
accountAdminPack.setIzSysn(CommonConstant.STATUS_0);
currentService.saveOne(accountAdminPack);
}
@ -173,6 +255,7 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
if(null == sysTenantPackAppAdmin){
// 创建超级管理员
SysTenantPack appAdminPack = new SysTenantPack(tenantId, "组织应用管理员", TenantConstant.APP_ADMIN);
appAdminPack.setIzSysn(CommonConstant.STATUS_0);
currentService.saveOne(appAdminPack);
}
@ -290,6 +373,18 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
packPermission.setPermissionId(permission);
sysPackPermissionMapper.insert(packPermission);
}
//如果需要自动分配给用户时候再去添加用户与套餐的关系数据
if(oConvertUtils.isNotEmpty(defaultPacks.getIzSysn()) && CommonConstant.STATUS_1.equals(defaultPacks.getIzSysn())) {
//查询当前租户下的用户
List<String> userIds = sysUserTenantMapper.getUserIdsByTenantId(tenantId);
if (oConvertUtils.isNotEmpty(userIds)) {
for (String userId : userIds) {
//根据租户id和套餐id添加用户与套餐关系数据
SysTenantPackUser tenantPackUser = new SysTenantPackUser(tenantId, pack.getId(), userId);
sysTenantPackUserMapper.insert(tenantPackUser);
}
}
}
}
/**
@ -301,4 +396,81 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
query.eq(SysTenantPackUser::getPackId, packId);
sysTenantPackUserMapper.delete(query);
}
@Override
public List<String> getPackIdByUserIdAndTenantId(String userId, Integer tenantId) {
return sysTenantPackUserMapper.getPackIdByTenantIdAndUserId(tenantId, userId);
}
@Override
public List<SysTenantPack> getPackListByTenantId(String tenantId) {
return sysTenantPackUserMapper.getPackListByTenantId(oConvertUtils.getInt(tenantId));
}
/**
* 根据套餐包的code 新增其他关联默认产品包下的角色与菜单的关系
*
* @param packCode
* @param permission
*/
private void addDefaultPackPermission(String packCode, String permission) {
if (oConvertUtils.isEmpty(packCode)) {
return;
}
//查询当前匹配非默认套餐包的其他默认套餐包
LambdaQueryWrapper<SysTenantPack> query = new LambdaQueryWrapper<>();
query.ne(SysTenantPack::getPackType, CommonConstant.TENANT_PACK_DEFAULT);
query.eq(SysTenantPack::getPackCode, packCode);
List<SysTenantPack> otherDefaultPacks = sysTenantPackMapper.selectList(query);
for (SysTenantPack pack : otherDefaultPacks) {
//新增套餐包用户菜单权限
this.addPermission(pack.getId(), permission);
}
}
/**
* 根据套餐包的code 删除其他关联默认套餐包下的角色与菜单的关系
*
* @param packCode
* @param permissionId
*/
private void deleteDefaultPackPermission(String packCode, String permissionId) {
if (oConvertUtils.isEmpty(packCode)) {
return;
}
//查询当前匹配非默认套餐包的其他默认套餐包
LambdaQueryWrapper<SysTenantPack> query = new LambdaQueryWrapper<>();
query.ne(SysTenantPack::getPackType, CommonConstant.TENANT_PACK_DEFAULT);
query.eq(SysTenantPack::getPackCode, packCode);
List<SysTenantPack> defaultPacks = sysTenantPackMapper.selectList(query);
for (SysTenantPack pack : defaultPacks) {
//删除套餐权限
deletePackPermission(pack.getId(), permissionId);
}
}
/**
* 同步同 packCode 下的相关套餐包数据
*
* @param sysTenantPack
*/
private void syncRelatedPackDataByDefaultPack(SysTenantPack sysTenantPack) {
//查询与默认套餐相同code的套餐
LambdaQueryWrapper<SysTenantPack> query = new LambdaQueryWrapper<>();
query.ne(SysTenantPack::getPackType, CommonConstant.TENANT_PACK_DEFAULT);
query.eq(SysTenantPack::getPackCode, sysTenantPack.getPackCode());
List<SysTenantPack> relatedPacks = sysTenantPackMapper.selectList(query);
for (SysTenantPack pack : relatedPacks) {
//更新自定义套餐
pack.setPackName(sysTenantPack.getPackName());
pack.setStatus(sysTenantPack.getStatus());
pack.setRemarks(sysTenantPack.getRemarks());
pack.setIzSysn(sysTenantPack.getIzSysn());
sysTenantPackMapper.updateById(pack);
//同步默认套餐报下的所有用户已
if (oConvertUtils.isNotEmpty(sysTenantPack.getIzSysn()) && CommonConstant.STATUS_1.equals(sysTenantPack.getIzSysn())) {
this.addPackUserByPackTenantId(pack.getTenantId(), pack.getId());
}
}
}
}

View File

@ -1,5 +1,6 @@
package org.jeecg.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -104,15 +105,27 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
@Override
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
public void invitationUserJoin(String ids, String phone) {
public void invitationUserJoin(String ids, String phone,String username) {
String[] idArray = ids.split(SymbolConstant.COMMA);
String userId = null;
SysUser userByPhone = null;
//update-begin---author:wangshuai ---date:20230313 for【QQYUN-4605】后台的邀请谁加入租户没办法选不是租户下的用户通过手机号邀请------------
SysUser userByPhone = userService.getUserByPhone(phone);
//说明用户不存在
if(null == userByPhone){
throw new JeecgBootException("当前用户不存在,请核对手机号");
if(oConvertUtils.isNotEmpty(phone)){
userByPhone = userService.getUserByPhone(phone);
//说明用户不存在
if(null == userByPhone){
throw new JeecgBootException("当前用户不存在,请核对手机号");
}
userId = userByPhone.getId();
}else{
userByPhone = userService.getUserByName(username);
//说明用户不存在
if(null == userByPhone){
throw new JeecgBootException("当前用户不存在,请核对手机号");
}
userId = userByPhone.getId();
}
String userId = userByPhone.getId();
//循环租户id
for (String id:idArray) {
//update-begin---author:wangshuai ---date:20221223 for[QQYUN-3371]租户逻辑改造,改成关系表------------
@ -124,6 +137,12 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
relation.setTenantId(Integer.valueOf(id));
relation.setStatus(CommonConstant.USER_TENANT_NORMAL);
userTenantMapper.insert(relation);
//给当前用户添加租户下的所有套餐
this.addPackUser(userId,id);
//update-begin---author:wangshuai---date:2025-09-06---for:【QQYUN-13720】邀请用户加入租户没有系统提醒移除有---
//邀请用户加入租户,发送消息
this.sendInvitationTenantMessage(userByPhone,id);
//update-end---author:wangshuai---date:2025-09-06---for:【QQYUN-13720】邀请用户加入租户没有系统提醒移除有---
}else{
//update-begin---author:wangshuai ---date:20230711 for【QQYUN-5723】2、用户已经在租户里了再次要求提示成功应该提示用户已经存在------------
//update-begin---author:wangshuai ---date:20230724 for【QQYUN-5885】邀请用户加入提示不准确------------
@ -138,6 +157,30 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
}
}
/**
* 低代码下发送邀请加入租户消息
*
* @param user
* @param id
*/
private void sendInvitationTenantMessage(SysUser user, String id) {
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
// 发消息
SysTenant sysTenant = this.baseMapper.querySysTenant((Integer.valueOf(id)));
MessageDTO messageDTO = new MessageDTO();
messageDTO.setToAll(false);
messageDTO.setToUser(user.getUsername());
messageDTO.setFromUser("system");
String title = sysUser.getRealname() + " 邀请您加入了 "+sysTenant.getName()+"";
messageDTO.setTitle(title);
Map<String, Object> data = new HashMap<>();
messageDTO.setData(data);
messageDTO.setContent(title);
messageDTO.setType("system");
messageDTO.setCategory(CommonConstant.MSG_CATEGORY_1);
sysBaseApi.sendSysAnnouncement(messageDTO);
}
@Override
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
public void leaveTenant(String userIds, String tenantId) {
@ -149,6 +192,13 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
query.eq(SysUserTenant::getUserId,userId);
userTenantMapper.delete(query);
//update-end---author:wangshuai ---date:20221223 for[QQYUN-3371]租户逻辑改造,改成关系表------------
//update-begin---author:wangshuai---date:2025-09-06---for:【QQYUN-13720】移出用户当前租户没有系统提醒---
// 给移除人员发送消息
SysTenantPackUser sysTenantPackUser = new SysTenantPackUser();
sysTenantPackUser.setTenantId(Integer.valueOf(tenantId));
sysTenantPackUser.setUserId(userId);
sendMsgForDelete(sysTenantPackUser);
//update-end---author:wangshuai---date:2025-09-06---for:【QQYUN-13720】移出用户当前租户没有系统提醒---
}
//租户移除用户,直接删除用户租户产品包
sysTenantPackUserMapper.deletePackUserByTenantId(Integer.valueOf(tenantId),Arrays.asList(userIds.split(SymbolConstant.COMMA)));
@ -636,7 +686,13 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
MessageDTO messageDTO = new MessageDTO();
messageDTO.setToAll(false);
messageDTO.setToUser(user.getUsername());
String title = "您已被 "+loginUser.getRealname()+""+sysTenant.getName()+""+sysTenantPackUser.getPackName()+"中移除。";
//低代码下移出用户已做提醒,用户移出没有套餐包名称的概念
String title = "";
if(oConvertUtils.isNotEmpty(sysTenantPackUser.getPackName())){
title = "您已被 "+loginUser.getRealname()+""+sysTenant.getName()+""+sysTenantPackUser.getPackName()+"中移除。";
} else {
title = "您已被 "+loginUser.getRealname()+""+sysTenant.getName() + "中移除。";
}
messageDTO.setTitle(title);
messageDTO.setFromUser("system");
Map<String, Object> data = new HashMap<>();
@ -961,4 +1017,28 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
userService.removeLogicDeleted(Collections.singletonList(userId));
}
/**
* 为用户添加租户下所有套餐
*
* @param userId 用户id
* @param tenantId 租户id
*/
public void addPackUser(String userId, String tenantId) {
//根据租户id和产品包的code获取租户套餐id
List<String> packIds = sysTenantPackMapper.getPackIdByPackCodeAndTenantId(oConvertUtils.getInt(tenantId));
if (CollectionUtil.isNotEmpty(packIds)) {
for (String packId : packIds) {
SysTenantPackUser sysTenantPackUser = new SysTenantPackUser();
sysTenantPackUser.setUserId(userId);
sysTenantPackUser.setTenantId(oConvertUtils.getInt(tenantId));
sysTenantPackUser.setPackId(packId);
sysTenantPackUser.setStatus(CommonConstant.STATUS_1_INT);
try {
this.addTenantPackUser(sysTenantPackUser);
} catch (Exception e) {
log.warn("添加用户套餐包失败,原因:" + e.getMessage());
}
}
}
}
}

View File

@ -1,19 +0,0 @@
package org.jeecg.modules.system.service.impl;
import org.jeecg.modules.system.entity.SysUserAgent;
import org.jeecg.modules.system.mapper.SysUserAgentMapper;
import org.jeecg.modules.system.service.ISysUserAgentService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 用户代理人设置
* @Author: jeecg-boot
* @Date: 2019-04-17
* @Version: V1.0
*/
@Service
public class SysUserAgentServiceImpl extends ServiceImpl<SysUserAgentMapper, SysUserAgent> implements ISysUserAgentService {
}

View File

@ -0,0 +1,16 @@
package org.jeecg.modules.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.system.entity.SysUserDepPost;
import org.jeecg.modules.system.mapper.SysUserDepPostMapper;
import org.jeecg.modules.system.service.ISysUserDepPostService;
import org.springframework.stereotype.Service;
/**
* @Description: 部门岗位用户实现类
* @author: wangshuai
* @date: 2025/9/5 11:46
*/
@Service
public class SysUserDepPostServiceImpl extends ServiceImpl<SysUserDepPostMapper, SysUserDepPost> implements ISysUserDepPostService {
}

View File

@ -1,14 +1,17 @@
package org.jeecg.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.DepartCategoryEnum;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
@ -174,6 +177,19 @@ public class SysUserDepartServiceImpl extends ServiceImpl<SysUserDepartMapper, S
}
}
//update-end---author:liusq ---date:20231215 for逗号分割多个用户翻译问题------------
//update-begin---author:liusq ---date:20250908 forJHHB-304 流程转办 人员选择时,加姓名搜索------------
if(oConvertUtils.isNotEmpty(realname)){
String COMMA = ",";
if(oConvertUtils.isNotEmpty(isMultiTranslate) && realname.contains(COMMA)){
String[] realnameArr = realname.split(COMMA);
query.in(SysUser::getRealname,realnameArr);
}else {
query.like(SysUser::getRealname, realname);
}
}
//update-end---author:liusq ---date:20250908 forJHHB-304 流程转办 人员选择时,加姓名搜索------------
//update-begin---author:wangshuai ---date:20220608 for[VUEN-1238]邮箱回复时发送到显示的为用户id------------
if(oConvertUtils.isNotEmpty(id)){
//update-begin---author:wangshuai ---date:2024-06-25 for【TV360X-1482】写信选择用户后第一次回显没翻译------------
@ -353,4 +369,87 @@ public class SysUserDepartServiceImpl extends ServiceImpl<SysUserDepartMapper, S
return res;
}
/**
* 查询部门岗位下的用户
* @param departId
* @param username
* @param realname
* @param pageSize
* @param pageNo
* @param id
* @param isMultiTranslate
* @return
*/
@Override
public IPage<SysUser> queryDepartPostUserPageList(String departId, String username, String realname, Integer pageSize, Integer pageNo, String id, String isMultiTranslate) {
Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
if (oConvertUtils.isEmpty(departId)) {
// 部门ID不存在 直接查询用户表即可
return getDepPostListByIdUserName(username,id,isMultiTranslate,page);
} else {
// 有部门ID 需要走部门岗位用户查询
return getDepartPostListByIdUserRealName(departId,username,realname,page);
}
}
/**
* 根据部门id和用户名获取部门岗位用户分页列表
*
* @param id
* @param username
* @param isMultiTranslate
* @param page
* @return
*/
private IPage<SysUser> getDepPostListByIdUserName(String username, String id, String isMultiTranslate, Page<SysUser> page) {
//需要查询部门下的用户故将写成自定义sql非Lambda表达式的用法
List<String> userIdList = new ArrayList<>();
List<String> userNameList = new ArrayList<>();
String userId = "";
String userName = "";
if (oConvertUtils.isNotEmpty(username)) {
String COMMA = ",";
if (oConvertUtils.isNotEmpty(isMultiTranslate) && username.contains(COMMA)) {
String[] usernameArr = username.split(COMMA);
userNameList.addAll(Arrays.asList(usernameArr));
} else {
userName = username;
}
}
if (oConvertUtils.isNotEmpty(id)) {
String COMMA = ",";
if (oConvertUtils.isNotEmpty(isMultiTranslate) && id.contains(COMMA)) {
String[] idArr = id.split(COMMA);
userIdList.addAll(Arrays.asList(idArr));
} else {
userId = "";
}
}
//------------------------------------------------------------------------------------------------
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
String tenantId = oConvertUtils.getString(TenantContext.getTenant(), "0");
List<String> userIdsList = userTenantMapper.getUserIdsByTenantId(Integer.valueOf(tenantId));
if (null != userIdsList && !userIdsList.isEmpty()) {
userIdList.addAll(userIdsList);
}
}
//------------------------------------------------------------------------------------------------
return sysUserMapper.getDepPostListByIdUserName(page,userIdList,userId,userName,userNameList);
}
/**
* 根据部门id、用户名和真实姓名获取部门岗位用户分页列表
*
* @param departId
* @param username
* @param realname
* @param page
* @return
*/
private IPage<SysUser> getDepartPostListByIdUserRealName(String departId, String username, String realname, Page<SysUser> page) {
SysDepart sysDepart = sysDepartService.getById(departId);
return sysUserMapper.getDepartPostListByIdUserRealName(page, username, realname, sysDepart.getOrgCode());
}
}

View File

@ -8,6 +8,7 @@ import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@ -24,10 +25,8 @@ import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.FillRuleConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.DySmsEnum;
import org.jeecg.common.constant.enums.MessageTypeEnum;
import org.jeecg.common.constant.enums.RoleIndexConfigEnum;
import org.jeecg.common.constant.enums.SysAnnmentTypeEnum;
import org.jeecg.common.constant.PasswordConstant;
import org.jeecg.common.constant.enums.*;
import org.jeecg.common.desensitization.annotation.SensitiveEncode;
import org.jeecg.common.exception.JeecgBootBizTipException;
import org.jeecg.common.exception.JeecgBootException;
@ -41,14 +40,11 @@ import org.jeecg.modules.jmreport.common.util.OkConvertUtils;
import org.jeecg.modules.message.handle.impl.SystemSendMsgHandle;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.model.SysUserSysDepPostModel;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
import org.jeecg.modules.system.service.ISysRoleIndexService;
import org.jeecg.modules.system.service.ISysThirdAccountService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.vo.SysUserDepVo;
import org.jeecg.modules.system.vo.SysUserExportVo;
import org.jeecg.modules.system.vo.SysUserPositionVo;
import org.jeecg.modules.system.vo.UserAvatar;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.util.ImportSysUserCache;
import org.jeecg.modules.system.vo.*;
import org.jeecg.modules.system.vo.lowapp.AppExportUserVo;
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
import org.jeecg.modules.system.vo.lowapp.DepartInfo;
@ -132,6 +128,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private ISysThirdAccountService sysThirdAccountService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private SysTenantPackUserMapper packUserMapper;
@Autowired
private SysUserDepPostMapper depPostMapper;
@Override
public Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo) {
@ -228,7 +230,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
}
//update-end---author:wangshuai---date:2023-10-08---for:【QQYUN-6668】钉钉部门和用户同步我怎么知道哪些用户是双向绑定成功的---
});
//update-begin---author:wangshuai---date:2025-09-06---for: 兼职岗位改造成中间表的方式---
//查询部门的兼职岗位
List<String> depPostList = depPostMapper.getDepPostByUserId(item.getId());
if(CollectionUtil.isNotEmpty(depPostList)){
item.setOtherDepPostId(StringUtils.join(depPostList.toArray(), SymbolConstant.COMMA));
}
//update-end---author:wangshuai---date:2025-09-06---for:兼职岗位改造成中间表的方式---
});
}
result.setSuccess(true);
@ -578,12 +587,13 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
* @param page
* @param roleId 角色id
* @param username 用户账户名称
* @param realname 用户姓名
* @return
*/
@Override
public IPage<SysUser> getUserByRoleId(Page<SysUser> page, String roleId, String username) {
public IPage<SysUser> getUserByRoleId(Page<SysUser> page, String roleId, String username, String realname) {
//update-begin---author:wangshuai ---date:20230220 for[QQYUN-3980]组织管理中 职位功能 职位表加租户id 加职位-用户关联表------------
IPage<SysUser> userRoleList = userMapper.getUserByRoleId(page, roleId, username);
IPage<SysUser> userRoleList = userMapper.getUserByRoleId(page, roleId, username,realname);
List<SysUser> records = userRoleList.getRecords();
if (null != records && records.size() > 0) {
List<String> userIds = records.stream().map(SysUser::getId).collect(Collectors.toList());
@ -779,11 +789,11 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
@Override
@Transactional(rollbackFor = Exception.class)
public void saveUser(SysUser user, String selectedRoles, String selectedDeparts, String relTenantIds) {
public void saveUser(SysUser user, String selectedRoles, String selectedDeparts, String relTenantIds, boolean izSyncPack) {
//step.1 保存用户
this.save(user);
//获取用户保存前台传过来的租户id并添加到租户
this.saveUserTenant(user.getId(),relTenantIds);
this.saveUserTenant(user.getId(),relTenantIds, izSyncPack);
//step.2 保存角色
if(oConvertUtils.isNotEmpty(selectedRoles)) {
String[] arr = selectedRoles.split(",");
@ -804,6 +814,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
//step.4 保存职位
this.saveUserPosition(user.getId(),user.getPost());
//step5 保存兼职岗位
this.saveUserOtherDepPost(user.getId(),user.getOtherDepPostId());
}
@Override
@ -863,8 +875,32 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
//step.5 修改职位
this.editUserPosition(user.getId(),user.getPost());
//update-begin---author:wangshuai---date:2025-09-06---for:兼职岗位改造成中间表的方式---
//step6 修改兼职岗位
//先删后加
depPostMapper.delete(new QueryWrapper<SysUserDepPost>().lambda().eq(SysUserDepPost::getUserId, user.getId()));
this.saveUserOtherDepPost(user.getId(),user.getOtherDepPostId());
//update-end---author:wangshuai---date:2025-09-06---for:兼职岗位改造成中间表的方式---
}
/**
* 保存兼职岗位
*
* @param userId
* @param otherDepPostId
*/
private void saveUserOtherDepPost(String userId, String otherDepPostId) {
if (oConvertUtils.isNotEmpty(otherDepPostId)) {
String[] depPostId = otherDepPostId.split(SymbolConstant.COMMA);
for (String postId : depPostId) {
SysUserDepPost userPosition = new SysUserDepPost(userId, postId);
depPostMapper.insert(userPosition);
}
}
}
@Override
public List<String> userIdToUsername(Collection<String> userIdList) {
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
@ -917,6 +953,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
SysUserTenant userTenant = new SysUserTenant();
userTenant.setStatus(CommonConstant.USER_TENANT_QUIT);
userTenantMapper.update(userTenant,query);
//update-end---author:wangshuai ---date:20230111 for[QQYUN-3951]租户用户离职重构------------
}
@Override
@ -1007,10 +1044,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
/**
* 保存租户
*
* @param userId
* @param relTenantIds
* @param izSyncPack 是否需要将用户同步当前产品包下
*/
private void saveUserTenant(String userId, String relTenantIds) {
private void saveUserTenant(String userId, String relTenantIds, boolean izSyncPack) {
if (oConvertUtils.isNotEmpty(relTenantIds)) {
String[] tenantIds = relTenantIds.split(SymbolConstant.COMMA);
for (String tenantId : tenantIds) {
@ -1028,6 +1067,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
relationMapper.updateById(tenantPresent);
}else{
relationMapper.insert(relation);
ISysTenantService currentService = SpringContextUtils.getApplicationContext().getBean(ISysTenantService.class);
//默认添加当前用户到租户套餐中
currentService.addPackUser(userId,tenantId);
}
}
}else{
@ -1043,6 +1085,11 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
relation.setTenantId(Integer.parseInt(tenantId));
relation.setStatus(CommonConstant.STATUS_1);
relationMapper.insert(relation);
if(izSyncPack){
ISysTenantService currentService = SpringContextUtils.getApplicationContext().getBean(ISysTenantService.class);
//自动为用户,添加租户下所有套餐
currentService.addPackUser(userId,tenantId);
}
}
}
//update-end---author:wangshuai ---date:20230220 for判断当前用户是否在当前租户里面如果不存在在新增------------
@ -1065,7 +1112,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
this.deleteTenantByUserId(userId, null);
} else if (oConvertUtils.isNotEmpty(relTenantIds) && CollectionUtils.isEmpty(oldTenantIds)) {
//如果传过来的租户id不为空但是数据库的租户id为空那么就新增
this.saveUserTenant(userId, relTenantIds);
this.saveUserTenant(userId, relTenantIds, false);
} else {
//都不为空,需要比较,进行添加或删除
if(oConvertUtils.isNotEmpty(relTenantIds) && CollectionUtils.isNotEmpty(oldTenantIds)){
@ -1079,7 +1126,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
//找到原来租户的用户id与新的租户id不同之处进行新增
String tenantIds = relTenantIdList.stream().filter(item -> !oldTenantIds.contains(Integer.valueOf(item))).collect(Collectors.joining(","));
this.saveUserTenant(userId, tenantIds);
this.saveUserTenant(userId, tenantIds, false);
}
}
}
@ -1096,6 +1143,13 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
query.eq(SysUserTenant::getTenantId, tenantId);
}
relationMapper.delete(query);
//删除产品包用户关联
LambdaQueryWrapper<SysTenantPackUser> packUserQuery = new LambdaQueryWrapper<>();
packUserQuery.eq(SysTenantPackUser::getUserId, userId);
if(oConvertUtils.isNotEmpty(tenantId)){
packUserQuery.eq(SysTenantPackUser::getTenantId, tenantId);
}
packUserMapper.delete(packUserQuery);
}
@ -1597,7 +1651,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
AppExportUserVo exportUserVo = new AppExportUserVo();
BeanUtils.copyProperties(sysUser, exportUserVo);
//update-begin---author:wangshuai---date:2025-01-17---for:【QQYUN-10926】组织管理——用户导出时部门没有导出上下级关系---
StringBuilder departNames = this.getDepartNames(userDepVos,sysUser);
Map<String, String> departMap = this.getDepartNamesAndCategory(userDepVos, sysUser);
String departNames = departMap.get("departNames");
exportUserVo.setDepart(departNames.toString());
//update-end---author:wangshuai---date:2025-01-17---for:【QQYUN-10926】组织管理——用户导出时部门没有导出上下级关系---
String posNames = positionVos.stream().filter(item -> item.getUserId().equals(sysUser.getId())).map(SysUserPositionVo::getName).collect(Collectors.joining(SymbolConstant.SEMICOLON));
@ -1620,14 +1675,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
/**
* 获取部门名称
* 获取部门名称和部门类型
* for【QQYUN-10926】组织管理——用户导出时部门没有导出上下级关系
*
* @param userDepVos
* @param sysUser
* @return
*/
private StringBuilder getDepartNames(List<SysUserDepVo> userDepVos, SysUser sysUser) {
private Map<String,String> getDepartNamesAndCategory(List<SysUserDepVo> userDepVos, SysUser sysUser) {
List<SysUserDepVo> SysUserDepVoList = userDepVos.stream().filter(item -> item.getUserId().equals(sysUser.getId()))
.map(item -> {
SysUserDepVo userDepVo = new SysUserDepVo();
@ -1635,44 +1690,62 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
userDepVo.setDeptId(item.getDeptId());
userDepVo.setDepartName(item.getDepartName());
userDepVo.setParentId(item.getParentId());
userDepVo.setOrgCategory(DepartCategoryEnum.getNameByValue(item.getOrgCategory()));
return userDepVo;
}).collect(Collectors.toList());
//循环SysUserDepVoList,如果存在父级id的情况下需要将父级id的部门名称查询出来
StringBuilder departNames = new StringBuilder();
StringBuilder departOrgCategorys = new StringBuilder();
for (SysUserDepVo sysUserDepVo : SysUserDepVoList) {
if(oConvertUtils.isEmpty(sysUserDepVo.getDepartName())){
continue;
}
//用于查询父级的部门名称
List<String> departNameList = new LinkedList<>();
//用于查询父级的部门类型
List<String> departOrgCategoryList = new LinkedList<>();
departNameList.add(sysUserDepVo.getDepartName());
departOrgCategoryList.add(sysUserDepVo.getOrgCategory());
if (StringUtils.isNotEmpty(sysUserDepVo.getParentId())) {
//递归查询部门名称
this.getDepartNameByParentId(sysUserDepVo.getParentId(), departNameList);
this.getDepartNameByParentId(sysUserDepVo.getParentId(), departNameList, departOrgCategoryList);
}
Collections.reverse(departNameList);
Collections.reverse(departOrgCategoryList);
String departName = departNameList.stream().collect(Collectors.joining(SymbolConstant.SINGLE_SLASH));
if (StringUtils.isNotEmpty(departNames.toString())) {
departNames.append(SymbolConstant.SEMICOLON);
}
departNames.append(departName);
String orgCatrgory = departOrgCategoryList.stream().collect(Collectors.joining(SymbolConstant.SINGLE_SLASH));
if (StringUtils.isNotEmpty(departOrgCategorys.toString())) {
departOrgCategorys.append(SymbolConstant.SEMICOLON);
}
departOrgCategorys.append(orgCatrgory);
}
return departNames;
//update-begin---author:wangshuai---date:2025-08-27---for:【QQYUN-13617】导入时 部门添加层级不对了---
Map<String,String> map = new HashMap<>();
map.put("departNames", departNames.toString());
map.put("departOrgCategorys",departOrgCategorys.toString());
return map;
//update-end---author:wangshuai---date:2025-08-27---for:【QQYUN-13617】导入时 部门添加层级不对了---
}
/**
* 根据父级id查询父级的部门名称
* 根据父级id查询父级的部门名称和部门类型
* for【QQYUN-10926】组织管理——用户导出时部门没有导出上下级关系
*
* @param parentId
* @param departNameList
* @param departOrgCategoryList
*/
private void getDepartNameByParentId(String parentId, List<String> departNameList) {
private void getDepartNameByParentId(String parentId, List<String> departNameList, List<String> departOrgCategoryList) {
SysDepart parentDepartId = sysDepartMapper.getDepartById(parentId);
if (null != parentDepartId) {
departNameList.add(parentDepartId.getDepartName());
departOrgCategoryList.add(DepartCategoryEnum.getNameByValue(parentDepartId.getOrgCategory()));
if (StringUtils.isNotEmpty(parentDepartId.getParentId())) {
this.getDepartNameByParentId(parentDepartId.getParentId(), departNameList);
this.getDepartNameByParentId(parentDepartId.getParentId(), departNameList, departOrgCategoryList);
}
}
}
@ -2160,22 +2233,44 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
if (CollectionUtil.isNotEmpty(userList)) {
//获取部门
List<SysUserDepVo> userDepVos = sysDepartMapper.getUserDepartByUserId(userList);
//获取职位
//获取角色
List<SysUserPositionVo> sysRoles = sysRoleMapper.getUserRoleByUserId(userList);
//存放职位名称的mapkey主岗位的id value: 职级的名称
Map<String, String> postNameMap = new HashMap<>();
//组装数据并返回
for (SysUser sysUser : userList) {
SysUserExportVo userExportVo = new SysUserExportVo();
BeanUtils.copyProperties(sysUser, userExportVo);
StringBuilder departNames = this.getDepartNames(userDepVos, sysUser);
userExportVo.setDepartNames(departNames.toString());
//update-begin---author:wangshuai---date:2025-08-27---for:【QQYUN-13617】导入时 部门添加层级不对了---
Map<String, String> departMap = this.getDepartNamesAndCategory(userDepVos, sysUser);
String departNames = departMap.get("departNames");
userExportVo.setDepartNames(departNames);
userExportVo.setOrgCategorys(departMap.get("departOrgCategorys"));
//update-end---author:wangshuai---date:2025-08-27---for:【QQYUN-13617】导入时 部门添加层级不对了---
String departIds = sysUser.getDepartIds();
if (oConvertUtils.isNotEmpty(departIds)) {
List<SysUserDepVo> depVoList = sysDepartMapper.getDepartByIds(Arrays.asList(departIds.split(",")));
StringBuilder names = this.getDepartNames(userDepVos, sysUser);
userExportVo.setDepartIds(names.toString());
Map<String, String> departMaps = this.getDepartNamesAndCategory(userDepVos, sysUser);
userExportVo.setDepartIds(departMaps.get("departNames"));
}
String posNames = sysRoles.stream().filter(item -> item.getUserId().equals(sysUser.getId())).map(SysUserPositionVo::getName).collect(Collectors.joining(SymbolConstant.SEMICOLON));
userExportVo.setRoleNames(posNames);
if (null != sysUser.getMainDepPostId()) {
String postName = "";
if (null != postNameMap && postNameMap.containsKey(sysUser.getMainDepPostId())) {
postName = postNameMap.get(sysUser.getMainDepPostId());
} else {
postName = sysDepartMapper.getPostNameByPostId(sysUser.getMainDepPostId());
}
userExportVo.setPostName(postName);
postNameMap.put(sysUser.getMainDepPostId(), postName);
}
//update-begin---author:wangshuai---date:2025-09-06---for:兼职岗位改造成中间表的方式---
List<String> depPost = depPostMapper.getDepPostByUserId(sysUser.getId());
if(CollectionUtil.isNotEmpty(depPost)){
userExportVo.setOtherDepPostId(String.join(SymbolConstant.COMMA, depPost));
}
//update-end---author:wangshuai---date:2025-09-06---for:兼职岗位改造成中间表的方式---
list.add(userExportVo);
}
}
@ -2185,13 +2280,17 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
@Override
public Result<?> importSysUser(HttpServletRequest request) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
String fileKey = multipartRequest.getParameter("fileKey");
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
// 错误信息
List<String> errorMessage = new ArrayList<>();
int successLines = 0, errorLines = 0;
//存放部门的map;key为名称 value为SysDepart对象。避免多次导入和查询
Map<String, SysDepart> departMap = new HashMap<>();
//职级map key: 职级名称 value: 职级id
Map<String, String> positionMap = new HashMap<>();
//岗位map key岗位名称 + 部门id value岗位部门id
Map<String,String> postMap = new HashMap<>();
String tenantId = TokenUtils.getTenantIdByRequest(request);
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
MultipartFile file = entity.getValue();// 获取上传文件对象
@ -2200,9 +2299,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<SysUserExportVo> listSysUsers = ExcelImportUtil.importExcel(file.getInputStream(), SysUserExportVo.class, params);
List<SysUserImportVo> listSysUsers = ExcelImportUtil.importExcel(file.getInputStream(), SysUserImportVo.class, params);
ImportSysUserCache.setImportSysUserMap(fileKey,0,listSysUsers.size(),"user");
for (int i = 0; i < listSysUsers.size(); i++) {
SysUserExportVo sysUserExcel = listSysUsers.get(i);
SysUserImportVo sysUserExcel = listSysUsers.get(i);
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(sysUserExcel, sysUser);
if (OkConvertUtils.isEmpty(sysUser.getUsername())) {
@ -2222,30 +2322,32 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
continue;
} else {
// 密码默认为 “123456”
sysUser.setPassword("123456");
sysUser.setPassword(PasswordConstant.DEFAULT_PASSWORD);
// 密码加密加盐
String salt = oConvertUtils.randomGen(8);
sysUser.setSalt(salt);
String passwordEncode = PasswordUtil.encrypt(sysUserExcel.getUsername(), sysUser.getPassword(), salt);
sysUser.setPassword(passwordEncode);
sysUser.setActivitiSync(CommonConstant.ACT_SYNC_1);
this.save(sysUser);
}
//添加部门
String departNames = sysUserExcel.getDepartNames();
String orgCategorys = sysUserExcel.getOrgCategorys();
//新增或编辑部门
Integer tenantIdInt = null;
Integer tenantIdInt = 0;
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
tenantIdInt = OkConvertUtils.getInt(tenantId, 0);
}
this.addOrEditDepart(sysUser.getId(), departNames, tenantIdInt, departMap);
this.lowAddOrEditDepart(sysUser.getId(), departNames, tenantIdInt, departMap, orgCategorys, sysUserExcel.getPostName(), sysUserExcel.getMainDepPostId(),postMap,positionMap);
//新增或编辑角色
String roleNames = sysUserExcel.getRoleNames();
this.saveOrEditRole(sysUser.getId(), roleNames, tenantIdInt);
//新增或编辑职位
String position = sysUserExcel.getPost();
/* String position = sysUserExcel.getPost();
if (oConvertUtils.isNotEmpty(position)) {
this.addOrEditPosition(sysUser.getId(), position, false, tenantIdInt, positionMap);
}
}*/
//添加负责部门
this.saveChargeDepart(sysUser, sysUserExcel.getDepartIds(), departMap);
successLines++;
@ -2269,14 +2371,17 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
log.error(e.getMessage(), e);
}
}
ImportSysUserCache.setImportSysUserMap(fileKey,i,listSysUsers.size(),"user");
}
} catch (Exception e) {
ImportSysUserCache.removeImportLowAppMap(fileKey);
errorMessage.add("发生异常:" + e.getMessage());
log.error(e.getMessage(), e);
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
ImportSysUserCache.removeImportLowAppMap(fileKey);
log.error(e.getMessage(), e);
}
}
@ -2284,12 +2389,201 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
try {
departMap.clear();
departMap = null;
//最终导入完成
ImportSysUserCache.setImportSysUserMap(fileKey,1,1,"user");
return ImportExcelUtil.imporReturnRes(errorLines, successLines, errorMessage);
} catch (IOException e) {
ImportSysUserCache.removeImportLowAppMap(fileKey);
throw new RuntimeException(e);
}
}
//================================================================ begin 【用户导入】导入时 部门添加层级不对了======================================================================
/**
* 低代码下添加部门和用户
*
* @Description 和敲敲云分割处理,原因:因低代码岗位等改造,有级别,故添加部门分开处理
* @param userId 用户id
* @param depart 部门名称
* @param tenantId 租户id
* @param departMap 存放部门的map;key为名称 value为SysDepart对象。
* @param orgCategorys 部门类型
* @param postName 职级名称
* @param mainDepPostName 岗位名称
* @param postMap key: 岗位名称 + 部门id value岗位部门id
* @param positionMap key: 职级名称 value: 职级id
*/
private void lowAddOrEditDepart(String userId, String depart, Integer tenantId, Map<String, SysDepart> departMap, String orgCategorys, String postName, String mainDepPostName, Map<String, String> postMap, Map<String, String> positionMap) {
//批量将部门和用户信息建立关联关系
if (StringUtils.isNotEmpty(depart)) {
Page<SysDepart> page = new Page<>(1, 1);
//多个部门分离开
String[] departNames = depart.split(SymbolConstant.SEMICOLON);
List<String> departNameList = Arrays.asList(departNames);
//部门类型
List<String> categoryList = new ArrayList<>();
if (oConvertUtils.isNotEmpty(orgCategorys)) {
categoryList = Arrays.asList(orgCategorys.split(SymbolConstant.SEMICOLON));
}
departNameList = departNameList.stream().distinct().collect(Collectors.toList());
//当下部门循环下标
int index = 0;
for (String departName : departNameList) {
//部门id
String parentId = "";
String[] names = departName.split(SymbolConstant.SINGLE_SLASH);
//部门名称拼接
String nameStr = "";
//部门类型
String[] orgCategory = null;
if (categoryList != null && categoryList.size() > index) {
orgCategory = categoryList.get(index).split(SymbolConstant.SINGLE_SLASH);
}
for (int i = 0; i < names.length; i++) {
String name = names[i];
//拼接name
if (oConvertUtils.isNotEmpty(nameStr)) {
nameStr = nameStr + SymbolConstant.SINGLE_SLASH + name;
} else {
nameStr = name;
}
SysDepart sysDepart = null;
//默认部门
String category = DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue();
if (null != orgCategory && orgCategory.length > i) {
category = orgCategory[i];
}
//判断map中是否存在该部门名称
if (departMap.containsKey(nameStr)) {
sysDepart = departMap.get(nameStr);
parentId = sysDepart.getId();
} else {
//不存在需要去查询
List<SysDepart> departPageByName = sysDepartMapper.getDepartPageByName(page, name, tenantId, parentId);
//部门为空需要新增部门
if (CollectionUtil.isEmpty(departPageByName)) {
JSONObject formData = new JSONObject();
formData.put("parentId", parentId);
String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
sysDepart = new SysDepart();
sysDepart.setParentId(parentId);
sysDepart.setOrgCode(codeArray[0]);
sysDepart.setOrgType(codeArray[1]);
sysDepart.setTenantId(tenantId);
sysDepart.setDepartName(name);
sysDepart.setIzLeaf(CommonConstant.IS_LEAF);
sysDepart.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
sysDepart.setStatus(CommonConstant.STATUS_1);
sysDepart.setOrgCategory(DepartCategoryEnum.getValueByName(category));
sysDepartMapper.insert(sysDepart);
} else {
sysDepart = departPageByName.get(0);
}
//父级id不为空那么就将父级部门改成不是叶子节点
if (oConvertUtils.isNotEmpty(parentId)) {
sysDepartMapper.setMainLeaf(parentId, CommonConstant.NOT_LEAF);
}
parentId = sysDepart.getId();
departMap.put(nameStr, sysDepart);
}
//最后一位新增部门用户关系表
if (i == names.length - 1) {
Long count = sysUserDepartMapper.getCountByDepartIdAndUserId(userId, sysDepart.getId());
if (count == 0) {
SysUserDepart userDepart = new SysUserDepart(userId, sysDepart.getId());
sysUserDepartMapper.insert(userDepart);
}
//添加岗位
if (oConvertUtils.isNotEmpty(mainDepPostName)) {
this.insertDepartPost(userId, parentId ,postName, mainDepPostName, postMap, tenantId, positionMap);
}
}
}
index++;
}
}
}
/**
* 添加部门岗位
*
* @param mainDepPost 岗位名称
* @param userId 用户id
* @param departId 部门id【上级部门id】
* @param postName 职级名称
* @param mainDepPostName 岗位名称
* @param postMap 岗位map key岗位名称 + 部门id value岗位部门id
* @param tenantId 租户id
* @param postionMap 职级map key: 职级名称 value: 职级id
*/
private void insertDepartPost(String userId, String depId, String postName, String mainDepPostName, Map<String, String> postMap, Integer tenantId, Map<String, String> postionMap) {
if(mainDepPostName.contains(SymbolConstant.COMMA)){
mainDepPostName = mainDepPostName.split(SymbolConstant.COMMA)[0];
}
//当前部门下已经存在岗位就不需要再次添加岗位了
if (null == postMap || !postMap.containsKey(mainDepPostName + depId)) {
//根据父级部门id和职务名称查找岗位id
String departId = sysDepartMapper.getDepIdByDepIdAndPostName(depId, postName);
//不存在新增岗位
if (oConvertUtils.isEmpty(departId) ) {
//新增岗位
SysDepart sysDepart = new SysDepart();
JSONObject formData = new JSONObject();
formData.put("parentId", depId);
String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
sysDepart.setParentId(depId);
sysDepart.setOrgCode(codeArray[0]);
sysDepart.setOrgType(codeArray[1]);
sysDepart.setTenantId(tenantId);
sysDepart.setDepartName(mainDepPostName);
sysDepart.setIzLeaf(CommonConstant.IS_LEAF);
sysDepart.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
sysDepart.setStatus(CommonConstant.STATUS_1);
sysDepart.setOrgCategory(DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
//获取职级id
String positionId = "";
if(postionMap.containsKey(postName)){
positionId = postionMap.get(postName);
} else {
//根据租户id和职级名称获取职级id
positionId = this.getSysPosition(tenantId, postName);
}
sysDepart.setPositionId(positionId);
postionMap.put(postName, positionId);
sysDepartMapper.insert(sysDepart);
sysDepartMapper.setMainLeaf(depId, CommonConstant.NOT_LEAF);
postMap.put(mainDepPostName + depId, sysDepart.getId());
//需要将用户表的主岗位进行关联
departId = sysDepart.getId();
}
if(oConvertUtils.isNotEmpty(departId)){
//更新用户主岗位
SysUser user = new SysUser();
user.setId(userId);
user.setMainDepPostId(departId);
userMapper.updateById(user);
}
}
}
/**
* 获取职务信息
*
* @param tenantId
* @param postName
* @return
*/
private String getSysPosition(Integer tenantId, String postName) {
tenantId = oConvertUtils.getInt(tenantId,0);
Page<SysPosition> page = new Page<>(1, 1);
List<String> namePage = sysPositionMapper.getPositionIdByName(postName, tenantId, page);
if (CollectionUtil.isNotEmpty(namePage)) {
return namePage.get(0);
}
return "";
}
//================================================================ end 【用户导入】导入时 部门添加层级不对了======================================================================
private void saveChargeDepart(SysUser sysUser, String departIds, Map<String, SysDepart> departMap) {
//判断那些部门没有,即没有加入到部门,则不能成为负责部门人员
if (OkConvertUtils.isEmpty(departIds)) {
@ -2309,8 +2603,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
if (departIdBulider.length() > 0 && departIdBulider.charAt(departIdBulider.length() - 1) == ',') {
departIdBulider.deleteCharAt(departIdBulider.length() - 1);
}
sysUser.setDepartIds(departIdBulider.toString());
this.updateById(sysUser);
SysUser user = new SysUser();
user.setId(sysUser.getId());
user.setDepartIds(departIdBulider.toString());
this.updateById(user);
}
/**
@ -2384,4 +2680,82 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
String newPassWord = PasswordUtil.encrypt(username, password, user.getSalt());
this.userMapper.update(new SysUser().setPassword(newPassWord), new LambdaQueryWrapper<SysUser>().eq(SysUser::getId, user.getId()));
}
/**
*
* @param userName
* @return
*/
@Override
public Map<String, String> queryUserAndDeptByName(String userName) {
// 返回用户和部门信息(根据需求调整)
Map<String, String> result = new HashMap<>();
SysUser user = this.getUserByName(userName);
result.put("userId", user.getId());
result.put("username", user.getUsername());
//用户的部门信息
String orgCode = user.getOrgCode();
if (oConvertUtils.isEmpty(orgCode)) {
return result;
}
// 查询公司部门
String companyName = Optional.ofNullable(sysDepartMapper.queryCompByOrgCode(orgCode))
.map(SysDepart::getDepartName)
.orElse("");
// 查询用户部门并匹配
String userDeptName = sysDepartMapper.queryDepartsByUsername(userName).stream()
.filter(depart -> orgCode.equals(depart.getOrgCode()))
.findFirst()
.map(SysDepart::getDepartName)
.orElse("");
// 设置部门显示文本
String compDepart;
if (StringUtils.isNotEmpty(companyName) && StringUtils.isNotEmpty(userDeptName)) {
compDepart = companyName.equals(userDeptName)
? companyName
: companyName + "-" + userDeptName;
} else {
compDepart = StringUtils.isNotEmpty(companyName) ? companyName : userDeptName;
}
result.put("compDepart", compDepart);
return result;
}
/**
* 查询部门、岗位下的用户 包括子部门下的用户
*
* @param orgCode
* @param userParams
* @param page
* @return
*/
@Override
public IPage<SysUserSysDepPostModel> queryDepartPostUserByOrgCode(String orgCode, SysUser userParams, IPage page) {
List<SysUserSysDepPostModel> sysDepartModels = baseMapper.queryDepartPostUserByOrgCode(page, orgCode, userParams);
if(CollectionUtil.isNotEmpty(sysDepartModels)){
List<String> userIds = sysDepartModels.stream().map(SysUserSysDepPostModel::getId).toList();
//获取部门名称
Map<String, String> useDepNames = this.getDepNamesByUserIds(userIds);
sysDepartModels.forEach(item -> {
List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(item.getId());
item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
item.setOrgCodeTxt(useDepNames.get(item.getId()));
//查询用户的租户ids
List<Integer> list = userTenantMapper.getTenantIdsByUserId(item.getId());
if (oConvertUtils.isNotEmpty(list)) {
item.setRelTenantIds(StringUtils.join(list.toArray(), SymbolConstant.COMMA));
} else {
item.setRelTenantIds("");
}
Integer posTenantId = null;
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
posTenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);;
}
});
}
return page.setRecords(sysDepartModels);
}
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -846,7 +847,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
* @param verifyConfig 是否验证配置未启用的APP会拒绝发送
* @return
*/
public JSONObject sendTextCardMessage(SysAnnouncement announcement, boolean verifyConfig) {
public JSONObject sendTextCardMessage(SysAnnouncement announcement,String mobileOpenUrl, boolean verifyConfig) {
SysThirdAppConfig config = this.getWeChatThirdAppConfig();
if (verifyConfig && null == config) {
return null;
@ -882,9 +883,30 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
textCard.setTouser(this.getTouser(usernameString, isToAll));
TextCardEntity entity = new TextCardEntity();
entity.setTitle(announcement.getTitile());
entity.setDescription(oConvertUtils.getString(announcement.getMsgAbstract(),""));
String baseUrl = null;
//update-begin---author:scott ---date:2025-08-05 for【QQYUN-13257】【h5】催办、抄送消息在企业微信中显示json乱码---
// 判断announcement.getMsgAbstract()值是json格式
if(oConvertUtils.isJson(announcement.getMsgAbstract()) && oConvertUtils.isNotEmpty(mobileOpenUrl)){
entity.setDescription(announcement.getMsgContent());
entity.setUrl(mobileOpenUrl);
}else{
entity.setDescription(oConvertUtils.getString(announcement.getMsgAbstract(),""));
entity.setUrl(geQywxtAnnouncementUrl(announcement));
}
//update-end---author:scott ---date::2025-08-05 for【QQYUN-13257】【h5】催办、抄送消息在企业微信中显示json乱码---
textCard.setTextcard(entity);
return JwMessageAPI.sendTextCardMessage(textCard, accessToken);
}
/**
* 获取企业微信的公告链接
*
* @return
*/
private String geQywxtAnnouncementUrl(SysAnnouncement announcement){
String baseUrl = null;
//优先通过请求获取basepath获取不到读取 jeecg.domainUrl.pc
try {
baseUrl = RestUtil.getBaseUrl();
@ -893,10 +915,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
baseUrl = jeecgBaseConfig.getDomainUrl().getPc();
//e.printStackTrace();
}
entity.setUrl(baseUrl + "/sys/annountCement/show/" + announcement.getId());
textCard.setTextcard(entity);
return JwMessageAPI.sendTextCardMessage(textCard, accessToken);
return baseUrl + "/sys/annountCement/show/" + announcement.getId();
}
private String getTouser(String origin, boolean toAll) {

View File

@ -0,0 +1,53 @@
package org.jeecg.modules.system.util;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: 导入缓存类,为了前台显示进度
* @author: wangshuai
* @date: 2025/9/6 14:09
*/
public class ImportSysUserCache {
private static final Map<String, Double> importSysUserMap = new HashMap<>();
/**
* 获取导入的列
*
* @param key
* @param type user 用户 可扩展
* @return
*/
public static Double getImportSysUserMap(String key, String type) {
if (importSysUserMap.containsKey(key + "__" + type)) {
return importSysUserMap.get(key + "__" + type);
}
return 0.0;
}
/**
* 设置导入缓存
*
* @param key 前村传过来的随机key
* @param num 导入行数
* @param length 总长度
* @param type 导入类型 user 用户列表
*/
public static void setImportSysUserMap(String key, int num, int length, String type) {
double percent = (num * 100.0) / length;
if(num == length){
percent = 100;
}
importSysUserMap.put(key + "__" + type, percent);
}
/**
* 移除导入缓存
*
* @param key
*/
public static void removeImportLowAppMap(String key) {
importSysUserMap.remove(key);
}
}

View File

@ -28,6 +28,9 @@ public class SysDepartExportVo {
/**机构类别 1=公司2=组织机构3=岗位*/
@Excel(name="机构类别",width=15,dicCode="org_category")
private String orgCategory;
/** 职级id */
@Excel(name="职级",width=15,dictTable = "sys_position", dicCode = "id", dicText = "name")
private String positionId;
/**机构编码*/
@Excel(name="机构编码",width=15)
private String orgCode;

View File

@ -0,0 +1,53 @@
package org.jeecg.modules.system.vo;
import lombok.Data;
/**
* @Description: 部门职务
*
* @author: wangshuai
* @date: 2025/8/18 10:11
*/
@Data
public class SysDepartPositionVo {
/**
* 部门id
*/
private String id;
/**
* 是否为叶子节点(数据返回)
*/
private Integer izLeaf;
/**
* 部门名称
*/
private String departName;
/**
* 职务名称
*/
private String positionName;
/**
* 父级id
*/
private String parentId;
/**
* 部门编码
*/
private String orgCode;
/**
* 机构类型
*/
private String orgCategory;
/**
* 上级岗位id
*/
private String depPostParentId;
}

View File

@ -0,0 +1,83 @@
package org.jeecg.modules.system.vo;
import lombok.Data;
import org.jeecg.common.constant.enums.DepartCategoryEnum;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysDepart;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 岗位下拉选择树
*
* @author: wangshuai
* @date: 2025/8/18 9:40
*/
@Data
public class SysPositionSelectTreeVo {
/** 对应SysDepart中的id字段,前端数据树中的value*/
private String value;
/** 对应depart_name字段,前端数据树中的title*/
private String title;
private boolean isLeaf;
/** 是否显示复选框 */
private boolean checkable;
/** 是否禁用 */
private boolean disabled;
// 以下所有字段均与SysDepart相同
private String id;
/**父级id*/
private String parentId;
/**部门类别*/
private String orgCategory;
/**部门编码*/
private String orgCode;
private List<SysPositionSelectTreeVo> children = new ArrayList<>();
/**
* 将SysDepart对象转换成SysDepartTreeModel对象
* @param sysDepart
*/
public SysPositionSelectTreeVo(SysDepart sysDepart) {
this.value = sysDepart.getId();
this.title = sysDepart.getDepartName();
this.id = sysDepart.getId();
this.parentId = sysDepart.getParentId();
this.orgCategory = sysDepart.getOrgCategory();
this.orgCode = sysDepart.getOrgCode();
if(0 == sysDepart.getIzLeaf()){
this.isLeaf = false;
}else{
this.isLeaf = true;
}
if(DepartCategoryEnum.DEPART_CATEGORY_POST.getValue().equals(sysDepart.getOrgCategory())){
this.checkable = true;
this.disabled = false;
}else{
this.checkable = false;
this.disabled = true;
}
}
public SysPositionSelectTreeVo(SysDepartPositionVo position) {
this.value = position.getId();
if(oConvertUtils.isNotEmpty(position.getDepartName())){
this.title = position.getPositionName() + "("+position.getDepartName()+")";
}else{
this.title = position.getPositionName();
}
this.id = position.getId();
this.parentId = position.getDepPostParentId();
this.orgCategory = "3";
if(0 == position.getIzLeaf()){
this.isLeaf = false;
}else{
this.isLeaf = true;
}
this.checkable = true;
this.disabled = false;
}
}

View File

@ -21,4 +21,14 @@ public class SysUserDepVo {
* 部门的父级id
*/
private String parentId;
/**
* 部门类型
*/
private String orgCategory;
/**
* 职级
*/
private String positionId;
}

View File

@ -1,8 +1,8 @@
package org.jeecg.modules.system.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
@ -77,13 +77,26 @@ public class SysUserExportVo {
*/
@Excel(name = "工号", width = 15)
private String workNo;
/**
* 主岗位
*/
@Excel(name="主岗位",width = 15,dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
@Dict(dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
private String mainDepPostId;
/**
* 职务,关联职务表
* 职
*/
@Excel(name = "", width = 15)
@TableField(exist = false)
private String post;
@Excel(name="", width = 15)
private String postName;
/**
* 兼职岗位
*/
@Excel(name="兼职岗位",width = 15,dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
@Dict(dictTable ="sys_depart",dicText = "depart_name",dicCode = "id")
private String otherDepPostId;
/**
* 座机号
@ -110,10 +123,22 @@ public class SysUserExportVo {
@Excel(name = "所属部门", width = 15)
private String departNames;
/**
* 机构类型
* 公司(1)、部门(2)、岗位(3)、子公司(4)
*/
@Excel(name = "部门类型(1-公司,2-部门,3-岗位,4-子公司)",width = 15)
private String orgCategorys;
/**
* 负责部门
*/
@Excel(name = "负责部门", width = 15)
private String departIds;
/**
* 职务
*/
@Excel(name="职务", dicCode = "user_position")
private String positionType;
}

View File

@ -0,0 +1,129 @@
package org.jeecg.modules.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @Description: 低代码用户导入
* @author: wangshuai
* @date: 2025/8/27 11:58
*/
@Data
public class SysUserImportVo {
/**
* 登录账号
*/
@Excel(name = "登录账号", width = 15)
private String username;
/**
* 真实姓名
*/
@Excel(name = "真实姓名", width = 15)
private String realname;
/**
* 头像
*/
@Excel(name = "头像", width = 15, type = 2)
private String avatar;
/**
* 生日
*/
@Excel(name = "生日", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
/**
* 性别1男 2
*/
@Excel(name = "性别", width = 15, dicCode = "sex")
private Integer sex;
/**
* 电子邮件
*/
@Excel(name = "电子邮件", width = 15)
private String email;
/**
* 电话
*/
@Excel(name = "电话", width = 15)
private String phone;
/**
* 状态(1正常 2冻结
*/
@Excel(name = "状态", width = 15, dicCode = "user_status")
private Integer status;
/**
* 删除状态0正常1已删除
*/
@Excel(name = "删除状态", width = 15, dicCode = "del_flag")
private Integer delFlag;
/**
* 工号,唯一键
*/
@Excel(name = "工号", width = 15)
private String workNo;
/**
* 主岗位
*/
@Excel(name="主岗位",width = 15)
private String mainDepPostId;
/**
* 职级
*/
@Excel(name="职级", width = 15)
private String postName;
/**
* 身份0 普通成员 1 上级)
*/
@Excel(name = "1普通成员 2上级", width = 15)
private Integer userIdentity;
/**
* 角色名称
*/
@Excel(name = "角色", width = 15)
private String roleNames;
/**
* 部门名称
*/
@Excel(name = "所属部门", width = 15)
private String departNames;
/**
* 机构类型
* 公司(1)、部门(2)、岗位(3)、子公司(4)
*/
@Excel(name = "部门类型(1-公司,2-部门,3-岗位,4-子公司)",width = 15)
private String orgCategorys;
/**
* 负责部门
*/
@Excel(name = "负责部门", width = 15)
private String departIds;
/**
* 职务
*/
@Excel(name="职务", dicCode = "user_position")
private String positionType;
}

View File

@ -1,7 +1,11 @@
package org.jeecg.modules.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @Description: 用户租户类(用户数据租户数据)
@ -44,7 +48,14 @@ public class SysUserTenantVo {
/**
* 头像
*/
private String avatar;
private String avatar;
/**
* 创建日期
*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 职位

View File

@ -1,27 +1,47 @@
-- 注意该页面对应的前台目录为views/${entityPackagePath}文件夹下
-- 如果你想更改到其他目录请修改sql中component字段对应的值
<#assign id = '${.now?string["yyyyMMddhhmmSSsss"]}0'>
<#assign mainId = "${.now?long}01">
<#assign addId = "${.now?long}02">
<#assign editId = "${.now?long}03">
<#assign delId = "${.now?long}04">
<#assign batchDelId = "${.now?long}05">
<#assign exportId = "${.now?long}06">
<#assign importId = "${.now?long}07">
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('${id}', NULL, '${tableVo.ftlDescription}', '/${entityPackagePath}/${entityName?uncap_first}List', '${entityPackagePath}/${entityName}List', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0);
-- 主菜单
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('${mainId}', NULL, '${tableVo.ftlDescription}', '/${entityPackagePath}/${entityName?uncap_first}List', '${entityPackagePath}/${entityName}List', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0);
-- 权限控制sql
-- 新增
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}1', '${id}', '添加${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
VALUES ('${addId}', '${mainId}', '添加${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 编辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}2', '${id}', '编辑${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
VALUES ('${editId}', '${mainId}', '编辑${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}3', '${id}', '删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
VALUES ('${delId}', '${mainId}', '删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 批量删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}4', '${id}', '批量删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
VALUES ('${batchDelId}', '${mainId}', '批量删除${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 导出excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}5', '${id}', '导出excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
VALUES ('${exportId}', '${mainId}', '导出excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 导入excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('${.now?string["yyyyMMddhhmmSSsss"]}6', '${id}', '导入excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
VALUES ('${importId}', '${mainId}', '导入excel_${tableVo.ftlDescription}', NULL, NULL, 0, NULL, NULL, 2, '${entityPackage}:${tableName}:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0, 0, '1', 0);
-- 角色授权 admin 角色为例role_id 可替换
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}08', 'f6817f48af4fb3af11b9e8bf182f618b', '${mainId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}09', 'f6817f48af4fb3af11b9e8bf182f618b', '${addId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}10', 'f6817f48af4fb3af11b9e8bf182f618b', '${editId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}11', 'f6817f48af4fb3af11b9e8bf182f618b', '${delId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}12', 'f6817f48af4fb3af11b9e8bf182f618b', '${batchDelId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}13', 'f6817f48af4fb3af11b9e8bf182f618b', '${exportId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');
INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('${.now?long}14', 'f6817f48af4fb3af11b9e8bf182f618b', '${importId}', NULL, '${.now?string["yyyy-MM-dd HH:mm:ss"]}', '127.0.0.1');

View File

@ -1,4 +1,4 @@
<#include "../utils.ftl">
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
<#if po.fieldName != 'id'>
${po.fieldName}: [

View File

@ -1,4 +1,4 @@
<#include "../../utils.ftl">
<#include "/common/utils.ftl">
<#list columns as po>
<#if po.isShow == 'Y' && poHasCheck(po)>
${po.fieldName}: [<#include "vue3CoreNative.ftl">],

View File

@ -1,4 +1,4 @@
<#include "../utils.ftl">
<#include "/common/utils.ftl">
<#if col.isShow == 'Y' && poHasCheck(col)>
validateRules: [
<#if col.fieldName != 'id'>

View File

@ -1,4 +1,3 @@
<#--<#include "../../../../../../../common/utils.ftl">-->
<#include "/common/utils.ftl">
<template>
<a-spin :spinning="confirmLoading">

View File

@ -1,4 +1,3 @@
<#--<#include "../../../../../../../common/utils.ftl">-->
<#include "/common/utils.ftl">
<#assign modal_width = 800>
<#if tableVo.fieldRowNum==2>

View File

@ -33,7 +33,7 @@
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
@ -303,7 +303,7 @@
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -339,7 +339,7 @@
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -378,7 +378,7 @@
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -4,7 +4,7 @@
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :maxHeight="500" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicForm @register="registerForm" name="${entityName}Form" />
<#if buttonList?? && buttonList?size gt 0>
<template #insertFooter>
@ -38,7 +38,8 @@
</#if>
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
baseRowStyle: { padding: "0 20px" }
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@ -107,7 +108,7 @@
};
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -110,7 +110,7 @@
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
@ -368,7 +368,7 @@
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -404,7 +404,7 @@
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -484,7 +484,7 @@
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -251,6 +251,6 @@
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
padding: 14px 20px;
}
</style>

View File

@ -1,9 +1,10 @@
<#include "/common/utils.ftl">
<template>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<j-modal :title="title" maxHeight="500px" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
<template #footer>
<#if buttonList?? && buttonList?size gt 0>
@ -77,7 +78,7 @@
visible.value = false;
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -177,7 +177,7 @@ public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, $
*/
private ${entityName} getTreeRoot(String pidVal){
${entityName} data = baseMapper.selectById(pidVal);
if(data != null && !I${entityName}Service.ROOT_PID_VALUE.equals(data.get${pidFieldName?cap_first}())){
if(data != null && !I${entityName}Service.ROOT_PID_VALUE.equals(data.get${pidFieldName?cap_first}()) && !data.get${pidFieldName?cap_first}().equals(data.getId())){
return this.getTreeRoot(data.get${pidFieldName?cap_first}());
}else{
return data;

View File

@ -38,7 +38,7 @@
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
@ -447,7 +447,7 @@
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -483,7 +483,7 @@
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -544,7 +544,7 @@
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -14,7 +14,7 @@
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :title="getTitle" @ok="handleSubmit">
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :maxHeight="500" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm" name="${entityName}Form" />
<#if buttonList?? && buttonList?size gt 0>
<template #insertFooter>
@ -65,6 +65,7 @@
xs: { span: 24 },
sm: { span: 18 },
},
baseRowStyle: { padding: "0 20px" }
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@ -80,8 +81,20 @@
await setFieldsValue({
...data.record,
});
updateSchema([
{
field: '${pidFieldName}',
componentProps: { hiddenNodeKey: data.record.id },
},
]);
} else {
model = null;
updateSchema([
{
field: '${pidFieldName}',
componentProps: { hiddenNodeKey: '' },
},
]);
}
//父级节点树信息
treeData.value = await loadTreeData({'async': false,'pcode':''});
@ -157,7 +170,7 @@
};
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -120,7 +120,7 @@
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
@ -518,7 +518,7 @@
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -559,7 +559,7 @@
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -597,7 +597,7 @@
}
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -54,6 +54,7 @@
pidField="${tableVo.extendParams.pidField}"
pidValue="0"
hasChildField="${tableVo.extendParams.hasChildren}"
:hiddenNodeKey="hiddenNodeKey"
<#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>>
</j-tree-select>
</a-form-item>
@ -106,6 +107,8 @@
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//需要隐藏的key
const hiddenNodeKey = ref<string>('');
//表单验证
const validatorRules = reactive({
<#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
@ -186,6 +189,11 @@
})
//赋值
Object.assign(formData,tmpData);
if(tmpData.id) {
hiddenNodeKey.value = tmpData.id;
} else {
hiddenNodeKey.value = "";
}
model = tmpData
});
}
@ -303,6 +311,6 @@
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
padding: 14px 20px;
}
</style>

View File

@ -1,9 +1,10 @@
<#include "/common/utils.ftl">
<template>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<j-modal :title="title" maxHeight="500px" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
<template #footer>
<#if buttonList?? && buttonList?size gt 0>

View File

@ -33,7 +33,7 @@
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
@ -154,6 +154,7 @@
api: list,
columns,
canResize: true,
maxHeight: 300,
clickToRowSelect: true,
rowSelection: {type: 'radio'},
formConfig: {
@ -349,7 +350,7 @@
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -384,7 +385,7 @@
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -443,7 +444,7 @@
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -4,7 +4,7 @@
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :maxHeight="500" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicForm @register="registerForm" name="${entityName}Form" />
<#if buttonList?? && buttonList?size gt 0>
<template #insertFooter>
@ -46,7 +46,8 @@
</#if>
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
baseRowStyle: { padding: "0 20px" }
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
@ -106,7 +107,7 @@
}
};
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -2,7 +2,7 @@
<#list subTables as sub>
#segment#${sub.entityName}Modal.vue
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :maxHeight="500" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
<BasicForm @register="registerForm" name="${sub.entityName}Form" />
</BasicModal>
</template>
@ -36,7 +36,8 @@
</#if>
schemas: ${sub.entityName?uncap_first}FormSchema,
showActionButtonGroup: false,
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}}
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
baseRowStyle: { padding: "0 20px" }
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {

View File

@ -114,7 +114,7 @@
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'button'>
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
</#if>
@ -243,6 +243,7 @@
api: list,
columns,
canResize:true,
maxHeight: 300,
useSearchForm: false,
clickToRowSelect: true,
rowSelection: {type: 'radio'},
@ -389,7 +390,7 @@
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
},
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -426,7 +427,7 @@
auth: '${entityPackage}:${tableName}:delete'
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle == 'link'>
,{
label: '${btn.buttonName}',
@ -464,7 +465,7 @@
}
</#if>
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='button'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -1,9 +1,10 @@
<#include "/common/utils.ftl">
<template>
<#assign buttonList=[]>
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
<#assign buttonList = tableVo.extendParams.cgButtonList?filter(btn -> btn??)>
</#if>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<j-modal :title="title" maxHeight="500px" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
<template #footer>
<#if buttonList?? && buttonList?size gt 0>
@ -79,7 +80,7 @@
}
<#if buttonList?size gt 0>
<#list buttonList?sort_by('orderNum') as btn>
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
<#if btn.buttonStyle=='form'>
function handle${btn.buttonCode?cap_first}(){
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');

View File

@ -222,7 +222,7 @@
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
padding: 14px 20px;
}
</style>
</#list>

View File

@ -2,7 +2,7 @@
<#list subTables as sub>
#segment#${sub.entityName}Modal.vue
<template>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<j-modal :title="title" maxHeight="500px" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<${sub.entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${sub.entityName}Form>
</j-modal>
</template>

View File

@ -1,7 +1,6 @@
<#-- noinspection JSDuplicatedDeclaration,RequiredAttributes,NpmUsedModulesInstalled -->
<#-- ** 引入全局工具方法 ** -->
<#--<#include "/common/utils.ftl">-->
<#include "../../../../../../common/utils.ftl">
<#include "/common/utils.ftl">
<#-- ** 定义全局使用的变量 ** -->
<#-- 是否有查询条件 -->
<#assign query_flag=false>

Some files were not shown because too many files have changed in this diff Show More