commit e8d399ac1965bb090e29f1cc4cd11e3740e8298b Author: Yen Date: Tue Sep 10 14:27:15 2024 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63208e1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.idea/ +logs/ +target/ +gyoa-java.iml +*.http +*.env.json +*.json +/src/test/ +questionnaire.iml diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ba26ef7 --- /dev/null +++ b/pom.xml @@ -0,0 +1,241 @@ + + + 4.0.0 + + com.qs + company-svc + 1.0.0RELEASE + + + org.springframework.boot + spring-boot-starter-parent + 2.6.4 + + + + 2.6.4 + 8 + 8 + 2.3.0 + 5.7.19 + 3.10.3 + 4.5.7 + 3.1 + 1.2.49 + 3.5.2 + true + 4.2.0 + + + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.13.0 + + + + cn.hutool + hutool-all + ${hutool.version} + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + org.springframework.boot + spring-boot-starter-undertow + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-validation + + + + com.auth0 + java-jwt + ${jwt.version} + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.4 + + + org.mybatis + mybatis-spring + + + org.mybatis + mybatis + + + + + + com.baomidou + dynamic-datasource-spring-boot-starter + ${mybatis-plus.version} + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + mysql + mysql-connector-java + 8.0.15 + + + + com.microsoft.sqlserver + mssql-jdbc + 8.4.1.jre8 + + + + org.projectlombok + lombok + 1.18.12 + compile + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + + com.github.binarywang + weixin-java-mp + ${wx.java.version} + + + + com.github.binarywang + weixin-java-cp + ${wx.java.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + RELEASE + test + + + + com.aliyun.oss + aliyun-sdk-oss + 3.16.1 + + + + org.springframework.cloud + spring-cloud-starter-openfeign + 3.1.5 + + + + + + serve + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + false + + + + diff --git a/src/main/java/com/qs/serve/Application.java b/src/main/java/com/qs/serve/Application.java new file mode 100644 index 0000000..6e49fbe --- /dev/null +++ b/src/main/java/com/qs/serve/Application.java @@ -0,0 +1,69 @@ +package com.qs.serve; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Indexed; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.annotation.PostConstruct; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.util.TimeZone; + +/** + * @author YenHex + * @since 2022/2/24 + */ +@Indexed +@EnableAsync +@EnableScheduling +@EnableTransactionManagement +@EnableCaching +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + @Value("${project.dev}") + String dev; + + public static void main(String[] args) { + long start = System.currentTimeMillis(); + SpringApplication.run(Application.class,args); + long end = System.currentTimeMillis(); + double diff = (end-start)/1000.0; + System.out.println("启动时间:"+diff + +"\n ____ _ _ __ _ _ \n" + + " / ___| | |_ __ _ _ __ | |_ _ _ _ __ ___ _ _ ___ ___ ___ ___ ___ / _| _ _ | || |\n" + + " \\___ \\ | __|/ _` || '__|| __| | | | || '_ \\ / __|| | | | / __|/ __|/ _ \\/ __|/ __|| |_ | | | || || |\n" + + " ___) || |_| (_| || | | |_ | |_| || |_) | \\__ \\| |_| || (__| (__| __/\\__ \\\\__ \\| _|| |_| || ||_|\n" + + " |____/ \\__|\\__,_||_| \\__| \\__,_|| .__/ |___/ \\__,_| \\___|\\___|\\___||___/|___/|_| \\__,_||_|(_)\n" + + " |_| \n"); + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + super.onStartup(servletContext); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder.sources(Application.class); + } + + @PostConstruct + void started() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + DevEnvironmentConfig.openDevEnv(dev.equals("true")); + } + +} diff --git a/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java b/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java new file mode 100644 index 0000000..26c2074 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java @@ -0,0 +1,24 @@ +package com.qs.serve.common.config; + +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.SessionTrackingMode; +import java.util.Collections; + + +/** + * 禁用jsessionid + * @author YenHex + * @since 2022/3/11 + */ +@Configuration +public class CustomServletContextInitializer implements ServletContextInitializer { + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE)); + } +} diff --git a/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java b/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java new file mode 100644 index 0000000..172699e --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java @@ -0,0 +1,33 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.util.Assert; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +/** + * @author YenHex + * @since 2022/3/11 + */ +@Slf4j +@UtilityClass +public class DevEnvironmentConfig { + + private static Boolean devEnv = null; + public static void openDevEnv(Boolean open){ + log.warn("环境变量:devEnv=>>> "+open); + devEnv = open; + } + + public static Boolean isDev(){ + if(devEnv==null){ + Assert.throwEx("资源加载中..."); + } + return devEnv; + } + + /** + * 开启账套 + */ + public final static boolean OPEN_TENANT_BOOK = true; + +} diff --git a/src/main/java/com/qs/serve/common/config/JwtConfig.java b/src/main/java/com/qs/serve/common/config/JwtConfig.java new file mode 100644 index 0000000..295c10d --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/JwtConfig.java @@ -0,0 +1,23 @@ +package com.qs.serve.common.config; + + +import lombok.Getter; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +public class JwtConfig { + + /** + * 单位分钟 + */ + private final Integer expire = 7; + + private final String iss = "KP_ISS"; + + private final String secret = "QiShenAa18n9VUcCxaSeSqLtFvsSCaRoVPKtBLaYxB0123456"; + +} diff --git a/src/main/java/com/qs/serve/common/config/MyBatisConfig.java b/src/main/java/com/qs/serve/common/config/MyBatisConfig.java new file mode 100644 index 0000000..5dc0761 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/MyBatisConfig.java @@ -0,0 +1,56 @@ +package com.qs.serve.common.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import com.qs.serve.common.framework.mybatis.handler.SysMetaHandler; +import com.qs.serve.common.framework.mybatis.handler.SysTenantHandler; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@MapperScan("com.qs.serve.modules.*.mapper") +@Configuration(proxyBeanMethods = false) +public class MyBatisConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 翻页拦截器 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + // 多租户、乐观锁等配置拦截 + interceptor.addInnerInterceptor(buildTenantHandler()); + // 添加防止全表更新与删除拦截器 + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + return interceptor; + } + + @Bean + public MetaObjectHandler sysMetaHandler(){ + return new SysMetaHandler(); + } + + public TenantLineInnerInterceptor buildTenantHandler(){ + String[] ignoreTable = new String[]{ + "sys_user", + "sys_user_tenant", + "sys_permit", + "sys_tenant", + "wx_app", + "sys_menu", + "sys_menu_permit", + "sys_request_log", + "bir_budget_target" + }; + SysTenantHandler sysTenantHandler = new SysTenantHandler(ignoreTable); + return new TenantLineInnerInterceptor(sysTenantHandler); + } + +} diff --git a/src/main/java/com/qs/serve/common/config/RedisConfig.java b/src/main/java/com/qs/serve/common/config/RedisConfig.java new file mode 100644 index 0000000..ce7f564 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/RedisConfig.java @@ -0,0 +1,70 @@ +package com.qs.serve.common.config; + + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.serializer.*; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + + +/** + * @author YenHex + * @since 2022/2/24 + */ +@EnableCaching +@Configuration(proxyBeanMethods = false) +public class RedisConfig extends CachingConfigurerSupport{ + + private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer(); + private static final GenericJackson2JsonRedisSerializer JACKSON__SERIALIZER = new GenericJackson2JsonRedisSerializer(); + + @Bean + public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { + //设置缓存过期时间 + RedisCacheConfiguration redisCacheCfg=RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofHours(1)) + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER)) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON__SERIALIZER)); + return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) + .cacheDefaults(redisCacheCfg) + .build(); + } + + @Bean + public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){ + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + return container; + } + + @Bean + @ConditionalOnMissingBean(name = "redisTemplate") + public RedisTemplate redisTemplate(RedisConnectionFactory factory){ + // 配置redisTemplate + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(factory); + // key序列化 + redisTemplate.setKeySerializer(STRING_SERIALIZER); + // value序列化 + redisTemplate.setValueSerializer(JACKSON__SERIALIZER); + // Hash key序列化 + redisTemplate.setHashKeySerializer(STRING_SERIALIZER); + // Hash value序列化 + redisTemplate.setHashValueSerializer(JACKSON__SERIALIZER); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } +} diff --git a/src/main/java/com/qs/serve/common/config/SecurityConfig.java b/src/main/java/com/qs/serve/common/config/SecurityConfig.java new file mode 100644 index 0000000..e834549 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/SecurityConfig.java @@ -0,0 +1,64 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.config.properties.PermitProperties; +import com.qs.serve.common.framework.security.filter.SecurityRequestFilter; +import com.qs.serve.common.framework.security.handler.SecurityAccessDeniedHandler; +import com.qs.serve.common.framework.security.handler.SecurityLogoutHandler; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author YenHex + * @since 2021/6/13 + */ +@Configuration +@AllArgsConstructor +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + private final SecurityRequestFilter securityRequestFilter; + private final UserDetailsService userService; + private final PermitProperties permitProperties; + + @Override + protected void configure(HttpSecurity http) throws Exception { + List permitUrls = new ArrayList<>(); + if(permitProperties.getPermits()!=null){ permitUrls.addAll(permitProperties.getPermits()); } + if(permitProperties.getTenants()!=null){ permitUrls.addAll(permitProperties.getTenants()); } + permitUrls = permitUrls.stream().distinct().collect(Collectors.toList()); + String[] permit_urls = new String[permitUrls.size()]; + permitUrls.toArray(permit_urls); + http.csrf().disable(); + http.authorizeRequests() + .antMatchers(HttpMethod.OPTIONS.toString()).permitAll() + .antMatchers(permit_urls).permitAll() + //.antMatchers().permitAll() //测试用 + .anyRequest().authenticated(); + http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER); + http.logout() + .logoutUrl("/portal/logout") + .addLogoutHandler(new SecurityLogoutHandler()) + .invalidateHttpSession(true); + http.headers().cacheControl(); + http.addFilterBefore(securityRequestFilter, UsernamePasswordAuthenticationFilter.class); + http.exceptionHandling().accessDeniedHandler(new SecurityAccessDeniedHandler()); + //http.formLogin().failureHandler(new SecurityAuthenticationFailureHandler()); + } + + @Override + public UserDetailsService userDetailsService() { + return userService; + } + +} diff --git a/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java b/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java new file mode 100644 index 0000000..f3cf536 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java @@ -0,0 +1,73 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.config.properties.ProjectProperties; +import com.qs.serve.common.framework.interceptor.LimitSubmitInterceptor; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +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.multipart.MultipartResolver; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author YenHex + * @since 2022/2/24 + */ +@Slf4j +@AllArgsConstructor +@Configuration(proxyBeanMethods = false) +public class SpringMvcConfig implements WebMvcConfigurer { + + private final LimitSubmitInterceptor limitSubmitInterceptor; + //private final ApiAuthInterceptor apiAuthInterceptor; + + private final ProjectProperties projectProperties; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(limitSubmitInterceptor) + .addPathPatterns("/**"); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + log.warn("PcWebLocal==>{}",projectProperties.getPcWebLocal()); + registry.addResourceHandler("/web/**") + .addResourceLocations("file:"+projectProperties.getPcWebLocal()); + registry.addResourceHandler("/static/**") + .addResourceLocations("file:"+projectProperties.getPcWebLocal()+"static/"); + } + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + /*是否允许请求带有验证信息*/ + corsConfiguration.setAllowCredentials(true); + /*允许访问的客户端域名*/ + corsConfiguration.addAllowedOrigin("*"); + /*允许服务端访问的客户端请求头*/ + corsConfiguration.addAllowedHeader("*"); + /*允许访问的方法名,GET POST等*/ + corsConfiguration.addAllowedMethod("*"); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); + } + + //@Bean + public MultipartResolver multipartResolver(){ + CommonsMultipartResolver resolver = new CommonsMultipartResolver(); + resolver.setMaxInMemorySize(5120); + resolver.setMaxInMemorySize(300 * 1024 * 1024); + resolver.setDefaultEncoding("UTF-8"); + return resolver; + } + +} diff --git a/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java b/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java new file mode 100644 index 0000000..f1128d5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java @@ -0,0 +1,56 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.util.ThreadsUtils; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + + +/** + * 线程池配置 + * @author YenHex + * @since 2022/2/24 + */ +@Configuration +public class ThreadPoolConfig { + + /** 核心线程池大小 */ + private final int corePoolSize = 50; + + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() { + // 最大可创建的线程数 + int maxPoolSize = 200; + // 队列最大长度 + int queueCapacity = 1000; + // 线程池维护线程所允许的空闲时间 + int keepAliveSeconds = 300; + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** 执行周期性或定时任务 */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) { + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + ThreadsUtils.printException(r, t); + } + }; + } +} diff --git a/src/main/java/com/qs/serve/common/config/properties/AliYunOssProperties.java b/src/main/java/com/qs/serve/common/config/properties/AliYunOssProperties.java new file mode 100644 index 0000000..fd69d18 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/AliYunOssProperties.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "aliyun.oss") +public class AliYunOssProperties { + + private String bucket; + private String accessKeyId; + private String accessKeySecret; + private String endpoint; + private String prefix; + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/AuthUrlConst.java b/src/main/java/com/qs/serve/common/config/properties/AuthUrlConst.java new file mode 100644 index 0000000..910aebc --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/AuthUrlConst.java @@ -0,0 +1,13 @@ +package com.qs.serve.common.config.properties; + +/** + * @author YenHex + * @since 2024/3/27 + */ +public class AuthUrlConst { + + public final static String[] AUTH_ALLOW_URL = new String[]{ + "bir/" + }; + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java b/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java new file mode 100644 index 0000000..c6269b4 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java @@ -0,0 +1,32 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project.ignore-url") +public class PermitProperties { + + /** + * 可通过路径(适用于回调场景、无拦截场景等) + */ + private List permits = new ArrayList<>(); + + /** + * 默认租户拦截(适用于无需登录接口,但有租户拦截) + */ + private List tenants = new ArrayList<>(); + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/ProjectApisProperties.java b/src/main/java/com/qs/serve/common/config/properties/ProjectApisProperties.java new file mode 100644 index 0000000..8d81797 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/ProjectApisProperties.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author YenHex + * @since 2023/9/7 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project.apis") +public class ProjectApisProperties { + + /** 支付接口 */ + private String costToPay; + + /** 同步核销的支付状态 */ + private String checkPayStatus; + + /** 调度系统-发货单 */ + private String diaoduPlanOrder; + + /** 嘉士利接口,spu转换sku */ + private String spuToSku; + + /** + * 原是生成销路通apt的中间表,替换伟成的接口直接生成 + */ + private String policySyncCate; + + private String policySyncInv; +} diff --git a/src/main/java/com/qs/serve/common/config/properties/ProjectProperties.java b/src/main/java/com/qs/serve/common/config/properties/ProjectProperties.java new file mode 100644 index 0000000..f232a0c --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/ProjectProperties.java @@ -0,0 +1,31 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project") +public class ProjectProperties { + + private String closeAuth; + + private String birService; + + private String birServiceUrl; + + private String hostUrl; + + private String webUrl; + + private String pcWebLocal; + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/QiShengDsProperties.java b/src/main/java/com/qs/serve/common/config/properties/QiShengDsProperties.java new file mode 100644 index 0000000..e1cd414 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/QiShengDsProperties.java @@ -0,0 +1,22 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author YenHex + * @since 2024/6/18 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.qisheng") +public class QiShengDsProperties { + + private String url; + private String username; + private String password; + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java b/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java new file mode 100644 index 0000000..34cd197 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "spring.redis") +public class RedisProperties { + + private String host; + + private Integer port; + + private String password; + + private Integer database; +} diff --git a/src/main/java/com/qs/serve/common/config/properties/SeeYonProperties.java b/src/main/java/com/qs/serve/common/config/properties/SeeYonProperties.java new file mode 100644 index 0000000..4b51678 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/SeeYonProperties.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project.seeyon") +public class SeeYonProperties { + + private Boolean enable; + + private String url; + + private String extApi; + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java b/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java new file mode 100644 index 0000000..a18b81e --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java @@ -0,0 +1,24 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author YenHex + * @since 2022/3/14 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project.upload") +public class UploadProperties { + + private String tempPath; + + private String proxyUrl; + + private String logicalPath; + +} diff --git a/src/main/java/com/qs/serve/common/framework/annotations/TagField.java b/src/main/java/com/qs/serve/common/framework/annotations/TagField.java new file mode 100644 index 0000000..53d4fec --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/annotations/TagField.java @@ -0,0 +1,4 @@ +package com.qs.serve.common.framework.annotations; + +public @interface TagField { +} diff --git a/src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java b/src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java new file mode 100644 index 0000000..be87556 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java @@ -0,0 +1,215 @@ +package com.qs.serve.common.framework.aop; + +import com.alibaba.fastjson.JSON; +import com.qs.serve.common.framework.manager.AsyncFactory; +import com.qs.serve.common.framework.manager.AsyncManager; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.ServletUtils; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** + * 操作日志织入 + * @author YenHex + * @since 2022/3/8 + */ +@Slf4j +@Aspect +@Component +public class SysLogAspect { + + @Autowired + private SysUserService sysUserService; + + ThreadLocal startTimeIndex = new ThreadLocal<>(); + + @Pointcut("@annotation(com.qs.serve.common.model.annotation.SysLog)") + public void logPointCut() {} + + @Before("@annotation(com.qs.serve.common.model.annotation.SysLog)") + public void doBefore() { + startTimeIndex.set(System.currentTimeMillis()); + } + + /** + * 处理完请求后执行 + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) { + handleLog(joinPoint, null, jsonResult); + } + + /** + * 拦截异常操作 + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "logPointCut()", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Exception e) { + handleLog(joinPoint, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) { + try { + // 获得注解 + SysLog controllerLog = getAnnotationLog(joinPoint); + if (controllerLog == null) { + return; + } + + HttpServletRequest request = ServletUtils.getRequest(); + //忽略GET + if(request.getMethod().equals("GET")){ + return; + } + // 获取当前的用户 + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + SysOperationLog operLog = new SysOperationLog(); + operLog.setReqIp(ServletUtils.getIp(request)); + operLog.setReqMethod(request.getMethod()); + operLog.setJsonResult(JSON.toJSONString(jsonResult)); + operLog.setReqUrl(request.getRequestURI()); + operLog.setUserAgent(request.getHeader(GySysConst.USER_AGENT_PROP)); + if (loginUser != null) { + operLog.setUserId(loginUser.getUserId()); + operLog.setUserType(loginUser.getTypeFlag().getCode()); + SysUser sysUser = sysUserService.getById(loginUser.getUserId()); + if(sysUser!=null){ + operLog.setCreatorName(sysUser.getName()); + } + } + if (e != null) { + operLog.setErrMsg(StringUtils.substring(e.getMessage(), 0, 2500)); + } + //耗时 + Long startTime = startTimeIndex.get(); + if(startTime!=null){ + operLog.setElapsedTime(System.currentTimeMillis()-startTime); + }else { + operLog.setElapsedTime(0L); + } + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setCodeMethod(className + "." + methodName + "()"); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog); + operLog.setTenantId(AuthContextUtils.getTenant()); + // 保存数据库 + AsyncManager.me().execute(AsyncFactory.saveOperationLog(operLog)); + } catch (Exception exp) { + // 记录本地异常日志 + log.error("==前置通知异常==\n异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 + * @param sysLog 日志 + * @param operationLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, SysLog sysLog, SysOperationLog operationLog) throws Exception { + operationLog.setBizType(sysLog.biz().getValue()); + operationLog.setInterType(sysLog.inter().name()); + operationLog.setTitle(sysLog.title()); + operationLog.setModule(sysLog.module().getVale()); + operationLog.setOptDesc(sysLog.desc()); + if (sysLog.saveReqParam()) { + setRequestValue(joinPoint, operationLog); + } + } + + /** + * 获取请求的参数,放到log中 + * @param operationLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperationLog operationLog) throws Exception { + String requestMethod = operationLog.getReqMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { + String params = argsArrayToString(joinPoint.getArgs()); + operationLog.setReqParam(StringUtils.substring(params, 0, 2500)); + } else { + Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operationLog.setReqParam(StringUtils.substring(paramsMap.toString(), 0, 2500)); + } + } + + /** 是否存在注解,如果存在就获取 */ + private SysLog getAnnotationLog(JoinPoint joinPoint){ + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + if (method != null) { + return method.getAnnotation(SysLog.class); + } + return null; + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) { + for (int i = 0; i < paramsArray.length; i++) { + if (paramsArray[i]!=null && !isFilterObject(paramsArray[i])) { + Object jsonObj = JSON.toJSON(paramsArray[i]); + params += jsonObj.toString() + " "; + } + } + } + return params.trim(); + } + + /** + * 判断是否需要过滤的对象。 + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) { + Class clazz = o.getClass(); + if (clazz.isArray()) { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } else if (Collection.class.isAssignableFrom(clazz)) { + Collection collection = (Collection) o; + for (Iterator iter = collection.iterator(); iter.hasNext(); ) { + return iter.next() instanceof MultipartFile; + } + } else if (Map.class.isAssignableFrom(clazz)) { + Map map = (Map) o; + for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry entry = (Map.Entry) iter.next(); + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/src/main/java/com/qs/serve/common/framework/exception/BaseException.java b/src/main/java/com/qs/serve/common/framework/exception/BaseException.java new file mode 100644 index 0000000..07d0353 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/exception/BaseException.java @@ -0,0 +1,21 @@ +package com.qs.serve.common.framework.exception; + +/** + * @author JcYen + * @date 2020/6/11 + * @version 1.0 + */ +public abstract class BaseException extends RuntimeException { + + public BaseException(String message){ + super(message); + } + + /** + * 错误代码 + * @return + */ + public abstract int getCode(); + + +} diff --git a/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java b/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java new file mode 100644 index 0000000..6679aca --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.framework.exception; + +import java.io.Serializable; + +/** + * @author JcYen + * @Date 2020/6/11 + * @Version 1.0 + */ +public class BusinessException extends BaseException implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer status; + + public BusinessException(String message,Integer status) { + super(message); + this.status = status; + } + + @Override + public int getCode() { + return status; + } +} diff --git a/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java b/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java new file mode 100644 index 0000000..046c83b --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java @@ -0,0 +1,148 @@ +package com.qs.serve.common.framework.exception; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.HttpCode; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.sql.SQLIntegrityConstraintViolationException; + + +/** + * @Author JcYen + * @Date 2019/6/7 + * @Version 1.0 + */ +@Slf4j +@Component +@ControllerAdvice +public class UnifiedExceptionHandler { + + + @ExceptionHandler(value = BusinessException.class) + @ResponseBody + public R handleBindException(BusinessException e,HttpServletRequest request) { + log.warn("自定义异常触发【{},{}】,请求地址:{}",e.getCode(),e.getMessage(),request.getRequestURI()); + return new R(e.getCode(),e.getMessage()); + } + + @ExceptionHandler(value = NullPointerException.class) + @ResponseBody + public R handleBindException(NullPointerException e,HttpServletRequest request) { + e.printStackTrace(); + log.error("空指针【{}】,请求地址:{}",e.getMessage(),request.getRequestURI()); + return R.error("数据不存在或被移除"); + } + + @ExceptionHandler({ + AccessDeniedException.class + }) + @ResponseBody + public R handleAccessException(AccessDeniedException e,HttpServletRequest request) { + HttpCode hc = HttpCode.FORBIDDEN_403; + log.error("访问拦截【{}】,请求地址:{}",e.getMessage(),request.getRequestURI()); + return new R(hc.getCode(),hc.getMsg()); + } + + @ExceptionHandler({ + UsernameNotFoundException.class, + }) + @ResponseBody + public R handlePrintMsgException(UsernameNotFoundException e) { + return R.error(); + } + + @ExceptionHandler({ + BadCredentialsException.class, + }) + @ResponseBody + public R handlePrintMsgException(Exception e) { + log.warn(e.getMessage()); + HttpCode hc = HttpCode.LOGIN_ERR_1; + return new R(hc.getCode(),hc.getMsg()); + } + + @ExceptionHandler({ + BindException.class, + HttpRequestMethodNotSupportedException.class + }) + @ResponseBody + public R handleDevPrintMsgException(Exception e,HttpServletRequest request) { + log.error("参数校验异常:{}",e.getMessage()); + if(DevEnvironmentConfig.isDev()){ + return R.error(e.getMessage()); + } + return R.error(); + } + + @ExceptionHandler({ + MethodArgumentNotValidException.class, + }) + @ResponseBody + public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e,HttpServletRequest request) { + log.error("参数校验异常【{}】,请求地址:{}",e.getMessage(),request.getRequestURI()); + return R.error(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); + } + + + @ExceptionHandler(value = DuplicateKeyException.class) + @ResponseBody + public R handleDuplicateKeyException(DuplicateKeyException e,HttpServletRequest request) { + log.error("限制重复数据【{}】,请求地址:{}",e.getMessage(),request.getRequestURI()); + e.printStackTrace(); + return R.error("限制重复数据,请联系管理员"); + } + + @ExceptionHandler(value = HttpMessageNotReadableException.class) + @ResponseBody + public R handleHttpMessageNotReadableException(HttpMessageNotReadableException e,HttpServletRequest request) { + log.error("请求参数无法解析【{}】,请求地址:{}",e.getMessage(),request.getRequestURI()); + return R.error("请求参数无法解析"); + } + + @ExceptionHandler({ + SQLIntegrityConstraintViolationException.class, + }) + @ResponseBody + public R handleSqlIntegrityException(Exception e,HttpServletRequest request) { + log.warn("数据库拦截【{}】,请求地址:{}",e.getMessage(),request.getRequestURI()); + e.printStackTrace(); + return new R(500,"数据库拦截,请联系管理员"); + } + + /** + * 强制运行写入成功 + * @param e + * @return + */ + @ExceptionHandler(value = HttpMessageNotWritableException.class) + @ResponseBody + public R handleMsgException(HttpMessageNotWritableException e) { + return R.ok(); + } + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public R handleException(Exception e,HttpServletRequest request) { + log.error("Servlet异常\n请求地址:{},异常类型:{}\n异常信息:{}\n异常体:",request.getRequestURI(),e.getClass().getSimpleName(),e.getMessage(),e); + e.printStackTrace(); + if(DevEnvironmentConfig.isDev()){return R.error(e.getMessage());} + return R.error(); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java b/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java new file mode 100644 index 0000000..c778351 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java @@ -0,0 +1,66 @@ +package com.qs.serve.common.framework.interceptor; + +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.util.StringUtils; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +/** + * 防止重复提交拦截器 + * @author YenHex + */ +@Configuration(proxyBeanMethods = false) +public class LimitSubmitInterceptor implements HandlerInterceptor { + + public final String REPEAT_Limit_KEY = "repeatLimitKey"; + + @Resource + public RedisService redisService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + LimitSubmit annotation = method.getAnnotation(LimitSubmit.class); + if (annotation != null) { + if (this.LimitSubmit(request, annotation)) { + if(StringUtils.isNotEmpty(annotation.message())){ + HttpResponsePrintUtil.print(response,406,annotation.message()); + }else { + HttpResponsePrintUtil.print(response,406,"系统处理中,请勿频繁操作"); + } + return false; + } + } + return true; + } else { + return true; + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * @param request 请求对象 + * @param annotation 防复注解 + * @return + */ + public boolean LimitSubmit(HttpServletRequest request, LimitSubmit annotation) throws Exception { + String key = REPEAT_Limit_KEY+"_"+request.getRequestURI()+"_"+request.getRemoteHost(); + Object cache = redisService.get(key); + if(cache!=null){return true;} + redisService.set(key,"true",annotation.interval(), TimeUnit.MILLISECONDS); + return false; + } + + +} diff --git a/src/main/java/com/qs/serve/common/framework/interceptor/LocalDateTimeFormatSerializer.java b/src/main/java/com/qs/serve/common/framework/interceptor/LocalDateTimeFormatSerializer.java new file mode 100644 index 0000000..7b345a6 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/interceptor/LocalDateTimeFormatSerializer.java @@ -0,0 +1,31 @@ +package com.qs.serve.common.framework.interceptor; + +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.ObjectSerializer; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +/** + * @author YenHex + * @since 2024/7/18 + */ +public class LocalDateTimeFormatSerializer implements ObjectSerializer { + + @Override + public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { + if (object == null) { + serializer.out.writeNull(); + return; + } + LocalDateTime date = (LocalDateTime) object; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String timeString = formatter.format(date); + serializer.write(timeString); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java b/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 0000000..6825fe9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,98 @@ +package com.qs.serve.common.framework.interceptor; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.model.annotation.RepeatSubmit; +import com.qs.serve.common.util.JsonUtil; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * 防止重复提交拦截器 + * @author YenHex + */ +@Configuration(proxyBeanMethods = false) +public class RepeatSubmitInterceptor implements HandlerInterceptor { + + public final String REPEAT_PARAMS = "repeatParams"; + public final String REPEAT_TIME = "repeatTime"; + public final String SESSION_REPEAT_KEY = "repeatData"; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) { + if (this.isRepeatSubmit(request, annotation)) { + HttpResponsePrintUtil.print(response,406,"系统正常处理,请勿重复提交"); + return false; + } + } + return true; + } else { + return true; + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * @param request 请求对象 + * @param annotation 防复注解 + * @return + */ + public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception { + // 本次参数及系统时间 + String nowParams = JsonUtil.objectToJson(request.getParameterMap()); + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + // 请求地址(作为存放session的key值) + String url = request.getRequestURI(); + HttpSession session = request.getSession(); + Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY); + if (sessionObj != null) { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) { + return true; + } + } + } + Map sessionMap = new HashMap<>(); + sessionMap.put(url, nowDataMap); + session.setAttribute(SESSION_REPEAT_KEY, sessionMap); + return false; + } + + /** + * 判断参数是否相同 + */ + private boolean compareParams(Map nowMap, Map preMap) { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap, int interval) { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < interval) { + return true; + } + return false; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java b/src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java new file mode 100644 index 0000000..9094c94 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java @@ -0,0 +1,35 @@ +package com.qs.serve.common.framework.manager; + + +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.mapper.SysOperationLogMapper; +import lombok.extern.slf4j.Slf4j; + +import java.util.TimerTask; + + +/** + * 异步工厂 + * @author YenHex + * @since 2022/2/24 + */ +@Slf4j +public class AsyncFactory { + + /** + * 操作日志记录 + * @param operationLog + * @return + */ + public static TimerTask saveOperationLog(final SysOperationLog operationLog) { + return new TimerTask() { + @Override + public void run() { + SpringUtils.getBean(SysOperationLogMapper.class).saveLog(operationLog); + } + }; + } + + +} diff --git a/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java b/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java new file mode 100644 index 0000000..d82e34f --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java @@ -0,0 +1,52 @@ +package com.qs.serve.common.framework.manager; + +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.common.util.ThreadsUtils; + +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + + +/** + * 异步任务管理器 + * @author YenHex + * @since 2022/2/24 + */ +public class AsyncManager { + /** + * 操作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + + /** + * 异步操作任务调度线程池 + */ + private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 单例模式 + */ + private AsyncManager() { + } + + private static AsyncManager me = new AsyncManager(); + + public static AsyncManager me() { + return me; + } + + /** + * 执行任务 + * @param task 任务 + */ + public void execute(TimerTask task) { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** 停止任务线程池 */ + public void shutdown() { + ThreadsUtils.shutdownAndAwaitTermination(executor); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java b/src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java new file mode 100644 index 0000000..6492549 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java @@ -0,0 +1,187 @@ +package com.qs.serve.common.framework.mvc; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.DateUtils; +import com.qs.serve.common.util.ServletUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * HttpServletRequest 过滤器 + * 解决: request.getInputStream()只能读取一次的问题 + * 目标: 流可重复读 + * @Author YenHex + * @Date 2021/4/9 + * @Version: 1.0 + **/ +@Slf4j +@Component +@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/") +@Order(10000) +public class HttpServletRequestFilter implements Filter{ + + @Resource + RedisService redisService; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + RequestWrapper requestWrapper = null; + if(servletRequest instanceof HttpServletRequest) { + //过滤文件URL + String url = ((HttpServletRequest) servletRequest).getRequestURI(); + if(!url.contains("import")&&!url.contains("upload")){ + requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); + } + } + long startTime = System.currentTimeMillis(); + if(null == requestWrapper) { + filterChain.doFilter(servletRequest, servletResponse); + } else { + filterChain.doFilter(requestWrapper, servletResponse); + } + long endTime = System.currentTimeMillis(); + double diffTime = DateUtils.diffTime(startTime,endTime); + assert servletRequest instanceof HttpServletRequest; + HttpServletRequest request = (HttpServletRequest)servletRequest; + String supplierId = request.getHeader("supplierId"); + String url = request.getRequestURL().toString(); + String method = request.getMethod(); + String queryStr = request.getQueryString(); + String reqBody = ""; + if (ServletUtils.isJsonRequest(request)&&requestWrapper!=null) { + reqBody = requestWrapper.getBody(); + } + StringBuffer buffer = new StringBuffer("\n["+method+"] "+url); + if(supplierId!=null){ + buffer.append(" 供应商ID: "+supplierId); + } + if(!StringUtils.isEmpty(queryStr)){ + buffer.append("\n参数: "+queryStr); + } + if(DevEnvironmentConfig.isDev() &&!StringUtils.isEmpty(reqBody)){ + buffer.append("\n请求体: "+reqBody); + } + if(diffTime>0.6D){ + buffer.append("\n耗时: "+diffTime+"秒"); + } + try { + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + buffer.append("\n用户: "+loginUser.getNick()); + buffer.append(" IP:["+ServletUtils.getIp(request)+"]"); + buffer.append(" 时间:["+ LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)+"]"); + } + } catch (Exception e) {} + if(diffTime< 1D){ + log.info(buffer.toString()); + }else if (diffTime< 20D){ + log.warn(buffer.toString()); + }else { + log.error(buffer.toString()); + } + String themeKey = AuthContextUtils.getLockTheme(); + if(StringUtils.hasText(themeKey)){ + log.warn("释放资源key:{}",themeKey); + redisService.remove(themeKey); + } + //释放资源 防止线程池重复利用出现脏数据 + AuthContextUtils.removeThreadLocal(); + } + + @Override + public void destroy() { + + } + + /*** + * HttpServletRequest 包装器 + * 解决: request.getInputStream()只能读取一次的问题 + * 目标: 流可重复读 + */ + public class RequestWrapper extends HttpServletRequestWrapper { + + /** + * 请求体 + */ + private String mBody; + + public RequestWrapper(HttpServletRequest request) { + super(request); + mBody = getBody(request); + } + + /** + * 获取请求体 + * @param request 请求 + * @return 请求体 + */ + private String getBody(HttpServletRequest request) { + return ServletUtils.getBodyString(request); + } + + /** + * 获取请求体 + * @return 请求体 + */ + public String getBody() { + return mBody; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // 创建字节数组输入流 + final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes(StandardCharsets.UTF_8)); + + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return bais.read(); + } + }; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java new file mode 100644 index 0000000..59b3b7a --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java @@ -0,0 +1,17 @@ +package com.qs.serve.common.framework.mybatis.handler; + +import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; +import com.qs.serve.common.util.NanoIdUtils; + +/** + * @author YenHex + * @since 2022/4/11 + */ +public class IdGeneratorHandler extends DefaultIdentifierGenerator { + + @Override + public String nextUUID(Object entity) { + return NanoIdUtils.randomNanoId(); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java new file mode 100644 index 0000000..7838399 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.mybatis.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.util.AuthContextUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; + +import java.time.LocalDateTime; + +/** + * 自动注入列数据 + * @author YenHex + * @since 2022/3/1 + */ +@Slf4j +public class SysMetaHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + this.strictInsertFill(metaObject, "createBy", () -> loginUser.getUserId(), String.class); + } + this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); + } + + @Override + public void updateFill(MetaObject metaObject) { + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + this.strictUpdateFill(metaObject, "updateBy", () -> loginUser.getUserId(), String.class); + } + this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java new file mode 100644 index 0000000..8255dd9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java @@ -0,0 +1,58 @@ +package com.qs.serve.common.framework.mybatis.handler; + +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; + +import java.util.Arrays; + +/** + * @Author YenHex + * @Date 2021/5/7 + * @Version: 1.0 + **/ +public class SysTenantHandler implements TenantLineHandler { + + public SysTenantHandler(String[] ignoreTables){ + this.IGNORE_TABLES = Arrays.asList(ignoreTables); + } + + + final private java.util.List IGNORE_TABLES; + + @Override + public Expression getTenantId() { + String tenant = AuthContextUtils.getTenant(); + if(tenant==null){ + Assert.throwEx(HttpCode.LOGIN_ERR_4001); + } + return new StringValue(tenant); + } + + @Override + public String getTenantIdColumn() { + return GySysConst.TENANT_COLUMN; + } + + /** + * 判断是否忽略该表,默认全忽略,匹配到的不忽略 + * @param tableName + * @return + */ + @Override + public boolean ignoreTable(String tableName) { + for (String tb : this.IGNORE_TABLES) { + if(tableName.equalsIgnoreCase(tb)){ + return true; + } + } + return false; + } + + + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java new file mode 100644 index 0000000..9efe3ba --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java @@ -0,0 +1,50 @@ +package com.qs.serve.common.framework.mybatis.handler.meta; + +import cn.hutool.json.JSONUtil; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 存储到数据库, 将String数组转换成字符串; + * 从数据库获取数据, 将字符串转为LONG数组. + * @author YenHex + * @since 2022/3/1 + */ +@MappedTypes({String[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class JsonStringTypeHandler extends BaseTypeHandler { + + private static String[] l = new String[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, + String[] parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public String[] getNullableResult(ResultSet rs, String columnName) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnName)).toArray(l); + } + + @Override + public String[] getNullableResult(ResultSet rs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l); + } + + @Override + public String[] getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java new file mode 100644 index 0000000..ac02252 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java @@ -0,0 +1,74 @@ +package com.qs.serve.common.framework.mybatis.handler.meta; + +import com.qs.serve.common.util.StringUtils; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; + +/** + * 存储到数据库, 将String数组转换成字符串; + * 从数据库获取数据, 将字符串转为LONG数组. + * @author YenHex + * @since 2022/3/1 + */ +@MappedTypes({String[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class SplitStringTypeHandler extends BaseTypeHandler { + + private static String[] l = new String[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) throws SQLException { + if(parameter!=null&¶meter.length>1){ + StringBuffer buffer = new StringBuffer(); + for (int i1 = 0; i1 < parameter.length; i1++) { + buffer.append(parameter[i1]); + if(i1+1 val != null && val.trim().length() > 0) + .toArray(String[]::new); + } + return null; + } + + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java new file mode 100644 index 0000000..4e14619 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java @@ -0,0 +1,115 @@ +package com.qs.serve.common.framework.mybatis.join; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity; +import com.qs.serve.common.framework.mybatis.join.enums.JoinType; +import com.qs.serve.common.framework.mybatis.join.model.JoinFieldData; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.common.util.WordUtil; +import lombok.extern.slf4j.Slf4j; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author YenHex + * @since 2022/5/24 + */ +@Slf4j +public class JoinUtil { + + private static Map> CACHE_MAP = new ConcurrentHashMap<>(); + + private static List getJoinFields(List list) { + if(CollectionUtil.isEmpty(list)){ + return new ArrayList<>(); + } + String className = list.get(0).getClass().getName(); + List joinFieldDataList = new ArrayList<>(); + Class clazz = null; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + if(clazz==null){return null;} + Field[] fields = clazz.getDeclaredFields(); + Field fieldJoinVal = null; + Field fieldSetVal = null; + BindEntity bindEntity = null; + for (Field field : fields) { + for (Annotation annotation : field.getAnnotations()) { + if(annotation instanceof BindEntity){ + fieldSetVal = field; + bindEntity = (BindEntity) annotation; + break; + } + } + } + if(fieldSetVal!=null){ + for (Field field :fields){ + if(field.getName().equals(bindEntity.joinField())){ + fieldJoinVal = field; + break; + } + } + } + if(bindEntity!=null&&fieldJoinVal!=null){ + JoinFieldData fieldData = new JoinFieldData(); + fieldData.setFieldJoinVal(fieldJoinVal); + fieldData.setBindEntity(bindEntity); + fieldData.setFieldSetVal(fieldSetVal); + joinFieldDataList.add(fieldData); + } + CACHE_MAP.put(className,joinFieldDataList); + return joinFieldDataList; + } + + public static void relate(List list) { + List joinFieldData = getJoinFields(list); + HashMap tempCache = new HashMap<>(list.size()+1); + for (JoinFieldData fieldData : joinFieldData) { + for (Object object : list) { + try { + Field fieldJoinVal = fieldData.getFieldJoinVal(); + Field fieldSetVal = fieldData.getFieldSetVal(); + BindEntity bindEntity = fieldData.getBindEntity(); + fieldSetVal.setAccessible(true); + fieldJoinVal.setAccessible(true); + IService iService = SpringUtils.getBean(bindEntity.service()); + Object identity = fieldJoinVal.get(object); + if(identity==null){ + continue; + } + Object result = tempCache.get(identity.toString()); + if(result!=null){ + fieldSetVal.set(object,result); + continue; + } + if(bindEntity.joinType()== JoinType.List){ + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(WordUtil.toLine(bindEntity.joinField()),identity); + result = iService.list(wrapper); + }else { + QueryWrapper wrapper = new QueryWrapper(); + wrapper.eq(WordUtil.toLine(bindEntity.selfField()),identity); + result = iService.getOne(wrapper,false); + } + fieldSetVal.set(object,result); + tempCache.put(identity.toString(),result); + } catch (IllegalAccessException e) { + log.warn("join 工具失败:",e); + } + } + } + tempCache = null; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java new file mode 100644 index 0000000..887fa1e --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.mybatis.join.annotations; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.common.framework.mybatis.join.enums.JoinType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 实现left join + * @author YenHex + * @since 2022/5/24 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface BindEntity { + + Class service(); + + /** + * 关联的表 + * @return + */ + String joinField() default ""; + + /** + * 主表 + * @return + */ + String selfField() default "id"; + + JoinType joinType() default JoinType.Object; + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java new file mode 100644 index 0000000..df49269 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java @@ -0,0 +1,14 @@ +package com.qs.serve.common.framework.mybatis.join.enums; + +/** + * @author YenHex + * @since 2022/5/24 + */ +public enum JoinType { + + /** + * 返回类型 + */ + Object,List + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java new file mode 100644 index 0000000..6d87537 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java @@ -0,0 +1,17 @@ +package com.qs.serve.common.framework.mybatis.join.model; + +import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity; +import lombok.Data; + +import java.lang.reflect.Field; + +/** + * @author YenHex + * @since 2022/5/24 + */ +@Data +public class JoinFieldData { + Field fieldJoinVal; + Field fieldSetVal; + BindEntity bindEntity; +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java new file mode 100644 index 0000000..01dadfe --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java @@ -0,0 +1,159 @@ +package com.qs.serve.common.framework.mybatis.query; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.mybatis.query.model.QueryFieldData; +import com.qs.serve.common.framework.mybatis.query.model.QueryFieldDataValue; +import com.qs.serve.common.framework.mybatis.query.model.QueryType; +import com.qs.serve.common.framework.mybatis.query.annotations.QueryWrap; +import com.qs.serve.common.util.WordUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author JcYen + * @Date 2017/10/28 + * @Version 1.0 + */ +@Slf4j +public class AnnotationQueryStorage { + + private static final Map> BEAN_QUERY_FIELD = new ConcurrentHashMap<>(); + + protected static List getQueryFieldList(String className){ + List queryFieldList = BEAN_QUERY_FIELD.get(className); + if(queryFieldList==null){ + Class clazz = null; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + queryFieldList = new ArrayList<>(); + if(clazz==null){return queryFieldList;} + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + Annotation[] annotations = field.getAnnotations(); + boolean isExist = false; + boolean isIgnore = false; + for (Annotation annotation : annotations) { + if(annotation instanceof QueryWrap){ + QueryWrap queryWrap = (QueryWrap)annotation; + QueryFieldData queryField= handleQueryField(queryWrap.type(),field); + if(queryField!=null){ + isExist = true; + queryFieldList.add(queryField); + break; + } + } + if(annotation instanceof TableField){ + TableField tableField = (TableField) annotation; + isIgnore = tableField.exist(); + } + } + //不存在,添加默认 + if( !isExist && !isIgnore ){ + QueryFieldData queryField = new QueryFieldData(); + //系统默认使用格式。示例: userInfo -> user_info + queryField.setColumnName(WordUtil.toLine(field.getName())); + queryField.setField(field); + queryField.setFieldName(field.getName()); + queryField.setType(QueryType.NONE); + queryFieldList.add(queryField); + } + } + BEAN_QUERY_FIELD.put(className,queryFieldList); + if(queryFieldList.size()==0){ + log.warn("无匹配的注解字段,类名:"+className); + } + } + return queryFieldList; + } + + /** + * 处理查询列 + * @param queryType + * @param field + * @return + */ + private static QueryFieldData handleQueryField(QueryType queryType, Field field){ + String columnName = null; + if(queryType!=null){ + QueryFieldData queryField = new QueryFieldData(); + if(StringUtils.isEmpty(columnName)){ + columnName = WordUtil.toLine(field.getName()); + } + queryField.setFieldName(field.getName()); + queryField.setColumnName(columnName); + queryField.setField(field); + queryField.setType(queryType); + return queryField; + } + return null; + } + + + /** + * 加载查询对象生成配置值 + * @param query + * @return + */ + protected static List loadQueryFieldDataValues(Object query){ + String className = query.getClass().getName(); + List dataList = AnnotationQueryStorage.getQueryFieldList(className); + if(!CollectionUtils.isEmpty(dataList)){ + List valueList = new ArrayList<>(); + for (QueryFieldData fieldData : dataList) { + Field field = fieldData.getField(); + field.setAccessible(true); + Object value = null; + try { + value = field.get(query); + } catch (IllegalAccessException e) { + log.warn("查询类字段参数异常。查询类:{},字段:{}",className,field.getName()); + } + if(value!=null){ + QueryFieldDataValue dataValue = new QueryFieldDataValue(fieldData); + //通过列条件,重新赋值(赋值查询条件和格式) + dataValue.setValue(value); + valueList.add(dataValue); + } + } + return valueList; + } + return null; + } + + /** + * 初始化封装包参数 + * @param fieldValues + * @param queryWrapper + * @param + * @return 判断是否排序 + */ + protected static void initWrap(List fieldValues, QueryWrapper queryWrapper){ + for (QueryFieldDataValue fieldValue : fieldValues) { + QueryType queryType = fieldValue.getType(); + Object value = fieldValue.getValue(); + String column = fieldValue.getColumnName(); + if(queryType.equals(QueryType.EQ)){ queryWrapper.eq(column,value); } + if(queryType.equals(QueryType.GE)){ queryWrapper.ge(column,value); } + if(queryType.equals(QueryType.GT)){ queryWrapper.gt(column,value); } + if(queryType.equals(QueryType.In)){ queryWrapper.in(column,value); } + if(queryType.equals(QueryType.LE)){ queryWrapper.le(column,value); } + if(queryType.equals(QueryType.Like)){ queryWrapper.like(column,value); } + if(queryType.equals(QueryType.LT)){ queryWrapper.lt(column,value); } + if(queryType.equals(QueryType.NE)){ queryWrapper.ne(column,value); } + if(queryType.equals(QueryType.RightLike)){ queryWrapper.likeRight(column,value); } + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java new file mode 100644 index 0000000..96cc08f --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java @@ -0,0 +1,32 @@ +package com.qs.serve.common.framework.mybatis.query.annotations; + +import com.qs.serve.common.framework.mybatis.query.model.QueryType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author JcYen + * @date 2020/5/26 + * SQL In条件注解 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface QueryWrap { + + /** + * 列名(默认为空字符串) + * 空字符串,采用字段转列策略 示例: userInfo -> user_info + * 非空时,采用列的值 + */ + String value() default ""; + + /** + * 查询类型(默认采用值相对) + */ + QueryType type() default QueryType.EQ; + +} + diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java new file mode 100644 index 0000000..1654861 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java @@ -0,0 +1,23 @@ +package com.qs.serve.common.framework.mybatis.query.model; + +import lombok.Getter; +import lombok.Setter; + +import java.lang.reflect.Field; + +/** + * 存储DTO + * @author JcYen + * @Date 2017/10/28 + * @Version 1.0 + */ +@Getter +@Setter +public class QueryFieldData { + + private Field field; + private QueryType type; + private String columnName; + private String fieldName; + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java new file mode 100644 index 0000000..718b176 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.framework.mybatis.query.model; + +import com.qs.serve.common.util.CopierUtil; +import lombok.Getter; +import lombok.Setter; + +/** + * 存储DTO + * @author JcYen + * @Date 2017/10/28 + * @Version 1.0 + */ +@Getter +@Setter +public class QueryFieldDataValue{ + + public QueryFieldDataValue(QueryFieldData data){ + CopierUtil.copy(data,this); + } + + private QueryType type; + private String columnName; + private String fieldName; + private Object value; +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java new file mode 100644 index 0000000..d32cd45 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java @@ -0,0 +1,40 @@ +package com.qs.serve.common.framework.mybatis.query.model; + +/** + * @author JcYen + */ +public enum QueryType { + + /** + * 无 + */ + NONE, + + /** + * 通用的equals(Integer,Long,String) + */ + EQ, + NE, + + /** + * 比较修饰符,修饰日期,数值类型(Integer,Long,Double,BigDecimal) + */ + LT, + LE, + GT, + GE, + + /** + * 修饰List + */ + In, + NotIn, + + /** + * 修饰字符串 + */ + Like, + RightLike, + NotLike, + +} diff --git a/src/main/java/com/qs/serve/common/framework/redis/RedisService.java b/src/main/java/com/qs/serve/common/framework/redis/RedisService.java new file mode 100644 index 0000000..b4f51e8 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/redis/RedisService.java @@ -0,0 +1,395 @@ +package com.qs.serve.common.framework.redis; + +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.stereotype.Service; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @author JcYen + * @since 2022/3/4 + */ +@Service +@AllArgsConstructor +public class RedisService { + + @Bean + @Primary + public RedisCacheManager selfCacheManager(RedisTemplate redisTemplate) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()); + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer())); + return new TtlRedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + + private RedisTemplate redisTemplate; + + private StringRedisTemplate stringRedisTemplate; + + /** + * 加锁 + * @param theme + * @param id + * @return 是否在锁 + */ + public void throwResLock(String theme,String id){ + String key = "LOCK_RES:"+theme+":"+id; + String value = this.getString(key); + System.out.println("throwResLock:"+value); + String newVal = "lock"; + if(newVal.equals(value)){ + Assert.throwEx("服务正在处理,请稍后再试"); + } + this.set(key,newVal,10,TimeUnit.MINUTES); + String value2 = this.getString(key); + if(!newVal.equals(value2)){ + Assert.throwEx("锁失效"); + } + AuthContextUtils.setLockTheme(key); + } + + /** + * 释放锁 + * @param theme + * @param id + * @return 是否在锁 + */ + public void removeResLock(String theme,String id){ + String key = "LOCK_RES:"+theme+":"+id; + this.remove(key); + } + + + /** + * 写入缓存 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value) { + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + result = true; + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 写入缓存设置时效时间 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value, int expireTime) { + return set(key, value, expireTime,TimeUnit.SECONDS); + } + + /** + * 写入缓存设置时效时间 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value, int expireTime,TimeUnit unit) { + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + redisTemplate.expire(key, expireTime, unit); + result = true; + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 批量删除对应的value + * + * @param keys + */ + public void remove(final String... keys) { + for (String key : keys) { + remove(key); + } + } + + /** + * 批量删除key + * + * @param pattern + */ + public void removePattern(final String pattern) { + Set keys = redisTemplate.keys(pattern); + if (keys.size() > 0) + redisTemplate.delete(keys); + } + + /** + * 删除对应的value + * + * @param key + */ + public void remove(final String key) { + if (exists(key)) { + redisTemplate.delete(key); + } + } + + /** + * 判断缓存中是否有对应的value + * + * @param text + * @return + */ + public Set list(final String text) { + Set keySet = redisTemplate.keys("*" + text + "*"); + for (String key : keySet) { + System.out.println(key); + } + return keySet; + } + + + /** + * 获取所有数据 + * + * @return + */ + public Set list() { + Set keySet = redisTemplate.keys("*" + "#" +"*"); + for (String key : keySet) { + System.out.println(key); + } + return keySet; + } + + + /** + * 判断缓存中是否有对应的value + * + * @param text + * @return + */ + public void removeForLike(final String text) { + Set keySet = redisTemplate.keys("*" + text + "*"); + Iterator it = keySet.iterator(); + while(it.hasNext()){ + redisTemplate.delete(it.next()); + } + } + + + public Map cleanRedis() { + Map map = new HashMap<>(); + try { + // 获取所有key + Set keys = redisTemplate.keys("*"); + assert keys != null; + // 迭代 + Iterator it1 = keys.iterator(); + while (it1.hasNext()) { + // 循环删除 + stringRedisTemplate.delete(it1.next()); + } + map.put("code", 1); + map.put("msg", "清理全局缓存成功"); + return map; + } catch (Exception e) { + map.put("code", -1); + map.put("msg", "清理全局缓存失败"); + return map; + } + } + + + /** + * 判断缓存中是否有对应的value + * + * @param key + * @return + */ + public boolean exists(final String key) { + return redisTemplate.hasKey(key); + } + + /** + * 读取缓存 + * + * @param key + * @return + */ + public Object get(final String key) { + Object result = null; + ValueOperations operations = redisTemplate.opsForValue(); + result = operations.get(key); + return result; + } + + public String getString(final String key) { + Object result = null; + ValueOperations operations = redisTemplate.opsForValue(); + result = operations.get(key); + if(result!=null){ + return result.toString(); + + } + return null; + } + + public Integer getInteger(final String key) { + String result = getString(key); + if(result!=null){ + return Integer.parseInt(result); + } + return null; + } + + public Long getLong(final String key) { + String result = getString(key); + if(result!=null){ + return Long.parseLong(result); + } + return null; + } + + /** + * 哈希 添加 + * + * @param key + * @param hashKey + * @param value + */ + public void hmSet(String key, Object hashKey, Object value) { + HashOperations hash = redisTemplate.opsForHash(); + hash.put(key, hashKey, value); + } + + /** + * 哈希获取数据 + * + * @param key + * @param hashKey + * @return + */ + public Object hmGet(String key, Object hashKey) { + HashOperations hash = redisTemplate.opsForHash(); + return hash.get(key, hashKey); + } + + /** + * 列表添加 + * + * @param k + * @param v + */ + public void lPush(String k, Object v) { + ListOperations list = redisTemplate.opsForList(); + list.rightPush(k, v); + } + + /** + * 列表获取 + * + * @param k + * @param l + * @param l1 + * @return + */ + public List lRange(String k, long l, long l1) { + ListOperations list = redisTemplate.opsForList(); + return list.range(k, l, l1); + } + + /** + * 集合添加 + * + * @param key + * @param value + */ + public void add(String key, Object value) { + SetOperations set = redisTemplate.opsForSet(); + set.add(key, value); + } + + /** + * 集合获取 + * + * @param key + * @return + */ + public Set setMembers(String key) { + SetOperations set = redisTemplate.opsForSet(); + return set.members(key); + } + + /** + * 有序集合添加 + * + * @param key + * @param value + * @param scoure + */ + public void zAdd(String key, Object value, double scoure) { + ZSetOperations zset = redisTemplate.opsForZSet(); + zset.add(key, value, scoure); + } + + /** + * 有序集合获取 + * + * @param key + * @param scoure + * @param scoure1 + * @return + */ + public Set rangeByScore(String key, double scoure, double scoure1) { + ZSetOperations zset = redisTemplate.opsForZSet(); + return zset.rangeByScore(key, scoure, scoure1); + } + + /** + * 移除业务锁 + * @param code + * @param targetId + */ + public void removeLock(String code,String targetId){ + String key = "lock_commit:"+code+":"+targetId; + this.remove(key); + } + + /** + * 锁 + * @param code + * @param targetId + * @return true--新建锁成功,false反之 + */ + public boolean tryToLock(String code,String targetId){ + String key = "lock_commit:"+code+":"+targetId; + Integer existState = getInteger(key); + if(existState==null){ + this.set(key,1,20,TimeUnit.SECONDS); + return true; + }else { + return false; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/redis/TtlRedisCacheManager.java b/src/main/java/com/qs/serve/common/framework/redis/TtlRedisCacheManager.java new file mode 100644 index 0000000..53ffc9b --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/redis/TtlRedisCacheManager.java @@ -0,0 +1,30 @@ +package com.qs.serve.common.framework.redis; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.cache.RedisCache; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.util.StringUtils; + +import java.time.Duration; + +@Slf4j +public class TtlRedisCacheManager extends RedisCacheManager { + public TtlRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) { + super(cacheWriter, defaultCacheConfiguration); + } + + @Override + protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) { + log.debug("TtlRedisCacheManager keyName:{}",name); + String[] cells = StringUtils.delimitedListToStringArray(name, "="); + name = cells[0]; + if (cells.length > 1) { + long ttl = Long.parseLong(cells[1]); + // 根据传参设置缓存失效时间,默认单位是秒 + cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl)); + } + return super.createRedisCache(name, cacheConfig); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java b/src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java new file mode 100644 index 0000000..7ff0120 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java @@ -0,0 +1,205 @@ +package com.qs.serve.common.framework.security.filter; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.config.properties.AuthUrlConst; +import com.qs.serve.common.config.properties.PermitProperties; +import com.qs.serve.common.config.properties.ProjectProperties; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserDTO; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.common.util.JwtUtils; +import com.qs.serve.common.framework.security.util.SecurityPermitUtil; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; + +/** + * 判断token情况 + * @Author JcYen + * @Date 2022/03/01 + * @Version 1.0 + */ +@Slf4j +@Component +public class SecurityRequestFilter extends OncePerRequestFilter { + + @Value("${server.servlet.context-path}") + public String contextPath; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private PermitProperties permitProperties; + + @Autowired + private RedisService redisService; + + @Autowired + private ProjectProperties projectProperties; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + + String supplierId = request.getHeader(GySysConst.SUPPLIER_PROP); + AuthContextUtils.setSupplierId(supplierId); + //移除前缀 + String url = request.getRequestURI(); + if(!StringUtils.isEmpty(contextPath)&&!contextPath.equals("/")){ + url = url.replace(contextPath,""); + } + //分析拦截类型 + boolean ignorePermit = false; + for(String reg : permitProperties.getPermits()){ + if(SecurityPermitUtil.verify(reg,url)){ + ignorePermit=true; + break; + } + } + //分析拦截类型 + boolean ignoreTenant = false; + for(String reg : permitProperties.getTenants()){ + if(SecurityPermitUtil.verify(reg,url)){ + ignoreTenant = true; + break; + } + } + response.setHeader("Access-Control-Allow-Origin", "*"); + //登录拦截 + if ("OPTIONS".equals(request.getMethod())) { + HttpResponsePrintUtil.print(response,200,"success"); + return; + } + if(!ignoreTenant){ + boolean hasTenant = handleTenant(request,response); + if(!hasTenant){ + return; + } + } + if(projectProperties.getCloseAuth()!=null && projectProperties.getCloseAuth().equals("true")){ + for (String allowUrl : AuthUrlConst.AUTH_ALLOW_URL) { + if(url.contains(allowUrl)){ + doSecurityAuthor(false,request, response, chain); + } + } + }else { + if(ignorePermit){ + //try to doSecurityAuthor + tryDoSecurityAuthor(request, response, chain); + chain.doFilter(request,response); + }else { + doSecurityAuthor(true,request, response, chain); + } + } + } + + /** + * 尝试执行登录 + * @param request + * @param response + * @param chain + * @throws IOException + * @throws ServletException + */ + private void tryDoSecurityAuthor(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + + String tenant = request.getHeader(GySysConst.TENANT_PROP); + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + if(tenant!=null&&token!=null&&JwtUtils.verify(token)){ + String userId = JwtUtils.getUserId(token); + AuthContextUtils.setTenant(tenant); + if(SecurityContextHolder.getContext().getAuthentication()==null){ + UserDetails userDetails = sysUserService.getLoginUserById(userId); + if(userDetails!=null){ + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + } + + + /** + * 执行登录 + * @param request + * @param response + * @param chain + * @throws IOException + * @throws ServletException + */ + private void doSecurityAuthor(boolean checkRedis,HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + if(!JwtUtils.verify(token)){ + HttpResponsePrintUtil.print2(response,401,"身份凭证无效或过期"); + }else{ + String userId = JwtUtils.getUserId(token); + String userType = JwtUtils.getUserType(token); + String client = JwtUtils.getClient(token); + if(checkRedis){ + String redisKey = com.qs.serve.common.util.StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,userId); + String cacheToken = redisService.getString(redisKey); + if(cacheToken==null){ + //redisService.remove(redisKey); + HttpResponsePrintUtil.print2(response,401,"已被系统登出"); + //return解决:security.access.AccessDeniedException + return; + } + } + if(SecurityContextHolder.getContext().getAuthentication()==null){ + UserDetails userDetails = sysUserService.getLoginUserById(userId); + if(userDetails==null){ + HttpResponsePrintUtil.print2(response,401,"登录信息无效,请重新登录"); + //return解决:security.access.AccessDeniedException + return; + }else { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + chain.doFilter(request, response); + } + } + + /** + * 多租户模式下使用 + * @param request + * @param response + * @throws IOException + * @throws ServletException + */ + private boolean handleTenant(HttpServletRequest request, HttpServletResponse response) throws IOException{ + String tenant = request.getHeader(GySysConst.TENANT_PROP); + if (tenant != null) { + AuthContextUtils.setTenant(tenant); + return true; + }else{ + log.error("商户信息错误,请求地址:{}",request.getRequestURI()); + HttpResponsePrintUtil.print2(response,4001,"商户信息错误"); + return false; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java new file mode 100644 index 0000000..eae472a --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java @@ -0,0 +1,22 @@ +package com.qs.serve.common.framework.security.handler; + +import com.qs.serve.common.model.HttpResponsePrintUtil; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2022/3/3 + */ +public class SecurityAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + HttpResponsePrintUtil.print(response,403,"权限不足"); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java new file mode 100644 index 0000000..fa5cef6 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java @@ -0,0 +1,22 @@ +package com.qs.serve.common.framework.security.handler; + +import com.qs.serve.common.model.HttpResponsePrintUtil; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2022/3/3 + */ +public class SecurityAuthenticationFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException { + HttpResponsePrintUtil.print(response,401,"登录信息已过期或失效"); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java new file mode 100644 index 0000000..5d1f017 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.security.handler; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutHandler; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2021/12/22 + */ +public class SecurityLogoutHandler implements LogoutHandler { + + + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + SysUserMapper sysUserMapper = SpringUtils.getBean(SysUserMapper.class); + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + sysUserMapper.updateYmTokenInt(loginUser.getUserId(),"#","#"); + } + try { + HttpResponsePrintUtil.print(response,200,"退出登录成功"); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java b/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java new file mode 100644 index 0000000..4744121 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java @@ -0,0 +1,97 @@ +package com.qs.serve.common.framework.security.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户登录信息 + * @author YenHex + * @since 2022/3/1 + */ +@Data +@AllArgsConstructor +public class LoginUser implements UserDetails { + + private String userId; + + private String nick; + + private String password; + + private String loginIp; + + /** 用户类型 */ + private LoginUserType typeFlag; + + private List authorList; + private List authorIds; + + private String tenant; + + @Override + public Collection getAuthorities() { + if(authorList!=null&&authorList.size()>0){ + return authorList + .stream() + .filter(n->n.length()>0) + .map(auth->new SimpleGrantedAuthority("ROLE_"+auth)) + .collect(Collectors.toList()); + } + return Collections.singletonList(new SimpleGrantedAuthority("NOT_ROLE")); + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return userId; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + public LoginUserDTO loginUserDTO(){ + return new LoginUserDTO(userId,nick,password,loginIp,typeFlag.getCode(),authorList,authorIds,tenant); + } + + public boolean verifyRole(String permitCode){ + return authorList.contains(permitCode); + } + + /** + * 是否拥有招生超管权限 + * @return + */ + public boolean hasRegSuperRole(){ + return verifyRole("edu:reg:admin"); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java new file mode 100644 index 0000000..2c847ca --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java @@ -0,0 +1,37 @@ +package com.qs.serve.common.framework.security.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 用户登录信息 + * @author YenHex + * @since 2022/3/1 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class LoginUserDTO { + + private String userId; + + private String nick; + + private String password; + + private String loginIp; + + private String typeFlagCode; + + private List authorList; + private List authorIds; + private String tenant; + + public LoginUser loginUser(){ + return new LoginUser(userId,nick,password,loginIp,LoginUserType.getByCode(typeFlagCode),authorList,authorIds,tenant); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java new file mode 100644 index 0000000..8538e03 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java @@ -0,0 +1,34 @@ +package com.qs.serve.common.framework.security.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Getter +@AllArgsConstructor +public enum LoginUserType { + + /** + * 人员分类 + */ + APP_USER("00","微信用户"), + SYS_USER("01","系统人员"), + SYS_SUP_USER("02","超级管理员") + ; + + private String code; + private String name; + + public static LoginUserType getByCode(String code){ + for (LoginUserType value : LoginUserType.values()) { + if(value.getCode().equals(code)){ + return value; + } + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java b/src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java new file mode 100644 index 0000000..a32d674 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java @@ -0,0 +1,31 @@ +package com.qs.serve.common.framework.security.service; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +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; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Service +@AllArgsConstructor +public class SysUserDetailsServiceImpl implements UserDetailsService { + + private final SysUserService sysUserService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return sysUserService.getLoginUserByAccount(username); + } + + public LoginUser buildLoginUser(SysUser sysUser){ + return sysUserService.buildLoginUser(sysUser); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java b/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java new file mode 100644 index 0000000..b03fac8 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.framework.security.util; + +/** + * @Author JcYen + * @Date 2021/9/24 + * @Version 1.0 + */ +public class SecurityPermitUtil { + + public static boolean verify(String reg, String input){ + if ("/*".equals(reg)) return true; + String[] reg_split = reg.split("\\*"); + int index = 0, reg_len = reg_split.length; + boolean b = reg.charAt(reg.length() - 1) == '*' ? true : false; + while (input.length() > 0) { + if (index == reg_len) { + if (b) return true; + else return false; + } + String r = reg_split[index++]; + int indexOf = input.indexOf(r); + if (indexOf != 0) return false; + input = input.substring(indexOf + r.length()); + } + return true; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/AmountDTO.java b/src/main/java/com/qs/serve/common/model/AmountDTO.java new file mode 100644 index 0000000..b663b89 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/AmountDTO.java @@ -0,0 +1,18 @@ +package com.qs.serve.common.model; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author YenHex + * @since 2023/7/31 + */ +@Data +public class AmountDTO { + + private String id; + + private BigDecimal amount; + +} diff --git a/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java b/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java new file mode 100644 index 0000000..9aa883d --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java @@ -0,0 +1,34 @@ +package com.qs.serve.common.model; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2022/3/30 + */ +public class HttpResponsePrintUtil { + + public static void print(HttpServletResponse response,Integer code ,String msg) throws IOException,SecurityException{ + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS"); + response.setHeader("Access-Control-Max-Age", "86400"); + response.setHeader("Access-Control-Allow-Headers", "*"); + response.setStatus(200); + response.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().print("{\"status\":"+code+",\"msg\":\""+msg+"\"}"); + response.getWriter().flush(); + } + + public static void print2(HttpServletResponse response,Integer code ,String msg)throws IOException,SecurityException{ + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().print("{\"status\":"+code+",\"msg\":\""+msg+"\"}"); + response.getWriter().flush(); + } + + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/BusinessDifference.java b/src/main/java/com/qs/serve/common/model/annotation/BusinessDifference.java new file mode 100644 index 0000000..394d592 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/BusinessDifference.java @@ -0,0 +1,20 @@ +package com.qs.serve.common.model.annotation; + +import java.lang.annotation.*; + +/** + * @author YenHex + * @since 2023/4/25 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface BusinessDifference { + + /** + * 字段备注 + * @return + */ + String value() default ""; + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java b/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java new file mode 100644 index 0000000..8ec4ce5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.model.annotation; + +import java.lang.annotation.*; + +/** + * 防止表单重复提交 + * @author YenHex + * @since 2022-03-01 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface LimitSubmit { + + /** + * 间隔时间(ms),在世界间隔内超过执行次数,视为被限制 + */ + int interval() default 1000; + + /** + * 提示消息 + */ + String message() default ""; + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java b/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java new file mode 100644 index 0000000..5bd1eba --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java @@ -0,0 +1,20 @@ +package com.qs.serve.common.model.annotation; + +/** + * 防止表单重复提交 + * @author YenHex + * @since 2022-03-01 + */ +public @interface RepeatSubmit { + + /** + * 间隔时间(ms),小于此时间视为重复提交 + */ + int interval() default 5000; + + /** + * 提示消息 + */ + String message() default "不允许重复提交,请稍后再试"; + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/SysLog.java b/src/main/java/com/qs/serve/common/model/annotation/SysLog.java new file mode 100644 index 0000000..cb30b55 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/SysLog.java @@ -0,0 +1,35 @@ +package com.qs.serve.common.model.annotation; + +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.model.enums.SystemModule; + +import java.lang.annotation.*; + +/** + * 记录用户登录操作 + * @author YenHex + * @since 2022-03-01 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SysLog { + + SystemModule module() default SystemModule.SYSTEM; + + /** 业务标题 */ + String title() default ""; + + /** 操作描述 */ + String desc() default ""; + + /** 操作类型 */ + BizType biz() default BizType.OTHER; + + /** 接口类型 */ + InterType inter() default InterType.ADMIN; + + boolean saveReqParam() default true; + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/BiCommonCounter.java b/src/main/java/com/qs/serve/common/model/chart/BiCommonCounter.java new file mode 100644 index 0000000..3403a26 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/BiCommonCounter.java @@ -0,0 +1,19 @@ +package com.qs.serve.common.model.chart; + +import lombok.Data; + +/** + * @author YenHex + * @since 2023/6/7 + */ +@Data +public class BiCommonCounter { + + /** + * 横轴下标的ID + */ + private String label; + + private Long counts; + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/BiMonthCounter.java b/src/main/java/com/qs/serve/common/model/chart/BiMonthCounter.java new file mode 100644 index 0000000..ed23bea --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/BiMonthCounter.java @@ -0,0 +1,15 @@ +package com.qs.serve.common.model.chart; + +import lombok.Data; + +/** + * @author YenHex + * @since 2023/6/7 + */ +@Data +public class BiMonthCounter { + + private String months; + private Long counts; + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/ChartAxisColumn.java b/src/main/java/com/qs/serve/common/model/chart/ChartAxisColumn.java new file mode 100644 index 0000000..3f01cb9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/ChartAxisColumn.java @@ -0,0 +1,39 @@ +package com.qs.serve.common.model.chart; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2023/6/7 + */ +@Data +public class ChartAxisColumn { + + /** 列Id */ + String columnId; + + /** 列名 */ + String columnName; + + /** 系列坐标值合计 */ + Double total; + + public static List buildMonthsOfYear(){ + List axisColumnList = new ArrayList<>(); + for (long i = 1; i < 13; i++) { + ChartAxisColumn axisColumn = new ChartAxisColumn(); + if(i>9){ + axisColumn.setColumnId(i+""); + }else { + axisColumn.setColumnId("0"+i); + } + axisColumn.setColumnName(i+"月"); + axisColumnList.add(axisColumn); + } + return axisColumnList; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/ChartDataVo.java b/src/main/java/com/qs/serve/common/model/chart/ChartDataVo.java new file mode 100644 index 0000000..7346a6f --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/ChartDataVo.java @@ -0,0 +1,148 @@ +package com.qs.serve.common.model.chart; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author YenHex + * @since 2023/6/7 + */ +@Data +public class ChartDataVo { + + /** + * 列(饼状图的主要参数) + */ + List axisColumnList; + + /** + * 系列 + */ + List seriesItemList; + + /** + * 分组 + */ + List groupItemList; + + + public void initAxisColumnTotal(){ + for (int i = 0; i < axisColumnList.size(); i++) { + ChartAxisColumn axisColumn = axisColumnList.get(i); + BigDecimal total = BigDecimal.ZERO; + if(seriesItemList!=null&&seriesItemList.size()>0){ + for (ChartSeriesItem seriesItem : seriesItemList) { + double value = seriesItem.getValues().get(i); + total = total.add(new BigDecimal(value+"")); + } + } + axisColumn.setTotal(total.doubleValue()); + } + } + + public static ChartDataVo buildStateChartData(List stateCounterList, Map stateMap){ + ChartDataVo chartDataVo = new ChartDataVo(); + List axisColumnList = new ArrayList<>(); + List seriesItemList = new ArrayList<>(); + List groupItemList = new ArrayList<>(); + ChartGroupItem groupItem = new ChartGroupItem(); + groupItem.setGroupId(100L); + groupItem.setGroupName("默认"); + groupItemList.add(groupItem); + for (String stateNum : stateMap.keySet()) { + String label = stateMap.get(stateNum); + ChartAxisColumn axisColumn = new ChartAxisColumn(); + axisColumn.setColumnId(stateNum); + axisColumn.setColumnName(label); + axisColumnList.add(axisColumn); + } + List values = new ArrayList<>(); + for (ChartAxisColumn chartAxisColumn : axisColumnList) { + Double currVal = 0.0; + for (BiCommonCounter counter : stateCounterList) { + if(chartAxisColumn.getColumnId().equals(counter.getLabel())){ + currVal = counter.getCounts().doubleValue(); + break; + } + } + values.add(currVal); + } + ChartSeriesItem seriesItem = new ChartSeriesItem(); + seriesItem.setGroupId(groupItem.getGroupId()); + seriesItem.setGroupName(groupItem.getGroupName()); + seriesItem.setValues(values); + seriesItemList.add(seriesItem); + //更新total + chartDataVo.setAxisColumnList(axisColumnList); + chartDataVo.setGroupItemList(groupItemList); + chartDataVo.setSeriesItemList(seriesItemList); + chartDataVo.initAxisColumnTotal(); + return chartDataVo; + } + + public void tes(){ + + } + + public void buildStateMap(Map stateMap){ + init(); + for (String stateNum : stateMap.keySet()) { + String label = stateMap.get(stateNum); + ChartAxisColumn axisColumn = new ChartAxisColumn(); + axisColumn.setColumnId(stateNum); + axisColumn.setColumnName(label); + this.axisColumnList.add(axisColumn); + } + } + public void buildStateMapOfMonths(){ + init(); + this.axisColumnList = ChartAxisColumn.buildMonthsOfYear(); + } + + /** + * 先调用buildStateMap + * @param groupId + * @param groupName + * @param stateCounterList + */ + public void addData(Long groupId,String groupName,List stateCounterList){ + ChartGroupItem groupItem = new ChartGroupItem(); + groupItem.setGroupId(groupId); + groupItem.setGroupName(groupName); + groupItemList.add(groupItem); + List values = new ArrayList<>(); + for (ChartAxisColumn chartAxisColumn : axisColumnList) { + Double currVal = 0.0; + for (BiCommonCounter counter : stateCounterList) { + if(chartAxisColumn.getColumnId().equals(counter.getLabel())){ + currVal = counter.getCounts().doubleValue(); + break; + } + } + values.add(currVal); + } + ChartSeriesItem seriesItem = new ChartSeriesItem(); + seriesItem.setGroupId(groupItem.getGroupId()); + seriesItem.setGroupName(groupItem.getGroupName()); + seriesItem.setValues(values); + seriesItemList.add(seriesItem); + this.initAxisColumnTotal(); + } + + private void init(){ + if(axisColumnList==null){ + axisColumnList = new ArrayList<>(); + } + if(seriesItemList==null){ + seriesItemList = new ArrayList<>(); + } + if(groupItemList==null){ + groupItemList = new ArrayList<>(); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/ChartGroupItem.java b/src/main/java/com/qs/serve/common/model/chart/ChartGroupItem.java new file mode 100644 index 0000000..6dc51d2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/ChartGroupItem.java @@ -0,0 +1,18 @@ +package com.qs.serve.common.model.chart; + +import lombok.Data; + +/** + * @author YenHex + * @since 2023/6/7 + */ +@Data +public class ChartGroupItem { + + /** 组id */ + private Long groupId; + + /** 组名 */ + private String groupName; + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/ChartSeriesItem.java b/src/main/java/com/qs/serve/common/model/chart/ChartSeriesItem.java new file mode 100644 index 0000000..0e5e99e --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/ChartSeriesItem.java @@ -0,0 +1,26 @@ +package com.qs.serve.common.model.chart; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2023/6/7 + */ +@Data +public class ChartSeriesItem { + + + /** 组id */ + Long groupId; + + /** 组名 */ + String groupName; + + /** + * 值列表(列对应axisColumns) + */ + List values; + +} diff --git a/src/main/java/com/qs/serve/common/model/chart/PrintChart.java b/src/main/java/com/qs/serve/common/model/chart/PrintChart.java new file mode 100644 index 0000000..846aed1 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/chart/PrintChart.java @@ -0,0 +1,75 @@ +package com.qs.serve.common.model.chart; + +import com.qs.serve.common.util.JsonUtil; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * @author YenHex + * @since 2023/2/17 + */ +public class PrintChart { + + + public static void main(String[] args) { + + //eg. 统计最近5年入学人数,并区分男女数量 + ChartDataVo chartDataVo = new ChartDataVo(); + + List axisColumnList = new ArrayList<>(); + List seriesItemList = new ArrayList<>(); + List groupItemList = new ArrayList<>(); + + ChartGroupItem groupItem = new ChartGroupItem(); + groupItem.setGroupId(100L); + groupItem.setGroupName("男学生"); + groupItemList.add(groupItem); + + ChartGroupItem groupItem2 = new ChartGroupItem(); + groupItem2.setGroupId(200L); + groupItem2.setGroupName("女学生"); + groupItemList.add(groupItem2); + + for (long i = 1; i <= 5; i++) { + ChartAxisColumn axisColumn = new ChartAxisColumn(); + axisColumn.setColumnId(i+""); + axisColumn.setColumnName("202"+i+"年"); + axisColumnList.add(axisColumn); + } + + Random random = new Random(); + for (ChartGroupItem chartGroupItem : groupItemList) { + ChartSeriesItem seriesItem = new ChartSeriesItem(); + seriesItem.setGroupId(chartGroupItem.getGroupId()); + seriesItem.setGroupName(chartGroupItem.getGroupName()); + List values = new ArrayList<>(); + for (int i = 0; i < axisColumnList.size(); i++) { + double result = random.nextInt(1000)+3000; + values.add(result); + } + seriesItem.setValues(values); + seriesItemList.add(seriesItem); + } + //更新total + for (int i = 0; i < axisColumnList.size(); i++) { + ChartAxisColumn axisColumn = axisColumnList.get(i); + BigDecimal total = BigDecimal.ZERO; + for (ChartSeriesItem seriesItem : seriesItemList) { + double value = seriesItem.getValues().get(i); + total = total.add(new BigDecimal(value+"")); + } + axisColumn.setTotal(total.doubleValue()); + } + chartDataVo.setAxisColumnList(axisColumnList); + chartDataVo.setGroupItemList(groupItemList); + chartDataVo.setSeriesItemList(seriesItemList); + String v = JsonUtil.objectToJson(chartDataVo); + System.out.println(v); + } + + + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/ApplyTypeConst.java b/src/main/java/com/qs/serve/common/model/consts/ApplyTypeConst.java new file mode 100644 index 0000000..9a4a958 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/ApplyTypeConst.java @@ -0,0 +1,13 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2023/9/19 + */ +public interface ApplyTypeConst { + + String CostBill = "CostBill"; + String CheckCost = "CheckCost"; + String ReleasePolicy = "ReleasePolicy"; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/BudgetLogRollbackFlag.java b/src/main/java/com/qs/serve/common/model/consts/BudgetLogRollbackFlag.java new file mode 100644 index 0000000..4d5772c --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/BudgetLogRollbackFlag.java @@ -0,0 +1,21 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2023/1/30 + */ +public interface BudgetLogRollbackFlag { + + /** 正常(标记为最新记录) */ + Integer State_0 = 0; + + /** 回退 */ + Integer State_1 = 1; + + /** 回退已处理 */ + Integer State_2 = 2; + + /** 删除已处理 */ + Integer State_3 = 3; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/DSName.java b/src/main/java/com/qs/serve/common/model/consts/DSName.java new file mode 100644 index 0000000..bd74fcd --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/DSName.java @@ -0,0 +1,11 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2024/3/20 + */ +public interface DSName { + + String QiSheng = "qisheng"; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/DateConst.java b/src/main/java/com/qs/serve/common/model/consts/DateConst.java new file mode 100644 index 0000000..6cf1d01 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/DateConst.java @@ -0,0 +1,10 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/2/24 + */ +public class DateConst { + + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/GySysConst.java b/src/main/java/com/qs/serve/common/model/consts/GySysConst.java new file mode 100644 index 0000000..23f36f3 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/GySysConst.java @@ -0,0 +1,41 @@ +package com.qs.serve.common.model.consts; + +/** + * 系统字段 + * @author YenHex + * @since 2022/2/24 + */ +public class GySysConst { + + /** 后台身份验证 */ + public static final String AUTHORIZATION_PROP = "Authorization"; + + /** API身份验证 */ + public static final String APP_TOKEN_PROP = "token"; + + /** 请求头参数 */ + public static final String USER_AGENT_PROP = "User-Agent"; + + public static final String TENANT_PROP = "tenant-id"; + public static final String SUPPLIER_PROP = "supplierId"; + + /** 系统租户数据库列 */ + public static final String TENANT_COLUMN = "tenant_id"; + + /** 第三方应用id。如:公众号 */ + public static final String APP_ID_PROP = "appid"; + + /** 通用参数 */ + public static final int STATUS_YES_1 = 1; + public static final int STATUS_NO_1 = 0; + + public static final String LANG_ZH_CN = "zh_CN"; + + + public static final String ROLE_ADMIN_OPT_LOG = "sys:operationLog:admin"; + public static final String ROLE_ADMIN_REG = "edu:reg:admin"; + + public static final String DEFAULT_PASSWORD = "12345678"; + + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/OssConst.java b/src/main/java/com/qs/serve/common/model/consts/OssConst.java new file mode 100644 index 0000000..6a8b2d2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/OssConst.java @@ -0,0 +1,32 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/5/10 + */ +public class OssConst { + + /** + * 访问类型 + */ + public static final String ACCESS_OWNER = "own"; + public static final String ACCESS_DEPT = "dept"; + + /** + * 文件夹前缀 + */ + public static final String OWNER_DIR = "owner/"; + public static final String DEPT_DIR = "dept/"; + public static final String SPLIT = "/"; + + /** + * Tag + */ + public static final String TAG_CREATOR = "creator"; + public static final String TAG_CREATE_BY = "create_by"; + + public static final String FILE_TYPE_DIR = "文件夹"; + + public static final String DIR_TYPE_UNKNOWN = "未知"; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java b/src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java new file mode 100644 index 0000000..de9ac61 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java @@ -0,0 +1,33 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public class RedisCacheKeys { + + public final static String SUPPLIER_RELATE_TREE = "supplier_relate_tree"; + + /** 租户列表 */ + public final static String Tenant_ALL_LIST = "expire_tenant_list"; + + + + /** 用户登录APP {}客户端 {}用户ID */ + public final static String LOGIN_KEY_APP = "login_app_{}:{}:"; + + /** 微信用户ID */ + public final static String WX_KEY_USER = "wx_usr_id:{}:"; + + /** 手机号验证吗 */ + public final static String PHONE_KEY = "phone_code_:"; + + /** + * 0-无需操作 + * 1-未处理 + * 2-同步中 + * 3-同步完成,但未更新表 + */ + public final static String HIS_UPDATE = "update_his_flag:"; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java b/src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java new file mode 100644 index 0000000..26b244d --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java @@ -0,0 +1,12 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public class RedisListenerKeys { + + public final static String EXPIRED_TYPE = "__keyevent@*__:expired"; + + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/ResultFlag.java b/src/main/java/com/qs/serve/common/model/consts/ResultFlag.java new file mode 100644 index 0000000..2641b44 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/ResultFlag.java @@ -0,0 +1,12 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2023/2/15 + */ +public interface ResultFlag { + + int OK = 1; + int NOT = 0; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/SysConfigKey.java b/src/main/java/com/qs/serve/common/model/consts/SysConfigKey.java new file mode 100644 index 0000000..4999b38 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/SysConfigKey.java @@ -0,0 +1,19 @@ +package com.qs.serve.common.model.consts; + +/** + * 系统配置 + * @author YenHex + * @since 2022/11/12 + */ +public interface SysConfigKey { + + /** 费用超支 */ + String TbsBudgetOverspend = "TbsBudgetOverspend"; + + /** 活动预计核销日期 */ + String ActivityPreCheckDays = "ActivityPreCheckDays"; + + String DateCheckApplyExcelYear = "DateCheckApplyExcelYear"; + + String PolicyDelayDays = "PolicyDelayDays"; +} diff --git a/src/main/java/com/qs/serve/common/model/dto/CommonIdsParam.java b/src/main/java/com/qs/serve/common/model/dto/CommonIdsParam.java new file mode 100644 index 0000000..ba8c866 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/CommonIdsParam.java @@ -0,0 +1,16 @@ +package com.qs.serve.common.model.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2024/6/11 + */ +@Data +public class CommonIdsParam { + + private List ids; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/DateSplitDTO.java b/src/main/java/com/qs/serve/common/model/dto/DateSplitDTO.java new file mode 100644 index 0000000..5f84393 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/DateSplitDTO.java @@ -0,0 +1,29 @@ +package com.qs.serve.common.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.util.Date; + +/** + * @author YenHex + * @since 2023/6/5 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DateSplitDTO { + + Integer days; + + LocalDate startDate; + + LocalDate endDate; + + Integer yearMonth; + + Integer sort; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/DiffFieldVal.java b/src/main/java/com/qs/serve/common/model/dto/DiffFieldVal.java new file mode 100644 index 0000000..021bf12 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/DiffFieldVal.java @@ -0,0 +1,17 @@ +package com.qs.serve.common.model.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2023/4/25 + */ +@Data +public class DiffFieldVal { + + String field; + String comment; + String orgValue; + String newValue; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/HeaderOption.java b/src/main/java/com/qs/serve/common/model/dto/HeaderOption.java new file mode 100644 index 0000000..1202829 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/HeaderOption.java @@ -0,0 +1,27 @@ +package com.qs.serve.common.model.dto; + +import com.qs.serve.common.util.PageUtil; +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2023/5/17 + */ +@Data +public class HeaderOption { + + private String name; +// private String width; +// private String prefix; +// private String suffix; + private Boolean isSum; + private Integer decimalLength; + private String align; + private List children; + + public HeaderOption(String name){ + this.name = name; + } +} diff --git a/src/main/java/com/qs/serve/common/model/dto/PageVo.java b/src/main/java/com/qs/serve/common/model/dto/PageVo.java new file mode 100644 index 0000000..c06af13 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/PageVo.java @@ -0,0 +1,56 @@ +package com.qs.serve.common.model.dto; + +import com.qs.serve.common.util.PageUtil; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class PageVo{ + + /** + * 页幅 + */ + private Integer pageSize; + + /** + * 页眉 + */ + private Integer pageNum; + + /** + * 总数据数 + */ + private Long total; + + /** + * 总页数 + */ + private Long totalPage; + + /** + * 数据列表 + */ + private List list; + + public void initPageByTotal(long total){ + this.total = total; + this.pageNum = PageUtil.getPageNum(); + this.pageSize = PageUtil.getPageSize(); + if(pageSize==null||pageSize==0){ return; } + this.totalPage = total%pageSize==0?total/pageSize:(total/pageSize+1); + } + + public static PageVo initNewList(PageVo oldVo,List list){ + PageVo newVo = new PageVo<>(); + newVo.setPageNum(oldVo.getPageNum()); + newVo.setPageSize(oldVo.getPageSize()); + newVo.setTotal(oldVo.getTotal()); + newVo.setTotalPage(oldVo.getTotalPage()); + newVo.setList(list); + return newVo; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/R.java b/src/main/java/com/qs/serve/common/model/dto/R.java new file mode 100644 index 0000000..bf6f27b --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/R.java @@ -0,0 +1,223 @@ +package com.qs.serve.common.model.dto; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.pagehelper.PageInfo; +import com.qs.serve.common.util.PageUtil; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 统一返回封装 + * 1.替代旧版的ViewResult + * 2.支持SmartDoc + * @author JcYen + * @date 2021/4/22 + * @version 2.0 + */ +@Getter +@Setter +public class R implements Serializable { + + public R(int status, String msg) { + this.status = status; + this.msg = msg; + } + + public R(int status, String msg, T data) { + this.status = status; + this.msg = msg; + this.data = data; + } + + /** + * 状态码 + */ + private Integer status; + + /** + * 信息 + */ + private String msg; + + /** + * 数据 + */ + private T data; + + public static final int SUCCESS_STATUS = 200; + public static final int IMPORT_ERROR = 201; + public static final int LOGOUT_STATUS = 401; + public static final int FORBIDDEN_STATUS = 403; + public static final int NOT_FOUND_STATUS = 434; + public static final int FAILED_STATUS = 500; + + public static final String SUCCESS_TIPS = "操作成功"; + public static final String FAILED_TIPS = "操作失败"; + public static final String FAILED_TIPS_2 = "业务操作失败"; + public static final String LOGOUT_TIPS = "登录无效"; + public static final String FORBIDDEN_TIPS = "无权限访问"; + public static final String NOT_FOUND_TIPS = "数据不存在或被移除"; + + public static R ok() { + return new R(SUCCESS_STATUS,SUCCESS_TIPS,null); + } + + public static R ok(String msg) { + return new R<>(SUCCESS_STATUS,msg,null); + } + + public static R ok(TYPE data) { + return new R<>(SUCCESS_STATUS,SUCCESS_TIPS,data); + } + + public static R ok(TYPE data,String message) { + return new R<>(SUCCESS_STATUS,message,data); + } + + public static R isTrue(Boolean bool){ + if(bool==null|| !bool){ + return error(); + } + return ok(); + } + + public static R isTrue(Boolean bool, String message){ + if(bool==null|| !bool){ + return error(message); + } + return ok(null,message); + } + + + public static R isNotNull(TYPE object){ + if(object==null){ + return error(); + } + return ok(object,SUCCESS_TIPS); + } + + public static R isOk(Boolean rs){ + if(rs==null){ + return error(); + } + return ok(); + } + + public static R isOk(Boolean rs,String errMsg){ + if(rs==null){ + return error(errMsg); + } + return ok(); + } + + public static R error(String message) { + return new R<>(FAILED_STATUS,message,null); + } + + public static R errorImport(Object data) { + return new R<>(IMPORT_ERROR,"导入异常",data); + } + + public static R error(String message,TYPE data) { + return new R<>(FAILED_STATUS,FAILED_TIPS,data); + } + + + + public static R error() { + return new R<>(FAILED_STATUS,FAILED_TIPS,null); + } + public static R errorNotFound() { + return new R<>(FAILED_STATUS,NOT_FOUND_TIPS,null); + } + public static R error2() { + return new R<>(FAILED_STATUS,FAILED_TIPS_2,null); + } + + public static R> byMbpList(IPage page){ + PageVo pageVo = new PageVo<>(); + pageVo.initPageByTotal(page.getTotal()); + pageVo.setList(page.getRecords()); + return R.ok(pageVo); + } + + public static R> byMbpList(IPage page,List data){ + PageVo pageVo = new PageVo<>(); + pageVo.initPageByTotal(page.getTotal()); + pageVo.setList(data); + return R.ok(pageVo); + } + + public static R> byPageHelperList(List data){ + return R.ok(buildPageHelperList(data)); + } + + public static PageVo buildPageHelperList(List data){ + PageVo pageVo = new PageVo<>(); + PageInfo pageInfo = new PageInfo<>(data); + pageVo.setPageSize(pageInfo.getPageSize()); + pageVo.setPageNum(pageInfo.getPageNum()); + pageVo.setTotal(pageInfo.getTotal()); + pageVo.setList(data); + pageVo.setTotalPage(new Long(pageInfo.getPages())); + return pageVo; + } + + public static PageVo buildPageHelperList(List sources,List details){ + PageVo pageVo = new PageVo<>(); + PageInfo pageInfo = new PageInfo<>(sources); + pageVo.setPageSize(pageInfo.getPageSize()); + pageVo.setPageNum(pageInfo.getPageNum()); + pageVo.setTotal(pageInfo.getTotal()); + pageVo.setList(details); + pageVo.setTotalPage(new Long(pageInfo.getPages())); + return pageVo; + } + + public static R> byEmptyList(){ + PageVo pageVo = new PageVo<>(); + pageVo.setPageSize(PageUtil.getPageSize()); + pageVo.setPageNum(PageUtil.getPageNum()); + pageVo.setTotal(0L); + pageVo.setList(null); + pageVo.setTotalPage(0L); + return R.ok(pageVo); + } + + public static R> byPageHelperList(List sources,List details){ + PageVo pageVo = new PageVo<>(); + PageInfo pageInfo = new PageInfo<>(sources); + pageVo.setPageSize(pageInfo.getPageSize()); + pageVo.setPageNum(pageInfo.getPageNum()); + pageVo.setTotal(pageInfo.getTotal()); + pageVo.setList(details); + pageVo.setTotalPage(new Long(pageInfo.getPages())); + return R.ok(pageVo); + } + + public static R> byPageList(Integer pageNum,Integer pageSize,Long total,List data){ + PageVo pageVo = new PageVo<>(); + pageVo.setPageSize(pageSize); + pageVo.setPageNum(pageNum); + pageVo.setTotal(total); + pageVo.setList(data); + pageVo.setTotalPage(total%pageSize==0?total/pageSize:total/pageSize+1); + return R.ok(pageVo); + } + + public static R> byPageList(Long total,List data){ + Integer pageNum = PageUtil.getPageNum(); + Integer pageSize = PageUtil.getPageSize(); + PageVo pageVo = new PageVo<>(); + pageVo.setPageSize(pageSize); + pageVo.setPageNum(pageNum); + pageVo.setTotal(total); + pageVo.setList(data); + pageVo.setTotalPage(total%pageSize==0?total/pageSize:total/pageSize+1); + return R.ok(pageVo); + } + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/RowParam.java b/src/main/java/com/qs/serve/common/model/dto/RowParam.java new file mode 100644 index 0000000..a7c491b --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/RowParam.java @@ -0,0 +1,26 @@ +package com.qs.serve.common.model.dto; + +import com.qs.serve.common.util.PageUtil; +import lombok.Data; + +/** + * @author YenHex + * @since 2023/5/17 + */ +@Data +public class RowParam { + + private Integer startIndex; + private Integer size; + + public RowParam(Integer startIndex, Integer size) { + this.startIndex = startIndex; + this.size = size; + } + + public RowParam(boolean pageable) { + this.size = PageUtil.getPageSize(); + this.startIndex = (PageUtil.getPageNum()-1)*size; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/SimpleCountValue.java b/src/main/java/com/qs/serve/common/model/dto/SimpleCountValue.java new file mode 100644 index 0000000..ac9edc2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/SimpleCountValue.java @@ -0,0 +1,16 @@ +package com.qs.serve.common.model.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2024/8/29 + */ +@Data +public class SimpleCountValue { + + String id; + + Long count; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java b/src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java new file mode 100644 index 0000000..b272630 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Data +@AllArgsConstructor +public class SimpleKeyValue { + + /** 键 */ + private String label; + + /** 值 */ + private T value; + + /** 说明 */ + private String remark; + + public SimpleKeyValue(String label,T value){ + this.label = label; + this.value = value; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/TargetDTO.java b/src/main/java/com/qs/serve/common/model/dto/TargetDTO.java new file mode 100644 index 0000000..b4821cb --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/TargetDTO.java @@ -0,0 +1,29 @@ +package com.qs.serve.common.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @author YenHex + * @since 2023/4/7 + */ +@Data +@AllArgsConstructor +public class TargetDTO { + String targetId; + String targetCode; + String targetName; + + public TargetDTO(String targetId, String targetCode, String targetName) { + this.targetId = targetId; + this.targetCode = targetCode; + this.targetName = targetName; + } + + //拜访相关业务 + String localX; + String localY; + String address; + String mapAddress; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/TargetObjectDTO.java b/src/main/java/com/qs/serve/common/model/dto/TargetObjectDTO.java new file mode 100644 index 0000000..86a5254 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/TargetObjectDTO.java @@ -0,0 +1,23 @@ +package com.qs.serve.common.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; + +/** + * @author YenHex + * @since 2023/4/7 + */ +@Data +public class TargetObjectDTO { + + String targetType; + String targetId; + + String targetCode; + String targetName; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/TreeNode.java b/src/main/java/com/qs/serve/common/model/dto/TreeNode.java new file mode 100644 index 0000000..817b8b5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/TreeNode.java @@ -0,0 +1,30 @@ +package com.qs.serve.common.model.dto; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 树节点 + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class TreeNode { + protected String id; + protected String parentId; + private Integer sort; + protected List children = new ArrayList<>(); + + public void addChildren(TreeNode treeNode) { + children.add(treeNode); + } + + public List getChildren() { + if(children==null||children.size()<=0){ + return null; + } + return children; + } +} diff --git a/src/main/java/com/qs/serve/common/model/enums/BizType.java b/src/main/java/com/qs/serve/common/model/enums/BizType.java new file mode 100644 index 0000000..deb1dda --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/BizType.java @@ -0,0 +1,53 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/3/8 + */ +@Getter +@AllArgsConstructor +public enum BizType { + + /** 其它 */ + OTHER("其它"), + + /** 新增 */ + INSERT("新增"), + + /** 修改 */ + UPDATE("修改"), + + /** 删除 */ + DELETE("删除"), + + /** 授权 */ + GRANT("授权"), + + /** 强退 */ + FORCE("强退"), + + /** 清空数据 */ + CLEAN("清空"), + + /** 登录 */ + LOGIN("登录"), + + LOGOUT("登出"), + + UPLOAD("上传"), + + DOWNLOAD("下载"), + + QUERY("查询"), + + LEAVE("离职"), + EXPORT("导出"), + SUBMIT("提交"), + + RESET("重置"); + + String value; +} diff --git a/src/main/java/com/qs/serve/common/model/enums/BudgetLogOptFlag.java b/src/main/java/com/qs/serve/common/model/enums/BudgetLogOptFlag.java new file mode 100644 index 0000000..0f50877 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/BudgetLogOptFlag.java @@ -0,0 +1,91 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author YenHex + * @since 2023/1/30 + */ +@Getter +@AllArgsConstructor +public enum BudgetLogOptFlag { + + /** 0-预算新增 */ + State_0(0,true), + + /** 1-费用申请(费用申请,预算调减) */ + State_1(1,false), + + /** 2-预算调增 */ + State_2(2,true), + + /** 3-预算调减 */ + State_3(3,false), + + /** 4-费用释放(预算调增) */ + State_4(4,true), + + /** 5-费用申请调增(费用申请,预算调增) */ + State_5(5,true), + + /** 6-费用申请调减(费用申请,预算调减) */ + State_6(6,false), + + /** 已取消 7-销售区域迁移调增 */ + State_7(7,false), + + /** 已取消 8-销售区域迁移调减 */ + State_8(8,false), + + /** 已取消 9-行政区域迁移调增 */ + State_9(9,false), + + /** 已取消 10-行政区域迁移调减 */ + State_10(10,false), + + /** 11-政策申请 */ + State_11(11,false), + + /** 12-政策申请调增(政策申请,预算调增) */ + State_12(12,true), + + /** 13-政策因费用申请调增(政策申请,预算转移) */ + State_13(13,true), + + /** 14-政策申请释放(被拒绝后,政策释放) */ + State_14(14,true), + + /** 15-费用申请释放(被拒绝后,预算增加) */ + State_15(15,true), + + /** 16-政策释放(释放操作,预算增加) */ + State_16(16,true); + + /** + * 编码 + */ + private Integer code; + + /** + * 是否取反,添加预算 + */ + private boolean addBudget; + + private final static List finalBudgetOptFlag = Arrays.asList(0, 2, 3); + + public final static List finalCostOptFlag = Arrays.asList(1,4,5,6); + + public final static List finalPolicyOptFlag = Arrays.asList(11,12,13,14,15); + + /** + * 预算规划,状态0,2,3,新增、调增、调减 + */ + public static List getFinalBudgetOptFlag(){ + return finalBudgetOptFlag; + } +} diff --git a/src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java b/src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java new file mode 100644 index 0000000..982e41f --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java @@ -0,0 +1,19 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; + +/** + * @author YenHex + * @since 2022/3/10 + */ +@AllArgsConstructor +public enum ExcelFilePath { + + /** 地址 */ + EDU_REG_ARCHIVE_IN("1000",""); + + String code; + + String path; + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/HttpCode.java b/src/main/java/com/qs/serve/common/model/enums/HttpCode.java new file mode 100644 index 0000000..18c2e61 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/HttpCode.java @@ -0,0 +1,44 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 请求状态码 + * @author YenHex + * @since 2022/2/28 + */ +@Getter +@AllArgsConstructor +public enum HttpCode { + + /** 基本参数 */ + SUCCESS(200,"操作成功"), + ERROR(500,"操作失败"), + DEV_ERR(500,"部分功能开发中..."), + WX_ERR(500,"微信服务调用异常"), + + LOGIN_ERR(401,"登录信息已过期或失效"), + LOGIN_ERR_2(500,"该账号已被停用,请联系系统管理员"), + LOGIN_ERR_1(500,"账号或登录密码不正确"), + LOGIN_ERR_4001(4001,"商户信息错误"), + LOGIN_ERR_4002(4002,"应用信息错误"), + + + /** 资源权限相关 */ + FORBIDDEN_403(403,"权限不足,无法访问"), + FORBIDDEN_403_1(403,"账套未注册,无权访问"), + FORBIDDEN_403_2(403,"客户端未注册,无权访问"), + FORBIDDEN_403_3(403,"IP地址未注册,无权访问"), + FORBIDDEN_403_4(403,"无招生超管权限,无权访问"), + FORBIDDEN_404(404,"资源不存在或被移除"), + FORBIDDEN_406(406,"系统正常处理,请勿重复提交"), + + + ERROR_EDU_SCHOOL_YEAR(5031,"当前学年信息错误,请重新设置当前学年"), + ; + + Integer code; + String msg; + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/InterType.java b/src/main/java/com/qs/serve/common/model/enums/InterType.java new file mode 100644 index 0000000..daf5495 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/InterType.java @@ -0,0 +1,21 @@ +package com.qs.serve.common.model.enums; + +/** + * @author YenHex + * @since 2022/3/8 + */ +public enum InterType { + + /** + * 前台接口 + */ + API, + + + + /** + * 后台接口 + */ + ADMIN + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/MonthValues.java b/src/main/java/com/qs/serve/common/model/enums/MonthValues.java new file mode 100644 index 0000000..22ac159 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/MonthValues.java @@ -0,0 +1,40 @@ +package com.qs.serve.common.model.enums; + +/** + * @author YenHex + * @since 2023/9/13 + */ +public class MonthValues { + + public static final int[] Q1 = {1,2,3}; + public static final int[] Q2 = {4,5,6}; + public static final int[] Q3 = {7,8,9}; + public static final int[] Q4 = {10,11,12}; + + + + public static int[] getQArr(Integer val){ + for (int i = 0; i < Q1.length; i++) { + if(val==Q1[i]){ + return Q1; + } + } + for (int i = 0; i < Q2.length; i++) { + if(val==Q2[i]){ + return Q2; + } + } + for (int i = 0; i < Q3.length; i++) { + if(val==Q3[i]){ + return Q3; + } + } + for (int i = 0; i < Q4.length; i++) { + if(val==Q4[i]){ + return Q4; + } + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/PolicyType.java b/src/main/java/com/qs/serve/common/model/enums/PolicyType.java new file mode 100644 index 0000000..d1a26a9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/PolicyType.java @@ -0,0 +1,35 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * minio策略配置 + * @author YenHex + * @since 2022/5/10 + */ +@Getter +@AllArgsConstructor +public enum PolicyType { + + /** + * 只读 + */ + READ("read-only"), + + /** + * 只写 + */ + WRITE("write-only"), + + /** + * 读写 + */ + READ_WRITE("read-write"); + + /** + * 类型 + */ + private final String type; + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/SystemModule.java b/src/main/java/com/qs/serve/common/model/enums/SystemModule.java new file mode 100644 index 0000000..a348f1e --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/SystemModule.java @@ -0,0 +1,34 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/7/25 + */ +@Getter +@AllArgsConstructor +public enum SystemModule { + + QUESTION("qms","问卷"), + BAZ("baz","拜访"), + Policy("tzc","政策"), + Payment("pay","支付"), + Budget("budget","预算"), + Verification("verification","核算"), + BIZ("biz","业务"), + BASE("bms","基础档案"), + GOODS("goods","商品"), + SYSTEM("sys","系统"), + UMS("ums","手机用户"), + DATA("data","数据"), + Excel("excel","excel数据"), + Tag("tag","标签"), + SALE("sale","销售"); + + String code; + + String vale; + +} diff --git a/src/main/java/com/qs/serve/common/model/group/EditGroup.java b/src/main/java/com/qs/serve/common/model/group/EditGroup.java new file mode 100644 index 0000000..e2fab74 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/group/EditGroup.java @@ -0,0 +1,8 @@ +package com.qs.serve.common.model.group; + +/** + * @author YenHex + * @since 2022/5/16 + */ +public interface EditGroup { +} diff --git a/src/main/java/com/qs/serve/common/model/group/SaveGroup.java b/src/main/java/com/qs/serve/common/model/group/SaveGroup.java new file mode 100644 index 0000000..e83376a --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/group/SaveGroup.java @@ -0,0 +1,8 @@ +package com.qs.serve.common.model.group; + +/** + * @author YenHex + * @since 2022/5/16 + */ +public interface SaveGroup { +} diff --git a/src/main/java/com/qs/serve/common/model/group/SearchGroup.java b/src/main/java/com/qs/serve/common/model/group/SearchGroup.java new file mode 100644 index 0000000..2ddbdd2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/group/SearchGroup.java @@ -0,0 +1,8 @@ +package com.qs.serve.common.model.group; + +/** + * @author YenHex + * @since 2022/5/16 + */ +public interface SearchGroup { +} diff --git a/src/main/java/com/qs/serve/common/model/oa/OaFormMainProcess.java b/src/main/java/com/qs/serve/common/model/oa/OaFormMainProcess.java new file mode 100644 index 0000000..7902459 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/oa/OaFormMainProcess.java @@ -0,0 +1,42 @@ +package com.qs.serve.common.model.oa; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2024/1/12 + */ +@Data +public class OaFormMainProcess { + + private String targetId; + + /** + * 上次文件 + */ + private List uploadFiles; + + /** + * data + */ + private Object data; + + /** + * 员工号 + */ + private String senderLoginName; + + /** + * 模板编码 + */ + private String templateCode; + + private String userId; + + /** + * 模板编码 + */ + private String tableName; +} diff --git a/src/main/java/com/qs/serve/common/model/oa/OaUploadFile.java b/src/main/java/com/qs/serve/common/model/oa/OaUploadFile.java new file mode 100644 index 0000000..0c13908 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/oa/OaUploadFile.java @@ -0,0 +1,27 @@ +package com.qs.serve.common.model.oa; + +import lombok.Data; + +/** + * @author YenHex + * @since 2024/1/12 + */ +@Data +public class OaUploadFile { + + /** + * 表单控件名称 + */ + private String field; + + /** + * 附件文件名 + */ + private String name; + + /** + * 附件url + */ + private String url; + +} diff --git a/src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java b/src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java new file mode 100644 index 0000000..d7fadaa --- /dev/null +++ b/src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java @@ -0,0 +1,26 @@ +package com.qs.serve.common.service; + +import com.qs.serve.common.util.AuthContextUtils; + +/** + * @author YenHex + * @since 2022/7/4 + */ +public abstract class RedisBaseListenerImpl implements RedisServiceListener{ + + @Override + public String getKey(String pk) { + return getPrefix()+pk+"_"+ AuthContextUtils.getTenant(); + } + + public String getPk(String key){ + return key.replace(getPrefix(),"") + .replace("_"+AuthContextUtils.getTenant(),""); + } + + @Override + public void doJob(String key) { + String[] vals = key.split("_"); + AuthContextUtils.setTenant(vals[vals.length-1]); + } +} diff --git a/src/main/java/com/qs/serve/common/service/RedisServiceListener.java b/src/main/java/com/qs/serve/common/service/RedisServiceListener.java new file mode 100644 index 0000000..8741860 --- /dev/null +++ b/src/main/java/com/qs/serve/common/service/RedisServiceListener.java @@ -0,0 +1,33 @@ +package com.qs.serve.common.service; + +/** + * @author YenHex + * @since 2022/7/4 + */ +public interface RedisServiceListener { + + /** + * 业务前缀 + * @return + */ + String getPrefix(); + + /** + * 获取完整的key + * @param pk + * @return + */ + String getKey(String pk); + + /** + * 同步最近时间段任务,添加redis实现监听 + */ + void syncTask(); + + /** + * 监听过期得key + * @param key + */ + void doJob(String key); + +} diff --git a/src/main/java/com/qs/serve/common/util/Assert.java b/src/main/java/com/qs/serve/common/util/Assert.java new file mode 100644 index 0000000..d1f440b --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/Assert.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.util; + + +import com.qs.serve.common.framework.exception.BusinessException; +import com.qs.serve.common.model.enums.HttpCode; +import lombok.experimental.UtilityClass; + +/** + * 抛出异常工具类 + * @author YenHex + * @since 2022/2/25 + */ +@UtilityClass +public class Assert { + + public static void throwEx(Integer code,String msg){ + throw new BusinessException(msg, code); + } + + public static void throwEx(HttpCode httpCode){ + throw new BusinessException(httpCode.getMsg(),httpCode.getCode()); + } + + public static void throwEx(String msg){ + throw new BusinessException(msg,500); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/AuthContextUtils.java b/src/main/java/com/qs/serve/common/util/AuthContextUtils.java new file mode 100644 index 0000000..dc1171a --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/AuthContextUtils.java @@ -0,0 +1,142 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.experimental.UtilityClass; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.Objects; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@UtilityClass +public class AuthContextUtils { + + private final static ThreadLocal THREAD_TENANT = new ThreadLocal<>(); + private final static ThreadLocal THREAD_SUPPLIER = new ThreadLocal<>(); + private final static ThreadLocal RES_THEME_LOCK = new ThreadLocal<>(); + + public static void removeThreadLocal(){ + THREAD_TENANT.remove(); + THREAD_SUPPLIER.remove(); + RES_THEME_LOCK.remove(); + } + + /** + * 标注开发时使用 + */ + public static boolean DEV_INDEX = true; + + public static String getAppId(){ + return getAppId(true); + } + + public static String getAppId(boolean throwEx){ + String appId = ServletUtils.getHeader(GySysConst.APP_ID_PROP); + if(throwEx&&StringUtils.isEmpty(appId)){ + Assert.throwEx(HttpCode.LOGIN_ERR_4002); + } + return appId; + } + + /** + * 获取用户登录信息 + * @return + */ + public static LoginUser getLoginUser(){ + return getLoginUser(true); + } + + /** + * 系统用户ID + * @return + */ + public static String getSysUserId(){ + LoginUser loginUser = getLoginUser(); + return loginUser.getUserId(); + } + + /** + * 系统用户ID + * @return + */ + public static String getSysUserId(Boolean throwEx){ + if(throwEx){ + return getSysUserId(); + }else { + LoginUser loginUser = getLoginUser(false); + if(loginUser==null){ + return null; + }else { + return loginUser.getUserId(); + } + } + } + + /** + * 判断是否超级管理员 + * @return + */ + public static boolean isSupAdmin(){ + return Objects.requireNonNull(getLoginUser(false)) + .getTypeFlag().equals(LoginUserType.SYS_SUP_USER); + } + + public static void setTenant(String value){THREAD_TENANT.set(value);} + + public static String getTenant(){return THREAD_TENANT.get();} + + + public static void setLockTheme(String value){RES_THEME_LOCK.set(value);} + + public static String getLockTheme(){return RES_THEME_LOCK.get();} + + public static void setSupplierId(String value){ + if(value!=null){ + try { + THREAD_SUPPLIER.set(Long.parseLong(value)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + + public static Long getSupplierId(){return THREAD_SUPPLIER.get();} + + public static void removeTenant(){THREAD_TENANT.remove();} + + public static LoginUser getLoginUser(boolean throwEx){ + UserDetails details = getUserDetail(throwEx); + if(details instanceof LoginUser){ + return (LoginUser) details; + } + return null; + } + + private static UserDetails getUserDetail(boolean throwEx){ + SecurityContext ctx = SecurityContextHolder.getContext(); + Authentication auth = ctx.getAuthentication(); + if (auth != null) { + Object authPri = auth.getPrincipal(); + if (authPri instanceof UserDetails) { + UserDetails details = (UserDetails) authPri; + return details; + } + } + if(throwEx){ + throw new UsernameNotFoundException("未登录或被登出"); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/BirHttpUtil.java b/src/main/java/com/qs/serve/common/util/BirHttpUtil.java new file mode 100644 index 0000000..f4544e5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/BirHttpUtil.java @@ -0,0 +1,140 @@ +package com.qs.serve.common.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.qs.serve.common.config.properties.ProjectProperties; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.dto.R; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.ParseException; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.EntityUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +/** + * @author YenHex + * @since 2022/11/23 + */ +@Slf4j +@UtilityClass +public class BirHttpUtil { + + /** + * 判断当前环境是否请求bir + * @return + */ + public static boolean isRestBir(){ + ProjectProperties projectProperties = SpringUtils.getBean(ProjectProperties.class); + return projectProperties.getBirService().equals("true"); + } + + public static String getBaseUrl(){ + ProjectProperties projectProperties = SpringUtils.getBean(ProjectProperties.class); + return projectProperties.getBirServiceUrl(); + } + + public static R get(String action){ + return get(action,null); + } + + public static R get(String action,Object query){ + String baseUrl = getBaseUrl(); + String url = "/"+action; + if(query!=null){ + Map map = JsonUtil.objectToMap(query); + String params = HttpUtil.createUrl(map); + if(url.contains("?")){ + url = url+params; + }else { + url = url+"?"+params; + } + } + HashMap hearders = new HashMap<>(); + HttpServletRequest request = ServletUtils.getRequest(); + String tenant = request.getHeader(GySysConst.TENANT_PROP); + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + hearders.put(GySysConst.TENANT_PROP,tenant); + hearders.put(GySysConst.AUTHORIZATION_PROP,token); + //自动封装翻页参数 + if(!url.contains("?")){ + url += "?"; + } + if(PageUtil.getPageSize()!=null){ + url += "&pageSize="+PageUtil.getPageSize(); + } + if(PageUtil.getPageNum()!=null){ + url += "&pageNum="+PageUtil.getPageNum(); + } + url = baseUrl + url; + url = url.replace("//","/"); + url = url.replace("http:/","http://"); + url = url.replace("https:/","https://"); + log.debug("请求BIR中转URL:{}",url); + String result = HttpUtil.doGet(url,hearders); + log.debug("请求BIR中转URL:{}\n数据返回:{}",url,result); + JSONObject object = JSON.parseObject(result); + Integer status = object.getInteger("status"); + String msg = object.getString("msg"); + Object data = object.get("data"); + R r = R.ok(data); + r.setStatus(status); + r.setMsg(msg); + return r; + } + + public static R post(String action,Object query){ + String baseUrl = getBaseUrl(); + String url = baseUrl+"/"+action; + + HashMap hearders = new HashMap<>(); + HttpServletRequest request = ServletUtils.getRequest(); + String tenant = request.getHeader(GySysConst.TENANT_PROP); + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + hearders.put(GySysConst.TENANT_PROP,tenant); + hearders.put(GySysConst.AUTHORIZATION_PROP,token); + //自动封装翻页参数 +// if(!url.contains("?")){ +// url += "?"; +// } +// if(PageUtil.getPageSize()!=null){ +// url += "&pageSize="+PageUtil.getPageSize(); +// } +// if(PageUtil.getPageNum()!=null){ +// url += "&pageNum="+PageUtil.getPageNum(); +// } + url = url.replace("//","/"); + url = url.replace("http:/","http://"); + url = url.replace("https:/","https://"); + log.debug("请求BIR中转URL:{}",url); + String json = JsonUtil.objectToJson(query); + log.debug("请求BIR中转Query:{}",json); + String result = HttpUtil.doPost(url,json,hearders); + log.debug("请求BIR中转URL:{}\n数据返回:{}",url,result); + JSONObject object = JSON.parseObject(result); + Integer status = object.getInteger("status"); + String msg = object.getString("msg"); + Object data = object.get("data"); + R r = R.ok(data); + r.setStatus(status); + r.setMsg(msg); + return r; + } + + +} diff --git a/src/main/java/com/qs/serve/common/util/BusinessDifferenceUtil.java b/src/main/java/com/qs/serve/common/util/BusinessDifferenceUtil.java new file mode 100644 index 0000000..0327af0 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/BusinessDifferenceUtil.java @@ -0,0 +1,78 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity; +import com.qs.serve.common.model.annotation.BusinessDifference; +import com.qs.serve.common.model.dto.DiffFieldVal; +import com.qs.serve.modules.sys.entity.SysBusinessLog; +import lombok.SneakyThrows; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2023/4/25 + */ +public class BusinessDifferenceUtil { + + @SneakyThrows + public static List getDifferenceList(T orgVal, T newVal){ + List diffFieldValList = new ArrayList<>(); + if(orgVal==null||newVal==null){ + return diffFieldValList; + } + Class clazz = null; + try { + clazz = Class.forName(orgVal.getClass().getName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + if(clazz==null){return diffFieldValList;} + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + for (Annotation annotation : field.getAnnotations()) { + if(annotation instanceof BusinessDifference){ + BusinessDifference busDiff = (BusinessDifference) annotation; + field.setAccessible(true); + Object orgValue = field.get(orgVal); + Object newValue = field.get(newVal); + if(newValue==null){ + continue; + } + if(orgValue==null){ + orgValue = ""; + } + if(!orgValue.equals(newValue)){ + DiffFieldVal fieldVal = new DiffFieldVal(); + fieldVal.setField(field.getName()); + fieldVal.setNewValue(newValue.toString()); + fieldVal.setOrgValue(orgValue.toString()); + fieldVal.setComment(busDiff.value()); + diffFieldValList.add(fieldVal); + } + } + } + } + return diffFieldValList; + } + + public static void main(String[] args) { +// BmsSupplierContacts supplierContacts = new BmsSupplierContacts(); +// supplierContacts.setContactsName("名称1"); +// supplierContacts.setContactsPost("setContactsPost"); +// +// +// BmsSupplierContacts supplierContacts2 = new BmsSupplierContacts(); +// supplierContacts2.setContactsName("名称2"); +// supplierContacts2.setContactsNumber("123456"); +// supplierContacts2.setContactsPost("setContactsPost"); + +// List diffFieldValList =BusinessDifferenceUtil.getDifferenceList(supplierContacts,supplierContacts2); +// for (DiffFieldVal fieldVal : diffFieldValList) { +// System.out.println(JsonUtil.objectToJson(fieldVal)); +// } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/CodeGenUtil.java b/src/main/java/com/qs/serve/common/util/CodeGenUtil.java new file mode 100644 index 0000000..a321453 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/CodeGenUtil.java @@ -0,0 +1,147 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.util.IdUtil; +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.framework.redis.RedisService; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.beans.BeansException; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * 生成编号 + * @author YenHex + * @since 2023/6/25 + */ +public class CodeGenUtil { + + @Getter + @AllArgsConstructor + public enum SourceKey{ + CostApply("cost_apply"), + SalePlan("SalePlan"), + Activity("activity"), + OmsOrder("OmsOrder"), + Verification("verification"), + VerificationBatch("verificationBatch"), + Policy("policy"), + Budget("Budget"), + BudgetChange("BudgetChange"), + BudgetBatch("BudgetBatch"), + AgreeCheck("AgreeCheck"), + PolicyItem("policy_item"); + private String code; + } + + @Getter + @AllArgsConstructor + public enum SourceDataKey{ + TagInfo("T","TagInfo"), + SaleRegion("S","SaleRegion"), + BizRegion("B","BizRegion"), + ActivityPayCondition("K","ActivityPayCondition"); + private String prefix; + private String code; + } + + + private static final int split_num = 1000; + + + final static String[] digits2 = { + "A" , "B" , "C" , "D" , "E" , + "F" , "G" , "H" ,"J" , "K" , + "L" , "M" , "N" , "P" , + "Q" , "R" , "T" , "U" , "V" , "W" , + "X" , "Y" + }; + + public static Long getIdx(String key){ + RedisService redisService = SpringUtils.getBean(RedisService.class); + Long value = redisService.getLong(key); + if(value==null){ + redisService.set(key,1); + value = 1L; + }else { + value++; + } + redisService.set(key,value); + return value; + } + + public synchronized static String generate(SourceKey sourceKey){ + try { + LocalDate localDateTime = LocalDate.now(); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd"); + String localTime = df.format(localDateTime); + localTime = localTime.substring(2); + String key = "code_index:"+sourceKey.getCode()+":"+localTime; + return localTime + getCommonValue(key); + } catch (BeansException e) { + e.printStackTrace(); + } + return IdUtil.getSnowflakeNextIdStr(); + } + + public static String getCommonValue(String key){ + Long value = getIdx(key); + String digitsNum = ""; + String appendStr = value+""; + if(value>split_num){ + appendStr = (value%100)+""; + Long d = value/split_num; + digitsNum = digits2[d.intValue()]; + } + StringBuilder appendZeros = new StringBuilder(); + for (int i = (appendStr+digitsNum).length(); i < 3; i++) { + appendZeros.append("0"); + } + //用于区分测试环境数据 + String subflex = DevEnvironmentConfig.isDev()?"TEST":""; + return digitsNum + appendZeros + appendStr+subflex; + } + + public synchronized static String getDataCode(SourceDataKey dataKey){ + String key = "code_data_index:"+dataKey.getCode(); + String commonVal = getCommonValue(key); + return dataKey.getPrefix() + commonVal; + } + + /** + * 32个字符,用来表示32进制 + */ + final static char[] digits = { + '0' , '1' , '2' , '3' , '4' , '5' , + '6' , '7' , '8' , '9' , 'A' , 'B' , + 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , + 'J' , 'K' , 'L' , 'M' , 'N' , 'P' , + 'Q' , 'R' , 'T' , 'U' , 'V' , 'W' , + 'X' , 'Y' + }; + + /** + * 10=>32 + * @param val + * @return + */ + static String digits32(long val) { + // 32=2^5=二进制100000 + int shift = 5; + // numberOfLeadingZeros 获取long值从高位连续为0的个数,比如val=0,则返回64 + // 此处mag=long值二进制减去高位0之后的长度 + int mag = Long.SIZE - Long.numberOfLeadingZeros(val); + int len = Math.max(((mag + (shift - 1)) / shift), 1); + char[] buf = new char[len]; + do { + // &31相当于%32 + buf[--len] = digits[((int) val) & 31]; + val >>>= shift; + } while (val != 0 && len > 0); + return new String(buf); + } + + +} diff --git a/src/main/java/com/qs/serve/common/util/CollectionUtil.java b/src/main/java/com/qs/serve/common/util/CollectionUtil.java new file mode 100644 index 0000000..b566282 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/CollectionUtil.java @@ -0,0 +1,90 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/25 + */ +@UtilityClass +public class CollectionUtil extends cn.hutool.core.collection.CollectionUtil{ + + /** + * 去除list中的重复数据 + */ + public static List removeRepeat(List list) { + if (isEmpty(list)) { + return list; + } + List result = new ArrayList(); + for (T e : list) { + if (!result.contains(e)) { + result.add(e); + } + } + return result; + } + + public static boolean hasNull(Object... objects){ + for (int i = 0; i < objects.length; i++) { + if(objects[i]==null){return true;} + } + return false; + } + + public static boolean hasNotNull(Object... objects){ + for (int i = 0; i < objects.length; i++) { + if(objects[i]!=null){return true;} + } + return false; + } + + /** + * 将集合转换为String数组 + */ + public static String[] toArray(List list) { + if (isEmpty(list)) { + return null; + } + String[] result = new String[list.size()]; + for (int i = 0; i < list.size(); i++) { + result[i] = String.valueOf(list.get(i)); + } + return result; + } + + /** + * 将list拆分成多给指定的大小的list + */ + public static List> createList(List target, int size) { + List> listArr = new ArrayList<>(); + //获取被拆分的数组个数 + int arrSize = target.size()%size==0?target.size()/size:target.size()/size+1; + for(int i=0;i sub = new ArrayList(); + //把指定索引数据放入到list中 + for(int j=i*size;j<=size*(i+1)-1;j++) { + if(j<=target.size()-1) { + sub.add(target.get(j)); + } + } + listArr.add(sub); + } + return listArr; + } + + public static boolean isNotEmpty(T[] arr){ + return arr!=null && arr.length>0; + } + + public static T selectFirst(List list){ + if(isNotEmpty(list)){ + return list.get(0); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/CopierUtil.java b/src/main/java/com/qs/serve/common/util/CopierUtil.java new file mode 100644 index 0000000..a79c226 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/CopierUtil.java @@ -0,0 +1,95 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; +import org.springframework.cglib.beans.BeanCopier; + +import java.io.*; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 取代BeanUtils.CP + * @Author JcYen + * @Date 2019/6/3 + * @Version 1.0 + */ +@UtilityClass +public class CopierUtil { + + private static final Map BEAN_COPIERS = new ConcurrentHashMap(); + + private static String genKey(Class source, Class target) { + return source.getName() + target.getName(); + } + + /** + * target字段值,会被source字段值覆盖(包括null) + * @param source + * @param target + */ + public static T copy(Object source, T target) { + String key = genKey(source.getClass(), target.getClass()); + BeanCopier copier; + if (!BEAN_COPIERS.containsKey(key)) { + copier = BeanCopier.create(source.getClass(), target.getClass(), false); + BEAN_COPIERS.put(key, copier); + } else { + copier = BEAN_COPIERS.get(key); + } + copier.copy(source, target, null); + return target; + } + + + /** + * 采用对象的序列化完成对象的深克隆 + * @param obj 待克隆的对象 + * @return + */ + @SuppressWarnings("unchecked") + public static T cloneObject(T obj) { + T cloneObj = null; + try { + // 写入字节流 + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream obs = new ObjectOutputStream(out); + obs.writeObject(obj); + obs.close(); + + // 分配内存,写入原始对象,生成新对象 + ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(ios); + // 返回生成的新对象 + cloneObj = (T) ois.readObject(); + ois.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return cloneObj; + } + + /** + * 利用序列化完成集合的深克隆 + * + * @param collection 待克隆的集合 + * @return + * @throws ClassNotFoundException + * @throws IOException + */ + @SuppressWarnings("unchecked") + public static Collection cloneCollection(Collection collection) throws ClassNotFoundException, IOException{ + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(collection); + out.close(); + + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + Collection dest = (Collection) in.readObject(); + in.close(); + + return dest; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/DateSplitUtil.java b/src/main/java/com/qs/serve/common/util/DateSplitUtil.java new file mode 100644 index 0000000..dcb76b9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/DateSplitUtil.java @@ -0,0 +1,67 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.model.dto.DateSplitDTO; +import lombok.experimental.UtilityClass; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * 分割时间DTO工具类 + * @author YenHex + * @since 2023/6/5 + */ +@UtilityClass +public class DateSplitUtil { + + public static List getSplitDto(LocalDate sDate, LocalDate eDate){ + int diffYear = eDate.getYear() - sDate.getYear(); + int diffMonthOfYear = eDate.getMonthValue() - sDate.getMonthValue(); + int diffMonth = diffYear * 12 + diffMonthOfYear; + //最后一个月的年月数 + int lastYearMonth = eDate.getYear()*100 + eDate.getMonthValue(); + int firstYearMonth = sDate.getYear()*100 + sDate.getMonthValue(); + if(diffMonth<1){ + //同一个月 + int days = eDate.getDayOfMonth() - sDate.getDayOfMonth() + 1; + DateSplitDTO splitDTO = new DateSplitDTO(days,sDate,eDate,lastYearMonth,1); + return Arrays.asList(splitDTO); + }else { + List dateSplitDTOS = new ArrayList<>(); + for (int i = 0; i < diffMonth+2; i++) { + int sort = i+1; + LocalDate newStartDate = sDate.plusMonths(i); + int currYearMonth = newStartDate.getYear()*100 + newStartDate.getMonthValue(); + //第一个月 + if(firstYearMonth==currYearMonth){ + int days = sDate.lengthOfMonth() - sDate.getDayOfMonth() + 1; + //当月最后一天 + LocalDate endLocalDate = LocalDate.of(sDate.getYear(),sDate.getMonth(),sDate.lengthOfMonth()); + DateSplitDTO splitDTO = new DateSplitDTO(days,sDate,endLocalDate,currYearMonth,sort); + dateSplitDTOS.add(splitDTO); + }else if(currYearMonth==lastYearMonth){ + int days = eDate.getDayOfMonth(); + //当月第一天 + LocalDate startDate = newStartDate.withDayOfMonth(1); + DateSplitDTO splitDTO = new DateSplitDTO(days,startDate,eDate,currYearMonth,sort); + dateSplitDTOS.add(splitDTO); + break; + }else { + int days = newStartDate.lengthOfMonth(); + //当月第一天 + LocalDate startDate = newStartDate.withDayOfMonth(1); + //当月最后一天 + LocalDate endLocalDate = LocalDate.of(newStartDate.getYear(),newStartDate.getMonth(),newStartDate.lengthOfMonth()); + DateSplitDTO splitDTO = new DateSplitDTO(days,startDate,endLocalDate,currYearMonth,sort); + dateSplitDTOS.add(splitDTO); + } + } + return dateSplitDTOS; + } + + } + +} diff --git a/src/main/java/com/qs/serve/common/util/DateUtils.java b/src/main/java/com/qs/serve/common/util/DateUtils.java new file mode 100644 index 0000000..86bf67a --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/DateUtils.java @@ -0,0 +1,127 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.util.model.DateFormatString; +import lombok.experimental.UtilityClass; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Date; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@UtilityClass +public class DateUtils { + + public static Date localDateToDate(LocalDate date){ + //LocalDate date = LocalDate.of(2006,07,26); + ZoneId zone = ZoneId.systemDefault(); + Instant instant = date.atStartOfDay().atZone(zone).toInstant(); + java.util.Date da = Date.from(instant); + return da; + } + + public static String getString(DateFormatString format){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format.getValue()); + return LocalDateTime.now().format(formatter); + } + + + public static LocalDate toLocalDate(Date date){ +// Instant instant = date.toInstant(); +// ZoneId zoneId = ZoneId.systemDefault(); +// return instant.atZone(zoneId).toLocalDate(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String str = dateFormat.format(date); + String[] a = str.split("-"); + return LocalDate.of(Integer.parseInt(a[0]),Integer.parseInt(a[1]),Integer.parseInt(a[2])); + } + + public static Date toDate(LocalDate localDate){ + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zdt = localDate.atStartOfDay(zoneId); + return Date.from(zdt.toInstant()); + } + + /** + * 获取设置后得时间 + * @param time + * @param unit + * @param num + * @return + */ + public static LocalDateTime beSetTime(LocalDateTime time, ChronoUnit unit,int num){ + if(num>0){ + return time.plus(num,unit); + }else { + return time.minus(-num,unit); + } + } + + public static LocalDate beSetDate(LocalDate time,int days){ + return time.plusDays(days); + } + + public static Date toDate(String str,String format){ + SimpleDateFormat sdf = new SimpleDateFormat(format); + try { + return sdf.parse(str); + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + public static Date toDate(LocalDateTime time){ + return Date.from( time.atZone( ZoneId.systemDefault()).toInstant()); + } + + public static double diffTime(long beganTime, long endTime) { + return (double)(endTime - beganTime) / 1000.0D; + } + + public static String format(LocalDateTime localDateTime, DateFormatString format){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format.getValue()); + return localDateTime.format(formatter); + } + + public static String datePath(){ + return format(LocalDate.now(),DateFormatString.DATE); + } + + public static String format(LocalDate localDate, DateFormatString format){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format.getValue()); + return localDate.format(formatter); + } + + public static void main(String[] args) { + System.out.println(DateUtils.beSetTime(LocalDateTime.now(), ChronoUnit.DAYS,-2)); + // Get the LocalDateTime instance + LocalDateTime ldt + = LocalDateTime + .parse("2019-12-31T19:15:30"); + + // Get the String representation of this LocalDateTime + System.out.println("Original LocalDateTime: " + + ldt.toString()); + + // subtract 200 DAYS to LocalDateTime + LocalDateTime value + = ldt.minus(200, ChronoUnit.DAYS); + + // print result + System.out.println("LocalDateTime after subtracting DAYS: " + + value); + } + + public static int getQuarter(int month) { + if (month >= 1 && month <= 3) return 1; + else if (month >= 4 && month <= 6) return 2; + else if (month >= 7 && month <= 9) return 3; + else return 4; + } +} diff --git a/src/main/java/com/qs/serve/common/util/HttpUtil.java b/src/main/java/com/qs/serve/common/util/HttpUtil.java new file mode 100644 index 0000000..116031b --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/HttpUtil.java @@ -0,0 +1,163 @@ +package com.qs.serve.common.util; + +import com.alibaba.fastjson.JSONObject; +import com.qs.serve.common.model.dto.R; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.ParseException; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +/** + * @author YenHex + * @since 2022/11/23 + */ +@Slf4j +@UtilityClass +public class HttpUtil { + + private final static String CONTENT_TYPE = "application/json"; + private final static String CHARSET = "UTF-8"; + private final static String EN_CONING = "UTF-8"; + + public static String doPost(String url, String jsonStr, HashMap headers) { + CloseableHttpClient client = HttpClientBuilder.create().build(); + CloseableHttpResponse response = null; + String errorMsg = null; + try { + //设post请求 + HttpPost post = new HttpPost(url); + //创建请求实体传参 + if(jsonStr!=null){ + StringEntity postingString = new StringEntity(jsonStr,CHARSET); + postingString.setContentEncoding(EN_CONING); + //设置post请求参数 + post.setEntity(postingString); + } + post.addHeader(HTTP.CONTENT_TYPE,CONTENT_TYPE); + if (headers != null) { + for (String key : headers.keySet()) { + post.addHeader(key,headers.get(key)); + } + } + post.setConfig( + RequestConfig.custom() + //连接超时60秒 + .setConnectTimeout(60*1000) + .build() + ); + //执行post请求 + response = client.execute(post); + //访问成功状态码为200 + if (response.getStatusLine().getStatusCode() == 200) { + return EntityUtils.toString(response.getEntity()); + } + } catch (IOException e) { + errorMsg = e.getMessage(); + e.printStackTrace(); + }finally { + try { + client.close(); + if(response!=null){ + response.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return errorMsg; + } + + public static String doGet(String url, HashMap headers) { + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpGet httpget = new HttpGet(url); + httpget.addHeader(HTTP.CONTENT_TYPE,CONTENT_TYPE); + if (headers != null) { + for (String key : headers.keySet()) { + httpget.addHeader(key,headers.get(key)); + } + } + CloseableHttpResponse response = httpclient.execute(httpget); + try { + if (response.getStatusLine().getStatusCode() == 200) { + return EntityUtils.toString(response.getEntity()); + } + } finally { + response.close(); + } + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (ParseException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + public static String createUrl(Map param){ + StringBuilder sb = new StringBuilder(); + for (String key : param.keySet()) { + String par = param.get(key).toString(); + try { + par = URLEncoder.encode(par,"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + sb.append("&").append(key).append("=").append(par); + } + return sb.toString(); + } + + public static R doGetResult(String url,HashMap headers){ + String result = HttpUtil.doGet(url,headers); + log.debug("url:{},result:{}",url,result); + if(result==null){ + Assert.throwEx("远程服务连接失败"); + } + JSONObject jsonObject = JSONObject.parseObject(result); + Integer status = jsonObject.getInteger("status"); + String msg = jsonObject.getString("msg"); + String data = jsonObject.getString("data"); + return new R(status,msg,data); + } + + public static R doPostResult(String url, String jsonStr, HashMap headers){ + String result = HttpUtil.doPost(url,jsonStr,headers); + log.debug("url:{},result:{}",url,result); + if(result==null){ + log.warn("jsonStr:{}",jsonStr); + Assert.throwEx("远程服务连接失败"); + } + JSONObject jsonObject = JSONObject.parseObject(result); + Integer status = jsonObject.getInteger("status"); + String msg = jsonObject.getString("msg"); + String data = jsonObject.getString("data"); + return new R(status,msg,data); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/IdUtil.java b/src/main/java/com/qs/serve/common/util/IdUtil.java new file mode 100644 index 0000000..d15bd32 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/IdUtil.java @@ -0,0 +1,61 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.lang.Snowflake; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Random; + +/** + * @author YenHex + * @since 2022/3/3 + */ +public class IdUtil extends cn.hutool.core.util.IdUtil { + + private static final long BASE_DIFF_MILLIS = 1648013774104L; + private static final long BASE_DIFF_MILLIS2 = 1578585779603640320L; + + private static final Snowflake snowflake = getSnowflake(1,1); + + public static String timeStampId() { + long millis = System.currentTimeMillis(); + String prefix = String.format("%013d", millis-BASE_DIFF_MILLIS); + Random random = new Random(); + int end2 = random.nextInt(999); + return prefix + String.format("%03d", end2); + } + + + public static Long timeStampLong() { + return System.currentTimeMillis()-BASE_DIFF_MILLIS; + } + + + public static String dateTimeStampId() { + LocalDateTime localDateTime = LocalDateTime.now(); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String localTime = df.format(localDateTime); + Random random = new Random(); + int end2 = random.nextInt(999); + return localTime + String.format("%03d", end2); + } + + public static String dateTimeId() { + LocalDateTime localDateTime = LocalDateTime.now(); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String localTime = df.format(localDateTime); + return localTime; + } + + public static String genCode(int len) { + int max = new Double(Math.pow(10, len)).intValue() - 1; + Random random = new Random(); + int end2 = random.nextInt(max); + return String.format("%0"+len+"d", end2); + } + + public static long getSnowFlakeId(){ + return snowflake.nextId()-BASE_DIFF_MILLIS2; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/JdbcUtil.java b/src/main/java/com/qs/serve/common/util/JdbcUtil.java new file mode 100644 index 0000000..1a7251e --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/JdbcUtil.java @@ -0,0 +1,107 @@ +package com.qs.serve.common.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; + +import java.sql.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 原生JDBC工具类 + * @Author JcYen + * @Date 2021/6/4 + */ +@Slf4j +public class JdbcUtil { + + private static final String[] FILTER_WORD = new String[]{"truncate","create","alter","eval","delete","sp_password"}; + + /** + * 执行SQL(为安全,拦截delete语句) + * @param username + * @param password + * @param url + * @param driverName + * @param sql + * @return + */ + public static List> query(String username, String password, String url, String driverName, String sql) { + //检查SQL,防止SQL执行DDL语句 + doSqlFilter(sql); + List> list = new ArrayList(); + Connection conn = null; + Statement stmt = null; + ResultSet rs = null; + try { + Class.forName(driverName); + conn = DriverManager.getConnection(url, username, password); + stmt = conn.createStatement(); + log.debug("JDBC工具类 Preparing SQL: {}",url); + rs = stmt.executeQuery(sql); + ResultSetMetaData md = rs.getMetaData(); + int columnCount = md.getColumnCount(); + while (rs.next()) { + Map rowData = new HashMap<>(); + for (int i = 1; i <= columnCount; i++) { + rowData.put(md.getColumnName(i), rs.getObject(i)); + } + list.add(rowData); + } + } catch (ClassNotFoundException e) { + log.warn(e.getMessage()); + } catch (SQLException throwables) { + log.error(throwables.getMessage()); + }finally { + if(rs!=null){ + try { + rs.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + if (stmt!=null){ + try { + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(conn!=null){ + try { + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + rs = null; + stmt = null; + conn = null; + } + return list; + } + + private static void doSqlFilter(String sql){ + boolean unsafe = false; + String[] parts = sql.split(" "); + for (String part : parts) { + if(unsafe){ break; } + if(StringUtils.isEmpty(part)){ + continue; + } + part = part.trim(); + for (String filterWord : FILTER_WORD) { + if(part.equalsIgnoreCase(filterWord)){ + unsafe = true; + break; + } + } + } + if(unsafe){ + //AssertUtil.("非法SQL被拦截 ==> "+sql); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/JsonUtil.java b/src/main/java/com/qs/serve/common/util/JsonUtil.java new file mode 100644 index 0000000..86fa535 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/JsonUtil.java @@ -0,0 +1,111 @@ +package com.qs.serve.common.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.serializer.SerializeConfig; +import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.qs.serve.common.framework.interceptor.LocalDateTimeFormatSerializer; +import lombok.experimental.UtilityClass; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +/** + * Jackson json序列化和反序列化工具类 + * @Author JcYen + * @Date 2019/6/3 + * @Version 1.0 + */ +@UtilityClass +public class JsonUtil { + + /** + * jackson对象 + */ + static final ObjectMapper MAPPER = new ObjectMapper(); + + static { + MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); + MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); + MAPPER.registerModule(new JavaTimeModule()); + } + + /** + * 将对象转换成json字符串。 + */ + public static String objectToJson(Object data) { + try { + String string = MAPPER.writeValueAsString(data); + return string; + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 将json结果集转化为对象 + * + * @param jsonData json数据 + * @param beanType 对象中的object类型 + */ + public static T jsonToPojo(String jsonData, Class beanType) { + try { + T t = MAPPER.readValue(jsonData, beanType); + return t; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 将json数据转换成pojo对象list + */ + public static List jsonToList(String jsonData, Class beanType) { + JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); + try { + List list = MAPPER.readValue(jsonData, javaType); + return list; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Map jsonToMap(String jsonStr){ + Map json = JSONObject.parseObject(jsonStr, Map.class); + return json; + } + + public static Map objectToMap(Object object){ + // 创建SerializeConfig对象,并设置日期时间的格式 + SerializeConfig config = new SerializeConfig(); + LocalDateTimeFormatSerializer dateFormatSerializer = new LocalDateTimeFormatSerializer(); + config.put(LocalDateTime.class, dateFormatSerializer); + String jsonString = JSON.toJSONString(object, config); + Map map = JSONObject.parseObject(jsonString); + return map; + } + + public static List> listToMap(List objects){ + List> result = new ArrayList<>(); + for (T object : objects) { + Map map = objectToMap(object); + result.add(map); + } + return result; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/JumpToUtil.java b/src/main/java/com/qs/serve/common/util/JumpToUtil.java new file mode 100644 index 0000000..3792f0b --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/JumpToUtil.java @@ -0,0 +1,18 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; + +/** + * @author YenHex + * @since 2023/6/8 + */ +@UtilityClass +public class JumpToUtil { + + public static String getJumpUrl(String host, String templateCode, String targetId) { + return host + "/#/jump?jumpType=apiApproval" + + "&targetCode="+templateCode + +"&targetId="+targetId; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/JwtUtils.java b/src/main/java/com/qs/serve/common/util/JwtUtils.java new file mode 100644 index 0000000..9f1c272 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/JwtUtils.java @@ -0,0 +1,82 @@ +package com.qs.serve.common.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.qs.serve.common.config.JwtConfig; +import com.qs.serve.common.framework.security.model.LoginUserType; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.BadCredentialsException; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Slf4j +public class JwtUtils { + + private final static String USER_ID_CLAIM = "UID"; + private final static String USER_TYPE_CLAIM = "TYPE"; + private final static String USER_CLIENT_CLAIM = "CLIENT"; + + private final static JwtConfig jwtConfig = new JwtConfig(); + + public static String generateToken(String userId, LoginUserType userType,String client) { + LocalDateTime dateTime = LocalDateTime.now(); + LocalDateTime exTime = DateUtils.beSetTime(dateTime, ChronoUnit.DAYS,jwtConfig.getExpire()); + Algorithm algorithm = Algorithm.HMAC256(jwtConfig.getSecret()); + return JWT.create() + .withIssuer(jwtConfig.getIss()) + .withIssuedAt(DateUtils.toDate(dateTime)) + .withExpiresAt(DateUtils.toDate(exTime)) + .withClaim(USER_TYPE_CLAIM,userType.getCode()) + .withClaim(USER_ID_CLAIM,userId) + .withClaim(USER_CLIENT_CLAIM,client) + .sign(algorithm); + } + + public static boolean verify(String token) { + try{ + Algorithm algorithm = Algorithm.HMAC256(jwtConfig.getSecret()); + JWTVerifier verifier = JWT.require(algorithm) + .withIssuer(jwtConfig.getIss()) + .build(); + verifier.verify(token); + return true; + } catch (Exception ex){ + log.debug("令牌验证异常:{}",ex.getMessage()); + return false; + } + } + + public static String getUserId(String token) { + try{ + return JWT.decode(token).getClaim(USER_ID_CLAIM).asString(); + }catch (Exception ex){ + log.debug("方法:getUserId() 令牌验证异常:{}",ex.getMessage()); + throw new BadCredentialsException("调用凭证无效"); + } + } + + public static String getUserType(String token) { + try{ + return JWT.decode(token).getClaim(USER_TYPE_CLAIM).asString(); + }catch (Exception ex){ + log.debug("方法:getUserId() 令牌验证异常:{}",ex.getMessage()); + throw new BadCredentialsException("调用凭证无效"); + } + } + + public static String getClient(String token) { + try{ + return JWT.decode(token).getClaim(USER_CLIENT_CLAIM).asString(); + }catch (Exception ex){ + log.debug("方法:getUserId() 令牌验证异常:{}",ex.getMessage()); + throw new BadCredentialsException("调用凭证无效"); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/MinioUtil.java b/src/main/java/com/qs/serve/common/util/MinioUtil.java new file mode 100644 index 0000000..6425bff --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/MinioUtil.java @@ -0,0 +1,84 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.model.enums.PolicyType; +import lombok.experimental.UtilityClass; + +/** + * @author YenHex + * @since 2022/5/10 + */ +@UtilityClass +public class MinioUtil { + + public static String getPolicy(String bucketName, PolicyType policyType) { + StringBuilder builder = new StringBuilder(); + builder.append("{\n"); + builder.append(" \"Statement\": [\n"); + builder.append(" {\n"); + builder.append(" \"Action\": [\n"); + if (policyType == PolicyType.WRITE) { + builder.append(" \"s3:GetBucketLocation\",\n"); + builder.append(" \"s3:ListBucketMultipartUploads\"\n"); + } else if (policyType == PolicyType.READ_WRITE) { + builder.append(" \"s3:GetBucketLocation\",\n"); + builder.append(" \"s3:ListBucket\",\n"); + builder.append(" \"s3:ListBucketMultipartUploads\"\n"); + } else { + builder.append(" \"s3:GetBucketLocation\"\n"); + } + builder.append(" ],\n"); + builder.append(" \"Effect\": \"Allow\",\n"); + builder.append(" \"Principal\": \"*\",\n"); + builder.append(" \"Resource\": \"arn:aws:s3:::"); + builder.append(bucketName); + builder.append("\"\n"); + builder.append(" },\n"); + if (PolicyType.READ.equals(policyType)) { + builder.append(" {\n"); + builder.append(" \"Action\": [\n"); + builder.append(" \"s3:ListBucket\"\n"); + builder.append(" ],\n"); + builder.append(" \"Effect\": \"Deny\",\n"); + builder.append(" \"Principal\": \"*\",\n"); + builder.append(" \"Resource\": \"arn:aws:s3:::"); + builder.append(bucketName); + builder.append("\"\n"); + builder.append(" },\n"); + } + builder.append(" {\n"); + builder.append(" \"Action\": "); + switch (policyType) { + case WRITE: + builder.append("[\n"); + builder.append(" \"s3:AbortMultipartUpload\",\n"); + builder.append(" \"s3:DeleteObject\",\n"); + builder.append(" \"s3:ListMultipartUploadParts\",\n"); + builder.append(" \"s3:PutObject\"\n"); + builder.append(" ],\n"); + break; + case READ_WRITE: + builder.append("[\n"); + builder.append(" \"s3:AbortMultipartUpload\",\n"); + builder.append(" \"s3:DeleteObject\",\n"); + builder.append(" \"s3:GetObject\",\n"); + builder.append(" \"s3:ListMultipartUploadParts\",\n"); + builder.append(" \"s3:PutObject\"\n"); + builder.append(" ],\n"); + break; + default: + builder.append("\"s3:GetObject\",\n"); + break; + } + builder.append(" \"Effect\": \"Allow\",\n"); + builder.append(" \"Principal\": \"*\",\n"); + builder.append(" \"Resource\": \"arn:aws:s3:::"); + builder.append(bucketName); + builder.append("/*\"\n"); + builder.append(" }\n"); + builder.append(" ],\n"); + builder.append(" \"Version\": \"2012-10-17\"\n"); + builder.append("}\n"); + return builder.toString(); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/NanoIdUtils.java b/src/main/java/com/qs/serve/common/util/NanoIdUtils.java new file mode 100644 index 0000000..da8b07d --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/NanoIdUtils.java @@ -0,0 +1,60 @@ +package com.qs.serve.common.util; + +import java.security.SecureRandom; +import java.util.Random; + +/** + * @author YenHex + * @since 2022/4/11 + */ +public final class NanoIdUtils { + public static final SecureRandom DEFAULT_NUMBER_GENERATOR = new SecureRandom(); + public static final char[] DEFAULT_ALPHABET = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + public static final int DEFAULT_SIZE = 21; + + private NanoIdUtils() { + } + + public static String randomNanoId() { + return randomNanoId(DEFAULT_NUMBER_GENERATOR, DEFAULT_ALPHABET, 21); + } + + public static String randomNanoId(Random random, char[] alphabet, int size) { + if (random == null) { + throw new IllegalArgumentException("random cannot be null."); + } else if (alphabet == null) { + throw new IllegalArgumentException("alphabet cannot be null."); + } else if (alphabet.length != 0 && alphabet.length < 256) { + if (size <= 0) { + throw new IllegalArgumentException("size must be greater than zero."); + } else { + int mask = (2 << (int)Math.floor(Math.log((double)(alphabet.length - 1)) / Math.log(2.0D))) - 1; + int step = (int)Math.ceil(1.6D * (double)mask * (double)size / (double)alphabet.length); + StringBuilder idBuilder = new StringBuilder(); + + while(true) { + byte[] bytes = new byte[step]; + random.nextBytes(bytes); + + for(int i = 0; i < step; ++i) { + int alphabetIndex = bytes[i] & mask; + if (alphabetIndex < alphabet.length) { + idBuilder.append(alphabet[alphabetIndex]); + if (idBuilder.length() == size) { + return idBuilder.toString(); + } + } + } + } + } + } else { + throw new IllegalArgumentException("alphabet must contain between 1 and 255 symbols."); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 1000; i++) { + System.out.println(randomNanoId()); + } + } +} diff --git a/src/main/java/com/qs/serve/common/util/PageUtil.java b/src/main/java/com/qs/serve/common/util/PageUtil.java new file mode 100644 index 0000000..9ce2e31 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/PageUtil.java @@ -0,0 +1,189 @@ +package com.qs.serve.common.util; + +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.pagehelper.PageHelper; +import com.qs.serve.common.framework.exception.BusinessException; +import lombok.experimental.UtilityClass; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 翻页工具类 + * @Author YenHex + * @Date 2021/6/9 + * @Version: 1.0 + **/ +@UtilityClass +public class PageUtil { + + private static final String PAGE_NUM = "pageNum"; + private static final String PAGE_SIZE = "pageSize"; + + private static final String ORDER_TYPE = "orderType"; + private static final String ORDER_PROP = "orderProp"; + + private static final String ORDER_TYPE_ASC = "ASC"; + private static final String ORDER_TYPE_DESC = "DESC"; + + private static final int MAX_PAGE_SIZE = 100; + + public static Page getMbpPage(){ + Integer pageNum = getPageNum(); + Integer pageSize = getPageSize(); + String orderProp = getOrderProp(); + String orderType = getOrderType(); + if ( pageNum ==null || pageNum<1 || pageSize==null || pageSize<1) { + throw new BusinessException("翻页参数异常",500); + } + Page page = new Page<>(); + page.setCurrent(pageNum); + page.setSize(pageSize); + if(StringUtils.hasText(orderProp)){ + OrderItem orderItem = new OrderItem(); + orderItem.setColumn(orderProp); + orderItem.setAsc(orderType.equals(ORDER_TYPE_ASC)); + List orderItems = new ArrayList<>(); + orderItems.add(orderItem); + page.setOrders(orderItems); + } + return page; + } + + public static Integer getPageNum(){ + Integer pageNum=null; + String pageNumStr = ServletUtils.getParameter(PAGE_NUM); + if(!StringUtils.hasText(pageNumStr)){ + Object pageNumObj = ServletUtils.getSession().getAttribute(PAGE_NUM); + if(pageNumObj!=null){ + pageNumStr = pageNumObj.toString(); + } + } + if(StringUtils.hasText(pageNumStr)){ + pageNum = Integer.parseInt(pageNumStr); + } + return pageNum; + } + + public static Integer getPageSize(){ + String pageSizeStr = ServletUtils.getParameter(PAGE_SIZE); + Integer pageSize = null; + if(!StringUtils.hasText(pageSizeStr)){ + Object pageNumObj = ServletUtils.getSession().getAttribute(PAGE_SIZE); + if(pageNumObj!=null){ + pageSizeStr = pageNumObj.toString(); + } + } + if(StringUtils.hasText(pageSizeStr)){ + pageSize = Integer.parseInt(pageSizeStr); + } + if(pageSize!=null && pageSize > MAX_PAGE_SIZE){ + throw new BusinessException("超出数据额度",500); + } + return pageSize; + } + + public static String getOrderProp(){ + String orderProp = ServletUtils.getParameter(ORDER_PROP); + if(StringUtils.hasText(orderProp)){ + orderProp = orderProp.trim(); + if(orderProp.contains(".")){ + String[] strings = orderProp.split("\\."); + return strings[0]+"."+strings[1]; + } + return WordUtil.toLine(orderProp); + } + return null; + } + + public static void setPageSize(String pageSize){ + ServletUtils.getSession().setAttribute(PAGE_SIZE,pageSize); + } + + public static void setPageNum(String pageNum){ + ServletUtils.getSession().setAttribute(PAGE_NUM,pageNum); + } + + public static String getOrderType(){ + String orderType = ServletUtils.getParameter(ORDER_TYPE); + if(StringUtils.hasText(orderType)){ + if(orderType.equalsIgnoreCase(ORDER_TYPE_DESC)){ + return ORDER_TYPE_DESC; + } + } + return ORDER_TYPE_ASC; + } + + public static Integer getStartRow(){ + Integer pageNum = getPageNum(); + Integer pageSize = getPageSize(); + if (pageNum==null || pageSize==null) { + throw new BusinessException("翻页参数异常",500); + } + return (pageNum-1)*pageSize; + } + + /** + * 启动翻页(翻页失败,会抛出异常) + * @return 是否使用翻页 + */ + public static boolean startPage(){ + return startPage(true); + } + + /** + * + * @param throwEx 是否抛异常 + * @return 是否使用翻页 + */ + public static boolean startPage(boolean throwEx){ + return startPage(null,null,throwEx); + } + + /** + * 执行翻页 + * @param object POJO + * @return 是否使用翻页 + */ + public static boolean startPage(T object){ + return startPage(object,null,true); + } + + public static boolean startPage(String prefix){ + return startPage(null,prefix,true); + } + /** + * + * @param throwEx 是否抛异常 + * @return 是否使用翻页 + */ + public static boolean startPage(T object,String prefix,boolean throwEx){ + Integer pageNum = getPageNum(); + Integer pageSize = getPageSize(); + String orderProp = getOrderProp(); + String orderType = getOrderType(); + if (pageNum!=null && pageNum>0 && pageSize!=null && pageSize>0) { + if(!StringUtils.isEmpty(orderProp)){ + if(prefix==null && object!=null){ + prefix = WordUtil.toLine(object.getClass().getSimpleName()); + } + if(prefix!=null){ + PageHelper.startPage(pageNum, pageSize).setOrderBy(prefix+"."+orderProp+" "+orderType); + }else { + PageHelper.startPage(pageNum, pageSize).setOrderBy(orderProp+" "+orderType); + } + return true; + } + PageHelper.startPage(pageNum, pageSize); + return true; + }else{ + if(throwEx){ + throw new BusinessException("翻页参数异常",500); + } + return false; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/ServletUtils.java b/src/main/java/com/qs/serve/common/util/ServletUtils.java new file mode 100644 index 0000000..d1f4abb --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/ServletUtils.java @@ -0,0 +1,135 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.model.consts.GySysConst; +import lombok.experimental.UtilityClass; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * Servlet容器工具类 + * @author YenHex + * @date 2021/6/9 + **/ +@UtilityClass +public class ServletUtils { + /** + * 获取String参数 + */ + public static String getParameter(String name) { + return getRequest().getParameter(name); + } + + public static String getAuthToken(){ + HttpServletRequest request = getRequest(); + return request.getHeader(GySysConst.AUTHORIZATION_PROP); + } + + /** + * 获取String参数 + */ + public static String getHeader(String name) { + return getRequest().getHeader(name); + } + + /** + * 获取IP + * @return + */ + public static String getIp(HttpServletRequest request) { + if(request==null){ + request = getRequest(); + } + 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(); + } + return ip; + } + + /** + * 判断本次请求的数据类型是否为json + * @param request request + * @return true: 是 JSON 数据; false: 非 json 数据 + */ + public static boolean isJsonRequest(HttpServletRequest request) { + if (request.getContentType() != null) { + return request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) || + request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE); + } + return false; + } + + /** + * 获取请求Body + * @param request + * @return + */ + public static String getBodyString(ServletRequest request) { + StringBuilder sb = new StringBuilder(); + InputStream inputStream = null; + BufferedReader reader = null; + try { + inputStream = request.getInputStream(); + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return sb.toString(); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + private static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/SmsReflectUtil.java b/src/main/java/com/qs/serve/common/util/SmsReflectUtil.java new file mode 100644 index 0000000..22b0dce --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/SmsReflectUtil.java @@ -0,0 +1,50 @@ +package com.qs.serve.common.util; + +import com.qs.serve.modules.wx.common.model.WxSmsProp; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/16 + */ +public class SmsReflectUtil { + + /** + * 反射获取WX_SMS配置 + * @param baseDto + * @param + * @return + */ + public static List getTemplateDataList(T baseDto){ + List dataList = new ArrayList<>(); + for (Field field : baseDto.getClass().getDeclaredFields()) { + WxSmsProp wxSmsProp = null; + for (Annotation annotation : field.getAnnotations()) { + if(annotation instanceof WxSmsProp){ + wxSmsProp = (WxSmsProp)annotation; + break; + } + } + try { + field.setAccessible(true); + Object fieldObject = field.get(baseDto); + String value = ""; + if(fieldObject!=null){ + value = fieldObject.toString(); + } + WxMpTemplateData templateData = new WxMpTemplateData(wxSmsProp.keyword(),value); + dataList.add(templateData); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return dataList; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/SpringUtils.java b/src/main/java/com/qs/serve/common/util/SpringUtils.java new file mode 100644 index 0000000..f38b899 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/SpringUtils.java @@ -0,0 +1,148 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.collection.CollectionUtil; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +/** + * spring工具类 + * @author YenHex + * @since 2022/2/28 + */ +@Component +public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtils.applicationContext = applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return CollectionUtil.isNotEmpty(Arrays.asList(activeProfiles)) ? activeProfiles[0] : null; + } +} diff --git a/src/main/java/com/qs/serve/common/util/SqlServerUtil.java b/src/main/java/com/qs/serve/common/util/SqlServerUtil.java new file mode 100644 index 0000000..46b94ce --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/SqlServerUtil.java @@ -0,0 +1,157 @@ +package com.qs.serve.common.util; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.microsoft.sqlserver.jdbc.SQLServerBulkCopy; +import com.microsoft.sqlserver.jdbc.SQLServerBulkCopyOptions; +import com.sun.rowset.CachedRowSetImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.type.JdbcType; +import org.springframework.beans.factory.annotation.Value; + +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.sql.*; +import java.util.List; + +/** + * SQL Server工具类 + * @author Trouble + * @version 1.0 + * @since 2024-04-25 15:00 + */ +@Slf4j +public class SqlServerUtil { + + /** + * 批量插入数据库 + * + * @param connectionUrl 数据库连接地址 + * @param list 要保存的对象集 + * @throws SQLException 插入对象失败 + */ + public static void batchInsert(String connectionUrl, List list) throws SQLException, IllegalAccessException { + long start = System.currentTimeMillis(); + String tableName = null; + //获取表名 + for (T t : list) { + TableName tableNameAnnotation = t.getClass().getAnnotation(TableName.class); + tableName = tableNameAnnotation.value(); + break; + } + + CachedRowSetImpl crs = getCachedRowSet(connectionUrl, tableName); + // 将对象转化为行数据 + for (Object obj : list) { + // 以动指针到插入行(虚拟行) + crs.moveToInsertRow(); + // 设置虚拟行相应的字段与数值;注意:字符串中的字段名与类型要与数据表中的一致 + Field[] declaredFields = obj.getClass().getDeclaredFields(); + for (Field field : declaredFields) { + + if(field.getName().equals("serialVersionUID")){ + continue; + } + + field.setAccessible(true); + + TableField tableField = field.getAnnotation(TableField.class); + String fieldName; + // 如果字段名不存在,则跳过 + // 如果字段名为空,则使用默认字段名称 + if (tableField != null) { + if (!tableField.exist()) { + continue; + } + fieldName = tableField.value(); + } else { + fieldName = field.getName(); + } + Object fieldValue = field.get(obj); + + if (tableField != null && tableField.jdbcType().equals(JdbcType.FLOAT)) { + crs.updateBigDecimal(fieldName, (BigDecimal) fieldValue); + } + else { + crs.updateObject(fieldName, fieldValue); + } + } + // 将虚拟行插入缓存 + crs.insertRow(); + // 将指针移动到当前行 + crs.moveToCurrentRow(); + } + saveRows(connectionUrl, tableName, crs, list.size()); + long end = System.currentTimeMillis(); + log.info("批量插入数据表{}成功,数量:{}条,耗时:{}ms", tableName, list.size(), end - start); + } + + /** + * 获取数据表的结构 + * + * @param url 链接对象 + * @param tableName 表名字 + * @return 数据表字段初始化的数据对象 + * @throws SQLException 数据表字段初始化失败 + */ + public static CachedRowSetImpl getCachedRowSet(String url, String tableName) throws SQLException { + // 链接方式固定(配置) + Connection con = connection(url); + String sql = String.format("select * from %s where 1 = 0", tableName); + // 执行sql语句封装 + PreparedStatement ps = con.prepareStatement(sql); + // 执行语句 + ResultSet rs = ps.executeQuery(); + // 创建行操作对象 + CachedRowSetImpl crs = new CachedRowSetImpl(); + // 设置表字段 + crs.populate(rs); + // 关闭流资源 + rs.close(); + // 关闭数据库链接 + con.close(); + // 返回含有表字段的行操作对象 + return crs; + } + + /** + * 连接数据库 + * + * @param connectionUrl 链接URL + * @return 链接对象 + * @throws SQLException 建立链接失败异常 + */ + public static Connection connection(String connectionUrl) throws SQLException { + return DriverManager.getConnection(connectionUrl); + } + + /** + * 将数据插入数据库 + * + * @param connectionUrl 数据库连接地址 + * @param tableName 数据表名称 + * @param crs 数据行操作对象 + * @param size 数据量 + * @throws SQLException 插入数据失败异常 + */ + public static void saveRows(String connectionUrl, String tableName, CachedRowSetImpl crs, int size) throws SQLException { + SQLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions(); + copyOptions.setKeepIdentity(true); + // 设置批量插入的数量 + copyOptions.setBatchSize(size); + // 开启事务 + copyOptions.setUseInternalTransaction(true); + // 配置url + SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(connectionUrl); + // 设置批量操作参数 + bulkCopy.setBulkCopyOptions(copyOptions); + // 设置要操作的表名 + bulkCopy.setDestinationTableName(tableName); + // 将数据保存到数据库 + bulkCopy.writeToServer(crs); + // 释放资源 + crs.close(); + // 释放资源 + bulkCopy.close(); + } +} diff --git a/src/main/java/com/qs/serve/common/util/StringUtils.java b/src/main/java/com/qs/serve/common/util/StringUtils.java new file mode 100644 index 0000000..0b88a7c --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/StringUtils.java @@ -0,0 +1,141 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author YenHex + * @since 2022/2/28 + */ +@UtilityClass +public class StringUtils extends org.springframework.util.StringUtils { + + /** 订单号生成(NEW) **/ + private static final AtomicInteger SEQ = new AtomicInteger(1000); + private static final AtomicInteger SEQ2 = new AtomicInteger(10001); + private static final DateTimeFormatter DF_FMT_PREFIX = DateTimeFormatter.ofPattern("yyMMddHHmmssSS"); + private static ZoneId ZONE_ID = ZoneId.of("Asia/Shanghai"); + + public static String generateOrderNo(){ + LocalDateTime dataTime = LocalDateTime.now(ZONE_ID); + if(SEQ.intValue()>9990){ + SEQ.getAndSet(1000); + } + return dataTime.format(DF_FMT_PREFIX)+SEQ.getAndIncrement(); + } + + public static String genShortId() { + // 2 位 年份的后两位 22001 后五位走随机 每天清一次缓存 99999 10 + StringBuilder idSb = new StringBuilder(); + /// 年份后两位 和 一年中的第几天 + LocalDate now = LocalDate.now(); + String year = now.getYear() + ""; + year = year.substring(2); + String day = now.getDayOfYear() + ""; + /// 补0 + if (day.length() < 3) { + StringBuilder sb = new StringBuilder(); + for (int i = day.length(); i < 3; i++) { + sb.append("0"); + } + day = sb.append(day).toString(); + } + idSb.append(year).append(day); + /// 后五位补随机数 + if(SEQ2.intValue()>99900){ + SEQ2.getAndSet(10000); + } + idSb.append(SEQ2.getAndIncrement()); + return idSb.toString(); + } + + public static void main(String[] args) { + for (int i = 0; i < 100; i++) { + System.out.println(genShortId()); + //System.out.println(generateOrderNo()); + } + } + + public static String tailorLen(String str,int len){ + if(StringUtils.hasText(str)&&str.length()>len){ + return str.substring(0,len-2)+"..."; + } + return str; + } + + /** 非空 */ + public static boolean isNotEmpty(String str){ + return !isEmpty(str); + } + + /** 含有空对象 */ + public static boolean hasEmpty(Object... strings){ + for (Object str : strings) { + if(isEmpty(str)){return true;} + } + return false; + } + + public static String getUrlByList(List list,String param){ + StringBuilder sb = new StringBuilder(); + for (Object val : list) { + sb.append("&"+param+"="+val); + } + return sb.toString(); + } + + /** + * 格式化 + * @param exp 含{}的表达式 + * @param params 参数(注意跳过空值) + * @return + */ + public static String format(String exp,String... params){ + StringBuilder builder = new StringBuilder(exp); + int idx_p = 0; + while (hasText(builder,"{}")){ + int idx = builder.indexOf("{}"); + if(idx_p splitIdString(String ids){ + if(ids==null){ + return null; + } + if(ids.contains(",")){ + String[] idsA= ids.split(","); + return Arrays.asList(idsA); + } + return Arrays.asList(ids); + } + + public static List splitIdLong(String ids){ + List strs = splitIdString(ids); + if(strs!=null){ + return strs.stream().map(Long::parseLong).collect(Collectors.toList()); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/ThreadsUtils.java b/src/main/java/com/qs/serve/common/util/ThreadsUtils.java new file mode 100644 index 0000000..03f7e2d --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/ThreadsUtils.java @@ -0,0 +1,75 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.*; + + +/** + * 线程相关 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@UtilityClass +public class ThreadsUtils { + + /** + * sleep等待,单位为毫秒 + */ + public static void sleep(long milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) { + return; + } + } + + /** + * 停止线程池 + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. + * 如果仍人超時,則強制退出. + * 另对在shutdown时线程本身被调用中断做了处理. + */ + public static void shutdownAndAwaitTermination(ExecutorService pool) { + if (pool != null && !pool.isShutdown()) { + pool.shutdown(); + try { + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { + pool.shutdownNow(); + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { + log.info("Pool did not terminate"); + } + } + } catch (InterruptedException ie) { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + /** + * 打印线程异常信息 + */ + public static void printException(Runnable r, Throwable t) { + if (t == null && r instanceof Future) { + try { + Future future = (Future) r; + if (future.isDone()) { + future.get(); + } + } catch (CancellationException ce) { + t = ce; + } catch (ExecutionException ee) { + t = ee.getCause(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + if (t != null) { + log.error(t.getMessage(), t); + } + } +} diff --git a/src/main/java/com/qs/serve/common/util/TokenUtil.java b/src/main/java/com/qs/serve/common/util/TokenUtil.java new file mode 100644 index 0000000..89aec72 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/TokenUtil.java @@ -0,0 +1,46 @@ +package com.qs.serve.common.util; + + +import com.qs.serve.common.util.model.DesUtils; + +/** + * @author YenHex + * @since 2022/2/25 + */ +public class TokenUtil { + + private static final String secretKey = "N2aD7vLTJjeo71vCHwbqYsSF9rZPUh"; + + /** + * 加密 + * @param userId + * @return + */ + public static String desEncrypt(String userId){ + String formatStr = userId+"-N2aD7vLTJjeo71vCHwbqYsSF9rZPUh"; + DesUtils des = new DesUtils(secretKey); + try { + return des.encrypt(formatStr); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 解密 + * @param encryptText + * @return clientId + */ + public static String desDecrypt(String encryptText){ + DesUtils des = new DesUtils(secretKey); + try { + String formatStr = des.decrypt(encryptText); + return formatStr.split("-")[0]; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/TreeUtil.java b/src/main/java/com/qs/serve/common/util/TreeUtil.java new file mode 100644 index 0000000..99dd8e3 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/TreeUtil.java @@ -0,0 +1,74 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.model.dto.TreeNode; +import lombok.experimental.UtilityClass; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@UtilityClass +public class TreeUtil { + + public static final String DEFAULT_PID_STRING = "0"; + + /** + * 两层循环实现建树 + * @param treeNodes 传入的树节点列表 + * @param rootPid + * @return + * sorted(Comparator.comparingInt(DemoEntity::getSort)) + */ + public List build(List treeNodes, String rootPid) { + List trees = new ArrayList<>(); + for (T treeNode : treeNodes) { + if (rootPid.equals(treeNode.getParentId())) { + trees.add(treeNode); + } + for (T it : treeNodes) { + if (it.getParentId().equals(treeNode.getId())) { + treeNode.addChildren(it); + } + } + } + return trees; + } + + /** + * 使用递归方法建树 + * + * @param treeNodes + * @return + */ + public List buildByRecursive(List treeNodes, Object root) { + List trees = new ArrayList(); + for (T treeNode : treeNodes) { + if (root.equals(treeNode.getParentId())) { + trees.add(findChildren(treeNode, treeNodes)); + } + } + return trees; + } + + /** + * 递归查找子节点 + * + * @param treeNodes + * @return + */ + public T findChildren(T treeNode, List treeNodes) { + for (T it : treeNodes) { + if (treeNode.getId().equals(it.getParentId())) { + if (treeNode.getChildren() == null) { + treeNode.setChildren(new ArrayList<>()); + } + treeNode.addChildren(findChildren(it, treeNodes)); + } + } + return treeNode; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/UploadUtil.java b/src/main/java/com/qs/serve/common/util/UploadUtil.java new file mode 100644 index 0000000..09eb9e5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/UploadUtil.java @@ -0,0 +1,53 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.io.FileUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; + +/** + * @author YenHex + * @since 2022/3/14 + */ +@Slf4j +public class UploadUtil { + + /** + * 返回相对地址 + * @param uploadPath 物理路径 + * @param fileName2 文件名 + * @param request + * @return + */ + public static String put(String uploadPath,final String fileName2,HttpServletRequest request){ + String contentType = request.getContentType(); + MultipartFile file = null; + if (contentType != null && contentType.toLowerCase().startsWith("multipart")) { + MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class); + file = multipartHttpServletRequest.getFile("file"); + } + if (file==null||file.isEmpty()) { + Assert.throwEx("请选择文件"); + } + String fileOrgName = file.getOriginalFilename(); + String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf(".")); + String fileName = fileName2 + mimeType ; + String prefix = LocalDate.now().toString().replace("-","")+"/"; + try { + FileUtil.createTempFile(new File(uploadPath+prefix)); + File dest = new File(uploadPath + prefix + fileName); + file.transferTo(dest); + return prefix + fileName; + } catch (IOException e) { + log.error(e.toString(), e); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/ValidateTools.java b/src/main/java/com/qs/serve/common/util/ValidateTools.java new file mode 100644 index 0000000..9f53ded --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/ValidateTools.java @@ -0,0 +1,85 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.framework.exception.BusinessException; +import lombok.experimental.UtilityClass; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.validator.HibernateValidator; +import org.springframework.util.CollectionUtils; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.util.List; +import java.util.Set; +/** + * validate方法中校验工具类 + *

+ * 只要在实体中加上相应的validate的相关注解即可 + *

+ * + * @author Zed + */ +@UtilityClass +public class ValidateTools { + /** + * 初始化检查器 + */ + private static final ValidatorFactory VALIDATOR_FACTORY = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory(); + private static final Validator VALIDATOR = VALIDATOR_FACTORY.getValidator(); + /** + * 校验返回异常信息 + * + * @param t 实体 + * @param 实体泛型 + */ + public static String validStr(T t) { + // 构造返回信息 + StringBuilder validMessage = new StringBuilder(); + // 检查实体T + Set> set = VALIDATOR.validate(t); + // 循环set,获取检查结果 + for (ConstraintViolation vo : set) { + validMessage.append(vo.getMessage()).append(";"); + } + return validMessage.toString(); + } + /** + * 校验实体抛出异常 + * + * @param t 实体 + * @param 实体泛型 + */ + public static void valid(T t) { + String validStr = validStr(t); + // 抛出业务异常 + if (StringUtils.isNotBlank(validStr)) { + throw new BusinessException(validStr,500); + } + } + /** + * 校验集合抛出异常 + * + * @param list 列表 + * @param 实体泛型 + */ + public static void valid(List list) { + if (CollectionUtils.isEmpty(list)) { + throw new BusinessException("数据不存在!",500); + } + // 构造返回信息 + StringBuilder validMessageTotal = new StringBuilder(); + // 遍历 + for (int i = 0; i < list.size(); i++) { + String validStr = validStr(list.get(i)); + if (StringUtils.isNotBlank(validStr)) { + String msg = String.format("第%d条数据校验结果:[%s]\n", i + 1, validStr); + validMessageTotal.append(msg); + } + } + // 抛出业务异常 + if (StringUtils.isNotBlank(validMessageTotal.toString())) { + throw new BusinessException(validMessageTotal.toString(),500); + } + } +} diff --git a/src/main/java/com/qs/serve/common/util/WarpUtil.java b/src/main/java/com/qs/serve/common/util/WarpUtil.java new file mode 100644 index 0000000..94b6481 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/WarpUtil.java @@ -0,0 +1,62 @@ +package com.qs.serve.common.util; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.mybatis.query.AnnotationQueryStorage; +import com.qs.serve.common.framework.mybatis.query.model.QueryFieldDataValue; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * 生成SQL条件包装对象 + * @author YenHex + * @date 2022/2/28 + **/ +@UtilityClass +@Slf4j +public class WarpUtil extends AnnotationQueryStorage { + + private static final String ORDER_PROP_NAME = "prop"; + private static final String ORDER_TYPE_NAME = "order"; + private static final String ORDER_DESC = "desc"; + private static final String CREATE_TIME = "create_time"; + + private static final String START_TIME = "startTime"; + private static final String END_TIME = "endTime"; + + public static QueryWrapper build(T query){ + return build(query,false); + } + + public static QueryWrapper build(T query,Boolean orderAble){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + List dataValues = loadQueryFieldDataValues(query); + assert dataValues != null; + initWrap(dataValues,queryWrapper); + initBetweenTime(queryWrapper); + if(orderAble){ + String columnsString = ServletUtils.getParameter(ORDER_PROP_NAME); + String orderType = ServletUtils.getParameter(ORDER_TYPE_NAME); + if(StringUtils.isNotEmpty(columnsString)){ + String[] columns = columnsString.split(","); +// if(orderType.equals(ORDER_DESC)){ +// queryWrapper.orderByDesc(columns); +// }else { +// queryWrapper.orderByAsc(columns); +// } + } + } + return queryWrapper; + } + + public static void initBetweenTime(QueryWrapper queryWrapper){ + String startTime = ServletUtils.getParameter(START_TIME); + String endTime = ServletUtils.getParameter(END_TIME); + if(!StringUtils.hasEmpty(startTime,endTime)){ + queryWrapper.ge(CREATE_TIME,startTime); + queryWrapper.le(CREATE_TIME,endTime); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/WordUtil.java b/src/main/java/com/qs/serve/common/util/WordUtil.java new file mode 100644 index 0000000..8c48f7a --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/WordUtil.java @@ -0,0 +1,109 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; +import org.springframework.util.StringUtils; + +/** + * 单词间转换工具类 + * @author JcYen + * @Date 2020/5/27 + * @Version 1.0 + */ +@UtilityClass +public class WordUtil { + + public static String lowerFirst(String className){ + return lowerFirst(className,null); + } + + /** + * 类名首字母小写 + * @param className 类名 + * @param rmPrefix 移除的前缀,不区分大小写 + * @return + */ + public static String lowerFirst(String className,String rmPrefix){ + if(className==null){throw new RuntimeException("className is null");} + if(rmPrefix!=null){ + String prefix = className.substring(0,rmPrefix.length()); + if(prefix.toLowerCase().equals(rmPrefix.toLowerCase())){ + className = className.substring(rmPrefix.length()); + } + } + char[]chars = className.toCharArray(); + chars[0] += 32; + return String.valueOf(chars); + } + + /** + * 数据库表名 转 类名 : ums_user_log ->> UmsUserLog + * 1.首字母转小写 + * 2.下横线后的字母大写,去掉"_"下横线, + * @param tableName + * @return + */ + public static String tableToClass(String tableName) { + if(StringUtils.isEmpty(tableName)){return null;} + char[] chars = tableName.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if(Character.isLowerCase(chars[i])&&i==0){ + chars[i] = Character.toUpperCase(chars[i]); + } + if(chars[i] == '_' && i+1> umsUserLog + * 1.首字母转小写 + * 2.下横线后的字母大写,去掉"_"下横线, + * @param columnName + * @return + */ + public static String columnToField(String columnName) { + if(StringUtils.isEmpty(columnName)){return null;} + char[] chars = columnName.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if(chars[i] == '_' && i+1> ums_user_log + * 1.首字母转小写 + * 2.字符非首个字母,添加"_"下横线,并大写字母转小写 + * @param fieldName + * @return + */ + public static String toLine(String fieldName) { + if(StringUtils.isEmpty(fieldName)){return null;} + columnToField(fieldName); + char[] chars = fieldName.toCharArray(); + int countUpper = 0; + for (int i = 0; i < chars.length; i++) { + if(Character.isUpperCase(chars[i])&&i!=0){ + countUpper ++ ; + } + } + char[] newChars = new char[chars.length+countUpper]; + //偏移量 + int offset = 0; + for (int i = 0; i < chars.length; i++) { + if(Character.isUpperCase(chars[i])){ + if(i!=0){ + newChars[i+offset] = '_'; + offset++; + } + } + newChars[i+offset] = Character.toLowerCase(chars[i]); + } + return String.valueOf(newChars); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/model/DateFormatString.java b/src/main/java/com/qs/serve/common/util/model/DateFormatString.java new file mode 100644 index 0000000..43aa4e4 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/model/DateFormatString.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.util.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/3/17 + */ +@Getter +@AllArgsConstructor +public enum DateFormatString { + + DATE_TIME("yyyy-MM-dd HH:mm:ss"), + DATE_TIME2("yyyy-MM-dd HH:mm:ss.000"), + DATE_TIME_NUM("yyyyMMddHHmmss"), + DATE_TIME_CN("yyyy年MM月dd日 HH时mm分ss秒"), + + DATE("yyyy-MM-dd"), + DATE_NUM("yyyyMMdd"), + DATE_CN("yyyy年MM月dd日"); + + private String value; + +} diff --git a/src/main/java/com/qs/serve/common/util/model/DesUtils.java b/src/main/java/com/qs/serve/common/util/model/DesUtils.java new file mode 100644 index 0000000..2617af1 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/model/DesUtils.java @@ -0,0 +1,125 @@ +package com.qs.serve.common.util.model; + +import javax.crypto.Cipher; +import java.security.Key; + +/** + * 使用DES算法对字符串进行加密解密 (加密解密的操作步骤正好相反, 参考 {@link #encrypt(String)}, {@link #decrypt(String)}) + */ +public class DesUtils { + private static String defaultSecretKey = "default_secret_key"; //默认密钥 + private Cipher encryptCipher = null; //加密器 + private Cipher decryptCipher = null; //解密器 + + public DesUtils() throws Exception { + this(defaultSecretKey); + } + + /** + * @param secretKey 加密解密使用的密钥 + */ + public DesUtils(String secretKey) { + Key key; + try { + key = getKey(secretKey.getBytes()); + encryptCipher = Cipher.getInstance("DES"); + encryptCipher.init(Cipher.ENCRYPT_MODE, key); + decryptCipher = Cipher.getInstance("DES"); + decryptCipher.init(Cipher.DECRYPT_MODE, key); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 加密 (逻辑: 1. 将要加密的字符串转换为字节数组(byte array)
+ * 2. 将第一步的字节数组作为输入使用加密器(Cipher)的doFinal方法进行加密, 返回字节数组
+ * 3. 把加密后的字节数组转换成十六进制的字符串)
+ * @param strIn 要加密的字符串 + * @return 返回加密后的十六进制字符串 + * @throws Exception + */ + public String encrypt(String strIn) throws Exception { + return byteArr2HexStr(encrypt(strIn.getBytes())); + } + + public byte[] encrypt(byte[] arrB) throws Exception { + return encryptCipher.doFinal(arrB); + } + + /** + * 解密 (逻辑: 1. 把加密后的十六进制字符串转换成字节数组(byte array)
+ * 2. 将第一步的字节数组作为输入使用加密器(Cipher)的doFinal方法进行解密, 返回字节数组(byte array)
+ * 3. 把解密后的字节数组转换成字符串)
+ * @param strIn + * @return + * @throws Exception + */ + public String decrypt(String strIn) throws Exception { + return new String(decrypt(hexStr2ByteArr(strIn))); + } + + public byte[] decrypt(byte[] arrB) throws Exception { + return decryptCipher.doFinal(arrB); + } + + public static String byteArr2HexStr(byte[] arrB) throws Exception { + int iLen = arrB.length; + // 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍 + StringBuffer sb = new StringBuffer(iLen * 2); + for (int i = 0; i < iLen; i++) { + int intTmp = arrB[i]; + // 把负数转换为正数 + while (intTmp < 0) { + intTmp = intTmp + 256; + } + // 小于0F的数需要在前面补0 + if (intTmp < 16) { + sb.append("0"); + } + sb.append(Integer.toString(intTmp, 16)); + } + return sb.toString(); + } + + public static byte[] hexStr2ByteArr(String strIn) throws Exception { + byte[] arrB = strIn.getBytes(); + int iLen = arrB.length; + // 两个字符表示一个字节,所以字节数组长度是字符串长度除以2 + byte[] arrOut = new byte[iLen / 2]; + for (int i = 0; i < iLen; i = i + 2) { + String strTmp = new String(arrB, i, 2); + arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16); + } + return arrOut; + } + + private Key getKey(byte[] arrBTmp) throws Exception { + // 创建一个空的8位字节数组(默认值为0) + byte[] arrB = new byte[8]; + // 将原始字节数组转换为8位 + for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) { + arrB[i] = arrBTmp[i]; + } + // 生成密钥 + Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES"); + return key; + } + + + /** + * 用法实例 + */ + public static void main(String[] args) { + try { + String test = "liwc"; + DesUtils des = new DesUtils("leemenz"); //自定义密钥 + System.out.println("加密前的字符:" + test); + System.out.println("加密后的字符:" + des.encrypt(test)); + System.out.println("解密后的字符:" + des.decrypt(des.encrypt(test))); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/model/QsJsonLocalDateTimeDeserializer.java b/src/main/java/com/qs/serve/common/util/model/QsJsonLocalDateTimeDeserializer.java new file mode 100644 index 0000000..ad46dfb --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/model/QsJsonLocalDateTimeDeserializer.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.util.model; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * @author YenHex + * @since 2023/7/25 + */ +public class QsJsonLocalDateTimeDeserializer extends JsonDeserializer { + + final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + @Override + public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + String val = jsonParser.getText(); + if (val==null||val.isEmpty()){ + return null; + } + return LocalDateTime.parse(val,df); + } +} diff --git a/src/main/java/com/qs/serve/modules/oss/entity/OssPolicySignVo.java b/src/main/java/com/qs/serve/modules/oss/entity/OssPolicySignVo.java new file mode 100644 index 0000000..bb7dc03 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/oss/entity/OssPolicySignVo.java @@ -0,0 +1,19 @@ +package com.qs.serve.modules.oss.entity; + +import lombok.Data; + +/** + * @author YenHex + * @since 2023/3/23 + */ +@Data +public class OssPolicySignVo { + + private String accessId; + private String policy; + private String signature; + private String host; + private Long expire; + private String dir; + +} diff --git a/src/main/java/com/qs/serve/modules/oss/service/OssService.java b/src/main/java/com/qs/serve/modules/oss/service/OssService.java new file mode 100644 index 0000000..34c0b5f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/oss/service/OssService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.oss.service; + +import com.aliyun.oss.OSS; +import com.qs.serve.modules.oss.entity.OssPolicySignVo; + +/** + * @author YenHex + * @since 2023/3/23 + */ +public interface OssService { + + /** + * 获取文件签名 + * @return + */ + OssPolicySignVo getPolicySign(); + + OSS getOSSClient(); + +} diff --git a/src/main/java/com/qs/serve/modules/oss/service/impl/OssServiceImpl.java b/src/main/java/com/qs/serve/modules/oss/service/impl/OssServiceImpl.java new file mode 100644 index 0000000..87f32ce --- /dev/null +++ b/src/main/java/com/qs/serve/modules/oss/service/impl/OssServiceImpl.java @@ -0,0 +1,84 @@ +package com.qs.serve.modules.oss.service.impl; + +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.common.utils.BinaryUtil; +import com.aliyun.oss.model.MatchMode; +import com.aliyun.oss.model.PolicyConditions; +import com.qs.serve.common.config.properties.AliYunOssProperties; +import com.qs.serve.modules.oss.entity.OssPolicySignVo; +import com.qs.serve.modules.oss.service.OssService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.io.UnsupportedEncodingException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author YenHex + * @since 2023/3/23 + */ +@Service +@AllArgsConstructor +public class OssServiceImpl implements OssService { + + AliYunOssProperties aliYunOSSProperties; + + @Override + public OSS getOSSClient() { + // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。 + String endpoint = aliYunOSSProperties.getEndpoint(); + // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 + String accessKeyId = aliYunOSSProperties.getAccessKeyId(); + String accessKeySecret = aliYunOSSProperties.getAccessKeySecret(); + // 填写Bucket名称,例如examplebucket。 + String bucketName = aliYunOSSProperties.getBucket(); + // 创建OSSClient实例。 + return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + } + + @Override + public OssPolicySignVo getPolicySign() { + // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。 + String endpoint = aliYunOSSProperties.getEndpoint(); + // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 + String accessKeyId = aliYunOSSProperties.getAccessKeyId(); + String accessKeySecret = aliYunOSSProperties.getAccessKeySecret(); + // 填写Bucket名称,例如examplebucket。 + String bucketName = aliYunOSSProperties.getBucket(); + // 创建OSSClient实例。 + String accessUrl = "https://"+bucketName+"."+endpoint; + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM/dd"); + String prefix = aliYunOSSProperties.getPrefix(); + String dir = prefix + "/" + sdf.format(new Date())+"/"; + + + long expireTime = 300; + long expireEndTime = System.currentTimeMillis() + expireTime * 1000; + Date expiration = new Date(expireEndTime); + PolicyConditions policyConds = new PolicyConditions(); + policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); + policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); + + String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); + byte[] binaryData = new byte[0]; + try { + binaryData = postPolicy.getBytes("utf-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + String encodedPolicy = BinaryUtil.toBase64String(binaryData); + String postSignature = ossClient.calculatePostSignature(postPolicy); + OssPolicySignVo policySignVo = new OssPolicySignVo(); + policySignVo.setAccessId(accessKeyId); + policySignVo.setPolicy(encodedPolicy); + policySignVo.setSignature(postSignature); + policySignVo.setHost(accessUrl); + policySignVo.setExpire(expireEndTime / 1000); + policySignVo.setDir(dir); + return policySignVo; + } + +} diff --git a/src/main/java/com/qs/serve/modules/portal/AdminPortalController.java b/src/main/java/com/qs/serve/modules/portal/AdminPortalController.java new file mode 100644 index 0000000..7bf4697 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/portal/AdminPortalController.java @@ -0,0 +1,165 @@ +package com.qs.serve.modules.portal; + +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.config.properties.ProjectProperties; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysTenant; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam; +import com.qs.serve.modules.sys.entity.dto.SysLoginParam; +import com.qs.serve.modules.sys.entity.dto.SysResetPwdByPhoneParam; +import com.qs.serve.modules.sys.service.SysTenantService; +import com.qs.serve.modules.sys.service.SysUserLoginService; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 门户:后台接口 + * @author YenHex + * @since 2022/3/2 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("portal") +public class AdminPortalController { + + private SysTenantService sysTenantService; + private SysUserLoginService sysUserLoginService; + private RedisService redisService; + private SysUserService sysUserService; + private ProjectProperties projectProperties; + + /** + * 获取所有租户 + * @return + */ + @GetMapping("/listTenant") + public R> getList(){ + List list = sysTenantService.list2(); + return R.ok(list); + } + + + /** + * 登录接口 + * @return + */ + @LimitSubmit + @SysLog(title = "人员",desc = "后台登录",biz = BizType.LOGIN,saveReqParam = false) + @PostMapping("/login") + public R login(@RequestBody @Valid SysLoginParam param){ + return R.ok(sysUserLoginService.login(param)); + } + + + /** + * 登录接口 + * @return + */ + @PostMapping("/flushToken") + public R flushToken(HttpServletRequest request){ + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + String userId = JwtUtils.getUserId(token); + String client = JwtUtils.getClient(token); + String redisKey = com.qs.serve.common.util.StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,userId); + Map tokenMap = new HashMap<>(10); + String token2 = JwtUtils.generateToken(userId, LoginUserType.SYS_USER,client); + redisService.set(redisKey,token2); + tokenMap.put("token", token2); + tokenMap.put("client",client); + return R.ok(tokenMap); + } + + /** + * 手机登陆 + * @return + */ + @LimitSubmit + @SysLog(title = "人员",desc = "手机登陆",biz = BizType.LOGIN,saveReqParam = false) + @PostMapping("/phoneLogin") + public R phoneLogin(@RequestBody @Valid SysLoginByPhoneParam param){ + return R.ok(sysUserLoginService.login(param)); + } + + /** + * 登出接口 + * @return + */ + @SysLog(title = "人员",desc = "退出登录",biz = BizType.LOGOUT,saveReqParam = false) + @GetMapping("/logout") + public R login(){ + return R.ok(); + } + + + /** + * 获取用户手机验证码 + */ + @LimitSubmit(interval = 10000,message = "请10秒后尝试") + @SysLog(title = "人员",desc = "获取用户手机验证码",biz = BizType.OTHER) + @GetMapping("/userPhoneCode/{phone}") + public R phoneCode(@PathVariable("phone") String phone){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,phone); + Long count = sysUserService.count(wrapper); + if(count<1L){ + return R.error("无效手机号,请重新输入"); + } + String key = RedisCacheKeys.PHONE_KEY+phone; + String code = redisService.getString(key); + if(code==null){ + code = IdUtil.genCode(6); + } + redisService.set(key,code,1, TimeUnit.MINUTES); + // send msg + return R.ok(); + } + + /** + * 重置手机用户密码 + */ + @LimitSubmit(interval = 10000,message = "请10秒后尝试") + @SysLog(title = "人员",desc = "重置手机用户密码",biz = BizType.RESET) + @PostMapping("/resetPwdByPhone") + public R phoneCode(@RequestBody @Valid SysResetPwdByPhoneParam param){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,param.getPhone()); + List userList = sysUserService.list(wrapper); + if(userList.size()<1){ + return R.error("无效手机号,请重新输入"); + } + String key = RedisCacheKeys.PHONE_KEY+param.getPhone(); + String code = redisService.getString(key); + if(!param.getCode().equals(code)){ + return R.error("验证码无效或过期"); + } + SysUser sysUser = new SysUser(); + sysUser.setId(userList.get(0).getId()); + sysUser.setPassword(SecureUtil.md5(param.getNewPwd())); + sysUserService.updateById(sysUser); + return R.ok(); + } + + +} diff --git a/src/main/java/com/qs/serve/modules/portal/CommonApi.java b/src/main/java/com/qs/serve/modules/portal/CommonApi.java new file mode 100644 index 0000000..e999f8c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/portal/CommonApi.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.portal; + +import com.qs.serve.common.model.dto.R; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; + +/** + * 门户:API通用接口 + * @author YenHex + * @since 2022/3/14 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/common") +public class CommonApi { + + + +} diff --git a/src/main/java/com/qs/serve/modules/portal/CommonController.java b/src/main/java/com/qs/serve/modules/portal/CommonController.java new file mode 100644 index 0000000..9124ed3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/portal/CommonController.java @@ -0,0 +1,115 @@ +package com.qs.serve.modules.portal; + +import com.qs.serve.common.config.properties.UploadProperties; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.oss.service.OssService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +/** + * 门户:后台通用接口 + * @author YenHex + * @since 2022/3/14 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/common") +public class CommonController { + + private UploadProperties uploadProperties; + + private OssService ossService; + + /** + * 获取签名 + * @param request + * @return + */ + @GetMapping("/getSign") + public R getSign(HttpServletRequest request) { + return R.ok(ossService.getPolicySign()); + } + + + /** + * 单图上传 + * @apiNote file不能为空 + * @param request + * @return + */ + @SysLog(title = "文件",biz = BizType.UPLOAD) + @PostMapping("/upload") + public R upload(HttpServletRequest request) { + String relativePath = UploadUtil.put(uploadProperties.getLogicalPath(),IdUtil.timeStampId(),request); + if(relativePath!=null){ + return R.ok(uploadProperties.getProxyUrl()+relativePath,"上传成功"); + } + return R.error("上传失败"); + } + + /** + * 验证token + * @param token + * @return + */ + @PostMapping("/validToken") + public R validToken(String token) { + return R.isOk(JwtUtils.verify(token),"无效token"); + } + + /** + * 多图上传 + * @apiNote files不能为空 + * @param request + * @return + */ + @SysLog(title = "文件",biz = BizType.UPLOAD) + @PostMapping( "/uploadMulti") + public R multiUpload(HttpServletRequest request) { + String contentType = request.getContentType(); + List files = null; + if (contentType != null && contentType.toLowerCase().startsWith("multipart")) { + MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class); + files = multipartHttpServletRequest.getFiles("files"); + } + if (files==null||files.isEmpty()) { + return R.error("请选择文件"); + } + List list = new ArrayList<>(); + for (int i = 0; i < files.size(); i++) { + MultipartFile file = files.get(i); + if (file.isEmpty()) { + return R.error("上传第" + (i++) + "个文件失败"); + } + String fileOrgName = file.getOriginalFilename(); + String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf(".")); + String filePath = LocalDate.now().toString().replace("-","")+"/"+ IdUtil.timeStampId()+mimeType; + String uploadPath = uploadProperties.getLogicalPath(); + File dest = new File(uploadPath + filePath); + try { + file.transferTo(dest); + list.add(uploadProperties.getProxyUrl()+filePath); + } catch (IOException e) { + log.error(e.toString(), e); + return R.error("上传第" + (i++) + "个文件失败"); + } + } + return R.ok(list); + } + +} diff --git a/src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java b/src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java new file mode 100644 index 0000000..2ee7c7e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.sys.common.consts; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public class SysStatusConst { + + /** 类型【0->菜单;1->按钮】 */ + public static final int SysPermission_Type_0 = 0; + public static final int SysPermission_Type_1 = 1; + + /** 超级管理标识【0->普通管理员;1->超级管理员】 */ + public static final int SysUser_SuperFlag_0 = 0; + public static final int SysUser_SuperFlag_1 = 1; + + + /** 可见类型【0->所有人可见;1->部分人员可见;2->部门可见】 */ + public static final int SysNotice_VisibleType_0 = 0; + public static final int SysNotice_VisibleType_1 = 1; + public static final int SysNotice_VisibleType_2 = 2; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/common/enums/BusinessLogOption.java b/src/main/java/com/qs/serve/modules/sys/common/enums/BusinessLogOption.java new file mode 100644 index 0000000..d355235 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/common/enums/BusinessLogOption.java @@ -0,0 +1,19 @@ +package com.qs.serve.modules.sys.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2023/4/25 + */ +@Getter +@AllArgsConstructor +public enum BusinessLogOption { + + SAVE("新增"), + UPDATE("修改"), + DELETE("删除"); + String label; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/common/enums/BusinessLogType.java b/src/main/java/com/qs/serve/modules/sys/common/enums/BusinessLogType.java new file mode 100644 index 0000000..75d7a1c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/common/enums/BusinessLogType.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2023/4/25 + */ +@Getter +@AllArgsConstructor +public enum BusinessLogType { + + SupplierContacts("客户联系人"), + SupplierAddress("客户地址"), + Point("网点信息"); + + String label; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java new file mode 100644 index 0000000..261c4cf --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java @@ -0,0 +1,143 @@ +package com.qs.serve.modules.sys.controller; + +import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.config.properties.UploadProperties; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.service.SysAttachService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +/** + * 系统:系统附件 + * @author YenHex + * @since 2022-03-24 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/attach") +public class SysAttachController { + + private SysAttachService sysAttachService; + + private UploadProperties uploadProperties; + + /** + * 附件上传 + * @param request + * @return + */ + @SysLog(title = "附件",biz = BizType.UPLOAD) + @PostMapping("/upload") + public R upload(HttpServletRequest request) { + String uploadPath = uploadProperties.getLogicalPath(); + String contentType = request.getContentType(); + MultipartFile file = null; + if (contentType != null && contentType.toLowerCase().startsWith("multipart")) { + MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class); + file = multipartHttpServletRequest.getFile("file"); + } + if (file==null||file.isEmpty()) { + Assert.throwEx("请选择文件"); + } + String fileOrgName = file.getOriginalFilename(); + String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf(".")); + String prefix = LocalDate.now().toString().replace("-","")+"/"; + try { + FileUtil.createTempFile(new File(uploadPath+prefix)); + String newName = IdUtil.timeStampId(); + String fileType = mimeType.toLowerCase(Locale.ROOT); + String relativeName = prefix + newName + fileType; + File dest = new File(uploadPath + relativeName); + Long size = file.getSize(); + file.transferTo(dest); + String path = uploadProperties.getProxyUrl() + relativeName; + SysAttach attach = new SysAttach(); + attach.setName(fileOrgName); + attach.setPath(path); + attach.setSize(size); + attach.setFileType(fileType); + attach.setRelativePath(relativeName); + sysAttachService.save(attach); + return R.ok(attach); + } catch (IOException e) { + log.error(e.toString(), e); + } + return R.error("上传失败"); + } + + /** + * 保存 + * @param attach + * @return + */ + @PostMapping("/save") + public R upload(@RequestBody SysAttach attach){ + attach.setId(null); + sysAttachService.save(attach); + return R.ok(attach); + } + + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(title = "附件",biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + SysAttach sysattach = sysAttachService.getById(id); + return R.ok(sysattach); + } + + /** + * 根据ID查询 + * @param ids + * @return + */ + @GetMapping("/listByIds/{ids}") + @SysLog(title = "附件",biz = BizType.QUERY) + public R> listByIds(@PathVariable("ids") String ids){ + String[] idStrs = ids.split(","); + List sysattach = sysAttachService.listByIds(Arrays.asList(idStrs)); + return R.ok(sysattach); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:attach:query')") + public R> getPage(SysAttach param){ + PageUtil.startPage(); + List list = sysAttachService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysBusinessLogController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysBusinessLogController.java new file mode 100644 index 0000000..f2b6c9a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysBusinessLogController.java @@ -0,0 +1,73 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.sys.entity.SysBusinessLog; +import com.qs.serve.modules.sys.service.SysBusinessLogService; + +import java.util.List; + +/** + * 系统 系统业务日志 + * @author YenHex + * @since 2023-04-25 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/businessLog") +public class SysBusinessLogController { + + private SysBusinessLogService sysBusinessLogService; + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + public R> getPage(SysBusinessLog param){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(param); + PageUtil.startPage(); + List list = sysBusinessLogService.list(lqw); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + public R getById(@PathVariable("id") String id){ + SysBusinessLog sysBusinessLog = sysBusinessLogService.getById(id); + return R.ok(sysBusinessLog); + } + + + + /** + * 删除 + * @param ids + * @return + */ + @DeleteMapping("/deleteById/{ids}") + public R deleteById(@PathVariable("ids") String ids){ + List idsLong = StringUtils.splitIdLong(ids); + boolean result = sysBusinessLogService.removeByIds(idsLong); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysConfigController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysConfigController.java new file mode 100644 index 0000000..66955d4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysConfigController.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.sys.entity.bo.SysConfigBo; +import com.qs.serve.modules.sys.entity.SysConfig; +import com.qs.serve.modules.sys.service.SysConfigService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统 系统配置 + * @author YenHex + * @since 2022-11-12 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/config") +public class SysConfigController { + + private SysConfigService sysConfigService; + + + /** + * ID查询 + * @param key + * @return + */ + @GetMapping("/getByKey/{key}") + public R getById(@PathVariable("key") String key){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysConfig::getConfigKey,key); + SysConfig sysConfig = sysConfigService.getOne(lqw); + return R.ok(sysConfig); + } + + /** + * 更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.SYSTEM, title = "系统配置", biz = BizType.UPDATE) + @PreAuthorize("hasRole('sys:config:update')") + public R updateById(@RequestBody @Valid SysConfigBo param){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysConfig::getConfigKey,param.getConfigKey()); + SysConfig sysConfig = sysConfigService.getOne(lqw); + sysConfig.setConfigValue(param.getConfigValue()); + sysConfigService.updateById(sysConfig); + return R.ok(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java new file mode 100644 index 0000000..7cf4b8c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java @@ -0,0 +1,217 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysDept; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.bo.SysDeptBatchBo; +import com.qs.serve.modules.sys.entity.dto.SysDeptTranParam; +import com.qs.serve.modules.sys.entity.dto.SysDeptTreeNode; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysDeptService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:部门 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/dept") +public class SysDeptController { + + private SysDeptService sysDeptService; + private SysUserMapper sysUserMapper; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:dept:query')") + public R> getList(SysDept param){ + PageUtil.startPage(); + param.setStopFlag(0); + List list = sysDeptService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 查询所有部门 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:dept:query')") + public R> getListAll(SysDept param){ + param.setStopFlag(0); + List list = sysDeptService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + + /** + * 查询列表树 + * @param param + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:dept:query')") + public R getTreeList(SysDept param){ + param.setStopFlag(0); + List list = sysDeptService.listDept(param); + List treeNodes = list.stream().map(dept->{ + SysDeptTreeNode treeNode = CopierUtil.copy(dept,new SysDeptTreeNode()); + treeNode.setId(dept.getId()); + treeNode.setParentId(dept.getParentId()); + treeNode.setMgrUserName(dept.getMgrUserName()); + treeNode.setSort(0); + return treeNode; + }).collect(Collectors.toList()); + treeNodes = TreeUtil.buildByRecursive(treeNodes,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeNodes); + } + + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "部门",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:dept:query')") + public R getById(@PathVariable("id") String id){ + SysDept sysDept = sysDeptService.getById(id); + if(sysDept.getMgrUserId()!=null){ + SysUser sysUser = sysUserMapper.selectById(sysDept.getMgrUserId()); + if(sysUser!=null){ + sysDept.setMgrUserName(sysUser.getName()); + } + } + return R.ok(sysDept); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "部门",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:dept:insert')") + public R save(@RequestBody @Valid SysDept param){ + boolean result = sysDeptService.save2(param); + return R.isTrue(result); + } + + /** + * (批量)保存,建议每次小于800条 + * @param param + * @return + */ + @SysLog(title = "部门",biz = BizType.INSERT) + @PostMapping("/saveBatch") + @PreAuthorize("hasRole('sys:dept:insert')") + public R saveBatch(@RequestBody @Valid SysDeptBatchBo param){ + List deptList = param.getDeptList(); + List ids = deptList.stream().map(d->d.getId()).collect(Collectors.toList()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysDept::getId,ids); + lqw.select(SysDept::getId); + List sysDeptIdObjs = sysDeptService.list(lqw); + List existIds = sysDeptIdObjs.stream().map(SysDept::getId).collect(Collectors.toList()); + List deptList4Upd = deptList.stream().filter(dep->existIds.contains(dep.getId())).collect(Collectors.toList()); + List deptList4save = deptList.stream().filter(dep->!existIds.contains(dep.getId())).collect(Collectors.toList()); + sysDeptService.saveBatch(deptList4save); + sysDeptService.updateBatchById(deptList4Upd); + return R.ok(); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "部门",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:dept:update')") + public R updateById(@RequestBody @Valid SysDept param){ + sysDeptService.updateById(param); + return R.ok(); + } + + /** + * 部门迁移 + * @param param + * @return + */ + @SysLog(title = "部门",desc = "部门迁移",biz = BizType.UPDATE) + @PostMapping("/updateLevel") + @PreAuthorize("hasRole('sys:post:update')") + @Transactional(rollbackFor = Exception.class) + public R updateLevel(@RequestBody @Valid SysDeptTranParam param){ + SysDept dept = sysDeptService.getById(param.getSelectId()); + if(dept.getParentId().equals(param.getParentId())){ + return R.ok(); + } + String subLevelPath = ""; + if(!dept.getParentId().equals(TreeUtil.DEFAULT_PID_STRING)){ + SysDept orgParent = sysDeptService.getById(dept.getParentId()); + subLevelPath = orgParent.getLevelPath()+"_"; + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(SysDept::getId,SysDept::getParentId,SysDept::getLevelPath); + wrapper.likeRight(SysDept::getLevelPath,dept.getLevelPath()); + List deptList = sysDeptService.list(wrapper); + SysDept parent = null; + if(param.getParentId().equals(TreeUtil.DEFAULT_PID_STRING)){ + parent = sysDeptService.getById(param.getParentId()); + } + for (SysDept sysDept : deptList) { + if(sysDept.getId().equals(param.getSelectId())){ + sysDept.setParentId(param.getParentId()); + } + String levelPath = sysDept.getLevelPath().replace(subLevelPath,""); + if(parent==null){ + sysDept.setLevelPath(levelPath); + }else { + sysDept.setLevelPath(parent.getLevelPath()+"_"+levelPath); + } + } + sysDeptService.updateBatchById(deptList); + return R.ok(); + } + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "部门",biz = BizType.DELETE) + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:dept:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysDeptService.removeById(id); + return R.ok(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java new file mode 100644 index 0000000..2ec559b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java @@ -0,0 +1,103 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.sys.entity.SysDict; +import com.qs.serve.modules.sys.service.SysDictService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统 字典 + * @author YenHex + * @since 2022-11-04 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/dict") +public class SysDictController { + + private SysDictService sysDictService; + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:dict:query')") + public R> getPage(SysDict param){ + PageUtil.startPage(); + LambdaQueryWrapper dictWrapper = new LambdaQueryWrapper<>(param); + List list = sysDictService.list(dictWrapper); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.SYSTEM, title = "字典", biz = BizType.QUERY) + @PreAuthorize("hasRole('sys:dict:query')") + public R getById(@PathVariable("id") String id){ + SysDict sysDict = sysDictService.getById(id); + return R.ok(sysDict); + } + + + + /** + * 更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.SYSTEM, title = "字典", biz = BizType.UPDATE) + @PreAuthorize("hasRole('sys:dict:update')") + public R updateById(@RequestBody @Valid SysDict param){ + boolean result = sysDictService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.SYSTEM, title = "字典", biz = BizType.INSERT) + @PreAuthorize("hasRole('sys:dict:insert')") + public R save(@RequestBody @Valid SysDict param){ + boolean result = sysDictService.save(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.SYSTEM, title = "字典", biz = BizType.DELETE) + @PreAuthorize("hasRole('sys:dict:delete')") + public R deleteById(@PathVariable("id") Long id){ + boolean result = sysDictService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysDictDataController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysDictDataController.java new file mode 100644 index 0000000..b4846ed --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysDictDataController.java @@ -0,0 +1,124 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.StringUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.sys.entity.SysDictData; +import com.qs.serve.modules.sys.service.SysDictDataService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统 字典数据 + * @author YenHex + * @since 2022-11-04 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/dictData") +public class SysDictDataController { + + private SysDictDataService sysDictDataService; + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:dictData:query')") + public R> getList(SysDictData param){ + if(!StringUtils.hasText(param.getGroupKey())){ + return R.ok(); + } + LambdaQueryWrapper dictDataWrapper = new LambdaQueryWrapper<>(param); + List list = sysDictDataService.list(dictDataWrapper); + return R.ok(list); + } + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:dictData:query')") + public R> getPage(SysDictData param){ + if(!StringUtils.hasText(param.getGroupKey())){ + return R.byEmptyList(); + } + PageUtil.startPage(); + LambdaQueryWrapper dictDataWrapper = new LambdaQueryWrapper<>(param); + List list = sysDictDataService.list(dictDataWrapper); + return R.byPageHelperList(list); + } + + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.SYSTEM, title = "字典数据", biz = BizType.QUERY) + @PreAuthorize("hasRole('sys:dictData:query')") + public R getById(@PathVariable("id") String id){ + SysDictData sysDictData = sysDictDataService.getById(id); + return R.ok(sysDictData); + } + + + + /** + * 更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.SYSTEM, title = "字典数据", biz = BizType.UPDATE) + @PreAuthorize("hasRole('sys:dictData:update')") + public R updateById(@RequestBody @Valid SysDictData param){ + boolean result = sysDictDataService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.SYSTEM, title = "字典数据", biz = BizType.INSERT) + @PreAuthorize("hasRole('sys:dictData:insert')") + public R save(@RequestBody @Valid SysDictData param){ + boolean result = sysDictDataService.save(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.SYSTEM, title = "字典数据", biz = BizType.DELETE) + @PreAuthorize("hasRole('sys:dictData:delete')") + public R deleteById(@PathVariable("id") Long id){ + boolean result = sysDictDataService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java new file mode 100644 index 0000000..72bb300 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java @@ -0,0 +1,188 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.entity.SysMenuPermit; +import com.qs.serve.modules.sys.entity.dto.SysMenuPermitParam; +import com.qs.serve.modules.sys.entity.dto.SysMenuTreeNode; +import com.qs.serve.modules.sys.service.SysMenuPermitService; +import com.qs.serve.modules.sys.service.SysMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:系统菜单 + * @author YenHex + * @since 2022-03-15 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/menu") +public class SysMenuController { + + private SysMenuService sysMenuService; + private SysMenuPermitService sysMenuPermitService; + + + /** + * 获取人员权限菜单 + * @return + */ + @PostMapping("/userMenus") + public R> userMenus(Integer clientType){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + List menuIds = loginUser.getAuthorIds(); + if(CollectionUtil.isNotEmpty(menuIds)){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysMenu::getId,menuIds); + wrapper.eq(SysMenu::getClientType,clientType==null?1:clientType); + return R.ok(sysMenuService.list(wrapper)); + } + return R.ok(); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:menu:query')") + public R> getPage(SysMenu param){ + PageUtil.startPage(); + List list = sysMenuService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 列表查询 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:menu:query')") + public R> getList(SysMenu param){ + List list = sysMenuService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 树形列表 + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:permit:query')") + public R> getTree(Integer clientType){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if(clientType==null){ + wrapper.eq(SysMenu::getClientType,0); + }else { + wrapper.eq(SysMenu::getClientType,clientType); + } + wrapper.eq(SysMenu::getHideFlag,0); + wrapper.orderByAsc(SysMenu::getSort,SysMenu::getId); + List list = sysMenuService.list(wrapper); + List treeNodes = list.stream().map(permit->{ + SysMenuTreeNode treeNode = CopierUtil.copy(permit,new SysMenuTreeNode()); + treeNode.setId(permit.getId()+""); + treeNode.setParentId(permit.getPid()); + treeNode.setSort(permit.getSort()); + return treeNode; + }).collect(Collectors.toList()); + treeNodes = TreeUtil.buildByRecursive(treeNodes,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeNodes); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:menu:query')") + public R getById(@PathVariable("id") String id){ + SysMenu sysMenu = sysMenuService.getById(id); + List menuPermitList = sysMenuPermitService.listByMenuId(id); + sysMenu.setPermitIds(menuPermitList.stream().map(SysMenuPermit::getPermitId).distinct().collect(Collectors.toList())); + return R.ok(sysMenu); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "菜单",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:menu:update')") + public R updateById(@RequestBody @Valid SysMenu param){ + boolean result = sysMenuService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增系统菜单 + * @param param + * @return + */ + @SysLog(title = "菜单",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:menu:insert')") + public R save(@RequestBody @Valid SysMenu param){ + boolean result = sysMenuService.save(param); + return R.isTrue(result); + } + + /** + * 授权系统菜单 + * @param param + * @return + */ + @SysLog(title = "菜单",biz = BizType.GRANT) + @PostMapping("/grantMenu") + @PreAuthorize("hasRole('sys:menu:insert')") + public R save2(@RequestBody @Valid SysMenuPermitParam param){ + sysMenuPermitService.removeByMenuId(param.getMenuId()); + List menuPermitList = new ArrayList<>(); + for (String permitId : param.getPermitIds()) { + SysMenuPermit menuPermit = new SysMenuPermit(); + menuPermit.setMenuId(param.getMenuId()); + menuPermit.setPermitId(permitId); + menuPermitList.add(menuPermit); + } + sysMenuPermitService.saveBatch(menuPermitList); + return R.ok(); + } + + /** + * 删除系统菜单 + * @param id + * @return + */ + @SysLog(title = "菜单",biz = BizType.DELETE) + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:menu:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysMenuService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java new file mode 100644 index 0000000..e0c06c2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java @@ -0,0 +1,220 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.*; +import com.qs.serve.modules.sys.entity.dto.SysUserVo; +import com.qs.serve.modules.sys.service.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:公示(管理员) + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/notice") +public class SysNoticeController { + + private SysNoticeService sysNoticeService; + private SysDeptService sysDeptService; + private SysUserService sysUserService; + private SysAttachService sysAttachService; + private SysNoticeUserService sysNoticeUserService; + + /** + * 查询个人列表 + * @param param + * @return + */ + @GetMapping("/pageSelf") + public R> getPageSelf(SysNotice param){ + PageUtil.startPage(); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(param); + if(param.getQueryStartTime()!=null){ + wrapper.ge(SysNotice::getLastPublishTime,param.getQueryStartTime()); + } + if(param.getQueryEndTime()!=null){ + wrapper.le(SysNotice::getLastPublishTime,param.getQueryEndTime()); + } + wrapper.eq(SysNotice::getCreateBy, AuthContextUtils.getSysUserId()); + List list = sysNoticeService.list(wrapper); + return R.byPageHelperList(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:notice:query')") + public R> getPage(SysNotice param){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(param); + if(param.getQueryStartTime()!=null){ + wrapper.ge(SysNotice::getLastPublishTime,param.getQueryStartTime()); + } + if(param.getQueryEndTime()!=null){ + wrapper.le(SysNotice::getLastPublishTime,param.getQueryEndTime()); + } + PageUtil.startPage(); + List list = sysNoticeService.list(wrapper); + for (SysNotice notice : list) { + SysUser sysUser = sysUserService.getById(notice.getCreateBy()); + if(sysUser!=null){ + notice.setCreatorName(sysUser.getName()); + } + } + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "公告",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:notice:query')") + public R getById(@PathVariable("id") String id){ + SysNotice sysNotice = sysNoticeService.getById(id); + if(sysNotice==null){ + return R.error("资源不存在或被移除"); + } + String[] arr = sysNotice.getVisibleIds(); + if(CollectionUtil.isNotEmpty(arr)){ + if(sysNotice.getVisibleType().equals(1)){ + List sysUsers = sysUserService.listByIds(Arrays.asList(arr)); + List sysUserVoLIst = sysUsers.stream().map(SysUser::toSysUserVo).collect(Collectors.toList()); + sysNotice.setUserInfos(sysUserVoLIst); + }else if(sysNotice.getVisibleType().equals(2)){ + List deptList = sysDeptService.listByIds(Arrays.asList(arr)); + sysNotice.setDeps(deptList); + } + } + if(CollectionUtil.isNotEmpty(sysNotice.getDocIds())){ + List documents = sysAttachService.listByIds(Arrays.asList(sysNotice.getDocIds())); + sysNotice.setDocuments(documents); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysNoticeUser::getNoticeId,id); + wrapper.eq(SysNoticeUser::getUserId,AuthContextUtils.getSysUserId()); + SysNoticeUser sysNoticeUser = sysNoticeUserService.getOne(wrapper,false); + if(sysNoticeUser!=null){ + sysNoticeUser.setReadFlag(true); + sysNoticeUser.setReadCount(sysNoticeUser.getReadCount()==null?1:sysNoticeUser.getReadCount()+1); + sysNoticeUser.setReadTime(LocalDateTime.now()); + sysNoticeUserService.updateById(sysNoticeUser); + } + return R.ok(sysNotice); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "公告",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:notice:insert')") + public R save(@RequestBody @Valid SysNotice param){ + boolean result = sysNoticeService.save(param); + return R.isTrue(result); + } + + /** + * 发布 + * @param id + * @return + */ + @SysLog(title = "公告",desc = "发布公告",biz = BizType.OTHER) + @PostMapping("/publish/{id}") + @PreAuthorize("hasRole('sys:notice:publish')") + public R publish(@PathVariable("id") String id){ + sysNoticeService.publish(id); + return R.ok(); + } + + /** + * 撤销、下架 + * @param id + * @return + */ + @SysLog(title = "公告",desc = "撤销公告",biz = BizType.OTHER) + @PostMapping("/repeal/{id}") + @PreAuthorize("hasRole('sys:notice:repeal')") + @Transactional(rollbackFor = Exception.class) + public R repeal(@PathVariable("id") String id){ + sysNoticeService.removeUserRelate(id); + SysNotice notice = sysNoticeService.getById(id); + notice.setEnable(0); + updateById(notice); + return R.ok(); + } + + /** + * 保存并发布 + * @param param + * @return + */ + @SysLog(title = "公告",desc = "保存并发布",biz = BizType.INSERT) + @PostMapping("/saveAndPublish") + @PreAuthorize("hasRole('sys:notice:publish') and hasRole('sys:notice:insert')") + @Transactional(rollbackFor = Exception.class) + public R publish(@RequestBody @Valid SysNotice param){ + param.setEnable(1); + if(param.getId()!=null){ + sysNoticeService.updateById(param); + }else { + sysNoticeService.save(param); + } + sysNoticeService.publish(param.getId()); + return R.ok(); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "公告",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:notice:update')") + public R updateById(@RequestBody @Valid SysNotice param){ + boolean result = sysNoticeService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "公告",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:notice:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysNoticeService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java new file mode 100644 index 0000000..eaf9c77 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java @@ -0,0 +1,109 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysNoticeType; +import com.qs.serve.modules.sys.service.SysNoticeTypeService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:公示分类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/noticeType") +public class SysNoticeTypeController { + + private SysNoticeTypeService sysNoticeTypeService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:noticeType:query')") + public R> getPage(SysNoticeType param){ + PageUtil.startPage(); + List list = sysNoticeTypeService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(SysNoticeType param){ + List list = sysNoticeTypeService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "公告类型",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:noticeType:query')") + public R getById(@PathVariable("id") String id){ + SysNoticeType sysNoticeType = sysNoticeTypeService.getById(id); + return R.ok(sysNoticeType); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "公告类型",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:noticeType:insert')") + public R save(@RequestBody @Valid SysNoticeType param){ + boolean result = sysNoticeTypeService.save(param); + return R.isTrue(result); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "公告类型",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:noticeType:update')") + public R updateById(@RequestBody @Valid SysNoticeType param){ + boolean result = sysNoticeTypeService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "公告类型",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:noticeType:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysNoticeTypeService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java new file mode 100644 index 0000000..bb98583 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java @@ -0,0 +1,75 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.entity.SysNotice; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import com.qs.serve.modules.sys.service.SysAttachService; +import com.qs.serve.modules.sys.service.SysNoticeService; +import com.qs.serve.modules.sys.service.SysNoticeUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; + +/** + * 系统:公示(用户) + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/noticeUser") +public class SysNoticeUserController { + + private SysNoticeUserService sysNoticeUserService; + + private SysNoticeService sysNoticeService; + + private SysAttachService sysAttachService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + public R> getList(SysNoticeUser param){ + param.setUserId(AuthContextUtils.getSysUserId()); + Page page = PageUtil.getMbpPage(); + IPage list = sysNoticeUserService.list2(page,param); + return R.byMbpList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + public R getById(@PathVariable("id") String id){ + SysNoticeUser sysNoticeUser = sysNoticeUserService.getById(id); + sysNoticeUser.setReadFlag(true); + sysNoticeUser.setReadCount(sysNoticeUser.getReadCount()==null?1:sysNoticeUser.getReadCount()+1); + sysNoticeUser.setReadTime(LocalDateTime.now()); + sysNoticeUserService.updateById(sysNoticeUser); + SysNotice notice = sysNoticeService.getById(sysNoticeUser.getNoticeId()); + if(CollectionUtil.isNotEmpty(notice.getDocIds())){ + List documents = sysAttachService.listByIds(Arrays.asList(notice.getDocIds())); + notice.setDocuments(documents); + } + return R.ok(notice); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java new file mode 100644 index 0000000..87f157e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java @@ -0,0 +1,82 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.service.SysOperationLogService; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:操作日志 + * @author YenHex + * @since 2022-03-08 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/operationLog") +public class SysOperationLogController { + + private SysOperationLogService sysOperationLogService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:operationLog:query')") + public R> getList(SysOperationLog param){ + //操作日志详情,当前账号只能查当前帐号日志,超管账号可查询全部 + LoginUser loginUser = AuthContextUtils.getLoginUser(); + if(!loginUser.verifyRole(GySysConst.ROLE_ADMIN_OPT_LOG)){ + param.setUserId(loginUser.getUserId()); + } + PageUtil.startPage(); + QueryWrapper wrapper = new QueryWrapper<>(param); + if(PageUtil.getOrderProp()==null){ + wrapper.orderByDesc("create_time"); + } + List list = sysOperationLogService.list(wrapper); + return R.byPageHelperList(list); + } + + /** + * 翻页查询(个人) + * @param param + * @return + */ + @GetMapping("/pageSelf") + public R> pageSelf(SysOperationLog param){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + param.setUserId(loginUser.getUserId()); + return this.getList(param); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:operationLog:query')") + public R getById(@PathVariable("id") String id){ + SysOperationLog sysOperationLog = sysOperationLogService.getById(id); + return R.ok(sysOperationLog); + } + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysOperationManualController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysOperationManualController.java new file mode 100644 index 0000000..d139628 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysOperationManualController.java @@ -0,0 +1,147 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.service.SysAttachService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.sys.entity.SysOperationManual; +import com.qs.serve.modules.sys.service.SysOperationManualService; + +import javax.validation.Valid; +import java.util.Arrays; +import java.util.List; + +/** + * 系统 + * @author YenHex + * @since 2023-08-11 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/operationManual") +public class SysOperationManualController { + + private SysOperationManualService sysOperationManualService; + private SysAttachService attachService; + + /** + * 列表 + * @param param + * @return + */ + @GetMapping("/list") + //@PreAuthorize("hasRole('sys:operationManual:query')") + public R> getList(SysOperationManual param){ + SysOperationManual entity = CopierUtil.copy(param,new SysOperationManual()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + List list = sysOperationManualService.list(lqw); + list.forEach(sysOperationManual->{ + if(CollectionUtil.isNotEmpty(sysOperationManual.getAttachIds())){ + List attachIds = Arrays.asList(sysOperationManual.getAttachIds()); + List attachList = attachService.listByIds(attachIds); + sysOperationManual.setAttachList(attachList); + } + }); + return R.ok(list); + } + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + //@PreAuthorize("hasRole('sys:operationManual:query')") + public R> getPage(SysOperationManual param){ + SysOperationManual entity = CopierUtil.copy(param,new SysOperationManual()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + PageUtil.startPage(); + List list = sysOperationManualService.list(lqw); + list.forEach(sysOperationManual->{ + if(CollectionUtil.isNotEmpty(sysOperationManual.getAttachIds())){ + List attachIds = Arrays.asList(sysOperationManual.getAttachIds()); + List attachList = attachService.listByIds(attachIds); + sysOperationManual.setAttachList(attachList); + } + }); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") +// @SysLog(module = SystemModule.${extend.moduleLog}, title = "", biz = BizType.QUERY) + //@PreAuthorize("hasRole('sys:operationManual:query')") + public R getById(@PathVariable("id") String id){ + SysOperationManual sysOperationManual = sysOperationManualService.getById(id); + if(CollectionUtil.isNotEmpty(sysOperationManual.getAttachIds())){ + List attachIds = Arrays.asList(sysOperationManual.getAttachIds()); + List attachList = attachService.listByIds(attachIds); + sysOperationManual.setAttachList(attachList); + } + return R.ok(sysOperationManual); + } + + + + /** + * 更新 + * @param param + * @return + */ + @PostMapping("/updateById") +// @SysLog(module = SystemModule.${extend.moduleLog}, title = "", biz = BizType.UPDATE) + //@PreAuthorize("hasRole('sys:operationManual:update')") + public R updateById(@RequestBody @Valid SysOperationManual param){ + SysOperationManual entity = CopierUtil.copy(param,new SysOperationManual()); + boolean result = sysOperationManualService.updateById(entity); + return R.isTrue(result); + } + + /** + * 新增 + * @param param + * @return + */ + @PostMapping("/save") +// @SysLog(module = SystemModule.${extend.moduleLog}, title = "", biz = BizType.INSERT) + //@PreAuthorize("hasRole('sys:operationManual:insert')") + public R save(@RequestBody @Valid SysOperationManual param){ + SysOperationManual entity = CopierUtil.copy(param,new SysOperationManual()); + boolean result = sysOperationManualService.save(entity); + return R.isTrue(result); + } + + /** + * 删除 + * @param ids + * @return + */ + @DeleteMapping("/deleteById/{ids}") +// @SysLog(module = SystemModule.${extend.moduleLog}, title = "", biz = BizType.DELETE) + //@PreAuthorize("hasRole('sys:operationManual:delete')") + public R deleteById(@PathVariable("ids") String ids){ + List idsLong = StringUtils.splitIdLong(ids); + boolean result = sysOperationManualService.removeByIds(idsLong); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java new file mode 100644 index 0000000..793c18b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java @@ -0,0 +1,86 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysPermit; +import com.qs.serve.modules.sys.entity.dto.SysPermitTreeNode; +import com.qs.serve.modules.sys.service.SysPermitService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:权限 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/permit") +public class SysPermitController { + + private SysPermitService sysPermitService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:permit:query')") + public R> getList(SysPermit param){ + PageUtil.startPage(); + param.setHideFlag(0); + List list = sysPermitService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 树形列表 + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:permit:query')") + public R> getTree(){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysPermit::getHideFlag,0); + List list = sysPermitService.list(wrapper); + List treeNodes = list.stream().map(permit->{ + SysPermitTreeNode treeNode = CopierUtil.copy(permit,new SysPermitTreeNode()); + treeNode.setId(permit.getId()+""); + treeNode.setParentId(permit.getPid()); + treeNode.setSort(0); + return treeNode; + }).collect(Collectors.toList()); + treeNodes = TreeUtil.buildByRecursive(treeNodes,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeNodes); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:permit:query')") + public R getById(@PathVariable("id") String id){ + SysPermit sysPermit = sysPermitService.getById(id); + return R.ok(sysPermit); + } + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java new file mode 100644 index 0000000..f70afa2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java @@ -0,0 +1,160 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysPost; +import com.qs.serve.modules.sys.entity.SysPostUser; +import com.qs.serve.modules.sys.entity.vo.SysPostTreeVo; +import com.qs.serve.modules.sys.service.SysDeptService; +import com.qs.serve.modules.sys.service.SysPostService; +import com.qs.serve.modules.sys.service.SysPostUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:职务 + * @author YenHex + * @since 2022-04-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/post") +public class SysPostController { + + private SysPostService sysPostService; + private SysPostUserService sysPostUserService; + + /** + * 列表查询 + * @param param + * @return + */ + @GetMapping("/tree") + public R> getList(SysPost param){ + List list = sysPostService.list(new QueryWrapper<>(param)); + List postUsers = sysPostUserService.list(); + + for (SysPost post : list) { + List puList = postUsers.stream().filter(a->a.getPostId().equals(post.getId())).collect(Collectors.toList()); + post.setPostUserList(puList); + } + + List treeVoList = list.stream().map(source->{ + SysPostTreeVo treeVo = new SysPostTreeVo(); + treeVo.setId(source.getId()); + treeVo.setPostName(source.getPostName()); + treeVo.setPostCode(source.getPostCode()); + treeVo.setPathIds(source.getPathIds()); + treeVo.setPathNames(source.getPathNames()); + treeVo.setRemark(source.getRemark()); + treeVo.setId(source.getId()); + treeVo.setParentId(source.getPid()); + treeVo.setPostUserList(source.getPostUserList()); + treeVo.setSort(0); + return treeVo; + }).collect(Collectors.toList()); + treeVoList = TreeUtil.buildByRecursive(treeVoList,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeVoList); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:post:query')") + public R> getPage(SysPost param){ + PageUtil.startPage(); + List list = sysPostService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(title = "职务",biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + SysPost sysPost = sysPostService.getById(id); + if(!sysPost.getPid().equals("0")){ + sysPost.setParentInfo(sysPostService.getById(id)); + } + return R.ok(sysPost); + } + + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "职务",biz = BizType.UPDATE) + @PostMapping("/updateById") + public R updateById(@RequestBody @Valid SysPost param){ + if(param.getId()==null){ + return R.error2(); + } + sysPostService.modify(param); + sysPostService.flushPathIds(); + return R.ok(); + } + + /** + * 刷新岗位ID路径 + * @return + */ + @GetMapping("/flushPathIds") + public R flushPathIds(){ + sysPostService.flushPathIds(); + return R.ok(); + } + + /** + * 新增系统职务 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(title = "职务",biz = BizType.INSERT) + public R save(@RequestBody @Valid SysPost param){ + param.setId(null); + sysPostService.modify(param); + sysPostService.flushPathIds(); + return R.ok(param); + } + + /** + * 删除系统职务 + * @param id + * @return + */ + @SysLog(title = "职务",biz = BizType.DELETE) + @DeleteMapping("/deleteById/{id}") + public R deleteById(@PathVariable("id") String id){ + LambdaQueryWrapper postLqw = new LambdaQueryWrapper<>(); + postLqw.eq(SysPost::getPid,id); + if(sysPostService.count(postLqw)>0){ + return R.error("含有子节点,无法删除"); + } + boolean result = sysPostService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysPostUserController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysPostUserController.java new file mode 100644 index 0000000..4247e13 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysPostUserController.java @@ -0,0 +1,107 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.sys.entity.so.SysPostUserSo; +import com.qs.serve.modules.sys.entity.bo.SysPostUserBo; +import com.qs.serve.modules.sys.entity.SysPostUser; +import com.qs.serve.modules.sys.service.SysPostUserService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统 系统职务 + * @author YenHex + * @since 2023-04-27 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/postUser") +public class SysPostUserController { + + private SysPostUserService sysPostUserService; + + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + public R> getPage(SysPostUserSo param){ + SysPostUser entity = CopierUtil.copy(param,new SysPostUser()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + PageUtil.startPage(); + List list = sysPostUserService.list(lqw); + return R.byPageHelperList(list); + } + + /** + * 列表 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(SysPostUserSo param){ + SysPostUser entity = CopierUtil.copy(param,new SysPostUser()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); +// PageUtil.startPage(); + List list = sysPostUserService.list(lqw); + return R.ok(list); + } + + /** + * ID查询 + * @param id + * @return + */ + //@GetMapping("/getById/{id}") + @SysLog(module = SystemModule.SYSTEM, title = "系统职务", biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + SysPostUser sysPostUser = sysPostUserService.getById(id); + return R.ok(sysPostUser); + } + + + /** + * 绑定用户与职务 + * @param param + * @return + */ + @PostMapping("/bind") + @SysLog(module = SystemModule.SYSTEM, title = "系统职务", biz = BizType.INSERT) + public R save(@RequestBody @Valid SysPostUserBo param){ + sysPostUserService.bind(param); + return R.ok(); + } + + /** + * 删除 + * @param ids + * @return + */ + @DeleteMapping("/deleteById/{ids}") + @SysLog(module = SystemModule.SYSTEM, title = "系统职务", biz = BizType.DELETE) + public R deleteById(@PathVariable("ids") String ids){ + List idsLong = StringUtils.splitIdLong(ids); + boolean result = sysPostUserService.removeByIds(idsLong); + return R.isTrue(result); + } + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java new file mode 100644 index 0000000..3e55ed5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java @@ -0,0 +1,224 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysRole; +import com.qs.serve.modules.sys.entity.SysRoleMenu; +import com.qs.serve.modules.sys.entity.SysUserRole; +import com.qs.serve.modules.sys.entity.dto.SysRoleMenuParam; +import com.qs.serve.modules.sys.entity.dto.SysRoleUserParam; +import com.qs.serve.modules.sys.entity.dto.UserRole4EditParam; +import com.qs.serve.modules.sys.service.SysRoleMenuService; +import com.qs.serve.modules.sys.service.SysRoleService; +import com.qs.serve.modules.sys.service.SysUserRoleService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +/** + * 系统:角色 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/role") +public class SysRoleController { + + private SysRoleService sysRoleService; + private SysRoleMenuService sysRoleMenuService; + private SysUserRoleService sysUserRoleService; + + /** + * 查询列表(用于人员编辑) + * @return + */ + @GetMapping("/list4UserEdit") + public R> getList(){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRole::getUserVisible,1); + wrapper.eq(SysRole::getEnable,1); + List list = sysRoleService.list(wrapper); + return R.ok(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:role:query')") + public R> getPage(SysRole param){ + PageUtil.startPage(); + List list = sysRoleService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:role:query')") + public R> getList(SysRole param){ + List list = sysRoleService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:role:query')") + public R getById(@PathVariable("id") String id){ + SysRole sysRole = sysRoleService.getById(id); + sysRole.setMenuList(sysRoleMenuService.listByRoleId(id)); + return R.ok(sysRole); + } + + /** + * 保存角色 + * @param param + * @return + */ + @SysLog(title = "角色",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:role:insert')") + public R save(@RequestBody @Valid SysRole param){ + param.setIsDefault(null); + boolean result = sysRoleService.save(param); + return R.isTrue(result); + } + + /** + * 根据ID更新角色 + * @param param + * @return + */ + @SysLog(title = "角色",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:role:update')") + public R updateById(@RequestBody @Valid SysRole param){ + SysRole sysRole = sysRoleService.getById(param.getId()); + if(sysRole.getIsDefault().equals(1)){ + return R.error("系统默认角色不可修改"); + } + param.setIsDefault(null); + boolean result = sysRoleService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除角色 + * @param id + * @return + */ + @SysLog(title = "角色",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:role:delete')") + public R deleteById(@PathVariable("id") String id){ + SysRole sysRole = sysRoleService.getById(id); + if(sysRole.getIsDefault().equals(1)){ + return R.error("系统默认角色不可删除"); + } + boolean result = sysRoleService.removeById(id); + sysRoleMenuService.removeByRoleId(id,null); + return R.isTrue(result); + } + + + /** + * 角色菜单授权 + * @param param + * @return + */ + @SysLog(title = "角色",desc ="菜单授权",biz = BizType.GRANT) + @PostMapping("/saveRoleMenu") + @PreAuthorize("hasRole('sys:permit:grant')") + @Transactional(rollbackFor = Exception.class) + public R grantRoleMenu(@RequestBody @Valid SysRoleMenuParam param){ + sysRoleMenuService.removeByRoleId(param.getRoleId(),param.getClientType()); + List roleMenus = new ArrayList<>(); + for (String menuId : param.getMenuIds()) { + SysRoleMenu sysRoleMenu = new SysRoleMenu(); + sysRoleMenu.setRoleId(param.getRoleId()); + sysRoleMenu.setMenuId(menuId); + roleMenus.add(sysRoleMenu); + } + sysRoleMenuService.saveBatch(roleMenus); + return R.isTrue(true); + } + + /** + * 添加用户授权 + * @param param + * @return + */ + @SysLog(title = "角色",desc ="保存用户授权",biz = BizType.GRANT) + @PostMapping("/saveUserRole") + @PreAuthorize("hasRole('sys:userRole:grant')") + @Transactional(rollbackFor = Exception.class) + public R grantUser(@RequestBody @Valid SysRoleUserParam param){ + SysRole sysRole = sysRoleService.getById(param.getRoleId()); + if(sysRole.getIsDefault().equals(1)){ + return R.error("应用所有用户的系统默认角色,无需授权"); + } + List sysUserRoles = new ArrayList<>(); + List uids = sysUserRoleService.notDataUserIds(param.getRoleId(),param.getUserIds()); + for (String userId : uids) { + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(userId); + userRole.setRoleId(param.getRoleId()); + sysUserRoles.add(userRole); + } + sysUserRoleService.saveBatch(sysUserRoles); + return R.isTrue(true); + } + + /** + * 编辑页面关联用户角色 + * @param param + * @return + */ + @SysLog(title = "角色",desc ="编辑用户授权",biz = BizType.GRANT) + @PostMapping("/saveUserRole4Edit") + @PreAuthorize("hasRole('sys:userRole:editGrant')") + @Transactional(rollbackFor = Exception.class) + public R saveUserRole4Edit(@RequestBody @Valid UserRole4EditParam param){ + List roleIds = param.getRoleIds(); + String userId = param.getUserId(); + sysRoleService.saveUserRole4Edit(roleIds,userId); + return R.isTrue(true); + } + + /** + * 删除用户授权 + * @param sysRoleUserParam + * @return + */ + @SysLog(title = "角色",desc ="移除用户授权",biz = BizType.GRANT) + @PostMapping("/removeUserRole") + @PreAuthorize("hasRole('sys:userRole:delete')") + public R deleteById(@RequestBody @Valid SysRoleUserParam sysRoleUserParam){ + sysUserRoleService.remove(sysRoleUserParam.getRoleId(),sysRoleUserParam.getUserIds()); + return R.ok(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java new file mode 100644 index 0000000..2218438 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java @@ -0,0 +1,98 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysTenant; +import com.qs.serve.modules.sys.service.SysTenantService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:租户 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/tenant") +public class SysTenantController { + + private SysTenantService sysTenantService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:tenant:query')") + public R> getList(SysTenant param){ + PageUtil.startPage(); + List list = sysTenantService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "租户",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:tenant:query')") + public R getById(@PathVariable("id") String id){ + SysTenant sysTenant = sysTenantService.getById(id); + return R.ok(sysTenant); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "租户",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:tenant:insert')") + public R save(@RequestBody @Valid SysTenant param){ + boolean result = sysTenantService.save(param); + return R.isTrue(result); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "租户",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:tenant:update')") + public R updateById(@RequestBody @Valid SysTenant param){ + boolean result = sysTenantService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "租户",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:tenant:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysTenantService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java new file mode 100644 index 0000000..68e880d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java @@ -0,0 +1,590 @@ +package com.qs.serve.modules.sys.controller; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.github.pagehelper.PageHelper; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.*; +import com.qs.serve.modules.sys.entity.bo.*; +import com.qs.serve.modules.sys.entity.dto.*; +import com.qs.serve.modules.sys.mapper.SysMenuMapper; +import com.qs.serve.modules.sys.service.*; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 系统:用户 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/user") +public class SysUserController { + + private SysUserService sysUserService; + private SysDeptService sysDeptService; + private SysPostService sysPostService; + private SysRoleService sysRoleService; + private WxUserService wxUserService; + private SysUserSalesService sysUserSalesService; + private final SysMenuMapper sysMenuMapper; + + /** + * 检查是否默认密码 + * @return true;false字符串 + */ + @GetMapping("/checkDefaultPassword") + public R checkDefaultPassword(){ + SysUser sysUser = sysUserService.getById(AuthContextUtils.getSysUserId()); + if(sysUser.getPassword().equals("25d55ad283aa400af464c76d713c07ad")){ + return R.ok("true","ok"); + } + return R.ok("false","ok"); + } + + + @GetMapping("/getChildList") + public R> getChildList(){ + List postUsers = sysUserService.listByChildIds(AuthContextUtils.getSysUserId()); + return R.ok(postUsers); + } + + /** + * 树查询 + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:user:query')") + public R> getTree(){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysUser::getSalesFlag,1); + List sysUsers = sysUserService.list(lqw); + List userSales = sysUserSalesService.list(); + for (SysUser sysUser : sysUsers) { + sysUser.setParentId("0"); + for (SysUserSales userSale : userSales) { + if(sysUser.getId().equals(userSale.getUserId())){ + sysUser.setParentId(userSale.getPid()); + break; + } + } + } + List treeVoList = sysUsers.stream().map(sysUser->{ +// SysDept sysDept = sysDeptService.getById(sysUser.getDeptId()); + SysUserSalesTreeVo treeNode = CopierUtil.copy(sysUser,new SysUserSalesTreeVo()); + treeNode.setId(sysUser.getId()); + treeNode.setParentId(sysUser.getParentId()); + treeNode.setSort(0); +// if(sysDept!=null){ +// treeNode.setDeptName(sysDept.getName()); +// } + return treeNode; + }).collect(Collectors.toList()); + treeVoList = TreeUtil.buildByRecursive(treeVoList,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeVoList); + } + + + /** + * (个人)登录信息 + * @return + */ + @PostMapping("/info") + public R info(){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser sysUser = sysUserService.getById(loginUser.getUserId()); + sysUser.setAuthorList(loginUser.getAuthorList()); + //解决H5页面权限不刷新 + List defaultRole = sysRoleService.getDefaultRole(); + List defaultRoleIds = defaultRole.stream().map(SysRole::getId).collect(Collectors.toList()); + List menuIds = sysMenuMapper.searchUserMenuIds(sysUser.getId()); + List defaultRoleMenuIds = sysMenuMapper.searchDefaultMenuIds(defaultRoleIds); + menuIds.addAll(defaultRoleMenuIds); + //sysUser.setAuthorIds(loginUser.getAuthorIds()); + sysUser.setAuthorIds(menuIds); + SysUserVo sysUserVo = sysUser.toSysUserVo(false); + SysDept dept = sysDeptService.getById(sysUser.getDeptId()); + sysUserVo.setDeptInfo(dept); + + //SysPost sysPost = sysPostService.getById(sysUser.getPositionId()); + //sysUserVo.setPostInfo(sysPost); + return R.ok(sysUserVo); + } + + + /** + * (个人)更新OA密码 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "个人密码更新",biz = BizType.UPDATE) + @PostMapping("/updateOAPwd") + public R updateOAPwd(@RequestBody SysUserPwdParam param){ + SysUser sysUser = sysUserService.getById(AuthContextUtils.getSysUserId()); + sysUserService.updateSeeYonPassword(sysUser.getSyUserId(),param.getNewPassword()); + return R.ok(); + } + + /** + * (个人)密码更新H5 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "个人密码更新",biz = BizType.UPDATE) + @PostMapping("/updatePwdH5") + public R updatePwdH5(@RequestBody SysUserPwdParam param){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser sysUser = new SysUser(); + sysUser.setId(loginUser.getUserId()); + sysUser.setPassword(SecureUtil.md5(param.getNewPassword())); + sysUser.setUpdateTime(LocalDateTime.now()); + sysUserService.updateById(sysUser); + //sysUserService.updateSeeYonPassword(sysUser.getSyUserId(),param.getNewPassword()); + return R.ok(); + } + + /** + * (个人)密码更新 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "个人密码更新",biz = BizType.UPDATE) + @PostMapping("/updatePwd") + public R updatePwd(@RequestBody @Valid SysUserPwdParam param){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser dbUser = sysUserService.getById(loginUser.getUserId()); + if(dbUser.getPassword().equalsIgnoreCase(SecureUtil.md5(param.getOldPassword()))){ + SysUser sysUser = new SysUser(); + sysUser.setId(loginUser.getUserId()); + sysUser.setPassword(SecureUtil.md5(param.getNewPassword())); + sysUser.setUpdateTime(LocalDateTime.now()); + sysUserService.updateById(sysUser); + return R.ok(); + } + return R.error(); + } + + /** + * 信息详细 + * @return + */ + @GetMapping("/detail") + public R detail(){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser sysUser = sysUserService.getById(loginUser.getUserId()); + sysUser.setAuthorIds(loginUser.getAuthorIds()); + sysUser.setAuthorList(loginUser.getAuthorList()); + sysUserService.relateInfo(sysUser,true); + sysUser.setPassword(null); + return R.ok(sysUser); + } + + + + /** + * 翻页查询 + * @param param + * @return + */ + @PostMapping("/page") + @PreAuthorize("hasRole('sys:user:query')") + public R> getPage(@RequestBody SysUser param){ + param.setTenantId(AuthContextUtils.getTenant()); + if(CollectionUtil.isNotEmpty(param.getMultiDeptIds()) && param.getLoadChildDept()!=null && param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)){ + List deptList = sysDeptService.listDeptByIds(param.getMultiDeptIds(),param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)); + List deptIds = deptList.stream().map(SysDept::getId).distinct().collect(Collectors.toList()); + param.setMultiDeptIds(deptIds); + } + //PageUtil.startPage(); + PageHelper.startPage(param.getPageNum(),param.getPageSize()); + List list = sysUserService.listUser(param); + //前端页面展示参数 + list.forEach(a->sysUserService.relateInfo(a,false)); + return R.byPageHelperList(list); + } + + + /** + * 列表查询 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:user:query')") + public R> getList(SysUser param){ + param.setTenantId(AuthContextUtils.getTenant()); + if(CollectionUtil.isNotEmpty(param.getMultiDeptIds()) && param.getLoadChildDept()!=null && param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)){ + List deptList = sysDeptService.listDeptByIds(param.getMultiDeptIds(),param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)); + List deptIds = deptList.stream().map(SysDept::getId).distinct().collect(Collectors.toList()); + param.setMultiDeptIds(deptIds); + } + List list = sysUserService.listUser(param); + for (SysUser sysUser : list) { + sysUser.setPassword(null); + List wxUserList = wxUserService.getBySysUserId(sysUser.getId()); + sysUser.setWxUserInfoList(wxUserList); + } + return R.ok(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "人员",desc = "用户查询",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:user:query')") + public R getById(@PathVariable("id") String id){ + SysUser sysUser = sysUserService.getById(id); + if(sysUser==null){ + return R.ok(); + } + sysUser.setPassword(null); + sysUserService.relateInfo(sysUser,true); + List wxUserList = wxUserService.getBySysUserId(sysUser.getId()); + sysUser.setWxUserInfoList(wxUserList); + return R.ok(sysUser); + } + + /** + * 保存 + * @param userBo + * @return + */ + @SysLog(title = "人员",desc = "用户新增",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:user:insert')") + @Transactional(rollbackFor = Exception.class) + public R save(@RequestBody @Valid SysUserBo userBo){ + SysUser param = CopierUtil.copy(userBo,new SysUser()); + param.setAccount(userBo.getCode()); + param.setSyAccount(userBo.getCode()); + //设置普通管理员 + param.setSuperFlag(0); + param.setTenantId(AuthContextUtils.getTenant()); + //检查手机号是否已用 + LambdaQueryWrapper wrapperCode = new LambdaQueryWrapper<>(); + wrapperCode.eq(SysUser::getCode,param.getCode()); + Long countCode = sysUserService.count(wrapperCode); + if(countCode>0L){ + return R.error("工号已被注册"); + } + //检查手机号是否已用 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getMobile,param.getMobile()); + wrapper.ne(SysUser::getServingState,0); + Long count = sysUserService.count(wrapper); + if(count>0L){ + return R.error("手机号已被注册"); + } + param.setPassword(SecureUtil.md5(GySysConst.DEFAULT_PASSWORD)); + if(param.getSyUserId()==null){ + param.setSyUserId(""); + } + if(param.getSyAccount()==null){ + param.setSyAccount(userBo.getCode()); + } + if(!StringUtils.hasText(param.getId())) { + param.setId("SU" + IdUtil.getSnowFlakeId()); + } + param.setServingState(0); + param.setId("SU"+IdUtil.getSnowFlakeId()); + param.setServingState(1); + boolean result = sysUserService.save(param); +// if(param.getId()!=null&& com.qs.serve.common.util.CollectionUtil.isNotEmpty(userBo.getRoleIds())){ +// sysRoleService.saveUserRole4Edit(userBo.getRoleIds(),param.getId()); +// } + return R.isTrue(result); + } + + /** + * 更新 + * @param userBo + * @return + */ + @SysLog(title = "人员",desc = "用户更新",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:user:update')") + @Transactional(rollbackFor = Exception.class) + public R updateById(@RequestBody SysUserBo userBo){ + SysUser param = CopierUtil.copy(userBo,new SysUser()); + param.setCode(null); +// if(param.getLoginEnable()!=null){ +// param.setServingState(param.getLoginEnable()==1?1:0); +// } +// if(param.getSyUserId()==null){ +// param.setSyUserId(""); +// } +// if(param.getSyAccount()==null){ +// param.setSyAccount(""); +// } + param.setSuperFlag(null); + param.setPassword(null); + param.setUpdateTime(LocalDateTime.now()); + boolean result = sysUserService.updateById(param); + return R.isTrue(result); + } + + /** + * 修改销售人员状态 + * @param userBo + * @return + */ + @SysLog(title = "人员",desc = "用户更新",biz = BizType.UPDATE) + @PostMapping("/updateSalesFlag") + @PreAuthorize("hasRole('sys:user:update')") + @Transactional(rollbackFor = Exception.class) + public R updateSalesFlag(@RequestBody @Valid SysUserSalesParam userBo){ + LambdaQueryWrapper lqwSale = new LambdaQueryWrapper<>(); + lqwSale.in(SysUserSales::getPid,userBo.getUserIds()); + if(sysUserSalesService.count(lqwSale)>0){ + return R.error("含有下级销售人员,操作失败"); + } + SysUser param = new SysUser(); + param.setSalesFlag(userBo.getSalesFlag().equals(0)?0:1); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysUser::getId,userBo.getUserIds()); + sysUserService.update(param,lqw); + if(param.getSalesFlag().equals(0)){ + sysUserSalesService.removeBatchByIds(userBo.getUserIds()); + }else { + List existList = sysUserSalesService.listByIds(userBo.getUserIds()); + List insertList = new ArrayList<>(); + for (String userId : userBo.getUserIds()) { + boolean exist = false; + for (SysUserSales userSales : existList) { + if(userId.equals(userSales.getUserId())){ + exist = true; + break; + } + } + if(!exist){ + SysUserSales userSale = new SysUserSales(); + userSale.setUserId(userId); + userSale.setPid("0"); + userSale.setPathIds("0_"+userId); + insertList.add(userSale); + } + } + sysUserSalesService.saveBatch(insertList); + } + return R.ok(); + } + + /** + * 用户path_ids初始化 + * @return + */ + @SysLog(title = "人员",desc = "用户path_ids初始化",biz = BizType.UPDATE) + @PostMapping("/initSalesParentPathIds") + @PreAuthorize("hasRole('sys:user:update')") + @Transactional(rollbackFor = Exception.class) + public R updateSalesParent(){ + LambdaQueryWrapper lqwSale = new LambdaQueryWrapper<>(); + lqwSale.eq(SysUserSales::getPid,"0"); + List userSales = sysUserSalesService.list(lqwSale); + userSales.forEach(a->{ + a.setPathIds("0_"+a.getUserId()); + }); + sysUserSalesService.updateBatchById(userSales); + initPath(userSales); + return R.ok(); + } + + + private void initPath(List pSales){ + pSales.forEach(p->{ + LambdaQueryWrapper lqwSale = new LambdaQueryWrapper<>(); + lqwSale.eq(SysUserSales::getPid,p.getUserId()); + List userSales = sysUserSalesService.list(lqwSale); + userSales.forEach(a->{ + a.setPathIds(p.getPathIds()+"_"+a.getUserId()); + }); + sysUserSalesService.updateBatchById(userSales); + + initPath(userSales); + }); + } + + /** + * 修改销售人员上下级 + * @param userBo + * @return + */ + @SysLog(title = "人员",desc = "用户更新",biz = BizType.UPDATE) + @PostMapping("/updateSalesParent") + @PreAuthorize("hasRole('sys:user:update')") + @Transactional(rollbackFor = Exception.class) + public R updateSalesParent(@RequestBody @Valid SysUserParentParam userBo){ + final String pid = userBo.getParentId(); + final List userIds = new ArrayList<>(); + userIds.addAll(userBo.getUserIds()); + if(!pid.equals("0")){ + userIds.add(pid); + } + List sysUserList = sysUserService.listByIds(userIds); + for (SysUser sysUser : sysUserList) { + if(sysUser.getSalesFlag().equals(0)){ + return R.error("["+sysUser.getName()+"]未设置销售属性"); + } + } + List updateAllList = new ArrayList<>(); + if(pid.equals("0")){ + //清除父级,还原回一级 + List sysUserSales = sysUserSalesService.listByIds(userBo.getUserIds()); + List updateList = this.updateSalesLevel(pid, "0", sysUserSales); + updateAllList.addAll(updateList); + }else { + SysUserSales parent = sysUserSalesService.getById(pid); + List sysUserSales = sysUserSalesService.listByIds(userBo.getUserIds()); + List updateList = this.updateSalesLevel(pid, parent.getPathIds(), sysUserSales); + updateAllList.addAll(updateList); + } + sysUserSalesService.updateBatchById(updateAllList); + return R.ok(); + } + + /** + * 更新id路径 + * @param pid + * @param newPrefixPath + * @param sysUserSales + * @return + */ + private List updateSalesLevel(String pid,String newPrefixPath,List sysUserSales) { + + List updateList = new ArrayList<>(); + for (SysUserSales userSale : sysUserSales) { + if(newPrefixPath.contains("_"+userSale.getUserId())){ + Assert.throwEx("不能选择该人员,上下级死循环"); + } + String pathIds = userSale.getPathIds(); + userSale.setPathIds(newPrefixPath+"_"+userSale.getUserId()); + userSale.setPid(pid); + updateList.add(userSale); + + //更新子节点 + if(pathIds.lastIndexOf(userSale.getUserId())<0){ + return updateList; + } + String oldPrefixPath = pathIds.substring(0,pathIds.lastIndexOf("_"+userSale.getUserId())-1); + log.info(oldPrefixPath); + List childList = sysUserSalesService.listByPathId(pathIds); + for (SysUserSales childNode : childList) { + String childPathIds = newPrefixPath + childNode.getPathIds().replace(oldPrefixPath, ""); + childNode.setPathIds(childPathIds); + updateList.add(childNode); + } + + } + return updateList; + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "人员",desc = "用户删除",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:user:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysUserService.removeById(id); + return R.isTrue(result); + } + + /** + * 重置密码 + * @param uid + * @return + */ + @SysLog(title = "人员",desc = "重置密码",biz = BizType.RESET) + @PostMapping("/resetPwd/{uid}") + @PreAuthorize("hasRole('sys:user:reset')") + public R resetPwd(@PathVariable("uid") String uid){ + SysUser sysUser = sysUserService.getById(uid); +// if(sysUser.getSuperFlag().equals(1)){ +// Assert.throwEx("最高级管理员不可重置密码"); +// } + SysUser sysUser1 = new SysUser(); + sysUser1.setId(uid); + sysUser1.setPassword(SecureUtil.md5(GySysConst.DEFAULT_PASSWORD)); + sysUserService.updateById(sysUser1); + return R.ok(); + } + + /** + * 人员离职(更新即将离职信息) + * @param userLeaveParam + * @return + */ + @SysLog(title = "人员",desc = "离职调整",biz = BizType.LEAVE) + @PostMapping("/leave") + //@PreAuthorize("hasRole('sys:user:leave')") + public R leave(@RequestBody @Valid SysUserLeaveBo userLeaveParam){ + sysUserService.leave(userLeaveParam); + return R.ok(); + } + + + /** + * 取消离职 + * @param uid + * @return + */ + @SysLog(title = "人员",desc = "取消离职",biz = BizType.RESET) + @PostMapping("/cancelLeave/{uid}") + //@PreAuthorize("hasRole('sys:user:leave')") + public R cancelLeave(@PathVariable("uid") String uid){ + sysUserService.cancelLeave(uid); + return R.ok(); + } + + /** + * 重新入职 + * @param uid + * @return + */ + @SysLog(title = "人员",desc = "重新入职",biz = BizType.RESET) + @PostMapping("/reEntry/{uid}") + //@PreAuthorize("hasRole('sys:user:leave')") + public R reEntry(@PathVariable("uid") String uid){ + sysUserService.reEntry(uid); + return R.ok(); + } + + /** + * 人员立刻离职 + * @param userId + * @return + */ + @SysLog(title = "人员",desc = "离职调整",biz = BizType.LEAVE) + @PostMapping("/leaveNow") + public R leaveNow(String userId){ + sysUserService.leaveNow(Arrays.asList(userId),true); + return R.ok(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/api/SysDictApi.java b/src/main/java/com/qs/serve/modules/sys/controller/api/SysDictApi.java new file mode 100644 index 0000000..9ca6d8f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/api/SysDictApi.java @@ -0,0 +1,69 @@ +package com.qs.serve.modules.sys.controller.api; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.controller.SysAttachController; +import com.qs.serve.modules.sys.entity.SysDict; +import com.qs.serve.modules.sys.entity.SysDictData; +import com.qs.serve.modules.sys.service.SysDictDataService; +import com.qs.serve.modules.sys.service.SysDictService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * API系统 字典 + * @author YenHex + * @since 2022-05-20 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("api/dict") +public class SysDictApi { + + private SysDictDataService sysDictDataService; + + private SysAttachController attachController; + + /** + * 列表查询 + * @param group 分组key + * @return + */ + @GetMapping("/list") + public R getList(String group){ + if(StringUtils.hasEmpty(group)){ + return R.error("查询参数为空"); + } + LambdaQueryWrapper dictWrapper = new LambdaQueryWrapper<>(); + dictWrapper.eq(SysDictData::getGroupKey,group); + dictWrapper.orderByDesc(SysDictData::getSort); + List list = sysDictDataService.list(dictWrapper); + return R.ok(list); + } + + /** + * 附件上传 + * @param request + * @return + */ + @PostMapping("/upload") + public R upload(HttpServletRequest request){ + return attachController.upload(request); + } + + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java b/src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java new file mode 100644 index 0000000..dce3569 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java @@ -0,0 +1,70 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 系统附件 实体类 + * @author YenHex + * @since 2022-03-24 + */ +@Data +@TableName("sys_attach") +public class SysAttach implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 文件名称 */ + private String name; + + /** 保存路径 */ + private String path; + + /** 大小 */ + private Long size; + + /** 文件类型 */ + private String fileType; + + private String relativePath; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @NotNull(message = "删除标识不能为空") + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysBusinessLog.java b/src/main/java/com/qs/serve/modules/sys/entity/SysBusinessLog.java new file mode 100644 index 0000000..fa3eac2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysBusinessLog.java @@ -0,0 +1,147 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 实体类 + * @author YenHex + * @since 2023-04-25 + */ +@Data +@TableName("sys_business_log") +public class SysBusinessLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 用户id */ + @Length(max = 255,message = "用户id长度不能超过255字") + private String userId; + + /** 用户编码 */ + @Length(max = 255,message = "用户编码长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String userCode; + + /** 用户 */ + @Length(max = 255,message = "用户长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String userName; + + /** 目标类型 */ + @Length(max = 255,message = "目标类型长度不能超过255字") + private String targetType; + + /** 目标id */ + @Length(max = 255,message = "目标id长度不能超过255字") + private String targetId; + + /** 目标 */ + @Length(max = 255,message = "目标长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String targetCode; + + /** 目标 */ + @Length(max = 255,message = "目标长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String targetName; + + /** 目标关联id */ + @Length(max = 255,message = "目标关联id长度不能超过255字") + private String targetRelateId; + + /** 操作类型 */ + @Length(max = 255,message = "操作类型长度不能超过255字") + private String optType; + + /** 原来值 */ + @Length(max = 255,message = "原来值长度不能超过255字") + private String orgJson; + + /** 新值 */ + @Length(max = 255,message = "新值长度不能超过255字") + private String newJson; + + /** 差异值 */ + @Length(max = 255,message = "差异值长度不能超过255字") + private String diffJson; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + + public static SysBusinessLog toNewObject(SysBusinessLog source){ + SysBusinessLog businessLog = new SysBusinessLog(); + businessLog.setId(source.getId()); + businessLog.setUserId(source.getUserId()); + businessLog.setUserCode(source.getUserCode()); + businessLog.setUserName(source.getUserName()); + businessLog.setTargetType(source.getTargetType()); + businessLog.setTargetId(source.getTargetId()); + businessLog.setTargetCode(source.getTargetCode()); + businessLog.setTargetName(source.getTargetName()); + businessLog.setTargetRelateId(source.getTargetRelateId()); + businessLog.setOptType(source.getOptType()); + businessLog.setOrgJson(source.getOrgJson()); + businessLog.setNewJson(source.getNewJson()); + businessLog.setDiffJson(source.getDiffJson()); + businessLog.setRemark(source.getRemark()); + businessLog.setCreateTime(source.getCreateTime()); + businessLog.setUpdateTime(source.getUpdateTime()); + businessLog.setTenantId(source.getTenantId()); + businessLog.setDelFlag(source.getDelFlag()); + businessLog.setCreateBy(source.getCreateBy()); + businessLog.setUpdateBy(source.getUpdateBy()); + return businessLog; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysConfig.java b/src/main/java/com/qs/serve/modules/sys/entity/SysConfig.java new file mode 100644 index 0000000..776ca03 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysConfig.java @@ -0,0 +1,81 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 实体类 + * @author YenHex + * @since 2022-11-12 + */ +@Data +@TableName("sys_config") +public class SysConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 参数名称 */ + @Length(max = 100,message = "参数名称长度不能超过100字") + private String configName; + + /** 参数键名 */ + @Length(max = 100,message = "参数键名长度不能超过100字") + private String configKey; + + /** 参数键值 */ + @Length(max = 500,message = "参数键值长度不能超过500字") + private String configValue; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysDeleteLog.java b/src/main/java/com/qs/serve/modules/sys/entity/SysDeleteLog.java new file mode 100644 index 0000000..3526391 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysDeleteLog.java @@ -0,0 +1,86 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 删除日志 实体类 + * @author YenHex + * @since 2023-12-08 + */ +@Data +@TableName("sys_delete_log") +public class SysDeleteLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 删除批次 */ + private String batchCode; + + /** 选项类型 */ + @Length(max = 50,message = "选项类型长度不能超过50字") + private String targetTable; + + /** 目标id */ + @Length(max = 100,message = "目标id长度不能超过100字") + private String targetId; + + /** 目标编码 */ + @Length(max = 100,message = "目标编码长度不能超过100字") + private String targetCode; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysDept.java b/src/main/java/com/qs/serve/modules/sys/entity/SysDept.java new file mode 100644 index 0000000..c7ba2a2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysDept.java @@ -0,0 +1,79 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 部门信息 实体类 + * @author YenHex + * @since 2022-02-28 + */ +@Data +@TableName("sys_dept") +public class SysDept implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.INPUT) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 部门编号 */ + @NotNull(message = "部门编号不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String parentId; + + /** 负责人 */ + private String mgrUserId; + + /** 级别路径 */ + private String levelPath; + + /** 停用状态 */ + private Integer stopFlag; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** 负责人信息 */ + @TableField(exist = false) + private String mgrUserName; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysDict.java b/src/main/java/com/qs/serve/modules/sys/entity/SysDict.java new file mode 100644 index 0000000..4780f12 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysDict.java @@ -0,0 +1,77 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 字典 实体类 + * @author YenHex + * @since 2022-11-04 + */ +@Data +@TableName("sys_dict") +public class SysDict implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 字典key */ + @NotBlank(message = "字典key不能为空") + @Length(max = 50,message = "字典key长度不能超过50字") + private String dictKey; + + /** 字典组名 */ + @NotBlank(message = "字典组名不能为空") + @Length(max = 50,message = "字典组名长度不能超过50字") + private String dictName; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysDictData.java b/src/main/java/com/qs/serve/modules/sys/entity/SysDictData.java new file mode 100644 index 0000000..2e11a84 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysDictData.java @@ -0,0 +1,85 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 字典数据 实体类 + * @author YenHex + * @since 2022-11-04 + */ +@Data +@TableName("sys_dict_data") +public class SysDictData implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 字典id */ + private Long dictId; + + /** 字典key */ + @Length(max = 50,message = "字典key长度不能超过50字") + private String groupKey; + + /** 数据值 */ + @Length(max = 50,message = "数据值长度不能超过50字") + private String keyVal; + + /** 数据标题 */ + @Length(max = 50,message = "数据标题长度不能超过50字") + private String label; + + /** 排序 */ + private Integer sort; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java b/src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java new file mode 100644 index 0000000..92c5c4d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java @@ -0,0 +1,58 @@ +package com.qs.serve.modules.sys.entity; + +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 系统菜单 实体类 + * @author YenHex + * @since 2022-03-15 + */ +@Data +@TableName("sys_menu") +public class SysMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.INPUT) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 排序 */ + private Integer sort; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型不能为空") + private Integer type; + + /** 是否隐藏 */ + @NotNull(message = "是否隐藏不能为空") + private Integer hideFlag; + + /** 客户端类型 */ + @NotNull(message = "客户端类型不能为空") + private Integer clientType; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @TableField(exist = false) + private List permitIds; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java b/src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java new file mode 100644 index 0000000..7451e62 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java @@ -0,0 +1,62 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 菜单权限 实体类 + * @author YenHex + * @since 2022-03-15 + */ +@Data +@TableName("sys_menu_permit") +public class SysMenuPermit implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 菜单ID */ + private String menuId; + + /** 权限ID */ + private String permitId; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @NotNull(message = "删除标识不能为空") + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java b/src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java new file mode 100644 index 0000000..4c7c51c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java @@ -0,0 +1,140 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.qs.serve.common.framework.mybatis.handler.meta.JsonStringTypeHandler; +import lombok.Data; +import org.apache.ibatis.type.JdbcType; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 注意信息 实体类 + * @author YenHex + * @since 2022-02-28 + */ +@Data +@TableName(value = "sys_notice",autoResultMap = true) +public class SysNotice implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 标题 */ + @NotNull + @TableField(condition = SqlCondition.LIKE) + @Length(max = 255,message = "输入内容不能超过50字") + private String title; + + /** 类型ID */ + private String typeId; + + /** 内容 */ + @NotNull + private String content; + + /** + * 是否启用 + */ + private Integer enable; + + /** + * 可见类型【0->所有人可见;1->部分人员可见;2->部门可见】 + */ + @NotNull + private Integer visibleType; + + /** + * 最新的发布时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime lastPublishTime; + + /** + * 可见目标id集合 + */ + @TableField(typeHandler = JsonStringTypeHandler.class,jdbcType = JdbcType.VARCHAR) + private String[] visibleIds; + + /** + * 附件id集合 + */ + @TableField(typeHandler = JsonStringTypeHandler.class,jdbcType = JdbcType.VARCHAR) + private String[] docIds; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** + * 附件列表 + */ + @TableField(exist = false) + private Object documents; + + /** + * 可见部门 + */ + @TableField(exist = false) + private Object deps; + + /** + * 可见人 + */ + @TableField(exist = false) + private Object userInfos; + + /** + * 开始时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryStartTime; + + /** + * 结束时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryEndTime; + + /** + * 创建人名称 + */ + @TableField(exist = false) + private String creatorName; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java new file mode 100644 index 0000000..8b34676 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 注意信息分类 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_notice_type") +public class SysNoticeType implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** name */ + @TableField(condition = SqlCondition.LIKE) + private String name; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java new file mode 100644 index 0000000..58d0e94 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java @@ -0,0 +1,94 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 注意信息&用户关系 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_notice_user") +public class SysNoticeUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 标题 */ + private String noticeId; + + /** 用户ID */ + private String userId; + + /** 阅读标识【0->未读;1->已读】 */ + private Boolean readFlag; + + /** 阅读时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime readTime; + + /** + * 阅读统计 + */ + private Integer readCount; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @JsonIgnore + private String tenantId; + + /** 标题 */ + @TableField(exist = false) + private String title; + + /** + * 开始时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryStartTime; + + /** + * 结束时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryEndTime; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java b/src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java new file mode 100644 index 0000000..1585b3d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java @@ -0,0 +1,116 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 操作日志 实体类 + * @author YenHex + * @since 2022-03-08 + */ +@Data +@TableName("sys_operation_log") +public class SysOperationLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 模块 */ + private String module; + + /** 模块标题 */ + @TableField(condition = SqlCondition.LIKE) + private String title; + + /** 业务类型 */ + private String bizType; + + private String optDesc; + + /** 接口类型 */ + private String interType; + + /** 代码方法 */ + private String codeMethod; + + /** 请求方式 */ + private String reqMethod; + + /** 请求地址 */ + private String reqUrl; + + /** 请求参数 */ + private String reqParam; + + /** 访问IP */ + private String reqIp; + + /** 用户类型 */ + private String userType; + + /** 用户ID */ + private String userId; + + /** 错误信息 */ + private String errMsg; + + /** 返回参数 */ + private String jsonResult; + + /** 耗时(单位毫秒) */ + private Long elapsedTime; + + /** 用户代理 */ + private String userAgent; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** 创建人名称 */ + @TableField(condition = SqlCondition.LIKE) + private String creatorName; + + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryStartTime; + + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryEndTime; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysOperationManual.java b/src/main/java/com/qs/serve/modules/sys/entity/SysOperationManual.java new file mode 100644 index 0000000..0eeef46 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysOperationManual.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.qs.serve.common.framework.mybatis.handler.meta.SplitStringTypeHandler; +import lombok.Data; +import org.apache.ibatis.type.JdbcType; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 实体类 + * @author YenHex + * @since 2023-08-11 + */ +@Data +@TableName(value = "sys_operation_manual", autoResultMap = true) +public class SysOperationManual implements Serializable { + + private static final long serialVersionUID = 1L; + + /** */ + @TableId(type = IdType.AUTO) + private Long id; + + /** */ + @Length(max = 255,message = "长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String name; + + /** 附件id */ + @TableField(typeHandler = SplitStringTypeHandler.class,jdbcType= JdbcType.VARCHAR) + private String[] attachIds; + + @TableField(exist = false) + private List attachList; + + /** */ + @JsonIgnore + @JsonProperty + private String delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java b/src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java new file mode 100644 index 0000000..0e6d6a9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 系统权限 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_permit") +public class SysPermit implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 编码 */ + @NotBlank(message = "编码不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型【0->菜单;1->按钮】不能为空") + private Integer type; + + private String url; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @JsonIgnore + private Integer hideFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysPost.java b/src/main/java/com/qs/serve/modules/sys/entity/SysPost.java new file mode 100644 index 0000000..350ebe7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysPost.java @@ -0,0 +1,98 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 系统职务 实体类 + * @author YenHex + * @since 2023-04-27 + */ +@Data +@TableName("sys_post") +public class SysPost implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull + @Length(max = 20,message = "名称长度不能超过20字") + @TableField(condition = SqlCondition.LIKE) + private String postName; + + /** 编码 */ + @Length(max = 30,message = "编码长度不能超过30字") + @TableField(condition = SqlCondition.LIKE) + private String postCode; + + private String pid; + + /** id路径 */ + @Length(max = 4255,message = "id路径长度不能超过4255字") + private String pathIds; + + /** 名称路径 */ + @Length(max = 4255,message = "名称路径长度不能超过4255字") + @TableField(condition = SqlCondition.LIKE) + private String pathNames; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + @TableField(exist = false) + private Object parentInfo; + + @TableField(exist = false) + private List postUserList; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysPostUser.java b/src/main/java/com/qs/serve/modules/sys/entity/SysPostUser.java new file mode 100644 index 0000000..96e314a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysPostUser.java @@ -0,0 +1,132 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 系统职务 实体类 + * @author YenHex + * @since 2023-04-27 + */ +@Data +@TableName("sys_post_user") +public class SysPostUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 用户id */ + @Length(max = 255,message = "用户id长度不能超过255字") + private String userId; + + /** 用户编码 */ + @Length(max = 255,message = "用户编码长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String userCode; + + /** 用户名称 */ + @Length(max = 255,message = "用户名称长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String userName; + + /** 岗位id */ + @Length(max = 64,message = "岗位id长度不能超过64字") + private String postId; + + /** 岗位名称 */ + @Length(max = 20,message = "岗位名称长度不能超过20字") + @TableField(condition = SqlCondition.LIKE) + private String postName; + + /** 岗位编码 */ + @Length(max = 30,message = "岗位编码长度不能超过30字") + @TableField(condition = SqlCondition.LIKE) + private String postCode; + + /** 岗位pid */ + @Length(max = 64,message = "岗位pid长度不能超过64字") + private String pid; + + /** id路径 */ + @Length(max = 4255,message = "id路径长度不能超过4255字") + private String pathIds; + + /** 名称路径 */ + @Length(max = 4255,message = "名称路径长度不能超过4255字") + private String pathNames; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + + public static SysPostUser toNewObject(SysPostUser source){ + SysPostUser postUser = new SysPostUser(); + postUser.setId(source.getId()); + postUser.setUserId(source.getUserId()); + postUser.setUserCode(source.getUserCode()); + postUser.setUserName(source.getUserName()); + postUser.setPostId(source.getPostId()); + postUser.setPostName(source.getPostName()); + postUser.setPostCode(source.getPostCode()); + postUser.setPid(source.getPid()); + postUser.setPathIds(source.getPathIds()); + postUser.setPathNames(source.getPathNames()); + postUser.setRemark(source.getRemark()); + postUser.setCreateTime(source.getCreateTime()); + postUser.setCreateBy(source.getCreateBy()); + postUser.setUpdateTime(source.getUpdateTime()); + postUser.setUpdateBy(source.getUpdateBy()); + postUser.setTenantId(source.getTenantId()); + postUser.setDelFlag(source.getDelFlag()); + return postUser; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysRole.java b/src/main/java/com/qs/serve/modules/sys/entity/SysRole.java new file mode 100644 index 0000000..973c494 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysRole.java @@ -0,0 +1,75 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 系统角色 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_role") +public class SysRole implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 角色名称 */ + @NotNull(message = "角色名称不能为空") + private String name; + + /** 是否可用 */ + private Integer enable; + + /** 是否默认 */ + private Integer isDefault; + + /** 是否默认 */ + private Integer userVisible; + + /** 显示人员模板中 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + @JsonIgnore + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @TableField(exist = false) + private List menuList; + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java b/src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java new file mode 100644 index 0000000..bbea731 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java @@ -0,0 +1,62 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 菜单用户 实体类 + * @author YenHex + * @since 2022-03-16 + */ +@Data +@TableName("sys_role_menu") +public class SysRoleMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 角色ID */ + private String menuId; + + /** 角色ID */ + private String roleId; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @NotNull(message = "删除标识不能为空") + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysSyncLog.java b/src/main/java/com/qs/serve/modules/sys/entity/SysSyncLog.java new file mode 100644 index 0000000..b235443 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysSyncLog.java @@ -0,0 +1,98 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 同步日志 实体类 + * @author YenHex + * @since 2023-03-15 + */ +@Data +@TableName("sys_sync_log") +public class SysSyncLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 来自系统 */ + @Length(max = 255,message = "来自系统长度不能超过255字") + @TableField(value = "form_plat") + private String fromPlat; + + /** 请求地址 */ + @Length(max = 255,message = "请求地址长度不能超过255字") + private String url; + + /** 请求类 */ + @Length(max = 255,message = "请求类长度不能超过255字") + private String entityClass; + + /** 请求json */ + @Length(max = 255,message = "请求json长度不能超过255字") + private String requestJson; + + /** 失败原因 */ + @Length(max = 255,message = "失败原因长度不能超过255字") + private String failReason; + + /** 成功标识 */ + private Integer successStatus; + + /** 是否需要处理 */ + private Integer todoState; + + private Integer tryTimes; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysTableTemp.java b/src/main/java/com/qs/serve/modules/sys/entity/SysTableTemp.java new file mode 100644 index 0000000..1441d9e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysTableTemp.java @@ -0,0 +1,102 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 临时数据表 实体类 + * @author YenHex + * @since 2024-01-15 + */ +@Data +@TableName("sys_table_temp") +public class SysTableTemp implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 表 */ + @Length(max = 255,message = "表长度不能超过255字") + private String tableName; + + /** 数据id */ + @Length(max = 255,message = "数据id长度不能超过255字") + private String tableId; + + /** 业务名称 */ + @Length(max = 255,message = "业务名称长度不能超过255字") + private String optionTitle; + + /** 结果 */ + @Length(max = 255,message = "结果长度不能超过255字") + private String resultMsg; + + private Integer dealState; + + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + + public static SysTableTemp toNewObject(SysTableTemp source){ + SysTableTemp tableTemp = new SysTableTemp(); + tableTemp.setId(source.getId()); + tableTemp.setTableName(source.getTableName()); + tableTemp.setTableId(source.getTableId()); + tableTemp.setOptionTitle(source.getOptionTitle()); + tableTemp.setResultMsg(source.getResultMsg()); + tableTemp.setCreateTime(source.getCreateTime()); + tableTemp.setCreateBy(source.getCreateBy()); + tableTemp.setUpdateTime(source.getUpdateTime()); + tableTemp.setUpdateBy(source.getUpdateBy()); + tableTemp.setTenantId(source.getTenantId()); + tableTemp.setDelFlag(source.getDelFlag()); + return tableTemp; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java b/src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java new file mode 100644 index 0000000..e3554ea --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java @@ -0,0 +1,59 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * 系统租户 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_tenant") +public class SysTenant implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 租户id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 租户名称 */ + @TableField(condition = SqlCondition.LIKE) + private String name; + + /** 校区电话 */ + private String callNum; + + /** 校区地址 */ + private String address; + + /** 创建时间 */ + @JsonIgnore + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @JsonIgnore + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @JsonIgnore + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @JsonIgnore + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUser.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUser.java new file mode 100644 index 0000000..73b9e45 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUser.java @@ -0,0 +1,256 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.io.Serializable; +import java.util.List; + +import cn.hutool.core.util.DesensitizedUtil; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.dto.SysUserSimpleVo; +import com.qs.serve.modules.sys.entity.dto.SysUserVo; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; + +/** + * 系统用户 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_user") +public class SysUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.INPUT) + private String id; + + /** 手机号 */ + @NotBlank(message = "手机号不能为空") + @Length(max = 64,message = "手机号长度不能超过64字") + private String mobile; + + /** 账号 */ + @Length(max = 64,message = "账号长度不能超过64字") + private String account; + + /** 昵称 */ + @Length(max = 64,message = "昵称长度不能超过64字") + private String name; + + /** 编号/工号 */ + @Length(max = 64,message = "编号/工号长度不能超过64字") + private String code; + + /** 密码 */ + @Length(max = 64,message = "密码长度不能超过64字") + private String password; + + /** 头像 */ + @Length(max = 255,message = "头像长度不能超过255字") + private String icon; + + /** 部门ID */ + @Length(max = 64,message = "部门ID长度不能超过64字") + private String deptId; + + /** 超级管理标识【0->普通管理员;1->超级管理员】 */ + private Integer superFlag; + + /** 系统登录权限【0->停用;1->启用】 */ + private Integer loginEnable; + + /** 在职状态【0->离职;1->在职;2->准备离职】 */ + private Integer servingState; + + /** 入职/复职日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate servingDate; + + /** 离职或上一次离职的日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate servingLeaveDate; + + /** 是否销售人员 */ + private Integer salesFlag; + + /** 身份证号码 */ + @Length(max = 45,message = "身份证号码长度不能超过45字") + private String identityNo; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + + /** 登陆客户端标识:android,ios */ + private String appClient; + + /** app推送token */ + private String appToken; + + /** 致远登陆账户 */ + private String syAccount; + + /** 致远用户id */ + private String syUserId; + + private String hrSystemInfo; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + + + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** 校区id */ + @JsonIgnore + private String tenantId; + + /** 在职状态【0->离职;1->在职;】 */ + @TableField(exist = false) + private String servingQueryState; + + /** 查询参数:部门ID多选 */ + @TableField(exist = false) + private List multiDeptIds; + + /** 查询参数:角色ID多选,新增用户时用 */ + @TableField(exist = false) + private List roleIds; + + /** 查询参数:是否加载部门子项参数 */ + @TableField(exist = false) + private Integer loadChildDept; + + /** 部门信息 */ + @TableField(exist = false) + private SysDept deptInfo; + + /** 角色信息 */ + @TableField(exist = false) + private List roleList; + + /** 权限编码 */ + @TableField(exist = false) + private List authorList; + + /** 权限ID */ + @TableField(exist = false) + private List authorIds; + + /** 选中ID */ + @TableField(exist = false) + private List selectIds; + + /** 选中岗位ID */ + @TableField(exist = false) + private List selectPostIds; + + @TableField(exist = false) + private List tenantInfo; + + @TableField(exist = false) + private List wxUserInfoList; + + @TableField(exist = false) + private String parentId; + + /** + * 离职信息 + */ + @TableField(exist = false) + private Object leaveInfo; + + + @TableField(exist = false) + private Integer pageNum; + + @TableField(exist = false) + private Integer pageSize; + + @TableField(exist = false) + private List positionList; + + /** + * 返回前端,过滤敏感信息 + * @return + */ + public SysUserVo toSysUserVo() { + return toSysUserVo(true); + } + + /** + * 返回前端,过滤敏感信息 + * @return + */ + public SysUserVo toSysUserVo(boolean desensitize) { + SysUserVo sysUserVo = CopierUtil.copy(this,new SysUserVo()); + if(desensitize){ + sysUserVo.setMobile(DesensitizedUtil.mobilePhone(sysUserVo.getMobile())); + sysUserVo.setAccount(DesensitizedUtil.mobilePhone(sysUserVo.getMobile())); + } + return sysUserVo; + } + + public boolean checkSyAccount(){ + return checkSyAccount(true); + } + + public boolean checkSyAccount(boolean throwEx){ + if(StringUtils.hasText(this.getSyUserId())){ + return true; + } + if(throwEx){ + Assert.throwEx("当前账号未设置致远信息"); + } + return false; + } + + /** + * 返回前端,过滤敏感信息 + * @return + */ + public SysUserSimpleVo toSimpleVo(boolean desensitize) { + SysUserSimpleVo sysUserVo = CopierUtil.copy(this,new SysUserSimpleVo()); + if(desensitize){ + sysUserVo.setMobile(DesensitizedUtil.mobilePhone(sysUserVo.getMobile())); + } + return sysUserVo; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUserCodeMath.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUserCodeMath.java new file mode 100644 index 0000000..eb2543a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUserCodeMath.java @@ -0,0 +1,89 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 用户编码对照表 实体类 + * @author YenHex + * @since 2023-09-08 + */ +@Data +@TableName("sys_user_code_math") +public class SysUserCodeMath implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 旧编码 */ + @Length(max = 255,message = "旧编码长度不能超过255字") + @TableId(type = IdType.ASSIGN_UUID) + private String sourCode; + + /** 当前编码 */ + @Length(max = 255,message = "当前编码长度不能超过255字") + private String currCode; + + /** 用户名称 */ + @Length(max = 255,message = "用户名称长度不能超过255字") + private String userName; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + + public static SysUserCodeMath toNewObject(SysUserCodeMath source){ + SysUserCodeMath userCodeMath = new SysUserCodeMath(); + userCodeMath.setSourCode(source.getSourCode()); + userCodeMath.setCurrCode(source.getCurrCode()); + userCodeMath.setUserName(source.getUserName()); + userCodeMath.setCreateTime(source.getCreateTime()); + userCodeMath.setUpdateTime(source.getUpdateTime()); + userCodeMath.setTenantId(source.getTenantId()); + userCodeMath.setCreateBy(source.getCreateBy()); + userCodeMath.setUpdateBy(source.getUpdateBy()); + userCodeMath.setDelFlag(source.getDelFlag()); + return userCodeMath; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUserLeave.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUserLeave.java new file mode 100644 index 0000000..03d030d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUserLeave.java @@ -0,0 +1,132 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 用户离职 实体类 + * @author YenHex + * @since 2023-02-13 + */ +@Data +@TableName("sys_user_leave") +public class SysUserLeave implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 离职员工id */ + @NotBlank(message = "离职员工id不能为空") + @Length(max = 32,message = "离职员工id长度不能超过32字") + private String userId; + + /** 离职员工 */ + @Length(max = 32,message = "离职员工长度不能超过32字") + private String userName; + + /** 离职员工工号 */ + @Length(max = 32,message = "离职员工工号长度不能超过32字") + private String userCode; + + /** 状态:0-待处理;1-已处理;2-取消离职 */ + @NotNull(message = "状态:0-待处理;1-已处理;2-取消离职不能为空") + private Integer leaveStatus; + + /** 离职原因 */ + @Length(max = 255,message = "离职原因长度不能超过255字") + private String leaveReason; + + /** 离职取消日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime leaveCancelDate; + + /** 离职生效日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate leaveEffectDate; + + /** 工作交接人id */ + @Length(max = 32,message = "工作交接人id长度不能超过32字") + private String flowUserId; + + /** 工作交接人 */ + @Length(max = 32,message = "工作交接人长度不能超过32字") + private String flowUserName; + + /** 工作交接人工号 */ + @Length(max = 32,message = "工作交接人工号长度不能超过32字") + private String flowUserCode; + + /** 客户交接人id */ + @Length(max = 32,message = "客户交接人id长度不能超过32字") + private String cusUserId; + + /** 客户交接人 */ + @Length(max = 32,message = "客户交接人长度不能超过32字") + private String cusUserName; + + /** 客户交接人工号 */ + @Length(max = 32,message = "客户交接人工号长度不能超过32字") + private String cusUserCode; + + /** 角色交接人id */ + @Length(max = 32,message = "角色交接人id长度不能超过32字") + private String roleUserId; + + /** 角色交接人 */ + @Length(max = 32,message = "角色交接人长度不能超过32字") + private String roleUserName; + + /** 角色交接人工号 */ + @Length(max = 32,message = "角色交接人工号长度不能超过32字") + private String roleUserCode; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + /** 系统id */ + @JsonIgnore + @JsonProperty + private String tenantId; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java new file mode 100644 index 0000000..bf78e73 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java @@ -0,0 +1,57 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 用户角色 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_user_role") +public class SysUserRole implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 用户ID */ + private String userId; + + /** 角色ID */ + private String roleId; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUserSales.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUserSales.java new file mode 100644 index 0000000..2bf9397 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUserSales.java @@ -0,0 +1,65 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 实体类 + * @author YenHex + * @since 2022-10-12 + */ +@Data +@TableName("sys_user_sales") +public class SysUserSales implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 用户id */ + @Length(max = 32,message = "用户id长度不能超过32字") + @TableId(type = IdType.INPUT) + private String userId; + + /** 父级id */ + @Length(max = 32,message = "父级id长度不能超过32字") + private String pid; + + private String pathIds; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysConfigBo.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysConfigBo.java new file mode 100644 index 0000000..a5c7754 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysConfigBo.java @@ -0,0 +1,37 @@ +package com.qs.serve.modules.sys.entity.bo; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * Bo + * @author YenHex + * @since 2022-11-12 + */ +@Data +public class SysConfigBo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 参数键名 */ + @Length(max = 100,message = "参数键名长度不能超过100字") + private String configKey; + + /** 参数键值 */ + @Length(max = 500,message = "参数键值长度不能超过500字") + private String configValue; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysDeptBatchBo.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysDeptBatchBo.java new file mode 100644 index 0000000..40e1bfa --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysDeptBatchBo.java @@ -0,0 +1,17 @@ +package com.qs.serve.modules.sys.entity.bo; + +import com.qs.serve.modules.sys.entity.SysDept; +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2022/10/8 + */ +@Data +public class SysDeptBatchBo { + + List deptList; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysPostUserBo.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysPostUserBo.java new file mode 100644 index 0000000..7cdb9f6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysPostUserBo.java @@ -0,0 +1,43 @@ +package com.qs.serve.modules.sys.entity.bo; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 系统职务 Bo + * @author YenHex + * @since 2023-04-27 + */ +@Data +public class SysPostUserBo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 用户id */ + private List userIds; + + /** 岗位id */ + private List postIds; + + /** + * 0:添加不进行删除 + * 1:以`用户id`为参照物,删除历史`岗位id`,并重新添加新的`岗位id` + * 2:以`岗位id`为参照物,删除历史`用户id`,并重新添加新的`用户id` + */ + private Integer saveType; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysRelateSuppliersParam.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysRelateSuppliersParam.java new file mode 100644 index 0000000..5e24077 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysRelateSuppliersParam.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.sys.entity.bo; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/10/25 + */ +@Data +public class SysRelateSuppliersParam { + + /** + * 用户ID。当user==null,为清楚客户绑定 + */ + String userId; + + /** + * 供应商id列表 + */ + @NotNull + List supplierIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysRelateSuppliersParam2.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysRelateSuppliersParam2.java new file mode 100644 index 0000000..4656b18 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysRelateSuppliersParam2.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.sys.entity.bo; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/10/25 + */ +@Data +public class SysRelateSuppliersParam2 { + + /** + * 用户ID。当userIds==null,为清除绑定 + */ + List userIds; + + /** + * 供应商id列表 + */ + @NotNull + Long supplierId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserBatchBo.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserBatchBo.java new file mode 100644 index 0000000..1974eda --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserBatchBo.java @@ -0,0 +1,17 @@ +package com.qs.serve.modules.sys.entity.bo; + +import lombok.Data; + +import java.util.List; + + +/** + * @author YenHex + * @since 2022/10/8 + */ +@Data +public class SysUserBatchBo { + + List userList; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserBo.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserBo.java new file mode 100644 index 0000000..eb87122 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserBo.java @@ -0,0 +1,77 @@ +package com.qs.serve.modules.sys.entity.bo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/10/8 + */ +@Data +public class SysUserBo { + + /** id */ + private String id; + + /** 手机号 */ + @Length(max = 64,message = "手机号长度不能超过20字") + private String mobile; + + /** 账号 */ + //@Length(max = 64,message = "账号长度不能超过20字") + //private String account; + + /** 昵称 */ + @Length(max = 64,message = "昵称长度不能超过20字") + private String name; + + /** 编号/工号 */ + @NotNull + @Length(max = 64,message = "编号/工号长度") + private String code; + + /** 头像 */ + //@Length(max = 255,message = "头像长度不能超过255字") + //private String icon; + + /** 部门ID */ + @Length(max = 64,message = "部门ID长度不能超过64字") + private String deptId; + + /** 职位ID */ + //@Length(max = 64,message = "部门ID长度不能超过64字") + //private String positionId; + + /** 身份证号码 */ + @Length(max = 45,message = "身份证号码长度不能超过45字") + private String identityNo; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 角色ID列表 */ + //@TableField(exist = false) + //private List roleIds; + + /** 致远登陆账户 */ + private String syAccount; + + /** 致远用户id */ + private String syUserId; + + /** 登陆客户端标识:android,ios */ + //private String appClient; + + /** app推送token */ + //private String appToken; + + private String hrSystemInfo; +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserLeaveBo.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserLeaveBo.java new file mode 100644 index 0000000..1aec384 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserLeaveBo.java @@ -0,0 +1,51 @@ +package com.qs.serve.modules.sys.entity.bo; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 用户离职 Bo + * @author YenHex + * @since 2023-02-13 + */ +@Data +public class SysUserLeaveBo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + private Long id; + + /** 离职员工id */ + private String userId; + + /** 离职原因 */ + private String leaveReason; + + /** 离职生效日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate leaveEffectDate; + + /** 工作交接人id */ + private String flowUserId; + + /** 客户交接人id */ + private String cusUserId; + + /** 角色交接人id */ + private String roleUserId; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserParentParam.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserParentParam.java new file mode 100644 index 0000000..930e957 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserParentParam.java @@ -0,0 +1,28 @@ +package com.qs.serve.modules.sys.entity.bo; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/10/26 + */ +@Data +public class SysUserParentParam { + + /** + * 用户id列表 + */ + @NotNull + private List userIds; + + /** + * 父级id + */ + @NotBlank + private String parentId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserSalesParam.java b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserSalesParam.java new file mode 100644 index 0000000..789288e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/bo/SysUserSalesParam.java @@ -0,0 +1,27 @@ +package com.qs.serve.modules.sys.entity.bo; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/10/26 + */ +@Data +public class SysUserSalesParam { + + /** + * 用户id列表 + */ + @NotNull + List userIds; + + /** + * 是否销售人员 1是 0否 + */ + @NotNull + private Integer salesFlag; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/CostDeletion.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/CostDeletion.java new file mode 100644 index 0000000..a2ff13c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/CostDeletion.java @@ -0,0 +1,25 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +@Data +public class CostDeletion { + + /** + * 员工号 + */ + private String empNo; + + private String cacc; + + /** + * 操作时间 + */ + private String requestDeleteTime; + + /** + * 核销案号 + */ + private String verificationCode; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SyUser.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SyUser.java new file mode 100644 index 0000000..ea99af7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SyUser.java @@ -0,0 +1,15 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2023/6/20 + */ +@Data +public class SyUser { + String id; + String name; + String code; + String mobile; +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java new file mode 100644 index 0000000..1f2ebb2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2022/4/14 + */ +@Data +public class SysDeptTranParam { + + /** + * 迁移的父级ID,根节点传0 + */ + private String parentId; + + /** + * 选中的部门ID + */ + private String selectId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java new file mode 100644 index 0000000..e523795 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java @@ -0,0 +1,64 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author YenHex + * @since 2022/3/3 + */ +@Data +public class SysDeptTreeNode extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 部门编号 */ + @NotNull(message = "部门编号不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String parentId; + + /** 负责人id */ + private String mgrUserId; + + private Integer isRepair; + + /** 类型【0集团部门 01校区部门 】 */ + @NotNull(message = "类型不能为空") + private Integer type; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + private String updateBy; + + /** 负责人 */ + private String mgrUserName; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java new file mode 100644 index 0000000..74cfe0b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysLoginByPhoneParam { + + @NotNull + private String phone; + + @NotNull + private String code; + + /** + * 友盟token + */ + private String ymToken; + + /** + * 登陆类型:ios、pc、android + */ + @NotNull + private String loginType; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java new file mode 100644 index 0000000..07ec0a8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysLoginParam { + + @NotNull + private String account; + + @NotNull + private String password; + + /** + * 友盟token + */ + private String ymToken; + + /** + * 登陆类型:ios、pc、android + */ + @NotNull + private String loginType; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java new file mode 100644 index 0000000..3c84fd6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author JcYen + * @date 2022/3/12 + */ +@Data +public class SysMenuPermitParam { + + String menuId; + + List permitIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java new file mode 100644 index 0000000..dab3c6e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/16 + */ +@Data +public class SysMenuTreeNode extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 排序 */ + private Integer sort; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型【0->菜单;1->按钮】不能为空") + private Integer type; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java new file mode 100644 index 0000000..ec68bfc --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java @@ -0,0 +1,39 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/11 + */ +@Data +public class SysPermitTreeNode extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 编码 */ + @NotNull(message = "编码不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型【0->菜单;1->按钮】不能为空") + private Integer type; + + private String url; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java new file mode 100644 index 0000000..847d8bb --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2022/4/7 + */ +@Data +public class SysResetPwdByPhoneParam { + + private String phone; + + private String code; + + private String newPwd; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java new file mode 100644 index 0000000..c1681d0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java @@ -0,0 +1,25 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author JcYen + * @date 2022/3/12 + */ +@Data +public class SysRoleMenuParam { + + @NotNull + String roleId; + + List menuIds; + + /** + * 客户端类型 0-PC 1-APP + */ + @NotNull + Integer clientType; +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java new file mode 100644 index 0000000..fb17480 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author JcYen + * @date 2022/3/12 + */ +@Data +public class SysRoleUserParam { + + String roleId; + + List userIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUpdateSeeYonPassword.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUpdateSeeYonPassword.java new file mode 100644 index 0000000..b8856c7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUpdateSeeYonPassword.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @author YenHex + * @since 2023/8/31 + */ +@Data +@AllArgsConstructor +public class SysUpdateSeeYonPassword { + + String memberId; + + String password; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java new file mode 100644 index 0000000..9c5628d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/4/1 + */ +@Data +public class SysUserLeaveParam { + + @NotNull + private String userId; + + /** + * 是否离职 + */ + @NotNull + private Integer leaveState; + + //@NotNull + private String apprId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java new file mode 100644 index 0000000..d852956 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/17 + */ +@Data +public class SysUserPwdParam { + + @NotNull + private String oldPassword; + + @NotNull + private String newPassword; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java new file mode 100644 index 0000000..af54975 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/4/1 + */ +@Data +public class SysUserRewardPunishParam { + + @NotNull + private String userId; + + @NotNull + private String apprId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSalesTreeVo.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSalesTreeVo.java new file mode 100644 index 0000000..94dca4a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSalesTreeVo.java @@ -0,0 +1,86 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @author YenHex + * @since 2022/10/12 + */ +@Data +public class SysUserSalesTreeVo extends TreeNode { + + @TableField(exist = false) + private String id; + + /** 手机号 */ + @TableField(exist = false) + private String mobile; + + /** 账号 */ + @TableField(exist = false) + private String account; + + /** 昵称 */ + @TableField(exist = false) + private String name; + + /** 编号/工号 */ + @TableField(exist = false) + private String code; + + /** 头像 */ + @TableField(exist = false) + private String icon; + + /** 部门ID */ + @TableField(exist = false) + private String deptId; + + /** 职位ID */ + @TableField(exist = false) + private String positionId; + + /** 系统登录权限【0->停用;1->启用】 */ + @TableField(exist = false) + private Integer loginEnable; + + /** 在职状态【0->离职;1->在职;2->准备离职】 */ + @TableField(exist = false) + private Integer servingState; + + /** 入职/复职日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate servingDate; + + /** 离职或上一次离职的日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate servingLeaveDate; + + /** 是否销售人员 */ + @TableField(exist = false) + private Integer salesFlag; + + /** 身份证号码 */ + @TableField(exist = false) + private String identityNo; + + /** 备注 */ + @TableField(exist = false) + private String remark; + + @TableField(exist = false) + private String deptName; +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java new file mode 100644 index 0000000..e225910 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java @@ -0,0 +1,40 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysUserSimpleVo { + + /** id */ + private String id; + + /** 手机号 */ + private String mobile; + + /** 编号 */ + private String code; + + private String deptId; + + /** 昵称 */ + private String name; + + /** 头像 */ + private String icon; + + /** 性别【0->女;1->男】 */ + private Integer gender; + + /** 完成状态 */ + private Integer finished; + + /** 客户主要负责人标识 */ + private Integer supplierMainFlag; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java new file mode 100644 index 0000000..f9ee9de --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/5/31 + */ +@Data +public class SysUserTenantEditParam { + + @NotNull + private String userId; + + @NotNull + private String[] tenantIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java new file mode 100644 index 0000000..e31f54d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/4/1 + */ +@Data +public class SysUserTranPostParam { + + @NotNull + private String userId; + + @NotNull + private String postId; + + //@NotNull + private String apprId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java new file mode 100644 index 0000000..c6b1e72 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java @@ -0,0 +1,53 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysUserVo { + + /** id */ + private String id; + + /** 手机号 */ + private String mobile; + + /** 账号 */ + private String account; + + /** 编号 */ + private String code; + + /** 昵称 */ + private String name; + + /** 头像 */ + private String icon; + + /** 性别【0->女;1->男】 */ + private Integer gender; + + /** 在职状态【0->离职;1->在职 ;2->将离职】 */ + private Integer servingState; + + /** 权限编码 */ + private List authorList; + + /** 权限ID */ + private List authorIds; + + private Object deptInfo; + + private Object postInfo; + + private String hrSystemInfo; + + /** 客户主要负责人标识 */ + private Integer supplierMainFlag; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java new file mode 100644 index 0000000..2926a0f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/4/12 + */ +@Data +public class UserRole4EditParam { + + private List roleIds; + + @NotNull + private String userId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/so/SysPostUserSo.java b/src/main/java/com/qs/serve/modules/sys/entity/so/SysPostUserSo.java new file mode 100644 index 0000000..9ddac6e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/so/SysPostUserSo.java @@ -0,0 +1,86 @@ +package com.qs.serve.modules.sys.entity.so; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 系统职务 查询参数 + * @author YenHex + * @since 2023-04-27 + */ +@Data +public class SysPostUserSo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + private Long id; + + /** 用户id */ + private String userId; + + /** 用户编码 */ + private String userCode; + + /** 用户名称 */ + private String userName; + + /** 岗位id */ + private String postId; + + /** 岗位名称 */ + private String postName; + + /** 岗位编码 */ + private String postCode; + + /** 岗位pid */ + private String pid; + + /** id路径 */ + private String pathIds; + + /** 名称路径 */ + private String pathNames; + + /** 备注 */ + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** 创建人 */ + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + + /** 更新人 */ + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/vo/SysPostTreeVo.java b/src/main/java/com/qs/serve/modules/sys/entity/vo/SysPostTreeVo.java new file mode 100644 index 0000000..9712ff9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/vo/SysPostTreeVo.java @@ -0,0 +1,51 @@ +package com.qs.serve.modules.sys.entity.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.SqlCondition; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +/** + * @author YenHex + * @since 2023/4/27 + */ +@Data +public class SysPostTreeVo extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @Length(max = 20,message = "名称长度不能超过20字") + @TableField(condition = SqlCondition.LIKE) + private String postName; + + /** 编码 */ + @Length(max = 30,message = "编码长度不能超过30字") + @TableField(condition = SqlCondition.LIKE) + private String postCode; + + private String pid; + + /** id路径 */ + @Length(max = 4255,message = "id路径长度不能超过4255字") + private String pathIds; + + /** 名称路径 */ + @Length(max = 4255,message = "名称路径长度不能超过4255字") + @TableField(condition = SqlCondition.LIKE) + private String pathNames; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + + private List postUserList; +} diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java new file mode 100644 index 0000000..02346e4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysAttach; + +/** + * 系统附件 Mapper + * @author YenHex + * @date 2022-03-24 + */ +public interface SysAttachMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysBusinessLogMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysBusinessLogMapper.java new file mode 100644 index 0000000..993cf6b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysBusinessLogMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysBusinessLog; + +/** + * Mapper + * @author YenHex + * @date 2023-04-25 + */ +public interface SysBusinessLogMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysConfigMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysConfigMapper.java new file mode 100644 index 0000000..4023303 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysConfigMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysConfig; + +/** + * Mapper + * @author YenHex + * @date 2022-11-12 + */ +public interface SysConfigMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysDeleteLogMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysDeleteLogMapper.java new file mode 100644 index 0000000..92f26e8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysDeleteLogMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysDeleteLog; + +/** + * 删除日志 Mapper + * @author YenHex + * @date 2023-12-08 + */ +public interface SysDeleteLogMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java new file mode 100644 index 0000000..5c00a27 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysDept; + +import java.util.List; + +/** + * 部门信息 Mapper + * @author YenHex + * @date 2022-02-28 + */ +public interface SysDeptMapper extends BaseMapper { + + /** + * 查询列表 + * @param sysDept + * @return + */ + List listDept(SysDept sysDept); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysDictDataMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysDictDataMapper.java new file mode 100644 index 0000000..8abaa8c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysDictDataMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysDictData; + +/** + * 字典数据 Mapper + * @author YenHex + * @date 2022-11-04 + */ +public interface SysDictDataMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java new file mode 100644 index 0000000..29c0c9f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysDict; + +/** + * 字典 Mapper + * @author YenHex + * @date 2022-05-20 + */ +public interface SysDictMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java new file mode 100644 index 0000000..6e32c8d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysMenu; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 系统菜单 Mapper + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuMapper extends BaseMapper { + + /** + * 查询用户所有菜单ID + * @param userId + * @return + */ + @Select("select distinct srm.menu_id from sys_user_role sur " + + " LEFT JOIN sys_role_menu srm ON sur.role_id = srm.role_id WHERE sur.user_id = #{userId}" + + " and srm.menu_id is not null and sur.del_flag = b'0' and srm.del_flag = '0'") + List searchUserMenuIds(@Param("userId") String userId); + + /** + * 加载角色菜单id + * @param roleIds + * @return + */ + List searchDefaultMenuIds(@Param("roleIds") List roleIds); + + /** + * 查询所有菜单ID + * @return + */ + @Select("select id from sys_menu where del_flag = '0'") + List searchMenuIds(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java new file mode 100644 index 0000000..0ba0353 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysMenuPermit; + +/** + * 菜单权限 Mapper + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuPermitMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java new file mode 100644 index 0000000..0c88201 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java @@ -0,0 +1,13 @@ +package com.qs.serve.modules.sys.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysNotice; + +/** + * 注意信息 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java new file mode 100644 index 0000000..4358758 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysNoticeType; + +/** + * 注意信息分类 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeTypeMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java new file mode 100644 index 0000000..80111eb --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 注意信息&用户关系 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeUserMapper extends BaseMapper { + + IPage list2(Page page, @Param("query") SysNoticeUser grouponUser); + + /** + * 统计未读公告 + * @param userId + * @param tenant + * @return + */ + @Select("SELECT " + + " notice.id " + + "FROM " + + " sys_notice_user notice_user " + + " LEFT JOIN sys_notice notice ON notice_user.notice_id = notice.id " + + "WHERE " + + " notice.del_flag = b'0' " + + " AND notice.tenant_id = #{tenant} " + + " AND notice_user.read_flag = '0' " + + " AND notice_user.user_id = #{userId} GROUP BY notice.id ") + @InterceptorIgnore(tenantLine = "1") + List countMyRead(@Param("userId") String userId, @Param("tenant") String tenant); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java new file mode 100644 index 0000000..586e136 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysOperationLog; + +/** + * 操作日志 Mapper + * @author YenHex + * @date 2022-03-08 + */ +public interface SysOperationLogMapper extends BaseMapper { + + /** + * 保存日志 + * @param log + * @return + */ + @InterceptorIgnore(tenantLine = "true") + boolean saveLog(SysOperationLog log); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationManualMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationManualMapper.java new file mode 100644 index 0000000..b1968d4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationManualMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysOperationManual; + +/** + * Mapper + * @author YenHex + * @date 2023-08-11 + */ +public interface SysOperationManualMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java new file mode 100644 index 0000000..d813a8d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPermit; + +/** + * 系统权限 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysPermitMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java new file mode 100644 index 0000000..a927f1f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPost; +import org.apache.ibatis.annotations.Update; + +/** + * 系统职务 Mapper + * @author YenHex + * @date 2022-04-01 + */ +public interface SysPostMapper extends BaseMapper { + + /** + * 修改post表 更关联表post_user + * @return + */ + @Update("update sys_post_user " + + " left join sys_post " + + " on sys_post_user.post_id = sys_post.id" + + " set " + + " sys_post_user.post_code = sys_post.post_code, " + + " sys_post_user.post_name = sys_post.post_name " + + " where sys_post_user.del_flag = 0 and sys_post.del_flag = 0 ") + int updatePostUserInfo(); + + /** + * 根据岗位更新员工的路径绑定ID + * @return + */ + @Update("update sys_post_user " + + "left join sys_post on sys_post_user.post_id = sys_post.id " + + "set sys_post_user.path_ids = sys_post.path_ids, " + + "sys_post_user.path_names = sys_post.path_names ") + int updatePostUserIdPaths(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysPostUserMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysPostUserMapper.java new file mode 100644 index 0000000..6b4536f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysPostUserMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPostUser; + +/** + * 系统职务 Mapper + * @author YenHex + * @date 2023-04-27 + */ +public interface SysPostUserMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java new file mode 100644 index 0000000..b65a9be --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java @@ -0,0 +1,13 @@ +package com.qs.serve.modules.sys.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysRole; + +/** + * 系统角色 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysRoleMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java new file mode 100644 index 0000000..dbbb50d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPermit; +import com.qs.serve.modules.sys.entity.SysRoleMenu; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 菜单用户 Mapper + * @author YenHex + * @date 2022-03-16 + */ +public interface SysRoleMenuMapper extends BaseMapper { + + /** + * 查询权限编码 + * @param roleIds + * @return + */ + @Select("") + @InterceptorIgnore(tenantLine = "1") + List listPermitCode(List roleIds); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysSyncLogMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysSyncLogMapper.java new file mode 100644 index 0000000..cb44249 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysSyncLogMapper.java @@ -0,0 +1,21 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysSyncLog; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 同步日志 Mapper + * @author YenHex + * @date 2023-03-15 + */ +public interface SysSyncLogMapper extends BaseMapper { + + @Select("SELECT * FROM `jsl_cost_base`.`sys_sync_log` WHERE `form_plat` = '一站式费用' and request_json ->> '$.costCode' = #{costCode} limit 1 ") + SysSyncLog selectThirtyLogByCostCode(@Param("costCode") String costCode); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java new file mode 100644 index 0000000..3a55a39 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysTenant; + +/** + * 系统租户 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysTenantMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserCodeMathMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserCodeMathMapper.java new file mode 100644 index 0000000..8600d88 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserCodeMathMapper.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUserCodeMath; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * 用户编码对照表 Mapper + * @author YenHex + * @date 2023-09-08 + */ +public interface SysUserCodeMathMapper extends BaseMapper { + + + @InterceptorIgnore(tenantLine = "true") + @Select("select `curr_code` from sys_user_code_math where sour_code = #{oldCode} limit 1 ") + String getNewCode(@Param("oldCode") String oldCode); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserLeaveMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserLeaveMapper.java new file mode 100644 index 0000000..1ee83da --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserLeaveMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUserLeave; + +/** + * 用户离职 Mapper + * @author YenHex + * @date 2023-02-13 + */ +public interface SysUserLeaveMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java new file mode 100644 index 0000000..d90405c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUser; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import java.util.List; + +/** + * 系统用户 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserMapper extends BaseMapper { + + /** + * 检测是否有编号 + * @param code + * @return + */ + @InterceptorIgnore(tenantLine = "1") + @Select("SELECT count(1) FROM `sys_user` sys_user where sys_user.code = #{code}") + long checkCode(@Param("code") String code); + + /** + * 更新友盟token + * @param uid + * @param token + * @param appClient + */ + @InterceptorIgnore(tenantLine = "1") + @Update("update `sys_user` sys_user set app_token = #{token}, app_client=#{appClient} where id = #{uid}") + void updateYmTokenInt(@Param("uid")String uid,@Param("token")String token,@Param("appClient")String appClient); + + /** + * 移除友盟遗留的token,登录时调用 + * @param token + */ + @InterceptorIgnore(tenantLine = "1") + @Update("update `sys_user` sys_user set sys_user.app_token = '#' where sys_user.app_token = #{token}") + void clearYmToken(@Param("token")String token); + + /** + * 查询用户 + * @param sysUser + * @return + */ + @InterceptorIgnore(tenantLine = "1") + List listUser(@Param("query") SysUser sysUser); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..076e8ba --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java @@ -0,0 +1,15 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUserRole; + + +/** + * 用户角色 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserRoleMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserSalesMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserSalesMapper.java new file mode 100644 index 0000000..17f0e57 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserSalesMapper.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUserSales; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +/** + * Mapper + * @author YenHex + * @date 2022-10-12 + */ +public interface SysUserSalesMapper extends BaseMapper { + + @InterceptorIgnore(tenantLine = "1") + List selectSysUserSalesList(@Param("query") SysUserSales userSales); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java b/src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java new file mode 100644 index 0000000..f3db1c1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java @@ -0,0 +1,33 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysAttach; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * 系统附件 服务接口 + * @author YenHex + * @date 2022-03-24 + */ +public interface SysAttachService extends IService { + + @Override + default List listByIds(Collection idList) { + List attaches = IService.super.listByIds(idList); + return attaches; + } + + default List listByIdArrs(String[] ids) { + if(ids==null||ids.length==0){ + return null; + } + List attaches = IService.super.listByIds(Arrays.asList(ids)); + return attaches; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysBusinessLogService.java b/src/main/java/com/qs/serve/modules/sys/service/SysBusinessLogService.java new file mode 100644 index 0000000..61866ce --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysBusinessLogService.java @@ -0,0 +1,25 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.common.enums.BusinessLogOption; +import com.qs.serve.modules.sys.common.enums.BusinessLogType; +import com.qs.serve.modules.sys.entity.SysBusinessLog; + +/** + * 服务接口 + * @author YenHex + * @date 2023-04-25 + */ +public interface SysBusinessLogService extends IService { + + + void buildLog4Save(BusinessLogType logType, String targetId,String targetCode,String targetName, String targetRelateId,Object newVal); + + void buildLog4Delete(BusinessLogType logType, String targetId,String targetCode,String targetName,String targetRelateId); + + void buildLog4Change(BusinessLogType logType, String targetId,String targetCode,String targetName,String targetRelateId, Object orgVal, Object newVal); + + void baseBuildLog(BusinessLogType logType, String targetId,String targetCode,String targetName,String targetRelateId, Object orgVal, Object newVal,BusinessLogOption option); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysConfigService.java b/src/main/java/com/qs/serve/modules/sys/service/SysConfigService.java new file mode 100644 index 0000000..1fa4a77 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysConfigService.java @@ -0,0 +1,16 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysConfig; + +/** + * 服务接口 + * @author YenHex + * @date 2022-11-12 + */ +public interface SysConfigService extends IService { + + SysConfig getByKey(String key); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysDeleteLogService.java b/src/main/java/com/qs/serve/modules/sys/service/SysDeleteLogService.java new file mode 100644 index 0000000..d365f19 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysDeleteLogService.java @@ -0,0 +1,21 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysDeleteLog; + +/** + * 删除日志 服务接口 + * @author YenHex + * @date 2023-12-08 + */ +public interface SysDeleteLogService extends IService { + + /** + * 删除费用申请相关所有数据 + * @param costApplyId + * @param remark + */ + void deleteCostApply(Long costApplyId,String remark); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java b/src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java new file mode 100644 index 0000000..cf59c86 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysDept; + +import java.util.List; + +/** + * 部门信息 服务接口 + * @author YenHex + * @date 2022-02-28 + */ +public interface SysDeptService extends IService { + + /** + * 保存 + * @param dept + * @return + */ + boolean save2(SysDept dept); + + /** + * 列表查询 + * @param sysDept + * @return + */ + List listDept(SysDept sysDept); + + /** + * id查询部门 + * @param ids + * @param loadChild + * @return + */ + List listDeptByIds(List ids,boolean loadChild); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysDictDataService.java b/src/main/java/com/qs/serve/modules/sys/service/SysDictDataService.java new file mode 100644 index 0000000..68f11cc --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysDictDataService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysDictData; + +/** + * 字典数据 服务接口 + * @author YenHex + * @date 2022-11-04 + */ +public interface SysDictDataService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysDictService.java b/src/main/java/com/qs/serve/modules/sys/service/SysDictService.java new file mode 100644 index 0000000..3763f1d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysDictService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysDict; + +/** + * 字典 服务接口 + * @author YenHex + * @date 2022-05-20 + */ +public interface SysDictService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java b/src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java new file mode 100644 index 0000000..344cde3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysMenuPermit; + +import java.util.List; + +/** + * 菜单权限 服务接口 + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuPermitService extends IService { + + void removeByMenuId(String menuId); + + List listByMenuId(String menuId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java b/src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java new file mode 100644 index 0000000..0af8250 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysMenu; + +/** + * 系统菜单 服务接口 + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java new file mode 100644 index 0000000..2d58fae --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysNotice; + +/** + * 注意信息 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeService extends IService { + + /** + * 发布 + * @param id + */ + void publish(String id); + + /** + * 删除用户关联 + * @param id + */ + void removeUserRelate(String id); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java new file mode 100644 index 0000000..3c5acaf --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysNoticeType; + +/** + * 注意信息分类 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeTypeService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java new file mode 100644 index 0000000..283baef --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysNoticeUser; + +/** + * 注意信息&用户关系 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeUserService extends IService { + + IPage list2(Page page,SysNoticeUser grouponUser); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java b/src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java new file mode 100644 index 0000000..9eb7023 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java @@ -0,0 +1,16 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysOperationLog; + +/** + * 操作日志 服务接口 + * @author YenHex + * @date 2022-03-08 + */ +public interface SysOperationLogService extends IService { + + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysOperationManualService.java b/src/main/java/com/qs/serve/modules/sys/service/SysOperationManualService.java new file mode 100644 index 0000000..af8d2b0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysOperationManualService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysOperationManual; + +/** + * 服务接口 + * @author YenHex + * @date 2023-08-11 + */ +public interface SysOperationManualService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java b/src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java new file mode 100644 index 0000000..772c4a0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysPermit; + +import java.util.List; + +/** + * 系统权限 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysPermitService extends IService { + + /** + * 权限列表 + * @return + */ + List listByCache(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysPostService.java b/src/main/java/com/qs/serve/modules/sys/service/SysPostService.java new file mode 100644 index 0000000..0e373f7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysPostService.java @@ -0,0 +1,21 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysPost; + +/** + * 系统职务 服务接口 + * @author YenHex + * @date 2022-04-01 + */ +public interface SysPostService extends IService { + + void modify(SysPost param); + + /** + * 刷新路径IDs + */ + void flushPathIds(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysPostUserService.java b/src/main/java/com/qs/serve/modules/sys/service/SysPostUserService.java new file mode 100644 index 0000000..3bd0b00 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysPostUserService.java @@ -0,0 +1,25 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysPostUser; +import com.qs.serve.modules.sys.entity.bo.SysPostUserBo; +import java.util.List; +/** + * 系统职务 服务接口 + * @author YenHex + * @date 2023-04-27 + */ +public interface SysPostUserService extends IService { + + List listByChildIds(String userId); + + List listByUserId(String userId); + + List listByUserIds(List userIds); + + void updatePathIds(String orgPathIds,String newPathIds,String orgPathNames,String newPathNames); + + void bind(SysPostUserBo param); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java b/src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java new file mode 100644 index 0000000..aeb3ee4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.entity.SysRoleMenu; + +import java.util.List; + +/** + * 菜单用户 服务接口 + * @author YenHex + * @date 2022-03-16 + */ +public interface SysRoleMenuService extends IService { + + boolean removeByRoleId(String roleId,Integer clientType); + + List listByRoleId(String roleId); +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java b/src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java new file mode 100644 index 0000000..47483c7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysRole; + +import java.util.List; + +/** + * 系统角色 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysRoleService extends IService { + + /** + * 加载可用角色 + * @param ids + * @return + */ + List getEnableByIds(List ids); + + /** + * 默认的角色 + * @return + */ + List getDefaultRole(); + + void saveUserRole4Edit(List roleIds,String userId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysSyncLogService.java b/src/main/java/com/qs/serve/modules/sys/service/SysSyncLogService.java new file mode 100644 index 0000000..b1997b0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysSyncLogService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysSyncLog; + +/** + * 同步日志 服务接口 + * @author YenHex + * @date 2023-03-15 + */ +public interface SysSyncLogService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java b/src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java new file mode 100644 index 0000000..19ef731 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysTenant; + +import java.util.List; + +/** + * 系统租户 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysTenantService extends IService { + + List list2(); + + SysTenant getCurrent(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserLeaveService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserLeaveService.java new file mode 100644 index 0000000..cec9e02 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserLeaveService.java @@ -0,0 +1,17 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.SysUserLeave; + +/** + * 用户离职 服务接口 + * @author YenHex + * @date 2023-02-13 + */ +public interface SysUserLeaveService extends IService { + + SysUserLeave getOneByUserId(String userId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java new file mode 100644 index 0000000..c8cbdf9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java @@ -0,0 +1,32 @@ +package com.qs.serve.modules.sys.service; + +import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam; +import com.qs.serve.modules.sys.entity.dto.SysLoginParam; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public interface SysUserLoginService { + + + /** + * 登录 + * @param loginParam + * @return + */ + Map login(SysLoginParam loginParam); + + Map login(String loginCode); + + String loginBySyUserId(String syUserId); + + /** + * 手机登陆 + * @param loginParam + * @return + */ + Map login(SysLoginByPhoneParam loginParam); +} diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java new file mode 100644 index 0000000..8b65df3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java @@ -0,0 +1,30 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysUserRole; + +import java.util.List; + +/** + * 用户角色 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserRoleService extends IService { + /** + * 用户查询列表 + * @param uid + * @return + */ + List listByUid(String uid); + + List notDataUserIds(String roleId,List userIds); + + boolean removeByRoleId(String roleId); + + boolean remove(String roleId,List userIds); + + boolean replaceAndRemove(String leafUserId,String enterUserId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserSalesService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserSalesService.java new file mode 100644 index 0000000..58f2675 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserSalesService.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysUserSales; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 服务接口 + * @author YenHex + * @date 2022-10-12 + */ +public interface SysUserSalesService extends IService { + + /** + * 加载所有销售人员 + * @param userSales + * @return + */ + List selectSysUserSalesList(SysUserSales userSales); + + /** + * 通过路径查询 + * @param pathId + * @return + */ + List listByPathId(String pathId); + + /** + * 加载销售人员下所有下级 + * @param userId + * @return + */ + List listByChildIds(String userId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserService.java new file mode 100644 index 0000000..f928570 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserService.java @@ -0,0 +1,85 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.modules.sys.entity.SysPostUser; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.bo.SysUserLeaveBo; + +import java.time.LocalDate; +import java.util.List; + +/** + * 系统用户 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserService extends IService { + + void updateSeeYonPassword(String syUserId,String password); + + /** + * 账号查询 + * @param acc + * @return + */ + SysUser getByAccount(String acc); + + SysUser getByIdentityNo(String acc); + + SysUser getBySyId(String acc); + + LoginUser getLoginUserByAccount(String account); + + LoginUser getLoginUserById(String id); + + /** + * 用户列表 + * @param sysUser + * @return + */ + List listUser(SysUser sysUser); + + void relateInfo(SysUser sysUser,boolean loadLeave); + + LoginUser buildLoginUser(SysUser sysUser); + + List listByOaMemberIds(List memberIds); + List listByCodes(List codes); + + SysUser listByOaMemberId(String memberId); + + /** + * 用户离职 + * @param userLeaveParam + */ + void leave(SysUserLeaveBo userLeaveParam); + + /** + * 立刻离职执行函数 + * @param userIds + * @param updateLeaveStatus + */ + void leaveNow(List userIds,Boolean updateLeaveStatus); + + /** + * 取消离职 + * @param userId + */ + void cancelLeave(String userId); + + /** + * 重新入职 + * @param userId + */ + void reEntry(String userId); + + /** + * 通过岗位上下级加载下级用户 + * @param userId + * @return + */ + List listByChildIds(String userId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java new file mode 100644 index 0000000..740a8b7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.mapper.SysAttachMapper; +import com.qs.serve.modules.sys.service.SysAttachService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 系统附件 服务实现类 + * @author YenHex + * @since 2022-03-24 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysAttachServiceImpl extends ServiceImpl implements SysAttachService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysBusinessLogServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysBusinessLogServiceImpl.java new file mode 100644 index 0000000..712f5c1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysBusinessLogServiceImpl.java @@ -0,0 +1,82 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.model.dto.DiffFieldVal; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.BusinessDifferenceUtil; +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.modules.sys.common.enums.BusinessLogOption; +import com.qs.serve.modules.sys.common.enums.BusinessLogType; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysBusinessLog; +import com.qs.serve.modules.sys.service.SysBusinessLogService; +import com.qs.serve.modules.sys.mapper.SysBusinessLogMapper; + +import java.util.List; + +/** + * 服务实现类 + * @author YenHex + * @since 2023-04-25 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysBusinessLogServiceImpl extends ServiceImpl implements SysBusinessLogService { + + SysUserMapper sysUserMapper; + + @Override + public void buildLog4Save(BusinessLogType logType, String targetId,String targetCode,String targetName,String targetRelateId, Object newVal) { + BusinessLogOption option = BusinessLogOption.SAVE; + this.baseBuildLog(logType,targetId,targetCode,targetName,targetRelateId,null,newVal,option); + } + + @Override + public void buildLog4Delete(BusinessLogType logType, String targetId,String targetCode,String targetName,String targetRelateId) { + BusinessLogOption option = BusinessLogOption.DELETE; + this.baseBuildLog(logType,targetId,targetCode,targetName,targetRelateId,null,null,option); + } + + @Override + public void buildLog4Change(BusinessLogType logType, String targetId,String targetCode,String targetName,String targetRelateId, Object orgVal, Object newVal) { + BusinessLogOption option = BusinessLogOption.UPDATE; + this.baseBuildLog(logType,targetId,targetCode,targetName,targetRelateId,orgVal,newVal,option); + } + + @Override + public void baseBuildLog(BusinessLogType logType, String targetId,String targetCode,String targetName, String targetRelateId,Object orgVal, Object newVal, BusinessLogOption option) { + try { + List diffFieldValList = BusinessDifferenceUtil.getDifferenceList(orgVal,newVal); + if(option.equals(BusinessLogOption.UPDATE)&&diffFieldValList.size()<1){ + return; + } + SysBusinessLog businessLog = new SysBusinessLog(); + SysUser sysUser = sysUserMapper.selectById(AuthContextUtils.getSysUserId()); + businessLog.setUserId(sysUser.getId()); + businessLog.setUserCode(sysUser.getCode()); + businessLog.setUserName(sysUser.getName()); + businessLog.setTargetType(logType.getLabel()); + businessLog.setTargetId(targetId); + businessLog.setOptType(option.getLabel()); + if(orgVal!=null){ + businessLog.setOrgJson(JsonUtil.objectToJson(orgVal)); + } + if(newVal!=null){ + businessLog.setNewJson(JsonUtil.objectToJson(newVal)); + } + businessLog.setDiffJson(JsonUtil.objectToJson(diffFieldValList)); + businessLog.setTargetCode(targetCode); + businessLog.setTargetName(targetName); + businessLog.setTargetRelateId(targetRelateId); + this.save(businessLog); + } catch (Exception e) { + e.printStackTrace(); + } + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysConfigServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..99dc88c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,30 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysConfig; +import com.qs.serve.modules.sys.service.SysConfigService; +import com.qs.serve.modules.sys.mapper.SysConfigMapper; + +/** + * 服务实现类 + * @author YenHex + * @since 2022-11-12 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysConfigServiceImpl extends ServiceImpl implements SysConfigService { + + @Override + public SysConfig getByKey(String key) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysConfig::getConfigKey,key); + SysConfig sysConfig = this.getOne(lqw); + return sysConfig; + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..e25223f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysDept; +import com.qs.serve.modules.sys.mapper.SysDeptMapper; +import com.qs.serve.modules.sys.service.SysDeptService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 部门信息 服务实现类 + * @author YenHex + * @since 2022-02-28 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysDeptServiceImpl extends ServiceImpl implements SysDeptService { + + @Override + public boolean save2(SysDept dept) { + dept.setId(IdUtil.getSnowFlakeId()+""); + if(dept.getParentId().equals(TreeUtil.DEFAULT_PID_STRING)){ + dept.setLevelPath(dept.getId()); + }else{ + SysDept parentDept = getById(dept.getParentId()); + dept.setLevelPath(parentDept.getLevelPath()+"_"+dept.getId()); + } + save(dept); + return true; + } + + @Override + public List listDept(SysDept sysDept) { + return baseMapper.listDept(sysDept); + } + + @Override + public List listDeptByIds(List ids, boolean loadChild) { + if(CollectionUtil.isEmpty(ids)){return null;} + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(SysDept::getId,ids); + List list = list(wrapper); + if(loadChild){ + final List levels = list.stream().map(SysDept::getLevelPath).collect(Collectors.toList()); + LambdaQueryWrapper deptQueryWrapper = new LambdaQueryWrapper<>(); + deptQueryWrapper.and(wq->{ + for (int i = 0; i < levels.size(); i++) { + if(i != 0 ){ + wq.or(); + } + wq.likeRight(SysDept::getLevelPath,levels.get(i)); + } + }); + return list(deptQueryWrapper); + } + return list; + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictDataServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..948c06a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysDictData; +import com.qs.serve.modules.sys.service.SysDictDataService; +import com.qs.serve.modules.sys.mapper.SysDictDataMapper; + +/** + * 字典数据 服务实现类 + * @author YenHex + * @since 2022-11-04 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysDictDataServiceImpl extends ServiceImpl implements SysDictDataService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java new file mode 100644 index 0000000..b7768f6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysDict; +import com.qs.serve.modules.sys.service.SysDictService; +import com.qs.serve.modules.sys.mapper.SysDictMapper; + +/** + * 字典 服务实现类 + * @author YenHex + * @since 2022-05-20 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysDictServiceImpl extends ServiceImpl implements SysDictService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java new file mode 100644 index 0000000..c8be382 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysMenuPermit; +import com.qs.serve.modules.sys.mapper.SysMenuPermitMapper; +import com.qs.serve.modules.sys.service.SysMenuPermitService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 菜单权限 服务实现类 + * @author YenHex + * @since 2022-03-15 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysMenuPermitServiceImpl extends ServiceImpl implements SysMenuPermitService { + + @Override + public void removeByMenuId(String menuId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysMenuPermit::getMenuId,menuId); + remove(wrapper); + } + + @Override + public List listByMenuId(String menuId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysMenuPermit::getMenuId,menuId); + return list(wrapper); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..2347fe6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.mapper.SysMenuMapper; +import com.qs.serve.modules.sys.service.SysMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 系统菜单 服务实现类 + * @author YenHex + * @since 2022-03-15 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysMenuServiceImpl extends ServiceImpl implements SysMenuService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..3712ede --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,89 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.sys.common.consts.SysStatusConst; +import com.qs.serve.modules.sys.entity.SysNotice; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.mapper.SysNoticeMapper; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysNoticeService; +import com.qs.serve.modules.sys.service.SysNoticeUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 注意信息 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysNoticeServiceImpl extends ServiceImpl implements SysNoticeService { + + private SysUserMapper sysUserMapper; + private SysNoticeUserService sysNoticeUserService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void publish(String id) { + SysNotice notice = getById(id); + //移除旧记录 + removeUserRelate(id); + LambdaQueryWrapper userLambdaQueryWrapper = new LambdaQueryWrapper<>(); + userLambdaQueryWrapper.select(SysUser::getId); + List userIds = null; + if(notice.getVisibleType().equals(SysStatusConst.SysNotice_VisibleType_0)){ + List userList = sysUserMapper.selectList(userLambdaQueryWrapper); + userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList()); + }else if (notice.getVisibleType().equals(SysStatusConst.SysNotice_VisibleType_1)){ + if(notice.getVisibleIds()==null||notice.getVisibleIds().length<1){ + Assert.throwEx("请设置可见人员"); + } + userIds = Arrays.asList(notice.getVisibleIds()); + }else if(notice.getVisibleType().equals(SysStatusConst.SysNotice_VisibleType_2)){ + if(notice.getVisibleIds()==null||notice.getVisibleIds().length<1){ + Assert.throwEx("请设置可见部门"); + } + userLambdaQueryWrapper.in(SysUser::getDeptId,Arrays.asList(notice.getVisibleIds())); + List userList = sysUserMapper.selectList(userLambdaQueryWrapper); + userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList()); + } + if(userIds!=null){ + List noticeUserList = new ArrayList<>(); + for (String userId : userIds) { + SysNoticeUser noticeUser = new SysNoticeUser(); + noticeUser.setUserId(userId); + noticeUser.setNoticeId(id); + noticeUserList.add(noticeUser); + } + List> tmpList = CollectionUtil.createList(noticeUserList,50); + for (List sysNoticeUsers : tmpList) { + sysNoticeUserService.saveBatch(sysNoticeUsers); + } + //TODO gyApiService.sendYmMsg("广雅公告消息",userIds,notice.getId(), GyApiConst.Notice); + notice.setLastPublishTime(LocalDateTime.now()); + updateById(notice); + } + } + + @Override + public void removeUserRelate(String id) { + LambdaQueryWrapper delWarp = new LambdaQueryWrapper<>(); + delWarp.eq(SysNoticeUser::getNoticeId,id); + sysNoticeUserService.remove(delWarp); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java new file mode 100644 index 0000000..d913db6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysNoticeType; +import com.qs.serve.modules.sys.mapper.SysNoticeTypeMapper; +import com.qs.serve.modules.sys.service.SysNoticeTypeService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 注意信息分类 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysNoticeTypeServiceImpl extends ServiceImpl implements SysNoticeTypeService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java new file mode 100644 index 0000000..9cfe1df --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import com.qs.serve.modules.sys.mapper.SysNoticeUserMapper; +import com.qs.serve.modules.sys.service.SysNoticeUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 注意信息&用户关系 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysNoticeUserServiceImpl extends ServiceImpl implements SysNoticeUserService { + + @Override + public IPage list2(Page page, SysNoticeUser grouponUser) { + grouponUser.setTenantId(AuthContextUtils.getTenant()); + return baseMapper.list2(page, grouponUser); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java new file mode 100644 index 0000000..1447f08 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.mapper.SysOperationLogMapper; +import com.qs.serve.modules.sys.service.SysOperationLogService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 操作日志 服务实现类 + * @author YenHex + * @since 2022-03-08 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysOperationLogServiceImpl extends ServiceImpl implements SysOperationLogService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationManualServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationManualServiceImpl.java new file mode 100644 index 0000000..d2cfafc --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationManualServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysOperationManual; +import com.qs.serve.modules.sys.service.SysOperationManualService; +import com.qs.serve.modules.sys.mapper.SysOperationManualMapper; + +/** + * 服务实现类 + * @author YenHex + * @since 2023-08-11 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysOperationManualServiceImpl extends ServiceImpl implements SysOperationManualService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java new file mode 100644 index 0000000..0654bbe --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java @@ -0,0 +1,30 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysPermit; +import com.qs.serve.modules.sys.mapper.SysPermitMapper; +import com.qs.serve.modules.sys.service.SysPermitService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统权限 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysPermitServiceImpl extends ServiceImpl implements SysPermitService { + + @Override + //@Cacheable(cacheNames = RedisCacheKeys.PERMIT_ALL_LIST) + public List listByCache() { + return list(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java new file mode 100644 index 0000000..b556d19 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java @@ -0,0 +1,128 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysPost; +import com.qs.serve.modules.sys.mapper.SysPostMapper; +import com.qs.serve.modules.sys.service.SysPostService; +import com.qs.serve.modules.sys.service.SysPostUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统职务 服务实现类 + * @author YenHex + * @since 2022-04-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysPostServiceImpl extends ServiceImpl implements SysPostService { + + SysPostUserService postUserService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void modify(SysPost param) { + SysPost dbData = this.getById(param.getId()); + SysPost parent = null; + if(param.getPid()!=null&&!param.getPid().equals("0")){ + parent = this.getById(param.getPid()); + if(parent==null){ + Assert.throwEx("父级标签不存在"); + } + if(param.getId()!=null){ + String[] pids = parent.getPathIds().split("_"); + for (String pid : pids) { + if(pid.equals(param.getId())){ + Assert.throwEx("出现循环节点"); + } + } + } + } + if(param.getId()==null){ + this.save(param); + } + if(parent==null){ + param.setPid("0"); + param.setPathIds(param.getId()); + }else { + param.setPathIds(parent.getPathIds()+"_"+param.getId()); + } + if(dbData==null){ + param.setPostCode(StringUtils.genShortId()+IdUtil.genCode(4)); + this.saveOrUpdate(param); + }else { + param.setPostCode(null); + this.updateById(param); + boolean changePid = !dbData.getPid().equals(param.getPid()); + if(changePid){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.and(v1->{ + v1.eq(SysPost::getPathIds,dbData.getPathIds()) + .or().likeRight(SysPost::getPathIds,dbData.getPathIds()+"_"); + }); + List childList = this.list(lqw); + List childList4Upd = childList.stream().map(obj->{ + SysPost par = new SysPost(); + par.setId(obj.getId()); + par.setPathIds(obj.getPathIds().replace(dbData.getPathIds(),param.getPathIds())); + return par; + }).collect(Collectors.toList()); + this.updateBatchById(childList4Upd); + //更新关联表 + postUserService.updatePathIds(dbData.getPathIds(),param.getPathIds(), + dbData.getPathNames(), param.getPathNames()); + + }else { + //不进行更新 + param.setPathIds(null); + param.setPid(null); + } + this.updateById(param); + } + + } + + @Override + public void flushPathIds() { + AuthContextUtils.setTenant("001"); + String pid = "0"; + toFlushPathIds(pid, null,null); + //更新绑定的用户路径 + baseMapper.updatePostUserIdPaths(); + baseMapper.updatePostUserInfo(); + } + + /** + * 递归设置 + * @param pid + * @param pPathId + * @param pPathName + */ + private void toFlushPathIds(String pid, String pPathId,String pPathName) { + List list = list(new LambdaQueryWrapper().eq(SysPost::getPid, pid)); + for (SysPost post : list) { + if("0".equals(pid)){ + post.setPathIds(post.getId()); + post.setPathNames(post.getPostName()); + }else { + post.setPathIds(pPathId +"_"+post.getId()); + post.setPathNames(pPathName+"_"+post.getPostName()); + } + this.updateById(post); + this.toFlushPathIds(post.getId(),post.getPathIds(),post.getPostName()); + } + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostUserServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostUserServiceImpl.java new file mode 100644 index 0000000..35da8d8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostUserServiceImpl.java @@ -0,0 +1,136 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.sys.entity.SysPost; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.bo.SysPostUserBo; +import com.qs.serve.modules.sys.mapper.SysPostMapper; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysPostService; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysPostUser; +import com.qs.serve.modules.sys.service.SysPostUserService; +import com.qs.serve.modules.sys.mapper.SysPostUserMapper; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 系统职务 服务实现类 + * @author YenHex + * @since 2023-04-27 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysPostUserServiceImpl extends ServiceImpl implements SysPostUserService { + + SysPostMapper postMapper; + SysUserMapper userMapper; + + + @Override + public List listByChildIds(String userId) { + List postUserList = this.listByUserId(userId); + Set userIdSet = new HashSet<>(); + for (SysPostUser postUser : postUserList) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.likeRight(SysPostUser::getPathIds,postUser.getPathIds()+"_"); + //lqw.select(SysPostUser::getUserId,SysPostUser::getId); + List sysPostUsers = this.list(lqw); + for (SysPostUser childUser : sysPostUsers) { + userIdSet.add(childUser.getUserId()); + } + } + return new ArrayList<>(userIdSet); + } + + @Override + public List listByUserId(String userId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysPostUser::getUserId,userId); + return this.list(lqw); + } + + @Override + public List listByUserIds(List userIds) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysPostUser::getUserId,userIds); + return this.list(lqw); + } + + @Override + public void updatePathIds(String orgPathIds,String newPathIds,String orgPathNames,String newPathNames){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.likeRight(SysPostUser::getPathIds,orgPathIds+"_"); + lqw.select(SysPostUser::getId,SysPostUser::getPathIds); + List postUserList = this.list(lqw); + if(CollectionUtil.isNotEmpty(postUserList)){ + for (SysPostUser postUser : postUserList) { + postUser.setPathIds(postUser.getPathIds().replace(orgPathIds,newPathIds)); + } + this.updateBatchById(postUserList); + } + } + + @Override + public void bind(SysPostUserBo param) { + Integer saveType = param.getSaveType()==null?0: param.getSaveType(); + LambdaQueryWrapper postLqw = new LambdaQueryWrapper<>(); + postLqw.in(SysPost::getId,param.getPostIds()); + List postList = postMapper.selectList(postLqw); + LambdaQueryWrapper userLqw = new LambdaQueryWrapper<>(); + userLqw.in(SysUser::getId,param.getUserIds()); + List userList = userMapper.selectList(userLqw); + if(CollectionUtil.isNotEmpty(postList)&&CollectionUtil.isNotEmpty(userList)){ + //移除历史数据 + if (saveType.equals(1)){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysPostUser::getUserId,param.getUserIds()); + this.remove(lqw); + }else if (saveType.equals(2)){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysPostUser::getPostId,param.getPostIds()); + this.remove(lqw); + } + List resultList = new ArrayList<>(); + for (SysUser sysUser : userList) { + for (SysPost sysPost : postList) { + //避免重复 + if(saveType.equals(0)){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysPostUser::getPostId,sysPost.getId()); + lqw.eq(SysPostUser::getUserId,sysUser.getId()); + if(this.count(lqw)>0){ + continue; + } + } + SysPostUser postUser = new SysPostUser(); + postUser.setUserId(sysUser.getId()); + postUser.setUserCode(sysUser.getCode()); + postUser.setUserName(sysUser.getName()); + postUser.setPostId(sysPost.getId()); + postUser.setPostName(sysPost.getPostName()); + postUser.setPostCode(sysPost.getPostCode()); + postUser.setPid(sysPost.getPid()); + postUser.setPathIds(sysPost.getPathIds()); + postUser.setPathNames(sysPost.getPathNames()); + resultList.add(postUser); + } + } + if(CollectionUtil.isNotEmpty(resultList)){ + this.saveBatch(resultList); + } + } + + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java new file mode 100644 index 0000000..bfed947 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.entity.SysRoleMenu; +import com.qs.serve.modules.sys.mapper.SysRoleMenuMapper; +import com.qs.serve.modules.sys.service.SysMenuService; +import com.qs.serve.modules.sys.service.SysRoleMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 菜单用户 服务实现类 + * @author YenHex + * @since 2022-03-16 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysRoleMenuServiceImpl extends ServiceImpl implements SysRoleMenuService { + + private SysMenuService sysMenuService; + + @Override + public boolean removeByRoleId(String roleId,Integer clientType) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRoleMenu::getRoleId,roleId); + if(clientType!=null){ + List sysRoleMenus = list(wrapper); + List menuIds = sysRoleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()); + LambdaQueryWrapper menuLambdaQueryWrapper = new LambdaQueryWrapper<>(); + menuLambdaQueryWrapper.eq(SysMenu::getClientType,clientType); + if(CollectionUtil.isNotEmpty(menuIds)){ + menuLambdaQueryWrapper.in(SysMenu::getId,menuIds); + } + List menuList = sysMenuService.list(menuLambdaQueryWrapper); + menuIds = menuList.stream().map(SysMenu::getId).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(menuIds)){ + wrapper.in(SysRoleMenu::getMenuId,menuIds); + }else { + return true; + } + } + remove(wrapper); + return true; + } + + @Override + public List listByRoleId(String roleId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRoleMenu::getRoleId,roleId); + List roleMenus = list(wrapper); + List menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId).distinct().collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(menuIds)){ + LambdaQueryWrapper wrapper2 = new LambdaQueryWrapper<>(); + wrapper2.in(SysMenu::getId,menuIds); + return sysMenuService.list(wrapper2); + } + return null; + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..a025e3e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,94 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.sys.entity.SysRole; +import com.qs.serve.modules.sys.entity.SysUserRole; +import com.qs.serve.modules.sys.mapper.SysRoleMapper; +import com.qs.serve.modules.sys.mapper.SysUserRoleMapper; +import com.qs.serve.modules.sys.service.SysRoleService; +import com.qs.serve.modules.sys.service.SysUserRoleService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统角色 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysRoleServiceImpl extends ServiceImpl implements SysRoleService { + + private SysRoleMapper sysRoleMapper; + private SysUserRoleMapper sysUserRoleMapper; + private SysUserRoleService sysUserRoleService; + @Override + public List getEnableByIds(List ids) { + if(CollectionUtil.isEmpty(ids)){return new ArrayList<>();} + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(SysRole::getId,ids); + wrapper.eq(SysRole::getEnable,1); + return list(wrapper); + } + + @Override + public List getDefaultRole() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRole::getIsDefault,1); + wrapper.eq(SysRole::getTenantId, AuthContextUtils.getTenant()); + return list(wrapper); + } + + @Override + public void saveUserRole4Edit(List roleIds, String userId) { + //适配空选项移除角色 + if(CollectionUtil.isEmpty(roleIds)){ + LambdaQueryWrapper roleWrap = new LambdaQueryWrapper<>(); + roleWrap.eq(SysRole::getEnable,1); + roleWrap.eq(SysRole::getIsDefault,0); + List list = list(roleWrap); + roleIds = list.stream().map(SysRole::getId).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(list)){ + //移除用户关联的用户板块的可见角色关联 + LambdaQueryWrapper delUserRole = new LambdaQueryWrapper<>(); + delUserRole.eq(SysUserRole::getUserId,userId); + delUserRole.in(SysUserRole::getRoleId,roleIds); + sysUserRoleMapper.delete(delUserRole); + } + } + //校验ID是否正常 + LambdaQueryWrapper roleWrap = new LambdaQueryWrapper<>(); + roleWrap.in(SysRole::getId,roleIds); + roleWrap.eq(SysRole::getEnable,1); + roleWrap.eq(SysRole::getUserVisible,1); + int count = baseMapper.selectCount(roleWrap).intValue(); + if(count!=roleIds.size()){ + Assert.throwEx("数据不配"); + } + //移除用户关联的用户板块的可见角色关联 + LambdaQueryWrapper delUserRole = new LambdaQueryWrapper<>(); + delUserRole.eq(SysUserRole::getUserId,userId); + delUserRole.in(SysUserRole::getRoleId,roleIds); + sysUserRoleMapper.delete(delUserRole); + //重新关联已有的角色 + List sysUserRoles = new ArrayList<>(); + for (String roleId : roleIds) { + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(userId); + userRole.setRoleId(roleId); + sysUserRoles.add(userRole); + } + sysUserRoleService.saveBatch(sysUserRoles); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysSyncLogServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysSyncLogServiceImpl.java new file mode 100644 index 0000000..3fd8ac8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysSyncLogServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysSyncLog; +import com.qs.serve.modules.sys.service.SysSyncLogService; +import com.qs.serve.modules.sys.mapper.SysSyncLogMapper; + +/** + * 同步日志 服务实现类 + * @author YenHex + * @since 2023-03-15 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysSyncLogServiceImpl extends ServiceImpl implements SysSyncLogService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java new file mode 100644 index 0000000..b8223c9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,37 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.sys.entity.SysTenant; +import com.qs.serve.modules.sys.mapper.SysTenantMapper; +import com.qs.serve.modules.sys.service.SysTenantService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统租户 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysTenantServiceImpl extends ServiceImpl implements SysTenantService { + + @Override + @Cacheable(cacheNames = RedisCacheKeys.Tenant_ALL_LIST) + public List list2() { + return list(); + } + + @Override + public SysTenant getCurrent() { + return getById(AuthContextUtils.getTenant()); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLeaveServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLeaveServiceImpl.java new file mode 100644 index 0000000..d289dc7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLeaveServiceImpl.java @@ -0,0 +1,30 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysUserLeave; +import com.qs.serve.modules.sys.service.SysUserLeaveService; +import com.qs.serve.modules.sys.mapper.SysUserLeaveMapper; + +/** + * 用户离职 服务实现类 + * @author YenHex + * @since 2023-02-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserLeaveServiceImpl extends ServiceImpl implements SysUserLeaveService { + + @Override + public SysUserLeave getOneByUserId(String userId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysUserLeave::getUserId,userId); + lqw.eq(SysUserLeave::getLeaveStatus,0); + return getOne(lqw,false); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java new file mode 100644 index 0000000..b7e5c88 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java @@ -0,0 +1,137 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.framework.security.service.SysUserDetailsServiceImpl; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam; +import com.qs.serve.modules.sys.entity.dto.SysLoginParam; +import com.qs.serve.modules.sys.mapper.SysTenantMapper; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysUserLoginService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.mapper.WxUserMapper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserLoginServiceImpl implements SysUserLoginService { + + private final SysUserDetailsServiceImpl userDetailsService; + + private final SysTenantMapper sysTenantMapper; + + private final SysUserMapper sysUserMapper; + + private final RedisService redisService; + + private final WxUserMapper wxUserMapper; + + @Override + public Map login(SysLoginParam loginParam) { + UserDetails userDetails = userDetailsService.loadUserByUsername(loginParam.getAccount()); + if(userDetails == null || !userDetails.getPassword().equalsIgnoreCase(SecureUtil.md5(loginParam.getPassword()))){ + throw new BadCredentialsException("账号或登录密码不正确"); + } + return buildResultMap(userDetails, loginParam.getLoginType(), loginParam.getYmToken()); + } + + @Override + public Map login(String loginCode) { + UserDetails userDetails = userDetailsService.loadUserByUsername(loginCode); + if(userDetails == null){ + throw new BadCredentialsException("账号不正确或未被收录"); + } + return buildResultMap(userDetails, "sso", null); + } + + @Override + public String loginBySyUserId(String syUserId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getSyUserId,syUserId); + List userList = sysUserMapper.selectList(wrapper); + if(userList.size()>0){ + UserDetails userDetails = userDetailsService.buildLoginUser(userList.get(0)); + return buildResultMap(userDetails, "sy", "").get("token").toString(); + } + return null; + } + + @Override + public Map login(SysLoginByPhoneParam loginParam) { + String key = RedisCacheKeys.PHONE_KEY+loginParam.getPhone(); + String code = redisService.getString(key); + if(!loginParam.getCode().equals(code)){ + Assert.throwEx("验证码无效或过期"); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,loginParam.getPhone()); + List list = sysUserMapper.selectList(wrapper); + SysUser sysUser = null; + if(list.size()>0){ + if(list.size()>1){ + log.warn("用户表电话号码[{}]重复!!",loginParam.getPhone()); + } + sysUser = list.get(0); + } + AuthContextUtils.setTenant(sysUser.getTenantId()); + UserDetails userDetails = userDetailsService.buildLoginUser(sysUser); + return buildResultMap(userDetails, loginParam.getLoginType(), loginParam.getYmToken()); + } + + + private Map buildResultMap(UserDetails userDetails,String loginType,String ymToken){ + LoginUser loginUser = (LoginUser)userDetails; + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + String appClient = null; + if("android".equalsIgnoreCase(loginType)){ + appClient = "android"; + }else if("ios".equalsIgnoreCase(loginType)){ + appClient = "ios"; + } + /*if(appClient!=null&&StringUtils.isNotEmpty(ymToken)){ + sysUserMapper.clearYmToken(ymToken); + sysUserMapper.updateYmTokenInt(loginUser.getUserId(),ymToken,appClient); + }*/ + String client = appClient==null?"pc":"app"; + String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,loginUser.getUserId()); + //更新管理员最后登录时间 + Map tokenMap = new HashMap<>(10); + String token = JwtUtils.generateToken(loginUser.getUserId(),loginUser.getTypeFlag(),client); + redisService.set(redisKey,token); + tokenMap.put("token", token); + tokenMap.put("userId", loginUser.getUserId()); + tokenMap.put("IP", loginUser.getLoginIp()); + tokenMap.put("tenant", sysTenantMapper.selectById(loginUser.getTenant())); + tokenMap.put("loginType",loginType); + tokenMap.put("client",client); + //拓展微信token + tokenMap.put("wxToken",""); + return tokenMap; + } + +} diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java new file mode 100644 index 0000000..71ce796 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java @@ -0,0 +1,81 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysUserRole; +import com.qs.serve.modules.sys.mapper.SysUserRoleMapper; +import com.qs.serve.modules.sys.service.SysUserRoleService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户角色 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserRoleServiceImpl extends ServiceImpl implements SysUserRoleService { + + @Override + public boolean removeByRoleId(String roleId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUserRole::getRoleId,roleId); + remove(wrapper); + return true; + } + + @Override + public List listByUid(String uid) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUserRole::getUserId,uid); + return list(wrapper); + } + + @Override + public List notDataUserIds(String roleId, final List userIds) { + if(CollectionUtil.isEmpty(userIds)){ + return new ArrayList<>(); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(SysUserRole::getUserId); + wrapper.in(SysUserRole::getUserId,userIds); + wrapper.eq(SysUserRole::getRoleId,roleId); + List sysUserRoles = list(wrapper); + List dbUserIds = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList()); + return userIds.stream().filter(uid->!dbUserIds.contains(uid)).collect(Collectors.toList()); + } + + @Override + public boolean remove(String roleId, List userIds) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(SysUserRole::getUserId,userIds); + wrapper.eq(SysUserRole::getRoleId,roleId); + return remove(wrapper); + } + + @Override + public boolean replaceAndRemove(String leafUserId, String enterUserId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUserRole::getUserId,leafUserId); + if(!StringUtils.hasText(enterUserId)){ + super.remove(wrapper); + }else { + List list = super.list(wrapper); + for (SysUserRole userRole : list) { + userRole.setUserId(enterUserId); + } + super.updateBatchById(list); + } + return true; + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserSalesServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserSalesServiceImpl.java new file mode 100644 index 0000000..fead353 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserSalesServiceImpl.java @@ -0,0 +1,67 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.StringUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysUserSales; +import com.qs.serve.modules.sys.service.SysUserSalesService; +import com.qs.serve.modules.sys.mapper.SysUserSalesMapper; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 服务实现类 + * @author YenHex + * @since 2022-10-12 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserSalesServiceImpl extends ServiceImpl implements SysUserSalesService { + + @Override + public List selectSysUserSalesList(SysUserSales userSales) { + return baseMapper.selectSysUserSalesList(userSales); + } + + @Override + public List listByPathId(String pathId) { + if(!StringUtils.hasText(pathId)){ + return new ArrayList<>(); + } + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.likeRight(SysUserSales::getPathIds,pathId); + lqw.ne(SysUserSales::getPathIds,pathId); + List list = this.list(lqw); +// List result = new ArrayList<>(); + //过滤数值类型脏数据 +// for (SysUserSales userSales : list) { +// String[] arr = userSales.getPathIds().split("_"); +// String lastId = arr[arr.length-1]; +// if(!lastId.equals(userSales.getUserId())){ +// continue; +// } +// result.add(userSales); +// } + return list; + } + + @Override + public List listByChildIds(String userId) { + SysUserSales sysUserSales = this.getById(userId); + if(sysUserSales!=null){ + List userSales = this.listByPathId(sysUserSales.getPathIds()); + return userSales.stream().map(SysUserSales::getUserId).collect(Collectors.toList()); + } + return new ArrayList<>(); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..3abe47f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java @@ -0,0 +1,330 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.DesensitizedUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.config.properties.SeeYonProperties; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.*; +import com.qs.serve.modules.sys.entity.bo.SysUserLeaveBo; +import com.qs.serve.modules.sys.entity.dto.SysUpdateSeeYonPassword; +import com.qs.serve.modules.sys.mapper.*; +import com.qs.serve.modules.sys.service.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统用户 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserServiceImpl extends ServiceImpl implements SysUserService { + + private final SysPostUserService sysPostUserService; + private final SysUserRoleService sysUserRoleService; + private final SysUserLeaveService sysUserLeaveService; + private final SysPermitService sysPermitService; + private final SysRoleService sysRoleService; + private final SysUserRoleService userRoleService; + private final SysDeptMapper sysDeptMapper; + private final SysMenuMapper sysMenuMapper; + private final SysPostMapper postMapper; + private final SeeYonProperties seeYonProperties; + + @Override + public void updateSeeYonPassword(String syUserId, String password) { + String apihost = seeYonProperties.getExtApi(); + if(StringUtils.hasText(syUserId)&&StringUtils.hasText(apihost)){ + String updateJson = JsonUtil.objectToJson(new SysUpdateSeeYonPassword(syUserId,password)); + try { + HttpUtil.doPost(apihost+"/api/oa/base/user/changePassword",updateJson,null); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } + + @Override + public SysUser getByAccount(String acc) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,acc); + return getOne(wrapper,false); + } + + @Override + public SysUser getByIdentityNo(String acc) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getIdentityNo,acc); + return getOne(wrapper,false); + } + + @Override + public SysUser getBySyId(String acc) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getSyUserId,acc); + return getOne(wrapper,false); + } + + @Override + public LoginUser getLoginUserByAccount(String account) { + SysUser sysUser = getByAccount(account); + if(AuthContextUtils.getTenant()==null){ + AuthContextUtils.setTenant(sysUser.getTenantId()); + } + return buildLoginUser(sysUser); + } + + @Override + public LoginUser getLoginUserById(String id) { + SysUser sysUser = getById(id); + return buildLoginUser(sysUser); + } + + @Override + public List listUser(SysUser sysUser) { + List list = baseMapper.listUser(sysUser); + list.forEach(usr->{ + usr.setMobile(DesensitizedUtil.mobilePhone(usr.getMobile())); + usr.setPassword(null); + }); + return list; + } + + @Override + public void relateInfo(SysUser sysUser,boolean loadLeave) { + if(sysUser==null){return;} + sysUser.setPassword(null); + List userRoles = sysUserRoleService.listByUid(sysUser.getId()); + List roleIds = userRoles.stream().map(SysUserRole::getRoleId).distinct().collect(Collectors.toList()); + List sysRoles = new ArrayList<>(); + if(CollectionUtil.isNotEmpty(roleIds)){ + sysRoles = sysRoleService.getEnableByIds(roleIds); + } + sysUser.setRoleList(sysRoles); + if(sysUser.getDeptId()!=null){ + sysUser.setDeptInfo(sysDeptMapper.selectById(sysUser.getDeptId())); + } + if(loadLeave){ + SysUserLeave sysUserLeave = sysUserLeaveService.getOneByUserId(sysUser.getId()); + sysUser.setLeaveInfo(sysUserLeave); + } + List postUserList = sysPostUserService.listByUserId(sysUser.getId()); + if(CollectionUtil.isNotEmpty(postUserList)){ + List postIds = postUserList.stream().map(SysPostUser::getPostId).distinct().collect(Collectors.toList()); + List postList = postMapper.selectBatchIds(postIds); + sysUser.setPositionList(postList); + } + } + + + + @Override + public LoginUser buildLoginUser(SysUser sysUser){ + if(sysUser==null){return null;} + if(sysUser.getLoginEnable().equals(0)){ + Assert.throwEx(HttpCode.LOGIN_ERR_2); + } + List authorCodes = new ArrayList<>(); + List menuIds = new ArrayList<>(); + //以下细分到权限和菜单 +// if(sysUser.getSuperFlag().equals(1)){ +// List sysRolePermits = sysPermitService.listByCache(); +// authorCodes = sysRolePermits.stream().map(SysPermit::getCode).distinct().collect(Collectors.toList()); +// menuIds = sysMenuMapper.searchMenuIds(); +// }else { +// List userRoles = sysUserRoleService.listByUid(sysUser.getId()); +// List roleIds = userRoles.stream().map(SysUserRole::getRoleId).distinct().collect(Collectors.toList()); +// //添加默认的角色ID +// List defaultRole = sysRoleService.getDefaultRole(); +// List defaultRoleIds = defaultRole.stream().map(SysRole::getId).collect(Collectors.toList()); +// roleIds.addAll(defaultRoleIds); +// List sysRoles = sysRoleService.getEnableByIds(roleIds); +// List sysRolePermits = new ArrayList<>(); +// if(CollectionUtil.isNotEmpty(sysRoles)){ +// //listPermitCode +// sysRolePermits = sysRoleMenuMapper.listPermitCode(sysRoles.stream().map(SysRole::getId).collect(Collectors.toList())); +// } +// for (SysPermit sysRolePermit : sysRolePermits) { +// if(sysRolePermit==null){continue;} +// authorCodes.add(sysRolePermit.getCode()); +// } +// menuIds = sysMenuMapper.searchUserMenuIds(sysUser.getId()); +// List defaultRoleMenuIds = sysMenuMapper.searchDefaultMenuIds(defaultRoleIds); +// menuIds.addAll(defaultRoleMenuIds); +// } + + + List sysRolePermits = sysPermitService.listByCache(); + authorCodes = sysRolePermits.stream().map(SysPermit::getCode).distinct().collect(Collectors.toList()); + List userRoles = sysUserRoleService.listByUid(sysUser.getId()); + List roleIds = userRoles.stream().map(SysUserRole::getRoleId).distinct().collect(Collectors.toList()); + //添加默认的角色ID + List defaultRole = sysRoleService.getDefaultRole(); + List defaultRoleIds = defaultRole.stream().map(SysRole::getId).collect(Collectors.toList()); + roleIds.addAll(defaultRoleIds); + + for (SysPermit sysRolePermit : sysRolePermits) { + if(sysRolePermit==null){continue;} + authorCodes.add(sysRolePermit.getCode()); + } + menuIds = sysMenuMapper.searchUserMenuIds(sysUser.getId()); + if(defaultRoleIds.size()<1){ + Assert.throwEx("请刷新页面"); + } + List defaultRoleMenuIds = sysMenuMapper.searchDefaultMenuIds(defaultRoleIds); + menuIds.addAll(defaultRoleMenuIds); + + + + + LoginUserType userType = sysUser.getSuperFlag()==0?LoginUserType.SYS_USER:LoginUserType.SYS_SUP_USER; + return new LoginUser(sysUser.getId(),sysUser.getName(),sysUser.getPassword(), ServletUtils.getIp(null),userType,authorCodes,menuIds,sysUser.getTenantId()); + } + + @Override + public List listByOaMemberIds(List memberIds) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysUser::getSyUserId,memberIds); + return this.list(lqw); + } + + @Override + public List listByCodes(List codes) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(SysUser::getCode,codes); + return this.list(lqw); + } + + @Override + public SysUser listByOaMemberId(String memberId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysUser::getSyUserId,memberId); + return this.getOne(lqw,false); + } + + @Override + public void leave(SysUserLeaveBo param) { + LocalDate currDate = LocalDate.now(); + SysUser leaveUser = this.getById(param.getUserId()); + if(currDate.isAfter(param.getLeaveEffectDate())){ + Assert.throwEx("离职日期必须大于等于今天"); + } + if(leaveUser.getServingState().equals(0)){ + Assert.throwEx("员工已离职"); + } + SysUserLeave userLeaveObj = sysUserLeaveService.getOneByUserId(param.getUserId()); + if(userLeaveObj==null){ + userLeaveObj = new SysUserLeave(); + } + userLeaveObj.setLeaveEffectDate(param.getLeaveEffectDate()); + userLeaveObj.setUserId(leaveUser.getId()); + userLeaveObj.setUserName(leaveUser.getName()); + userLeaveObj.setUserCode(leaveUser.getCode()); + if(StringUtils.hasText(param.getCusUserId())){ + SysUser cusUser = this.getById(param.getCusUserId()); + userLeaveObj.setCusUserId(cusUser.getId()); + userLeaveObj.setCusUserCode(cusUser.getCode()); + userLeaveObj.setCusUserName(cusUser.getName()); + } + if(StringUtils.hasText(param.getFlowUserId())){ + SysUser flowUser = this.getById(param.getFlowUserId()); + userLeaveObj.setFlowUserId(flowUser.getId()); + userLeaveObj.setFlowUserName(flowUser.getName()); + userLeaveObj.setFlowUserCode(flowUser.getCode()); + } + if(StringUtils.hasText(param.getRoleUserId())){ + SysUser roleUser = this.getById(param.getRoleUserId()); + userLeaveObj.setRoleUserId(roleUser.getId()); + userLeaveObj.setRoleUserCode(roleUser.getCode()); + userLeaveObj.setRoleUserName(roleUser.getName()); + }else { + userLeaveObj.setRoleUserId(""); + userLeaveObj.setRoleUserCode(""); + userLeaveObj.setRoleUserName(""); + } + userLeaveObj.setLeaveReason(param.getLeaveReason()); + sysUserLeaveService.saveOrUpdate(userLeaveObj); + //更新员工信息 + SysUser user = new SysUser(); + user.setId(leaveUser.getId()); + user.setServingState(2); + this.updateById(user); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void leaveNow(List userIds,Boolean updateLeaveStatus) { + + } + + + + + @Override + public void cancelLeave(String userId) { + SysUser sysUser = this.getById(userId); + if(!sysUser.getServingState().equals(2)){ + Assert.throwEx("非准备离职状态,取消失败"); + } + SysUser user = new SysUser(); + user.setId(sysUser.getId()); + user.setServingState(1); + this.updateById(user); + LambdaQueryWrapper leaveLqw = new LambdaQueryWrapper<>(); + leaveLqw.eq(SysUserLeave::getUserId,userId); + leaveLqw.eq(SysUserLeave::getLeaveStatus,0); + SysUserLeave userLeave = new SysUserLeave(); + userLeave.setLeaveStatus(2); + userLeave.setLeaveCancelDate(LocalDateTime.now()); + sysUserLeaveService.update(userLeave,leaveLqw); + } + + @Override + public void reEntry(String userId) { + SysUser sysUser = this.getById(userId); + if(!sysUser.getServingState().equals(0)){ + Assert.throwEx("非离职状态,操作失败"); + } + SysUser user = new SysUser(); + user.setId(userId); + user.setServingDate(LocalDate.now()); + user.setServingState(1); + user.setLoginEnable(1); + this.updateById(user); + } + + @Override + public List listByChildIds(String userId) { + List postUsers = sysPostUserService.listByUserId(userId); + if(CollectionUtil.isEmpty(postUsers)){ + return new ArrayList<>(); + } + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.ne(SysPostUser::getUserId,userId); + lqw.and(aa->{ + for (SysPostUser postUser : postUsers) { + aa.or().likeRight(SysPostUser::getPathIds,postUser.getPathIds()+"_"); + } + }); + List childPostUsers = sysPostUserService.list(lqw); + return childPostUsers; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java new file mode 100644 index 0000000..98969ea --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.wx.api; + +import com.qs.serve.modules.wx.common.conf.WxMpConfig; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + + +/** + * API 微信公众号JSAPI + * @author YenHex + * @since 2022-03-07 + */ +@AllArgsConstructor +//@RestController +//@RequestMapping("/api/mp/jsapi/{appid}") +public class WxMpJsapiApi { + @Autowired(required = false) + private WxMpConfig wxMpConfig; + + /** + * 获取票据 + * @param appid + * @return + * @throws WxErrorException + */ + @GetMapping("/getJsapiTicket") + public String getJsapiTicket(@PathVariable String appid) throws WxErrorException { + final WxJsapiSignature jsapiSignature = wxMpConfig.wxMpService().switchoverTo(appid).createJsapiSignature("111"); + System.out.println(jsapiSignature); + return wxMpConfig.wxMpService().getJsapiTicket(true); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java new file mode 100644 index 0000000..58b6449 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java @@ -0,0 +1,190 @@ +package com.qs.serve.modules.wx.api; + +import com.qs.serve.modules.wx.common.conf.WxMpConfig; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.menu.WxMenu; +import me.chanjar.weixin.common.bean.menu.WxMenuButton; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; +import me.chanjar.weixin.mp.bean.menu.WxMpMenu; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.net.MalformedURLException; +import java.net.URL; + +import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; + +/** + * API 微信公众号菜单 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@AllArgsConstructor +//@RestController +//@RequestMapping("/api/mp/menu/{appid}") +public class WxMpMenuApi { + @Autowired(required = false) + private WxMpConfig wxMpConfig; + + /** + * 自定义菜单创建接口 + * @apiNote
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
+     * 如果要创建个性化菜单,请设置matchrule属性
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * @return 如果是个性化菜单,则返回menuid,否则返回null + */ + @PostMapping("/create") + public String menuCreate(@PathVariable String appid, @RequestBody WxMenu menu) throws WxErrorException { + return wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().menuCreate(menu); + } + + //@GetMapping("/createByData") + public String menuCreateSample(@PathVariable String appid) throws WxErrorException, MalformedURLException { + WxMenu menu = new WxMenu(); + WxMenuButton button1 = new WxMenuButton(); + button1.setType(MenuButtonType.CLICK); + button1.setName("今日歌曲"); + button1.setKey("V1001_TODAY_MUSIC"); + +// WxMenuButton button2 = new WxMenuButton(); +// button2.setType(WxConsts.BUTTON_MINIPROGRAM); +// button2.setName("小程序"); +// button2.setAppId("wx286b93c14bbf93aa"); +// button2.setPagePath("pages/lunar/index.html"); +// button2.setUrl("http://mp.weixin.qq.com"); + + WxMenuButton button3 = new WxMenuButton(); + button3.setName("菜单"); + + menu.getButtons().add(button1); +// menu.getButtons().add(button2); + menu.getButtons().add(button3); + + WxMenuButton button31 = new WxMenuButton(); + button31.setType(MenuButtonType.VIEW); + button31.setName("搜索"); + button31.setUrl("http://www.soso.com/"); + + WxMenuButton button32 = new WxMenuButton(); + button32.setType(MenuButtonType.VIEW); + button32.setName("视频"); + button32.setUrl("http://v.qq.com/"); + + WxMenuButton button33 = new WxMenuButton(); + button33.setType(MenuButtonType.CLICK); + button33.setName("赞一下我们"); + button33.setKey("V1001_GOOD"); + + WxMenuButton button34 = new WxMenuButton(); + button34.setType(MenuButtonType.VIEW); + button34.setName("获取用户信息"); + + ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (servletRequestAttributes != null) { + HttpServletRequest request = servletRequestAttributes.getRequest(); + URL requestURL = new URL(request.getRequestURL().toString()); + String url = wxMpConfig.wxMpService().switchoverTo(appid).getOAuth2Service().buildAuthorizationUrl( + String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appid), + WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); + button34.setUrl(url); + } + + button3.getSubButtons().add(button31); + button3.getSubButtons().add(button32); + button3.getSubButtons().add(button33); + button3.getSubButtons().add(button34); + + wxMpConfig.wxMpService().switchover(appid); + return wxMpConfig.wxMpService().getMenuService().menuCreate(menu); + } + + /** + * + * 自定义菜单创建接口 + * @apiNote
详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
+     * 如果要创建个性化菜单,请设置matchrule属性
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * @return 如果是个性化菜单,则返回menuid,否则返回null + */ + @PostMapping("/createByJson") + public String menuCreate(@PathVariable String appid, @RequestBody String json) throws WxErrorException { + return wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().menuCreate(json); + } + + /** + * 自定义菜单删除接口 + * @apiNote
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN
+     * 
+ */ + @GetMapping("/delete") + public void menuDelete(@PathVariable String appid) throws WxErrorException { + wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().menuDelete(); + } + + /** + * 删除个性化菜单接口 + * @apiNote
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * @param menuId 个性化菜单的menuid + */ + @GetMapping("/delete/{menuId}") + public void menuDelete(@PathVariable String appid, @PathVariable String menuId) throws WxErrorException { + wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().menuDelete(menuId); + } + + /** + * 自定义菜单查询接口 + * @apiNote
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN
+     * 
+ */ + @GetMapping("/get") + public WxMpMenu menuGet(@PathVariable String appid) throws WxErrorException { + return wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().menuGet(); + } + + /** + * 测试个性化菜单匹配结果 + * @apiNote
+     * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
+     * 
+ * + * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 + */ + @GetMapping("/menuTryMatch/{userid}") + public WxMenu menuTryMatch(@PathVariable String appid, @PathVariable String userid) throws WxErrorException { + return wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().menuTryMatch(userid); + } + + /** + * 获取自定义菜单配置接口 + * @apiNote
+     * 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过API调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。
+     * 请注意:
+     * 1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。
+     * 2、本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。
+     * 3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。
+     * 4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。
+     * 5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。
+     *  接口调用请求说明:
+     * http请求方式: GET(请使用https协议)
+     * https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
+     * 
+ */ + @GetMapping("/getSelfMenuInfo") + public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appid) throws WxErrorException { + return wxMpConfig.wxMpService().switchoverTo(appid).getMenuService().getSelfMenuInfo(); + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpPortalApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpPortalApi.java new file mode 100644 index 0000000..a4a6324 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpPortalApi.java @@ -0,0 +1,129 @@ +package com.qs.serve.modules.wx.api; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * 门户:微信公众号回调 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@AllArgsConstructor +//@RestController +//@RequestMapping("/api/wx/mp/portal/{appid}") +public class WxMpPortalApi { + + private final WxMpService wxService; + private final WxMpMessageRouter messageRouter; + + /** + * 校验身份 + * @param appid + * @param signature + * @param timestamp + * @param nonce + * @param echostr + * @return + */ + @GetMapping(produces = "text/plain;charset=utf-8") + public String authGet(@PathVariable String appid, + @RequestParam(name = "signature", required = false) String signature, + @RequestParam(name = "timestamp", required = false) String timestamp, + @RequestParam(name = "nonce", required = false) String nonce, + @RequestParam(name = "echostr", required = false) String echostr) { + + log.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, + timestamp, nonce, echostr); + if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { + throw new IllegalArgumentException("请求参数非法,请核实!"); + } + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + if (wxService.checkSignature(timestamp, nonce, signature)) { + return echostr; + } + return "非法请求"; + } + + /** + * 身份校验2 + * @param appid + * @param requestBody + * @param signature + * @param timestamp + * @param nonce + * @param openid + * @param encType + * @param msgSignature + * @return + */ + @PostMapping(produces = "application/xml; charset=UTF-8") + public String post(@PathVariable String appid, + @RequestBody String requestBody, + @RequestParam("signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce, + @RequestParam("openid") String openid, + @RequestParam(name = "encrypt_type", required = false) String encType, + @RequestParam(name = "msg_signature", required = false) String msgSignature) { + log.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}]," + + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + openid, signature, encType, msgSignature, timestamp, nonce, requestBody); + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + + if (!wxService.checkSignature(timestamp, nonce, signature)) { + throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); + } + String out = null; + if (encType == null) { + // 明文传输的消息 + WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody); + WxMpXmlOutMessage outMessage = this.route(inMessage); + if (outMessage == null) { + return ""; + } + out = outMessage.toXml(); + } else if ("aes".equalsIgnoreCase(encType)) { + // aes加密的消息 + WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(), + timestamp, nonce, msgSignature); + log.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); + WxMpXmlOutMessage outMessage = this.route(inMessage); + if (outMessage == null) { + return ""; + } + + out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage()); + } + + log.debug("\n组装回复信息:{}", out); + return out; + } + + private WxMpXmlOutMessage route(WxMpXmlMessage message) { + try { + return this.messageRouter.route(message); + } catch (Exception e) { + log.error("路由消息时出现异常!", e); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java new file mode 100644 index 0000000..1587819 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java @@ -0,0 +1,39 @@ +package com.qs.serve.modules.wx.api; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * 微信公众号重定向 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@AllArgsConstructor +//@Controller +//@RequestMapping("/api/mp/redirect/{appid}") +public class WxMpRedirectApi { + private final WxMpService wxService; + + @RequestMapping("/greet") + public String greetUser(@PathVariable String appid, @RequestParam String code, ModelMap map) { + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + + try { + WxOAuth2AccessToken accessToken = wxService.getOAuth2Service().getAccessToken(code); + WxOAuth2UserInfo user = wxService.getOAuth2Service().getUserInfo(accessToken, null); + map.put("user", user); + } catch (WxErrorException e) { + e.printStackTrace(); + } + return "greet_user"; + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxSvcLoginApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxSvcLoginApi.java new file mode 100644 index 0000000..036fbc5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxSvcLoginApi.java @@ -0,0 +1,190 @@ +package com.qs.serve.modules.wx.api; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.framework.security.service.SysUserDetailsServiceImpl; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.mapper.SysTenantMapper; +import com.qs.serve.modules.sys.service.SysUserService; +import com.qs.serve.modules.wx.common.conf.WxCpConfig; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxLoginUser; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.api.WxCpOAuth2Service; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.WxCpUserService; +import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; +import me.chanjar.weixin.cp.bean.WxCpUser; +import org.jetbrains.annotations.NotNull; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 门户:微信登录 + * @author YenHex + * @since 2022/3/7 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/wx/login") +public class WxSvcLoginApi { + + private final WxUserService wxUserService; + + private final RedisService redisService; + + private final SysUserDetailsServiceImpl userDetailsService; + + private final SysTenantMapper sysTenantMapper; + + private SysUserService sysUserService; + + /** + * 企业微信登录 + * @param wxLoginUser + * @param request + * @return + */ + @SysLog(title = "企业微信登录",biz = BizType.LOGIN,inter = InterType.API) + @PostMapping("/cp") + public R loginCompanyApp(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){ + WxUser wxUser = null; + try { + wxUser = wxUserService.login(wxLoginUser,request); + } catch (Exception e) { + Assert.throwEx(e.getMessage()); + } + if(wxUser==null){ + Assert.throwEx(HttpCode.WX_ERR); + } + Map objectMap = genTokenInfo(request, wxUser); + return R.ok(objectMap); + } + + /** + * 小程序登陆(暂测试) + * @param wxLoginUser + * @param request + * @return + */ + @SysLog(title = "小程序登录",biz = BizType.LOGIN,inter = InterType.API) + @PostMapping("/ma") + public R loginMicroApp(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){ + WxUser wxUser = null; + try { + wxUser = wxUserService.login(wxLoginUser,request); + } catch (Exception e) { + log.warn(e.getMessage()); + } + if(wxUser==null){ + Assert.throwEx(HttpCode.WX_ERR); + } + Map objectMap = genTokenInfo(request, wxUser); + return R.ok(objectMap); + } + + /** + * 公众号登录 + * @param wxLoginUser + * @return + * @throws Exception + */ + @SysLog(title = "公众号登录",biz = BizType.LOGIN,inter = InterType.API) + @PostMapping("/mp") + public R login(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){ + WxUser wxUser = null; + try { + wxUser = wxUserService.login(wxLoginUser,request); + } catch (Exception e) { + log.warn(e.getMessage()); + } + if(wxUser==null){ + Assert.throwEx(HttpCode.WX_ERR); + } + Map objectMap = genTokenInfo(request, wxUser); + return R.ok(objectMap); + } + + @NotNull + private Map genTokenInfo(HttpServletRequest request, WxUser wxUser) { + Map objectMap = new HashMap<>(); + String token = IdUtil.fastSimpleUUID(); + LoginUser loginUser = new LoginUser(wxUser.getId(), wxUser.getEmpName(),"", + ServletUtils.getIp(request), LoginUserType.APP_USER,new ArrayList<>(),null,AuthContextUtils.getTenant()); + objectMap.put("token",token); + //微信登录ID + String wxUserKey = StringUtils.format(RedisCacheKeys.WX_KEY_USER,token); + redisService.set(wxUserKey, wxUser.getId()); + //后台管理员信息 + Map tokenMap = new HashMap<>(10); + String client = "wx_app"; + String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client, wxUser.getSysUserId()); + String pctoken = JwtUtils.generateToken(wxUser.getSysUserId(),loginUser.getTypeFlag(),client); + redisService.set(redisKey,pctoken); + tokenMap.put("token", pctoken); + tokenMap.put("userId", wxUser.getSysUserId()); + tokenMap.put("IP", loginUser.getLoginIp()); + tokenMap.put("tenant", sysTenantMapper.selectById(loginUser.getTenant())); + tokenMap.put("loginType",client); + tokenMap.put("client",client); + //关联 + objectMap.put("adminTokenInfo",tokenMap); + return objectMap; + } + + /** + * 公众号测试登录 + */ + @PostMapping("/mptest") + public R login(HttpServletRequest request){ + Map objectMap = new HashMap<>(); + String token = IdUtil.fastSimpleUUID(); + //微信登录ID + String wxUserKey = StringUtils.format(RedisCacheKeys.WX_KEY_USER,token); + redisService.set(wxUserKey,"1"); + + LoginUser loginUser = new LoginUser("1","微信测试用户","", + ServletUtils.getIp(request), LoginUserType.APP_USER,new ArrayList<>(),null,AuthContextUtils.getTenant()); + objectMap.put("token",token); + String sysUserId = "1"; + Map tokenMap = new HashMap<>(10); + String client = "wx_app"; + String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,sysUserId); + String pctoken = JwtUtils.generateToken(sysUserId,loginUser.getTypeFlag(),client); + redisService.set(redisKey,pctoken); + tokenMap.put("token", pctoken); + tokenMap.put("userId", sysUserId); + tokenMap.put("IP", loginUser.getLoginIp()); + tokenMap.put("tenant", sysTenantMapper.selectById(loginUser.getTenant())); + tokenMap.put("loginType",client); + tokenMap.put("client",client); + //关联 + objectMap.put("adminTokenInfo",tokenMap); + return R.ok(objectMap); + } + + + +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java new file mode 100644 index 0000000..8bed2d3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java @@ -0,0 +1,162 @@ +package com.qs.serve.modules.wx.api; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.framework.security.service.SysUserDetailsServiceImpl; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysDept; +import com.qs.serve.modules.sys.entity.SysRole; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysUserVo; +import com.qs.serve.modules.sys.mapper.SysMenuMapper; +import com.qs.serve.modules.sys.service.SysRoleService; +import com.qs.serve.modules.sys.service.SysUserSalesService; +import com.qs.serve.modules.sys.service.SysUserService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxPhoneBindParam; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 微信:API 微信用户 + * @author YenHex + * @since 2022/3/8 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/wx/user") +public class WxSvcUserApi { + + private WxUserService wxUserService; + private RedisService redisService; + private SysUserService sysUserService; + private SysUserDetailsServiceImpl userDetailsService; + private SysRoleService sysRoleService; + private SysUserSalesService sysUserSalesService; + private final SysMenuMapper sysMenuMapper; + + /** + * 用户信息 + */ + @GetMapping("/info") + public R info(){ + WxUser wxUser = wxUserService.getCurrentWxUser(true); + SysUserVo sysUserVo = null; + if(StringUtils.hasText(wxUser.getSysUserId())){ + SysUser sysUser = sysUserService.getById(wxUser.getSysUserId()); + if(sysUser!=null){ + // 解决H5页面权限不刷新 + List defaultRole = sysRoleService.getDefaultRole(); + List defaultRoleIds = defaultRole.stream().map(SysRole::getId).collect(Collectors.toList()); + List menuIds = sysMenuMapper.searchUserMenuIds(sysUser.getId()); + List defaultRoleMenuIds = sysMenuMapper.searchDefaultMenuIds(defaultRoleIds); + menuIds.addAll(defaultRoleMenuIds); + + LoginUser userDetails = userDetailsService.buildLoginUser(sysUser); + sysUser.setAuthorIds(menuIds); + sysUser.setAuthorList(userDetails.getAuthorList()); + sysUserVo = sysUser.toSysUserVo(false); + } + } + + if(wxUser.getAppType()!=null&&wxUser.getAppType().equals(3)){ + //企业微信转化为公众号用户 + WxUser wxUser1 = wxUserService.getOne(new LambdaQueryWrapper() + .eq(WxUser::getSysUserId,wxUser.getSysUserId()) + .eq(WxUser::getAppType,2),false); + if(wxUser1==null){ + Assert.throwEx("请前往公众号绑定信息"); + } + wxUser1.setSysUserInfo(sysUserVo); + return R.ok(wxUser1); + }else { + wxUser.setSysUserInfo(sysUserVo); + } + return R.ok(wxUser); + } + + /** + * 获取手机绑定验证码 + */ + @LimitSubmit(interval = 10000) + @SysLog(title = "手机绑定验证码",inter = InterType.API) + @GetMapping("/phoneCode/{phone}") + public R phoneCode(@PathVariable("phone") String phone){ + //拦截未注册的手机号 + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysUser::getMobile,phone); + Long count = sysUserService.count(lqw); + if(count<1L){ + return R.error("手机号未被收录"); + } + String key = RedisCacheKeys.PHONE_KEY+phone; + String code = redisService.getString(key); + if(code==null){ + code = IdUtil.genCode(6); + } + //tianYiYunSmsService.send(phone,code); + //tencentYunSmsService.send(phone,code); + log.debug("手机'{}'验证码:{}",phone,code); + redisService.set(key,code,10, TimeUnit.MINUTES); + return R.ok(); + } + + /** + * 手机号绑定 + * @param param + * @return + */ + @SysLog(title = "手机绑定",biz = BizType.UPDATE, inter = InterType.API) + @PostMapping("/bindPhone") + public R phoneCode(@RequestBody @Valid WxPhoneBindParam param){ + String key = RedisCacheKeys.PHONE_KEY+param.getPhone(); + String code = redisService.getString(key); + if(!param.getCode().equals(code)){ + return R.error("验证码无效或过期"); + } + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysUser::getMobile,param.getPhone()); + SysUser sysUser = sysUserService.getOne(lqw,false); + + WxUser wxUser = wxUserService.getCurrentWxUser(); + wxUser.setPhone(param.getPhone()); + wxUser.setEmpName(sysUser.getName()); + wxUser.setSysUserId(sysUser.getId()); + wxUser.setSysUserCode(sysUser.getCode()); + wxUserService.updateById(wxUser); + //便于多设备登陆 + redisService.remove(key); + + //返回登陆信息 +// String client = "wx_app"; +// String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,wxUser.getSysUserId()); +// String pctoken = JwtUtils.generateToken(wxUser.getSysUserId(), LoginUserType.APP_USER,client); +// redisService.set(redisKey,pctoken); +// Map tokenMap = new HashMap<>(10); +// tokenMap.put("token", pctoken); +// tokenMap.put("userId", wxUser.getSysUserId()); +// tokenMap.put("loginType",client); +// tokenMap.put("client",client); + return R.ok(); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java new file mode 100644 index 0000000..e74f58c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.wx.common.builder.mp; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +public class ImageBuilder implements MpXmlMessageBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + return m; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java new file mode 100644 index 0000000..efbece0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.common.builder.mp; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +public interface MpXmlMessageBuilder { + + WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service); +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java new file mode 100644 index 0000000..2e5f9f1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.wx.common.builder.mp; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +public class TextBuilder implements MpXmlMessageBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + return m; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/conf/WxCpConfig.java b/src/main/java/com/qs/serve/modules/wx/common/conf/WxCpConfig.java new file mode 100644 index 0000000..f9fdfbd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/conf/WxCpConfig.java @@ -0,0 +1,46 @@ +package com.qs.serve.modules.wx.common.conf; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.cp.api.WxCpOAuth2Service; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.WxCpUserService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +/** + * 企业微信配置 + * @author YenHex + * @since 2024/8/12 + */ +@Slf4j +public class WxCpConfig { + + private static Map secretMap = new HashMap<>(); + + static { + //测试环境 + //CRM + secretMap.put(1000008,"tC2ENr_hs0on-OMfWMQ6ch3TL2ndcUDz1b34K-M7VGg"); + //订单 + secretMap.put(1000009,"uyyatorEYuaT_1Qm45sFQ-UAIVIViR095KI_SV94yrU"); + + //正式环境 + //CRM + secretMap.put(1000015,"ylgxFjYWogNXAdVGRrWiCBN2lx6Ys7PgYMG8GkQatrY"); + //订单 + secretMap.put(1000016,"0lYdQJXaYrJ_1WUeXDHpHGcYnOQva6Ve6S-6gxQpfdY"); + } + + public static String getSecret(Integer agentId){ + return secretMap.get(agentId); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java b/src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java new file mode 100644 index 0000000..2f153e8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java @@ -0,0 +1,137 @@ +package com.qs.serve.modules.wx.common.conf; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.config.properties.RedisProperties; +import com.qs.serve.modules.wx.common.consts.WxStatusConst; +import com.qs.serve.modules.wx.common.handler.mp.*; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.service.WxAppService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +import java.util.List; +import java.util.stream.Collectors; + +import static me.chanjar.weixin.common.api.WxConsts.EventType; +import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE; +import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE; +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT; +import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*; +import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY; +/** + * 微信公众号配置 + * @author YenHex + * @since 2022/3/7 + */ +@Slf4j +@AllArgsConstructor +@Configuration(proxyBeanMethods = false) +public class WxMpConfig { + + private final LogHandler logHandler; + private final NullHandler nullHandler; + private final KfSessionHandler kfSessionHandler; + private final StoreCheckNotifyHandler storeCheckNotifyHandler; + private final LocationHandler locationHandler; + private final MenuHandler menuHandler; + private final MsgHandler msgHandler; + private final UnsubscribeHandler unsubscribeHandler; + private final SubscribeHandler subscribeHandler; + private final ScanHandler scanHandler; + private final WxAppService wxAppService; + private final RedisProperties redisProperties; + private static WxMpService wxMpService = null; + + @Bean + public WxMpService wxMpService() { + if(wxMpService!=null){ + return wxMpService; + } + //超时时间 + LambdaQueryWrapper appWrapper = new LambdaQueryWrapper<>(); + appWrapper.eq(WxApp::getAppType, WxStatusConst.WxApp_AppType_2); + List wxAppList = wxAppService.list(appWrapper); + if (CollectionUtil.isEmpty(wxAppList)) { + log.warn("公众号配置为空"); + } + WxMpService service = new WxMpServiceImpl(); + service.setMultiConfigStorages(wxAppList + .stream().map(app -> { + WxMpDefaultConfigImpl configStorage; +// JedisPoolConfig poolConfig = new JedisPoolConfig(); +// JedisPool jedisPool = new JedisPool( +// poolConfig, +// redisProperties.getHost(), +// redisProperties.getPort(), +// timeout, +// redisProperties.getPassword(), +// redisProperties.getDatabase()); +// configStorage = new WxMpRedisConfigImpl(new JedisWxRedisOps(jedisPool), app.getId()); + log.warn("进行公众号配置:{}",app.getId()); + configStorage = new WxMpDefaultConfigImpl(); + configStorage.setAppId(app.getId()); + configStorage.setSecret(app.getSecret()); + configStorage.setToken(app.getToken()); + configStorage.setAesKey(app.getAesKey()); + return configStorage; + }).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o))); + WxMpConfig.wxMpService = service; + return service; + } + + @Bean + public WxMpMessageRouter messageRouter(WxMpService wxMpService) { + final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); + + // 记录所有事件的日志 (异步执行) + newRouter.rule().handler(this.logHandler).next(); + + // 接收客服会话管理事件 + newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION) + .handler(this.kfSessionHandler).end(); + newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION) + .handler(this.kfSessionHandler).end(); + newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION) + .handler(this.kfSessionHandler).end(); + + // 门店审核事件 + newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end(); + + // 自定义菜单事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end(); + + // 点击菜单连接事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end(); + + // 关注事件 + newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end(); + + // 取消关注事件 + newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end(); + + // 上报地理位置事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end(); + + // 接收地理位置消息 + newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end(); + + // 扫码事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end(); + + // 默认 + newRouter.rule().async(false).handler(this.msgHandler).end(); + + return newRouter; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java b/src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java new file mode 100644 index 0000000..5d222da --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java @@ -0,0 +1,35 @@ +package com.qs.serve.modules.wx.common.consts; + +/** + * 微信字段 + * @author YenHex + * @since 2022/3/7 + */ +public class WxStatusConst { + + /** wx */ + /** 应用类型【1->小程序;2->公众号】 */ + public static final int WxUser_AppType_1 = 1; + public static final int WxUser_AppType_2 = 2; + + /** 是否订阅【1->是;0->否;2->网页授权用户】 */ + public static final int WxUser_Subscribe_1 = 1; + public static final int WxUser_Subscribe_0 = 0; + public static final int WxUser_Subscribe_2 = 2; + + /** 应用类型【1->小程序;2->公众号 ;企业微信】 */ + public static final int WxApp_AppType_1 = 1; + public static final int WxApp_AppType_2 = 2; + public static final int WxApp_AppType_3 = 3; + + /** 是否第三方平台应用【1->是;0->否】 */ + public static final int WxApp_IsComponent_1 = 1; + public static final int WxApp_IsComponent_0 = 0; + + /** 【0->订阅号;1->由历史老帐号升级后的订阅号;2->服务号】 */ + public static final int WxApp_WeixinType_0 = 0; + public static final int WxApp_WeixinType_1 = 1; + public static final int WxApp_WeixinType_2 = 2; + + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java new file mode 100644 index 0000000..b2f32ad --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java @@ -0,0 +1,27 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class KfSessionHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + //TODO 对会话做处理 + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java new file mode 100644 index 0000000..c1c9520 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java @@ -0,0 +1,47 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import com.qs.serve.modules.wx.common.builder.mp.TextBuilder; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class LocationHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { + //TODO 接收处理用户发送的地理位置消息 + try { + String content = "感谢反馈,您的的地理位置已收到!"; + return new TextBuilder().build(content, wxMessage, null); + } catch (Exception e) { + log.error("位置消息接收处理失败", e); + return null; + } + } + + //上报地理位置事件 + log.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",wxMessage.getLatitude(), wxMessage.getLongitude(), wxMessage.getPrecision()); + + //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 + + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java new file mode 100644 index 0000000..c433c05 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java @@ -0,0 +1,32 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import com.qs.serve.common.util.JsonUtil; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class LogHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + log.info("\n接收到请求消息,内容:{}", JsonUtil.objectToJson(wxMessage)); + return null; + } + + + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java new file mode 100644 index 0000000..a4070fe --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java @@ -0,0 +1,37 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.EventType; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class MenuHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + String msg = String.format("type:%s, event:%s, key:%s", + wxMessage.getMsgType(), wxMessage.getEvent(), + wxMessage.getEventKey()); + if (EventType.VIEW.equals(wxMessage.getEvent())) { + return null; + } + + return WxMpXmlOutMessage.TEXT().content(msg) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java new file mode 100644 index 0000000..9ed90cd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java @@ -0,0 +1,54 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.modules.wx.common.builder.mp.TextBuilder; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class MsgHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + + if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { + //TODO 可以选择将消息保存到本地 + } + + //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服 + try { + if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服") + && weixinService.getKefuService().kfOnlineList() + .getKfOnlineList().size() > 0) { + return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE() + .fromUser(wxMessage.getToUser()) + .toUser(wxMessage.getFromUser()).build(); + } + } catch (WxErrorException e) { + e.printStackTrace(); + } + + //TODO 组装回复消息 + String content = "收到信息内容:" + JsonUtil.objectToJson(wxMessage); + + return new TextBuilder().build(content, wxMessage, weixinService); + + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java new file mode 100644 index 0000000..fe76188 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class NullHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java new file mode 100644 index 0000000..0015686 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java @@ -0,0 +1,27 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import java.util.Map; + +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import org.springframework.stereotype.Component; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class ScanHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, + WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { + // 扫码事件处理 + return null; + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java new file mode 100644 index 0000000..d6f5d7a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java @@ -0,0 +1,29 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + + + /** + * 门店审核事件处理 + * @author YenHex + * @since 2022-03-07 +*/ +@Component +public class StoreCheckNotifyHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + // TODO 处理门店审核事件 + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java new file mode 100644 index 0000000..4d0dc13 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java @@ -0,0 +1,72 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import java.util.Map; + +import com.qs.serve.modules.wx.common.builder.mp.TextBuilder; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import org.springframework.stereotype.Component; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.result.WxMpUser; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class SubscribeHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) throws WxErrorException { + + log.info("新关注用户 OPENID: " + wxMessage.getFromUser()); + // 获取微信用户基本信息 + try { + WxMpUser userWxInfo = weixinService.getUserService() + .userInfo(wxMessage.getFromUser(), null); + if (userWxInfo != null) { + // TODO 可以添加关注用户到本地数据库 + } + } catch (WxErrorException e) { + if (e.getError().getErrorCode() == 48001) { + log.info("该公众号没有获取用户信息权限!"); + } + } + WxMpXmlOutMessage responseResult = null; + try { + responseResult = this.handleSpecial(wxMessage); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + if (responseResult != null) { + return responseResult; + } + + try { + return new TextBuilder().build("感谢关注", wxMessage, weixinService); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + return null; + } + + /** + * 处理特殊请求,比如如果是扫码进来的,可以做相应处理 + */ + private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) + throws Exception { + //TODO + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java new file mode 100644 index 0000000..5ae0c72 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class UnsubscribeHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + String openId = wxMessage.getFromUser(); + log.info("取消关注用户 OPENID: " + openId); + // TODO 可以更新本地数据库为取消关注状态 + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java b/src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java new file mode 100644 index 0000000..4369ff3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java @@ -0,0 +1,19 @@ +package com.qs.serve.modules.wx.common.model; + +import java.lang.annotation.*; + +/** + * 微信发送模板参数 + * @author YenHex + * @since 2022-03-16 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface WxSmsProp { + + String keyword() default ""; + + String value() default ""; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java new file mode 100644 index 0000000..143e9d2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java @@ -0,0 +1,93 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.service.WxAppService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信应用 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +//@AllArgsConstructor +//@RestController +//@RequestMapping("wx/app") +public class WxAppController { + + private WxAppService wxAppService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('wx:app:query')") + public R> getList(WxApp param){ + PageUtil.startPage(); + List list = wxAppService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('wx:app:query')") + public R getById(@PathVariable("id") String id){ + WxApp wxApp = wxAppService.getById(id); + return R.ok(wxApp); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @PreAuthorize("hasRole('wx:app:update')") + public R updateById(@RequestBody @Valid WxApp param){ + boolean result = wxAppService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增微信应用 + * @param param + * @return + */ + @PostMapping("/save") + @PreAuthorize("hasRole('wx:app:insert')") + public R save(@RequestBody @Valid WxApp param){ + boolean result = wxAppService.save(param); + return R.isTrue(result); + } + + /** + * 删除微信应用 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('wx:app:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = wxAppService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushController.java new file mode 100644 index 0000000..29523d3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushController.java @@ -0,0 +1,343 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.service.SysAttachService; +import com.qs.serve.modules.sys.service.SysUserService; +import com.qs.serve.modules.wx.entity.*; +import com.qs.serve.modules.wx.entity.dto.sms.WxSmsNewForm; +import com.qs.serve.modules.wx.entity.vo.WxPushResultVo; +import com.qs.serve.modules.wx.mapper.WxFormPushMapper; +import com.qs.serve.modules.wx.service.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.wx.entity.bo.WxFormPushBo; + +import javax.validation.Valid; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 微信 表单推送 + * @author YenHex + * @since 2023-04-19 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("wx/formPush") +public class WxFormPushController { + + private WxFormPushMapper wxFormPushMapper; + private WxFormPushService wxFormPushService; + private WxFormPushUserService wxFormPushUserService; + private WxFormPushTypeService wxFormPushTypeService; + private WxUserService wxUserService; + private WxPushService wxPushService; + private WxAppService wxAppService; + private SysAttachService attachService; + private SysUserService sysUserService; + + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + public R> getPage(WxFormPush param){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(param); + PageUtil.startPage(); + lqw.orderByDesc(WxFormPush::getCreateTime); + List list = wxFormPushService.list(lqw); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.Verification, title = "表单推送", biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + WxFormPush wxFormPush = wxFormPushService.getById(id); + LambdaQueryWrapper userlqw = new LambdaQueryWrapper<>(); + userlqw.eq(WxFormPushUser::getFormPushId,wxFormPush.getId()); + List list = wxFormPushUserService.list(userlqw); + wxFormPush.setShowCompensateButton(0); + for (WxFormPushUser pushUser : list) { + if(pushUser.getPushStatus().equals(0)){ + wxFormPush.setShowCompensateButton(1); + break; + } + } + wxFormPush.setWxFormPushUserList(list); + if(CollectionUtil.isNotEmpty(wxFormPush.getAttachIds())){ + List attachIds = Arrays.asList(wxFormPush.getAttachIds()); + List attachList = attachService.listByIds(attachIds); + wxFormPush.setAttachList(attachList); + } + return R.ok(wxFormPush); + } + + + + /** + * 发布 + * @param param + * @return + */ + @PostMapping("/publishById") + @SysLog(module = SystemModule.Verification, title = "表单推送发布", biz = BizType.UPDATE) + public R publishById(@RequestBody WxFormPushBo param){ + String id = param.getId(); + WxFormPush entity = wxFormPushService.getById(id); + if(entity.getId().equals("1")){ + return R.error("已发布的消息不能再次发布"); + } + entity.setStatus("1"); + entity.setPublishTime(LocalDateTime.now()); + boolean result = wxFormPushService.updateById(entity); + LambdaQueryWrapper userlqw = new LambdaQueryWrapper<>(); + userlqw.eq(WxFormPushUser::getFormPushId,entity.getId()); + userlqw.eq(WxFormPushUser::getPushStatus,0); + List list = wxFormPushUserService.list(userlqw); + List userCodes = list.stream().map(WxFormPushUser::getUserCode).collect(Collectors.toList()); + if(userCodes.size()<1){ + return R.ok(); + } + WxApp app = wxAppService.getOne(new LambdaQueryWrapper<>(),false); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getAppId,app.getId()); + lqw.in(WxUser::getSysUserCode,userCodes); + List wxUserList = wxUserService.list(lqw); + Set wxUserIdSet = new HashSet<>(); + for (WxUser wxUser : wxUserList) { + if (wxUser.getOpenId().equals("0")) { + continue; + } + boolean exist = wxUserIdSet.stream().anyMatch(a->a.equals(wxUser.getOpenId())); + if(exist){ + continue; + }else { + wxUserIdSet.add(wxUser.getOpenId()); + } + WxSmsNewForm wxSmsNewForm = new WxSmsNewForm(); + wxSmsNewForm.setTitle(entity.getTitle()); + wxSmsNewForm.setUserName(wxUser.getEmpName()); + wxSmsNewForm.setBizType(entity.getBusinessType() == null ? "通知" : entity.getBusinessType()); + wxSmsNewForm.setBitTime(LocalDateTime.now().toString().replace("T", " ")); + wxSmsNewForm.setRemark(entity.getRemark()); + wxPushService.sendWxMsg(wxUser, "表单通知", wxSmsNewForm, true, entity.getId()); + } + return R.isTrue(result); + } + + /** + * 补偿通知 + * @param param + * @return + */ + @PostMapping("/compensate") + @SysLog(module = SystemModule.Verification, title = "表单推送补偿通知", biz = BizType.UPDATE) + public R compensate(@RequestBody WxFormPushBo param){ + String id = param.getId(); + List userIds = param.getUserIds(); + WxFormPush entity = wxFormPushService.getById(id); + if(entity.getId().equals("0")){ + return R.error("未发布"); + } + LambdaQueryWrapper userlqw = new LambdaQueryWrapper<>(); + userlqw.eq(WxFormPushUser::getFormPushId,entity.getId()); + if(CollectionUtil.isNotEmpty(userIds)) { + userlqw.in(WxFormPushUser::getUserId,userIds); + } + userlqw.eq(WxFormPushUser::getPushStatus,0); + List list = wxFormPushUserService.list(userlqw); + userIds = list.stream().map(WxFormPushUser::getUserId).collect(Collectors.toList()); + if(userIds.size()<1){ + return R.ok(); + } + WxApp app = wxAppService.getOne(new LambdaQueryWrapper<>(),false); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getAppId,app.getId()); + lqw.in(WxUser::getSysUserId,userIds); + List wxUserList = wxUserService.list(lqw); + Set wxUserIdSet = new HashSet<>(); + int successCount = 0; + for (WxFormPushUser pushUser : list) { + boolean pushOk = false; + for (WxUser wxUser : wxUserList) { + if (wxUser.getOpenId().equals("0")) { + continue; + } + boolean exist = wxUserIdSet.stream().anyMatch(a->a.equals(wxUser.getOpenId())); + if(exist){ + continue; + }else { + wxUserIdSet.add(wxUser.getOpenId()); + } + pushOk = true; + WxSmsNewForm wxSmsNewForm = new WxSmsNewForm(); + wxSmsNewForm.setTitle(entity.getTitle()); + wxSmsNewForm.setUserName(wxUser.getEmpName()); + wxSmsNewForm.setBizType(entity.getBusinessType() == null ? "通知" : entity.getBusinessType()); + wxSmsNewForm.setBitTime(LocalDateTime.now().toString().replace("T", " ")); + wxSmsNewForm.setRemark(entity.getRemark()); + wxPushService.sendWxMsg(wxUser, "表单通知", wxSmsNewForm, true, entity.getId()); + } + if(pushOk){ + successCount++; + WxFormPushUser upd_param = new WxFormPushUser(); + upd_param.setId(pushUser.getId()); + upd_param.setPushStatus(1); + wxFormPushUserService.updateById(upd_param); + } + } + return R.ok("成功通知数:"+successCount); + } + + /** + * 撤消 + * @param param + * @return + */ + @PostMapping("/unPublishById") + @SysLog(module = SystemModule.Verification, title = "撤消表单推送", biz = BizType.UPDATE) + public R unPublishById(@RequestBody WxFormPushBo param){ + String id = param.getId(); + WxFormPush entity = wxFormPushService.getById(id); + entity.setStatus("0"); + boolean result = wxFormPushService.updateById(entity); + return R.isTrue(result); + } + + /** + * 新增或保存 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.Verification, title = "表单推送", biz = BizType.INSERT) + public R saveOrUpdate(@RequestBody @Valid WxFormPushBo param){ + WxFormPush entity = CopierUtil.copy(param,new WxFormPush()); + entity.setPreNotifyStatus(param.getPreNotifyTime()==null?0:1); + WxFormPushType pushType = null; + if(param.getTypeId()!=null){ + pushType = wxFormPushTypeService.getById(param.getTypeId()); + entity.setTypeCode(pushType.getCode()); + entity.setTypeName(pushType.getTitle()); + }else{ + entity.setTypeId("0"); + entity.setTypeCode("默认"); + entity.setTypeName("默认分类"); + } + entity.setPreNotifyStatus(entity.getPreNotifyTime()==null?0:1); + if(null==entity.getId()) { + entity.setPublishTime(LocalDateTime.now()); + wxFormPushService.save(entity); + }else{ + WxFormPush ori_entity = wxFormPushService.getById(entity.getId()); + if(ori_entity.getStatus().equals("1")){ + return R.error("已发布的消息不能更新"); + } + if(entity.getPreNotifyTime()==null){ + wxFormPushMapper.updateSetNotifyTimeNull(entity.getId()); + } + wxFormPushService.updateById(entity); + } + //保存推送人员 + List userIds = param.getUserIds().stream().distinct().collect(Collectors.toList()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + WxApp app = wxAppService.getOne(new LambdaQueryWrapper<>(),false); + lqw.eq(WxUser::getAppId,app.getId()); + lqw.in(WxUser::getSysUserId,userIds); + List wxUserList = wxUserService.list(lqw); + List pushUserList = new ArrayList<>(); + Set wxUserIdSet = new HashSet<>(); + List sysUserList = sysUserService.listByIds(userIds); + for (SysUser sysUser : sysUserList) { + int pushOk = 0; + for (WxUser wxUser : wxUserList) { + if(wxUser.getSysUserId().equals(sysUser.getId())){ + if (wxUser.getOpenId().equals("0")) { + continue; + } + boolean exist = wxUserIdSet.stream().anyMatch(a->a.equals(wxUser.getOpenId())); + if(exist){ + continue; + }else { + wxUserIdSet.add(wxUser.getOpenId()); + } + pushOk = 1; + WxSmsNewForm wxSmsNewForm = new WxSmsNewForm(); + wxSmsNewForm.setTitle(param.getTitle()); + wxSmsNewForm.setUserName(wxUser.getEmpName()); + wxSmsNewForm.setBizType(param.getBusinessType()==null?"通知":param.getBusinessType()); + wxSmsNewForm.setBitTime(LocalDateTime.now().toString().replace("T"," ")); + wxSmsNewForm.setRemark(param.getRemark()); + if(param.getStatus().equals("1")) { + wxPushService.sendWxMsg(wxUser, "表单通知", wxSmsNewForm, true, entity.getId()); + } + } + } + WxFormPushUser pushUser = new WxFormPushUser(); + pushUser.setFormPushId(entity.getId()); + pushUser.setFormTitle(entity.getTitle()); + pushUser.setPushStatus(pushOk); + pushUser.setUserId(sysUser.getId()); + pushUser.setUserCode(sysUser.getCode()); + pushUser.setUserName(sysUser.getName()); + pushUser.setTypeId(pushType.getId()); + pushUser.setTypeCode(pushType.getCode()); + pushUser.setTypeName(pushType.getTitle()); + pushUserList.add(pushUser); + } + if(null==entity.getId()) { + wxFormPushUserService.saveBatch(pushUserList); + }else{ + LambdaQueryWrapper dellqw = new LambdaQueryWrapper<>(); + dellqw.eq(WxFormPushUser::getFormPushId,entity.getId()); + wxFormPushUserService.remove(dellqw); + wxFormPushUserService.saveBatch(pushUserList); + } + return R.ok(entity); + } + + /** + * 删除 + * @param ids + * @return + */ + @DeleteMapping("/deleteById/{ids}") + @SysLog(module = SystemModule.Verification, title = "表单推送", biz = BizType.DELETE) + public R deleteById(@PathVariable("ids") String ids){ + List idsLong = StringUtils.splitIdString(ids); + List list = wxFormPushService.listByIds(idsLong); + for(WxFormPush formPush:list){ + if(formPush.getStatus().equals("1")){ + return R.error("已发布的消息不能删除"); + } + } + boolean result = wxFormPushService.removeByIds(idsLong); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushTypeController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushTypeController.java new file mode 100644 index 0000000..46aacb6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushTypeController.java @@ -0,0 +1,131 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.wx.entity.WxFormPush; +import com.qs.serve.modules.wx.service.WxFormPushService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.wx.entity.so.WxFormPushTypeSo; +import com.qs.serve.modules.wx.entity.bo.WxFormPushTypeBo; +import com.qs.serve.modules.wx.entity.WxFormPushType; +import com.qs.serve.modules.wx.service.WxFormPushTypeService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信 表单类型 + * @author YenHex + * @since 2023-04-24 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("wx/formPushType") +public class WxFormPushTypeController { + + private WxFormPushTypeService wxFormPushTypeService; + private WxFormPushService wxFormPushService; + + + /** + * 列表 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(WxFormPushTypeSo param){ + WxFormPushType entity = CopierUtil.copy(param,new WxFormPushType()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + List list = wxFormPushTypeService.list(lqw); + return R.ok(list); + } + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + public R> getPage(WxFormPushTypeSo param){ + WxFormPushType entity = CopierUtil.copy(param,new WxFormPushType()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + PageUtil.startPage(); + List list = wxFormPushTypeService.list(lqw); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.Verification, title = "表单类型", biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + WxFormPushType wxFormPushType = wxFormPushTypeService.getById(id); + return R.ok(wxFormPushType); + } + + + + /** + * 更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.Verification, title = "表单类型", biz = BizType.UPDATE) + public R updateById(@RequestBody @Valid WxFormPushTypeBo param){ + if(param.getId().equals("0")){ + return R.error("默认分类无法删除"); + } + WxFormPushType entity = CopierUtil.copy(param,new WxFormPushType()); + boolean result = wxFormPushTypeService.updateById(entity); + return R.isTrue(result); + } + + /** + * 新增 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.Verification, title = "表单类型", biz = BizType.INSERT) + public R save(@RequestBody @Valid WxFormPushTypeBo param){ + WxFormPushType entity = CopierUtil.copy(param,new WxFormPushType()); + boolean result = wxFormPushTypeService.save(entity); + return R.isTrue(result); + } + + /** + * 删除 + * @param ids + * @return + */ + @DeleteMapping("/deleteById/{ids}") + @SysLog(module = SystemModule.Verification, title = "表单类型", biz = BizType.DELETE) + public R deleteById(@PathVariable("ids") String ids){ + List idsString = StringUtils.splitIdString(ids); + for (String id : idsString) { + if(id.equals("0")){ + return R.error("默认分类无法删除"); + } + } + boolean result = wxFormPushTypeService.removeByIds(idsString); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushUserController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushUserController.java new file mode 100644 index 0000000..bc6d5e4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxFormPushUserController.java @@ -0,0 +1,119 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.StringUtils; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.wx.entity.so.WxFormPushUserSo; +import com.qs.serve.modules.wx.entity.bo.WxFormPushUserBo; +import com.qs.serve.modules.wx.entity.WxFormPushUser; +import com.qs.serve.modules.wx.service.WxFormPushUserService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信 表单推送用户 + * @author YenHex + * @since 2023-04-24 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("wx/formPushUser") +public class WxFormPushUserController { + + private WxFormPushUserService wxFormPushUserService; + + /** + * 列表 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(WxFormPushUserSo param){ + WxFormPushUser entity = CopierUtil.copy(param,new WxFormPushUser()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + List list = wxFormPushUserService.list(lqw); + return R.ok(list); + } + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + public R> getPage(WxFormPushUserSo param){ + WxFormPushUser entity = CopierUtil.copy(param,new WxFormPushUser()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(entity); + PageUtil.startPage(); + List list = wxFormPushUserService.list(lqw); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + //@GetMapping("/getById/{id}") + @SysLog(module = SystemModule.Verification, title = "表单推送用户", biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + WxFormPushUser wxFormPushUser = wxFormPushUserService.getById(id); + return R.ok(wxFormPushUser); + } + + + + /** + * 更新 + * @param param + * @return + */ + //@PostMapping("/updateById") + @SysLog(module = SystemModule.Verification, title = "表单推送用户", biz = BizType.UPDATE) + public R updateById(@RequestBody @Valid WxFormPushUserBo param){ + WxFormPushUser entity = CopierUtil.copy(param,new WxFormPushUser()); + boolean result = wxFormPushUserService.updateById(entity); + return R.isTrue(result); + } + + /** + * 新增 + * @param param + * @return + */ + //@PostMapping("/save") + @SysLog(module = SystemModule.Verification, title = "表单推送用户", biz = BizType.INSERT) + public R save(@RequestBody @Valid WxFormPushUserBo param){ + WxFormPushUser entity = CopierUtil.copy(param,new WxFormPushUser()); + boolean result = wxFormPushUserService.save(entity); + return R.isTrue(result); + } + + /** + * 删除 + * @param ids + * @return + */ + @DeleteMapping("/deleteById/{ids}") + @SysLog(module = SystemModule.Verification, title = "表单推送用户", biz = BizType.DELETE) + public R deleteById(@PathVariable("ids") String ids){ + List idsLong = StringUtils.splitIdLong(ids); + boolean result = wxFormPushUserService.removeByIds(idsLong); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java new file mode 100644 index 0000000..68316df --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java @@ -0,0 +1,93 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; +import com.qs.serve.modules.wx.service.WxTemplateMsgService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信模板/订阅消息 后台接口 + * @author YenHex + * @since 2022-03-23 + */ +@Slf4j +//@AllArgsConstructor +//@RestController +//@RequestMapping("wx/templateMsg") +public class WxTemplateMsgController { + + private WxTemplateMsgService wxTemplateMsgService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('wx:templateMsg:query')") + public R> getPage(WxTemplateMsg param){ + PageUtil.startPage(); + List list = wxTemplateMsgService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('wx:templateMsg:query')") + public R getById(@PathVariable("id") String id){ + WxTemplateMsg wxTemplateMsg = wxTemplateMsgService.getById(id); + return R.ok(wxTemplateMsg); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @PreAuthorize("hasRole('wx:templateMsg:update')") + public R updateById(@RequestBody @Valid WxTemplateMsg param){ + boolean result = wxTemplateMsgService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增微信模板/订阅消息 + * @param param + * @return + */ + @PostMapping("/save") + @PreAuthorize("hasRole('wx:templateMsg:insert')") + public R save(@RequestBody @Valid WxTemplateMsg param){ + boolean result = wxTemplateMsgService.save(param); + return R.isTrue(result); + } + + /** + * 删除微信模板/订阅消息 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('wx:templateMsg:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = wxTemplateMsgService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java new file mode 100644 index 0000000..9f997ab --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java @@ -0,0 +1,155 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.service.SysUserService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxUserBindBo; +import com.qs.serve.modules.wx.entity.dto.WxUserRmBindBo; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信用户 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("wx/user") +public class WxUserController { + + private WxUserService wxUserService; + private SysUserService sysUserService; + private RedisService redisService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + public R> getList(WxUser param){ + PageUtil.startPage(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(param); + //lqw.eq(WxUser::getFirstFlag,1); + if(param.getNotBindFlag()!=null&¶m.getNotBindFlag().equals(1)){ + lqw.isNull(WxUser::getPhone).or().eq(WxUser::getPhone,""); + }else if (param.getNotBindFlag()!=null&¶m.getNotBindFlag().equals(0)){ + lqw.isNotNull(WxUser::getPhone); + lqw.ne(WxUser::getPhone,""); + } + List list = wxUserService.list(lqw); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + public R getById(@PathVariable("id") String id){ + WxUser wxUser = wxUserService.getById(id); + return R.ok(wxUser); + } + + /** + * 绑定用户 + * @param param + * @return + */ + @PostMapping("/bind") + public R bind(@RequestBody @Valid WxUserBindBo param){ + WxUser wxUser = wxUserService.getById(param.getWxUserId()); + if(StringUtils.hasText(wxUser.getSysUserId())&&!wxUser.getSysUserId().equals("0")){ + return R.error("该微信用户已被绑定"); + } + SysUser sysUser = sysUserService.getById(param.getSysUserId()); + if(sysUser.getMobile()==null||sysUser.getMobile().length()<4){ + return R.error("用户未绑定手机号"); + } + if(!StringUtils.hasText(wxUser.getUnionId())){ + WxUser updVo = new WxUser(); + updVo.setId(wxUser.getId()); + updVo.setSysUserId(sysUser.getId()); + updVo.setSysUserCode(sysUser.getCode()); + updVo.setEmpName(sysUser.getName()); + updVo.setPhone(sysUser.getMobile()); + wxUserService.updateById(updVo); + }else { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getUnionId,wxUser.getUnionId()); + WxUser updVo = new WxUser(); + updVo.setSysUserId(sysUser.getId()); + updVo.setSysUserCode(sysUser.getCode()); + updVo.setEmpName(sysUser.getName()); + updVo.setPhone(sysUser.getMobile()); + wxUserService.update(updVo,lqw); + } + return R.ok(); + } + + /** + * 移除绑定 + * @param param + * @return + */ + @PostMapping("/rmBind") + public R rmBind(@RequestBody @Valid WxUserRmBindBo param){ + String sysUserId = null; + String wxUserId = null; + if(StringUtils.hasText(param.getWxUserId())){ + WxUser wxUser = wxUserService.getById(param.getWxUserId()); + sysUserId = wxUser.getSysUserId(); + wxUserId = wxUser.getId(); + if(!StringUtils.hasText(wxUser.getUnionId())){ + wxUser.setSysUserId("0"); + wxUser.setSysUserCode(""); + wxUser.setEmpName(wxUser.getNickName()); + wxUser.setPhone(""); + wxUserService.updateById(wxUser); + }else { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getUnionId,wxUser.getUnionId()); + WxUser updVo = new WxUser(); + updVo.setSysUserId("0"); + wxUser.setSysUserCode(""); + updVo.setEmpName(wxUser.getNickName()); + updVo.setPhone(""); + wxUserService.update(updVo,lqw); + } + }else if (StringUtils.hasText(param.getSysUserId())){ + sysUserId = param.getSysUserId(); + SysUser sysUser = sysUserService.getById(param.getSysUserId()); + List wxUserList = wxUserService.getBySysUserId(sysUser.getId()); + for (WxUser wxUser : wxUserList) { + wxUser.setSysUserId("0"); + wxUser.setSysUserCode(""); + wxUser.setEmpName(wxUser.getNickName()); + wxUser.setPhone(""); + wxUserService.updateById(wxUser); + } + } + String client = "wx_app"; + String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,sysUserId); + redisService.remove(redisKey); + return R.ok(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/my/WxFormPushMyController.java b/src/main/java/com/qs/serve/modules/wx/controller/my/WxFormPushMyController.java new file mode 100644 index 0000000..d9eb9f9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/my/WxFormPushMyController.java @@ -0,0 +1,119 @@ +package com.qs.serve.modules.wx.controller.my; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.service.SysAttachService; +import com.qs.serve.modules.wx.entity.WxFormPush; +import com.qs.serve.modules.wx.entity.WxFormPushUser; +import com.qs.serve.modules.wx.entity.bo.WxFormPushBo; +import com.qs.serve.modules.wx.mapper.WxFormPushMapper; +import com.qs.serve.modules.wx.service.WxFormPushService; +import com.qs.serve.modules.wx.service.WxFormPushUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.*; + +/** + * 微信 表单推送(我的) + * @author YenHex + * @since 2023-04-19 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("my/formPush") +public class WxFormPushMyController { + + private WxFormPushService wxFormPushService; + private WxFormPushMapper wxFormPushMapper; + private SysAttachService attachService; + private WxFormPushUserService wxFormPushUserService; + + /** + * 列表 + * @param param + * @return + */ + @GetMapping("/page") + public R> getList(WxFormPush param){ +// lqw.eq(WxFormPushUser::getUserId,AuthContextUtils.getSysUserId()); +// List list = wxFormPushUserService.list(lqw); +// List result = new ArrayList<>(); +// for (WxFormPushUser pushUser : list) { +// WxFormPush formPush = wxFormPushService.getById(pushUser.getFormPushId()); +// formPush.setReadFlag(pushUser.getReadFlag()); +// result.add(formPush); +// } + PageUtil.startPage(); + param.setQueryUserId(AuthContextUtils.getSysUserId()); + param.setStatus("1"); + List formPushUsers = wxFormPushMapper.selectUserFormPushList(param); + return R.byPageHelperList(formPushUsers); + } + + /** + * 小红点统计(未读数量) + * @return + */ + @GetMapping("/getCounter") + public R getPage(){ + WxFormPush param = new WxFormPush(); + param.setQueryUserId(AuthContextUtils.getSysUserId()); + param.setStatus("1"); + param.setReadFlag(0); + List formPushUsers = wxFormPushMapper.selectUserFormPushList(param); + Map map = new HashMap<>(); + map.put("unFinished",formPushUsers.size()); + return R.ok(map,"ok"); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.Verification, title = "表单推送", biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + LambdaQueryWrapper lqw2 = new LambdaQueryWrapper<>(); + lqw2.eq(WxFormPushUser::getFormPushId,id); + lqw2.eq(WxFormPushUser::getUserId, AuthContextUtils.getSysUserId()); + if(wxFormPushUserService.count(lqw2)<1){ + return R.error("表单已撤销"); + } + WxFormPush wxFormPush = wxFormPushService.getById(id); + if(wxFormPush.getStatus().equals("0")){ + //未发布不能查询 + wxFormPush.setId(null); + wxFormPush.setTitle(null); + wxFormPush.setFormContext(null); + wxFormPush.setFormContextValue(null); + return R.ok(wxFormPush); + } + if(CollectionUtil.isNotEmpty(wxFormPush.getAttachIds())){ + List attachIds = Arrays.asList(wxFormPush.getAttachIds()); + List attachList = attachService.listByIds(attachIds); + wxFormPush.setAttachList(attachList); + } + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxFormPushUser::getFormPushId,id); + lqw.eq(WxFormPushUser::getUserId, AuthContextUtils.getSysUserId()); + lqw.ne(WxFormPushUser::getReadFlag,1); + WxFormPushUser pushUser = new WxFormPushUser(); + pushUser.setReadFlag(1); + wxFormPushUserService.update(pushUser,lqw); + return R.ok(wxFormPush); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxApp.java b/src/main/java/com/qs/serve/modules/wx/entity/WxApp.java new file mode 100644 index 0000000..978c310 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxApp.java @@ -0,0 +1,115 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 微信应用 实体类 + * @author YenHex + * @since 2022-03-07 + */ +@Data +@TableName("wx_app") +public class WxApp implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 应用ID */ + @TableId(type = IdType.INPUT) + private String id; + + /** 机构ID */ + @NotNull(message = "机构ID不能为空") + private String organId; + + /** 微信原始标识 */ + @NotNull(message = "微信原始标识不能为空") + private String weixinSign; + + /** 应用类型【1->小程序;2->公众号;3->企业公众号】 */ + private Integer appType; + + /** 应用密钥 */ + private String secret; + + /** token */ + private String token; + + /** EncodingAESKey */ + private String aesKey; + + /** 微信号名称 */ + private String name; + + /** 是否第三方平台应用【1->是;0->否】 */ + private Integer isComponent; + + /** 【0->订阅号;1->由历史老帐号升级后的订阅号;2->服务号】 */ + private Integer weixinType; + + /** 公众号微信号 */ + private String weixinHao; + + /** 认证类型 */ + private Integer verifyType; + + /** logo */ + private String logo; + + /** 二维码 */ + private String qrCode; + + /** 主体名称 */ + private String principalName; + + /** 微社区URL */ + private String community; + + /** 备注信息 */ + private String remarks; + + /** 绑定的会员卡ID */ + private String vipCardId; + + /** 微信支付商户号 */ + private String mchId; + + /** 微信支付商户密钥 */ + private String mchKey; + + /** p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头) */ + private String keyPath; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxFormPush.java b/src/main/java/com/qs/serve/modules/wx/entity/WxFormPush.java new file mode 100644 index 0000000..32e7619 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxFormPush.java @@ -0,0 +1,182 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.qs.serve.common.framework.mybatis.handler.meta.SplitStringTypeHandler; +import lombok.Data; +import org.apache.ibatis.type.JdbcType; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单推送 实体类 + * @author YenHex + * @since 2023-04-24 + */ +@Data +@TableName(value = "wx_form_push",autoResultMap = true) +public class WxFormPush implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 分类id */ + @Length(max = 36,message = "分类id长度不能超过36字") + private String typeId; + + /** 分类编码 */ + @Length(max = 255,message = "分类编码长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String typeCode; + + /** 分类 */ + @Length(max = 255,message = "分类长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String typeName; + + /** 业务类型,默认:通知 */ + @TableField(condition = SqlCondition.LIKE) + private String businessType; + /** 标题 */ + @Length(max = 255,message = "标题长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String title; + +// @Length(message = "是否发布,保存并发布->1,保存草稿->0") + private String status; + + /** 表单内容 */ + private String formContext; + + /** 表单值 */ + private String formContextValue; + + /** 备注 */ + @Length(max = 600,message = "备注长度不能超过600字") + private String remark; + + /** 预通知标识:0->无通知;1->未通知;2->已通知 */ + private Integer preNotifyStatus; + + /** 生效开始时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime effectiveStartTime; + + /** 生效结束时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime effectiveEndTime; + + /** 预通知时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime preNotifyTime; + + /** 发布时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime publishTime; + + /** 附件ids */ + @TableField(typeHandler = SplitStringTypeHandler.class,jdbcType= JdbcType.VARCHAR) + private String[] attachIds; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + /** 是否已读 */ + @TableField(exist = false) + private Integer readFlag; + + /** 查询的用户id */ + @TableField(exist = false) + private String queryUserId; + + @TableField(exist = false) + private String formTitle; + + /** 查询的用户id */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate queryStartTime; + + /** 查询的用户id */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate queryEndTime; + + + @TableField(exist = false) + private List wxFormPushUserList; + + /** 附件 */ + @TableField(exist = false) + private List attachList; + + /** 显示补偿按钮 */ + @TableField(exist = false) + private Integer showCompensateButton; + + public static WxFormPush toNewObject(WxFormPush source){ + WxFormPush formPush = new WxFormPush(); + formPush.setId(source.getId()); + formPush.setTypeId(source.getTypeId()); + formPush.setTypeCode(source.getTypeCode()); + formPush.setTypeName(source.getTypeName()); + formPush.setTitle(source.getTitle()); + formPush.setFormContext(source.getFormContext()); + formPush.setFormContextValue(source.getFormContextValue()); + formPush.setRemark(source.getRemark()); + formPush.setCreateTime(source.getCreateTime()); + formPush.setUpdateTime(source.getUpdateTime()); + formPush.setTenantId(source.getTenantId()); + formPush.setCreateBy(source.getCreateBy()); + formPush.setUpdateBy(source.getUpdateBy()); + formPush.setDelFlag(source.getDelFlag()); + return formPush; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxFormPushType.java b/src/main/java/com/qs/serve/modules/wx/entity/WxFormPushType.java new file mode 100644 index 0000000..208ecaa --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxFormPushType.java @@ -0,0 +1,95 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单类型 实体类 + * @author YenHex + * @since 2023-04-24 + */ +@Data +@TableName("wx_form_push_type") +public class WxFormPushType implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 编码 */ + @Length(max = 255,message = "编码长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String code; + + /** 标题 */ + @Length(max = 255,message = "标题长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String title; + + /** 备注 */ + @Length(max = 600,message = "备注长度不能超过600字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + + public static WxFormPushType toNewObject(WxFormPushType source){ + WxFormPushType formPushType = new WxFormPushType(); + formPushType.setId(source.getId()); + formPushType.setCode(source.getCode()); + formPushType.setTitle(source.getTitle()); + formPushType.setRemark(source.getRemark()); + formPushType.setCreateTime(source.getCreateTime()); + formPushType.setUpdateTime(source.getUpdateTime()); + formPushType.setTenantId(source.getTenantId()); + formPushType.setCreateBy(source.getCreateBy()); + formPushType.setUpdateBy(source.getUpdateBy()); + formPushType.setDelFlag(source.getDelFlag()); + return formPushType; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxFormPushUser.java b/src/main/java/com/qs/serve/modules/wx/entity/WxFormPushUser.java new file mode 100644 index 0000000..bb022cb --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxFormPushUser.java @@ -0,0 +1,132 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单推送用户 实体类 + * @author YenHex + * @since 2023-04-24 + */ +@Data +@TableName("wx_form_push_user") +public class WxFormPushUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 推送id */ + @Length(max = 36,message = "推送id长度不能超过36字") + private String formPushId; + + @TableField(condition = SqlCondition.LIKE) + private String formTitle; + + /** 推送状态 0-N,1-Y */ + private Integer pushStatus; + + /** 用户id */ + @Length(max = 64,message = "用户id长度不能超过64字") + private String userId; + + /** 用户编码 */ + @Length(max = 255,message = "用户编码长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String userCode; + + /** 用户名称 */ + @Length(max = 255,message = "用户名称长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String userName; + + /** 是否已读 */ + private Integer readFlag; + + /** 备注 */ + @Length(max = 600,message = "备注长度不能超过600字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + /** 分类id */ + @Length(max = 36,message = "分类id长度不能超过36字") + private String typeId; + + /** 分类编码 */ + @Length(max = 255,message = "分类编码长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String typeCode; + + /** 分类 */ + @Length(max = 255,message = "分类长度不能超过255字") + @TableField(condition = SqlCondition.LIKE) + private String typeName; + + + public static WxFormPushUser toNewObject(WxFormPushUser source){ + WxFormPushUser formPushUser = new WxFormPushUser(); + formPushUser.setId(source.getId()); + formPushUser.setFormPushId(source.getFormPushId()); + formPushUser.setUserId(source.getUserId()); + formPushUser.setUserCode(source.getUserCode()); + formPushUser.setUserName(source.getUserName()); + formPushUser.setReadFlag(source.getReadFlag()); + formPushUser.setRemark(source.getRemark()); + formPushUser.setCreateTime(source.getCreateTime()); + formPushUser.setUpdateTime(source.getUpdateTime()); + formPushUser.setTenantId(source.getTenantId()); + formPushUser.setCreateBy(source.getCreateBy()); + formPushUser.setUpdateBy(source.getUpdateBy()); + formPushUser.setDelFlag(source.getDelFlag()); + formPushUser.setTypeId(source.getTypeId()); + formPushUser.setTypeCode(source.getTypeCode()); + formPushUser.setTypeName(source.getTypeName()); + return formPushUser; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java b/src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java new file mode 100644 index 0000000..83df80b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java @@ -0,0 +1,73 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 微信模板/订阅消息 实体类 + * @author YenHex + * @since 2022-03-23 + */ +@Data +@TableName("wx_template_msg") +public class WxTemplateMsg implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键 */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 微信应用id */ + @NotNull(message = "微信应用id不能为空") + private String appId; + + /** 模板ID */ + @NotNull(message = "模板ID不能为空") + private String templateId; + + /** 模版标题 */ + @NotNull(message = "模版标题不能为空") + private String title; + + /** 跳转地址 */ + private String jumpUrl; + + /** 是否启用 */ + private Integer enable; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxUser.java b/src/main/java/com/qs/serve/modules/wx/entity/WxUser.java new file mode 100644 index 0000000..d97e775 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxUser.java @@ -0,0 +1,153 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 微信用户 实体类 + * @author YenHex + * @since 2022-03-07 + */ +@Data +@TableName("wx_user") +public class WxUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键 */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 公众号配置ID、小程序AppID */ + @NotNull(message = "公众号配置ID、小程序AppID不能为空") + private String appId; + + private String sysUserId; + private String sysUserCode; + + /** 应用类型【1->小程序;2->公众号】 */ + private Integer appType; + + /** 是否订阅【1->是;0->否;2->网页授权用户】 */ + private Integer subscribe; + + /** 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENEPROFILE LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_OTHERS 其他 */ + private String subscribeScene; + + /** 关注时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime subscribeTime; + + /** 关注次数 */ + private Integer subscribeNum; + + /** 取消关注时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime cancelSubscribeTime; + + /** 用户标识 */ + @NotNull(message = "用户标识不能为空") + private String openId; + + /** wx昵称 */ + @TableField(condition = SqlCondition.LIKE) + private String nickName; + + /** 员工昵称 */ + @TableField(condition = SqlCondition.LIKE) + private String empName; + + /** 性别(1:男,2:女,0:未知) */ + private String sex; + + /** 所在城市 */ + private String city; + + /** 所在国家 */ + private String country; + + /** 所在省份 */ + private String province; + + /** 手机号码 */ + @TableField(condition = SqlCondition.LIKE) + private String phone; + + /** 用户语言 */ + private String language; + + /** 头像 */ + private String headimgUrl; + + /** union_id */ + private String unionId; + + /** 用户组 */ + private String groupId; + + /** 标签列表 */ + private String tagidList; + + /** 二维码扫码场景 */ + private String qrSceneStr; + + /** 地理位置纬度 */ + private Double latitude; + + /** 地理位置经度 */ + private Double longitude; + + /** 地理位置精度 */ + private Double precisionVal; + + /** 会话密钥 */ + private String sessionKey; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @JsonIgnore + private Integer firstFlag; + + /** + * 为绑定标识,当值=1表未绑定用户 + */ + @TableField(exist = false) + private Integer notBindFlag; + + @TableField(exist = false) + private Object sysUserInfo; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushBo.java b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushBo.java new file mode 100644 index 0000000..66e53a0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushBo.java @@ -0,0 +1,72 @@ +package com.qs.serve.modules.wx.entity.bo; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +/** + * 表单推送 实体类 + * @author YenHex + * @since 2023-04-19 + */ +@Data +public class WxFormPushBo implements Serializable { + + private String id; + + @NotNull(message = "分类Id不能为空") + private String typeId; + /** 推送分类编码 */ + + /** 标题 */ + @NotNull(message = "标题不能为空") + private String title; + + /** 表单内容 */ + @NotNull(message = "表单内容不能为空") + private String formContext; + + /** 业务类型,默认:通知 */ + private String businessType; + + /** 表单值 */ + private String formContextValue; + + /** 备注 */ + private String remark; + + /** 工号列表 */ + @NotNull(message = "人员ID不能为空") + private List userIds; + + /** 是否发布,保存并发布->1,保存草稿->0 */ + @NotNull(message = "状态不能为空") + private String status; + + /** 附件ids */ + private String[] attachIds; + + /** 预通知时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime preNotifyTime; + + /** 生效开始时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime effectiveStartTime; + + /** 生效结束时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime effectiveEndTime; +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushThirdBo.java b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushThirdBo.java new file mode 100644 index 0000000..8040401 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushThirdBo.java @@ -0,0 +1,51 @@ +package com.qs.serve.modules.wx.entity.bo; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.List; + +/** + * 表单推送 实体类 + * @author YenHex + * @since 2023-04-19 + */ +@Data +public class WxFormPushThirdBo implements Serializable { + + private String id; + /** APPID */ + @NotNull(message = "appId不能为空") + private String appId; + + private String typeId; + /** 推送分类编码 */ + private String typeCode; + + /** 标题 */ + @NotNull(message = "标题不能为空") + private String title; + + /** 表单内容 */ + @NotNull(message = "表单内容不能为空") + private String formContext; + + /** 业务类型,默认:通知 */ + private String businessType; + + /** 表单值 */ + private String formContextValue; + + /** 备注 */ + private String remark; + + /** 工号列表 */ + @NotNull(message = "工号列表不能为空") + private List userCodes; + + @NotNull(message = "是否发布,保存并发布->1,保存草稿->0") + private String status; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushTypeBo.java b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushTypeBo.java new file mode 100644 index 0000000..19696c0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushTypeBo.java @@ -0,0 +1,44 @@ +package com.qs.serve.modules.wx.entity.bo; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单类型 Bo + * @author YenHex + * @since 2023-04-24 + */ +@Data +public class WxFormPushTypeBo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + private String id; + + /** 编码 */ + @Length(max = 255,message = "编码长度不能超过255字") + private String code; + + /** 标题 */ + @Length(max = 255,message = "标题长度不能超过255字") + private String title; + + /** 备注 */ + @Length(max = 600,message = "备注长度不能超过600字") + private String remark; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushUserBo.java b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushUserBo.java new file mode 100644 index 0000000..dd73c24 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/bo/WxFormPushUserBo.java @@ -0,0 +1,91 @@ +package com.qs.serve.modules.wx.entity.bo; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单推送用户 Bo + * @author YenHex + * @since 2023-04-24 + */ +@Data +public class WxFormPushUserBo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + private Long id; + + /** 推送id */ + @Length(max = 36,message = "推送id长度不能超过36字") + private String formPushId; + + /** 用户id */ + @Length(max = 64,message = "用户id长度不能超过64字") + private String userId; + + /** 用户编码 */ + @Length(max = 255,message = "用户编码长度不能超过255字") + private String userCode; + + /** 用户名称 */ + @Length(max = 255,message = "用户名称长度不能超过255字") + private String userName; + + /** 是否已读 */ + private Integer readFlag; + + /** 备注 */ + @Length(max = 600,message = "备注长度不能超过600字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建人 */ + private String createBy; + + /** 更新人 */ + private String updateBy; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + /** 分类id */ + @Length(max = 36,message = "分类id长度不能超过36字") + private String typeId; + + /** 分类编码 */ + @Length(max = 255,message = "分类编码长度不能超过255字") + private String typeCode; + + /** 分类 */ + @Length(max = 255,message = "分类长度不能超过255字") + private String typeName; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java new file mode 100644 index 0000000..037cb20 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java @@ -0,0 +1,11 @@ +package com.qs.serve.modules.wx.entity.dto; + +/** + * @author YenHex + * @since 2022/7/25 + */ +public abstract class SmsBaseDto { + + + +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java new file mode 100644 index 0000000..761a402 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java @@ -0,0 +1,17 @@ +package com.qs.serve.modules.wx.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Data +public class WxLoginUser { + + @NotNull + private String code; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java new file mode 100644 index 0000000..b3b3c05 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.wx.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/11 + */ +@Data +public class WxPhoneBindParam { + + @NotNull + private String phone; + + @NotNull + private String code; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/WxUserBindBo.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxUserBindBo.java new file mode 100644 index 0000000..9a511ed --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxUserBindBo.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.wx.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/9/26 + */ +@Data +public class WxUserBindBo { + + /** + * 微信用户ID + */ + @NotNull + private String wxUserId; + + /** + * 人员用户ID + */ + @NotNull + private String sysUserId; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/WxUserRmBindBo.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxUserRmBindBo.java new file mode 100644 index 0000000..fe12d92 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxUserRmBindBo.java @@ -0,0 +1,24 @@ +package com.qs.serve.modules.wx.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/9/26 + */ +@Data +public class WxUserRmBindBo { + + /** + * 微信用户ID(其一不能为空) + */ + private String wxUserId; + + /** + * 人员用户ID(其一不能为空) + */ + private String sysUserId; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/sms/WxSmsNewForm.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/sms/WxSmsNewForm.java new file mode 100644 index 0000000..ff53a21 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/sms/WxSmsNewForm.java @@ -0,0 +1,43 @@ +package com.qs.serve.modules.wx.entity.dto.sms; + +import com.qs.serve.modules.wx.common.model.WxSmsProp; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +/** + * @author YenHex + * @since 2022/9/21 + */ +@Getter +public class WxSmsNewForm extends SmsBaseDto { + + @Setter + @WxSmsProp(keyword = "first") + private String title; + + @Setter + @WxSmsProp(keyword = "keyword1") + private String userName; + + @Setter + @WxSmsProp(keyword = "keyword2") + private String bizType; + + @Setter + @WxSmsProp(keyword = "keyword3") + private String bitTime; + + @Setter + @WxSmsProp(keyword = "remark") + private String remark; + + public void setRemark(String remark) { + if(remark==null){ + this.remark = title; + }else { + this.remark = title + "(" +remark+")"; + } + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/so/WxFormPushTypeSo.java b/src/main/java/com/qs/serve/modules/wx/entity/so/WxFormPushTypeSo.java new file mode 100644 index 0000000..1b27d83 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/so/WxFormPushTypeSo.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.wx.entity.so; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单类型 查询参数 + * @author YenHex + * @since 2023-04-24 + */ +@Data +public class WxFormPushTypeSo implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** 编码 */ + private String code; + + /** 标题 */ + private String title; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/so/WxFormPushUserSo.java b/src/main/java/com/qs/serve/modules/wx/entity/so/WxFormPushUserSo.java new file mode 100644 index 0000000..7e232cc --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/so/WxFormPushUserSo.java @@ -0,0 +1,86 @@ +package com.qs.serve.modules.wx.entity.so; + +import java.time.LocalDate; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 表单推送用户 查询参数 + * @author YenHex + * @since 2023-04-24 + */ +@Data +public class WxFormPushUserSo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + private Long id; + + /** 推送id */ + private String formPushId; + + /** 用户id */ + private String userId; + + /** 推送状态 0-N,1-Y */ + private Integer pushStatus; + + /** 用户编码 */ + private String userCode; + + /** 用户名称 */ + private String userName; + + /** 是否已读 */ + private Integer readFlag; + + /** 备注 */ + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** 最后更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + + /** 所属租户 */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建人 */ + private String createBy; + + /** 更新人 */ + private String updateBy; + + /** 逻辑删除标记(0:显示;1:隐藏) */ + @JsonIgnore + @JsonProperty + private String delFlag; + + /** 分类id */ + private String typeId; + + /** 分类编码 */ + private String typeCode; + + /** 分类 */ + private String typeName; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/vo/WxPushResultVo.java b/src/main/java/com/qs/serve/modules/wx/entity/vo/WxPushResultVo.java new file mode 100644 index 0000000..defec29 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/vo/WxPushResultVo.java @@ -0,0 +1,19 @@ +package com.qs.serve.modules.wx.entity.vo; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2023/4/19 + */ +@Data +public class WxPushResultVo { + + /** + * 未绑定的用户列表 + */ + List notBindUserCodeList; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java new file mode 100644 index 0000000..2833bff --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxApp; + +/** + * 微信应用 Mapper + * @author YenHex + * @date 2022-03-07 + */ +public interface WxAppMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushMapper.java new file mode 100644 index 0000000..a03f17c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushMapper.java @@ -0,0 +1,21 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxFormPush; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import java.util.List; +/** + * 表单推送 Mapper + * @author YenHex + * @date 2023-04-19 + */ +public interface WxFormPushMapper extends BaseMapper { + + List selectUserFormPushList(@Param("query") WxFormPush param); + + @Update("update `wx_form_push` set pre_notify_time = null where id = #{id}") + void updateSetNotifyTimeNull(@Param("id")String id); +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushTypeMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushTypeMapper.java new file mode 100644 index 0000000..db2e12a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushTypeMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxFormPushType; + +/** + * 表单类型 Mapper + * @author YenHex + * @date 2023-04-24 + */ +public interface WxFormPushTypeMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushUserMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushUserMapper.java new file mode 100644 index 0000000..8dc81a6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxFormPushUserMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxFormPushUser; + +/** + * 表单推送用户 Mapper + * @author YenHex + * @date 2023-04-19 + */ +public interface WxFormPushUserMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java new file mode 100644 index 0000000..e9ca153 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; + +/** + * 微信模板/订阅消息 Mapper + * @author YenHex + * @date 2022-03-23 + */ +public interface WxTemplateMsgMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java new file mode 100644 index 0000000..51599d4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxUser; + +/** + * 微信用户 Mapper + * @author YenHex + * @date 2022-03-07 + */ +public interface WxUserMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxAppService.java b/src/main/java/com/qs/serve/modules/wx/service/WxAppService.java new file mode 100644 index 0000000..134ab14 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxAppService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxApp; + +/** + * 微信应用 服务接口 + * @author YenHex + * @date 2022-03-07 + */ +public interface WxAppService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxFormPushService.java b/src/main/java/com/qs/serve/modules/wx/service/WxFormPushService.java new file mode 100644 index 0000000..58445c0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxFormPushService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxFormPush; + +/** + * 表单推送 服务接口 + * @author YenHex + * @date 2023-04-19 + */ +public interface WxFormPushService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxFormPushTypeService.java b/src/main/java/com/qs/serve/modules/wx/service/WxFormPushTypeService.java new file mode 100644 index 0000000..f8a31d6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxFormPushTypeService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxFormPushType; + +/** + * 表单类型 服务接口 + * @author YenHex + * @date 2023-04-24 + */ +public interface WxFormPushTypeService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxFormPushUserService.java b/src/main/java/com/qs/serve/modules/wx/service/WxFormPushUserService.java new file mode 100644 index 0000000..246aafd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxFormPushUserService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxFormPushUser; + +/** + * 表单推送用户 服务接口 + * @author YenHex + * @date 2023-04-19 + */ +public interface WxFormPushUserService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxPushService.java b/src/main/java/com/qs/serve/modules/wx/service/WxPushService.java new file mode 100644 index 0000000..18d5b63 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxPushService.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.wx.service; + +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; + +/** + * @author YenHex + * @since 2022/3/16 + */ +public interface WxPushService { + + /** + * 发送微信模板信息 + * @param appId + * @param message + * @return 是否推送成功 + */ + void sendWxMsg(String appId,WxMpTemplateMessage message); + + void sendWxMsg(WxUser wxUser, String title, SmsBaseDto body); + + void sendWxMsg(WxUser wxUser,String title,SmsBaseDto body,Boolean jumpUrl); + + /** + * 通用方法 + * @param wxUser + * @param title + * @param body + * @param jumpUrl + * @param key + * @return + */ + void sendWxMsg(WxUser wxUser,String title,SmsBaseDto body,Boolean jumpUrl,String key); + +} diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java b/src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java new file mode 100644 index 0000000..74ef16d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; + +/** + * 微信模板/订阅消息 服务接口 + * @author YenHex + * @date 2022-03-23 + */ +public interface WxTemplateMsgService extends IService { + + /** + * 标题查询 + * @param appId + * @param title + * @return + */ + WxTemplateMsg getByTitle(String appId,String title); + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxUserService.java b/src/main/java/com/qs/serve/modules/wx/service/WxUserService.java new file mode 100644 index 0000000..6651a0f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxUserService.java @@ -0,0 +1,51 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxLoginUser; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * 微信用户 服务接口 + * @author YenHex + * @date 2022-03-07 + */ +public interface WxUserService extends IService { + + WxUser getCurrentWxUser(); + /** + * 获取当前微信用 + * @param updateSub + * @return + */ + WxUser getCurrentWxUser(boolean updateSub); + + void syncSubscribe(); + + List getByUnionId(String unionId); + List getBySysUserId(String userId); + WxUser getByCurrSysUserId(String userId); + List getBySysUserIds(List userIds); + + /** + * 用户登录 + * @param wxLoginUser + * @return + * @throws Exception + */ + WxUser login(WxLoginUser wxLoginUser, HttpServletRequest request) throws Exception; + + /** + * openId查询 + * @param openId + * @return + */ + @Deprecated + WxUser getByOpenId(String openId); + + WxUser getByOpenId(String appId,String openId); + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java new file mode 100644 index 0000000..4083858 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.mapper.WxAppMapper; +import com.qs.serve.modules.wx.service.WxAppService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 微信应用 服务实现类 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxAppServiceImpl extends ServiceImpl implements WxAppService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushServiceImpl.java new file mode 100644 index 0000000..2d000fd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.wx.entity.WxFormPush; +import com.qs.serve.modules.wx.service.WxFormPushService; +import com.qs.serve.modules.wx.mapper.WxFormPushMapper; + +/** + * 表单推送 服务实现类 + * @author YenHex + * @since 2023-04-19 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxFormPushServiceImpl extends ServiceImpl implements WxFormPushService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushTypeServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushTypeServiceImpl.java new file mode 100644 index 0000000..d4f8ebd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushTypeServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.wx.entity.WxFormPushType; +import com.qs.serve.modules.wx.service.WxFormPushTypeService; +import com.qs.serve.modules.wx.mapper.WxFormPushTypeMapper; + +/** + * 表单类型 服务实现类 + * @author YenHex + * @since 2023-04-24 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxFormPushTypeServiceImpl extends ServiceImpl implements WxFormPushTypeService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushUserServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushUserServiceImpl.java new file mode 100644 index 0000000..6080e4f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxFormPushUserServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.wx.entity.WxFormPushUser; +import com.qs.serve.modules.wx.service.WxFormPushUserService; +import com.qs.serve.modules.wx.mapper.WxFormPushUserMapper; + +/** + * 表单推送用户 服务实现类 + * @author YenHex + * @since 2023-04-19 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxFormPushUserServiceImpl extends ServiceImpl implements WxFormPushUserService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java new file mode 100644 index 0000000..9740a23 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java @@ -0,0 +1,81 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.common.util.SmsReflectUtil; +import com.qs.serve.modules.wx.common.conf.WxMpConfig; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import com.qs.serve.modules.wx.service.WxPushService; +import com.qs.serve.modules.wx.service.WxTemplateMsgService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +/** + * 微信推送 + * @author YenHex + * @since 2022/3/16 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxPushServiceImpl implements WxPushService { + + @Autowired(required = false) + private WxMpConfig wxMpConfig; + + private final WxTemplateMsgService wxTemplateMsgService; + + @Async + @Override + public void sendWxMsg(String appId,WxMpTemplateMessage message) { + String msgId = null; + try { + // 发送模板消息 + msgId = wxMpConfig.wxMpService().switchoverTo(appId).getTemplateMsgService().sendTemplateMsg(message); + } catch (WxErrorException e) { + log.warn("推送微信模板失败,{}",e.getMessage()); + } + log.info("推送微信模板信息:{}\n{}", msgId != null ? "成功" : "失败", JsonUtil.objectToJson(message)); + } + + @Override + public void sendWxMsg(WxUser wxUser, String title, SmsBaseDto body) { + sendWxMsg(wxUser, title, body,false); + } + + @Override + public void sendWxMsg(WxUser wxUser, String title, SmsBaseDto body, Boolean jumpUrl) { + sendWxMsg(wxUser, title, body, jumpUrl,null); + } + + @Async + @Override + public void sendWxMsg(WxUser wxUser, String title, SmsBaseDto body, Boolean jumpUrl, String key) { + AuthContextUtils.setTenant("001"); + try { + WxTemplateMsg wxTemplateMsg = wxTemplateMsgService.getByTitle(wxUser.getAppId(),title); + if(wxTemplateMsg!=null){ + WxMpTemplateMessage wxMpTemplateMessage = + WxMpTemplateMessage.builder().templateId(wxTemplateMsg.getTemplateId()) + .toUser(wxUser.getOpenId()) + .data(SmsReflectUtil.getTemplateDataList(body)).build(); + if(jumpUrl){ + wxMpTemplateMessage.setUrl(key==null?wxTemplateMsg.getJumpUrl():wxTemplateMsg.getJumpUrl()+key); + } + sendWxMsg(wxUser.getAppId(),wxMpTemplateMessage); + }else { + log.warn("AppId:{},无可用的微信通知模板:[{}]",wxUser.getAppId(),title); + } + } catch (Exception e) { + log.warn(e.getMessage()); + } + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java new file mode 100644 index 0000000..42eac09 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java @@ -0,0 +1,32 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; +import com.qs.serve.modules.wx.mapper.WxTemplateMsgMapper; +import com.qs.serve.modules.wx.service.WxTemplateMsgService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 微信模板/订阅消息 服务实现类 + * @author YenHex + * @since 2022-03-23 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxTemplateMsgServiceImpl extends ServiceImpl implements WxTemplateMsgService { + + @Override + public WxTemplateMsg getByTitle(String appId,String title) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(WxTemplateMsg::getTitle,title); + wrapper.eq(WxTemplateMsg::getAppId,appId); + wrapper.eq(WxTemplateMsg::getEnable,1); + return getOne(wrapper,false); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java new file mode 100644 index 0000000..c08868a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java @@ -0,0 +1,301 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.wx.common.conf.WxCpConfig; +import com.qs.serve.modules.wx.common.conf.WxMpConfig; +import com.qs.serve.modules.wx.common.consts.WxStatusConst; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxLoginUser; +import com.qs.serve.modules.wx.mapper.WxUserMapper; +import com.qs.serve.modules.wx.service.WxAppService; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.service.WxOAuth2Service; +import me.chanjar.weixin.cp.api.WxCpOAuth2Service; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.WxCpUserService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.bean.WxCpUserDetail; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; +import me.chanjar.weixin.cp.config.impl.WxCpTpDefaultConfigImpl; +import me.chanjar.weixin.cp.tp.service.WxCpTpService; +import me.chanjar.weixin.cp.tp.service.impl.WxCpTpServiceImpl; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.WxMpUserService; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.GetMapping; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; + +/** + * 微信用户 服务实现类 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Service +public class WxUserServiceImpl extends ServiceImpl implements WxUserService { + + @Autowired(required = false) + private WxMpConfig wxMpConfig; + + @Autowired(required = false) + private WxAppService wxAppService; + + @Autowired + private RedisService redisService; + + @Autowired + private SysUserMapper sysUserMapper; + + private List getOpenIds(WxMpUserService wxMpUserService,String nextOpenId){ + WxMpUserList wxMpUserList = null; + List openIds = new ArrayList<>(); + try { + wxMpUserList = wxMpUserService.userList(nextOpenId); + openIds = wxMpUserList.getOpenids(); + String currNextOpenId = wxMpUserList.getNextOpenid(); + if(openIds.size() == 10000) { + openIds.addAll(getOpenIds(wxMpUserService,currNextOpenId)); + } + } catch (WxErrorException e) { + e.printStackTrace(); + } + return openIds; + } + + @Override + public void syncSubscribe(){ + log.warn("**同步订阅用户流程-开始**"); + WxMpUserService wxMpUserService = wxMpConfig.wxMpService().getUserService(); + List allOpenIds = this.getOpenIds(wxMpUserService,null); + if(CollectionUtil.isEmpty(allOpenIds)){ + List> tmpList = CollectionUtil.createList(allOpenIds,800); + for (List openIdList : tmpList) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getSubscribe,0); + lqw.in(WxUser::getOpenId,openIdList); + WxUser wxUser = new WxUser(); + wxUser.setSubscribe(1); + this.update(wxUser,lqw); + } + } + log.warn("**同步订阅用户流程-结束**"); + } + + + @Override + public WxUser getCurrentWxUser() { + return this.getCurrentWxUser(false); + } + + + @Override + public WxUser getCurrentWxUser( boolean updateSub) { + String token = ServletUtils.getHeader(GySysConst.APP_TOKEN_PROP); + String wxUserKey = StringUtils.format(RedisCacheKeys.WX_KEY_USER,token); + String wxUserId = redisService.getString(wxUserKey); + String appId = AuthContextUtils.getAppId(); + WxUser wxUser = this.getById(wxUserId); + if(updateSub&&!wxUser.getId().equals("1") + &&(wxUser.getAppType().equals(1)||wxUser.getAppType().equals(2))){ + try { + WxMpService wxMpService = wxMpConfig.wxMpService().switchoverTo(appId); + WxMpUser wxMpUser = wxMpService.getUserService().userInfo(wxUser.getOpenId(), GySysConst.LANG_ZH_CN); + wxUser.setSubscribe(wxMpUser.getSubscribe()?1:0); + wxUser.setSubscribeScene(wxMpUser.getSubscribeScene()); + wxUser.setTagidList(JsonUtil.objectToJson(wxMpUser.getTagIds())); + wxUser.setUnionId(wxMpUser.getUnionId()); + } catch (WxErrorException e) { + e.printStackTrace(); + } + } + return wxUser; + } + + @Override + public List getByUnionId(String unionId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getUnionId,unionId); + return this.list(lqw); + } + + @Override + public List getBySysUserId(String userId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getSysUserId,userId); + return this.list(lqw); + } + + @Override + public WxUser getByCurrSysUserId(String userId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getSysUserId,userId); + lqw.eq(WxUser::getAppId,AuthContextUtils.getAppId(false)); + return this.getOne(lqw,false); + } + + @Override + public List getBySysUserIds(List userIds) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(WxUser::getSysUserId,userIds); + return this.list(lqw); + } + + @Override + public WxUser login(WxLoginUser wxLoginUser, HttpServletRequest request){ + String code = wxLoginUser.getCode(); + String appId = AuthContextUtils.getAppId(); + String agentIdStr = request.getHeader("agentId"); + WxApp wxApp = wxAppService.getById(appId); + WxUser wxUser = null; + if(wxApp.getAppType().equals(WxStatusConst.WxApp_AppType_3)){ + Integer agentId = Integer.parseInt(agentIdStr); + // 企业微信登录 + WxCpService wxCpService = new WxCpServiceImpl(); + WxCpDefaultConfigImpl config =new WxCpDefaultConfigImpl(); + config.setAgentId(agentId); + config.setCorpSecret(WxCpConfig.getSecret(agentId)); + config.setCorpId(wxApp.getId()); + wxCpService.setWxCpConfigStorage(config); + // 授权方式登录 + WxCpOAuth2Service oauth2Service = wxCpService.getOauth2Service(); + WxCpOauth2UserInfo cpOauth2UserInfo = null; + // 获取敏感信息 + WxCpUserDetail wxCpUserDetail = null; + WxCpUser wxCpUser = null; + try { + cpOauth2UserInfo = oauth2Service.getUserInfo(agentId,code); + // 基础用户信息 + WxCpUserService wxCpUserService = wxCpService.getUserService(); + wxCpUser = wxCpUserService.getById(cpOauth2UserInfo.getUserId()); + // 获取敏感信息 + wxCpUserDetail = oauth2Service.getUserDetail(cpOauth2UserInfo.getUserTicket()); + } catch (WxErrorException e) { + log.error("企业微信登录失败:{}",e.getMessage()); + } + if(wxCpUserDetail==null||wxCpUser==null){ + Assert.throwEx("企业微信登录失败"); + } + String userId = wxCpUserDetail.getUserId(); + wxUser = this.getByOpenId(appId,userId); + if(wxUser == null){ + wxUser = new WxUser(); + wxUser.setAppId(wxApp.getId()); + wxUser.setAppType(wxApp.getAppType()); + wxUser.setNickName(wxCpUser.getName()); + wxUser.setEmpName(wxCpUser.getName()); + wxUser.setUnionId(userId); + wxUser.setOpenId(userId); + wxUser.setHeadimgUrl(wxCpUserDetail.getAvatar()); + } + //通过手机号绑定员工号 + //if(StringUtils.hasText(wxCpUser.getMobile())){ + //List sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper() + // .eq(SysUser::getMobile,wxCpUser.getMobile())); + List sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper().eq(SysUser::getCode,userId)); + if(sysUsers.size()>0){ + if(sysUsers.size()>1){ + //log.error("企业微信登录,一个号码被多人使用:{}",wxCpUser.getMobile()); + log.error("企业微信登录,员工号出现重复:{}",userId); + } + SysUser sysUser = sysUsers.get(0); + wxUser.setSysUserId(sysUser.getId()); + wxUser.setSysUserCode(sysUser.getCode()); + wxUser.setEmpName(sysUser.getName()); + wxUser.setPhone(sysUser.getMobile()); + }else { + //Assert.throwEx("CMS未收录该手机号["+wxCpUser.getMobile()+"]"); + Assert.throwEx("CMS未收录该员工号["+userId+"]"); + } + if(wxUser.getId()==null){ + save(wxUser); + }else { + updateById(wxUser); + } + }else if(wxApp.getAppType().equals(WxStatusConst.WxApp_AppType_1)){ + Assert.throwEx(HttpCode.DEV_ERR); + }else if(wxApp.getAppType().equals(WxStatusConst.WxApp_AppType_2)){ + WxMpService wxMpService = wxMpConfig.wxMpService().switchoverTo(appId); + WxOAuth2Service auth2Service = wxMpService.getOAuth2Service(); + try { + WxOAuth2AccessToken auth2AccessToken = auth2Service.getAccessToken(code); + log.debug("auth2AccessToken:{}",auth2AccessToken.getAccessToken()); + WxOAuth2UserInfo auth2UserInfo = auth2Service.getUserInfo(auth2AccessToken, GySysConst.LANG_ZH_CN); + WxMpUser wxMpUser = wxMpService.getUserService().userInfo(auth2UserInfo.getOpenid(), GySysConst.LANG_ZH_CN); + wxUser = this.getByOpenId(appId,auth2UserInfo.getOpenid()); + if(wxUser == null){ + wxUser = new WxUser(); + wxUser.setAppId(wxApp.getId()); + wxUser.setAppType(wxApp.getAppType()); + wxUser.setNickName(auth2UserInfo.getNickname()); + wxUser.setEmpName(auth2UserInfo.getNickname()); + wxUser.setUnionId(auth2UserInfo.getUnionId()); + wxUser.setHeadimgUrl(auth2UserInfo.getHeadImgUrl()); + wxUser.setOpenId(auth2UserInfo.getOpenid()); + } + if(StringUtils.hasText(auth2UserInfo.getUnionId())){ + wxUser.setUnionId(auth2UserInfo.getUnionId()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(WxUser::getUnionId,auth2UserInfo.getUnionId()); + Long count = this.count(lqw); + if(count<1){ + wxUser.setFirstFlag(1); + } + } + wxUser.setSubscribe(wxMpUser.getSubscribe()?1:0); + wxUser.setSubscribeScene(wxMpUser.getSubscribeScene()); + wxUser.setTagidList(JsonUtil.objectToJson(wxMpUser.getTagIds())); + if(wxUser.getId()==null){ + save(wxUser); + }else { + updateById(wxUser); + } + } catch (WxErrorException e) { + log.debug("微信登录失败:{}",e.getMessage()); + } + } + //TODO 登录日志 + return wxUser; + } + + @Override + public WxUser getByOpenId(String openId) { + LambdaQueryWrapper wxUserLambdaQueryWrapper = new LambdaQueryWrapper<>(); + wxUserLambdaQueryWrapper.eq(WxUser::getOpenId,openId); + return getOne(wxUserLambdaQueryWrapper,false); + } + + @Override + public WxUser getByOpenId(String appId, String openId) { + LambdaQueryWrapper wxUserLambdaQueryWrapper = new LambdaQueryWrapper<>(); + wxUserLambdaQueryWrapper.eq(WxUser::getOpenId,openId); + wxUserLambdaQueryWrapper.eq(WxUser::getAppId,appId); + return getOne(wxUserLambdaQueryWrapper,false); + } +} + diff --git a/src/main/resources/META-INT/spring.components b/src/main/resources/META-INT/spring.components new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..313d25c --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,41 @@ +#项目配置 +project: + upload: + #上传映射地址 + proxy-url: https://qsjslservice.oss-cn-guangzhou.aliyuncs.com/jsl/ + +aliyun: + oss: + bucket: qsjslservice + accessKeyId: LTAI5tHvNJT7M9YZJ9BSmURK + accessKeySecret: OzH0ea3w8fgjrll9P0XTQlqmEg3Cky + endpoint: oss-cn-guangzhou.aliyuncs.com + prefix: jsl +#服务配置 +server: + port: 7400 + servlet: + context-path: / + +#SpringBoot相关 +spring: + datasource: + dynamic: + primary: crm_db + strict: false + datasource: + crm_db: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://192.168.0.9:3306/jsl_mall_qs_dev?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: kpjsl + password: 123456 + qisheng: + url: jdbc:sqlserver://192.168.10.11:1433;DatabaseName=JSL_COST_QS + username: sa + password: JSL2282125 + driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver + redis: + database: 1 + host: 127.0.0.1 + port: 6379 + password: diff --git a/src/main/resources/application-pro.yml b/src/main/resources/application-pro.yml new file mode 100644 index 0000000..08be04f --- /dev/null +++ b/src/main/resources/application-pro.yml @@ -0,0 +1,87 @@ +#项目配置 +project: + #关闭权限 + close-auth: 'false' + #true-请求端;false-接收端 + bir-service: 'false' + #对应233服务的的cms + bir-service-url: 'http://59.37.164.96:7400' + #bir-service-url: 'http://127.0.0.1:7401' + web_url: 'http://192.168.0.9:6031' + host_url: 'http://192.168.0.9:7400' + pc-web-local: 'D:\Software\Nginx1.8\html\jslcrm3\' + apis: + #支付接口 + cost-to-pay: 'http://59.37.164.96:2505/api/cms/api/add' + check-pay-status: 'http://59.37.164.96:2506/action/cms/cost/match' + # 核销生成报价单接口 + diaodu-plan-order: '' + # 嘉士利接口,spu转换sku + spu-to-sku: 'http://59.37.164.96:2505/api/cms/order/matchInvCode' + # 政策同步 + policy-sync-cate: 'http://192.168.10.18:9003/api/cms/saleCost/costPolicy/syncCate' + # 政策同步旧的 + policy-sync-inv: 'http://192.168.10.18:9003/api/cms/saleCost/costPolicy/syncInv' + task: false + dev: false + seeyon: + enable: true + url: 'http://192.168.0.9:7444' + #请求致远OA的拓展服务(用于修改密码) + extApi: 'http://192.168.10.244:9003/' + + upload: + #上传映射地址 + proxy-url: https://qsjslservice.oss-cn-guangzhou.aliyuncs.com/jsl/ + #物理存储地址 + logical-path: D:\\WebMapPath\\ +#腾讯云配置 +tencent: + sms: + secret-id: AKIDR3A5mVkSaXFUT3TABanPxc2MtkMu45wb + secret-key: iLkjeKzHwegQ4eE55xX9byXmBLxgwypV + sdkAppId: 1400174031 + signName: 柒胜软件 + templateId: 689207 +#天翼云配置 +tianyi: + sms: + appid: 'WIgWyCFn4DnHLtjKBIXBVyZbGevFg3J4' + appKey: 'bjfsZlF01OZPUzyiCLSFOrOOnfsZhYZJ' +aliyun: + oss: + bucket: qsjslservice + accessKeyId: LTAI5tHvNJT7M9YZJ9BSmURK + accessKeySecret: OzH0ea3w8fgjrll9P0XTQlqmEg3Cky + endpoint: oss-cn-guangzhou.aliyuncs.com + prefix: jsl +#服务配置 +server: + port: 7401 + servlet: + context-path: / +#SpringBoot相关 +spring: + datasource: + dynamic: + primary: crm_db #设置默认的数据源或者数据源组,默认值即为master + strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 + datasource: + crm_db: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://183.56.249.148:3306/jsl_cost_base?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: root + password: '@Jsl2282125' + qisheng: + url: jdbc:sqlserver://192.168.10.11:1433;DatabaseName=JSL_COST_QS + username: sa + password: JSL2282125 + driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver + redis: + database: 2 + host: 127.0.0.1 + port: 6379 + password: +#工作流配置 +flowable: + database-schema-update: true diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..7c9b812 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,81 @@ +spring: + servlet: + multipart: + max-file-size: 100MB + max-request-size: 160MB + profiles: + active: dev + main: + #easypoi启用覆盖 + allow-bean-definition-overriding: true + jmx: + enabled: false + devtools: + restart: + enabled: false +#项目配置 +project: + ignore-url: + tenants: #忽略租户拦截 + - /callback + - /favicon.ico + - /error + - /portal/syKeyLogin + - /bir/roiRate/test + - /static/* + - /web/* + permits: #忽略登录 + - /thirty/** #第三方接口 + - /portal/flushToken #第三方接口 + - /common/upload #支持API上传调整 + - /common/validToken #验证token + - /api/** + - /static/** + - /web/** + - /portal/** + - /favicon.ico + - /error + - /callback + - /bir/roiRate/test + +#mybatis plus +mybatis-plus: + mapper-locations: classpath:mapper/*/*.xml + type-aliases-package: com.qs.serve.modules.*.entity.* + configuration: + map-underscore-to-camel-case: true + #log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl + global-config: + banner: false + db-config: + logic-delete-value: 1 + logic-not-delete-value: 0 + select-strategy: not_empty + logic-delete-field: delFlag +# 日志配置 +logging: + level: + ROOT: info + com.qs.serve: debug + org.xnio.nio: info + org.springframework: info + com.baomidou: info + org.mybatis: info + org.hibernate.validator: info + druid.sql.ResultSet: info + druid.sql.Connection: info + com.zaxxer.hikari.pool: info + com.zaxxer.hikari.HikariConfig: info + java.io: warn + io.netty: info + io.undertow: info + io.lettuce.core: info + config: classpath:log4j2.xml +# PageHelper分页插件 +pagehelper: + reasonable: false + #helper-dialect: sqlserver + autoRuntimeDialect: true + supportMethodsArguments: true + params: count=countSql + diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..09bf7ff --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,4 @@ +${AnsiBackground.BLACK} +-- ---------------------------- +-- 嘉士利CRM系统 by.柒胜 +-- ---------------------------- diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..f7d1bce --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/baz/BazVisitInstanceMapper.xml b/src/main/resources/mapper/baz/BazVisitInstanceMapper.xml new file mode 100644 index 0000000..885444b --- /dev/null +++ b/src/main/resources/mapper/baz/BazVisitInstanceMapper.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + baz_visit_instance.`id`, + baz_visit_instance.`title`, + baz_visit_instance.`visit_id`, + baz_visit_instance.`target_type`, + baz_visit_instance.`visit_state`, + baz_visit_instance.`visitor_id`, + baz_visit_instance.`visitor_code`, + baz_visit_instance.`visitor_name`, + baz_visit_instance.`target_id`, + baz_visit_instance.`target_code`, + baz_visit_instance.`target_name`, + baz_visit_instance.`target_local_x`, + baz_visit_instance.`target_local_y`, + baz_visit_instance.`target_address`, + baz_visit_instance.`target_map_address`, + baz_visit_instance.`finished_time`, + baz_visit_instance.`miss_local_flag`, + baz_visit_instance.`remark`, + baz_visit_instance.`position_status_content`, + baz_visit_instance.`position_status`, + baz_visit_instance.`create_time`, + baz_visit_instance.`update_time`, + baz_visit_instance.`tenant_id`, + baz_visit_instance.`del_flag`, + baz_visit_instance.`create_by`, + baz_visit_instance.`update_by` + + + + diff --git a/src/main/resources/mapper/bir/BirActivityCenterGoodsMapper.xml b/src/main/resources/mapper/bir/BirActivityCenterGoodsMapper.xml new file mode 100644 index 0000000..ad6b886 --- /dev/null +++ b/src/main/resources/mapper/bir/BirActivityCenterGoodsMapper.xml @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tbs_activity_center_goods.`id`, + tbs_activity_center_goods.`center_goods_code`, + tbs_activity_center_goods.`cost_apply_id`, + tbs_activity_center_goods.`activity_id`, + tbs_activity_center_goods.`activity_code`, + tbs_activity_center_goods.`subject_id`, + tbs_activity_center_goods.`subject_code`, + tbs_activity_center_goods.`subject_name`, + tbs_activity_center_goods.`center_type`, + tbs_activity_center_goods.`center_id`, + tbs_activity_center_goods.`center_code`, + tbs_activity_center_goods.`center_name`, + tbs_activity_center_goods.`center_amount`, + tbs_activity_center_goods.`center_rate`, + tbs_activity_center_goods.`center_goods_amount`, + tbs_activity_center_goods.`center_goods_rate`, + tbs_activity_center_goods.`used_amount`, + tbs_activity_center_goods.`target_type`, + tbs_activity_center_goods.`target_id`, + tbs_activity_center_goods.`target_code`, + tbs_activity_center_goods.`target_name`, + tbs_activity_center_goods.`target_level_path_ids`, + tbs_activity_center_goods.`target_level_path_names`, + tbs_activity_center_goods.`remark`, + tbs_activity_center_goods.`create_time`, + tbs_activity_center_goods.`update_time`, + tbs_activity_center_goods.`tenant_id`, + tbs_activity_center_goods.`create_by`, + tbs_activity_center_goods.`update_by`, + tbs_activity_center_goods.`del_flag`, + tbs_activity_center_goods.`act_start_date`, + tbs_activity_center_goods.`act_end_date`, + tbs_activity_center_goods.`pre_start_date`, + tbs_activity_center_goods.`pre_end_date`, + tbs_activity_center_goods.`pre_check_date`, + tbs_activity_center_goods.`tmp_uk`, + tbs_activity_center_goods.`supplier_id`, + tbs_activity_center_goods.`supplier_code`, + tbs_activity_center_goods.`supplier_name` + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/bir/BirBaseActivityMapper.xml b/src/main/resources/mapper/bir/BirBaseActivityMapper.xml new file mode 100644 index 0000000..fd26a9e --- /dev/null +++ b/src/main/resources/mapper/bir/BirBaseActivityMapper.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tbs_activity.`id`, + tbs_activity.`activity_code`, + tbs_activity.`activity_state`, + tbs_activity.`cost_apply_id`, + tbs_activity.`cost_pass_time`, + tbs_activity.`cost_pass_flag`, + tbs_activity.`act_title`, + tbs_activity.`supplier_id`, + tbs_activity.`supplier_code`, + tbs_activity.`supplier_name`, + tbs_activity.`act_start_date`, + tbs_activity.`act_end_date`, + tbs_activity.`pre_start_date`, + tbs_activity.`pre_end_date`, + tbs_activity.`pre_check_date`, + tbs_activity.`pre_act_flag`, + tbs_activity.`pre_act_quantity`, + tbs_activity.`pre_not_act_quantity`, + tbs_activity.`pre_roi_rate`, + tbs_activity.`remark`, + tbs_activity.`total_amount`, + tbs_activity.`used_amount`, + tbs_activity.`reopen_flag`, + tbs_activity.`finished_flag`, + tbs_activity.`finished_time`, + tbs_activity.`release_flag`, + tbs_activity.`release_amount`, + tbs_activity.`release_time`, + tbs_activity.`release_user_id`, + tbs_activity.`release_user_name`, + tbs_activity.`create_time`, + tbs_activity.`update_time` + + + + + + + diff --git a/src/main/resources/mapper/bir/BirBudgetTargetMapper.xml b/src/main/resources/mapper/bir/BirBudgetTargetMapper.xml new file mode 100644 index 0000000..bff9a10 --- /dev/null +++ b/src/main/resources/mapper/bir/BirBudgetTargetMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + bir_budget_target.id, + bir_budget_target.search_type, + bir_budget_target.year_num, + bir_budget_target.quarter_num, + bir_budget_target.month_num, + bir_budget_target.target_amt, + bir_budget_target.budget_amt, + bir_budget_target.dispatch_amt, + bir_budget_target.last_year_dispatch_amt, + bir_budget_target.province_city_amt, + bir_budget_target.province_city_region_amt, + bir_budget_target.total_real_amt, + bir_budget_target.brand_id, + bir_budget_target.brand_code, + bir_budget_target.brand_name, + bir_budget_target.center_type, + bir_budget_target.center_id, + bir_budget_target.center_code, + bir_budget_target.center_name + + + + diff --git a/src/main/resources/mapper/bir/BirRoiRateMapper.xml b/src/main/resources/mapper/bir/BirRoiRateMapper.xml new file mode 100644 index 0000000..d06c82b --- /dev/null +++ b/src/main/resources/mapper/bir/BirRoiRateMapper.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + bir_roi_rate.id, + bir_roi_rate.key_num, + bir_roi_rate.activity_amt, + bir_roi_rate.verification_amt, + bir_roi_rate.shipment_qty, + bir_roi_rate.shipment_amt, + bir_roi_rate.supplier_id, + bir_roi_rate.supplier_code, + bir_roi_rate.supplier_name, + bir_roi_rate.user_id, + bir_roi_rate.user_code, + bir_roi_rate.user_name, + bir_roi_rate.create_time, + bir_roi_rate.update_time, + bir_roi_rate.tenant_id, + bir_roi_rate.del_flag + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/bir/BirTbsVtbPayJoinMapper.xml b/src/main/resources/mapper/bir/BirTbsVtbPayJoinMapper.xml new file mode 100644 index 0000000..6689aec --- /dev/null +++ b/src/main/resources/mapper/bir/BirTbsVtbPayJoinMapper.xml @@ -0,0 +1,227 @@ + + + + + + update tbs_activity + left join ( + select activity_id, + GROUP_CONCAT(DISTINCT center_name SEPARATOR ', ') AS center_name + from tbs_activity_center where del_flag = 0 and cost_apply_id > #{maxCostId} + GROUP BY activity_id + ) tmp on tmp.activity_id = tbs_activity.id + set all_center_names = tmp.center_name + where cost_apply_id > #{maxCostId} + + + + + + + + + + diff --git a/src/main/resources/mapper/bir/TbsActivityTemplateMapper.xml b/src/main/resources/mapper/bir/TbsActivityTemplateMapper.xml new file mode 100644 index 0000000..c7d77db --- /dev/null +++ b/src/main/resources/mapper/bir/TbsActivityTemplateMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + tbs_activity_template.`id`, + tbs_activity_template.`template_name`, + tbs_activity_template.`template_state`, + tbs_activity_template.`template_value`, + tbs_activity_template.`sale_region_flag`, + tbs_activity_template.`biz_region_flag`, + tbs_activity_template.`contract_flag`, + tbs_activity_template.`cost_theme`, + tbs_activity_template.`cost_theme_edit_flag`, + tbs_activity_template.`pre_remark`, + tbs_activity_template.`remark`, + tbs_activity_template.`start_time`, + tbs_activity_template.`end_time`, + tbs_activity_template.`create_time`, + tbs_activity_template.`create_by`, + tbs_activity_template.`update_time`, + tbs_activity_template.`update_by`, + tbs_activity_template.`tenant_id`, + tbs_activity_template.`del_flag` + + + + diff --git a/src/main/resources/mapper/biz/BizSignTypeMapper.xml b/src/main/resources/mapper/biz/BizSignTypeMapper.xml new file mode 100644 index 0000000..01b8641 --- /dev/null +++ b/src/main/resources/mapper/biz/BizSignTypeMapper.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + biz_sign_type.`id`, + biz_sign_type.`type_name`, + biz_sign_type.`template_id`, + biz_sign_type.`remark`, + biz_sign_type.`create_time`, + biz_sign_type.`update_time`, + biz_sign_type.`tenant_id`, + biz_sign_type.`del_flag`, + biz_sign_type.`create_by`, + biz_sign_type.`update_by` + + + + diff --git a/src/main/resources/mapper/biz/BizUserGroupItemMapper.xml b/src/main/resources/mapper/biz/BizUserGroupItemMapper.xml new file mode 100644 index 0000000..feb56fb --- /dev/null +++ b/src/main/resources/mapper/biz/BizUserGroupItemMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + biz_user_group_item.`id`, + biz_user_group_item.`group_id`, + biz_user_group_item.`target_type`, + biz_user_group_item.`target_id`, + biz_user_group_item.`target_name`, + biz_user_group_item.`target_code`, + biz_user_group_item.`remark`, + biz_user_group_item.`create_time`, + biz_user_group_item.`create_by`, + biz_user_group_item.`update_time`, + biz_user_group_item.`update_by`, + biz_user_group_item.`del_flag`, + biz_user_group_item.`tenant_id` + + + + diff --git a/src/main/resources/mapper/bms/BmsChannelMapper.xml b/src/main/resources/mapper/bms/BmsChannelMapper.xml new file mode 100644 index 0000000..b9dcaae --- /dev/null +++ b/src/main/resources/mapper/bms/BmsChannelMapper.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + bms_channel.`id`, + bms_channel.`channel_code`, + bms_channel.`channel_name`, + bms_channel.`channel_type`, + bms_channel.`head_channel`, + bms_channel.`head_channel_code`, + bms_channel.`head_channel_id`, + bms_channel.`remark`, + bms_channel.`create_time`, + bms_channel.`update_time`, + bms_channel.`tenant_id`, + bms_channel.`del_flag`, + bms_channel.`create_by`, + bms_channel.`update_by`, + bms_channel.`cost_flag` + + + + diff --git a/src/main/resources/mapper/bms/BmsChannelPointMapper.xml b/src/main/resources/mapper/bms/BmsChannelPointMapper.xml new file mode 100644 index 0000000..c6abae1 --- /dev/null +++ b/src/main/resources/mapper/bms/BmsChannelPointMapper.xml @@ -0,0 +1,375 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bms_channel_point.`id`, + bms_channel_point.`channel_id`, + bms_channel_point.`channel_code`, + bms_channel_point.`channel_name`, + bms_channel_point.`point_code`, + bms_channel_point.`point_name`, + bms_channel_point.`shop_area`, + bms_channel_point.`count_checkstand`, + bms_channel_point.`point_level`, + bms_channel_point.`point_type`, + bms_channel_point.`address`, + bms_channel_point.`sale_region_id`, + bms_channel_point.`sale_region_path`, + bms_channel_point.`sale_region_path_ids`, + bms_channel_point.`biz_region_id`, + bms_channel_point.`biz_region_path`, + bms_channel_point.`biz_region_path_ids`, + bms_channel_point.`remark`, + bms_channel_point.`create_time`, + bms_channel_point.`update_time`, + bms_channel_point.`tenant_id`, + bms_channel_point.`local_x`, + bms_channel_point.`local_y`, + bms_channel_point.`map_address`, + bms_channel_point.`del_flag`, + bms_channel_point.`cost_flag`, + bms_channel_point.`create_by`, + bms_channel_point.`update_by` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/bms/BmsMasterUserMapper.xml b/src/main/resources/mapper/bms/BmsMasterUserMapper.xml new file mode 100644 index 0000000..9c7b66c --- /dev/null +++ b/src/main/resources/mapper/bms/BmsMasterUserMapper.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bms_master_user.`id`, + bms_master_user.`type`, + bms_master_user.`target_id`, + bms_master_user.`user_id`, + bms_master_user.`master_flag`, + bms_master_user.`remark`, + bms_master_user.`create_time`, + bms_master_user.`create_by`, + bms_master_user.`update_time`, + bms_master_user.`update_by`, + bms_master_user.`tenant_id`, + bms_master_user.`del_flag` + + + and `bms_master_user`.`id` = #{query.id} + and `bms_master_user`.`type` = #{query.type} + and `bms_master_user`.`target_id` = #{query.targetId} + and `bms_master_user`.`user_id` = #{query.userId} + and `bms_master_user`.`master_flag` = #{query.masterFlag} + + + + and `bms_master_user`.`remark` = #{query.remark} + and `bms_master_user`.`create_time` = #{query.createTime} + and `bms_master_user`.`create_by` = #{query.createBy} + and `bms_master_user`.`update_time` = #{query.updateTime} + and `bms_master_user`.`update_by` = #{query.updateBy} + and `bms_master_user`.`tenant_id` = #{query.tenantId} + and `bms_master_user`.`del_flag` = #{query.delFlag} + + + + + + + + diff --git a/src/main/resources/mapper/bms/BmsRuleSkuMapper.xml b/src/main/resources/mapper/bms/BmsRuleSkuMapper.xml new file mode 100644 index 0000000..5a28e79 --- /dev/null +++ b/src/main/resources/mapper/bms/BmsRuleSkuMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + bms_rule_sku.`id`, + bms_rule_sku.`rule_id`, + bms_rule_sku.`sku_id`, + bms_rule_sku.`spu_id`, + bms_rule_sku.`remark`, + bms_rule_sku.`create_time`, + bms_rule_sku.`create_by`, + bms_rule_sku.`update_time`, + bms_rule_sku.`update_by`, + bms_rule_sku.`tenant_id`, + bms_rule_sku.`del_flag` + + + + + + diff --git a/src/main/resources/mapper/bms/BmsSkuSupplierMapper.xml b/src/main/resources/mapper/bms/BmsSkuSupplierMapper.xml new file mode 100644 index 0000000..1f0a87c --- /dev/null +++ b/src/main/resources/mapper/bms/BmsSkuSupplierMapper.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + bms_sku_supplier.`id`, + bms_sku_supplier.`spu_id`, + bms_sku_supplier.`sku_id`, + bms_sku_supplier.`supplier_id`, + bms_sku_supplier.`ban_status`, + bms_sku_supplier.`create_time`, + bms_sku_supplier.`create_by`, + bms_sku_supplier.`update_time`, + bms_sku_supplier.`update_by`, + bms_sku_supplier.`tenant_id`, + bms_sku_supplier.`del_flag` + + + + diff --git a/src/main/resources/mapper/bms/BmsSupplierAddressMapper.xml b/src/main/resources/mapper/bms/BmsSupplierAddressMapper.xml new file mode 100644 index 0000000..1f01466 --- /dev/null +++ b/src/main/resources/mapper/bms/BmsSupplierAddressMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bms_supplier.name as supplier_name, + bms_supplier.code as supplier_code, + bms_supplier_address.`id`, + bms_supplier_address.`supplier_id`, + bms_supplier_address.`default_flag`, + bms_supplier_address.`province_code`, + bms_supplier_address.`province`, + bms_supplier_address.`city_code`, + bms_supplier_address.`city`, + bms_supplier_address.`area_code`, + bms_supplier_address.`area`, + bms_supplier_address.`detail`, + bms_supplier_address.`phone`, + bms_supplier_address.`receiver`, + bms_supplier_address.`remark`, + bms_supplier_address.`create_time`, + bms_supplier_address.`update_time`, + bms_supplier_address.`tenant_id`, + bms_supplier_address.`del_flag`, + bms_supplier_address.`create_by`, + bms_supplier_address.`update_by` + + + + diff --git a/src/main/resources/mapper/bms/BmsSupplierChannelMapper.xml b/src/main/resources/mapper/bms/BmsSupplierChannelMapper.xml new file mode 100644 index 0000000..a06d867 --- /dev/null +++ b/src/main/resources/mapper/bms/BmsSupplierChannelMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + bms_supplier_channel.`id`, + bms_supplier_channel.`channel_id`, + bms_supplier_channel.`supplier_id`, + bms_supplier_channel.`create_time`, + bms_supplier_channel.`update_time`, + bms_supplier_channel.`tenant_id`, + bms_supplier_channel.`del_flag`, + bms_supplier_channel.`create_by`, + bms_supplier_channel.`update_by` + + + + diff --git a/src/main/resources/mapper/bms/BmsSupplierMapper.xml b/src/main/resources/mapper/bms/BmsSupplierMapper.xml new file mode 100644 index 0000000..7403980 --- /dev/null +++ b/src/main/resources/mapper/bms/BmsSupplierMapper.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bms_supplier.`id`, + bms_supplier.`region_first`, + bms_supplier.`region_second`, + bms_supplier.`region_third`, + bms_supplier.`region_last`, + bms_supplier.`region2_first`, + bms_supplier.`region2_second`, + bms_supplier.`region2_third`, + bms_supplier.`region2_last`, + bms_supplier.`address`, + bms_supplier.`name`, + bms_supplier.`code`, + bms_supplier.`pid`, + bms_supplier.`parent_code`, + bms_supplier.`user_id`, + bms_supplier.`user_code`, + bms_supplier.`user_name`, + bms_supplier.`other_user_ids`, + bms_supplier.`other_user_names`, + bms_supplier.`other_user_codes`, + bms_supplier.`belong`, + bms_supplier.`create_time`, + bms_supplier.`create_by`, + bms_supplier.`update_time`, + bms_supplier.`update_by`, + bms_supplier.`tenant_id`, + bms_supplier.`cost_flag`, + bms_supplier.`supplier_flag`, + bms_supplier.`supplier_info_flag`, + bms_supplier.`supplier_tax_number`, + bms_supplier.`supplier_license_img`, + bms_supplier.`supplier_user`, + bms_supplier.`com_region`, + bms_supplier.`com_region_code`, + bms_supplier.`stop_flag`, + bms_supplier.`cooperate_pause_flag`, + bms_supplier.`stop_flag_date`, + bms_supplier.`cooperate_pause_flag_date`, + bms_supplier.`cd_order_flag`, + bms_supplier.`del_flag` + + + + + + UPDATE bms_supplier + SET user_id = NULL,user_code = null, user_name = null + WHERE id IN + + #{item} + + + + + UPDATE bms_supplier + SET other_user_ids = NULL,other_user_codes = null, other_user_names = null + WHERE id IN + + #{item} + + + diff --git a/src/main/resources/mapper/erp/ErpDispatchDataMapper.xml b/src/main/resources/mapper/erp/ErpDispatchDataMapper.xml new file mode 100644 index 0000000..fc1dbde --- /dev/null +++ b/src/main/resources/mapper/erp/ErpDispatchDataMapper.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + erp_dispatch_data.`id`, + erp_dispatch_data.`place`, + erp_dispatch_data.`dl_code`, + erp_dispatch_data.`date`, + erp_dispatch_data.`cus_code`, + erp_dispatch_data.`cus_name`, + erp_dispatch_data.`inv_code`, + erp_dispatch_data.`inv_name`, + erp_dispatch_data.`inv_batch`, + erp_dispatch_data.`sales_dep_code`, + erp_dispatch_data.`dep_name`, + erp_dispatch_data.`qty`, + erp_dispatch_data.`sum_money`, + erp_dispatch_data.`volume`, + erp_dispatch_data.`net_weight`, + erp_dispatch_data.`dispatch_cost`, + erp_dispatch_data.`inv_dispatch_cost`, + erp_dispatch_data.`inv_trans_fee`, + erp_dispatch_data.`inv_produce_cost`, + erp_dispatch_data.`create_time` + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/exl/ExlTableConfMapper.xml b/src/main/resources/mapper/exl/ExlTableConfMapper.xml new file mode 100644 index 0000000..dfe1de5 --- /dev/null +++ b/src/main/resources/mapper/exl/ExlTableConfMapper.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + exl_table_conf.`id`, + exl_table_conf.`table_name`, + exl_table_conf.`excel_title`, + exl_table_conf.`enable_flag`, + exl_table_conf.`enable_time`, + exl_table_conf.`remark`, + exl_table_conf.`create_time`, + exl_table_conf.`update_time`, + exl_table_conf.`tenant_id`, + exl_table_conf.`create_by`, + exl_table_conf.`update_by`, + exl_table_conf.`del_flag` + + + + + + and + + ${item.column} <= #{item.value} + + + + and + + ${item.column} >= #{item.value} + + + + and + + ${item.column} = #{item.value} + + + + and + + + ${item.column} like concat('%', #{item.value} ,'%') + + + 1=1 + + + + + and + + ${inItem.column} in ( + + #{item} + + ) + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/goods/GoodsAccreditMapper.xml b/src/main/resources/mapper/goods/GoodsAccreditMapper.xml new file mode 100644 index 0000000..10a4d7c --- /dev/null +++ b/src/main/resources/mapper/goods/GoodsAccreditMapper.xml @@ -0,0 +1,132 @@ + + + + + + + select + 'accredit' as unionType, + goods_accredit.`sku_id`, + goods_accredit.`spu_id`, + goods_accredit.`category_id`, + + goods_accredit_item.`acc_type`, + goods_accredit_item.`target_id`, + + goods_accredit.`code`, + goods_accredit.`name`, + + '0' as biz_region_id, + '0' as sale_region_id, + '0' as supplier_id, + '0' as user_id, + + goods_accredit_item.id+'_goods' as id, + goods_accredit_item.`target_type`, + goods_accredit_item.`target_code`, + goods_accredit_item.`target_name`, + + goods_accredit_item.create_time, + sys_user.name as `create_user`, + sys_user.code as `create_user_code` + + from goods_accredit + left join goods_accredit_item + on goods_accredit.id = goods_accredit_item.acc_id + left join sys_user on sys_user.id = goods_accredit_item.create_by + + and `goods_accredit`.`del_flag` = 0 + and `goods_accredit_item`.`del_flag` = 0 + and `goods_accredit`.`empty_flag` = 0 + + + and ( sys_user.`code` like concat('%',#{query.userKeywords},'%') + or sys_user.`name` like concat('%',#{query.userKeywords},'%') ) + + + and goods_accredit.`code` in + + #{codeitem} + + + + and goods_accredit_item.`target_code` in + + #{codeitem} + + + + + + + + + select + 'rule' as unionType, + '0' as sku_id, + '0' as `spu_id`, + '0' as `category_id`, + + '0' as `acc_type`, + '0' as target_id, + + goods_rule_item.target_code as `code`, + goods_rule_item.target_name as `name`, + + goods_rule.biz_region_id, + goods_rule.sale_region_id, + goods_rule.supplier_id, + goods_rule.user_id, + + goods_rule_item.id + '_rul' as id, + goods_rule_item.target_type, + goods_rule.code as target_code, + goods_rule.name as target_name, + + goods_rule_item.create_time, + sys_user.name as `create_user`, + sys_user.code as `create_user_code` + + from goods_rule + left join goods_rule_item + on goods_rule.id = goods_rule_item.rule_id + left join sys_user on sys_user.id = goods_rule_item.create_by + where 1=1 + AND`goods_rule`.`del_flag` = 0 + AND `goods_rule_item`.`del_flag` = 0 + AND goods_rule.empty_flag = 0 + + + and ( sys_user.`code` like concat('%',#{query.userKeywords},'%') + or sys_user.`name` like concat('%',#{query.userKeywords},'%') ) + + + and goods_rule_item.`target_code` in + + #{codeitem} + + + + and goods_rule.`code` in + + #{codeitem} + + + + + + + + + + diff --git a/src/main/resources/mapper/goods/GoodsCustomerPriceMapper.xml b/src/main/resources/mapper/goods/GoodsCustomerPriceMapper.xml new file mode 100644 index 0000000..2278400 --- /dev/null +++ b/src/main/resources/mapper/goods/GoodsCustomerPriceMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + goods_customer_price.`id`, + goods_customer_price.`supplier_id`, + goods_customer_price.`supplier_code`, + goods_customer_price.`supplier_name`, + goods_customer_price.`sku_code`, + goods_customer_price.`sku_id`, + goods_customer_price.`sku_name`, + goods_customer_price.`sku_unit`, + goods_customer_price.`init_price`, + goods_customer_price.`real_price`, + goods_customer_price.`maker`, + goods_customer_price.`maker_code`, + goods_customer_price.`mark_time` + + + + diff --git a/src/main/resources/mapper/goods/GoodsImminentBatchMapper.xml b/src/main/resources/mapper/goods/GoodsImminentBatchMapper.xml new file mode 100644 index 0000000..1c9e6b7 --- /dev/null +++ b/src/main/resources/mapper/goods/GoodsImminentBatchMapper.xml @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + goods_imminent_batch.`id`, + goods_imminent_batch.`batch_code`, + goods_imminent_batch.`quantity`, + goods_imminent_batch.`order_quantity`, + goods_imminent_batch.`end_date`, + goods_imminent_batch.`remark` + + + + + + + + goods_sku.`sku_name`, + goods_sku.`sku_code`, + goods_sku.`pic_url`, + goods_sku.`sales_price`, + goods_sku.`market_price`, + goods_sku.`cost_price`, + goods_sku.`spec_infos`, + goods_sku.`stock`, + goods_sku.`unit_id`, + goods_sku.`unit_name`, + goods_sku.`weight`, + goods_sku.`volume`, + goods_sku.`inv_unit_weight`, + goods_sku.`min_purchase`, + goods_sku.`cost_flag`, + goods_sku.`belong`, + goods_sku.`belong_sort`, + goods_sku.`wrap_val`, + goods_sku.`taste_val`, + goods_sku.`order_flag`, + goods_sku.`special_flag`, + goods_sku.`abct`, + goods_sku.`order_online_flag`, + goods_sku.`order_offline_flag`, + goods_sku.`book_belong`, + goods_sku.`book_name` + + + + goods_spu.`spu_code`, + goods_spu.`name` as `spu_name`, + goods_spu.`category_first`, + goods_spu.`category_second`, + goods_spu.`category_third`, + goods_spu.`category_last`, + goods_spu.`pic_urls`, + goods_spu.`shelf`, + goods_spu.`sort`, + goods_spu.`sale_num`, + goods_spu.`spec_type`, + goods_spu.`taste_value`, + goods_spu.`create_time`, + goods_spu.`update_time`, + goods_spu.`create_by`, + goods_spu.`update_by`, + goods_spu.`tenant_id`, + goods_spu.`cost_flag`, + goods_spu.`order_flag`, + goods_spu.`book_belong`, + goods_spu.`book_name`, + goods_spu.`special_sku_id`, + goods_spu.`spu_cunhuo_flag`, + goods_spu.`sku_num_val` + + + + + and `goods_spu`.`name` like concat('%',#{query.spuName},'%') + + and (`goods_spu`.`name` like concat('%',#{query.spuCodeOrName},'%') or `goods_spu`.`spu_code` like concat('%',#{query.spuCodeOrName},'%')) + + and `goods_spu`.`spu_code` like concat('%',#{query.spuCode},'%') + + and `goods_spu`.`book_belong` in + + #{selectId} + + + + + and `goods_spu`.`id` in + + #{selectId} + + + + and `goods_spu`.`id` not in + + #{selectId} + + + + and (`goods_spu`.`category_first` in + + #{selectId} + + or `goods_spu`.`category_second` in + + #{selectId} + + or `goods_spu`.`category_third` in + + #{selectId} + ) + + + and (`goods_spu`.`category_first` not in + + #{selectId} + + and `goods_spu`.`category_second` not in + + #{selectId} + + and `goods_spu`.`category_third` not in + + #{selectId} + ) + + + + + and (`goods_sku`.`belong` = #{query.belong} or goods_sku.special_flag=1) + + + and `goods_sku`.`special_flag` = #{query.selectSpecialFlag} + + + and `goods_sku`.`sku_add_code` like concat('%', #{query.skuAddCode},'%') + + + and (`goods_sku`.`order_flag` = #{query.orderFlag} or `goods_sku`.`special_flag` = 1) + + + + and `goods_sku`.`sku_name` like concat('%', #{query.skuName},'%') + + + and `goods_sku`.`sku_code` like concat('%', #{query.skuCode},'%') + + + and `goods_sku`.`id` not in + + #{selectId} + + + + and `goods_sku`.`id` not in( + select sku.id FROM goods_sku sku + left join goods_spu spu on sku.spu_id = spu.id + left join goods_category cate1 on cate1.id = spu.category_first + left join goods_category cate2 on cate2.id = spu.category_second + left join goods_category cate3 on cate3.id = spu.category_third + where + ( + sku.id in + + #{selectId} + + or spu.id in + + #{selectId} + + or cate1.id in + + #{selectId} + + or cate2.id in + + #{selectId} + + or cate3.id in + + #{selectId} + + ) and + sku.id not in + + #{selectId} + + and + spu.id not in + + #{selectId} + + and + cate1.id not in + + #{selectId} + + and + cate2.id not in + + #{selectId} + + and + cate3.id not in + + #{selectId} + + ) + + + + diff --git a/src/main/resources/mapper/goods/GoodsSkuMapper.xml b/src/main/resources/mapper/goods/GoodsSkuMapper.xml new file mode 100644 index 0000000..d6abc02 --- /dev/null +++ b/src/main/resources/mapper/goods/GoodsSkuMapper.xml @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + goods_sku.`id`, + goods_sku.`sku_code`, + goods_sku.`sku_add_code`, + goods_sku.`sku_name`, + goods_sku.`spu_id`, + goods_sku.`pic_url`, + goods_sku.`sales_price`, + goods_sku.`market_price`, + goods_sku.`cost_price`, + goods_sku.`inv_unit_weight`, + goods_sku.`spec_infos`, + goods_sku.`stock`, + goods_sku.`unit_id`, + goods_sku.`unit_name`, + goods_sku.`weight`, + goods_sku.`volume`, + `goods_sku`.`order_online_flag`, + `goods_sku`.`order_offline_flag`, + goods_sku.`wrap_val`, + goods_sku.`taste_val`, + goods_sku.`min_purchase`, + goods_sku.`enable`, + goods_sku.`version`, + goods_sku.`remark`, + goods_sku.`update_time`, + goods_sku.`create_time`, + goods_sku.`tenant_id`, + goods_sku.`del_flag`, + goods_sku.`create_by`, + goods_sku.`cost_flag`, + goods_sku.`update_by`, + goods_sku.`special_flag`, + goods_sku.`order_flag`, + goods_sku.`belong`, + goods_sku.`book_belong`, + goods_sku.`book_name` + + + + update `goods_sku` + LEFT JOIN `goods_spu` + ON goods_sku.spu_id = goods_spu.id + set goods_sku.book_belong = #{bookCode},goods_sku.book_name = #{bookName} + WHERE + 1=1 + and goods_sku.del_flag = 0 + and goods_sku.enable = 1 + and goods_spu.shelf = 1 + and ( + goods_spu.category_third in + + #{selectId} + + or + goods_spu.category_second in + + #{selectId} + + or + goods_spu.category_first in + + #{selectId} + + ) + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/goods/GoodsSpuMapper.xml b/src/main/resources/mapper/goods/GoodsSpuMapper.xml new file mode 100644 index 0000000..3882c53 --- /dev/null +++ b/src/main/resources/mapper/goods/GoodsSpuMapper.xml @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + goods_sku.volume, + goods_sku.weight, + goods_sku.sales_price as sku_price, + goods_sku.sku_name as sku_name, + goods_sku.id as sku_id, + goods_sku.sku_code as sku_code, + goods_sku.special_flag as sku_special_flag, + goods_sku.belong as sku_belong + + + + + goods_spu.`id`, + goods_spu.`spu_code`, + goods_spu.`name`, + goods_spu.`category_first`, + goods_spu.`category_second`, + goods_spu.`category_third`, + goods_spu.`category_last`, + goods_spu.`pic_urls`, + goods_spu.`shelf`, + goods_spu.`sort`, + goods_spu.`sale_num`, + goods_spu.`spec_type`, + goods_spu.`taste_value`, + goods_spu.`create_time`, + goods_spu.`update_time`, + goods_spu.`create_by`, + goods_spu.`update_by`, + goods_spu.`tenant_id`, + goods_spu.`cost_flag`, + goods_spu.`order_flag`, + goods_spu.`book_belong`, + goods_spu.`book_name`, + goods_spu.`del_flag`, + goods_spu.`special_sku_id`, + goods_spu.`spu_cunhuo_flag`, + goods_spu.`sku_num_val` + + + + and (`goods_sku`.`belong` = #{query.belong} or goods_sku.special_flag=1) + + + and `goods_sku`.`special_flag` = #{query.selectSpecialFlag} + + + and `goods_sku`.`sku_add_code` like concat('%', #{query.skuAddCode},'%') + + + and (`goods_sku`.`order_flag` = #{query.orderFlag} or `goods_sku`.`special_flag` = 1) + + + + and ( + `goods_spu`.`name` like concat('%', #{query.keyword},'%') or + `goods_spu`.`spu_code` like concat('%', #{query.keyword},'%') or + `goods_sku`.`sku_code` like concat('%', #{query.keyword},'%') or + `goods_sku`.`sku_name` like concat('%', #{query.keyword},'%') + ) + + + and `goods_sku`.`id` not in + + #{selectId} + + + + and `goods_sku`.`id` not in( + select sku.id FROM goods_sku sku + left join goods_spu spu on sku.spu_id = spu.id + left join goods_category cate1 on cate1.id = spu.category_first + left join goods_category cate2 on cate2.id = spu.category_second + left join goods_category cate3 on cate3.id = spu.category_third + where + ( + sku.id in + + #{selectId} + + or spu.id in + + #{selectId} + + or cate1.id in + + #{selectId} + + or cate2.id in + + #{selectId} + + or cate3.id in + + #{selectId} + + ) and + sku.id not in + + #{selectId} + + and + spu.id not in + + #{selectId} + + and + cate1.id not in + + #{selectId} + + and + cate2.id not in + + #{selectId} + + and + cate3.id not in + + #{selectId} + + ) + + + + + and `goods_spu`.`del_flag` = 0 + and `goods_spu`.`id` = #{query.id} + and `goods_spu`.`spu_code` like concat('%', #{query.spuCode},'%') + + and (`goods_spu`.`spu_code` like concat('%', #{query.spuCodeOrName},'%') or `goods_spu`.`name` like concat('%', #{query.spuCodeOrName},'%') ) + + and `goods_spu`.`name` like concat('%', #{query.name},'%') + and `goods_spu`.`category_first` = #{query.categoryFirst} + and `goods_spu`.`category_second` = #{query.categorySecond} + and `goods_spu`.`category_third` = #{query.categoryThird} + and `cate1`.`name` like concat('%',#{query.cateFirstLabel},'%') + and `cate2`.`name` like concat('%',#{query.cateSecondLabel},'%') + and `cate3`.`name` like concat('%',#{query.cateThirdLabel},'%') + and `goods_spu`.`category_last` = #{query.categoryLast} + and `goods_spu`.`shelf` = #{query.shelf} + and `goods_spu`.`cost_flag` = #{query.costFlag} + and `goods_spu`.`order_online_flag` = #{query.orderOnlineFlag} + and `goods_spu`.`order_offline_flag` = #{query.orderOfflineFlag} + and `goods_spu`.`spu_cunhuo_flag` = #{query.spuCunhuoFlag} + and `goods_spu`.`order_flag` = #{query.orderFlag} + and `goods_spu`.`sort` = #{query.sort} + and `goods_spu`.`book_belong` = #{query.bookBelong} + and `goods_spu`.`sale_num` = #{query.saleNum} + and `goods_spu`.`taste_value` like concat('%',#{query.tasteValue},'%') + and `goods_spu`.`create_time` = #{query.createTime} + and `goods_spu`.`update_time` = #{query.updateTime} + and `goods_spu`.`create_by` = #{query.createBy} + and `goods_spu`.`update_by` = #{query.updateBy} + and `goods_spu`.`tenant_id` = #{query.tenantId} + and `goods_spu`.`del_flag` = #{query.delFlag} + + + and (`goods_spu`.`name` like concat('%',#{query.searchValue},'%') or `goods_spu`.`goods_spu` like concat('%',#{query.searchValue},'%')) + + + and `goods_spu`.`book_belong` in + + #{selectId} + + + + + and `goods_spu`.`id` in + + #{selectId} + + + + and `goods_spu`.`id` not in + + #{selectId} + + + + and (`goods_spu`.`category_first` in + + #{selectId} + + or `goods_spu`.`category_second` in + + #{selectId} + + or `goods_spu`.`category_third` in + + #{selectId} + ) + + + and (`goods_spu`.`category_first` not in + + #{selectId} + + and `goods_spu`.`category_second` not in + + #{selectId} + + and `goods_spu`.`category_third` not in + + #{selectId} + ) + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/his/HisUserChannelPointMapper.xml b/src/main/resources/mapper/his/HisUserChannelPointMapper.xml new file mode 100644 index 0000000..e9f352b --- /dev/null +++ b/src/main/resources/mapper/his/HisUserChannelPointMapper.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + his_user_channel_point.`id`, + his_user_channel_point.`user_id`, + his_user_channel_point.`point_id`, + his_user_channel_point.`source_type`, + his_user_channel_point.`source_ids`, + his_user_channel_point.`remark`, + his_user_channel_point.`create_time`, + his_user_channel_point.`update_time`, + his_user_channel_point.`tenant_id`, + his_user_channel_point.`del_flag`, + his_user_channel_point.`create_by`, + his_user_channel_point.`update_by`, + his_user_channel_point.`cost_flag` + + + + diff --git a/src/main/resources/mapper/his/HisUserSupplierMapper.xml b/src/main/resources/mapper/his/HisUserSupplierMapper.xml new file mode 100644 index 0000000..e7f3f21 --- /dev/null +++ b/src/main/resources/mapper/his/HisUserSupplierMapper.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/pay/PayPaymentItemMapper.xml b/src/main/resources/mapper/pay/PayPaymentItemMapper.xml new file mode 100644 index 0000000..9273760 --- /dev/null +++ b/src/main/resources/mapper/pay/PayPaymentItemMapper.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pay_payment_item.`id`, + pay_payment_item.`pay_type`, + pay_payment_item.`payment_id`, + pay_payment_item.`supplier_id`, + pay_payment_item.`item_pay_amount`, + pay_payment_item.`verification_id`, + pay_payment_item.`verification_subject_id`, + pay_payment_item.`cost_apply_id`, + pay_payment_item.`activity_id`, + pay_payment_item.`activity_code`, + pay_payment_item.`subject_id`, + pay_payment_item.`subject_code`, + pay_payment_item.`subject_name`, + pay_payment_item.`remark`, + pay_payment_item.`create_time`, + pay_payment_item.`update_time`, + pay_payment_item.`tenant_id`, + pay_payment_item.`create_by`, + pay_payment_item.`update_by`, + pay_payment_item.`del_flag`, + pay_payment_item.`policy_item_id`, + pay_payment_item.`policy_item_code` + + + + + + + + + + + + + update pay_payment_item set sync_act_flag = 1 + where activity_id in + + #{selectId} + + + + + update pay_payment set sync_cost_state = 1 + where cost_apply_id in + + #{selectId} + + + + diff --git a/src/main/resources/mapper/pay/PaySupplierMapper.xml b/src/main/resources/mapper/pay/PaySupplierMapper.xml new file mode 100644 index 0000000..f5723cf --- /dev/null +++ b/src/main/resources/mapper/pay/PaySupplierMapper.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/qms/QmsGroupMapper.xml b/src/main/resources/mapper/qms/QmsGroupMapper.xml new file mode 100644 index 0000000..c407230 --- /dev/null +++ b/src/main/resources/mapper/qms/QmsGroupMapper.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + qms_group.`id`, + qms_group.`name`, + qms_group.`descr`, + qms_group.`form_id`, + qms_group.`form_context`, + qms_group.`publish_state`, + qms_group.`version`, + qms_group.`remark`, + qms_group.`create_time`, + qms_group.`create_by`, + qms_group.`update_time`, + qms_group.`update_by`, + qms_group.`tenant_id`, + qms_group.`del_flag` + + + + + + diff --git a/src/main/resources/mapper/qms/QmsGroupScopeMapper.xml b/src/main/resources/mapper/qms/QmsGroupScopeMapper.xml new file mode 100644 index 0000000..9e55091 --- /dev/null +++ b/src/main/resources/mapper/qms/QmsGroupScopeMapper.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + qms_group_scope.`id`, + qms_group_scope.`group_id`, + qms_group_scope.`scope_type`, + qms_group_scope.`scope_value`, + qms_group_scope.`finished`, + qms_group_scope.`del_flag`, + qms_group_scope.`tenant_id`, + qms_group_scope.`create_time`, + qms_group_scope.`create_by`, + qms_group_scope.`update_time`, + qms_group_scope.`update_by` + + + + + + diff --git a/src/main/resources/mapper/seeyon/CommonCheckMapper.xml b/src/main/resources/mapper/seeyon/CommonCheckMapper.xml new file mode 100644 index 0000000..5cf0b77 --- /dev/null +++ b/src/main/resources/mapper/seeyon/CommonCheckMapper.xml @@ -0,0 +1,508 @@ + + + + + + + + + diff --git a/src/main/resources/mapper/sys/SysDeptMapper.xml b/src/main/resources/mapper/sys/SysDeptMapper.xml new file mode 100644 index 0000000..c534fa8 --- /dev/null +++ b/src/main/resources/mapper/sys/SysDeptMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + sys_dept.id, + sys_dept.name, + sys_dept.code, + sys_dept.parent_id, + sys_dept.mgr_user_id, + sys_dept.level_path, + sys_dept.create_time, + sys_dept.create_by, + sys_dept.update_time, + sys_dept.update_by + + + + + + diff --git a/src/main/resources/mapper/sys/SysMenuMapper.xml b/src/main/resources/mapper/sys/SysMenuMapper.xml new file mode 100644 index 0000000..3e866a8 --- /dev/null +++ b/src/main/resources/mapper/sys/SysMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + sys_menu.`id`, + sys_menu.`name`, + sys_menu.`sort`, + sys_menu.`pid`, + sys_menu.`type`, + sys_menu.`client_type`, + sys_menu.`hide_flag`, + sys_menu.`del_flag` + + + + + diff --git a/src/main/resources/mapper/sys/SysNoticeUsermapper.xml b/src/main/resources/mapper/sys/SysNoticeUsermapper.xml new file mode 100644 index 0000000..ea94e95 --- /dev/null +++ b/src/main/resources/mapper/sys/SysNoticeUsermapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + `sys_notice_user`.`id`, + `sys_notice_user`.`notice_id`, + `sys_notice_user`.`user_id`, + `sys_notice_user`.`read_flag`, + `sys_notice_user`.`read_time`, + `sys_notice_user`.`read_count`, + `sys_notice_user`.`create_time`, + `sys_notice_user`.`create_by`, + `sys_notice_user`.`update_time`, + `sys_notice_user`.`update_by`, + `sys_notice_user`.`tenant_id`, + `sys_notice_user`.`del_flag` + + + + + + diff --git a/src/main/resources/mapper/sys/SysOperationLogMapper.xml b/src/main/resources/mapper/sys/SysOperationLogMapper.xml new file mode 100644 index 0000000..34494d6 --- /dev/null +++ b/src/main/resources/mapper/sys/SysOperationLogMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sys_operation_log.id, + sys_operation_log.title, + sys_operation_log.biz_type, + sys_operation_log.inter_type, + sys_operation_log.code_method, + sys_operation_log.req_method, + sys_operation_log.req_url, + sys_operation_log.req_param, + sys_operation_log.req_ip, + sys_operation_log.user_type, + sys_operation_log.user_id, + sys_operation_log.err_msg, + sys_operation_log.json_result, + sys_operation_log.elapsed_time, + sys_operation_log.user_agent, + sys_operation_log.create_time, + sys_operation_log.create_by, + sys_operation_log.update_time, + sys_operation_log.update_by + + + + INSERT INTO sys_operation_log + (module,title, biz_type, inter_type, code_method, req_method, req_url, req_param, req_ip, user_type, user_id, + err_msg, json_result, elapsed_time, user_agent, create_time, create_by, tenant_id,creator_name) + VALUES + ( #{module},#{title}, #{bizType}, #{interType}, #{codeMethod}, #{reqMethod}, #{reqUrl}, #{reqParam}, #{reqIp}, #{userType}, #{userId}, + #{errMsg}, #{jsonResult}, #{elapsedTime}, #{userAgent}, now(), #{userId}, #{tenantId},#{creatorName}); + + + + + + diff --git a/src/main/resources/mapper/sys/SysUserMapper.xml b/src/main/resources/mapper/sys/SysUserMapper.xml new file mode 100644 index 0000000..c7a09f3 --- /dev/null +++ b/src/main/resources/mapper/sys/SysUserMapper.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sys_user.id, + sys_user.mobile, + sys_user.account, + sys_user.name, + sys_user.code, + sys_user.password, + sys_user.icon, + sys_user.dept_id, + sys_user.super_flag, + sys_user.login_enable, + sys_user.serving_state, + sys_user.sales_flag, + sys_user.identity_no, + sys_user.remark, + sys_user.app_client, + sys_user.app_token, + sys_user.create_time, + sys_user.create_by, + sys_user.update_time, + sys_user.update_by, + sys_user.del_flag, + sys_user.sy_account, + sys_user.sy_user_id, + sys_user.tenant_id + + + + diff --git a/src/main/resources/mapper/sys/SysUserSalesMapper.xml b/src/main/resources/mapper/sys/SysUserSalesMapper.xml new file mode 100644 index 0000000..f568802 --- /dev/null +++ b/src/main/resources/mapper/sys/SysUserSalesMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + sys_user.id, + sys_user.mobile, + sys_user.account, + sys_user.name, + sys_user.code, + sys_user.icon, + sys_user.dept_id, + sys_user.position_id, + sys_user.super_flag, + sys_user.login_enable, + sys_user.serving_state, + sys_user.sales_flag, + sys_user.identity_no, + sys_user.remark, + sys_user_sales.`user_id`, + sys_user_sales.`pid` + + + + diff --git a/src/main/resources/mapper/tag/TagDataMapper.xml b/src/main/resources/mapper/tag/TagDataMapper.xml new file mode 100644 index 0000000..a675220 --- /dev/null +++ b/src/main/resources/mapper/tag/TagDataMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + tag_data.`id`, + tag_data.`tag_name`, + tag_data.`tag_id`, + tag_data.`target_type`, + tag_data.`target_id`, + tag_data.`target_code`, + tag_data.`target_name`, + tag_data.`remark`, + tag_data.`create_time`, + tag_data.`start_date`, + tag_data.`end_date`, + tag_data.`update_time`, + tag_data.`create_by`, + tag_data.`update_by`, + tag_data.`tenant_id`, + tag_data.`del_flag` + + + + + + + and ${tagQuery.sqlColumn} in + ( + select target_id from tag_data + left join tag_info on tag_data.tag_id = tag_info.id and tag_info.del_flag=0 + where tag_data.del_flag = 0 + and (tag_data.start_date is null or tag_data.start_date >= now() ) + and (tag_data.end_date is null or tag_data.end_date <= now() ) + + and tag_id in + + #{selectId} + + + + and tag_info.tag_name like concat('%',#{tagQuery.tagName},'%') + + and tag_data.target_type = #{tagQuery.targetType} + group by tag_data.target_id + ) + + + + + diff --git a/src/main/resources/mapper/tbs/TbsBudget2Mapper.xml b/src/main/resources/mapper/tbs/TbsBudget2Mapper.xml new file mode 100644 index 0000000..af48d51 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsBudget2Mapper.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tbs/TbsBudgetChangeMapper.xml b/src/main/resources/mapper/tbs/TbsBudgetChangeMapper.xml new file mode 100644 index 0000000..bdd7dba --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsBudgetChangeMapper.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tbs/TbsBudgetConditionMapper.xml b/src/main/resources/mapper/tbs/TbsBudgetConditionMapper.xml new file mode 100644 index 0000000..84668a4 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsBudgetConditionMapper.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + tbs_budget_condition.`id`, + tbs_budget_condition.`budgt_id`, + tbs_budget_condition.`target_type`, + tbs_budget_condition.`target_id`, + tbs_budget_condition.`target_code`, + tbs_budget_condition.`target_name`, + tbs_budget_condition.`target_level_path_ids`, + tbs_budget_condition.`target_level_path_names`, + tbs_budget_condition.`remark`, + tbs_budget_condition.`create_time`, + tbs_budget_condition.`update_time`, + tbs_budget_condition.`tenant_id`, + tbs_budget_condition.`create_by`, + tbs_budget_condition.`update_by`, + tbs_budget_condition.`del_flag` + + + + + diff --git a/src/main/resources/mapper/tbs/TbsBudgetMapper.xml b/src/main/resources/mapper/tbs/TbsBudgetMapper.xml new file mode 100644 index 0000000..2389d29 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsBudgetMapper.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + tbs_budget.`id`, + tbs_budget.`subject_id`, + tbs_budget.`subject_code`, + tbs_budget.`subject_name`, + tbs_budget.`center_type`, + tbs_budget.`center_id`, + tbs_budget.`center_code`, + tbs_budget.`center_name`, + tbs_budget.`schedule_id`, + tbs_budget.`schedule_code`, + tbs_budget.`schedule_name`, + tbs_budget.`remark`, + tbs_budget.`create_time`, + tbs_budget.`update_time`, + tbs_budget.`tenant_id`, + tbs_budget.`create_by`, + tbs_budget.`update_by`, + tbs_budget.`del_flag` + + + + + + diff --git a/src/main/resources/mapper/tbs/TbsBudgetMatchMapper.xml b/src/main/resources/mapper/tbs/TbsBudgetMatchMapper.xml new file mode 100644 index 0000000..c9f774c --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsBudgetMatchMapper.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tbs/TbsCostApplyMapper.xml b/src/main/resources/mapper/tbs/TbsCostApplyMapper.xml new file mode 100644 index 0000000..5f3a114 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsCostApplyMapper.xml @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tbs_cost_apply.`id`, + tbs_cost_apply.`code`, + tbs_cost_apply.`charge_theme`, + tbs_cost_apply.`supplier_id`, + tbs_cost_apply.`supplier_code`, + tbs_cost_apply.`supplier_name`, + tbs_cost_apply.`supplier_biz_region_first_name`, + tbs_cost_apply.`supplier_biz_region_second_name`, + tbs_cost_apply.`supplier_biz_region_third_name`, + tbs_cost_apply.`charge_state`, + tbs_cost_apply.`check_state`, + tbs_cost_apply.`submit_time`, + tbs_cost_apply.`pass_time`, + tbs_cost_apply.`remark`, + tbs_cost_apply.`user_id`, + tbs_cost_apply.`user_code`, + tbs_cost_apply.`user_name`, + tbs_cost_apply.`sy_form_id`, + tbs_cost_apply.`sy_flow_id`, + tbs_cost_apply.`total_activity`, + tbs_cost_apply.`total_activity_amount`, + tbs_cost_apply.`total_activity_used_amount`, + tbs_cost_apply.`contract_flag`, + tbs_cost_apply.`create_time`, + tbs_cost_apply.`update_time`, + tbs_cost_apply.`tenant_id`, + tbs_cost_apply.`create_by`, + tbs_cost_apply.`update_by`, + tbs_cost_apply.`del_flag`, + tbs_cost_apply.`template_id`, + tbs_cost_apply.`change_source_id`, + tbs_cost_apply.`change_extend_id`, + tbs_cost_apply.`cancel_flag`, + tbs_cost_apply.`ext_user_id`, + tbs_cost_apply.`ext_user_code`, + tbs_cost_apply.`ext_user_name`, + tbs_cost_apply.`template_title` + + + + update tbs_cost_apply + set ext_user_id = #{obj.id},ext_user_id=#{obj.id},ext_user_name=#{obj.name},ext_user_code=#{obj.code} + where del_flag=0 and id in + + #{selectId} + + + + update tbs_cost_apply set ext_user_id = null,ext_user_id=null,ext_user_name=null,ext_user_code where id in + + #{selectId} + + + + + + + + + + + + + and `tbs_cost_apply`.`check_state` = #{query.checkState} + and `tbs_cost_apply`.`id` = #{query.id} + and `tbs_cost_apply`.`code` like concat('%', #{query.code},'%') + and `tbs_cost_apply`.`charge_theme` like concat('%', #{query.chargeTheme},'%') + and `tbs_cost_apply`.`supplier_id` = #{query.supplierId} + and `tbs_cost_apply`.`supplier_code` like concat('%', #{query.supplierCode},'%') + and `tbs_cost_apply`.`supplier_name` like concat('%', #{query.supplierName},'%') + and `tbs_cost_apply`.`supplier_biz_region_first_name` like concat('%', #{query.supplierBizRegionFirstName},'%') + and `tbs_cost_apply`.`supplier_biz_region_second_name` like concat('%', #{query.supplierBizRegionSecondName},'%') + and `tbs_cost_apply`.`supplier_biz_region_third_name` like concat('%', #{query.supplierBizRegionThirdName},'%') + and `tbs_cost_apply`.`charge_state` = #{query.chargeState} + and `tbs_cost_apply`.`submit_time` = #{query.submitTime} + and `tbs_cost_apply`.`pass_time` = #{query.passTime} + and `tbs_cost_apply`.`user_id` = #{query.userId} + and `tbs_cost_apply`.`user_code` like concat('%', #{query.userCode},'%') + and `tbs_cost_apply`.`user_name` like concat('%', #{query.userName},'%') + and `tbs_cost_apply`.`sy_form_id` = #{query.syFormId} + and `tbs_cost_apply`.`sy_flow_id` = #{query.syFlowId} + and `tbs_cost_apply`.`total_activity` = #{query.totalActivity} + and `tbs_cost_apply`.`total_activity_amount` = #{query.totalActivityAmount} + and `tbs_cost_apply`.`total_activity_used_amount` = #{query.totalActivityUsedAmount} + and `tbs_cost_apply`.`contract_flag` = #{query.contractFlag} + and `tbs_cost_apply`.`create_time` = #{query.createTime} + and `tbs_cost_apply`.`update_time` = #{query.updateTime} + and `tbs_cost_apply`.`tenant_id` = #{query.tenantId} + and `tbs_cost_apply`.`create_by` = #{query.createBy} + and `tbs_cost_apply`.`update_by` = #{query.updateBy} + and `tbs_cost_apply`.`ext_user_name` like concat('%', #{query.extUserName},'%') + and `tbs_cost_apply`.`del_flag` = #{query.delFlag} + and `tbs_cost_apply`.`template_title` like concat('%', #{query.templateTitle},'%') + + + + + diff --git a/src/main/resources/mapper/tbs/TbsCostApplySumAmountMapper.xml b/src/main/resources/mapper/tbs/TbsCostApplySumAmountMapper.xml new file mode 100644 index 0000000..436efc9 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsCostApplySumAmountMapper.xml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tbs/TbsCostTodoMapper.xml b/src/main/resources/mapper/tbs/TbsCostTodoMapper.xml new file mode 100644 index 0000000..5b950f5 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsCostTodoMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tbs_cost_todo.`id`, + tbs_cost_todo.`todo_code`, + tbs_cost_todo.`cost_apply_id`, + tbs_cost_todo.`check_status`, + tbs_cost_todo.`sy_from_id`, + tbs_cost_todo.`submit_time`, + tbs_cost_todo.`brands`, + tbs_cost_todo.`descr`, + tbs_cost_todo.`amount`, + tbs_cost_todo.`finished_flag`, + tbs_cost_todo.`finished_time`, + tbs_cost_todo.`remark`, + tbs_cost_todo.`create_time`, + tbs_cost_todo.`create_by`, + tbs_cost_todo.`update_time`, + tbs_cost_todo.`update_by`, + tbs_cost_todo.`del_flag`, + tbs_cost_todo.`tenant_id`, + tbs_cost_todo.`pay_msg`, + tbs_cost_todo.`pre_pay_date` + + + + diff --git a/src/main/resources/mapper/tbs/TbsScheduleItemBudget2Mapper.xml b/src/main/resources/mapper/tbs/TbsScheduleItemBudget2Mapper.xml new file mode 100644 index 0000000..bf341c0 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsScheduleItemBudget2Mapper.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tbs/TbsScheduleItemBudgetMapper.xml b/src/main/resources/mapper/tbs/TbsScheduleItemBudgetMapper.xml new file mode 100644 index 0000000..0b5c5e8 --- /dev/null +++ b/src/main/resources/mapper/tbs/TbsScheduleItemBudgetMapper.xml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + tbs_schedule_item_budget.`id`, + tbs_schedule_item_budget.`schedule_id`, + tbs_schedule_item_budget.`schedule_item_id`, + tbs_schedule_item_budget.`item_name`, + tbs_schedule_item_budget.`start_date`, + tbs_schedule_item_budget.`end_date`, + tbs_schedule_item_budget.`budget_id`, + tbs_schedule_item_budget.`budget_amount`, + tbs_schedule_item_budget.`remark`, + tbs_schedule_item_budget.`create_time`, + tbs_schedule_item_budget.`update_time`, + tbs_schedule_item_budget.`tenant_id`, + tbs_schedule_item_budget.`create_by`, + tbs_schedule_item_budget.`update_by`, + tbs_schedule_item_budget.`del_flag` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tzc/TzcPolicyMapper.xml b/src/main/resources/mapper/tzc/TzcPolicyMapper.xml new file mode 100644 index 0000000..b51220c --- /dev/null +++ b/src/main/resources/mapper/tzc/TzcPolicyMapper.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tzc_policy.`id`, + tzc_policy.`title`, + tzc_policy.`policy_code`, + tzc_policy.`policy_status`, + tzc_policy.`pass_time`, + tzc_policy.`submit_time`, + tzc_policy.`total_items`, + tzc_policy.`total_item_amount`, + tzc_policy.`total_item_used_amount`, + tzc_policy.`supplier_id`, + tzc_policy.`supplier_code`, + tzc_policy.`supplier_name`, + tzc_policy.`user_id`, + tzc_policy.`user_code`, + tzc_policy.`user_name`, + tzc_policy.`sy_flow_id`, + tzc_policy.`sy_form_id`, + tzc_policy.`remark`, + tzc_policy.`create_time`, + tzc_policy.`update_time`, + tzc_policy.`tenant_id`, + tzc_policy.`create_by`, + tzc_policy.`update_by`, + tzc_policy.`del_flag`, + tzc_policy.`ext_user_id`, + tzc_policy.`ext_user_code`, + tzc_policy.`ext_user_name` + + + + + + + update tzc_policy + set ext_user_id = #{obj.id},ext_user_code=#{obj.code},ext_user_name=#{obj.name} + where del_flag=0 and id in + + #{selectId} + + + + + update vtb_verification set ext_user_id = null,ext_user_id=null,ext_user_name=null where cost_apply_id in + + #{selectId} + + + + diff --git a/src/main/resources/mapper/vtb/VtbFundFlowMapper.xml b/src/main/resources/mapper/vtb/VtbFundFlowMapper.xml new file mode 100644 index 0000000..4805489 --- /dev/null +++ b/src/main/resources/mapper/vtb/VtbFundFlowMapper.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vtb_fund_flow.`id`, + vtb_fund_flow.`fund_type`, + vtb_fund_flow.`verification_id`, + vtb_fund_flow.`center_goods_code`, + vtb_fund_flow.`cost_apply_id`, + vtb_fund_flow.`activity_id`, + vtb_fund_flow.`subject_id`, + vtb_fund_flow.`subject_code`, + vtb_fund_flow.`subject_name`, + vtb_fund_flow.`center_type`, + vtb_fund_flow.`center_id`, + vtb_fund_flow.`center_code`, + vtb_fund_flow.`center_name`, + vtb_fund_flow.`used_amount`, + vtb_fund_flow.`target_type`, + vtb_fund_flow.`target_id`, + vtb_fund_flow.`target_code`, + vtb_fund_flow.`target_name`, + vtb_fund_flow.`target_level_path_ids`, + vtb_fund_flow.`target_level_path_names`, + vtb_fund_flow.`remark`, + vtb_fund_flow.`create_time`, + vtb_fund_flow.`update_time`, + vtb_fund_flow.`tenant_id`, + vtb_fund_flow.`create_by`, + vtb_fund_flow.`update_by`, + vtb_fund_flow.`del_flag`, + vtb_fund_flow.`center_good_item_id`, + vtb_fund_flow.`supplier_id`, + vtb_fund_flow.`supplier_code`, + vtb_fund_flow.`supplier_name` + + + + + + + + + + diff --git a/src/main/resources/mapper/vtb/VtbVerForPayReportMapper.xml b/src/main/resources/mapper/vtb/VtbVerForPayReportMapper.xml new file mode 100644 index 0000000..cbeb6d9 --- /dev/null +++ b/src/main/resources/mapper/vtb/VtbVerForPayReportMapper.xml @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + pay_payment_item.`id`, + pay_payment_item.`verification_main_code`, + pay_payment_item.`verification_code`, + pay_payment.`pay_code`, + pay_payment_item.`pay_time`, + pay_payment_item.`pay_date`, + pay_payment_item.`bill_number`, + pay_payment_item.`erp_id`, + pay_payment_item.`pay_type`, + pay_payment_item.`payment_id`, + pay_payment_item.`supplier_id`, + pay_payment_item.`item_pay_amount`, + pay_payment_item.`verification_id`, + pay_payment_item.`verification_subject_id`, + pay_payment_item.`cost_apply_id`, + cost.`code` as `cost_apply_code`, + cost.`charge_theme` as `cost_apply_title`, + act.`act_title` as `activity_title`, + pay_payment_item.`activity_id`, + pay_payment_item.`activity_code`, + pay_payment_item.`subject_id`, + pay_payment_item.`subject_code`, + pay_payment_item.`subject_name`, + pay_payment_item.`remark`, + pay_payment_item.`create_time`, + pay_payment_item.`policy_item_id`, + pay_payment_item.`policy_item_code` + + + + and pay_payment_item.del_flag = 0 + and vtb.del_flag = 0 + and act.del_flag = 0 + and act.cancel_flag = 0 + and pay_payment.del_flag = 0 + and `pay_payment_item`.`pay_type` = #{query.payType} + and `pay_payment`.`pay_code` like concat('%',#{query.payCode},'%') + and `pay_payment_item`.`payment_id` = #{query.paymentId} + and `cost`.`code` like concat('%',#{query.costApplyCode},'%') + and `pay_payment`.`supplier_code` like concat('%',#{query.supplierCode},'%') + and `pay_payment`.`supplier_name` like concat('%',#{query.supplierName},'%') + and `pay_payment`.`user_code` like concat('%',#{query.userCode},'%') + and `pay_payment`.`user_name` like concat('%',#{query.userName},'%') + and `cost`.`charge_theme` like concat('%',#{query.costApplyTitle},'%') + and `act`.`act_title` like concat('%',#{query.activityTitle},'%') + and `pay_payment_item`.`supplier_id` = #{query.supplierId} + and `pay_payment_item`.`cost_apply_id` = #{query.costApplyId} + and `pay_payment_item`.`activity_id` = #{query.activityId} + and `pay_payment_item`.`activity_code` like concat('%',#{query.activityCode},'%') + and `pay_payment_item`.`subject_code` = #{query.subjectCode} + and `pay_payment_item`.`subject_name` = #{query.subjectName} + and `pay_payment_item`.`policy_item_code` = #{query.policyItemCode} + + and `pay_payment_item`.`cost_apply_id` in + + #{selectId} + + + + + + + + + + + diff --git a/src/main/resources/mapper/vtb/VtbVerReportMapper.xml b/src/main/resources/mapper/vtb/VtbVerReportMapper.xml new file mode 100644 index 0000000..9763723 --- /dev/null +++ b/src/main/resources/mapper/vtb/VtbVerReportMapper.xml @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/vtb/VtbVerfifcationMapper.xml b/src/main/resources/mapper/vtb/VtbVerfifcationMapper.xml new file mode 100644 index 0000000..ce2e643 --- /dev/null +++ b/src/main/resources/mapper/vtb/VtbVerfifcationMapper.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vtb_verification.`id`, + vtb_verification.`verification_main_code`, + vtb_verification.`verification_code`, + vtb_verification.`finished_time`, + vtb_verification.`batch_id`, + vtb_verification.`cost_apply_id`, + vtb_verification.`activity_id`, + vtb_verification.`policy_item_id`, + vtb_verification.`policy_item_code`, + vtb_verification.`attach_ids`, + vtb_verification.`verification_state`, + vtb_verification.`payment_state`, + vtb_verification.`reg_release_flag`, + vtb_verification.`reg_release_user_id`, + vtb_verification.`amount`, + vtb_verification.`amount_record`, + vtb_verification.`way_id`, + vtb_verification.`way_title`, + vtb_verification.`dis_code`, + vtb_verification.`bill_number`, + vtb_verification.`remark`, + vtb_verification.`create_time`, + vtb_verification.`update_time`, + vtb_verification.`tenant_id`, + vtb_verification.`create_by`, + vtb_verification.`update_by`, + vtb_verification.`del_flag`, + vtb_verification.`sy_form_id`, + vtb_verification.`sy_flow_id`, + vtb_verification.`supplier_id`, + vtb_verification.`supplier_code`, + vtb_verification.`supplier_name`, + vtb_verification.`user_id`, + vtb_verification.`user_code`, + vtb_verification.`user_name`, + vtb_verification.`pay_condition_id`, + vtb_verification.`activity_code`, + vtb_verification.`cost_apply_code`, + vtb_verification.`supplier_biz_region_first_name`, + vtb_verification.`supplier_biz_region_second_name`, + vtb_verification.`supplier_biz_region_third_name`, + vtb_verification.`input_release_flag`, + vtb_verification.`pay_release_flag`, + vtb_verification.`ext_user_id`, + vtb_verification.`ext_user_code`, + vtb_verification.`ext_user_name`, + vtb_verification.`template_title` + + + + + + + update vtb_verification + set ext_user_id = #{obj.id},ext_user_code=#{obj.code},ext_user_name=#{obj.name},ext_user_code=#{obj.code} + where del_flag=0 and cost_apply_id in + + #{selectId} + + + + + update vtb_verification set sync_pay_flag=1 where verification_code in + + #{selectId} + + + + + update vtb_verification set ext_user_id = null,ext_user_id=null,ext_user_name=null where cost_apply_id in + + #{selectId} + + + + + + + diff --git a/src/main/resources/mapper/vtb/VtbVerificationBatchMapper.xml b/src/main/resources/mapper/vtb/VtbVerificationBatchMapper.xml new file mode 100644 index 0000000..e4653c7 --- /dev/null +++ b/src/main/resources/mapper/vtb/VtbVerificationBatchMapper.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vtb_verification_batch.`id`, + vtb_verification_batch.`vtb_batch_code`, + vtb_verification_batch.`vtb_batch_status`, + vtb_verification_batch.`finished_time`, + vtb_verification_batch.`cost_apply_id`, + vtb_verification_batch.`remark`, + vtb_verification_batch.`create_time`, + vtb_verification_batch.`update_time`, + vtb_verification_batch.`tenant_id`, + vtb_verification_batch.`create_by`, + vtb_verification_batch.`update_by`, + vtb_verification_batch.`del_flag`, + vtb_verification_batch.`sy_form_id`, + vtb_verification_batch.`sy_flow_id`, + vtb_verification_batch.`supplier_id`, + vtb_verification_batch.`supplier_code`, + vtb_verification_batch.`supplier_name`, + vtb_verification_batch.`user_id`, + vtb_verification_batch.`user_code`, + vtb_verification_batch.`user_name`, + vtb_verification_batch.`ext_user_id`, + vtb_verification_batch.`ext_user_code`, + vtb_verification_batch.`ext_user_name`, + vtb_verification_batch.`backed_time`, + vtb_verification_batch.`refuse_time`, + vtb_verification_batch.`way_id`, + vtb_verification_batch.`way_title`, + vtb_verification_batch.`apply_check_amount`, + vtb_verification_batch.`result_check_amount` + + + + diff --git a/src/main/resources/mapper/wx/WxFormPushMapper.xml b/src/main/resources/mapper/wx/WxFormPushMapper.xml new file mode 100644 index 0000000..abd832c --- /dev/null +++ b/src/main/resources/mapper/wx/WxFormPushMapper.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wx_form_push.`id`, + wx_form_push.`type_id`, + wx_form_push.`type_code`, + wx_form_push.`type_name`, + wx_form_push.`title`, + wx_form_push.`form_context`, + wx_form_push.`form_context_value`, + wx_form_push.`remark`, + wx_form_push.`create_time`, + wx_form_push.`update_time`, + wx_form_push.`tenant_id`, + wx_form_push.`create_by`, + wx_form_push.`update_by`, + wx_form_push.`del_flag`, + wx_form_push.`status`, + wx_form_push.`pre_notify_status`, + wx_form_push.`effective_start_time`, + wx_form_push.`effective_end_time`, + wx_form_push.`business_type` + + + + diff --git a/src/main/resources/tx-log4j2.xml b/src/main/resources/tx-log4j2.xml new file mode 100644 index 0000000..23cdc82 --- /dev/null +++ b/src/main/resources/tx-log4j2.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +