commit 8cae29f3b272db8b6102e87e364124dbb9fafbab Author: localuser Date: Sat Nov 8 10:26:37 2025 +0800 Initialize app-only repo diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b4bd40c --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +/logs/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ca2a05f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# syntax=docker/dockerfile:1 +FROM eclipse-temurin:17-jre-alpine + +LABEL maintainer="platform-team" + +ENV TZ=Asia/Shanghai \ + LANG=zh_CN.UTF-8 \ + JAVA_OPTS="-Dfile.encoding=UTF-8" \ + SPRING_PROFILES_ACTIVE=dev + +RUN apk add --no-cache tzdata && \ + ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +WORKDIR /app + +# 注意:在构建镜像前先执行 `mvn -DskipTests package` 生成 WAR +COPY target/platform-1.0.war /app/app.war + +EXPOSE 8093 + +ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.war --spring.profiles.active=$SPRING_PROFILES_ACTIVE"] \ No newline at end of file diff --git a/frontend/readme.md b/frontend/readme.md new file mode 100644 index 0000000..dfaf36f --- /dev/null +++ b/frontend/readme.md @@ -0,0 +1 @@ +这里放置前端项目的readme文件 \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4f357a2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,374 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.0 + + + com.yfd + platform + 1.0 + war + platform + springboot 项目基础框架3.0 + + 17 + UTF-8 + 2023.0.1.0 + 2023.0.1 + 3.3.0 + 17 + 17 + 17 + 3.5.16 + 3.5.6 + + 30.0-jre + 3.0.3 + 1.2.20 + 1.2.20 + 3.32.3.2 + 5.8.8 + 4.1.2 + 4.1.2 + 1.2.70 + 2.5.0 + 2.3.28 + 1.11.3 + 1.16 + 1.7.2 + 1.6.2 + 1.21 + + + + + + + + org.mybatis + mybatis + ${mybatis.version} + + + org.mybatis + mybatis-spring + 3.0.3 + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + org.springframework.boot + spring-boot-starter-cache + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + com.google.guava + guava + ${guava.version} + + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + + org.springframework.boot + spring-boot-starter-quartz + + + + + + + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.spring.boot.starter.version} + + + + + org.mybatis + mybatis + ${mybatis.version} + + + + + com.alibaba + druid + ${druid.version} + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + + com.alibaba + druid-spring-boot-starter + ${druid.starter.version} + + + + + com.mysql + mysql-connector-j + runtime + + + + + org.xerial + sqlite-jdbc + ${sqlite-jdbc.version} + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + com.baomidou + mybatis-plus-generator + ${mybatis-plus.version} + + + + + org.apache.commons + commons-lang3 + + + + + org.projectlombok + lombok + true + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + + org.apache.poi + poi + ${poi.version} + + + org.apache.poi + poi-ooxml + ${poi.ooxml.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + + io.micrometer + micrometer-registry-prometheus + + + + org.freemarker + freemarker + ${freemarker.version} + compile + + + org.jsoup + jsoup + ${jsoup.version} + + + + + com.github.ulisesbocchio + jasypt-spring-boot-starter + ${jasypt.version} + + + + org.lionsoul + ip2region + ${ip2region.version} + + + + + com.github.whvcse + easy-captcha + ${easy.captcha.version} + + + + + eu.bitwalker + UserAgentUtils + ${useragentutils.version} + + + + + + + src/main/resources + + **/*.* + + false + + + src/main/java + + **/*.* + + + **/*.java + + false + + + + + + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.8 + + + generate-docs + prepare-package + + process-asciidoc + + + html + book + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.4.1 + + + enforce-rules + + enforce + + + + + + [3.6.3,) + + + [17,) + + + + + + + + + + + + diff --git a/src/main/java/com/yfd/platform/PlatformApplication.java b/src/main/java/com/yfd/platform/PlatformApplication.java new file mode 100644 index 0000000..a98fea6 --- /dev/null +++ b/src/main/java/com/yfd/platform/PlatformApplication.java @@ -0,0 +1,45 @@ +package com.yfd.platform; + +import com.yfd.platform.annotation.rest.AnonymousGetMapping; +import com.yfd.platform.datasource.DynamicDataSourceConfig; +import com.yfd.platform.utils.SpringContextHolder; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.web.bind.annotation.RestController; + +//@SpringBootApplication +@RestController +@EnableTransactionManagement +@ServletComponentScan("com.yfd.platform.config") +@MapperScan(basePackages = "com.yfd.platform.modules.*.mapper,com.yfd.platform.*.mapper") +@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class}) +@Import({DynamicDataSourceConfig.class}) +@EnableCaching +public class PlatformApplication { + + public static void main(String[] args) { + SpringApplication.run(PlatformApplication.class, args); + } + + @Bean + public SpringContextHolder springContextHolder() { + return new SpringContextHolder(); + } + + /** + * 访问首页提示 + * + * @return / + */ + @AnonymousGetMapping("/") + public String index() { + return "Backend service started successfully"; + } +} diff --git a/src/main/java/com/yfd/platform/ServletInitializer.java b/src/main/java/com/yfd/platform/ServletInitializer.java new file mode 100644 index 0000000..0234b48 --- /dev/null +++ b/src/main/java/com/yfd/platform/ServletInitializer.java @@ -0,0 +1,13 @@ +package com.yfd.platform; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(PlatformApplication.class); + } + +} diff --git a/src/main/java/com/yfd/platform/annotation/AnonymousAccess.java b/src/main/java/com/yfd/platform/annotation/AnonymousAccess.java new file mode 100644 index 0000000..2fbd4c0 --- /dev/null +++ b/src/main/java/com/yfd/platform/annotation/AnonymousAccess.java @@ -0,0 +1,30 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.annotation; + +import java.lang.annotation.*; + +/** + * @author jacky + * 用于标记匿名访问方法 + */ +@Inherited +@Documented +@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface AnonymousAccess { + +} diff --git a/src/main/java/com/yfd/platform/annotation/Log.java b/src/main/java/com/yfd/platform/annotation/Log.java new file mode 100644 index 0000000..6739494 --- /dev/null +++ b/src/main/java/com/yfd/platform/annotation/Log.java @@ -0,0 +1,20 @@ +package com.yfd.platform.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author TangWei + * @date 2018-11-24 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Log { + + String value() default ""; + + String module() default ""; +} + diff --git a/src/main/java/com/yfd/platform/annotation/rest/AnonymousGetMapping.java b/src/main/java/com/yfd/platform/annotation/rest/AnonymousGetMapping.java new file mode 100644 index 0000000..01fcc32 --- /dev/null +++ b/src/main/java/com/yfd/platform/annotation/rest/AnonymousGetMapping.java @@ -0,0 +1,86 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yfd.platform.annotation.rest; + +import com.yfd.platform.annotation.AnonymousAccess; +import org.springframework.core.annotation.AliasFor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.lang.annotation.*; + +/** + * Annotation for mapping HTTP {@code GET} requests onto specific handler + * methods. + *

+ * 支持匿名访问 GetMapping + * + * @author liaojinlong + * @see RequestMapping + */ +@AnonymousAccess +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@RequestMapping(method = RequestMethod.GET) +public @interface AnonymousGetMapping { + + /** + * Alias for {@link RequestMapping#name}. + */ + @AliasFor(annotation = RequestMapping.class) + String name() default ""; + + /** + * Alias for {@link RequestMapping#value}. + */ + @AliasFor(annotation = RequestMapping.class) + String[] value() default {}; + + /** + * Alias for {@link RequestMapping#path}. + */ + @AliasFor(annotation = RequestMapping.class) + String[] path() default {}; + + /** + * Alias for {@link RequestMapping#params}. + */ + @AliasFor(annotation = RequestMapping.class) + String[] params() default {}; + + /** + * Alias for {@link RequestMapping#headers}. + */ + @AliasFor(annotation = RequestMapping.class) + String[] headers() default {}; + + /** + * Alias for {@link RequestMapping#consumes}. + * + * @since 4.3.5 + */ + @AliasFor(annotation = RequestMapping.class) + String[] consumes() default {}; + + /** + * Alias for {@link RequestMapping#produces}. + */ + @AliasFor(annotation = RequestMapping.class) + String[] produces() default {}; + +} diff --git a/src/main/java/com/yfd/platform/aspect/LogAspect.java b/src/main/java/com/yfd/platform/aspect/LogAspect.java new file mode 100644 index 0000000..0c52a21 --- /dev/null +++ b/src/main/java/com/yfd/platform/aspect/LogAspect.java @@ -0,0 +1,93 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.aspect; + +import com.yfd.platform.system.domain.SysLog; +import com.yfd.platform.system.mapper.SysUserMapper; +import com.yfd.platform.system.service.ISysLogService; +import com.yfd.platform.system.service.IUserService; +import com.yfd.platform.utils.RequestHolder; +import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * @author + * @date 2018-11-24 + */ +@Component +@Aspect +@Slf4j +public class LogAspect { + + @Resource + private final ISysLogService sysLogService; + + @Resource + private IUserService userService; + + ThreadLocal currentTime = new ThreadLocal<>(); + + public LogAspect(ISysLogService sysLogService) { + this.sysLogService = sysLogService; + } + + /** + * 配置切入点 + */ + @Pointcut("@annotation(com.yfd.platform.annotation.Log)") + public void logPointcut() { + // 该方法无方法体,主要为了让同类中其他方法使用此切入点 + } + + /** + * 配置环绕通知,使用在方法logPointcut()上注册的切入点 + * + * @param joinPoint join point for advice + */ + @Around("logPointcut()") + public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { + Object result; + currentTime.set(System.currentTimeMillis()); + result = joinPoint.proceed(); + SysLog log = new SysLog("INFO"); + currentTime.remove(); + HttpServletRequest request = RequestHolder.getHttpServletRequest(); + Map nameInfo = userService.getNameInfo(); + String nickname = nameInfo.get("nickname"); + String username = nameInfo.get("username"); + sysLogService.save(nickname, username, StringUtils.getBrowser(request), + StringUtils.getIp(request), joinPoint, log); + return result; + } + + public String getUsername() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception e) { + return ""; + } + } +} diff --git a/src/main/java/com/yfd/platform/component/ServerSendEventServer.java b/src/main/java/com/yfd/platform/component/ServerSendEventServer.java new file mode 100644 index 0000000..ca1b1fe --- /dev/null +++ b/src/main/java/com/yfd/platform/component/ServerSendEventServer.java @@ -0,0 +1,147 @@ +package com.yfd.platform.component; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +/** + * @author Huhailong + * SSE Server send Event 服务器推送服务 + */ +@Slf4j +public class ServerSendEventServer { + + /** + * 当前连接数 + */ + private static AtomicInteger count = new AtomicInteger(0); + + private static Map sseEmitterMap = + new ConcurrentHashMap<>(); + + public static SseEmitter connect(String userId) { + //设置超时时间,0表示不过期,默认是30秒,超过时间未完成会抛出异常 + SseEmitter sseEmitter = new SseEmitter(0L); + //SseEmitter sseEmitter = new SseEmitter(); + //注册回调 + sseEmitter.onCompletion(completionCallBack(userId)); + sseEmitter.onError(errorCallBack(userId)); + sseEmitter.onTimeout(timeOutCallBack(userId)); + sseEmitterMap.put(userId, sseEmitter); + //数量+1 + count.getAndIncrement(); + log.info("create new sse connect ,current user:{}", userId); + return sseEmitter; + } + + /** + * 给指定用户发消息 + */ + public static void sendMessage(String userId, String message) { + if (sseEmitterMap.containsKey(userId)) { + try { + sseEmitterMap.get(userId).send(message); + } catch (IOException e) { + log.error("user id:{}, send message error:{}", userId, + e.getMessage()); + e.printStackTrace(); + } + } + } + + /** + * 给所有用户发消息 + */ + public static void sendMessage(String message) { + if (sseEmitterMap != null && !sseEmitterMap.isEmpty()) { + sseEmitterMap.forEach((k, v) -> { + // 发送消息 + sendMessage(k, message); + + }); + } + } + + /** + * 想多人发送消息,组播 + */ + public static void groupSendMessage(String groupId, String message) { + if (sseEmitterMap != null && !sseEmitterMap.isEmpty()) { + sseEmitterMap.forEach((k, v) -> { + try { + if (k.startsWith(groupId)) { + v.send(message, MediaType.APPLICATION_JSON); + } + } catch (IOException e) { + log.error("user id:{}, send message error:{}", groupId, + message); + removeUser(k); + } + }); + } + } + + public static void batchSendMessage(String message) { + sseEmitterMap.forEach((k, v) -> { + try { + v.send(message, MediaType.APPLICATION_JSON); + } catch (IOException e) { + log.error("user id:{}, send message error:{}", k, + e.getMessage()); + removeUser(k); + } + }); + } + + /** + * 群发消息 + */ + public static void batchSendMessage(String message, Set userIds) { + userIds.forEach(userId -> sendMessage(userId, message)); + } + + public static void removeUser(String userId) { + sseEmitterMap.remove(userId); + //数量-1 + count.getAndDecrement(); + log.info("remove user id:{}", userId); + } + + public static List getIds() { + return new ArrayList<>(sseEmitterMap.keySet()); + } + + public static int getUserCount() { + return count.intValue(); + } + + private static Runnable completionCallBack(String userId) { + return () -> { + log.info("结束连接,{}", userId); + removeUser(userId); + }; + } + + private static Runnable timeOutCallBack(String userId) { + return () -> { + log.info("连接超时,{}", userId); + removeUser(userId); + }; + } + + private static Consumer errorCallBack(String userId) { + return throwable -> { + log.error("连接异常,{}", userId); + removeUser(userId); + }; + } +} diff --git a/src/main/java/com/yfd/platform/component/WebSocketServer.java b/src/main/java/com/yfd/platform/component/WebSocketServer.java new file mode 100644 index 0000000..1d0b913 --- /dev/null +++ b/src/main/java/com/yfd/platform/component/WebSocketServer.java @@ -0,0 +1,106 @@ +package com.yfd.platform.component; + +import org.springframework.stereotype.Component; + +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArrayList; + +@ServerEndpoint("/websocket/{token}") +@Component +public class WebSocketServer { + private static int onlineCount=0;//在线人数 + private static CopyOnWriteArrayList webSocketSet=new CopyOnWriteArrayList();//在线用户集合 + private Session session;//与某个客户端的连接会话 + private String currentUser; + + @OnOpen + public void onOpen(@PathParam("token") String token, Session session){ + this.currentUser = token; + this.session=session; + webSocketSet.add(this);//加入set中 + addOnlineCount(); + System.out.println("有新连接加入!当前在线人数为"+getOnlineCount()); + allCurrentOnline(); + } + + @OnClose + public void onClose(){ + webSocketSet.remove(this); + subOnlineCount(); + System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); + allCurrentOnline(); + } + + @OnMessage + public void onMessage(String message, Session session){ + System.out.println("来自客户端的消息:"+message); + for (WebSocketServer item:webSocketSet){ + try { + item.sendMessage(message); + } catch (IOException e) { + e.printStackTrace(); + continue; + } + } + } + + @OnError + public void onError(Session session, Throwable throwable){ + System.out.println("发生错误!"); + throwable.printStackTrace(); + } + + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + + /** + * 获取当前所有在线用户名 + */ + public static void allCurrentOnline(){ + for (WebSocketServer item : webSocketSet) { + System.out.println(item.currentUser); + } + } + + /** + * 发送给指定用户 + */ + public static void sendMessageTo(String message,String token) throws IOException { + for (WebSocketServer item : webSocketSet) { + if(item.currentUser.equals(token)){ + item.session.getBasicRemote().sendText(message); + } + } + } + + /** + * 群发自定义消息 + */ + public static void sendInfo(String message) throws IOException { + System.out.println(message); + for (WebSocketServer item : webSocketSet) { + try { + item.sendMessage(message); + } catch (IOException e) { + continue; + } + } + } + + public static synchronized int getOnlineCount(){ + return onlineCount; + } + public static synchronized void addOnlineCount(){ + WebSocketServer.onlineCount++; + } + public static synchronized void subOnlineCount(){ + WebSocketServer.onlineCount--; + } + +} + + diff --git a/src/main/java/com/yfd/platform/config/FileProperties.java b/src/main/java/com/yfd/platform/config/FileProperties.java new file mode 100644 index 0000000..c179499 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/FileProperties.java @@ -0,0 +1,59 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "file") +public class FileProperties { + + /** 文件大小限制 */ + private Long maxSize; + + /** 头像大小限制 */ + private Long avatarMaxSize; + + private ElPath mac; + + private ElPath linux; + + private ElPath windows; + + public ElPath getPath(){ + String os = System.getProperty("os.name"); + if(os.toLowerCase().startsWith("win")) { + return windows; + } else if(os.toLowerCase().startsWith("mac")){ + return mac; + } + return linux; + } + + @Data + public static class ElPath{ + + private String path; + + private String avatar; + } +} diff --git a/src/main/java/com/yfd/platform/config/FileSpaceProperties.java b/src/main/java/com/yfd/platform/config/FileSpaceProperties.java new file mode 100644 index 0000000..74aab7d --- /dev/null +++ b/src/main/java/com/yfd/platform/config/FileSpaceProperties.java @@ -0,0 +1,17 @@ +package com.yfd.platform.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 文件空间相关配置,替换 @Value("${file-space.system}") 用法 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "file-space") +public class FileSpaceProperties { + + /** 基础目录,例如 D:/data/platform/ */ + private String system; +} \ No newline at end of file diff --git a/src/main/java/com/yfd/platform/config/GlobalExceptionHandler.java b/src/main/java/com/yfd/platform/config/GlobalExceptionHandler.java new file mode 100644 index 0000000..d9c7d7a --- /dev/null +++ b/src/main/java/com/yfd/platform/config/GlobalExceptionHandler.java @@ -0,0 +1,24 @@ +package com.yfd.platform.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @author TangWei + * @Date: 2023/3/27 18:07 + * @Description: + */ +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + + @ResponseBody + @ExceptionHandler(value = Throwable.class) + public ResponseResult handleException(Throwable e) { + log.error("message:{}", e.getMessage()); + return ResponseResult.error(e.getMessage()); + } + +} diff --git a/src/main/java/com/yfd/platform/config/JobRunner.java b/src/main/java/com/yfd/platform/config/JobRunner.java new file mode 100644 index 0000000..c0d451e --- /dev/null +++ b/src/main/java/com/yfd/platform/config/JobRunner.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yfd.platform.system.domain.QuartzJob; +import com.yfd.platform.system.mapper.QuartzJobMapper; +import com.yfd.platform.utils.QuartzManage; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author + * @date 2019-01-07 + */ +@Component +@RequiredArgsConstructor +public class JobRunner implements ApplicationRunner { + + private static final Logger log = LoggerFactory.getLogger(JobRunner.class); + private final QuartzJobMapper quartzJobMapper; + private final QuartzManage quartzManage; + + /** + * 项目启动时重新激活启用的定时任务 + * + * @param applicationArguments / + */ + @Override + public void run(ApplicationArguments applicationArguments) { + log.info("--------------------注入定时任务---------------------"); + List quartzJobs = + quartzJobMapper.selectList(new LambdaQueryWrapper().eq(QuartzJob::getStatus, "1")); + quartzJobs.forEach(quartzManage::addJob); + log.info("--------------------定时任务注入完成---------------------"); + } +} diff --git a/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java b/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..bcb79c0 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java @@ -0,0 +1,83 @@ +package com.yfd.platform.config; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.jwt.JWT; +import cn.hutool.jwt.JWTUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yfd.platform.component.ServerSendEventServer; +import com.yfd.platform.constant.Constant; +import com.yfd.platform.system.domain.LoginUser; +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.service.IMessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import jakarta.annotation.Resource; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + @Autowired + private WebConfig webConfig; + + @Override + protected void doFilterInternal(HttpServletRequest httpServletRequest, + HttpServletResponse httpServletResponse, + FilterChain filterChain) throws ServletException, IOException { + //获取token + String uri = httpServletRequest.getRequestURI(); + String token = httpServletRequest.getHeader("token"); + if (StrUtil.isEmpty(token) || "/user/login".equals(uri)) { + filterChain.doFilter(httpServletRequest, httpServletResponse); + return; + } + //解析token + boolean isok = JWTUtil.verify(token, "12345678".getBytes()); + String userid = ""; + if (isok) { + final JWT jwt = JWTUtil.parseToken(token); + userid = jwt.getPayload("userid").toString(); + //从cachekey中获取用户信息失效时间 + String cachekey = "expire_time:" + userid; + if(StrUtil.isNotEmpty(webConfig.loginuserCache().get(cachekey))){ + long expire_time =Long.parseLong(webConfig.loginuserCache().get(cachekey)); + if (System.currentTimeMillis() > expire_time) { + httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Token超过期限!"); + return; + } + } + } + + //从cachekey中获取用户信息 + String cachekey = "login:" + userid; + String jsonstr = webConfig.loginuserCache().get(cachekey); + LoginUser loginUser = JSON.parseObject(jsonstr, LoginUser.class); + if (ObjectUtil.isEmpty(loginUser)) { + httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, + "登录用户已失效!"); + return; + } + //存入SecurityContextHolder + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(loginUser, null, + loginUser.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + webConfig.loginuserCache().put(Constant.TOKEN + userid, token); + //更新了超期时间 + long expireTime =System.currentTimeMillis() + ( 30L * 60L * 1000L); + webConfig.loginuserCache().put("expire_time:" + userid, String.valueOf(expireTime)); + //放行过滤器 + filterChain.doFilter(httpServletRequest, httpServletResponse); + } + +} diff --git a/src/main/java/com/yfd/platform/config/MessageConfig.java b/src/main/java/com/yfd/platform/config/MessageConfig.java new file mode 100644 index 0000000..e079d02 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/MessageConfig.java @@ -0,0 +1,50 @@ +package com.yfd.platform.config; + +import cn.hutool.cache.Cache; +import cn.hutool.cache.impl.CacheObj; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yfd.platform.component.ServerSendEventServer; +import com.yfd.platform.constant.Constant; +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.service.IMessageService; +import com.yfd.platform.system.service.IUserService; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import jakarta.annotation.Resource; +import java.util.Iterator; + +/** + * @author TangWei + * @Date: 2023/3/24 15:56 + * @Description: + */ +@Component +public class MessageConfig { + + @Resource + private IMessageService messageService; + + @Resource + private IUserService userService; + + @Resource + private WebConfig webConfig; + + public void sendMessage() { + long count = + messageService.count(new LambdaQueryWrapper().eq(Message::getStatus, "1")); + String userId = userService.getUserInfo().getId(); + String token = webConfig.loginuserCache().get(Constant.TOKEN + userId); + ServerSendEventServer.sendMessage(token, count + ""); + } + + public void addMessage(Message message) { + messageService.save(message); + long count = + messageService.count(new LambdaQueryWrapper().eq(Message::getStatus, "1")); + ServerSendEventServer.sendMessage(count + ""); + } +} diff --git a/src/main/java/com/yfd/platform/config/MybitsPlusConfig.java b/src/main/java/com/yfd/platform/config/MybitsPlusConfig.java new file mode 100644 index 0000000..de009d7 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/MybitsPlusConfig.java @@ -0,0 +1,24 @@ +package com.yfd.platform.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/****************************** + * 用途说明: + * 作者姓名: pcj + * 创建时间: 2022/10/24 10:50 + ******************************/ +@Configuration +public class MybitsPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); + mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return mybatisPlusInterceptor; + } + +} diff --git a/src/main/java/com/yfd/platform/config/QuartzConfig.java b/src/main/java/com/yfd/platform/config/QuartzConfig.java new file mode 100644 index 0000000..41a36db --- /dev/null +++ b/src/main/java/com/yfd/platform/config/QuartzConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config; + +import org.quartz.Scheduler; +import org.quartz.spi.TriggerFiredBundle; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.AdaptableJobFactory; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * 定时任务配置 + * + * @author / + * @date 2019-01-07 + */ +@Configuration +public class QuartzConfig { + + /** + * 解决Job中注入Spring Bean为null的问题 + */ + @Component("quartzJobFactory") + public static class QuartzJobFactory extends AdaptableJobFactory { + + private final AutowireCapableBeanFactory capableBeanFactory; + + public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) { + this.capableBeanFactory = capableBeanFactory; + } + + @Override + protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { + + //调用父类的方法 + Object jobInstance = super.createJobInstance(bundle); + capableBeanFactory.autowireBean(jobInstance); + return jobInstance; + } + } + + /** + * 注入scheduler到spring + * + * @param quartzJobFactory / + * @return Scheduler + * @throws Exception / + */ + @Bean(name = "scheduler") + public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception { + SchedulerFactoryBean factoryBean = new SchedulerFactoryBean(); + factoryBean.setJobFactory(quartzJobFactory); + factoryBean.afterPropertiesSet(); + Scheduler scheduler = factoryBean.getScheduler(); + scheduler.start(); + return scheduler; + } + +} diff --git a/src/main/java/com/yfd/platform/config/ResponseResult.java b/src/main/java/com/yfd/platform/config/ResponseResult.java new file mode 100644 index 0000000..9638fcf --- /dev/null +++ b/src/main/java/com/yfd/platform/config/ResponseResult.java @@ -0,0 +1,57 @@ +package com.yfd.platform.config; + +import java.util.HashMap; + +public class ResponseResult extends HashMap { + private static final long serialVersionUID = 1L; + + public ResponseResult() { + } + + public static ResponseResult unlogin() { + return message("401", "未登录"); + } + + public static ResponseResult error() { + return error("操作失败"); + } + + public static ResponseResult success() { + return success("操作成功"); + } + + public static ResponseResult error(String msg) { + ResponseResult json = new ResponseResult(); + json.put((String)"code", "1");//错误 + json.put((String)"msg", msg); + return json; + } + + public static ResponseResult message(String code, String msg) { + ResponseResult json = new ResponseResult(); + json.put((String)"code", code); + json.put((String)"msg", msg); + return json; + } + + public static ResponseResult success(String msg) { + ResponseResult json = new ResponseResult(); + json.put((String)"code", "0");//正常 + json.put((String)"msg", msg); + return json; + } + + public static ResponseResult successData(Object obj) { + ResponseResult json = new ResponseResult(); + json.put((String)"code", "0");//正常 + json.put((String)"msg", "操作成功"); + json.put("data", obj); + return json; + } + + + public ResponseResult put(String key, Object value) { + super.put(key, value); + return this; + } +} diff --git a/src/main/java/com/yfd/platform/config/SecurityConfig.java b/src/main/java/com/yfd/platform/config/SecurityConfig.java new file mode 100644 index 0000000..f1e1cfa --- /dev/null +++ b/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -0,0 +1,91 @@ +package com.yfd.platform.config; + +import com.yfd.platform.config.bean.LoginProperties; +import com.yfd.platform.exception.AccessDeniedHandExcetion; +import com.yfd.platform.exception.AuthenticationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +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.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + @ConfigurationProperties(prefix = "login", ignoreUnknownFields = true) + public LoginProperties loginProperties() { + return new LoginProperties(); + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + + @Autowired + private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; + + @Autowired + private AuthenticationException authenticationException; + + @Autowired + private AccessDeniedHandExcetion accessDeniedHandExcetion; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .authorizeHttpRequests(auth -> auth + .requestMatchers("/user/login").anonymous() + .requestMatchers("/user/code").permitAll() + .requestMatchers(HttpMethod.GET, + "/*.html", + "/**/*.html", + "/**/*.css", + "/**/*.js", + "/webSocket/**").permitAll() + .requestMatchers( + "/swagger-ui.html", + "/swagger-ui/**", + "/v3/api-docs/**", + "/v3/api-docs.yaml", + "/swagger-resources/**", + "/webjars/**", + "/*/api-docs").permitAll() + .requestMatchers( + "/report/**", + "/images/**", + "/pageimage/**", + "/avatar/**", + "/systemurl/**", + "/api/imageserver/upload").permitAll() + .requestMatchers("/**/**").permitAll() + .anyRequest().authenticated() + ) + .cors(cors -> {}); + + http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + + http.exceptionHandling(ex -> ex + .authenticationEntryPoint(authenticationException) + .accessDeniedHandler(accessDeniedHandExcetion) + ); + + return http.build(); + } +} diff --git a/src/main/java/com/yfd/platform/config/SwaggerConfig.java b/src/main/java/com/yfd/platform/config/SwaggerConfig.java new file mode 100644 index 0000000..b92f09b --- /dev/null +++ b/src/main/java/com/yfd/platform/config/SwaggerConfig.java @@ -0,0 +1,50 @@ +package com.yfd.platform.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springdoc.core.models.GroupedOpenApi; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.Contact; + +/** + * Springdoc OpenAPI 配置 + */ +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI projectOpenAPI() { + return new OpenAPI() + .info(new Info() + .title("项目API 接口文档") + .version("3.0") + .description("") + .contact(new Contact().name("郑顺利").email("13910913995@163.com")) + ); + } + + @Bean + public GroupedOpenApi groupWebsiteApi() { + return GroupedOpenApi.builder() + .group("1. 深北莫网站") + .packagesToScan("com.yfd.platform.modules.sbmwebsitedb.controller") + .build(); + } + + @Bean + public GroupedOpenApi groupQuartzApi() { + return GroupedOpenApi.builder() + .group("2. 定时任务") + .packagesToScan("com.yfd.platform.modules.quartz.controller") + .build(); + } + + @Bean + public GroupedOpenApi groupSystemApi() { + return GroupedOpenApi.builder() + .group("3. 系统管理") + .packagesToScan("com.yfd.platform.system.controller") + .build(); + } +} diff --git a/src/main/java/com/yfd/platform/config/WebConfig.java b/src/main/java/com/yfd/platform/config/WebConfig.java new file mode 100644 index 0000000..c242a34 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/WebConfig.java @@ -0,0 +1,58 @@ +package com.yfd.platform.config; + +import cn.hutool.cache.Cache; +import cn.hutool.cache.CacheUtil; +import lombok.SneakyThrows; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Resource + private FileSpaceProperties fileSpaceProperties; + + + + @Bean + public Cache loginuserCache() { + return CacheUtil.newLRUCache(200);//用户登录缓存数 缺省200 + } + + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = + new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + config.addAllowedOriginPattern("*"); + config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + config.setMaxAge(3600L); + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } + + @SneakyThrows + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 菜单图标访问路径 + String iconUrl = "file:" + System.getProperty("user.dir") + "\\src" + + "\\main\\resources\\static\\icon\\"; + registry.addResourceHandler("/menu/**").addResourceLocations(iconUrl).setCachePeriod(0); + + registry.addResourceHandler("swagger-ui.html").addResourceLocations( + "classpath:/META-INF/resources/"); + + String systemUrl = "file:" + fileSpaceProperties.getSystem().replace("\\", "/")+"user\\"; + registry.addResourceHandler("/avatar/**").addResourceLocations(systemUrl).setCachePeriod(0); + + + } + +} diff --git a/src/main/java/com/yfd/platform/config/WebSocketConfig.java b/src/main/java/com/yfd/platform/config/WebSocketConfig.java new file mode 100644 index 0000000..349ead0 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/WebSocketConfig.java @@ -0,0 +1,16 @@ +package com.yfd.platform.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +@Configuration +public class WebSocketConfig { + + @Bean + public ServerEndpointExporter serverEndpointExporter() { + + return new ServerEndpointExporter(); + } +} + diff --git a/src/main/java/com/yfd/platform/config/bean/LoginCode.java b/src/main/java/com/yfd/platform/config/bean/LoginCode.java new file mode 100644 index 0000000..2a7586b --- /dev/null +++ b/src/main/java/com/yfd/platform/config/bean/LoginCode.java @@ -0,0 +1,61 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.bean; + +import lombok.Data; + +/** + * 登录验证码配置信息 + * + * @author: liaojinlong + * @date: 2020/6/10 18:53 + */ +@Data +public class LoginCode { + + /** + * 验证码配置 + */ + private LoginCodeEnum codeType; + /** + * 验证码有效期 分钟 + */ + private Long expiration = 2L; + /** + * 验证码内容长度 + */ + private int length = 2; + /** + * 验证码宽度 + */ + private int width = 111; + /** + * 验证码高度 + */ + private int height = 36; + /** + * 验证码字体 + */ + private String fontName; + /** + * 字体大小 + */ + private int fontSize = 25; + + public LoginCodeEnum getCodeType() { + return codeType; + } +} diff --git a/src/main/java/com/yfd/platform/config/bean/LoginCodeEnum.java b/src/main/java/com/yfd/platform/config/bean/LoginCodeEnum.java new file mode 100644 index 0000000..d9ade21 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/bean/LoginCodeEnum.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.bean; + +/** + * 验证码配置枚举 + * + * @author: liaojinlong + * @date: 2020/6/10 17:40 + */ + +public enum LoginCodeEnum { + /** + * 算数 + */ + arithmetic, + /** + * 中文 + */ + chinese, + /** + * 中文闪图 + */ + chinese_gif, + /** + * 闪图 + */ + gif, + spec +} diff --git a/src/main/java/com/yfd/platform/config/bean/LoginProperties.java b/src/main/java/com/yfd/platform/config/bean/LoginProperties.java new file mode 100644 index 0000000..b16644d --- /dev/null +++ b/src/main/java/com/yfd/platform/config/bean/LoginProperties.java @@ -0,0 +1,110 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version loginCode.length.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-loginCode.length.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.bean; + +import cn.hutool.core.util.StrUtil; +import com.wf.captcha.*; +import com.wf.captcha.base.Captcha; +import com.yfd.platform.exception.BadConfigurationException; +import lombok.Data; +import java.awt.*; +import java.util.Objects; + +/** + * 配置文件读取 + * + * @author liaojinlong + * @date loginCode.length0loginCode.length0/6/10 17:loginCode.length6 + */ +@Data +public class LoginProperties { + + /** + * 账号单用户 登录 + */ + private boolean singleLogin = false; + + private LoginCode loginCode; + /** + * 用户登录信息缓存 + */ + private boolean cacheEnable; + + public boolean isSingleLogin() { + return singleLogin; + } + + public boolean isCacheEnable() { + return cacheEnable; + } + + /** + * 获取验证码生产类 + * + * @return / + */ + public Captcha getCaptcha() { + if (Objects.isNull(loginCode)) { + loginCode = new LoginCode(); + if (Objects.isNull(loginCode.getCodeType())) { + loginCode.setCodeType(LoginCodeEnum.arithmetic); + } + } + return switchCaptcha(loginCode); + } + + /** + * 依据配置信息生产验证码 + * + * @param loginCode 验证码配置信息 + * @return / + */ + private Captcha switchCaptcha(LoginCode loginCode) { + Captcha captcha; + synchronized (this) { + switch (loginCode.getCodeType()) { + case arithmetic: + // 算术类型 https://gitee.com/whvse/EasyCaptcha + captcha = new ArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight()); + // 几位数运算,默认是两位 + captcha.setLen(loginCode.getLength()); + break; + case chinese: + captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + case chinese_gif: + captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + case gif: + captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + case spec: + captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight()); + captcha.setLen(loginCode.getLength()); + break; + default: + throw new BadConfigurationException("验证码配置信息错误!正确配置查看 LoginCodeEnum "); + } + } + if(StrUtil.isNotBlank(loginCode.getFontName())){ + captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize())); + } + return captcha; + } +} diff --git a/src/main/java/com/yfd/platform/config/thread/AsyncTaskExecutePool.java b/src/main/java/com/yfd/platform/config/thread/AsyncTaskExecutePool.java new file mode 100644 index 0000000..ff10654 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/thread/AsyncTaskExecutePool.java @@ -0,0 +1,70 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.thread; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 异步任务线程池装配类 + * @author https://juejin.im/entry/5abb8f6951882555677e9da2 + * @date 2019年10月31日15:06:18 + */ +@Slf4j +@Configuration +public class AsyncTaskExecutePool implements AsyncConfigurer { + + /** 注入配置类 */ + private final AsyncTaskProperties config; + + public AsyncTaskExecutePool(AsyncTaskProperties config) { + this.config = config; + } + + @Override + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + //核心线程池大小 + executor.setCorePoolSize(config.getCorePoolSize()); + //最大线程数 + executor.setMaxPoolSize(config.getMaxPoolSize()); + //队列容量 + executor.setQueueCapacity(config.getQueueCapacity()); + //活跃时间 + executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); + //线程名字前缀 + executor.setThreadNamePrefix("el-async-"); + // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 + // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return (throwable, method, objects) -> { + log.error("===="+throwable.getMessage()+"====", throwable); + log.error("exception method:"+method.getName()); + }; + } +} diff --git a/src/main/java/com/yfd/platform/config/thread/AsyncTaskProperties.java b/src/main/java/com/yfd/platform/config/thread/AsyncTaskProperties.java new file mode 100644 index 0000000..a5bc7d2 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/thread/AsyncTaskProperties.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.thread; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 线程池配置属性类 + * @author https://juejin.im/entry/5abb8f6951882555677e9da2 + * @date 2019年10月31日14:58:18 + */ +@Data +@Component +@ConfigurationProperties(prefix = "task.pool") +public class AsyncTaskProperties { + + private int corePoolSize; + + private int maxPoolSize; + + private int keepAliveSeconds; + + private int queueCapacity; +} diff --git a/src/main/java/com/yfd/platform/config/thread/TheadFactoryName.java b/src/main/java/com/yfd/platform/config/thread/TheadFactoryName.java new file mode 100644 index 0000000..118faba --- /dev/null +++ b/src/main/java/com/yfd/platform/config/thread/TheadFactoryName.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.thread; + +import org.springframework.stereotype.Component; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 自定义线程名称 + * @author + * @date 2019年10月31日17:49:55 + */ +@Component +public class TheadFactoryName implements ThreadFactory { + + private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1); + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + + public TheadFactoryName() { + this("el-pool"); + } + + private TheadFactoryName(String name){ + // 使用当前线程的线程组,避免依赖已弃用的 SecurityManager + group = Thread.currentThread().getThreadGroup(); + //此时namePrefix就是 name + 第几个用这个工厂创建线程池的 + this.namePrefix = name + + POOL_NUMBER.getAndIncrement(); + } + + @Override + public Thread newThread(Runnable r) { + //此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程 + Thread t = new Thread(group, r, + namePrefix + "-thread-"+threadNumber.getAndIncrement(), + 0); + if (t.isDaemon()) { + t.setDaemon(false); + } + if (t.getPriority() != Thread.NORM_PRIORITY) { + t.setPriority(Thread.NORM_PRIORITY); + } + return t; + } +} diff --git a/src/main/java/com/yfd/platform/config/thread/ThreadPoolExecutorUtil.java b/src/main/java/com/yfd/platform/config/thread/ThreadPoolExecutorUtil.java new file mode 100644 index 0000000..cb84cc4 --- /dev/null +++ b/src/main/java/com/yfd/platform/config/thread/ThreadPoolExecutorUtil.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.config.thread; + + + +import com.yfd.platform.utils.SpringContextHolder; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 用于获取自定义线程池 + * @author + * @date 2019年10月31日18:16:47 + */ +public class ThreadPoolExecutorUtil { + + public static ThreadPoolExecutor getPoll(){ + AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class); + return new ThreadPoolExecutor( + properties.getCorePoolSize(), + properties.getMaxPoolSize(), + properties.getKeepAliveSeconds(), + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(properties.getQueueCapacity()), + new TheadFactoryName() + ); + } +} diff --git a/src/main/java/com/yfd/platform/constant/Constant.java b/src/main/java/com/yfd/platform/constant/Constant.java new file mode 100644 index 0000000..c460999 --- /dev/null +++ b/src/main/java/com/yfd/platform/constant/Constant.java @@ -0,0 +1,42 @@ +package com.yfd.platform.constant; + +/** + * @author TangWei + * @Date: 2023/3/3 17:40 + * @Description: 常量类 + */ +public class Constant { + + public static final String LOGIN = "login:"; + public static final String TOKEN = "token:"; + public static final String USER_ID = "userid"; + public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + public static final String CODE_KEY = "code-key-"; + public static final long CODE_EXPIRATION_TIME = 1000 * 60; + /** + * 用于IP定位转换 + */ + public static final String REGION = "内网IP|内网IP"; + /** + * win 系统 + */ + public static final String WIN = "win"; + + /** + * mac 系统 + */ + public static final String MAC = "mac"; + + /** + * 常用接口 + */ + public static class Url { + + // IP归属地查询 + // public static final String IP_URL = "http://whois.pconline.com + // .cn/ipJson.jsp?ip=%s&json=true"; + public static final String IP_URL = "http://whois.pconline.com" + + ".cn/ipJson.jsp?ip=%s&json=true"; + } +} diff --git a/src/main/java/com/yfd/platform/datasource/DataSource.java b/src/main/java/com/yfd/platform/datasource/DataSource.java new file mode 100644 index 0000000..7c6d795 --- /dev/null +++ b/src/main/java/com/yfd/platform/datasource/DataSource.java @@ -0,0 +1,17 @@ +package com.yfd.platform.datasource; + +import java.lang.annotation.*; + +/****************************** + * 用途说明: + * 作者姓名: wxy + * 创建时间: 2022/9/23 17:48 + ******************************/ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataSource { + + String name() default ""; + +} diff --git a/src/main/java/com/yfd/platform/datasource/DataSourceAspect.java b/src/main/java/com/yfd/platform/datasource/DataSourceAspect.java new file mode 100644 index 0000000..f20c0f8 --- /dev/null +++ b/src/main/java/com/yfd/platform/datasource/DataSourceAspect.java @@ -0,0 +1,55 @@ +package com.yfd.platform.datasource; + +import cn.hutool.core.util.StrUtil; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +/****************************** + * 用途说明: + * 作者姓名: wxy + * 创建时间: 2022/9/23 17:50 + ******************************/ +@Aspect +@Component +public class DataSourceAspect { + + @Pointcut("@annotation(com.yfd.platform.datasource.DataSource)") + public void dataSourcePointCut() { + + } + + private String DataBaseName; + + @Around("dataSourcePointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable { + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + if (StrUtil.isNotBlank(DataBaseName)){ + DynamicDataSource.setDataSource(DataBaseName); + }else { + DynamicDataSource.setDataSource("master"); + } + + try { + return point.proceed(); + } finally { + DynamicDataSource.clearDataSource(); + } + } + + public String getDataBase(Integer type){ + if (type == 1){ + DataBaseName="master"; + }else { + DataBaseName="slave"; + } + return DataBaseName; + } + +} diff --git a/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java b/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java new file mode 100644 index 0000000..8b52521 --- /dev/null +++ b/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java @@ -0,0 +1,40 @@ +package com.yfd.platform.datasource; + +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +import javax.sql.DataSource; +import java.util.Map; + +/****************************** + * 用途说明: + * 作者姓名: wxy + * 创建时间: 2022/9/23 17:47 + ******************************/ +public class DynamicDataSource extends AbstractRoutingDataSource { + private static final ThreadLocal contextHolder = new ThreadLocal<>(); + + public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) { + super.setDefaultTargetDataSource(defaultTargetDataSource); + super.setTargetDataSources(targetDataSources); + super.afterPropertiesSet(); + } + + @Override + protected Object determineCurrentLookupKey() { + return getDataSource(); + } + + public static void setDataSource(String dataSource) { + contextHolder.set(dataSource); + } + + public static String getDataSource() { + return contextHolder.get(); + } + + public static void clearDataSource() { + contextHolder.remove(); + } + + +} diff --git a/src/main/java/com/yfd/platform/datasource/DynamicDataSourceConfig.java b/src/main/java/com/yfd/platform/datasource/DynamicDataSourceConfig.java new file mode 100644 index 0000000..fc4a972 --- /dev/null +++ b/src/main/java/com/yfd/platform/datasource/DynamicDataSourceConfig.java @@ -0,0 +1,38 @@ +package com.yfd.platform.datasource; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.Map; + +/****************************** + * 用途说明: + * 作者姓名: wxy + * 创建时间: 2022/9/23 17:45 + ******************************/ +@Configuration +@Component +public class DynamicDataSourceConfig { + + @Bean + @ConfigurationProperties("spring.datasource.druid.master") + public DataSource wglMasterDataSource(){ + return DruidDataSourceBuilder.create().build(); + } + + @Bean + @Primary + public DynamicDataSource dataSource(DataSource wglMasterDataSource, DataSource wglSlaveDataSource) { + Map targetDataSources = new HashMap<>(); + targetDataSources.put("master",wglMasterDataSource); + return new DynamicDataSource(wglMasterDataSource, targetDataSources); + } + + +} diff --git a/src/main/java/com/yfd/platform/exception/AccessDeniedHandExcetion.java b/src/main/java/com/yfd/platform/exception/AccessDeniedHandExcetion.java new file mode 100644 index 0000000..0bb0ed3 --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/AccessDeniedHandExcetion.java @@ -0,0 +1,27 @@ +package com.yfd.platform.exception; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +@Component +public class AccessDeniedHandExcetion implements AccessDeniedHandler { + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + JSONObject jobj=new JSONObject(); + jobj.putOnce("status","403"); + jobj.putOnce("msg","用户权限不足,不能访问"); + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().println(JSONUtil.toJsonStr(jobj)); + } +} diff --git a/src/main/java/com/yfd/platform/exception/AuthenticationException.java b/src/main/java/com/yfd/platform/exception/AuthenticationException.java new file mode 100644 index 0000000..15e8e97 --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/AuthenticationException.java @@ -0,0 +1,32 @@ +package com.yfd.platform.exception; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.yfd.platform.config.ResponseResult; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +@Component +public class AuthenticationException implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException { + JSONObject jobj=new JSONObject(); + if(authException.getMessage().equals("用户账号不存在!")){ + jobj.putOnce("code","401"); + jobj.putOnce("msg","用户账号不存在/密码错误,登录失败!"); + }else{ + jobj.putOnce("code","401"); + jobj.putOnce("msg","用户Token失效,请重新登录!"); + } + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().println(JSONUtil.toJsonStr(jobj)); + } +} diff --git a/src/main/java/com/yfd/platform/exception/BadConfigurationException.java b/src/main/java/com/yfd/platform/exception/BadConfigurationException.java new file mode 100644 index 0000000..92ffac0 --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/BadConfigurationException.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.exception; + +/** + * 统一关于错误配置信息 异常 + * + * @author: liaojinlong + * @date: 2020/6/10 18:06 + */ +public class BadConfigurationException extends RuntimeException { + /** + * Constructs a new runtime exception with {@code null} as its + * detail message. The cause is not initialized, and may subsequently be + * initialized by a call to {@link #initCause}. + */ + public BadConfigurationException() { + super(); + } + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public BadConfigurationException(String message) { + super(message); + } + + /** + * Constructs a new runtime exception with the specified detail message and + * cause.

Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public BadConfigurationException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new runtime exception with the specified cause and a + * detail message of {@code (cause==null ? null : cause.toString())} + * (which typically contains the class and detail message of + * {@code cause}). This constructor is useful for runtime exceptions + * that are little more than wrappers for other throwables. + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public BadConfigurationException(Throwable cause) { + super(cause); + } + + /** + * Constructs a new runtime exception with the specified detail + * message, cause, suppression enabled or disabled, and writable + * stack trace enabled or disabled. + * + * @param message the detail message. + * @param cause the cause. (A {@code null} value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @param enableSuppression whether or not suppression is enabled + * or disabled + * @param writableStackTrace whether or not the stack trace should + * be writable + * @since 1.7 + */ + protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/com/yfd/platform/exception/BadRequestException.java b/src/main/java/com/yfd/platform/exception/BadRequestException.java new file mode 100644 index 0000000..f2202ec --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/BadRequestException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +/** + * @author + * @date 2018-11-23 + * 统一异常处理 + */ +@Getter +public class BadRequestException extends RuntimeException{ + + private Integer status = BAD_REQUEST.value(); + + public BadRequestException(String msg){ + super(msg); + } + + public BadRequestException(HttpStatus status, String msg){ + super(msg); + this.status = status.value(); + } +} diff --git a/src/main/java/com/yfd/platform/exception/ChildrenExistException.java b/src/main/java/com/yfd/platform/exception/ChildrenExistException.java new file mode 100644 index 0000000..18eca34 --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/ChildrenExistException.java @@ -0,0 +1,20 @@ +package com.yfd.platform.exception; + +import org.springframework.util.StringUtils; + +/** + * @Author pcj + * @Date 2021/1/26 9:07 + * @Version 1.0 + */ +public class ChildrenExistException extends RuntimeException{ + + public ChildrenExistException(Class clazz, String field, String val) { + super(ChildrenExistException.generateMessage(clazz.getSimpleName(), field, val)); + } + + private static String generateMessage(String entity, String field, String val) { + return StringUtils.capitalize(entity) + + " with " + field + " "+ val + " Children Exist"; + } +} diff --git a/src/main/java/com/yfd/platform/exception/EntityExistException.java b/src/main/java/com/yfd/platform/exception/EntityExistException.java new file mode 100644 index 0000000..028aeed --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/EntityExistException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.exception; + +import org.springframework.util.StringUtils; + +/** + * @author + * @date 2018-11-23 + */ +public class EntityExistException extends RuntimeException { + + public EntityExistException(Class clazz, String field, String val) { + super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val)); + } + + private static String generateMessage(String entity, String field, String val) { + return StringUtils.capitalize(entity) + + " with " + field + " "+ val + " existed"; + } +} \ No newline at end of file diff --git a/src/main/java/com/yfd/platform/exception/EntityNotFoundException.java b/src/main/java/com/yfd/platform/exception/EntityNotFoundException.java new file mode 100644 index 0000000..8f5e1c5 --- /dev/null +++ b/src/main/java/com/yfd/platform/exception/EntityNotFoundException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.exception; + +import org.springframework.util.StringUtils; + +/** + * @author + * @date 2018-11-23 + */ +public class EntityNotFoundException extends RuntimeException { + + public EntityNotFoundException(Class clazz, String field, String val) { + super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val)); + } + + private static String generateMessage(String entity, String field, String val) { + return StringUtils.capitalize(entity) + + " with " + field + " "+ val + " does not exist"; + } +} \ No newline at end of file diff --git a/src/main/java/com/yfd/platform/system/controller/DataSourceController.java b/src/main/java/com/yfd/platform/system/controller/DataSourceController.java new file mode 100644 index 0000000..b34b37c --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/DataSourceController.java @@ -0,0 +1,42 @@ +package com.yfd.platform.system.controller; + +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.datasource.DataSource; +import com.yfd.platform.datasource.DataSourceAspect; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.annotation.Resource; + +/** + * @author zhengsl + * @since 2022-09-20 + */ +@RestController +@RequestMapping("/system") +@Tag(name = "切换数据库") +public class DataSourceController { + + @Resource + DataSourceAspect dataSourceAspect; + + /** + * 切换数据库 + * + * @DataSource(name="master") 可以通过注解方式切换数据库 + */ + @GetMapping("/changeDataSource") + @Operation(summary = "切换数据库") + public ResponseResult changeDataSource(Integer type) { + if (type == null) { + return ResponseResult.error("参数为空"); + } + String dataBase = dataSourceAspect.getDataBase(type); + String mess = "已切换为" + dataBase + "数据库"; + return ResponseResult.success(mess); + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/LoginController.java b/src/main/java/com/yfd/platform/system/controller/LoginController.java new file mode 100644 index 0000000..78d66e6 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/LoginController.java @@ -0,0 +1,238 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import cn.hutool.jwt.JWTUtil; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.wf.captcha.base.Captcha; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.config.WebConfig; +import com.yfd.platform.config.bean.LoginCodeEnum; +import com.yfd.platform.config.bean.LoginProperties; +import com.yfd.platform.constant.Constant; +import com.yfd.platform.system.domain.LoginUser; +import com.yfd.platform.system.domain.SysLog; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.service.ISysLogService; +import com.yfd.platform.system.service.IUserService; +import com.yfd.platform.utils.RequestHolder; +import com.yfd.platform.utils.RsaUtils; +import com.yfd.platform.utils.StringUtils; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; + +/** + * @author TangWei + */ +@RestController +@RequestMapping("/user") +@Tag(name = "用户登录") +public class LoginController { + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private WebConfig webConfig; + + @Resource + private IUserService userService; + + @Value("${rsa.private_key}") + private String privateKey; + + @Resource + private ISysLogService sysLogService; + + @Resource + private LoginProperties loginProperties; + + @PostMapping("/login") + @Operation(summary = "登录用户") + @ResponseBody + public ResponseResult login(SysUser user) throws Exception { + // 密码解密 + String password = RsaUtils.decryptByPrivateKey(privateKey, + user.getPassword()); + + // 是否需要验证码不需要改成false + boolean hascode = false; + if (hascode) { + // 查询验证码 + String code = webConfig.loginuserCache().get(user.getUuid()); + // 清除验证码 + webConfig.loginuserCache().remove(user.getUuid()); + if (StrUtil.isBlank(code)) { + return ResponseResult.error("验证码不存在或已过期"); + } + if (StrUtil.isBlank(user.getCode()) || !user.getCode().equalsIgnoreCase(code)) { + return ResponseResult.error("验证码错误"); + } + } + //如果认证通过了,使用userId生成token token存入ResponseResult返回 + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(user.getUsername(), + password); + Authentication authenticate = + authenticationManager.authenticate(authenticationToken); + if (ObjectUtil.isNull(authenticate)) { + return ResponseResult.unlogin(); + } + LoginUser loginUser = (LoginUser) authenticate.getPrincipal(); + Integer status = loginUser.getUser().getStatus(); + if ("0".equals(status.toString())) { + return ResponseResult.error("账号已停用"); + } + HttpServletRequest request = RequestHolder.getHttpServletRequest(); + SysLog sysLog = new SysLog(); + sysLog.setUsercode(user.getUsername()); + sysLog.setUsername(loginUser.getUser().getNickname()); + sysLog.setRequestip(StringUtils.getIp(request)); + sysLog.setBrowser(StringUtils.getBrowser(request)); + sysLog.setOpttype("登录(login)"); + sysLog.setModule("用户登录"); + String className = this.getClass().getName(); + String method = + Thread.currentThread().getStackTrace()[1].getMethodName(); + sysLog.setMethod(className + "." + method + "()"); + //sysLog.setParams(user.toString()); + sysLog.setDescription(loginUser.getUser().getNickname() + "登录系统!"); + sysLog.setLogtime(new Timestamp(System.currentTimeMillis())); + sysLogService.save(sysLog); + String userId = loginUser.getUser().getId(); + Map map = new HashMap(10) { + private static final long serialVersionUID = 1L; + + { + put("userid", userId); + put("username", loginUser.getUsername()); + long expireTime = + System.currentTimeMillis() + (long) (30L * 24L * 60L * 60L * 1000L); + put("expire_time", expireTime);//个月过期 + } + }; + + String token = JWTUtil.createToken(map, "12345678".getBytes()); + map.put("token", token); + //把完整的用户信息存入到HuTool缓存中,userId作为key + String jsonStr = JSONUtil.toJsonStr(loginUser); + webConfig.loginuserCache().put("login:" + userId, jsonStr); + webConfig.loginuserCache().put("expire_time:" + userId, map.get("expire_time").toString()); + return ResponseResult.successData(map); + } + + @Operation(summary = "获取验证码") + @GetMapping(value = "/code") + public ResponseResult getCode() { + // 获取运算的结果 + Captcha captcha = loginProperties.getCaptcha(); + String uuid = Constant.CODE_KEY + IdUtil.simpleUUID(); + //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型 + String captchaValue = captcha.text(); + if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(".")) { + captchaValue = captchaValue.split("\\.")[0]; + } + // 保存 + //redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode() + // .getExpiration(), TimeUnit.MINUTES); + // 将验证码放入缓存,设置失效时间为60秒 + webConfig.loginuserCache().put(uuid, captchaValue, + Constant.CODE_EXPIRATION_TIME); + // 验证码信息 + Map imgResult = new HashMap(2) {{ + put("img", captcha.toBase64()); + put("uuid", uuid); + }}; + return ResponseResult.successData(imgResult); + } + + @PostMapping("/logout") + @Operation(summary = "退出登录") + @ResponseBody + public ResponseResult logout() { + //获取SecurityContextHolder中的用户id + UsernamePasswordAuthenticationToken authentication = + (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginuser = (LoginUser) authentication.getPrincipal(); + String userId = loginuser.getUser().getId(); + //删除redis中的登陆用户信息 + webConfig.loginuserCache().remove("login:" + userId); + //记录退出日志 + HttpServletRequest request = RequestHolder.getHttpServletRequest(); + SysLog sysLog = new SysLog(); + sysLog.setUsercode(loginuser.getUsername()); + sysLog.setUsername(loginuser.getUser().getNickname()); + sysLog.setRequestip(StringUtils.getIp(request)); + sysLog.setBrowser(StringUtils.getBrowser(request)); + sysLog.setOpttype("其他(other)"); + sysLog.setModule("注销退出"); + sysLog.setDescription("注销退出系统!"); + sysLog.setLogtime(new Timestamp(System.currentTimeMillis())); + sysLogService.save(sysLog); + return ResponseResult.success(); + } + + @Log(module = "用户登录", value = "更改用户密码") + @GetMapping("/updatePassword") + @Operation(summary = "更改用户密码") + @ResponseBody + public ResponseResult updatePassword(@RequestBody SysUser user) throws Exception { + // 密码解密 + String password = RsaUtils.decryptByPrivateKey(privateKey, + user.getPassword()); + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + String cryptPassword = passwordEncoder.encode(password); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.set("password", cryptPassword); + updateWrapper.eq("id", user.getId()); + userService.update(updateWrapper); + return ResponseResult.success(); + } + + @GetMapping("/me") + @Operation(summary = "查询当前用户信息") + @ResponseBody + public ResponseResult getUserInfo() { + ResponseResult responseResult = userService.getLoginUserInfo(); + return ResponseResult.successData(responseResult); + } + + @Log(module = "用户登录", value = "修改个人信息") + @PostMapping("/updatePersonalInfo") + @Operation(summary = "修改个人信息") + @ResponseBody + public ResponseResult updateUser(@org.springframework.web.bind.annotation.RequestBody SysUser user) { + if (StrUtil.isEmpty(user.getId())) { + return ResponseResult.error("没有用户ID"); + } + //填写 当前用户名称 + user.setLastmodifier(userService.getUsername()); + //填写 当前日期 + user.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + boolean ok = userService.updateById(user); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/MessageController.java b/src/main/java/com/yfd/platform/system/controller/MessageController.java new file mode 100644 index 0000000..58f61ba --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/MessageController.java @@ -0,0 +1,150 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.MessageConfig; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.config.WebConfig; +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.service.IMessageService; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.util.*; + +/** + *

+ * 消息通知 前端控制器 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +@RestController +@RequestMapping("/system/message") +@Tag(name = "消息通知") +public class MessageController { + + @Resource + private IMessageService messageService; + + @Resource + private MessageConfig messageConfig; + + @Operation(summary = "查询消息") + @GetMapping("/getMessageList") + public ResponseResult getMessageList(Page page, + String status, String title, + String type, String startDate, + String endDate) { + if (StrUtil.isBlank(status)) { + return ResponseResult.error("参数为空"); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if ("0".equals(status)) { + queryWrapper.eq(Message::getStatus, "1"); + } else { + List statusList = new ArrayList<>(); + statusList.add("2"); + statusList.add("9"); + queryWrapper.in(Message::getStatus, statusList); + + if (StrUtil.isNotBlank(title)) { + queryWrapper.like(Message::getTitle, title); + } + + if (StrUtil.isNotBlank(type)) { + queryWrapper.eq(Message::getType, type); + } + + DateTime parseStartDate = DateUtil.parse(startDate); + DateTime parseEndDate = DateUtil.parse(endDate); + DateTime dateTime = DateUtil.offsetDay(parseEndDate, 1); + + if (parseStartDate != null && parseEndDate != null) { + queryWrapper.ge(Message::getCreatetime, parseStartDate).lt(Message::getCreatetime, dateTime); + } + } + queryWrapper.orderByDesc(Message::getCreatetime); + Page pageList = messageService.page(page, queryWrapper); + return ResponseResult.successData(pageList); + } + + @Operation(summary = "根据ID查询消息") + @GetMapping("/getMessageById") + public ResponseResult getMessageById(String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + Message message = messageService.getById(id); + Map map = new HashMap<>(); + map.put("title", message.getTitle()); + map.put("content", message.getContent()); + map.put("createtime", message.getCreatetime()); + return ResponseResult.successData(map); + } + + @Log(module = "消息通知",value = "根据ID删除消息") + @Operation(summary = "根据ID删除消息") + @PostMapping("/deleteMessageById") + public ResponseResult deleteMessageById(@RequestParam String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + String[] split = id.split(","); + List idList = Arrays.asList(split); + boolean ok = messageService.removeByIds(idList); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error("删除失败"); + } + + } + + @Log(module = "消息通知", value = "将消息标记为已阅状态") + @Operation(summary = "标记已阅") + @PostMapping("/setMessageStatus") + public ResponseResult setMessageStatus(@RequestParam String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + String[] split = id.split(","); + long time = System.currentTimeMillis(); + for (String mid : split) { + Message message = messageService.getById(mid); + if ("9".equals(message.getStatus())) { + continue; + } + message.setStatus("2"); + message.setReadtime(new Timestamp(time)); + messageService.updateById(message); + } + messageConfig.sendMessage(); + return ResponseResult.success(); + } + + @Operation(summary = "全部已阅") + @PostMapping("/setAllMessageStatus") + public ResponseResult setAllMessageStatus() { + long time = System.currentTimeMillis(); + List list = + messageService.list(new LambdaQueryWrapper().eq(Message::getStatus, "1")); + for (Message message : list) { + message.setStatus("2"); + message.setReadtime(new Timestamp(time)); + messageService.updateById(message); + } + messageConfig.sendMessage(); + return ResponseResult.success(); + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/QuartzJobController.java b/src/main/java/com/yfd/platform/system/controller/QuartzJobController.java new file mode 100644 index 0000000..9da6c89 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/QuartzJobController.java @@ -0,0 +1,183 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.QuartzJob; +import com.yfd.platform.system.service.IQuartzJobService; +import com.yfd.platform.system.service.impl.UserServiceImpl; +import com.yfd.platform.utils.QuartzManage; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.quartz.CronExpression; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.time.LocalDateTime; + +/** + *

+ * 定时任务 前端控制器 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +@RestController +@RequestMapping("/system/quartzjob") +@Tag(name = "定时任务") +@Transactional +public class QuartzJobController { + + @Resource + private IQuartzJobService quartzJobService; + + @Resource + private UserServiceImpl currentUser; + + @Resource + private QuartzManage quartzManage; + + @Operation(summary = "查询定时任务") + @GetMapping("/getQuartzJobList") + public ResponseResult getQuartzJobList(Page page, + String jobName) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(jobName)) { + queryWrapper.like(QuartzJob::getJobName, jobName); + } + queryWrapper.orderByAsc(QuartzJob::getOrderno); + Page pageList = quartzJobService.page(page, queryWrapper); + return ResponseResult.successData(pageList); + } + + @Log(module = "定时任务管理", value = "新增定时任务") + @Operation(summary = "新增定时任务") + @PostMapping("/addQuartzJob") + public ResponseResult addQuartzJob(@RequestBody QuartzJob quartzJob) { + if (quartzJob == null) { + return ResponseResult.error("参数为空"); + } + // 添加最近修改人 + quartzJob.setLastmodifier(currentUser.getUsername()); + // 添加最近修改时间 + quartzJob.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + if (StrUtil.isBlank(quartzJob.getJobCron()) || !CronExpression.isValidExpression(quartzJob.getJobCron())) { + return ResponseResult.error("cron表达式格式错误"); + } + quartzJob.setStatus("0"); + boolean ok = quartzJobService.addQuartzJob(quartzJob); + quartzManage.addJob(quartzJob); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error("新增失败"); + } + } + + @Log(module = "定时任务管理", value = "设置定时任务是否有效") + @Operation(summary = "设置定时任务是否有效") + @PostMapping("/setQuartzStatus") + public ResponseResult setQuartzStatus(@RequestParam String id, + @RequestParam String status) { + if (StrUtil.isBlank(id) || StrUtil.isBlank(status)) { + return ResponseResult.error("参数为空"); + } + LambdaUpdateWrapper updateWrapper = + new LambdaUpdateWrapper<>(); + //根据id 更新状态,最近修改人,最近修改时间 + updateWrapper.eq(QuartzJob::getId, id).set(QuartzJob::getStatus, + status).set( + QuartzJob::getLastmodifier, currentUser.getUsername()).set(QuartzJob::getLastmodifydate, + LocalDateTime.now()); + boolean ok = quartzJobService.update(updateWrapper); + QuartzJob quartzJob = quartzJobService.getById(id); + if ("0".equals(quartzJob.getStatus())) { + quartzManage.pauseJob(quartzJob); + } else { + quartzManage.resumeJob(quartzJob); + } + + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + @Operation(summary = "根据ID查询定时任务") + @GetMapping("/getQuartzJobById") + public ResponseResult getQuartzJobById(String id) { + QuartzJob quartzJob = quartzJobService.getById(id); + return ResponseResult.successData(quartzJob); + } + + @Log(module = "定时任务管理", value = "修改定时任务") + @Operation(summary = "修改定时任务") + @PostMapping("/updateQuartzJob") + @Transactional(rollbackFor = Exception.class) + public ResponseResult updateQuartzJob(@RequestBody QuartzJob quartzJob) { + // 添加最近修改人 + quartzJob.setLastmodifier(currentUser.getUsername()); + // 添加最近修改时间 + quartzJob.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + if (StrUtil.isBlank(quartzJob.getJobCron()) || !CronExpression.isValidExpression(quartzJob.getJobCron())) { + return ResponseResult.error("cron表达式格式错误"); + } + boolean ok = quartzJobService.updateById(quartzJob); + quartzManage.updateJobCron(quartzJob); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error("修改失败"); + } + } + + @Log(module = "定时任务管理", value = "删除定时任务") + @Operation(summary = "删除定时任务") + @PostMapping("/deleteQuartzJob") + public ResponseResult deleteQuartzJob(@RequestParam String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + boolean ok = quartzJobService.deleteQuartzJob(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error("删除失败"); + } + } + + @Log(module = "定时任务管理", value = "执行定时任务") + @Operation(summary = "执行定时任务") + @PostMapping("/execution") + public ResponseResult execution(@RequestParam String id) { + quartzJobService.execution(quartzJobService.getById(id)); + return ResponseResult.success(); + } + + /********************************** + * 用途说明: 拖动修改定时顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 成功或者失败 + ***********************************/ + @Log(module = "定时任务管理", value = "拖动定时任务") + @PostMapping("/changeDictOrder") + @Operation(summary = "拖动修改定时任务顺序") + public ResponseResult changeQuartzOrder(@RequestParam String fromID, + @RequestParam String toID) { + + boolean ok = quartzJobService.changeDictOrder(fromID, toID); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + + } +} diff --git a/src/main/java/com/yfd/platform/system/controller/SSEController.java b/src/main/java/com/yfd/platform/system/controller/SSEController.java new file mode 100644 index 0000000..41adfbb --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SSEController.java @@ -0,0 +1,59 @@ +package com.yfd.platform.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yfd.platform.component.ServerSendEventServer; +import com.yfd.platform.config.WebConfig; +import com.yfd.platform.constant.Constant; +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.service.IMessageService; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import jakarta.annotation.Resource; + +/** + * @author Huhailong + */ +@Slf4j +@RestController +@CrossOrigin +@RequestMapping("/sse") +@Tag(name = "SSE推送服务") +public class SSEController { + + @Resource + private IMessageService messageService; + + @GetMapping("/connect/{token}") + @Operation(summary = "建立连接") + public SseEmitter connect(@PathVariable String token) { + SseEmitter connect = ServerSendEventServer.connect(token); + long count = + messageService.count(new LambdaQueryWrapper().eq(Message::getStatus, "1")); + ServerSendEventServer.sendMessage(token, count + ""); + return connect; + } + + @GetMapping("/sendmsg") + @Operation(summary = "发送消息") + public void sendMessage(String token, String message) throws InterruptedException { + + ServerSendEventServer.sendMessage(token, message); + } + + @GetMapping("/sendgroupmsg") + @Operation(summary = "多人发送消息") + public void sendgroupmsg(String groupid, String message) throws InterruptedException { + ServerSendEventServer.groupSendMessage(groupid, message); + } + + @GetMapping("/disconnect/{token}") + @Operation(summary = "关闭连接") + public void disconnect(@PathVariable String token) throws InterruptedException { + ServerSendEventServer.removeUser(token); + } +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysConfigController.java b/src/main/java/com/yfd/platform/system/controller/SysConfigController.java new file mode 100644 index 0000000..3cfa7cc --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysConfigController.java @@ -0,0 +1,68 @@ +package com.yfd.platform.system.controller; + + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysConfig; +import com.yfd.platform.system.service.ISysConfigService; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.IOException; +import java.sql.Timestamp; + + +/** + *

+ * 系统全局配置 前端控制器 + *

+ * + * @author zhengsl + * @since 2022-01-19 + */ +@RestController + @RequestMapping("/system/config") +@Tag(name = "系统全局配置") +public class SysConfigController { + @Resource + private ISysConfigService configService; + + @Resource + private IUserService userService; + + @PostMapping("/getOneById") + @Operation(summary = "根据id查询全局配置详情记录") + @ResponseBody + public SysConfig getOneById(String id){ + return configService.getById(id); + } + + @PostMapping("/addConfig") + @Operation(summary = "根据id查询全局配置详情记录") + @ResponseBody + public ResponseResult addConfig(@RequestBody SysConfig config ) throws IOException, UnsupportedAudioFileException { + if (StrUtil.isEmpty(config.getId())){ + config.setId(IdUtil.fastSimpleUUID()); } + config.setLastmodifier(userService.getUsername()); + config.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + boolean ok=configService.save(config); + return ResponseResult.success(); + } + + @PostMapping("/updateById") + @Operation(summary = "根据id修改全局配置记录") + @ResponseBody + public ResponseResult updateById(@RequestBody SysConfig config) throws IOException, UnsupportedAudioFileException { + config.setLastmodifier(userService.getUsername()); + config.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + boolean ok=configService.updateById(config); + return ResponseResult.success(); + } + + +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysDictionaryController.java b/src/main/java/com/yfd/platform/system/controller/SysDictionaryController.java new file mode 100644 index 0000000..70a5fdf --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysDictionaryController.java @@ -0,0 +1,142 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysDictionary; +import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; +import com.yfd.platform.system.service.ISysDictionaryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.util.List; +import java.util.Objects; + +/** + *

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

+ * + * @author TangWei + * @since 2023-03-08 + */ +@RestController +@RequestMapping("/system/dictionary") +@Tag(name = "数据字典") +public class SysDictionaryController { + + @Resource + private ISysDictionaryService sysDictionaryService; + + /********************************** + * 用途说明: 获取数据字典列表 + * 参数说明 dictType 字典类型 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + @GetMapping("/dictList") + @Operation(summary = "获取数据字典列表") + public ResponseResult getDictList(String dictType) { + if (StrUtil.isBlank(dictType)) { + return ResponseResult.error("参数为空"); + } + List sysDictionaries = + sysDictionaryService.getDictList(dictType); + return ResponseResult.successData(sysDictionaries); + } + + /********************************** + * 用途说明: 根据ID删除字典 + * 参数说明 id 字典ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除结果成功或者失败 + ***********************************/ + @Log(module = "数据字典", value = "根据ID删除字典") + @PostMapping("/deleteById") + @Operation(summary = "根据ID删除字典") + public ResponseResult deleteDictById(@RequestParam String id) { + boolean ok = sysDictionaryService.deleteDictById(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 新增字典 + * 参数说明 sysDictionary 字典对象 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败 + ***********************************/ + @Log(module = "数据字典", value = "新增数据字典") + @PostMapping("/addDict") + @Operation(summary = "新增字典") + public ResponseResult addDict(@RequestBody SysDictionary sysDictionary) { + if (sysDictionary == null) { + return ResponseResult.error("参数为空"); + } + boolean ok = sysDictionaryService.addDict(sysDictionary); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 修改字典 + * 参数说明 sysDictionary 字典对象 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败 + ***********************************/ + @Log(module = "数据字典", value = "修改数据字典") + @PostMapping("/updateDict") + @Operation(summary = "修改字典") + public ResponseResult updateDict(@RequestBody SysDictionary sysDictionary) { + if (sysDictionary == null) { + return ResponseResult.error("参数为空"); + } + boolean ok = sysDictionaryService.updateById(sysDictionary); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 根据ID查询字典 + * 参数说明 sysDictionary 字典对象 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回查询结果 + ***********************************/ + @PostMapping("/getDictById") + @Operation(summary = "根据ID查询字典") + public ResponseResult getDictById(String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + SysDictionary sysDictionary = sysDictionaryService.getById(id); + return ResponseResult.successData(sysDictionary); + } + + /********************************** + * 用途说明: 拖动修改字典顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + @Log(module = "数据字典", value = "拖动修改字典顺序") + @PostMapping("/changeDictOrder") + @Operation(summary = "拖动修改字典顺序") + public ResponseResult changeDictOrder(@RequestParam String fromID, + @RequestParam String toID) { + + boolean ok = sysDictionaryService.changeDictOrder(fromID, toID); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysDictionaryItemsController.java b/src/main/java/com/yfd/platform/system/controller/SysDictionaryItemsController.java new file mode 100644 index 0000000..bf85d30 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysDictionaryItemsController.java @@ -0,0 +1,201 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysDictionaryItems; +import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; +import com.yfd.platform.system.service.ISysDictionaryItemsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.List; + +/** + *

+ * 数据字典明细 前端控制器 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@RestController +@RequestMapping("/system/dictionaryItems") +@Tag(name = "数据字典项") +public class SysDictionaryItemsController { + + @Resource + private ISysDictionaryItemsService sysDictionaryItemsService; + + /********************************** + * 用途说明: 分页查询字典项信息 + * 参数说明 dictID 字典ID ItemName 字典项名称 pageNum 当前页 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + @GetMapping("/page") + @Operation(summary = "分页查询字典项信息") + public ResponseResult getDictItemPage(String dictId, String dictName, + Page page) { + + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + queryWrapper.eq(SysDictionaryItems::getDictId, dictId).orderByAsc(SysDictionaryItems::getOrderNo); + + // 查询前将序号初始化 + List list = + sysDictionaryItemsService.list(queryWrapper); + for (int i = 0; i < list.size(); i++) { + SysDictionaryItems sysDictionaryItems = list.get(i); + sysDictionaryItems.setOrderNo(i + 1); + sysDictionaryItemsService.updateById(sysDictionaryItems); + } + Page sysDictionaryItemsPage = + sysDictionaryItemsService.getDictItemPage(dictId, dictName, + page); + + return ResponseResult.successData(sysDictionaryItemsPage); + } + + /********************************** + * 用途说明: 增加字典项 + * 参数说明 sysDictionaryItems 字典项信息 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败 + ***********************************/ + @Log(module = "数据字典项", value = "增加字典项") + @PostMapping("/addDictionaryItem") + @Operation(summary = "增加字典项") + public ResponseResult addDictionaryItem(@RequestBody SysDictionaryItems sysDictionaryItems) { + if (sysDictionaryItems == null) { + return ResponseResult.error("参数为空"); + } + boolean ok = + sysDictionaryItemsService.addDictionaryItem(sysDictionaryItems); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 修改字典项 + * 参数说明 sysDictionaryItems 字典项信息 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败 + ***********************************/ + @Log(module = "数据字典项", value = "修改字典项") + @PostMapping("/updateDictionaryItem") + @Operation(summary = "修改字典项") + public ResponseResult updateDictionaryItem(@RequestBody SysDictionaryItems sysDictionaryItems) { + if (sysDictionaryItems == null) { + return ResponseResult.error("参数为空"); + } + boolean ok = + sysDictionaryItemsService.updateById(sysDictionaryItems); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 根据ID查询字典项 + * 参数说明 id 字典项ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回字典项信息 + ***********************************/ + @GetMapping("/getDictItemById") + @Operation(summary = "根据ID查询字典项") + public ResponseResult getDictItemById(String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + SysDictionaryItems sysDictionaryItems = + sysDictionaryItemsService.getById(id); + return ResponseResult.successData(sysDictionaryItems); + } + + /********************************** + * 用途说明: 根据ID删除字典项 + * 参数说明 id 字典项ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败 + ***********************************/ + @Log(module = "数据字典项", value = "根据ID删除字典项") + @PostMapping("/deleteDictItemById") + @Operation(summary = "根据ID删除字典项") + public ResponseResult deleteDictItemById(@RequestParam String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + boolean ok = sysDictionaryItemsService.removeById(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 批量删除字典项 + * 参数说明 ids 字典项id数组 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败 + ***********************************/ + @Log(module = "数据字典项", value = "批量删除字典项") + @PostMapping("/deleteDictItemByIds") + @Operation(summary = "批量删除字典项") + public ResponseResult deleteDictItemByIds(@RequestParam String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + String[] splitIds = id.split(","); + // 数组转集合 + List ids = Arrays.asList(splitIds); + boolean ok = sysDictionaryItemsService.removeByIds(ids); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 拖动修改字典项顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + @Log(module = "数据字典项", value = "拖动修改字典项顺序") + @PostMapping("/changeItemOrder") + @Operation(summary = "拖动修改字典项顺序") + public ResponseResult changeItemOrder(@RequestParam String fromID, + @RequestParam String toID) { + boolean ok = sysDictionaryItemsService.changeItemOrder(fromID, toID); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 导出数据字典项数据 + * 参数说明 sysDictionaryItemsList 所需导出的字典项集合 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回导出成功或失败 + ***********************************/ + @Log(module = "数据字典项", value = "导出字典数据到Excel") + @GetMapping("/exportExcel") + @Operation(summary = "导出数据字典项数据") + public void exportExcel(String dictID, String itemName, + Page page, + HttpServletResponse response) { + Page sysDictionaryItemsPage = + sysDictionaryItemsService.getDictItemPage(dictID, itemName, + page); + sysDictionaryItemsService.exportExcel(sysDictionaryItemsPage.getRecords(), response); + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysLogController.java b/src/main/java/com/yfd/platform/system/controller/SysLogController.java new file mode 100644 index 0000000..9f2081a --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysLogController.java @@ -0,0 +1,74 @@ +package com.yfd.platform.system.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysLog; +import com.yfd.platform.system.service.ISysLogService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统操作日志 前端控制器 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@RestController +@RequestMapping("/system/log") +@Tag(name = "系统日志") +public class SysLogController { + + @Resource + private ISysLogService sysLogService; + + /********************************** + * 用途说明: 分页查询日志信息 + * 参数说明 page分页对象、username(用户名)、(optType) + * 操作类型、startDate(开始日期)、endDate(结束日期) + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + @PostMapping("/getLogList") + @Operation(summary = "分页查询日志信息") + public ResponseResult getLogList(String username, String optType, + String startDate, + String endDate, Page page) { + + Page sysLogPage = sysLogService.getLogList(username, optType, + startDate, endDate, page); + Map map = new HashMap<>(); + map.put("list", sysLogPage.getRecords()); + map.put("total", sysLogPage.getTotal()); + map.put("size", sysLogPage.getSize()); + map.put("current", sysLogPage.getCurrent()); + return ResponseResult.successData(map); + } + + /********************************** + * 用途说明: 导出日志数据 + * 参数说明 sysLogs 所需导出的字典项集合 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回导出成功或者失败 + ***********************************/ + @Log(module = "系统日志", value = "导出系统日志到Excel") + @GetMapping("/exportExcel") + @Operation(summary = "导出日志数据") + public void exportExcel(String username, String optType, + String startDate, + String endDate, Page page, + HttpServletResponse response) throws IOException { + + Page sysLogPage = sysLogService.getLogList(username, optType, + startDate, endDate, page); + sysLogService.exportExcel(sysLogPage.getRecords(), response); + } +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysMenuController.java b/src/main/java/com/yfd/platform/system/controller/SysMenuController.java new file mode 100644 index 0000000..70a16a0 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysMenuController.java @@ -0,0 +1,308 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysMenu; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.service.ISysMenuService; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import org.apache.catalina.User; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.annotation.Resource; +import java.io.File; +import java.io.FileNotFoundException; +import java.sql.Timestamp; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + *

+ * 菜单及按钮 前端控制器 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@RestController +@RequestMapping("/system/menu") +@Tag(name = "菜单及按钮") +public class SysMenuController { + + @Resource + private ISysMenuService sysMenuService; + + @Resource + private IUserService userService; + + // 菜单图片路径通过服务层配置获取,无需在控制器注入 + + /*********************************** + * 用途说明:获取菜单结构树(含按钮) + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + @PostMapping("/getMenuButtonTree") + @Operation(summary = "获取菜单结构树(含按钮)") + @ResponseBody + public List> getMenuButtonTree(String systemcode, + String name, + String isdisplay) { + return sysMenuService.getMenuButtonTree(systemcode, name, isdisplay); + } + + /*********************************** + * 用途说明:获取菜单结构树(不含按钮) + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + @PostMapping("/getMenuTree") + @Operation(summary = "获取菜单结构树(不含按钮)") + @ResponseBody + public List> getMenuTree(String systemcode, + String name, + String isdisplay) { + return sysMenuService.getMenuTree(systemcode, name, isdisplay); + } + + /*********************************** + * 用途说明:权限分配 + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + @PostMapping("/permissionAssignment") + @Operation(summary = "获取分配权限(不含按钮)") + @ResponseBody + public List> permissionAssignment(String roleId) { + + return sysMenuService.permissionAssignment(roleId); + } + + /********************************** + * 用途说明: 获取当前用户菜单结构树 + * 参数说明 + * 返回值说明: java.util.List + ***********************************/ + @GetMapping("/treeRoutes") + @Operation(summary = "获取当前用户菜单结构树") + @ResponseBody + public List> getMenuTreeByUser() { + SysUser userInfo = userService.getUserInfo(); + String id = ""; + if (0 != userInfo.getUsertype()) { + id = userInfo.getId(); + } + return sysMenuService.getMenuTree(id); + } + + /*********************************** + * 用途说明:根据id查询菜单或按钮详情 + * 参数说明 + * id 菜单或按钮表id + * 返回值说明: 菜单或按钮表对象 + ***********************************/ + @PostMapping("/getOneById") + @Operation(summary = "根据id查询菜单或按钮详情") + @ResponseBody + public ResponseResult getOneById(String id) { + SysMenu sysMenu = sysMenuService.getById(id); + return ResponseResult.successData(sysMenu); + } + + /*********************************** + * 用途说明:新增菜单及按钮 + * 参数说明 + * sysMenu 菜单或按钮表对象 + * 返回值说明: 是否添加成功提示 + ***********************************/ + @Log(module = "菜单及按钮", value = "新增菜单及按钮!") + @PostMapping("/addMenu") + @Operation(summary = "新增菜单及按钮") + @ResponseBody + public ResponseResult addMenu(@RequestBody SysMenu sysMenu) { + boolean isOk = sysMenuService.addMenu(sysMenu); + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:修改菜单及按钮 + * 参数说明 + * sysMenu 菜单或按钮表对象 + * 返回值说明: 是否修改成功提示 + ***********************************/ + @Log(module = "菜单及按钮", value = "修改菜单及按钮") + @PostMapping("/updateById") + @Operation(summary = "修改菜单及按钮") + @ResponseBody + public ResponseResult updateById(@RequestBody SysMenu sysMenu) { + sysMenu.setLastmodifier(userService.getUsername()); + sysMenu.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + boolean isOk = sysMenuService.updateById(sysMenu); + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:根据id删除单个图标 + * 参数说明 + * id 删除图标id + * icon 图标名称 + * 返回值说明: 是否删除成功 + ***********************************/ + @Log(module = "菜单及按钮", value = "根据id删除单个图标!") + @PostMapping("/deleteIcon") + @Operation(summary = "根据id删除单个图标") + @ResponseBody + public ResponseResult deleteIcon(@RequestParam String id) { + boolean ok = sysMenuService.deleteIcon(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:更新菜单及按钮是否有效 + * 参数说明 + * id 菜单及按钮表id + * isdisplay 是否有效字段 + * 返回值说明: 是否更新成功 + ***********************************/ + @Log(module = "菜单及按钮", value = "更新菜单及按钮是否有效!") + @PostMapping("/setIsDisplay") + @Operation(summary = "更新菜单及按钮是否有效") + @ResponseBody + public ResponseResult setIsDisplay(String id, String isdisplay) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 修改是否显示 ,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("isdisplay", isdisplay).set( + "lastmodifier", userService.getUsername()).set( + "lastmodifydate", + new Timestamp(System.currentTimeMillis())); + boolean ok = sysMenuService.update(updateWrapper); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:菜单及按钮序号排序 + * 参数说明 + * parentid 上级id + * orderMap map<菜单及按钮表id,排列序号> + * 返回值说明: 是否更新成功 + ***********************************/ + @Log(module = "菜单及按钮", value = "菜单及按钮序号排序!") + @PostMapping("/moveOrderno") + @Operation(summary = "菜单及按钮序号排序") + @ResponseBody + public ResponseResult moveOrderno(@RequestParam String parentid, + @RequestParam String id, + @RequestParam int orderno) { + boolean ok = sysMenuService.moveOrderno(parentid, id, orderno); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:根据id删除菜单或按钮 + * 参数说明 + * id 删除列的id + * 返回值说明: 是否删除成功 + ***********************************/ + @Log(module = "菜单及按钮", value = "根据id删除菜单或按钮!") + @PostMapping("/deleteById") + @Operation(summary = "根据id删除菜单或按钮") + @ResponseBody + public ResponseResult deleteById(@RequestParam String id) { + boolean ok = sysMenuService.deleteById(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /********************************** + * 用途说明: 菜单或者按钮拖动 + * 参数说明 id + * 参数说明 id1 + * 返回值说明: com.yfd.platform.config.ResponseResult + ***********************************/ + @Log(module = "菜单及按钮", value = "拖动修改菜单或按钮同级顺序!") + @PostMapping("/changeMenuOrder") + @Operation(summary = "菜单或按钮切换") + @ResponseBody + public ResponseResult changeMenuOrder(@RequestParam String fromId, + @RequestParam String toId) { + if (StrUtil.isBlank(fromId) || StrUtil.isBlank(toId)) { + return ResponseResult.error("参数为空!"); + } + if (fromId.equals(toId)) { + return ResponseResult.error("切换失败!"); + } + boolean ok = sysMenuService.changeOderNoById(fromId, toId); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:上传单个图标 + * 参数说明 + * icon 图标 + * 返回值说明: 是否上传成功 + ***********************************/ + @PostMapping("/uploadIcon") + @Operation(summary = "上传单个图标") + @ResponseBody + public ResponseResult uploadIcon(MultipartFile icon, String menuId) throws FileNotFoundException { + if (StrUtil.isNotBlank(menuId)) { + SysMenu sysMenu = sysMenuService.getById(menuId); + //图片路径 + String iconname = + System.getProperty("user.dir") + "\\src\\main" + + "\\resources\\static\\icon" + File.separator + sysMenu.getIcon(); + //删除图标 + new File(iconname).delete(); + } + String filename = sysMenuService.uploadIcon(icon); + SysMenu sysMenu = new SysMenu(); + sysMenu.setId(menuId); + sysMenu.setIcon(filename); + sysMenuService.updateById(sysMenu); + return ResponseResult.successData(filename); + } +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysOrganizationController.java b/src/main/java/com/yfd/platform/system/controller/SysOrganizationController.java new file mode 100644 index 0000000..9f51b71 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysOrganizationController.java @@ -0,0 +1,210 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysOrganization; +import com.yfd.platform.system.domain.SysRole; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.mapper.SysRoleMapper; +import com.yfd.platform.system.service.ISysOrganizationService; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 系统组织框架 前端控制器 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@RestController +@RequestMapping("/system/organization") +@Tag(name = "系统组织框架") +public class SysOrganizationController { + + @Resource + private ISysOrganizationService organizationService; + + @Resource + private IUserService userService; + + /*********************************** + * 用途说明:获取组织范围树结构 + * 参数说明 + *parentid 上级id + * params 名称(根据名称查询二级) + * 返回值说明: 组织树集合 + ***********************************/ + @PostMapping("/getOrgScopeTree") + @Operation(summary = "获取组织范围树结构") + @ResponseBody + public List> getOrgScopeTree(String roleId) { + return organizationService.getOrgScopeTree(roleId); + } + + /*********************************** + * 用途说明:获取组织范围 + * 参数说明 + * 返回值说明: 组织范围集合 + ***********************************/ + @PostMapping("/getOrgTree") + @Operation(summary = "获取组织结构树") + @ResponseBody + public List> getOrgTree(String parentid, + String params) { + return organizationService.getOrgTree(parentid, params); + } + + /*********************************** + * 用途说明:根据企业ID查询组织详情 + * 参数说明 + * id 企业id + * 返回值说明: 系统组织框架对象 + ***********************************/ + @PostMapping("/getOrganizationById") + @Operation(summary = "根据企业ID查询组织信息") + @ResponseBody + public ResponseResult getOrganizationById(String id, String orgName) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("查询失败!"); + } + List sysOrganizations = + organizationService.getOrganizationById(id, orgName); + return ResponseResult.successData(sysOrganizations); + } + + /*********************************** + * 用途说明:根据ID查询组织详情 + * 参数说明 + * id 系统组织id + * 返回值说明: 系统组织框架对象 + ***********************************/ + @PostMapping("/getOneById") + @Operation(summary = "根据ID查询组织详情") + @ResponseBody + public ResponseResult getOneById(String id) { + SysOrganization sysOrganization = organizationService.getById(id); + return ResponseResult.successData(sysOrganization); + } + + /*********************************** + * 用途说明:新增系统组织框架 + * 参数说明 + * sysOrganization 系统组织框架对象 + * 返回值说明: 是否新增成功 + ***********************************/ + @Log(module = "系统组织框架", value = "新增企业或者部门!") + @PostMapping("/addOrg") + @Operation(summary = "新增系统组织框架") + @ResponseBody + public ResponseResult addOrg(@RequestBody SysOrganization sysOrganization) { + //判断是否是否填写 有效 否则默认为 1 + if (StrUtil.isEmpty(sysOrganization.getIsvaild())) { + sysOrganization.setIsvaild("1"); + } + //填写 当前用户名称 + sysOrganization.setLastmodifier(userService.getUsername()); + //填写 当前日期 + sysOrganization.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //新增 系统组织R + boolean isOk = organizationService.addOrg(sysOrganization); + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:修改系统组织框架 + * 参数说明 + * sysOrganization 系统组织框架对象 + * 返回值说明: 是否修改成功 + ***********************************/ + @Log(module = "系统组织框架", value = "修改企业或者部门信息!") + @PostMapping("/updateById") + @Operation(summary = "修改系统组织框架") + @ResponseBody + public ResponseResult updateById(@RequestBody SysOrganization sysOrganization) { + //填写 当前用户名称 + sysOrganization.setLastmodifier(userService.getUsername()); + //填写 当前日期 + sysOrganization.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //根据id 修改系统组织 + boolean isOk = organizationService.updateById(sysOrganization); + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:修改系统组织框架 + * 参数说明 + * sysOrganization 系统组织框架对象 + * 返回值说明: 是否修改成功 + ***********************************/ + @Log(module = "系统组织框架", value = "设置企业/部门是否有效!") + @PostMapping("/setIsValid") + @Operation(summary = "设置组织是否有效") + @ResponseBody + public ResponseResult setIsValid(@RequestParam String id, + @RequestParam String isvaild) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 修改是否有效,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("isvaild", isvaild).set("lastmodifier" + , userService.getUsername()).set("lastmodifydate", + new Timestamp(System.currentTimeMillis())); + boolean isOk = organizationService.update(updateWrapper); + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:根据id删除系统组织框架 + * 参数说明 + * id 系统组织框架id + * 返回值说明: 是否删除成功 + ***********************************/ + @Log(module = "系统组织框架", value = "根据ID删除企业或者部门!") + @PostMapping("/deleteById") + @Operation(summary = "根据id删除系统组织框架") + @ResponseBody + public ResponseResult deleteById(@RequestParam String id) { + String[] orgIds = id.split(","); + for (String orgId : orgIds) { + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + List list = + organizationService.list(queryWrapper.eq(SysOrganization::getParentid, orgId)); + List ids = + list.stream().map(SysOrganization::getId).collect(Collectors.toList()); + boolean isOk = organizationService.removeById(orgId); + if (!isOk) { + continue; + } + for (String oid : ids) { + organizationService.removeById(oid); + } + } + return ResponseResult.success(); + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/SysRoleController.java b/src/main/java/com/yfd/platform/system/controller/SysRoleController.java new file mode 100644 index 0000000..ea2fa0f --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/SysRoleController.java @@ -0,0 +1,324 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysRole; +import com.yfd.platform.system.service.ISysRoleService; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统角色 前端控制器 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@RestController +@RequestMapping("/system/role") +@Tag(name = "系统角色") +public class SysRoleController { + + @Resource + private ISysRoleService roleService; + + @Resource + private IUserService userService; + + /*********************************** + * 用途说明:查询所有角色 + * 参数说明 + * roleName 角色名称 + * 返回值说明: 查询都有角色 + ***********************************/ + @PostMapping("/list") + @Operation(summary = "查询所有角色") + @ResponseBody + public List list(String rolename) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(rolename)) { + //根据角色名称模糊查询 + queryWrapper.like("rolename", rolename); + } + //根据角色级别,角色编号 正序排序 + queryWrapper.ne("level", "1").orderByAsc("level", "lastmodifydate"); + return roleService.list(queryWrapper); + } + + /*********************************** + * 用途说明:根据Id获取当个角色 + * 参数说明 + * id 角色表id + * 返回值说明: 根据id查询到角色详情 + ***********************************/ + @PostMapping("/getOneById") + @Operation(summary = "根据Id获取当个角色") + @ResponseBody + public ResponseResult getOneById(String id) { + SysRole sysRole = roleService.getById(id); + return ResponseResult.successData(sysRole); + } + + /*********************************** + * 用途说明:新增角色 + * 参数说明 + * sysRole 新增角色信息 + * 返回值说明: 是否新增成功 + ***********************************/ + @Log(module = "系统角色", value = "新增角色") + @PostMapping("/addRole") + @Operation(summary = "新增角色") + @ResponseBody + public ResponseResult addRole(@RequestBody SysRole sysRole) { + boolean isOk = roleService.addRole(sysRole); + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:分配操作权限 + * 参数说明 + * id 角色id + * optscope 分配的权限 + * 返回值说明: 是否新增成功 + ***********************************/ + @Log(module = "系统角色", value = "分配操作权限") + @PostMapping("/setOptScope") + @Operation(summary = "分配操作权限") + @ResponseBody + public ResponseResult setOptScope(@RequestParam String id, + @RequestParam String optscope) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 更新权限,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("optscope", optscope).set( + "lastmodifier", userService.getUsername()).set( + "lastmodifydate", LocalDateTime.now()); + boolean ok = roleService.update(updateWrapper); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:角色菜单权限 + * 参数说明 + * id 角色id + * menuIds 权限id字符串 + * 返回值说明: 是否分配成功 + ***********************************/ + @Log(module = "系统角色", value = "角色菜单权限") + @PostMapping("/setMenuById") + @Operation(summary = "角色菜单权限") + @ResponseBody + public ResponseResult setMenuById(String id, String menuIds) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + if (StrUtil.isBlank(menuIds)) { + return ResponseResult.success(); + } + boolean ok = roleService.setMenuById(id, menuIds); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + + } + + /*********************************** + * 用途说明:设置组织范围 + * 参数说明 + * id 角色id + * orgscope 组织范围 + * 返回值说明: 是否新增成功 + ***********************************/ + @Log(module = "系统角色", value = "设置组织范围") + @PostMapping("/setOrgscope") + @Operation(summary = "设置组织范围") + @ResponseBody + public ResponseResult setOrgscope(@RequestParam String id, + @RequestParam String orgscope) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 更新组织范围,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("orgscope", orgscope).set( + "lastmodifier", userService.getUsername()).set( + "lastmodifydate", LocalDateTime.now()); + boolean ok = roleService.update(updateWrapper); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:设置业务范围 + * 参数说明 + * id 角色id + * busscope 业务范围 + * 返回值说明: 是否新增成功 + ***********************************/ + @Log(module = "系统角色", value = "设置业务范围") + @PostMapping("/setBusscope") + @Operation(summary = "设置业务范围") + @ResponseBody + public ResponseResult setBusscope(@RequestParam String id, + @RequestParam String busscope) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 更新业务范围,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("busscope", busscope).set( + "lastmodifier", userService.getUsername()).set( + "lastmodifydate", LocalDateTime.now()); + boolean ok = roleService.update(updateWrapper); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:角色添加用户 + * 参数说明 + * roleid 角色id + * userids 用户id组 + * 返回值说明: 是否新增成功 + ***********************************/ + @Log(module = "系统角色", value = "角色添加用户") + @PostMapping("/setRoleUsers") + @Operation(summary = "角色添加用户") + @ResponseBody + public ResponseResult setRoleUsers(String roleid, String userids) { + boolean isOk = true; + String[] temp = userids.split(","); + for (String userid : temp) { + isOk = isOk && userService.addUserRoles(roleid, userid); + } + if (isOk) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:删除角色用户 + * 参数说明 + * roleid 角色id + * 返回值说明: 是否新增成功 + ***********************************/ + @PostMapping("/deleteRoleUser") + @Operation(summary = "删除角色用户") + @ResponseBody + public ResponseResult deleteRoleUsers(@RequestParam String roleid, + @RequestParam String userids) { + //根据角色id、用户id删除 + boolean ok = roleService.deleteRoleUsers(roleid, userids); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:设置角色是否有效 + * 参数说明 + * id 角色id + *isvaild 是否有效(1 是 0 否 ) + * 返回值说明: 是否新增成功 + ***********************************/ + @PostMapping("/setIsvaild") + @Operation(summary = "设置角色是否有效") + @ResponseBody + public ResponseResult setIsvaild(String id, String isvaild) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 更新业务范围,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("isvaild", isvaild).set("lastmodifier" + , userService.getUsername()).set("lastmodifydate", + LocalDateTime.now()); + boolean ok = roleService.update(updateWrapper); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:更新角色信息 + * 参数说明 + *sysRole 角色对象 + * 返回值说明: 是否修改成功 + ***********************************/ + @PostMapping("/updateById") + @Operation(summary = "更新角色信息") + @ResponseBody + public ResponseResult updateById(@RequestBody SysRole sysRole) { + //更新最近修改人 + sysRole.setLastmodifier(userService.getUsername()); + //更新最近修改时间 + sysRole.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //根据id更新角色信息 + boolean ok = roleService.updateById(sysRole); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:根据id删除角色 + * 参数说明 + *id 角色id + * 返回值说明: 是否删除成功 + ***********************************/ + @PostMapping("/deleteById") + @Operation(summary = "根据id删除角色") + @ResponseBody + public ResponseResult deleteById(@RequestParam String id) { + roleService.deleteById(id); + return ResponseResult.success(); + } + + /*********************************** + * 用途说明:查询已分配的用户 + * 参数说明 + *orgid 所属组织 + *username 用户名称 + *status 状态 + *level 角色级别 + * rolename 角色名称 + * isvaild 角色是否有效 + * 返回值说明: 系统用户角色数据集合 + ***********************************/ + @PostMapping("/listRoleUsers") + @Operation(summary = "查询已分配的用户") + @ResponseBody + public List listRoleUsers(String orgid, String username, + String status, String level, + String rolename, String isvaild) { + return roleService.listRoleUsers(orgid, username, status, level, + rolename, isvaild); + } + +} diff --git a/src/main/java/com/yfd/platform/system/controller/UserController.java b/src/main/java/com/yfd/platform/system/controller/UserController.java new file mode 100644 index 0000000..c90e345 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/controller/UserController.java @@ -0,0 +1,188 @@ +package com.yfd.platform.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.datasource.DataSource; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.service.IUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.util.Map; + +/** + *

+ * 用户信息 前端控制器 + *

+ * + * @author zhengsl + * @since 2022-09-20 + */ +@RestController +@RequestMapping("/system/user") +@Tag(name = "系统用户") +public class UserController { + + @Resource + private IUserService userService; + + @Log(module = "系统用户", value = "新增系统用户") + @PostMapping("/addUser") + @Operation(summary = "新增系统用户") + @ResponseBody + public ResponseResult addUser(@RequestBody SysUser user, String roleids) { + Map reslut = userService.addUser(user, roleids); + return ResponseResult.successData(reslut); + } + + @Log(module = "系统用户", value = "修改用户信息") + @PostMapping("/updateUser") + @Operation(summary = "修改用户信息") + @ResponseBody + public ResponseResult updateUser(@RequestBody SysUser user, + String roleids) { + if (StrUtil.isEmpty(user.getId())) { + return ResponseResult.error("没有用户ID"); + } + //填写 当前用户名称 + user.setLastmodifier(userService.getUsername()); + //填写 当前日期 + user.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + Map reslut = userService.updateById(user, roleids); + return ResponseResult.successData(reslut); + } + + @GetMapping("/queryUsers") + @Operation(summary = "查询用户信息") + @ResponseBody + public ResponseResult queryUsers(String orgid, + String username, Page page) { + + Page> mapPage = userService.queryUsers(orgid, + username, page); + return ResponseResult.successData(mapPage); + } + + /*********************************** + * 用途说明:用户分配角色 + * 参数说明 + *idMap 用户id与角色id + * 返回值说明: 判断是否添加成功 + ************************************/ + @Log(module = "系统用户", value = "用户分配角色") + @PostMapping("/setUserRoles") + @Operation(summary = "用户分配角色") + @ResponseBody + public ResponseResult setUserRoles(String roleid, String userids) { + boolean ok = userService.setUserRoles(roleid, userids); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:根据id删除用户 + * 参数说明 + *id 用户id + * 返回值说明: 判断是否删除成功 + ************************************/ + @Log(module = "系统用户", value = "根据ID删除用户") + @PostMapping("/deleteById") + @Operation(summary = "根据ID删除用户") + @ResponseBody + public ResponseResult deleteById(String id) { + userService.deleteById(id); + return ResponseResult.success(); + } + + /*********************************** + * 用途说明:根据ID批量删除用户 + * 参数说明 + *ids 用户id集合 + * 返回值说明: 判断是否删除成功 + ************************************/ + @Log(module = "系统用户", value = "根据ID批量删除用户") + @PostMapping("/deleteUserByIds") + @Operation(summary = "根据ID批量删除用户") + @ResponseBody + public ResponseResult deleteUserByIds(String id) { + if (StrUtil.isBlank(id)) { + return ResponseResult.error("参数为空"); + } + boolean ok = userService.deleteUserByIds(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:重置用户密码(管理员) + * 参数说明 + *id 重置密码的 用户id + * 返回值说明: 判断是否重置成功 + ************************************/ + @Log(module = "系统用户", value = "重置用户密码") + @PostMapping("/resetPassword") + @Operation(summary = "重置用户密码") + @ResponseBody + @DataSource + public ResponseResult resetPassword(String id) throws Exception { + if (StrUtil.isBlank(id)) { + ResponseResult.error("参数为空"); + } + boolean ok = userService.resetPassword(id); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:设置账号状态(管理员) + * 参数说明 + *id 用户id + * status 设置状态 + * 返回值说明: 判断是否设置成功 + ************************************/ + @Log(module = "系统用户", value = "设置账号状态") + @PostMapping("/setStatus") + @Operation(summary = "设置账号状态") + @ResponseBody + public ResponseResult setStatus(@RequestParam String id, + @RequestParam String status) { + boolean ok = userService.setStatus(id, status); + if (ok) { + return ResponseResult.success(); + } else { + return ResponseResult.error(); + } + } + + /*********************************** + * 用途说明:修改头像(管理员) + * 参数说明 + * multipartFile 文件对象 + * status 设置状态 + * 返回值说明: 文件名 + ************************************/ + @Operation(summary = "修改头像") + @PostMapping(value = "/updateAvatar") + public ResponseResult updateAvatar(String id, MultipartFile multipartFile) { + if (multipartFile == null) { + ResponseResult.error("参数为空"); + } + boolean ok = userService.uploadAvatar(id, multipartFile); + return ResponseResult.success(); + } +} diff --git a/src/main/java/com/yfd/platform/system/domain/Dictionary.java b/src/main/java/com/yfd/platform/system/domain/Dictionary.java new file mode 100644 index 0000000..df234e3 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/Dictionary.java @@ -0,0 +1,78 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 数据字典表 + *

+ * + * @author zhengsl + * @since 2021-10-27 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("rca_dictionary") +public class Dictionary implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 类型 + */ + private String type; + + /** + * 类型名称 + */ + private String typename; + + /** + * 代码 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 顺序号 + */ + private String orderno; + + /** + * 上级代码 + */ + private String parentcode; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + + +} diff --git a/src/main/java/com/yfd/platform/system/domain/LoginUser.java b/src/main/java/com/yfd/platform/system/domain/LoginUser.java new file mode 100644 index 0000000..44cfb35 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/LoginUser.java @@ -0,0 +1,76 @@ +package com.yfd.platform.system.domain; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class LoginUser implements UserDetails { + + private SysUser user; + + private List permissions; + + public LoginUser(SysUser user, List permissions) { + this.user = user; + this.permissions = permissions; + } + + @JSONField(serialize = false) + private List authorities; + + @Override + public Collection getAuthorities() { + // 将权限信息放入集合 + authorities = permissions.stream() + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + return authorities; + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public String getUsername() { + return user.getUsername(); + } + + //获取用户昵称 + public String geNickname() { + return user.getNickname(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/com/yfd/platform/system/domain/Message.java b/src/main/java/com/yfd/platform/system/domain/Message.java new file mode 100644 index 0000000..54578e5 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/Message.java @@ -0,0 +1,117 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * 消息通知 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_message") +public class Message implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(type = IdType.ASSIGN_UUID) + @Schema(description = "ID") + private String id; + + /** + * 创建时间:排序 + */ + @Schema(description = "创建时间:排序") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Timestamp createtime; + + /** + * 消息类型:1-定时任务 2-工作流触发 3-人工触发 + */ + @Schema(description = "消息类型:1-定时任务 2-工作流触发 3-人工触发") + private String type; + + /** + * 消息标题 + */ + @Schema(description = "消息标题") + private String title; + + /** + * 消息内容 + */ + @Schema(description = "消息内容") + private String content; + + /** + * 发送者名称,定时器,人员 + */ + @Schema(description = "发送者名称,定时器,人员") + private String senderName; + + /** + * 接收者代码 人员账号列表 + */ + @Schema(description = "接收者代码 人员账号列表 ") + private String receiverCodes; + + /** + * 接收者名称:为空 即为所有人,人员名称列表 + */ + @Schema(description = "接收者名称:为空 即为所有人,人员名称列表") + private String receiverNames; + + /** + * 状态:1、初始创建 2-消息已阅 9-消息过期 + */ + @Schema(description = "状态:1、初始创建 2-消息已阅 9-消息过期") + private String status; + + /** + * 有效期:小时 + */ + @Schema(description = "有效期:小时") + private Integer validperiod; + + /** + * 已阅时间 + */ + @Schema(description = "已阅时间") + private Timestamp readtime; + + /** + * 备用1 + */ + @Schema(description = "备用1") + private String custom1; + + /** + * 备用2 + */ + @Schema(description = "备用2") + private String custom2; + + /** + * 备用3 + */ + @Schema(description = "备用3") + private String custom3; + +} diff --git a/src/main/java/com/yfd/platform/system/domain/QuartzJob.java b/src/main/java/com/yfd/platform/system/domain/QuartzJob.java new file mode 100644 index 0000000..e3504ce --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/QuartzJob.java @@ -0,0 +1,118 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * 定时任务 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_quartz_job") +public class QuartzJob implements Serializable { + + public static final String JOB_KEY = "JOB_KEY"; + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @Schema(description = "ID") + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 排序号 + */ + @Schema(description = "排序号") + private Integer orderno; + + /** + * 任务名称 + */ + @Schema(description = "任务名称") + private String jobName; + + /** + * 执行类名称 + */ + @Schema(description = "执行类名称") + private String jobClass; + + /** + * 执行方法名称 + */ + @Schema(description = "执行方法名称") + private String jobMethod; + + /** + * 时间周期表达式 + */ + @Schema(description = "时间周期表达式") + private String jobCron; + + /** + * 方法参数 + */ + @Schema(description = "方法参数") + private String jobParams; + + /** + * 任务描述 + */ + @Schema(description = "任务描述") + private String description; + + /** + * 状态:0-暂停、1-启用 + */ + @Schema(description = "状态:0-暂停、1-启用") + private String status; + + /** + * 最近修改者 + */ + @Schema(description = "最近修改者") + private String lastmodifier; + + /** + * 最近修改日期 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Schema(description = "最近修改日期") + private Timestamp lastmodifydate; + + /** + * 备用1 + */ + @Schema(description = "备用1") + private String custom1; + + /** + * 备用2 + */ + @Schema(description = "备用2") + private String custom2; + + /** + * 备用3 + */ + @Schema(description = "备用3") + private String custom3; + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysConfig.java b/src/main/java/com/yfd/platform/system/domain/SysConfig.java new file mode 100644 index 0000000..3bef030 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysConfig.java @@ -0,0 +1,78 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 系统全局配置 + *

+ * + * @author zhengsl + * @since 2022-01-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_config") +public class SysConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 欢迎词 + */ + private String welcome; + + /** + * 系统功能介绍 + */ + private String funcation; + + /** + * 系统版本信息 + */ + private String versioninfo; + + /** + * 备注 + */ + private String remark; + + /** + * 最近修改者 + */ + private String lastmodifier; + + /** + * 最近修改日期 + */ + @TableField(fill = FieldFill.UPDATE) + private Timestamp lastmodifydate; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysDictionary.java b/src/main/java/com/yfd/platform/system/domain/SysDictionary.java new file mode 100644 index 0000000..ca1fb9c --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysDictionary.java @@ -0,0 +1,71 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 数据字典表 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class SysDictionary implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 字典类型 00-系统内置 01-用户配置 + */ + @TableField("dicttype") + private String dictType; + + /** + * 顺序号 + */ + @TableField("orderno") + private Integer orderNo; + + /** + * 字典编码 + */ + @TableField("dictcode") + private String dictCode; + + /** + * 字典名称 + */ + @TableField("dictname") + private String dictName; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysDictionaryItems.java b/src/main/java/com/yfd/platform/system/domain/SysDictionaryItems.java new file mode 100644 index 0000000..431bfda --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysDictionaryItems.java @@ -0,0 +1,77 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 数据字典明细 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class SysDictionaryItems implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 对应字典ID + */ + @TableField("dictid") + private String dictId; + + /** + * 顺序号 + */ + @TableField("orderno") + private Integer orderNo; + + /** + * 项编码 + */ + @TableField("itemcode") + private String itemCode; + + /** + * 项名称 + */ + @TableField("dictname") + private String dictName; + + /** + * 父项编码 + */ + @TableField("parentcode") + private String parentCode; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysLog.java b/src/main/java/com/yfd/platform/system/domain/SysLog.java new file mode 100644 index 0000000..dfe091d --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysLog.java @@ -0,0 +1,92 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.sql.Timestamp; +import java.time.LocalDateTime; + +/** + *

+ * 系统操作日志 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class SysLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 用户账号 + */ + @TableField("usercode") + private String usercode; + + /** + * 用户名称 + */ + private String username; + + /** + * 操作类型 00-登录 01-新增 02-修改 03-删除 06-查询 09其他 + */ + @TableField("opttype") + private String opttype; + + /** + * 模块名称 + */ + private String module; + + /** + * 日志描述 + */ + private String description; + + /** + * 操作方法 + */ + private String method; + + /** + * 方法参数 + */ + private String params; + + /** + * 创建时间 + */ + @TableField("logtime") + private Timestamp logtime; + + /** + * 请求IP + */ + @TableField("requestip") + private String requestip; + + /** + * 浏览器类型 + */ + private String browser; + + public SysLog(String opttype) { + this.opttype = opttype; + } +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysMenu.java b/src/main/java/com/yfd/platform/system/domain/SysMenu.java new file mode 100644 index 0000000..18802d7 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysMenu.java @@ -0,0 +1,114 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 菜单及按钮 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_menu") +public class SysMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 1-web 2-pad 3-mobile + */ + private String systemcode; + + /** + * 1-菜单 2-按钮 + */ + private String type; + + /** + * 在系统内自动生成 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 图标地址 + */ + private String icon; + + /** + * 是否外链 + */ + private String islink; + + /** + * 内部模块路径或者外链地址 + */ + private String opturl; + + /** + * 权限控制标识 + */ + private String permission; + + /** + * 顶级为0 + */ + private String parentid; + + /** + * 排序号 + */ + private Integer orderno; + + /** + * 0-不显示 1-显示 + */ + private String isdisplay; + + /** + * 最近修改者 + */ + private String lastmodifier; + + /** + * 最近修改日期 + */ + @TableField(fill = FieldFill.UPDATE) + private Timestamp lastmodifydate; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysOrganization.java b/src/main/java/com/yfd/platform/system/domain/SysOrganization.java new file mode 100644 index 0000000..cc7f711 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysOrganization.java @@ -0,0 +1,93 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 系统组织框架 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_organization") +public class SysOrganization implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 1-公司 -2-部门 + */ + private String orgtype; + + /** + * 两位一级 + */ + private String orgcode; + + /** + * 组织名称 + */ + private String orgname; + + /** + * 上级id + */ + private String parentid; + + /** + * 组织负责人 + */ + private String manager; + + /** + * 1-是 0-否 + */ + private String isvaild; + + /** + * 描述 + */ + private String description; + + /** + * 最近修改者 + */ + private String lastmodifier; + + /** + * 最近修改日期 + */ + @TableField(fill = FieldFill.UPDATE) + private Timestamp lastmodifydate; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysRole.java b/src/main/java/com/yfd/platform/system/domain/SysRole.java new file mode 100644 index 0000000..1b21e76 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysRole.java @@ -0,0 +1,98 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 系统角色 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_role") +public class SysRole implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 系统生成,三位编号 + */ + private String rolecode; + + /** + * 角色名称 + */ + private String rolename; + + /** + * 1-超级管理员 2-单位管理员 3-普通用户 + */ + private String level; + + /** + * 描述 + */ + private String description; + + /** + * org1,org2 + */ + private String orgscope; + + /** + * 多个操作代码(菜单、按钮) + */ + private String optscope; + + /** + * json格式自定义业务范围 + */ + private String busscope; + + /** + * 1-是 0-否 + */ + private String isvaild; + + /** + * 最近修改者 + */ + private String lastmodifier; + + /** + * 最近修改日期 + */ + @TableField(fill = FieldFill.UPDATE) + private Timestamp lastmodifydate; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; + + +} diff --git a/src/main/java/com/yfd/platform/system/domain/SysUser.java b/src/main/java/com/yfd/platform/system/domain/SysUser.java new file mode 100644 index 0000000..0e01f4a --- /dev/null +++ b/src/main/java/com/yfd/platform/system/domain/SysUser.java @@ -0,0 +1,116 @@ +package com.yfd.platform.system.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + *

+ * 系统用户 + *

+ * + * @author zhengsl + * @since 2021-10-27 + */ + +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_user") +public class SysUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id 主键 + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 用户类型 0-管理员 1-普通用户 + */ + private Integer usertype; + + /** + * 用户名(账号) + */ + private String username; + /** + * 用户昵称 + */ + private String nickname; + + /** + * 登录密码(加密存储) + */ + private String password; + + /** + * 性别(0-男 1-女 ) + */ + private String sex; + + /** + * 邮箱 + */ + private String email; + /** + * 手机号 + */ + private String phone; + + /** + * 头像(预留) + */ + private String avatar; + + /** + * 账号状态(1-正常 0-停用) + */ + private Integer status; + + /** + * 部门ID + */ + private String orgid; + + /** + * 密码重置时间 + */ + private String pwdresettime; + + /** + * 最近修改者 + */ + private String lastmodifier; + + /** + * 最近修改日期 + */ + @TableField(fill = FieldFill.UPDATE) + private Timestamp lastmodifydate; + + @TableField(exist = false) + private String uuid; + + @TableField(exist = false) + private String code; + + /** + * 备用1 + */ + private String custom1; + + /** + * 备用2 + */ + private String custom2; + + /** + * 备用3 + */ + private String custom3; +} diff --git a/src/main/java/com/yfd/platform/system/mapper/MessageMapper.java b/src/main/java/com/yfd/platform/system/mapper/MessageMapper.java new file mode 100644 index 0000000..d08fa95 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/MessageMapper.java @@ -0,0 +1,16 @@ +package com.yfd.platform.system.mapper; + +import com.yfd.platform.system.domain.Message; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 消息通知 Mapper 接口 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +public interface MessageMapper extends BaseMapper { + +} diff --git a/src/main/java/com/yfd/platform/system/mapper/QuartzJobMapper.java b/src/main/java/com/yfd/platform/system/mapper/QuartzJobMapper.java new file mode 100644 index 0000000..ad46f1b --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/QuartzJobMapper.java @@ -0,0 +1,16 @@ +package com.yfd.platform.system.mapper; + +import com.yfd.platform.system.domain.QuartzJob; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 定时任务 Mapper 接口 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +public interface QuartzJobMapper extends BaseMapper { + +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysConfigMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysConfigMapper.java new file mode 100644 index 0000000..5bae048 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysConfigMapper.java @@ -0,0 +1,17 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysConfig; + + +/** + *

+ * 系统全局配置 Mapper 接口 + *

+ * + * @author zhengsl + * @since 2022-01-19 + */ +public interface SysConfigMapper extends BaseMapper { + +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysDictionaryItemsMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysDictionaryItemsMapper.java new file mode 100644 index 0000000..de7deaa --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysDictionaryItemsMapper.java @@ -0,0 +1,17 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.system.domain.SysDictionaryItems; + +/** + *

+ * 数据字典明细 Mapper 接口 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +public interface SysDictionaryItemsMapper extends BaseMapper { + +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysDictionaryMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysDictionaryMapper.java new file mode 100644 index 0000000..7d03ca9 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysDictionaryMapper.java @@ -0,0 +1,22 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysDictionary; + +/** + *

+ * 数据字典表 Mapper 接口 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +public interface SysDictionaryMapper extends BaseMapper { + + /********************************** + * 用途说明: 根据字典类型获取字典最大序号 + * 参数说明 sysDictionary 字典对象 + * 返回值说明: 返回增加成功或者失败 + ***********************************/ + Integer selectMaxNo(String dictType); +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysLogMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysLogMapper.java new file mode 100644 index 0000000..7b18518 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysLogMapper.java @@ -0,0 +1,16 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysLog; + +/** + *

+ * 系统操作日志 Mapper 接口 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +public interface SysLogMapper extends BaseMapper { + +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysMenuMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysMenuMapper.java new file mode 100644 index 0000000..f57b35e --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysMenuMapper.java @@ -0,0 +1,59 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysMenu; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 菜单及按钮 Mapper 接口 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +public interface SysMenuMapper extends BaseMapper { + + /*********************************** + * 用途说明:菜单及按钮序号向上移动 + * 参数说明 + * parentid 上级id + *Orderno 小于序号(原序号) + *upOrderno 大于等于序号(更改的序号加一) + * 返回值说明: 是否更新成功 + ***********************************/ + boolean upMoveOrderno(@Param("parentid") String parentid, @Param("Orderno") int Orderno, @Param("upOrderno") int upOrderno); + + /*********************************** + * 用途说明:菜单及按钮序号向下移动 + * 参数说明 + * parentid 上级id + *Orderno 大于序号(原序号) + *downOrderno 小于等于序号(更改的序号减一) + * 返回值说明: 是否更新成功 + ***********************************/ + boolean downMoveOrderno(@Param("parentid") String parentid, @Param("Orderno") int Orderno, @Param("downOrderno") int downOrderno); + + + List selectPermsByUserId(String userId); + + //List selectMenuByUserId(String userId); + List> selectMenuByUserId(String userId); + + /*********************************** + * 用途说明:根据权限id查找系统类型 + * 参数说明 id 权限id + * 返回值说明: 返回系统类型 + ***********************************/ + String getSystemCodeById(String id); + + /*********************************** + * 用途说明:根据角色Id查找权限 + * 参数说明 id 权限id + * 返回值说明: 返回权限集合 + ***********************************/ + List selectMenuByRoleId(String id); +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysOrganizationMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysOrganizationMapper.java new file mode 100644 index 0000000..e856aae --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysOrganizationMapper.java @@ -0,0 +1,33 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysOrganization; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 系统组织框架 Mapper 接口 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +public interface SysOrganizationMapper extends BaseMapper { + + /*********************************** + * 用途说明:去重查询组织分类 + * 返回值说明: 所有组织分类 + ***********************************/ + List queryOrgtype(); + + /*********************************** + * 用途说明:根据组织分类查询上级id + * 参数说明 + * orgtype 组织分类 + * 返回值说明: 上级id + ***********************************/ + List queryParentid(@Param("orgtype") String orgtype); + +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysRoleMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysRoleMapper.java new file mode 100644 index 0000000..acb7a81 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysRoleMapper.java @@ -0,0 +1,89 @@ +package com.yfd.platform.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.system.domain.SysRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统角色 Mapper 接口 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +public interface SysRoleMapper extends BaseMapper { + + /*********************************** + * 用途说明:根据角色id查询是否存在用户 + * 参数说明 + * roleid 角色id + * 返回值说明: 该角色下是否存在用户 + ************************************/ + List> isRoleUsersByroleid(String roleid); + + /*********************************** + * 用途说明:根据角色id查询是否存在权限 + * 参数说明 + * roleid 角色id + * 返回值说明: 该角色下是否存在权限 + ************************************/ + List> isRoleMenuByRoleId(String roleId); + + /*********************************** + * 用途说明:查询已分配的用户 + * 参数说明 + *orgid 所属组织 + *username 用户名称 + *status 状态 + *level 角色级别 '1-超级管理员 2-单位管理员 3-普通用户' + * rolename 角色名称 + * isvaild 角色是否有效 + * 返回值说明: 系统用户角色数据集合 + ***********************************/ + List listRoleUsers(String orgid, String username, String status, + String level, String rolename, String isvaild); + + /*********************************** + * 用途说明:根据 角色id和用户id 删除 (admin除外) + * 参数说明 + *roleid 角色id + * urserid 用户id + * 返回值说明: 是否删除成功 + ***********************************/ + boolean deleteRoleUsers(String roleid, String urserid); + + /********************************** + * 用途说明: 根据用户id获取角色信息 + * 参数说明 id 角色id + * 返回值说明: void + ***********************************/ + List getRoleByUserId(String id); + + /********************************** + * 用途说明: 根据角色ID删除菜单与角色关联信息 + * 参数说明 id 角色id + * 返回值说明: void + ***********************************/ + boolean deleteRoleMenus(String id); + + /********************************** + * 用途说明: 根据角色ID删除用户与角色关联信息 + * 参数说明 id 角色id + * 返回值说明: void + ***********************************/ + boolean deleteRoleUser(String id); + + /********************************** + * 用途说明: 根据角色id获取用户id + * 参数说明 id 角色id + * 返回值说明: 用户id + ***********************************/ + List getUserIdById(String id); + + void addRoleMenu(@Param("id") String id, @Param("roleid") String roleid, + @Param("menuid") String menuid); +} diff --git a/src/main/java/com/yfd/platform/system/mapper/SysUserMapper.java b/src/main/java/com/yfd/platform/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..ea57c78 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/mapper/SysUserMapper.java @@ -0,0 +1,96 @@ +package com.yfd.platform.system.mapper; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.system.domain.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统用户表 Mapper 接口 + *

+ * + * @author zhengsl + * @since 2021-10-27 + */ +public interface SysUserMapper extends BaseMapper { + List list(@Param("total")String total, @Param("size")String size, @Param("orgid")String orgid, @Param("username")String username, @Param("mobile")String mobile , @Param("status")String status); + + /*********************************** + * 用途说明:新增系统角色用户对照表 对用户分配角色 + * 参数说明 + * id 生成的id + * roleid 角色id + * userid 用户id + * 返回值说明: + ************************************/ + boolean addUserRoles(@Param("id")String id,@Param("roleid") String roleid,@Param("userid") String userid); + + /*********************************** + * 用途说明:根据用户id 和角色id 查询 系统角色用户对照表 + * 参数说明 + * userid 用户id + * roleid 角色id + * 返回值说明: + ************************************/ + List getRoleUsersByid(@Param("roleid") String roleid,@Param("userid") String userid); + + /*********************************** + * 用途说明:根据用户表id查询角色表所有角色 + * 参数说明 + * userid 用户id + * 返回值说明: + ************************************/ + List getLevel(@Param("userid") String userid); + + /*********************************** + * 用途说明:根据用户表id查询角色表所有角色id + * 参数说明 + * userid 用户id + * 返回值说明: + ************************************/ + List getRoleid(@Param("userid") String userid); + + /*********************************** + * 用途说明:根据用户表id查询角色表级别 + * 参数说明 + * userid 用户id + * 返回值说明: + ************************************/ + String getMaxLevel(@Param("userid") String userid); + + /*********************************** + * 用途说明:根据用户id删除所分配的角色 + * 参数说明 + * userid 用户id + * 返回值说明: + ************************************/ + boolean delRoleUsersByUserid(@Param("userid") String userid); + + /*********************************** + * 用途说明:根据用户id删除所分配的不包含角色 + * 参数说明 + * userid 用户id + * roleids 多个角色id + * 返回值说明: + ************************************/ + boolean delInRoleUsersByUserid(@Param("userid") String userid,@Param("roleids")String[] roleids); + + Page> queryUsers(String orgid, + String username, + Page page); + + Map getOrganizationByid(String id); + + /********************************** + * 用途说明: 根据ID删除用户与角色的关联信息 + * 参数说明 ids 用户id集合 + * 返回值说明: void + ***********************************/ + void delRoleUsersByUserIds(List ids); +} diff --git a/src/main/java/com/yfd/platform/system/service/IMessageService.java b/src/main/java/com/yfd/platform/system/service/IMessageService.java new file mode 100644 index 0000000..2b4c645 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/IMessageService.java @@ -0,0 +1,16 @@ +package com.yfd.platform.system.service; + +import com.yfd.platform.system.domain.Message; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 消息通知 服务类 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +public interface IMessageService extends IService { + +} diff --git a/src/main/java/com/yfd/platform/system/service/IQuartzJobService.java b/src/main/java/com/yfd/platform/system/service/IQuartzJobService.java new file mode 100644 index 0000000..8b71868 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/IQuartzJobService.java @@ -0,0 +1,43 @@ +package com.yfd.platform.system.service; + +import com.yfd.platform.system.domain.QuartzJob; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 定时任务 服务类 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +public interface IQuartzJobService extends IService { + + /********************************** + * 用途说明: 新增定时任务 + * 参数说明 quartzJob 定时对象 + * 返回值说明: boolean 是否成功 + ***********************************/ + boolean addQuartzJob(QuartzJob quartzJob); + + /********************************** + * 用途说明: 删除定时任务 + * 参数说明 id id + * 返回值说明: boolean 是否成功 + ***********************************/ + boolean deleteQuartzJob(String id); + + /********************************** + * 用途说明: 拖动修改定时任务顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + boolean changeDictOrder(String fromID, String toID); + + /********************************** + * 用途说明: 执行定时任务 + * 参数说明 id id + * 返回值说明: void + ***********************************/ + void execution(QuartzJob byId); +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysConfigService.java b/src/main/java/com/yfd/platform/system/service/ISysConfigService.java new file mode 100644 index 0000000..ef3a399 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysConfigService.java @@ -0,0 +1,22 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysConfig; + +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.IOException; +import java.util.Map; + +/** + *

+ * 系统全局配置 服务类 + *

+ * + * @author zhengsl + * @since 2022-01-19 + */ +public interface ISysConfigService extends IService { + + + +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysDictionaryItemsService.java b/src/main/java/com/yfd/platform/system/service/ISysDictionaryItemsService.java new file mode 100644 index 0000000..32f9b8f --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysDictionaryItemsService.java @@ -0,0 +1,47 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysDictionaryItems; + +import jakarta.servlet.http.HttpServletResponse; +import java.util.List; + +/** + *

+ * 数据字典明细 服务类 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +public interface ISysDictionaryItemsService extends IService { + + /********************************** + * 用途说明: 分页查询字典项信息 + * 参数说明 dictID 字典ID ItemName 字典项名称 pageNum 当前页 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + Page getDictItemPage(String dictId, String itemName, Page page); + + /********************************** + * 用途说明: 增加字典项 + * 参数说明 sysDictionaryItems 字典项信息 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败 + ***********************************/ + boolean addDictionaryItem(SysDictionaryItems sysDictionaryItems); + + /********************************** + * 用途说明: 拖动修改字典项顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + boolean changeItemOrder(String fromID, String toID); + + /********************************** + * 用途说明: 导出数据字典项数据 + * 参数说明 sysDictionaryItemsList 所需导出的字典项集合 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回导出成功或失败 + ***********************************/ + void exportExcel(List records, HttpServletResponse response); +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysDictionaryService.java b/src/main/java/com/yfd/platform/system/service/ISysDictionaryService.java new file mode 100644 index 0000000..f3a4990 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysDictionaryService.java @@ -0,0 +1,45 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysDictionary; + +import java.util.List; + +/** + *

+ * 数据字典表 服务类 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +public interface ISysDictionaryService extends IService { + + /********************************** + * 用途说明: 获取数据字典列表 + * 参数说明 dictType 字典类型 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + List getDictList(String dictType); + + /********************************** + * 用途说明: 新增字典 + * 参数说明 sysDictionary 字典对象 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败 + ***********************************/ + boolean addDict(SysDictionary sysDictionary); + + /********************************** + * 用途说明: 根据ID删除字典 + * 参数说明 id 字典ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除结果成功或者失败 + ***********************************/ + boolean deleteDictById(String id); + + /********************************** + * 用途说明: 拖动修改字典顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + boolean changeDictOrder(String fromID, String toID); +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysLogService.java b/src/main/java/com/yfd/platform/system/service/ISysLogService.java new file mode 100644 index 0000000..85fdffa --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysLogService.java @@ -0,0 +1,52 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysLog; +import org.aspectj.lang.ProceedingJoinPoint; + +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统操作日志 服务类 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +public interface ISysLogService extends IService { + + /********************************** + * 用途说明: 分页查询日志信息 + * 参数说明 pageNum(页码数)、pageSize(页大小,如果是固定页大小可不传)、username(用户名)、(optType) + * 操作类型、startDate(开始日期)、endDate(结束日期) + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + Page getLogList(String username, String optType, + String startDate, + String endDate, Page page); + + + /********************************** + * 用途说明: 导出日志数据 + * 参数说明 sysLogs 所需导出的字典项集合 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回导出成功或者失败 + ***********************************/ + void exportExcel(List sysLogs, HttpServletResponse response) throws IOException; + + /********************************** + * 用途说明: 新增日志 + * 参数说明 nickname 用户名 + * 参数说明 username 用户账号 + * 参数说明 browser 浏览器 + * 参数说明 ip 本机Ip地址 + * 参数说明 joinPoint 连接点 + * 参数说明 log 日志信息 + * 返回值说明: void + ***********************************/ + void save(String nickname,String username, String browser, String ip, ProceedingJoinPoint joinPoint, SysLog log); +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysMenuService.java b/src/main/java/com/yfd/platform/system/service/ISysMenuService.java new file mode 100644 index 0000000..7093e3b --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysMenuService.java @@ -0,0 +1,101 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; + +import com.yfd.platform.system.domain.SysMenu; +import org.springframework.web.multipart.MultipartFile; + +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Map; + +/** + *

+ * 菜单及按钮 服务类 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +public interface ISysMenuService extends IService { + + /*********************************** + * 用途说明:获取菜单结构树(含按钮) + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + List> getMenuButtonTree(String systemcode, String name, String isdisplay); + + /*********************************** + * 用途说明:获取菜单结构树(不含按钮) + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + List> getMenuTree(String systemcode, String name, String isdisplay); + + + /*********************************** + * 用途说明:新增菜单及按钮 + * 参数说明 + * sysMenu 菜单或按钮表对象 + * 返回值说明: 是否添加成功提示 + ***********************************/ + boolean addMenu(SysMenu sysMenu); + + /*********************************** + * 用途说明:上传单个图标 + * 参数说明 + * id 上传图标id + * icon 图标 + * 返回值说明: 是否上传成功 + ***********************************/ + boolean uploadIcon(String id, MultipartFile icon); + + /*********************************** + * 用途说明:根据id删除单个图标 + * 参数说明 + * id 删除图标id + * icon 图标名称 + * 返回值说明: 是否删除成功 + ***********************************/ + boolean deleteIcon(String id); + + /*********************************** + * 用途说明:菜单及按钮序号排序 + * 参数说明 + * parentid 上级id + * orderMap map<菜单及按钮表id,排列序号> + * 返回值说明: 是否更新成功 + ***********************************/ + boolean moveOrderno(String parentid, String id, int orderno); + + /*********************************** + * 用途说明:根据id删除菜单或按钮 + * 参数说明 + * id 删除列的id + * 返回值说明: 是否删除成功 + ***********************************/ + boolean deleteById(String id); + + boolean changeOderNoById(String fromId, String toId); + + List> getMenuTree(String id); + + /*********************************** + * 用途说明:权限分配 + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + List> permissionAssignment(String roleId); + + String uploadIcon(MultipartFile icon) throws FileNotFoundException; +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysOrganizationService.java b/src/main/java/com/yfd/platform/system/service/ISysOrganizationService.java new file mode 100644 index 0000000..5b03119 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysOrganizationService.java @@ -0,0 +1,60 @@ +package com.yfd.platform.system.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysOrganization; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统组织框架 服务类 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +public interface ISysOrganizationService extends IService { + + /*********************************** + * 用途说明:获取组织结构树 + * 参数说明 + *parentid 上级id + * params 名称(根据名称查询二级) + * 返回值说明: 组织树集合 + ***********************************/ + List> getOrgTree(String parentid, String params); + + /*********************************** + * 用途说明:新增系统组织框架 + * 参数说明 + * sysOrganization 系统组织框架对象 + * 返回值说明: 是否新增成功 + ***********************************/ + boolean addOrg(SysOrganization sysOrganization); + + /*********************************** + * 用途说明:根据企业ID查询组织详情 + * 参数说明 + * id 企业id + * 返回值说明: 系统组织框架对象 + ***********************************/ + List getOrganizationById(String id,String orgName); + + /*********************************** + * 用途说明:获取组织范围树结构 + * 参数说明 + *roleId 角色id + * 返回值说明: 组织树集合 + ***********************************/ + List> getOrgScopeTree(String roleId); + + /********************************** + * 用途说明: 修改角色组织范围 + * 参数说明 roleId 角色id + * 参数说明 orgscope 组织id集合 + * 返回值说明: boolean 是否修改成功 + ***********************************/ + boolean updateOrgScopeByRoleId(String roleId, String orgscope); +} diff --git a/src/main/java/com/yfd/platform/system/service/ISysRoleService.java b/src/main/java/com/yfd/platform/system/service/ISysRoleService.java new file mode 100644 index 0000000..7dcdb5c --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/ISysRoleService.java @@ -0,0 +1,66 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.system.domain.SysRole; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统角色 服务类 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +public interface ISysRoleService extends IService { + + /*********************************** + * 用途说明:新增角色 + * 参数说明 + * sysRole 新增角色信息 + * 返回值说明: 是否新增成功 + ***********************************/ + boolean addRole(SysRole sysRole); + + /*********************************** + * 用途说明:删除角色用户 + * 参数说明 + * id 系统角色用户对照表id + * 返回值说明: 是否新增成功 + ***********************************/ + + boolean deleteRoleUsers(String roleid, String urserids); + + /*********************************** + * 用途说明:根据id删除角色 + * 参数说明 + *id 角色id + * 返回值说明: 是否删除成功 + ***********************************/ + void deleteById(String id); + + /*********************************** + * 用途说明:查询已分配的用户 + * 参数说明 + *orgid 所属组织 + *username 用户名称 + *status 状态 + *level 角色级别 + * rolename 角色名称 + * isvaild 角色是否有效 + * 返回值说明: 系统用户角色数据集合 + ***********************************/ + List listRoleUsers(String orgid, String username, String status, String level, String rolename, String isvaild); + + + /*********************************** + * 用途说明:角色分配权限 + * 参数说明 + * id 角色id + * menuIds 权限id字符串 + * 返回值说明: 是否分配成功 + ***********************************/ + boolean setMenuById(String id, String menuIds); +} diff --git a/src/main/java/com/yfd/platform/system/service/IUserService.java b/src/main/java/com/yfd/platform/system/service/IUserService.java new file mode 100644 index 0000000..b141e53 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/IUserService.java @@ -0,0 +1,143 @@ +package com.yfd.platform.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.LoginUser; +import com.yfd.platform.system.domain.SysUser; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统用户 + *

+ * + * @author zhengsl + * @since 2021-10-27 + */ +public interface IUserService extends IService { + + //获取当前用户账号及名称 + String getUsername(); + + //获取当前用户信息 + SysUser getUserInfo(); + /*********************************** + * 用途说明:获取当前用户账号与姓名 + * 返回值说明: 当前用户账号与姓名 + ************************************/ + Map getNameInfo(); + //获取当前用户信息带权限 + ResponseResult getLoginUserInfo(); + + /*********************************** + * 用途说明:新增用户 + * 参数说明 + *sysUser 新增用户对象 + * id 创建者id + * roleId 角色id + * 返回值说明: 提示字符串 + ************************************/ + Map addUser(SysUser sysUser, String roleids); + + /*********************************** + * 用途说明:查询系统用户 + * 参数说明 + *page 分页集合参数 + *orgid 所属组织 + *username 用户名称 + * mobile 手机号 + * status 状态 + * 返回值说明: 用户分页集合 + ************************************/ + List list(String total, String size, String orgid, String username, + String mobile, String status); + + /*********************************** + * 用途说明:根据ID查询用户详情 + * 参数说明 + *id 用户id + * 返回值说明: 用户表对象 + ************************************/ + Map getOneById(String id); + + /*********************************** + * 用途说明:根据ID修改用户 + * 参数说明 + *sysUser 用户对象 + *roleids 角色id + * 返回值说明: 是否更新成功 + ************************************/ + Map updateById(SysUser sysUser, String roleids); + + /*********************************** + * 用途说明:用户分配角色(多个) + * 参数说明 + *roleid 角色id + * userids 用户id数组 + * 返回值说明: 判断是否添加成功 + ************************************/ + boolean setUserRoles(String roleid, String userids); + + /*********************************** + * 用途说明:根据id删除用户 + * 参数说明 + *id 用户id + * 返回值说明: 判断是否删除成功 + ************************************/ + boolean deleteById(String id); + + /*********************************** + * 用途说明:重置用户密码(管理员) + * 参数说明 + *id 重置密码的 用户id + * 返回值说明: 判断是否重置成功 + ************************************/ + boolean resetPassword(String id) throws Exception; + + /*********************************** + * 用途说明:设置账号状态(管理员) + * 参数说明 + *id 用户id + * status 设置状态 + * 返回值说明: 判断是否设置成功 + ************************************/ + boolean setStatus(String id, String status); + + /*********************************** + * 用途说明:上传用户头像 + * 参数说明 + * id 用户id + * img 账号头像 + * 返回值说明: 判断是否上传 + ***********************************/ + boolean uploadAvatar(String id, MultipartFile img); + + /*********************************** + * 用途说明:新增系统角色用户对照表 对用户分配角色(单个) + * 参数说明 + * id 生成的id + * userid 用户id + * roleid 角色id + * 返回值说明: + ************************************/ + boolean addUserRoles(String roleid, String userid); + + //Page queryUsers(String orgid, String username, Page page); + Page> queryUsers(String orgid, String username, Page page); + + /*********************************** + * 用途说明:根据ID批量删除用户 + * 参数说明 + *ids 用户id集合 + * 返回值说明: 判断是否删除成功 + ************************************/ + boolean deleteUserByIds(String ids); + + + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/MessageServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/MessageServiceImpl.java new file mode 100644 index 0000000..0d3875f --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/MessageServiceImpl.java @@ -0,0 +1,20 @@ +package com.yfd.platform.system.service.impl; + +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.mapper.MessageMapper; +import com.yfd.platform.system.service.IMessageService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 消息通知 服务实现类 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +@Service +public class MessageServiceImpl extends ServiceImpl implements IMessageService { + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/QuartzJobServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/QuartzJobServiceImpl.java new file mode 100644 index 0000000..d2a9030 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/QuartzJobServiceImpl.java @@ -0,0 +1,114 @@ +package com.yfd.platform.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yfd.platform.system.domain.QuartzJob; +import com.yfd.platform.system.domain.SysDictionary; +import com.yfd.platform.system.mapper.QuartzJobMapper; +import com.yfd.platform.system.service.IQuartzJobService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.utils.QuartzManage; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + *

+ * 定时任务 服务实现类 + *

+ * + * @author TangWei + * @since 2023-03-19 + */ +@Service +public class QuartzJobServiceImpl extends ServiceImpl implements IQuartzJobService { + + @Resource + private QuartzJobMapper quartzJobMapper; + + @Resource + private QuartzManage quartzManage; + + /********************************** + * 用途说明: 新增定时任务 + * 参数说明 quartzJob 定时对象 + * 返回值说明: boolean 是否成功 + ***********************************/ + @Override + public boolean addQuartzJob(QuartzJob quartzJob) { + // 生成序号 + long orderNo = this.count() + 1L; + quartzJob.setOrderno((int) orderNo); + return this.save(quartzJob); + } + + /********************************** + * 用途说明: 删除定时任务 + * 参数说明 id id + * 返回值说明: boolean 是否成功 + ***********************************/ + @Override + public boolean deleteQuartzJob(String id) { + String[] split = id.split(","); + Set ids = Arrays.stream(split).collect(Collectors.toSet()); + for (String s : ids) { + QuartzJob quartzJob = this.getById(s); + quartzManage.deleteJob(quartzJob); + this.removeById(s); + } + + // 查询所有定时任务 + List list = + this.list(new LambdaQueryWrapper().orderByAsc(QuartzJob::getOrderno)); + // 更新序号 + for (int i = 0; i < list.size(); i++) { + QuartzJob quartzJob = list.get(i); + quartzJob.setOrderno(i + 1); + this.updateById(quartzJob); + } + return true; + } + + /********************************** + * 用途说明: 拖动修改定时任务顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + @Override + public boolean changeDictOrder(String fromID, String toID) { + QuartzJob fromQuartzJob = + quartzJobMapper.selectById(fromID); + QuartzJob toQuartzJob = quartzJobMapper.selectById(toID); + // 如果数据字典不存在拖动失败 + if (fromQuartzJob == null || toQuartzJob == null) { + return false; + } + Integer fromOrderNo = fromQuartzJob.getOrderno(); + Integer toOrderNo = toQuartzJob.getOrderno(); + // 如果数据字典的顺序号不存在拖动失败 + if (fromOrderNo == null || toOrderNo == null) { + return false; + } + // 将顺序号放入字典对象中 + fromQuartzJob.setOrderno(toOrderNo); + toQuartzJob.setOrderno(fromOrderNo); + // 更改顺序号 + boolean fromBool = this.updateById(fromQuartzJob); + boolean toBool = this.updateById(toQuartzJob); + return fromBool && toBool; + } + + /********************************** + * 用途说明: 执行定时任务 + * 参数说明 id id + * 返回值说明: void + ***********************************/ + @Override + public void execution(QuartzJob quartzJob) { + quartzManage.runJobNow(quartzJob); + } +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysConfigServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..da15188 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,34 @@ +package com.yfd.platform.system.service.impl; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.system.domain.SysConfig; +import com.yfd.platform.system.mapper.SysConfigMapper; +import com.yfd.platform.system.service.ISysConfigService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 系统全局配置 服务实现类 + *

+ * + * @author zhengsl + * @since 2022-01-19 + */ +@Service +public class SysConfigServiceImpl extends ServiceImpl implements ISysConfigService { + @Resource + private UserServiceImpl currentUser; + + + + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysDictionaryItemsServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysDictionaryItemsServiceImpl.java new file mode 100644 index 0000000..26a30ab --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysDictionaryItemsServiceImpl.java @@ -0,0 +1,123 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.system.domain.SysDictionaryItems; +import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; +import com.yfd.platform.system.service.ISysDictionaryItemsService; +import com.yfd.platform.utils.FileUtil; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + *

+ * 数据字典明细 服务实现类 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@Service +public class SysDictionaryItemsServiceImpl extends ServiceImpl implements ISysDictionaryItemsService { + + @Resource + private SysDictionaryItemsMapper sysDictionaryItemsMapper; + + /********************************** + * 用途说明: 分页查询字典项信息 + * 参数说明 dictID 字典ID ItemName 字典项名称 pageNum 当前页 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + @Override + public Page getDictItemPage(String dictId, + String itemName, + Page page) { + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(itemName)) { + queryWrapper.like(SysDictionaryItems::getDictName, itemName); + } + queryWrapper.eq(SysDictionaryItems::getDictId, dictId).orderByAsc(SysDictionaryItems::getOrderNo); + return sysDictionaryItemsMapper.selectPage(page, queryWrapper); + } + + /********************************** + * 用途说明: 增加字典项 + * 参数说明 sysDictionaryItems 字典项信息 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败 + ***********************************/ + @Override + public boolean addDictionaryItem(SysDictionaryItems sysDictionaryItems) { + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + queryWrapper.eq(SysDictionaryItems::getDictId,sysDictionaryItems.getDictId()); + long orderNo = this.count(queryWrapper) + 1L; + // 添加顺序号 + sysDictionaryItems.setOrderNo((int) orderNo); + return this.save(sysDictionaryItems); + } + + /********************************** + * 用途说明: 拖动修改字典项顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + @Override + public boolean changeItemOrder(String fromID, String toID) { + SysDictionaryItems fromSysDictionaryItems = + sysDictionaryItemsMapper.selectById(fromID); + SysDictionaryItems toSysDictionaryItems = + sysDictionaryItemsMapper.selectById(toID); + // 如果数据字典项不存在拖动失败 + if (fromSysDictionaryItems == null || toSysDictionaryItems == null) { + return false; + } + Integer fromOrderNo = fromSysDictionaryItems.getOrderNo(); + Integer toOrderNo = toSysDictionaryItems.getOrderNo(); + // 如果数据字典的顺序号不存在拖动失败 + if (fromOrderNo == null || toOrderNo == null) { + return false; + } + // 将顺序号放入字典对象中 + fromSysDictionaryItems.setOrderNo(toOrderNo); + toSysDictionaryItems.setOrderNo(fromOrderNo); + // 更改顺序号 + boolean fromBool = this.updateById(fromSysDictionaryItems); + boolean toBool = this.updateById(toSysDictionaryItems); + return fromBool && toBool; + + } + + /********************************** + * 用途说明: 导出数据字典项数据 + * 参数说明 sysDictionaryItemsList 所需导出的字典项集合 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回导出成功或失败 + ***********************************/ + @Override + public void exportExcel(List sysDictionaryItems, + HttpServletResponse response) { + try { + List> list = new LinkedList<>(); + for (SysDictionaryItems sysDictionaryItem : sysDictionaryItems) { + Map map = new LinkedHashMap<>(); + map.put("项编号", sysDictionaryItem.getItemCode()); + map.put("项名称", sysDictionaryItem.getDictName()); + map.put("父编码", sysDictionaryItem.getParentCode()); + map.put("备注", sysDictionaryItem.getCustom1()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysDictionaryServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysDictionaryServiceImpl.java new file mode 100644 index 0000000..58508b3 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysDictionaryServiceImpl.java @@ -0,0 +1,114 @@ +package com.yfd.platform.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.system.domain.SysDictionary; +import com.yfd.platform.system.domain.SysDictionaryItems; +import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; +import com.yfd.platform.system.mapper.SysDictionaryMapper; +import com.yfd.platform.system.service.ISysDictionaryService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import jakarta.annotation.Resource; +import java.util.List; + +/** + *

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

+ * + * @author TangWei + * @since 2023-03-08 + */ +@Service +public class SysDictionaryServiceImpl extends ServiceImpl implements ISysDictionaryService { + + @Resource + private SysDictionaryMapper sysDictionaryMapper; + + @Resource + private SysDictionaryItemsMapper sysDictionaryItemsMapper; + + /********************************** + * 用途说明: 获取数据字典列表 + * 参数说明 dictType 字典类型 + * 返回值说明: 返回字典列表集合 + ***********************************/ + @Override + public List getDictList(String dictType) { + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + queryWrapper.eq(SysDictionary::getDictType, dictType).orderByAsc(SysDictionary::getOrderNo); + return sysDictionaryMapper.selectList(queryWrapper); + } + + /********************************** + * 用途说明: 新增字典 + * 参数说明 sysDictionary 字典对象 + * 返回值说明: 返回增加成功或者失败 + ***********************************/ + @Override + public boolean addDict(SysDictionary sysDictionary) { + //int orderNo = this.count() + 1; + Integer maxNo = + sysDictionaryMapper.selectMaxNo(sysDictionary.getDictType()); + if (maxNo == null) { + maxNo = 0; + } + // 添加顺序号 + sysDictionary.setOrderNo(maxNo + 1); + return this.save(sysDictionary); + } + + /********************************** + * 用途说明: 根据ID删除字典 + * 参数说明 id 字典ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除结果成功或者失败 + ***********************************/ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteDictById(String id) { + // 根据字典编码查询字典项中是否关联 + boolean isok=true; + QueryWrapper Wrapper = new QueryWrapper<>(); + Wrapper.eq("dictid", id); + if(sysDictionaryItemsMapper.delete(Wrapper)>0) { + isok=true; + } + return isok&&this.removeById(id); + } + + /********************************** + * 用途说明: 拖动修改字典顺序 + * 参数说明 fromID 当前ID toID 到达ID + * 返回值说明: com.yfd.platform.config.ResponseResult 返回拖动成功或者失败 + ***********************************/ + @Override + public boolean changeDictOrder(String fromID, String toID) { + SysDictionary fromSysDictionary = + sysDictionaryMapper.selectById(fromID); + SysDictionary toSysDictionary = sysDictionaryMapper.selectById(toID); + // 如果数据字典不存在拖动失败 + if (fromSysDictionary == null || toSysDictionary == null) { + return false; + } + Integer fromOrderNo = fromSysDictionary.getOrderNo(); + Integer toOrderNo = toSysDictionary.getOrderNo(); + // 如果数据字典的顺序号不存在拖动失败 + if (fromOrderNo == null || toOrderNo == null) { + return false; + } + // 将顺序号放入字典对象中 + fromSysDictionary.setOrderNo(toOrderNo); + toSysDictionary.setOrderNo(fromOrderNo); + // 更改顺序号 + boolean fromBool = this.updateById(fromSysDictionary); + boolean toBool = this.updateById(toSysDictionary); + return fromBool && toBool; + } + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysLogServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysLogServiceImpl.java new file mode 100644 index 0000000..ee671bf --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysLogServiceImpl.java @@ -0,0 +1,219 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.annotation.Log; +import com.yfd.platform.system.domain.SysLog; +import com.yfd.platform.system.mapper.SysLogMapper; +import com.yfd.platform.system.mapper.SysUserMapper; +import com.yfd.platform.system.service.ISysLogService; +import com.yfd.platform.utils.FileUtil; +import com.yfd.platform.utils.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + *

+ * 系统操作日志 服务实现类 + *

+ * + * @author TangWei + * @since 2023-03-08 + */ +@Service +public class SysLogServiceImpl extends ServiceImpl implements ISysLogService { + + @Resource + private SysLogMapper sysLogMapper; + + /********************************** + * 用途说明: 分页查询日志信息 + * 参数说明 pageNum(页码数)、pageSize(页大小,如果是固定页大小可不传)、username(用户名)、(optType) + * 操作类型、startDate(开始日期)、endDate(结束日期) + * 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果 + ***********************************/ + @Override + public Page getLogList(String username, String optType, + String startDate, + String endDate, Page page) { + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // 没有传username就不按此条件查询 + if (StrUtil.isNotBlank(username)) { + queryWrapper.like(SysLog::getUsername, username); + } + // 没有传optType就不按此条件查询 + if (StrUtil.isNotBlank(optType)) { + queryWrapper.eq(SysLog::getOpttype, optType); + } + DateTime parseStartDate = DateUtil.parse(startDate); + DateTime parseEndDate = DateUtil.parse(endDate); + DateTime dateTime = DateUtil.offsetDay(parseEndDate, 1); + if (parseStartDate != null && parseEndDate != null) { + queryWrapper.ge(SysLog::getLogtime, parseStartDate).lt(SysLog::getLogtime, dateTime); + } + + queryWrapper.orderByDesc(SysLog::getLogtime); + return sysLogMapper.selectPage(page, queryWrapper); + } + + /********************************** + * 用途说明: 导出日志数据 + * 参数说明 sysLogs 所需导出的字典项集合 + * 返回值说明: com.yfd.platform.config.ResponseResult 返回导出成功或者失败 + ***********************************/ + @Override + public void exportExcel(List sysLogs, + HttpServletResponse response) { + try { + List> list = new LinkedList<>(); + for (SysLog sysLog : sysLogs) { + Map map = new LinkedHashMap<>(); + map.put("操作账号", sysLog.getUsercode()); + map.put("用户姓名", sysLog.getUsername()); + map.put("IP地址", sysLog.getRequestip()); + map.put("浏览器", sysLog.getBrowser()); + map.put("日志类型", sysLog.getOpttype()); + map.put("模块名称", sysLog.getModule()); + map.put("日志描述", sysLog.getDescription()); + Timestamp logTime = sysLog.getLogtime(); + String dateTime = ""; + if (logTime != null) { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd " + + "HH:mm:ss"); + dateTime = df.format(logTime); + } + + /*String dateTime = ""; + if (logTime != null) { + dateTime = logTime.format(DateTimeFormatter.ofPattern( + "yyyy-MM-dd HH:mm:ss")); + }*/ + + map.put("操作日期", dateTime); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /********************************** + * 用途说明: 新增日志 + * 参数说明 nickname 用户名 + * 参数说明 username 用户账号 + * 参数说明 browser 浏览器 + * 参数说明 ip 本机Ip地址 + * 参数说明 joinPoint 连接点 + * 参数说明 log 日志信息 + * 返回值说明: void + ***********************************/ + @Override + public void save(String nickname, String username, String browser, + String ip, + ProceedingJoinPoint joinPoint, SysLog log) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + Log aopLog = method.getAnnotation(Log.class); + // 方法路径 + String methodName = + joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()"; + // 描述 + if (log != null) { + log.setDescription(aopLog.value()); + log.setModule(aopLog.module()); + } + assert log != null; + log.setUsercode(username); + log.setRequestip(ip); + log.setMethod(methodName); + log.setUsername(nickname); + log.setParams(getParameter(method, joinPoint.getArgs())); + log.setBrowser(browser); + String operationtype = getOperationtype(signature.getName()); + log.setOpttype(operationtype); + log.setLogtime(new Timestamp(System.currentTimeMillis())); + sysLogMapper.insert(log); + } + + /** + * 根据方法和传入的参数获取请求参数 + */ + private String getParameter(Method method, Object[] args) { + List argList = new ArrayList<>(); + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + //将RequestBody注解修饰的参数作为请求参数 + AnnotatedType type = parameters[i].getAnnotatedType(); + + RequestBody requestBody = + parameters[i].getAnnotation(RequestBody.class); + if (requestBody != null) { + argList.add(args[i]); + } + + //将RequestParam注解修饰的参数作为请求参数 + RequestParam requestParam = + parameters[i].getAnnotation(RequestParam.class); + if (requestParam != null) { + Map map = new HashMap<>(); + String key = parameters[i].getName(); + if (!StringUtils.isEmpty(requestParam.value())) { + key = requestParam.value(); + } + map.put(key, args[i]); + argList.add(map); + } + } + if (argList.size() == 0) { + return ""; + } + return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : + JSONUtil.toJsonStr(argList); + } + + public static String getOperationtype(String value) { + String type = ""; + if (value.contains("get") || value.contains("select")) { + type = "查询(select)"; + } else if (value.contains("add") || value.contains("insert")) { + type = "添加(insert)"; + } else if (value.contains("update") || value.contains("upd") || value.contains("change") || value.contains("set")) { + type = "修改(update)"; + } else if (value.contains("delete") || value.contains("del")) { + type = "删除(delete)"; + } else if (value.contains("dowload")) { + type = "下载(dowload)"; + } else if (value.contains("import")) { + type = "导入(import)"; + } else if (value.contains("word")) { + type = "word转pdf(wordToPdf)"; + } else { + type = "其他(other)"; + } + return type; + } + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysMenuServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..b53b789 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,674 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.system.domain.SysMenu; +import com.yfd.platform.system.domain.SysRole; +import com.yfd.platform.system.mapper.SysMenuMapper; +import com.yfd.platform.system.mapper.SysRoleMapper; +import com.yfd.platform.system.service.ISysMenuService; +import com.yfd.platform.utils.FileUtil; +import com.yfd.platform.config.FileSpaceProperties; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ResourceUtils; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.annotation.Resource; +import java.io.File; +import java.io.FileNotFoundException; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 菜单及按钮 服务实现类 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@Service +@Transactional +public class SysMenuServiceImpl extends ServiceImpl implements ISysMenuService { + + @Resource + private SysMenuMapper sysMenuMapper; + + @Resource + private UserServiceImpl currentUser; + + @Resource + private SysRoleMapper sysRoleMapper; + + // 菜单图片路径配置 + @Resource + private FileSpaceProperties fileSpaceProperties; + + /*********************************** + * 用途说明:查询菜单及按钮树状图 + * 参数说明 + * systemcode 系统 + *isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + @Override + public List> getMenuButtonTree(String systemcode, + String name, + String isdisplay) { + List> listMap=null; + if(StrUtil.isEmpty(name)){//不带名称查询,返回树结构 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("parentid", "0").eq("systemcode", systemcode).orderByAsc("orderno"); + listMap = this.listMaps(queryWrapper); + + for (int i = 0; i < listMap.size(); i++) { + //查询下一子集 + List> childList = child(listMap.get(i).get( + "id").toString(), systemcode, name, null, null); + listMap.get(i).put("children", childList); //添加新列 子集 + } + }else{ //根据菜单名称查询,直接返回类别 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.like("name", name).eq("systemcode", systemcode).orderByAsc("name"); + listMap = this.listMaps(queryWrapper); + } + + + + return listMap; + } + + /*********************************** + * 用途说明:获取菜单结构树(不含按钮) + * 参数说明 + * systemcode 系统 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + @Override + public List> getMenuTree(String systemcode, + String name, + String isdisplay) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(isdisplay)) { + queryWrapper.eq("isdisplay", isdisplay); + } else { + queryWrapper.eq("isdisplay", 1); + } + + //根据系统 ,类型不为2 显示,序号 正序排序 + queryWrapper.eq("parentid", "0").eq("systemcode", systemcode).ne( + "type", "2").orderByAsc("orderno"); + List> listMap = this.listMaps(queryWrapper); + for (int i = 0; i < listMap.size(); i++) { + List> childList = child(listMap.get(i).get( + "id").toString(), systemcode, name, isdisplay, "2");//查询下一子集 + listMap.get(i).put("children", childList); //添加新列 子集 + } + return listMap; + } + + /*********************************** + * 用途说明:查询菜单及按钮树状图 + * 参数说明 + * parentid 上级id + *systemcode 系统 + * isdisplay 是否显示 + * type 按钮 + * 返回值说明: 菜单结构树集合 + ***********************************/ + private List> child(String parentid, + String systemcode, String name, + String isdisplay, String type) { + List> listMap = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("parentid", parentid).eq("systemcode", systemcode); + //根据上级id 系统 查询 + if (StrUtil.isNotEmpty(type)) { + queryWrapper.ne("type", type); + } + + if (StrUtil.isNotEmpty(name)) { //根据菜单名称查询 + queryWrapper.like("name", name); + } + listMap = this.listMaps(queryWrapper.orderByAsc("orderno")); + if (listMap.size() > 0) { //判断是否存在子集 + for (int i = 0; i < listMap.size(); i++) { //遍历表数据 + List> childList = + child(listMap.get(i).get("id").toString(), systemcode + , name, isdisplay, type); //循环获取下一子集 + listMap.get(i).put("children", childList); //添加新列 子集 + } + } + + return listMap; + } + + /*********************************** + * 用途说明:新增菜单及按钮 + * 参数说明 + * sysMenu 菜单或按钮表对象 + * 返回值说明: 是否添加成功提示 + ***********************************/ + @Override + public boolean addMenu(SysMenu sysMenu) { + String parentId = sysMenu.getParentid(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + //根据上级id 查询到总数 并累加 + long orderno = this.count(queryWrapper.eq("parentid", + parentId)) + 1L; + // 生成排序号 + sysMenu.setOrderno((int) orderno); + // 生成编号 + QueryWrapper queryMaxCode = new QueryWrapper<>(); + queryMaxCode.eq("parentid", + parentId); + // 查询最大的编号 + List maxList = this.listObjs(queryMaxCode.select("max(code) " + + "code").eq("systemcode", sysMenu.getSystemcode())); + SysMenu parentMenu = sysMenuMapper.selectById(parentId); + // 最大编号转换成int类型 + String maxCode = maxList.size() > 0 ? maxList.get(0).toString() : "0"; + int max = ObjectUtil.isEmpty(maxList) ? 0 : + Integer.parseInt(maxCode); + DecimalFormat df; + if ("0".equals(sysMenu.getParentid())) { + df = new DecimalFormat("00"); + } else if (parentMenu.getCode().length() == 2) { + df = new DecimalFormat("0000"); + } else { + df = new DecimalFormat("000000"); + } + //DecimalFormat df = new DecimalFormat("00"); + //int parentCode = Integer.parseInt(parentMenu.getCode()); + String parentCode = ""; + if (parentMenu != null) { + parentCode = parentMenu.getCode(); + } + // 生成的新编号 年月日+4位编号 + String code; + if (max > 0) { + code = df.format(max + 1); + } else { + max = max + 1; + if (StrUtil.isBlank(parentCode)) { + parentCode = "0" + max; + } else { + int i = Integer.parseInt(parentCode); + parentCode = i + "0" + max; + } + + int format = Integer.parseInt(parentCode); + code = df.format(format); + } + + // 判断是否显示字段 是否填写 为空 + if (StrUtil.isEmpty(sysMenu.getIsdisplay())) { + // 默认设置成 1 显示 + sysMenu.setIsdisplay("1"); + } + // 判断是否填写父级id 为空 默认设置成 0 + if (StrUtil.isEmpty(sysMenu.getParentid())) { + sysMenu.setParentid("0"); + } + // 添加编号 + sysMenu.setCode(code); + // 添加排序号 + sysMenu.setOrderno((int) orderno); + // 添加最近修改人 + sysMenu.setLastmodifier(currentUser.getUsername()); + // 添加最近修改时间 + sysMenu.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + return this.save(sysMenu); + } + + /*********************************** + * 用途说明:上传单个图标 + * 参数说明 + * id 上传图标id + * icon 图标 + * 返回值说明: 是否上传成功 + ***********************************/ + @Override + public boolean uploadIcon(String id, MultipartFile icon) { + //根据id查询 + SysMenu sysMenu = this.getById(id); + //图片路径 + String iconPath = fileSpaceProperties.getSystem() + "menu" + File.separator; + String iconname = + IdUtil.fastSimpleUUID() + "." + FileUtil.getExtensionName(icon.getOriginalFilename()); + //上传图标并获取图标名称 (图片改为png格式) + String filename = + FileUtil.upload(icon, iconPath, iconname).getName(); + //更新图标名称 + sysMenu.setIcon(filename); + //添加最近修改人 + sysMenu.setLastmodifier(currentUser.getUsername()); + //添加最近修改时间 + sysMenu.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //更新数据 + boolean isOk = this.updateById(sysMenu); + return isOk; + } + + /*********************************** + * 用途说明:根据id删除单个图标 + * 参数说明 + * id 删除图标id + * icon 图标名称 + * 返回值说明: 是否删除成功 + ***********************************/ + @Override + public boolean deleteIcon(String id) { + //根据id查询 + SysMenu sysMenu = this.getById(id); + //图片路径 + String iconname = + System.getProperty("user.dir") + "\\src\\main" + + "\\resources\\static\\icon" + File.separator + sysMenu.getIcon(); + //更新图标名称 + sysMenu.setIcon(""); + //添加最近修改人 + sysMenu.setLastmodifier(currentUser.getUsername()); + //添加最近修改时间 + sysMenu.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //更新数据 + boolean isOk = this.updateById(sysMenu); + //更新成功 删除图片 + if (isOk == true) { + FileUtil.del(iconname); + } + return isOk; + } + + /*********************************** + * 用途说明:菜单及按钮序号排序 + * 参数说明 + * parentid 上级id + * id + * orderno 更改后序号 + * 返回值说明: 是否更新成功 + ***********************************/ + @Override + public boolean moveOrderno(String parentid, String id, int orderno) { + boolean ok = true; + SysMenu sysMenu = this.getById(id); //根据id查询原顺序号 + if (sysMenu.getOrderno() > orderno) { + ok = sysMenuMapper.upMoveOrderno(parentid, sysMenu.getOrderno(), + orderno); //根据 父级id 小于原序号 大于等于更改序号 + } else { + ok = sysMenuMapper.downMoveOrderno(parentid, sysMenu.getOrderno() + , orderno); //根据 父级id 大于原序号 小于等于更改序号 + } + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + ok = ok && this.update(updateWrapper.eq("id", id).set("orderno", + orderno)); //根据 id修改序号 + return ok; + } + + /*********************************** + * 用途说明:根据id删除菜单或按钮 + * 参数说明 + * id 删除列的id + * 返回值说明: 是否删除成功 + ***********************************/ + @Override + public boolean deleteById(String id) { + //根据id查询 + SysMenu sysMenu = this.getById(id); + //图片路径 + String iconname = + fileSpaceProperties.getSystem() + "menu" + File.separator + sysMenu.getIcon(); + //删除图标 + new File(iconname).delete(); + //根据id删除 + boolean isOk = this.removeById(id); + //删除成功同步更新表数据 + if (isOk) { + //1 创建list集合,用于封装所有删除目录或菜单id值 + List idList = new ArrayList<>(); + this.selectPermissionChildById(id, idList); + if (idList.size() > 0) { + sysMenuMapper.deleteBatchIds(idList); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + //根据上级id 查询 根据 orderno 正序排序 + queryWrapper.eq("parentid", sysMenu.getParentid()).orderByAsc( + "orderno"); + List list = this.list(queryWrapper); + for (int i = 0; i < list.size(); i++) { + SysMenu menu = list.get(i); + //更新序列号 + menu.setOrderno(i + 1); + } + //更新表数据 + this.updateBatchById(list); + } + return isOk; + } + + //2 根据当前菜单id,查询菜单里面子菜单id,封装到list集合 + private void selectPermissionChildById(String id, List idList) { + //查询菜单里面子菜单id + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("parentid", id); + wrapper.select("id"); + List childIdList = baseMapper.selectList(wrapper); + //把childIdList里面菜单id值获取出来,封装idList里面,做递归查询 + childIdList.stream().forEach(item -> { + //封装idList里面 + idList.add(item.getId()); + //递归查询 + this.selectPermissionChildById(item.getId(), idList); + }); + } + + /********************************** + * 用途说明: 调换菜单或按钮的位置 + * 参数说明 upperId 选中的菜单Id + * 参数说明 belowId 切换的菜单Id + * 返回值说明: boolean + ***********************************/ + @Override + @Transactional + public boolean changeOderNoById(String fromId, String toId) { + SysMenu fromSysMenu = this.getById(fromId); + SysMenu toSysMenu = this.getById(toId); + // 如果菜单或按钮不存在拖动失败 + if (fromSysMenu == null || toSysMenu == null) { + return false; + } + Integer fromOrderNo = fromSysMenu.getOrderno(); + Integer toOrderNo = toSysMenu.getOrderno(); + // 如果菜单或按钮的顺序号不存在拖动失败 + if (fromOrderNo == null || toOrderNo == null) { + return false; + } + fromSysMenu.setOrderno(toOrderNo); + toSysMenu.setOrderno(fromOrderNo); + boolean fromBool = this.updateById(fromSysMenu); + boolean toBool = this.updateById(toSysMenu); + return fromBool && toBool; + } + + /********************************** + * 用途说明: 根据用户id获取菜单树 + * 参数说明 id 用户id + * 返回值说明: 返回菜单树 + ***********************************/ + @Override + public List> getMenuTree(String id) { + // 根据id获取菜单 + //List sysMenus = sysMenuMapper.selectMenuByUserId(id); + List> list; + if (StrUtil.isBlank(id)) { + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + list = this.listMaps(queryWrapper.eq(SysMenu::getIsdisplay, "1").ne(SysMenu::getType, "2").eq(SysMenu::getSystemcode, "1").orderByAsc(SysMenu::getOrderno)); + } else { + list = sysMenuMapper.selectMenuByUserId(id); + } + // 将菜单转换成树 + List> sysMenus = buildTreeLeft(list); + return sysMenus; + } + + /*********************************** + * 用途说明:权限分配 + * 参数说明 + * systemcode 系统 + * name 名称 + * isdisplay 是否显示 + * 返回值说明: 菜单结构树集合 + ***********************************/ + @Override + public List> permissionAssignment(String roleId) { + + String code = sysMenuMapper.getSystemCodeById(roleId); + if (code == null) { + code = "1"; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysMenu::getSystemcode, code).select(SysMenu::getId, + SysMenu::getParentid, SysMenu::getName).orderByAsc + (SysMenu::getOrderno); + List> listAll = + sysMenuMapper.selectMaps(queryWrapper); + List listRole = + sysMenuMapper.selectMenuByRoleId(roleId); + for (Map map : listAll) { + String id = (String) map.get("id"); + if (listRole.contains(id)) { + map.put("checkinfo", true); + } else { + map.put("checkinfo", false); + } + + } + List> listTree = buildTrees(listAll); + return listTree; + } + + // 另一种方法 + /*public List> permissionAssignment(String roleId) { + + String code = sysMenuMapper.getSystemCodeById(roleId); + if (code == null) { + code = "1"; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysMenu::getSystemcode, code).select(SysMenu::getId, + SysMenu::getParentid, SysMenu::getName).orderByAsc + (SysMenu::getOrderno); + List> listAll = + sysMenuMapper.selectMaps(queryWrapper); + *//*List listRole = + sysMenuMapper.selectMenuByRoleId(roleId);*//* + SysRole sysRole = sysRoleMapper.selectById(roleId); + String optscope = sysRole.getOptscope(); + // 将当前角色所对应权限id拆分 + String[] split = optscope.split(","); + List listRole = Arrays.asList(split); + for (Map map : listAll) { + String id = (String) map.get("id"); + if (listRole.contains(id)) { + map.put("checkinfo", true); + } else { + map.put("checkinfo", false); + } + + } + List> listTree = buildTrees(listAll); + return listTree; + }*/ + + /*********************************** + * 用途说明:上传单个图标 + * 参数说明 + * icon 图标 + * 返回值说明: 是否上传成功 + ***********************************/ + @Override + public String uploadIcon(MultipartFile icon) throws FileNotFoundException { + + String path = System.getProperty("user.dir") + "\\src\\main" + + "\\resources\\"; + //图片路径 + String iconPath = path + "static\\icon" + File.separator; + String iconname = + IdUtil.fastSimpleUUID() + "." + FileUtil.getExtensionName(icon.getOriginalFilename()); + //上传图标并获取图标名称 (图片改为png格式) + String filename = + FileUtil.upload(icon, iconPath, iconname).getName(); + return filename; + } + + /** + * 菜单集合递归生成树状菜单(List) + * + * @param sysMenus 菜单对象 + * @return + */ + /* public List buildTree(List sysMenus) { + List resultMenuList = new ArrayList<>(); + for (SysMenu sysMenu : sysMenus) { + + for (SysMenu menu : sysMenus) { + if (menu.getParentid().equals(sysMenu.getId())) { + sysMenu.getChildren().add(menu); + } + } + if ("0".equals(sysMenu.getParentid())) { + resultMenuList.add(sysMenu); + } + } + return resultMenuList; + }*/ + + /** + * 菜单集合递归生成树状菜单(Map)(暂不使用该方法) + * + * @param sysMenus 菜单对象 + * @return + */ + public List> buildTree(List> sysMenus) { + List> resultMenuList = new ArrayList<>(); + for (Map sysMenu : sysMenus) { + + List> childrenList = new ArrayList<>(); + for (Map menu : sysMenus) { + if (menu.get("parentid").equals(sysMenu.get("id"))) { + childrenList.add(menu); + } + } + if ("0".equals(sysMenu.get("parentid"))) { + if (childrenList.size() > 0) { + sysMenu.put("children", childrenList); + } + resultMenuList.add(sysMenu); + } + } + return resultMenuList; + } + + /********************************** + * 用途说明: 左侧菜单树构建 + * 参数说明 sysMenus + * 返回值说明: java.util.List> + ***********************************/ + public List> buildTreeLeft(List> sysMenus) { + List> resultMenuList = new ArrayList<>(); + for (Map sysMenu : sysMenus) { + if ("0".equals(sysMenu.get("parentid"))) { + resultMenuList.add(sysMenu); + } + } + for (Map sysMenu : resultMenuList) { + List> menus = iterateMenusLeft(sysMenus, + (String) sysMenu.get("id")); + if (menus.size() > 0) { + sysMenu.put("children", menus); + } + } + return resultMenuList; + } + + /** + * 左侧多级菜单查询方法 + * + * @param menuVoList 不包含最高层次菜单的菜单集合 + * @param pid 父类id + * @return + */ + public List> iterateMenusLeft(List> menuVoList, String pid) { + List> result = new ArrayList<>(); + for (Map menu : menuVoList) { + //获取菜单的id + String menuid = (String) menu.get("id"); + //获取菜单的父id + String parentid = (String) menu.get("parentid"); + if (StrUtil.isNotBlank(parentid)) { + if (parentid.equals(pid)) { + //递归查询当前子菜单的子菜单 + List> iterateMenu = + iterateMenus(menuVoList, menuid); + if (iterateMenu.size() > 0) { + menu.put("children", iterateMenu); + } + result.add(menu); + } + } + } + return result; + } + + /********************************** + * 用途说明: 生成权菜单权限树 + * 参数说明 sysMenus + * 返回值说明: java.util.List> + ***********************************/ + public List> buildTrees(List> sysMenus) { + List> resultMenuList = new ArrayList<>(); + for (Map sysMenu : sysMenus) { + if ("0".equals(sysMenu.get("parentid"))) { + resultMenuList.add(sysMenu); + } + } + for (Map sysMenu : resultMenuList) { + List> menus = iterateMenus(sysMenus, + (String) sysMenu.get("id")); + for (Map menu : menus) { + if (!(boolean) menu.get("checkinfo")) { + sysMenu.put("checkinfo", false); + break; + } + } + sysMenu.put("children", menus); + } + return resultMenuList; + } + + /** + * 多级菜单查询方法 + * + * @param menuVoList 不包含最高层次菜单的菜单集合 + * @param pid 父类id + * @return + */ + public List> iterateMenus(List> menuVoList, String pid) { + List> result = new ArrayList<>(); + for (Map menu : menuVoList) { + //获取菜单的id + String menuid = (String) menu.get("id"); + //获取菜单的父id + String parentid = (String) menu.get("parentid"); + if (StrUtil.isNotBlank(parentid)) { + if (parentid.equals(pid)) { + //递归查询当前子菜单的子菜单 + List> iterateMenu = + iterateMenus(menuVoList, menuid); + for (Map map : iterateMenu) { + boolean checkinfo = (boolean) map.get("checkinfo"); + if (!checkinfo) { + menu.put("checkinfo", false); + } + } + menu.put("children", iterateMenu); + result.add(menu); + } + } + } + return result; + } + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java new file mode 100644 index 0000000..01ea014 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java @@ -0,0 +1,338 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysOrganization; +import com.yfd.platform.system.domain.SysRole; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.mapper.SysOrganizationMapper; +import com.yfd.platform.system.mapper.SysRoleMapper; +import com.yfd.platform.system.service.ISysOrganizationService; +import com.yfd.platform.system.service.IUserService; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 系统组织框架 服务实现类 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@Service +public class SysOrganizationServiceImpl extends ServiceImpl implements ISysOrganizationService { + + @Resource + private UserServiceImpl currentUser; + + @Resource + private IUserService userService; + + @Resource + private SysRoleMapper sysRoleMapper; + + @Resource + private SysOrganizationMapper sysOrganizationMapper; + + /*********************************** + * 用途说明:获取组织结构树 + * 参数说明 + *parentid 上级id + * params 名称(根据名称查询二级) + * 返回值说明: 组织树集合 + ***********************************/ + @Override + public List> getOrgTree(String parentid, + String params) { + List> listMap = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + //根据父级id查询 + queryWrapper.eq("parentid", parentid); + if (StrUtil.isNotEmpty(params)) { + queryWrapper.like("orgname", params); // 根据 部门名称 + } + SysUser userInfo = userService.getUserInfo(); + if (userInfo.getUsertype() != 0) { + List roleByUserId = + sysRoleMapper.getRoleByUserId(userInfo.getId()); + List ids = new ArrayList<>(); + // 循环当前角色 + for (SysRole sysRole : roleByUserId) { + // 获取角色的组织Id + String orgscope = sysRole.getOrgscope(); + if (StrUtil.isBlank(orgscope)) { + continue; + } + // 拆分组织Id + String[] split = orgscope.split(","); + List stringList = Arrays.asList(split); + Set set = new HashSet<>(); + if (stringList.size() > 0) { + List list = + sysOrganizationMapper.selectList(new LambdaQueryWrapper().in(SysOrganization::getId, stringList)); + list.forEach(l -> set.add(l.getParentid())); + } + ids.addAll(stringList); + ids.addAll(set); + } + queryWrapper.in("id", ids); + } + listMap = this.listMaps(queryWrapper.orderByAsc("orgcode")); + for (int i = 0; i < listMap.size(); i++) { + List> childList = child(listMap.get(i).get( + "id").toString());//查询下一子集 + listMap.get(i).put("childList", childList); //添加新列 子集 + } + return listMap; + } + + /*********************************** + * 用途说明:获取组织结构树 + * 参数说明 + *parentid 上级id + * params (根据参数查询 组织名称 负责人 描述) + * 返回值说明: 组织树集合 + ***********************************/ + private List> child(String parentid) { + List> listMap = new ArrayList<>(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("parentid", parentid); //根据上级id 查询 + listMap = this.listMaps(queryWrapper.orderByAsc("orgcode")); + if (listMap.size() > 0) { //判断是否存在子集 + for (int i = 0; i < listMap.size(); i++) { //遍历表数据 + List> childList = + child(listMap.get(i).get("id").toString()); //循环获取下一子集 + listMap.get(i).put("childList", childList); //添加新列 子集 + } + } + return listMap; + } + + /*********************************** + * 用途说明:新增系统组织框架 + * 参数说明 + * sysOrganization 系统组织框架对象 + * 返回值说明: 是否新增成功 + ***********************************/ + @Override + public boolean addOrg(SysOrganization sysOrganization) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + SysOrganization parent = null; + int codeMax = 0; + //查询最大的编号 判断是否存在父级id 有值 根据父级id查询 否则 根据父级id为0 查询 + queryWrapper.select("max(orgcode)"); + if (StrUtil.isNotEmpty(sysOrganization.getParentid())) { + //根据父级id查询父级信息 + parent = this.getById(sysOrganization.getParentid()); + queryWrapper.eq("parentid", sysOrganization.getParentid()); + } else { + //默认 填写父级id为0 + sysOrganization.setParentid("0"); + queryWrapper.eq("parentid", "0"); + } + List max = this.listObjs(queryWrapper); + //判断查询是否存在 存在转换成int类型并给codeMax替换值 + if (max.size() > 0) { + codeMax = + Integer.parseInt(max.get(0).toString().substring(max.get(0).toString().length() - 2)); + } + //2位数字编号 + DecimalFormat df = new DecimalFormat("00"); + //编号 + String code = df.format(codeMax + 1); + //查询到父级不为空 重新赋值 父级编号+新的序号 + if (parent != null) { + code = parent.getOrgcode() + df.format(codeMax + 1); + } + //判断是否是否填写 有效 否则默认为 1 + if (StrUtil.isEmpty(sysOrganization.getIsvaild())) { + sysOrganization.setIsvaild("1"); + } + //填写 编号 + sysOrganization.setOrgcode(code); + //填写 当前用户名称 + sysOrganization.setLastmodifier(currentUser.getUsername()); + //填写 当前日期 + sysOrganization.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + return this.save(sysOrganization); + } + + /*********************************** + * 用途说明:根据企业ID查询组织详情 + * 参数说明 + * id 企业id + * 返回值说明: 系统组织框架对象 + ***********************************/ + @Override + public List getOrganizationById(String id, + String orgName) { + + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + SysUser userInfo = userService.getUserInfo(); + if (userInfo.getUsertype() != 0) { + List roleByUserId = + sysRoleMapper.getRoleByUserId(userInfo.getId()); + List ids = new ArrayList<>(); + // 循环当前角色 + for (SysRole sysRole : roleByUserId) { + // 获取角色的组织Id + String orgscope = sysRole.getOrgscope(); + if (StrUtil.isBlank(orgscope)) { + continue; + } + // 拆分组织Id + String[] split = orgscope.split(","); + List stringList = Arrays.asList(split); + ids.addAll(stringList); + } + if (ObjectUtil.isNotEmpty(ids)) { + queryWrapper.in(SysOrganization::getId, ids); + } + + } + if (StrUtil.isNotBlank(orgName)) { + queryWrapper.like(SysOrganization::getOrgname, orgName); + } + queryWrapper.eq(SysOrganization::getParentid, id).orderByDesc(SysOrganization::getOrgcode); + return this.list(queryWrapper); + } + + /*********************************** + * 用途说明:获取组织范围树结构 + * 参数说明 + *parentid 上级id + * params 名称(根据名称查询二级) + * 返回值说明: 组织树集合 + ***********************************/ + @Override + public List> getOrgScopeTree(String roleId) { + LambdaQueryWrapper queryWrapper = + new LambdaQueryWrapper<>(); + queryWrapper.eq(SysOrganization::getIsvaild, '1'); + queryWrapper.orderByAsc(SysOrganization::getOrgcode); + List> listMaps = this.listMaps(queryWrapper); + // 获取当前角色 + SysRole sysRole = sysRoleMapper.selectById(roleId); + String orgscope = sysRole.getOrgscope(); + List ids = new ArrayList<>(); + if (StrUtil.isNotBlank(orgscope)) { + String[] split = orgscope.split(","); + ids = Arrays.asList(split); + } + + for (Map map : listMaps) { + String id = (String) map.get("id"); + if (ids.contains(id)) { + map.put("checkinfo", true); + } else { + map.put("checkinfo", false); + } + map.put("bool", true); + } + // 生成组织树 + List> listMap = buildTrees(listMaps); + return listMap; + } + + /********************************** + * 用途说明: 修改角色组织范围 + * 参数说明 roleId 角色id + * 参数说明 orgscope 组织id集合 + * 返回值说明: boolean 是否修改成功 + ***********************************/ + @Override + public boolean updateOrgScopeByRoleId(String roleId, String orgscope) { + SysRole sysRole = new SysRole(); + sysRole.setId(roleId); + sysRole.setOrgscope(orgscope); + int i = sysRoleMapper.updateById(sysRole); + if (i > 0) { + return true; + } else { + return false; + } + + } + + /********************************** + * 用途说明: 生成组织范围树 + * 参数说明 sysMenus + * 返回值说明: java.util.List> + ***********************************/ + public List> buildTrees(List> sysMenus) { + List> resultMenuList = new ArrayList<>(); + // 获取父节点 + for (Map sysMenu : sysMenus) { + if ("0".equals(sysMenu.get("parentid"))) { + resultMenuList.add(sysMenu); + } + } + // 寻找子节点 + for (Map sysMenu : resultMenuList) { + sysMenu.put("checkinfo", true); + List> children = new ArrayList<>(); + List array = new ArrayList<>(); + for (Map menu : sysMenus) { + String id = (String) sysMenu.get("id"); + String parentid = (String) menu.get("parentid"); + if (id.equals(parentid)) { + // 如果存在一个子节点没有被选中,父节点则不是全选状态 + if (!(boolean) menu.get("checkinfo")) { + sysMenu.put("checkinfo", false); + } else { + // 将处于选中状态的子节点加入到数组中 + array.add((String) menu.get("orgname")); + } + children.add(menu); + } + } + // 所有子节点加入父节点 + sysMenu.put("children", children); + sysMenu.put("array", array); + } + return resultMenuList; + } + + /** + * 组织集合递归生成树状菜单(Map) + * + * @param sysOrgList 组织集合 + * @return + */ + public List> buildTree(List> sysOrgList) { + List> resultOrgList = new ArrayList<>(); + for (Map sysOrg : sysOrgList) { + List> childrenList = new ArrayList<>(); + List array = new ArrayList<>(); + for (Map org : sysOrgList) { + if (org.get("parentid").equals(sysOrg.get("id"))) { + if (!(boolean) org.get("checkinfo")) { + sysOrg.put("checkinfo", false); + } + array.add((String) org.get("orgname")); + childrenList.add(org); + } + } + if ("0".equals(sysOrg.get("parentid"))) { + if (childrenList.size() > 0) { + sysOrg.put("children", childrenList); + } + resultOrgList.add(sysOrg); + } + sysOrg.put("array", array); + } + return resultOrgList; + } +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/SysRoleServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..63d5c36 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,163 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.SysRole; +import com.yfd.platform.system.mapper.SysRoleMapper; +import com.yfd.platform.system.service.ISysRoleService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.util.List; +import java.util.Map; + +/** + *

+ * 系统角色 服务实现类 + *

+ * + * @author zhengsl + * @since 2021-12-15 + */ +@Service +@Transactional +public class SysRoleServiceImpl extends ServiceImpl implements ISysRoleService { + + @Resource + private SysRoleMapper roleMapper; + + @Resource + private UserServiceImpl currentuser; + + /*********************************** + * 用途说明:新增角色 + * 参数说明 + * sysRole 新增角色信息 + * 返回值说明: 是否新增成功 + ***********************************/ + @Override + public boolean addRole(SysRole sysRole) { + //生成用户编号 + int codeMax = 0; + DecimalFormat df = new DecimalFormat("000");//四位数字编号 + QueryWrapper queryWrapper = new QueryWrapper<>(); + List max = this.listObjs(queryWrapper.select("MAX(rolecode) " + + "rolecode"));// 查询最大的编号 + if (max.size() > 0) { + codeMax = Integer.parseInt(max.get(0).toString());//判断查询是否存在 + } + // 存在转换成int类型并给codeMax替换值 + String code = df.format(codeMax + 1); // 最大编号累加 + + sysRole.setRolecode(code); //添加角色编号 + if (StringUtils.isEmpty(sysRole.getIsvaild())) { + sysRole.setIsvaild("1"); //判断是否填写有效性 默认为 1 是 + } + sysRole.setLastmodifier(currentuser.getUsername()); //添加最近修改者 + sysRole.setLastmodifydate(new Timestamp(System.currentTimeMillis())); //添加最近修改时间 + return this.save(sysRole); + } + + /*********************************** + * 用途说明:删除角色用户(admin除外) + * 参数说明 + * id 系统角色用户对照表id + * 返回值说明: 是否新增成功 + ***********************************/ + @Override + public boolean deleteRoleUsers(String roleid, String urserids) { + boolean ok = true; + //得到单个用户id + String[] temp = urserids.split(","); + for (String userid : temp) { + //根据角色id、用户id删除 (登录账号admin除外) + ok = ok && roleMapper.deleteRoleUsers(roleid, userid); + + } + return ok; + } + + /*********************************** + * 用途说明:根据id删除角色 //待修改 + * 参数说明 + *id 角色id + * 返回值说明: 是否删除成功 + ***********************************/ + @Override + public void deleteById(String id) { + String[] ids = id.split(","); + for (String roleId : ids) { + //根据id删除 角色 + boolean isOk = this.removeById(roleId); + if (!isOk) { + continue; + } + roleMapper.deleteRoleMenus(roleId); + roleMapper.deleteRoleUser(roleId); + } + } + /* 原逻辑 + @Override + public boolean deleteById(String id) { + //根据角色id查询 所关联的用户 + List> isRoleUsersByroleid = + roleMapper.isRoleUsersByroleid(id); + //判断是否关联用户 + if (isRoleUsersByroleid.size() > 0) { + return false; + } + //根据id删除 角色 + boolean isOk = this.removeById(id); + if (isOk) { + return true; + } + return false; + }*/ + + /*********************************** + * 用途说明:查询已分配的用户 + * 参数说明 + *orgid 所属组织 + *username 用户名称 + *status 状态 + *level 角色级别 + * rolename 角色名称 + * isvaild 角色是否有效 + * 返回值说明: 系统用户角色数据集合 + ***********************************/ + @Override + public List listRoleUsers(String orgid, String username, + String status, String level, + String rolename, String isvaild) { + return roleMapper.listRoleUsers(orgid, username, status, level, + rolename, isvaild); + } + + /*********************************** + * 用途说明:角色分配权限 + * 参数说明 + * id 角色id + * menuIds 权限id字符串 + * 返回值说明: 是否分配成功 + ***********************************/ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean setMenuById(String id, String menuIds) { + // 删除角色所对应的权限 + roleMapper.deleteRoleMenus(id); + // 重新赋予权限 + String[] ids = menuIds.split(","); + for (String menuId : ids) { + String uuid = IdUtil.fastSimpleUUID(); + roleMapper.addRoleMenu(uuid, id, menuId); + } + return true; + } + +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java new file mode 100644 index 0000000..dc28501 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java @@ -0,0 +1,52 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.yfd.platform.datasource.DataSource; +import com.yfd.platform.system.domain.LoginUser; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.mapper.SysMenuMapper; +import com.yfd.platform.system.service.IUserService; +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; + +import jakarta.annotation.Resource; +import java.util.List; + +/** + *

+ * 用户服务实现类 继承UserDetailsService 实现接口 + *

+ * + * @author zhengsl + * @since 2021-10-27 + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + + @Resource + private IUserService userService; + + @Resource + private SysMenuMapper sysMenuMapper; + + @Override + @DataSource(name = "master") + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + //根据用户名称查询用户信息 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("username", username); + SysUser user = userService.getOne(queryWrapper); + if (ObjectUtil.isEmpty(user)) { + throw new RuntimeException("用户账号不存在!"); + } + //Todo 根据用户查询权限信息 添加到LoginUser中 + List permissions = + sysMenuMapper.selectPermsByUserId(user.getId()); + + //封装成UserDetails对象返回 + return new LoginUser(user,permissions); + } +} diff --git a/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java b/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..566d608 --- /dev/null +++ b/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java @@ -0,0 +1,550 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.config.FileProperties; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.domain.LoginUser; +import com.yfd.platform.system.domain.SysOrganization; +import com.yfd.platform.system.domain.SysRole; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.mapper.SysOrganizationMapper; +import com.yfd.platform.system.mapper.SysRoleMapper; +import com.yfd.platform.system.mapper.SysUserMapper; +import com.yfd.platform.system.service.IUserService; +import com.yfd.platform.utils.FileUtil; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import com.yfd.platform.config.FileSpaceProperties; +import jakarta.annotation.Resource; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.annotation.Resource; +import jakarta.validation.constraints.NotBlank; +import java.io.File; +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 用户服务实现类 + *

+ * + * @author zhengsl + * @since 2021-10-27 + */ +@Service +@RequiredArgsConstructor +public class UserServiceImpl extends ServiceImpl implements IUserService { + + @Resource + private SysUserMapper sysUserMapper; + + @Resource + private SysRoleMapper sysRoleMapper; + + @Resource + private PasswordEncoder passwordEncoder; + /** + * 文件空间配置 + */ + @Resource + private FileSpaceProperties fileSpaceProperties; + + /********************************** + * 用途说明:获取当前用户账号及名称 + * 参数说明 + * 返回值说明: 系统管理员[admin] + ***********************************/ + @Override + public String getUsername() { + UsernamePasswordAuthenticationToken authentication = + (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginuser = (LoginUser) authentication.getPrincipal(); + String acountname = + loginuser.getUser().getNickname(); + return acountname; + //return "admin"; + } + + @Override + public Map getNameInfo() { + UsernamePasswordAuthenticationToken authentication = + (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginuser = (LoginUser) authentication.getPrincipal(); + String nickname = loginuser.getUser().getNickname(); + String username = loginuser.getUser().getUsername(); + Map map = new HashMap<>(); + map.put("nickname", nickname); + map.put("username", username); + return map; + } + + @Override + public SysUser getUserInfo() { + UsernamePasswordAuthenticationToken authentication = + (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginuser = (LoginUser) authentication.getPrincipal(); + return loginuser.getUser(); + } + + @Override + public ResponseResult getLoginUserInfo() { + UsernamePasswordAuthenticationToken authentication = + (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + LoginUser loginuser = (LoginUser) authentication.getPrincipal(); + SysUser user = loginuser.getUser(); + //根据用户ID获取组织 + Map userInfo = + sysUserMapper.getOrganizationByid(user.getId()); + List roles = + sysRoleMapper.selectList(new QueryWrapper().inSql( + "id ", "SELECT roleid FROM sys_role_users ru WHERE ru" + + ".userid = '" + user.getId() + "'")); + List collect = + roles.stream().map(SysRole::getRolename).collect(Collectors.toList()); + ResponseResult responseResult = new ResponseResult(); + responseResult.put("userInfo", userInfo); + responseResult.put("roles", collect); + responseResult.put("permissions", loginuser.getPermissions()); + return responseResult; + } + + /*********************************** + * 用途说明:新增用户 + * 参数说明 + *sysUser 新增用户对象 + * id 创建者id + * roleId 角色id + * 返回值说明: 提示字符串 + ************************************/ + @Override + public Map addUser(SysUser sysUser, String roleids) { + //返回信息 + Map result = new HashMap<>(); + sysUser.setId(IdUtil.fastSimpleUUID()); + //普通用户 + sysUser.setUsertype(1); + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + //设置缺省密码 + String cryptPassword = passwordEncoder.encode("123456"); + sysUser.setPassword(cryptPassword); + sysUser.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + sysUser.setLastmodifier(getUsername()); + //账号有效 + sysUser.setStatus(1); + //判断注册的登录账号是否存在 + if (isExistAccount(sysUser.getUsername())) { + //新增用户 + boolean ok = this.save(sysUser); + //新增用户分配权限 + if (StrUtil.isNotEmpty(roleids)) { + String[] roles = roleids.split(","); + for (String roleid : roles) { + //系统生成id + String id = IdUtil.fastSimpleUUID(); + //新增sys_role_users表数据 + ok = ok && sysUserMapper.addUserRoles(id, roleid, + sysUser.getId()); + } + } + //判断新增是否成功 消息提示 + if (ok) { + result.put("status", "sucess"); + result.put("msg", "新增用户成功!"); + + } else { + result.put("status", "error"); + result.put("msg", "新增用户失败!"); + } + } else { + result.put("status", "error"); + result.put("msg", "用户账号已存在,不能重复添加!"); + } + return result; + } + + /*********************************** + * 用途说明:查询系统用户 + * 参数说明 + *page 分页集合参数 + *orgid 所属组织 + *username 用户名称 + * mobile 手机号 + * status 状态 + * 返回值说明: 用户分页集合 + ************************************/ + @Override + public List list(String total, String size, String orgid, + String username, String mobile, String status) { + List list = sysUserMapper.list(total, size, orgid, username, + mobile, status); + for (Map map : list) { + List mapList = + sysUserMapper.getLevel(map.get("id").toString()); + String roleid = ""; + String level = ""; + String rolename = ""; + for (Map map1 : mapList) { + roleid += map1.get("id") + ","; + level += map1.get("level") + ","; + rolename += map1.get("rolename") + ","; + } + if (roleid.endsWith(",")) { + roleid = roleid.substring(0, roleid.length() - 1); + } + if (level.endsWith(",")) { + level = level.substring(0, level.length() - 1); + } + if (rolename.endsWith(",")) { + rolename = rolename.substring(0, rolename.length() - 1); + } + + map.put("roleid", roleid); + map.put("level", level); + map.put("rolename", rolename); + } + return list; //返回分页集合 + } + + /*********************************** + * 用途说明:根据ID修改用户 + * 参数说明 + *sysUser 用户对象 + *roleids 角色id + * 返回值说明: 是否更新成功 + ************************************/ + @Override + public Map updateById(SysUser sysUser, String roleids) { + //返回信息 + Map result = new HashMap<>(); + //获取当前用户 最近修改者替换 + sysUser.setLastmodifier(getUsername()); + //获取当前时间 最近修改日期替换 + sysUser.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //根据修改 + boolean ok = this.updateById(sysUser); + if (ok) { + if (StrUtil.isNotEmpty(roleids)) { + String[] roles = roleids.split(","); + List list = sysUserMapper.getRoleid(sysUser.getId()); + for (String role : roles) { + if (!list.contains(role)) { + //系统生成id + String id = IdUtil.fastSimpleUUID(); + //新增sys_role_users表数据 + ok = ok && sysUserMapper.addUserRoles(id, role, + sysUser.getId()); + } + } + //删除不包含的角色 + sysUserMapper.delInRoleUsersByUserid(sysUser.getId(), roles); + + } else { + //根据用户id 删除该用户角色关联 + ok = ok && sysUserMapper.delRoleUsersByUserid(sysUser.getId()); + } + result.put("status", "sucess"); + result.put("msg", "用户信息修改成功!"); + } else { + result.put("status", "error"); + result.put("msg", "用户信息修改失败!"); + } + + return result; + } + + @Override + public Map getOneById(String id) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + Map map = this.getMap(queryWrapper.eq("id", id)); + List mapList = sysUserMapper.getLevel(id); + String roleid = ""; + String level = ""; + String rolename = ""; + for (Map map1 : mapList) { + roleid += map1.get("id") + ","; + level += map1.get("level") + ","; + rolename += map1.get("rolename") + ","; + } + if (roleid.endsWith(",")) { + roleid = roleid.substring(0, roleid.length() - 1); + } + if (level.endsWith(",")) { + level = level.substring(0, level.length() - 1); + } + if (rolename.endsWith(",")) { + rolename = rolename.substring(0, rolename.length() - 1); + } + + map.put("roleid", roleid); + map.put("level", level); + map.put("rolename", rolename); + return map; + } + + /*********************************** + * 用途说明:用户分配角色 + * 参数说明 + *listId 用户id与角色id + * 返回值说明: 判断是否添加成功 + ************************************/ + @Override + public boolean setUserRoles(String roleid, String userids) { + boolean isOk = true; + //拆分userid 数组 + String[] temp = userids.split(","); + //遍历userid + for (String userid : temp) { + //根据角色id与用户id查询 + List list = sysUserMapper.getRoleUsersByid(roleid, userid); + //判断是否用户已分配此权限 + if (list.size() == 0) { + //系统生成id + String id = IdUtil.fastSimpleUUID(); + //新增sys_role_users表数据 + isOk = isOk && sysUserMapper.addUserRoles(id, roleid, userid); + } + } + return isOk; + } + + /*********************************** + * 用途说明:根据id删除用户 + * 参数说明 + *id 用户id + * 返回值说明: 判断是否删除成功 + ************************************/ + @Override + public boolean deleteById(String id) { + //根据id查询 + SysUser sysUser = this.getById(id); + //账号头像存储地址 + String imgName = + fileSpaceProperties.getSystem() + File.separator + "user" + File.separator + sysUser.getAvatar(); + if ("admin".equals(sysUser.getUsername())) { + return false; + } else { + boolean isOk = this.removeById(id); + //判断是否删除成功 + if (isOk) { + //根据用户id 删除该用户角色关联 + sysUserMapper.delRoleUsersByUserid(id); + //判断是否存在 账号头像 存在删除 + if (StrUtil.isNotEmpty(sysUser.getAvatar())) { + FileUtil.del(imgName); + } + return false; + } else { + return false; + } + } + } + + /*********************************** + * 用途说明:重置用户密码(管理员) + * 参数说明 + *id 重置密码的 用户id + * 返回值说明: 判断是重置成功 + ************************************/ + @Override + public boolean resetPassword(String id) throws Exception { + boolean isOk = false; + //根据当前用户id 查询角色表的级别 currentUser.getUser() 获取当前用户id + String level = sysUserMapper.getMaxLevel(id); + //判断是否获取级别 + if (StrUtil.isNotEmpty(level)) { + //判断当前用户级别 管理员及以上权限 + if (Integer.parseInt(level) <= 2) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id 修改密码,密码修改时间,最近修改者,最近修改日期 将密码修改为 123456 + String cryptPassword = passwordEncoder.encode("123456"); + updateWrapper.eq("id", id).set("password", cryptPassword).set( + "pwdresettime", + new Timestamp(System.currentTimeMillis())).set( + "lastmodifydate", + new Timestamp(System.currentTimeMillis())).set( + "lastmodifier", getUsername()); + //是否修改成功 + isOk = this.update(updateWrapper); + } + } + return isOk; + } + + /*********************************** + * 用途说明:设置账号状态(管理员) + * 参数说明 + *id 用户id + * status 设置状态 + * 返回值说明: 判断是否设置成功 + ************************************/ + @Override + public boolean setStatus(String id, String status) { + boolean isOk = false; + //根据当前用户id 查询角色表的级别 currentUser.getUser() 获取当前用户id + String level = sysUserMapper.getMaxLevel(id); + //判断当前用户级别 管理员及以上权限 + if (Integer.parseInt(level) <= 2) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + //根据id修改用户状态,最近修改人,最近修改时间 + updateWrapper.eq("id", id).set("status", status).set( + "lastmodifydate", + new Timestamp(System.currentTimeMillis())).set( + "lastmodifier", getUsername()); + //是否修改成功 + isOk = this.update(updateWrapper); + } + return isOk; + } + + /*********************************** + * 用途说明:上传用户头像 + * 参数说明 + * id 用户id + * img 账号头像 + * 返回值说明: 判断是否上传 + ***********************************/ + @Override + public boolean uploadAvatar(String id, MultipartFile img) { + //根据id查询 + SysUser sysUser = this.getById(id); + //账号头像存储地址 + String imgPath = fileSpaceProperties.getSystem() + "user"; + String avatar = sysUser.getAvatar(); + if (StrUtil.isNotBlank(avatar)) { + String imgName = imgPath + File.separator + avatar; + FileUtil.del(imgName); + } + //上传图片 并获取图片名称 (图片格式修改成png) + String imgName = FileUtil.upload(img, imgPath, + IdUtil.fastSimpleUUID() + "." + FileUtil.getExtensionName(img.getOriginalFilename())).getName(); + //修改 账户头像 + sysUser.setAvatar(imgName); + //修改 最近修改者 + sysUser.setLastmodifier(getUsername()); + //修改 最近修改日期 + sysUser.setLastmodifydate(new Timestamp(System.currentTimeMillis())); + //更新用户表 + boolean isOk = this.updateById(sysUser); + return isOk; + } + + /*********************************** + * 用途说明:新增系统角色用户对照表 对用户分配角色(单个) + * 参数说明 + * id 生成的id + * roleid 角色id + * userid 用户id + * 返回值说明: + ************************************/ + @Override + public boolean addUserRoles(String roleid, String userid) { + boolean isOk = true; + //根据角色id与用户id查询 + List list = sysUserMapper.getRoleUsersByid(roleid, userid); + //判断是否用户已分配此权限 + if (list.size() == 0) { + //系统生成id + String id = IdUtil.fastSimpleUUID(); + //新增sys_role_users表数据 + isOk = sysUserMapper.addUserRoles(id, roleid, userid); + } + return isOk; + } + + /* @Override + public Page queryUsers(String orgid, + String username, Page page) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // 分页查询中的条件查询 + if (StrUtil.isNotBlank(username)) { + queryWrapper.like(SysUser::getUsername, username); + } + queryWrapper.eq(SysUser::getOrgid, orgid); + return sysUserMapper.selectPage(page, queryWrapper); + }*/ + + @Override + public Page> queryUsers(String orgid, + String username, + Page page) { + Page> mapPage = sysUserMapper.queryUsers(orgid, + username, page); + List> list = new ArrayList<>(); + List> records = mapPage.getRecords(); + for (Map record : records) { + String id = (String) record.get("id"); + List sysRoles = sysRoleMapper.getRoleByUserId(id); + record.put("roles", sysRoles); + list.add(record); + } + mapPage.setRecords(list); + return mapPage; + } + + /*********************************** + * 用途说明:根据ID批量删除用户 + * 参数说明 + *ids 用户id集合 + * 返回值说明: 判断是否删除成功 + ************************************/ + @Override + public boolean deleteUserByIds(String id) { + String[] splitId = id.split(","); + List ids = Arrays.asList(splitId); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(SysUser::getId, ids); + List sysUsers = sysUserMapper.selectList(queryWrapper); + List names = + sysUsers.stream().map(SysUser::getUsername).collect(Collectors.toList()); + if (names.contains("admin")) { + return false; + } else { + int result = sysUserMapper.deleteBatchIds(ids); + if (result <= 0) { + return false; + } + // 根据ID删除用户与角色的关联信息 + sysUserMapper.delRoleUsersByUserIds(ids); + List avatars = + sysUsers.stream().map(SysUser::getAvatar).collect(Collectors.toList()); + if (avatars.size() > 0) { + for (String avatar : avatars) { + //账号头像存储地址 + String imgName = + fileSpaceProperties.getSystem() + File.separator + "user" + File.separator + avatar; + FileUtil.del(imgName); + } + } + return true; + } + } + + /*********************************** + * 用途说明:比较登录名称是否有重复 + * 参数说明 + * account 登录名称 + * 返回值说明: 重复返回 false 否则返回 true + ************************************/ + private boolean isExistAccount(String username) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (this.list(queryWrapper.eq("username", username)).size() > 0) { + //判断 查询登录账号 结果集是否为null 重复返回 false 否则返回 tree + return false; + } else { + return true; + } + } +} diff --git a/src/main/java/com/yfd/platform/task/TaskMessage.java b/src/main/java/com/yfd/platform/task/TaskMessage.java new file mode 100644 index 0000000..4a43d15 --- /dev/null +++ b/src/main/java/com/yfd/platform/task/TaskMessage.java @@ -0,0 +1,57 @@ +package com.yfd.platform.task; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yfd.platform.component.ServerSendEventServer; +import com.yfd.platform.config.MessageConfig; +import com.yfd.platform.config.WebConfig; +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.service.IMessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.util.List; + +/** + * @author TangWei + * @Date: 2023/3/22 15:39 + * @Description: + */ +@Component +public class TaskMessage { + + @Resource + private IMessageService messageService; + + /********************************** + * 用途说明: 定时监控消息是否过期 + * 参数说明 + * 返回值说明: void + ***********************************/ + public void examineMessage() { + List list = + messageService.list(new LambdaQueryWrapper().eq(Message::getStatus, "1")); + for (Message message : list) { + Timestamp createtime = message.getCreatetime(); + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + long create = createtime.getTime(); + long now = timestamp.getTime(); + Integer validperiod = message.getValidperiod(); + long v = validperiod * 60 * 60 * 1000; + if ((now - create) > v) { + message.setStatus("9"); + message.setReadtime(timestamp); + messageService.updateById(message); + } + + } + } + + /*public void sendMessage() { + String loginToken = webConfig.loginuserCache().get("loginToken"); + long count = + messageService.count(new LambdaQueryWrapper().eq(Message::getStatus, "1")); + ServerSendEventServer.sendMessage(loginToken, count + ""); + }*/ +} diff --git a/src/main/java/com/yfd/platform/utils/CallBack.java b/src/main/java/com/yfd/platform/utils/CallBack.java new file mode 100644 index 0000000..5f13d70 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/CallBack.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yfd.platform.utils; + +/** + * @author: liaojinlong + * @date: 2020/6/9 17:02 + * @since: 1.0 + * @see {@link SpringContextHolder} + * 针对某些初始化方法,在SpringContextHolder 初始化前时,
+ * 可提交一个 提交回调任务。
+ * 在SpringContextHolder 初始化后,进行回调使用 + */ + +public interface CallBack { + /** + * 回调执行方法 + */ + void executor(); + + /** + * 本回调任务名称 + * @return / + */ + default String getCallBackName() { + return Thread.currentThread().getId() + ":" + this.getClass().getName(); + } +} + diff --git a/src/main/java/com/yfd/platform/utils/CodeGenerator.java b/src/main/java/com/yfd/platform/utils/CodeGenerator.java new file mode 100644 index 0000000..1c65429 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/CodeGenerator.java @@ -0,0 +1,75 @@ +package com.yfd.platform.utils; + +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; + +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中 +public class CodeGenerator { + + public static String scanner(String tip) { + Scanner scanner = new Scanner(System.in); + StringBuilder help = new StringBuilder(); + help.append("请输入" + tip + ":"); + System.out.println(help.toString()); + if (scanner.hasNext()) { + String ipt = scanner.next(); + if (ipt != null && !ipt.trim().isEmpty()) { + return ipt; + } + } + throw new RuntimeException("请输入正确的" + tip + "!"); + } + + public static void main(String[] args) { + String projectPath = System.getProperty("user.dir"); + String module = scanner("模块名称"); + + Map pathInfo = new HashMap<>(); + pathInfo.put(OutputFile.entity, projectPath + "/src/main/java/com/yfd/platform/" + module + "/domain"); + pathInfo.put(OutputFile.mapper, projectPath + "/src/main/java/com/yfd/platform/" + module + "/mapper"); + pathInfo.put(OutputFile.controller, projectPath + "/src/main/java/com/yfd/platform/" + module + "/controller"); + pathInfo.put(OutputFile.serviceImpl, projectPath + "/src/main/java/com/yfd/platform/" + module + "/service/impl"); + pathInfo.put(OutputFile.service, projectPath + "/src/main/java/com/yfd/platform/" + module + "/service"); + pathInfo.put(OutputFile.xml, projectPath + "/src/main/resources/mapper/" + module); + + FastAutoGenerator.create( + "jdbc:mysql://43.143.220.7:3306/frameworkdb2023?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai", + "root", + "zhengg7QkXa { + builder.author("TangWei") + .disableOpenDir() + .outputDir(projectPath + "/src/main/java"); + }) + .packageConfig(builder -> { + builder.parent("com.yfd.platform") + .moduleName(module) + .pathInfo(pathInfo); + }) + .strategyConfig(builder -> { + builder.addInclude(scanner("表名,多个英文逗号分割").split(",")) + .entityBuilder() + .enableLombok() + .naming(NamingStrategy.underline_to_camel) + .columnNaming(NamingStrategy.underline_to_camel) + .controllerBuilder() + .enableRestStyle() + .mapperBuilder() + .formatMapperFileName("%sMapper") + .serviceBuilder() + .formatServiceFileName("%sService") + .formatServiceImplFileName("%sServiceImpl") + .controllerBuilder() + .formatFileName("%sController"); + }) + .templateEngine(new FreemarkerTemplateEngine()) + .execute(); + } + +} diff --git a/src/main/java/com/yfd/platform/utils/EncryptConfigUtil.java b/src/main/java/com/yfd/platform/utils/EncryptConfigUtil.java new file mode 100644 index 0000000..4df5527 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/EncryptConfigUtil.java @@ -0,0 +1,28 @@ +package com.yfd.platform.utils; + +import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; +import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; +import org.jasypt.util.text.BasicTextEncryptor; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +public class EncryptConfigUtil { + + public static void main(String[] args) { + +// String salt = "rca20230101"; +// String password = "123456"; +// +// BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); +// //加密所需的salt +// textEncryptor.setPassword(salt); +// //要加密的数据(数据库的用户名或密码) +// String encrypt = textEncryptor.encrypt(password); +// System.out.println("password:"+encrypt); + + + BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder(); + String cryptPassword=passwordEncoder.encode("dl_2023");//设置缺省密码 + + } + +} \ No newline at end of file diff --git a/src/main/java/com/yfd/platform/utils/EncryptUtils.java b/src/main/java/com/yfd/platform/utils/EncryptUtils.java new file mode 100644 index 0000000..2ae2b26 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/EncryptUtils.java @@ -0,0 +1,100 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.IvParameterSpec; +import java.nio.charset.StandardCharsets; + +/** + * 加密 + * @author + * @date 2018-11-23 + */ + +public class EncryptUtils { + + private static final String STR_PARAM = "Passw0rd"; + + private static Cipher cipher; + + private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8)); + + private static DESKeySpec getDesKeySpec(String source) throws Exception { + if (source == null || source.length() == 0){ + return null; + } + cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); + String strKey = "Passw0rd"; + return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8)); + } + + /** + * 对称加密 + */ + public static String desEncrypt(String source) throws Exception { + DESKeySpec desKeySpec = getDesKeySpec(source); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV); + return byte2hex( + cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase(); + } + + /** + * 对称解密 + */ + public static String desDecrypt(String source) throws Exception { + byte[] src = hex2byte(source.getBytes(StandardCharsets.UTF_8)); + DESKeySpec desKeySpec = getDesKeySpec(source); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey secretKey = keyFactory.generateSecret(desKeySpec); + cipher.init(Cipher.DECRYPT_MODE, secretKey, IV); + byte[] retByte = cipher.doFinal(src); + return new String(retByte); + } + + private static String byte2hex(byte[] inStr) { + String stmp; + StringBuilder out = new StringBuilder(inStr.length * 2); + for (byte b : inStr) { + stmp = Integer.toHexString(b & 0xFF); + if (stmp.length() == 1) { + // 如果是0至F的单位字符串,则添加0 + out.append("0").append(stmp); + } else { + out.append(stmp); + } + } + return out.toString(); + } + + private static byte[] hex2byte(byte[] b) { + int size = 2; + if ((b.length % size) != 0){ + throw new IllegalArgumentException("长度不是偶数"); + } + byte[] b2 = new byte[b.length / 2]; + for (int n = 0; n < b.length; n += size) { + String item = new String(b, n, 2); + b2[n / 2] = (byte) Integer.parseInt(item, 16); + } + return b2; + } +} diff --git a/src/main/java/com/yfd/platform/utils/ExecutionJob.java b/src/main/java/com/yfd/platform/utils/ExecutionJob.java new file mode 100644 index 0000000..c4a2fcf --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/ExecutionJob.java @@ -0,0 +1,103 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import com.yfd.platform.config.MessageConfig; +import com.yfd.platform.config.thread.ThreadPoolExecutorUtil; +import com.yfd.platform.system.domain.Message; +import com.yfd.platform.system.domain.QuartzJob; +import com.yfd.platform.system.service.IMessageService; +import com.yfd.platform.system.service.IQuartzJobService; +import org.quartz.JobExecutionContext; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; + +import jakarta.annotation.Resource; +import java.sql.Timestamp; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 参考人人开源,https://gitee.com/renrenio/renren-security + * + * @author / + * @date 2019-01-07 + */ +@Async +@SuppressWarnings({"unchecked", "all"}) +public class ExecutionJob extends QuartzJobBean { + + /** + * 该处仅供参考 + */ + private final static ThreadPoolExecutor EXECUTOR = + ThreadPoolExecutorUtil.getPoll(); + + @Resource + private IMessageService messageService; + + @Resource + private MessageConfig messageConfig; + + @Override + public void executeInternal(JobExecutionContext context) { + QuartzJob quartzJob = + (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY); + // 获取spring bean + IQuartzJobService quartzJobService = + SpringContextHolder.getBean(IQuartzJobService.class); + String uuid = quartzJob.getId(); + long startTime = System.currentTimeMillis(); + String jobName = quartzJob.getJobName(); + try { + // 执行任务 + System.out.println( + "--------------------------------------------------------------"); + System.out.println("任务开始执行,任务名称:" + jobName); + QuartzRunnable task = new QuartzRunnable(quartzJob.getJobClass(), + quartzJob.getJobMethod(), + quartzJob.getJobParams()); + Future future = EXECUTOR.submit(task); + future.get(); + long times = System.currentTimeMillis() - startTime; + Message message = new Message(); + message.setCreatetime(new Timestamp(System.currentTimeMillis())); + message.setType("1"); + message.setTitle(quartzJob.getJobName()); + message.setContent(quartzJob.getDescription()); + message.setSenderName("定时器"); + message.setReceiverCodes(quartzJob.getOrderno().toString()); + message.setReceiverNames(""); + message.setStatus("1"); + message.setValidperiod(24); + messageConfig.addMessage(message); + // 任务状态 + System.out.println("任务执行完毕,任务名称:" + jobName + ", " + + "执行时间:" + times + "毫秒"); + System.out.println( + "--------------------------------------------------------------"); + } catch (Exception e) { + System.out.println("任务执行失败,任务名称:" + jobName); + System.out.println( + "--------------------------------------------------------------"); + quartzJob.setStatus("0"); + //更新状态 + quartzJobService.updateById(quartzJob); + } + } + +} diff --git a/src/main/java/com/yfd/platform/utils/FileUtil.java b/src/main/java/com/yfd/platform/utils/FileUtil.java new file mode 100644 index 0000000..6940aee --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/FileUtil.java @@ -0,0 +1,398 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.BigExcelWriter; +import cn.hutool.poi.excel.ExcelUtil; +import com.yfd.platform.exception.BadRequestException; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.tomcat.util.http.fileupload.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLDecoder; +import java.security.MessageDigest; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * File工具类,扩展 hutool 工具包 + * + * @author + * @date 2018-12-27 + */ +public class FileUtil extends cn.hutool.core.io.FileUtil { + + private static final Logger log = LoggerFactory.getLogger(FileUtil.class); + + /** + * 系统临时目录 + *
+ * windows 包含路径分割符,但Linux 不包含, + * 在windows \\==\ 前提下, + * 为安全起见 同意拼装 路径分割符, + *
+     *       java.io.tmpdir
+     *       windows : C:\Users/xxx\AppData\Local\Temp\
+     *       linux: /temp
+     * 
+ */ + public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator; + /** + * 定义GB的计算常量 + */ + private static final int GB = 1024 * 1024 * 1024; + /** + * 定义MB的计算常量 + */ + private static final int MB = 1024 * 1024; + /** + * 定义KB的计算常量 + */ + private static final int KB = 1024; + + /** + * 格式化小数 + */ + private static final DecimalFormat DF = new DecimalFormat("0.00"); + + public static final String IMAGE = "image"; + public static final String TXT = "document"; + public static final String MUSIC = "music"; + public static final String VIDEO = "video"; + public static final String OTHER = "other"; + + + /** + * MultipartFile转File + */ + public static File toFile(MultipartFile multipartFile) { + // 获取文件名 + String fileName = multipartFile.getOriginalFilename(); + // 获取文件后缀 + String prefix = "." + getExtensionName(fileName); + File file = null; + try { + // 用uuid作为文件名,防止生成的临时文件重复 + file = File.createTempFile(IdUtil.simpleUUID(), prefix); + // MultipartFile to File + multipartFile.transferTo(file); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + return file; + } + + /** + * 获取文件扩展名,不带 . + */ + public static String getExtensionName(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length() - 1))) { + return filename.substring(dot + 1); + } + } + return filename; + } + + /** + * Java文件操作 获取不带扩展名的文件名 + */ + public static String getFileNameNoEx(String filename) { + if ((filename != null) && (filename.length() > 0)) { + int dot = filename.lastIndexOf('.'); + if ((dot > -1) && (dot < (filename.length()))) { + return filename.substring(0, dot); + } + } + return filename; + } + + /** + * 文件大小转换 + */ + public static String getSize(long size) { + String resultSize; + if (size / GB >= 1) { + //如果当前Byte的值大于等于1GB + resultSize = DF.format(size / (float) GB) + "GB "; + } else if (size / MB >= 1) { + //如果当前Byte的值大于等于1MB + resultSize = DF.format(size / (float) MB) + "MB "; + } else if (size / KB >= 1) { + //如果当前Byte的值大于等于1KB + resultSize = DF.format(size / (float) KB) + "KB "; + } else { + resultSize = size + "B "; + } + return resultSize; + } + + /** + * inputStream 转 File + */ + static File inputStreamToFile(InputStream ins, String name) throws Exception { + File file = new File(SYS_TEM_DIR + name); + if (file.exists()) { + return file; + } + OutputStream os = new FileOutputStream(file); + int bytesRead; + int len = 8192; + byte[] buffer = new byte[len]; + while ((bytesRead = ins.read(buffer, 0, len)) != -1) { + os.write(buffer, 0, bytesRead); + } + os.close(); + ins.close(); + return file; + } + + /** + * 将文件名解析成文件的上传路径 + */ + public static File upload(MultipartFile file, String filePath) { + Date date = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); + String name = getFileNameNoEx(file.getOriginalFilename()); + String suffix = getExtensionName(file.getOriginalFilename()); + String nowStr = "-" + format.format(date); + try { + String fileName = name + "." + suffix; + String path = filePath +File.separator + fileName; + // getCanonicalFile 可解析正确各种路径 + File dest = new File(path).getCanonicalFile(); + // 检测是否存在目录 + if (!dest.getParentFile().exists()) { + if (!dest.getParentFile().mkdirs()) { + System.out.println("was not successful."); + } + } + // 文件写入 + file.transferTo(dest); + return dest; + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return null; + } + + /** + * 将文件名解析成文件的上传路径 + * file 上传的文件 + * filePath 存储路径 + * tofilename 保存文件名称 + + */ + public static File upload(MultipartFile file, String filePath,String tofilename) { + try { + String filename = filePath + File.separator + tofilename; + File dest = new File(filename).getCanonicalFile(); + // 检测是否存在目录 + if (!dest.getParentFile().exists()) { + if (!dest.getParentFile().mkdirs()) { + } + } + // 文件写入 + file.transferTo(dest); + return dest; + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return null; + } + + + /** + * 导出excel + */ + public static void downloadExcel(List> list, HttpServletResponse response) throws IOException { + String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; + String filename = "record"+cn.hutool.core.date.DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss"); + File file = new File(tempPath); + BigExcelWriter writer = ExcelUtil.getBigWriter(file); + // 一次性写出内容,使用默认样式,强制输出标题 + writer.write(list, true); + SXSSFSheet sheet = (SXSSFSheet)writer.getSheet(); + //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法 + sheet.trackAllColumnsForAutoSizing(); + //列宽自适应 + writer.autoSizeColumnAll(); + //response为HttpServletResponse对象 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 + response.setHeader("Content-Disposition", "attachment;filename="+filename+".xlsx"); + ServletOutputStream out = response.getOutputStream(); + // 终止后删除临时文件 + file.deleteOnExit(); + writer.flush(out, true); + //此处记得关闭输出Servlet流 + IoUtil.close(out); + } + + public static String getFileType(String type) { + String documents = "txt doc pdf ppt pps xlsx xls docx"; + String music = "mp3 wav wma mpa ram ra aac aif m4a"; + String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; + String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; + if (image.contains(type)) { + return IMAGE; + } else if (documents.contains(type)) { + return TXT; + } else if (music.contains(type)) { + return MUSIC; + } else if (video.contains(type)) { + return VIDEO; + } else { + return OTHER; + } + } + + public static void checkSize(long maxSize, long size) { + // 1M + int len = 1024 * 1024; + if (size > (maxSize * len)) { + throw new BadRequestException("文件超出规定大小"); + } + } + + /** + * 判断两个文件是否相同 + */ + public static boolean check(File file1, File file2) { + String img1Md5 = getMd5(file1); + String img2Md5 = getMd5(file2); + return img1Md5.equals(img2Md5); + } + + /** + * 判断两个文件是否相同 + */ + public static boolean check(String file1Md5, String file2Md5) { + return file1Md5.equals(file2Md5); + } + + private static byte[] getByte(File file) { + // 得到文件长度 + byte[] b = new byte[(int) file.length()]; + try { + InputStream in = new FileInputStream(file); + try { + System.out.println(in.read(b)); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } catch (FileNotFoundException e) { + log.error(e.getMessage(), e); + return null; + } + return b; + } + + private static String getMd5(byte[] bytes) { + // 16进制字符 + char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + try { + MessageDigest mdTemp = MessageDigest.getInstance("MD5"); + mdTemp.update(bytes); + byte[] md = mdTemp.digest(); + int j = md.length; + char[] str = new char[j * 2]; + int k = 0; + // 移位 输出字符串 + for (byte byte0 : md) { + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return null; + } + + /** + * 下载文件 + * + * @param request / + * @param response / + * @param file / + */ + public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { + response.setCharacterEncoding(request.getCharacterEncoding()); + response.setContentType("application/octet-stream"); + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); + IOUtils.copy(fis, response.getOutputStream()); + response.flushBuffer(); + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + if (fis != null) { + try { + fis.close(); + if (deleteOnExit) { + file.deleteOnExit(); + } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + } + } + /** + * 预览PDF文件 + * + * @param filepath / + * @param response / + */ + public static void viewPDF(String filepath, HttpServletResponse response) throws IOException { + File file=new File(filepath); + String originFileName=file.getName(); //中文编码 + response.setCharacterEncoding("UTF-8"); + String showName= StrUtil.isNotBlank(originFileName)?originFileName:file.getName(); + showName= URLDecoder.decode(showName,"UTF-8"); + response.setHeader("Content-Disposition","inline;fileName="+new String(showName.getBytes(), "ISO8859-1")+";fileName*=UTF-8''"+ new String(showName.getBytes(), "ISO8859-1")); + FileInputStream fis = new FileInputStream(file); + response.setHeader("content-type", "application/pdf"); + response.setContentType("application/pdf; charset=utf-8"); + IOUtils.copy(fis, response.getOutputStream()); + fis.close(); + } + + public static String getMd5(File file) { + return getMd5(getByte(file)); + } + +} diff --git a/src/main/java/com/yfd/platform/utils/MpGenerator.java b/src/main/java/com/yfd/platform/utils/MpGenerator.java new file mode 100644 index 0000000..e3aec6e --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/MpGenerator.java @@ -0,0 +1,79 @@ +package com.yfd.platform.utils; + +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +public class MpGenerator { + /** + * 读取控制台内容 + */ + public static String scanner(String tip) { + Scanner scanner = new Scanner(System.in); + StringBuilder help = new StringBuilder(); + help.append("请输入" + tip + ":"); + System.out.println(help.toString()); + if (scanner.hasNext()) { + String ipt = scanner.next(); + if (StringUtils.hasText(ipt)) { + return ipt; + } + } + throw new RuntimeException("请输入正确的" + tip + "!"); + } + + public static void main(String[] args) { + String projectPath = System.getProperty("user.dir"); + String url = PropertiesUtils.getPropertyField("spring.datasource.url"); + String username = PropertiesUtils.getPropertyField("spring.datasource.username"); + String password = PropertiesUtils.getPropertyField("spring.datasource.password"); + + String moduleName = scanner("模块名"); + String modulePath = moduleName.replace(".", "/"); + + Map pathInfo = new HashMap<>(); + pathInfo.put(OutputFile.entity, projectPath + "/src/main/java/com/yfd/platform/modules/domain" + modulePath + "/entity"); + pathInfo.put(OutputFile.mapper, projectPath + "/src/main/java/com/yfd/platform/modules/domain/" + modulePath + "/dao"); + pathInfo.put(OutputFile.controller, projectPath + "/src/main/java/com/yfd/platform/modules/domain" + modulePath + "/controller"); + pathInfo.put(OutputFile.service, projectPath + "/src/main/java/com/yfd/platform/modules/domain" + modulePath + "/service"); + pathInfo.put(OutputFile.serviceImpl, projectPath + "/src/main/java/com/yfd/platform/modules/domain" + modulePath + "/service/impl"); + pathInfo.put(OutputFile.xml, projectPath + "/src/main/resources/mapper/" + modulePath); + + FastAutoGenerator.create(url, username, password) + .globalConfig(builder -> { + builder.author("fwh") + .disableOpenDir() + .outputDir(projectPath + "/src/main/java"); + }) + .packageConfig(builder -> { + builder.parent(PropertiesUtils.getPropertyField("project.package.name")) + .moduleName(moduleName) + .pathInfo(pathInfo); + }) + .strategyConfig(builder -> { + builder.addInclude(scanner("表名,多个英文逗号分割").split(",")) + .entityBuilder() + .enableLombok() + .naming(NamingStrategy.underline_to_camel) + .columnNaming(NamingStrategy.underline_to_camel) + .controllerBuilder() + .enableRestStyle() + .mapperBuilder() + .formatMapperFileName("%sDao") + .serviceBuilder() + .formatServiceFileName("%sService") + .formatServiceImplFileName("%sServiceImpl") + .controllerBuilder() + .formatFileName("%sController"); + }) + .templateEngine(new FreemarkerTemplateEngine()) + .execute(); + } +} + diff --git a/src/main/java/com/yfd/platform/utils/PropertiesUtils.java b/src/main/java/com/yfd/platform/utils/PropertiesUtils.java new file mode 100644 index 0000000..93c7cfd --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/PropertiesUtils.java @@ -0,0 +1,29 @@ +package com.yfd.platform.utils; + +import org.springframework.core.io.ClassPathResource; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Properties; +/****************************** + * 用途说明: + * 作者姓名: pcj + * 创建时间: 2022/9/20 14:31 + ******************************/ +public class PropertiesUtils { + public final static String RESOURCE_PATH = "application.properties"; + + public final static Properties properties = new Properties(); + + public static String getPropertyField(String parameter) { + //对应resources目录下的资源路径 + ClassPathResource resource = new ClassPathResource(RESOURCE_PATH); + try { + properties.load(new InputStreamReader(resource.getInputStream(), "gbk")); + } catch (IOException e) { + throw new RuntimeException(e); + } + return properties.getProperty(parameter); + } + +} diff --git a/src/main/java/com/yfd/platform/utils/QuartzManage.java b/src/main/java/com/yfd/platform/utils/QuartzManage.java new file mode 100644 index 0000000..3ff265c --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/QuartzManage.java @@ -0,0 +1,187 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import com.yfd.platform.system.domain.QuartzJob; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; +import org.quartz.impl.triggers.CronTriggerImpl; +import org.springframework.stereotype.Component; + +import jakarta.annotation.Resource; +import java.util.Date; + +import static org.quartz.TriggerBuilder.newTrigger; + +/** + * @author + * @date 2019-01-07 + */ +@Slf4j +@Component +public class QuartzManage { + + private static final String JOB_NAME = "TASK_"; + + @Resource(name = "scheduler") + private Scheduler scheduler; + + public void addJob(QuartzJob quartzJob) { + try { + // 构建job信息 + JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class). + withIdentity(JOB_NAME + quartzJob.getId()).build(); + + //通过触发器名和cron 表达式创建 Trigger + Trigger cronTrigger = newTrigger() + .withIdentity(JOB_NAME + quartzJob.getId()) + .startNow() + .withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getJobCron())) + .build(); + + cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob); + + //重置启动时间 + ((CronTriggerImpl) cronTrigger).setStartTime(new Date()); + + //执行定时任务 + scheduler.scheduleJob(jobDetail, cronTrigger); + + // 暂停任务 + if ("0".equals(quartzJob.getStatus())) { + pauseJob(quartzJob); + } + } catch (Exception e) { + log.error("创建定时任务失败", e); + throw new RuntimeException("创建定时任务失败"); + } + } + + /** + * 更新job cron表达式 + * + * @param quartzJob / + */ + public void updateJobCron(QuartzJob quartzJob) { + try { + TriggerKey triggerKey = + TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); + CronTrigger trigger = + (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if (trigger == null) { + addJob(quartzJob); + trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + } + CronScheduleBuilder scheduleBuilder = + CronScheduleBuilder.cronSchedule(quartzJob.getJobCron()); + trigger = + trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); + //重置启动时间 + ((CronTriggerImpl) trigger).setStartTime(new Date()); + trigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob); + + scheduler.rescheduleJob(triggerKey, trigger); + // 暂停任务 + if ("0".equals(quartzJob.getStatus())) { + pauseJob(quartzJob); + } + } catch (Exception e) { + log.error("更新定时任务失败", e); + throw new RuntimeException("更新定时任务失败"); + } + + } + + /** + * 删除一个job + * + * @param quartzJob / + */ + public void deleteJob(QuartzJob quartzJob) { + try { + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.pauseJob(jobKey); + scheduler.deleteJob(jobKey); + } catch (Exception e) { + log.error("删除定时任务失败", e); + throw new RuntimeException("删除定时任务失败"); + } + } + + /** + * 恢复一个job + * + * @param quartzJob / + */ + public void resumeJob(QuartzJob quartzJob) { + try { + TriggerKey triggerKey = + TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); + CronTrigger trigger = + (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if (trigger == null) { + addJob(quartzJob); + } + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.resumeJob(jobKey); + } catch (Exception e) { + log.error("恢复定时任务失败", e); + throw new RuntimeException("恢复定时任务失败"); + } + } + + /** + * 立即执行job + * + * @param quartzJob / + */ + public void runJobNow(QuartzJob quartzJob) { + try { + TriggerKey triggerKey = + TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); + CronTrigger trigger = + (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if (trigger == null) { + addJob(quartzJob); + } + JobDataMap dataMap = new JobDataMap(); + dataMap.put(QuartzJob.JOB_KEY, quartzJob); + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.triggerJob(jobKey, dataMap); + } catch (Exception e) { + log.error("定时任务执行失败", e); + throw new RuntimeException("定时任务执行失败"); + } + } + + /** + * 暂停一个job + * + * @param quartzJob / + */ + public void pauseJob(QuartzJob quartzJob) { + try { + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.pauseJob(jobKey); + } catch (Exception e) { + log.error("定时任务暂停失败", e); + throw new RuntimeException("定时任务暂停失败"); + } + } +} diff --git a/src/main/java/com/yfd/platform/utils/QuartzRunnable.java b/src/main/java/com/yfd/platform/utils/QuartzRunnable.java new file mode 100644 index 0000000..b1da541 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/QuartzRunnable.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +/** + * 执行定时任务 + * @author / + */ +@Slf4j +public class QuartzRunnable implements Callable { + + private final Object target; + private final Method method; + private final String params; + + QuartzRunnable(String beanName, String methodName, String params) + throws NoSuchMethodException, SecurityException { + this.target = SpringContextHolder.getBean(beanName); + this.params = params; + + if (StringUtils.isNotBlank(params)) { + this.method = target.getClass().getDeclaredMethod(methodName, String.class); + } else { + this.method = target.getClass().getDeclaredMethod(methodName); + } + } + + @Override + public Object call() throws Exception { + ReflectionUtils.makeAccessible(method); + if (StringUtils.isNotBlank(params)) { + method.invoke(target, params); + } else { + method.invoke(target); + } + return null; + } +} diff --git a/src/main/java/com/yfd/platform/utils/RequestHolder.java b/src/main/java/com/yfd/platform/utils/RequestHolder.java new file mode 100644 index 0000000..3dbfa55 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/RequestHolder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Objects; + +/** + * 获取 HttpServletRequest + * @author + * @date 2018-11-24 + */ +public class RequestHolder { + + public static HttpServletRequest getHttpServletRequest() { + return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); + } +} diff --git a/src/main/java/com/yfd/platform/utils/RsaUtils.java b/src/main/java/com/yfd/platform/utils/RsaUtils.java new file mode 100644 index 0000000..6638ac7 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/RsaUtils.java @@ -0,0 +1,181 @@ +package com.yfd.platform.utils; + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * @author https://www.cnblogs.com/nihaorz/p/10690643.html + * @description Rsa 工具类,公钥私钥生成,加解密 + * @date 2020-05-18 + **/ +public class RsaUtils { + + private static final String SRC = "123456"; + + public static void main(String[] args) throws Exception { + System.out.println("\n"); + RsaKeyPair keyPair = generateKeyPair(); + System.out.println("公钥:" + keyPair.getPublicKey()); + System.out.println("私钥:" + keyPair.getPrivateKey()); + System.out.println("\n"); + test1(keyPair); + System.out.println("\n"); + test2(keyPair); + System.out.println("\n"); + } + + /** + * 公钥加密私钥解密 + */ + private static void test1(RsaKeyPair keyPair) throws Exception { + System.out.println("***************** 公钥加密私钥解密开始 *****************"); + String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC); + String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1); + System.out.println("加密前:" + RsaUtils.SRC); + System.out.println("加密后:" + text1); + System.out.println("解密后:" + text2); + if (RsaUtils.SRC.equals(text2)) { + System.out.println("解密字符串和原始字符串一致,解密成功"); + } else { + System.out.println("解密字符串和原始字符串不一致,解密失败"); + } + System.out.println("***************** 公钥加密私钥解密结束 *****************"); + } + + /** + * 私钥加密公钥解密 + * @throws Exception / + */ + private static void test2(RsaKeyPair keyPair) throws Exception { + System.out.println("***************** 私钥加密公钥解密开始 *****************"); + String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC); + String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1); + System.out.println("加密前:" + RsaUtils.SRC); + System.out.println("加密后:" + text1); + System.out.println("解密后:" + text2); + if (RsaUtils.SRC.equals(text2)) { + System.out.println("解密字符串和原始字符串一致,解密成功"); + } else { + System.out.println("解密字符串和原始字符串不一致,解密失败"); + } + System.out.println("***************** 私钥加密公钥解密结束 *****************"); + } + + /** + * 公钥解密 + * + * @param publicKeyText 公钥 + * @param text 待解密的信息 + * @return / + * @throws Exception / + */ + public static String decryptByPublicKey(String publicKeyText, String text) throws Exception { + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, publicKey); + byte[] result = cipher.doFinal(Base64.decodeBase64(text)); + return new String(result); + } + + /** + * 私钥加密 + * + * @param privateKeyText 私钥 + * @param text 待加密的信息 + * @return / + * @throws Exception / + */ + public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception { + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, privateKey); + byte[] result = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64String(result); + } + + /** + * 私钥解密 + * + * @param privateKeyText 私钥 + * @param text 待解密的文本 + * @return / + * @throws Exception / + */ + public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception { + PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + byte[] result = cipher.doFinal(Base64.decodeBase64(text)); + return new String(result); + } + + /** + * 公钥加密 + * + * @param publicKeyText 公钥 + * @param text 待加密的文本 + * @return / + */ + public static String encryptByPublicKey(String publicKeyText, String text) throws Exception { + X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2); + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + byte[] result = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64String(result); + } + + /** + * 构建RSA密钥对 + * + * @return / + * @throws NoSuchAlgorithmException / + */ + public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(1024); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); + String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded()); + String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded()); + return new RsaKeyPair(publicKeyString, privateKeyString); + } + + + /** + * RSA密钥对对象 + */ + public static class RsaKeyPair { + + private final String publicKey; + private final String privateKey; + + public RsaKeyPair(String publicKey, String privateKey) { + this.publicKey = publicKey; + this.privateKey = privateKey; + } + + public String getPublicKey() { + return publicKey; + } + + public String getPrivateKey() { + return privateKey; + } + + } +} diff --git a/src/main/java/com/yfd/platform/utils/SecurityUtils.java b/src/main/java/com/yfd/platform/utils/SecurityUtils.java new file mode 100644 index 0000000..9df23cd --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/SecurityUtils.java @@ -0,0 +1,84 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.yfd.platform.exception.BadRequestException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; + +import java.util.List; + +/** + * 获取当前登录的用户 + * @author + * @date 2019-01-17 + */ +@Slf4j +public class SecurityUtils { + + /** + * 获取当前登录的用户 + * @return UserDetails + */ + public static UserDetails getCurrentUser() { + UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class); + return userDetailsService.loadUserByUsername(getCurrentUsername()); + } + + /** + * 获取系统用户名称 + * + * @return 系统用户名称 + */ + public static String getCurrentUsername() { + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null) { + throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期"); + } + if (authentication.getPrincipal() instanceof UserDetails) { + UserDetails userDetails = (UserDetails) authentication.getPrincipal(); + return userDetails.getUsername(); + } + throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息"); + } + + /** + * 获取系统用户ID + * @return 系统用户ID + */ + public static Long getCurrentUserId() { + UserDetails userDetails = getCurrentUser(); + return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class); + } + + /** + * 获取当前用户的数据权限 + * @return / + */ + public static List getCurrentUserDataScope(){ + UserDetails userDetails = getCurrentUser(); + JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes")); + return JSONUtil.toList(array,Long.class); + } + +} diff --git a/src/main/java/com/yfd/platform/utils/SpringContextHolder.java b/src/main/java/com/yfd/platform/utils/SpringContextHolder.java new file mode 100644 index 0000000..b85c770 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/SpringContextHolder.java @@ -0,0 +1,145 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.env.Environment; + +import java.util.ArrayList; +import java.util.List; +/** + * @author Jie + * @date 2019-01-07 + */ +@Slf4j +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + private static final List CALL_BACKS = new ArrayList<>(); + private static boolean addCallback = true; + + /** + * 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。 + * 在SpringContextHolder 初始化后,进行回调使用 + * + * @param callBack 回调函数 + */ + public synchronized static void addCallBacks(CallBack callBack) { + if (addCallback) { + SpringContextHolder.CALL_BACKS.add(callBack); + } else { + log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName()); + callBack.executor(); + } + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 获取SpringBoot 配置信息 + * + * @param property 属性key + * @param defaultValue 默认值 + * @param requiredType 返回类型 + * @return / + */ + public static T getProperties(String property, T defaultValue, Class requiredType) { + T result = defaultValue; + try { + result = getBean(Environment.class).getProperty(property, requiredType); + } catch (Exception ignored) {} + return result; + } + + /** + * 获取SpringBoot 配置信息 + * + * @param property 属性key + * @return / + */ + public static String getProperties(String property) { + return getProperties(property, null, String.class); + } + + /** + * 获取SpringBoot 配置信息 + * + * @param property 属性key + * @param requiredType 返回类型 + * @return / + */ + public static T getProperties(String property, Class requiredType) { + return getProperties(property, null, requiredType); + } + + /** + * 检查ApplicationContext不为空. + */ + private static void assertContextInjected() { + if (applicationContext == null) { + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); + } + } + + /** + * 清除SpringContextHolder中的ApplicationContext为Null. + */ + private static void clearHolder() { + log.debug("清除SpringContextHolder中的ApplicationContext:" + + applicationContext); + applicationContext = null; + } + + @Override + public void destroy() { + SpringContextHolder.clearHolder(); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (SpringContextHolder.applicationContext != null) { + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); + } + SpringContextHolder.applicationContext = applicationContext; + if (addCallback) { + for (CallBack callBack : SpringContextHolder.CALL_BACKS) { + callBack.executor(); + } + CALL_BACKS.clear(); + } + SpringContextHolder.addCallback = false; + } +} diff --git a/src/main/java/com/yfd/platform/utils/StringUtils.java b/src/main/java/com/yfd/platform/utils/StringUtils.java new file mode 100644 index 0000000..b2a9be7 --- /dev/null +++ b/src/main/java/com/yfd/platform/utils/StringUtils.java @@ -0,0 +1,305 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yfd.platform.utils; + + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.yfd.platform.constant.Constant; +import lombok.SneakyThrows; +import org.lionsoul.ip2region.DataBlock; +import org.lionsoul.ip2region.DbConfig; +import org.lionsoul.ip2region.DbSearcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; +import eu.bitwalker.useragentutils.Browser; +import eu.bitwalker.useragentutils.UserAgent; +import jakarta.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.UnknownHostException; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; + +/** + * @author + * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + private static final Logger log = LoggerFactory.getLogger(StringUtils.class); + private static boolean ipLocal = false; + private static File file ; + private static DbConfig config; + private static final char SEPARATOR = '_'; + private static final String UNKNOWN = "unknown"; + + static { + SpringContextHolder.addCallBacks(() -> { + StringUtils.ipLocal = SpringContextHolder.getProperties("ip.local-parsing", false, Boolean.class); + if (ipLocal) { + /* + * 此文件为独享 ,不必关闭 + */ + String path = "ip2region/ip2region.db"; + String name = "ip2region.db"; + try { + config = new DbConfig(); + file = FileUtil.inputStreamToFile(new ClassPathResource(path).getInputStream(), name); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + }); + } + + /** + * 驼峰命名法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCamelCase(String s) { + if (s == null) { + return null; + } + + s = s.toLowerCase(); + + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == SEPARATOR) { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + + return sb.toString(); + } + + /** + * 驼峰命名法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCapitalizeCamelCase(String s) { + if (s == null) { + return null; + } + s = toCamelCase(s); + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + /** + * 驼峰命名法工具 + * + * @return toCamelCase(" hello_world ") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + static String toUnderScoreCase(String s) { + if (s == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + boolean nextUpperCase = true; + + if (i < (s.length() - 1)) { + nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); + } + + if ((i > 0) && Character.isUpperCase(c)) { + if (!upperCase || !nextUpperCase) { + sb.append(SEPARATOR); + } + upperCase = true; + } else { + upperCase = false; + } + + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 获取ip地址 + */ + public static String getIp(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + String comma = ","; + String localhost = "127.0.0.1"; + if (ip.contains(comma)) { + ip = ip.split(",")[0]; + } + if (localhost.equals(ip)) { + // 获取本机真正的ip地址 + try { + ip = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + log.error(e.getMessage(), e); + } + } + return ip; + } + + /** + * 根据ip获取详细地址 + */ + @SneakyThrows + public static String getCityInfo(String ip) { + if (ipLocal) { + return getLocalCityInfo(ip); + } else { + return getHttpCityInfo(ip); + } + } + + /** + * 根据ip获取详细地址 + */ + public static String getHttpCityInfo(String ip) { + String host = "202.108.22.5"; + //超时应该在3钞以上 + int timeOut = 3000; + boolean status = false; + try { + status = InetAddress.getByName(host).isReachable(timeOut); + } catch (IOException e) { + e.printStackTrace(); + } + String api =""; + if (status){ + api = HttpUtil.get(String.format(Constant.Url.IP_URL, ip)); + }else { + api = "{\"ip\":\"127.0.0.1\",\"pro\":\"\",\"proCode\":\"999999\",\"city\":\"\",\"cityCode\":\"0\",\"region\":\"\",\"regionCode\":\"0\",\"addr\":\" 局域网\",\"regionNames\":\"\",\"err\":\"noprovince\"}"; + } + JSONObject object = JSONUtil.parseObj(api); + return object.get("addr", String.class); + } + + + /** + * 根据ip获取详细地址 + */ + public static String getLocalCityInfo(String ip) { + try { + DataBlock dataBlock = new DbSearcher(config, file.getPath()) + .binarySearch(ip); + String region = dataBlock.getRegion(); + String address = region.replace("0|", ""); + char symbol = '|'; + if (address.charAt(address.length() - 1) == symbol) { + address = address.substring(0, address.length() - 1); + } + return address.equals(Constant.REGION) ? "内网IP" : address; + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return ""; + } + + public static String getBrowser(HttpServletRequest request) { + UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); + Browser browser = userAgent.getBrowser(); + return browser.getName(); + } + + /** + * 获得当天是周几 + */ + public static String getWeekDay() { + String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date()); + + int w = cal.get(Calendar.DAY_OF_WEEK) - 1; + if (w < 0) { + w = 0; + } + return weekDays[w]; + } + + /** + * 获取当前机器的IP + * + * @return / + */ + public static String getLocalIp() { + try { + InetAddress candidateAddress = null; + // 遍历所有的网络接口 + for (Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) { + NetworkInterface anInterface = interfaces.nextElement(); + // 在所有的接口下再遍历IP + for (Enumeration inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) { + InetAddress inetAddr = inetAddresses.nextElement(); + // 排除loopback类型地址 + if (!inetAddr.isLoopbackAddress()) { + if (inetAddr.isSiteLocalAddress()) { + // 如果是site-local地址,就是它了 + return inetAddr.getHostAddress(); + } else if (candidateAddress == null) { + // site-local类型的地址未被发现,先记录候选地址 + candidateAddress = inetAddr; + } + } + } + } + if (candidateAddress != null) { + return candidateAddress.getHostAddress(); + } + // 如果没有发现 non-loopback地址.只能用最次选的方案 + InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); + if (jdkSuppliedAddress == null) { + return ""; + } + return jdkSuppliedAddress.getHostAddress(); + } catch (Exception e) { + return ""; + } + } +} diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml new file mode 100644 index 0000000..a53b797 --- /dev/null +++ b/src/main/resources/all-application.yml @@ -0,0 +1,168 @@ + + + +# 此配置文件只是用作展示所有配置项, 不可不直接使用 + + +spring: + # REDIS数据库配置 + redis: + # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 + host: 127.0.0.1 + # [必须修改] 端口号 + port: 6379 + # [可选] 数据库 DB + database: 6 + # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 + password: + # [可选] 超时时间 + timeout: 10000 + # [可选] 一个pool最多可分配多少个jedis实例 + poolMaxTotal: 1000 + # [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例 + poolMaxIdle: 500 + # [可选] 最大的等待时间(秒) + poolMaxWait: 5 + # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 + datasource: + # 使用mysql 打开23-28行注释, 删除29-36行 + name: wvp + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true + username: + password: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + # name: eiot +# url: jdbc:sqlite::resource:wvp.sqlite +# username: +# password: +# type: com.alibaba.druid.pool.DruidDataSource +# driver-class-name: org.sqlite.JDBC + max-active: 1 + min-idle: 1 + +# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 +server: + port: 18080 + # [可选] HTTPS配置, 默认不开启 + ssl: + # [可选] 是否开启HTTPS访问 + enabled: false + # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名 + key-store: classpath:xxx.jks + # [可选] 证书密码 + key-password: password + # [可选] 证书类型, 默认为jks,根据实际修改 + key-store-type: JKS + +# 作为28181服务器的配置 +sip: + # [必须修改] 本机的IP, 必须是网卡上的IP,用于sip下协议栈监听ip,如果监听所有设置为0.0.0.0 + monitor-ip: 0.0.0.0 + # [必须修改] 本机的IP + ip: 192.168.0.100 + # [可选] 28181服务监听的端口 + port: 5060 + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) + # 后两位为行业编码,定义参照附录D.3 + # 3701020049标识山东济南历下区 信息行业接入 + # [可选] + domain: 4401020049 + # [可选] + id: 44010200492000000001 + # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验 + password: admin123 + # [可选] 心跳超时时间, 建议设置为心跳周期的三倍 + keepalive-timeout: 255 + # [可选] 国标级联注册失败,再次发起注册的时间间隔。 默认60秒 + register-time-interval: 60 + # [可选] 云台控制速度 + ptz-speed: 50 + # TODO [可选] 收到心跳后自动上线, 重启服务后会将所有设备置为离线,默认false,等待注册后上线。设置为true则收到心跳设置为上线。 + # keepalliveToOnline: false + +#zlm 默认服务器配置 +media: + # [可选] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId + id: + # [必须修改] zlm服务器的内网IP + ip: 192.168.0.100 + # [可选] 返回流地址时的ip,置空使用 media.ip + stream-ip: + # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip + sdp-ip: + # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip + hook-ip: + # [必须修改] zlm服务器的http.port + http-port: 80 + # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置 + http-ssl-port: + # [可选] zlm服务器的rtmp.port, 置空使用zlm配置文件配置 + rtmp-port: + # [可选] zlm服务器的rtmp.sslport, 置空使用zlm配置文件配置 + rtmp-ssl-port: + # [可选] zlm服务器的 rtp_proxy.port, 置空使用zlm配置文件配置 + rtp-proxy-port: + # [可选] zlm服务器的 rtsp.port, 置空使用zlm配置文件配置 + rtsp-port: + # [可选] zlm服务器的 rtsp.sslport, 置空使用zlm配置文件配置 + rtsp-ssl-port: + # [可选] 是否自动配置ZLM, 如果希望手动配置ZLM, 可以设为false, 不建议新接触的用户修改 + auto-config: true + # [可选] zlm服务器的hook.admin_params=secret + secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc + # [可选] zlm服务器的general.streamNoneReaderDelayMS + stream-none-reader-delay-ms: 18000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流 + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 + rtp: + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 + enable: true + # [可选] 在此范围内选择端口用于媒体流传输, + port-range: 30000,30500 # 端口范围 + # [可选] 国标级联在此范围内选择端口发送媒体流, + send-port-range: 30000,30500 # 端口范围 + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 + record-assist-port: 0 + +# [可选] 日志配置, 一般不需要改 +logging: + file: + name: logs/wvp.log + max-history: 30 + max-size: 10MB + total-size-cap: 300MB + level: + com.genersoft.iot: debug + com.genersoft.iot.vmp.storager.dao: info + com.genersoft.iot.vmp.gb28181: info +# [根据业务需求配置] +user-settings: + # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true + auto-apply-play: false + # [可选] 部分设备需要扩展SDP,需要打开此设置 + senior-sdp: false + # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认) + save-position-history: false + # 点播等待超时时间,单位:毫秒 + play-timeout: 3000 + # 等待音视频编码信息再返回, true: 可以根据编码选择合适的播放器,false: 可以更快点播 + wait-track: false + # 是否开启接口鉴权 + interface-authentication: true + # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录 + interface-authentication-excludes: + - /api/v1/** + # 推流直播是否录制 + record-push-live: true + # 是否将日志存储进数据库 + logInDatebase: true + +# 在线文档: swagger-ui(生产环境建议关闭) +swagger-ui: + enabled: true + +# 版本信息, 不需修改 +version: + version: "@project.version@" + description: "@project.description@" + artifact-id: "@project.artifactId@" \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..b814931 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,84 @@ +server: + port: 8093 + +spring: + #应用名称 + application: + name: Project-plateform + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + master: + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://43.138.168.68:3306/frameworkdb2023?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true + username: root + password: ylfw20230626@ + slave: + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://43.138.168.68:3306/frameworkdb2023?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true + username: root + password: ylfw20230626@ + + mvc: + pathmatch: + matching-strategy: ant_path_matcher + servlet: + multipart: + max-file-size: 30MB + max-request-size: 100MB + +logging: + file: + name: logs/projectname.log + level: + com.genersoft.iot: debug + com.genersoft.iot.vmp.storager.dao: info + com.genersoft.iot.vmp.gb28181: info + +# 在线文档: swagger-ui(生产环境建议关闭) +swagger-ui: + enabled: true + + +# 登录相关配置 +login: + # 登录缓存 + cache-enable: true + # 是否限制单用户登录 + single-login: false + # 验证码 + login-code: + # 验证码类型配置 查看 LoginProperties 类 + code-type: arithmetic + # 登录图形验证码有效时间/分钟 + expiration: 2 + # 验证码高度 + width: 111 + # 验证码宽度 + heigth: 36 + # 内容长度 + length: 2 + # 字体名称,为空则使用默认字体 + font-name: + # 字体大小 + font-size: 25 + +# IP 本地解析 +ip: + local-parsing: true + + +file-space: #项目文档空间 + files: D:\demoproject\files\ #单独上传的文件附件 + system: D:\demoproject\system\ #单独上传的文件 + +task: + pool: + # 核心线程池大小 + core-pool-size: 10 + # 最大线程数 + max-pool-size: 30 + # 活跃时间 + keep-alive-seconds: 60 + # 队列容量 + queue-capacity: 50 diff --git a/src/main/resources/application-server.yml b/src/main/resources/application-server.yml new file mode 100644 index 0000000..c5a5b91 --- /dev/null +++ b/src/main/resources/application-server.yml @@ -0,0 +1,43 @@ +server: + port: 8090 + +spring: + #应用名称 + application: + name: Project-plateform + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + master: + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://43.138.168.68:3306/framework2023?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true + username: root + password: zhengg7QkXa + + + + + + + + + + UTF-8 + ${LOG_PATTERN} + + + + + + ${LOG_PATH}/${LOG_FILE}.log + + UTF-8 + ${LOG_PATTERN} + + + ${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.log + 30 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..c949c89 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,45 @@ + + + yfAdmin + + + + + + + ${log.pattern} + ${log.charset} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/system/DictionaryMapper.xml b/src/main/resources/mapper/system/DictionaryMapper.xml new file mode 100644 index 0000000..16edd1e --- /dev/null +++ b/src/main/resources/mapper/system/DictionaryMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/MessageMapper.xml b/src/main/resources/mapper/system/MessageMapper.xml new file mode 100644 index 0000000..96cbcfc --- /dev/null +++ b/src/main/resources/mapper/system/MessageMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/Model3dMapper.xml b/src/main/resources/mapper/system/Model3dMapper.xml new file mode 100644 index 0000000..d935f68 --- /dev/null +++ b/src/main/resources/mapper/system/Model3dMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/QuartzJobMapper.xml b/src/main/resources/mapper/system/QuartzJobMapper.xml new file mode 100644 index 0000000..b523b0a --- /dev/null +++ b/src/main/resources/mapper/system/QuartzJobMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/SysConfigMapper.xml b/src/main/resources/mapper/system/SysConfigMapper.xml new file mode 100644 index 0000000..cf22aa4 --- /dev/null +++ b/src/main/resources/mapper/system/SysConfigMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/SysDictionaryItemsMapper.xml b/src/main/resources/mapper/system/SysDictionaryItemsMapper.xml new file mode 100644 index 0000000..1bf0942 --- /dev/null +++ b/src/main/resources/mapper/system/SysDictionaryItemsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/SysDictionaryMapper.xml b/src/main/resources/mapper/system/SysDictionaryMapper.xml new file mode 100644 index 0000000..6963e40 --- /dev/null +++ b/src/main/resources/mapper/system/SysDictionaryMapper.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/src/main/resources/mapper/system/SysLogMapper.xml b/src/main/resources/mapper/system/SysLogMapper.xml new file mode 100644 index 0000000..1046de9 --- /dev/null +++ b/src/main/resources/mapper/system/SysLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/SysMenuMapper.xml b/src/main/resources/mapper/system/SysMenuMapper.xml new file mode 100644 index 0000000..febfab3 --- /dev/null +++ b/src/main/resources/mapper/system/SysMenuMapper.xml @@ -0,0 +1,103 @@ + + + + + + update sys_menu set orderno=orderno+1 where parentid=#{parentid} and orderno < #{Orderno} and orderno >= #{upOrderno} + + + + + update sys_menu SET orderno=orderno-1 where parentid=#{parentid} and orderno > #{Orderno} and orderno <= #{downOrderno} + + + + + + + + + + diff --git a/src/main/resources/mapper/system/SysMessageMapper.xml b/src/main/resources/mapper/system/SysMessageMapper.xml new file mode 100644 index 0000000..cda7c6f --- /dev/null +++ b/src/main/resources/mapper/system/SysMessageMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/SysOrganizationMapper.xml b/src/main/resources/mapper/system/SysOrganizationMapper.xml new file mode 100644 index 0000000..053c5ae --- /dev/null +++ b/src/main/resources/mapper/system/SysOrganizationMapper.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/src/main/resources/mapper/system/SysQuartzJobMapper.xml b/src/main/resources/mapper/system/SysQuartzJobMapper.xml new file mode 100644 index 0000000..268cb3d --- /dev/null +++ b/src/main/resources/mapper/system/SysQuartzJobMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/system/SysRoleMapper.xml b/src/main/resources/mapper/system/SysRoleMapper.xml new file mode 100644 index 0000000..4b37516 --- /dev/null +++ b/src/main/resources/mapper/system/SysRoleMapper.xml @@ -0,0 +1,116 @@ + + + + + INSERT INTO sys_role_menu + + + id, + + + roleid, + + + menuid + + + + + #{id}, + + + #{roleid}, + + + #{menuid} + + + + + + + + + + + + + + + + + + + + delete from sys_role_users where userid !=(select u.id from sys_user u where u.account="admin") and roleid=#{roleid} and userid=#{urserid} + + + + + DELETE FROM sys_role_menu WHERE roleid= #{id} + + + + + DELETE FROM sys_role_users WHERE roleid= #{id} + + diff --git a/src/main/resources/mapper/system/SysUserMapper.xml b/src/main/resources/mapper/system/SysUserMapper.xml new file mode 100644 index 0000000..f89b6dc --- /dev/null +++ b/src/main/resources/mapper/system/SysUserMapper.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + insert into sys_role_users value (#{id},#{roleid},#{userid}) + + + + + + + + + + + + + + + + + + delete from sys_role_users where userid=#{userid} + + + + delete from sys_role_users + where + userid=#{userid} + and roleid not in + + #{roleids} + + + + DELETE FROM sys_role_users WHERE userid IN + + #{id} + + + + diff --git a/src/main/resources/quartz.properties b/src/main/resources/quartz.properties new file mode 100644 index 0000000..03d3988 --- /dev/null +++ b/src/main/resources/quartz.properties @@ -0,0 +1,21 @@ +######################################## +# Quartz 默认配置示例(RAMJobStore) +######################################## + +org.quartz.scheduler.instanceName = PlatformScheduler +org.quartz.scheduler.instanceId = AUTO + +# 线程池配置 +org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool +org.quartz.threadPool.threadCount = 10 +org.quartz.threadPool.threadPriority = 5 + +# 使用内存存储(如需持久化请改为 JobStoreTX 并配置数据源) +org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore + +# Misfire 阈值 +org.quartz.jobStore.misfireThreshold = 60000 + +# 插件(可选):关闭时清理 +org.quartz.plugin.shutdownHook.class = org.quartz.plugins.management.ShutdownHookPlugin +org.quartz.plugin.shutdownHook.cleanShutdown = true \ No newline at end of file diff --git a/src/main/resources/static/icon/0312cfde741a47ad9dfd2b6379c24229.png b/src/main/resources/static/icon/0312cfde741a47ad9dfd2b6379c24229.png new file mode 100644 index 0000000..1520447 Binary files /dev/null and b/src/main/resources/static/icon/0312cfde741a47ad9dfd2b6379c24229.png differ diff --git a/src/main/resources/static/icon/1376916838a345799b96ac1eacc8608f.png b/src/main/resources/static/icon/1376916838a345799b96ac1eacc8608f.png new file mode 100644 index 0000000..5fc1f6f Binary files /dev/null and b/src/main/resources/static/icon/1376916838a345799b96ac1eacc8608f.png differ diff --git a/src/main/resources/static/icon/1449347c56414681a321dc3c84302b00.png b/src/main/resources/static/icon/1449347c56414681a321dc3c84302b00.png new file mode 100644 index 0000000..1520447 Binary files /dev/null and b/src/main/resources/static/icon/1449347c56414681a321dc3c84302b00.png differ diff --git a/src/main/resources/static/icon/56b7117b688a40699246aa378119c005.png b/src/main/resources/static/icon/56b7117b688a40699246aa378119c005.png new file mode 100644 index 0000000..5fc1f6f Binary files /dev/null and b/src/main/resources/static/icon/56b7117b688a40699246aa378119c005.png differ diff --git a/src/main/resources/static/icon/78e0a2de1f8e4354ad4bc46101ff7b1d.png b/src/main/resources/static/icon/78e0a2de1f8e4354ad4bc46101ff7b1d.png new file mode 100644 index 0000000..8d7bdd7 Binary files /dev/null and b/src/main/resources/static/icon/78e0a2de1f8e4354ad4bc46101ff7b1d.png differ diff --git a/src/main/resources/static/icon/88d05ff3ffa74bcd9f80584c9edf300d.png b/src/main/resources/static/icon/88d05ff3ffa74bcd9f80584c9edf300d.png new file mode 100644 index 0000000..1520447 Binary files /dev/null and b/src/main/resources/static/icon/88d05ff3ffa74bcd9f80584c9edf300d.png differ diff --git a/src/main/resources/static/icon/91a883092f2a40ee84b135aea9640fd1.png b/src/main/resources/static/icon/91a883092f2a40ee84b135aea9640fd1.png new file mode 100644 index 0000000..029257c Binary files /dev/null and b/src/main/resources/static/icon/91a883092f2a40ee84b135aea9640fd1.png differ diff --git a/src/main/resources/static/icon/aff16e96f9164e5196942b3738c55c10.png b/src/main/resources/static/icon/aff16e96f9164e5196942b3738c55c10.png new file mode 100644 index 0000000..1520447 Binary files /dev/null and b/src/main/resources/static/icon/aff16e96f9164e5196942b3738c55c10.png differ diff --git a/src/main/resources/static/icon/beaea0bdfd514f61b451d400e93f81b4.png b/src/main/resources/static/icon/beaea0bdfd514f61b451d400e93f81b4.png new file mode 100644 index 0000000..1b81de4 Binary files /dev/null and b/src/main/resources/static/icon/beaea0bdfd514f61b451d400e93f81b4.png differ diff --git a/src/main/resources/static/icon/c6cdc92296c24d168c8c08aa2009d7ca.png b/src/main/resources/static/icon/c6cdc92296c24d168c8c08aa2009d7ca.png new file mode 100644 index 0000000..7fa7077 Binary files /dev/null and b/src/main/resources/static/icon/c6cdc92296c24d168c8c08aa2009d7ca.png differ diff --git a/src/main/resources/static/icon/cc9abc741e7d444e9d8736056d76cb49.png b/src/main/resources/static/icon/cc9abc741e7d444e9d8736056d76cb49.png new file mode 100644 index 0000000..712c34b Binary files /dev/null and b/src/main/resources/static/icon/cc9abc741e7d444e9d8736056d76cb49.png differ diff --git a/src/main/resources/static/icon/cf3e2b0ace7a42a7b627cdd4929b21d1.png b/src/main/resources/static/icon/cf3e2b0ace7a42a7b627cdd4929b21d1.png new file mode 100644 index 0000000..54ce7e4 Binary files /dev/null and b/src/main/resources/static/icon/cf3e2b0ace7a42a7b627cdd4929b21d1.png differ diff --git a/src/test/java/com/yfd/platform/PlatformApplicationTests.java b/src/test/java/com/yfd/platform/PlatformApplicationTests.java new file mode 100644 index 0000000..c04ccc4 --- /dev/null +++ b/src/test/java/com/yfd/platform/PlatformApplicationTests.java @@ -0,0 +1,49 @@ +package com.yfd.platform; + +import cn.hutool.jwt.JWTUtil; +import org.junit.jupiter.api.Test; + +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Map; + +class PlatformApplicationTests { + + @Test + void contextLoads() { + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + Timestamp timestamp1 = new Timestamp(System.currentTimeMillis()); + long time = timestamp.getTime(); + long time1 = timestamp1.getTime(); + System.out.println(time1 - time); + String path = System.getProperty("user.dir"); + System.out.println(path); + int max = 101; + DecimalFormat df = new DecimalFormat("0000"); + String code = df.format(max + 1); + int i = Integer.parseInt("0030"); + System.out.println(i); + } + + @Test + void myTest() throws InterruptedException { + Map map = new HashMap() { + private static final long serialVersionUID = 1L; + + { + put("userid", Integer.parseInt("123232323")); + put("expire_time", System.currentTimeMillis() + 5 * 1000); + } + }; + String token = JWTUtil.createToken(map, "1234".getBytes()); + System.out.println(token); + Thread.sleep(10 * 1000); + + //解析token + boolean isok = JWTUtil.verify(token, "1234".getBytes()); + String userid = ""; + + } + +} diff --git a/src/test/java/com/yfd/platform/TestGuaVA.java b/src/test/java/com/yfd/platform/TestGuaVA.java new file mode 100644 index 0000000..870023e --- /dev/null +++ b/src/test/java/com/yfd/platform/TestGuaVA.java @@ -0,0 +1,73 @@ +package com.yfd.platform; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class TestGuaVA { + private Cache cache = CacheBuilder.newBuilder().maximumSize(2).expireAfterWrite(10, TimeUnit.MINUTES).build(); + + public Object getCache(K keyValue, final String ThreadName) { + Object value = null; + try { + System.out.println("ThreadName getCache==============" + ThreadName); + value = cache.get(keyValue, new Callable() { + @SuppressWarnings("unchecked") + public V call() { + System.out.println("ThreadName 执行业务数据并返回处理结果的数据(访问数据库等)==============" + ThreadName); + return (V) "dataValue"; + } + }); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return value; + } + + public static void main(String[] args) { + final TestGuaVA TestGuaVA=new TestGuaVA(); + + + Thread t1=new Thread(new Runnable() { + @Override + public void run() { + System.out.println("T1======start========"); + Object value=TestGuaVA.getCache("key","T1"); + System.out.println("T1 value=============="+value); + System.out.println("T1======end========"); + + } + }); + + Thread t2=new Thread(new Runnable() { + @Override + public void run() { + System.out.println("T2======start========"); + Object value=TestGuaVA.getCache("key","T2"); + System.out.println("T2 value=============="+value); + System.out.println("T2======end========"); + + } + }); + + Thread t3=new Thread(new Runnable() { + @Override + public void run() { + System.out.println("T3======start========"); + Object value=TestGuaVA.getCache("key","T3"); + System.out.println("T3 value=============="+value); + System.out.println("T3======end========"); + + } + }); + + t1.start(); + t2.start(); + t3.start(); + } + +} +