diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..5eb155f --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +.idea/* +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 0000000..59b5ef2 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + + com.intelligentHealthCare + IntelligentHealthCare + 1.0-SNAPSHOT + + + com.intelligentHealthCare + api + jar + + + 8 + 8 + UTF-8 + + + + + + org.springframework.boot + spring-boot-devtools + true + true + + + + + + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + com.intelligentHealthCare + feign-api + 1.0-SNAPSHOT + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + com.github.penggle + kaptcha + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + com.intelligentHealthCare.ApiApplication + ZIP + + + + + + repackage + + + + + + + diff --git a/api/src/main/java/com/intelligentHealthCare/ApiApplication.java b/api/src/main/java/com/intelligentHealthCare/ApiApplication.java new file mode 100644 index 0000000..af6a09d --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/ApiApplication.java @@ -0,0 +1,185 @@ +package com.intelligentHealthCare; + +import com.intelligentHealthCare.annotation.NoAuth; +import com.intelligentHealthCare.config.CommonAppProperty; +import com.intelligentHealthCare.config.DefaultFeignConfiguration; +import com.intelligentHealthCare.remote.ApiServiceRemote; +import com.intelligentHealthCare.security.UrlMethodAccessDecision; +import com.querydsl.core.util.ArrayUtils; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.util.ClassUtils; +import org.springframework.web.bind.annotation.*; + +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +@SpringBootApplication +@EnableDiscoveryClient +@RefreshScope +@EnableAspectJAutoProxy +@Slf4j +@EnableFeignClients(basePackages = {"com.intelligentHealthCare"}, defaultConfiguration = {DefaultFeignConfiguration.class}) +@EnableCaching +public class ApiApplication { + private final static String BASE_PACKAGE = "com.intelligentHealthCare.api.controller"; + private final static String RESOURCE_PATTERN = "/**/*.class"; + + + + public static void main(String[] args) throws ClassNotFoundException { + ApplicationContext context = SpringApplication.run(ApiApplication.class, args); + ApiServiceRemote apiServiceRemote = context.getBean(ApiServiceRemote.class); + UrlMethodAccessDecision urlMethodAccessDecision = context.getBean(UrlMethodAccessDecision.class); + CommonAppProperty commonAppProperty = context.getBean(CommonAppProperty.class); + init(apiServiceRemote, urlMethodAccessDecision, commonAppProperty); + } + + public static void init(ApiServiceRemote apiServiceRemote, UrlMethodAccessDecision urlMethodAccessDecision, CommonAppProperty commonAppProperty) { + //spring工具类,可以获取指定路径下的全部类 + ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN; + List resultApi = apiServiceRemote.getAll(); + LinkedList apis = new LinkedList<>(); + LinkedList noAuthApis = new LinkedList<>(); + try { + Resource[] resources = resourcePatternResolver.getResources(pattern); + //MetadataReader 的工厂类 + MetadataReaderFactory readerfactory = new CachingMetadataReaderFactory(resourcePatternResolver); + for (Resource resource : resources) { + //用于读取类信息 + MetadataReader reader = readerfactory.getMetadataReader(resource); + //扫描到的class + String classname = reader.getClassMetadata().getClassName(); + Class clazz = Class.forName(classname); + //判断是否有指定主解 + RequestMapping annotation = clazz.getAnnotation(RequestMapping.class); + Api apiAnnotation = clazz.getAnnotation(Api.class); + String prefixUrl = ""; + String prefixName = ""; + if (annotation != null) { + prefixUrl = annotation.value()[0].replace("${app.baseService}", commonAppProperty.getBaseService()); + } + if (apiAnnotation != null) { + prefixName = apiAnnotation.tags()[0]; + } + if (prefixName.equals("") && prefixName.equals("")) { + continue; + } + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + AtomicBoolean checkSameMethod = new AtomicBoolean(false); + com.intelligentHealthCare.entity.Api api = new com.intelligentHealthCare.entity.Api(); + Operation operation = method.getAnnotation(Operation.class); + PostMapping postMapping = method.getAnnotation(PostMapping.class); + DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class); + PutMapping putMapping = method.getAnnotation(PutMapping.class); + GetMapping getMapping = method.getAnnotation(GetMapping.class); + NoAuth noAuth = method.getAnnotation(NoAuth.class); + if (operation == null) { + continue; + } + api.setName(prefixName + "-" + operation.summary()); + if (postMapping != null) { + if (!ArrayUtils.isEmpty(postMapping.value())) { + api.setRest(prefixUrl + postMapping.value()[0]); + } else { + api.setRest(prefixUrl); + } + api.setMethod("POST"); + } + if (deleteMapping != null) { + if (!ArrayUtils.isEmpty(deleteMapping.value())) { + api.setRest(prefixUrl + deleteMapping.value()[0]); + } else { + api.setRest(prefixUrl); + } + api.setMethod("DELETE"); + } + if (putMapping != null) { + if (!ArrayUtils.isEmpty(putMapping.value())) { + api.setRest(prefixUrl + putMapping.value()[0]); + } else { + api.setRest(prefixUrl); + } + api.setMethod("PUT"); + } + if (getMapping != null) { + if (!ArrayUtils.isEmpty(getMapping.value())) { + api.setRest(prefixUrl + getMapping.value()[0]); + } else { + api.setRest(prefixUrl); + } + api.setMethod("GET"); + } + if (noAuth != null) { + noAuthApis.add(api.getRest()); + continue; + } + resultApi.forEach(i -> { + //相同菜单 + if (i.getName().equals(api.getName()) && i.getRest().equals(api.getRest()) && i.getMethod().equals(api.getMethod())) { + checkSameMethod.set(true); + return; + } + //方法和名称相同但是api路径不相同的api,更新api路径 + if (i.getName().equals(api.getName()) && !i.getRest().equals(api.getRest()) && i.getMethod().equals(api.getMethod())) { + api.setId(i.getId()); + return; + } + //名称相同,路径不同,方法不同,更新路径和方法 + if (i.getName().equals(api.getName()) && !i.getRest().equals(api.getRest()) && !i.getMethod().equals(api.getMethod())) { + api.setId(i.getId()); + return; + } + //路径相同,方法相同,名称不同,更新名称 + if (!i.getName().equals(api.getName()) && i.getRest().equals(api.getRest()) && i.getMethod().equals(api.getMethod())) { + api.setId(i.getId()); + return; + } + //路径相同,名称相同,方法不同,更新方法 + if (i.getName().equals(api.getName()) && i.getRest().equals(api.getRest()) && !i.getMethod().equals(api.getMethod())) { + api.setId(i.getId()); + return; + } + + }); + if (checkSameMethod.get()) { + continue; + } + + if (api.getMethod() != null && api.getName() != null && api.getRest() != null) { + apis.add(api); + } + } + } + log.info("所有的api信息" + resultApi); + log.info("需要认证且未添加到数据库API" + apis); + log.info("无需认证API路径" + noAuthApis); + urlMethodAccessDecision.setAnonymousUrls(noAuthApis); + if (!apis.isEmpty()) { + apiServiceRemote.batchSave(apis); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/annotation/NoAuth.java b/api/src/main/java/com/intelligentHealthCare/annotation/NoAuth.java new file mode 100644 index 0000000..12a4932 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/annotation/NoAuth.java @@ -0,0 +1,14 @@ +package com.intelligentHealthCare.annotation; + +import java.lang.annotation.*; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/10/4 17:48 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface NoAuth { +} diff --git a/api/src/main/java/com/intelligentHealthCare/aop/SystemLogAop.java b/api/src/main/java/com/intelligentHealthCare/aop/SystemLogAop.java new file mode 100644 index 0000000..8a87c39 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/aop/SystemLogAop.java @@ -0,0 +1,125 @@ +package com.intelligentHealthCare.aop; + +import com.alibaba.fastjson.JSON; +import com.intelligentHealthCare.annotation.NoAuth; +import com.intelligentHealthCare.entity.SystemLog; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.SystemLogServiceRemote; +import com.intelligentHealthCare.security.SecurityUser; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.URLDecoder; +import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/10/22 08:50 + */ +@Aspect +@Component +@Slf4j +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +public class SystemLogAop { + + private final HttpServletRequest request; + + private final SystemLogServiceRemote systemLogServiceRemote; + + private SystemLog systemLog; + @Before("execution(* com.intelligentHealthCare.api.controller..*(..))") + public void beforeMethodExecution(JoinPoint joinPoint) throws UnsupportedEncodingException { + Object[] args = joinPoint.getArgs(); + Object target = joinPoint.getTarget(); + Class targetClass = target.getClass(); + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + // 获取类上的注解信息 + Api api = targetClass.getAnnotation(Api.class); + Operation operation = method.getAnnotation(Operation.class); + NoAuth noAuth = method.getAnnotation(NoAuth.class); + String requestURI = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8.toString()); + String requestMethod = request.getMethod(); + String userIP = getClientIp(request); + SecurityUser securityUser = null; + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if(authentication != null && authentication.getPrincipal() instanceof SecurityUser){ + securityUser = (SecurityUser) authentication.getPrincipal(); + } + systemLog = SystemLog.builder().userIp(userIP).method(requestMethod).moudle(api.tags()[0]) + .operation(operation.summary()).url(requestURI).param(Arrays.toString(args)) + .accountId(securityUser == null ? "未知用户" : securityUser.getAccount().getId()) + .nickName(securityUser == null ? "未知用户" : securityUser.getAccount().getNickname()) + .isDangerous(userIP == null || (securityUser == null && noAuth == null)).account(securityUser == null ? "" : securityUser.getAccount().getUsername()).build(); + } + + + @AfterReturning(pointcut = "execution(* com.intelligentHealthCare.api.controller..*(..))", returning = "returnValue") + public void afterMethodExecution(JoinPoint joinPoint, Object returnValue) { + systemLog.setIsSuccess(true); + Result result = null; + if(returnValue instanceof Result) { + result = (Result) returnValue; + } + if(result != null) { + result.setStatus(ResultCodeEnum.SUCCESS); + } + systemLog.setResult(JSON.toJSONString(result)); + systemLogServiceRemote.saveSystemLog(systemLog); + } + + @AfterThrowing(pointcut = "execution(* com.intelligentHealthCare.api.controller..*(..))", throwing = "exception") + public void afterMethodException(JoinPoint joinPoint, Throwable exception) { + systemLog.setIsSuccess(false); + systemLog.setResult(exception.getMessage()); + systemLogServiceRemote.saveSystemLog(systemLog); + } + + public String getClientIp(HttpServletRequest request) { + String ipAddress = request.getHeader("X-Forwarded-For"); + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + if (ipAddress.equals("127.0.0.1")) { + // 根据网卡取本机配置的IP + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + ipAddress = inet.getHostAddress(); + } + } + // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照","分割 + if (ipAddress != null && ipAddress.length() > 15) { + if (ipAddress.indexOf(",") > 0) { + ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); + } + } + return ipAddress; + } + +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/AccountController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/AccountController.java new file mode 100644 index 0000000..46b42a8 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/AccountController.java @@ -0,0 +1,61 @@ +package com.intelligentHealthCare.api.controller; + +import com.intelligentHealthCare.annotation.NoAuth; +import com.intelligentHealthCare.dto.AccountDto; +import com.intelligentHealthCare.entity.Account; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.security.SecurityUser; +import com.intelligentHealthCare.service.impl.AccountHandle; +import com.intelligentHealthCare.vo.AccountVo; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("/${app.baseService}/account") +@Api(tags = "账号管理") +public class AccountController { + @Autowired + private AccountHandle accountHandle; + + @PostMapping("/register") + @Operation(summary = "账号注册") + @NoAuth + public Result register(@RequestBody Account account){ + return Result.builder().data(accountHandle.register(account)).build(); + } + + + @PostMapping("/login") + @Operation(summary = "登录") + @NoAuth + public Result login(@RequestBody AccountVo accountVo, HttpServletRequest httpServletRequest){ + Account account = new Account(); + BeanUtils.copyProperties(accountVo, account); + return Result.builder().data(accountHandle.login(account, accountVo.getCode(), httpServletRequest.getRemoteAddr())).status(ResultCodeEnum.SUCCESS).build(); + } + + @PostMapping("/logout") + @Operation(summary = "退出登录") + @NoAuth + public Result logout(){ + return Result.builder().data(accountHandle.logout()).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/getAccountInfo") + @Operation(summary = "获取当前账号信息") + @NoAuth + public Result getAccountInfo() { + SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + AccountDto accountDto = new AccountDto(); + BeanUtils.copyProperties(securityUser.getAccount(), accountDto); + return Result.builder().data(accountDto).status(ResultCodeEnum.SUCCESS).build(); + } + +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/CommonStaticFileControllerTest.java b/api/src/main/java/com/intelligentHealthCare/api/controller/CommonStaticFileControllerTest.java new file mode 100644 index 0000000..abc612c --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/CommonStaticFileControllerTest.java @@ -0,0 +1,71 @@ +package com.intelligentHealthCare.api.controller; + +import com.intelligentHealthCare.config.CommonAppProperty; +import com.intelligentHealthCare.entity.CommonStaticFile; +import com.intelligentHealthCare.pojo.BaseFile; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.CommonStaticFileRemoteService; +import feign.Response; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotNull; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/11/14 14:18 + */ +@RestController +@Api(tags = "公共静态资源文件管理") +@RequestMapping("/${app.baseService}/commonStaticFile") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +public class CommonStaticFileControllerTest { + private final CommonStaticFileRemoteService commonStaticFileRemoteService; + + private final CommonAppProperty commonAppProperty; + + @PostMapping + @Operation(summary = "保存实体") + public Result save(@RequestBody CommonStaticFile commonStaticFile){ + return Result.builder().data(commonStaticFileRemoteService.save(commonStaticFile)).build(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除实体") + public Result delete(@PathVariable("id") String id){ + return Result.builder().data(commonStaticFileRemoteService.delete(id)).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "查询实体根据id") + public Result getById(@PathVariable("id") String id){ + return Result.builder().data(commonStaticFileRemoteService.getById(id)).build(); + } + + @GetMapping("/loadStaticFile/**") + @Operation(summary = "下载静态资源文件") + public ResponseEntity loadStaticFile(HttpServletRequest httpServletRequest, @RequestParam("filename") String filename){ + String requestURI = httpServletRequest.getRequestURI(); + String replace = requestURI.replace("/"+ commonAppProperty.getBaseService() + "/commonStaticFile/loadStaticFile/", ""); + ResponseEntity responseEntity = commonStaticFileRemoteService.loadStaticFile(replace); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.addAll(responseEntity.getHeaders()); + httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=" + filename); + return ResponseEntity.ok().headers(httpHeaders).body((Resource) responseEntity.getBody()); + } + + @PostMapping(path = "/saveStaticFile") + @Operation(summary = "保存静态资源文件") + public Result saveStaticFile(@NotNull(message = "文件不能为空")MultipartFile file){ + return Result.builder().data(commonStaticFileRemoteService.saveStaticFile(file)).build(); + } +} + diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/KaptchaController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/KaptchaController.java new file mode 100644 index 0000000..a023e4d --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/KaptchaController.java @@ -0,0 +1,73 @@ +package com.intelligentHealthCare.api.controller; + +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.intelligentHealthCare.annotation.NoAuth; +import com.intelligentHealthCare.exception.BizException; +import com.intelligentHealthCare.utils.RedisCache; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.imageio.ImageIO; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.util.concurrent.TimeUnit; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/10/31 22:49 + */ +@Controller +@RequestMapping("/${app.baseService}/kaptcha") +@Api(tags = "验证码管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@Slf4j +public class KaptchaController { + + private final DefaultKaptcha defaultKaptcha; + + private final RedisCache redisCache; + @GetMapping("/getCodeImg/*") + @Operation(summary = "获取验证码") + @NoAuth + public void img(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws Exception { + byte[] captchaChallengeAsJpeg = null; + ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); + try { + String createText = defaultKaptcha.createText(); + // 生产验证码字符串并保存到 Redis 中,ip-rightCode,有效期为 10 分钟 + String ip = httpServletRequest.getRemoteAddr(); + log.info("ip:" + ip + ",rightCode = " + createText); + redisCache.setCacheObject(ip, createText, 10, TimeUnit.MINUTES); + // 使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中 + BufferedImage challenge = defaultKaptcha.createImage(createText); + ImageIO.write(challenge, "jpg", jpegOutputStream); + } catch (IllegalArgumentException e) { + httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + // 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组 + captchaChallengeAsJpeg = jpegOutputStream.toByteArray(); + httpServletResponse.setHeader("Cache-Control", "no-store"); + httpServletResponse.setHeader("Pragma", "no-cache"); + httpServletResponse.setDateHeader("Expires", 0); + httpServletResponse.setContentType("image/jpeg"); + ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream(); + responseOutputStream.write(captchaChallengeAsJpeg); + responseOutputStream.flush(); + responseOutputStream.close(); + } + +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/client/ArticleController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/client/ArticleController.java new file mode 100644 index 0000000..584f5ec --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/client/ArticleController.java @@ -0,0 +1,75 @@ +package com.intelligentHealthCare.api.controller.client; + +import com.intelligentHealthCare.config.CommonAppProperty; +import com.intelligentHealthCare.entity.Article; +import com.intelligentHealthCare.pojo.BaseFile; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.ArticleServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotNull; + +/** + * @author deng + * @version 1.0 + * @date Created in 2024/4/27 09:58 + */ +@RestController +@Api(tags = "文章管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/article") +public class ArticleController { + private final ArticleServiceRemote articleServiceRemote; + + private final CommonAppProperty commonAppProperty; + + @PostMapping + @Operation(summary = "保存实体") + public Result
save(@RequestBody Article article) { + return Result.
builder().data(articleServiceRemote.save(article)).build(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除实体") + public Result delete(@PathVariable("id") String id) { + return Result.builder().data(articleServiceRemote.delete(id)).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "查询实体根据id") + public Result
getById(@PathVariable("id") String id) { + return Result.
builder().data(articleServiceRemote.getById(id)).build(); + } + + @GetMapping("/loadStaticFile/**") + @Operation(summary = "下载静态资源文件") + public ResponseEntity loadStaticFile(HttpServletRequest httpServletRequest) { + String requestURI = httpServletRequest.getRequestURI(); + String replace = requestURI.replace("/" + commonAppProperty.getBaseService() + "/article/loadStaticFile/", ""); + ResponseEntity responseEntity = articleServiceRemote.loadStaticFile(replace); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.addAll(responseEntity.getHeaders()); + return ResponseEntity.ok().headers(httpHeaders).body((Resource) responseEntity.getBody()); + } + + @PostMapping(path = "/saveStaticFile") + @Operation(summary = "保存静态资源文件") + public Result saveStaticFile(@RequestBody @NotNull(message = "文件不能为空") MultipartFile file) { + return Result.builder().data(articleServiceRemote.saveStaticFile(file)).build(); + } + + @PostMapping(path = "/uploadVideo") + @Operation(summary = "上传视频") + public Result uploadVideo(@RequestBody @NotNull(message = "文件不能为空") MultipartFile file) { + return Result.builder().data(articleServiceRemote.saveStaticFile(file)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/organization/DepartmentController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/DepartmentController.java new file mode 100644 index 0000000..9e0e812 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/DepartmentController.java @@ -0,0 +1,66 @@ +package com.intelligentHealthCare.api.controller.organization; +import com.intelligentHealthCare.condition.StaffCondition; +import com.intelligentHealthCare.dto.StaffDto; +import com.intelligentHealthCare.entity.Department; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.DepartmentRemote; +import com.intelligentHealthCare.remote.StaffServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@Api(tags = "部门管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/department") +public class DepartmentController { + private final DepartmentRemote departmentRemote; + + private final StaffServiceRemote staffServiceRemote; + + @GetMapping + @Operation(summary = "获取全部部门") + public Result getall(@RequestParam("departmentCondition") String departmentName){ + List getall = departmentRemote.getall(departmentName); + return Result.builder().data(getall).build(); + } + + @PostMapping("/add") + @Operation(summary = "插入部门") + public Result add(@RequestBody Department department){ + departmentRemote.add(department); + return Result.builder().data("成功").build(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除部门") + public Result deleteByid(@PathVariable("id") String id){ + String s = departmentRemote.deleteByid(id); + return Result.builder().data(s).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "回显部门") + public Result echoData(@PathVariable("id") String id){ + Department department = departmentRemote.echoData(id); + return Result.builder().data(department).build(); + } + + @PutMapping + @Operation(summary = "修改部门") + public Result update(@RequestBody Department department){ + return Result.builder().data(departmentRemote.update(department)).build(); + } + + @PostMapping("/getDepartmentStaffTree") + @Operation(summary = "获取部门员工数据树形结构") + public Result> getDepartmentStaffTree(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(departmentRemote.getDepartmentStaffTree(conditionAndPageInfo)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/organization/OfficeController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/OfficeController.java new file mode 100644 index 0000000..cf31f9e --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/OfficeController.java @@ -0,0 +1,62 @@ +package com.intelligentHealthCare.api.controller.organization; + +import com.intelligentHealthCare.dto.OfficeDto; +import com.intelligentHealthCare.entity.Department; +import com.intelligentHealthCare.entity.Office; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.DepartmentRemote; +import com.intelligentHealthCare.remote.OfficeServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@Api(tags = "职务管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/office") +public class OfficeController { + private final OfficeServiceRemote officeServiceRemote; + + private final DepartmentRemote departmentRemote; + + @GetMapping("/getTree") + @Operation(summary = "获取职务信息") + public Result getTree(){ + List getTree = officeServiceRemote.getTree(); + return Result.builder().data(getTree).build(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "根据Id删除数据") + public Result deleteById(@PathVariable("id") String officeId){ + return Result.builder().data(officeServiceRemote.delete(officeId)).build(); + } + + @PostMapping("/saveOfficeAndDepartmentOffice") + @Operation(summary = "保存实体并保存与部门关系") + public Result saveOfficeAndDepartmentOffice(@RequestBody OfficeDto officeDto){ + return Result.builder().data(officeServiceRemote.saveOfficeAndDepartmentOffice(officeDto)).build(); + } + + @GetMapping("/getDepartmentsTree") + @Operation(summary = "获取部门树") + public Result> getDepartmentsTree(){ + return Result.>builder().data(departmentRemote.getall("")).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "获取职务通过id") + public Result getById(@PathVariable("id")String id){ + return Result.builder().data(officeServiceRemote.getById(id)).build(); + } + + @PutMapping("/update") + @Operation(summary = "修改实体") + public Result updateDto(@RequestBody OfficeDto officeDto){ + return Result.builder().data(officeServiceRemote.updateDto(officeDto)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/organization/StaffBatchOperationController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/StaffBatchOperationController.java new file mode 100644 index 0000000..8c49fb7 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/StaffBatchOperationController.java @@ -0,0 +1,96 @@ +package com.intelligentHealthCare.api.controller.organization; + +import com.intelligentHealthCare.condition.KeywordCondition; +import com.intelligentHealthCare.config.CommonAppProperty; +import com.intelligentHealthCare.dto.StaffDto; +import com.intelligentHealthCare.entity.Office; +import com.intelligentHealthCare.entity.Role; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.CommonStaticFileRemoteService; +import com.intelligentHealthCare.remote.OfficeServiceRemote; +import com.intelligentHealthCare.remote.RoleServiceRemote; +import com.intelligentHealthCare.remote.StaffServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/12/14 15:22 + */ +@RestController +@Api(tags = "批量添加员工") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/staffBatchOperation") +public class StaffBatchOperationController { + private final StaffServiceRemote staffServiceRemote; + + private final RoleServiceRemote roleServiceRemote; + + private final OfficeServiceRemote officeServiceRemote; + + private final CommonAppProperty commonAppProperty; + + private final CommonStaticFileRemoteService commonStaticFileRemoteService; + @PostMapping("/batchAdd") + @Operation(summary = "批量添加员工") + public Result> batchAdd(@RequestBody List staffDto){ + staffDto.forEach(i -> { + //加密密码 + if(StringUtils.hasText(i.getStaffPassword())) { + i.setStaffPassword(new BCryptPasswordEncoder().encode(i.getStaffPassword())); + } + }); + return Result.>builder().data(staffServiceRemote.batchAddStaff(staffDto)).build(); + } + + @PostMapping("/checkBatchStaff") + @Operation(summary = "检查员工是否允许添加") + public Result> checkBatchStaff(@RequestBody List staffDtos){ + return Result.>builder().data(staffServiceRemote.checkBatchStaff(staffDtos)).build(); + } + + @PostMapping("/getRolePage") + @Operation(summary = "获取角色信息分页") + public Result> page(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(roleServiceRemote.getFilterList(conditionAndPageInfo)).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/existSameAccount/{account}") + @Operation(summary = "检查是否存在相同账号") + public Result existSameAccount(@PathVariable("account")String account){ + return Result.builder().data(staffServiceRemote.existSameAccount(account)).build(); + } + + @GetMapping("/getOfficeTree") + @Operation(summary = "获取职务信息") + public Result> getTree(){ + return Result.>builder().data(officeServiceRemote.getTree()).build(); + } + + @GetMapping("/downloadStaffImportFile/**") + @Operation(summary = "下载员工导入文件") + public ResponseEntity loadStaticFile(HttpServletRequest httpServletRequest, @RequestParam("filename") String filename){ + String requestURI = httpServletRequest.getRequestURI(); + String replace = requestURI.replace("/"+ commonAppProperty.getBaseService() + "/staffBatchOperation/downloadStaffImportFile/", ""); + return commonStaticFileRemoteService.loadStaticFile(replace); +// HttpHeaders httpHeaders = new HttpHeaders(); +// httpHeaders.addAll(responseEntity.getHeaders()); +// httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=" + filename); +// return ResponseEntity.ok().headers(httpHeaders).body((Resource) responseEntity.getBody()); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/organization/StaffController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/StaffController.java new file mode 100644 index 0000000..021d84a --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/organization/StaffController.java @@ -0,0 +1,102 @@ +package com.intelligentHealthCare.api.controller.organization; + +import com.intelligentHealthCare.condition.KeywordCondition; +import com.intelligentHealthCare.condition.StaffCondition; +import com.intelligentHealthCare.dto.StaffDto; +import com.intelligentHealthCare.entity.Office; +import com.intelligentHealthCare.entity.Role; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.OfficeServiceRemote; +import com.intelligentHealthCare.remote.OfficeStaffServiceRemote; +import com.intelligentHealthCare.remote.RoleServiceRemote; +import com.intelligentHealthCare.remote.StaffServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.security.core.parameters.P; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author deng + * @version 1.0 + * @date Created in 2023/11/17 11:45 + */ +@RestController +@Api(tags = "员工管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/staff") +public class StaffController { + + private final OfficeStaffServiceRemote officeStaffServiceRemote; + + private final OfficeServiceRemote officeServiceRemote; + + private final RoleServiceRemote roleServiceRemote; + + private final StaffServiceRemote staffServiceRemote; + + @PostMapping("/page") + @Operation(summary = "获取人员信息分页") + public Result> getStaffDtoPage(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(staffServiceRemote.getStaffDtoPage(conditionAndPageInfo)).build(); + } + @GetMapping("/getOfficeTree") + @Operation(summary = "获取职务信息") + public Result> getTree(){ + return Result.>builder().data(officeServiceRemote.getTree()).build(); + } + + @PostMapping("/getRolePage") + @Operation(summary = "获取角色信息分页") + public Result> page(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(roleServiceRemote.getFilterList(conditionAndPageInfo)).status(ResultCodeEnum.SUCCESS).build(); + } + + @PostMapping("/saveStaffAndOffice") + @Operation(summary = "保存员工并且保存和职务的关系") + public Result saveStaffAndOffice(@RequestBody StaffDto staffDto){ + //加密密码 + if(StringUtils.hasText(staffDto.getStaffPassword())) { + staffDto.setStaffPassword(new BCryptPasswordEncoder().encode(staffDto.getStaffPassword())); + } + return Result.builder().data(staffServiceRemote.saveStaffAndOffice(staffDto)).build(); + } + + @GetMapping("/getStaff/{id}") + @Operation(summary = "根据id获取员工信息") + public Result findByIdDto(@PathVariable("id")String id){ + return Result.builder().data(staffServiceRemote.findByIdDto(id)).build(); + } + + @PutMapping("/updateStaff") + @Operation(summary = "修改员工信息") + public Result updateStaffDto(@RequestBody StaffDto staffDto){ + return Result.builder().data(staffServiceRemote.updateStaffDto(staffDto)).build(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除员工") + public Result deleteById(@PathVariable("id")String id){ + return Result.builder().data(staffServiceRemote.delete(id)).build(); + } + + @GetMapping("/existSameAccount/{account}") + @Operation(summary = "检查是否存在相同账号") + public Result existSameAccount(@PathVariable("account")String account){ + return Result.builder().data(staffServiceRemote.existSameAccount(account)).build(); + } + + @GetMapping("/updateAccountEnabledStatus/{account}/{accountEnabledStatus}") + @Operation(summary = "修改账号启用状态") + public Result updateAccountEnabledStatus(@PathVariable("account") String account, @PathVariable("accountEnabledStatus") Boolean accountEnabledStatus){ + return Result.builder().data(staffServiceRemote.updateAccountEnabledStatus(account, accountEnabledStatus)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/personnel/VolunteerController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/personnel/VolunteerController.java new file mode 100644 index 0000000..2055f02 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/personnel/VolunteerController.java @@ -0,0 +1,149 @@ +package com.intelligentHealthCare.api.controller.personnel; + +import com.intelligentHealthCare.condition.KeywordCondition; +import com.intelligentHealthCare.condition.VolunteerCondition; +import com.intelligentHealthCare.condition.workflow.HistoryTaskCondition; +import com.intelligentHealthCare.condition.workflow.TaskCondition; +import com.intelligentHealthCare.constant.ProcessConstant; +import com.intelligentHealthCare.dto.VolunteerDto; +import com.intelligentHealthCare.dto.workflow.BaseWorkflowDto; +import com.intelligentHealthCare.dto.workflow.HistoricTaskDTO; +import com.intelligentHealthCare.dto.workflow.TaskDto; +import com.intelligentHealthCare.entity.Volunteer; +import com.intelligentHealthCare.enums.VolunteerAuditStatus; +import com.intelligentHealthCare.exception.BizException; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.RemoteVolunteerService; +import com.intelligentHealthCare.remote.workflow.WorkflowServiceRemote; +import com.intelligentHealthCare.security.SecurityUser; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.activiti.api.process.model.ProcessInstance; +import org.activiti.api.task.model.Task; +import org.activiti.engine.history.HistoricTaskInstance; +import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntityImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.util.ObjectUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author yang + * @version 1.0 + * @date Created in 2024/1/23 21:32 + * @description 志愿者管理 + */ +@RestController +@RequestMapping("/${app.baseService}/volunteer") +@Api(tags = "志愿者管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +public class VolunteerController { + + private final RemoteVolunteerService remoteVolunteerService; + + private final WorkflowServiceRemote workflowServiceRemote; + + @Operation(summary = "保存实体") + @PostMapping + public Result save(@RequestBody VolunteerDto volunteerDto){ + return Result.builder().data(remoteVolunteerService.saveDto(volunteerDto)).build(); + } + + @Operation(summary = "修改实体") + @PutMapping + public Result update(@RequestBody VolunteerDto volunteerDto){ + return Result.builder().data(remoteVolunteerService.updateDto(volunteerDto)).build(); + } + + @Operation(summary = "获取志愿者信息分页") + @PostMapping("/page") + public Result> page(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + //查询当前用户的所有任务 + SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + List tasks = workflowServiceRemote.getTasks(TaskCondition.builder().assignee(securityUser.getUsername()).build()); + conditionAndPageInfo.getCondition().setProcessInstanceId(tasks.stream().map(Task::getProcessInstanceId).collect(Collectors.toList())); + Page filterListDto = remoteVolunteerService.getFilterListDto(conditionAndPageInfo); + filterListDto.forEach(v -> { + tasks.forEach(t ->{ + if(!ObjectUtils.isEmpty(v.getProcessInstanceId()) && v.getProcessInstanceId().equals(t.getProcessInstanceId())){ + v.setIsAudit(true); + v.setTaskId(t.getId()); + } + }); + }); + return Result.>builder().data(filterListDto).build(); + } + + @GetMapping("/startVolunteerAccountApplyAudit/{volunteerId}") + @Operation(summary = "启动志愿者账号申请审核") + public Result startVolunteerAccountApplyAudit(@PathVariable("volunteerId") String volunteerId){ + //获取志愿者信息 + VolunteerDto volunteerDto = remoteVolunteerService.getByIdDto(volunteerId); + if(ObjectUtils.isEmpty(volunteerDto)){ + throw new BizException("志愿者信息不存在"); + } + //设置流程启动信息(创建人,业务数据id,流程Key) + HashMap variables = new HashMap<>(); + variables.put("draft", volunteerDto.getCreateBy()); + BaseWorkflowDto baseWorkflowDto = BaseWorkflowDto.builder().variables(variables).businessKey(volunteerDto.getId()).processDefineKey(ProcessConstant.VOLUNTEER_ACCOUNT_APPLY_AUDIT).build(); + ProcessInstance processInstance = workflowServiceRemote.startWorkflow(baseWorkflowDto); + //获取起草人任务节点 + List tasks = workflowServiceRemote.getTasks(TaskCondition.builder().businessKey(volunteerDto.getId()).assignee(volunteerDto.getCreateBy()).build()); + //完成起草人任务节点 + workflowServiceRemote.completeTask(TaskDto.builder().taskId(tasks.get(0).getId()).build()); + //更新审核状态 + volunteerDto.setAuditStatus(VolunteerAuditStatus.AUDIT); + volunteerDto.setProcessInstanceId(processInstance.getId()); + volunteerDto.setProcessDefineKey(processInstance.getProcessDefinitionKey()); + remoteVolunteerService.updateDto(volunteerDto); + return Result.builder().data(processInstance).build(); + } + @GetMapping("/getProcess/{processId}") + @Operation(summary = "获取流程图") + public ResponseEntity getProcess(@PathVariable("processId") String processId) { + ResponseEntity process = workflowServiceRemote.getProcess(processId); + return process; + } + + @PostMapping("/getHistories") + @Operation(summary = "获取历史记录") + public Result> getHistoryTask(@RequestBody HistoryTaskCondition historyTaskCondition){ + return Result.>builder().data(workflowServiceRemote.getHistoryTask(historyTaskCondition)).build(); + } + + @Operation(summary = "完成任务") + @PostMapping("/completeTask") + public Result completeTask(@RequestBody TaskDto taskDto){ + Boolean completeTask = workflowServiceRemote.completeTask(taskDto); + //获取业务数据 + VolunteerDto volunteerDto = remoteVolunteerService.getByIdDto(taskDto.getBusinessKey()); + //获取该业务数据的任务信息 + List historyTask = workflowServiceRemote.getHistoryTask(HistoryTaskCondition.builder().businessKey(volunteerDto.getId()).build()); + if(!historyTask.isEmpty()){ + //查看审核是否被退回,退回则修改业务数据状态 + if(historyTask.get(historyTask.size() - 1).getName().equals(historyTask.get(0).getName())){ + //审核被退回 + volunteerDto.setAuditStatus(VolunteerAuditStatus.AUDIT_BACK); + }else{ + volunteerDto.setAuditStatus(VolunteerAuditStatus.AUDIT); + } + remoteVolunteerService.updateDto(volunteerDto); + } + return Result.builder().data(completeTask).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "根据志愿者id获取志愿者信息") + public Result getVolunteerById(@PathVariable("id")String id){ + return Result.builder().data(remoteVolunteerService.getByIdDto(id)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/system/MenuController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/system/MenuController.java new file mode 100644 index 0000000..9b0c50a --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/system/MenuController.java @@ -0,0 +1,86 @@ +package com.intelligentHealthCare.api.controller.system; + +import com.intelligentHealthCare.annotation.NoAuth; +import com.intelligentHealthCare.dto.MenuDto; +import com.intelligentHealthCare.entity.Menu; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.MenuServiceRemote; +import com.intelligentHealthCare.security.SecurityUser; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/9/27 21:58 + */ +@RestController +@Api(tags = "菜单管理") +@RequestMapping("/${app.baseService}/menu") +public class MenuController { + @Autowired + private MenuServiceRemote menuServiceRemote; + + @Operation(summary = "根据账号id获取菜单树") + @GetMapping("/tree/getMenuTreeByAccountId") + @NoAuth + public Result> getMenuTreeByAccountId(){ + SecurityUser securityUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return Result.>builder().data(menuServiceRemote.getMenuTreeByAccountId(securityUser.getAccount().getId())).status(ResultCodeEnum.SUCCESS).build(); + } + + @Operation(summary = "获取菜单树") + @GetMapping("/tree/getMenuTree") + public Result> getMenuTree(){ + return Result.>builder().data(menuServiceRemote.getMenuTree()).status(ResultCodeEnum.SUCCESS).build(); + } + + @Operation(summary = "添加菜单") + @PostMapping + public Result add(@RequestBody Menu menu){ + return Result.builder().data(menuServiceRemote.save(menu)).status(ResultCodeEnum.SUCCESS).build(); + } + + @Operation(summary = "删除菜单") + @DeleteMapping("/{id}") + public Result delete(@PathVariable("id")String id){ + return Result.builder().data(menuServiceRemote.delete(id)).status(ResultCodeEnum.SUCCESS).build(); + } + + @Operation(summary = "修改菜单") + @PutMapping + public Result update(@RequestBody Menu menu){ + return Result.builder().data(menuServiceRemote.update(menu)).status(ResultCodeEnum.SUCCESS).build(); + } + + @Operation(summary = "获取单个菜单") + @GetMapping("/{id}") + public Result get(@PathVariable("id") String id){ + return Result.builder().data(menuServiceRemote.getById(id)).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/getParentMenu") + @Operation(summary = "获取父级菜单") + public Result> getParentMenu(){ + return Result.>builder().data(menuServiceRemote.getParentMenu()).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/existSameMenuTitle/{menuTitle}") + @Operation(summary = "检查是否存在相同的菜单名称") + public Result existSameMenuTitle(@PathVariable("menuTitle")String menuTitle){ + return Result.builder().data(menuServiceRemote.existSameMenuTitle(menuTitle)).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/existSameMenuPath") + @Operation(summary = "检查是否存在相同的菜单路径") + public Result existSameMenuPath(@RequestParam("menuPath")String menuPath){ + return Result.builder().data(menuServiceRemote.existSameMenuPath(menuPath)).status(ResultCodeEnum.SUCCESS).build(); + } + +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/system/RoleController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/system/RoleController.java new file mode 100644 index 0000000..6bf7d98 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/system/RoleController.java @@ -0,0 +1,92 @@ +package com.intelligentHealthCare.api.controller.system; + +import com.intelligentHealthCare.annotation.NoAuth; +import com.intelligentHealthCare.condition.KeywordCondition; +import com.intelligentHealthCare.controller.ApiAbstractSimpleController; +import com.intelligentHealthCare.dto.ApiDto; +import com.intelligentHealthCare.entity.Menu; +import com.intelligentHealthCare.entity.Role; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.ApiServiceRemote; +import com.intelligentHealthCare.remote.MenuServiceRemote; +import com.intelligentHealthCare.remote.RoleServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.*; +import springfox.documentation.annotations.Cacheable; + +import java.util.List; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/10/3 16:54 + */ +@RestController +@Api(tags = "角色管理") +@RequestMapping("/${app.baseService}/role") +public class RoleController{ + @Autowired + private RoleServiceRemote roleServiceRemote; + + @Autowired + private ApiServiceRemote apiServiceRemote; + + @Autowired + private MenuServiceRemote menuServiceRemote; + + @PostMapping("/page") + @Operation(summary = "获取角色信息分页") + public Result> page(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + + return Result.>builder().data(roleServiceRemote.getFilterList(conditionAndPageInfo)).status(ResultCodeEnum.SUCCESS).build(); + } + + @PostMapping + @Operation(summary = "新增角色") + public Result add(@RequestBody Role role){ + return Result.builder().data(roleServiceRemote.save(role)).status(ResultCodeEnum.SUCCESS).build(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除角色") + public Result remove(@PathVariable("id") String id){ + return Result.builder().data(roleServiceRemote.delete(id)).status(ResultCodeEnum.SUCCESS).build(); + } + + @PutMapping + @Operation(summary = "修改角色") + public Result update(@RequestBody Role role){ + return Result.builder().data(roleServiceRemote.update(role)).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "根据id获取实体") + public Result getById(@PathVariable("id")String id){ + return Result.builder().data(roleServiceRemote.getById(id)).status(ResultCodeEnum.SUCCESS).build(); + } + + @GetMapping("/existSameName/{roleName}") + @Operation(summary = "检查是否存在相同名称的角色") + public Result existSameName(@PathVariable("roleName")String roleName){ + return Result.builder().data(roleServiceRemote.existSameName(roleName)).status(ResultCodeEnum.SUCCESS).build(); + } + + + @GetMapping("/getAllAndAssigned/{id}") + @Operation(summary = "获取所有接口信息并携带已分配的接口") + public Result> getAllAndAssigned(@PathVariable("id")String id){ + return Result.>builder().data(apiServiceRemote.getAllAndAssigned(id)).status(ResultCodeEnum.SUCCESS).build(); + } + + @PostMapping("/updateRoleApiPermission/{roleId}") + @Operation(summary = "更改角色和api的关系") + public Result updateRoleApiPermission(@RequestBody List apiDtoList, @PathVariable("roleId")String roleId){ + return Result.builder().data(apiServiceRemote.updateRoleApiPermission(apiDtoList, roleId)).status(ResultCodeEnum.SUCCESS).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/system/SystemLogController.java b/api/src/main/java/com/intelligentHealthCare/api/controller/system/SystemLogController.java new file mode 100644 index 0000000..4cc5954 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/system/SystemLogController.java @@ -0,0 +1,40 @@ +package com.intelligentHealthCare.api.controller.system; + + +import com.intelligentHealthCare.condition.SystemCondition; +import com.intelligentHealthCare.dto.SystemLogDto; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.SystemLogServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/10/3 16:54 + */ +@RestController +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@Api(tags = "系统日志") +@RequestMapping("/${app.baseService}/systemLog") +public class SystemLogController { + private final SystemLogServiceRemote systemLogServiceRemote; + @PostMapping("/page") + @Operation(summary = "获取系统日志分页") + public Result> page(@RequestBody ConditionAndPageInfo conditionAndPageInfo) { + return Result.>builder().data(systemLogServiceRemote.getFilterListDto(conditionAndPageInfo)).status(ResultCodeEnum.SUCCESS).build(); + } + + @DeleteMapping("/deleteBatch") + @Operation(summary = "删除截至到某个时间段的日志") + public Result deleteBatch(@RequestBody SystemLogDto systemLogDto){ + return Result.builder().data(systemLogServiceRemote.deleteBatch(systemLogDto)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/DeploymentModel.java b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/DeploymentModel.java new file mode 100644 index 0000000..3763483 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/DeploymentModel.java @@ -0,0 +1,37 @@ +package com.intelligentHealthCare.api.controller.workflow.modelManage; + +import com.intelligentHealthCare.condition.KeywordCondition; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.workflow.ModelManageServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.activiti.api.process.model.ProcessDefinition; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yang + * @version 1.0 + * @date Created in 2024/3/5 09:33 + * @description + */ +@RestController +@Api(tags = "已部署模型管理") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/deploymentModel") +public class DeploymentModel { + + private final ModelManageServiceRemote modelManageServiceRemote; + + @PostMapping("/getDeploymentModelPage") + @Operation(summary = "获取已部署的模型分页") + public Result> getDeploymentModelPage(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(modelManageServiceRemote.getDeploymentModelPage(conditionAndPageInfo)).build(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/ModelCreate.java b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/ModelCreate.java new file mode 100644 index 0000000..795ce25 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/ModelCreate.java @@ -0,0 +1,49 @@ +package com.intelligentHealthCare.api.controller.workflow.modelManage; + +import com.intelligentHealthCare.condition.StaffCondition; +import com.intelligentHealthCare.dto.StaffDto; +import com.intelligentHealthCare.dto.workflow.ModelDto; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.StaffServiceRemote; +import com.intelligentHealthCare.remote.workflow.ModelManageServiceRemote; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + +/** + * @author yang + * @version 1.0 + * @date Created in 2024/2/28 14:19 + * @description + */ +@RestController +@Api(tags = "模型创建") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/modelCreate") +public class ModelCreate { + + private final StaffServiceRemote staffServiceRemote; + + private final ModelManageServiceRemote modelManageServiceRemote; + @PostMapping("/getStaffPage") + @Operation(summary = "获取人员信息分页") + public Result> getStaffDtoPage(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(staffServiceRemote.getStaffDtoPage(conditionAndPageInfo)).build(); + } + @PostMapping("/updateModel") + @Operation(summary = "更新模型") + public Result updateModel(@RequestBody ModelDto modelDto){ + return Result.builder().data(modelManageServiceRemote.updateModel(modelDto)).build(); + } + + @GetMapping("/{id}") + @Operation(summary = "根据模型id获取流程") + public Result getProcessByModelId(@PathVariable("id") String id){ + return Result.builder().data(modelManageServiceRemote.getProcessByModelId(id)).build(); + } + +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/ModelDefine.java b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/ModelDefine.java new file mode 100644 index 0000000..33ec820 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/ModelDefine.java @@ -0,0 +1,81 @@ +package com.intelligentHealthCare.api.controller.workflow.modelManage; + +import com.intelligentHealthCare.condition.KeywordCondition; +import com.intelligentHealthCare.condition.workflow.ModelCondition; +import com.intelligentHealthCare.pojo.ConditionAndPageInfo; +import com.intelligentHealthCare.pojo.Result; +import com.intelligentHealthCare.remote.workflow.ModelManageServiceRemote; +import com.intelligentHealthCare.utils.SortUtil; +import io.swagger.annotations.Api; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl; +import org.activiti.engine.impl.persistence.entity.ModelEntityImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.util.ObjectUtils; +import org.springframework.web.bind.annotation.*; +import org.activiti.engine.repository.Model; + +/** + * @author yang + * @version 1.0 + * @date Created in 2024/2/29 21:49 + * @description + */ +@RestController +@Api(tags = "模型定义") +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +@RequestMapping("/${app.baseService}/modelDefine") +public class ModelDefine { + private final ModelManageServiceRemote modelManageServiceRemote; + + /** + * 创建模型 + * @param key + * @param name + * @param description + */ + @GetMapping("/modelCreate/{key}/{name}/{description}") + @Operation(summary = "创建模型") + public Result modelCreate(@PathVariable("key")String key, @PathVariable("name")String name, @PathVariable("description")String description){ + modelManageServiceRemote.modelCreate(key, name, description); + return Result.builder().build(); + } + + /** + * 分页获取所有模型 + * @param conditionAndPageInfo + * @return + */ + @PostMapping("/page") + @Operation(summary = "分页获取所有的模型") + public Result> modelPage(@RequestBody ConditionAndPageInfo conditionAndPageInfo){ + return Result.>builder().data(modelManageServiceRemote.modelPage(conditionAndPageInfo)).build(); + } + + /** + * 根据模型id删除模型 + * @param modelId + * @return + */ + @DeleteMapping("/deleteModelById/{modelId}") + @Operation(summary = "根据模型id删除模型") + public Result deleteModelById(@PathVariable("modelId")String modelId){ + return Result.builder().data(modelManageServiceRemote.deleteModelById(modelId)).build(); + } + + /** + * 根据模型id部署模型 + * @param modelId + */ + @GetMapping("/deploymentModel/{modelId}") + @Operation(summary = "根据模型id部署模型") + public Result deploymentModel(@PathVariable("modelId")String modelId){ + modelManageServiceRemote.deploymentModel(modelId); + return Result.builder().build(); + } + +} diff --git a/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/Workflow.java b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/Workflow.java new file mode 100644 index 0000000..98996f9 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/api/controller/workflow/modelManage/Workflow.java @@ -0,0 +1,10 @@ +package com.intelligentHealthCare.api.controller.workflow.modelManage; + +/** + * @author yang + * @version 1.0 + * @date Created in 2024/2/29 21:43 + * @description + */ +public class Workflow { +} diff --git a/api/src/main/java/com/intelligentHealthCare/config/CommonAppProperty.java b/api/src/main/java/com/intelligentHealthCare/config/CommonAppProperty.java new file mode 100644 index 0000000..f2c0b39 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/config/CommonAppProperty.java @@ -0,0 +1,42 @@ +package com.intelligentHealthCare.config; + +import com.intelligentHealthCare.utils.JwtUtil; +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/11/1 15:57 + */ +@Data +@ConfigurationProperties(prefix = "app") +@Component +public class CommonAppProperty { + /** + * 基础服务路径 + */ + private String baseService; + + /** + * 认证令牌 + */ + @Value("${app.security.JWT-KEY}") + private String JWT_KEY; + + /** + * 令牌过期时间 + */ + @Value("${app.security.JWT-TTL}") + private Long JWT_TTL; + + @PostConstruct + public void initJwtUtil(){ + JwtUtil.JWT_KEY = JWT_KEY; + JwtUtil.JWT_TTL = JWT_TTL; + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/config/KaptchaConfig.java b/api/src/main/java/com/intelligentHealthCare/config/KaptchaConfig.java new file mode 100644 index 0000000..98b040c --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/config/KaptchaConfig.java @@ -0,0 +1,44 @@ +package com.intelligentHealthCare.config; + +import com.google.code.kaptcha.impl.DefaultKaptcha; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import com.google.code.kaptcha.util.Config; +import java.util.Properties; + +//kaptcha配置类 +@Component +public class KaptchaConfig { + @Bean + public DefaultKaptcha getDefaultKaptcha() { + com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha(); + Properties properties = new Properties(); + // 图片边框 + properties.setProperty("kaptcha.border", "yes"); + // 边框颜色 + properties.setProperty("kaptcha.border.color", "black"); + // 字体颜色 + properties.setProperty("kaptcha.textproducer.font.color", "black"); + // 图片宽 + properties.setProperty("kaptcha.image.width", "135"); + // 图片高 + properties.setProperty("kaptcha.image.height", "32"); + //使用哪些字符生成验证码 + properties.setProperty("kaptcha.textproducer.char.string", "ACEHKTW247"); + // 字体大小 + properties.setProperty("kaptcha.textproducer.font.size", "30"); + // session key + properties.setProperty("kaptcha.session.key", "code"); + // 验证码长度 + properties.setProperty("kaptcha.textproducer.char.length", "4"); + // 字体 + properties.setProperty("kaptcha.textproducer.font.names", "Arial"); + //干扰线颜色 + properties.setProperty("kaptcha.noise.color", "black"); + + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + + return defaultKaptcha; + } +} \ No newline at end of file diff --git a/api/src/main/java/com/intelligentHealthCare/config/SpringSecurityConfigurer.java b/api/src/main/java/com/intelligentHealthCare/config/SpringSecurityConfigurer.java new file mode 100644 index 0000000..48662db --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/config/SpringSecurityConfigurer.java @@ -0,0 +1,90 @@ +package com.intelligentHealthCare.config; + + +import com.intelligentHealthCare.exception.AccessDeniedHandlerException; +import com.intelligentHealthCare.exception.AuthenticationEntryPointException; +import com.intelligentHealthCare.exception.AuthenticationFailureException; +import com.intelligentHealthCare.filter.JwtAuthenticationTokenFilter; +import com.intelligentHealthCare.security.UrlMethodAccessDecision; +import com.intelligentHealthCare.security.UrlMethodAccessDecisionManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + + + +@Configuration +@EnableWebSecurity +public class SpringSecurityConfigurer extends WebSecurityConfigurerAdapter { + @Bean + public PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } + + + @Autowired + private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; + + @Autowired + private AccessDeniedHandlerException accessDeniedHandlerException; + + @Autowired + private AuthenticationEntryPointException authenticationEntryPointException; + + @Autowired + private AuthenticationFailureException authenticationFailureException; + + @Autowired + private UrlMethodAccessDecisionManager urlMethodAccessDecisionManager; + + + + + /** + * 配置HTTP安全设置,以定义应用程序的 seguridad 配置。 + * + * @param http 用于配置HttpSecurity的接口。 + * @throws Exception 配置过程中可能抛出的异常。 + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // 禁用CSRF保护 + .csrf().disable() + // 设置会话管理策略为无状态 + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + // 配置请求授权 + .authorizeRequests() + // 设置访问决策管理器 + .accessDecisionManager(urlMethodAccessDecisionManager) + // 所有请求都需要认证 + .anyRequest().authenticated(); + + // 在过滤器链中添加JWT认证过滤器 + http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + + // 配置异常处理,包括访问拒绝和认证入口点 + http.exceptionHandling().accessDeniedHandler(accessDeniedHandlerException).authenticationEntryPoint(authenticationEntryPointException); + + // 配置表单登录失败处理器 + http.formLogin().failureHandler(authenticationFailureException); + } + + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + +} diff --git a/api/src/main/java/com/intelligentHealthCare/exception/AccessDeniedHandlerException.java b/api/src/main/java/com/intelligentHealthCare/exception/AccessDeniedHandlerException.java new file mode 100644 index 0000000..11e15de --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/exception/AccessDeniedHandlerException.java @@ -0,0 +1,37 @@ +package com.intelligentHealthCare.exception; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.Result; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/9/28 21:07 + */ +@Component +public class AccessDeniedHandlerException implements AccessDeniedHandler { + @Override + public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException { + Result result = Result.builder().data(e.getMessage()).status(ResultCodeEnum.NoPermission).build(); + // 设置响应的内容类型为JSON + httpServletResponse.setContentType("application/json"); + httpServletResponse.setCharacterEncoding("UTF-8"); + // 将result对象转换为JSON字符串 + String jsonResult = new ObjectMapper().writeValueAsString(result); + // 将JSON字符串写入响应输出流 + PrintWriter writer = httpServletResponse.getWriter(); + writer.write(jsonResult); + writer.flush(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/exception/AuthenticationEntryPointException.java b/api/src/main/java/com/intelligentHealthCare/exception/AuthenticationEntryPointException.java new file mode 100644 index 0000000..253231f --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/exception/AuthenticationEntryPointException.java @@ -0,0 +1,36 @@ +package com.intelligentHealthCare.exception; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.intelligentHealthCare.enums.ResultCodeEnum; +import com.intelligentHealthCare.pojo.Result; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/9/28 21:16 + */ +@Component +public class AuthenticationEntryPointException implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { + Result result = Result.builder().data("账号过期,请重新登录").status(ResultCodeEnum.Unauth).build(); + // 设置响应的内容类型为JSON + httpServletResponse.setContentType("application/json"); + httpServletResponse.setCharacterEncoding("UTF-8"); + // 将result对象转换为JSON字符串 + String jsonResult = new ObjectMapper().writeValueAsString(result); + // 将JSON字符串写入响应输出流 + PrintWriter writer = httpServletResponse.getWriter(); + writer.write(jsonResult); + writer.flush(); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/exception/AuthenticationFailureException.java b/api/src/main/java/com/intelligentHealthCare/exception/AuthenticationFailureException.java new file mode 100644 index 0000000..1cda26f --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/exception/AuthenticationFailureException.java @@ -0,0 +1,23 @@ +package com.intelligentHealthCare.exception; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/9/28 16:41 + */ +@Component +public class AuthenticationFailureException implements AuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { + throw new SystemException("认证异常"); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/exception/CustomAuthenticationException.java b/api/src/main/java/com/intelligentHealthCare/exception/CustomAuthenticationException.java new file mode 100644 index 0000000..c0420c0 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/exception/CustomAuthenticationException.java @@ -0,0 +1,18 @@ +package com.intelligentHealthCare.exception; + +import org.springframework.security.core.AuthenticationException; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/9/29 15:09 + */ +public class CustomAuthenticationException extends AuthenticationException { + public CustomAuthenticationException(String msg, Throwable t) { + super(msg, t); + } + + public CustomAuthenticationException(String msg) { + super(msg); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/filter/JwtAuthenticationTokenFilter.java b/api/src/main/java/com/intelligentHealthCare/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..165ecd3 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,110 @@ +package com.intelligentHealthCare.filter; + +import com.intelligentHealthCare.dto.RequestModuleDto; +import com.intelligentHealthCare.entity.Api; +import com.intelligentHealthCare.exception.AuthenticationEntryPointException; +import com.intelligentHealthCare.exception.CustomAuthenticationException; +import com.intelligentHealthCare.remote.ApiServiceRemote; +import com.intelligentHealthCare.security.SecurityUser; +import com.intelligentHealthCare.utils.JwtUtil; +import com.intelligentHealthCare.utils.RedisCache; +import io.jsonwebtoken.Claims; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.http.server.PathContainer; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.pattern.PathPattern; +import org.springframework.web.util.pattern.PathPatternParser; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +@Component +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + private final RedisCache redisCache; + + private final ApiServiceRemote apiServiceRemote; + + public static RequestModuleDto requestModuleDto; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + packageRequestModule(request); + //获取token + Cookie[] cookies = request.getCookies(); + String token = ""; + if (cookies != null) { + for (Cookie cookie : cookies) { + String name = cookie.getName(); + String value = cookie.getValue(); + // 在这里对获取到的Cookie进行处理 + if(name.equals("token")){ + token = value; + break; + } + } + } + if (!StringUtils.hasText(token)) { + //放行 + filterChain.doFilter(request, response); + return; + } + //解析token + String userid; + Claims claims = JwtUtil.parseJWT(token); + // 检查令牌是否过期 + userid = claims.getSubject(); + //从redis中获取用户信息 + SecurityUser securityUser = (SecurityUser) redisCache.getCacheObject(userid); + //存入SecurityContextHolder + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); + //放行 + filterChain.doFilter(request, response); + } + + /** + * 封装请求模型 + * @param httpServletRequest + */ + public void packageRequestModule(HttpServletRequest httpServletRequest){ + requestModuleDto = new RequestModuleDto(); + requestModuleDto.setUrl(httpServletRequest.getRequestURI()); + requestModuleDto.setMethod(httpServletRequest.getMethod()); + + List apis = apiServiceRemote.getAll(); + PathPatternParser pathPatternParser = new PathPatternParser(); + + apis.forEach(api -> { + PathPattern pathPattern = pathPatternParser.parse(api.getRest()); + // 使用matchingCondition确保精确匹配 + PathPattern.PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(PathContainer.parsePath(httpServletRequest.getRequestURI())); + if (pathMatchInfo != null && pathMatchInfo.getUriVariables().isEmpty() && api.getMethod().equals(httpServletRequest.getMethod())) { + requestModuleDto.setModule(api.getName().split("-")[0]); + requestModuleDto.setOperation(api.getName().split("-")[1]); + requestModuleDto.setFullOperation(api.getName()); + } + }); + } + +} \ No newline at end of file diff --git a/api/src/main/java/com/intelligentHealthCare/interceptor/AccountHeaderInterceptor.java b/api/src/main/java/com/intelligentHealthCare/interceptor/AccountHeaderInterceptor.java new file mode 100644 index 0000000..0f21334 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/interceptor/AccountHeaderInterceptor.java @@ -0,0 +1,23 @@ +package com.intelligentHealthCare.interceptor; + +import com.intelligentHealthCare.security.SecurityUser; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +@Configuration +public class AccountHeaderInterceptor implements RequestInterceptor { + @Override + public void apply(RequestTemplate template) { + SecurityUser securityUser = null; + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if(authentication != null && authentication.getPrincipal() instanceof SecurityUser){ + securityUser = (SecurityUser) authentication.getPrincipal(); + } + if(securityUser != null){ + template.header("userId", securityUser.getAccount().getId()); + } + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/security/SecurityUserDetailService.java b/api/src/main/java/com/intelligentHealthCare/security/SecurityUserDetailService.java new file mode 100644 index 0000000..a4b87e2 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/security/SecurityUserDetailService.java @@ -0,0 +1,31 @@ +package com.intelligentHealthCare.security; + +import com.intelligentHealthCare.entity.Account; +import com.intelligentHealthCare.remote.AccountServiceRemote; +import com.intelligentHealthCare.remote.RoleApiPermissionServiceRemote; +import com.intelligentHealthCare.repository.AccountRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + + +@Service +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +public class SecurityUserDetailService implements UserDetailsService { + + private final AccountServiceRemote accountServiceRemote; + + private final RoleApiPermissionServiceRemote roleApiPermissionServiceRemote; + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Account byUserName = accountServiceRemote.findByUsername(username); + if(byUserName == null) { + return null; + } + //TODO 根据用户查询权限信息 + return new SecurityUser(byUserName, roleApiPermissionServiceRemote.getAllByAccountId(byUserName.getId())); + } +} diff --git a/api/src/main/java/com/intelligentHealthCare/security/UrlMethodAccessDecision.java b/api/src/main/java/com/intelligentHealthCare/security/UrlMethodAccessDecision.java new file mode 100644 index 0000000..87e524b --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/security/UrlMethodAccessDecision.java @@ -0,0 +1,85 @@ +package com.intelligentHealthCare.security; + +import com.intelligentHealthCare.dto.RequestModuleDto; +import com.intelligentHealthCare.filter.JwtAuthenticationTokenFilter; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.access.AccessDecisionVoter; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.FilterInvocation; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.web.util.pattern.PathPatternParser; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @author yang + * @version 1.0 + * @date Created in 2023/9/27 15:56 + */ +@Getter +@Setter +@Component +public class UrlMethodAccessDecision implements AccessDecisionVoter { + private List anonymousUrls; + + + @Override + public boolean supports(ConfigAttribute configAttribute) { + return true; + } + + @Override + public boolean supports(Class aClass) { + return true; + } + + @Override + public int vote(Authentication authentication, Object o, Collection collection) { + //获取请求模型 + RequestModuleDto requestModuleDto = JwtAuthenticationTokenFilter.requestModuleDto; + FilterInvocation filterInvocation = (FilterInvocation) o; + String requestUrl = filterInvocation.getRequestUrl(); + String method = filterInvocation.getHttpRequest().getMethod(); + AntPathMatcher pathMatcher = new AntPathMatcher(); + AtomicBoolean anonymousUrlMatch = new AtomicBoolean(false); + if(anonymousUrls != null) { + anonymousUrls.forEach(anonymousUrl -> { + if (pathMatcher.match(anonymousUrl, requestUrl)) { + anonymousUrlMatch.set(true); + } + }); + } + if(anonymousUrlMatch.get()){ + return ACCESS_GRANTED; + } + if(authentication.getPrincipal().equals("anonymousUser")){ + throw new AccessDeniedException("没有 [" + requestModuleDto.getFullOperation() + "] 权限,请联系管理员分配"); + } + SecurityUser securityUser = (SecurityUser) authentication.getPrincipal(); + if(securityUser.getAccount().getSystemManager()){ + return ACCESS_GRANTED; + } + AtomicBoolean hasAuth = new AtomicBoolean(false); + if(securityUser.getPermissions() != null) { + securityUser.getPermissions().forEach(api -> { + if (pathMatcher.match(api.getRest(), requestUrl) && method.equals(api.getMethod())) { + hasAuth.set(true); + return; + } + }); + } + if(hasAuth.get()){ + return ACCESS_GRANTED; + } + throw new AccessDeniedException("没有 [" + requestModuleDto.getFullOperation() + "] 权限,请联系管理员分配"); + } + + +} diff --git a/api/src/main/java/com/intelligentHealthCare/security/UrlMethodAccessDecisionManager.java b/api/src/main/java/com/intelligentHealthCare/security/UrlMethodAccessDecisionManager.java new file mode 100644 index 0000000..ca36835 --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/security/UrlMethodAccessDecisionManager.java @@ -0,0 +1,40 @@ +package com.intelligentHealthCare.security; + +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.access.AccessDecisionVoter; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; +@Component +public class UrlMethodAccessDecisionManager implements AccessDecisionManager { + + private final AccessDecisionVoter accessDecisionVoter; + + public UrlMethodAccessDecisionManager(AccessDecisionVoter accessDecisionVoter) { + this.accessDecisionVoter = accessDecisionVoter; + } + + @Override + public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { + int result = accessDecisionVoter.vote(authentication, object, (List) configAttributes); + + if (result == AccessDecisionVoter.ACCESS_DENIED) { + throw new AccessDeniedException("Access is denied"); + } + } + + @Override + public boolean supports(ConfigAttribute attribute) { + return true; + } + + @Override + public boolean supports(Class clazz) { + return true; + } +} \ No newline at end of file diff --git a/api/src/main/java/com/intelligentHealthCare/service/impl/AccountHandle.java b/api/src/main/java/com/intelligentHealthCare/service/impl/AccountHandle.java new file mode 100644 index 0000000..867076d --- /dev/null +++ b/api/src/main/java/com/intelligentHealthCare/service/impl/AccountHandle.java @@ -0,0 +1,77 @@ +package com.intelligentHealthCare.service.impl; + +import com.intelligentHealthCare.entity.Account; +import com.intelligentHealthCare.exception.BizException; +import com.intelligentHealthCare.exception.LoginFailException; +import com.intelligentHealthCare.remote.AccountServiceRemote; +import com.intelligentHealthCare.security.SecurityUser; +import com.intelligentHealthCare.utils.JwtUtil; +import com.intelligentHealthCare.utils.RedisCache; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__({@Autowired})) +public class AccountHandle { + + @Autowired + private final AuthenticationManager authenticationManager; + + @Autowired + private final RedisCache redisCache; + + @Autowired + private final AccountServiceRemote accountServiceRemote; + + public String login(Account account, String code, String userIp) { + Object cacheCode = redisCache.getCacheObject(userIp); + if(cacheCode == null){ + throw new BizException("验证码已过期"); + } else if (!cacheCode.toString().equalsIgnoreCase(code)) { + throw new BizException("验证码有误"); + } + redisCache.deleteObject(userIp); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account.getUsername(), account.getPassword()); + Authentication authenticate; + try { + authenticate = authenticationManager.authenticate(authenticationToken); + }catch (DisabledException disabledException){ + throw new LoginFailException("账号已被停用"); + }catch (BadCredentialsException e){ + throw new LoginFailException("密码错误"); + }catch (AuthenticationException e){ + log.error("认证错误", e); + throw new LoginFailException("账号不存在"); + } + SecurityUser loginAccount = (SecurityUser) authenticate.getPrincipal(); + String jwt = JwtUtil.createJWT(loginAccount.getAccount().getId()); + redisCache.setCacheObject(loginAccount.getAccount().getId(), loginAccount, 7, TimeUnit.DAYS); + return jwt; + } + + + public Boolean logout() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + SecurityUser loginAccount = (SecurityUser) authentication.getPrincipal(); + return redisCache.deleteObject(loginAccount.getAccount().getId()); + } + + + public Account register(Account account) { + account.setPassword(new BCryptPasswordEncoder().encode(account.getPassword())); + return accountServiceRemote.register(account); + } +} diff --git a/api/src/main/resources/application-dev.yml b/api/src/main/resources/application-dev.yml new file mode 100644 index 0000000..e69de29 diff --git a/api/src/main/resources/application-prod.yml b/api/src/main/resources/application-prod.yml new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/api/src/main/resources/application-prod.yml @@ -0,0 +1,3 @@ + + + diff --git a/api/src/main/resources/application.yml b/api/src/main/resources/application.yml new file mode 100644 index 0000000..f307e0c --- /dev/null +++ b/api/src/main/resources/application.yml @@ -0,0 +1,79 @@ +spring: + devtools: + restart: + enabled: true #设置开启热部署 + additional-paths: src/main/java #重启目录 + servlet: + multipart: + location: D:\intelligentHealthCare\resources\temp + max-file-size: 200MB + max-request-size: 200MB + datasource: + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/intelligentHealthCare?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true + jpa: + properties: + hibernate: + format_sql: true + jdbc: + time_zone: Asia/Shanghai + hbm2ddl: + auto: update + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL5InnoDBDialect + jdbc: + time_zone: Asia/Shanghai + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + locale: zh_CN + default-property-inclusion: non_null + serialization: + write_dates_as_timestamps: false + profiles: + active: local + mail: + #配置smtp服务主机地址 + # qq邮箱为smtp.qq.com 端口号465或587 + # sina smtp.sina.cn + # aliyun smtp.aliyun.com + # 163 smtp.163.com 端口号465或994 + host: smtp.qq.com + #配置密码,注意不是真正的密码,而是刚刚申请到的授权码 + username: 1545558448@qq.com + password: akruwpztoznnigdf + #端口号465或587 + port: 587 + #默认的邮件编码为UTF-8 + default-encoding: UTF-8 + #其他参数 + properties: + mail: + #配置SSL 加密工厂 + smtp: + ssl: + #本地测试,先放开ssl + enable: false + required: false + #开启debug模式,这样邮件发送过程的日志会在控制台打印出来,方便排查错误 + debug: true +app: + baseService: api + resources-location: D:\intelligentHealthCare\resources\ + default-sub-location: resources + remoteService: service + workflowService: workflow + clientService: clientService + security: + JWT-KEY: "INTELLIGENT" #认证令牌 + JWT-TTL: 6048000000 #过期时间七天 +logging: + level: + com.intelligentHealthCare: debug +platform: + name: "智能康养管理平台" + email: "1545558448@qq.com" + website: "127.0.0.1:5173" diff --git a/api/src/main/resources/bootstrap.yml b/api/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..123ddf8 --- /dev/null +++ b/api/src/main/resources/bootstrap.yml @@ -0,0 +1,37 @@ +spring: + application: + name: api + cloud: + nacos: + config: + server-addr: localhost:8848 +biz-service: + ribbon: + NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 + +server: + port: 8003 + +feign: + httpclient: + enabled: true #开启feign对httpclient的支持 + max-connections: 200 #最大连接数量 + max-connections-per-route: 50 #每个路由最大连接数量 + # Feign org.springframework.data.domain.Page编码和解码 + # Feign org.springframework.data.domain.Sort编码解码 + connection-timeout: 30000 #连接超时时间 + client: + config: + default: + connect-timeout: 30000 #链接超时 + read-timeout: 60000 #超时 + request-interceptors: + - com.intelligentHealthCare.interceptor.AccountHeaderInterceptor + autoconfiguration: + jackson: + # 如果为true,则将提供PageJacksonModule、SortJacksonModule用jackson对Page进行编码和解码操作,默认:false + enabled: true + sentinel: + enabled: true #开启流量整合 + + diff --git a/api/src/main/resources/rebel.xml b/api/src/main/resources/rebel.xml new file mode 100644 index 0000000..5e49845 --- /dev/null +++ b/api/src/main/resources/rebel.xml @@ -0,0 +1,16 @@ + + + + + + api + + + + + + +