mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-08 17:12:28 +08:00
3.7.0大版本发布
This commit is contained in:
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-system-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.3</version>
|
||||
<version>3.7.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -85,6 +85,14 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
*/
|
||||
@GetMapping("/sys/api/getRolesByUsername")
|
||||
List<String> getRolesByUsername(@RequestParam("username") String username);
|
||||
|
||||
/**
|
||||
* 7通过用户账号查询角色集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/getRolesByUserId")
|
||||
List<String> getRolesByUserId(@RequestParam("userId") String userId);
|
||||
|
||||
/**
|
||||
* 8通过用户账号查询部门集合
|
||||
@ -93,6 +101,14 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
*/
|
||||
@GetMapping("/sys/api/getDepartIdsByUsername")
|
||||
List<String> getDepartIdsByUsername(@RequestParam("username") String username);
|
||||
|
||||
/**
|
||||
* 8通过用户账号查询部门集合
|
||||
* @param userId
|
||||
* @return 部门 id
|
||||
*/
|
||||
@GetMapping("/sys/api/getDepartIdsByUserId")
|
||||
List<String> getDepartIdsByUserId(@RequestParam("userId") String userId);
|
||||
|
||||
/**
|
||||
* 8.2 通过用户账号查询部门父ID集合
|
||||
@ -304,6 +320,14 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
*/
|
||||
@GetMapping("/sys/api/getUserRoleSet")
|
||||
Set<String> getUserRoleSet(@RequestParam("username")String username);
|
||||
|
||||
/**
|
||||
* 30获取用户的角色集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/getUserRoleSetById")
|
||||
Set<String> getUserRoleSetById(@RequestParam("userId")String userId);
|
||||
|
||||
/**
|
||||
* 31获取用户的权限集合
|
||||
@ -348,6 +372,15 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@Override
|
||||
@GetMapping("/sys/api/queryUserRoles")
|
||||
Set<String> queryUserRoles(@RequestParam("username")String username);
|
||||
|
||||
/**
|
||||
* 35查询用户角色信息
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/queryUserRolesById")
|
||||
Set<String> queryUserRolesById(@RequestParam("userId")String userId);
|
||||
|
||||
/**
|
||||
* 36查询用户权限信息
|
||||
@ -387,6 +420,15 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@SensitiveDecode
|
||||
@GetMapping("/sys/api/getUserByName")
|
||||
LoginUser getUserByName(@RequestParam("username") String username);
|
||||
|
||||
/**
|
||||
* 39根据用户账号查询用户ID CommonAPI中定义
|
||||
* @param username
|
||||
* @return 用户ID
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/getUserIdByName")
|
||||
String getUserIdByName(@RequestParam("username") String username);
|
||||
|
||||
/**
|
||||
* 40字典表的 翻译
|
||||
@ -609,7 +651,7 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @param dataLogDto
|
||||
*/
|
||||
@PostMapping("/sys/api/saveDataLog")
|
||||
void saveDataLog(DataLogDTO dataLogDto);
|
||||
void saveDataLog(@RequestBody DataLogDTO dataLogDto);
|
||||
|
||||
/**
|
||||
* 更新头像
|
||||
|
||||
@ -60,11 +60,21 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRolesByUserId(String userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDepartIdsByUsername(String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDepartIdsByUserId(String userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDepartParentIdsByUsername(String username) {
|
||||
return null;
|
||||
@ -193,6 +203,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getUserRoleSetById(String userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getUserPermissionSet(String userId) {
|
||||
return null;
|
||||
@ -218,6 +233,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryUserRolesById(String userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryUserAuths(String userId) {
|
||||
return null;
|
||||
@ -239,6 +259,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserIdByName(String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translateDictFromTable(String table, String text, String code, String key) {
|
||||
return null;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-system-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.3</version>
|
||||
<version>3.7.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -81,6 +81,13 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @return
|
||||
*/
|
||||
List<String> getRolesByUsername(String username);
|
||||
|
||||
/**
|
||||
* 7通过用户账号查询角色集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> getRolesByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 8通过用户账号查询部门集合
|
||||
@ -88,6 +95,12 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @return 部门 id
|
||||
*/
|
||||
List<String> getDepartIdsByUsername(String username);
|
||||
/**
|
||||
* 8通过用户账号查询部门集合
|
||||
* @param userId
|
||||
* @return 部门 id
|
||||
*/
|
||||
List<String> getDepartIdsByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 8.2 通过用户账号查询部门父ID集合
|
||||
@ -299,7 +312,13 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @return
|
||||
*/
|
||||
Set<String> getUserRoleSet(String username);
|
||||
|
||||
/**
|
||||
* 31获取用户的角色集合
|
||||
* @param useId
|
||||
* @return
|
||||
*/
|
||||
Set<String> getUserRoleSetById(String useId);
|
||||
|
||||
/**
|
||||
* 32获取用户的权限集合
|
||||
* @param userId
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.3</version>
|
||||
<version>3.7.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<version>3.6.3</version>
|
||||
<version>3.7.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -29,17 +29,16 @@
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>jeewx-api</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木报表设计 -->
|
||||
<!-- 积木报表 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木仪表盘 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-drag</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木报表 mongo redis 支持包
|
||||
<!-- 积木报表 mongo redis 支持包
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-nosql-starter</artifactId>
|
||||
|
||||
@ -15,6 +15,10 @@ import org.springframework.context.annotation.Configuration;
|
||||
* 提醒: 达梦数据库需要修改下面的参数${spring.datasource.dynamic.datasource.master.url:}配置
|
||||
* @author: scott
|
||||
* @date: 2021年02月18日 16:30
|
||||
*
|
||||
* 重要说明:此类改路径或者名称,需要同步修改
|
||||
* org/jeecg/interceptor/OnlineRepairCodeGenerateDbConfig.java里面的注解
|
||||
* @ConditionalOnMissingClass("org.jeecg.config.init.CodeGenerateDbConfig")
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
|
||||
@ -36,7 +36,11 @@ public class JimuReportTokenService implements JmReportTokenServiceI {
|
||||
|
||||
@Override
|
||||
public String getToken(HttpServletRequest request) {
|
||||
return TokenUtils.getTokenByRequest(request);
|
||||
try {
|
||||
return TokenUtils.getTokenByRequest(request);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -8,6 +8,7 @@ import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.jeecg.common.api.dto.LogDTO;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.entity.SysTenantPack;
|
||||
@ -52,7 +53,7 @@ public class TenantPackUserLogAspect {
|
||||
for(Object obj: args){
|
||||
if(obj instanceof SysTenantPack){
|
||||
// logType=3 租户操作日志
|
||||
logType = 3;
|
||||
logType = CommonConstant.LOG_TYPE_3;
|
||||
SysTenantPack pack = (SysTenantPack)obj;
|
||||
if(opType==2){
|
||||
content = "创建了角色权限 "+ pack.getPackName();
|
||||
@ -60,7 +61,7 @@ public class TenantPackUserLogAspect {
|
||||
tenantId = pack.getTenantId();
|
||||
break;
|
||||
}else if(obj instanceof SysTenantPackUser){
|
||||
logType = 3;
|
||||
logType = CommonConstant.LOG_TYPE_3;
|
||||
SysTenantPackUser packUser = (SysTenantPackUser)obj;
|
||||
if(opType==2){
|
||||
content = "将 "+packUser.getRealname()+" 添加到角色 "+ packUser.getPackName();
|
||||
|
||||
@ -102,6 +102,17 @@ public class SystemApiController {
|
||||
}
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户账号查询用户ID
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getUserIdByName")
|
||||
public String getUserIdByName(@RequestParam("username") String username){
|
||||
String userId = sysBaseApi.getUserIdByName(username);
|
||||
return userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户id查询用户信息
|
||||
@ -129,6 +140,16 @@ public class SystemApiController {
|
||||
List<String> getRolesByUsername(@RequestParam("username") String username){
|
||||
return sysBaseApi.getRolesByUsername(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户账号查询角色集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getRolesByUserId")
|
||||
List<String> getRolesByUserId(@RequestParam("userId") String userId){
|
||||
return sysBaseApi.getRolesByUserId(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户账号查询部门集合
|
||||
@ -139,6 +160,16 @@ public class SystemApiController {
|
||||
List<String> getDepartIdsByUsername(@RequestParam("username") String username){
|
||||
return sysBaseApi.getDepartIdsByUsername(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户账号查询部门集合
|
||||
* @param userId
|
||||
* @return 部门 id
|
||||
*/
|
||||
@GetMapping("/getDepartIdsByUserId")
|
||||
List<String> getDepartIdsByUserId(@RequestParam("userId") String userId){
|
||||
return sysBaseApi.getDepartIdsByUserId(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户账号查询部门父ID集合
|
||||
@ -383,6 +414,16 @@ public class SystemApiController {
|
||||
public Set<String> getUserRoleSet(@RequestParam("username")String username){
|
||||
return sysBaseApi.getUserRoleSet(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的角色集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getUserRoleSetById")
|
||||
public Set<String> getUserRoleSetById(@RequestParam("userId")String userId){
|
||||
return sysBaseApi.getUserRoleSetById(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的权限集合
|
||||
@ -415,6 +456,16 @@ public class SystemApiController {
|
||||
public Set<String> queryUserRoles(@RequestParam("username") String username){
|
||||
return sysUserService.getUserRolesSet(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户角色信息
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryUserRolesById")
|
||||
public Set<String> queryUserRolesById(@RequestParam("userId") String userId){
|
||||
return sysUserService.getUserRoleSetById(userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -893,7 +944,7 @@ public class SystemApiController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getUserAccountsByDepCode")
|
||||
public List<String> getUserAccountsByDepCode(String orgCode){
|
||||
public List<String> getUserAccountsByDepCode(@RequestParam("orgCode") String orgCode){
|
||||
return sysBaseApi.getUserAccountsByDepCode(orgCode);
|
||||
}
|
||||
|
||||
|
||||
@ -173,7 +173,7 @@ public class SysMessageTemplateController extends JeecgController<SysMessageTemp
|
||||
sysBaseApi.sendTemplateMessage(md);
|
||||
return result.success("消息发送成功!");
|
||||
} catch (Exception e) {
|
||||
log.error("发送消息出错", e.getMessage());
|
||||
log.error("发送消息出错:" + e.getMessage(), e);
|
||||
return result.error500("发送消息出错!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,6 @@ public enum RangeDateEnum {
|
||||
//本周
|
||||
calendar1.set(Calendar.DAY_OF_WEEK, 2);
|
||||
|
||||
calendar2.set(Calendar.DAY_OF_WEEK,2);
|
||||
calendar2.add(Calendar.WEEK_OF_MONTH,1);
|
||||
calendar2.add(Calendar.DAY_OF_WEEK,-1);
|
||||
} else if(SZ.key.equals(key)){
|
||||
|
||||
@ -31,8 +31,13 @@ public class WebSocket {
|
||||
* Redis触发监听名字
|
||||
*/
|
||||
public static final String REDIS_TOPIC_NAME = "socketHandler";
|
||||
|
||||
//避免初次调用出现空指针的情况
|
||||
private static JeecgRedisClient jeecgRedisClient;
|
||||
@Autowired
|
||||
private JeecgRedisClient jeecgRedisClient;
|
||||
private void setJeecgRedisClient(JeecgRedisClient jeecgRedisClient){
|
||||
WebSocket.jeecgRedisClient = jeecgRedisClient;
|
||||
}
|
||||
|
||||
|
||||
//==========【websocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================
|
||||
@ -109,6 +114,9 @@ public class WebSocket {
|
||||
log.debug("【系统 WebSocket】收到客户端消息:" + message);
|
||||
}else{
|
||||
log.debug("【系统 WebSocket】收到客户端消息:" + message);
|
||||
//update-begin---author:wangshuai---date:2024-05-07---for:【issues/1161】前端websocket因心跳导致监听不起作用---
|
||||
this.sendMessage(userId, "ping");
|
||||
//update-end---author:wangshuai---date:2024-05-07---for:【issues/1161】前端websocket因心跳导致监听不起作用---
|
||||
}
|
||||
|
||||
// //------------------------------------------------------------------------------
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package org.jeecg.modules.monitor.actuator;
|
||||
|
||||
import org.jeecg.modules.monitor.actuator.httptrace.CustomInMemoryHttpTraceRepository;
|
||||
import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceProperties;
|
||||
import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 自定义健康监控配置类
|
||||
*
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/5/13 17:20
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(HttpTraceProperties.class)
|
||||
@AutoConfigureBefore(HttpTraceAutoConfiguration.class)
|
||||
public class CustomActuatorConfig {
|
||||
|
||||
/**
|
||||
* 请求追踪
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:52
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "management.trace.http", name = "enabled", matchIfMissing = true)
|
||||
@ConditionalOnMissingBean(HttpTraceRepository.class)
|
||||
public CustomInMemoryHttpTraceRepository traceRepository() {
|
||||
return new CustomInMemoryHttpTraceRepository();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package org.jeecg.modules.monitor.actuator.httptrace;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Selector;
|
||||
import org.springframework.boot.actuate.trace.http.HttpTrace;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.boot.actuate.endpoint.annotation.Selector.Match.ALL_REMAINING;
|
||||
|
||||
/**
|
||||
* @Description: ENDPOINT: 请求追踪(新),支持通过responseCode筛选
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/5/13 17:02
|
||||
*/
|
||||
@Component
|
||||
@Endpoint(id = "httptrace-new")
|
||||
public class CustomHttpTraceEndpoint{
|
||||
private final CustomInMemoryHttpTraceRepository repository;
|
||||
|
||||
public CustomHttpTraceEndpoint(CustomInMemoryHttpTraceRepository repository) {
|
||||
Assert.notNull(repository, "Repository must not be null");
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public HttpTraceDescriptor traces(@Selector(match = ALL_REMAINING) String query) {
|
||||
return new CustomHttpTraceEndpoint.HttpTraceDescriptor(this.repository.findAll(query));
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static final class HttpTraceDescriptor {
|
||||
private final List<HttpTrace> traces;
|
||||
|
||||
private HttpTraceDescriptor(List<HttpTrace> traces) {
|
||||
this.traces = traces;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
package org.jeecg.modules.monitor.actuator.httptrace;
|
||||
|
||||
import org.springframework.boot.actuate.trace.http.HttpTrace;
|
||||
import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @Description: 自定义内存请求追踪存储
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/5/13 17:02
|
||||
*/
|
||||
public class CustomInMemoryHttpTraceRepository extends InMemoryHttpTraceRepository {
|
||||
|
||||
@Override
|
||||
public List<HttpTrace> findAll() {
|
||||
return super.findAll();
|
||||
}
|
||||
|
||||
public List<HttpTrace> findAll(String query) {
|
||||
List<HttpTrace> allTrace = super.findAll();
|
||||
if (null != allTrace && !allTrace.isEmpty()) {
|
||||
Stream<HttpTrace> stream = allTrace.stream();
|
||||
String[] params = query.split(",");
|
||||
stream = filter(params, stream);
|
||||
stream = sort(params, stream);
|
||||
allTrace = stream.collect(Collectors.toList());
|
||||
}
|
||||
return allTrace;
|
||||
}
|
||||
|
||||
private Stream<HttpTrace> sort(String[] params, Stream<HttpTrace> stream) {
|
||||
if (params.length < 2) {
|
||||
return stream;
|
||||
}
|
||||
String sortBy = params[1];
|
||||
String order;
|
||||
if (params.length > 2) {
|
||||
order = params[2];
|
||||
} else {
|
||||
order = "desc";
|
||||
}
|
||||
return stream.sorted((o1, o2) -> {
|
||||
int i = 0;
|
||||
if("timeTaken".equalsIgnoreCase(sortBy)) {
|
||||
i = o1.getTimeTaken().compareTo(o2.getTimeTaken());
|
||||
}else if("timestamp".equalsIgnoreCase(sortBy)){
|
||||
i = o1.getTimestamp().compareTo(o2.getTimestamp());
|
||||
}
|
||||
if("desc".equalsIgnoreCase(order)){
|
||||
i *=-1;
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
|
||||
private static Stream<HttpTrace> filter(String[] params, Stream<HttpTrace> stream) {
|
||||
if (params.length == 0) {
|
||||
return stream;
|
||||
}
|
||||
String statusQuery = params[0];
|
||||
if (null != statusQuery && !statusQuery.isEmpty()) {
|
||||
statusQuery = statusQuery.toLowerCase().trim();
|
||||
switch (statusQuery) {
|
||||
case "error":
|
||||
stream = stream.filter(httpTrace -> {
|
||||
int status = httpTrace.getResponse().getStatus();
|
||||
return status >= 404 && status < 501;
|
||||
});
|
||||
break;
|
||||
case "warn":
|
||||
stream = stream.filter(httpTrace -> {
|
||||
int status = httpTrace.getResponse().getStatus();
|
||||
return status >= 201 && status < 404;
|
||||
});
|
||||
break;
|
||||
case "success":
|
||||
stream = stream.filter(httpTrace -> {
|
||||
int status = httpTrace.getResponse().getStatus();
|
||||
return status == 200;
|
||||
});
|
||||
break;
|
||||
case "all":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package org.jeecg.modules.monitor.controller;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: 内存健康检查
|
||||
* @author: chenrui
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/sys/actuator/memory")
|
||||
public class ActuatorMemoryController {
|
||||
|
||||
|
||||
/**
|
||||
* 内存详情
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping("/info")
|
||||
public Result<?> getRedisInfo() throws Exception {
|
||||
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
JSONObject operatingSystemJson = JSONObject.parseObject(JSONObject.toJSONString(operatingSystemMXBean));
|
||||
long totalPhysicalMemory = operatingSystemJson.getLongValue("totalPhysicalMemorySize");
|
||||
long freePhysicalMemory = operatingSystemJson.getLongValue("freePhysicalMemorySize");
|
||||
long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory;
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
Map<String,Number> result = new HashMap<>();
|
||||
result.put("memory.physical.total", totalPhysicalMemory);
|
||||
result.put("memory.physical.used", freePhysicalMemory);
|
||||
result.put("memory.physical.free", usedPhysicalMemory);
|
||||
result.put("memory.physical.usage", NumberUtil.div(usedPhysicalMemory, totalPhysicalMemory));
|
||||
result.put("memory.runtime.total", runtime.totalMemory());
|
||||
result.put("memory.runtime.used", runtime.freeMemory());
|
||||
result.put("memory.runtime.max", runtime.totalMemory() - runtime.freeMemory());
|
||||
result.put("memory.runtime.free", runtime.maxMemory() - runtime.totalMemory() + runtime.freeMemory());
|
||||
result.put("memory.runtime.usage", NumberUtil.div(runtime.totalMemory() - runtime.freeMemory(), runtime.totalMemory()));
|
||||
return Result.ok(result);
|
||||
}
|
||||
|
||||
}
|
||||
@ -43,6 +43,21 @@ public class ActuatorRedisController {
|
||||
return Result.ok(infoList);
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240514 for:[QQYUN-9247]系统监控功能优化------------
|
||||
/**
|
||||
* Redis历史性能指标查询(过去一小时)
|
||||
* @return
|
||||
* @throws Exception
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:56
|
||||
*/
|
||||
@GetMapping(value = "/metrics/history")
|
||||
public Result<?> getMetricsHistory() throws Exception {
|
||||
Map<String,List<Map<String,Object>>> metricsHistory = this.redisService.getMetricsHistory();
|
||||
return Result.OK(metricsHistory);
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240514 for:[QQYUN-9247]系统监控功能优化------------
|
||||
|
||||
@GetMapping("/keysSize")
|
||||
public Map<String, Object> getKeysSize() throws Exception {
|
||||
return redisService.getKeysSize();
|
||||
|
||||
@ -44,4 +44,12 @@ public interface RedisService {
|
||||
* @throws RedisConnectException
|
||||
*/
|
||||
Map<String, JSONArray> getMapForReport(String type) throws RedisConnectException ;
|
||||
|
||||
/**
|
||||
* 获取历史性能指标
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:57
|
||||
*/
|
||||
Map<String, List<Map<String, Object>>> getMetricsHistory();
|
||||
}
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
package org.jeecg.modules.monitor.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ -12,13 +8,13 @@ import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.monitor.domain.RedisInfo;
|
||||
import org.jeecg.modules.monitor.exception.RedisConnectException;
|
||||
import org.jeecg.modules.monitor.service.RedisService;
|
||||
import org.springframework.cglib.beans.BeanMap;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -40,6 +36,11 @@ public class RedisServiceImpl implements RedisService {
|
||||
*/
|
||||
private static final String REDIS_MESSAGE = "3";
|
||||
|
||||
/**
|
||||
* redis性能信息记录
|
||||
*/
|
||||
private static final Map<String,List<Map<String, Object>>> REDIS_METRICS = new HashMap<>(2);
|
||||
|
||||
/**
|
||||
* Redis详细信息
|
||||
*/
|
||||
@ -126,4 +127,48 @@ public class RedisServiceImpl implements RedisService {
|
||||
mapJson.put("data",json);
|
||||
return mapJson;
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240514 for:[QQYUN-9247]系统监控功能优化------------
|
||||
/**
|
||||
* 获取历史性能指标
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:57
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<Map<String, Object>>> getMetricsHistory() {
|
||||
return REDIS_METRICS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录近一小时redis监控数据 <br/>
|
||||
* 60s一次,,记录存储keysize和内存
|
||||
* @throws RedisConnectException
|
||||
* @author chenrui
|
||||
* @date 2024/5/14 14:09
|
||||
*/
|
||||
@Scheduled(fixedRate = 60000)
|
||||
public void recordCustomMetric() throws RedisConnectException {
|
||||
List<Map<String, Object>> list= new ArrayList<>();
|
||||
if(REDIS_METRICS.containsKey("dbSize")){
|
||||
list = REDIS_METRICS.get("dbSize");
|
||||
}else{
|
||||
REDIS_METRICS.put("dbSize",list);
|
||||
}
|
||||
if(list.size()>60){
|
||||
list.remove(0);
|
||||
}
|
||||
list.add(getKeysSize());
|
||||
list= new ArrayList<>();
|
||||
if(REDIS_METRICS.containsKey("memory")){
|
||||
list = REDIS_METRICS.get("memory");
|
||||
}else{
|
||||
REDIS_METRICS.put("memory",list);
|
||||
}
|
||||
if(list.size()>60){
|
||||
list.remove(0);
|
||||
}
|
||||
list.add(getMemoryInfo());
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240514 for:[QQYUN-9247]系统监控功能优化------------
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ public class QuartzJobController {
|
||||
* @param quartzJob
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:add")
|
||||
@RequestMapping(value = "/add", method = RequestMethod.POST)
|
||||
public Result<?> add(@RequestBody QuartzJob quartzJob) {
|
||||
@ -93,7 +93,7 @@ public class QuartzJobController {
|
||||
* @param quartzJob
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:edit")
|
||||
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
|
||||
@ -112,7 +112,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:delete")
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
@ -131,7 +131,7 @@ public class QuartzJobController {
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:deleteBatch")
|
||||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
@ -151,7 +151,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:pause")
|
||||
@GetMapping(value = "/pause")
|
||||
@ApiOperation(value = "停止定时任务")
|
||||
@ -170,7 +170,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:resume")
|
||||
@GetMapping(value = "/resume")
|
||||
@ApiOperation(value = "启动定时任务")
|
||||
@ -271,7 +271,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequiresRoles("admin")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:execute")
|
||||
@GetMapping("/execute")
|
||||
public Result<?> execute(@RequestParam(name = "id", required = true) String id) {
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
package org.jeecg.modules.system.cache;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthCacheConfig;
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class AuthStateRedisCache implements AuthStateCache {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
private ValueOperations<String, String> valueOperations;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
valueOperations = redisTemplate.opsForValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入缓存,默认3分钟
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
*/
|
||||
@Override
|
||||
public void cache(String key, String value) {
|
||||
valueOperations.set(key, value, AuthCacheConfig.timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @param value 缓存内容
|
||||
* @param timeout 指定缓存过期时间(毫秒)
|
||||
*/
|
||||
@Override
|
||||
public void cache(String key, String value, long timeout) {
|
||||
valueOperations.set(key, value, timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存内容
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @return 缓存内容
|
||||
*/
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return valueOperations.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在key,如果对应key的value值已过期,也返回false
|
||||
*
|
||||
* @param key 缓存key
|
||||
* @return true:存在key,并且value没过期;false:key不存在或者已过期
|
||||
*/
|
||||
@Override
|
||||
public boolean containsKey(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.jeecg.modules.system.config;
|
||||
|
||||
import me.zhyd.oauth.cache.AuthStateCache;
|
||||
import org.jeecg.modules.system.cache.AuthStateRedisCache;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AuthStateConfiguration {
|
||||
|
||||
@Bean
|
||||
public AuthStateCache authStateCache() {
|
||||
return new AuthStateRedisCache();
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@ import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
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.*;
|
||||
|
||||
@ -243,7 +243,7 @@ public class LoginController {
|
||||
* 获取访问量
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("visitInfo")
|
||||
@GetMapping("/visitInfo")
|
||||
public Result<List<Map<String,Object>>> visitInfo() {
|
||||
Result<List<Map<String,Object>>> result = new Result<List<Map<String,Object>>>();
|
||||
Calendar calendar = new GregorianCalendar();
|
||||
@ -295,12 +295,14 @@ public class LoginController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/sms")
|
||||
public Result<String> sms(@RequestBody JSONObject jsonObject) {
|
||||
public Result<String> sms(@RequestBody JSONObject jsonObject,HttpServletRequest request) {
|
||||
Result<String> result = new Result<String>();
|
||||
String clientIp = IpUtils.getIpAddr(request);
|
||||
String mobile = jsonObject.get("mobile").toString();
|
||||
//手机号模式 登录模式: "2" 注册模式: "1"
|
||||
String smsmode=jsonObject.get("smsmode").toString();
|
||||
log.info(mobile);
|
||||
log.info("-------- IP:{}, 手机号:{},获取绑定验证码", clientIp, mobile);
|
||||
|
||||
if(oConvertUtils.isEmpty(mobile)){
|
||||
result.setMessage("手机号不允许为空!");
|
||||
result.setSuccess(false);
|
||||
@ -318,6 +320,17 @@ public class LoginController {
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
//增加 check防止恶意刷短信接口
|
||||
if(!DySmsLimit.canSendSms(clientIp)){
|
||||
log.warn("--------[警告] IP地址:{}, 短信接口请求太多-------", clientIp);
|
||||
result.setMessage("短信接口请求太多,请稍后再试!");
|
||||
result.setCode(CommonConstant.PHONE_SMS_FAIL_CODE);
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
//随机数
|
||||
String captcha = RandomUtil.randomNumbers(6);
|
||||
JSONObject obj = new JSONObject();
|
||||
@ -734,4 +747,82 @@ public class LoginController {
|
||||
redisUtil.set(key, ++val, 600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码接口(修改密码)
|
||||
*
|
||||
* @param jsonObject
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/sendChangePwdSms")
|
||||
public Result<String> sendSms(@RequestBody JSONObject jsonObject) {
|
||||
Result<String> result = new Result<>();
|
||||
String mobile = jsonObject.get("mobile").toString();
|
||||
if (oConvertUtils.isEmpty(mobile)) {
|
||||
result.setMessage("手机号不允许为空!");
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
String username = sysUser.getUsername();
|
||||
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
|
||||
query.eq(SysUser::getUsername, username).eq(SysUser::getPhone, mobile);
|
||||
SysUser user = sysUserService.getOne(query);
|
||||
if (null == user) {
|
||||
return Result.error("当前登录用户和绑定的手机号不匹配,无法修改密码!");
|
||||
}
|
||||
String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE + mobile;
|
||||
Object object = redisUtil.get(redisKey);
|
||||
if (object != null) {
|
||||
result.setMessage("验证码10分钟内,仍然有效!");
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
//随机数
|
||||
String captcha = RandomUtil.randomNumbers(6);
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("code", captcha);
|
||||
try {
|
||||
boolean b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.CHANGE_PASSWORD_TEMPLATE_CODE);
|
||||
if (!b) {
|
||||
result.setMessage("短信验证码发送失败,请稍后重试");
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
}
|
||||
//验证码5分钟内有效
|
||||
redisUtil.set(redisKey, captcha, 300);
|
||||
result.setSuccess(true);
|
||||
} catch (ClientException e) {
|
||||
e.printStackTrace();
|
||||
result.error500(" 短信接口未配置,请联系管理员!");
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 图形验证码
|
||||
* @param sysLoginModel
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/smsCheckCaptcha", method = RequestMethod.POST)
|
||||
public Result<?> smsCheckCaptcha(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request){
|
||||
String captcha = sysLoginModel.getCaptcha();
|
||||
String checkKey = sysLoginModel.getCheckKey();
|
||||
if(captcha==null){
|
||||
return Result.error("验证码无效");
|
||||
}
|
||||
String lowerCaseCaptcha = captcha.toLowerCase();
|
||||
String realKey = Md5Util.md5Encode(lowerCaseCaptcha+checkKey+jeecgBaseConfig.getSignatureSecret(), "utf-8");
|
||||
Object checkCode = redisUtil.get(realKey);
|
||||
if(checkCode==null || !checkCode.equals(lowerCaseCaptcha)) {
|
||||
return Result.error("验证码错误");
|
||||
}
|
||||
String clientIp = IpUtils.getIpAddr(request);
|
||||
//清空短信记录数量
|
||||
DySmsLimit.clearSendSmsCount(clientIp);
|
||||
redisUtil.removeAll(realKey);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
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;
|
||||
@ -18,10 +17,7 @@ import org.jeecg.common.constant.WebsocketConst;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.message.enums.RangeDateEnum;
|
||||
import org.jeecg.modules.message.websocket.WebSocket;
|
||||
@ -40,6 +36,7 @@ import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -51,7 +48,10 @@ import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@ -86,7 +86,9 @@ public class SysAnnouncementController {
|
||||
@Autowired
|
||||
@Lazy
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Autowired
|
||||
public RedisTemplate redisTemplate;
|
||||
|
||||
/**
|
||||
* QQYUN-5072【性能优化】线上通知消息打开有点慢
|
||||
*/
|
||||
@ -332,12 +334,19 @@ public class SysAnnouncementController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/listByUser", method = RequestMethod.GET)
|
||||
public Result<Map<String, Object>> listByUser(@RequestParam(required = false, defaultValue = "5") Integer pageSize) {
|
||||
public Result<Map<String, Object>> listByUser(@RequestParam(required = false, defaultValue = "5") Integer pageSize, HttpServletRequest request) {
|
||||
long start = System.currentTimeMillis();
|
||||
Result<Map<String,Object>> result = new Result<Map<String,Object>>();
|
||||
Map<String,Object> sysMsgMap = new HashMap(5);
|
||||
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
|
||||
String userId = sysUser.getId();
|
||||
|
||||
|
||||
//update-begin---author:scott ---date:2024-05-11 for:【性能优化】优化系统通知,只查近2个月的通知---
|
||||
// 获取上个月的第一天(只查近两个月的通知)
|
||||
Date lastMonthStartDay = DateRangeUtils.getLastMonthStartDay();
|
||||
log.info("-----查询近两个月收到的未读通知-----,近2月的第一天:{}", lastMonthStartDay);
|
||||
//update-end---author:scott ---date::2024-05-11 for:【性能优化】优化系统通知,只查近2个月的通知---
|
||||
|
||||
// //补推送数据(用户和通知的关系表)
|
||||
// completeNoteThreadPool.execute(()->{
|
||||
@ -347,19 +356,19 @@ public class SysAnnouncementController {
|
||||
// 2.查询用户未读的系统消息
|
||||
Page<SysAnnouncement> anntMsgList = new Page<SysAnnouncement>(0, pageSize);
|
||||
//通知公告消息
|
||||
anntMsgList = sysAnnouncementService.querySysCementPageByUserId(anntMsgList,userId,"1");
|
||||
anntMsgList = sysAnnouncementService.querySysCementPageByUserId(anntMsgList,userId,"1",null, lastMonthStartDay);
|
||||
sysMsgMap.put("anntMsgList", anntMsgList.getRecords());
|
||||
sysMsgMap.put("anntMsgTotal", anntMsgList.getTotal());
|
||||
|
||||
log.info("begin 获取用户系统公告 (通知)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
log.info("begin 获取用户近2个月的系统公告 (通知)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
//系统消息
|
||||
Page<SysAnnouncement> sysMsgList = new Page<SysAnnouncement>(0, pageSize);
|
||||
sysMsgList = sysAnnouncementService.querySysCementPageByUserId(sysMsgList,userId,"2");
|
||||
sysMsgList = sysAnnouncementService.querySysCementPageByUserId(sysMsgList,userId,"2",null, lastMonthStartDay);
|
||||
sysMsgMap.put("sysMsgList", sysMsgList.getRecords());
|
||||
sysMsgMap.put("sysMsgTotal", sysMsgList.getTotal());
|
||||
|
||||
log.info("end 获取用户系统公告 (系统消息)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
log.info("end 获取用户2个月的系统公告 (系统消息)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
result.setSuccess(true);
|
||||
result.setResult(sysMsgMap);
|
||||
@ -367,6 +376,24 @@ public class SysAnnouncementController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取未读消息通知数量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getUnreadMessageCount", method = RequestMethod.GET)
|
||||
public Result<Integer> getUnreadMessageCount(@RequestParam(required = false, defaultValue = "5") Integer pageSize, HttpServletRequest request) {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
String userId = sysUser.getId();
|
||||
|
||||
// 获取上个月的第一天(只查近两个月的通知)
|
||||
Date lastMonthStartDay = DateRangeUtils.getLastMonthStartDay();
|
||||
log.info(" ------查询近两个月收到的未读通知消息数量------,近2月的第一天:{}", lastMonthStartDay);
|
||||
Integer unreadMessageCount = sysAnnouncementService.getUnreadMessageCountByUserId(userId, lastMonthStartDay);
|
||||
return Result.ok(unreadMessageCount);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
@ -570,15 +597,37 @@ public class SysAnnouncementController {
|
||||
*/
|
||||
@GetMapping("/getLastAnnountTime")
|
||||
public Result<Page<SysAnnouncementSend>> getLastAnnountTime(@RequestParam(name = "userId") String userId){
|
||||
Result<Page<SysAnnouncementSend>> result = new Result<>();
|
||||
Page<SysAnnouncementSend> page = new Page<>(1,1);
|
||||
Result<Page<SysAnnouncementSend>> result = new Result<>();
|
||||
//----------------------------------------------------------------------------------------
|
||||
// step.1 此接口过慢,可以采用缓存一小时方案
|
||||
String keyString = String.format(CommonConstant.CACHE_KEY_USER_LAST_ANNOUNT_TIME_1HOUR, userId);
|
||||
if (redisTemplate.hasKey(keyString)) {
|
||||
log.info("[SysAnnouncementSend Redis] 通过Redis缓存查询用户最后一次收到系统通知时间,userId={}", userId);
|
||||
Page<SysAnnouncementSend> pageList = (Page<SysAnnouncementSend>) redisTemplate.opsForValue().get(keyString);
|
||||
result.setSuccess(true);
|
||||
result.setResult(pageList);
|
||||
return result;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
Page<SysAnnouncementSend> page = new Page<>(1,1);
|
||||
LambdaQueryWrapper<SysAnnouncementSend> query = new LambdaQueryWrapper<>();
|
||||
query.eq(SysAnnouncementSend::getUserId,userId);
|
||||
query.select(SysAnnouncementSend::getCreateTime);
|
||||
//只查询上个月和本月,的通知的数据
|
||||
query.ne(SysAnnouncementSend::getCreateTime, DateRangeUtils.getLastMonthStartDay());
|
||||
query.select(SysAnnouncementSend::getCreateTime); // 提高查询效率
|
||||
query.orderByDesc(SysAnnouncementSend::getCreateTime);
|
||||
Page<SysAnnouncementSend> pageList = sysAnnouncementSendService.page(page, query);
|
||||
result.setSuccess(true);
|
||||
result.setResult(pageList);
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
if (pageList != null && pageList.getSize() > 0) {
|
||||
// step.3 保留1小时redis缓存
|
||||
redisTemplate.opsForValue().set(keyString, pageList, 3600, TimeUnit.SECONDS);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
result.setSuccess(true);
|
||||
result.setResult(pageList);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -326,6 +326,13 @@ public class SysDictController {
|
||||
@RequestParam(name="condition") String condition,
|
||||
@RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) {
|
||||
Result<List<TreeSelectModel>> result = new Result<List<TreeSelectModel>>();
|
||||
|
||||
// 【QQYUN-9207】防止参数为空导致报错
|
||||
if (oConvertUtils.isEmpty(tableName) || oConvertUtils.isEmpty(text) || oConvertUtils.isEmpty(code)) {
|
||||
result.error500("字典Code格式不正确!");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 1.获取查询条件参数
|
||||
Map<String, String> query = null;
|
||||
if(oConvertUtils.isNotEmpty(condition)) {
|
||||
|
||||
@ -17,9 +17,11 @@ import cn.hutool.core.util.RandomUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.base.BaseMap;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
@ -83,6 +85,8 @@ public class SysRoleController {
|
||||
private ISysUserRoleService sysUserRoleService;
|
||||
@Autowired
|
||||
private BaseCommonService baseCommonService;
|
||||
@Autowired
|
||||
private JeecgRedisClient jeecgRedisClient;
|
||||
|
||||
/**
|
||||
* 分页列表查询 【系统角色,不做租户隔离】
|
||||
@ -124,7 +128,9 @@ public class SysRoleController {
|
||||
HttpServletRequest req) {
|
||||
Result<IPage<SysRole>> result = new Result<IPage<SysRole>>();
|
||||
//此接口必须通过租户来隔离查询
|
||||
role.setTenantId(oConvertUtils.getInt(!"0".equals(TenantContext.getTenant()) ? TenantContext.getTenant() : "", -1));
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
role.setTenantId(oConvertUtils.getInt(!"0".equals(TenantContext.getTenant()) ? TenantContext.getTenant() : "", -1));
|
||||
}
|
||||
|
||||
QueryWrapper<SysRole> queryWrapper = QueryGenerator.initQueryWrapper(role, req.getParameterMap());
|
||||
Page<SysRole> page = new Page<SysRole>(pageNo, pageSize);
|
||||
@ -145,7 +151,9 @@ public class SysRoleController {
|
||||
Result<SysRole> result = new Result<SysRole>();
|
||||
try {
|
||||
//开启多租户隔离,角色id自动生成10位
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
//update-begin---author:wangshuai---date:2024-05-23---for:【TV360X-42】角色新增时设置的编码,保存后不一致---
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL && oConvertUtils.isEmpty(role.getRoleCode())){
|
||||
//update-end---author:wangshuai---date:2024-05-23---for:【TV360X-42】角色新增时设置的编码,保存后不一致---
|
||||
role.setRoleCode(RandomUtil.randomString(10));
|
||||
}
|
||||
role.setCreateTime(new Date());
|
||||
@ -222,6 +230,7 @@ public class SysRoleController {
|
||||
//update-end---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】禁止删除 admin 角色---
|
||||
|
||||
sysRoleService.deleteRole(id);
|
||||
|
||||
return Result.ok("删除角色成功");
|
||||
}
|
||||
|
||||
@ -570,4 +579,5 @@ public class SysRoleController {
|
||||
result.setResult(sysRoleCountPage);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@ -351,10 +352,10 @@ public class SysTenantController {
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("/deletePackPermissions")
|
||||
@DeleteMapping("/deleteTenantPack")
|
||||
@RequiresPermissions("system:tenant:delete:pack")
|
||||
public Result<String> deletePackPermissions(@RequestParam(value = "ids") String ids) {
|
||||
sysTenantPackService.deletePackPermissions(ids);
|
||||
public Result<String> deleteTenantPack(@RequestParam(value = "ids") String ids) {
|
||||
sysTenantPackService.deleteTenantPack(ids);
|
||||
return Result.ok("删除租户产品包成功");
|
||||
}
|
||||
|
||||
@ -500,7 +501,7 @@ public class SysTenantController {
|
||||
Integer tenantId = sysTenantService.joinTenantByHouseNumber(sysTenant, sysUser.getId());
|
||||
Result<Integer> result = new Result<>();
|
||||
if(tenantId != 0){
|
||||
result.setMessage("申请租户成功");
|
||||
result.setMessage("申请加入组织成功");
|
||||
result.setSuccess(true);
|
||||
result.setResult(tenantId);
|
||||
return result;
|
||||
@ -935,4 +936,39 @@ public class SysTenantController {
|
||||
return Result.error("类型不匹配,禁止修改数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 目前只给敲敲云租户下删除用户使用
|
||||
*
|
||||
* 根据密码删除用户
|
||||
*/
|
||||
@DeleteMapping("/deleteUserByPassword")
|
||||
public Result<String> deleteUserByPassword(@RequestBody SysUser sysUser,HttpServletRequest request){
|
||||
Integer tenantId = oConvertUtils.getInteger(TokenUtils.getTenantIdByRequest(request), null);
|
||||
sysTenantService.deleteUserByPassword(sysUser, tenantId);
|
||||
return Result.ok("删除用户成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的所有有效租户【知识库专用接口】
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getCurrentUserTenantForFile", method = RequestMethod.GET)
|
||||
public Result<Map<String,Object>> getCurrentUserTenantForFile() {
|
||||
Result<Map<String,Object>> result = new Result<Map<String,Object>>();
|
||||
try {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
List<SysTenant> tenantList = sysTenantService.getTenantListByUserId(sysUser.getId());
|
||||
Map<String,Object> map = new HashMap<>(5);
|
||||
//在开启saas租户隔离的时候并且租户数据不为空,则返回租户信息
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL && CollectionUtil.isNotEmpty(tenantList)) {
|
||||
map.put("list", tenantList);
|
||||
}
|
||||
result.setSuccess(true);
|
||||
result.setResult(map);
|
||||
}catch(Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
result.error500("查询失败!");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ 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;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -17,15 +16,17 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
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;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
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.model.DepartIdModel;
|
||||
import org.jeecg.modules.system.model.SysUserSysDepartModel;
|
||||
@ -101,6 +102,9 @@ public class SysUserController {
|
||||
@Autowired
|
||||
private ISysUserTenantService userTenantService;
|
||||
|
||||
@Autowired
|
||||
private JeecgRedisClient jeecgRedisClient;
|
||||
|
||||
/**
|
||||
* 获取租户下用户数据(支持租户隔离)
|
||||
* @param user
|
||||
@ -1129,7 +1133,7 @@ public class SysUserController {
|
||||
}
|
||||
sysUser = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername,username).eq(SysUser::getPhone,phone));
|
||||
if (sysUser == null) {
|
||||
result.setMessage("未找到用户!");
|
||||
result.setMessage("当前登录用户和绑定的手机号不匹配,无法修改密码!");
|
||||
result.setSuccess(false);
|
||||
return result;
|
||||
} else {
|
||||
@ -1143,6 +1147,8 @@ public class SysUserController {
|
||||
//update-end---author:wangshuai ---date:20220316 for:[VUEN-234]密码重置添加敏感日志------------
|
||||
result.setSuccess(true);
|
||||
result.setMessage("密码重置完成!");
|
||||
//修改完密码后清空redis
|
||||
redisUtil.removeAll(redisKey);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1551,15 +1557,15 @@ public class SysUserController {
|
||||
@RequestParam(name = "departId", required = false) String departId,
|
||||
@RequestParam(name = "roleId", required = false) String roleId,
|
||||
@RequestParam(name="keyword",required=false) String keyword,
|
||||
@RequestParam(name="excludeUserIdList",required = false) String excludeUserIdList) {
|
||||
@RequestParam(name="excludeUserIdList",required = false) String excludeUserIdList,
|
||||
HttpServletRequest req) {
|
||||
//------------------------------------------------------------------------------------------------
|
||||
Integer tenantId = null;
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
String tenantStr = TenantContext.getTenant();
|
||||
if(oConvertUtils.isNotEmpty(tenantStr)){
|
||||
tenantId = Integer.parseInt(tenantStr);
|
||||
}
|
||||
tenantId = oConvertUtils.getInteger(tenantStr, oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(req), -1));
|
||||
log.info("---------简流中选择用户接口,通过租户筛选,租户ID={}", tenantId);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
IPage<SysUser> pageList = sysUserDepartService.getUserInformation(tenantId, departId,roleId, keyword, pageSize, pageNo,excludeUserIdList);
|
||||
|
||||
@ -61,8 +61,13 @@ public class ThirdAppController {
|
||||
@GetMapping("/getEnabledType")
|
||||
public Result getEnabledType() {
|
||||
Map<String, Boolean> enabledMap = new HashMap(5);
|
||||
//update-begin---author:wangshuai ---date:20230224 for:[QQYUN-3440]通过租户模式隔离 ------------
|
||||
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
int tenantId;
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), -1);
|
||||
} else {
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
}
|
||||
//查询当前租户下的第三方配置
|
||||
List<SysThirdAppConfig> list = appConfigService.getThirdConfigListByThirdType(tenantId);
|
||||
//钉钉是否已配置
|
||||
|
||||
@ -74,6 +74,8 @@ public class SysDepart implements Serializable {
|
||||
private String delFlag;
|
||||
/**对接企业微信的ID*/
|
||||
private String qywxIdentifier;
|
||||
/**对接钉钉的部门ID*/
|
||||
private String dingIdentifier;
|
||||
/**创建人*/
|
||||
private String createBy;
|
||||
/**创建日期*/
|
||||
|
||||
@ -108,6 +108,12 @@ public class SysLog implements Serializable {
|
||||
*/
|
||||
@Dict(dicCode = "operate_type")
|
||||
private Integer operateType;
|
||||
|
||||
/**
|
||||
* 客户终端类型 pc:电脑端 app:手机端 h5:移动网页端
|
||||
*/
|
||||
@Dict(dicCode = "client_type")
|
||||
private String clientType;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
|
||||
@ -26,7 +26,16 @@ public interface SysAnnouncementMapper extends BaseMapper<SysAnnouncement> {
|
||||
* @param msgCategory 消息类型
|
||||
* @return
|
||||
*/
|
||||
List<SysAnnouncement> querySysCementListByUserId(Page<SysAnnouncement> page, @Param("userId")String userId,@Param("msgCategory")String msgCategory);
|
||||
List<SysAnnouncement> querySysCementListByUserId(Page<SysAnnouncement> page, @Param("userId")String userId,@Param("msgCategory")String msgCategory,
|
||||
@Param("tenantId")Integer tenantId, @Param("beginDate")Date beginDate);
|
||||
|
||||
/**
|
||||
* 获取用户未读消息数量
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return
|
||||
*/
|
||||
Integer getUnreadMessageCountByUserId(@Param("userId") String userId, @Param("beginDate") Date beginDate);
|
||||
|
||||
/**
|
||||
* 分页查询全部消息列表
|
||||
|
||||
@ -40,6 +40,14 @@ public interface SysDepartMapper extends BaseMapper<SysDepart> {
|
||||
* @return
|
||||
*/
|
||||
public List<SysDepart> queryDepartsByUsername(@Param("username") String username);
|
||||
|
||||
/**
|
||||
* 根据用户名查询部门
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
public List<String> queryDepartsByUserId(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 通过部门编码获取部门id
|
||||
|
||||
@ -20,4 +20,12 @@ public interface SysPackPermissionMapper extends BaseMapper<SysPackPermission> {
|
||||
* @return
|
||||
*/
|
||||
List<String> getPermissionsByPackId(@Param("packId") String packId);
|
||||
|
||||
/**
|
||||
* 删除产品包对应的菜单权限
|
||||
*
|
||||
* @param tenantIdList
|
||||
*/
|
||||
void deletePackPermByTenantIds(@Param("tenantIdList") List<Integer> tenantIdList);
|
||||
|
||||
}
|
||||
|
||||
@ -37,7 +37,16 @@ public interface SysRoleMapper extends BaseMapper<SysRole> {
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
SysRole getRoleNoTenant(@Param("roleCode") String roleCode);
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户id查询用户拥有的角色Code
|
||||
*
|
||||
* @param userId
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
List<SysRole> getRoleCodeListByUserId(@Param("userId") String userId, @Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 删除角色与用户关系
|
||||
* @Author scott
|
||||
|
||||
@ -127,4 +127,11 @@ public interface SysTenantMapper extends BaseMapper<SysTenant> {
|
||||
*/
|
||||
@Select("select count(1) from sys_tenant where id = #{tenantId} and del_flag = 0")
|
||||
Long tenantIzExist(@Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 根据用户id获取租户
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<SysTenant> getTenantListByUserId(@Param("userId") String userId);
|
||||
}
|
||||
|
||||
@ -14,4 +14,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
*/
|
||||
public interface SysTenantPackMapper extends BaseMapper<SysTenantPack> {
|
||||
|
||||
/**
|
||||
* 删除租户产品包
|
||||
*
|
||||
* @param tenantIdList
|
||||
*/
|
||||
void deletePackByTenantIds(@Param("tenantIdList") List<Integer> tenantIdList);
|
||||
}
|
||||
|
||||
@ -31,5 +31,17 @@ public interface SysTenantPackUserMapper extends BaseMapper<SysTenantPackUser> {
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
Long izHaveBuyAuth(@Param("userId") String userId, @Param("tenantId") String tenantId);
|
||||
Long izHaveBuyAuth(@Param("userId") String userId, @Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 根据租户id 删除租户产品包下的 用户
|
||||
* @param tenantId
|
||||
*/
|
||||
void deletePackUserByTenantId(@Param("tenantId") Integer tenantId, @Param("userIds") List<String> userIds);
|
||||
|
||||
/**
|
||||
* 根据多个租户id 删除租户产品包下的 用户
|
||||
* @param
|
||||
*/
|
||||
void deletePackUserByTenantIds(@Param("tenantIds") List<Integer> tenantIds);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
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.SysUserSysDepartModel;
|
||||
@ -27,6 +28,13 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
* @return
|
||||
*/
|
||||
public SysUser getUserByName(@Param("username") String username);
|
||||
|
||||
/**
|
||||
* 通过用户账号查询用户Id
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
public String getUserIdByName(@Param("username") String username);
|
||||
|
||||
/**
|
||||
* 根据部门Id查询用户信息
|
||||
@ -205,4 +213,13 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
* @return
|
||||
*/
|
||||
List<SysUser> getUserByDepartsTenantId(@Param("departIds") List<String> departIds,@Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 根据用户名和手机号获取用户
|
||||
* @param phone
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
@Select("select id,phone from sys_user where phone = #{phone} and username = #{username}")
|
||||
SysUser getUserByNameAndPhone(@Param("phone") String phone, @Param("username") String username);
|
||||
}
|
||||
|
||||
@ -23,6 +23,14 @@ public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
|
||||
*/
|
||||
@Select("select role_code from sys_role where id in (select role_id from sys_user_role where user_id = (select id from sys_user where username=#{username}))")
|
||||
List<String> getRoleByUserName(@Param("username") String username);
|
||||
|
||||
/**
|
||||
* 通过用户账号查询角色集合
|
||||
* @param userId 用户id
|
||||
* @return List<String>
|
||||
*/
|
||||
@Select("select role_code from sys_role where id in (select role_id from sys_user_role where user_id = #{userId})")
|
||||
List<String> getRoleCodeByUserId(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 通过用户账号查询角色Id集合
|
||||
|
||||
@ -166,4 +166,12 @@ public interface SysUserTenantMapper extends BaseMapper<SysUserTenant> {
|
||||
* @return
|
||||
*/
|
||||
List<JwUserDepartVo> getUsersByTenantIdAndName(@Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 根据多个用户id获取租户id
|
||||
*
|
||||
* @param userIds
|
||||
* @return
|
||||
*/
|
||||
List<Integer> getTenantIdsByUserIds(@Param("userIds") List<String> userIds);
|
||||
}
|
||||
|
||||
@ -37,11 +37,19 @@
|
||||
where send_status = '1'
|
||||
and del_flag = '0'
|
||||
and msg_category = #{msgCategory}
|
||||
and id IN ( select annt_id from sys_announcement_send where user_id = #{userId} and read_flag = 0)
|
||||
and create_time >= #{beginDate}
|
||||
<if test="tenantId!=null and tenantId != 0">
|
||||
and tenant_id = #{tenantId}
|
||||
</if>
|
||||
and id IN ( select annt_id from sys_announcement_send where user_id = #{userId} and read_flag = 0 and create_time >= #{beginDate})
|
||||
order by create_time DESC
|
||||
</select>
|
||||
|
||||
|
||||
<!-- 获取用户未读消息数量 -->
|
||||
<select id="getUnreadMessageCountByUserId" resultType="java.lang.Integer">
|
||||
select count(1) from sys_announcement_send where user_id = #{userId} and read_flag = 0 and create_time >= #{beginDate}
|
||||
</select>
|
||||
|
||||
<!-- 查询消息记录 -->
|
||||
<select id="queryAllMessageList" resultMap="SysAnnouncement">
|
||||
select
|
||||
@ -72,6 +80,7 @@
|
||||
|
||||
<if test="beginDate!=null">
|
||||
and a.create_time >= #{beginDate}
|
||||
and b.create_time >= #{beginDate}
|
||||
</if>
|
||||
<if test="endDate!=null">
|
||||
and a.create_time <= #{endDate}
|
||||
|
||||
@ -20,6 +20,17 @@
|
||||
)
|
||||
)
|
||||
</select>
|
||||
|
||||
<!-- 根据username查询所拥有的部门 -->
|
||||
<select id="queryDepartsByUserId" parameterType="String" resultType="java.lang.String">
|
||||
SELECT id
|
||||
FROM sys_depart
|
||||
WHERE id IN (
|
||||
SELECT dep_id
|
||||
FROM sys_user_depart
|
||||
WHERE user_id = #{userId}
|
||||
)
|
||||
</select>
|
||||
|
||||
<!-- 根据部门Id查询,当前和下级所有部门IDS -->
|
||||
<select id="getSubDepIdsByDepId" resultType="java.lang.String">
|
||||
|
||||
@ -7,5 +7,15 @@
|
||||
where
|
||||
pack_id = #{packId}
|
||||
</select>
|
||||
|
||||
|
||||
<!--删除产品包对应的菜单权限-->
|
||||
<delete id="deletePackPermByTenantIds">
|
||||
delete from sys_tenant_pack_perms
|
||||
where pack_id in(
|
||||
select id from sys_tenant_pack where tenant_id in
|
||||
<foreach collection="tenantIdList" index="index" item="tenantId" open="(" separator="," close=")">
|
||||
#{tenantId}
|
||||
</foreach>
|
||||
)
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -136,6 +136,7 @@
|
||||
SELECT distinct a.permission_id
|
||||
FROM sys_tenant_pack_perms a
|
||||
INNER JOIN sys_tenant_pack b ON a.pack_id = b.id AND b.STATUS = '1'
|
||||
INNER JOIN sys_tenant st ON st.id = b.tenant_id and st.del_flag = 0
|
||||
INNER JOIN sys_tenant_pack_user c ON c.pack_id = b.id AND c.STATUS = '1' AND c.user_id = #{userId,jdbcType=VARCHAR}
|
||||
)
|
||||
and p.del_flag = 0
|
||||
|
||||
@ -20,5 +20,14 @@
|
||||
SELECT * from sys_role
|
||||
WHERE role_code = #{roleCode}
|
||||
</select>
|
||||
|
||||
|
||||
<!-- 根据用户id查询用户拥有的角色 -->
|
||||
<select id="getRoleCodeListByUserId" resultType="org.jeecg.modules.system.entity.SysRole">
|
||||
SELECT id, role_code from sys_role
|
||||
WHERE id in (SELECT role_id from sys_user_role WHERE user_id = #{userId})
|
||||
<if test="tenantId != null">
|
||||
AND tenant_id = #{tenantId}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -132,5 +132,12 @@
|
||||
and a.tenant_id = #{tenantId}
|
||||
and b.user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<!--根据用户id获取租户信息-->
|
||||
<select id="getTenantListByUserId" resultType="org.jeecg.modules.system.entity.SysTenant">
|
||||
SELECT st.id,st.name FROM sys_tenant st
|
||||
LEFT JOIN sys_user_tenant sut on st.id= sut.tenant_id and st.status = 1 and sut.status='1'
|
||||
WHERE sut.user_id = #{userId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -2,4 +2,12 @@
|
||||
<!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.SysTenantPackMapper">
|
||||
|
||||
<!--删除租户产品包-->
|
||||
<delete id="deletePackByTenantIds">
|
||||
delete from sys_tenant_pack
|
||||
where tenant_id in
|
||||
<foreach collection="tenantIdList" index="index" item="tenantId" open="(" separator="," close=")">
|
||||
#{tenantId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -23,4 +23,22 @@
|
||||
and stpu.user_id = #{userId}
|
||||
and stp.pack_code in('superAdmin','accountAdmin')
|
||||
</select>
|
||||
|
||||
<!--根据租户id 删除租户产品包下的 用户-->
|
||||
<delete id="deletePackUserByTenantId">
|
||||
delete from sys_tenant_pack_user where tenant_id = #{tenantId}
|
||||
and user_id in
|
||||
<foreach collection="userIds" index="index" item="userId" open="(" separator="," close=")">
|
||||
#{userId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<!--根据多个租户id 删除租户产品包下的 用户-->
|
||||
<delete id="deletePackUserByTenantIds">
|
||||
delete from sys_tenant_pack_user
|
||||
where tenant_id in
|
||||
<foreach collection="tenantIds" index="index" item="tenantId" open="(" separator="," close=")">
|
||||
#{tenantId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
@ -6,6 +6,11 @@
|
||||
<select id="getUserByName" resultType="org.jeecg.modules.system.entity.SysUser">
|
||||
select * from sys_user where username = #{username} and del_flag = 0
|
||||
</select>
|
||||
|
||||
<!-- 根据用户名查询用户ID -->
|
||||
<select id="getUserIdByName" resultType="String">
|
||||
select id from sys_user where username = #{username} and del_flag = 0
|
||||
</select>
|
||||
|
||||
<!-- 根据部门Id查询 -->
|
||||
<select id="getUserByDepId" resultType="org.jeecg.modules.system.entity.SysUser">
|
||||
@ -231,7 +236,7 @@
|
||||
|
||||
<!--获取租户下的用户离职列表信息-->
|
||||
<select id="getTenantQuitList" resultType="org.jeecg.modules.system.entity.SysUser">
|
||||
select su.id,su.username,su.realname,su.sex,su.avatar from sys_user su
|
||||
select su.id,su.username,su.realname,su.sex,su.avatar,su.create_time,sut.create_by from sys_user su
|
||||
join sys_user_tenant sut on sut.user_id = su.id and sut.status = '2'
|
||||
where
|
||||
su.status = 1
|
||||
|
||||
@ -43,7 +43,15 @@ public interface ISysAnnouncementService extends IService<SysAnnouncement> {
|
||||
* @param msgCategory 消息类型
|
||||
* @return Page<SysAnnouncement>
|
||||
*/
|
||||
public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory);
|
||||
public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory, Integer tenantId, Date beginDate);
|
||||
|
||||
/**
|
||||
* 获取用户未读消息数量
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return
|
||||
*/
|
||||
public Integer getUnreadMessageCountByUserId(String userId, Date beginDate);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -103,6 +103,14 @@ public interface ISysDepartService extends IService<SysDepart>{
|
||||
* @return
|
||||
*/
|
||||
List<SysDepart> queryDepartsByUsername(String username);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询部门
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> queryDepartsByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 根据部门id批量删除并删除其可能存在的子级部门
|
||||
|
||||
@ -37,7 +37,7 @@ public interface ISysTenantPackService extends IService<SysTenantPack> {
|
||||
* 删除租户产品包
|
||||
* @param ids
|
||||
*/
|
||||
void deletePackPermissions(String ids);
|
||||
void deleteTenantPack(String ids);
|
||||
|
||||
/**
|
||||
* 退出租户
|
||||
|
||||
@ -217,4 +217,19 @@ public interface ISysTenantService extends IService<SysTenant> {
|
||||
* @param content
|
||||
*/
|
||||
void sendMsgForAgreeAndRefuseJoin(SysUser user, String content);
|
||||
|
||||
/**
|
||||
* 根据密码删除当前用户
|
||||
*
|
||||
* @param sysUser
|
||||
* @param tenantId
|
||||
*/
|
||||
void deleteUserByPassword(SysUser sysUser, Integer tenantId);
|
||||
|
||||
/**
|
||||
* 根据用户id获取租户信息
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<SysTenant> getTenantListByUserId(String userId);
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @param user
|
||||
* @param roles
|
||||
*/
|
||||
public void addUserWithRole(SysUser user,String roles);
|
||||
public void addUserWithRole(SysUser user, String roles);
|
||||
|
||||
|
||||
/**
|
||||
@ -97,7 +97,7 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @param user
|
||||
* @param roles
|
||||
*/
|
||||
public void editUserWithRole(SysUser user,String roles);
|
||||
public void editUserWithRole(SysUser user, String roles);
|
||||
|
||||
/**
|
||||
* 获取用户的授权角色
|
||||
@ -113,7 +113,7 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @param version 前端UI版本
|
||||
* @return
|
||||
*/
|
||||
public SysRoleIndex getDynamicIndexByUserRole(String username,String version);
|
||||
public SysRoleIndex getDynamicIndexByUserRole(String username, String version);
|
||||
|
||||
/**
|
||||
* 查询用户信息包括 部门信息
|
||||
@ -177,7 +177,7 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @param username 用户账户名称
|
||||
* @return
|
||||
*/
|
||||
public IPage<SysUser> getUserByRoleId(Page<SysUser> page,String roleId, String username);
|
||||
public IPage<SysUser> getUserByRoleId(Page<SysUser> page, String roleId, String username);
|
||||
|
||||
/**
|
||||
* 通过用户名获取用户角色集合
|
||||
@ -186,6 +186,14 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @return 角色集合
|
||||
*/
|
||||
Set<String> getUserRolesSet(String username);
|
||||
|
||||
/**
|
||||
* 通过用户名获取用户角色集合
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 角色集合
|
||||
*/
|
||||
Set<String> getUserRoleSetById(String userId);
|
||||
|
||||
/**
|
||||
* 通过用户名获取用户权限集合
|
||||
@ -347,7 +355,7 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @param sysUser
|
||||
* @return
|
||||
*/
|
||||
Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result);
|
||||
Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result);
|
||||
|
||||
//--- author:taoyan date:20221231 for: QQYUN-3515【应用】应用下的组织机构管理功能,细节实现 ---
|
||||
/**
|
||||
@ -417,4 +425,21 @@ public interface ISysUserService extends IService<SysUser> {
|
||||
* @param ids
|
||||
*/
|
||||
void checkUserAdminRejectDel(String ids);
|
||||
|
||||
/**
|
||||
* 修改手机号
|
||||
*
|
||||
* @param json
|
||||
* @param username
|
||||
*/
|
||||
void changePhone(JSONObject json, String username);
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param jsonObject
|
||||
* @param username 用户名
|
||||
* @param ipAddress ip地址
|
||||
*/
|
||||
void sendChangePhoneSms(JSONObject jsonObject, String username, String ipAddress);
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.DateRangeUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.system.entity.SysAnnouncement;
|
||||
@ -139,14 +140,19 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory) {
|
||||
public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory, Integer tenantId, Date beginDate) {
|
||||
if (page.getSize() == -1) {
|
||||
return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(null, userId, msgCategory));
|
||||
return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(null, userId, msgCategory,tenantId,beginDate));
|
||||
} else {
|
||||
return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(page, userId, msgCategory));
|
||||
return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(page, userId, msgCategory,tenantId,beginDate));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getUnreadMessageCountByUserId(String userId, Date beginDate) {
|
||||
return sysAnnouncementMapper.getUnreadMessageCountByUserId(userId, beginDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeAnnouncementSendInfo() {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
|
||||
@ -157,6 +157,18 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames=CommonConstant.SYS_USER_ID_MAPPING_CACHE, key="#username")
|
||||
public String getUserIdByName(String username) {
|
||||
if (oConvertUtils.isEmpty(username)) {
|
||||
return null;
|
||||
}
|
||||
String userId = userMapper.getUserIdByName(username);
|
||||
return userId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String translateDictFromTable(String table, String text, String code, String key) {
|
||||
return sysDictService.queryTableDictTextByKey(table, text, code, key);
|
||||
@ -265,9 +277,12 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
// }
|
||||
|
||||
if(user!=null) {
|
||||
info.setSysUserId(user.getId());
|
||||
info.setSysUserCode(user.getUsername());
|
||||
info.setSysUserName(user.getRealname());
|
||||
info.setSysOrgCode(user.getOrgCode());
|
||||
info.setSysOrgId(user.getOrgId());
|
||||
info.setSysRoleCode(user.getRoleCode());
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
@ -311,6 +326,11 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
public List<String> getRolesByUsername(String username) {
|
||||
return sysUserRoleMapper.getRoleByUserName(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRolesByUserId(String userId) {
|
||||
return sysUserRoleMapper.getRoleCodeByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDepartIdsByUsername(String username) {
|
||||
@ -321,6 +341,11 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDepartIdsByUserId(String userId) {
|
||||
return sysDepartService.queryDepartsByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDepartParentIdsByUsername(String username) {
|
||||
@ -1092,6 +1117,20 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
log.info("-------通过数据库读取用户拥有的角色Rules------username: " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
|
||||
return new HashSet<>(roles);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询用户拥有的角色集合
|
||||
* @param useId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getUserRoleSetById(String useId) {
|
||||
// 查询用户拥有的角色集合
|
||||
List<String> roles = sysUserRoleMapper.getRoleCodeByUserId(useId);
|
||||
log.info("-------通过数据库读取用户拥有的角色Rules------useId: " + useId + ",Roles size: " + (roles == null ? 0 : roles.size()));
|
||||
return new HashSet<>(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户拥有的权限集合
|
||||
@ -1175,6 +1214,11 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
return getUserRoleSet(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryUserRolesById(String userId) {
|
||||
return getUserRoleSetById(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户拥有的权限集合 common api 里面的接口实现
|
||||
* @param userId
|
||||
@ -1588,25 +1632,33 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
||||
|
||||
@Override
|
||||
public void saveDataLog(DataLogDTO dataLogDto) {
|
||||
SysDataLog entity = new SysDataLog();
|
||||
entity.setDataTable(dataLogDto.getTableName());
|
||||
entity.setDataId(dataLogDto.getDataId());
|
||||
entity.setDataContent(dataLogDto.getContent());
|
||||
entity.setType(dataLogDto.getType());
|
||||
entity.setDataVersion("1");
|
||||
if (oConvertUtils.isNotEmpty(dataLogDto.getCreateName())) {
|
||||
entity.setCreateBy(dataLogDto.getCreateName());
|
||||
} else {
|
||||
entity.autoSetCreateName();
|
||||
try {
|
||||
SysDataLog entity = new SysDataLog();
|
||||
entity.setDataTable(dataLogDto.getTableName());
|
||||
entity.setDataId(dataLogDto.getDataId());
|
||||
entity.setDataContent(dataLogDto.getContent());
|
||||
entity.setType(dataLogDto.getType());
|
||||
entity.setDataVersion("1");
|
||||
if (oConvertUtils.isNotEmpty(dataLogDto.getCreateName())) {
|
||||
entity.setCreateBy(dataLogDto.getCreateName());
|
||||
} else {
|
||||
entity.autoSetCreateName();
|
||||
}
|
||||
sysDataLogService.save(entity);
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
//e.printStackTrace();
|
||||
}
|
||||
sysDataLogService.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAvatar(LoginUser loginUser) {
|
||||
SysUser sysUser = new SysUser();
|
||||
BeanUtils.copyProperties(loginUser, sysUser);
|
||||
sysUserService.updateById(sysUser);
|
||||
SysUser sysUser = new SysUser();
|
||||
// 创建UpdateWrapper对象
|
||||
UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", loginUser.getId()); // 设置更新条件
|
||||
sysUser.setAvatar(loginUser.getAvatar()); // 设置要更新的字段
|
||||
sysUserService.update(sysUser, updateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -489,6 +489,12 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
|
||||
public List<SysDepart> queryDepartsByUsername(String username) {
|
||||
return baseMapper.queryDepartsByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> queryDepartsByUserId(String userId) {
|
||||
List<String> list = baseMapper.queryDepartsByUserId(userId);
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户所负责部门ids获取父级部门编码
|
||||
|
||||
@ -84,8 +84,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
|
||||
// 2.SQL注入check(只限制非法串改数据库)
|
||||
//关联表字典(举例:sys_user,realname,id)
|
||||
SqlInjectionUtil.filterContent(table);
|
||||
SqlInjectionUtil.filterContent(fieldName);
|
||||
SqlInjectionUtil.filterContentMulti(table, fieldName);
|
||||
|
||||
String checkSql = table + SymbolConstant.COMMA + fieldName + SymbolConstant.COMMA;
|
||||
// 【QQYUN-6533】表字典白名单check
|
||||
@ -251,7 +250,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
}
|
||||
|
||||
// 3.SQL注入check
|
||||
SqlInjectionUtil.filterContent(table, text, code);
|
||||
SqlInjectionUtil.filterContentMulti(table, text, code);
|
||||
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
|
||||
|
||||
// 4.针对采用 ${}写法的表名和字段进行转义和check
|
||||
@ -269,8 +268,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
|
||||
// 1.SQL注入校验(只限制非法串改数据库)
|
||||
SqlInjectionUtil.specialFilterContentForDictSql(table);
|
||||
SqlInjectionUtil.filterContent(text);
|
||||
SqlInjectionUtil.filterContent(code);
|
||||
SqlInjectionUtil.filterContentMulti(text, code);
|
||||
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
|
||||
|
||||
String str = table+","+text+","+code;
|
||||
@ -313,7 +311,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
return null;
|
||||
}
|
||||
// 2.sql注入check
|
||||
SqlInjectionUtil.filterContent(table, text, code, key);
|
||||
SqlInjectionUtil.filterContentMulti(table, text, code, key);
|
||||
|
||||
// 3.针对采用 ${}写法的表名和字段进行转义和check
|
||||
table = SqlInjectionUtil.getSqlInjectTableName(table);
|
||||
@ -358,7 +356,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
}
|
||||
|
||||
// 3.SQL注入check
|
||||
SqlInjectionUtil.filterContent(table, text, code);
|
||||
SqlInjectionUtil.filterContentMulti(table, text, code);
|
||||
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
|
||||
|
||||
// 4.针对采用 ${}写法的表名和字段进行转义和check
|
||||
@ -420,7 +418,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
}
|
||||
|
||||
// 2.SQL注入check
|
||||
SqlInjectionUtil.filterContent(table, text, code);
|
||||
SqlInjectionUtil.filterContentMulti(table, text, code);
|
||||
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
|
||||
|
||||
String str = table+","+text+","+code;
|
||||
@ -626,9 +624,15 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
pidField = SqlInjectionUtil.getSqlInjectField(pidField);
|
||||
hasChildField = SqlInjectionUtil.getSqlInjectField(hasChildField);
|
||||
|
||||
if(oConvertUtils.isEmpty(text) || oConvertUtils.isEmpty(code)){
|
||||
log.warn("text={},code={}", text, code);
|
||||
log.warn("加载树字典参数有误,text和code不允许为空!");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2.检测最终SQL是否存在SQL注入风险
|
||||
String dictCode = table + "," + text + "," + code;
|
||||
SqlInjectionUtil.filterContent(dictCode);
|
||||
SqlInjectionUtil.filterContentMulti(dictCode);
|
||||
|
||||
// 【QQYUN-6533】表字典白名单check
|
||||
sysBaseAPI.dictTableWhiteListCheckByDict(table, text, code);
|
||||
@ -697,7 +701,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
||||
}
|
||||
|
||||
// 3.SQL注入check
|
||||
SqlInjectionUtil.filterContent(dictCode);
|
||||
SqlInjectionUtil.filterContentMulti(dictCode);
|
||||
|
||||
Page<DictModel> pageList = baseMapper.queryDictTablePageList(page, query);
|
||||
return pageList.getRecords();
|
||||
|
||||
@ -113,10 +113,12 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deletePackPermissions(String ids) {
|
||||
public void deleteTenantPack(String ids) {
|
||||
String[] idsArray = ids.split(SymbolConstant.COMMA);
|
||||
for (String id : idsArray) {
|
||||
this.deletePackPermission(id,null);
|
||||
//删除产品包下面的用户
|
||||
this.deletePackUser(id);
|
||||
sysTenantPackMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
@ -251,4 +253,13 @@ public class SysTenantPackServiceImpl extends ServiceImpl<SysTenantPackMapper, S
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除产品包下面的用户
|
||||
* @param packId
|
||||
*/
|
||||
private void deletePackUser(String packId) {
|
||||
LambdaQueryWrapper<SysTenantPackUser> query = new LambdaQueryWrapper<>();
|
||||
query.eq(SysTenantPackUser::getPackId, packId);
|
||||
sysTenantPackUserMapper.delete(query);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.dto.message.BusMessageDTO;
|
||||
import org.jeecg.common.api.dto.message.MessageDTO;
|
||||
@ -14,18 +15,18 @@ import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.constant.CacheConstant;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.exception.JeecgBootBizTipException;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.PasswordUtil;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.constant.enums.SysAnnmentTypeEnum;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.aop.TenantLog;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.mapper.SysTenantMapper;
|
||||
import org.jeecg.modules.system.mapper.SysTenantPackUserMapper;
|
||||
import org.jeecg.modules.system.mapper.SysUserDepartMapper;
|
||||
import org.jeecg.modules.system.mapper.SysUserTenantMapper;
|
||||
import org.jeecg.modules.system.mapper.*;
|
||||
import org.jeecg.modules.system.service.ISysTenantPackService;
|
||||
import org.jeecg.modules.system.service.ISysTenantService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
@ -67,6 +68,12 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
|
||||
@Autowired
|
||||
private SysUserDepartMapper sysUserDepartMapper;
|
||||
|
||||
@Autowired
|
||||
private SysTenantPackMapper sysTenantPackMapper;
|
||||
|
||||
@Autowired
|
||||
private SysPackPermissionMapper sysPackPermissionMapper;
|
||||
|
||||
@Override
|
||||
public List<SysTenant> queryEffectiveTenant(Collection<Integer> idList) {
|
||||
if(oConvertUtils.listIsEmpty(idList)){
|
||||
@ -143,6 +150,8 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
|
||||
userTenantMapper.delete(query);
|
||||
//update-end---author:wangshuai ---date:20221223 for:[QQYUN-3371]租户逻辑改造,改成关系表------------
|
||||
}
|
||||
//租户移除用户,直接删除用户租户产品包
|
||||
sysTenantPackUserMapper.deletePackUserByTenantId(Integer.valueOf(tenantId),Arrays.asList(userIds.split(SymbolConstant.COMMA)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -192,11 +201,11 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
|
||||
if(CommonConstant.USER_TENANT_UNDER_REVIEW.equals(relation.getStatus())){
|
||||
msg = ",状态:审核中";
|
||||
}else if(CommonConstant.USER_TENANT_REFUSE.equals(relation.getStatus())){
|
||||
throw new JeecgBootException("管理员已拒绝您加入租户,请联系租户管理员");
|
||||
throw new JeecgBootBizTipException("管理员已拒绝您加入租户,请联系租户管理员");
|
||||
}else if(CommonConstant.USER_TENANT_QUIT.equals(relation.getStatus())){
|
||||
msg = ",状态:已离职";
|
||||
}
|
||||
throw new JeecgBootException("您已是该租户成员"+msg);
|
||||
throw new JeecgBootBizTipException("您已是该租户成员"+msg);
|
||||
}
|
||||
//用户加入门牌号审核中状态
|
||||
SysUserTenant tenant = new SysUserTenant();
|
||||
@ -236,6 +245,11 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
|
||||
//删除租户下的用户
|
||||
userTenantMapper.deleteUserByTenantId(list);
|
||||
//update-ennd---author:wangshuai ---date:20230710 for:【QQYUN-5723】3、租户彻底删除,用户租户关系表也需要删除------------
|
||||
|
||||
//update-begin---author:wangshuai ---date:20230710 for:【QQYUN-5723】3、租户彻底删除,用户租户关系表也需要删除------------
|
||||
//删除租户下的产品包
|
||||
this.deleteTenantPackByTenantId(list);
|
||||
//update-ennd---author:wangshuai ---date:20230710 for:【QQYUN-5723】3、租户彻底删除,用户租户关系表也需要删除------------
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -833,4 +847,67 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除租户下的产品包
|
||||
*
|
||||
* @param tenantIdList
|
||||
*/
|
||||
private void deleteTenantPackByTenantId(List<Integer> tenantIdList) {
|
||||
//1.删除产品包下的用户
|
||||
sysTenantPackUserMapper.deletePackUserByTenantIds(tenantIdList);
|
||||
//2.删除产品包对应的菜单权限
|
||||
sysPackPermissionMapper.deletePackPermByTenantIds(tenantIdList);
|
||||
//3.删除产品包
|
||||
sysTenantPackMapper.deletePackByTenantIds(tenantIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUserByPassword(SysUser sysUser, Integer tenantId) {
|
||||
//被删除人的用户id
|
||||
String userId = sysUser.getId();
|
||||
//被删除人的密码
|
||||
String password = sysUser.getPassword();
|
||||
//当前登录用户
|
||||
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
//step1 判断当前用户是否为当前租户的管理员(只有超级管理员和账号管理员可以删除)
|
||||
Long isHaveAdmin = sysTenantPackUserMapper.izHaveBuyAuth(user.getId(), tenantId);
|
||||
if(null == isHaveAdmin || 0 == isHaveAdmin){
|
||||
throw new JeecgBootException("您不是当前组织的管理员,无法删除用户!");
|
||||
}
|
||||
//step2 离职状态下,并且无其他组织情况下,可以删除
|
||||
SysUserTenant sysUserTenant = userTenantMapper.getUserTenantByTenantId(userId, tenantId);
|
||||
if(null == sysUserTenant || !CommonConstant.USER_TENANT_QUIT.equals(sysUserTenant.getStatus())){
|
||||
throw new JeecgBootException("用户没有离职,不允许删除!");
|
||||
}
|
||||
List<Integer> tenantIdsByUserId = userTenantMapper.getTenantIdsByUserId(userId);
|
||||
if(CollectionUtils.isNotEmpty(tenantIdsByUserId) && tenantIdsByUserId.size()>0){
|
||||
throw new JeecgBootException("用户尚有未退出的组织,无法删除!");
|
||||
}
|
||||
//step3 当天创建的用户和创建人可以删除
|
||||
SysUser sysUserData = userService.getById(userId);
|
||||
if(!sysUserData.getCreateBy().equals(user.getUsername())){
|
||||
throw new JeecgBootException("您不是该用户的创建人,无法删除!");
|
||||
}
|
||||
Date createTime = sysUserData.getCreateTime();
|
||||
boolean sameDay = DateUtils.isSameDay(createTime, new Date());
|
||||
if(!sameDay){
|
||||
throw new JeecgBootException("用户不是今天创建的,无法删除!");
|
||||
}
|
||||
//step4 验证密码
|
||||
String passwordEncode = PasswordUtil.encrypt(sysUserData.getUsername(), password, sysUserData.getSalt());
|
||||
if(!passwordEncode.equals(sysUserData.getPassword())){
|
||||
throw new JeecgBootException("您输入的密码不正确,无法删除该用户!");
|
||||
}
|
||||
//step5 逻辑删除用户
|
||||
userService.deleteUser(userId);
|
||||
//step6 真实删除用户
|
||||
userService.removeLogicDeleted(Collections.singletonList(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysTenant> getTenantListByUserId(String userId) {
|
||||
return tenantMapper.getTenantListByUserId(userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -72,6 +72,7 @@ public class SysThirdAccountServiceImpl extends ServiceImpl<SysThirdAccountMappe
|
||||
thirdQuery.eq(SysThirdAccount::getSysUserId,sysUser.getId());
|
||||
thirdQuery.eq(SysThirdAccount::getThirdType,account.getThirdType());
|
||||
thirdQuery.eq(SysThirdAccount::getThirdUserUuid,thirdUserUuid);
|
||||
thirdQuery.eq(SysThirdAccount::getTenantId,CommonConstant.TENANT_ID_DEFAULT_VALUE);
|
||||
SysThirdAccount sysThirdAccounts = sysThirdAccountMapper.selectOne(thirdQuery);
|
||||
if(sysThirdAccounts!=null){
|
||||
sysThirdAccount.setThirdUserId(sysThirdAccounts.getThirdUserId());
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
package org.jeecg.modules.system.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
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,11 +23,12 @@ 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.desensitization.annotation.SensitiveEncode;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.system.vo.SysUserCacheInfo;
|
||||
import org.jeecg.common.util.*;
|
||||
@ -38,20 +38,22 @@ 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.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.SysUserPositionVo;
|
||||
import org.jeecg.modules.system.vo.UserAvatar;
|
||||
import org.jeecg.modules.system.vo.lowapp.AppExportUserVo;
|
||||
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
|
||||
import org.jeecg.modules.system.vo.lowapp.DepartInfo;
|
||||
import org.jeecg.modules.system.vo.lowapp.AppExportUserVo;
|
||||
import org.jeecg.modules.system.vo.lowapp.UpdateDepartInfo;
|
||||
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.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -103,13 +105,13 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@Autowired
|
||||
private SysThirdAccountMapper sysThirdAccountMapper;
|
||||
@Autowired
|
||||
ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
|
||||
ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
|
||||
@Autowired
|
||||
ThirdAppDingtalkServiceImpl dingtalkService;
|
||||
ThirdAppDingtalkServiceImpl dingtalkService;
|
||||
@Autowired
|
||||
SysRoleIndexMapper sysRoleIndexMapper;
|
||||
ISysRoleIndexService sysRoleIndexService;
|
||||
@Autowired
|
||||
SysTenantMapper sysTenantMapper;
|
||||
SysTenantMapper sysTenantMapper;
|
||||
@Autowired
|
||||
private SysUserTenantMapper relationMapper;
|
||||
@Autowired
|
||||
@ -123,6 +125,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
|
||||
@Autowired
|
||||
private ISysThirdAccountService sysThirdAccountService;
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Override
|
||||
public Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo) {
|
||||
@ -158,6 +163,20 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
}
|
||||
//update-end-author:taoyan--date:20220104--for: JTC-372 【用户冻结问题】 online授权、用户组件,选择用户都能看到被冻结的用户
|
||||
|
||||
//update-begin---author:wangshuai---date:2024-03-08---for:【QQYUN-8110】在线通讯录支持设置权限(只能看分配的技术支持)---
|
||||
String tenantId = TokenUtils.getTenantIdByRequest(req);
|
||||
String lowAppId = TokenUtils.getLowAppIdByRequest(req);
|
||||
// Object bean = ResourceUtil.getImplementationClass(DataEnhanceEnum.getClassPath(tenantId,lowAppId));
|
||||
// if(null != bean){
|
||||
// UserFilterEnhance userEnhanceService = (UserFilterEnhance) bean;
|
||||
// LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
// List<String> userIds = userEnhanceService.getUserIds(sysUser.getId());
|
||||
// if(CollectionUtil.isNotEmpty(userIds)){
|
||||
// queryWrapper.in("id", userIds);
|
||||
// }
|
||||
// }
|
||||
//update-end---author:wangshuai---date:2024-03-08---for:【QQYUN-8110】在线通讯录支持设置权限(只能看分配的技术支持)---
|
||||
|
||||
//TODO 外部模拟登陆临时账号,列表不显示
|
||||
queryWrapper.ne("username", "_reserve_user_external");
|
||||
Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
|
||||
@ -169,7 +188,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
List<String> userIds = pageList.getRecords().stream().map(SysUser::getId).collect(Collectors.toList());
|
||||
if (userIds != null && userIds.size() > 0) {
|
||||
Map<String, String> useDepNames = this.getDepNamesByUserIds(userIds);
|
||||
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
pageList.getRecords().forEach(item -> {
|
||||
item.setOrgCodeTxt(useDepNames.get(item.getId()));
|
||||
//查询用户的租户ids
|
||||
@ -181,14 +199,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
}
|
||||
Integer posTenantId = null;
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
posTenantId = tenantId;
|
||||
posTenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);;
|
||||
}
|
||||
//查询用户职位关系表(获取租户下面的)
|
||||
//update-begin---author:wangshuai---date:2023-11-15---for:【QQYUN-7028】用户职务保存后未回显---
|
||||
List<String> positionList = sysUserPositionMapper.getPositionIdByUserTenantId(item.getId(),posTenantId);
|
||||
//update-end---author:wangshuai---date:2023-11-15---for:【QQYUN-7028】用户职务保存后未回显---
|
||||
//update-end---author:wangshuai ---date:20230228 for:[QQYUN-4354]加入更多字段:当前加入时间应该取当前租户的/职位也是当前租户下的------------
|
||||
item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
|
||||
item.setPost(CommonUtils.getSplitText(positionList, SymbolConstant.COMMA));
|
||||
|
||||
//update-begin---author:wangshuai---date:2023-10-08---for:【QQYUN-6668】钉钉部门和用户同步,我怎么知道哪些用户是双向绑定成功的---
|
||||
//是否根据租户隔离(敲敲云用户列表专用,用于展示是否同步钉钉)
|
||||
@ -251,7 +269,13 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteUser(String userId) {
|
||||
//1.删除用户
|
||||
//update-begin---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】admin用户禁止删除---
|
||||
//1.验证当前用户是管理员账号 admin
|
||||
//验证用户是否为管理员
|
||||
this.checkUserAdminRejectDel(userId);
|
||||
//update-end---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】admin用户禁止删除---
|
||||
|
||||
//2.删除用户
|
||||
this.removeById(userId);
|
||||
return false;
|
||||
}
|
||||
@ -260,7 +284,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteBatchUsers(String userIds) {
|
||||
//1.删除用户
|
||||
//1.验证当前用户是管理员账号 admin
|
||||
this.checkUserAdminRejectDel(userIds);
|
||||
//2.删除用户
|
||||
this.removeByIds(Arrays.asList(userIds.split(",")));
|
||||
return false;
|
||||
}
|
||||
@ -318,33 +344,40 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
|
||||
/**
|
||||
* 获取动态首页路由配置
|
||||
*
|
||||
* @param username
|
||||
* @param version
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public SysRoleIndex getDynamicIndexByUserRole(String username,String version) {
|
||||
public SysRoleIndex getDynamicIndexByUserRole(String username, String version) {
|
||||
List<String> roles = sysUserRoleMapper.getRoleByUserName(username);
|
||||
String componentUrl = RoleIndexConfigEnum.getIndexByRoles(roles);
|
||||
SysRoleIndex roleIndex = new SysRoleIndex(componentUrl);
|
||||
boolean isV3 = CommonConstant.VERSION_V3.equals(version);
|
||||
//只有 X-Version=v3 的时候,才读取sys_role_index表获取角色首页配置
|
||||
if (oConvertUtils.isNotEmpty(version) && roles!=null && roles.size()>0) {
|
||||
LambdaQueryWrapper<SysRoleIndex> routeIndexQuery = new LambdaQueryWrapper();
|
||||
if (isV3 && CollectionUtils.isNotEmpty(roles)) {
|
||||
LambdaQueryWrapper<SysRoleIndex> routeIndexQuery = new LambdaQueryWrapper<>();
|
||||
//用户所有角色
|
||||
routeIndexQuery.in(SysRoleIndex::getRoleCode, roles);
|
||||
//角色首页状态0:未开启 1:开启
|
||||
routeIndexQuery.eq(SysRoleIndex::getStatus, CommonConstant.STATUS_1);
|
||||
//优先级正序排序
|
||||
routeIndexQuery.orderByAsc(SysRoleIndex::getPriority);
|
||||
List<SysRoleIndex> list = sysRoleIndexMapper.selectList(routeIndexQuery);
|
||||
if (null != list && list.size() > 0) {
|
||||
List<SysRoleIndex> list = sysRoleIndexService.list(routeIndexQuery);
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
roleIndex = list.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
//如果componentUrl为空,则返回空
|
||||
if(oConvertUtils.isEmpty(roleIndex.getComponent())){
|
||||
return null;
|
||||
|
||||
if (oConvertUtils.isEmpty(roleIndex.getComponent())) {
|
||||
if (isV3) {
|
||||
// 如果角色没有配置首页,则使用默认首页
|
||||
return sysRoleIndexService.queryDefaultIndex();
|
||||
} else {
|
||||
// 非v3返回null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return roleIndex;
|
||||
}
|
||||
@ -361,17 +394,30 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
log.info("-------通过数据库读取用户拥有的角色Rules------username: " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
|
||||
return new HashSet<>(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户名获取用户角色集合
|
||||
* @param userId 用户ID
|
||||
* @return 角色集合
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getUserRoleSetById(String userId) {
|
||||
// 查询用户拥有的角色集合
|
||||
List<String> roles = sysUserRoleMapper.getRoleCodeByUserId(userId);
|
||||
log.info("-------通过数据库读取用户拥有的角色Rules------userId: " + userId + ",Roles size: " + (roles == null ? 0 : roles.size()));
|
||||
return new HashSet<>(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户名获取用户权限集合
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param userId 用户ID
|
||||
* @return 权限集合
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getUserPermissionsSet(String username) {
|
||||
public Set<String> getUserPermissionsSet(String userId) {
|
||||
Set<String> permissionSet = new HashSet<>();
|
||||
List<SysPermission> permissionList = sysPermissionMapper.queryByUser(username);
|
||||
List<SysPermission> permissionList = sysPermissionMapper.queryByUser(userId);
|
||||
//================= begin 开启租户的时候 如果没有test角色,默认加入test角色================
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
if (permissionList == null) {
|
||||
@ -390,7 +436,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
permissionSet.add(po.getPerms());
|
||||
}
|
||||
}
|
||||
log.info("-------通过数据库读取用户拥有的权限Perms------username: "+ username+",Perms size: "+ (permissionSet==null?0:permissionSet.size()) );
|
||||
log.info("-------通过数据库读取用户拥有的权限Perms------userId: "+ userId+",Perms size: "+ (permissionSet==null?0:permissionSet.size()) );
|
||||
return permissionSet;
|
||||
}
|
||||
|
||||
@ -444,7 +490,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public IPage<SysUser> getUserByDepId(Page<SysUser> page, String departId,String username) {
|
||||
public IPage<SysUser> getUserByDepId(Page<SysUser> page, String departId, String username) {
|
||||
return userMapper.getUserByDepId(page, departId,username);
|
||||
}
|
||||
|
||||
@ -487,7 +533,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
//根据部门orgCode查询部门,需要将职位id进行传递
|
||||
for (SysUserSysDepartModel model:list) {
|
||||
List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(model.getId());
|
||||
model.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
|
||||
model.setPost(CommonUtils.getSplitText(positionList, SymbolConstant.COMMA));
|
||||
}
|
||||
Integer total = baseMapper.getUserByOrgCodeTotal(orgCode, userParams);
|
||||
|
||||
@ -796,7 +842,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username")
|
||||
@Cacheable(cacheNames= CacheConstant.SYS_USERS_CACHE, key="#username")
|
||||
@SensitiveEncode
|
||||
public LoginUser getEncodeUserInfo(String username){
|
||||
if(oConvertUtils.isEmpty(username)) {
|
||||
@ -812,6 +858,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
return null;
|
||||
}
|
||||
BeanUtils.copyProperties(sysUser, loginUser);
|
||||
// 查询当前登录用户的部门id
|
||||
loginUser.setOrgId(this.getDepartIdByOrCode(sysUser.getOrgCode()));
|
||||
// 查询当前登录用户的角色code(多个逗号分割)
|
||||
loginUser.setRoleCode(this.getJoinRoleCodeByUserId(sysUser.getId()));
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
@ -835,7 +885,6 @@ 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
|
||||
@ -854,7 +903,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result){
|
||||
public Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result){
|
||||
// update-begin--Author:sunjianlei Date:20210802 for:获取用户租户信息
|
||||
//用户有哪些租户
|
||||
// List<SysTenant> tenantList = null;
|
||||
@ -1294,7 +1343,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
* @param orgName
|
||||
* @param orgId
|
||||
*/
|
||||
private void getParentDepart(SysDepart depart,List<String> orgName,List<String> orgId){
|
||||
private void getParentDepart(SysDepart depart, List<String> orgName, List<String> orgId){
|
||||
String pid = depart.getParentId();
|
||||
orgName.add(0, depart.getDepartName());
|
||||
orgId.add(0, depart.getId());
|
||||
@ -1422,17 +1471,58 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
private void userPositionId(SysUser sysUser) {
|
||||
if(null != sysUser){
|
||||
List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(sysUser.getId());
|
||||
sysUser.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
|
||||
sysUser.setPost(CommonUtils.getSplitText(positionList, SymbolConstant.COMMA));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户当前登录部门的id
|
||||
*
|
||||
* @param orgCode
|
||||
*/
|
||||
private @Nullable String getDepartIdByOrCode(String orgCode) {
|
||||
if (oConvertUtils.isEmpty(orgCode)) {
|
||||
return null;
|
||||
}
|
||||
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysDepart::getOrgCode, orgCode);
|
||||
queryWrapper.select(SysDepart::getId);
|
||||
SysDepart depart = sysDepartMapper.selectOne(queryWrapper);
|
||||
if (depart == null || oConvertUtils.isEmpty(depart.getId())) {
|
||||
return null;
|
||||
}
|
||||
return depart.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户的角色code(多个逗号分割)
|
||||
*
|
||||
* @param userId
|
||||
*/
|
||||
private @Nullable String getJoinRoleCodeByUserId(String userId) {
|
||||
if (oConvertUtils.isEmpty(userId)) {
|
||||
return null;
|
||||
}
|
||||
// 判断是否开启saas模式,根据租户id过滤
|
||||
Integer tenantId = null;
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
// 开启了但是没有租户ID,默认-1,使其查询不到任何数据
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), -1);
|
||||
}
|
||||
List<SysRole> roleList = sysRoleMapper.getRoleCodeListByUserId(userId, tenantId);
|
||||
if (CollectionUtils.isEmpty(roleList)) {
|
||||
return null;
|
||||
}
|
||||
return roleList.stream().map(SysRole::getRoleCode).collect(Collectors.joining(SymbolConstant.COMMA));
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除部门负责人
|
||||
* @param departChargeUserIdList
|
||||
* @param departChargeUsers
|
||||
* @param departId
|
||||
*/
|
||||
private void removeDepartmentManager(List<String> departChargeUserIdList,List<SysUser> departChargeUsers,String departId){
|
||||
private void removeDepartmentManager(List<String> departChargeUserIdList, List<SysUser> departChargeUsers, String departId){
|
||||
//移除部门负责人
|
||||
for(String chargeUserId: departChargeUserIdList){
|
||||
for(SysUser chargeUser: departChargeUsers){
|
||||
@ -1796,6 +1886,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
String title = sysUser.getRealname() + " 邀请您加入 " + tenantName + "。";
|
||||
messageDTO.setTitle(title);
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
//update-begin---author:wangshuai---date:2024-03-11---for:【QQYUN-8425】用户导入成功后 消息提醒 跳转至同意页面---
|
||||
data.put(CommonConstant.NOTICE_MSG_BUS_TYPE, SysAnnmentTypeEnum.TENANT_INVITE.getType());
|
||||
//update-end---author:wangshuai---date:2024-03-11---for:【QQYUN-8425】用户导入成功后 消息提醒 跳转至同意页面---
|
||||
messageDTO.setData(data);
|
||||
messageDTO.setContent(title);
|
||||
messageDTO.setToUser(invitedUsername);
|
||||
@ -1804,6 +1897,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
//update-end---author:wangshuai ---date:20230710 for:【QQYUN-5731】导入用户时,没有提醒------------
|
||||
}
|
||||
//======================================= end 用户与部门 用户列表导入 =========================================
|
||||
|
||||
@Override
|
||||
public void checkUserAdminRejectDel(String userIds) {
|
||||
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
|
||||
@ -1815,4 +1909,118 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
throw new JeecgBootException("admin用户,不允许删除!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changePhone(JSONObject json, String username) {
|
||||
String smscode = json.getString("smscode");
|
||||
String phone = json.getString("phone");
|
||||
String type = json.getString("type");
|
||||
if(oConvertUtils.isEmpty(phone)){
|
||||
throw new JeecgBootException("请填写原手机号!");
|
||||
}
|
||||
if(oConvertUtils.isEmpty(smscode)){
|
||||
throw new JeecgBootException("请填写验证码!");
|
||||
}
|
||||
//step1 验证原手机号是否和当前用户匹配
|
||||
SysUser sysUser = userMapper.getUserByNameAndPhone(phone,username);
|
||||
if (null == sysUser){
|
||||
throw new JeecgBootException("原手机号不匹配,无法修改密码!");
|
||||
}
|
||||
//step2 根据类型判断是验证原手机号的验证码还是新手机号的验证码
|
||||
//验证原手机号
|
||||
if(CommonConstant.VERIFY_ORIGINAL_PHONE.equals(type)){
|
||||
this.verifyPhone(phone, smscode);
|
||||
}else if(CommonConstant.UPDATE_PHONE.equals(type)){
|
||||
//修改手机号
|
||||
String newPhone = json.getString("newPhone");
|
||||
//需要验证新手机号和原手机号是否一致,一致不让修改
|
||||
if(newPhone.equals(phone)){
|
||||
throw new JeecgBootException("新手机号与原手机号一致,无法修改!");
|
||||
}
|
||||
this.verifyPhone(newPhone, smscode);
|
||||
//step3 新手机号验证码验证成功之后即可修改手机号
|
||||
sysUser.setPhone(newPhone);
|
||||
userMapper.updateById(sysUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证手机号
|
||||
*
|
||||
* @param phone
|
||||
* @param smsCode
|
||||
* @return
|
||||
*/
|
||||
public void verifyPhone(String phone, String smsCode){
|
||||
String phoneKey = CommonConstant.CHANGE_PHONE_REDIS_KEY_PRE + phone;
|
||||
Object phoneCode = redisUtil.get(phoneKey);
|
||||
if(null == phoneCode){
|
||||
throw new JeecgBootException("验证码失效,请重新发送验证码!");
|
||||
}
|
||||
if(!smsCode.equals(phoneCode.toString())) {
|
||||
throw new JeecgBootException("短信验证码不匹配!");
|
||||
}
|
||||
//验证完成之后清空手机验证码
|
||||
redisUtil.removeAll(phoneKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChangePhoneSms(JSONObject jsonObject, String username, String ipAddress) {
|
||||
String type = jsonObject.getString("type");
|
||||
String phone = jsonObject.getString("phone");
|
||||
if(oConvertUtils.isEmpty(phone)){
|
||||
throw new JeecgBootException("请填写手机号!");
|
||||
}
|
||||
//step1 根据类型判断是发送旧手机号验证码还是新的手机号验证码
|
||||
if(CommonConstant.VERIFY_ORIGINAL_PHONE.equals(type)){
|
||||
//step2 旧手机号验证码需要验证手机号是否匹配
|
||||
SysUser sysUser = userMapper.getUserByNameAndPhone(phone, username);
|
||||
if(null == sysUser){
|
||||
throw new JeecgBootException("旧手机号不匹配,无法修改手机号!");
|
||||
}
|
||||
}else if(CommonConstant.UPDATE_PHONE.equals(type)){
|
||||
//step3 新手机号需要验证手机号码是否已注册过
|
||||
SysUser userByPhone = userMapper.getUserByPhone(phone);
|
||||
if(null != userByPhone){
|
||||
throw new JeecgBootException("手机号已被注册,请尝试其他手机号!");
|
||||
}
|
||||
}
|
||||
//step4 发送短信验证码
|
||||
this.sendPhoneSms(phone, ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
* @param phone
|
||||
*/
|
||||
private void sendPhoneSms(String phone, String clientIp) {
|
||||
String redisKey = CommonConstant.CHANGE_PHONE_REDIS_KEY_PRE+phone;
|
||||
Object object = redisUtil.get(redisKey);
|
||||
|
||||
if (object != null) {
|
||||
throw new JeecgBootException("验证码10分钟内,仍然有效!");
|
||||
}
|
||||
|
||||
//增加 check防止恶意刷短信接口
|
||||
if(!DySmsLimit.canSendSms(clientIp)){
|
||||
log.warn("--------[警告] IP地址:{}, 短信接口请求太多-------", clientIp);
|
||||
throw new JeecgBootException("短信接口请求太多,请稍后再试!", CommonConstant.PHONE_SMS_FAIL_CODE);
|
||||
}
|
||||
|
||||
//随机数
|
||||
String captcha = RandomUtil.randomNumbers(6);
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("code", captcha);
|
||||
try {
|
||||
boolean sendSmsSuccess = DySmsHelper.sendSms(phone, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
|
||||
if(!sendSmsSuccess){
|
||||
throw new JeecgBootException("短信验证码发送失败,请稍后重试!");
|
||||
}
|
||||
//验证码10分钟内有效
|
||||
redisUtil.set(redisKey, captcha, 600);
|
||||
} catch (ClientException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
throw new JeecgBootException("短信接口未配置,请联系管理员!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,10 +30,7 @@ import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.constant.enums.MessageTypeEnum;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.PasswordUtil;
|
||||
import org.jeecg.common.util.RestUtil;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
@ -233,7 +230,9 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
||||
for (JdtDepartmentTreeVo departmentTree : departmentTreeList) {
|
||||
LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
|
||||
// 根据 source_identifier 字段查询
|
||||
queryWrapper.eq(SysDepart::getId, departmentTree.getSource_identifier());
|
||||
//update-begin---author:wangshuai---date:2024-04-10---for:【issues/6017】钉钉同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
queryWrapper.and(item -> item.eq(SysDepart::getId, departmentTree.getSource_identifier()).or().eq(SysDepart::getDingIdentifier,departmentTree.getDept_id()));
|
||||
//update-end---author:wangshuai---date:2024-04-10---for:【issues/6017】钉钉同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
SysDepart sysDepart = sysDepartService.getOne(queryWrapper);
|
||||
if (sysDepart != null) {
|
||||
// 执行更新操作
|
||||
@ -270,14 +269,21 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
||||
newSysDepart.setOrgCategory("1");
|
||||
}
|
||||
try {
|
||||
if(oConvertUtils.isEmpty(departmentTree.getParent_id())){
|
||||
newSysDepart.setDingIdentifier(departmentTree.getDept_id().toString());
|
||||
}
|
||||
newSysDepart.setTenantId(tenantId);
|
||||
sysDepartService.saveDepartData(newSysDepart, username);
|
||||
// 更新钉钉 source_identifier
|
||||
Department updateDtDepart = new Department();
|
||||
updateDtDepart.setDept_id(departmentTree.getDept_id());
|
||||
updateDtDepart.setSource_identifier(newSysDepart.getId());
|
||||
Response response = JdtDepartmentAPI.update(updateDtDepart, accessToken);
|
||||
if (!response.isSuccess()) {
|
||||
throw new RuntimeException(response.getErrmsg());
|
||||
//为空说明是最顶级部门,最顶级部门不允许修改操作
|
||||
if(oConvertUtils.isNotEmpty(newSysDepart.getParentId())){
|
||||
Response response = JdtDepartmentAPI.update(updateDtDepart, accessToken);
|
||||
if (!response.isSuccess()) {
|
||||
throw new RuntimeException(response.getErrmsg());
|
||||
}
|
||||
}
|
||||
String str = String.format("部门 %s 创建成功!", newSysDepart.getDepartName());
|
||||
syncInfo.addSuccessInfo(str);
|
||||
@ -1234,7 +1240,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
Long count = tenantMapper.tenantIzExist(tenantId);
|
||||
if(ObjectUtil.isEmpty(count) || 0 == count){
|
||||
throw new JeecgBootException("租户不存在!");
|
||||
throw new JeecgBootException("租户ID:" + tenantId + "无效,平台中不存在!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +284,9 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
||||
if (sysDepart != null) {
|
||||
// 执行更新操作
|
||||
SysDepart updateSysDepart = this.qwDepartmentToSysDepart(departmentTree, sysDepart);
|
||||
if (sysParentId != null) {
|
||||
//update-begin---author:wangshuai---date:2024-04-10---for:【issues/6017】企业微信同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
if (sysParentId != null && !"0".equals(sysParentId)) {
|
||||
//update-end---author:wangshuai---date:2024-04-10---for:【issues/6017】企业微信同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
updateSysDepart.setParentId(sysParentId);
|
||||
}
|
||||
try {
|
||||
@ -302,7 +304,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
||||
} else {
|
||||
// 执行新增操作
|
||||
SysDepart newSysDepart = this.qwDepartmentToSysDepart(departmentTree, null);
|
||||
if (sysParentId != null) {
|
||||
if (sysParentId != null && !"0".equals(sysParentId)) {
|
||||
newSysDepart.setParentId(sysParentId);
|
||||
// 2 = 组织机构
|
||||
newSysDepart.setOrgCategory("2");
|
||||
@ -390,7 +392,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
||||
int errCode = JwUserAPI.updateUser(qwUser, accessToken);
|
||||
// 收集错误信息
|
||||
this.syncUserCollectErrInfo(errCode, sysUser, syncInfo);
|
||||
this.thirdAccountSaveOrUpdate(sysThirdAccount, sysUser.getId(), qwUser.getUserid(),qwUser.getName());
|
||||
this.thirdAccountSaveOrUpdate(sysThirdAccount, sysUser.getId(), qwUser.getUserid(),qwUser.getName(), null);
|
||||
// 更新完成,直接跳到下一次外部循环继续
|
||||
continue for1;
|
||||
}
|
||||
@ -400,7 +402,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
||||
// 收集错误信息
|
||||
boolean apiSuccess = this.syncUserCollectErrInfo(errCode, sysUser, syncInfo);
|
||||
if (apiSuccess) {
|
||||
this.thirdAccountSaveOrUpdate(sysThirdAccount, sysUser.getId(), qwUser.getUserid(),qwUser.getName());
|
||||
this.thirdAccountSaveOrUpdate(sysThirdAccount, sysUser.getId(), qwUser.getUserid(),qwUser.getName(), null);
|
||||
}
|
||||
}
|
||||
return syncInfo;
|
||||
@ -471,13 +473,16 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
||||
* @param qwUserId 企业微信用户ID
|
||||
* @param wechatRealName 企业微信用户真实姓名
|
||||
*/
|
||||
private void thirdAccountSaveOrUpdate(SysThirdAccount sysThirdAccount, String sysUserId, String qwUserId, String wechatRealName) {
|
||||
private void thirdAccountSaveOrUpdate(SysThirdAccount sysThirdAccount, String sysUserId, String qwUserId, String wechatRealName, Integer tenantId) {
|
||||
if (sysThirdAccount == null) {
|
||||
sysThirdAccount = new SysThirdAccount();
|
||||
sysThirdAccount.setSysUserId(sysUserId);
|
||||
sysThirdAccount.setStatus(1);
|
||||
sysThirdAccount.setDelFlag(0);
|
||||
sysThirdAccount.setThirdType(THIRD_TYPE);
|
||||
if(oConvertUtils.isNotEmpty(tenantId)){
|
||||
sysThirdAccount.setTenantId(tenantId);
|
||||
}
|
||||
}
|
||||
sysThirdAccount.setThirdUserId(qwUserId);
|
||||
sysThirdAccount.setThirdUserUuid(qwUserId);
|
||||
@ -1184,7 +1189,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
||||
this.createUserTenant(sysUserId,false,tenantId);
|
||||
//step 3 新建或更新第三方账号表
|
||||
SysThirdAccount sysThirdAccount = sysThirdAccountService.getOneByUuidAndThirdType(wechatUserId, THIRD_TYPE, tenantId, wechatUserId);
|
||||
this.thirdAccountSaveOrUpdate(sysThirdAccount,sysUserId,wechatUserId,wechatRealName);
|
||||
this.thirdAccountSaveOrUpdate(sysThirdAccount,sysUserId,wechatUserId,wechatRealName,tenantId);
|
||||
//step 4 新建或更新用户部门关系表
|
||||
if(oConvertUtils.isNotEmpty(wechatDepartId)){
|
||||
String wechatDepartIds = wechatDepartId.toString();
|
||||
|
||||
@ -5,6 +5,7 @@ import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 钉钉树结构的部门
|
||||
@ -48,8 +49,20 @@ public class JdtDepartmentTreeVo extends Department {
|
||||
public static List<JdtDepartmentTreeVo> listToTree(List<Department> allDepartment) {
|
||||
// 先找出所有的父级
|
||||
List<JdtDepartmentTreeVo> treeList = getByParentId(1, allDepartment);
|
||||
Optional<Department> departmentOptional = allDepartment.stream().filter(item -> item.getParent_id() == null).findAny();
|
||||
Department department = new Department();
|
||||
//判断是否找到数据
|
||||
if(departmentOptional.isPresent()){
|
||||
department = departmentOptional.get();
|
||||
}
|
||||
getChildrenRecursion(treeList, allDepartment);
|
||||
return treeList;
|
||||
//update-begin---author:wangshuai---date:2024-04-10---for:【issues/6017】钉钉同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
JdtDepartmentTreeVo treeVo = new JdtDepartmentTreeVo(department);
|
||||
treeVo.setChildren(treeList);
|
||||
List<JdtDepartmentTreeVo> list = new ArrayList<>();
|
||||
list.add(treeVo);
|
||||
return list;
|
||||
//update-end---author:wangshuai---date:2024-04-10---for:【issues/6017】钉钉同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
}
|
||||
|
||||
private static List<JdtDepartmentTreeVo> getByParentId(Integer parentId, List<Department> allDepartment) {
|
||||
|
||||
@ -5,6 +5,7 @@ import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 企业微信树结构的部门
|
||||
@ -48,8 +49,20 @@ public class JwDepartmentTreeVo extends Department {
|
||||
public static List<JwDepartmentTreeVo> listToTree(List<Department> allDepartment) {
|
||||
// 先找出所有的父级
|
||||
List<JwDepartmentTreeVo> treeList = getByParentId("1", allDepartment);
|
||||
Optional<Department> departmentOptional = allDepartment.stream().filter(item -> "0".equals(item.getParentid())).findAny();
|
||||
Department department = new Department();
|
||||
//判断是否找到数据
|
||||
if(departmentOptional.isPresent()){
|
||||
department = departmentOptional.get();
|
||||
}
|
||||
getChildrenRecursion(treeList, allDepartment);
|
||||
return treeList;
|
||||
//update-begin---author:wangshuai---date:2024-04-10---for:【issues/6017】企业微信同步部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
JwDepartmentTreeVo treeVo = new JwDepartmentTreeVo(department);
|
||||
treeVo.setChildren(treeList);
|
||||
List<JwDepartmentTreeVo> list = new ArrayList<>();
|
||||
list.add(treeVo);
|
||||
return list;
|
||||
//update-begin---author:wangshuai---date:2024-04-10---for:【issues/6017】企业微信部门时没有最顶层的部门名,同步用户时,用户没有部门信息---
|
||||
}
|
||||
|
||||
private static List<JwDepartmentTreeVo> getByParentId(String parentId, List<Department> allDepartment) {
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
TimePicker,
|
||||
</#if>
|
||||
<#if need_pca>
|
||||
JAreaLinkage,
|
||||
JAreaSelect,
|
||||
</#if>
|
||||
<#if need_upload>
|
||||
JUpload,
|
||||
|
||||
@ -8,104 +8,104 @@
|
||||
<#elseif po.dictField?default("")?trim?length gt 1>
|
||||
<#assign form_field_dictCode="${po.dictField}">
|
||||
</#if>
|
||||
<a-col :span="${form_span}">
|
||||
<a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
|
||||
<#if po.classType =='date'>
|
||||
<a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" value-format="YYYY-MM-DD" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType =='datetime'>
|
||||
<a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" showTime value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType =='time'>
|
||||
<#assign need_time = true>
|
||||
<time-picker placeholder="请选择${po.filedComment}" value-format="HH:mm:ss" v-model:value="formData.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType =='popup'>
|
||||
<#assign need_popup = true>
|
||||
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
|
||||
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
|
||||
<j-popup
|
||||
placeholder="请选择${po.filedComment}"
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
code="${po.dictTable}"
|
||||
:fieldConfig="[
|
||||
<#list sourceFields as fieldName>
|
||||
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
|
||||
</#list>
|
||||
]"
|
||||
:multi="${po.extendParams.popupMulti?c}"
|
||||
:setFieldsValue="setFieldsValue"
|
||||
<#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if><#rt>
|
||||
/>
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
<#assign need_dept = true>
|
||||
<j-select-dept v-model:value="formData.${po.fieldName}" :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> />
|
||||
<#elseif po.classType =='switch'>
|
||||
<#assign need_switch = true>
|
||||
<j-switch v-model:value="formData.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-switch>
|
||||
<#elseif po.classType =='pca'>
|
||||
<#assign need_pca = true>
|
||||
<j-area-select v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> />
|
||||
<#elseif po.classType =='markdown'>
|
||||
<#assign need_markdown = true>
|
||||
<j-markdown-editor v-model:value="formData.${autoStringSuffixForModel(po)}" id="${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-markdown-editor>
|
||||
<#elseif po.classType =='password'>
|
||||
<a-input-password v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType =='sel_user'>
|
||||
<#assign need_dept_user = true>
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<j-select-user v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<#elseif po.classType =='textarea'>
|
||||
<a-textarea v-model:value="formData.${autoStringSuffixForModel(po)}" :rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType=='radio'>
|
||||
<#assign need_select_tag = true>
|
||||
<j-dict-select-tag type='radio' v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType=='list'>
|
||||
<#assign need_select_tag = true>
|
||||
<j-dict-select-tag v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType=='list_multi'>
|
||||
<#assign need_multi = true>
|
||||
<j-select-multiple type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> :triggerChange="false"/>
|
||||
<#elseif po.classType=='checkbox'>
|
||||
<#assign need_checkbox = true>
|
||||
<j-checkbox type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType=='sel_search'>
|
||||
<#assign need_search = true>
|
||||
<j-search-select v-model:value="formData.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> />
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
<#assign need_category = true>
|
||||
<j-category-select v-model:value="formData.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}"</#if> <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> @change="(value) => handleFormChange('${po.fieldName}', value)" />
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<a-input-number v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.classType=='file'>
|
||||
<#assign need_upload = true>
|
||||
<j-upload v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if> <#if po.uploadnum??>:maxCount=${po.uploadnum}</#if>></j-upload>
|
||||
<#elseif po.classType=='image'>
|
||||
<#assign need_image_upload = true>
|
||||
<j-image-upload <#if po.uploadnum??>:fileMax=${po.uploadnum}</#if> v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></j-image-upload>
|
||||
<#elseif po.classType=='umeditor'>
|
||||
<#assign need_editor = true>
|
||||
<j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>/>
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
<a-input v-model:value="formData.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></a-input>
|
||||
<#elseif po.classType == 'sel_tree'>
|
||||
<#assign need_select_tree = true>
|
||||
<j-tree-select
|
||||
<#if po.dictText??>
|
||||
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
|
||||
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
|
||||
<#elseif po.dictText?split(',')[1]??>
|
||||
pidField="${po.dictText?split(',')[1]}"
|
||||
<#elseif po.dictText?split(',')[3]??>
|
||||
hasChildField="${po.dictText?split(',')[3]}"
|
||||
</#if>
|
||||
</#if>
|
||||
pidValue="${po.dictField}"
|
||||
<#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
@change="(value) => handleFormChange('${po.fieldName}', value)">
|
||||
</j-tree-select>
|
||||
<#else>
|
||||
<a-input v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>></a-input>
|
||||
</#if>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="${form_span}">
|
||||
<a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
|
||||
<#if po.classType =='date'>
|
||||
<a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" value-format="YYYY-MM-DD" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType =='datetime'>
|
||||
<a-date-picker placeholder="请选择${po.filedComment}" v-model:value="formData.${po.fieldName}" showTime value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType =='time'>
|
||||
<#assign need_time = true>
|
||||
<time-picker placeholder="请选择${po.filedComment}" value-format="HH:mm:ss" v-model:value="formData.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType =='popup'>
|
||||
<#assign need_popup = true>
|
||||
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
|
||||
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
|
||||
<j-popup
|
||||
placeholder="请选择${po.filedComment}"
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
code="${po.dictTable}"
|
||||
:fieldConfig="[
|
||||
<#list sourceFields as fieldName>
|
||||
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
|
||||
</#list>
|
||||
]"
|
||||
:multi="${po.extendParams.popupMulti?c}"
|
||||
:setFieldsValue="setFieldsValue"
|
||||
<#if po.readonly=='Y'>disabled</#if><#rt>
|
||||
/>
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
<#assign need_dept = true>
|
||||
<j-select-dept v-model:value="formData.${po.fieldName}" :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled</#if> />
|
||||
<#elseif po.classType =='switch'>
|
||||
<#assign need_switch = true>
|
||||
<j-switch v-model:value="formData.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
|
||||
<#elseif po.classType =='pca'>
|
||||
<#assign need_pca = true>
|
||||
<j-area-select v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> />
|
||||
<#elseif po.classType =='markdown'>
|
||||
<#assign need_markdown = true>
|
||||
<j-markdown-editor v-model:value="formData.${autoStringSuffixForModel(po)}" id="${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></j-markdown-editor>
|
||||
<#elseif po.classType =='password'>
|
||||
<a-input-password v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType =='sel_user'>
|
||||
<#assign need_dept_user = true>
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<j-select-user v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<#elseif po.classType =='textarea'>
|
||||
<a-textarea v-model:value="formData.${autoStringSuffixForModel(po)}" :rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType=='radio'>
|
||||
<#assign need_select_tag = true>
|
||||
<j-dict-select-tag type='radio' v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType=='list'>
|
||||
<#assign need_select_tag = true>
|
||||
<j-dict-select-tag v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType=='list_multi'>
|
||||
<#assign need_multi = true>
|
||||
<j-select-multiple type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> :triggerChange="false"/>
|
||||
<#elseif po.classType=='checkbox'>
|
||||
<#assign need_checkbox = true>
|
||||
<j-checkbox type="${po.classType}" v-model:value="formData.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType=='sel_search'>
|
||||
<#assign need_search = true>
|
||||
<j-search-select v-model:value="formData.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> />
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
<#assign need_category = true>
|
||||
<j-category-select v-model:value="formData.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}"</#if> <#if po.readonly=='Y'>disabled</#if> @change="(value) => handleFormChange('${po.fieldName}', value)" />
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<a-input-number v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.classType=='file'>
|
||||
<#assign need_upload = true>
|
||||
<j-upload v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:maxCount=${po.uploadnum}</#if>></j-upload>
|
||||
<#elseif po.classType=='image'>
|
||||
<#assign need_image_upload = true>
|
||||
<j-image-upload <#if po.uploadnum??>:fileMax=${po.uploadnum}</#if> v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
|
||||
<#elseif po.classType=='umeditor'>
|
||||
<#assign need_editor = true>
|
||||
<j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
<a-input v-model:value="formData.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
|
||||
<#elseif po.classType == 'sel_tree'>
|
||||
<#assign need_select_tree = true>
|
||||
<j-tree-select
|
||||
<#if po.dictText??>
|
||||
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
|
||||
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
|
||||
<#elseif po.dictText?split(',')[1]??>
|
||||
pidField="${po.dictText?split(',')[1]}"
|
||||
<#elseif po.dictText?split(',')[3]??>
|
||||
hasChildField="${po.dictText?split(',')[3]}"
|
||||
</#if>
|
||||
</#if>
|
||||
pidValue="${po.dictField}"
|
||||
<#if po.readonly=='Y'>disabled</#if>
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
@change="(value) => handleFormChange('${po.fieldName}', value)">
|
||||
</j-tree-select>
|
||||
<#else>
|
||||
<a-input v-model:value="formData.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
|
||||
</#if>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</#if>
|
||||
@ -0,0 +1,21 @@
|
||||
<#-- 原生查询区域样式 -->
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
.ant-form-item:not(.ant-form-item-with-help){
|
||||
margin-bottom: 16px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
${po.fieldName}: <#if po.defaultVal??>${po.defaultVal}<#else>undefined</#if>,
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
${po.fieldName}String: <#if po.defaultVal??>${po.defaultVal}<#else>''</#if>,
|
||||
${po.fieldName}String: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
|
||||
<#else>
|
||||
${po.fieldName}: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
|
||||
</#if>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
${po.fieldName}: <#if po.defaultVal??>${po.defaultVal}<#else>undefined</#if>,
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
${po.fieldName}String: <#if po.defaultVal??>${po.defaultVal}<#else>''</#if>,
|
||||
${po.fieldName}String: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
|
||||
<#else>
|
||||
${po.fieldName}: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
|
||||
</#if>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
${po.fieldName}: <#if po.defaultVal??>${po.defaultVal}<#else>undefined</#if>,
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
${po.fieldName}String: <#if po.defaultVal??>${po.defaultVal}<#else>''</#if>,
|
||||
${po.fieldName}String: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
|
||||
<#else>
|
||||
${po.fieldName}: <#if po.defaultVal??>'${po.defaultVal}'<#else>''</#if>,
|
||||
</#if>
|
||||
|
||||
@ -151,7 +151,7 @@
|
||||
<#assign dictCode="dictCode: '${po.dictField}'">
|
||||
</#if>
|
||||
|
||||
<#if po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='checkbox'>
|
||||
<#if po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='checkbox' || po.classType=='radio'>
|
||||
<#assign extAttrs="${dictCode},">
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
<#-- 分类字典树 -->
|
||||
|
||||
@ -14,13 +14,13 @@
|
||||
{ validator: (rule, value, callback) => validateDuplicateValue(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}', value, this.model.id, callback)},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
<#-- 6到18位字符串 -->
|
||||
<#elseif fieldValidType == 's6-18'>
|
||||
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
|
||||
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
|
||||
<#-- 网址 -->
|
||||
<#elseif fieldValidType == 'url'>
|
||||
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
|
||||
|
||||
@ -10,13 +10,13 @@
|
||||
{ validator: ${po.fieldName}Duplicatevalidate }<#rt>
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'}<#rt>,
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'}<#rt>,
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}<#rt>,
|
||||
<#-- 6到18位字符串 -->
|
||||
<#elseif fieldValidType == 's6-18'>
|
||||
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}<#rt>,
|
||||
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},<#rt>,
|
||||
<#-- 网址 -->
|
||||
<#elseif fieldValidType == 'url'>
|
||||
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'}<#rt>,
|
||||
|
||||
@ -132,7 +132,7 @@
|
||||
//流程表单data
|
||||
formData: {
|
||||
type: Object,
|
||||
default: ()=>{},
|
||||
default: () => ({}),
|
||||
required: false
|
||||
},
|
||||
//表单模式:true流程表单 false普通表单
|
||||
|
||||
@ -116,7 +116,9 @@
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y'>
|
||||
<#if po.queryMode!='single'>
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<#-- update-begin---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time'>
|
||||
<#-- update-end---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
|
||||
</#if>
|
||||
</#if>
|
||||
|
||||
@ -122,6 +122,9 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -169,6 +172,10 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
component: 'JRangeNumber',
|
||||
<#-- update-begin---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#elseif po.classType=='time'>
|
||||
component: 'RangeTime',
|
||||
<#-- update-end---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#else>
|
||||
component: 'Input', //TODO 范围查询
|
||||
</#if>
|
||||
@ -215,6 +222,9 @@ export const formSchema: FormSchema[] = [
|
||||
<#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
|
||||
<#if po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -252,12 +262,18 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -334,7 +350,7 @@ export const formSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
|
||||
@ -355,7 +355,9 @@
|
||||
* @param value
|
||||
*/
|
||||
function handleFormJoinChange(key, value) {
|
||||
queryParam[key] = value.join(',');
|
||||
if (typeof value != 'string') {
|
||||
queryParam[key] = value.join(',');
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
|
||||
@ -408,20 +410,5 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
}
|
||||
<#include "/common/form/native/vueNativeSearchStyle.ftl">
|
||||
</style>
|
||||
|
||||
@ -121,6 +121,9 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -201,6 +204,9 @@ export const formSchema: FormSchema[] = [
|
||||
field: ${autoStringSuffix(po)},
|
||||
<#if po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -238,11 +244,17 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode: "${form_field_dictCode}"
|
||||
},
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
@ -320,13 +332,13 @@ export const formSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
<#-- 6到18位字符串 -->
|
||||
<#elseif fieldValidType == 's6-18'>
|
||||
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
|
||||
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
|
||||
<#-- 网址 -->
|
||||
<#elseif fieldValidType == 'url'>
|
||||
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<#assign need_category = false>
|
||||
<#assign bpm_flag=false>
|
||||
<#assign need_pca = false>
|
||||
@ -39,12 +41,14 @@
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
<#if bpm_flag>
|
||||
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
|
||||
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
|
||||
</a-col>
|
||||
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
|
||||
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
|
||||
</a-col>
|
||||
</#if>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
</JFormContainer>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
@ -56,13 +60,14 @@
|
||||
import { getValueType } from '/@/utils';
|
||||
import { saveOrUpdate } from '../${entityName}.api';
|
||||
import { Form } from 'ant-design-vue';
|
||||
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
|
||||
<#if hasOnlyValidate == true>
|
||||
import { duplicateValidate } from '/@/utils/helper/validator'
|
||||
</#if>
|
||||
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
formData: { type: Object, default: ()=>{} },
|
||||
formData: { type: Object, default: () => ({})},
|
||||
formBpm: { type: Boolean, default: true }
|
||||
});
|
||||
const formRef = ref();
|
||||
@ -77,9 +82,9 @@
|
||||
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
//表单验证
|
||||
const validatorRules = {
|
||||
const validatorRules = reactive({
|
||||
<#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
|
||||
};
|
||||
});
|
||||
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
|
||||
|
||||
// 表单禁用
|
||||
@ -218,8 +223,6 @@
|
||||
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
height: 500px !important;
|
||||
overflow-y: auto;
|
||||
padding: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineExpose } from 'vue';
|
||||
import ${entityName}Form from './${entityName}Form.vue'
|
||||
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
|
||||
|
||||
const title = ref<string>('');
|
||||
const width = ref<number>(800);
|
||||
@ -67,9 +68,10 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="less">
|
||||
/**隐藏样式-modal确定按钮 */
|
||||
.jee-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@ -405,7 +405,7 @@
|
||||
//流程表单data
|
||||
formData: {
|
||||
type: Object,
|
||||
default: ()=>{},
|
||||
default: () => ({}),
|
||||
required: false
|
||||
},
|
||||
//表单模式:false流程表单 true普通表单
|
||||
|
||||
@ -119,7 +119,9 @@
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y'>
|
||||
<#if po.queryMode!='single'>
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<#-- update-begin---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time'>
|
||||
<#-- update-end---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
|
||||
</#if>
|
||||
</#if>
|
||||
|
||||
@ -125,11 +125,20 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
showTime:true
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
showTime:true,
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||
},
|
||||
<#elseif po.classType=='pca'>
|
||||
component: 'JAreaLinkage',
|
||||
<#elseif po.classType=='popup'>
|
||||
@ -187,6 +196,10 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
component: 'JRangeNumber',
|
||||
<#-- update-begin---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#elseif po.classType=='time'>
|
||||
component: 'RangeTime',
|
||||
<#-- update-end---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#else>
|
||||
component: 'Input', //TODO 范围查询
|
||||
</#if>
|
||||
@ -241,11 +254,14 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
showTime:true,
|
||||
valueFormat: 'YYYY-MM-DD hh:mm:ss'
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||
},
|
||||
<#elseif po.classType =='time'>
|
||||
component: 'TimePicker',
|
||||
@ -278,11 +294,17 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
@ -363,7 +385,7 @@ export const formSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
|
||||
@ -527,7 +527,9 @@
|
||||
* @param value
|
||||
*/
|
||||
function handleFormJoinChange(key, value) {
|
||||
queryParam[key] = value.join(',');
|
||||
if (typeof value != 'string') {
|
||||
queryParam[key] = value.join(',');
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
|
||||
@ -565,20 +567,5 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
}
|
||||
<#include "/common/form/native/vueNativeSearchStyle.ftl">
|
||||
</style>
|
||||
|
||||
@ -127,6 +127,9 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -231,11 +234,14 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
showTime:true,
|
||||
valueFormat: 'YYYY-MM-DD hh:mm:ss'
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||
},
|
||||
<#elseif po.classType =='time'>
|
||||
component: 'TimePicker',
|
||||
@ -268,10 +274,16 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode: "${form_field_dictCode}"
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
@ -353,7 +365,7 @@ export const formSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!' },
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!' },
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!' },
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<#assign need_category = false>
|
||||
<#assign bpm_flag=false>
|
||||
<#assign need_pca = false>
|
||||
@ -37,32 +39,34 @@
|
||||
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
|
||||
<#assign hasOnlyValidate = true>
|
||||
</#if>
|
||||
<#if po.fieldDbName == tableVo.extendParams.pidField>
|
||||
<#assign pidFieldName = po.fieldName>
|
||||
<#assign need_select_tree = true>
|
||||
<a-col :span="${form_span}">
|
||||
<a-form-item label="父级节点" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
|
||||
<j-tree-select
|
||||
placeholder="请选择${po.filedComment}"
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
dict="${tableVo.tableName},${tableVo.extendParams.textField},id"
|
||||
pidField="${tableVo.extendParams.pidField}"
|
||||
pidValue="0"
|
||||
hasChildField="${tableVo.extendParams.hasChildren}"
|
||||
<#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>>
|
||||
</j-tree-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</#if>
|
||||
<#if po.fieldDbName == tableVo.extendParams.pidField>
|
||||
<#assign pidFieldName = po.fieldName>
|
||||
<#assign need_select_tree = true>
|
||||
<a-col :span="${form_span}">
|
||||
<a-form-item label="父级节点" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
|
||||
<j-tree-select
|
||||
placeholder="请选择${po.filedComment}"
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
dict="${tableVo.tableName},${tableVo.extendParams.textField},id"
|
||||
pidField="${tableVo.extendParams.pidField}"
|
||||
pidValue="0"
|
||||
hasChildField="${tableVo.extendParams.hasChildren}"
|
||||
<#if po.readonly=='Y'>disabled<#else>:disabled="disabled"</#if>>
|
||||
</j-tree-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</#if>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
<#if bpm_flag>
|
||||
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
|
||||
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
|
||||
</a-col>
|
||||
</#if>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<#if bpm_flag>
|
||||
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
|
||||
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
|
||||
</a-col>
|
||||
</#if>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
</JFormContainer>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
@ -74,6 +78,7 @@
|
||||
import { getValueType } from '/@/utils';
|
||||
import {loadTreeData, saveOrUpdateDict} from '../${entityName}.api';
|
||||
import { Form } from 'ant-design-vue';
|
||||
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
|
||||
<#if hasOnlyValidate == true>
|
||||
import { duplicateValidate } from '/@/utils/helper/validator'
|
||||
</#if>
|
||||
@ -95,13 +100,13 @@
|
||||
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
//表单验证
|
||||
const validatorRules = {
|
||||
const validatorRules = reactive({
|
||||
<#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
|
||||
};
|
||||
});
|
||||
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
formData: { type: Object, default: ()=>{} },
|
||||
formData: { type: Object, default: () => ({}) },
|
||||
formBpm: { type: Boolean, default: true }
|
||||
});
|
||||
|
||||
@ -270,8 +275,6 @@
|
||||
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
height: 500px !important;
|
||||
overflow-y: auto;
|
||||
padding: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineExpose } from 'vue';
|
||||
import ${entityName}Form from './${entityName}Form.vue'
|
||||
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
|
||||
|
||||
const title = ref<string>('');
|
||||
const width = ref<number>(800);
|
||||
@ -73,9 +74,10 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="less">
|
||||
/**隐藏样式-modal确定按钮 */
|
||||
.jee-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="p-2 cgformErpList">
|
||||
<#assign list_need_category=false>
|
||||
<#assign list_need_pca=false>
|
||||
<#assign bpm_flag=false>
|
||||
@ -17,7 +17,8 @@
|
||||
</#if>
|
||||
</#list>
|
||||
<#-- 结束循环 -->
|
||||
<!--引用表格-->
|
||||
<div class="content">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
@ -70,7 +71,7 @@
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!--子表表格tab-->
|
||||
<a-tabs defaultActiveKey="1">
|
||||
<a-tabs defaultActiveKey="1" style="margin: 10px">
|
||||
<#assign sub_seq=1>
|
||||
<#list subTables as sub>
|
||||
<a-tab-pane tab="${sub.ftlDescription}" key="${sub_seq}" <#if sub_seq gt 1>forceRender</#if>>
|
||||
@ -78,7 +79,8 @@
|
||||
</a-tab-pane>
|
||||
<#assign sub_seq=sub_seq+1>
|
||||
</#list>
|
||||
</a-tabs>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<!-- 表单区域 -->
|
||||
<${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal>
|
||||
</div>
|
||||
@ -125,7 +127,9 @@
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y'>
|
||||
<#if po.queryMode!='single'>
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<#-- update-begin---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time'>
|
||||
<#-- update-end---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end']],
|
||||
</#if>
|
||||
</#if>
|
||||
@ -335,6 +339,14 @@
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
<style lang="less" scoped>
|
||||
html[data-theme='light'] {
|
||||
.cgformErpList {
|
||||
height: 100%;
|
||||
.content {
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -119,6 +119,9 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -161,6 +164,10 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
component: 'JRangeNumber',
|
||||
<#-- update-begin---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#elseif po.classType=='time'>
|
||||
component: 'RangeTime',
|
||||
<#-- update-end---author:chenrui ---date:20240527 for:[TV360X-388]时间范围查询控件---------- -->
|
||||
<#else>
|
||||
component: 'Input', //TODO 范围查询
|
||||
</#if>
|
||||
@ -208,6 +215,9 @@ export const formSchema: FormSchema[] = [
|
||||
<#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
|
||||
<#if po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -245,11 +255,17 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',//TODO 注意string转换问题
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
@ -328,7 +344,7 @@ export const formSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
@ -488,6 +504,9 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
<#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
|
||||
<#if po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -608,7 +627,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="p-2 erpNativeList">
|
||||
<#assign query_field_no=0>
|
||||
<#assign need_category = false>
|
||||
<#assign need_pca = false>
|
||||
@ -85,6 +85,7 @@
|
||||
</a-form>
|
||||
</div>
|
||||
<#-- 结束循环 -->
|
||||
<div class="content">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
@ -139,7 +140,7 @@
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!--子表表格tab-->
|
||||
<a-tabs defaultActiveKey="1">
|
||||
<a-tabs defaultActiveKey="1" style="margin: 10px">
|
||||
<#assign sub_seq=1>
|
||||
<#list subTables as sub>
|
||||
<a-tab-pane tab="${sub.ftlDescription}" key="${sub_seq}" <#if sub_seq gt 1>forceRender</#if>>
|
||||
@ -148,6 +149,7 @@
|
||||
<#assign sub_seq=sub_seq+1>
|
||||
</#list>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<!-- 表单区域 -->
|
||||
<${entityName}Modal ref="registerModal" @success="handleSuccess" />
|
||||
</div>
|
||||
@ -423,25 +425,19 @@
|
||||
* @param value
|
||||
*/
|
||||
function handleFormJoinChange(key, value) {
|
||||
queryParam[key] = value.join(',');
|
||||
if (typeof value != 'string') {
|
||||
queryParam[key] = value.join(',');
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
<#include "/common/form/native/vueNativeSearchStyle.ftl">
|
||||
.erpNativeList {
|
||||
height: 100%;
|
||||
.content {
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -119,6 +119,9 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType=='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -210,6 +213,9 @@ export const formSchema: FormSchema[] = [
|
||||
component: 'DatePicker',
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
componentProps: {
|
||||
showTime:true,
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||
@ -245,11 +251,17 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',//TODO 注意string转换问题
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583] Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
@ -328,7 +340,7 @@ export const formSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
@ -488,6 +500,9 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
<#-- update-end-author:taoyan date:2022-6-24 for: VUEN-1190【代码生成】默认值未生成 -->
|
||||
<#if po.classType =='date'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
<#elseif po.classType =='datetime'>
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
@ -525,11 +540,17 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
<#elseif po.classType=='list'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
dictCode:"${form_field_dictCode}"
|
||||
},
|
||||
<#elseif po.classType=='radio'>
|
||||
component: 'JDictSelectTag',
|
||||
componentProps:{
|
||||
dictCode:"${form_field_dictCode}",
|
||||
type: "radio"
|
||||
},
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:[QQYUN-7583]Vue3风格表单页面多选控件渲染成了下拉多选---------- -->
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
@ -608,7 +629,7 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema)[0]},
|
||||
<#-- 6到16位数字 -->
|
||||
<#elseif fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<#list subTables as sub>
|
||||
#segment#${sub.entityName}List.vue
|
||||
<#assign need_pca = false>
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<#-- 结束循环 -->
|
||||
@ -43,6 +44,7 @@
|
||||
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
|
||||
</#if>
|
||||
<#if po.classType=='pca'>
|
||||
<#assign need_pca = true>
|
||||
<!--省市区字段回显插槽-->
|
||||
{{ getAreaTextByCode(text) }}
|
||||
</#if>
|
||||
@ -66,6 +68,9 @@
|
||||
import { isEmpty } from "/@/utils/is";
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { downloadFile } from '/@/utils/common/renderUtils';
|
||||
<#if need_pca>
|
||||
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
|
||||
</#if>
|
||||
|
||||
const toggleSearchStatus = ref<boolean>(false);
|
||||
//接收主表id
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<#assign need_category = false>
|
||||
<#assign bpm_flag=false>
|
||||
<#assign need_pca = false>
|
||||
@ -38,13 +40,15 @@
|
||||
</#if>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
<#if bpm_flag>
|
||||
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
|
||||
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
|
||||
</a-col>
|
||||
</#if>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<#if bpm_flag>
|
||||
<a-col v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;">
|
||||
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm">提 交</a-button>
|
||||
</a-col>
|
||||
</#if>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
</JFormContainer>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
@ -56,13 +60,14 @@
|
||||
import { getValueType } from '/@/utils';
|
||||
import { saveOrUpdate } from '../${entityName}.api';
|
||||
import { Form } from 'ant-design-vue';
|
||||
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
|
||||
<#if hasOnlyValidate == true>
|
||||
import { duplicateValidate } from '/@/utils/helper/validator'
|
||||
</#if>
|
||||
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
formData: { type: Object, default: ()=>{} },
|
||||
formData: { type: Object, default: () => ({}) },
|
||||
formBpm: { type: Boolean, default: true }
|
||||
});
|
||||
const useForm = Form.useForm;
|
||||
@ -76,9 +81,9 @@
|
||||
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
//表单验证
|
||||
const validatorRules = {
|
||||
const validatorRules = reactive({
|
||||
<#include "/common/validatorRulesTemplate/native/vue3MainNative.ftl">
|
||||
};
|
||||
});
|
||||
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
|
||||
const formRef = ref();
|
||||
// 表单禁用
|
||||
@ -217,8 +222,6 @@
|
||||
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
height: 500px !important;
|
||||
overflow-y: auto;
|
||||
padding: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<${entityName}Form ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></${entityName}Form>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineExpose } from 'vue';
|
||||
import ${entityName}Form from './${entityName}Form.vue'
|
||||
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
|
||||
|
||||
const title = ref<string>('');
|
||||
const width = ref<number>(800);
|
||||
@ -72,4 +73,5 @@
|
||||
.jee-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user