33 changed files with 2003 additions and 45 deletions
-
18common/src/main/java/com/storeroom/config/RsaProperties.java
-
12system/pom.xml
-
6system/src/main/java/com/storeroom/AppRun.java
-
47system/src/main/java/com/storeroom/config/ConfigurerAdapter.java
-
15system/src/main/java/com/storeroom/config/WebSocketConfig.java
-
51system/src/main/java/com/storeroom/config/thread/AsyncTaskExecutePool.java
-
20system/src/main/java/com/storeroom/config/thread/AsyncTaskProperties.java
-
44system/src/main/java/com/storeroom/config/thread/TheadFactoryName.java
-
22system/src/main/java/com/storeroom/config/thread/ThreadPoolExecutorUtil.java
-
6system/src/main/java/com/storeroom/modules/security/config/ConfigBeanConfiguration.java
-
125system/src/main/java/com/storeroom/modules/security/controller/AuthorizationController.java
-
3system/src/main/java/com/storeroom/modules/security/security/JwtAccessDeniedHandler.java
-
7system/src/main/java/com/storeroom/modules/security/security/JwtAuthenticationEntryPoint.java
-
6system/src/main/java/com/storeroom/modules/security/service/dto/AuthUserDto.java
-
188system/src/main/java/com/storeroom/modules/system/controller/UserController.java
-
17system/src/main/java/com/storeroom/modules/system/repository/DictDetailRepository.java
-
3system/src/main/java/com/storeroom/modules/system/repository/DictRepository.java
-
102system/src/main/java/com/storeroom/modules/system/service/DeptService.java
-
66system/src/main/java/com/storeroom/modules/system/service/JobService.java
-
102system/src/main/java/com/storeroom/modules/system/service/MenuService.java
-
24system/src/main/java/com/storeroom/modules/system/service/dto/JobQueryCriteria.java
-
73system/src/main/java/com/storeroom/modules/system/service/impl/DataServiceImpl.java
-
267system/src/main/java/com/storeroom/modules/system/service/impl/DeptServiceImpl.java
-
80system/src/main/java/com/storeroom/modules/system/service/impl/DictDetailServiceImpl.java
-
104system/src/main/java/com/storeroom/modules/system/service/impl/DictServiceImpl.java
-
106system/src/main/java/com/storeroom/modules/system/service/impl/JobServiceImpl.java
-
339system/src/main/java/com/storeroom/modules/system/service/impl/MenuServiceImpl.java
-
68system/src/main/resources/application-dev.yml
-
43system/src/main/resources/application.yml
-
8system/src/main/resources/banner.txt
-
27system/src/main/resources/generator.properties
-
4system/src/main/resources/log4jdbc.log4j2.properties
-
45system/src/main/resources/logback.xml
@ -0,0 +1,18 @@ |
|||
package com.storeroom.config; |
|||
|
|||
|
|||
import lombok.Data; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Data |
|||
@Component |
|||
public class RsaProperties { |
|||
|
|||
public static String privateKey; |
|||
|
|||
@Value("${rsa.private_key}") |
|||
public void setPrivateKey(String privateKey) { |
|||
RsaProperties.privateKey = privateKey; |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
package com.storeroom.config; |
|||
|
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.web.cors.CorsConfiguration; |
|||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
|||
import org.springframework.web.filter.CorsFilter; |
|||
import org.springframework.web.servlet.config.annotation.EnableWebMvc; |
|||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; |
|||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
|||
|
|||
|
|||
@Configuration |
|||
@EnableWebMvc |
|||
public class ConfigurerAdapter implements WebMvcConfigurer { |
|||
|
|||
/** 文件配置 */ |
|||
private final FileProperties properties; |
|||
|
|||
public ConfigurerAdapter(FileProperties properties) { |
|||
this.properties = properties; |
|||
} |
|||
|
|||
@Bean |
|||
public CorsFilter corsFilter() { |
|||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); |
|||
CorsConfiguration config = new CorsConfiguration(); |
|||
config.setAllowCredentials(true); |
|||
config.addAllowedOriginPattern("*"); |
|||
config.addAllowedHeader("*"); |
|||
config.addAllowedMethod("*"); |
|||
|
|||
|
|||
source.registerCorsConfiguration("/**", config); |
|||
return new CorsFilter(source); |
|||
} |
|||
|
|||
@Override |
|||
public void addResourceHandlers(ResourceHandlerRegistry registry) { |
|||
FileProperties.YsPath path = properties.getPath(); |
|||
String avatarUtl = "file:" + path.getAvatar().replace("\\","/"); |
|||
String pathUtl = "file:" + path.getPath().replace("\\","/"); |
|||
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0); |
|||
registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0); |
|||
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0); |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
package com.storeroom.config; |
|||
|
|||
|
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.web.socket.server.standard.ServerEndpointExporter; |
|||
|
|||
@Configuration |
|||
public class WebSocketConfig { |
|||
|
|||
@Bean |
|||
public ServerEndpointExporter serverEndpointExporter() { |
|||
return new ServerEndpointExporter(); |
|||
} |
|||
} |
@ -0,0 +1,51 @@ |
|||
package com.storeroom.config.thread; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.scheduling.annotation.AsyncConfigurer; |
|||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
|||
|
|||
import java.util.concurrent.Executor; |
|||
import java.util.concurrent.ThreadPoolExecutor; |
|||
|
|||
|
|||
@Slf4j |
|||
@Configuration |
|||
public class AsyncTaskExecutePool implements AsyncConfigurer { |
|||
|
|||
/** 注入配置类 */ |
|||
private final AsyncTaskProperties config; |
|||
|
|||
public AsyncTaskExecutePool(AsyncTaskProperties config) { |
|||
this.config = config; |
|||
} |
|||
|
|||
@Override |
|||
public Executor getAsyncExecutor() { |
|||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
|||
//核心线程池大小 |
|||
executor.setCorePoolSize(config.getCorePoolSize()); |
|||
//最大线程数 |
|||
executor.setMaxPoolSize(config.getMaxPoolSize()); |
|||
//队列容量 |
|||
executor.setQueueCapacity(config.getQueueCapacity()); |
|||
//活跃时间 |
|||
executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); |
|||
//线程名字前缀 |
|||
executor.setThreadNamePrefix("yxk-async-"); |
|||
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 |
|||
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 |
|||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
|||
executor.initialize(); |
|||
return executor; |
|||
} |
|||
|
|||
@Override |
|||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { |
|||
return (throwable, method, objects) -> { |
|||
log.error("===="+throwable.getMessage()+"====", throwable); |
|||
log.error("exception method:"+method.getName()); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,20 @@ |
|||
package com.storeroom.config.thread; |
|||
|
|||
|
|||
import lombok.Data; |
|||
import org.springframework.boot.context.properties.ConfigurationProperties; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Data |
|||
@Component |
|||
@ConfigurationProperties(prefix = "task.pool") |
|||
public class AsyncTaskProperties { |
|||
|
|||
private int corePoolSize; |
|||
|
|||
private int maxPoolSize; |
|||
|
|||
private int keepAliveSeconds; |
|||
|
|||
private int queueCapacity; |
|||
} |
@ -0,0 +1,44 @@ |
|||
package com.storeroom.config.thread; |
|||
|
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.concurrent.ThreadFactory; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
|
|||
|
|||
@Component |
|||
public class TheadFactoryName implements ThreadFactory { |
|||
|
|||
private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1); |
|||
private final ThreadGroup group; |
|||
private final AtomicInteger threadNumber = new AtomicInteger(1); |
|||
private final String namePrefix; |
|||
|
|||
public TheadFactoryName() { |
|||
this("yxk-pool"); |
|||
} |
|||
|
|||
private TheadFactoryName(String name){ |
|||
SecurityManager s = System.getSecurityManager(); |
|||
group = (s != null) ? s.getThreadGroup() : |
|||
Thread.currentThread().getThreadGroup(); |
|||
//此时namePrefix就是 name + 第几个用这个工厂创建线程池的 |
|||
this.namePrefix = name + |
|||
POOL_NUMBER.getAndIncrement(); |
|||
} |
|||
|
|||
@Override |
|||
public Thread newThread(Runnable r) { |
|||
//此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程 |
|||
Thread t = new Thread(group, r, |
|||
namePrefix + "-thread-"+threadNumber.getAndIncrement(), |
|||
0); |
|||
if (t.isDaemon()) { |
|||
t.setDaemon(false); |
|||
} |
|||
if (t.getPriority() != Thread.NORM_PRIORITY) { |
|||
t.setPriority(Thread.NORM_PRIORITY); |
|||
} |
|||
return t; |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.storeroom.config.thread; |
|||
|
|||
import com.storeroom.utils.SpringContextHolder; |
|||
|
|||
import java.util.concurrent.ArrayBlockingQueue; |
|||
import java.util.concurrent.ThreadPoolExecutor; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
public class ThreadPoolExecutorUtil { |
|||
|
|||
public static ThreadPoolExecutor getPoll(){ |
|||
AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class); |
|||
return new ThreadPoolExecutor( |
|||
properties.getCorePoolSize(), |
|||
properties.getMaxPoolSize(), |
|||
properties.getKeepAliveSeconds(), |
|||
TimeUnit.SECONDS, |
|||
new ArrayBlockingQueue<>(properties.getQueueCapacity()), |
|||
new TheadFactoryName() |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,125 @@ |
|||
package com.storeroom.modules.security.controller; |
|||
|
|||
|
|||
import cn.hutool.core.util.IdUtil; |
|||
import com.storeroom.annotaion.rest.AnonymousDeleteMapping; |
|||
import com.storeroom.annotaion.rest.AnonymousGetMapping; |
|||
import com.storeroom.annotaion.rest.AnonymousPostMapping; |
|||
import com.storeroom.config.RsaProperties; |
|||
import com.storeroom.exception.BaseException; |
|||
import com.storeroom.exception.constant.ResponseStatus; |
|||
import com.storeroom.modules.security.config.bean.LoginCodeEnum; |
|||
import com.storeroom.modules.security.config.bean.LoginProperties; |
|||
import com.storeroom.modules.security.config.bean.SecurityProperties; |
|||
import com.storeroom.modules.security.security.TokenProvider; |
|||
import com.storeroom.modules.security.service.OnlineUserService; |
|||
import com.storeroom.modules.security.service.dto.AuthUserDto; |
|||
import com.storeroom.modules.security.service.dto.JwtUserDto; |
|||
import com.storeroom.utils.*; |
|||
import com.storeroom.utils.enums.DataStatusEnum; |
|||
import com.wf.captcha.base.Captcha; |
|||
import io.swagger.annotations.Api; |
|||
import io.swagger.annotations.ApiOperation; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
|||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
|||
import org.springframework.security.core.Authentication; |
|||
import org.springframework.security.core.context.SecurityContextHolder; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import javax.annotation.Resource; |
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
@Slf4j |
|||
@RestController |
|||
@RequestMapping("/auth") |
|||
@RequiredArgsConstructor |
|||
@Api(tags = "系统:系统授权接口") |
|||
public class AuthorizationController { |
|||
|
|||
private final SecurityProperties properties; |
|||
private final RedisUtils redisUtils; |
|||
private final OnlineUserService onlineUserService; |
|||
private final TokenProvider tokenProvider; |
|||
private final AuthenticationManagerBuilder authenticationManagerBuilder; |
|||
|
|||
@Resource |
|||
private LoginProperties loginProperties; |
|||
|
|||
|
|||
@ApiOperation("登录授权") |
|||
@AnonymousPostMapping(value = "/login") |
|||
public ApiResponse<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception { |
|||
// 密码解密 |
|||
String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword()); |
|||
// 查询验证码 |
|||
String code = (String) redisUtils.get(authUser.getUuid()); |
|||
// 清除验证码 |
|||
redisUtils.del(authUser.getUuid()); |
|||
if (StringUtils.isBlank(code)) { |
|||
throw new BaseException("验证码不存在或已过期"); |
|||
} |
|||
if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) { |
|||
throw new BaseException("验证码错误"); |
|||
} |
|||
UsernamePasswordAuthenticationToken authenticationToken = |
|||
new UsernamePasswordAuthenticationToken(authUser.getUsername(), password); |
|||
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); |
|||
SecurityContextHolder.getContext().setAuthentication(authentication); |
|||
String token = tokenProvider.createToken(authentication); |
|||
final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal(); |
|||
// 保存在线信息 |
|||
onlineUserService.save(jwtUserDto, token, request); |
|||
// 返回 token 与 用户信息 |
|||
Map<String, Object> authInfo = new HashMap<String, Object>(2) {{ |
|||
put("token", properties.getTokenStartWith() + token); |
|||
put("user", jwtUserDto); |
|||
}}; |
|||
if (loginProperties.isSingleLogin()) { |
|||
//踢掉之前已经登录的token |
|||
onlineUserService.checkLoginOnUser(authUser.getUsername(), token); |
|||
} |
|||
return ApiResponse.success(authInfo); |
|||
} |
|||
|
|||
@ApiOperation("获取用户信息") |
|||
@GetMapping(value = "/info") |
|||
public ApiResponse<Object> getUserInfo() { |
|||
return ApiResponse.success(SecurityUtils.getCurrentUser()); |
|||
} |
|||
|
|||
@ApiOperation("获取验证码") |
|||
@AnonymousGetMapping(value = "/code") |
|||
public ApiResponse<Object> getCode() { |
|||
// 获取运算的结果 |
|||
Captcha captcha = loginProperties.getCaptcha(); |
|||
String uuid = properties.getCodeKey() + IdUtil.simpleUUID(); |
|||
//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型 |
|||
String captchaValue = captcha.text(); |
|||
if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(".")) { |
|||
captchaValue = captchaValue.split("\\.")[0]; |
|||
} |
|||
// 保存 |
|||
redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES); |
|||
// 验证码信息 |
|||
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{ |
|||
put("img", captcha.toBase64()); |
|||
put("uuid", uuid); |
|||
}}; |
|||
return ApiResponse.success(imgResult); |
|||
} |
|||
|
|||
@ApiOperation("退出登录") |
|||
@AnonymousDeleteMapping(value = "/logout") |
|||
public ApiResponse<Object> logout(HttpServletRequest request) { |
|||
onlineUserService.logout(tokenProvider.getToken(request)); |
|||
return ApiResponse.success(ResponseStatus.SUCCESS); |
|||
} |
|||
} |
@ -0,0 +1,188 @@ |
|||
package com.storeroom.modules.system.controller; |
|||
|
|||
|
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.storeroom.config.RsaProperties; |
|||
import com.storeroom.exception.BaseException; |
|||
import com.storeroom.modules.system.domain.Dept; |
|||
import com.storeroom.modules.system.domain.User; |
|||
import com.storeroom.modules.system.domain.vo.UserPassVo; |
|||
import com.storeroom.modules.system.service.DataService; |
|||
import com.storeroom.modules.system.service.DeptService; |
|||
import com.storeroom.modules.system.service.RoleService; |
|||
import com.storeroom.modules.system.service.UserService; |
|||
import com.storeroom.modules.system.service.dto.RoleSmallDto; |
|||
import com.storeroom.modules.system.service.dto.UserDto; |
|||
import com.storeroom.modules.system.service.dto.UserQueryCriteria; |
|||
import com.storeroom.utils.PageUtil; |
|||
import com.storeroom.utils.RsaUtils; |
|||
import com.storeroom.utils.SecurityUtils; |
|||
import io.swagger.annotations.Api; |
|||
import io.swagger.annotations.ApiOperation; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.security.crypto.password.PasswordEncoder; |
|||
import org.springframework.util.CollectionUtils; |
|||
import org.springframework.util.ObjectUtils; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.*; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.Set; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Api(tags = "系统:用户管理") |
|||
@RestController |
|||
@RequestMapping("/api/users") |
|||
@RequiredArgsConstructor |
|||
public class UserController { |
|||
|
|||
|
|||
private final PasswordEncoder passwordEncoder; |
|||
private final UserService userService; |
|||
private final DataService dataService; |
|||
private final DeptService deptService; |
|||
private final RoleService roleService; |
|||
|
|||
|
|||
|
|||
@ApiOperation("导出用户数据") |
|||
@GetMapping(value = "/download") |
|||
@PreAuthorize("@el.check('user:list')") |
|||
public void exportUser(HttpServletResponse response, UserQueryCriteria criteria) throws IOException { |
|||
userService.download(userService.queryAll(criteria), response); |
|||
} |
|||
|
|||
@ApiOperation("查询用户") |
|||
@GetMapping |
|||
@PreAuthorize("@el.check('user:list')") |
|||
public ResponseEntity<Object> queryUser(UserQueryCriteria criteria, Pageable pageable){ |
|||
if (!ObjectUtils.isEmpty(criteria.getDeptId())) { |
|||
criteria.getDeptIds().add(criteria.getDeptId()); |
|||
// 先查找是否存在子节点 |
|||
List<Dept> data = deptService.findByPid(criteria.getDeptId()); |
|||
// 然后把子节点的ID都加入到集合中 |
|||
criteria.getDeptIds().addAll(deptService.getDeptChildren(data)); |
|||
} |
|||
// 数据权限 |
|||
List<Long> dataScopes = dataService.getDeptIds(userService.findByName(SecurityUtils.getCurrentUsername())); |
|||
// criteria.getDeptIds() 不为空并且数据权限不为空则取交集 |
|||
if (!CollectionUtils.isEmpty(criteria.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)){ |
|||
// 取交集 |
|||
criteria.getDeptIds().retainAll(dataScopes); |
|||
if(!CollectionUtil.isEmpty(criteria.getDeptIds())){ |
|||
return new ResponseEntity<>(userService.queryAll(criteria,pageable), HttpStatus.OK); |
|||
} |
|||
} else { |
|||
// 否则取并集 |
|||
criteria.getDeptIds().addAll(dataScopes); |
|||
return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); |
|||
} |
|||
return new ResponseEntity<>(PageUtil.toPage(null,0),HttpStatus.OK); |
|||
} |
|||
|
|||
//@Log("新增用户") |
|||
@ApiOperation("新增用户") |
|||
@PostMapping |
|||
@PreAuthorize("@el.check('user:add')") |
|||
public ResponseEntity<Object> createUser(@Validated @RequestBody User resources){ |
|||
checkLevel(resources); |
|||
// 默认密码 123456 |
|||
resources.setPassword(passwordEncoder.encode("123456")); |
|||
userService.create(resources); |
|||
return new ResponseEntity<>(HttpStatus.CREATED); |
|||
} |
|||
|
|||
//@Log("修改用户") |
|||
@ApiOperation("修改用户") |
|||
@PutMapping |
|||
@PreAuthorize("@el.check('user:edit')") |
|||
public ResponseEntity<Object> updateUser(@Validated(User.Update.class) @RequestBody User resources) throws Exception { |
|||
checkLevel(resources); |
|||
userService.update(resources); |
|||
return new ResponseEntity<>(HttpStatus.NO_CONTENT); |
|||
} |
|||
|
|||
//@Log("修改用户:个人中心") |
|||
@ApiOperation("修改用户:个人中心") |
|||
@PutMapping(value = "center") |
|||
public ResponseEntity<Object> centerUser(@Validated(User.Update.class) @RequestBody User resources){ |
|||
if(!resources.getId().equals(SecurityUtils.getCurrentUserId())){ |
|||
throw new BaseException("不能修改他人资料"); |
|||
} |
|||
userService.updateCenter(resources); |
|||
return new ResponseEntity<>(HttpStatus.NO_CONTENT); |
|||
} |
|||
|
|||
//@Log("删除用户") |
|||
@ApiOperation("删除用户") |
|||
@DeleteMapping |
|||
@PreAuthorize("@el.check('user:del')") |
|||
public ResponseEntity<Object> deleteUser(@RequestBody Set<Long> ids){ |
|||
for (Long id : ids) { |
|||
Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); |
|||
Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); |
|||
if (currentLevel > optLevel) { |
|||
throw new BaseException("角色权限不足,不能删除:" + userService.findById(id).getUsername()); |
|||
} |
|||
} |
|||
userService.delete(ids); |
|||
return new ResponseEntity<>(HttpStatus.OK); |
|||
} |
|||
|
|||
@ApiOperation("修改密码") |
|||
@PostMapping(value = "/updatePass") |
|||
public ResponseEntity<Object> updateUserPass(@RequestBody UserPassVo passVo) throws Exception { |
|||
String oldPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getOldPass()); |
|||
String newPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getNewPass()); |
|||
UserDto user = userService.findByName(SecurityUtils.getCurrentUsername()); |
|||
if(!passwordEncoder.matches(oldPass, user.getPassword())){ |
|||
throw new BaseException("修改失败,旧密码错误"); |
|||
} |
|||
if(passwordEncoder.matches(newPass, user.getPassword())){ |
|||
throw new BaseException("新密码不能与旧密码相同"); |
|||
} |
|||
userService.updatePass(user.getUsername(),passwordEncoder.encode(newPass)); |
|||
return new ResponseEntity<>(HttpStatus.OK); |
|||
} |
|||
|
|||
@ApiOperation("修改头像") |
|||
@PostMapping(value = "/updateAvatar") |
|||
public ResponseEntity<Object> updateUserAvatar(@RequestParam MultipartFile avatar){ |
|||
return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK); |
|||
} |
|||
|
|||
//@Log("修改邮箱") |
|||
// @ApiOperation("修改邮箱") |
|||
// @PostMapping(value = "/updateEmail/{code}") |
|||
// public ResponseEntity<Object> updateUserEmail(@PathVariable String code,@RequestBody User user) throws Exception { |
|||
// String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,user.getPassword()); |
|||
// UserDto userDto = userService.findByName(SecurityUtils.getCurrentUsername()); |
|||
// if(!passwordEncoder.matches(password, userDto.getPassword())){ |
|||
// throw new BaseException("密码错误"); |
|||
// } |
|||
// verificationCodeService.validated(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey() + user.getEmail(), code); |
|||
// userService.updateEmail(userDto.getUsername(),user.getEmail()); |
|||
// return new ResponseEntity<>(HttpStatus.OK); |
|||
// } |
|||
|
|||
/** |
|||
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误 |
|||
* @param resources / |
|||
*/ |
|||
private void checkLevel(User resources) { |
|||
Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); |
|||
Integer optLevel = roleService.findByRoles(resources.getRoles()); |
|||
if (currentLevel > optLevel) { |
|||
throw new BaseException("角色权限不足"); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.storeroom.modules.system.repository; |
|||
|
|||
import com.storeroom.modules.system.domain.DictDetail; |
|||
import org.springframework.data.jpa.repository.JpaRepository; |
|||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface DictDetailRepository extends JpaRepository<DictDetail, Long>, JpaSpecificationExecutor<DictDetail> { |
|||
|
|||
/** |
|||
* 根据字典名称查询 |
|||
* @param name / |
|||
* @return / |
|||
*/ |
|||
List<DictDetail> findByDictName(String name); |
|||
} |
@ -1,4 +1,106 @@ |
|||
package com.storeroom.modules.system.service; |
|||
|
|||
import com.storeroom.modules.system.domain.Dept; |
|||
import com.storeroom.modules.system.service.dto.DeptDto; |
|||
import com.storeroom.modules.system.service.dto.DeptQueryCriteria; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.List; |
|||
import java.util.Set; |
|||
|
|||
public interface DeptService { |
|||
|
|||
/** |
|||
* 查询所有数据 |
|||
* @param criteria 条件 |
|||
* @param isQuery / |
|||
* @throws Exception / |
|||
* @return / |
|||
*/ |
|||
List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception; |
|||
|
|||
/** |
|||
* 根据ID查询 |
|||
* @param id / |
|||
* @return / |
|||
*/ |
|||
DeptDto findById(Long id); |
|||
|
|||
/** |
|||
* 创建 |
|||
* @param resources / |
|||
*/ |
|||
void create(Dept resources); |
|||
|
|||
/** |
|||
* 编辑 |
|||
* @param resources / |
|||
*/ |
|||
void update(Dept resources); |
|||
|
|||
/** |
|||
* 删除 |
|||
* @param deptDtos / |
|||
* |
|||
*/ |
|||
void delete(Set<DeptDto> deptDtos); |
|||
|
|||
/** |
|||
* 根据PID查询 |
|||
* @param pid / |
|||
* @return / |
|||
*/ |
|||
List<Dept> findByPid(long pid); |
|||
|
|||
/** |
|||
* 根据角色ID查询 |
|||
* @param id / |
|||
* @return / |
|||
*/ |
|||
Set<Dept> findByRoleId(Long id); |
|||
|
|||
/** |
|||
* 导出数据 |
|||
* @param queryAll 待导出的数据 |
|||
* @param response / |
|||
* @throws IOException / |
|||
*/ |
|||
void download(List<DeptDto> queryAll, HttpServletResponse response) throws IOException; |
|||
|
|||
/** |
|||
* 获取待删除的部门 |
|||
* @param deptList / |
|||
* @param deptDtos / |
|||
* @return / |
|||
*/ |
|||
Set<DeptDto> getDeleteDepts(List<Dept> deptList, Set<DeptDto> deptDtos); |
|||
|
|||
/** |
|||
* 根据ID获取同级与上级数据 |
|||
* @param deptDto / |
|||
* @param depts / |
|||
* @return / |
|||
*/ |
|||
List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts); |
|||
|
|||
/** |
|||
* 构建树形数据 |
|||
* @param deptDtos / |
|||
* @return / |
|||
*/ |
|||
Object buildTree(List<DeptDto> deptDtos); |
|||
|
|||
/** |
|||
* 获取 |
|||
* @param deptList |
|||
* @return |
|||
*/ |
|||
List<Long> getDeptChildren(List<Dept> deptList); |
|||
|
|||
/** |
|||
* 验证是否被角色或用户关联 |
|||
* @param deptDtos / |
|||
*/ |
|||
void verification(Set<DeptDto> deptDtos); |
|||
} |
@ -1,4 +1,70 @@ |
|||
package com.storeroom.modules.system.service; |
|||
|
|||
import com.storeroom.modules.system.domain.Job; |
|||
import com.storeroom.modules.system.service.dto.JobDto; |
|||
import com.storeroom.modules.system.service.dto.JobQueryCriteria; |
|||
import org.springframework.data.domain.Pageable; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Set; |
|||
|
|||
public interface JobService { |
|||
|
|||
/** |
|||
* 根据ID查询 |
|||
* @param id / |
|||
* @return / |
|||
*/ |
|||
JobDto findById(Long id); |
|||
|
|||
/** |
|||
* 创建 |
|||
* @param resources / |
|||
* @return / |
|||
*/ |
|||
void create(Job resources); |
|||
|
|||
/** |
|||
* 编辑 |
|||
* @param resources / |
|||
*/ |
|||
void update(Job resources); |
|||
|
|||
/** |
|||
* 删除 |
|||
* @param ids / |
|||
*/ |
|||
void delete(Set<Long> ids); |
|||
|
|||
/** |
|||
* 分页查询 |
|||
* @param criteria 条件 |
|||
* @param pageable 分页参数 |
|||
* @return / |
|||
*/ |
|||
Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable); |
|||
|
|||
/** |
|||
* 查询全部数据 |
|||
* @param criteria / |
|||
* @return / |
|||
*/ |
|||
List<JobDto> queryAll(JobQueryCriteria criteria); |
|||
|
|||
/** |
|||
* 导出数据 |
|||
* @param queryAll 待导出的数据 |
|||
* @param response / |
|||
* @throws IOException / |
|||
*/ |
|||
void download(List<JobDto> queryAll, HttpServletResponse response) throws IOException; |
|||
|
|||
/** |
|||
* 验证是否被用户关联 |
|||
* @param ids / |
|||
*/ |
|||
void verification(Set<Long> ids); |
|||
} |
@ -1,4 +1,106 @@ |
|||
package com.storeroom.modules.system.service; |
|||
|
|||
import com.storeroom.modules.system.domain.Menu; |
|||
import com.storeroom.modules.system.service.dto.MenuDto; |
|||
import com.storeroom.modules.system.service.dto.MenuQueryCriteria; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.List; |
|||
import java.util.Set; |
|||
|
|||
public interface MenuService { |
|||
|
|||
/** |
|||
* 查询全部数据 |
|||
* @param criteria 条件 |
|||
* @param isQuery / |
|||
* @throws Exception / |
|||
* @return / |
|||
*/ |
|||
List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception; |
|||
|
|||
/** |
|||
* 根据ID查询 |
|||
* @param id / |
|||
* @return / |
|||
*/ |
|||
MenuDto findById(long id); |
|||
|
|||
/** |
|||
* 创建 |
|||
* @param resources / |
|||
*/ |
|||
void create(Menu resources); |
|||
|
|||
/** |
|||
* 编辑 |
|||
* @param resources / |
|||
*/ |
|||
void update(Menu resources); |
|||
|
|||
/** |
|||
* 获取所有子节点,包含自身ID |
|||
* @param menuList / |
|||
* @param menuSet / |
|||
* @return / |
|||
*/ |
|||
Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet); |
|||
|
|||
/** |
|||
* 构建菜单树 |
|||
* @param menuDtos 原始数据 |
|||
* @return / |
|||
*/ |
|||
List<MenuDto> buildTree(List<MenuDto> menuDtos); |
|||
|
|||
/** |
|||
* 构建菜单树 |
|||
* @param menuDtos / |
|||
* @return / |
|||
*/ |
|||
Object buildMenus(List<MenuDto> menuDtos); |
|||
|
|||
/** |
|||
* 根据ID查询 |
|||
* @param id / |
|||
* @return / |
|||
*/ |
|||
Menu findOne(Long id); |
|||
|
|||
/** |
|||
* 删除 |
|||
* @param menuSet / |
|||
*/ |
|||
void delete(Set<Menu> menuSet); |
|||
|
|||
/** |
|||
* 导出 |
|||
* @param queryAll 待导出的数据 |
|||
* @param response / |
|||
* @throws IOException / |
|||
*/ |
|||
void download(List<MenuDto> queryAll, HttpServletResponse response) throws IOException; |
|||
|
|||
/** |
|||
* 懒加载菜单数据 |
|||
* @param pid / |
|||
* @return / |
|||
*/ |
|||
List<MenuDto> getMenus(Long pid); |
|||
|
|||
/** |
|||
* 根据ID获取同级与上级数据 |
|||
* @param menuDto / |
|||
* @param objects / |
|||
* @return / |
|||
*/ |
|||
List<MenuDto> getSuperior(MenuDto menuDto, List<Menu> objects); |
|||
|
|||
/** |
|||
* 根据当前用户获取菜单 |
|||
* @param currentUserId / |
|||
* @return / |
|||
*/ |
|||
List<MenuDto> findByUser(Long currentUserId); |
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.storeroom.modules.system.service.dto; |
|||
|
|||
import com.storeroom.annotaion.Query; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
|
|||
import java.sql.Timestamp; |
|||
import java.util.List; |
|||
|
|||
|
|||
@Data |
|||
@NoArgsConstructor |
|||
public class JobQueryCriteria { |
|||
|
|||
|
|||
@Query(type = Query.Type.INNER_LIKE) |
|||
private String name; |
|||
|
|||
@Query |
|||
private Boolean enabled; |
|||
|
|||
@Query(type = Query.Type.BETWEEN) |
|||
private List<Timestamp> createTime; |
|||
} |
@ -0,0 +1,73 @@ |
|||
package com.storeroom.modules.system.service.impl; |
|||
|
|||
|
|||
import com.storeroom.modules.system.domain.Dept; |
|||
import com.storeroom.modules.system.service.DataService; |
|||
import com.storeroom.modules.system.service.DeptService; |
|||
import com.storeroom.modules.system.service.RoleService; |
|||
import com.storeroom.modules.system.service.dto.RoleSmallDto; |
|||
import com.storeroom.modules.system.service.dto.UserDto; |
|||
import com.storeroom.utils.enums.DataScopeEnum; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.annotation.CacheConfig; |
|||
import org.springframework.cache.annotation.Cacheable; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.*; |
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@CacheConfig(cacheNames = "data") |
|||
public class DataServiceImpl implements DataService { |
|||
|
|||
private final RoleService roleService; |
|||
private final DeptService deptService; |
|||
|
|||
|
|||
/** |
|||
* 用户角色改变时需清理缓存 |
|||
* @param user / |
|||
* @return / |
|||
*/ |
|||
@Override |
|||
@Cacheable(key = "'user:' + #p0.id") |
|||
public List<Long> getDeptIds(UserDto user) { |
|||
// 用于存储部门id |
|||
Set<Long> deptIds = new HashSet<>(); |
|||
// 查询用户角色 |
|||
List<RoleSmallDto> roleSet = roleService.findByUsersId(user.getId()); |
|||
// 获取对应的部门ID |
|||
for (RoleSmallDto role : roleSet) { |
|||
DataScopeEnum dataScopeEnum = DataScopeEnum.find(role.getDataScope()); |
|||
switch (Objects.requireNonNull(dataScopeEnum)) { |
|||
case THIS_LEVEL: |
|||
deptIds.add(user.getDept().getId()); |
|||
break; |
|||
case CUSTOMIZE: |
|||
deptIds.addAll(getCustomize(deptIds, role)); |
|||
break; |
|||
default: |
|||
return new ArrayList<>(deptIds); |
|||
} |
|||
} |
|||
return new ArrayList<>(deptIds); |
|||
} |
|||
|
|||
/** |
|||
* 获取自定义的数据权限 |
|||
* @param deptIds 部门ID |
|||
* @param role 角色 |
|||
* @return 数据权限ID |
|||
*/ |
|||
public Set<Long> getCustomize(Set<Long> deptIds, RoleSmallDto role){ |
|||
Set<Dept> depts = deptService.findByRoleId(role.getId()); |
|||
for (Dept dept : depts) { |
|||
deptIds.add(dept.getId()); |
|||
List<Dept> deptChildren = deptService.findByPid(dept.getId()); |
|||
if (deptChildren != null && deptChildren.size() != 0) { |
|||
deptIds.addAll(deptService.getDeptChildren(deptChildren)); |
|||
} |
|||
} |
|||
return deptIds; |
|||
} |
|||
} |
@ -0,0 +1,267 @@ |
|||
package com.storeroom.modules.system.service.impl; |
|||
|
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.storeroom.exception.BaseException; |
|||
import com.storeroom.modules.system.domain.Dept; |
|||
import com.storeroom.modules.system.domain.User; |
|||
import com.storeroom.modules.system.repository.DeptRepository; |
|||
import com.storeroom.modules.system.repository.RoleRepository; |
|||
import com.storeroom.modules.system.repository.UserRepository; |
|||
import com.storeroom.modules.system.service.DeptService; |
|||
import com.storeroom.modules.system.service.dto.DeptDto; |
|||
import com.storeroom.modules.system.service.dto.DeptQueryCriteria; |
|||
import com.storeroom.modules.system.service.mapstruct.DeptMapper; |
|||
import com.storeroom.utils.*; |
|||
import com.storeroom.utils.enums.DataScopeEnum; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.annotation.CacheConfig; |
|||
import org.springframework.cache.annotation.Cacheable; |
|||
import org.springframework.data.domain.Sort; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.lang.reflect.Field; |
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@CacheConfig(cacheNames = "dept") |
|||
public class DeptServiceImpl implements DeptService { |
|||
|
|||
private final DeptRepository deptRepository; |
|||
private final DeptMapper deptMapper; |
|||
private final UserRepository userRepository; |
|||
private final RedisUtils redisUtils; |
|||
private final RoleRepository roleRepository; |
|||
|
|||
|
|||
@Override |
|||
public List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception { |
|||
Sort sort = Sort.by(Sort.Direction.ASC, "deptSort"); |
|||
String dataScopeType = SecurityUtils.getDataScopeType(); |
|||
if (isQuery) { |
|||
if(dataScopeType.equals(DataScopeEnum.ALL.getValue())){ |
|||
criteria.setPidIsNull(true); |
|||
} |
|||
List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>()); |
|||
List<String> fieldNames = new ArrayList<String>(){{ add("pidIsNull");add("enabled");}}; |
|||
for (Field field : fields) { |
|||
//设置对象的访问权限,保证对private的属性的访问 |
|||
field.setAccessible(true); |
|||
Object val = field.get(criteria); |
|||
if(fieldNames.contains(field.getName())){ |
|||
continue; |
|||
} |
|||
if (ObjectUtil.isNotNull(val)) { |
|||
criteria.setPidIsNull(null); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
List<DeptDto> list = deptMapper.toDto(deptRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort)); |
|||
// 如果为空,就代表为自定义权限或者本级权限,就需要去重,不理解可以注释掉,看查询结果 |
|||
if(StringUtils.isBlank(dataScopeType)){ |
|||
return deduplication(list); |
|||
} |
|||
return list; |
|||
} |
|||
|
|||
@Override |
|||
@Cacheable(key = "'id:' + #p0") |
|||
public DeptDto findById(Long id) { |
|||
Dept dept = deptRepository.findById(id).orElseGet(Dept::new); |
|||
ValidationUtil.isNull(dept.getId(),"Dept","id",id); |
|||
return deptMapper.toDto(dept); |
|||
} |
|||
|
|||
@Override |
|||
public List<Dept> findByPid(long pid) { |
|||
return deptRepository.findByPid(pid); |
|||
} |
|||
|
|||
@Override |
|||
public Set<Dept> findByRoleId(Long id) { |
|||
return deptRepository.findByRoleId(id); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void create(Dept resources) { |
|||
deptRepository.save(resources); |
|||
// 计算子节点数目 |
|||
resources.setSubCount(0); |
|||
// 清理缓存 |
|||
updateSubCnt(resources.getPid()); |
|||
// 清理自定义角色权限的datascope缓存 |
|||
delCaches(resources.getPid()); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void update(Dept resources) { |
|||
// 旧的部门 |
|||
Long oldPid = findById(resources.getId()).getPid(); |
|||
Long newPid = resources.getPid(); |
|||
if(resources.getPid() != null && resources.getId().equals(resources.getPid())) { |
|||
throw new BaseException("上级不能为自己"); |
|||
} |
|||
Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new); |
|||
ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId()); |
|||
resources.setId(dept.getId()); |
|||
deptRepository.save(resources); |
|||
// 更新父节点中子节点数目 |
|||
updateSubCnt(oldPid); |
|||
updateSubCnt(newPid); |
|||
// 清理缓存 |
|||
delCaches(resources.getId()); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void delete(Set<DeptDto> deptDtos) { |
|||
for (DeptDto deptDto : deptDtos) { |
|||
// 清理缓存 |
|||
delCaches(deptDto.getId()); |
|||
deptRepository.deleteById(deptDto.getId()); |
|||
updateSubCnt(deptDto.getPid()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void download(List<DeptDto> deptDtos, HttpServletResponse response) throws IOException { |
|||
List<Map<String, Object>> list = new ArrayList<>(); |
|||
for (DeptDto deptDTO : deptDtos) { |
|||
Map<String,Object> map = new LinkedHashMap<>(); |
|||
map.put("部门名称", deptDTO.getName()); |
|||
map.put("部门状态", deptDTO.getEnabled() ? "启用" : "停用"); |
|||
map.put("创建日期", deptDTO.getCreateTime()); |
|||
list.add(map); |
|||
} |
|||
FileUtil.downloadExcel(list, response); |
|||
} |
|||
|
|||
@Override |
|||
public Set<DeptDto> getDeleteDepts(List<Dept> menuList, Set<DeptDto> deptDtos) { |
|||
for (Dept dept : menuList) { |
|||
deptDtos.add(deptMapper.toDto(dept)); |
|||
List<Dept> depts = deptRepository.findByPid(dept.getId()); |
|||
if(depts!=null && depts.size()!=0){ |
|||
getDeleteDepts(depts, deptDtos); |
|||
} |
|||
} |
|||
return deptDtos; |
|||
} |
|||
|
|||
@Override |
|||
public List<Long> getDeptChildren(List<Dept> deptList) { |
|||
List<Long> list = new ArrayList<>(); |
|||
deptList.forEach(dept -> { |
|||
if (dept!=null && dept.getEnabled()) { |
|||
List<Dept> depts = deptRepository.findByPid(dept.getId()); |
|||
if (depts.size() != 0) { |
|||
list.addAll(getDeptChildren(depts)); |
|||
} |
|||
list.add(dept.getId()); |
|||
} |
|||
} |
|||
); |
|||
return list; |
|||
} |
|||
|
|||
@Override |
|||
public List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts) { |
|||
if(deptDto.getPid() == null){ |
|||
depts.addAll(deptRepository.findByPidIsNull()); |
|||
return deptMapper.toDto(depts); |
|||
} |
|||
depts.addAll(deptRepository.findByPid(deptDto.getPid())); |
|||
return getSuperior(findById(deptDto.getPid()), depts); |
|||
} |
|||
|
|||
@Override |
|||
public Object buildTree(List<DeptDto> deptDtos) { |
|||
Set<DeptDto> trees = new LinkedHashSet<>(); |
|||
Set<DeptDto> depts= new LinkedHashSet<>(); |
|||
List<String> deptNames = deptDtos.stream().map(DeptDto::getName).collect(Collectors.toList()); |
|||
boolean isChild; |
|||
for (DeptDto deptDTO : deptDtos) { |
|||
isChild = false; |
|||
if (deptDTO.getPid() == null) { |
|||
trees.add(deptDTO); |
|||
} |
|||
for (DeptDto it : deptDtos) { |
|||
if (it.getPid() != null && deptDTO.getId().equals(it.getPid())) { |
|||
isChild = true; |
|||
if (deptDTO.getChildren() == null) { |
|||
deptDTO.setChildren(new ArrayList<>()); |
|||
} |
|||
deptDTO.getChildren().add(it); |
|||
} |
|||
} |
|||
if(isChild) { |
|||
depts.add(deptDTO); |
|||
} else if(deptDTO.getPid() != null && !deptNames.contains(findById(deptDTO.getPid()).getName())) { |
|||
depts.add(deptDTO); |
|||
} |
|||
} |
|||
|
|||
if (CollectionUtil.isEmpty(trees)) { |
|||
trees = depts; |
|||
} |
|||
Map<String,Object> map = new HashMap<>(2); |
|||
map.put("totalElements",deptDtos.size()); |
|||
map.put("content",CollectionUtil.isEmpty(trees)? deptDtos :trees); |
|||
return map; |
|||
} |
|||
|
|||
@Override |
|||
public void verification(Set<DeptDto> deptDtos) { |
|||
Set<Long> deptIds = deptDtos.stream().map(DeptDto::getId).collect(Collectors.toSet()); |
|||
if(userRepository.countByDepts(deptIds) > 0){ |
|||
throw new BaseException("所选部门存在用户关联,请解除后再试!"); |
|||
} |
|||
if(roleRepository.countByDepts(deptIds) > 0){ |
|||
throw new BaseException("所选部门存在角色关联,请解除后再试!"); |
|||
} |
|||
} |
|||
|
|||
private void updateSubCnt(Long deptId){ |
|||
if(deptId != null){ |
|||
int count = deptRepository.countByPid(deptId); |
|||
deptRepository.updateSubCntById(count, deptId); |
|||
} |
|||
} |
|||
|
|||
private List<DeptDto> deduplication(List<DeptDto> list) { |
|||
List<DeptDto> deptDtos = new ArrayList<>(); |
|||
for (DeptDto deptDto : list) { |
|||
boolean flag = true; |
|||
for (DeptDto dto : list) { |
|||
if (dto.getId().equals(deptDto.getPid())) { |
|||
flag = false; |
|||
break; |
|||
} |
|||
} |
|||
if (flag){ |
|||
deptDtos.add(deptDto); |
|||
} |
|||
} |
|||
return deptDtos; |
|||
} |
|||
|
|||
/** |
|||
* 清理缓存 |
|||
* @param id / |
|||
*/ |
|||
public void delCaches(Long id){ |
|||
List<User> users = userRepository.findByRoleDeptId(id); |
|||
// 删除数据权限 |
|||
redisUtils.delByKeys(CacheKey.DATA_USER, users.stream().map(User::getId).collect(Collectors.toSet())); |
|||
redisUtils.del(CacheKey.DEPT_ID + id); |
|||
} |
|||
} |
@ -0,0 +1,80 @@ |
|||
package com.storeroom.modules.system.service.impl; |
|||
|
|||
import com.storeroom.modules.system.domain.Dict; |
|||
import com.storeroom.modules.system.domain.DictDetail; |
|||
import com.storeroom.modules.system.repository.DictDetailRepository; |
|||
import com.storeroom.modules.system.repository.DictRepository; |
|||
import com.storeroom.modules.system.service.DictDetailService; |
|||
import com.storeroom.modules.system.service.dto.DictDetailDto; |
|||
import com.storeroom.modules.system.service.dto.DictDetailQueryCriteria; |
|||
import com.storeroom.modules.system.service.mapstruct.DictDetailMapper; |
|||
import com.storeroom.utils.*; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.annotation.CacheConfig; |
|||
import org.springframework.cache.annotation.Cacheable; |
|||
import org.springframework.data.domain.Page; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@CacheConfig(cacheNames = "dict") |
|||
public class DictDetailServiceImpl implements DictDetailService { |
|||
|
|||
|
|||
private final DictRepository dictRepository; |
|||
private final DictDetailRepository dictDetailRepository; |
|||
private final DictDetailMapper dictDetailMapper; |
|||
private final RedisUtils redisUtils; |
|||
|
|||
|
|||
@Override |
|||
public Map<String,Object> queryAll(DictDetailQueryCriteria criteria, Pageable pageable) { |
|||
Page<DictDetail> page = dictDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); |
|||
return PageUtil.toPage(page.map(dictDetailMapper::toDto)); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void create(DictDetail resources) { |
|||
dictDetailRepository.save(resources); |
|||
// 清理缓存 |
|||
delCaches(resources); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void update(DictDetail resources) { |
|||
DictDetail dictDetail = dictDetailRepository.findById(resources.getId()).orElseGet(DictDetail::new); |
|||
ValidationUtil.isNull( dictDetail.getId(),"DictDetail","id",resources.getId()); |
|||
resources.setId(dictDetail.getId()); |
|||
dictDetailRepository.save(resources); |
|||
// 清理缓存 |
|||
delCaches(resources); |
|||
} |
|||
|
|||
@Override |
|||
@Cacheable(key = "'name:' + #p0") |
|||
public List<DictDetailDto> getDictByName(String name) { |
|||
return dictDetailMapper.toDto(dictDetailRepository.findByDictName(name)); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void delete(Long id) { |
|||
DictDetail dictDetail = dictDetailRepository.findById(id).orElseGet(DictDetail::new); |
|||
// 清理缓存 |
|||
delCaches(dictDetail); |
|||
dictDetailRepository.deleteById(id); |
|||
} |
|||
|
|||
public void delCaches(DictDetail dictDetail){ |
|||
Dict dict = dictRepository.findById(dictDetail.getDict().getId()).orElseGet(Dict::new); |
|||
redisUtils.del(CacheKey.DICT_NAME + dict.getName()); |
|||
} |
|||
} |
@ -0,0 +1,104 @@ |
|||
package com.storeroom.modules.system.service.impl; |
|||
|
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.storeroom.modules.system.domain.Dict; |
|||
import com.storeroom.modules.system.repository.DictRepository; |
|||
import com.storeroom.modules.system.service.DictService; |
|||
import com.storeroom.modules.system.service.dto.DictDetailDto; |
|||
import com.storeroom.modules.system.service.dto.DictDto; |
|||
import com.storeroom.modules.system.service.dto.DictQueryCriteria; |
|||
import com.storeroom.modules.system.service.mapstruct.DictMapper; |
|||
import com.storeroom.utils.*; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.annotation.CacheConfig; |
|||
import org.springframework.data.domain.Page; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.*; |
|||
|
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@CacheConfig(cacheNames = "dict") |
|||
public class DictServiceImpl implements DictService { |
|||
|
|||
private final DictRepository dictRepository; |
|||
private final DictMapper dictMapper; |
|||
private final RedisUtils redisUtils; |
|||
|
|||
@Override |
|||
public Map<String, Object> queryAll(DictQueryCriteria dict, Pageable pageable){ |
|||
Page<Dict> page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable); |
|||
return PageUtil.toPage(page.map(dictMapper::toDto)); |
|||
} |
|||
|
|||
@Override |
|||
public List<DictDto> queryAll(DictQueryCriteria dict) { |
|||
List<Dict> list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb)); |
|||
return dictMapper.toDto(list); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void create(Dict resources) { |
|||
dictRepository.save(resources); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void update(Dict resources) { |
|||
// 清理缓存 |
|||
delCaches(resources); |
|||
Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new); |
|||
ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId()); |
|||
dict.setName(resources.getName()); |
|||
dict.setDescription(resources.getDescription()); |
|||
dictRepository.save(dict); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void delete(Set<Long> ids) { |
|||
// 清理缓存 |
|||
List<Dict> dicts = dictRepository.findByIdIn(ids); |
|||
for (Dict dict : dicts) { |
|||
delCaches(dict); |
|||
} |
|||
dictRepository.deleteByIdIn(ids); |
|||
} |
|||
|
|||
@Override |
|||
public void download(List<DictDto> dictDtos, HttpServletResponse response) throws IOException { |
|||
List<Map<String, Object>> list = new ArrayList<>(); |
|||
for (DictDto dictDTO : dictDtos) { |
|||
if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){ |
|||
for (DictDetailDto dictDetail : dictDTO.getDictDetails()) { |
|||
Map<String,Object> map = new LinkedHashMap<>(); |
|||
map.put("字典名称", dictDTO.getName()); |
|||
map.put("字典描述", dictDTO.getDescription()); |
|||
map.put("字典标签", dictDetail.getLabel()); |
|||
map.put("字典值", dictDetail.getValue()); |
|||
map.put("创建日期", dictDetail.getCreateTime()); |
|||
list.add(map); |
|||
} |
|||
} else { |
|||
Map<String,Object> map = new LinkedHashMap<>(); |
|||
map.put("字典名称", dictDTO.getName()); |
|||
map.put("字典描述", dictDTO.getDescription()); |
|||
map.put("字典标签", null); |
|||
map.put("字典值", null); |
|||
map.put("创建日期", dictDTO.getCreateTime()); |
|||
list.add(map); |
|||
} |
|||
} |
|||
FileUtil.downloadExcel(list, response); |
|||
} |
|||
|
|||
public void delCaches(Dict dict){ |
|||
redisUtils.del(CacheKey.DICT_NAME + dict.getName()); |
|||
} |
|||
} |
@ -0,0 +1,106 @@ |
|||
package com.storeroom.modules.system.service.impl; |
|||
|
|||
import com.storeroom.exception.BaseException; |
|||
import com.storeroom.modules.system.domain.Job; |
|||
import com.storeroom.modules.system.repository.JobRepository; |
|||
import com.storeroom.modules.system.repository.UserRepository; |
|||
import com.storeroom.modules.system.service.JobService; |
|||
import com.storeroom.modules.system.service.dto.JobDto; |
|||
import com.storeroom.modules.system.service.dto.JobQueryCriteria; |
|||
import com.storeroom.modules.system.service.mapstruct.JobMapper; |
|||
import com.storeroom.utils.*; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.annotation.CacheConfig; |
|||
import org.springframework.cache.annotation.CacheEvict; |
|||
import org.springframework.cache.annotation.Cacheable; |
|||
import org.springframework.data.domain.Page; |
|||
import org.springframework.data.domain.Pageable; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.util.*; |
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@CacheConfig(cacheNames = "job") |
|||
public class JobServiceImpl implements JobService { |
|||
|
|||
private final JobRepository jobRepository; |
|||
private final JobMapper jobMapper; |
|||
private final RedisUtils redisUtils; |
|||
private final UserRepository userRepository; |
|||
|
|||
@Override |
|||
public Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable) { |
|||
Page<Job> page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); |
|||
return PageUtil.toPage(page.map(jobMapper::toDto).getContent(),page.getTotalElements()); |
|||
} |
|||
|
|||
@Override |
|||
public List<JobDto> queryAll(JobQueryCriteria criteria) { |
|||
List<Job> list = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); |
|||
return jobMapper.toDto(list); |
|||
} |
|||
|
|||
@Override |
|||
@Cacheable(key = "'id:' + #p0") |
|||
public JobDto findById(Long id) { |
|||
Job job = jobRepository.findById(id).orElseGet(Job::new); |
|||
ValidationUtil.isNull(job.getId(),"Job","id",id); |
|||
return jobMapper.toDto(job); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void create(Job resources) { |
|||
Job job = jobRepository.findByName(resources.getName()); |
|||
if(job != null){ |
|||
throw new BaseException("name",resources.getName()); |
|||
} |
|||
jobRepository.save(resources); |
|||
} |
|||
|
|||
@Override |
|||
@CacheEvict(key = "'id:' + #p0.id") |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void update(Job resources) { |
|||
Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new); |
|||
Job old = jobRepository.findByName(resources.getName()); |
|||
if(old != null && !old.getId().equals(resources.getId())){ |
|||
throw new BaseException("name",resources.getName()); |
|||
} |
|||
ValidationUtil.isNull( job.getId(),"Job","id",resources.getId()); |
|||
resources.setId(job.getId()); |
|||
jobRepository.save(resources); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void delete(Set<Long> ids) { |
|||
jobRepository.deleteAllByIdIn(ids); |
|||
// 删除缓存 |
|||
redisUtils.delByKeys(CacheKey.JOB_ID, ids); |
|||
} |
|||
|
|||
@Override |
|||
public void download(List<JobDto> jobDtos, HttpServletResponse response) throws IOException { |
|||
List<Map<String, Object>> list = new ArrayList<>(); |
|||
for (JobDto jobDTO : jobDtos) { |
|||
Map<String,Object> map = new LinkedHashMap<>(); |
|||
map.put("岗位名称", jobDTO.getName()); |
|||
map.put("岗位状态", jobDTO.getEnabled() ? "启用" : "停用"); |
|||
map.put("创建日期", jobDTO.getCreateTime()); |
|||
list.add(map); |
|||
} |
|||
FileUtil.downloadExcel(list, response); |
|||
} |
|||
|
|||
@Override |
|||
public void verification(Set<Long> ids) { |
|||
if(userRepository.countByJobs(ids) > 0){ |
|||
throw new BaseException("所选的岗位中存在用户关联,请解除关联再试!"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,339 @@ |
|||
package com.storeroom.modules.system.service.impl; |
|||
|
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.storeroom.exception.BaseException; |
|||
import com.storeroom.modules.system.domain.Menu; |
|||
import com.storeroom.modules.system.domain.Role; |
|||
import com.storeroom.modules.system.domain.User; |
|||
import com.storeroom.modules.system.domain.vo.MenuMetaVo; |
|||
import com.storeroom.modules.system.domain.vo.MenuVo; |
|||
import com.storeroom.modules.system.repository.MenuRepository; |
|||
import com.storeroom.modules.system.repository.UserRepository; |
|||
import com.storeroom.modules.system.service.MenuService; |
|||
import com.storeroom.modules.system.service.RoleService; |
|||
import com.storeroom.modules.system.service.dto.MenuDto; |
|||
import com.storeroom.modules.system.service.dto.MenuQueryCriteria; |
|||
import com.storeroom.modules.system.service.dto.RoleSmallDto; |
|||
import com.storeroom.modules.system.service.mapstruct.MenuMapper; |
|||
import com.storeroom.utils.*; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.cache.annotation.CacheConfig; |
|||
import org.springframework.cache.annotation.Cacheable; |
|||
import org.springframework.data.domain.Sort; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import javax.servlet.http.HttpServletResponse; |
|||
import java.io.IOException; |
|||
import java.lang.reflect.Field; |
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
|
|||
@Service |
|||
@RequiredArgsConstructor |
|||
@CacheConfig(cacheNames = "menu") |
|||
public class MenuServiceImpl implements MenuService { |
|||
|
|||
private final MenuRepository menuRepository; |
|||
private final UserRepository userRepository; |
|||
private final MenuMapper menuMapper; |
|||
private final RoleService roleService; |
|||
private final RedisUtils redisUtils; |
|||
|
|||
@Override |
|||
public List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception { |
|||
Sort sort = Sort.by(Sort.Direction.ASC, "menuSort"); |
|||
if(Boolean.TRUE.equals(isQuery)){ |
|||
criteria.setPidIsNull(true); |
|||
List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>()); |
|||
for (Field field : fields) { |
|||
//设置对象的访问权限,保证对private的属性的访问 |
|||
field.setAccessible(true); |
|||
Object val = field.get(criteria); |
|||
if("pidIsNull".equals(field.getName())){ |
|||
continue; |
|||
} |
|||
if (ObjectUtil.isNotNull(val)) { |
|||
criteria.setPidIsNull(null); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
return menuMapper.toDto(menuRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort)); |
|||
} |
|||
|
|||
@Override |
|||
@Cacheable(key = "'id:' + #p0") |
|||
public MenuDto findById(long id) { |
|||
Menu menu = menuRepository.findById(id).orElseGet(Menu::new); |
|||
ValidationUtil.isNull(menu.getId(),"Menu","id",id); |
|||
return menuMapper.toDto(menu); |
|||
} |
|||
|
|||
/** |
|||
* 用户角色改变时需清理缓存 |
|||
* @param currentUserId / |
|||
* @return / |
|||
*/ |
|||
@Override |
|||
@Cacheable(key = "'user:' + #p0") |
|||
public List<MenuDto> findByUser(Long currentUserId) { |
|||
List<RoleSmallDto> roles = roleService.findByUsersId(currentUserId); |
|||
Set<Long> roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet()); |
|||
LinkedHashSet<Menu> menus = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2); |
|||
return menus.stream().map(menuMapper::toDto).collect(Collectors.toList()); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void create(Menu resources) { |
|||
if(menuRepository.findByTitle(resources.getTitle()) != null){ |
|||
throw new BaseException("title",resources.getTitle()); |
|||
} |
|||
if(StringUtils.isNotBlank(resources.getComponentName())){ |
|||
if(menuRepository.findByComponentName(resources.getComponentName()) != null){ |
|||
throw new BaseException("componentName",resources.getComponentName()); |
|||
} |
|||
} |
|||
if(resources.getPid().equals(0L)){ |
|||
resources.setPid(null); |
|||
} |
|||
if(resources.getIFrame()){ |
|||
String http = "http://", https = "https://"; |
|||
if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) { |
|||
throw new BaseException("外链必须以http://或者https://开头"); |
|||
} |
|||
} |
|||
menuRepository.save(resources); |
|||
// 计算子节点数目 |
|||
resources.setSubCount(0); |
|||
// 更新父节点菜单数目 |
|||
updateSubCnt(resources.getPid()); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void update(Menu resources) { |
|||
if(resources.getId().equals(resources.getPid())) { |
|||
throw new BaseException("上级不能为自己"); |
|||
} |
|||
Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new); |
|||
ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId()); |
|||
|
|||
if(resources.getIFrame()){ |
|||
String http = "http://", https = "https://"; |
|||
if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) { |
|||
throw new BaseException("外链必须以http://或者https://开头"); |
|||
} |
|||
} |
|||
Menu menu1 = menuRepository.findByTitle(resources.getTitle()); |
|||
|
|||
if(menu1 != null && !menu1.getId().equals(menu.getId())){ |
|||
throw new BaseException("title",resources.getTitle()); |
|||
} |
|||
|
|||
if(resources.getPid().equals(0L)){ |
|||
resources.setPid(null); |
|||
} |
|||
|
|||
// 记录的父节点ID |
|||
Long oldPid = menu.getPid(); |
|||
Long newPid = resources.getPid(); |
|||
|
|||
if(StringUtils.isNotBlank(resources.getComponentName())){ |
|||
menu1 = menuRepository.findByComponentName(resources.getComponentName()); |
|||
if(menu1 != null && !menu1.getId().equals(menu.getId())){ |
|||
throw new BaseException("componentName",resources.getComponentName()); |
|||
} |
|||
} |
|||
menu.setTitle(resources.getTitle()); |
|||
menu.setComponent(resources.getComponent()); |
|||
menu.setPath(resources.getPath()); |
|||
menu.setIcon(resources.getIcon()); |
|||
menu.setIFrame(resources.getIFrame()); |
|||
menu.setPid(resources.getPid()); |
|||
menu.setMenuSort(resources.getMenuSort()); |
|||
menu.setCache(resources.getCache()); |
|||
menu.setHidden(resources.getHidden()); |
|||
menu.setComponentName(resources.getComponentName()); |
|||
menu.setPermission(resources.getPermission()); |
|||
menu.setType(resources.getType()); |
|||
menuRepository.save(menu); |
|||
// 计算父级菜单节点数目 |
|||
updateSubCnt(oldPid); |
|||
updateSubCnt(newPid); |
|||
// 清理缓存 |
|||
delCaches(resources.getId()); |
|||
} |
|||
|
|||
@Override |
|||
public Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet) { |
|||
for (Menu menu : menuList) { |
|||
menuSet.add(menu); |
|||
List<Menu> menus = menuRepository.findByPid(menu.getId()); |
|||
if(menus!=null && menus.size()!=0){ |
|||
getChildMenus(menus, menuSet); |
|||
} |
|||
} |
|||
return menuSet; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void delete(Set<Menu> menuSet) { |
|||
for (Menu menu : menuSet) { |
|||
// 清理缓存 |
|||
delCaches(menu.getId()); |
|||
roleService.untiedMenu(menu.getId()); |
|||
menuRepository.deleteById(menu.getId()); |
|||
updateSubCnt(menu.getPid()); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public List<MenuDto> getMenus(Long pid) { |
|||
List<Menu> menus; |
|||
if(pid != null && !pid.equals(0L)){ |
|||
menus = menuRepository.findByPid(pid); |
|||
} else { |
|||
menus = menuRepository.findByPidIsNull(); |
|||
} |
|||
return menuMapper.toDto(menus); |
|||
} |
|||
|
|||
@Override |
|||
public List<MenuDto> getSuperior(MenuDto menuDto, List<Menu> menus) { |
|||
if(menuDto.getPid() == null){ |
|||
menus.addAll(menuRepository.findByPidIsNull()); |
|||
return menuMapper.toDto(menus); |
|||
} |
|||
menus.addAll(menuRepository.findByPid(menuDto.getPid())); |
|||
return getSuperior(findById(menuDto.getPid()), menus); |
|||
} |
|||
|
|||
@Override |
|||
public List<MenuDto> buildTree(List<MenuDto> menuDtos) { |
|||
List<MenuDto> trees = new ArrayList<>(); |
|||
Set<Long> ids = new HashSet<>(); |
|||
for (MenuDto menuDTO : menuDtos) { |
|||
if (menuDTO.getPid() == null) { |
|||
trees.add(menuDTO); |
|||
} |
|||
for (MenuDto it : menuDtos) { |
|||
if (menuDTO.getId().equals(it.getPid())) { |
|||
if (menuDTO.getChildren() == null) { |
|||
menuDTO.setChildren(new ArrayList<>()); |
|||
} |
|||
menuDTO.getChildren().add(it); |
|||
ids.add(it.getId()); |
|||
} |
|||
} |
|||
} |
|||
if(trees.size() == 0){ |
|||
trees = menuDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList()); |
|||
} |
|||
return trees; |
|||
} |
|||
|
|||
@Override |
|||
public List<MenuVo> buildMenus(List<MenuDto> menuDtos) { |
|||
List<MenuVo> list = new LinkedList<>(); |
|||
menuDtos.forEach(menuDTO -> { |
|||
if (menuDTO!=null){ |
|||
List<MenuDto> menuDtoList = menuDTO.getChildren(); |
|||
MenuVo menuVo = new MenuVo(); |
|||
menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponentName()) ? menuDTO.getComponentName() : menuDTO.getTitle()); |
|||
// 一级目录需要加斜杠,不然会报警告 |
|||
menuVo.setPath(menuDTO.getPid() == null ? "/" + menuDTO.getPath() :menuDTO.getPath()); |
|||
menuVo.setHidden(menuDTO.getHidden()); |
|||
// 如果不是外链 |
|||
if(!menuDTO.getIFrame()){ |
|||
if(menuDTO.getPid() == null){ |
|||
menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent()); |
|||
// 如果不是一级菜单,并且菜单类型为目录,则代表是多级菜单 |
|||
}else if(menuDTO.getType() == 0){ |
|||
menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"ParentView":menuDTO.getComponent()); |
|||
}else if(StringUtils.isNoneBlank(menuDTO.getComponent())){ |
|||
menuVo.setComponent(menuDTO.getComponent()); |
|||
} |
|||
} |
|||
menuVo.setMeta(new MenuMetaVo(menuDTO.getTitle(),menuDTO.getIcon(),!menuDTO.getCache())); |
|||
if(CollectionUtil.isNotEmpty(menuDtoList)){ |
|||
menuVo.setAlwaysShow(true); |
|||
menuVo.setRedirect("noredirect"); |
|||
menuVo.setChildren(buildMenus(menuDtoList)); |
|||
// 处理是一级菜单并且没有子菜单的情况 |
|||
} else if(menuDTO.getPid() == null){ |
|||
MenuVo menuVo1 = new MenuVo(); |
|||
menuVo1.setMeta(menuVo.getMeta()); |
|||
// 非外链 |
|||
if(!menuDTO.getIFrame()){ |
|||
menuVo1.setPath("index"); |
|||
menuVo1.setName(menuVo.getName()); |
|||
menuVo1.setComponent(menuVo.getComponent()); |
|||
} else { |
|||
menuVo1.setPath(menuDTO.getPath()); |
|||
} |
|||
menuVo.setName(null); |
|||
menuVo.setMeta(null); |
|||
menuVo.setComponent("Layout"); |
|||
List<MenuVo> list1 = new ArrayList<>(); |
|||
list1.add(menuVo1); |
|||
menuVo.setChildren(list1); |
|||
} |
|||
list.add(menuVo); |
|||
} |
|||
} |
|||
); |
|||
return list; |
|||
} |
|||
|
|||
@Override |
|||
public Menu findOne(Long id) { |
|||
Menu menu = menuRepository.findById(id).orElseGet(Menu::new); |
|||
ValidationUtil.isNull(menu.getId(),"Menu","id",id); |
|||
return menu; |
|||
} |
|||
|
|||
@Override |
|||
public void download(List<MenuDto> menuDtos, HttpServletResponse response) throws IOException { |
|||
List<Map<String, Object>> list = new ArrayList<>(); |
|||
for (MenuDto menuDTO : menuDtos) { |
|||
Map<String,Object> map = new LinkedHashMap<>(); |
|||
map.put("菜单标题", menuDTO.getTitle()); |
|||
map.put("菜单类型", menuDTO.getType() == null ? "目录" : menuDTO.getType() == 1 ? "菜单" : "按钮"); |
|||
map.put("权限标识", menuDTO.getPermission()); |
|||
map.put("外链菜单", menuDTO.getIFrame() ? "是" : "否"); |
|||
map.put("菜单可见", menuDTO.getHidden() ? "否" : "是"); |
|||
map.put("是否缓存", menuDTO.getCache() ? "是" : "否"); |
|||
map.put("创建日期", menuDTO.getCreateTime()); |
|||
list.add(map); |
|||
} |
|||
FileUtil.downloadExcel(list, response); |
|||
} |
|||
|
|||
private void updateSubCnt(Long menuId){ |
|||
if(menuId != null){ |
|||
int count = menuRepository.countByPid(menuId); |
|||
menuRepository.updateSubCntById(count, menuId); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 清理缓存 |
|||
* @param id 菜单ID |
|||
*/ |
|||
public void delCaches(Long id){ |
|||
List<User> users = userRepository.findByMenuId(id); |
|||
redisUtils.del(CacheKey.MENU_ID + id); |
|||
redisUtils.delByKeys(CacheKey.MENU_USER, users.stream().map(User::getId).collect(Collectors.toSet())); |
|||
// 清除 Role 缓存 |
|||
List<Role> roles = roleService.findInMenuId(new ArrayList<Long>(){{ |
|||
add(id); |
|||
}}); |
|||
redisUtils.delByKeys(CacheKey.ROLE_ID, roles.stream().map(Role::getId).collect(Collectors.toSet())); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,8 @@ |
|||
██ ██ ██ ██ ██ ██ ████████ ██ ███████ |
|||
░░██ ██ ░░██ ██ ░██ ██ ██░░░░░░ ░██ ░██░░░░██ |
|||
░░████ ░░██ ██ ░██ ██ ░██ ██████ ██████ ██████ █████ ░██ ░██ ██████ ██████ ██████████ |
|||
░░██ ░░███ ░████ ░█████████░░░██░ ██░░░░██░░██░░█ ██░░░██ ░███████ ██░░░░██ ██░░░░██░░██░░██░░██ |
|||
░██ ██░██ ░██░██ ░░░░░░░░██ ░██ ░██ ░██ ░██ ░ ░███████ ░██░░░██ ░██ ░██░██ ░██ ░██ ░██ ░██ |
|||
░██ ██ ░░██ ░██░░██ ░██ ░██ ░██ ░██ ░██ ░██░░░░ ░██ ░░██ ░██ ░██░██ ░██ ░██ ░██ ░██ |
|||
░██ ██ ░░██░██ ░░██ ████████ ░░██ ░░██████ ░███ ░░██████ ░██ ░░██░░██████ ░░██████ ███ ░██ ░██ |
|||
░░ ░░ ░░ ░░ ░░ ░░░░░░░░ ░░ ░░░░░░ ░░░ ░░░░░░ ░░ ░░ ░░░░░░ ░░░░░░ ░░░ ░░ ░░ |
@ -0,0 +1,27 @@ |
|||
#数据库类型转Java类型 |
|||
tinyint=Integer |
|||
smallint=Integer |
|||
mediumint=Integer |
|||
int=Integer |
|||
integer=Integer |
|||
|
|||
bigint=Long |
|||
|
|||
float=Float |
|||
|
|||
double=Double |
|||
|
|||
decimal=BigDecimal |
|||
|
|||
bit=Boolean |
|||
|
|||
char=String |
|||
varchar=String |
|||
tinytext=String |
|||
text=String |
|||
mediumtext=String |
|||
longtext=String |
|||
|
|||
date=Timestamp |
|||
datetime=Timestamp |
|||
timestamp=Timestamp |
@ -0,0 +1,4 @@ |
|||
# If you use SLF4J. First, you need to tell log4jdbc-log4j2 that you want to use the SLF4J logger |
|||
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator |
|||
log4jdbc.auto.load.popular.drivers=false |
|||
log4jdbc.drivers=com.mysql.cj.jdbc.Driver |
@ -0,0 +1,45 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<configuration scan="true" scanPeriod="30 seconds" debug="false"> |
|||
<contextName>yxk-storeroom</contextName> |
|||
<property name="log.charset" value="utf-8" /> |
|||
<property name="log.pattern" value="%contextName- %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n" /> |
|||
|
|||
<!--输出到控制台--> |
|||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
<charset>${log.charset}</charset> |
|||
</encoder> |
|||
</appender> |
|||
|
|||
<!--普通日志输出到控制台--> |
|||
<root level="info"> |
|||
<appender-ref ref="console" /> |
|||
</root> |
|||
|
|||
<!--监控sql日志输出,如需监控 Sql 打印,请设置为 INFO --> |
|||
<logger name="jdbc.sqlonly" level="ERROR" additivity="false"> |
|||
<appender-ref ref="console" /> |
|||
</logger> |
|||
|
|||
<logger name="jdbc.resultset" level="ERROR" additivity="false"> |
|||
<appender-ref ref="console" /> |
|||
</logger> |
|||
|
|||
<!-- 如想看到表格数据,将OFF改为INFO --> |
|||
<logger name="jdbc.resultsettable" level="OFF" additivity="false"> |
|||
<appender-ref ref="console" /> |
|||
</logger> |
|||
|
|||
<logger name="jdbc.connection" level="OFF" additivity="false"> |
|||
<appender-ref ref="console" /> |
|||
</logger> |
|||
|
|||
<logger name="jdbc.sqltiming" level="OFF" additivity="false"> |
|||
<appender-ref ref="console" /> |
|||
</logger> |
|||
|
|||
<logger name="jdbc.audit" level="OFF" additivity="false"> |
|||
<appender-ref ref="console" /> |
|||
</logger> |
|||
</configuration> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue