diff --git a/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java b/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java index 3500d76..a543eeb 100644 --- a/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java +++ b/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java @@ -1,6 +1,6 @@ package org.nl.api.task.api; -import org.nl.api.task.core.QRCodeTaskRequestParam; +import org.nl.api.task.core.TaskRequestParam; import org.nl.response.WebResponse; /** @@ -33,28 +33,28 @@ public interface TaskAPI { String taskOperationConfirm(String taskCode,String vehicleNumber); /** - * 二维码生成任务 + * 生成任务 * @param param * @return */ - WebResponse createTask(QRCodeTaskRequestParam param); + WebResponse createTask(TaskRequestParam param,String source); /** - * 二维码生成任务 + * 取消任务 * @param taskCode * @return */ WebResponse cancelTask(String taskCode); /** - * 二维码查询任务信息 + * 根据房间号查询任务信息 * @param room * @return */ WebResponse queryTaskInfoByRoom(String room); /** - * 二维码查询任务信息 + * 任务操作确认 * @param taskCode * @return */ diff --git a/nl-business-api/src/main/java/org/nl/api/task/core/QRCodeTaskRequestParam.java b/nl-business-api/src/main/java/org/nl/api/task/core/TaskRequestParam.java similarity index 93% rename from nl-business-api/src/main/java/org/nl/api/task/core/QRCodeTaskRequestParam.java rename to nl-business-api/src/main/java/org/nl/api/task/core/TaskRequestParam.java index 41f7d05..382bb23 100644 --- a/nl-business-api/src/main/java/org/nl/api/task/core/QRCodeTaskRequestParam.java +++ b/nl-business-api/src/main/java/org/nl/api/task/core/TaskRequestParam.java @@ -8,7 +8,7 @@ import lombok.Data; * 2025/12/23 */ @Data -public class QRCodeTaskRequestParam { +public class TaskRequestParam { /** * 目标点 diff --git a/nl-business-map/src/main/java/org/nl/map/station/controller/MapStationController.java b/nl-business-map/src/main/java/org/nl/map/station/controller/MapStationController.java new file mode 100644 index 0000000..c32cce0 --- /dev/null +++ b/nl-business-map/src/main/java/org/nl/map/station/controller/MapStationController.java @@ -0,0 +1,28 @@ +package org.nl.map.station.controller; + +import jakarta.annotation.Resource; +import org.nl.logging.annotation.Log; +import org.nl.map.station.service.MapStationService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author dsh + * 2026/1/21 + */ +@RestController +@RequestMapping("/mapStation") +public class MapStationController { + + @Resource + private MapStationService mapStationService; + + @Log("查询所有站点") + @GetMapping("/queryAllStations") + public ResponseEntity queryAllStations() { + return new ResponseEntity<>(mapStationService.queryAllStation(), HttpStatus.OK); + } +} diff --git a/nl-business-map/src/main/java/org/nl/map/station/service/MapStationService.java b/nl-business-map/src/main/java/org/nl/map/station/service/MapStationService.java new file mode 100644 index 0000000..7c1b918 --- /dev/null +++ b/nl-business-map/src/main/java/org/nl/map/station/service/MapStationService.java @@ -0,0 +1,14 @@ +package org.nl.map.station.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.map.station.entity.Station; +import org.nl.response.WebResponse; + +/** + * @author dsh + * 2026/1/21 + */ +public interface MapStationService extends IService { + + WebResponse queryAllStation(); +} diff --git a/nl-business-map/src/main/java/org/nl/map/station/service/impl/MapStationServiceImpl.java b/nl-business-map/src/main/java/org/nl/map/station/service/impl/MapStationServiceImpl.java new file mode 100644 index 0000000..6f23777 --- /dev/null +++ b/nl-business-map/src/main/java/org/nl/map/station/service/impl/MapStationServiceImpl.java @@ -0,0 +1,28 @@ +package org.nl.map.station.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.map.station.entity.Station; +import org.nl.map.station.mapper.StationMapper; +import org.nl.map.station.service.MapStationService; +import org.nl.response.WebResponse; +import org.springframework.stereotype.Service; + +/** + * @author dsh + * 2026/1/21 + */ +@Slf4j +@Service +public class MapStationServiceImpl extends ServiceImpl implements MapStationService { + + @Resource + private StationMapper stationMapper; + + @Override + public WebResponse queryAllStation() { + return WebResponse.requestParamOk(stationMapper.selectList(new QueryWrapper<>())); + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java index 5c4d2ba..4b9b79d 100644 --- a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java @@ -1,6 +1,7 @@ package org.nl.schedule.modular.vehicle.controller; import jakarta.validation.constraints.NotBlank; +import org.nl.logging.annotation.Log; import org.nl.schedule.modular.vehicle.service.VehicleService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -29,4 +30,10 @@ public class VehicleController { public ResponseEntity getVehicleInfoByNumber(@PathVariable @NotBlank String vehicleNumber) { return new ResponseEntity<>(vehicleService.getVehicleInfoByNumber(vehicleNumber), HttpStatus.OK); } + + @GetMapping("/getVehicleInfos") + @Log("获取车辆信息列表") + public ResponseEntity getVehicleInfos() { + return new ResponseEntity<>(vehicleService.getVehicleInfos(),HttpStatus.OK); + } } diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java index 3b7521e..27c25ce 100644 --- a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java @@ -20,5 +20,9 @@ public interface VehicleService { */ VehicleInfoDto getVehicleInfoByNumber(String vehicleNumber); - + /** + * 获取内存中的车辆信息 + * @return + */ + WebResponse getVehicleInfos(); } diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java index e654d61..7401268 100644 --- a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java @@ -12,6 +12,7 @@ import org.nl.api.task.api.TaskAPI; import org.nl.response.WebResponse; import org.nl.schedule.core.websocket.WebSocketVehicleInfoServer; import org.nl.schedule.modular.vehicle.dto.VehicleInfoDto; +import org.nl.schedule.modular.vehicle.entity.Location; import org.nl.schedule.modular.vehicle.service.VehicleService; import org.nl.util.URLConstant; import org.springframework.scheduling.annotation.Scheduled; @@ -45,7 +46,7 @@ public class VehicleServiceImpl implements VehicleService { /** * 定时更新车辆信息(每秒执行) */ - @Scheduled(fixedRate = 1000) // 每秒执行一次 + @Scheduled(fixedRate = 7000) // 每秒执行一次 public void updateVehicleInfo() { try { List vehicles = getAllVehicles(); @@ -109,4 +110,39 @@ public class VehicleServiceImpl implements VehicleService { // 直接从缓存中获取 return vehicleCache.get(vehicleNumber); } + + @Override + public WebResponse getVehicleInfos() { + VehicleInfoDto vehicleInfoDto = new VehicleInfoDto(); + vehicleInfoDto.setVehicleId("1"); + vehicleInfoDto.setVehicleNumber("1"); + vehicleInfoDto.setIp("127.0.0.1"); + vehicleInfoDto.setBatteryLevel(100); + vehicleInfoDto.setIceCapacity(50); + vehicleInfoDto.setWaterCapacity(50); + vehicleInfoDto.setSignalType("wifi"); + vehicleInfoDto.setSignalStrength(10); + vehicleInfoDto.setError_code(0); + vehicleInfoDto.setError_msg(""); + vehicleInfoDto.setError_info(new JSONObject()); + vehicleInfoDto.setCurrentLocation(new Location()); + vehicleInfoDto.setLastUpdated("2026-01-27 00:00:00"); + vehicleCache.put("1",vehicleInfoDto); + VehicleInfoDto vehicleInfoDto2 = new VehicleInfoDto(); + vehicleInfoDto2.setVehicleId("2"); + vehicleInfoDto2.setVehicleNumber("2"); + vehicleInfoDto2.setIp("127.0.0.1"); + vehicleInfoDto2.setBatteryLevel(80); + vehicleInfoDto2.setIceCapacity(60); + vehicleInfoDto2.setWaterCapacity(60); + vehicleInfoDto2.setSignalType("5G"); + vehicleInfoDto2.setSignalStrength(20); + vehicleInfoDto2.setError_code(0); + vehicleInfoDto2.setError_msg(""); + vehicleInfoDto2.setError_info(new JSONObject()); + vehicleInfoDto2.setCurrentLocation(new Location()); + vehicleInfoDto2.setLastUpdated("2026-01-27 12:00:00"); + vehicleCache.put("2",vehicleInfoDto2); + return WebResponse.requestParamOk(vehicleCache); + } } diff --git a/nl-business-sys/pom.xml b/nl-business-sys/pom.xml index b16089b..c723a3e 100644 --- a/nl-business-sys/pom.xml +++ b/nl-business-sys/pom.xml @@ -40,6 +40,61 @@ sa-token-spring-boot3-starter + + io.github.eternalstone + captcha-spring-boot-starter + + + + + + + + + + + cn.dev33 + sa-token-sso + + + + commons-beanutils + commons-beanutils-core + + + + + cn.dev33 + sa-token-jwt + + + + com.alicp.jetcache + jetcache-starter-redis + + + + + org.springframework.boot + spring-boot-starter-cache + + + + org.redisson + redisson-spring-boot-starter + + + org.projectlombok + lombok + provided + + + + + com.github.oshi + oshi-core + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/controller/AnomalyInfoController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/controller/AnomalyInfoController.java index e76300c..29a6cd4 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/controller/AnomalyInfoController.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/controller/AnomalyInfoController.java @@ -8,6 +8,7 @@ import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling; import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo; import org.nl.sys.modular.anomalyInfo.listener.ErrorHandlingListener; import org.nl.sys.modular.anomalyInfo.listener.ErrorInfoListener; +import org.nl.sys.modular.anomalyInfo.param.QueryErrorInfoPageParam; import org.nl.sys.modular.anomalyInfo.service.AnomalyInfoService; import org.nl.sys.modular.anomalyInfo.service.ErrorHandlingService; import org.nl.sys.modular.anomalyInfo.service.ErrorInfoService; @@ -15,10 +16,7 @@ import org.nl.util.FileConstant; import org.nl.util.ParseZip; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; @@ -119,4 +117,16 @@ public class AnomalyInfoController { } } + @PostMapping("/queryErrorInfos") + @Log("分页查询异常信息") + public ResponseEntity queryErrorInfos(@RequestBody QueryErrorInfoPageParam param) { + return new ResponseEntity<>(errorInfoService.queryErrorInfoPage(param), HttpStatus.OK); + } + + @PostMapping("/updateErrorInfo") + @Log("修改异常信息") + public ResponseEntity updateErrorInfo(@RequestBody ErrorInfo errorInfo) { + return new ResponseEntity<>(errorInfoService.updateErrorInfo(errorInfo),HttpStatus.OK); + } + } diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/dao/ErrorInfo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/dao/ErrorInfo.java index cff0ac7..e0cfd1f 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/dao/ErrorInfo.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/dao/ErrorInfo.java @@ -69,8 +69,8 @@ public class ErrorInfo { private String en_error_description; /** - * 异常信息类型(1电气 2导航) + * 异常信息类型(1底层 2调度) */ - @ExcelProperty(index = 9,value = "异常类型(1电气,2导航)") + @ExcelProperty(index = 9,value = "异常类型(1底层,2调度)") private Integer error_type; } diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/param/QueryErrorInfoPageParam.java b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/param/QueryErrorInfoPageParam.java new file mode 100644 index 0000000..818986c --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/param/QueryErrorInfoPageParam.java @@ -0,0 +1,39 @@ +package org.nl.sys.modular.anomalyInfo.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2026/1/23 + */ +@Data +public class QueryErrorInfoPageParam { + + /** + * 当前页 + */ + @NotBlank(message = "当前页不能为空") + private int pageNum; + + /** + * 页大小 + */ + @NotBlank(message = "页大小不能为空") + private int pageSize; + + /** + * 异常信息编码 + */ + private String error_code; + + /** + * 异常类别 + */ + private Integer error_category; + + /** + * 异常信息类型 + */ + private Integer error_type; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/provider/ErrorInfoAPIProvider.java b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/provider/ErrorInfoAPIProvider.java index 836fecf..f8003eb 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/provider/ErrorInfoAPIProvider.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/provider/ErrorInfoAPIProvider.java @@ -29,7 +29,7 @@ public class ErrorInfoAPIProvider implements ErrorInfoAPI { return null; } ErrorInfo errorInfo = errorInfoService.getOne(new LambdaQueryWrapper<>(ErrorInfo.class) - .eq(ErrorInfo::getError_code,code) + .eq(ErrorInfo::getError_code,code.toString()) ); return errorInfo == null ? null : JSONObject.parseObject(JSONObject.toJSONString(errorInfo)); } diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/ErrorInfoService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/ErrorInfoService.java index 928b49b..5656291 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/ErrorInfoService.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/ErrorInfoService.java @@ -1,11 +1,27 @@ package org.nl.sys.modular.anomalyInfo.service; import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.response.WebResponse; import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo; +import org.nl.sys.modular.anomalyInfo.param.QueryErrorInfoPageParam; /** * @author dsh * 2025/12/29 */ public interface ErrorInfoService extends IService { + + /** + * 分页查询异常信息 + * @param param + * @return + */ + WebResponse queryErrorInfoPage(QueryErrorInfoPageParam param); + + /** + * 修改异常信息 + * @param errorInfo + * @return + */ + WebResponse updateErrorInfo(ErrorInfo errorInfo); } diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/impl/ErrorInfoServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/impl/ErrorInfoServiceImpl.java index e9a2fed..d8c5fc6 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/impl/ErrorInfoServiceImpl.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/anomalyInfo/service/impl/ErrorInfoServiceImpl.java @@ -1,7 +1,16 @@ package org.nl.sys.modular.anomalyInfo.service.impl; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.nl.exception.BadRequestException; +import org.nl.response.WebResponse; import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo; +import org.nl.sys.modular.anomalyInfo.param.QueryErrorInfoPageParam; import org.nl.sys.modular.anomalyInfo.service.ErrorInfoService; import org.nl.sys.modular.anomalyInfo.mapper.ErrorInfoMapper; import org.springframework.stereotype.Service; @@ -13,4 +22,26 @@ import org.springframework.stereotype.Service; @Service public class ErrorInfoServiceImpl extends ServiceImpl implements ErrorInfoService { + @Resource + private ErrorInfoMapper errorInfoMapper; + + @Override + public WebResponse queryErrorInfoPage(QueryErrorInfoPageParam param) { + Page page = new Page<>(param.getPageNum(), param.getPageSize()); + IPage infoPage = errorInfoMapper.selectPage(page,new LambdaQueryWrapper<>(ErrorInfo.class) + .eq(StrUtil.isNotEmpty(param.getError_code()), ErrorInfo::getError_code, param.getError_code()) + .eq(ObjectUtil.isNotEmpty(param.getError_category()),ErrorInfo::getError_category,param.getError_category()) + .eq(ObjectUtil.isNotEmpty(param.getError_type()),ErrorInfo::getError_type,param.getError_type()) + ); + return WebResponse.requestParamOk(infoPage); + } + + @Override + public WebResponse updateErrorInfo(ErrorInfo errorInfo) { + boolean result = errorInfoMapper.updateById(errorInfo) > 0; + if (!result){ + throw new BadRequestException("修改异常信息失败"); + } + return WebResponse.requestOk(); + } } diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/BaseDTO.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/BaseDTO.java new file mode 100644 index 0000000..24c7df5 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/BaseDTO.java @@ -0,0 +1,33 @@ +package org.nl.sys.modular.backgroundmanagement.common.base; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Zheng Jie + * @date 2019年10月24日20:48:53 + */ +@Data +public class BaseDTO implements Serializable { + + private String create_name; + + private String create_id; + + private String update_name; + + private String update_id; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private Date create_time; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private Date update_time; + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/BaseMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/BaseMapper.java new file mode 100644 index 0000000..8c6e5d9 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/BaseMapper.java @@ -0,0 +1,53 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.base; + +import java.util.List; + +/** + * @author Zheng Jie + * @date 2018-11-23 + */ +public interface BaseMapper { + + /** + * DTO转Entity + * @param dto / + * @return / + */ + E toEntity(D dto); + + /** + * Entity转DTO + * @param entity / + * @return / + */ + D toDto(E entity); + + /** + * DTO集合转Entity集合 + * @param dtoList / + * @return / + */ + List toEntity(List dtoList); + + /** + * Entity集合转DTO集合 + * @param entityList / + * @return / + */ + List toDto(List entityList); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/CommonFinalParam.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/CommonFinalParam.java new file mode 100644 index 0000000..87d17e8 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/CommonFinalParam.java @@ -0,0 +1,84 @@ +/** + * @author ls + * @date 2023/12/6 16:04 + */ +package org.nl.sys.modular.backgroundmanagement.common.base; + +import lombok.Data; + +@Data +public class CommonFinalParam { + + public static final String DELETE = "0"; + /** + * 分隔符 + */ + private final String BARRE = "-"; + private final String POINT = "."; + + public static final String ZERO = "0"; + public static final String ONE = "1"; + + public static final String TWO = "2"; + + public static final String THREE = "3"; + public static final String FOUR = "4"; + public static final String FIVE = "5"; + public static final String SIX = "6"; + public static final String SEVEN = "7"; + public static final String EIGHT = "8"; + public static final String NINE = "9"; + public static final String TEN = "10"; + public static final String ELEVEN = "11"; + + + /** + * 无货 + */ + public static final int DEVICE_MOVE_ZERO = 0; + /** + * 设备联机等待 + */ + public static final int DEVICE_MODE_TWO = 2; + /** + * 成功状态 + */ + public static final int STATUS_OPEN = 200; + + /** + * 动作信号 + */ + public static final int ACTION_ONE = 1; + public static final int ACTION_TWO = 2; + public static final int ACTION_THREE = 3; + + /** + * 申请任务type类型 + */ + public static final String TYPE_ONE = "1"; + public static final String TYPE_TWO = "2"; + public static final String TYPE_THREE = "3"; + public static final String TYPE_FOUR = "4"; + public static final String TYPE_FIVE = "5"; + public static final String TYPE_SIX = "6"; + public static final String TYPE_SEVEN = "7"; + + + + + /** + * 切割点符号 + */ + public static final String DOT = "."; + /** + * 切割横杠符号 + */ + public static final String HYPHEN_ = "-"; + + + + /** + * 自动门 + */ + public static final String DOORS = "doors"; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/TableDataInfo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/TableDataInfo.java new file mode 100644 index 0000000..e23da37 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/base/TableDataInfo.java @@ -0,0 +1,78 @@ +package org.nl.sys.modular.backgroundmanagement.common.base; + +import cn.hutool.http.HttpStatus; +import com.baomidou.mybatisplus.core.metadata.IPage; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 表格分页数据对象 + * + * @author Lion Li + */ + +@Data +@NoArgsConstructor +public class TableDataInfo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 总记录数 + */ + private long totalElements; + + /** + * 列表数据 + */ + private List content; + + /** + * 消息状态码 + */ + private int code; + + /** + * 消息内容 + */ + private String msg; + + /** + * 分页 + * + * @param list 列表数据 + * @param total 总记录数 + */ + public TableDataInfo(List list, long total) { + this.content = list; + this.totalElements = total; + } + + public static TableDataInfo build(IPage page) { + TableDataInfo rspData = new TableDataInfo<>(); + rspData.setCode(HttpStatus.HTTP_OK); + rspData.setMsg("查询成功"); + rspData.setContent(page.getRecords()); + rspData.setTotalElements(page.getTotal()); + return rspData; + } + + public static TableDataInfo build(List list) { + TableDataInfo rspData = new TableDataInfo<>(); + rspData.setCode(HttpStatus.HTTP_OK); + rspData.setMsg("查询成功"); + rspData.setContent(list); + rspData.setTotalElements(list.size()); + return rspData; + } + + public static TableDataInfo build() { + TableDataInfo rspData = new TableDataInfo<>(); + rspData.setCode(HttpStatus.HTTP_OK); + rspData.setMsg("查询成功"); + return rspData; + } + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/constant/DictConstantPool.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/constant/DictConstantPool.java new file mode 100644 index 0000000..2d8f425 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/constant/DictConstantPool.java @@ -0,0 +1,11 @@ +package org.nl.sys.modular.backgroundmanagement.common.domain.constant; + +/* + * @author ZZQ + * @Date 2022/12/26 9:29 上午 + */ +public class DictConstantPool { + + public static final String DICT_SYS_CODE = "system_type"; + public static final String DICT_SYS_NAME = "所属系统"; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/BaseQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/BaseQuery.java new file mode 100644 index 0000000..0296af1 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/BaseQuery.java @@ -0,0 +1,81 @@ +package org.nl.sys.modular.backgroundmanagement.common.domain.query; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; +import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache; +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.enums.QueryTEnum; +import org.nl.sys.modular.backgroundmanagement.common.util.MapOf; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Date; +import java.util.Map; + +/* + * @author ZZQ + * @Date 2022/12/14 6:33 下午 + * 泛型必须为数据tb对应do:由mybatis管理 + */ +@Data +public class BaseQuery { + /** + * 模糊查询 + */ + private String blurry; + /** + * 是否启用 + */ + private Boolean is_used; + /** + * 创建时间范围查询 + */ + private Date start_time; + private Date end_time; + + + /** + * 字段映射Map:指定字段对应QueryWrapper的查询类型 + * 字段与数据库字段对应,不支持驼峰 + * @see QueryTEnum + * 通过buid构建 + */ + public Map doP = MapOf.of("blurry", QParam.builder().k(new String[]{"name"}).type(QueryTEnum.LK).build() + ,"startTime", QParam.builder().k(new String[]{"create_time"}).type(QueryTEnum.LT).build() + ,"endTime", QParam.builder().k(new String[]{"create_time"}).type(QueryTEnum.LE).build() + ,"sort", QParam.builder().k(new String[]{"sort"}).type(QueryTEnum.BY).build() + ); + + public QueryWrapper build(){ + this.paramMapping(); + QueryWrapper wrapper = new QueryWrapper<>(); + JSONObject json = (JSONObject)JSONObject.toJSON(this); + // jdk17不能直接引用ParameterizedTypeImpl +// Type[] types = ((ParameterizedTypeImpl) this.getClass().getGenericSuperclass()).getActualTypeArguments(); + Type genericSuperclass = this.getClass().getGenericSuperclass(); + if (genericSuperclass instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; + Type[] types = parameterizedType.getActualTypeArguments(); + Map columnMap = LambdaUtils.getColumnMap((Class) types[0]); + json.forEach((key, vel) -> { + if (vel != null && !key.equals("doP")){ + QParam qParam = doP.get(key); + if (qParam != null){ + QueryTEnum.build(qParam.type,wrapper,qParam.k,vel); + }else { + ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(key)); + if (columnCache!=null){ + wrapper.eq(columnCache.getColumn(),vel); + } + } + } + }); + } else { + throw new IllegalStateException("当前类不是泛型子类"); + } + return wrapper; + } + + public void paramMapping(){}; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/LConsumer.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/LConsumer.java new file mode 100644 index 0000000..97fd1f7 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/LConsumer.java @@ -0,0 +1,12 @@ +package org.nl.sys.modular.backgroundmanagement.common.domain.query; + +/* + * @author ZZQ + * @Date 2022/12/14 8:40 下午 + */ +@FunctionalInterface +public interface LConsumer { + + void accept(X x,Y y,Z z); + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/PageQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/PageQuery.java new file mode 100644 index 0000000..ab3b356 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/PageQuery.java @@ -0,0 +1,111 @@ +package org.nl.sys.modular.backgroundmanagement.common.domain.query; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.util.Locale; + + +/** + * 分页参数 + */ +@Data +public class PageQuery implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 分页大小 + */ + private Integer size; + + /** + * 当前页数 + */ + private Integer page; + + /** + * 排序列 + */ + private String sort; + + /** + * 排序的方向desc或者asc + */ + private Boolean isAsc; + + /** + * 当前记录起始索引 默认值 + */ + public static final int DEFAULT_PAGE_NUM = 1; + + /** + * 每页显示记录数 默认值 默认查全部 + */ + public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; + + public Page build() { + Integer pageNum = ObjectUtil.defaultIfNull(getPage(), DEFAULT_PAGE_NUM); + Integer pageSize = ObjectUtil.defaultIfNull(getSize(), DEFAULT_PAGE_SIZE); + if (pageNum <= 0) { + pageNum = DEFAULT_PAGE_NUM; + } + Page page = new Page<>(pageNum, pageSize); + if (StringUtils.isNotEmpty(sort)){ + String[] split = sort.split(","); + for (int i = 0; i < (split.length & ~1); i=i+2) { + String col = split[i]; + OrderItem item = new OrderItem(); + item.setColumn(col); + item.setAsc(split[i+1].toLowerCase(Locale.ROOT).equals("asc")); + page.addOrder(item); + } + } + return page; + } + + public Page build(Class r) { + Integer pageNum = ObjectUtil.defaultIfNull(getPage(), DEFAULT_PAGE_NUM); + Integer pageSize = ObjectUtil.defaultIfNull(getSize(), DEFAULT_PAGE_SIZE); + if (pageNum <= 0) { + pageNum = DEFAULT_PAGE_NUM; + } + Page page = new Page<>(pageNum, pageSize); + if (StringUtils.isNotEmpty(sort)){ + String[] split = sort.split(","); + for (int i = 0; i < (split.length & ~1); i=i+2) { + String col = split[i]; + if ("id".equals(col)){ + String mId = mappingId(r); + col = StringUtils.isNotEmpty(mId)?mId:col; + } + OrderItem item = new OrderItem(); + item.setColumn(col); + item.setAsc(split[i+1].toLowerCase(Locale.ROOT).equals("asc")); + page.addOrder(item); + } + + } + return page; + } + + private String mappingId(R r){ + if (r instanceof Class){ + Field[] fields = ((Class) r).getDeclaredFields(); + for (Field field : fields) { + TableId[] byType = field.getAnnotationsByType(TableId.class); + if (byType !=null && byType.length>0){ + TableId tableId = byType[0]; + return tableId.value(); + } + } + } + return null; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/QParam.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/QParam.java new file mode 100644 index 0000000..1b184e6 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/query/QParam.java @@ -0,0 +1,15 @@ +package org.nl.sys.modular.backgroundmanagement.common.domain.query; + +import lombok.Builder; +import org.nl.sys.modular.backgroundmanagement.common.enums.QueryTEnum; + + +/* + * @author ZZQ + * @Date 2022/12/15 1:41 下午 + */ +@Builder +public class QParam { + public String[] k; + public QueryTEnum type; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/DeptVo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/DeptVo.java new file mode 100644 index 0000000..a78cd3f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/DeptVo.java @@ -0,0 +1,66 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.domain.vo; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import org.nl.sys.modular.backgroundmanagement.common.base.BaseDTO; + +import java.io.Serializable; +import java.util.List; + +/** +* @author Zheng Jie +* @date 2019-03-25 +*/ +@Getter +@Setter +public class DeptVo extends BaseDTO implements Serializable { + + + private String dept_id; + + private String code; + + private String ext_id; + + + private Integer dept_sort; + + + @NotBlank + private String name; + + @NotNull + private Boolean is_used; + + private Long pid; + + private Integer sub_count = 0; + //前端显示 + private Boolean has_children =Boolean.FALSE; + + private List children; + + public void setSub_count(Integer sub_count) { + this.sub_count = sub_count; + if (sub_count >0){ + this.has_children =Boolean.TRUE; + } + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/MenuMetaVo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/MenuMetaVo.java new file mode 100644 index 0000000..55fcd5c --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/MenuMetaVo.java @@ -0,0 +1,36 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.domain.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Zheng Jie + * @date 2018-12-20 + */ +@Data +@AllArgsConstructor +public class MenuMetaVo implements Serializable { + + private String title; + + private String icon; + + private Boolean noCache; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/MenuVo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/MenuVo.java new file mode 100644 index 0000000..a24bea4 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/MenuVo.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 构建前端路由时用到 + * @author Zheng Jie + * @date 2018-12-20 + */ +@Data +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class MenuVo implements Serializable { + + private String name; + + private String path; + + private Boolean hidden; + + private String redirect; + + private String component; + + private Boolean alwaysShow; + + private MenuMetaVo meta; + + private List children; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/RoleVo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/RoleVo.java new file mode 100644 index 0000000..2c341dc --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/RoleVo.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.domain.vo; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * 角色 + * @author Zheng Jie + * @date 2018-11-22 + */ +@Getter +@Setter +public class RoleVo implements Serializable { + + + private Long role_id; + + @NotBlank + private String name; + + private Integer level = 3; + + private String remark; + + private String order_seq; + + private String is_used; + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/UserPassVo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/UserPassVo.java new file mode 100644 index 0000000..a5e0744 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/domain/vo/UserPassVo.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.domain.vo; + +import lombok.Data; + +/** + * 修改密码的 Vo 类 + * @author Zheng Jie + * @date 2019年7月11日13:59:49 + */ +@Data +public class UserPassVo { + + private String oldPass; + + private String newPass; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/enums/NoticeEnum.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/enums/NoticeEnum.java new file mode 100644 index 0000000..7288a6c --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/enums/NoticeEnum.java @@ -0,0 +1,22 @@ +package org.nl.sys.modular.backgroundmanagement.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Author: lyd + * @Description: + * @Date: 2023/5/9 + */ +@Getter +@AllArgsConstructor +public enum NoticeEnum { + HAVE_READ_OFF("1","未读"), + HAVE_READ_ON("2", "已读"), + DEAL_STATUS_NO("1", "未处理"), + DEAL_STATUS_YES("2", "已处理"), + DEAL_STATUS_NO_NEED("3", "无需处理"); + + private final String value; + private final String desc; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/enums/QueryTEnum.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/enums/QueryTEnum.java new file mode 100644 index 0000000..7c36f4e --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/enums/QueryTEnum.java @@ -0,0 +1,35 @@ +package org.nl.sys.modular.backgroundmanagement.common.enums; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.Getter; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.LConsumer; + +import java.util.Collection; + +/* + * @author ZZQ + * @Date 2022/12/14 8:26 下午 + */ +@Getter +public enum QueryTEnum { + // + EQ((q, k, v) -> { q.eq(k[0],v); }), + IN((q, key, o) -> { if (o instanceof Collection){ q.in(key[0],(Collection) o); } }), + LK((q, keys, o) -> { for (String key : keys) { q.like(key,o); } }), + LE((q, k, v) -> { q.le(k[0],v); }), + BY((q, k, v) -> { q.orderByDesc(k[0],v); }), + NO((q, k, v) -> { q.isNull(k[0]); }), + LT((q, k, v) -> { q.lt(k[0],v); }), + OREQ((q, k, v) -> { if (StrUtil.isBlank((String)v)){ q.isNull(k[0]); }else { q.eq(k[0],v); } }); + + private LConsumer doP; + + QueryTEnum(LConsumer doP) { + this.doP = doP; + } + + public static void build(QueryTEnum type, QueryWrapper q, String[] k , Object v){ + type.getDoP().accept(q,k,v); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/exception/BadConfigurationException.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/exception/BadConfigurationException.java new file mode 100644 index 0000000..40084af --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/exception/BadConfigurationException.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.exception; + +/** + * 统一关于错误配置信息 异常 + * + * @author: liaojinlong + * @date: 2020/6/10 18:06 + */ +public class BadConfigurationException extends RuntimeException { + /** + * Constructs a new runtime exception with {@code null} as its + * detail message. The cause is not initialized, and may subsequently be + * initialized by a call to {@link #initCause}. + */ + public BadConfigurationException() { + super(); + } + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public BadConfigurationException(String message) { + super(message); + } + + /** + * Constructs a new runtime exception with the specified detail message and + * cause.

Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public BadConfigurationException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new runtime exception with the specified cause and a + * detail message of {@code (cause==null ? null : cause.toString())} + * (which typically contains the class and detail message of + * {@code cause}). This constructor is useful for runtime exceptions + * that are little more than wrappers for other throwables. + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public BadConfigurationException(Throwable cause) { + super(cause); + } + + /** + * Constructs a new runtime exception with the specified detail + * message, cause, suppression enabled or disabled, and writable + * stack trace enabled or disabled. + * + * @param message the detail message. + * @param cause the cause. (A {@code null} value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @param enableSuppression whether or not suppression is enabled + * or disabled + * @param writableStackTrace whether or not the stack trace should + * be writable + * @since 1.7 + */ + protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/MsgType.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/MsgType.java new file mode 100644 index 0000000..0170005 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/MsgType.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.mnt.websocket; + +/** + * @author ZhangHouYing + * @date 2019-08-10 9:56 + */ +public enum MsgType { + /** 连接 */ + CONNECT, + /** 关闭 */ + CLOSE, + /** 信息 */ + INFO, + /** 错误 */ + ERROR +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/SocketMsg.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/SocketMsg.java new file mode 100644 index 0000000..d0030e9 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/SocketMsg.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.mnt.websocket; + +import lombok.Data; + +/** + * @author ZhangHouYing + * @date 2019-08-10 9:55 + */ +@Data +public class SocketMsg { + private Object msg; + private MsgType msgType; + + public SocketMsg(Object msg, MsgType msgType) { + this.msg = msg; + this.msgType = msgType; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/WebSocketServer.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/WebSocketServer.java new file mode 100644 index 0000000..4fa18e0 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/mnt/websocket/WebSocketServer.java @@ -0,0 +1,140 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.mnt.websocket; + +import com.alibaba.fastjson.JSONObject; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * @author ZhangHouYing + * @date 2019-08-10 15:46 + */ +@ServerEndpoint("/webSocket/{sid}") +@Slf4j +@Component +public class WebSocketServer { + + /** + * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 + */ + private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet(); + + /** + * 与某个客户端的连接会话,需要通过它来给客户端发送数据 + */ + private Session session; + + /** + * 接收sid + */ + private String sid=""; + /** + * 连接建立成功调用的方法 + * */ + @OnOpen + public void onOpen(Session session,@PathParam("sid") String sid) { + this.session = session; + //如果存在就先删除一个,防止重复推送消息 + for (WebSocketServer webSocket:webSocketSet) { + if (webSocket.sid.equals(sid)) { + webSocketSet.remove(webSocket); + } + } + webSocketSet.add(this); + this.sid=sid; + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose() { + webSocketSet.remove(this); + } + + /** + * 收到客户端消息后调用的方法 + * @param message 客户端发送过来的消息*/ + @OnMessage + public void onMessage(String message, Session session) { + log.info("收到来"+sid+"的信息:"+message); + //群发消息 + for (WebSocketServer item : webSocketSet) { + try { + item.sendMessage(message); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + + @OnError + public void onError(Session session, Throwable error) { + log.error("发生错误"); + error.printStackTrace(); + } + /** + * 实现服务器主动推送 + */ + private void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + + + /** + * 群发自定义消息 + * */ + public static void sendInfo(SocketMsg socketMsg, @PathParam("sid") String sid) throws IOException { + String message = JSONObject.toJSONString(socketMsg); + log.info("推送消息到"+sid+",推送内容:"+message); + for (WebSocketServer item : webSocketSet) { + try { + //这里可以设定只推送给这个sid的,为null则全部推送 + if(sid==null) { + item.sendMessage(message); + }else if(item.sid.equals(sid)){ + item.sendMessage(message); + } + } catch (IOException ignored) { } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + WebSocketServer that = (WebSocketServer) o; + return Objects.equals(session, that.session) && + Objects.equals(sid, that.sid); + } + + @Override + public int hashCode() { + return Objects.hash(session, sid); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/ConfigBeanConfiguration.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/ConfigBeanConfiguration.java new file mode 100644 index 0000000..ffc38d8 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/ConfigBeanConfiguration.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.security.config; + +import org.nl.sys.modular.backgroundmanagement.common.security.config.bean.LoginProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @apiNote 配置文件转换Pojo类的 统一配置 类 + * @author: liaojinlong + * @date: 2020/6/10 19:04 + */ +@Configuration +public class ConfigBeanConfiguration { + + @Bean + @ConfigurationProperties(prefix = "login", ignoreUnknownFields = true) + public LoginProperties loginProperties() { + return new LoginProperties(); + } + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginCode.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginCode.java new file mode 100644 index 0000000..f0c399a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginCode.java @@ -0,0 +1,61 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.security.config.bean; + +import lombok.Data; + +/** + * 登录验证码配置信息 + * + * @author: liaojinlong + * @date: 2020/6/10 18:53 + */ +@Data +public class LoginCode { + + /** + * 验证码配置 + */ + private LoginCodeEnum codeType; + /** + * 验证码有效期 分钟 + */ + private Long expiration = 2L; + /** + * 验证码内容长度 + */ + private int length = 2; + /** + * 验证码宽度 + */ + private int width = 111; + /** + * 验证码高度 + */ + private int height = 36; + /** + * 验证码字体 + */ + private String fontName; + /** + * 字体大小 + */ + private int fontSize = 25; + + public LoginCodeEnum getCodeType() { + return codeType; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginCodeEnum.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginCodeEnum.java new file mode 100644 index 0000000..7f6845f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginCodeEnum.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.security.config.bean; + +/** + * 验证码配置枚举 + * + * @author: liaojinlong + * @date: 2020/6/10 17:40 + */ + +public enum LoginCodeEnum { + /** + * 算数 + */ + arithmetic, + /** + * 中文 + */ + chinese, + /** + * 中文闪图 + */ + chinese_gif, + /** + * 闪图 + */ + gif, + spec +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginProperties.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginProperties.java new file mode 100644 index 0000000..ebf34ac --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/config/bean/LoginProperties.java @@ -0,0 +1,111 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version loginCode.length.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-loginCode.length.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.security.config.bean; + +import cn.hutool.core.util.StrUtil; +import io.github.eternalstone.captcha.gp.base.Captcha; +import io.github.eternalstone.captcha.gp.captcha.*; +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.exception.BadConfigurationException; + +import java.awt.*; +import java.util.Objects; + +/** + * 配置文件读取 + * + * @author liaojinlong + * @date loginCode.length0loginCode.length0/6/10 17:loginCode.length6 + */ +@Data +public class LoginProperties { + + /** + * 账号单用户 登录 + */ + private boolean singleLogin = false; + + private LoginCode loginCode; + /** + * 用户登录信息缓存 + */ + private boolean cacheEnable; + + public boolean isSingleLogin() { + return singleLogin; + } + + public boolean isCacheEnable() { + return cacheEnable; + } + + /** + * 获取验证码生产类 + * + * @return / + */ + public Captcha getCaptcha() { + if (Objects.isNull(loginCode)) { + loginCode = new LoginCode(); + if (Objects.isNull(loginCode.getCodeType())) { + loginCode.setCodeType(LoginCodeEnum.arithmetic); + } + } + return switchCaptcha(loginCode); + } + + /** + * 依据配置信息生产验证码 + * + * @param loginCode 验证码配置信息 + * @return / + */ + private Captcha switchCaptcha(LoginCode loginCode) { + Captcha captcha; + synchronized (this) { + switch (loginCode.getCodeType()) { + case arithmetic: + // 算术类型 https://gitee.com/whvse/EasyCaptcha + captcha = new ArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight()); + // 几位数运算,默认是两位 + captcha.setLen(loginCode.getLength()); + break; + case chinese: + captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + case chinese_gif: + captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + case gif: + captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + case spec: + captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + default: + throw new BadConfigurationException("验证码配置信息错误!正确配置查看 LoginCodeEnum "); + } + } + if(StrUtil.isNotEmpty(loginCode.getFontName())){ + captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize())); + } + return captcha; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/RedisListenerConfig.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/RedisListenerConfig.java new file mode 100644 index 0000000..5513f80 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/RedisListenerConfig.java @@ -0,0 +1,22 @@ +//package org.nl.sys.modular.backgroundmanagement.common.security.satoken; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.data.redis.connection.RedisConnectionFactory; +//import org.springframework.data.redis.listener.RedisMessageListenerContainer; +// +///** +// * @author: lyd +// * @description: redis监听配置 +// * @Date: 2022/10/8 +// */ +//@Configuration +//public class RedisListenerConfig { +// +//// @Bean +//// RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { +//// RedisMessageListenerContainer container = new RedisMessageListenerContainer(); +//// container.setConnectionFactory(connectionFactory); +//// return container; +//// } +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/SaTokenConfigure.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/SaTokenConfigure.java new file mode 100644 index 0000000..2e7bd1c --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/SaTokenConfigure.java @@ -0,0 +1,28 @@ +//package org.nl.sys.modular.backgroundmanagement.common.security.satoken; +// +//import cn.dev33.satoken.interceptor.SaInterceptor; +//import cn.dev33.satoken.jwt.StpLogicJwtForSimple; +//import cn.dev33.satoken.stp.StpLogic; +//import cn.dev33.satoken.stp.StpUtil; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +// +///** +// * @author: lyd +// * @description: sa-token的配置路由拦截 +// * @Date: 2022-09-20 +// */ +//@Slf4j +//@Configuration +//public class SaTokenConfigure implements WebMvcConfigurer { +// +// // Sa-Token 整合 jwt (Simple 简单模式) +// @Bean +// public StpLogic getStpLogicJwt() { +// return new StpLogicJwtForSimple(); +// } +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/StpInterfaceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/StpInterfaceImpl.java new file mode 100644 index 0000000..7cacad8 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/StpInterfaceImpl.java @@ -0,0 +1,38 @@ +//package org.nl.sys.modular.backgroundmanagement.common.security.satoken; +// +//import cn.dev33.satoken.stp.StpInterface; +//import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +//import org.springframework.stereotype.Component; +// +//import java.util.List; +// +///** +// * @author: lyd +// * @description: stp接口impl 自定义权限验证接口扩展 保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展 +// * @Date: 2022-09-20 +// */ +//@Component +//public class StpInterfaceImpl implements StpInterface { +// +// /** +// * 用户权限获取 +// * @param o login存入的值,此处存放用户id +// * @param s +// * @return +// */ +// @Override +// public List getPermissionList(Object o, String s) { +// return SecurityUtils.getCurrentUserPermissions(); +// } +// +// /** +// * 角色权限获取 - 数据库没有设计角色code,因此不推荐使用角色鉴权 +// * @param o +// * @param s +// * @return +// */ +// @Override +// public List getRoleList(Object o, String s) { +// return null; +// } +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/hint.md b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/hint.md new file mode 100644 index 0000000..627b958 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/satoken/hint.md @@ -0,0 +1,88 @@ +## 关于satoken的提示 +### 本系统采用两个session存放相关信息 +1、其中tokenSession存放的是 +提供公共模块使用,获取是Object可以直接强转此实体. +主要使用在 SecurityUtils类上,使用的key: userInfo +```java +@Data +public class CurrentUser implements Serializable { + @JsonSerialize(using = ToStringSerializer.class) + private String id; + + private String username; + + private Object user; + + private List permissions = new ArrayList<>(); +} +``` +2、Session存放的是UserDto,提供业务模块使用使用的key: UserDto +```java +@Getter +@Setter +public class UserDto extends BaseDTO implements Serializable { + @JsonSerialize(using = ToStringSerializer.class) + private String id; + + private Set roles; + + private Set jobs; + + private DeptSmallDto dept; + + private Long deptId; + + private String username; + + private String nickName; + + private String email; + + private String phone; + + private String gender; + + private String avatarName; + + private String avatarPath; + + private String extId; + + private String extuserId; + + + @JsonIgnore + private String password; + + private Boolean enabled; + + @JsonIgnore + private Boolean isAdmin = false; + + private Date pwdResetTime; +} +``` + +### 加密规则 +``` +SaSecureUtil.md5BySalt("123456", "salt") +``` + +### 另一种拦截 +``` +registry.addInterceptor(new SaRouteInterceptor((request, response, handler) -> { + System.out.println(SaHolder.getRequest().getRequestPath()); + // 登录验证 -- 排除多个路径 + SaRouter + // 获取所有的 + .match("/**") + // 排除下不需要拦截的 + .notMatch(securityProperties.getExcludes()) + // 对未排除的路径进行检查 + .check(() -> { + // 检查是否登录 是否有token + StpUtil.checkLogin(); + }); + })).addPathPatterns("/**"); + registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**"); +``` \ No newline at end of file diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/service/UserCacheClean.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/service/UserCacheClean.java new file mode 100644 index 0000000..8b3b83e --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/security/service/UserCacheClean.java @@ -0,0 +1,49 @@ +package org.nl.sys.modular.backgroundmanagement.common.security.service;///* +// * Copyright 2019-2020 the original author or authors. +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ +// +//package org.nl.common.security.service; +// +//import cn.hutool.core.util.StrUtil; +//import org.springframework.stereotype.Component; +// +///** +// * @author: liaojinlong +// * @date: 2020/6/11 18:01 +// * @apiNote: 用于清理 用户登录信息缓存,为防止Spring循环依赖与安全考虑 ,单独构成工具类 +// */ +//@Component +//public class UserCacheClean { +// +// /** +// * 清理特定用户缓存信息
+// * 用户信息变更时 +// * +// * @param userName / +// */ +// public void cleanUserCache(String userName) { +// if (StrUtil.isNotEmpty(userName)) { +//// UserDetailsServiceImpl.userDtoCache.remove(userName); +// } +// } +// +// /** +// * 清理所有用户的缓存信息
+// * ,如发生角色授权信息变化,可以简便的全部失效缓存 +// */ +//// public void cleanAll() { +//// UserDetailsServiceImpl.userDtoCache.clear(); +//// } +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/CopyUtil.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/CopyUtil.java new file mode 100644 index 0000000..bcded42 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/CopyUtil.java @@ -0,0 +1,36 @@ +package org.nl.sys.modular.backgroundmanagement.common.util; + +import org.springframework.beans.BeanUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/* + * @author ZZQ + * @Date 2022/12/1 3:35 下午 + */ +public class CopyUtil { + public static List copyList(final Collection sources, final Class clazz) { + if (sources == null) { + return new ArrayList(0); + } else { + List list = new ArrayList(sources.size()); + Iterator var3 = sources.iterator(); + + while(var3.hasNext()) { + Object source = var3.next(); + + try { + T dest = clazz.newInstance(); + BeanUtils.copyProperties(source, dest); + list.add(dest); + } catch (Throwable var6) { + } + } + return list; + } + } + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/ElAdminConstant.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/ElAdminConstant.java new file mode 100644 index 0000000..af27bcc --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/ElAdminConstant.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.util; + +/** + * 常用静态常量 + * + * @author Zheng Jie + * @date 2018-12-26 + */ +public class ElAdminConstant { + + /** + * 用于IP定位转换 + */ + public static final String REGION = "内网IP|内网IP"; + /** + * win 系统 + */ + public static final String WIN = "win"; + + /** + * mac 系统 + */ + public static final String MAC = "mac"; + + /** + * 常用接口 + */ + public static class Url { + // IP归属地查询 + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true"; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/EncryptUtils.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/EncryptUtils.java new file mode 100644 index 0000000..36983c7 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/EncryptUtils.java @@ -0,0 +1,100 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.util; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.IvParameterSpec; +import java.nio.charset.StandardCharsets; + +/** + * 加密 + * @author Zheng Jie + * @date 2018-11-23 + */ + +public class EncryptUtils { + + private static final String STR_PARAM = "Passw0rd"; + + private static Cipher cipher; + + private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8)); + + private static DESKeySpec getDesKeySpec(String source) throws Exception { + if (source == null || source.length() == 0){ + return null; + } + cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); + String strKey = "Passw0rd"; + return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8)); + } + + /** + * 对称加密 + */ + public static String desEncrypt(String source) throws Exception { + DESKeySpec desKeySpec = getDesKeySpec(source); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV); + return byte2hex( + cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase(); + } + + /** + * 对称解密 + */ + public static String desDecrypt(String source) throws Exception { + byte[] src = hex2byte(source.getBytes(StandardCharsets.UTF_8)); + DESKeySpec desKeySpec = getDesKeySpec(source); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + cipher.init(Cipher.DECRYPT_MODE, secretKey, IV); + byte[] retByte = cipher.doFinal(src); + return new String(retByte); + } + + private static String byte2hex(byte[] inStr) { + String stmp; + StringBuilder out = new StringBuilder(inStr.length * 2); + for (byte b : inStr) { + stmp = Integer.toHexString(b & 0xFF); + if (stmp.length() == 1) { + // 如果是0至F的单位字符串,则添加0 + out.append("0").append(stmp); + } else { + out.append(stmp); + } + } + return out.toString(); + } + + private static byte[] hex2byte(byte[] b) { + int size = 2; + if ((b.length % size) != 0){ + throw new IllegalArgumentException("长度不是偶数"); + } + byte[] b2 = new byte[b.length / 2]; + for (int n = 0; n < b.length; n += size) { + String item = new String(b, n, 2); + b2[n / 2] = (byte) Integer.parseInt(item, 16); + } + return b2; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/FileUtil.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/FileUtil.java new file mode 100644 index 0000000..ed32fbf --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/FileUtil.java @@ -0,0 +1,347 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.util; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.poi.excel.BigExcelWriter; +import cn.hutool.poi.excel.ExcelUtil; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.nl.exception.BadRequestException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.security.MessageDigest; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * File工具类,扩展 hutool 工具包 + * + * @author Zheng Jie + * @date 2018-12-27 + */ +public class FileUtil extends cn.hutool.core.io.FileUtil { + + private static final Logger log = LoggerFactory.getLogger(FileUtil.class); + + /** + * 系统临时目录 + *
+ * windows 包含路径分割符,但Linux 不包含, + * 在windows \\==\ 前提下, + * 为安全起见 同意拼装 路径分割符, + *

+     *       java.io.tmpdir
+     *       windows : C:\Users/xxx\AppData\Local\Temp\
+     *       linux: /temp
+     * 
+ */ + public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator; + /** + * 定义GB的计算常量 + */ + private static final int GB = 1024 * 1024 * 1024; + /** + * 定义MB的计算常量 + */ + private static final int MB = 1024 * 1024; + /** + * 定义KB的计算常量 + */ + private static final int KB = 1024; + + /** + * 格式化小数 + */ + private static final DecimalFormat DF = new DecimalFormat("0.00"); + + public static final String IMAGE = "图片"; + public static final String TXT = "文档"; + public static final String MUSIC = "音乐"; + public static final String VIDEO = "视频"; + public static final String OTHER = "其他"; + + + /** + * MultipartFile转File + */ + public static File toFile(MultipartFile multipartFile) { + // 获取文件名 + String fileName = multipartFile.getOriginalFilename(); + // 获取文件后缀 + String prefix = "." + getExtensionName(fileName); + File file = null; + try { + // 用uuid作为文件名,防止生成的临时文件重复 + //file = File.createTempFile(IdUtil.simpleUUID(), prefix); + file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix); + // MultipartFile to File + multipartFile.transferTo(file); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + return file; + } + + /** + * 获取文件扩展名,不带 . + */ + public static String getExtensionName(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length() - 1))) { + return filename.substring(dot + 1); + } + } + return filename; + } + + /** + * Java文件操作 获取不带扩展名的文件名 + */ + public static String getFileNameNoEx(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length()))) { + return filename.substring(0, dot); + } + } + return filename; + } + + /** + * 文件大小转换 + */ + public static String getSize(long size) { + String resultSize; + if (size / GB >= 1) { + //如果当前Byte的值大于等于1GB + resultSize = DF.format(size / (float) GB) + "GB "; + } else if (size / MB >= 1) { + //如果当前Byte的值大于等于1MB + resultSize = DF.format(size / (float) MB) + "MB "; + } else if (size / KB >= 1) { + //如果当前Byte的值大于等于1KB + resultSize = DF.format(size / (float) KB) + "KB "; + } else { + resultSize = size + "B "; + } + return resultSize; + } + + /** + * inputStream 转 File + */ + static File inputStreamToFile(InputStream ins, String name) throws Exception { + File file = new File(SYS_TEM_DIR + name); + if (file.exists()) { + return file; + } + OutputStream os = new FileOutputStream(file); + int bytesRead; + int len = 8192; + byte[] buffer = new byte[len]; + while ((bytesRead = ins.read(buffer, 0, len)) != -1) { + os.write(buffer, 0, bytesRead); + } + os.close(); + ins.close(); + return file; + } + + /** + * 将文件名解析成文件的上传路径 + */ + public static File upload(MultipartFile file, String filePath) { + Date date = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); + String name = getFileNameNoEx(file.getOriginalFilename()); + String suffix = getExtensionName(file.getOriginalFilename()); + String nowStr = "-" + format.format(date); + try { + String fileName = name + nowStr + "." + suffix; + String path = filePath + fileName; + // getCanonicalFile 可解析正确各种路径 + File dest = new File(path).getCanonicalFile(); + // 检测是否存在目录 + if (!dest.getParentFile().exists()) { + if (!dest.getParentFile().mkdirs()) { + System.out.println("was not successful."); + } + } + // 文件写入 + file.transferTo(dest); + return dest; + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return null; + } + + /** + * 导出excel + */ + public static void downloadExcel(List> list, HttpServletResponse response) throws IOException { + String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; + File file = new File(tempPath); + BigExcelWriter writer = ExcelUtil.getBigWriter(file); + // 一次性写出内容,使用默认样式,强制输出标题 + writer.write(list, true); + SXSSFSheet sheet = (SXSSFSheet)writer.getSheet(); + //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法 + sheet.trackAllColumnsForAutoSizing(); + //列宽自适应 + writer.autoSizeColumnAll(); + //response为HttpServletResponse对象 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); + ServletOutputStream out = response.getOutputStream(); + // 终止后删除临时文件 + file.deleteOnExit(); + writer.flush(out, true); + //此处记得关闭输出Servlet流 + IoUtil.close(out); + } + + public static String getFileType(String type) { + String documents = "txt doc pdf ppt pps xlsx xls docx"; + String music = "mp3 wav wma mpa ram ra aac aif m4a"; + String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; + String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg svg"; + if (image.contains(type)) { + return IMAGE; + } else if (documents.contains(type)) { + return TXT; + } else if (music.contains(type)) { + return MUSIC; + } else if (video.contains(type)) { + return VIDEO; + } else { + return OTHER; + } + } + + public static void checkSize(long maxSize, long size) { + // 1M + int len = 1024 * 1024; + if (size > (maxSize * len)) { + throw new BadRequestException("文件超出规定大小"); + } + } + + /** + * 判断两个文件是否相同 + */ + public static boolean check(File file1, File file2) { + String img1Md5 = getMd5(file1); + String img2Md5 = getMd5(file2); + return img1Md5.equals(img2Md5); + } + + /** + * 判断两个文件是否相同 + */ + public static boolean check(String file1Md5, String file2Md5) { + return file1Md5.equals(file2Md5); + } + + private static byte[] getByte(File file) { + // 得到文件长度 + byte[] b = new byte[(int) file.length()]; + try { + InputStream in = new FileInputStream(file); + try { + System.out.println(in.read(b)); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } catch (FileNotFoundException e) { + log.error(e.getMessage(), e); + return null; + } + return b; + } + + private static String getMd5(byte[] bytes) { + // 16进制字符 + char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + try { + MessageDigest mdTemp = MessageDigest.getInstance("MD5"); + mdTemp.update(bytes); + byte[] md = mdTemp.digest(); + int j = md.length; + char[] str = new char[j * 2]; + int k = 0; + // 移位 输出字符串 + for (byte byte0 : md) { + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return null; + } + + /** + * 下载文件 + * + * @param request / + * @param response / + * @param file / + */ + public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { + response.setCharacterEncoding(request.getCharacterEncoding()); + response.setContentType("application/octet-stream"); + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); + IOUtils.copy(fis, response.getOutputStream()); + response.flushBuffer(); + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + if (fis != null) { + try { + fis.close(); + if (deleteOnExit) { + file.deleteOnExit(); + } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + } + } + + public static String getMd5(File file) { + return getMd5(getByte(file)); + } + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/IdUtil.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/IdUtil.java new file mode 100644 index 0000000..87bd417 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/IdUtil.java @@ -0,0 +1,11 @@ +package org.nl.sys.modular.backgroundmanagement.common.util; + +public class IdUtil { + public static Long getLongId() { + return cn.hutool.core.util.IdUtil.getSnowflake(1, 1).nextId(); + } + + public static String getStringId() { + return String.valueOf(IdUtil.getLongId()); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/MapOf.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/MapOf.java new file mode 100644 index 0000000..563875d --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/MapOf.java @@ -0,0 +1,20 @@ +package org.nl.sys.modular.backgroundmanagement.common.util; + + +import java.io.Serializable; +import java.util.HashMap; + +/* + * @author ZZQ + * @Date 2022/11/29 2:55 下午 + */ +public class MapOf implements Serializable { + + public static HashMap of(K... key){ + HashMap map = new HashMap<>(); + for (int i = 0; i < (key.length & ~1); i=i+2) { + map.put(key[i],key[i+1]); + } + return map; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/PageUtil.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/PageUtil.java new file mode 100644 index 0000000..3d86006 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/PageUtil.java @@ -0,0 +1,59 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.util; + + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * 分页工具 + * @author Zheng Jie + * @date 2018-12-10 + */ +public class PageUtil extends cn.hutool.core.util.PageUtil { + + /** + * List 分页 + */ + public static List toPage(int page, int size , List list) { + int fromIndex = page * size; + int toIndex = page * size + size; + if(fromIndex > list.size()){ + return new ArrayList(); + } else if(toIndex >= list.size()) { + return list.subList(fromIndex,list.size()); + } else { + return list.subList(fromIndex,toIndex); + } + } + + + /** + * 自定义分页 + */ + public static Map toPage(Object object, Object totalElements) { + Map map = new LinkedHashMap<>(2); + map.put("content",object); + map.put("totalElements",totalElements); + return map; + } + + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/RedisUtils.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/RedisUtils.java new file mode 100644 index 0000000..4bea25a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/RedisUtils.java @@ -0,0 +1,708 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.Cursor; +import org.springframework.data.redis.core.RedisConnectionUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ScanOptions; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @author / + */ +@Component +@SuppressWarnings({"unchecked", "all"}) +public class RedisUtils { + private static final Logger log = LoggerFactory.getLogger(RedisUtils.class); + private RedisTemplate redisTemplate; + /* @Value("${jwt.online-key}")*/ + private String onlineKey; + + public RedisUtils(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + return true; + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @param timeUnit 单位 + */ + public boolean expire(String key, long time, TimeUnit timeUnit) { + try { + if (time > 0) { + redisTemplate.expire(key, time, timeUnit); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + return true; + } + + /** + * 根据 key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(Object key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 查找匹配key + * + * @param pattern key + * @return / + */ + public List scan(String pattern) { + ScanOptions options = ScanOptions.scanOptions().match(pattern).build(); + RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); + RedisConnection rc = Objects.requireNonNull(factory).getConnection(); + Cursor cursor = rc.scan(options); + List result = new ArrayList<>(); + while (cursor.hasNext()) { + result.add(new String(cursor.next())); + } + try { + RedisConnectionUtils.releaseConnection(rc, factory); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return result; + } + + /** + * 分页查询 key + * + * @param patternKey key + * @param page 页码 + * @param size 每页数目 + * @return / + */ + public List findKeysForPage(String patternKey, int page, int size) { + ScanOptions options = ScanOptions.scanOptions().match(patternKey).build(); + RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); + RedisConnection rc = Objects.requireNonNull(factory).getConnection(); + Cursor cursor = rc.scan(options); + List result = new ArrayList<>(size); + int tmpIndex = 0; + int fromIndex = page * size; + int toIndex = page * size + size; + while (cursor.hasNext()) { + if (tmpIndex >= fromIndex && tmpIndex < toIndex) { + result.add(new String(cursor.next())); + tmpIndex++; + continue; + } + // 获取到满足条件的数据后,就可以退出了 + if (tmpIndex >= toIndex) { + break; + } + tmpIndex++; + cursor.next(); + } + try { + RedisConnectionUtils.releaseConnection(rc, factory); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return result; + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + public void del(String... keys) { + if (keys != null && keys.length > 0) { + if (keys.length == 1) { + boolean result = redisTemplate.delete(keys[0]); + log.debug("--------------------------------------------"); + log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString()); + log.debug("--------------------------------------------"); + } else { + Set keySet = new HashSet<>(); + for (String key : keys) { + keySet.addAll(redisTemplate.keys(key)); + } + long count = redisTemplate.delete(keySet); + log.debug("--------------------------------------------"); + log.debug("成功删除缓存:" + keySet.toString()); + log.debug("缓存删除数量:" + count + "个"); + log.debug("--------------------------------------------"); + } + } + } + + // ============================String============================= + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 批量获取 + * + * @param keys + * @return + */ +// public List multiGet(List keys) { +// List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys)); +// List resultList = Lists.newArrayList(); +// Optional.ofNullable(list).ifPresent(e-> list.forEach(ele-> Optional.ofNullable(ele).ifPresent(resultList::add))); +// return resultList; +// } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间 + * @param timeUnit 类型 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time, TimeUnit timeUnit) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, timeUnit); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + // ================================Map================================= + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) { + expire(key, time); + } + return count; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return / + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + return redisTemplate.opsForList().remove(key, count, value); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * @param prefix 前缀 + * @param ids id + */ + public void delByKeys(String prefix, Set ids) { + Set keys = new HashSet<>(); + /* for (String id : ids) { + keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString())); + }*/ + long count = redisTemplate.delete(keys); + // 此处提示可自行删除 + log.debug("--------------------------------------------"); + log.debug("成功删除缓存:" + keys.toString()); + log.debug("缓存删除数量:" + count + "个"); + log.debug("--------------------------------------------"); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/SecurityUtils.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/SecurityUtils.java new file mode 100644 index 0000000..d05af51 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/SecurityUtils.java @@ -0,0 +1,87 @@ +package org.nl.sys.modular.backgroundmanagement.common.util; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.sys.modular.backgroundmanagement.common.util.dto.CurrentUser; + +import java.util.List; + +/** + * @author: lyd + * @description: 获取当前用户的信息 - 前提下在登录之后将数据存储到session + * @Date: + */ +@Slf4j +public class SecurityUtils { + + /** + * 获取系统用户 - CurrentUser + * + * @return 系统用户 + */ + public static CurrentUser getCurrentUser() { + try { + JSONObject json = (JSONObject) StpUtil.getExtra("loginInfo"); + if (ObjectUtil.isNotEmpty(json)) { + return json.toBean(CurrentUser.class); + } + } catch (Exception e) { + return new CurrentUser(); + } + return null; + } + + /** + * 获取系统用户名称 + * + * @return 系统用户名称 + */ + public static String getCurrentUsername() { + return getCurrentUser().getUsername(); + } + + /** + * 获取系统用户名称 + * + * @return 系统用户名称 + */ + public static String getCurrentNickName() { + return getCurrentUser().getPresonName(); + } + + /** + * 获取系统用户Id + * + * @return 系统用户Id + */ + public static String getCurrentUserId() { + return getCurrentUser().getId(); + } + + /** + * 获取系统用户Id + * + * @return 系统用户Id + */ + public static Long getDeptId() { +// return getCurrentUser().getUser().getDept().getId(); + return 1L; + } + + /** + * 获取当前用户权限 + * + * @return 权限列表 + */ + public static List getCurrentUserPermissions() { + JSONObject json = (JSONObject) StpUtil.getExtra("loginInfo"); + JSONArray permissions = json.getJSONArray("permissions"); + if (permissions.size() > 0) { + return permissions.toList(String.class); + } + return null; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/StringUtils.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/StringUtils.java new file mode 100644 index 0000000..ac3d483 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/StringUtils.java @@ -0,0 +1,254 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.common.util; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import nl.basjes.parse.useragent.UserAgent; +import nl.basjes.parse.useragent.UserAgentAnalyzer; +import org.nl.sys.modular.backgroundmanagement.config.ElAdminProperties; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.UnknownHostException; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; + +/** + * @author Zheng Jie + * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 + */ +@Slf4j +public class StringUtils { + + private static final char SEPARATOR = '_'; + private static final String UNKNOWN = "unknown"; + + + private static final UserAgentAnalyzer USER_AGENT_ANALYZER = UserAgentAnalyzer + .newBuilder() + .hideMatcherLoadStats() + .withCache(10000) + .withField(UserAgent.AGENT_NAME_VERSION) + .build(); + + /** + * 驼峰命名法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCamelCase(String s) { + if (s == null) { + return null; + } + + s = s.toLowerCase(); + + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == SEPARATOR) { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + + return sb.toString(); + } + + /** + * 驼峰命名法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCapitalizeCamelCase(String s) { + if (s == null) { + return null; + } + s = toCamelCase(s); + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + /** + * 驼峰命名法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + static String toUnderScoreCase(String s) { + if (s == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + boolean nextUpperCase = true; + + if (i < (s.length() - 1)) { + nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); + } + + if ((i > 0) && Character.isUpperCase(c)) { + if (!upperCase || !nextUpperCase) { + sb.append(SEPARATOR); + } + upperCase = true; + } else { + upperCase = false; + } + + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 获取ip地址 + */ + public static String getIp(HttpServletRequest request) { + // TODO 不解析IP地址 + if(true){ + return "127.0.0.1"; + } + + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + String comma = ","; + String localhost = "127.0.0.1"; + if (ip.contains(comma)) { + ip = ip.split(",")[0]; + } + if (localhost.equals(ip)) { + // 获取本机真正的ip地址 + try { + ip = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + log.error(e.getMessage(), e); + } + } + return ip; + } + + /** + * 根据ip获取详细地址 + */ + public static String getCityInfo(String ip) { + if (ElAdminProperties.ipLocal) { + // return getLocalCityInfo(ip); + return "局域网"; + } else { + return "局域网"; + // return getHttpCityInfo(ip); + } + } + + /** + * 根据ip获取详细地址 + */ + public static String getHttpCityInfo(String ip) { + String api = String.format(ElAdminConstant.Url.IP_URL, ip); + JSONObject object = JSONUtil.parseObj(HttpUtil.get(api)); + return object.get("addr", String.class); + } + + + public static String getBrowser(HttpServletRequest request) { + UserAgent.ImmutableUserAgent userAgent = USER_AGENT_ANALYZER.parse(request.getHeader("User-Agent")); + return userAgent.get(UserAgent.AGENT_NAME_VERSION).getValue(); + } + + /** + * 获得当天是周几 + */ + public static String getWeekDay() { + String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date()); + + int w = cal.get(Calendar.DAY_OF_WEEK) - 1; + if (w < 0) { + w = 0; + } + return weekDays[w]; + } + + /** + * 获取当前机器的IP + * + * @return / + */ + public static String getLocalIp() { + try { + InetAddress candidateAddress = null; + // 遍历所有的网络接口 + for (Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) { + NetworkInterface anInterface = interfaces.nextElement(); + // 在所有的接口下再遍历IP + for (Enumeration inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) { + InetAddress inetAddr = inetAddresses.nextElement(); + // 排除loopback类型地址 + if (!inetAddr.isLoopbackAddress()) { + if (inetAddr.isSiteLocalAddress()) { + // 如果是site-local地址,就是它了 + return inetAddr.getHostAddress(); + } else if (candidateAddress == null) { + // site-local类型的地址未被发现,先记录候选地址 + candidateAddress = inetAddr; + } + } + } + } + if (candidateAddress != null) { + return candidateAddress.getHostAddress(); + } + // 如果没有发现 non-loopback地址.只能用最次选的方案 + InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); + if (jdkSuppliedAddress == null) { + return ""; + } + return jdkSuppliedAddress.getHostAddress(); + } catch (Exception e) { + return ""; + } + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/dto/CurrentUser.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/dto/CurrentUser.java new file mode 100644 index 0000000..46d5394 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/common/util/dto/CurrentUser.java @@ -0,0 +1,31 @@ +package org.nl.sys.modular.backgroundmanagement.common.util.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @author: lyd + * @description: 当前用户的信息 + * @Date: + */ +@Data +public class CurrentUser implements Serializable { + @JsonSerialize(using = ToStringSerializer.class) + private String id; + + //账号 + private String username; + //姓名 + private String presonName; + + //用户详细信息 + private SysUser user; + + private List permissions = new ArrayList<>(); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/CallBack.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/CallBack.java new file mode 100644 index 0000000..198451f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/CallBack.java @@ -0,0 +1,41 @@ +package org.nl.sys.modular.backgroundmanagement.config;/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author: liaojinlong + * @date: 2020/6/9 17:02 + * @since: 1.0 + * @see {@link SpringContextHolder} + * 针对某些初始化方法,在SpringContextHolder 初始化前时,
+ * 可提交一个 提交回调任务。
+ * 在SpringContextHolder 初始化后,进行回调使用 + */ + +public interface CallBack { + /** + * 回调执行方法 + */ + void executor(); + + /** + * 本回调任务名称 + * @return / + */ + default String getCallBackName() { + return Thread.currentThread().getId() + ":" + this.getClass().getName(); + } +} + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/ElAdminProperties.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/ElAdminProperties.java new file mode 100644 index 0000000..40567fc --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/ElAdminProperties.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.config; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author Zheng Jie + * @description + * @date 2021-11-22 + **/ +@Data +@Component +public class ElAdminProperties { + + public static Boolean ipLocal; + + @Value("${ip.local-parsing}") + public void setIpLocal(Boolean ipLocal) { + ElAdminProperties.ipLocal = ipLocal; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/ElPermissionConfig.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/ElPermissionConfig.java new file mode 100644 index 0000000..9000dcf --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/ElPermissionConfig.java @@ -0,0 +1,33 @@ +///* +// * Copyright 2019-2020 Zheng Jie +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ +//package org.nl.sys.modular.backgroundmanagement.config; +// +//import org.springframework.stereotype.Service; +// +///** +// * @author Zheng Jie +// */ +//@Service(value = "el") +//public class ElPermissionConfig { +// +// public Boolean check(String ...permissions){ +// // 获取当前用户的所有权限 +//// List elPermissions = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()); +// // 判断当前用户的所有权限是否包含接口上定义的权限 +//// return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains); +// return true; +// } +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/RedisConfig.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/RedisConfig.java new file mode 100644 index 0000000..0a29b40 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/RedisConfig.java @@ -0,0 +1,216 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.config; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cache.Cache; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.CacheErrorHandler; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Zheng Jie + * @date 2018-11-24 + */ +@Slf4j +@Configuration +@EnableCaching +@ConditionalOnClass(RedisOperations.class) +@EnableConfigurationProperties(RedisProperties.class) +public class RedisConfig extends CachingConfigurerSupport { + + /** + * 设置 redis 数据默认过期时间,默认2小时 + * 设置@cacheable 序列化方式 + */ + @Bean + public RedisCacheConfiguration redisCacheConfiguration(){ + FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); + RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); + configuration = configuration.serializeValuesWith(RedisSerializationContext. + SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(6)); + return configuration; + } + + @SuppressWarnings("all") + @Bean(name = "redisTemplate") + @ConditionalOnMissingBean(name = "redisTemplate") + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + //序列化 + FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); + // value值的序列化采用fastJsonRedisSerializer + template.setValueSerializer(fastJsonRedisSerializer); + template.setHashValueSerializer(fastJsonRedisSerializer); + // 全局开启AutoType,这里方便开发,使用全局的方式 + ParserConfig.getGlobalInstance().setAutoTypeSupport(true); + // 建议使用这种方式,小范围指定白名单 + // ParserConfig.getGlobalInstance().addAccept("org.nl.domain"); + // key的序列化采用StringRedisSerializer + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.setConnectionFactory(redisConnectionFactory); + return template; + } + + /** + * 自定义缓存key生成策略,默认将使用该策略 + */ + @Bean + @Override + public KeyGenerator keyGenerator() { + return (target, method, params) -> { + Map container = new HashMap<>(3); + Class targetClassClass = target.getClass(); + // 类地址 + container.put("class",targetClassClass.toGenericString()); + // 方法名称 + container.put("methodName",method.getName()); + // 包名称 + container.put("package",targetClassClass.getPackage()); + // 参数列表 + for (int i = 0; i < params.length; i++) { + container.put(String.valueOf(i),params[i]); + } + // 转为JSON字符串 + String jsonString = JSON.toJSONString(container); + // 做SHA256 Hash计算,得到一个SHA256摘要作为Key + return DigestUtils.sha256Hex(jsonString); + }; + } + + @Bean + @Override + public CacheErrorHandler errorHandler() { + // 异常处理,当Redis发生异常时,打印日志,但是程序正常走 + log.info("初始化 -> [{}]", "Redis CacheErrorHandler"); + return new CacheErrorHandler() { + @Override + public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { + log.error("Redis occur handleCacheGetError:key -> [{}]", key, e); + } + + @Override + public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { + log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e); + } + + @Override + public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { + log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e); + } + + @Override + public void handleCacheClearError(RuntimeException e, Cache cache) { + log.error("Redis occur handleCacheClearError:", e); + } + }; + } + +} + +/** + * Value 序列化 + * + * @author / + * @param + */ + class FastJsonRedisSerializer implements RedisSerializer { + + private final Class clazz; + + FastJsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8); + } + + @Override + public T deserialize(byte[] bytes) { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, StandardCharsets.UTF_8); + return JSON.parseObject(str, clazz); + } + +} + +/** + * 重写序列化器 + * + * @author / + */ +class StringRedisSerializer implements RedisSerializer { + + private final Charset charset; + + StringRedisSerializer() { + this(StandardCharsets.UTF_8); + } + + private StringRedisSerializer(Charset charset) { + Assert.notNull(charset, "Charset must not be null!"); + this.charset = charset; + } + + @Override + public String deserialize(byte[] bytes) { + return (bytes == null ? null : new String(bytes, charset)); + } + + @Override + public byte[] serialize(Object object) { + String string = JSON.toJSONString(object); + if (StrUtil.isEmpty(string)) { + return null; + } + string = string.replace("\"", ""); + return string.getBytes(charset); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/SpringContextHolder.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/SpringContextHolder.java new file mode 100644 index 0000000..e02f743 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/SpringContextHolder.java @@ -0,0 +1,156 @@ +package org.nl.sys.modular.backgroundmanagement.config;/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.env.Environment; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jie + * @date 2019-01-07 + */ +@Slf4j +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + //数据库连接的bean名字 + public static String dataSourceBeanName="dataSource"; + private static final List CALL_BACKS = new ArrayList<>(); + private static boolean addCallback = true; + + /** + * 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。 + * 在SpringContextHolder 初始化后,进行回调使用 + * + * @param callBack 回调函数 + */ + public synchronized static void addCallBacks(CallBack callBack) { + if (addCallback) { + SpringContextHolder.CALL_BACKS.add(callBack); + } else { + log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName()); + callBack.executor(); + } + } + public static ApplicationContext getApplicationContext() { + try { + + } catch (Exception e) { + e.printStackTrace(); + } + return applicationContext; + + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 获取SpringBoot 配置信息 + * + * @param property 属性key + * @param defaultValue 默认值 + * @param requiredType 返回类型 + * @return / + */ + public static T getProperties(String property, T defaultValue, Class requiredType) { + T result = defaultValue; + try { + result = getBean(Environment.class).getProperty(property, requiredType); + } catch (Exception ignored) {} + return result; + } + + /** + * 获取SpringBoot 配置信息 + * + * @param property 属性key + * @return / + */ + public static String getProperties(String property) { + return getProperties(property, null, String.class); + } + + /** + * 获取SpringBoot 配置信息 + * + * @param property 属性key + * @param requiredType 返回类型 + * @return / + */ + public static T getProperties(String property, Class requiredType) { + return getProperties(property, null, requiredType); + } + + /** + * 检查ApplicationContext不为空. + */ + private static void assertContextInjected() { + if (applicationContext == null) { + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); + } + } + + /** + * 清除SpringContextHolder中的ApplicationContext为Null. + */ + private static void clearHolder() { + log.debug("清除SpringContextHolder中的ApplicationContext:" + + applicationContext); + applicationContext = null; + } + + @Override + public void destroy() { + SpringContextHolder.clearHolder(); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (SpringContextHolder.applicationContext != null) { + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); + } + SpringContextHolder.applicationContext = applicationContext; + if (addCallback) { + for (CallBack callBack : SpringContextHolder.CALL_BACKS) { + callBack.executor(); + } + CALL_BACKS.clear(); + } + SpringContextHolder.addCallback = false; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/StringConverter.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/StringConverter.java new file mode 100644 index 0000000..4797716 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/StringConverter.java @@ -0,0 +1,20 @@ +package org.nl.sys.modular.backgroundmanagement.config; + + +import cn.hutool.core.util.StrUtil; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +@Component +public class StringConverter implements Converter { + + @Override + public String convert(String source) { + if (StrUtil.isNotEmpty(source)) { + if (source.contains("\\")) { + source = source.replace("\\", "\\\\\\"); + } + } + return source; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/jackson/BigNumberSerializer.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/jackson/BigNumberSerializer.java new file mode 100644 index 0000000..1545298 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/jackson/BigNumberSerializer.java @@ -0,0 +1,42 @@ +package org.nl.sys.modular.backgroundmanagement.config.jackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; +import com.fasterxml.jackson.databind.ser.std.NumberSerializer; + +import java.io.IOException; + +/** + * 超出 JS 最大最小值 处理 + * + * @author Lion Li + */ +@JacksonStdImpl +public class BigNumberSerializer extends NumberSerializer { + + /** + * 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来 + */ + private static final long MAX_SAFE_INTEGER = 9007199254740991L; + private static final long MIN_SAFE_INTEGER = -9007199254740991L; + + /** + * 提供实例 + */ + public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class); + + public BigNumberSerializer(Class rawType) { + super(rawType); + } + + @Override + public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { + // 超出范围 序列化位字符串 + if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { + super.serialize(value, gen, provider); + } else { + gen.writeString(value.toString()); + } + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/jackson/JacksonObjectMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/jackson/JacksonObjectMapper.java new file mode 100644 index 0000000..d18f00e --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/jackson/JacksonObjectMapper.java @@ -0,0 +1,81 @@ +package org.nl.sys.modular.backgroundmanagement.config.jackson; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; + +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; + +/** + * jackson 配置 + * + * @author Lion Li + * @author JohanChan + * @ProjectName Demo + * @Description 与前端交互时对实体类中Long类型的ID字段序列号 + * @time 2021/6/23 11:30 + */ +/** + * @author JohanChan + * @ProjectName Demo + * @Description 与前端交互时对实体类中Long类型的ID字段序列号 + * @time 2021/6/23 11:30 + */ + +/** + * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象 + * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象] + * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON] + */ +public class JacksonObjectMapper extends ObjectMapper { + + public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; + public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss"; + + public JacksonObjectMapper() { + super(); + //收到未知属性时不报异常 + this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); + + //反序列化时,属性不存在的兼容处理 + this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + SimpleModule simpleModule = new SimpleModule() + //将BigInteger型数字转换成字符串,避免丢失精度 + .addSerializer(BigInteger.class, ToStringSerializer.instance) + //将Long型数字转换成字符串,避免丢失精度 + .addSerializer(Long.class, ToStringSerializer.instance) + //将Integer型数字转换成字符串 + .addSerializer(Integer.class, ToStringSerializer.instance) + //将int型数字转换成字符串 + .addSerializer(int.class, ToStringSerializer.instance) + //将long型数字转换成字符串 + .addSerializer(long.class, ToStringSerializer.instance) + //序列化和反序列化日期格式 + .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))) + .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))) + .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))) + .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))) + .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))) + .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))); + + + //注册功能模块 例如,可以添加自定义序列化器和反序列化器 + this.registerModule(simpleModule); + } +} + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/saconfig/LoginUserHandler.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/saconfig/LoginUserHandler.java new file mode 100644 index 0000000..0209e7d --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/saconfig/LoginUserHandler.java @@ -0,0 +1,24 @@ +//package org.nl.sys.modular.backgroundmanagement.config.saconfig; +// +//import cn.dev33.satoken.stp.StpUtil; +//import cn.dev33.satoken.util.SaResult; +//import org.springframework.stereotype.Component; +// +//import java.util.function.BiFunction; +// +///* +// * @author ZZQ +// * @Date 2022/11/24 3:47 下午 +// */ +//@Component +//public class LoginUserHandler implements BiFunction { +// @Override +// public Object apply(String user, String password) { +// //用户登入账号密码查询: +// StpUtil.login(Long.valueOf(password)); +// +// return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue()); +// +// } +// +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/saconfig/SaInitCOnfig.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/saconfig/SaInitCOnfig.java new file mode 100644 index 0000000..de44ad2 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/config/saconfig/SaInitCOnfig.java @@ -0,0 +1,33 @@ +//package org.nl.sys.modular.backgroundmanagement.config.saconfig; +// +//import cn.dev33.satoken.config.SaSsoConfig; +//import cn.hutool.http.HttpRequest; +//import cn.hutool.http.HttpResponse; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.servlet.ModelAndView; +// +///* +// * @author ZZQ +// * @Date 2022/11/28 10:58 上午 +// */ +//@Configuration +//public class SaInitCOnfig { +// +// @Autowired +// LoginUserHandler loginUserHandler; +// +// @Autowired +// public void configSso(SaSsoConfig sso) { +// System.out.println("启动初始化-----SaSsoConfig"); +// // 配置:未登录时返回的View +// sso.setNotLoginView(() -> new ModelAndView("sa-login")); +// // 配置:登录处理函数 +// sso.setDoLoginHandle(loginUserHandler); +// +// sso.setSendHttp(s -> { +// HttpResponse execute = HttpRequest.get(s).execute(); +// return execute.body(); +// }); +// } +//} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/controller/DeptController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/controller/DeptController.java new file mode 100644 index 0000000..47fb588 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/controller/DeptController.java @@ -0,0 +1,109 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.dept.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.nl.exception.BadRequestException; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.util.PageUtil; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysDept; +import org.nl.sys.modular.backgroundmanagement.dept.dto.DeptQuery; +import org.nl.sys.modular.backgroundmanagement.dept.service.ISysDeptService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Set; + +/** +* @author Zheng Jie +* @date 2019-03-25 +*/ +@RestController +@RequestMapping("/api/dept") +public class DeptController { + + @Autowired + private ISysDeptService deptService; + + @Log("查询部门") + @GetMapping + public ResponseEntity query(DeptQuery query) throws Exception { + List list = deptService.list(query.build()); + return new ResponseEntity<>(PageUtil.toPage(list, list.size()),HttpStatus.OK); + } + + @Log("查询部门") + @GetMapping("/vo") + public ResponseEntity queryvo(DeptQuery query, PageQuery pageQuery) throws Exception { + Page deptPage = deptService.queryVo(query, pageQuery); + return new ResponseEntity((TableDataInfo.build(deptPage)),HttpStatus.OK); + } + + + @Log("查询所有部门树") + @GetMapping("/allTree") + public ResponseEntity allTree(DeptQuery query) { + return new ResponseEntity<>(deptService.buildTree(query),HttpStatus.OK); + } + + @Log("查询部门:根据ID获取同级与上级数据") + @PostMapping("/superior") + @SaCheckPermission(value = {"user:list", "dept:list"}, mode = SaMode.AND) + public ResponseEntity getSuperior(@RequestBody List ids) { + if (CollectionUtils.isEmpty(ids)){ + return ResponseEntity.noContent().build(); + } + return new ResponseEntity<>(deptService.getSuperior(ids),HttpStatus.OK); + } + + @Log("新增部门") + @PostMapping +// @SaCheckPermission("dept:add") + public ResponseEntity create(@Validated @RequestBody SysDept resources){ + deptService.createDept(resources); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @Log("修改部门") + @PutMapping +// @SaCheckPermission("dept:edit") + public ResponseEntity update(@Validated @RequestBody SysDept dept){ + if (dept.getPid() != null && dept.getDept_id().equals(dept.getPid())) { + throw new BadRequestException("上级不能为自己"); + } + deptService.updateDept(dept); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除部门") + @DeleteMapping + public ResponseEntity delete(@RequestBody Set deptIds){ + if (CollectionUtils.isEmpty(deptIds)){ + return ResponseEntity.noContent().build(); + } + deptService.delateDept(deptIds); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dao/SysDept.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dao/SysDept.java new file mode 100644 index 0000000..800d3db --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dao/SysDept.java @@ -0,0 +1,93 @@ +package org.nl.sys.modular.backgroundmanagement.dept.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 部门 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_dept") +public class SysDept implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "dept_id", type = IdType.NONE) + private String dept_id; + + /** + * 上级部门 + */ + private String pid; + + /** + * 子部门数目 + */ + private Integer sub_count; + + /** + * 名称 + */ + private String name; + + /** + * 排序 + */ + private Integer dept_sort; + + /** + * 状态 + */ + private Boolean is_used; + + private String create_id; + + /** + * 创建者 + */ + private String create_name; + + private String update_id; + + /** + * 更新者 + */ + private String update_name; + + /** + * 创建日期 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date create_time; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date update_time; + + /** + * 部门编号 + */ + private String code; + + private String ext_id; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dao/SysUserDept.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dao/SysUserDept.java new file mode 100644 index 0000000..a7bc4d4 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dao/SysUserDept.java @@ -0,0 +1,35 @@ +package org.nl.sys.modular.backgroundmanagement.dept.dao; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 部门表 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_user_dept") +public class SysUserDept implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户标识 + */ + private Long user_id; + + /** + * 部门标识 + */ + private Long dept_id; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dto/DeptQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dto/DeptQuery.java new file mode 100644 index 0000000..ab494d7 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dto/DeptQuery.java @@ -0,0 +1,33 @@ +package org.nl.sys.modular.backgroundmanagement.dept.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.BaseQuery; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.QParam; +import org.nl.sys.modular.backgroundmanagement.common.enums.QueryTEnum; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysDept; + +import java.util.List; + +/* + * @author ZZQ + * @Date 2022/12/15 4:20 下午 + */ +@Data +public class DeptQuery extends BaseQuery { + + private List deptIds; + + private String name; + + private String code; + + private Long pid; + + private Boolean pid_is_null; + + @Override + public void paramMapping() { + super.doP.put("pid_is_null", QParam.builder().k(new String[]{"pid"}).type(QueryTEnum.NO).build()); + super.doP.put("deptIds", QParam.builder().k(new String[]{"dept_id"}).type(QueryTEnum.IN).build()); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dto/DeptTree.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dto/DeptTree.java new file mode 100644 index 0000000..ece80b6 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/dto/DeptTree.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.dept.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** +* @author Zheng Jie +* @date 2019-03-25 +*/ +@Getter +@Setter +public class DeptTree implements Serializable { + + private String dept_id; + + private String pid; + + private String name; + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/SysDeptMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/SysDeptMapper.java new file mode 100644 index 0000000..4ba41c0 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/SysDeptMapper.java @@ -0,0 +1,44 @@ +package org.nl.sys.modular.backgroundmanagement.dept.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysDept; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + *

+ * 部门 Mapper 接口 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface SysDeptMapper extends BaseMapper { + + /** + * 保存依赖关系 + * @param UserId + * @param deptId + */ + void saveDeptRelation(@Param("user") String UserId,@Param("depts") Collection deptId); + void delDeptRelation(@Param("user") String UserId); + + List getDeptRelation(@Param("deptIds") Collection deptIds); + + /** + * 跟新sub_count字段 + * @param deptId + * @return + */ + int updateSubCount(String deptId); + + /** + * 返回字符串列表 split = , + * @param pid + * @return + */ + String findAllChild(String pid); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/SysUserDeptMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/SysUserDeptMapper.java new file mode 100644 index 0000000..f6a51c1 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/SysUserDeptMapper.java @@ -0,0 +1,16 @@ +package org.nl.sys.modular.backgroundmanagement.dept.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysUserDept; + +/** + *

+ * 部门表 Mapper 接口 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface SysUserDeptMapper extends BaseMapper { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/mapping/SysDeptMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/mapping/SysDeptMapper.xml new file mode 100644 index 0000000..2f23169 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/mapping/SysDeptMapper.xml @@ -0,0 +1,40 @@ + + + + + + replace into sys_user_dept values + + (#{user},#{dept}) + + + + delete from sys_user_dept where user_id = #{user} + + + + update sys_dept set sub_count = + (select m.count from (select count(*) count from sys_dept where pid = #{pid}) as m) + where dept_id = #{pid} + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/mapping/SysUserDeptMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/mapping/SysUserDeptMapper.xml new file mode 100644 index 0000000..28f4809 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/mapper/mapping/SysUserDeptMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/ISysDeptService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/ISysDeptService.java new file mode 100644 index 0000000..2dba9a2 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/ISysDeptService.java @@ -0,0 +1,67 @@ +package org.nl.sys.modular.backgroundmanagement.dept.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysDept; +import org.nl.sys.modular.backgroundmanagement.dept.dto.DeptQuery; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 部门 服务类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface ISysDeptService extends IService { + /** + * 条件查询 + * @param query + * @param pageQuery + * @return + */ + Page queryVo(DeptQuery query, PageQuery pageQuery); + + /** + * 条件查询树结构 + * @param query + * @return + */ + Map buildTree(DeptQuery query); + + /** + * 查询当前部门id的上级id + * @param deptIds + * @return + */ + Map getSuperior(List deptIds); + + /** + * 保存用户部门关系 + * @param UserId + * @param deptIds + */ + void saveUserDeptRelation(String UserId, Collection deptIds); + void delUserDeptRelation(String user); + + /** + * 更新部门:同时更新节点 + * @param dept + */ + void updateDept(SysDept dept); + + /** + * 删除部门及子部门 + * @param deptIds + */ + void delateDept(Set deptIds); + + void createDept(SysDept dept); + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/ISysUserDeptService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/ISysUserDeptService.java new file mode 100644 index 0000000..c60927a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/ISysUserDeptService.java @@ -0,0 +1,16 @@ +package org.nl.sys.modular.backgroundmanagement.dept.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysUserDept; + +/** + *

+ * 部门表 服务类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface ISysUserDeptService extends IService { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/impl/SysDeptServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..eba3a45 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,179 @@ +package org.nl.sys.modular.backgroundmanagement.dept.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.domain.vo.DeptVo; +import org.nl.sys.modular.backgroundmanagement.common.util.CopyUtil; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.common.util.dto.CurrentUser; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysDept; +import org.nl.sys.modular.backgroundmanagement.dept.dto.DeptQuery; +import org.nl.sys.modular.backgroundmanagement.dept.dto.DeptTree; +import org.nl.sys.modular.backgroundmanagement.dept.mapper.SysDeptMapper; +import org.nl.sys.modular.backgroundmanagement.dept.service.ISysDeptService; +import org.nl.util.IdUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 部门 服务实现类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Service +public class SysDeptServiceImpl extends ServiceImpl implements ISysDeptService { + + @Autowired + private SysDeptMapper sysDeptMapper; + + @Override + public Map buildTree(DeptQuery query) { + List list = this.list(query.build()); + List deptTrees = CopyUtil.copyList(list, DeptTree.class); + return this.buildTree(deptTrees); + } + + @Override + public Map getSuperior(List deptIds) { + return null; + } + + private Map buildTree(List deptDtos) { + List trees= new ArrayList<>(); + Set depts = new LinkedHashSet<>(); + List deptNames = deptDtos.stream().map(DeptTree::getName).collect(Collectors.toList()); + boolean isChild; + for (DeptTree deptDTO : deptDtos) { + isChild = false; + if (deptDTO.getPid() == null) { + trees.add(deptDTO); + } + for (DeptTree it : deptDtos) { + if (it.getPid() != null && deptDTO.getDept_id().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(this.getById(deptDTO.getPid()).getName())) { + depts.add(deptDTO); + } + } + Map map = new HashMap<>(2); + map.put("totalElements", deptDtos.size()); + map.put("content", CollectionUtil.isEmpty(trees) ? deptDtos : trees); + return map; + } + + @Override + public Page queryVo(DeptQuery query, PageQuery pageQuery) { + if (query.getPid_is_null() == null){ + if (query.getPid() == null){ + query.setPid_is_null(true); + } + if (StrUtil.isNotEmpty(query.getName()) || query.getIs_used()!=null){ + query.setPid_is_null(null); + } + } + Page page = this.page(pageQuery.build(SysDept.class), query.build()); + page.setRecords(CopyUtil.copyList(page.getRecords(), DeptVo.class)); + if (StrUtil.isNotEmpty(query.getName()) || query.getIs_used()!=null){ + page.getRecords().forEach(a->((DeptVo)a).setHas_children(false) ); + } + return page; + } + + + @Override + public void saveUserDeptRelation(String userId, Collection deptIds) { + if (StrUtil.isEmpty(userId) || CollectionUtils.isEmpty(deptIds)){ + return; + } + sysDeptMapper.saveDeptRelation(userId,deptIds); + } + + @Override + public void delUserDeptRelation(String user) { + sysDeptMapper.delDeptRelation(user); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDept(SysDept dept) { + if (dept == null ||StrUtil.isEmpty(dept.getDept_id())){ + return; + } + this.updateById(dept); + //删除节点信息 + sysDeptMapper.updateSubCount(dept.getDept_id()); + if (StrUtil.isNotEmpty(dept.getPid())){ + sysDeptMapper.updateSubCount(dept.getPid()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delateDept(Set deptIds) { + if (CollectionUtils.isEmpty(deptIds)){ + return; + } + verification(deptIds); + Set depts = new HashSet<>(); + Set pids = new HashSet<>(); + List deptList = sysDeptMapper.selectList(new QueryWrapper().in("dept_id", deptIds)); + for (String deptId : deptIds) { + depts.add(deptId); + String allChild = sysDeptMapper.findAllChild(deptId); + if (StrUtil.isNotEmpty(allChild)){ + String[] split = allChild.split(","); + depts.addAll(Arrays.asList(split)); + } + } + this.remove(new QueryWrapper().in("dept_id", depts)); + deptList.forEach(dept -> { + if (StrUtil.isNotEmpty(dept.getPid())){sysDeptMapper.updateSubCount(dept.getPid());} + }); + + } + + private void verification(Set depeIds) { + if (!CollectionUtils.isEmpty(depeIds)){ + List deptRelation = sysDeptMapper.getDeptRelation(depeIds); + if (!CollectionUtils.isEmpty(deptRelation)){ + throw new BadRequestException("部门存在绑定的人员,请先解绑人员对应部门"); + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void createDept(SysDept dept) { + dept.setDept_id(IdUtil.getStringId()); + CurrentUser user = SecurityUtils.getCurrentUser(); + dept.setCreate_id(user.getId()); + dept.setCreate_name(user.getPresonName()); + dept.setCreate_time(new Date()); + this.save(dept); + // 清理缓存 + if (StrUtil.isNotEmpty(dept.getPid())){ + sysDeptMapper.updateSubCount(dept.getPid()); + } + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/impl/SysUserDeptServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/impl/SysUserDeptServiceImpl.java new file mode 100644 index 0000000..c9bf5f6 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dept/service/impl/SysUserDeptServiceImpl.java @@ -0,0 +1,20 @@ +package org.nl.sys.modular.backgroundmanagement.dept.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysUserDept; +import org.nl.sys.modular.backgroundmanagement.dept.mapper.SysUserDeptMapper; +import org.nl.sys.modular.backgroundmanagement.dept.service.ISysUserDeptService; +import org.springframework.stereotype.Service; + +/** + *

+ * 部门表 服务实现类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Service +public class SysUserDeptServiceImpl extends ServiceImpl implements ISysUserDeptService { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/controller/SysDictController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/controller/SysDictController.java new file mode 100644 index 0000000..ead2461 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/controller/SysDictController.java @@ -0,0 +1,113 @@ +package org.nl.sys.modular.backgroundmanagement.dict.controller; + +import com.alibaba.fastjson.JSONObject; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; +import org.nl.sys.modular.backgroundmanagement.dict.dto.DictQuery; +import org.nl.sys.modular.backgroundmanagement.dict.service.ISysDictService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 字典表 前端控制器 + *

+ * + * @author generator + * @since 2022-12-14 + */ +@RestController +@RequestMapping("/api/dict") +public class SysDictController { + + @Autowired + private ISysDictService dictService; + + @Log("查询字典") + @GetMapping + public ResponseEntity query(@RequestParam Map whereJson, PageQuery pageable){ + return new ResponseEntity<>(TableDataInfo.build(dictService.queryAll(whereJson,pageable)), HttpStatus.OK); + } + + @Log("查询所有字典信息") + @GetMapping(value = "/all") + public ResponseEntity queryAll(){ + return new ResponseEntity<>(dictService.queryAll(),HttpStatus.OK); + } + + @Log("新增字典") + @PostMapping + public ResponseEntity create(@RequestBody Dict dict){ + dictService.create(dict); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PutMapping + @Log("修改字典") + public ResponseEntity updateDict(@Validated @RequestBody Dict dto){ + dictService.updateDict(dto); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除字典") + @DeleteMapping +// @SaCheckPermission("dict:del") + public ResponseEntity delete(@RequestBody Set ids){ + dictService.deleteBatchByIds(ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + @GetMapping("/dictDetail") + @Log("查询字典详情") + public ResponseEntity queryDetails(@RequestParam Map criteria, PageQuery pageable){ + DictQuery dictQuery = JSONObject.parseObject(JSONObject.toJSONString(criteria), DictQuery.class); + return new ResponseEntity<>(TableDataInfo.build(dictService.queryAllDetail(dictQuery,pageable)),HttpStatus.OK); + } + + @Log("查询多个字典详情") + @GetMapping(value = "/dictDetail/map") + public ResponseEntity getDictDetailMaps(@RequestParam String dictName){ + String[] names = dictName.split("[,,]"); + Map> dictMap = new HashMap<>(16); + for (String name : names) { + dictMap.put(name, dictService.getDictByName(name)); + } + return new ResponseEntity<>(dictMap, HttpStatus.OK); + } + + @Log("新增字典详情") + @PostMapping("/dictDetail") +// @SaCheckPermission("dict:add") + public ResponseEntity createDetail(@RequestBody Dict resources){ + dictService.createDetail(resources); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @Log("修改字典详情") + @PutMapping("/dictDetail") +// @SaCheckPermission("dict:edit") + public ResponseEntity updateDetail(@RequestBody Dict resources){ + dictService.updateDetail(resources); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除字典详情") + @DeleteMapping(value = "/dictDetail/{id}") +// @SaCheckPermission("dict:del") + public ResponseEntity deleteDetail(@PathVariable String id){ + dictService.deleteDetail(id); + return new ResponseEntity<>(HttpStatus.OK); + } + +} + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/dao/Dict.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/dao/Dict.java new file mode 100644 index 0000000..22b0542 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/dao/Dict.java @@ -0,0 +1,107 @@ +package org.nl.sys.modular.backgroundmanagement.dict.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + *

+ * 字典表 + *

+ * + * @author generator + * @since 2022-12-14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_dict") +public class Dict implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 字典标识 + */ + @TableId(value = "dict_id") + private String dict_id; + + /** + * 编码 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 字典标签 + */ + private String label; + + /** + * 字典值 + */ + private String value; + + /** + * 排序号 + */ + private BigDecimal dict_sort; + + /** + * 字典类型 + */ + private String dict_type; + + /** + * 参数1 + */ + private String para1; + + /** + * 参数2 + */ + private String para2; + + /** + * 参数3 + */ + private String para3; + + /** + * 创建人 + */ + private String create_id; + + /** + * 创建人 + */ + private String create_name; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改人 + */ + private String update_id; + + /** + * 修改人 + */ + private String update_name; + + /** + * 修改时间 + */ + private String update_time; + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/dto/DictQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/dto/DictQuery.java new file mode 100644 index 0000000..299fd33 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/dto/DictQuery.java @@ -0,0 +1,18 @@ +package org.nl.sys.modular.backgroundmanagement.dict.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.BaseQuery; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; + +/** + * @Author: lyd + * @Description: + * @Date: 2022/12/15 + */ +@Data +public class DictQuery extends BaseQuery { + private String code; + + private String dict_name; + private String dict_id; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/mapper/SysDictMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/mapper/SysDictMapper.java new file mode 100644 index 0000000..8c4c516 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/mapper/SysDictMapper.java @@ -0,0 +1,16 @@ +package org.nl.sys.modular.backgroundmanagement.dict.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; + +/** + *

+ * 字典表 Mapper 接口 + *

+ * + * @author generator + * @since 2022-12-14 + */ +public interface SysDictMapper extends BaseMapper { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/mapper/mapping/SysDictMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/mapper/mapping/SysDictMapper.xml new file mode 100644 index 0000000..21de339 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/mapper/mapping/SysDictMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/service/ISysDictService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/service/ISysDictService.java new file mode 100644 index 0000000..3d9976d --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/service/ISysDictService.java @@ -0,0 +1,87 @@ +package org.nl.sys.modular.backgroundmanagement.dict.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; +import org.nl.sys.modular.backgroundmanagement.dict.dto.DictQuery; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 字典表 服务类 + *

+ * + * @author generator + * @since 2022-12-14 + */ +public interface ISysDictService extends IService { + + /** + * 分页查找 + * @param whereJson + * @param pageable + * @return + */ + IPage queryAll(Map whereJson, PageQuery pageable); + + /** + * 新增 + * @param dict + */ + void create(Dict dict); + + /** + * 修改字典数据 + * @param dto + */ + void updateDict(Dict dto); + + /** + * 通过id批量删除字典 + * @param ids + */ + void deleteBatchByIds(Set ids); + + /** + * 分页查询获取字典明细 + * @param criteria + * @param pageable + * @return + */ + IPage queryAllDetail(DictQuery criteria, PageQuery pageable); + + /** + * 获取字典明细 + * @param name + * @return + */ + List getDictByName(String name); + + /** + * 添加字典明细 + * @param resources + */ + void createDetail(Dict resources); + + /** + * 更新字典明细 + * @param resources + */ + void updateDetail(Dict resources); + + /** + * 删除字典 + * @param id + */ + void deleteDetail(String id); + + /** + * 查询所有字典信息 + * @return + */ + List queryAll(); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/service/impl/SysDictServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/service/impl/SysDictServiceImpl.java new file mode 100644 index 0000000..7e17f49 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/dict/service/impl/SysDictServiceImpl.java @@ -0,0 +1,196 @@ +package org.nl.sys.modular.backgroundmanagement.dict.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; +import org.nl.sys.modular.backgroundmanagement.dict.dto.DictQuery; +import org.nl.sys.modular.backgroundmanagement.dict.mapper.SysDictMapper; +import org.nl.sys.modular.backgroundmanagement.dict.service.ISysDictService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 字典表 服务实现类 + *

+ * + * @author generator + * @since 2022-12-14 + */ +@Service +public class SysDictServiceImpl extends ServiceImpl implements ISysDictService { + @Autowired + private SysDictMapper sysDictMapper; + + @Override + public IPage queryAll(Map whereJson, PageQuery page) { + String blurry = null; + if (ObjectUtil.isNotEmpty(whereJson.get("blurry"))) blurry = whereJson.get("blurry").toString(); + IPage pages = this.page(new Page<>(page.getPage() + 1, page.getSize()), new QueryWrapper() + .select("MAX(dict_id) AS dict_id, code, name") + .lambda() + .like(ObjectUtil.isNotEmpty(blurry), Dict::getCode, blurry) + .or(ObjectUtil.isNotEmpty(blurry)) + .like(ObjectUtil.isNotEmpty(blurry), Dict::getName, blurry) + .orderBy(true, true, Dict::getCode) + .groupBy(Dict::getCode, Dict::getName)); + return pages; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Dict dict) { + String currentUserId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String date = DateUtil.now(); + List oldDict = sysDictMapper.selectList(new LambdaQueryWrapper() + .eq(ObjectUtil.isNotEmpty(dict.getCode()), Dict::getCode, dict.getCode())); + if (ObjectUtil.isNotEmpty(oldDict)) throw new BadRequestException("字典[" + dict.getCode() + "]已存在"); + dict.setDict_id(IdUtil.getSnowflake(1, 1).nextIdStr()); + dict.setCreate_id(currentUserId); + dict.setCreate_name(nickName); + dict.setCreate_time(date); + dict.setUpdate_id(currentUserId); + dict.setUpdate_name(nickName); + dict.setUpdate_time(date); + sysDictMapper.insert(dict); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDict(Dict dto) { + Dict dict = sysDictMapper.selectById(dto.getDict_id()); + if (ObjectUtil.isEmpty(dict)) { + throw new BadRequestException("字典不存在"); + } + List dictList = sysDictMapper.selectList(new LambdaQueryWrapper().eq(Dict::getCode, dto.getCode())); + if (ObjectUtil.isNotEmpty(dictList) && !dto.getCode().equals(dict.getCode())) + throw new BadRequestException("字典[" + dto.getCode() + "]已存在"); + String currentUserId = SecurityUtils.getCurrentUserId(); + String currentNickName = SecurityUtils.getCurrentNickName(); + // 根据code获取所有字典 + List dicts = sysDictMapper.selectList(new LambdaQueryWrapper().eq(Dict::getCode, dict.getCode())); + dicts.forEach(di -> { + di.setCode(dto.getCode()); + di.setName(dto.getName()); + di.setUpdate_id(currentUserId); + di.setUpdate_name(currentNickName); + di.setUpdate_time(DateUtil.now()); + sysDictMapper.updateById(di); + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteBatchByIds(Set ids) { + // 查找code删除 + ids.forEach(id -> { + String code = sysDictMapper.selectById(id).getCode(); + sysDictMapper.delete(new LambdaQueryWrapper().eq(Dict::getCode, code)); + }); + } + + @Override + public IPage queryAllDetail(DictQuery criteria, PageQuery page) { + LambdaQueryWrapper lam = new LambdaQueryWrapper<>(); + lam.eq(Dict::getCode, criteria.getCode()) + .isNotNull(Dict::getLabel) + .ne(Dict::getLabel, "") + .orderBy(true, true, Dict::getDict_sort); + IPage pages = new Page<>(page.getPage() + 1, page.getSize()); + sysDictMapper.selectPage(pages, lam); + return pages; + } + + @Override + public List getDictByName(String name) { + List dictList = sysDictMapper.selectList(new LambdaQueryWrapper().eq(Dict::getCode, name) + .isNotNull(Dict::getLabel) + .ne(Dict::getLabel, "")); + return dictList; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void createDetail(Dict dict) { + // 校验是否已经有标签 + Dict one = sysDictMapper.selectOne(new LambdaQueryWrapper().eq(Dict::getLabel, dict.getLabel()) + .eq(Dict::getCode, dict.getCode())); + if (ObjectUtil.isNotEmpty(one)) throw new BadRequestException("标签[" + dict.getLabel() + "]已存在"); + // 判断是否有空的值 + List selectOne = sysDictMapper.selectList(new LambdaQueryWrapper().eq(Dict::getCode, dict.getCode())); + Dict dic = selectOne.get(0); + if (ObjectUtil.isEmpty(dic.getLabel())) { + // 空就赋值 + dic.setCode(dict.getCode()); + dic.setLabel(dict.getLabel()); + dic.setValue(dict.getValue()); + dic.setDict_sort(dict.getDict_sort()); + dic.setDict_type(dict.getDict_type()); + dic.setPara1(dict.getPara1()); + dic.setPara2(dict.getPara2()); + dic.setPara3(dict.getPara3()); + sysDictMapper.updateById(dic); + return; + } + // 插入新的数据 + dict.setDict_id(IdUtil.getSnowflake(1, 1).nextIdStr()); + dict.setCode(dic.getCode()); + dict.setName(dic.getName()); + dict.setCreate_id(SecurityUtils.getCurrentUserId()); + dict.setCreate_name(SecurityUtils.getCurrentNickName()); + dict.setCreate_time(DateUtil.now()); + dict.setUpdate_id(SecurityUtils.getCurrentUserId()); + dict.setUpdate_name(SecurityUtils.getCurrentNickName()); + dict.setUpdate_time(DateUtil.now()); + sysDictMapper.insert(dict); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDetail(Dict resources) { + Dict dict = sysDictMapper.selectById(resources.getDict_id()); + if (ObjectUtil.isEmpty(dict)) { + throw new BadRequestException("被删除或无权限,操作失败!"); + } + // 校验是否已经有标签 + List dictList = sysDictMapper.selectList(new LambdaQueryWrapper().eq(Dict::getLabel, resources.getLabel()) + .eq(Dict::getCode, resources.getCode())); + if (ObjectUtil.isNotEmpty(dictList) && !resources.getLabel().equals(dict.getLabel())) { + throw new BadRequestException("标签[" + resources.getLabel() + "]已存在"); + } + resources.setUpdate_id(SecurityUtils.getCurrentUserId()); + resources.setUpdate_name(SecurityUtils.getCurrentNickName()); + resources.setUpdate_time(DateUtil.now()); + sysDictMapper.updateById(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteDetail(String id) { + sysDictMapper.deleteById(id); + } + + @Override + public List queryAll() { + return sysDictMapper.selectList(new QueryWrapper() + .select("MAX(dict_id) AS dictId, code, name") + .lambda() + .groupBy(Dict::getCode, Dict::getName)); + } + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/controller/SysMenuController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/controller/SysMenuController.java new file mode 100644 index 0000000..71f11d7 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/controller/SysMenuController.java @@ -0,0 +1,128 @@ +package org.nl.sys.modular.backgroundmanagement.menu.controller; + + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.menu.dao.SysMenu; +import org.nl.sys.modular.backgroundmanagement.menu.dto.MenuDto; +import org.nl.sys.modular.backgroundmanagement.menu.dto.MenuQuery; +import org.nl.sys.modular.backgroundmanagement.menu.service.ISysMenuService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 菜单表 前端控制器 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@RestController +@RequestMapping("api/sysMenu") +public class SysMenuController { + @Autowired + private ISysMenuService iSysMenuService; + + @GetMapping(value = "/build") + @Log("根据用户获取菜单") + public ResponseEntity buildMenus(@Validated String systemType) { + //校验系统表是否存在该系统类型 + return new ResponseEntity(iSysMenuService.buildMenus(systemType),HttpStatus.OK); + } + + @Log("返回全部的菜单") + @GetMapping(value = "/lazy") + @SaCheckPermission(value = {"menu:list", "roles:list"}, mode = SaMode.AND) + public ResponseEntity query(@RequestParam String pid) { + return new ResponseEntity<>(iSysMenuService.getMenus(pid), HttpStatus.OK); + } + @Log("获取菜单列表") + @PostMapping(value = "/getMenusByRole") + @SaCheckPermission(value = {"menu:list", "roles:list"}, mode = SaMode.AND) + public ResponseEntity getMenusByRole(@RequestBody JSONObject json) { + String role_id = json.getString("role_id"); + String system_type = json.getString("system_type"); + String category = json.getString("category"); + return new ResponseEntity<>(iSysMenuService.getMenusByRole(role_id, system_type, category), HttpStatus.OK); + } + + @Log("根据菜单ID返回所有子节点ID,包含自身ID") + @GetMapping(value = "/child") + @SaCheckPermission(value = {"menu:list", "roles:list"}, mode = SaMode.AND) + public ResponseEntity child(@RequestParam String id) { + Set menuSet = new HashSet<>(); + List menuList = iSysMenuService.getMenus(id); + menuSet.add(iSysMenuService.findById(id)); + menuSet = iSysMenuService.getChildMenus(menuList, menuSet); + Set ids = menuSet.stream().map(SysMenu::getMenu_id).collect(Collectors.toSet()); + return new ResponseEntity<>(ids, HttpStatus.OK); + } + + @GetMapping + @Log("查询菜单") + @SaCheckPermission("menu:list") + public ResponseEntity pageQuery(MenuQuery query, PageQuery page) throws Exception { + if (ObjectUtil.isEmpty(page.getSort())) { + page.setSort("menu_sort,asc"); + } + List list = iSysMenuService.query(query, page); + return new ResponseEntity<>(TableDataInfo.build(list), HttpStatus.OK); + } + + @Log("查询菜单:根据ID获取同级与上级数据") + @PostMapping("/superior") + @SaCheckPermission("menu:list") + public ResponseEntity getSuperior(@RequestBody JSONObject param) { + Set menuDtos = new LinkedHashSet<>(); + String id=param.getString("ids"); + if (StrUtil.isNotEmpty(id)) { + menuDtos.addAll(iSysMenuService.getSuperior(iSysMenuService.doToDto(iSysMenuService.findById(id)), new ArrayList<>())); + return new ResponseEntity<>(iSysMenuService.buildTree(new ArrayList<>(menuDtos)), HttpStatus.OK); + } + return new ResponseEntity<>(iSysMenuService.getMenus(null), HttpStatus.OK); + } + + @Log("新增菜单") + @PostMapping + @SaCheckPermission("menu:add") + public ResponseEntity create(@RequestBody SysMenu form) { + iSysMenuService.create(form); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @Log("修改菜单") + @PutMapping + @SaCheckPermission("menu:edit") + public ResponseEntity update( @RequestBody SysMenu form) { + iSysMenuService.update(form); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除菜单") + @DeleteMapping + @SaCheckPermission("menu:del") + public ResponseEntity delete(@RequestBody Set ids) { + Set menuSet = new HashSet<>(); + for (String id : ids) { + List menuList = iSysMenuService.getMenus(id); + menuSet.add(iSysMenuService.findById(id)); + menuSet = iSysMenuService.getChildMenus(menuList, menuSet); + } + iSysMenuService.delete(menuSet); + return new ResponseEntity<>(HttpStatus.OK); + } +} + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dao/SysMenu.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dao/SysMenu.java new file mode 100644 index 0000000..28537c3 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dao/SysMenu.java @@ -0,0 +1,141 @@ +package org.nl.sys.modular.backgroundmanagement.menu.dao; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 菜单表 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_menu") +public class SysMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 菜单标识 + */ + @TableId(value = "menu_id", type = IdType.NONE) + private String menu_id; + + /** + * 上级菜单ID + */ + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String pid; + + /** + * 子菜单数目 + */ + private Integer sub_count; + + /** + * 菜单类型 + */ + private String type; + + /** + * 所属系统 + */ + private String system_type; + + /** + * 菜单分类 + */ + private String category; + + /** + * 菜单标题 + */ + private String title; + + /** + * 组件名称 + */ + private String component_name; + + /** + * 组件 + */ + private String component; + + /** + * 排序 + */ + private Integer menu_sort; + + /** + * 图标 + */ + private String icon; + + /** + * 链接地址 + */ + private String path; + + /** + * 是否外链 + */ + private Boolean iframe; + + /** + * 是否缓存 + */ + private Boolean cache; + + /** + * 是否隐藏 + */ + private Boolean hidden; + + /** + * 权限 + */ + private String permission; + + /** + * 创建人标识 + */ + private String create_id; + + /** + * 创建人 + */ + private String create_name; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date create_time; + + /** + * 修改人标识 + */ + private String update_id; + + /** + * 修改人 + */ + private String update_name; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date update_time; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dto/MenuDto.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dto/MenuDto.java new file mode 100644 index 0000000..dd45f7e --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dto/MenuDto.java @@ -0,0 +1,93 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.menu.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.base.BaseDTO; + +import java.io.Serializable; +import java.util.List; +import java.util.Objects; + +@Data +public class MenuDto extends BaseDTO implements Serializable { + + private String menu_id; + + private List children; + + private String type; + + private String permission; + + private String title; + + private Integer menu_sort; + + private String path; + private String name; + + private String component; + + private String pid; + + private Integer sub_count; + + private Boolean iframe; + + private String system_type; + + private Boolean cache; + + private Boolean hidden; + + private String component_name; + + private String icon; + + private boolean has_children; + + private boolean leaf; + + public Boolean getHas_children() { + return sub_count > 0; + } + + public Boolean getLeaf() { + return sub_count <= 0; + } + + public String getLabel() { + return title; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MenuDto menuDto = (MenuDto) o; + return Objects.equals(menu_id, menuDto.menu_id); + } + + @Override + public int hashCode() { + return Objects.hash(menu_id); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dto/MenuQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dto/MenuQuery.java new file mode 100644 index 0000000..0d3b485 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/dto/MenuQuery.java @@ -0,0 +1,23 @@ +package org.nl.sys.modular.backgroundmanagement.menu.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.BaseQuery; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.QParam; +import org.nl.sys.modular.backgroundmanagement.common.enums.QueryTEnum; +import org.nl.sys.modular.backgroundmanagement.menu.dao.SysMenu; + +/** + * @Author: lyd + * @Description: + * @Date: 2022/12/15 + */ +@Data +public class MenuQuery extends BaseQuery { + private String pid = ""; + private String system_type; + @Override + public void paramMapping() { + this.doP.put("pid", QParam.builder().k(new String[]{"pid"}).type(QueryTEnum.OREQ).build()); + this.doP.put("blurry", QParam.builder().k(new String[]{"title"}).type(QueryTEnum.LK).build()); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/mapper/SysMenuMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/mapper/SysMenuMapper.java new file mode 100644 index 0000000..cf1ab88 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/mapper/SysMenuMapper.java @@ -0,0 +1,62 @@ +package org.nl.sys.modular.backgroundmanagement.menu.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.nl.sys.modular.backgroundmanagement.menu.dao.SysMenu; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 菜单表 Mapper 接口 + *

+ * + * @author ldjun + * @since 2022-12-15 + */ +public interface SysMenuMapper extends BaseMapper { + @Select("select * from sys_menu where (pid is null or pid = '' or pid = 0 )") + List findByPidIsNull(); + + @Select("select * from sys_menu where pid = #{pid}") + List findByPid(@Param("pid") String pid); + + /** + * 根据用户获取菜单 + * + * @param userId 用户标识 + * @return 当前用户拥有的菜单列表 + */ + List findByUser(@Param("userId") String userId); + + /** + * 获取系统菜单 + * @param userId + * @param systemType + * @return + */ + List findSystemMenu(@Param("user") String userId,@Param("systemType") String systemType); + + /** + * 根据用户标识获取权限列表 + * + * @param userId 用户标识 + * @return 权限列表 + */ + List getPermissionByUserId(@Param("userId") String userId); + + /** + * 解绑角色菜单 + * + * @param menuId 菜单ID + */ + @Delete(value = "delete from sys_roles_menus where menu_id = #{menuId}") + void untiedMenu(String menuId); + + List getMenusByRole(@Param("systemType") String systemType, @Param("category")String category); + + String findAllChild(String pid); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/mapper/mapping/SysMenuMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/mapper/mapping/SysMenuMapper.xml new file mode 100644 index 0000000..3c63431 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/mapper/mapping/SysMenuMapper.xml @@ -0,0 +1,102 @@ + + + + + + + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/service/ISysMenuService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/service/ISysMenuService.java new file mode 100644 index 0000000..0203b11 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/service/ISysMenuService.java @@ -0,0 +1,140 @@ +package org.nl.sys.modular.backgroundmanagement.menu.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.domain.vo.MenuVo; +import org.nl.sys.modular.backgroundmanagement.menu.dao.SysMenu; +import org.nl.sys.modular.backgroundmanagement.menu.dto.MenuDto; +import org.nl.sys.modular.backgroundmanagement.menu.dto.MenuQuery; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 菜单表 服务类 + *

+ * + * @author ldjun + * @since 2022-12-15 + */ +public interface ISysMenuService extends IService { + /** + * 查询全部数据,菜单不使用分页 + * + * @param param 查询条件 + * @return + */ + List queryAll(Map param); + + /** + * 条件查询 + * @param query + * @param page + * @return + */ + List query(MenuQuery query, PageQuery page); + + /** + * 根据ID获取同级与上级数据 + * + * @param menuDto 菜单对象 + * @param menus + * @return / + */ + List getSuperior(MenuDto menuDto, List menus); + + /** + * 根据ID查询 菜单对象 + * + * @param id 菜单标识 + * @return 菜单对象 + */ + SysMenu findById(String id); + + /** + * 根据菜单父节点标识查询菜单列表 + * + * @param pid + * @return 菜单列表 + */ + List findByPid(String pid); + + /** + * 查询父节点为空的菜单列表 + * + * @return 菜单列表 + */ + List findByPidIsNull(); + + /** + * 获取所有子节点,包含自身ID + * + * @param menuList + * @param menuSet + * @return / + */ + Set getChildMenus(List menuList, Set menuSet); + + /** + * 创建 + * + * @param menu + */ + void create(SysMenu menu); + + /** + * 删除 + * + * @param menuSet + */ + void delete(Set menuSet); + + /** + * 编辑 + * + * @param menu + */ + void update(SysMenu menu); + + + List findByUser(String userId); + + /** + * 构建菜单树 + * + * @param menuDtos + * @return / + */ + List buildMenus(List menuDtos); + List buildMenus(List menuDtos,String pid); + + List buildMenus(String systemType); + + /** + * 构建菜单树 + * + * @param menuDtos 原始数据 + * @return / + */ + List buildTree(List menuDtos); + + /** + * 懒加载菜单数据 + * + * @param pid / + * @return / + */ + List getMenus(String pid); + + /** + * @param sysMenu + * @return + */ + MenuDto doToDto(SysMenu sysMenu); + + List getMenusByRole(String roleId, String systemType, String category); + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/service/impl/SysMenuServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..265316f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/menu/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,455 @@ +package org.nl.sys.modular.backgroundmanagement.menu.service.impl; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +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.compress.utils.Lists; +import org.apache.commons.lang3.StringUtils; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.domain.constant.DictConstantPool; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.domain.vo.MenuMetaVo; +import org.nl.sys.modular.backgroundmanagement.common.domain.vo.MenuVo; +import org.nl.sys.modular.backgroundmanagement.common.util.CopyUtil; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; +import org.nl.sys.modular.backgroundmanagement.dict.mapper.SysDictMapper; +import org.nl.sys.modular.backgroundmanagement.menu.dao.SysMenu; +import org.nl.sys.modular.backgroundmanagement.menu.dto.MenuDto; +import org.nl.sys.modular.backgroundmanagement.menu.dto.MenuQuery; +import org.nl.sys.modular.backgroundmanagement.menu.mapper.SysMenuMapper; +import org.nl.sys.modular.backgroundmanagement.menu.service.ISysMenuService; +import org.nl.util.IdUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 菜单表 服务实现类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Service +@Slf4j +public class SysMenuServiceImpl extends ServiceImpl implements ISysMenuService { + + @Autowired + private SysMenuMapper baseMapper; + + @Autowired + private SysDictMapper sysDictMapper; + + @Override + public List queryAll(Map param) { +// 父节点标识 + String pid = MapUtil.getStr(param, "pid"); + return getMenus(pid).stream().map(menu -> this.doToDto(menu)).collect(Collectors.toList()); + } + + + @Override + public List query(MenuQuery query, PageQuery page) { + if (StringUtils.isNotEmpty(query.getBlurry())){ + query.setPid(null); + } + Page menuPage = this.page(page.build(), query.build()); + List collect = menuPage.getRecords().stream().map(menu -> this.doToDto(menu)).collect(Collectors.toList()); + return collect; + } + + @Override + public List getSuperior(MenuDto menuDto, List menus) { + if (menuDto.getPid() == null) { + menus.addAll(this.findByPidIsNull()); + return menus.stream().map(menu -> this.doToDto(menu)).collect(Collectors.toList()); + } + menus.addAll(baseMapper.findByPid(menuDto.getPid())); + + return getSuperior(this.doToDto(findById(menuDto.getPid())), menus); + } + + @Override + public SysMenu findById(String id) { + return baseMapper.selectById(id); + } + + @Override + public List findByPid(String pid) { + return baseMapper.findByPid(pid); + } + + @Override + public List findByPidIsNull() { + return baseMapper.findByPidIsNull(); + } + + @Override + public Set getChildMenus(List menuList, Set menuSet) { + for (SysMenu menu : menuList) { + menuSet.add(menu); + List menus = this.findByPid(menu.getMenu_id()); + if (menus != null && menus.size() != 0) { + getChildMenus(menus, menuSet); + } + } + return menuSet; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void create(SysMenu resources) { + + if (resources.getIframe()) { + String http = "http://", https = "https://"; + if (!(resources.getPath().toLowerCase().startsWith(http) || resources.getPath().toLowerCase().startsWith(https))) { + throw new BadRequestException("外链必须以http://或者https://开头"); + } + } + resources.setMenu_id(IdUtil.getStringId()); + if (resources.getPid().equals("0")) { + resources.setPid(null); + addSystemTypeDict(resources); + } + + baseMapper.insert(resources); + // 计算子节点数目 + resources.setSub_count(0); + // 更新父节点菜单数目 + updateSubCnt(resources.getPid()); + updateRootSystemType(resources); + } + + private void addSystemTypeDict(SysMenu resources) { + Dict dict = sysDictMapper.selectOne(new QueryWrapper().eq("code", DictConstantPool.DICT_SYS_CODE).orderByDesc("value").last("limit 1")); + Integer currentType = dict!=null?Integer.valueOf(dict.getValue())+1:1; + Dict currentSysType = new Dict(); + currentSysType.setDict_id(IdUtil.getStringId()); + currentSysType.setCode(DictConstantPool.DICT_SYS_CODE); + currentSysType.setName(DictConstantPool.DICT_SYS_NAME); + currentSysType.setLabel(resources.getTitle()); + currentSysType.setValue(String.valueOf(currentType)); + currentSysType.setPara1(resources.getMenu_id()); + sysDictMapper.insert(currentSysType); + resources.setSystem_type(String.valueOf(currentType)); + } + private void updateRootSystemType(SysMenu sysMenu) { + String rootMenuId = this.findRootMenuId(sysMenu.getMenu_id()); + if (sysMenu.getMenu_id().equals(rootMenuId)){ + return; + } + SysMenu rootMenu = this.findById(rootMenuId); + sysMenu.setSystem_type(rootMenu.getSystem_type()); + this.updateById(sysMenu); + } + private String findRootMenuId(String menuId) { + SysMenu sysMenu = this.findById(menuId); + if (StrUtil.isEmpty(sysMenu.getPid())) { + return menuId; + } else { + return findRootMenuId(sysMenu.getPid()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set menuSet) { + List pids = Lists.newArrayList(); + for (SysMenu menu : menuSet) { + //解绑菜单 + baseMapper.untiedMenu(menu.getMenu_id()); + baseMapper.deleteById(menu.getMenu_id()); + String pid = menu.getPid(); + if (StringUtils.isEmpty(pid)){ + pids.add(pid); + } + updateSubCnt(pid); + } + if (!CollectionUtils.isEmpty(pids)){ + sysDictMapper.delete(new QueryWrapper().in("para1", pids).eq("code", DictConstantPool.DICT_SYS_CODE)); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void update(SysMenu resources) { + String menuId = resources.getMenu_id(); + SysMenu menu = baseMapper.selectById(menuId); + String allChild = baseMapper.findAllChild(menuId); // 获取当前菜单的所有子菜单 + List allChildIds = ObjectUtil.isNotEmpty(allChild)?Arrays.asList(allChild.split(",")):null; + if (ObjectUtil.isNotEmpty(allChildIds) && allChildIds.contains(resources.getPid())){ + throw new BadRequestException("上级不能为自己或自己的下级"); + } + if (resources.getIframe()) { + String http = "http://", https = "https://"; + if (!(resources.getPath().toLowerCase().startsWith(http) || resources.getPath().toLowerCase().startsWith(https))) { + throw new BadRequestException("外链必须以http://或者https://开头"); + } + } + + if (resources.getPid().equals("0")) { + resources.setPid(null); + if (StringUtils.isNotEmpty(menu.getPid())){ + addSystemTypeDict(resources); + } + }else { + resources.setSystem_type(this.findById(resources.getPid()).getSystem_type()); + } + String oldPid = menu.getPid(); + String newPid = resources.getPid(); + // 记录的父节点ID + if (oldPid == null && newPid != null){ + sysDictMapper.delete(new QueryWrapper().eq("para1",menu.getMenu_id())); + } + 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.setMenu_sort(resources.getMenu_sort()); + menu.setCache(resources.getCache()); + menu.setHidden(resources.getHidden()); + menu.setComponent_name(resources.getComponent_name()); + menu.setPermission(resources.getPermission()); + menu.setType(resources.getType()); + baseMapper.updateById(menu); + // 计算父级菜单节点数目 + updateSubCnt(oldPid); + updateSubCnt(newPid); + //更新SystemType + if (!resources.getSystem_type().equals(menu.getSystem_type())){ + this.update(new UpdateWrapper().set(DictConstantPool.DICT_SYS_CODE,resources.getSystem_type()).in("menu_id",allChildIds)); + } + + } + + /** + * 计算菜单子节点数目 + * + * @param menuId + */ + private void updateSubCnt(String menuId) { + if (menuId != null) { + int count = baseMapper.findByPid(menuId).size(); + SysMenu sysMenu = baseMapper.selectById(menuId); + if (ObjectUtil.isEmpty(sysMenu)) return; + sysMenu.setSub_count(count); + baseMapper.updateById(sysMenu); + } + } + + @Override + public List findByUser(String userId) { + return baseMapper.findByUser(userId).stream().map(menu -> this.doToDto(menu)).collect(Collectors.toList()); + } + + @Override + public List buildMenus(List menuDtos) { + List list = new LinkedList<>(); + menuDtos.forEach(menuDTO -> { + if (menuDTO != null) { + List menuDtoList = menuDTO.getChildren(); + MenuVo menuVo = new MenuVo(); + menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponent_name()) ? menuDTO.getComponent_name() : menuDTO.getTitle()); + // 一级目录需要加斜杠,不然会报警告 + menuVo.setPath(ObjectUtil.isEmpty(menuDTO.getPid()) ? "/" + menuDTO.getPath() : menuDTO.getPath()); + menuVo.setHidden(menuDTO.getHidden()); + // 如果不是外链 + if (!menuDTO.getIframe()) { + if (ObjectUtil.isEmpty(menuDTO.getPid())) { + menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent()) ? "Layout" : menuDTO.getComponent()); + } else if (!ObjectUtil.isEmpty(menuDTO.getPid()) && "0".equals(menuDTO.getType())) { + menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent()) ? "ParentView" : menuDTO.getComponent()); + + } else if (!StrUtil.isEmpty(menuDTO.getComponent())) { + menuVo.setComponent(menuDTO.getComponent()); + } + } + menuVo.setMeta(new MenuMetaVo(menuDTO.getTitle(), menuDTO.getIcon(), !menuDTO.getCache())); + if (menuDtoList != null && menuDtoList.size() != 0) { + menuVo.setAlwaysShow(true); + menuVo.setRedirect("noredirect"); + menuVo.setChildren(buildMenus(menuDtoList)); + // 处理是一级菜单并且没有子菜单的情况 + } else if (ObjectUtil.isEmpty(menuDTO.getPid())) { + 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 list1 = new ArrayList<>(); + list1.add(menuVo1); + menuVo.setChildren(list1); + } + list.add(menuVo); + } + } + ); + return list; + } + + @Override + public List buildTree(List menuDtos) { + List trees = new ArrayList<>(); + Set ids = new HashSet<>(); + for (MenuDto menuDTO : menuDtos) { + if (menuDTO.getPid() == null) { + trees.add(menuDTO); + } + for (MenuDto it : menuDtos) { + if (menuDTO.getMenu_id().equals(it.getPid())) { + if (menuDTO.getChildren() == null) { + menuDTO.setChildren(new ArrayList<>()); + } + menuDTO.getChildren().add(it); + ids.add(it.getMenu_id()); + } + } + } + if (trees.size() == 0) { + trees = menuDtos.stream().filter(s -> !ids.contains(s.getMenu_id())).collect(Collectors.toList()); + } + return trees; + } + + @Override + public List getMenus(String pid) { + QueryWrapper queryWrapper; + if (pid != null && !"0".equals(pid)) { + queryWrapper = new QueryWrapper().eq("pid", pid); + } else { + queryWrapper = new QueryWrapper().isNull("pid"); + } + return baseMapper.selectList(queryWrapper.orderByAsc("menu_sort")); + } + + @Override + public MenuDto doToDto(SysMenu entity) { + + MenuDto menuDto = new MenuDto(); + if (ObjectUtil.isEmpty(entity)){ + return menuDto; + } + menuDto.setMenu_id(entity.getMenu_id()); + menuDto.setType(entity.getType()); + menuDto.setPermission(entity.getPermission()); + menuDto.setTitle(entity.getTitle()); + menuDto.setMenu_sort(entity.getMenu_sort()); + menuDto.setPath(entity.getPath()); + menuDto.setComponent(entity.getComponent()); + menuDto.setSystem_type(entity.getSystem_type()); + menuDto.setPid(entity.getPid()); + menuDto.setSub_count(entity.getSub_count()); + menuDto.setIframe(entity.getIframe()); + menuDto.setCache(entity.getCache()); + menuDto.setHidden(entity.getHidden()); + menuDto.setComponent_name(entity.getComponent_name()); + menuDto.setIcon(entity.getIcon()); + menuDto.setCreate_time(entity.getCreate_time()); + + //构建前端需要的数据结构树 + Integer sub_count = entity.getSub_count(); + if (sub_count <= 0) { + menuDto.setLeaf(true); + menuDto.setHas_children(false); + } else { + menuDto.setLeaf(false); + menuDto.setHas_children(true); + } + return menuDto; + } + + @Override + public List buildMenus(String systemType) { + Dict dict = sysDictMapper.selectOne(new QueryWrapper().eq("code", DictConstantPool.DICT_SYS_CODE).eq("value", systemType)); + if (dict == null || StringUtils.isEmpty(dict.getPara1())){ + throw new BadRequestException("获取对应的系统菜单不存在"); + } + String pid = dict.getPara1(); + List menuDtoList = baseMapper.findSystemMenu(SecurityUtils.getCurrentUserId(),systemType); + //移除系统级菜单 + menuDtoList.removeIf(a->a.getMenu_id().equals(pid)); + List menuDtos = this.buildTree(CopyUtil.copyList(menuDtoList, MenuDto.class)); + return this.buildMenus(menuDtos,pid); + } + + @Override + public List buildMenus(List menuDtos, String pid) { + List list = new LinkedList<>(); + //剔除系统级菜单 + menuDtos.forEach(menuDTO -> { + if (menuDTO != null) { + List menuDtoList = menuDTO.getChildren(); + MenuVo menuVo = new MenuVo(); + menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponent_name()) ? menuDTO.getComponent_name() : menuDTO.getTitle()); + // 一级目录需要加斜杠,不然会报警告 + menuVo.setPath(pid.equals(menuDTO.getPid())? "/" + menuDTO.getPath() : menuDTO.getPath()); + menuVo.setHidden(menuDTO.getHidden()); + // 如果不是外链 + if (!menuDTO.getIframe()) { + if (pid.equals(menuDTO.getPid())) { + menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent()) ? "Layout" : menuDTO.getComponent()); + } else if (!pid.equals(menuDTO.getPid()) && "0".equals(menuDTO.getType())) { + menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent()) ? "ParentView" : menuDTO.getComponent()); + + } else if (!StrUtil.isEmpty(menuDTO.getComponent())) { + menuVo.setComponent(menuDTO.getComponent()); + } + } + menuVo.setMeta(new MenuMetaVo(menuDTO.getTitle(), menuDTO.getIcon(), !menuDTO.getCache())); + if (menuDtoList != null && menuDtoList.size() != 0) { + menuVo.setAlwaysShow(true); + menuVo.setRedirect("noredirect"); + menuVo.setChildren(buildMenus(menuDtoList,pid)); + // 处理是一级菜单并且没有子菜单的情况 + } else if (StrUtil.isEmpty(menuDTO.getPid())) { + 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 list1 = new ArrayList<>(); + list1.add(menuVo1); + menuVo.setChildren(list1); + } + list.add(menuVo); + } + } + ); + return list; + } + + @Override + public List getMenusByRole(String roleId, String systemType, String category) { + baseMapper.getMenusByRole(systemType,category); + return null; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/controller/MonitorController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/controller/MonitorController.java new file mode 100644 index 0000000..26c318f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/controller/MonitorController.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.monitor.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import jakarta.annotation.Resource; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.monitor.service.MonitorService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author Zheng Jie + * @date 2020-05-02 + */ +@RestController +@RequestMapping("/api/monitor") +public class MonitorController { + + @Resource + private MonitorService serverService; + + @GetMapping + @Log("查询服务监控") + @SaCheckPermission("monitor:list") + public ResponseEntity query() { + return new ResponseEntity<>(serverService.getServers(),HttpStatus.OK); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/service/MonitorService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/service/MonitorService.java new file mode 100644 index 0000000..95f611d --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/service/MonitorService.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.monitor.service; + +import java.util.Map; + +/** + * @author Zheng Jie + * @date 2020-05-02 + */ +public interface MonitorService { + + /** + * 查询数据分页 + * @return Map + */ + Map getServers(); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/service/impl/MonitorServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/service/impl/MonitorServiceImpl.java new file mode 100644 index 0000000..56f5c76 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/monitor/service/impl/MonitorServiceImpl.java @@ -0,0 +1,189 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.monitor.service.impl; + +import cn.hutool.core.date.BetweenFormatter; +import cn.hutool.core.date.DateUtil; +import org.nl.sys.modular.backgroundmanagement.common.util.ElAdminConstant; +import org.nl.sys.modular.backgroundmanagement.common.util.FileUtil; +import org.nl.sys.modular.backgroundmanagement.common.util.StringUtils; +import org.nl.sys.modular.backgroundmanagement.monitor.service.MonitorService; +import org.springframework.stereotype.Service; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.hardware.VirtualMemory; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.FormatUtil; +import oshi.util.Util; + +import java.lang.management.ManagementFactory; +import java.text.DecimalFormat; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Zheng Jie + * @date 2020-05-02 + */ +@Service +public class MonitorServiceImpl implements MonitorService { + + private final DecimalFormat df = new DecimalFormat("0.00"); + + @Override + public Map getServers(){ + Map resultMap = new LinkedHashMap<>(8); + try { + SystemInfo si = new SystemInfo(); + OperatingSystem os = si.getOperatingSystem(); + HardwareAbstractionLayer hal = si.getHardware(); + // 系统信息 + resultMap.put("sys", getSystemInfo(os)); + // cpu 信息 + resultMap.put("cpu", getCpuInfo(hal.getProcessor())); + // 内存信息 + resultMap.put("memory", getMemoryInfo(hal.getMemory())); + // 交换区信息 + resultMap.put("swap", getSwapInfo(hal.getMemory())); + // 磁盘 + resultMap.put("disk", getDiskInfo(os)); + resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss")); + } catch (Exception e) { + e.printStackTrace(); + } + return resultMap; + } + + /** + * 获取磁盘信息 + * @return / + */ + private Map getDiskInfo(OperatingSystem os) { + Map diskInfo = new LinkedHashMap<>(); + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + String osName = System.getProperty("os.name"); + long available = 0, total = 0; + for (OSFileStore fs : fsArray){ + // windows 需要将所有磁盘分区累加,linux 和 mac 直接累加会出现磁盘重复的问题,待修复 + if(osName.toLowerCase().startsWith(ElAdminConstant.WIN)) { + available += fs.getUsableSpace(); + total += fs.getTotalSpace(); + } else { + available = fs.getUsableSpace(); + total = fs.getTotalSpace(); + break; + } + } + long used = total - available; + diskInfo.put("total", total > 0 ? FileUtil.getSize(total) : "?"); + diskInfo.put("available", FileUtil.getSize(available)); + diskInfo.put("used", FileUtil.getSize(used)); + diskInfo.put("usageRate", df.format(used/(double)total * 100)); + return diskInfo; + } + + /** + * 获取交换区信息 + * @param memory / + * @return / + */ + private Map getSwapInfo(GlobalMemory memory) { + Map swapInfo = new LinkedHashMap<>(); + VirtualMemory virtualMemory = memory.getVirtualMemory(); + long total = virtualMemory.getSwapTotal(); + long used = virtualMemory.getSwapUsed(); + swapInfo.put("total", FormatUtil.formatBytes(total)); + swapInfo.put("used", FormatUtil.formatBytes(used)); + swapInfo.put("available", FormatUtil.formatBytes(total - used)); + if(used == 0){ + swapInfo.put("usageRate", 0); + } else { + swapInfo.put("usageRate", df.format(used/(double)total * 100)); + } + return swapInfo; + } + + /** + * 获取内存信息 + * @param memory / + * @return / + */ + private Map getMemoryInfo(GlobalMemory memory) { + Map memoryInfo = new LinkedHashMap<>(); + memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal())); + memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable())); + memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable())); + memoryInfo.put("usageRate", df.format((memory.getTotal() - memory.getAvailable())/(double)memory.getTotal() * 100)); + return memoryInfo; + } + + /** + * 获取Cpu相关信息 + * @param processor / + * @return / + */ + private Map getCpuInfo(CentralProcessor processor) { + Map cpuInfo = new LinkedHashMap<>(); + cpuInfo.put("name", processor.getProcessorIdentifier().getName()); + cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU"); + cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心"); + cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount()); + cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU"); + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + // 等待1秒... + Util.sleep(1000); + long[] ticks = processor.getSystemCpuLoadTicks(); + long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; + long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; + long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal; + cpuInfo.put("used", df.format(100d * user / totalCpu + 100d * sys / totalCpu)); + cpuInfo.put("idle", df.format(100d * idle / totalCpu)); + return cpuInfo; + } + + /** + * 获取系统相关信息,系统、运行天数、系统IP + * @param os / + * @return / + */ + private Map getSystemInfo(OperatingSystem os){ + Map systemInfo = new LinkedHashMap<>(); + // jvm 运行时间 + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + Date date = new Date(time); + // 计算项目运行时间 5.4.3:BetweenFormater, 5.7.14改名为BetweenFormatter + String formatBetween = DateUtil.formatBetween(date, new Date(), BetweenFormatter.Level.HOUR); + // 系统信息 + systemInfo.put("os", os.toString()); + systemInfo.put("day", formatBetween); + systemInfo.put("ip", StringUtils.getLocalIp()); + return systemInfo; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/controller/SysNoticeController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/controller/SysNoticeController.java new file mode 100644 index 0000000..fd9a3ae --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/controller/SysNoticeController.java @@ -0,0 +1,100 @@ +package org.nl.sys.modular.backgroundmanagement.notice.controller; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.notice.dao.SysNotice; +import org.nl.sys.modular.backgroundmanagement.notice.service.ISysNoticeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; +import java.util.Set; + +/** +* @author lyd +* @date 2023-05-09 +**/ +@Slf4j +@RestController +@RequestMapping("/api/notice") +public class SysNoticeController { + + @Autowired + private ISysNoticeService noticeService; + + @GetMapping + @Log("查询消息通知") + //@SaCheckPermission("@el.check('sysNotice:list')") + public ResponseEntity query(@RequestParam Map whereJson, PageQuery page){ + return new ResponseEntity<>(TableDataInfo.build(noticeService.queryAll(whereJson,page)),HttpStatus.OK); + } + + @PostMapping + @Log("新增消息通知") + //@SaCheckPermission("@el.check('sysNotice:add')") + public ResponseEntity create(@Validated @RequestBody SysNotice entity){ + noticeService.create(entity); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PutMapping + @Log("修改消息通知") + //@SaCheckPermission("@el.check('sysNotice:edit')") + public ResponseEntity update(@Validated @RequestBody SysNotice entity){ + noticeService.update(entity); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除消息通知") + //@SaCheckPermission("@el.check('sysNotice:del')") + @DeleteMapping + public ResponseEntity delete(@RequestBody Set ids) { + noticeService.deleteAll(ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + @Log("获取未读的接收消息条数") + @GetMapping("/countByReceiveNotRead") + public ResponseEntity countByReceiveNotRead(){ + return new ResponseEntity<>(noticeService.countByReceiveNotRead(), HttpStatus.OK); + } + + @Log("接收消息分页") + @GetMapping("/pageByReceive") + public ResponseEntity pageByReceive(){ + return new ResponseEntity<>(noticeService.pageByReceive(), HttpStatus.OK); + } + + @Log("标为已读") + @PostMapping("/read") + public ResponseEntity read(@RequestBody String id){ + noticeService.read(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("消息详情") + @PostMapping("/findById") + public ResponseEntity findById(@RequestBody String id){ + return new ResponseEntity<>(noticeService.getById(id), HttpStatus.OK); + } + + @Log("修改已处理") + @PostMapping("/deal") + public ResponseEntity deal(@RequestBody String id){ + noticeService.deal(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("批量已读") + @PostMapping("/changeRead") + public ResponseEntity changeRead(@RequestBody JSONObject jsonObject) { + noticeService.changeRead(jsonObject); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dao/SysNotice.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dao/SysNotice.java new file mode 100644 index 0000000..ecfaf41 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dao/SysNotice.java @@ -0,0 +1,44 @@ +package org.nl.sys.modular.backgroundmanagement.notice.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** +* @description / +* @author lyd +* @date 2023-05-09 +**/ +@Data +@Builder +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +@TableName("sys_notice") +public class SysNotice implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "notice_id", type = IdType.NONE) + private String notice_id; + + private String notice_title; + + private String notice_content; + + private String notice_type; + + private String have_read; + + private String read_time; + + private String deal_status; + + private String create_time; + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dto/SysNoticeDto.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dto/SysNoticeDto.java new file mode 100644 index 0000000..7365f1b --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dto/SysNoticeDto.java @@ -0,0 +1,38 @@ +package org.nl.sys.modular.backgroundmanagement.notice.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** +* @description / +* @author lyd +* @date 2023-05-09 +**/ +@Data +public class SysNoticeDto implements Serializable { + + /** 信息标识 */ + private String notice_id; + + /** 信息标题 */ + private String notice_title; + + /** 信息内容 */ + private String notice_content; + + /** 信息类型 */ + private String notice_type; + + /** 读取状态 */ + private String have_read; + + /** 读取时间 */ + private String read_time; + + /** 处理状态 */ + private String deal_status; + + /** 创建时间 */ + private String create_time; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dto/SysNoticeQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dto/SysNoticeQuery.java new file mode 100644 index 0000000..85241cf --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/dto/SysNoticeQuery.java @@ -0,0 +1,13 @@ +package org.nl.sys.modular.backgroundmanagement.notice.dto; + + +import org.nl.sys.modular.backgroundmanagement.common.domain.query.BaseQuery; +import org.nl.sys.modular.backgroundmanagement.notice.dao.SysNotice; + +/** +* @author lyd +* @date 2023-05-09 +**/ +public class SysNoticeQuery extends BaseQuery { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/mapper/SysNoticeMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/mapper/SysNoticeMapper.java new file mode 100644 index 0000000..1422fa3 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/mapper/SysNoticeMapper.java @@ -0,0 +1,12 @@ +package org.nl.sys.modular.backgroundmanagement.notice.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.nl.sys.modular.backgroundmanagement.notice.dao.SysNotice; + +/** +* @author lyd +* @date 2023-05-09 +**/ +public interface SysNoticeMapper extends BaseMapper { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/mapper/mapping/SysNoticeMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/mapper/mapping/SysNoticeMapper.xml new file mode 100644 index 0000000..bc4d451 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/mapper/mapping/SysNoticeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/service/ISysNoticeService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/service/ISysNoticeService.java new file mode 100644 index 0000000..b25e210 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/service/ISysNoticeService.java @@ -0,0 +1,83 @@ +package org.nl.sys.modular.backgroundmanagement.notice.service; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.notice.dao.SysNotice; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** +* @description 服务接口 +* @author lyd +* @date 2023-05-09 +**/ +public interface ISysNoticeService extends IService { + + /** + * 查询数据分页 + * @param whereJson 条件 + * @param pageable 分页参数 + * @return IPage + */ + IPage queryAll(Map whereJson, PageQuery pageable); + + /** + * 创建 + * @param entity / + */ + void create(SysNotice entity); + + /** + * 编辑 + * @param entity / + */ + void update(SysNotice entity); + + /** + * 多选删除 + * @param ids / + */ + void deleteAll(Set ids); + + /** + * 获取未读的接收消息条数 + */ + Integer countByReceiveNotRead(); + + /** + * 获取不同类型的前三条信息 + * @return + */ + LinkedList> pageByReceive(); + + /** + * 标记已读 + * @param id + */ + void read(String id); + + /** + * 处理信息 + * @param id + */ + void deal(String id); + + /** + * 批量已读 + * @param jsonObject + */ + void changeRead(JSONObject jsonObject); + + /** + * 写入信息 + * @param msg + * @param title + * @param type + */ + void createNotice(String msg, String title, String type); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/service/impl/SysNoticeServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..11b3e2e --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/notice/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,184 @@ +package org.nl.sys.modular.backgroundmanagement.notice.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.enums.NoticeEnum; +import org.nl.sys.modular.backgroundmanagement.common.mnt.websocket.MsgType; +import org.nl.sys.modular.backgroundmanagement.common.mnt.websocket.SocketMsg; +import org.nl.sys.modular.backgroundmanagement.common.mnt.websocket.WebSocketServer; +import org.nl.sys.modular.backgroundmanagement.dict.dao.Dict; +import org.nl.sys.modular.backgroundmanagement.dict.mapper.SysDictMapper; +import org.nl.sys.modular.backgroundmanagement.notice.dao.SysNotice; +import org.nl.sys.modular.backgroundmanagement.notice.mapper.SysNoticeMapper; +import org.nl.sys.modular.backgroundmanagement.notice.service.ISysNoticeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** +* @description 服务实现 +* @author lyd +* @date 2023-05-09 +**/ +@Slf4j +@Service +public class SysNoticeServiceImpl extends ServiceImpl implements ISysNoticeService { + + @Autowired + private SysNoticeMapper sysNoticeMapper; + + @Autowired + private SysDictMapper dictMapper; + + @Resource + private WebSocketServer webSocketServer; + + @Override + public IPage queryAll(Map whereJson, PageQuery page){ + String notice_title = ObjectUtil.isNotEmpty(whereJson.get("notice_title"))?whereJson.get("notice_title").toString():null; + String notice_type = ObjectUtil.isNotEmpty(whereJson.get("notice_type"))?whereJson.get("notice_type").toString():null; + String have_read = ObjectUtil.isNotEmpty(whereJson.get("have_read"))?whereJson.get("have_read").toString():null; + String deal_status = ObjectUtil.isNotEmpty(whereJson.get("deal_status"))?whereJson.get("deal_status").toString():null; + LambdaQueryWrapper lam = new LambdaQueryWrapper<>(); + lam.like(ObjectUtil.isNotEmpty(notice_title), SysNotice::getNotice_title, notice_title) + .eq(ObjectUtil.isNotEmpty(notice_type), SysNotice::getNotice_type, notice_type) + .eq(ObjectUtil.isNotEmpty(have_read), SysNotice::getHave_read, have_read) + .eq(ObjectUtil.isNotEmpty(deal_status), SysNotice::getDeal_status, deal_status) + .orderByAsc(SysNotice::getHave_read) + .orderByDesc(SysNotice::getCreate_time); + IPage pages = new Page<>(page.getPage() + 1, page.getSize()); + sysNoticeMapper.selectPage(pages, lam); + return pages; + } + + @Override + public void create(SysNotice entity) { + String now = DateUtil.now(); + + entity.setNotice_id(IdUtil.getSnowflake(1, 1).nextIdStr()); + entity.setCreate_time(now); + sysNoticeMapper.insert(entity); + } + + @Override + public void update(SysNotice entity) { + SysNotice dto = sysNoticeMapper.selectById(entity.getNotice_id()); + if (dto == null) throw new BadRequestException("被删除或无权限,操作失败!"); + sysNoticeMapper.updateById(entity); + } + + @Override + public void deleteAll(Set ids) { + // 真删除 + sysNoticeMapper.deleteBatchIds(ids); + } + + @Override + public Integer countByReceiveNotRead() { + List sysNotices = sysNoticeMapper.selectList(new LambdaQueryWrapper().eq(SysNotice::getHave_read, NoticeEnum.HAVE_READ_OFF.getValue())); + return ObjectUtil.isNotEmpty(sysNotices)?sysNotices.size():0; + } + + @Override + public LinkedList> pageByReceive() { + LinkedList> result = new LinkedList<>(); + List dictList = dictMapper.selectList(new LambdaQueryWrapper() + .eq(Dict::getCode, "notice_type") + .orderByAsc(Dict::getDict_sort)); + dictList.forEach(dict -> { + List sysNotices = sysNoticeMapper.selectList(new LambdaQueryWrapper() + .eq(SysNotice::getNotice_type, dict.getValue()) + .eq(SysNotice::getHave_read, NoticeEnum.HAVE_READ_OFF.getValue()) + .orderByDesc(SysNotice::getCreate_time) + .last("LIMIT 0,3")); + result.add(sysNotices); + }); + return result; + } + + @Override + public void read(String id) { + SysNotice notice = this.getById(id); + if (ObjectUtil.isEmpty(notice)) { + throw new BadRequestException("该信息不存在!"); + } + notice.setHave_read(NoticeEnum.HAVE_READ_ON.getValue()); + notice.setRead_time(DateUtil.now()); + sysNoticeMapper.updateById(notice); + } + + @Override + public void deal(String id) { + SysNotice notice = this.getById(id); + if (ObjectUtil.isEmpty(notice)) { + throw new BadRequestException("该信息不存在!"); + } + // 设置处理 + notice.setDeal_status(NoticeEnum.DEAL_STATUS_YES.getValue()); + // 判断是否读取 + if (notice.getHave_read().equals(NoticeEnum.HAVE_READ_OFF.getValue())) { + // 标记已读并设置读取时间 + notice.setHave_read(NoticeEnum.HAVE_READ_ON.getValue()); + notice.setRead_time(DateUtil.now()); + } + sysNoticeMapper.updateById(notice); + } + + @Override + public void changeRead(JSONObject jsonObject) { + JSONArray data = jsonObject.getJSONArray("data"); + String haveRead = jsonObject.getString("have_read"); + List sysNotices = JSON.parseArray(data.toJSONString(), SysNotice.class); + sysNotices.forEach(sysNotice -> sysNotice.setHave_read(haveRead)); + this.updateBatchById(sysNotices); + } + + @Override + public void createNotice(String msg, String title, String type) { + log.info("创建消息通知-信息:{}, 标题:{}, 类型:{}", msg, title, type); + // 获取标题相同的信息 + List sysNotices = sysNoticeMapper.selectList(new LambdaQueryWrapper() + .eq(SysNotice::getNotice_title, title) + .eq(SysNotice::getHave_read, NoticeEnum.HAVE_READ_OFF.getValue())); + if (ObjectUtil.isNotEmpty(sysNotices)) return; + SysNotice noticeDto = SysNotice.builder() + .notice_id(IdUtil.getSnowflake(1, 1).nextIdStr()) + .notice_type(type) + .notice_title(title) + .notice_content(msg) + .deal_status(NoticeEnum.DEAL_STATUS_NO.getValue()) + .have_read(NoticeEnum.HAVE_READ_OFF.getValue()) + .create_time(DateUtil.now()) + .build(); + // 插入 + sysNoticeMapper.insert(noticeDto); + JSONObject res = new JSONObject(); + res.put("data", "notice_message_update"); + SocketMsg messageInfo = new SocketMsg(res, MsgType.INFO); + try { + webSocketServer.sendInfo(messageInfo, "messageInfo"); + } catch (IOException e) { + throw new BadRequestException("消息发送失败"); + } + } + + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/controller/SysParamController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/controller/SysParamController.java new file mode 100644 index 0000000..44cca62 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/controller/SysParamController.java @@ -0,0 +1,74 @@ +package org.nl.sys.modular.backgroundmanagement.param.controller; + +import cn.dev33.satoken.annotation.SaIgnore; +import lombok.extern.slf4j.Slf4j; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.param.dao.Param; +import org.nl.sys.modular.backgroundmanagement.param.service.ISysParamService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统参数表 前端控制器 + *

+ * + * @author generator + * @since 2022-12-14 + */ +@Slf4j +@RestController +@RequestMapping("/api/param") +class SysParamController { + + @Autowired + private ISysParamService paramService; + @GetMapping + @Log("查询系统参数") + public ResponseEntity query(@RequestParam Map whereJson, PageQuery page){ + return new ResponseEntity<>(TableDataInfo.build(paramService.queryPage(whereJson, page)), HttpStatus.OK); + } + + @PostMapping + @Log("新增系统参数") + public ResponseEntity create(@Validated @RequestBody Param param){ + paramService.create(param); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PutMapping + @Log("修改系统参数") + //@SaCheckPermission("param:edit") + public ResponseEntity update(@Validated @RequestBody Param param){ + paramService.update(param); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除系统参数") + //@SaCheckPermission("param:del") + @DeleteMapping + public ResponseEntity delete(@RequestBody String[] ids) { + List Ids = Arrays.asList(ids); + paramService.deleteByIds(Ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + @PostMapping("/getValueByCode/{code}") + @Log("根据编码获取值") + @SaIgnore + public ResponseEntity getValueByCode(@PathVariable String code) { + return new ResponseEntity<>(paramService.findByCode(code), HttpStatus.CREATED); + } + +} + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/dao/Param.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/dao/Param.java new file mode 100644 index 0000000..4bbbc17 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/dao/Param.java @@ -0,0 +1,92 @@ +package org.nl.sys.modular.backgroundmanagement.param.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 系统参数表 + *

+ * + * @author generator + * @since 2022-12-14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_param") +public class Param implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 标识 + */ + @TableId + private String id; + + /** + * 编码 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 值 + */ + private String value; + + /** + * 备注 + */ + private String remark; + + /** + * 是否启用 + */ + private Boolean is_active; + + /** + * 是否删除 + */ + private Boolean is_delete; + + /** + * 创建者ID + */ + private String create_id; + + /** + * 创建者 + */ + private String create_name; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改者ID + */ + private String update_id; + + /** + * 修改者 + */ + private String update_name; + + /** + * 修改时间 + */ + private String update_time; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/dto/ParamQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/dto/ParamQuery.java new file mode 100644 index 0000000..142d634 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/dto/ParamQuery.java @@ -0,0 +1,15 @@ +package org.nl.sys.modular.backgroundmanagement.param.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.BaseQuery; +import org.nl.sys.modular.backgroundmanagement.param.dao.Param; + +/** + * @Author: lyd + * @Description: + * @Date: 2022/12/15 + */ +@Data +public class ParamQuery extends BaseQuery { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/mapper/SysParamMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/mapper/SysParamMapper.java new file mode 100644 index 0000000..88d941a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/mapper/SysParamMapper.java @@ -0,0 +1,16 @@ +package org.nl.sys.modular.backgroundmanagement.param.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.nl.sys.modular.backgroundmanagement.param.dao.Param; + +/** + *

+ * 系统参数表 Mapper 接口 + *

+ * + * @author generator + * @since 2022-12-14 + */ +public interface SysParamMapper extends BaseMapper { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/mapper/mapping/SysParamMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/mapper/mapping/SysParamMapper.xml new file mode 100644 index 0000000..6259723 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/mapper/mapping/SysParamMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/service/ISysParamService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/service/ISysParamService.java new file mode 100644 index 0000000..725a29f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/service/ISysParamService.java @@ -0,0 +1,58 @@ +package org.nl.sys.modular.backgroundmanagement.param.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.param.dao.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统参数表 服务类 + *

+ * + * @author generator + * @since 2022-12-14 + */ +public interface ISysParamService extends IService { + + /** + * 分页查找 + * + * @param whereJson 参数列表 + * @param page 分页信息 + * @return + */ + Page queryPage(Map whereJson, PageQuery page); + + /** + * 创建参数 + * + * @param param + */ + void create(Param param); + + /** + * 更新 + * + * @param param + */ + void update(Param param); + + /** + * 删除 + * + * @param ids + */ + void deleteByIds(List ids); + + /** + * 根据编码查询 + * + * @param code code + * @return Param + */ + Param findByCode(String code); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/service/impl/SysParamServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/service/impl/SysParamServiceImpl.java new file mode 100644 index 0000000..486c314 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/param/service/impl/SysParamServiceImpl.java @@ -0,0 +1,97 @@ +package org.nl.sys.modular.backgroundmanagement.param.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.util.MapOf; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.param.dao.Param; +import org.nl.sys.modular.backgroundmanagement.param.mapper.SysParamMapper; +import org.nl.sys.modular.backgroundmanagement.param.service.ISysParamService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统参数表 服务实现类 + *

+ * + * @author generator + * @since 2022-12-14 + */ +@Slf4j +@Service +public class SysParamServiceImpl extends ServiceImpl implements ISysParamService { + + @Autowired + private SysParamMapper paramMapper; + + @Override + public Page queryPage(Map whereJson, PageQuery page) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.orderBy(true, true, "create_time"); + Page paramPage = paramMapper.selectPage(page.build(), queryWrapper); + return paramPage; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Param param) { + List code = paramMapper.selectByMap(MapOf.of("code", param.getCode())); + if (ObjectUtil.isNotEmpty(code)) throw new BadRequestException("编码不能一致"); + param.setId(IdUtil.getSnowflake(1, 1).nextIdStr()); + String currentUserId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String now = DateUtil.now(); + param.setCreate_id(currentUserId); + param.setCreate_name(nickName); + param.setCreate_time(now); + param.setUpdate_id(currentUserId); + param.setUpdate_name(nickName); + param.setUpdate_time(now); + paramMapper.insert(param); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Param param) { + Param paramObj = paramMapper.selectById(param.getId()); + if (ObjectUtil.isEmpty(paramObj)) { + throw new BadRequestException("被删除或无权限,操作失败!"); + } + Param param1 = paramMapper.selectOne(new LambdaQueryWrapper().eq(Param::getCode, param.getCode()) + .and(lam -> lam.ne(Param::getId, param.getId()))); + if (ObjectUtil.isNotEmpty(param1)) { + throw new BadRequestException("编码[" + param.getCode() + "]已存在"); + } + param.setUpdate_id(SecurityUtils.getCurrentUserId()); + param.setUpdate_name(SecurityUtils.getCurrentNickName()); + param.setUpdate_time(DateUtil.now()); + paramMapper.updateById(param); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteByIds(List ids) { + paramMapper.deleteBatchIds(ids); + } + + @Override + public Param findByCode(String code) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("code", code); + Param param = paramMapper.selectOne(queryWrapper); + return param; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/controller/SysRoleController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/controller/SysRoleController.java new file mode 100644 index 0000000..7c94d77 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/controller/SysRoleController.java @@ -0,0 +1,77 @@ +package org.nl.sys.modular.backgroundmanagement.role.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.alibaba.fastjson.JSONObject; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.role.service.ISysRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; +import java.util.Set; + +/** + *

+ * 角色表 前端控制器 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@RestController +@RequestMapping("/api/sysRole") +public class SysRoleController { + + @Autowired + private ISysRoleService roleService; + + @Log("分页查询角色") + @GetMapping + @SaCheckPermission("roles:list") + public ResponseEntity pageQuery(@RequestParam Map param, PageQuery page) { + return new ResponseEntity<>(TableDataInfo.build(roleService.query(param, page)), HttpStatus.OK); + } + + @Log("查询所有角色") + @GetMapping("/all") + public ResponseEntity queryAll() { + return new ResponseEntity<>(roleService.list(), HttpStatus.OK); + } + + @Log("新增角色") + @PostMapping + @SaCheckPermission("roles:add") + public ResponseEntity create(@RequestBody JSONObject param) { + roleService.create(param); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @Log("修改角色") + @PutMapping + @SaCheckPermission("roles:edit") + public ResponseEntity update(@RequestBody JSONObject param) { + roleService.update(param); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除角色") + @DeleteMapping + @SaCheckPermission("roles:del") + public ResponseEntity delete(@RequestBody Set ids) { + roleService.deleteBatchByIds(ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + @Log("修改角色菜单") + @PutMapping(value = "/menu") + @SaCheckPermission("roles:edit") + public ResponseEntity updateMenu(@RequestBody JSONObject form) { + roleService.updateMenu(form); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } +} + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/dao/SysRole.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/dao/SysRole.java new file mode 100644 index 0000000..d882c72 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/dao/SysRole.java @@ -0,0 +1,101 @@ +package org.nl.sys.modular.backgroundmanagement.role.dao; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + *

+ * 角色表 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_role") +public class SysRole implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "role_id") + private String role_id; + + /** + * 名称 + */ + private String name; + + /** + * 角色级别 + */ + private BigDecimal level; + + /** + * 排序 + */ + private BigDecimal order_seq; + + /** + * 备注 + */ + private String remark; + + /** + * 是否启用 + */ + private String is_used; + + /** + * 是否删除 + */ + private String is_delete; + + /** + * 创建人标识 + */ + private String create_id; + + /** + * 创建人 + */ + private String create_name; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改人标识 + */ + private String update_id; + + /** + * 修改人 + */ + private String update_name; + + /** + * 修改时间 + */ + private String update_time; + + /** + * 角色菜单id + */ + @TableField(exist = false) + private List menus; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/mapper/SysRoleMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/mapper/SysRoleMapper.java new file mode 100644 index 0000000..05d04e0 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/mapper/SysRoleMapper.java @@ -0,0 +1,33 @@ +package org.nl.sys.modular.backgroundmanagement.role.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.nl.sys.modular.backgroundmanagement.role.dao.SysRole; + +import java.util.Collection; +import java.util.List; + +/** + *

+ * 角色表 Mapper 接口 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface SysRoleMapper extends BaseMapper { + + void saveRoleRelation(@Param("user") String UserId, @Param("roles") Collection roles); + void delRoleRelation(@Param("user") String UserId); + + void deleteRoleMenuBatchRoleIds(Collection ids); + + List selectMenuIdsByRoles(String roleId); + + /** + * 插入角色/菜单表 + * @param roleId + * @param menuIds + */ + void insertRoleMenu(String roleId, Collection menuIds); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/mapper/mapping/SysRoleMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/mapper/mapping/SysRoleMapper.xml new file mode 100644 index 0000000..041d66a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/mapper/mapping/SysRoleMapper.xml @@ -0,0 +1,29 @@ + + + + + + replace into sys_users_roles values + + (#{user},#{role}) + + + + delete from sys_users_roles where user_id = #{user} + + + insert into sys_roles_menus values + + (#{menuId},#{roleId}) + + + + DELETE FROM sys_roles_menus WHERE role_id in + + #{id} + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/service/ISysRoleService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/service/ISysRoleService.java new file mode 100644 index 0000000..c11004a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/service/ISysRoleService.java @@ -0,0 +1,64 @@ +package org.nl.sys.modular.backgroundmanagement.role.service; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.role.dao.SysRole; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 角色表 服务类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface ISysRoleService extends IService { + + IPage query(Map param, PageQuery page); + + /** + * 创建角色 + * @param param + */ + void create(JSONObject param); + + /** + * 更新角色 + * @param param + */ + void update(JSONObject param); + + /** + * 删除角色 + * @param ids + */ + void deleteBatchByIds(Set ids); + + /** + * 更新角色菜单 + * @param form + */ + void updateMenu(JSONObject form); + + /** + * 通过id获取用户的权限 + * @param userDto + * @return + */ + List getPermissionList(JSONObject userDto); + + + /** + * 保存用户角色关系 + * @param UserId + * @param deptIds + */ + void saveUserRoleRelation(String UserId, List deptIds); + void delUserRoleRelation(String UserId); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/service/impl/SysRoleServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..333f843 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/role/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,149 @@ +package org.nl.sys.modular.backgroundmanagement.role.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.menu.mapper.SysMenuMapper; +import org.nl.sys.modular.backgroundmanagement.role.dao.SysRole; +import org.nl.sys.modular.backgroundmanagement.role.mapper.SysRoleMapper; +import org.nl.sys.modular.backgroundmanagement.role.service.ISysRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.*; + +/** + *

+ * 角色表 服务实现类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Service +public class SysRoleServiceImpl extends ServiceImpl implements ISysRoleService { + + @Autowired + private SysRoleMapper roleMapper; + @Autowired + private SysMenuMapper sysMenuMapper; + + @Override + public IPage query(Map param, PageQuery page) { + String blurry = null; + if (ObjectUtil.isNotEmpty(param.get("blurry"))) blurry = param.get("blurry").toString(); + LambdaQueryWrapper lam = new LambdaQueryWrapper<>(); + lam.like(ObjectUtil.isNotEmpty(blurry), SysRole::getName, blurry); + IPage pages = new Page<>(page.getPage() + 1, page.getSize()); + roleMapper.selectPage(pages, lam); + // 需要吧menus返回去 + pages.getRecords().forEach(sysRole -> sysRole.setMenus(roleMapper.selectMenuIdsByRoles(sysRole.getRole_id()))); + return pages; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(JSONObject param) { + //判断角色名字是否存在 + String name = param.getString("name"); + if (StrUtil.isEmpty(name)) throw new BadRequestException("角色名字不能为空!"); + SysRole sysRole = JSONObject.parseObject(JSONObject.toJSONString(param), SysRole.class); + + //判断角色名字是否存在 + SysRole role = roleMapper.selectOne(new LambdaQueryWrapper().eq(SysRole::getName, sysRole.getName())); + if (ObjectUtil.isNotEmpty(role)) throw new BadRequestException("角色【" + name + "】已存在!"); + String userId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String now = DateUtil.now(); + // 插入 + sysRole.setRole_id(IdUtil.getSnowflake(1, 1).nextIdStr()); + sysRole.setCreate_id(userId); + sysRole.setCreate_name(nickName); + sysRole.setCreate_time(now); + sysRole.setUpdate_id(userId); + sysRole.setUpdate_name(nickName); + sysRole.setUpdate_time(now); + roleMapper.insert(sysRole); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(JSONObject param) { + SysRole sysRole = JSONObject.parseObject(JSONObject.toJSONString(param), SysRole.class); + //判断角色名字是否存在 + String name = sysRole.getName(); + if (StrUtil.isEmpty(name)) throw new BadRequestException("角色名字不能为空!"); + + //判断角色名字是否存在 + SysRole role = roleMapper.selectOne(new LambdaQueryWrapper().eq(SysRole::getName, sysRole.getName()) + .ne(SysRole::getRole_id, sysRole.getRole_id())); + if (ObjectUtil.isNotEmpty(role)) throw new BadRequestException("角色【" + name + "】已存在!"); + String userId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String now = DateUtil.now(); + sysRole.setUpdate_id(userId); + sysRole.setUpdate_name(nickName); + sysRole.setUpdate_time(now); + roleMapper.updateById(sysRole); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteBatchByIds(Set ids) { + // 删除角色表 + roleMapper.deleteBatchIds(ids); + // 删除角色菜单绑定关系 + roleMapper.deleteRoleMenuBatchRoleIds(ids); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMenu(JSONObject form) { + String roleId = form.getString("role_id"); + JSONArray menus = form.getJSONArray("menus"); + Set menuIds = new HashSet<>(); + for (int i = 0; i < menus.size(); i++) { + JSONObject object = menus.getJSONObject(i); + menuIds.add(object.getString("menuId")); + } + // 删除当前角色绑定的菜单 + roleMapper.deleteRoleMenuBatchRoleIds(Arrays.asList(roleId)); + // 插入数据 + roleMapper.insertRoleMenu(roleId, menuIds); + } + + @Override + public List getPermissionList(JSONObject userDto) { + List permission = new LinkedList<>(); + // 查看是否为管理员 + permission.add("admin"); + permission.addAll(sysMenuMapper.getPermissionByUserId(userDto.getString("userId"))); + return permission; + } + + @Override + public void saveUserRoleRelation(String user, List roles) { + if (StringUtils.isEmpty(user) || CollectionUtils.isEmpty(roles)){ + return; + } + roleMapper.saveRoleRelation(user,roles); + } + + @Override + public void delUserRoleRelation(String user) { + roleMapper.delRoleRelation(user); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/controller/AuthorizationController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/controller/AuthorizationController.java new file mode 100644 index 0000000..7f9b28b --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/controller/AuthorizationController.java @@ -0,0 +1,112 @@ + +package org.nl.sys.modular.backgroundmanagement.secutiry.controller; + + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSONObject; +import io.github.eternalstone.captcha.gp.base.Captcha; +import io.github.eternalstone.captcha.gp.base.TextEntry; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.security.config.bean.LoginCodeEnum; +import org.nl.sys.modular.backgroundmanagement.common.security.config.bean.LoginProperties; +import org.nl.sys.modular.backgroundmanagement.common.util.RedisUtils; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.common.util.dto.CurrentUser; +import org.nl.sys.modular.backgroundmanagement.secutiry.service.OnlineUserService; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; +import org.nl.sys.modular.backgroundmanagement.user.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @author Zheng Jie + * @date 2018-11-23 + * 授权、根据token获取用户详细信息 + */ +@Slf4j +@RestController +@RequestMapping("/auth") +public class AuthorizationController { + @Autowired + private RedisUtils redisUtils; + @Autowired + private OnlineUserService onlineUserService; + @Autowired + private ISysUserService userService; + @Autowired + private LoginProperties loginProperties; + + @Log("登录授权") + @PostMapping(value = "/login") + public ResponseEntity login(@RequestBody Map authMap) throws Exception { + if (ObjectUtil.isEmpty(authMap)){ + return ResponseEntity.noContent().build(); + } + return ResponseEntity.ok(onlineUserService.login(authMap)); + } + + + @Log("获取用户信息") + @GetMapping(value = "/info") + public ResponseEntity getUserInfo() { + CurrentUser currentUser = SecurityUtils.getCurrentUser(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("roles", SecurityUtils.getCurrentUserPermissions()); + jsonObject.put("user", currentUser.getUser()); + return ResponseEntity.ok(jsonObject); + } + + @Log("获取指定用户信息") + @GetMapping(value = "/userInfo") + public ResponseEntity getUserInfo(Long loginId) { + if (loginId != null){ + SysUser user = userService.getById(loginId); + return ResponseEntity.ok(user); + } + return ResponseEntity.noContent().build(); + } + + @Log("获取验证码") + @GetMapping(value = "/code") + public ResponseEntity getCode() { + // 获取运算的结果 + Captcha captcha = loginProperties.getCaptcha(); + String uuid = IdUtil.simpleUUID(); + TextEntry textEntry = captcha.createText(); + //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型 + String captchaValue = textEntry.getKey(); + + if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(".")) { + captchaValue = captchaValue.split("\\.")[0]; + } + // 保存 + redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES); + // 验证码信息 + Map imgResult = new HashMap(2) {{ + put("img", captcha.toBase64(textEntry)); + put("uuid", uuid); + }}; + return ResponseEntity.ok(imgResult); + } + + @Log("退出登录") + @DeleteMapping(value = "/logout") + public ResponseEntity logout(HttpServletRequest request) { + if (ObjectUtil.isNotEmpty(StpUtil.getTokenValue())) { + onlineUserService.logout(StpUtil.getTokenValue()); + } + StpUtil.logout(); + return new ResponseEntity<>(HttpStatus.OK); + } + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/dto/AuthUserDto.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/dto/AuthUserDto.java new file mode 100644 index 0000000..49d07fd --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/dto/AuthUserDto.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.secutiry.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + + +/** + * @author Zheng Jie + * @date 2018-11-30 + */ +@Getter +@Setter +public class AuthUserDto { + + @NotBlank + private String username; + + @NotBlank + private String password; + + private String code; + + private String uuid = ""; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/dto/UserDto.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/dto/UserDto.java new file mode 100644 index 0000000..bce57fa --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/dto/UserDto.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.secutiry.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Getter; +import lombok.Setter; +import org.nl.sys.modular.backgroundmanagement.common.base.BaseDTO; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Zheng Jie + * @date 2018-11-23 + */ +@Getter +@Setter +public class UserDto extends BaseDTO implements Serializable { + @JsonSerialize(using = ToStringSerializer.class) + private String id; + +// private Set roles; + + + private String username; + + private String personName; + + private String email; + + private String phone; + + private String gender; + + private String avatarName; + + private String avatarPath; + + private String extId; + + private String extuserId; + + + @JsonIgnore + private String password; + + private Boolean enabled; + + @JsonIgnore + private Boolean isAdmin = false; + + private Date pwdResetTime; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/service/OnlineUserService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/service/OnlineUserService.java new file mode 100644 index 0000000..03ab6a5 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/secutiry/service/OnlineUserService.java @@ -0,0 +1,269 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.secutiry.service; + +import cn.dev33.satoken.secure.SaSecureUtil; +import cn.dev33.satoken.stp.SaLoginModel; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.nl.exception.BadRequestException; +import org.nl.sys.modular.backgroundmanagement.common.util.*; +import org.nl.sys.modular.backgroundmanagement.common.util.dto.CurrentUser; +import org.nl.sys.modular.backgroundmanagement.role.service.ISysRoleService; +import org.nl.sys.modular.backgroundmanagement.secutiry.dto.AuthUserDto; +import org.nl.sys.modular.backgroundmanagement.secutiry.dto.UserDto; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; +import org.nl.sys.modular.backgroundmanagement.user.dto.OnlineUserDto; +import org.nl.sys.modular.backgroundmanagement.user.service.ISysUserService; +import org.nl.util.RsaUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.*; + +/** + * @author Zheng Jie + * @date 2019年10月26日21:56:27 + */ +@Service +@Slf4j +public class OnlineUserService { + + @Autowired + private ISysUserService sysUserService; + @Autowired + private ISysRoleService roleService; + @Autowired + private RedisUtils redisUtils; + + public OnlineUserService(RedisUtils redisUtils) { + this.redisUtils = redisUtils; + } + + /** + * 保存在线用户信息 + * @param userDto / + * @param token / + * @param request / + */ + public void save(UserDto userDto, String token, HttpServletRequest request){ +// String dept = userDto.getDept().getName(); + String dept = ""; + String ip = StringUtils.getIp(request); + String browser = StringUtils.getBrowser(request); + // String address = StringUtils.getCityInfo(ip); + String address = "局域网"; + OnlineUserDto onlineUserDto = null; + try { +// onlineUserDto = new OnlineUserDto(userDto.getUsername(), userDto.getNickName(), dept, browser , ip, address, EncryptUtils.desEncrypt(token), new Date()); + } catch (Exception e) { + log.error(e.getMessage(),e); + } + redisUtils.set(token, onlineUserDto, StpUtil.getTokenTimeout()); + } + + /** + * 查询全部数据 + * @param filter / + * @param pageable / + * @return / + */ + public Map getAll(String filter, Pageable pageable){ + List onlineUserDtos = getAll(filter); + return PageUtil.toPage( + PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(), onlineUserDtos), + onlineUserDtos.size() + ); + } + + /** + * 查询全部数据,不分页 + * @param filter / + * @return / + */ + public List getAll(String filter){ + List keys = redisUtils.scan("*"); + Collections.reverse(keys); + List onlineUserDtos = new ArrayList<>(); + for (String key : keys) { + if (key.length() == 1511) { + OnlineUserDto onlineUserDto = (OnlineUserDto) redisUtils.get(key); + if(StrUtil.isNotEmpty(filter)){ + if(onlineUserDto.toString().contains(filter)){ + onlineUserDtos.add(onlineUserDto); + } + } else { + onlineUserDtos.add(onlineUserDto); + } + } + + } + onlineUserDtos.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime())); + return onlineUserDtos; + } + + /** + * 踢出用户 + * @param key / + */ + public void kickOut(String key){ + redisUtils.del(key); + } + + /** + * 退出登录 + * @param token / + */ + public void logout(String token) { + redisUtils.del(token); + } + + /** + * 导出 + * @param all / + * @param response / + * @throws IOException / + */ + public void download(List all, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (OnlineUserDto user : all) { + Map map = new LinkedHashMap<>(); + map.put("用户名", user.getUserName()); + map.put("部门", user.getDept()); + map.put("登录IP", user.getIp()); + map.put("登录地点", user.getAddress()); + map.put("浏览器", user.getBrowser()); + map.put("登录日期", user.getLoginTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + /** + * 查询用户 + * @param key / + * @return / + */ + public OnlineUserDto getOne(String key) { + return (OnlineUserDto)redisUtils.get(key); + } + + /** + * 检测用户是否在之前已经登录,已经登录踢下线 + * @param userName 用户名 + */ + public void checkLoginOnUser(String userName, String igoreToken){ + List onlineUserDtos = getAll(userName); + if(onlineUserDtos ==null || onlineUserDtos.isEmpty()){ + return; + } + for(OnlineUserDto onlineUserDto : onlineUserDtos){ + if(onlineUserDto.getUserName().equals(userName)){ + try { + String token = EncryptUtils.desDecrypt(onlineUserDto.getKey()); + if(StrUtil.isNotEmpty(igoreToken)&&!igoreToken.equals(token)){ + this.kickOut(token); + }else if(StrUtil.isEmpty(igoreToken)){ + this.kickOut(token); + } + } catch (Exception e) { + log.error("checkUser is error",e); + } + } + } + } + + /** + * 根据用户名强退用户 + * @param username / + */ + @Async + public void kickOutForUsername(String username) throws Exception { + List onlineUsers = getAll(username); + for (OnlineUserDto onlineUser : onlineUsers) { + if (onlineUser.getUserName().equals(username)) { + String token = EncryptUtils.desDecrypt(onlineUser.getKey()); + kickOut(token); + } + } + } + @SneakyThrows + public Map login(Map paramMap){ + // 密码解密 - 前端的加密规则: encrypt + AuthUserDto authUser = JSON.toJavaObject((JSON) JSON.toJSON(paramMap), AuthUserDto.class); + String password = RsaUtils.decryptByPrivateKey(RsaUtils.privateKey, authUser.getPassword()); + // 查询验证码 + String code = (String) redisUtils.get(authUser.getUuid()); + // 清除验证码 + redisUtils.del(authUser.getUuid()); + if (StrUtil.isEmpty(code)) { + throw new BadRequestException("验证码不存在或已过期"); + } + if (StrUtil.isEmpty(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) { + throw new BadRequestException("验证码错误"); + } + // 校验数据库 + // 根据用户名查询,在比对密码 + SysUser userInfo = sysUserService.getOne(new QueryWrapper().eq("username",authUser.getUsername())); + if (userInfo == null||!userInfo.getPassword().equals(SaSecureUtil.md5BySalt(password, "salt"))) { // 这里需要密码加密 + throw new BadRequestException("账号或密码错误"); + } + + // 获取权限列表 - 登录查找权限 + List permissionList = roleService.getPermissionList((JSONObject) JSON.toJSON(userInfo)); + + + if (!userInfo.getIs_used()) { + throw new BadRequestException("账号未激活"); + } + + // 登录输入,登出删除 + CurrentUser user = new CurrentUser(); + user.setId(userInfo.getUser_id()); + user.setUsername(userInfo.getUsername()); + user.setPresonName((userInfo.getPerson_name())); + user.setUser(userInfo); + user.setPermissions(permissionList); + + // SaLoginModel 配置登录相关参数 + StpUtil.login(userInfo.getUser_id(), new SaLoginModel() + .setDevice("PC") // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型 + .setExtra("loginInfo", user) // Token挂载的扩展参数 (此方法只有在集成jwt插件时才会生效) + ); + + // 返回 token 与 用户信息 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("roles", permissionList); + jsonObject.put("user", userInfo); + Map authInfo = new HashMap(2) {{ + put("token", "Bearer " + StpUtil.getTokenValue()); + put("user", user); + }}; + // 保存在线信息 +// onlineUserService.save(userDto, StpUtil.getTokenValue(), request); + return authInfo; + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/task/controller/ManagerTaskController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/task/controller/ManagerTaskController.java new file mode 100644 index 0000000..69cac9f --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/task/controller/ManagerTaskController.java @@ -0,0 +1,34 @@ +package org.nl.sys.modular.backgroundmanagement.task.controller; + +import jakarta.annotation.Resource; +import org.nl.api.task.api.TaskAPI; +import org.nl.api.task.core.TaskRequestParam; +import org.nl.enums.TaskSourceEnum; +import org.nl.logging.annotation.Log; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +/** + * @author dsh + * 2026/1/21 + */ +@RestController +@RequestMapping("/managerTask") +public class ManagerTaskController { + + @Resource + private TaskAPI taskAPI; + + @Log("后台管理系统创建任务") + @PostMapping("/createTask") + public ResponseEntity createTask(@RequestBody TaskRequestParam param){ + return new ResponseEntity<>(taskAPI.createTask(param, TaskSourceEnum.BACKGROUNDMANAGEMENT.getName()), HttpStatus.OK); + } + + @Log("后台管理系统取消任务") + @PostMapping("/cancelTask") + public ResponseEntity cancelTask(@RequestParam String taskCode){ + return new ResponseEntity<>(taskAPI.cancelTask(taskCode), HttpStatus.OK); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/controller/OnlineController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/controller/OnlineController.java new file mode 100644 index 0000000..42f6d21 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/controller/OnlineController.java @@ -0,0 +1,66 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.user.controller; + +import jakarta.servlet.http.HttpServletResponse; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.util.EncryptUtils; +import org.nl.sys.modular.backgroundmanagement.secutiry.service.OnlineUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Set; + +/** + * @author Zheng Jie + */ +@RestController +@RequestMapping("/auth/online") +public class OnlineController { + + @Autowired + private OnlineUserService onlineUserService; + + @Log("查询在线用户") + @GetMapping + // @SaCheckPermission("@el.check()") + public ResponseEntity query(String filter, Pageable pageable){ + return new ResponseEntity<>(onlineUserService.getAll(filter, pageable),HttpStatus.OK); + } + + @Log("导出数据") + @GetMapping(value = "/download") + // @SaCheckPermission("@el.check()") + public void download(HttpServletResponse response, String filter) throws IOException { + onlineUserService.download(onlineUserService.getAll(filter), response); + } + + @Log("踢出用户") + @DeleteMapping + // @SaCheckPermission("@el.check()") + public ResponseEntity delete(@RequestBody Set keys) throws Exception { + for (String key : keys) { + // 解密Key + key = EncryptUtils.desDecrypt(key); + onlineUserService.kickOut(key); + } + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/controller/UserController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/controller/UserController.java new file mode 100644 index 0000000..d76a20d --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/controller/UserController.java @@ -0,0 +1,133 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.user.controller; + +import cn.dev33.satoken.secure.SaSecureUtil; +import cn.dev33.satoken.stp.StpUtil; +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 lombok.RequiredArgsConstructor; +import org.nl.exception.BadRequestException; +import org.nl.logging.annotation.Log; +import org.nl.sys.modular.backgroundmanagement.common.base.TableDataInfo; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserQuery; +import org.nl.sys.modular.backgroundmanagement.user.service.ISysUserService; +import org.nl.util.RsaUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; +import java.util.Set; + +/** + * @author Zheng Jie + * @date 2018-11-23 + */ +@RestController +@RequestMapping("/api/users") +@RequiredArgsConstructor +public class UserController { + + @Autowired + private ISysUserService userService; + + + @Log("查询用户") + @GetMapping + public ResponseEntity query(UserQuery query, PageQuery page){ + return new ResponseEntity(TableDataInfo.build(userService.getUserDetail(query, page)),HttpStatus.OK); + } + + @Log("新增用户") + @PostMapping + public ResponseEntity create(@RequestBody Map user){ + userService.create(user); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @Log("修改用户") + @PutMapping + public ResponseEntity update( @RequestBody Map resources) throws Exception { + userService.update(resources); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("修改用户:个人中心") + public ResponseEntity center(@RequestBody SysUser resources){ + if(!resources.getUser_id().equals(StpUtil.getLoginIdAsLong())){ + throw new BadRequestException("不能修改他人资料"); + } + userService.saveOrUpdate(resources); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Log("删除用户") + @DeleteMapping + public ResponseEntity delete(@RequestBody Set ids) { + userService.removeByIds(ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + @Log("修改密码") + @PostMapping(value = "/updatePass") + public ResponseEntity updatePass(@RequestBody JSONObject passVo) throws Exception { + // 解密,得到字符密码 + String oldPass = RsaUtils.decryptByPrivateKey(RsaUtils.privateKey,passVo.getString("oldPass")); + String newPass = RsaUtils.decryptByPrivateKey(RsaUtils.privateKey,passVo.getString("newPass")); + SysUser user = userService.getOne(new LambdaQueryWrapper().eq(SysUser::getUsername, SecurityUtils.getCurrentUsername())); + if (!SaSecureUtil.md5BySalt(user.getPassword(), "salt").equals(SaSecureUtil.md5BySalt(oldPass, "salt"))) { + throw new BadRequestException("修改失败,旧密码错误"); + } + if (!SaSecureUtil.md5BySalt(user.getPassword(), "salt").equals(SaSecureUtil.md5BySalt(newPass, "salt"))) { + throw new BadRequestException("新密码不能与旧密码相同"); + } + user.setPassword(SaSecureUtil.md5BySalt(newPass, "salt")); + userService.updateById(user); + return new ResponseEntity<>(HttpStatus.OK); + } + + @Log("修改头像") + @PostMapping(value = "/updateAvatar") + public ResponseEntity updateAvatar(@RequestParam MultipartFile avatar){ + return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK); + } + + @Log("修改邮箱") + @PostMapping(value = "/updateEmail/{code}") + public ResponseEntity updateEmail(@PathVariable String code,@RequestBody SysUser user) throws Exception { + String password = RsaUtils.decryptByPrivateKey(RsaUtils.privateKey,user.getPassword()); + SysUser userInfo = userService.getOne(new QueryWrapper().eq("username",SecurityUtils.getCurrentUsername())); + if(!SaSecureUtil.md5BySalt(userInfo.getPassword(), "salt").equals(SaSecureUtil.md5BySalt(password, "salt"))){ + throw new BadRequestException("密码错误"); + } + userService.update(new UpdateWrapper().set(userInfo.getUsername(),user.getEmail())); + return new ResponseEntity<>(HttpStatus.OK); + } + + /** + * 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误 + * @param resources / + */ + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dao/SysUser.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dao/SysUser.java new file mode 100644 index 0000000..0708599 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dao/SysUser.java @@ -0,0 +1,139 @@ +package org.nl.sys.modular.backgroundmanagement.user.dao; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 用户表 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_user") +public class SysUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户标识 + */ + @TableId(value = "user_id", type = IdType.NONE) + private String user_id; + + /** + * 登录账号 + */ + private String username; + + /** + * 姓名 + */ + private String person_name; + + /** + * 性别 + */ + private String gender; + + /** + * 电话 + */ + private String phone; + + /** + * 电子邮箱 + */ + private String email; + + /** + * 头像地址 + */ + private String avatar_name; + + /** + * 头像真实路径 + */ + private String avatar_path; + + /** + * 密码 + */ + private String password; + + /** + * 是否为admin账号 + */ + private Boolean is_admin; + + /** + * 是否启用 + */ + private Boolean is_used; + + /** + * 密码重置者 + */ + private Long pwd_reset_user_id; + + /** + * 密码重置时间 + */ + private Date pwd_reset_time; + + /** + * 创建人标识 + */ + private String create_id; + + /** + * 创建人 + */ + private String create_name; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private Date create_time; + + /** + * 修改人标识 + */ + private String update_id; + + /** + * 修改人 + */ + private String update_name; + + /** + * 修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date update_time; + + /** + * 外部人员标识 + */ + private String extperson_id; + + /** + * 外部用户标识 + */ + private String extuser_id; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/OnlineUserDto.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/OnlineUserDto.java new file mode 100644 index 0000000..77ce2de --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/OnlineUserDto.java @@ -0,0 +1,74 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.sys.modular.backgroundmanagement.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +/** + * 在线用户 + * @author Zheng Jie + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class OnlineUserDto { + + /** + * 用户名 + */ + private String userName; + + /** + * 昵称 + */ + private String nickName; + + /** + * 岗位 + */ + private String dept; + + /** + * 浏览器 + */ + private String browser; + + /** + * IP + */ + private String ip; + + /** + * 地址 + */ + private String address; + + /** + * token + */ + private String key; + + /** + * 登录时间 + */ + private Date loginTime; + + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/SysUserDetail.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/SysUserDetail.java new file mode 100644 index 0000000..d9971e9 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/SysUserDetail.java @@ -0,0 +1,19 @@ +package org.nl.sys.modular.backgroundmanagement.user.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.dept.dao.SysDept; +import org.nl.sys.modular.backgroundmanagement.role.dao.SysRole; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; + +import java.util.List; + +/* + * @author ZZQ + * @Date 2022/12/16 10:02 上午 + */ +@Data +public class SysUserDetail extends SysUser { + private List depts; + + private List roles; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/UserDataPermissionDto.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/UserDataPermissionDto.java new file mode 100644 index 0000000..ecf9e42 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/UserDataPermissionDto.java @@ -0,0 +1,31 @@ +package org.nl.sys.modular.backgroundmanagement.user.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.List; + +/** + * @Author: lyd + * @Description: 用户-权限表 + * @Date: 2022/12/20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_user_data_permission") +public class UserDataPermissionDto implements Serializable { + private String user_id; + + private String permission_scope_type; + + private String permission_id; + + @TableField(exist = false) + private List users; + + @TableField(exist = false) + private List depts; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/UserQuery.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/UserQuery.java new file mode 100644 index 0000000..08e5b8a --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/dto/UserQuery.java @@ -0,0 +1,22 @@ +package org.nl.sys.modular.backgroundmanagement.user.dto; + +import lombok.Data; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.BaseQuery; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.QParam; +import org.nl.sys.modular.backgroundmanagement.common.enums.QueryTEnum; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; + +/* + * @author ZZQ + * @Date 2022/12/15 9:53 上午 + */ +@Data +public class UserQuery extends BaseQuery { + + private Long dept_id; + + @Override + public void paramMapping() { + this.doP.put("dept_id", QParam.builder().k(new String[]{"dept_id"}).type(QueryTEnum.LK).build()); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/mapper/SysUserMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/mapper/SysUserMapper.java new file mode 100644 index 0000000..b047555 --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/mapper/SysUserMapper.java @@ -0,0 +1,37 @@ +package org.nl.sys.modular.backgroundmanagement.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; +import org.nl.sys.modular.backgroundmanagement.user.dto.SysUserDetail; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserDataPermissionDto; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserQuery; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface SysUserMapper extends BaseMapper { + + List getUserDetail(@Param("query") UserQuery query, @Param("page") PageQuery page); + + List> getDetailForMap(@Param("query") UserQuery query, @Param("page")PageQuery page); + + List getUserDataPermissionByPermissionId(String permissionId); + + List getUserDataPermissionByUserId(String userId); + + void deleteDataPermissionById(String userId); + + void insertDataPermission(@Param("dataPermission") UserDataPermissionDto dataPermission); + + List getUserIdByDeptId(String deptId); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/mapper/mapping/SysUserMapper.xml b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/mapper/mapping/SysUserMapper.xml new file mode 100644 index 0000000..42ddbbf --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/mapper/mapping/SysUserMapper.xml @@ -0,0 +1,143 @@ + + + + + sys_user.user_id as userId, + sys_user.username as username, + sys_user.person_name as personName, + sys_user.gender, + sys_user.phone, + sys_user.email, + sys_user.avatar_name as avatarName, + sys_user.avatar_path as avatarPath, + sys_user.password, + sys_user.is_admin as isAdmin, + sys_user.is_used as isUsed, + sys_user.pwd_reset_user_id as pwdResetUserId, + sys_user.pwd_reset_time as pwdResetTime, + sys_user.create_id as createId, + sys_user.create_name as createName, + sys_user.create_time as createTime, + sys_user.update_id as updateId, + sys_user.update_name as updateName, + sys_user.update_time as updateTime, + sys_user.extperson_id as extpersonId, + sys_user.extuser_id as extuserId + + + INSERT INTO sys_user_data_permission(user_id, permission_scope_type, permission_id) VALUES (#{dataPermission.user_id}, #{dataPermission.permission_scope_type}, #{dataPermission.permission_id}) + + + DELETE FROM sys_user_data_permission WHERE user_id = #{userId} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/service/ISysUserService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/service/ISysUserService.java new file mode 100644 index 0000000..25212ed --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/service/ISysUserService.java @@ -0,0 +1,40 @@ +package org.nl.sys.modular.backgroundmanagement.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; +import org.nl.sys.modular.backgroundmanagement.user.dto.SysUserDetail; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserDataPermissionDto; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserQuery; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +public interface ISysUserService extends IService { + + Map updateAvatar(MultipartFile avatar); + + List getUserDetail(UserQuery query, PageQuery pageQuery); + + void create(Map userDetail); + + void update(Map userDetail); + + List getUserDataPermissionByPermissionId(String permissionId); + List getUserDataPermissionByUserId(String userId); + + void deleteDataPermissionById(String userId); + + void insertDataPermission(UserDataPermissionDto userDataPermissionDto); + + List getUserIdByDeptId(String deptId); +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/service/impl/ISysUserServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/service/impl/ISysUserServiceImpl.java new file mode 100644 index 0000000..97d4faa --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/backgroundmanagement/user/service/impl/ISysUserServiceImpl.java @@ -0,0 +1,159 @@ +package org.nl.sys.modular.backgroundmanagement.user.service.impl; + +import cn.dev33.satoken.secure.SaSecureUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.SneakyThrows; +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.beanutils.ConvertUtils; +import org.nl.sys.modular.backgroundmanagement.common.domain.query.PageQuery; +import org.nl.sys.modular.backgroundmanagement.common.util.FileUtil; +import org.nl.sys.modular.backgroundmanagement.common.util.SecurityUtils; +import org.nl.sys.modular.backgroundmanagement.dept.service.ISysDeptService; +import org.nl.sys.modular.backgroundmanagement.role.service.ISysRoleService; +import org.nl.sys.modular.backgroundmanagement.user.dao.SysUser; +import org.nl.sys.modular.backgroundmanagement.user.dto.SysUserDetail; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserDataPermissionDto; +import org.nl.sys.modular.backgroundmanagement.user.dto.UserQuery; +import org.nl.sys.modular.backgroundmanagement.user.mapper.SysUserMapper; +import org.nl.sys.modular.backgroundmanagement.user.service.ISysUserService; +import org.nl.util.FileProperties; +import org.nl.util.IdUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author generator + * @since 2022-12-15 + */ +@Service +public class ISysUserServiceImpl extends ServiceImpl implements ISysUserService { + + @Autowired + private FileProperties properties; + @Autowired + private SysUserMapper sysUserMapper; + @Autowired + private ISysDeptService deptService; + @Autowired + private ISysRoleService roleService; + + @Override + public Map updateAvatar(MultipartFile multipartFile) { + SysUser user = this.getOne(new QueryWrapper().eq("username", SecurityUtils.getCurrentUsername())); + String oldPath = user.getAvatar_path(); + File file = FileUtil.upload(multipartFile, properties.getPath().getAvatar()); + user.setAvatar_path(Objects.requireNonNull(file).getPath()); + user.setAvatar_name(file.getName()); + this.saveOrUpdate(user); + if (StrUtil.isNotEmpty(oldPath)) { + FileUtil.del(oldPath); + } + return new HashMap(1) {{ + put("avatar", file.getName()); + }}; + } + + @Override + public List getUserDetail(UserQuery query, PageQuery pageQuery) { + List userDetail = sysUserMapper.getUserDetail(query, pageQuery); + return userDetail; + } + + @Override + @Transactional(rollbackFor = Exception.class) + @SneakyThrows + public void create(Map userDetail) { + SysUser sysUser = new SysUser(); + BeanUtils.populate(sysUser,userDetail); + // 默认密码 123456 + if (ObjectUtil.isEmpty(sysUser.getPassword())) { + sysUser.setPassword(SaSecureUtil.md5BySalt("123456", "salt")); + } else { + sysUser.setPassword(SaSecureUtil.md5BySalt(sysUser.getPassword(), "salt")); + } + String userId = IdUtil.getStringId(); + sysUser.setUser_id(userId); + this.save(sysUser); + if (userDetail.get("depts") !=null){ + deptService.saveUserDeptRelation(userId,(List)userDetail.get("depts")); + }; + if (userDetail.get("roles") !=null){ + roleService.saveUserRoleRelation(userId,(List)userDetail.get("roles")); + }; + } + + @Override + @Transactional + public void update(Map userDetail) { + if(CollectionUtils.isEmpty(userDetail) || ObjectUtil.isEmpty(userDetail.get("user_id"))){ + return; + } + + SysUser sysUser = new SysUser(); + org.springframework.beans.BeanUtils.copyProperties(userDetail,sysUser); + //转换器 + ConvertUtils.register((aClass, o) -> { + try { + if (o == null){ return null; } + return new SimpleDateFormat("yyyy-MM-dd").parse(o.toString()); + }catch (Exception ex){ + return null; + } + }, Date.class); + try { + BeanUtils.populate(sysUser,userDetail); + }catch (Exception ex){ + throw new RuntimeException(); + } + sysUser.setUpdate_time(new Date()); + sysUser.setUpdate_id(SecurityUtils.getCurrentUserId()); + this.updateById(sysUser); + if (userDetail.get("deptIds")!=null){ + deptService.delUserDeptRelation(sysUser.getUser_id()); + deptService.saveUserDeptRelation(sysUser.getUser_id(), (List) userDetail.get("deptIds")); + }; + if (userDetail.get("rolesIds") !=null){ + roleService.delUserRoleRelation(sysUser.getUser_id()); + roleService.saveUserRoleRelation(sysUser.getUser_id(),(List) userDetail.get("rolesIds")); + } + } + + @Override + public List getUserDataPermissionByPermissionId(String permissionId) { + return sysUserMapper.getUserDataPermissionByPermissionId(permissionId); + } + + @Override + public List getUserDataPermissionByUserId(String userId) { + return sysUserMapper.getUserDataPermissionByUserId(userId); + } + + @Override + public void deleteDataPermissionById(String userId) { + sysUserMapper.deleteDataPermissionById(userId); + } + + @Override + public void insertDataPermission(UserDataPermissionDto userDataPermissionDto) { + sysUserMapper.insertDataPermission(userDataPermissionDto); + } + + @Override + public List getUserIdByDeptId(String deptId) { + return sysUserMapper.getUserIdByDeptId(deptId); + } +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/controller/QRCodeController.java b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/controller/QRCodeController.java index a18830c..b374120 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/controller/QRCodeController.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/controller/QRCodeController.java @@ -1,7 +1,7 @@ package org.nl.sys.modular.qrcode.controller; import jakarta.annotation.Resource; -import org.nl.api.task.core.QRCodeTaskRequestParam; +import org.nl.api.task.core.TaskRequestParam; import org.nl.logging.annotation.Log; import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam; import org.nl.sys.modular.qrcode.service.QRCodeService; @@ -34,7 +34,7 @@ public class QRCodeController { @PostMapping("/createTask") @Log("二维码创建任务") - public ResponseEntity createTask(@RequestBody QRCodeTaskRequestParam param){ + public ResponseEntity createTask(@RequestBody TaskRequestParam param){ return new ResponseEntity<>(qrCodeService.createTask(param),HttpStatus.OK); } diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/dao/QRcodeInfo.java b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/dao/QRcodeInfo.java new file mode 100644 index 0000000..896046b --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/dao/QRcodeInfo.java @@ -0,0 +1,50 @@ +package org.nl.sys.modular.qrcode.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author dsh + * 2026/1/30 + */ +@Data +@TableName("qrcode_info") +public class QRcodeInfo { + + /** + * 二维码标识 + */ + @TableId + private String qrcode_id; + + /** + * 二维码文件名称 + */ + private String file_name; + + /** + * 房间编码 + */ + private String room_code; + + /** + * 二维码地址 + */ + private String file_address; + + /** + * 二维码文件大小(KB) + */ + private String file_size; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改时间 + */ + private String update_time; +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/mapper/QRcodeInfoMapper.java b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/mapper/QRcodeInfoMapper.java new file mode 100644 index 0000000..a3c5f6e --- /dev/null +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/mapper/QRcodeInfoMapper.java @@ -0,0 +1,14 @@ +package org.nl.sys.modular.qrcode.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.nl.sys.modular.qrcode.dao.QRcodeInfo; + +/** + * @author dsh + * 2026/1/30 + */ +@Mapper +public interface QRcodeInfoMapper extends BaseMapper { + +} diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/QRCodeService.java b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/QRCodeService.java index 53bef59..a3b5b6c 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/QRCodeService.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/QRCodeService.java @@ -1,6 +1,6 @@ package org.nl.sys.modular.qrcode.service; -import org.nl.api.task.core.QRCodeTaskRequestParam; +import org.nl.api.task.core.TaskRequestParam; import org.nl.response.WebResponse; import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam; @@ -22,7 +22,7 @@ public interface QRCodeService { * @param qrCodeTaskRequestParam * @return */ - WebResponse createTask(QRCodeTaskRequestParam qrCodeTaskRequestParam); + WebResponse createTask(TaskRequestParam qrCodeTaskRequestParam); /** * 二维码创建任务 diff --git a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/impl/QRCodeServiceImpl.java b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/impl/QRCodeServiceImpl.java index 0eefc96..09e0cd6 100644 --- a/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/impl/QRCodeServiceImpl.java +++ b/nl-business-sys/src/main/java/org/nl/sys/modular/qrcode/service/impl/QRCodeServiceImpl.java @@ -1,14 +1,20 @@ package org.nl.sys.modular.qrcode.service.impl; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import jakarta.annotation.Resource; import org.nl.api.task.api.TaskAPI; -import org.nl.api.task.core.QRCodeTaskRequestParam; +import org.nl.api.task.core.TaskRequestParam; +import org.nl.enums.TaskSourceEnum; import org.nl.exception.BadRequestException; import org.nl.response.WebResponse; +import org.nl.sys.modular.qrcode.dao.QRcodeInfo; +import org.nl.sys.modular.qrcode.mapper.QRcodeInfoMapper; import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam; import org.nl.sys.modular.qrcode.service.QRCodeService; import org.nl.util.FileProperties; +import org.nl.util.IdUtil; import org.nl.util.QRCodeUtil; import org.springframework.stereotype.Service; @@ -22,22 +28,42 @@ public class QRCodeServiceImpl implements QRCodeService { @Resource private FileProperties fileProperties; + @Resource + private QRcodeInfoMapper qrcodeInfoMapper; + @Resource private TaskAPI taskAPI; @Override public WebResponse generateQRCode(GenerateQRCodeParam param) { + //result 返回文件大小 String result = QRCodeUtil.generateQRCode(param.getData(), param.getWidth(), param.getHeight(),fileProperties.getPath().getQrcode(),param.getRoom()+".png"); if (StrUtil.isBlank(result)){ throw new BadRequestException("生成二维码失败"); } + + boolean exists = qrcodeInfoMapper.selectCount(new LambdaQueryWrapper<>(QRcodeInfo.class) + .eq(QRcodeInfo::getRoom_code,param.getRoom()) + )>0; + if (exists){ + throw new BadRequestException("该房间已存在二维码,无法继续生成"); + } + QRcodeInfo qrcodeInfo = new QRcodeInfo(); + qrcodeInfo.setQrcode_id(IdUtil.getStringId()); + qrcodeInfo.setFile_name(param.getRoom()+".png"); + qrcodeInfo.setRoom_code(param.getRoom()); + qrcodeInfo.setFile_address("/qrcode/"+param.getRoom()+".png"); + qrcodeInfo.setFile_size(result); + qrcodeInfo.setCreate_time(DateUtil.now()); + + qrcodeInfoMapper.insert(qrcodeInfo); return WebResponse.requestOk(); } @Override - public WebResponse createTask(QRCodeTaskRequestParam qrCodeTaskRequestParam) { - taskAPI.createTask(qrCodeTaskRequestParam); + public WebResponse createTask(TaskRequestParam qrCodeTaskRequestParam) { + taskAPI.createTask(qrCodeTaskRequestParam, TaskSourceEnum.QRCODE.getName()); return null; } diff --git a/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java b/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java index 0fed757..3efbcb2 100644 --- a/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java +++ b/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java @@ -3,7 +3,7 @@ package org.nl.task.controller; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.nl.logging.annotation.Log; -import org.nl.task.enums.TaskSourceEnum; +import org.nl.enums.TaskSourceEnum; import org.nl.task.param.CancelTaskRequestParam; import org.nl.task.param.CreateTaskRequestParam; import org.nl.task.param.OneClickOperationRequestParam; @@ -14,8 +14,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.List; - /** * @author dsh * 2025/11/27 @@ -70,4 +68,10 @@ public class TaskController { return new ResponseEntity<>(taskService.oneClickOperation(oneClickOperationRequestParam, TaskSourceEnum.SCREEN.getName()),HttpStatus.OK); } + @GetMapping("/queryCurrentTaskInfo") + @Log("查询当前任务") + public ResponseEntity queryCurrentTaskInfo(){ + return new ResponseEntity<>(taskService.queryCurrentTaskInfo(),HttpStatus.OK); + } + } diff --git a/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java b/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java index 3a946e1..7c6087c 100644 --- a/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java +++ b/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java @@ -9,12 +9,10 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.nl.api.task.api.TaskAPI; -import org.nl.api.task.core.QRCodeTaskRequestParam; -import org.nl.enums.ScheduleTaskReportStatusEnum; -import org.nl.exception.BadRequestException; +import org.nl.api.task.core.TaskRequestParam; import org.nl.response.WebResponse; import org.nl.task.entity.Task; -import org.nl.task.enums.TaskSourceEnum; +import org.nl.enums.TaskSourceEnum; import org.nl.task.enums.TaskStatusEnum; import org.nl.task.param.CancelTaskRequestParam; import org.nl.task.param.CreateTaskRequestParam; @@ -72,9 +70,9 @@ public class TaskAPIProvider implements TaskAPI { } @Override - public WebResponse createTask(QRCodeTaskRequestParam qrCodeTaskRequestParam) { - CreateTaskRequestParam param = BeanUtil.toBean(qrCodeTaskRequestParam, CreateTaskRequestParam.class); - return taskService.createTask(param, TaskSourceEnum.QRCODE.getName()); + public WebResponse createTask(TaskRequestParam taskRequestParam,String taskSource) { + CreateTaskRequestParam param = BeanUtil.toBean(taskRequestParam, CreateTaskRequestParam.class); + return taskService.createTask(param, taskSource); } @Override diff --git a/nl-business-task/src/main/java/org/nl/task/service/TaskService.java b/nl-business-task/src/main/java/org/nl/task/service/TaskService.java index b4436c7..aafb07e 100644 --- a/nl-business-task/src/main/java/org/nl/task/service/TaskService.java +++ b/nl-business-task/src/main/java/org/nl/task/service/TaskService.java @@ -66,7 +66,7 @@ public interface TaskService extends IService{ WebResponse oneClickOperation(OneClickOperationRequestParam oneClickOperationRequestParam,String taskSource); /** - * 根据房间号查询当前任务信息 + * 查询当前任务信息 * @return List */ List queryCurrentTaskInfo(); diff --git a/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java b/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java index aa0add3..5aecb46 100644 --- a/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java +++ b/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java @@ -169,11 +169,11 @@ public class TaskServiceImpl extends ServiceImpl implements Tas throw new BadRequestException("任务号不能为空"); } - HttpResponse result = scheduleTaskAPI.cancelTask(cancelTaskRequestParam.getTask_code()); - if (result == null || !result.isOk()){ - log.info("取消调度任务失败"); - throw new BadRequestException("取消调度任务失败"); - } +// HttpResponse result = scheduleTaskAPI.cancelTask(cancelTaskRequestParam.getTask_code()); +// if (result == null || !result.isOk()){ +// log.info("取消调度任务失败"); +// throw new BadRequestException("取消调度任务失败"); +// } taskMapper.update(new LambdaUpdateWrapper<>(Task.class) .set(Task::getStatus,TaskStatusEnum.CANCELED.getCode()) @@ -260,6 +260,12 @@ public class TaskServiceImpl extends ServiceImpl implements Tas @Override public WebResponse taskOperationConfirm(String task_code) { + // 校验一下当前是否到达上报点位,如果未到达上报点位,不能触发确认到达。 + Task task = taskMapper.selectOne(new LambdaQueryWrapper<>(Task.class).eq(Task::getTask_code, task_code)); + if (!ScheduleTaskReportStatusEnum.REPORTED.getCode().equals(task.getVehicleReportStatus())) { + throw new BadRequestException("未到达上报点位,无法确认到达"); + } + boolean reuslt = taskMapper.update(new LambdaUpdateWrapper<>(Task.class) .set(Task::getVehicleReportStatus, ScheduleTaskReportStatusEnum.FINISH_REPORTED.getCode()) .set(Task::getUpdate_time,DateUtil.now()) diff --git a/nl-common/pom.xml b/nl-common/pom.xml index 473365d..896fa07 100644 --- a/nl-common/pom.xml +++ b/nl-common/pom.xml @@ -77,5 +77,23 @@ cn.dev33 sa-token-spring-boot3-starter + + + + org.apache.commons + commons-pool2 + + + + org.redisson + redisson-spring-boot-starter + + + + + cn.dev33 + sa-token-jwt + + diff --git a/nl-common/src/main/java/org/nl/config/MybatisPlusConfig.java b/nl-common/src/main/java/org/nl/config/MybatisPlusConfig.java new file mode 100644 index 0000000..6424a57 --- /dev/null +++ b/nl-common/src/main/java/org/nl/config/MybatisPlusConfig.java @@ -0,0 +1,22 @@ +package org.nl.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author dsh + * 2026/1/13 + */ +@Configuration +public class MybatisPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} diff --git a/nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java b/nl-common/src/main/java/org/nl/enums/TaskSourceEnum.java similarity index 75% rename from nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java rename to nl-common/src/main/java/org/nl/enums/TaskSourceEnum.java index 79344c2..33f3149 100644 --- a/nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java +++ b/nl-common/src/main/java/org/nl/enums/TaskSourceEnum.java @@ -1,4 +1,4 @@ -package org.nl.task.enums; +package org.nl.enums; import lombok.Getter; @@ -24,7 +24,11 @@ public enum TaskSourceEnum { /** * 二维码 */ - QRCODE("4", "QRCode", "二维码"); + QRCODE("4", "QRCode", "二维码"), + /** + * 后台管理系统 + */ + BACKGROUNDMANAGEMENT("5", "BackGroundManagement", "后台管理系统"); private String code; private String name; diff --git a/nl-common/src/main/java/org/nl/satoken/SaTokenConfig.java b/nl-common/src/main/java/org/nl/satoken/SaTokenConfig.java new file mode 100644 index 0000000..1194450 --- /dev/null +++ b/nl-common/src/main/java/org/nl/satoken/SaTokenConfig.java @@ -0,0 +1,28 @@ +package org.nl.satoken; + +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.stp.StpUtil; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + + +/** + * @author dsh + * 2025/10/22 + */ +@Configuration +public class SaTokenConfig implements WebMvcConfigurer { + + @Resource + private SecurityProperties securityProperties; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin())) + .addPathPatterns("/**") + .excludePathPatterns(securityProperties.getExcludes()); + } +} diff --git a/nl-common/src/main/java/org/nl/satoken/SecurityProperties.java b/nl-common/src/main/java/org/nl/satoken/SecurityProperties.java new file mode 100644 index 0000000..e129a58 --- /dev/null +++ b/nl-common/src/main/java/org/nl/satoken/SecurityProperties.java @@ -0,0 +1,21 @@ +package org.nl.satoken; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author dsh + * 2025/10/22 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "security") +public class SecurityProperties { + + /** + * 排除路径 + */ + private String[] excludes; + +} diff --git a/nl-common/src/main/java/org/nl/util/FileProperties.java b/nl-common/src/main/java/org/nl/util/FileProperties.java index e083f25..791f363 100644 --- a/nl-common/src/main/java/org/nl/util/FileProperties.java +++ b/nl-common/src/main/java/org/nl/util/FileProperties.java @@ -41,5 +41,7 @@ public class FileProperties { private String path; private String qrcode; + + private String avatar; } } diff --git a/nl-common/src/main/java/org/nl/util/QRCodeUtil.java b/nl-common/src/main/java/org/nl/util/QRCodeUtil.java index 58cec85..08df5a6 100644 --- a/nl-common/src/main/java/org/nl/util/QRCodeUtil.java +++ b/nl-common/src/main/java/org/nl/util/QRCodeUtil.java @@ -10,6 +10,7 @@ import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; +import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; @@ -28,7 +29,7 @@ public class QRCodeUtil { * @param width 二维码宽度(像素) * @param height 二维码高度(像素) * @param filePath 保存路径(需包含.png后缀) - * @return 生成的二维码文件路径,失败时返回null + * @return 生成文件大小KB,失败时返回null */ public static String generateQRCode(String data, int width, int height, String filePath,String fileName) { @@ -64,7 +65,11 @@ public class QRCodeUtil { File qrCodeFile = new File(filePath, fileName); ImageIO.write(image, "png", qrCodeFile); log.info("二维码已生成并保存到: {}", filePath); - return filePath; + double fileSizeKB = qrCodeFile.length() / 1024.0; + // 保留后小数点后2位 + String formattedNumber = String.format("%.2f", fileSizeKB); + log.info("文件大小: {}KB", formattedNumber); + return formattedNumber; } catch (Exception e) { log.info("生成二维码错误:{}", e.getMessage()); return null; diff --git a/nl-web-app/pom.xml b/nl-web-app/pom.xml index f79d4a2..6b6f1b2 100644 --- a/nl-web-app/pom.xml +++ b/nl-web-app/pom.xml @@ -68,6 +68,11 @@ com.mysql mysql-connector-j + + + com.alicp.jetcache + jetcache-starter-redis + diff --git a/nl-web-app/src/main/java/org/nl/Application.java b/nl-web-app/src/main/java/org/nl/Application.java index e1232b5..9c543da 100644 --- a/nl-web-app/src/main/java/org/nl/Application.java +++ b/nl-web-app/src/main/java/org/nl/Application.java @@ -12,6 +12,8 @@ */ package org.nl; +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; @@ -35,6 +37,8 @@ import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @EnableScheduling @EnableTransactionManagement +@EnableMethodCache(basePackages = "org.nl") +@EnableCreateCacheAnnotation @MapperScan("org.nl.**.mapper") public class Application { diff --git a/nl-web-app/src/main/resources/config/application-dev.yml b/nl-web-app/src/main/resources/config/application-dev.yml index fd81680..d96c471 100644 --- a/nl-web-app/src/main/resources/config/application-dev.yml +++ b/nl-web-app/src/main/resources/config/application-dev.yml @@ -59,18 +59,32 @@ spring: wall: config: multi-statement-allow: true + data: + redis: + #数据库索引 + database: 2 + host: 192.168.29.130 + port: 6379 + password: 123456 + +# IP 本地解析 +ip: + local-parsing: true # 文件存储路径 file: mac: path: ~/file/ - qrcode: ~/avatar/ + qrcode: ~/qrcode/ + avatar: ~/avatar/ linux: path: /home/eladmin/file/ qrcode: /home/eladmin/qrcode/ + avatar: /home/eladmin/avatar/ windows: - path: C:\eladmin\file\ + path: C:\eladmin\file\currentMap\ qrcode: C:\eladmin\qrcode\ + avatar: C:\eladmin\avatar\ # 文件大小 /M maxSize: 100 avatarMaxSize: 5 @@ -82,7 +96,7 @@ sa-token: # token有效期,单位s 默认30天, -1代表永不过期 timeout: 2592000 # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 - activity-timeout: -1 + active-timeout: -1 # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) is-concurrent: true # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) @@ -90,4 +104,59 @@ sa-token: # token风格 token-style: random-128 # 是否输出操作日志 - is-log: true \ No newline at end of file + is-log: true + jwt-secret-key: opsjajisdnnca0sdkksdfaaasdfwwq + # token 前缀 + token-prefix: Bearer + sso: + # Ticket有效期 (单位: 秒),默认五分钟 + ticket-timeout: 300 + # 所有允许的授权回调地址 + allow-url: "*" + # 是否打开单点注销功能 + is-slo: true + + # ------- SSO-模式三相关配置 (下面的配置在SSO模式三并且 is-slo=true 时打开) + # 是否打开模式三 + isHttp: true + # 接口调用秘钥(用于SSO模式三的单点注销功能) + secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor + # ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明) + is-read-cookie: true + is-print: false + # 未登录 StpUtil.getTokenSession() 设置值,获取值 @SaIgnore 得忽略接口 + token-session-check-login: false + alone-redis: + # Redis数据库索引(默认为0) + database: 2 + # Redis服务器地址 + host: 192.168.29.130 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: 123456 + # 连接超时时间 + timeout: 10s + +# 登录相关配置 +login: + # 登录缓存 + cache-enable: true + # 是否限制单用户登录 + single-login: false + # 验证码 + login-code: + # 验证码类型配置 查看 LoginProperties 类 + code-type: arithmetic + # 登录图形验证码有效时间/分钟 + expiration: 2 + # 验证码高度 + width: 111 + # 验证码宽度 + heigth: 36 + # 内容长度 + length: 2 + # 字体名称,为空则使用默认字体 + font-name: + # 字体大小 + font-size: 25 diff --git a/nl-web-app/src/main/resources/config/application-prod.yml b/nl-web-app/src/main/resources/config/application-prod.yml index c71864a..82afbb9 100644 --- a/nl-web-app/src/main/resources/config/application-prod.yml +++ b/nl-web-app/src/main/resources/config/application-prod.yml @@ -55,18 +55,32 @@ spring: wall: config: multi-statement-allow: true + data: + redis: + #数据库索引 + database: 2 + host: 192.168.29.130 + port: 6379 + password: 123456 + +# IP 本地解析 +ip: + local-parsing: true # 文件存储路径 file: mac: path: ~/file/ qrcode: ~/qrcode/ + avatar: ~/avatar/ linux: path: /home/pi/nl_robot/map/ qrcode: /home/pi/nl_robot/qrcode/ + avatar: /home/pi/nl_robot/avatar/ windows: path: C:\eladmin\file\currentMap\ qrcode: C:\eladmin\qrcode\currentMap\ + avatar: C:\eladmin\avatar\ # 文件大小 /M maxSize: 100 avatarMaxSize: 5 @@ -78,7 +92,7 @@ sa-token: # token有效期,单位s 默认30天, -1代表永不过期 timeout: 2592000 # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 - activity-timeout: -1 + active-timeout: -1 # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) is-concurrent: true # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) diff --git a/nl-web-app/src/main/resources/config/application.yml b/nl-web-app/src/main/resources/config/application.yml index f9f3181..2bb8f68 100644 --- a/nl-web-app/src/main/resources/config/application.yml +++ b/nl-web-app/src/main/resources/config/application.yml @@ -7,7 +7,7 @@ spring: basename: language/task/task,language/error/error,language/buss/buss encoding: UTF-8 profiles: - active: prod + active: dev jackson: time-zone: GMT+8 @@ -30,7 +30,7 @@ customize: #密码加密传输,前端公钥加密,后端私钥解密 rsa: - private_key: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMjhH5OmC7osPfdelXwkX1uTW1vuj8miZIU546Y6dy7TI2RF04rcW2eneBqrvF/8Ni1b+A+bqAJfMi01TDBmdyp+7vyZzUPRXv02HpI/ZM9dkQhv2m4VnTNnWOM0mY/7fJtDfLXhfDNmBMz7h57oDUFV0ESQtp5i4K7hlIVeezijAgMBAAECgYBVuPQfruksPnsHGB7UhjUHQD/pYEmN8zXQQJ7sLeD0Y3ej78RRaq268xVm1Eij8V4xRyD5kCRHNtaTwj3MHb3V68QC3amBR392yay4+S5ZOEPOjZ64hMSZWPezHbemLMjtUn1NR1k1aGfaiGPEk3npiXJHf9ZXU2GGglLJ50eP+QJBAPD3TTRtOVuTIPQS+m0PEeW6ALZDp3EONoqOMePuGLqj38QjwV+jGdxzA+Hhsf8oQo+QG2S3YPph09TFZc3dvj0CQQDVaY9TGeDyxf2DDL/oBFecIkixkV/AWRJb9CrDCZ8H9K1xWuEmhIW1pFJ+gmjbZccZQe/n1M+tRKq9DPaXsiBfAkANgE27GkOUdfHquwV9BtMh5AIWNEQ1eW5k5QK2mqiYDIaFHtu+2Ayi5W7aQSMQANl54cEnK38riD+uNEE3/6yhAkAN3ZfkTFAjNd3sv81QI8gVatzSPKG9+4uH0etdVKiyeaEzNjZerEmLrat2cL6jUo+HApO1ukvr9AQr2EXFQVt9AkEAoQcTx50AK6osp15kAoOQH5NV7TF2qoDbkNfp4xJReLlNpn9oPh2CNQOuVfna5gDQmkaEaJwwVuBvWN5RPrp2HA== + private_key: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIMZaFRFRq8aS0CGAeyz+iR1sPUUuSyEtbIqyEhdY07Tk9z+iEkHc5wPiJWZ5ITkojRDOcD4qVh01z7kZ6pNC6gs2WpKG0foNF998cTlDRsro/O/ZnZgM+Amri3gYaN/atSoAQDwcgmEgzopyYFkm4y3nlE/Klv3wJEaJSATxe3DAgMBAAECgYAPIGeJ0FkothjNup35O7EBSPUglNdi5sh3j3kpjwujhO/QNYGbJOQhiHyi1QK+6gnkjDHbQrXOJ454dW6YAf4gqztPF+eTf2F+i4FOHwD4xS3MvlW4WIIqo+UrbbPLOX3ysikw42hd9fUh0GuI+1QSe1ia3CQsik7D3nPRY4/niQJBAMfLeRoiUImVJhl9FU2PFMRJFeqK/QiO5HxT3xf/XgW+sY2gmEE4+Sa+D/WVf5Ez25S2jjaW7rPlCSjhzx41fakCQQCn+rgHUbOW2qbzSUTsb14+pJNQUy0poWl8iChxCE5nMvdr+BdS413Nb2iXACJumi4/VZP2T3VUIY7i77C+FvuLAkEAx3QQbI+PGRplU5K0fp31HFLd5yxjmHSWEqvkDl/n7BJHzFxjQtFuoUeiRQe+tyUu81IfvM2GdN6T+1UZ4E2EKQJAMWrA2OZgPvD0TH4xmJzqzOL9s5PEpYqmzcwAmcAn0JRd1ZWWxvu8jMNJsaKIfqE9GcTDUqLtkWKN9pUtGb8JIQJBALj9byua7l6wI2YcPxau9I6q1LO7zsjOn+tW9shwoDPkLwOz34dIFhPiEyUQWO+Kl3nMUlsgY3AmTaNIH9O+7AQ= # sa-token白名单配置 security: @@ -45,10 +45,12 @@ security: - /vehicle/** - /webSocket/** - /file/** + - /qrcode/** - /routeInfo/** - /station/** # 静态资源 - /*.html - /**/*.html - /**/*.css - - /**/*.js \ No newline at end of file + - /**/*.js + - /**/*.png \ No newline at end of file diff --git a/pom.xml b/pom.xml index 23d43ed..4d60669 100644 --- a/pom.xml +++ b/pom.xml @@ -167,6 +167,58 @@ 2.12.0 + + org.redisson + redisson-spring-boot-starter + 3.16.4 + + + + io.github.eternalstone + captcha-spring-boot-starter + 3.0.0 + + + + + com.github.oshi + oshi-core + 6.4.4 + + + + + nl.basjes.parse.useragent + yauaa + 5.23 + + + + commons-beanutils + commons-beanutils-core + 1.8.0 + + + + + cn.dev33 + sa-token-jwt + 1.37.0 + + + + com.alicp.jetcache + jetcache-starter-redis + 2.5.14 + + + + + org.springframework.boot + spring-boot-starter-cache + ${spring-boot.version} + + cn.hutool