完成部门管理

This commit is contained in:
none 2023-02-19 17:12:52 +08:00
parent 384d61437f
commit 4ada5e9ff8
11 changed files with 88 additions and 137 deletions

18
pom.xml
View File

@ -20,12 +20,6 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -87,18 +81,6 @@
<version>2.3.2</version> <version>2.3.2</version>
</dependency> </dependency>
<!--Fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.21</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId>
<version>2.0.21</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>

View File

@ -24,9 +24,18 @@ public class DepartmentBus {
if (parentDepartment == null) { if (parentDepartment == null) {
throw new NotFoundException("父级部门不存在"); throw new NotFoundException("父级部门不存在");
} }
parentChain = parentDepartment.getParentChain() + "," + parentId; String pc = parentDepartment.getParentChain();
parentChain = pc == null || pc.length() == 0 ? parentId + "" : pc + "," + parentId;
} }
return parentChain; return parentChain;
} }
public static String childrenParentChain(Department department) {
String prefix = department.getId() + "";
if (department.getParentChain() != null && department.getParentChain().length() > 0) {
prefix = department.getParentChain() + "," + prefix;
}
return prefix;
}
} }

View File

@ -1,10 +1,10 @@
package xyz.playedu.api.config; package xyz.playedu.api.config;
import com.alibaba.fastjson2.support.spring.data.redis.FastJsonRedisSerializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration @Configuration
@ -21,9 +21,9 @@ public class RedisConfig {
redisTemplate.setHashKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer);
// value值采用fastjson2序列化 // value值采用fastjson2序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(jsonRedisSerializer);
return redisTemplate; return redisTemplate;
} }

View File

@ -1,24 +1,15 @@
package xyz.playedu.api.config; package xyz.playedu.api.config;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import xyz.playedu.api.middleware.AdminAuthMiddleware; import xyz.playedu.api.middleware.AdminAuthMiddleware;
import java.util.ArrayList;
import java.util.List;
@Configuration @Configuration
@Slf4j @Slf4j
public class WebMvcConfig implements WebMvcConfigurer { public class WebMvcConfig implements WebMvcConfigurer {
@ -43,26 +34,4 @@ public class WebMvcConfig implements WebMvcConfigurer {
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins(ConfigOrigins).allowedHeaders("*").allowedMethods("GET", "POST", "DELETE", "PUT").maxAge(3600); registry.addMapping("/**").allowedOrigins(ConfigOrigins).allowedHeaders("*").allowedMethods("GET", "POST", "DELETE", "PUT").maxAge(3600);
} }
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(fastJsonHttpMessageConverter());
}
private HttpMessageConverter<?> fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
// 中文乱码解决方案
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_JSON);
fastConverter.setSupportedMediaTypes(mediaTypes);
// 配置
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
fastJsonConfig.setWriterFeatures(JSONWriter.Feature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
return fastConverter;
}
} }

View File

@ -15,10 +15,10 @@ import java.util.List;
@RestControllerAdvice @RestControllerAdvice
public class ExceptionController { public class ExceptionController {
@ExceptionHandler(Exception.class) // @ExceptionHandler(Exception.class)
public JsonResponse exceptionHandler(Exception e) { // public JsonResponse exceptionHandler(Exception e) {
return JsonResponse.error("系统错误", 500); // return JsonResponse.error("系统错误", 500);
} // }
@ExceptionHandler(ServiceException.class) @ExceptionHandler(ServiceException.class)
public JsonResponse serviceExceptionHandler(ServiceException e) { public JsonResponse serviceExceptionHandler(ServiceException e) {

View File

@ -42,7 +42,7 @@ public class DepartmentController {
} }
@PostMapping("/create") @PostMapping("/create")
public JsonResponse store(@RequestBody DepartmentRequest request) throws NotFoundException { public JsonResponse store(@RequestBody @Validated DepartmentRequest request) throws NotFoundException {
String parentChain = ""; String parentChain = "";
if (request.getParentId() != 0) { if (request.getParentId() != 0) {
parentChain = departmentBus.compParentChain(request.getParentId()); parentChain = departmentBus.compParentChain(request.getParentId());

View File

@ -1,6 +1,6 @@
package xyz.playedu.api.middleware; package xyz.playedu.api.middleware;
import com.alibaba.fastjson2.JSON; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -16,6 +16,7 @@ import xyz.playedu.api.service.AdminUserService;
import xyz.playedu.api.service.JWTService; import xyz.playedu.api.service.JWTService;
import xyz.playedu.api.types.JWTPayload; import xyz.playedu.api.types.JWTPayload;
import xyz.playedu.api.types.JsonResponse; import xyz.playedu.api.types.JsonResponse;
import xyz.playedu.api.util.HelperUtil;
import xyz.playedu.api.util.RequestUtil; import xyz.playedu.api.util.RequestUtil;
import java.io.IOException; import java.io.IOException;
@ -69,9 +70,10 @@ public class AdminAuthMiddleware implements HandlerInterceptor {
} }
private boolean responseTransform(HttpServletResponse response, int code, String msg) throws IOException { private boolean responseTransform(HttpServletResponse response, int code, String msg) throws IOException {
ObjectMapper mapper = new ObjectMapper();
response.setStatus(code); response.setStatus(code);
response.setContentType("application/json;charset=utf-8"); response.setContentType("application/json;charset=utf-8");
response.getWriter().print(JSON.toJSONString(JsonResponse.error(msg))); response.getWriter().print(HelperUtil.toJsonStr(JsonResponse.error(msg)));
return false; return false;
} }

View File

@ -1,10 +1,9 @@
package xyz.playedu.api.request.backend; package xyz.playedu.api.request.backend;
import jakarta.validation.constraints.Min; import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
import org.springframework.validation.annotation.Validated;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
@ -13,7 +12,6 @@ import java.io.Serializable;
* @Author 杭州白书科技有限公司 * @Author 杭州白书科技有限公司
* @create 2023/2/19 10:42 * @create 2023/2/19 10:42
*/ */
@Validated
@Data @Data
public class DepartmentRequest implements Serializable { public class DepartmentRequest implements Serializable {
@Serial @Serial
@ -23,11 +21,11 @@ public class DepartmentRequest implements Serializable {
@Length(min = 1, max = 20, message = "部门名称长度在1-20个字符之间") @Length(min = 1, max = 20, message = "部门名称长度在1-20个字符之间")
private String name; private String name;
@NotNull(message = "请选择部门上级") @JsonProperty("parent_id")
@NotNull(message = "请选择上级部门")
private Integer parentId; private Integer parentId;
@NotNull(message = "请输入排序值") @NotNull(message = "请输入排序值")
@Min(value = 0, message = "排序值不能小于0")
private Integer sort; private Integer sort;
} }

View File

@ -3,7 +3,9 @@ package xyz.playedu.api.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import xyz.playedu.api.bus.DepartmentBus;
import xyz.playedu.api.domain.Department; import xyz.playedu.api.domain.Department;
import xyz.playedu.api.exception.NotFoundException; import xyz.playedu.api.exception.NotFoundException;
import xyz.playedu.api.service.DepartmentService; import xyz.playedu.api.service.DepartmentService;
@ -22,14 +24,15 @@ import java.util.List;
@Service @Service
@Slf4j @Slf4j
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService { public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {
@Override @Override
public List<Department> listByParentId(Integer id) { public List<Department> listByParentId(Integer id) {
return this.getBaseMapper().selectList(query().eq("parent_id", id)); return list(query().getWrapper().eq("parent_id", id));
} }
@Override @Override
public Department findOrFail(Integer id) throws NotFoundException { public Department findOrFail(Integer id) throws NotFoundException {
Department department = this.getBaseMapper().selectById(id); Department department = getById(id);
if (department == null) { if (department == null) {
throw new NotFoundException("部门不存在"); throw new NotFoundException("部门不存在");
} }
@ -40,53 +43,68 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
@Transactional @Transactional
public void deleteById(Integer id) throws NotFoundException { public void deleteById(Integer id) throws NotFoundException {
Department department = findOrFail(id); Department department = findOrFail(id);
updateParentChain(department); updateParentChain(department.getParentChain(), DepartmentBus.childrenParentChain(department));
removeById(department.getId()); removeById(department.getId());
} }
@Override @Override
@Transactional @Transactional
public void update(Department department, String name, Integer parentId, Integer sort) throws NotFoundException { public void update(Department department, String name, Integer parentId, Integer sort) throws NotFoundException {
//计算该部门作为其它子部门的parentChain值
String childrenChainPrefix = DepartmentBus.childrenParentChain(department);
Department data = new Department(); Department data = new Department();
if (!department.getName().equals(name)) { data.setId(department.getId());
if (!department.getName().equals(name)) {//更换部门名称
data.setName(name); data.setName(name);
} }
if (!department.getParentId().equals(parentId)) { if (!department.getParentId().equals(parentId)) {
data.setParentId(parentId); data.setParentId(parentId);
Department parent = findOrFail(parentId); if (parentId.equals(0)) {//重置一级部门
data.setParentChain(parent.getParentChain() + "," + parent.getId()); data.setParentChain("");
} else {
Department parentDepartment = findOrFail(parentId);
data.setParentChain(DepartmentBus.childrenParentChain(parentDepartment));
}
} }
if (!department.getSort().equals(sort)) { if (!department.getSort().equals(sort)) {//更换部门排序值
data.setSort(sort); data.setSort(sort);
} }
save(data);
//提交更换
updateById(data);
department = getById(department.getId()); department = getById(department.getId());
updateParentChain(department); updateParentChain(DepartmentBus.childrenParentChain(department), childrenChainPrefix);
} }
private void updateParentChain(Department department) { private void updateParentChain(String newChildrenPC, String oldChildrenPC) {
if (department.getParentId().equals(0)) { List<Department> children = list(query().getWrapper().like("parent_chain", oldChildrenPC + "%"));
return;
}
//需要重置chain的子部门
List<Department> children = list(query().like("parent_chain", "%" + department.getParentChain()));
if (children.size() == 0) { if (children.size() == 0) {
return; return;
} }
// 计算新的parentChain前缀
String[] chainIds = department.getParentChain().split(",");
String newChainPrefix = String.join(",", Arrays.copyOfRange(chainIds, 0, chainIds.length - 1));
log.info("新的前缀:" + newChainPrefix);
ArrayList<Department> updateRows = new ArrayList<>(); ArrayList<Department> updateRows = new ArrayList<>();
for (Department tmpDepartment : children) { for (Department tmpDepartment : children) {
Department tmpUpdateDepartment = new Department(); Department tmpUpdateDepartment = new Department();
tmpUpdateDepartment.setId(tmpDepartment.getId()); tmpUpdateDepartment.setId(tmpDepartment.getId());
tmpUpdateDepartment.setParentChain(tmpDepartment.getParentChain().replaceFirst(department.getParentChain(), newChainPrefix));
// parentChain计算
String pc = newChildrenPC;
if (!tmpDepartment.getParentChain().equals(oldChildrenPC)) {
pc = tmpDepartment.getParentChain().replaceFirst(oldChildrenPC + ",", newChildrenPC.length() == 0 ? newChildrenPC : newChildrenPC + ',');
}
tmpUpdateDepartment.setParentChain(pc);
// parentId计算
int parentId = 0;
if (pc != null && pc.length() > 0) {
String[] parentIds = pc.split(",");
parentId = Integer.parseInt(parentIds[parentIds.length - 1]);
}
tmpUpdateDepartment.setParentId(parentId);
updateRows.add(tmpUpdateDepartment); updateRows.add(tmpUpdateDepartment);
} }

View File

@ -1,12 +1,11 @@
package xyz.playedu.api.util; package xyz.playedu.api.util;
import com.alibaba.fastjson2.JSON; import com.fasterxml.jackson.core.JsonProcessingException;
import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.reflect.TypeToken; import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.DigestUtils; import org.springframework.util.DigestUtils;
import java.io.*; import java.io.*;
import java.lang.reflect.Type;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -124,45 +123,6 @@ public class HelperUtil {
} }
} }
/**
* JSON转 Map<String, String>
*
* @param json 对象
* @return Map<String, String>
* @author fzr
*/
public static Map<String, String> jsonToMap(String json) {
Type type = new TypeToken<Map<String, String>>() {
}.getType();
return JSON.parseObject(json, type);
}
/**
* JSON转 Map<String, Object>
*
* @param json 对象
* @return Map<String, String>
* @author fzr
*/
public static Map<String, Object> jsonToMapAsObj(String json) {
Type type = new TypeToken<Map<String, Object>>() {
}.getType();
return JSON.parseObject(json, type);
}
/**
* JSON转Map<String, String>
*
* @param object 对象
* @return Map<String, String>
* @author fzr
*/
public static Map<String, String> objectToMap(Object object) {
Type type = new TypeToken<Map<String, String>>() {
}.getType();
return JSON.parseObject(JSONObject.toJSONString(object), type);
}
/** /**
* 对象类型Map合并 * 对象类型Map合并
* *
@ -191,4 +151,9 @@ public class HelperUtil {
return map2; return map2;
} }
public static String toJsonStr(Object obj) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
}
} }

View File

@ -1,6 +1,7 @@
package xyz.playedu.api.util; package xyz.playedu.api.util;
import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -60,16 +61,23 @@ public class IpUtil {
return "内网"; return "内网";
} }
@Data
class Response {
private String pro;
private String city;
private String region;
private String addr;
}
try { try {
String rspStr = HttpUtil.sendGet(IP_URL, "ip=" + ip + "&json=true", "GBK"); String rspStr = HttpUtil.sendGet(IP_URL, "ip=" + ip + "&json=true", "GBK");
if (StringUtil.isEmpty(rspStr)) { if (StringUtil.isEmpty(rspStr)) {
log.error("获取地理位置异常 {}", ip); log.error("获取地理位置异常 {}", ip);
return UNKNOWN; return UNKNOWN;
} }
JSONObject obj = JSONObject.parseObject(rspStr); ObjectMapper objectMapper = new ObjectMapper();
String region = obj.getString("pro"); Response obj = objectMapper.readValue(rspStr, Response.class);
String city = obj.getString("city"); return String.format("%s-%s", obj.getPro(), obj.getCity());
return String.format("%s-%s", region, city);
} catch (Exception e) { } catch (Exception e) {
log.error("获取地理位置异常 {}", ip); log.error("获取地理位置异常 {}", ip);
} }