Commit 0c1344e2afa280fd48d13da7030985f252dd4d73

Authored by guzijian
1 parent ef340c0f

feat: 新增装修垃圾独立模块,新增用户控制层,修改单点登录

Showing 47 changed files with 2210 additions and 101 deletions
@@ -228,6 +228,7 @@ @@ -228,6 +228,7 @@
228 <module>trash-workflow</module> 228 <module>trash-workflow</module>
229 <module>trash-daily</module> 229 <module>trash-daily</module>
230 <module>trash-unit</module> 230 <module>trash-unit</module>
  231 + <module>trash-garbage</module>
231 </modules> 232 </modules>
232 <packaging>pom</packaging> 233 <packaging>pom</packaging>
233 234
trash-framework/src/main/java/com/trash/framework/web/service/SysLoginService.java
@@ -173,16 +173,7 @@ public class SysLoginService @@ -173,16 +173,7 @@ public class SysLoginService
173 user.setNickName(userJson.getString("name")); 173 user.setNickName(userJson.getString("name"));
174 user.setPassword(userJson.getString("id")); 174 user.setPassword(userJson.getString("id"));
175 SysDept dept = new SysDept(); 175 SysDept dept = new SysDept();
176 -  
177 - JSONArray depts = redisCache.getCacheObject("CSUserDepartmentType");  
178 -  
179 - if(depts == null){  
180 - Map<String, String> map = new HashMap<String, String>();  
181 - map.put("type", "CSUserDepartmentType");  
182 - depts = RemoteServerUtils.getDict(map);  
183 - redisCache.setCacheObject("CSUserDepartmentType", depts);  
184 - }  
185 - 176 +
186 if(userJson.getJSONArray("userIdentityList")!=null){ 177 if(userJson.getJSONArray("userIdentityList")!=null){
187 178
188 List<String> poStrings = new ArrayList<String>(); 179 List<String> poStrings = new ArrayList<String>();
trash-garbage/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>trash</artifactId>
  7 + <groupId>com.trash</groupId>
  8 + <version>3.2.0</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>trash-garbage</artifactId>
  13 +
  14 + <properties>
  15 + <maven.compiler.source>8</maven.compiler.source>
  16 + <maven.compiler.target>8</maven.compiler.target>
  17 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18 + </properties>
  19 +
  20 + <dependencies>
  21 + <dependency>
  22 + <groupId>com.trash</groupId>
  23 + <artifactId>trash-common</artifactId>
  24 + </dependency>
  25 + <!-- mysql connect-->
  26 + <dependency>
  27 + <groupId>mysql</groupId>
  28 + <artifactId>mysql-connector-java</artifactId>
  29 + </dependency>
  30 + <dependency>
  31 + <groupId>com.alibaba</groupId>
  32 + <artifactId>druid-spring-boot-starter</artifactId>
  33 + <version>1.2.1</version>
  34 + </dependency>
  35 + <!-- mybatis plus-->
  36 + <dependency>
  37 + <groupId>com.baomidou</groupId>
  38 + <artifactId>mybatis-plus-boot-starter</artifactId>
  39 + <version>3.5.4.1</version>
  40 + </dependency>
  41 + <dependency>
  42 + <groupId>org.springframework.boot</groupId>
  43 + <artifactId>spring-boot-starter-web</artifactId>
  44 + </dependency>
  45 + <!-- knife4j swagger-ui-->
  46 + <dependency>
  47 + <groupId>com.github.xiaoymin</groupId>
  48 + <artifactId>knife4j-spring-boot-starter</artifactId>
  49 + <!--在引用时请在maven中央仓库搜索2.X最新版本号-->
  50 + <version>2.0.7</version>
  51 + </dependency>
  52 + <dependency>
  53 + <groupId>org.projectlombok</groupId>
  54 + <artifactId>lombok</artifactId>
  55 + </dependency>
  56 + <!-- jjwt -->
  57 + <dependency>
  58 + <groupId>io.jsonwebtoken</groupId>
  59 + <artifactId>jjwt</artifactId>
  60 + </dependency>
  61 + <!-- fastjson-->
  62 + <dependency>
  63 + <groupId>com.alibaba</groupId>
  64 + <artifactId>fastjson</artifactId>
  65 + </dependency>
  66 + <!-- hutool 工具包-->
  67 + <dependency>
  68 + <groupId>cn.hutool</groupId>
  69 + <artifactId>hutool-all</artifactId>
  70 + <version>5.3.8</version>
  71 + </dependency>
  72 + <!-- 引入redis连接池的依赖 -->
  73 + <!-- 我配置文件配置了redis连接池 所以需要这个依赖-->
  74 + <dependency>
  75 + <groupId>org.apache.commons</groupId>
  76 + <artifactId>commons-pool2</artifactId>
  77 + <version>2.8.1</version>
  78 + </dependency>
  79 + <dependency>
  80 + <groupId>org.springframework</groupId>
  81 + <artifactId>spring-webmvc</artifactId>
  82 + </dependency>
  83 + <!-- jackson 2.x 相关依赖 -->
  84 +
  85 + <dependency>
  86 + <groupId>com.fasterxml.jackson.core</groupId>
  87 + <artifactId>jackson-core</artifactId>
  88 + </dependency>
  89 + <dependency>
  90 + <groupId>com.fasterxml.jackson.core</groupId>
  91 + <artifactId>jackson-databind</artifactId>
  92 + </dependency>
  93 + <dependency>
  94 + <groupId>com.fasterxml.jackson.core</groupId>
  95 + <artifactId>jackson-annotations</artifactId>
  96 + </dependency>
  97 + <dependency>
  98 + <groupId>com.aliyun</groupId>
  99 + <artifactId>aliyun-java-sdk-core</artifactId>
  100 + <version>4.5.16</version>
  101 + </dependency>
  102 + <dependency>
  103 + <groupId>com.aliyun</groupId>
  104 + <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
  105 + <version>2.1.0</version>
  106 + </dependency>
  107 + </dependencies>
  108 +
  109 + <build>
  110 + <finalName>garbage</finalName>
  111 + <plugins>
  112 + <plugin>
  113 + <groupId>org.springframework.boot</groupId>
  114 + <artifactId>spring-boot-maven-plugin</artifactId>
  115 + </plugin>
  116 + </plugins>
  117 + </build>
  118 +</project>
0 \ No newline at end of file 119 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/GarbageApplication.java 0 → 100644
  1 +package com.trash.garbage;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.springframework.boot.SpringApplication;
  5 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  6 +import org.springframework.context.ConfigurableApplicationContext;
  7 +import org.springframework.core.env.ConfigurableEnvironment;
  8 +import org.springframework.scheduling.annotation.EnableAsync;
  9 +
  10 +import java.net.InetAddress;
  11 +import java.net.UnknownHostException;
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +import java.util.regex.Matcher;
  15 +import java.util.regex.Pattern;
  16 +
  17 +/**
  18 + * @author trash
  19 + */
  20 +@SpringBootApplication
  21 +@EnableAsync
  22 +@Slf4j
  23 +public class GarbageApplication {
  24 + public static void main(String[] args) throws UnknownHostException {
  25 + ConfigurableApplicationContext run = SpringApplication.run(GarbageApplication.class, args);
  26 + ConfigurableEnvironment env = run.getEnvironment();
  27 + String ip = InetAddress.getLocalHost().getHostAddress();
  28 + String port = env.getProperty("server.port");
  29 + String path = env.getProperty("server.servlet.context-path");
  30 + String redisPort = env.getProperty("spring.redis.port");
  31 + String redisHost = env.getProperty("spring.redis.host");
  32 + String sqlUrl = env.getProperty("spring.datasource.druid.url");
  33 + List<String> sqlInfo = getSqlInfo(sqlUrl);
  34 + log.info(
  35 + "\n Swagger访问地址:http://" + ip + ":" + port + path + "/doc.html \n" +
  36 + " Redis服务器地址:" + redisHost + ":" + redisPort + "\n" +
  37 + " Mysql服务器地址:" + sqlInfo.get(0) + ":" + sqlInfo.get(1));
  38 + log.info("--装修垃圾服务启动成功--");
  39 + }
  40 + private static List<String> getSqlInfo(String sqlInfo) {
  41 + List<String> str = new ArrayList<>(3);
  42 + Pattern pattern = Pattern.compile("jdbc:mysql://([a-zA-Z0-9.-]+):(\\d+)/");
  43 + Matcher matcher = pattern.matcher(sqlInfo);
  44 + if (matcher.find()) {
  45 + str.add(matcher.group(1));
  46 + str.add(matcher.group(2));
  47 + }
  48 + return str;
  49 + }
  50 +}
trash-garbage/src/main/java/com/trash/garbage/config/CorsConfig.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +
  3 +import org.springframework.context.annotation.Configuration;
  4 +import org.springframework.web.servlet.config.annotation.CorsRegistry;
  5 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  6 +
  7 +/**
  8 + *
  9 + * 允许跨域 后期修改 前端做服务代理
  10 + * @author 20412
  11 + */
  12 +@Configuration
  13 +public class CorsConfig implements WebMvcConfigurer {
  14 +
  15 + @Override
  16 + public void addCorsMappings(CorsRegistry registry) {
  17 + registry.addMapping("/**")
  18 + .allowedOrigins("*")
  19 + .allowCredentials(true)
  20 + .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
  21 + .maxAge(3600);
  22 + }
  23 +
  24 +}
trash-garbage/src/main/java/com/trash/garbage/config/MybatisConfig.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.DbType;
  4 +import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
  5 +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  6 +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
  7 +import org.mybatis.spring.annotation.MapperScan;
  8 +import org.springframework.context.annotation.Bean;
  9 +import org.springframework.context.annotation.Configuration;
  10 +
  11 +
  12 +/**
  13 + * @author 20412
  14 + */
  15 +@Configuration
  16 +@MapperScan("com.trash.garbage.mapper")
  17 +public class MybatisConfig {
  18 +
  19 + @Bean
  20 + public MybatisPlusInterceptor mybatisPlusInterceptor() {
  21 + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  22 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  23 + return interceptor;
  24 + }
  25 +}
trash-garbage/src/main/java/com/trash/garbage/config/RedisConfig.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +
  3 +import com.trash.garbage.utils.FastJson2JsonRedisSerializer;
  4 +import org.springframework.cache.CacheManager;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.data.redis.cache.RedisCacheConfiguration;
  8 +import org.springframework.data.redis.cache.RedisCacheManager;
  9 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  10 +import org.springframework.data.redis.core.RedisTemplate;
  11 +import org.springframework.data.redis.serializer.RedisSerializationContext;
  12 +import org.springframework.data.redis.serializer.RedisSerializer;
  13 +import org.springframework.data.redis.serializer.StringRedisSerializer;
  14 +
  15 +import java.time.Duration;
  16 +
  17 +
  18 +/**
  19 + * redis 配置文件
  20 + * @author 20412
  21 + */
  22 +// 开启缓存
  23 +//@EnableCaching
  24 +@Configuration
  25 +public class RedisConfig {
  26 + @Bean
  27 + public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
  28 + RedisTemplate<String, Object> template = new RedisTemplate<>();
  29 + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  30 +// Jackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  31 + // 使用fast json来完成反序列
  32 + FastJson2JsonRedisSerializer<Object> fastJson2JsonRedisSerializer = new FastJson2JsonRedisSerializer<>(Object.class);
  33 +// ObjectMapper om = new ObjectMapper();
  34 +// om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  35 + // 解决linkArraylist反序列化问题
  36 +// om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
  37 +// genericJackson2JsonRedisSerializer.setObjectMapper(om);
  38 + template.setConnectionFactory(factory);
  39 + //key序列化方式
  40 + template.setKeySerializer(stringRedisSerializer);
  41 + //value序列化
  42 + template.setValueSerializer(fastJson2JsonRedisSerializer);
  43 + template.setHashKeySerializer(stringRedisSerializer);
  44 + //value hashmap序列化 Jackson2JsonRedisSerializer 主要针对String类型的数据
  45 + template.setHashValueSerializer(fastJson2JsonRedisSerializer);
  46 + return template;
  47 + }
  48 +
  49 + @Bean
  50 + public CacheManager cacheManager(RedisConnectionFactory factory) {
  51 + RedisSerializer<String> redisSerializer = new StringRedisSerializer();
  52 + FastJson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new FastJson2JsonRedisSerializer<>(Object.class);
  53 +// 配置序列化(解决乱码的问题),过期时间600秒
  54 + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
  55 + .entryTtl(Duration.ofSeconds(600))
  56 + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
  57 + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
  58 + .disableCachingNullValues();
  59 + RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
  60 + .cacheDefaults(config)
  61 + .build();
  62 + return cacheManager;
  63 + }
  64 +}
0 \ No newline at end of file 65 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/config/RestTemplateConfig.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.web.client.RestTemplate;
  6 +
  7 +@Configuration
  8 +public class RestTemplateConfig {
  9 + @Bean
  10 + public RestTemplate getRestTemplate(){
  11 + return new RestTemplate();
  12 + }
  13 +}
trash-garbage/src/main/java/com/trash/garbage/config/SwaggerConfiguration.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +
  3 +import com.trash.garbage.global.ResultCode;
  4 +import org.springframework.beans.factory.annotation.Autowired;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.web.bind.annotation.RequestMethod;
  8 +import springfox.documentation.builders.ApiInfoBuilder;
  9 +import springfox.documentation.builders.PathSelectors;
  10 +import springfox.documentation.builders.RequestHandlerSelectors;
  11 +import springfox.documentation.builders.ResponseMessageBuilder;
  12 +import springfox.documentation.schema.ModelRef;
  13 +import springfox.documentation.service.ApiInfo;
  14 +import springfox.documentation.service.ResponseMessage;
  15 +import springfox.documentation.spi.DocumentationType;
  16 +import springfox.documentation.spring.web.plugins.Docket;
  17 +import springfox.documentation.swagger2.annotations.EnableSwagger2;
  18 +
  19 +import java.util.ArrayList;
  20 +import java.util.Arrays;
  21 +import java.util.List;
  22 +
  23 +/**
  24 + * @author guzijian
  25 + * 2020/11/07 9:26
  26 + * @since:knife4j-spring-boot-fast-demo 1.0
  27 + */
  28 +@Configuration
  29 +@EnableSwagger2
  30 +public class SwaggerConfiguration {
  31 +
  32 + @Bean(value = "defaultApi2")
  33 + public Docket defaultApi2() {
  34 + //添加全局响应状态码
  35 + List<ResponseMessage> responseMessageList = new ArrayList<>();
  36 + Arrays.stream(ResultCode.values()).forEach(errorEnum -> {
  37 + responseMessageList.add(
  38 + new ResponseMessageBuilder().code(errorEnum.getCode()).message(errorEnum.getMsg()).responseModel(
  39 + new ModelRef(errorEnum.getMsg()))
  40 + .build()
  41 + );
  42 + });
  43 +
  44 + String groupName="学习间swagger";
  45 +
  46 + Docket docket=new Docket(DocumentationType.SWAGGER_2)
  47 + .globalResponseMessage(RequestMethod.GET,responseMessageList)
  48 + .globalResponseMessage(RequestMethod.POST,responseMessageList)
  49 + .globalResponseMessage(RequestMethod.DELETE,responseMessageList)
  50 + .globalResponseMessage(RequestMethod.PUT,responseMessageList)
  51 + .host("http://localhost:9090/")
  52 + .apiInfo(apiInfo())
  53 + .groupName(groupName)
  54 + .select()
  55 + .apis(RequestHandlerSelectors.basePackage("com.trash.garbage"))
  56 + .paths(PathSelectors.any())
  57 + .build();
  58 + return docket;
  59 + }
  60 +
  61 + private ApiInfo apiInfo() {
  62 + return new ApiInfoBuilder()
  63 + .description(" 学习间接口文档 ")
  64 + .contact("204126329@qq.com")
  65 + .version("1.0")
  66 + .build();
  67 + }
  68 +}
0 \ No newline at end of file 69 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/config/WebSecurityConfig.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +import com.trash.garbage.security.JwtAuthenticationFilterAbstract;
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.security.authentication.AuthenticationManager;
  8 +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  9 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  10 +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  11 +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  12 +import org.springframework.security.config.http.SessionCreationPolicy;
  13 +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  14 +import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  15 +import org.springframework.security.web.util.matcher.OrRequestMatcher;
  16 +import org.springframework.security.web.util.matcher.RequestMatcher;
  17 +
  18 +/**
  19 + * security配置类
  20 + * @author gzj
  21 + */
  22 +@Configuration
  23 +@EnableWebSecurity
  24 +@EnableGlobalMethodSecurity(prePostEnabled = true)
  25 +public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  26 +
  27 + @Autowired
  28 + private JwtAuthenticationFilterAbstract jwtAuthenticationFilter;
  29 +
  30 + /**
  31 + * 放行路径
  32 + */
  33 + @Value("${trash.garbage.config.location.exclude}")
  34 + private String[] exclude;
  35 +
  36 + /**
  37 + * 放行端口 和security配置
  38 + * @param http
  39 + * @throws Exception
  40 + */
  41 + @Override
  42 + protected void configure(HttpSecurity http) throws Exception {
  43 +
  44 + RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
  45 + new AntPathRequestMatcher("/**", "OPTIONS"),
  46 + new AntPathRequestMatcher("/error/**")
  47 + );
  48 +
  49 + http
  50 + // 关闭 csrf
  51 + .csrf().disable()
  52 + // 前后端分离的项目session就不管用了 不通过session获取securityContext
  53 + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  54 + .and()
  55 + .authorizeRequests()
  56 + // 对于登录接口 允许匿名访问
  57 + .antMatchers(exclude).anonymous()
  58 + .requestMatchers(PUBLIC_URLS).permitAll()
  59 + // 任意认证成功后都可以访问
  60 + .anyRequest().authenticated();
  61 +
  62 + http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
  63 + // spring security 异常处理 用于权限认证
  64 +// http.exceptionHandling()
  65 + // 权限异常
  66 +// .accessDeniedHandler()
  67 + // 认证异常
  68 +// .authenticationEntryPoint();
  69 + }
  70 +
  71 + /**
  72 + * 重写认证管理
  73 + * @return
  74 + * @throws Exception
  75 + */
  76 + @Bean
  77 + @Override
  78 + public AuthenticationManager authenticationManagerBean() throws Exception {
  79 + return super.authenticationManagerBean();
  80 + }
  81 +
  82 + /**
  83 + * 监听器 监听认证结果 当认证成功后触发
  84 + * @param applicationEventPublisher
  85 + * @return
  86 + */
  87 +// @Bean
  88 +// public AuthenticationEventPublisher authenticationEventPublisher
  89 +// (ApplicationEventPublisher applicationEventPublisher) {
  90 +// return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
  91 +// }
  92 +
  93 +
  94 +}
0 \ No newline at end of file 95 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/config/WxConfig.java 0 → 100644
  1 +package com.trash.garbage.config;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.beans.factory.InitializingBean;
  5 +import org.springframework.boot.context.properties.ConfigurationProperties;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +/**
  10 + * @author 20412
  11 + */
  12 +@Component
  13 +@ConfigurationProperties(prefix = "wx")
  14 +public class WxConfig {
  15 + private String appId;
  16 + private String secret;
  17 +
  18 + public String getAppId() {
  19 + return appId;
  20 + }
  21 +
  22 + public void setAppId(String appId) {
  23 + this.appId = appId;
  24 + }
  25 +
  26 + public String getSecret() {
  27 + return secret;
  28 + }
  29 +
  30 + public void setSecret(String secret) {
  31 + this.secret = secret;
  32 + }
  33 +}
trash-garbage/src/main/java/com/trash/garbage/controller/GarbageUserController.java 0 → 100644
  1 +package com.trash.garbage.controller;
  2 +
  3 +
  4 +import com.aliyuncs.exceptions.ClientException;
  5 +import com.trash.garbage.global.Result;
  6 +import com.trash.garbage.pojo.vo.LoginVo;
  7 +import com.trash.garbage.service.GarUserService;
  8 +import com.trash.garbage.utils.SMSUtils;
  9 +import com.trash.garbage.utils.ValidateCodeUtil;
  10 +import io.swagger.annotations.Api;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import io.swagger.annotations.Tag;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.web.bind.annotation.*;
  15 +
  16 +import java.util.Random;
  17 +
  18 +/**
  19 + * @author 20412
  20 + */
  21 +@RestController
  22 +@RequestMapping("user")
  23 +@Api(tags = "建筑垃圾-用户接口")
  24 +public class GarbageUserController {
  25 +
  26 + @Autowired
  27 + private GarUserService garUserService;
  28 +
  29 + /**
  30 + * 用户登录
  31 + *
  32 + * @param user
  33 + * @return
  34 + */
  35 + @ApiOperation("用户接口-用户登录")
  36 + @PostMapping("/login")
  37 + public Result<String> login(@RequestBody LoginVo user) {
  38 + return Result.OK(garUserService.login(user));
  39 + }
  40 +
  41 + @ApiOperation("用户接口-发送验证码")
  42 + @GetMapping("/send/verify")
  43 + public Result<?> sendVerify(@RequestParam("tel") String tel) {
  44 + try {
  45 + garUserService.sendVerify(tel);
  46 + return Result.OK();
  47 + } catch (Exception e) {
  48 + e.printStackTrace();
  49 + return Result.ERROR();
  50 + }
  51 +
  52 + }
  53 +}
trash-garbage/src/main/java/com/trash/garbage/filter/JwtAuthenticationFilter.java 0 → 100644
  1 +package com.trash.garbage.filter;
  2 +
  3 +import com.trash.common.utils.StringUtils;
  4 +import com.trash.garbage.global.GlobalRedisProperties;
  5 +import com.trash.garbage.security.JwtAuthenticationFilterAbstract;
  6 +import com.trash.garbage.security.UserCustom;
  7 +import com.trash.garbage.utils.JwtUtils;
  8 +import com.trash.garbage.utils.RedisUtils;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.beans.factory.annotation.Value;
  12 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  13 +import org.springframework.security.core.Authentication;
  14 +import org.springframework.security.core.context.SecurityContextHolder;
  15 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  16 +import org.springframework.stereotype.Component;
  17 +import org.springframework.util.AntPathMatcher;
  18 +import javax.servlet.FilterChain;
  19 +import javax.servlet.ServletException;
  20 +import javax.servlet.http.HttpServletRequest;
  21 +import javax.servlet.http.HttpServletResponse;
  22 +import java.io.IOException;
  23 +import static com.trash.garbage.interfaces.Authorization.AUTHORIZATION;
  24 +
  25 +/**
  26 + * 实现登录认证逻辑
  27 + * @author 20412
  28 + */
  29 +@Component
  30 +@Slf4j
  31 +public class JwtAuthenticationFilter extends JwtAuthenticationFilterAbstract {
  32 +
  33 + private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
  34 +
  35 + @Autowired
  36 + private RedisUtils redisUtils;
  37 +
  38 + @Value("${trash.garbage.config.location.exclude}")
  39 + private String[] exclude;
  40 +
  41 + @Override
  42 + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  43 + String token = request.getHeader(AUTHORIZATION);
  44 + // 如果为空说明没有认证 进入下一层过滤器进行安全认证
  45 + if(StringUtils.isBlank(token) || doCheck(request.getRequestURI())){
  46 + filterChain.doFilter(request, response);
  47 + return;
  48 + }
  49 +
  50 + String userId = JwtUtils.getUserId(token);
  51 + UserCustom customUser = (UserCustom) redisUtils.get(GlobalRedisProperties.REDIS_USER_HEADER.getValue() + userId);
  52 + if(customUser == null){
  53 + throw new UsernameNotFoundException("认证信息过期,请重新登录");
  54 + }
  55 + log.info("userId:{}",userId);
  56 + Authentication authenticationToken = new UsernamePasswordAuthenticationToken(customUser,null,null);
  57 + SecurityContextHolder.getContext().setAuthentication(authenticationToken);
  58 + // 放行
  59 + filterChain.doFilter(request,response);
  60 + }
  61 +
  62 + private boolean doCheck(String url) {
  63 + for (String location : exclude) {
  64 + if (PATH_MATCHER.match(location,url)){
  65 + return true;
  66 + }
  67 + }
  68 + return false;
  69 + }
  70 +}
0 \ No newline at end of file 71 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/global/GlobalRedisProperties.java 0 → 100644
  1 +package com.trash.garbage.global;
  2 +
  3 +/**
  4 + * @author 20412
  5 + */
  6 +public enum GlobalRedisProperties {
  7 + REDIS_USER_CODE("code:","验证码请求头"),
  8 + REDIS_USER_HEADER("login:user:","用户的redis头部标签"),
  9 + REDIS_USER_COUNT("count","用户在线人数"),
  10 + REDIS_USER_CACHE_VALUE("user:cache","用户信息缓存value"),
  11 + REDIS_USER_CACHE_KEY("plan","用户计划缓存");
  12 +
  13 + private String value;
  14 + private String description;
  15 +
  16 + GlobalRedisProperties(String value, String description) {
  17 + this.value = value;
  18 + this.description = description;
  19 + }
  20 +
  21 + public String getValue() {
  22 + return value;
  23 + }
  24 +}
trash-garbage/src/main/java/com/trash/garbage/global/GlobalStatus.java 0 → 100644
  1 +package com.trash.garbage.global;
  2 +
  3 +/**
  4 + * 全局状态管理
  5 + * @author guzijian
  6 + */
  7 +public class GlobalStatus {
  8 + /**
  9 + * 未注销
  10 + */
  11 + public static final int DEL_FLAG_NO = 0;
  12 + /**
  13 + * 已注销
  14 + */
  15 + public static final int DEL_FLAG_YES = 1;
  16 +
  17 + /**
  18 + * 用户状态管理
  19 + */
  20 + public enum UserStatusEnum{
  21 + /**
  22 + * 管理员
  23 + */
  24 + WX_LOGIN(1,"微信登录"),
  25 + /**
  26 + * 普通用户
  27 + */
  28 + NORMAL_LOGIN(0,"普通登录");
  29 +
  30 + private Integer status;
  31 + private String description;
  32 + public int getStatus(){
  33 + return this.status;
  34 + }
  35 + UserStatusEnum(Integer status,String description){
  36 + this.status = status;
  37 + this.description = description;
  38 + }
  39 + }
  40 + /**
  41 + * 字典
  42 + */
  43 + public enum DicEnum{
  44 + MODE("MODE"),
  45 + CUSTOM("CUSTOM");
  46 + DicEnum(String type){
  47 + this.type = type;
  48 + }
  49 + private String type;
  50 + public String getValue(){
  51 + return this.type;
  52 + }
  53 + }
  54 +}
trash-garbage/src/main/java/com/trash/garbage/global/Result.java 0 → 100644
  1 +package com.trash.garbage.global;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import static com.trash.garbage.global.ResultCode.CODE_200;
  8 +import static com.trash.garbage.global.ResultCode.CODE_500;
  9 +
  10 +
  11 +/**
  12 + * 返回结果
  13 + * @author 20412
  14 + */
  15 +@Data
  16 +@ApiModel("返回结果")
  17 +public class Result<T extends Object> {
  18 +
  19 + @ApiModelProperty(value = "是否成功")
  20 + private Boolean success;
  21 +
  22 + @ApiModelProperty(value = "状态码")
  23 + private Integer code;
  24 +
  25 + @ApiModelProperty(value = "返回消息")
  26 + private String msg;
  27 +
  28 + @ApiModelProperty(value = "返回对象")
  29 + private T data ;
  30 +
  31 + private Result() {}
  32 +
  33 + /** 成功静态方法 */
  34 + public static Result OK() {
  35 + Result r = new Result();
  36 + r.setSuccess(true);
  37 + r.setCode(CODE_200.getCode());
  38 + r.setMsg("成功");
  39 + return r;
  40 + }
  41 +
  42 + public static <T> Result<T> OK(ResultCode code,T data){
  43 + Result r = new Result();
  44 + r.setSuccess(true);
  45 + r.setCode(code.getCode());
  46 + r.setMsg("部分成功");
  47 + r.setData(data);
  48 + return r;
  49 + }
  50 +
  51 + /** 成功静态方法 */
  52 + public static <T> Result<T> OK(T data) {
  53 + Result r = new Result();
  54 + r.setSuccess(true);
  55 + r.setCode(CODE_200.getCode());
  56 + r.setData(data);
  57 + r.setMsg("成功");
  58 + return r;
  59 + }
  60 +
  61 + /** 成功静态方法 */
  62 + public static <T> Result<T> OK(T data, String message) {
  63 + Result r = new Result();
  64 + r.setSuccess(true);
  65 + r.setCode(CODE_200.getCode());
  66 + r.setData(data);
  67 + r.setMsg(message);
  68 + return r;
  69 + }
  70 +
  71 + /** 失败静态方法 */
  72 + public static Result ERROR() {
  73 + Result r = new Result();
  74 + r.setSuccess(false);
  75 + r.setCode(CODE_500.getCode());
  76 + r.setMsg("失败");
  77 + return r;
  78 + }
  79 + /** 失败静态方法 */
  80 + public static Result ERROR(ResultCode code,String msg) {
  81 + Result r = new Result();
  82 + r.setSuccess(false);
  83 + r.setCode(code.getCode());
  84 + r.setMsg(msg);
  85 + return r;
  86 + }
  87 +
  88 + /** 失败静态方法 */
  89 + public static Result ERROR(String message) {
  90 + Result r = new Result();
  91 + r.setSuccess(false);
  92 + r.setCode(CODE_500.getCode());
  93 + r.setMsg(message);
  94 + return r;
  95 + }
  96 +
  97 + /** 设置状态码 */
  98 + public Result code(Integer code){
  99 + this.setCode(code);
  100 + return this;
  101 + }
  102 +
  103 + /** 设置集合 */
  104 + public Result<T> data(T map){
  105 + this.setData(map);
  106 + return this;
  107 + }
  108 +}
trash-garbage/src/main/java/com/trash/garbage/global/ResultCode.java 0 → 100644
  1 +package com.trash.garbage.global;
  2 +
  3 +public enum ResultCode {
  4 +
  5 + /*
  6 + * 错误信息
  7 + * */
  8 + CODE_200(200, "操作成功"),
  9 + CODE_201(201,"对象创建成功"),
  10 + CODE_202(202,"请求已经被接受"),
  11 + CODE_207(207,"请求已经成功处理了部分内容,但是还有其他内容未被处理"),
  12 + CODE_400(400,"参数列表错误(缺少,格式不匹配)"),
  13 + CODE_401(401,"未授权"),
  14 + CODE_403(403,"访问受限,授权过期"),
  15 + CODE_404(404,"资源,服务未找到"),
  16 + CODE_500(500,"操作失败"),
  17 + ;
  18 +
  19 + private Integer Code;
  20 + private String Msg;
  21 + ResultCode(Integer Code, String Msg) {
  22 + this.Code = Code;
  23 + this.Msg = Msg;
  24 + }
  25 + public Integer getCode() {
  26 + return Code;
  27 + }
  28 + public String getMsg() {
  29 + return Msg;
  30 + }
  31 +}
0 \ No newline at end of file 32 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/interceptor/MyMetaObjectHandler.java 0 → 100644
  1 +package com.trash.garbage.interceptor;
  2 +
  3 +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
  4 +import com.trash.garbage.global.GlobalStatus;
  5 +import com.trash.garbage.utils.SecurityUtil;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.apache.ibatis.reflection.MetaObject;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.Date;
  11 +import java.util.Objects;
  12 +
  13 +/**
  14 + * mybatis 拦截器全局注入
  15 + * @author 20412
  16 + */
  17 +@Slf4j
  18 +@Component
  19 +public class MyMetaObjectHandler implements MetaObjectHandler {
  20 +
  21 + @Override
  22 + public void insertFill(MetaObject metaObject) {
  23 + log.info("start insert fill ....");
  24 + if (metaObject.hasGetter("garCreateTime")){
  25 + this.strictInsertFill(metaObject, "garCreateTime", Date.class, new Date());
  26 + }
  27 +
  28 + if (metaObject.hasGetter("garCreateBy")){
  29 + if (!Objects.isNull(SecurityUtil.getUserCustom())){
  30 + this.strictInsertFill(metaObject, "garCreateBy", String.class, SecurityUtil.getUserCustom().getUser().getUserId());
  31 + }
  32 + }
  33 +
  34 + if (metaObject.hasGetter("garUpdateTime")){
  35 + this.strictInsertFill(metaObject, "garUpdateTime", Date.class, new Date());
  36 + }
  37 + if (metaObject.hasGetter("garUserId")){
  38 + if (!Objects.isNull(SecurityUtil.getUserCustom())) {
  39 + this.strictInsertFill(metaObject, "garUserId", String.class, SecurityUtil.getUserCustom().getUser().getUserId());
  40 + }
  41 + }
  42 + if (metaObject.hasGetter("garUpdateBy")){
  43 + if (!Objects.isNull(SecurityUtil.getUserCustom())){
  44 + this.strictInsertFill(metaObject, "garUpdateBy", String.class, SecurityUtil.getUserCustom().getUser().getUserId());
  45 + }
  46 + }
  47 + }
  48 +
  49 + @Override
  50 + public void updateFill(MetaObject metaObject) {
  51 + log.info("start update fill ....");
  52 + if (metaObject.hasGetter("garUpdateTime")){
  53 + this.strictUpdateFill(metaObject, "garUpdateTime", Date.class, new Date());
  54 + }
  55 + if (metaObject.hasGetter("garUpdateBy")){
  56 + this.strictUpdateFill(metaObject,"garUpdateBy",String.class,SecurityUtil.getUserCustom().getUser().getUserId());
  57 + }
  58 + }
  59 +}
0 \ No newline at end of file 60 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/interfaces/Authorization.java 0 → 100644
  1 +package com.trash.garbage.interfaces;
  2 +
  3 +/**
  4 + * 请求头规范
  5 + * @date 2023-3-21
  6 + * @author 20412
  7 + */
  8 +public interface Authorization {
  9 + String AUTHORIZATION = "Authorization";
  10 +
  11 + /**
  12 + * 这个已经被淘汰,请使用AUTHORIZATION
  13 + */
  14 + @Deprecated
  15 + String TOKEN = "X-TOKEN-AUTH";
  16 +}
trash-garbage/src/main/java/com/trash/garbage/mapper/GarAddressMapper.java 0 → 100644
  1 +package com.trash.garbage.mapper;
  2 +
  3 +import com.trash.garbage.pojo.domain.GarAddress;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 +* @author 20412
  9 +* @description 针对表【gar_address(建筑垃圾-用户地址)】的数据库操作Mapper
  10 +* @createDate 2023-11-20 16:03:15
  11 +* @Entity garbage.domain.GarAddress
  12 +*/
  13 +@Mapper
  14 +public interface GarAddressMapper extends BaseMapper<GarAddress> {
  15 +
  16 +}
  17 +
  18 +
  19 +
  20 +
trash-garbage/src/main/java/com/trash/garbage/mapper/GarUserMapper.java 0 → 100644
  1 +package com.trash.garbage.mapper;
  2 +
  3 +import com.trash.garbage.pojo.domain.GarUser;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 +* @author 20412
  9 +* @description 针对表【gar_user(建筑垃圾-用户表)】的数据库操作Mapper
  10 +* @createDate 2023-11-20 16:03:15
  11 +* @Entity garbage.domain.GarUser
  12 +*/
  13 +@Mapper
  14 +public interface GarUserMapper extends BaseMapper<GarUser> {
  15 +
  16 +}
  17 +
  18 +
  19 +
  20 +
trash-garbage/src/main/java/com/trash/garbage/pojo/domain/GarAddress.java 0 → 100644
  1 +package com.trash.garbage.pojo.domain;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableField;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import java.io.Serializable;
  7 +import java.util.Date;
  8 +import lombok.Data;
  9 +
  10 +/**
  11 + * 建筑垃圾-用户地址
  12 + * @author 20412
  13 + * @TableName gar_address
  14 + */
  15 +@TableName(value ="gar_address")
  16 +@Data
  17 +public class GarAddress implements Serializable {
  18 + /**
  19 + * 地址id
  20 + */
  21 + @TableId
  22 + private Long garAddressId;
  23 +
  24 + /**
  25 + * 用户id
  26 + */
  27 + private Long garUserId;
  28 +
  29 + /**
  30 + * 用户地址
  31 + */
  32 + private String garUserAddress;
  33 +
  34 + /**
  35 + * 默认地址
  36 + */
  37 + private Integer garUserDefault;
  38 +
  39 + /**
  40 + * 创建时间
  41 + */
  42 + private Date garCreateTime;
  43 +
  44 + /**
  45 + * 修改时间
  46 + */
  47 + private Date garUpdateTime;
  48 +
  49 + /**
  50 + * 备注
  51 + */
  52 + private String garRemark;
  53 +
  54 + @TableField(exist = false)
  55 + private static final long serialVersionUID = 1L;
  56 +
  57 + @Override
  58 + public boolean equals(Object that) {
  59 + if (this == that) {
  60 + return true;
  61 + }
  62 + if (that == null) {
  63 + return false;
  64 + }
  65 + if (getClass() != that.getClass()) {
  66 + return false;
  67 + }
  68 + GarAddress other = (GarAddress) that;
  69 + return (this.getGarAddressId() == null ? other.getGarAddressId() == null : this.getGarAddressId().equals(other.getGarAddressId()))
  70 + && (this.getGarUserId() == null ? other.getGarUserId() == null : this.getGarUserId().equals(other.getGarUserId()))
  71 + && (this.getGarUserAddress() == null ? other.getGarUserAddress() == null : this.getGarUserAddress().equals(other.getGarUserAddress()))
  72 + && (this.getGarUserDefault() == null ? other.getGarUserDefault() == null : this.getGarUserDefault().equals(other.getGarUserDefault()))
  73 + && (this.getGarCreateTime() == null ? other.getGarCreateTime() == null : this.getGarCreateTime().equals(other.getGarCreateTime()))
  74 + && (this.getGarUpdateTime() == null ? other.getGarUpdateTime() == null : this.getGarUpdateTime().equals(other.getGarUpdateTime()))
  75 + && (this.getGarRemark() == null ? other.getGarRemark() == null : this.getGarRemark().equals(other.getGarRemark()));
  76 + }
  77 +
  78 + @Override
  79 + public int hashCode() {
  80 + final int prime = 31;
  81 + int result = 1;
  82 + result = prime * result + ((getGarAddressId() == null) ? 0 : getGarAddressId().hashCode());
  83 + result = prime * result + ((getGarUserId() == null) ? 0 : getGarUserId().hashCode());
  84 + result = prime * result + ((getGarUserAddress() == null) ? 0 : getGarUserAddress().hashCode());
  85 + result = prime * result + ((getGarUserDefault() == null) ? 0 : getGarUserDefault().hashCode());
  86 + result = prime * result + ((getGarCreateTime() == null) ? 0 : getGarCreateTime().hashCode());
  87 + result = prime * result + ((getGarUpdateTime() == null) ? 0 : getGarUpdateTime().hashCode());
  88 + result = prime * result + ((getGarRemark() == null) ? 0 : getGarRemark().hashCode());
  89 + return result;
  90 + }
  91 +
  92 + @Override
  93 + public String toString() {
  94 + StringBuilder sb = new StringBuilder();
  95 + sb.append(getClass().getSimpleName());
  96 + sb.append(" [");
  97 + sb.append("Hash = ").append(hashCode());
  98 + sb.append(", garAddressId=").append(garAddressId);
  99 + sb.append(", garUserId=").append(garUserId);
  100 + sb.append(", garUserAddress=").append(garUserAddress);
  101 + sb.append(", garUserDefault=").append(garUserDefault);
  102 + sb.append(", garCreateTime=").append(garCreateTime);
  103 + sb.append(", garUpdateTime=").append(garUpdateTime);
  104 + sb.append(", garRemark=").append(garRemark);
  105 + sb.append(", serialVersionUID=").append(serialVersionUID);
  106 + sb.append("]");
  107 + return sb.toString();
  108 + }
  109 +}
0 \ No newline at end of file 110 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/pojo/domain/GarUser.java 0 → 100644
  1 +package com.trash.garbage.pojo.domain;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import java.io.Serializable;
  8 +import java.util.Date;
  9 +
  10 +import com.trash.garbage.security.UserAbstract;
  11 +import lombok.Data;
  12 +
  13 +/**
  14 + * 建筑垃圾-用户表
  15 + * @TableName gar_user
  16 + */
  17 +@TableName(value ="gar_user")
  18 +@Data
  19 +public class GarUser extends UserAbstract implements Serializable {
  20 + /**
  21 + * 建筑垃圾用户id
  22 + */
  23 + @TableId(value = "gar_user_id")
  24 + private String garUserId;
  25 +
  26 + /**
  27 + * 手机号
  28 + */
  29 + private String garUserTel;
  30 +
  31 + /**
  32 + * 用户名
  33 + */
  34 + private String garUserName;
  35 +
  36 + /**
  37 + * 用户类型
  38 + */
  39 + private String garUserType;
  40 +
  41 + /**
  42 + * 车牌号
  43 + */
  44 + private String garUserCarNum;
  45 +
  46 + /**
  47 + * 是否注销
  48 + */
  49 + private Integer garUserDelFlag;
  50 +
  51 + /**
  52 + * 创建时间
  53 + */
  54 +
  55 + @TableField(fill = FieldFill.INSERT)
  56 + private Date garCreateTime;
  57 +
  58 + /**
  59 + * 修改时间
  60 + */
  61 + @TableField(fill = FieldFill.INSERT_UPDATE)
  62 + private Date garUpdateTime;
  63 +
  64 + /**
  65 + * 备注
  66 + */
  67 + private String garRemark;
  68 +
  69 + @TableField(exist = false)
  70 + private static final long serialVersionUID = 1L;
  71 +
  72 + @Override
  73 + public boolean equals(Object that) {
  74 + if (this == that) {
  75 + return true;
  76 + }
  77 + if (that == null) {
  78 + return false;
  79 + }
  80 + if (getClass() != that.getClass()) {
  81 + return false;
  82 + }
  83 + GarUser other = (GarUser) that;
  84 + return (this.getGarUserId() == null ? other.getGarUserId() == null : this.getGarUserId().equals(other.getGarUserId()))
  85 + && (this.getGarUserTel() == null ? other.getGarUserTel() == null : this.getGarUserTel().equals(other.getGarUserTel()))
  86 + && (this.getGarUserName() == null ? other.getGarUserName() == null : this.getGarUserName().equals(other.getGarUserName()))
  87 + && (this.getGarUserType() == null ? other.getGarUserType() == null : this.getGarUserType().equals(other.getGarUserType()))
  88 + && (this.getGarUserCarNum() == null ? other.getGarUserCarNum() == null : this.getGarUserCarNum().equals(other.getGarUserCarNum()))
  89 + && (this.getGarUserDelFlag() == null ? other.getGarUserDelFlag() == null : this.getGarUserDelFlag().equals(other.getGarUserDelFlag()))
  90 + && (this.getGarCreateTime() == null ? other.getGarCreateTime() == null : this.getGarCreateTime().equals(other.getGarCreateTime()))
  91 + && (this.getGarUpdateTime() == null ? other.getGarUpdateTime() == null : this.getGarUpdateTime().equals(other.getGarUpdateTime()))
  92 + && (this.getGarRemark() == null ? other.getGarRemark() == null : this.getGarRemark().equals(other.getGarRemark()));
  93 + }
  94 +
  95 + @Override
  96 + public int hashCode() {
  97 + final int prime = 31;
  98 + int result = 1;
  99 + result = prime * result + ((getGarUserId() == null) ? 0 : getGarUserId().hashCode());
  100 + result = prime * result + ((getGarUserTel() == null) ? 0 : getGarUserTel().hashCode());
  101 + result = prime * result + ((getGarUserName() == null) ? 0 : getGarUserName().hashCode());
  102 + result = prime * result + ((getGarUserType() == null) ? 0 : getGarUserType().hashCode());
  103 + result = prime * result + ((getGarUserCarNum() == null) ? 0 : getGarUserCarNum().hashCode());
  104 + result = prime * result + ((getGarUserDelFlag() == null) ? 0 : getGarUserDelFlag().hashCode());
  105 + result = prime * result + ((getGarCreateTime() == null) ? 0 : getGarCreateTime().hashCode());
  106 + result = prime * result + ((getGarUpdateTime() == null) ? 0 : getGarUpdateTime().hashCode());
  107 + result = prime * result + ((getGarRemark() == null) ? 0 : getGarRemark().hashCode());
  108 + return result;
  109 + }
  110 +
  111 + @Override
  112 + public String toString() {
  113 + StringBuilder sb = new StringBuilder();
  114 + sb.append(getClass().getSimpleName());
  115 + sb.append(" [");
  116 + sb.append("Hash = ").append(hashCode());
  117 + sb.append(", garUserId=").append(garUserId);
  118 + sb.append(", garUserTel=").append(garUserTel);
  119 + sb.append(", garUserName=").append(garUserName);
  120 + sb.append(", garUserType=").append(garUserType);
  121 + sb.append(", garUserCarNum=").append(garUserCarNum);
  122 + sb.append(", garUserDelFlag=").append(garUserDelFlag);
  123 + sb.append(", garCreateTime=").append(garCreateTime);
  124 + sb.append(", garUpdateTime=").append(garUpdateTime);
  125 + sb.append(", garRemark=").append(garRemark);
  126 + sb.append(", serialVersionUID=").append(serialVersionUID);
  127 + sb.append("]");
  128 + return sb.toString();
  129 + }
  130 +
  131 + @Override
  132 + public String getTel() {
  133 + return this.garUserTel;
  134 + }
  135 +}
0 \ No newline at end of file 136 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/pojo/vo/LoginVo.java 0 → 100644
  1 +package com.trash.garbage.pojo.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotBlank;
  8 +
  9 +/**
  10 + * @author 20412
  11 + */
  12 +@Data
  13 +@ApiModel(value = "登录vo")
  14 +public class LoginVo {
  15 + @ApiModelProperty(value = "登录vo-手机号")
  16 + private String tel;
  17 + @ApiModelProperty(value = "登录vo-验证码")
  18 + private Integer code;
  19 + @ApiModelProperty(value = "登录vo-用户昵称")
  20 + private String nickname;
  21 + @ApiModelProperty(value = "登录vo-wxCode")
  22 + private String wxCode;
  23 + @ApiModelProperty(value = "登录vo-loginType:0 手机号登录 , 1 微信登录")
  24 + private Integer loginType;
  25 + private String encryptedData;
  26 + private String iv;
  27 +}
trash-garbage/src/main/java/com/trash/garbage/security/JwtAuthenticationFilterAbstract.java 0 → 100644
  1 +package com.trash.garbage.security;
  2 +
  3 +import org.springframework.web.filter.OncePerRequestFilter;
  4 +
  5 +
  6 +
  7 +/**
  8 + * 使用抽象类
  9 + * 因为不同的调用者可能需要的过滤不一样
  10 + * 由调用者自己实现
  11 + * @author 20412
  12 + */
  13 +public abstract class JwtAuthenticationFilterAbstract extends OncePerRequestFilter {
  14 +
  15 +}
trash-garbage/src/main/java/com/trash/garbage/security/PasswordCustom.java 0 → 100644
  1 +package com.trash.garbage.security;
  2 +
  3 +import org.springframework.security.crypto.password.PasswordEncoder;
  4 +import org.springframework.stereotype.Component;
  5 +import org.springframework.util.DigestUtils;
  6 +
  7 +/**
  8 + * @author 20412
  9 + */
  10 +@Component
  11 +public class PasswordCustom implements PasswordEncoder {
  12 +
  13 + /** 密码加密 */
  14 + @Override
  15 + public String encode(CharSequence charSequence) {
  16 + return "";
  17 + }
  18 +
  19 + /** 密码配对 用户登录的密码加密后是否配对上 */
  20 + @Override
  21 + public boolean matches(CharSequence rawPassword, String password) {
  22 + return true;
  23 + }
  24 +}
trash-garbage/src/main/java/com/trash/garbage/security/UserAbstract.java 0 → 100644
  1 +package com.trash.garbage.security;
  2 +
  3 +/**
  4 + * 封装用户信息必须实现一下模板
  5 + * @author guzijian
  6 + */
  7 +public abstract class UserAbstract {
  8 +
  9 + /**
  10 + * 可选属性 根据需要设置
  11 + */
  12 + String garUserId;
  13 +
  14 + /**
  15 + * 实现获取用手机号
  16 + * @return
  17 + */
  18 + public abstract String getTel();
  19 +
  20 + public String getUserId(){
  21 + return this.garUserId;
  22 + }
  23 +
  24 +}
trash-garbage/src/main/java/com/trash/garbage/security/UserCustom.java 0 → 100644
  1 +package com.trash.garbage.security;
  2 +
  3 +import com.alibaba.fastjson.annotation.JSONField;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import org.springframework.security.core.GrantedAuthority;
  7 +import org.springframework.security.core.authority.SimpleGrantedAuthority;
  8 +import org.springframework.security.core.userdetails.UserDetails;
  9 +import java.io.Serializable;
  10 +import java.util.Collection;
  11 +import java.util.List;
  12 +import java.util.stream.Collectors;
  13 +
  14 +/**
  15 + * @author 20412
  16 + */
  17 +@Data
  18 +@NoArgsConstructor
  19 +public class UserCustom implements Serializable , UserDetails {
  20 +
  21 + private static final long serialVersionUID = -2L;
  22 +
  23 + /**
  24 + * 用户实体
  25 + */
  26 + private UserAbstract user;
  27 +
  28 + /**
  29 + * 权限集合
  30 + */
  31 + private List<String> permissions;
  32 + @JSONField(serialize = false)
  33 + private Collection<? extends GrantedAuthority> authorities;
  34 +
  35 + /**
  36 + * 初始化构造
  37 + * @param user 用户实体
  38 + * @param permissions 权限集合
  39 + */
  40 + public UserCustom(UserAbstract user, List<String> permissions) {
  41 + this.user = user;
  42 + this.permissions = permissions;
  43 + }
  44 +
  45 + public UserAbstract getUser() {
  46 + return this.user;
  47 + }
  48 +
  49 + @Override
  50 + public Collection<? extends GrantedAuthority> getAuthorities() {
  51 + if (authorities != null){
  52 + return authorities;
  53 + }
  54 +
  55 + authorities = permissions.stream()
  56 + .map(SimpleGrantedAuthority::new)
  57 + .collect(Collectors.toList());
  58 +
  59 + return this.authorities;
  60 + }
  61 +
  62 + @Override
  63 + public String getPassword() {
  64 + return this.user.getTel();
  65 + }
  66 +
  67 + @Override
  68 + public String getUsername() {
  69 + return this.user.getTel();
  70 + }
  71 +
  72 + @Override
  73 + public boolean isAccountNonExpired() {
  74 + return true;
  75 + }
  76 +
  77 + @Override
  78 + public boolean isAccountNonLocked() {
  79 + return true;
  80 + }
  81 +
  82 + @Override
  83 + public boolean isCredentialsNonExpired() {
  84 + return true;
  85 + }
  86 +
  87 + @Override
  88 + public boolean isEnabled() {
  89 + return true;
  90 + }
  91 +}
trash-garbage/src/main/java/com/trash/garbage/service/AsyncJobHandlerService.java 0 → 100644
  1 +package com.trash.garbage.service;
  2 +
  3 +import org.springframework.scheduling.annotation.Async;
  4 +import org.springframework.stereotype.Service;
  5 +
  6 +import javax.annotation.Resource;
  7 +
  8 +/**
  9 + * 处理异步任务
  10 + * @author 20412
  11 + */
  12 +@Service
  13 +@Async
  14 +public class AsyncJobHandlerService {
  15 +
  16 +}
trash-garbage/src/main/java/com/trash/garbage/service/GarAddressService.java 0 → 100644
  1 +package com.trash.garbage.service;
  2 +
  3 +import com.trash.garbage.pojo.domain.GarAddress;
  4 +import com.baomidou.mybatisplus.extension.service.IService;
  5 +
  6 +/**
  7 +* @author 20412
  8 +* @description 针对表【gar_address(建筑垃圾-用户地址)】的数据库操作Service
  9 +* @createDate 2023-11-20 16:03:15
  10 +*/
  11 +public interface GarAddressService extends IService<GarAddress> {
  12 +
  13 +}
trash-garbage/src/main/java/com/trash/garbage/service/GarUserService.java 0 → 100644
  1 +package com.trash.garbage.service;
  2 +
  3 +import com.aliyuncs.exceptions.ClientException;
  4 +import com.trash.garbage.pojo.domain.GarUser;
  5 +import com.baomidou.mybatisplus.extension.service.IService;
  6 +import com.trash.garbage.pojo.vo.LoginVo;
  7 +
  8 +/**
  9 +* @author 20412
  10 +* @description 针对表【gar_user(建筑垃圾-用户表)】的数据库操作Service
  11 +* @createDate 2023-11-20 16:03:15
  12 +*/
  13 +public interface GarUserService extends IService<GarUser> {
  14 +
  15 + String login(LoginVo user);
  16 +
  17 + void sendVerify(String tel) throws ClientException;
  18 +}
trash-garbage/src/main/java/com/trash/garbage/service/impl/GarAddressServiceImpl.java 0 → 100644
  1 +package com.trash.garbage.service.impl;
  2 +
  3 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  4 +import com.trash.garbage.pojo.domain.GarAddress;
  5 +import com.trash.garbage.service.GarAddressService;
  6 +import com.trash.garbage.mapper.GarAddressMapper;
  7 +import org.springframework.stereotype.Service;
  8 +
  9 +/**
  10 +* @author 20412
  11 +* @description 针对表【gar_address(建筑垃圾-用户地址)】的数据库操作Service实现
  12 +* @createDate 2023-11-20 16:03:15
  13 +*/
  14 +@Service
  15 +public class GarAddressServiceImpl extends ServiceImpl<GarAddressMapper, GarAddress>
  16 + implements GarAddressService{
  17 +
  18 +}
  19 +
  20 +
  21 +
  22 +
trash-garbage/src/main/java/com/trash/garbage/service/impl/GarUserServiceImpl.java 0 → 100644
  1 +package com.trash.garbage.service.impl;
  2 +
  3 +import cn.hutool.http.HttpUtil;
  4 +import com.alibaba.fastjson.JSONObject;
  5 +import com.aliyuncs.exceptions.ClientException;
  6 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7 +import com.trash.garbage.config.WxConfig;
  8 +import com.trash.garbage.global.GlobalRedisProperties;
  9 +import com.trash.garbage.global.GlobalStatus;
  10 +import com.trash.garbage.global.Result;
  11 +import com.trash.garbage.pojo.domain.GarUser;
  12 +import com.trash.garbage.pojo.vo.LoginVo;
  13 +import com.trash.garbage.security.UserCustom;
  14 +import com.trash.garbage.service.GarUserService;
  15 +import com.trash.garbage.mapper.GarUserMapper;
  16 +import com.trash.garbage.utils.JwtUtils;
  17 +import com.trash.garbage.utils.RedisUtils;
  18 +import com.trash.garbage.utils.SMSUtils;
  19 +import com.trash.garbage.utils.ValidateCodeUtil;
  20 +import org.apache.commons.codec.binary.Base64;
  21 +import org.apache.commons.lang3.StringUtils;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.security.authentication.AuthenticationManager;
  24 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  25 +import org.springframework.security.core.Authentication;
  26 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  27 +import org.springframework.stereotype.Service;
  28 +import org.springframework.transaction.annotation.Transactional;
  29 +
  30 +import javax.annotation.Resource;
  31 +import javax.crypto.Cipher;
  32 +import javax.crypto.spec.IvParameterSpec;
  33 +import javax.crypto.spec.SecretKeySpec;
  34 +import java.security.spec.AlgorithmParameterSpec;
  35 +import java.util.Objects;
  36 +import java.util.concurrent.TimeUnit;
  37 +
  38 +/**
  39 + * @author 20412
  40 + * @description 针对表【gar_user(建筑垃圾-用户表)】的数据库操作Service实现
  41 + * @createDate 2023-11-20 16:03:15
  42 + */
  43 +@Service
  44 +@Transactional
  45 +public class GarUserServiceImpl extends ServiceImpl<GarUserMapper, GarUser>
  46 + implements GarUserService {
  47 + @Resource
  48 + private WxConfig wxConfig;
  49 + @Autowired
  50 + private AuthenticationManager authenticationManager;
  51 +
  52 + @Resource
  53 + private RedisUtils redisUtils;
  54 +
  55 +
  56 + @Override
  57 + public String login(LoginVo user) {
  58 + if (Objects.isNull(user)) {
  59 + throw new UsernameNotFoundException("当前用户不存在");
  60 + }
  61 + // TODO 微信登录
  62 + if (user.getLoginType().equals(GlobalStatus.UserStatusEnum.WX_LOGIN.getStatus())) {
  63 + String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxConfig.getAppId() + "&secret=" + wxConfig.getSecret() + "&js_code=" + user.getWxCode() + "&grant_type=authorization_code";
  64 + String body = HttpUtil.createGet(url).header("cache-control", "no-cache").execute().body();
  65 + JSONObject open = JSONObject.parseObject(body);
  66 + String sessionKey = open.getString("session_key");
  67 + try {
  68 + user.setTel(decrypt(user.getEncryptedData(), sessionKey, user.getIv()));
  69 + } catch (Exception e) {
  70 + throw new RuntimeException("解密失败");
  71 + }
  72 + }
  73 + // 验证码验证
  74 + Integer code = (Integer) redisUtils.get(GlobalRedisProperties.REDIS_USER_CODE.getValue() + user.getTel());
  75 + if (!code.equals(user.getCode())) {
  76 + throw new RuntimeException("验证码错误!!");
  77 + }
  78 + // 封装成authentication对象
  79 + Authentication authentication = new UsernamePasswordAuthenticationToken(user.getTel(), "");
  80 + // 开始认证
  81 + Authentication authenticate = authenticationManager.authenticate(authentication);
  82 + if (Objects.isNull(authenticate)) {
  83 + throw new RuntimeException("用户名或密码错误");
  84 + }
  85 + UserCustom userCustom = (UserCustom) authenticate.getPrincipal();
  86 + // 存入redis
  87 + redisUtils.set(GlobalRedisProperties.REDIS_USER_HEADER.getValue() + userCustom.getUser().getUserId(), userCustom);
  88 + // 修改在线状态
  89 + return JwtUtils.createToken(userCustom.getUser().getTel(), userCustom.getUser().getUserId());
  90 + }
  91 +
  92 + @Override
  93 + public void sendVerify(String tel) throws ClientException {
  94 + //随机生成6位数字验证码
  95 + Integer validateCode = ValidateCodeUtil.generatorCode(4);
  96 + //给用户发送验证码
  97 +// SMSUtils.sendMessage("", tel, validateCode.toString(), "");
  98 + // 保存redis
  99 + System.out.println("code:"+ validateCode);
  100 + redisUtils.setEx(GlobalRedisProperties.REDIS_USER_CODE.getValue() + tel, validateCode, 60, TimeUnit.SECONDS);
  101 + }
  102 +
  103 +
  104 + /**
  105 + * 微信小程序解密
  106 + *
  107 + * @param encrypted
  108 + * @param session_key
  109 + * @param iv
  110 + * @return
  111 + * @throws Exception
  112 + */
  113 + private String decrypt(String encrypted, String session_key, String iv) throws Exception {
  114 + byte[] encrypData = Base64.decodeBase64(encrypted);
  115 + byte[] ivData = Base64.decodeBase64(iv);
  116 + byte[] sessionKey = Base64.decodeBase64(session_key);
  117 + AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
  118 + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  119 + SecretKeySpec keySpec = new SecretKeySpec(sessionKey, "AES");
  120 + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
  121 + // 解析解密后的字符串
  122 + return new String(cipher.doFinal(encrypData), "UTF-8");
  123 + }
  124 +
  125 +
  126 +}
  127 +
  128 +
  129 +
  130 +
trash-garbage/src/main/java/com/trash/garbage/service/impl/UserDetailServiceImpl.java 0 → 100644
  1 +package com.trash.garbage.service.impl;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4 +import com.trash.garbage.global.GlobalStatus;
  5 +import com.trash.garbage.pojo.domain.GarUser;
  6 +import com.trash.garbage.security.UserCustom;
  7 +import com.trash.garbage.service.GarUserService;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.security.core.userdetails.UserDetails;
  10 +import org.springframework.security.core.userdetails.UserDetailsService;
  11 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import java.util.Collections;
  15 +import java.util.Objects;
  16 +
  17 +/**
  18 + * 用户信息实现类
  19 + * @author 20412
  20 + */
  21 +@Component
  22 +public class UserDetailServiceImpl implements UserDetailsService {
  23 +
  24 + @Autowired
  25 + private GarUserService userService;
  26 +
  27 + /** 查询数据库中的数据是否配对上 */
  28 + @Override
  29 + public UserDetails loadUserByUsername(String tel) throws UsernameNotFoundException {
  30 + // 查表是否有对应的tel
  31 + QueryWrapper<GarUser> qw = new QueryWrapper<>();
  32 + qw.lambda().eq(GarUser::getGarUserTel, tel);
  33 + GarUser user = userService.getOne(qw);
  34 + if (Objects.isNull(user)) {
  35 + // 不存在就创建用户
  36 + GarUser nUser = new GarUser();
  37 + nUser.setGarUserTel(tel);
  38 + nUser.setGarUserDelFlag(GlobalStatus.DEL_FLAG_NO);
  39 + nUser.setGarUserType("iphone");
  40 + if (userService.save(nUser)) {
  41 + return new UserCustom(nUser, Collections.emptyList());
  42 + }
  43 + }
  44 + // 第二参数是控制权限 普通用户无需角色认证
  45 + return new UserCustom(user, Collections.emptyList());
  46 + }
  47 +}
trash-garbage/src/main/java/com/trash/garbage/utils/FastJson2JsonRedisSerializer.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.parser.ParserConfig;
  5 +import com.alibaba.fastjson.serializer.SerializerFeature;
  6 +import com.fasterxml.jackson.databind.JavaType;
  7 +import com.fasterxml.jackson.databind.ObjectMapper;
  8 +import com.fasterxml.jackson.databind.type.TypeFactory;
  9 +import org.springframework.data.redis.serializer.RedisSerializer;
  10 +import org.springframework.data.redis.serializer.SerializationException;
  11 +import org.springframework.util.Assert;
  12 +
  13 +import java.nio.charset.Charset;
  14 +/**
  15 + * FastJson2JsonRedisSerializer
  16 + * Redis使用FastJson序列化
  17 + */
  18 +public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
  19 + private ObjectMapper objectMapper = new ObjectMapper();
  20 + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
  21 +
  22 + private Class<T> clazz;
  23 +
  24 + static {
  25 + ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  26 + //如果遇到反序列化autoType is not support错误,请添加并修改一下包名到bean文件路径
  27 + // ParserConfig.getGlobalInstance().addAccept("com.xxxxx.xxx");
  28 + }
  29 + public FastJson2JsonRedisSerializer(Class<T> clazz) {
  30 + super();
  31 + this.clazz = clazz;
  32 + }
  33 +
  34 + public byte[] serialize(T t) throws SerializationException {
  35 + if (t == null) {
  36 + return new byte[0];
  37 + }
  38 + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
  39 + }
  40 +
  41 + public T deserialize(byte[] bytes) throws SerializationException {
  42 + if (bytes == null || bytes.length <= 0) {
  43 + return null;
  44 + }
  45 + String str = new String(bytes, DEFAULT_CHARSET);
  46 +
  47 + return JSON.parseObject(str, clazz);
  48 + }
  49 + public void setObjectMapper(ObjectMapper objectMapper) {
  50 + Assert.notNull(objectMapper, "'objectMapper' must not be null");
  51 + this.objectMapper = objectMapper;
  52 + }
  53 +
  54 + protected JavaType getJavaType(Class<?> clazz) {
  55 + return TypeFactory.defaultInstance().constructType(clazz);
  56 + }
  57 +
  58 +}
trash-garbage/src/main/java/com/trash/garbage/utils/JsonUtil.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import com.alibaba.fastjson.JSON;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +
  9 +
  10 +/**
  11 + * @Author : guzijian
  12 + * @Description :
  13 + **/
  14 +public final class JsonUtil {
  15 + static Logger log = LoggerFactory.getLogger(JsonUtil.class) ;
  16 + /**
  17 + * 把Java对象转换成json字符串
  18 + *
  19 + * @param object 待转化为JSON字符串的Java对象
  20 + * @return json 串 or null
  21 + */
  22 + public static String parseObjToJson(Object object) {
  23 + String string = null;
  24 + try {
  25 + string = JSONObject.toJSONString(object);
  26 + } catch (Exception e) {
  27 + log.info("把Java对象转换成json字符串转换异常:{}",e.getMessage());
  28 + }
  29 + return string;
  30 + }
  31 +
  32 + /**
  33 + * 将Json字符串信息转换成对应的Java对象
  34 + *
  35 + * @param json json字符串对象
  36 + * @param c 对应的类型
  37 + */
  38 + public static <T> T parseJsonToObj(String json, Class<T> c) {
  39 + try {
  40 + JSONObject jsonObject = JSON.parseObject(json);
  41 + return JSON.toJavaObject(jsonObject, c);
  42 + } catch (Exception e) {
  43 + log.info("将Json字符串信息转换成对应的Java对象转换异常:{}",e.getMessage());
  44 + return null;
  45 + }
  46 + }
  47 +
  48 + public static <T> T parseObjToObj(Object obj,Class<T> clazz){
  49 + try {
  50 + return BeanUtil.toBean(obj, clazz);
  51 + }catch (Exception e){
  52 + log.info("将Json字符串信息转换成对应的Java对象转换异常:{}",e.getMessage());
  53 + }
  54 + return null;
  55 + }
  56 +}
0 \ No newline at end of file 57 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/utils/JwtUtils.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +import io.jsonwebtoken.*;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +
  6 +import javax.servlet.http.HttpServletRequest;
  7 +import java.util.Date;
  8 +
  9 +/**
  10 + * jwt 工具类
  11 + * @author 20412
  12 + */
  13 +@Slf4j
  14 +public class JwtUtils {
  15 +
  16 + /** 过期时间设置 365天*/
  17 + private final static long tokenExpiration = 365 * 24 * 60 * 60 * 1000;
  18 + /** jwt密钥*/
  19 + private final static String tokenSecret = "guzijian";
  20 +
  21 + /** 创建token */
  22 + public static String createToken(String username, String userId) {
  23 + String token = Jwts.builder()
  24 + // 说明
  25 + .setSubject("AUTH-USER")
  26 + // 过期时间
  27 + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
  28 + // 加入认证信息
  29 + .claim("userId",userId)
  30 + .claim("username",username)
  31 + // 加密方式 jwt 密钥方便解密
  32 + .signWith(SignatureAlgorithm.HS256, tokenSecret)
  33 + // 压缩方式
  34 + .compressWith(CompressionCodecs.GZIP)
  35 + // 构建契约
  36 + .compact();
  37 + return token;
  38 + }
  39 +
  40 + /** 通过token获取user id */
  41 + public static String getUserId(String token){
  42 + Claims claims = null;
  43 + try {
  44 + Jws<Claims> claimsJws = Jwts.parser()
  45 + .setSigningKey(tokenSecret)
  46 + .parseClaimsJws(token);
  47 + claims = claimsJws.getBody();
  48 + } catch (Exception e) {
  49 + log.info("token:{},反解析报错:{}",token,e.getMessage());
  50 + return null;
  51 + }
  52 + return (String)claims.get("userId");
  53 + }
  54 +
  55 + /** 获取用户id*/
  56 + public static String getUserId(HttpServletRequest request){
  57 + String token = request.getHeader("Authority");
  58 + Claims claims = null;
  59 + try {
  60 + Jws<Claims> claimsJws = Jwts.parser()
  61 + .setSigningKey(tokenSecret)
  62 + .parseClaimsJws(token);
  63 + claims = claimsJws.getBody();
  64 + } catch (Exception e) {
  65 + throw new RuntimeException("解析失败" + e.getMessage());
  66 + }
  67 + return (String)claims.get("userId");
  68 + }
  69 +
  70 + public static String getUserName(String token){
  71 + Claims claims = null;
  72 + try {
  73 + Jws<Claims> claimsJws = Jwts.parser()
  74 + .setSigningKey(tokenSecret)
  75 + .parseClaimsJws(token);
  76 + claims = claimsJws.getBody();
  77 + } catch (Exception e) {
  78 + throw new RuntimeException("token解析失败" + e.getMessage());
  79 + }
  80 + return (String)claims.get("username");
  81 + }
  82 +
  83 + public static String getUserName(HttpServletRequest request){
  84 + String token = request.getHeader("Authority");
  85 + Claims claims = null;
  86 + try {
  87 + Jws<Claims> claimsJws = Jwts.parser()
  88 + .setSigningKey(tokenSecret)
  89 + .parseClaimsJws(token);
  90 + claims = claimsJws.getBody();
  91 + } catch (Exception e) {
  92 + throw new RuntimeException("token解析失败" + e.getMessage());
  93 + }
  94 + return (String)claims.get("username");
  95 + }
  96 +
  97 + public String getUserIdByRequest(HttpServletRequest request){
  98 + String authorization = request.getHeader("Authorization");
  99 + Claims claims = null;
  100 + try {
  101 + Jws<Claims> claimsJws = Jwts.parser()
  102 + .setSigningKey(tokenSecret)
  103 + .parseClaimsJws(authorization);
  104 + claims = claimsJws.getBody();
  105 + } catch (Exception e) {
  106 + throw new RuntimeException("token解析失败" + e.getMessage());
  107 + }
  108 + return (String)claims.get("userId");
  109 + }
  110 +
  111 +// public static void main(String[] args) {
  112 +// String guzijian = createToken(new UserCustom(new User("1", "204126329@qq.com", "guzijian"), Collections.emptyList()));
  113 +// System.out.println(guzijian);
  114 +// }
  115 +}
trash-garbage/src/main/java/com/trash/garbage/utils/RedisUtils.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import org.springframework.beans.factory.annotation.Autowired;
  5 +import org.springframework.data.redis.core.RedisTemplate;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import java.util.concurrent.TimeUnit;
  9 +
  10 +/**
  11 + * redis工具类
  12 + * @author guzijian
  13 + */
  14 +@Component
  15 +public class RedisUtils {
  16 +
  17 + @Autowired
  18 + private RedisTemplate redisTemplate;
  19 +
  20 + public void set(String key, Object obj){
  21 + redisTemplate.opsForValue().set(key, obj);
  22 + }
  23 +
  24 + public Object get(String key){
  25 + return redisTemplate.opsForValue().get(key);
  26 + }
  27 +
  28 + public <T> T get(String key,Class<T> clazz){
  29 + return BeanUtil.toBean(redisTemplate.opsForValue().get(key), clazz);
  30 + }
  31 +
  32 + public boolean setNxAndEx(String key,String value,long expireTime){
  33 + return redisTemplate.opsForValue().setIfAbsent(key,value,expireTime, TimeUnit.SECONDS);
  34 + }
  35 +
  36 + public Boolean remove(String key){
  37 + return redisTemplate.delete(key);
  38 + }
  39 +
  40 + public void setEx(String key,Object obj,long time,TimeUnit unit){
  41 + redisTemplate.opsForValue().set(key, obj, time, unit);
  42 + }
  43 +}
trash-garbage/src/main/java/com/trash/garbage/utils/SMSUtils.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +
  4 +import com.aliyuncs.DefaultAcsClient;
  5 +import com.aliyuncs.IAcsClient;
  6 +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
  7 +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
  8 +import com.aliyuncs.exceptions.ClientException;
  9 +import com.aliyuncs.profile.DefaultProfile;
  10 +
  11 +/**
  12 + * 短信发送工具类
  13 + */
  14 +public class SMSUtils {
  15 +
  16 + /**
  17 + * 发送短信
  18 + * @param signName 签名
  19 + * @param templateCode 模板
  20 + * @param phoneNumbers 手机号
  21 + * @param param 参数
  22 + */
  23 + public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param) throws ClientException {
  24 + DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI5tHRxs2FeCu5JcJTGbm2", "v0H4PaJpXSwNr6XChtlVYAgmQWgKRA");
  25 +
  26 + IAcsClient client = new DefaultAcsClient(profile);
  27 +
  28 + SendSmsRequest request = new SendSmsRequest();
  29 +
  30 + request.setSysRegionId("cn-hangzhou");
  31 +// 要发送给那个人的电话号码
  32 + request.setPhoneNumbers(phoneNumbers);
  33 +// 我们在阿里云设置的签名
  34 + request.setSignName(signName);
  35 +// 我们在阿里云设置的模板
  36 + request.setTemplateCode(templateCode);
  37 +// 在设置模板的时候有一个占位符
  38 + request.setTemplateParam("{\"code\":\""+param+"\"}");
  39 +
  40 +// request.setPhoneNumbers("1368846****");//接收短信的手机号码
  41 +// request.setSignName("阿里云");//短信签名名称
  42 +// request.setTemplateCode("SMS_20933****");//短信模板CODE
  43 +// request.setTemplateParam("张三");//短信模板变量对应的实际值
  44 +
  45 + SendSmsResponse response = client.getAcsResponse(request);
  46 + }
  47 +
  48 +}
0 \ No newline at end of file 49 \ No newline at end of file
trash-garbage/src/main/java/com/trash/garbage/utils/SecurityUtil.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +import com.trash.garbage.security.UserCustom;
  4 +import org.springframework.security.core.context.SecurityContextHolder;
  5 +
  6 +/**
  7 + * @author 20412
  8 + */
  9 +public class SecurityUtil {
  10 +
  11 +
  12 + public static UserCustom getUserCustom() {
  13 + if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof UserCustom)
  14 + return (UserCustom) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  15 + return null;
  16 + }
  17 +
  18 +}
trash-garbage/src/main/java/com/trash/garbage/utils/ValidateCodeUtil.java 0 → 100644
  1 +package com.trash.garbage.utils;
  2 +
  3 +import java.util.Random;
  4 +
  5 +public class ValidateCodeUtil {
  6 + public static Integer generatorCode(int bit){
  7 + int code = 0;
  8 + for (int i = 0; i < bit; i++) {
  9 + code = code * 10 + new Random().nextInt(10);
  10 + }
  11 + return code;
  12 + }
  13 +}
trash-garbage/src/main/resources/application-dev.yml 0 → 100644
  1 +spring:
  2 + datasource:
  3 + type: com.alibaba.druid.pool.DruidDataSource
  4 + driverClassName: com.mysql.cj.jdbc.Driver
  5 + druid:
  6 + # 主库数据源
  7 + url: jdbc:mysql://localhost:3306/trash?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&useAffectedRows=true&allowMultiQueries=true
  8 + username: root
  9 + password: guzijian
  10 + # 初始连接数
  11 + initialSize: 5
  12 + # 最小连接池数量
  13 + minIdle: 10
  14 + # 最大连接池数量
  15 + maxActive: 20
  16 + # 配置获取连接等待超时的时间
  17 + maxWait: 60000
  18 + # 配置连接超时时间
  19 + connectTimeout: 30000
  20 + # 配置网络超时时间
  21 + socketTimeout: 60000
  22 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  23 + timeBetweenEvictionRunsMillis: 60000
  24 + # 配置一个连接在池中最小生存的时间,单位是毫秒
  25 + minEvictableIdleTimeMillis: 300000
  26 + # 配置一个连接在池中最大生存的时间,单位是毫秒
  27 + maxEvictableIdleTimeMillis: 900000
  28 + # 配置检测连接是否有效
  29 + validationQuery: SELECT 1 FROM DUAL
  30 + testWhileIdle: true
  31 + testOnBorrow: false
  32 + testOnReturn: false
  33 + webStatFilter:
  34 + enabled: true
  35 + statViewServlet:
  36 + enabled: true
  37 + # 设置白名单,不填则允许所有访问
  38 + allow:
  39 + url-pattern: /druid/*
  40 + # 控制台管理用户名和密码
  41 + login-username: ruoyi
  42 + login-password: 123456
  43 + filter:
  44 + stat:
  45 + enabled: true
  46 + # 慢SQL记录
  47 + log-slow-sql: true
  48 + slow-sql-millis: 1000
  49 + merge-sql: true
  50 + wall:
  51 + config:
  52 + multi-statement-allow: true
  53 + redis:
  54 + # 地址
  55 +# host: 121.41.83.61
  56 + host: 192.168.172.221
  57 + database: 0
  58 + # password: "guzijian"
  59 + port: 6378
  60 + # 连接超时时间
  61 + timeout: 10s
  62 + lettuce:
  63 + pool:
  64 + # 连接池中的最小空闲连接
  65 + min-idle: 0
  66 + # 连接池中的最大空闲连接
  67 + max-idle: 8
  68 + # 连接池的最大数据库连接数
  69 + max-active: 8
  70 + # #连接池最大阻塞等待时间(使用负值表示没有限制)
  71 + max-wait: -1ms
  72 + #返回json的全局时间格式
  73 + jackson:
  74 + date-format: yyyy-MM-dd HH:mm:ss
  75 + time-zone: GMT+8
  76 +
  77 +# mybaits 配置
  78 +mybatis-plus:
  79 + global-config:
  80 + # 指定逻辑删除含义
  81 + db-config:
  82 + logic-delete-field: delFlag
  83 + logic-delete-value: 1
  84 + logic-not-delete-value: 0
  85 + configuration:
  86 + # 日志打印sql
  87 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  88 +
  89 +trash:
  90 + garbage:
  91 + config:
  92 + location:
  93 + # security 放行路径
  94 + exclude: /user/login,/user/send/verify,/user/sendCode/**,/doc.html,/swagger-ui.html,/swagger-ui/**,/swagger-resources/**,/v2/api-docs,/v3/api-docs,/webjars/**,/ws/**
  95 +
  96 +wx:
  97 + appId: 'wxc3f60667dc9d6cea'
  98 + secret: 'd35996a9f898dff37974efba0b6f23ed'
0 \ No newline at end of file 99 \ No newline at end of file
trash-garbage/src/main/resources/application.yml 0 → 100644
  1 +server:
  2 + servlet:
  3 + context-path:
  4 + port: 9090
  5 +spring:
  6 + profiles:
  7 + active: dev
0 \ No newline at end of file 8 \ No newline at end of file
trash-garbage/src/main/resources/mapper/GarAddressMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper
  3 + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4 + "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5 +<mapper namespace="com.trash.garbage.mapper.GarAddressMapper">
  6 +
  7 + <resultMap id="BaseResultMap" type="com.trash.garbage.pojo.domain.GarAddress">
  8 + <id property="garAddressId" column="gar_address_id" jdbcType="BIGINT"/>
  9 + <result property="garUserId" column="gar_user_id" jdbcType="BIGINT"/>
  10 + <result property="garUserAddress" column="gar_user_address" jdbcType="VARCHAR"/>
  11 + <result property="garUserDefault" column="gar_user_default" jdbcType="TINYINT"/>
  12 + <result property="garCreateTime" column="gar_create_time" jdbcType="TIMESTAMP"/>
  13 + <result property="garUpdateTime" column="gar_update_time" jdbcType="TIMESTAMP"/>
  14 + <result property="garRemark" column="gar_remark" jdbcType="VARCHAR"/>
  15 + </resultMap>
  16 +
  17 + <sql id="Base_Column_List">
  18 + gar_address_id,gar_user_id,gar_user_address,
  19 + gar_user_default,gar_create_time,gar_update_time,
  20 + gar_remark
  21 + </sql>
  22 +</mapper>
trash-garbage/src/main/resources/mapper/GarUserMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper
  3 + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4 + "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5 +<mapper namespace="com.trash.garbage.mapper.GarUserMapper">
  6 +
  7 + <resultMap id="BaseResultMap" type="com.trash.garbage.pojo.domain.GarUser">
  8 + <id property="garUserId" column="gar_user_id" jdbcType="VARCHAR"/>
  9 + <result property="garUserTel" column="gar_user_tel" jdbcType="BIGINT"/>
  10 + <result property="garUserName" column="gar_user_name" jdbcType="VARCHAR"/>
  11 + <result property="garUserType" column="gar_user_type" jdbcType="VARCHAR"/>
  12 + <result property="garUserCarNum" column="gar_user_car_num" jdbcType="VARCHAR"/>
  13 + <result property="garUserDelFlag" column="gar_user_del_flag" jdbcType="INTEGER"/>
  14 + <result property="garCreateTime" column="gar_create_time" jdbcType="TIMESTAMP"/>
  15 + <result property="garUpdateTime" column="gar_update_time" jdbcType="TIMESTAMP"/>
  16 + <result property="garRemark" column="gar_remark" jdbcType="VARCHAR"/>
  17 + </resultMap>
  18 +
  19 + <sql id="Base_Column_List">
  20 + gar_user_id,gar_user_tel,gar_user_name,
  21 + gar_user_type,gar_user_car_num,gar_user_del_flag,
  22 + gar_create_time,gar_update_time,gar_remark
  23 + </sql>
  24 +</mapper>
trash-ui/src/layout/index.vue
1 <template> 1 <template>
  2 + <div :class="classObj" class="app-wrapper">
  3 + <sidebar class="sidebar-container" />
  4 + <div :class="{ hasTagsView: true }" class="main-container">
  5 + <tags-view v-if="needTagsView" />
2 <app-main /> 6 <app-main />
  7 +
  8 + </div>
  9 + </div>
3 </template> 10 </template>
4 11
5 <script> 12 <script>
6 import RightPanel from '@/components/RightPanel' 13 import RightPanel from '@/components/RightPanel'
  14 +import { mapState } from 'vuex'
7 import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components' 15 import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
8 import ResizeMixin from './mixin/ResizeHandler' 16 import ResizeMixin from './mixin/ResizeHandler'
9 -import { mapState } from 'vuex'  
10 17
11 export default { 18 export default {
12 name: 'Layout', 19 name: 'Layout',
@@ -45,45 +52,56 @@ export default { @@ -45,45 +52,56 @@ export default {
45 </script> 52 </script>
46 53
47 <style lang="scss" scoped> 54 <style lang="scss" scoped>
48 - @import "~@/assets/styles/mixin.scss";  
49 - @import "~@/assets/styles/variables.scss"; 55 +@import "~@/assets/styles/mixin.scss";
  56 +@import "~@/assets/styles/variables.scss";
50 57
51 - .app-wrapper {  
52 - @include clearfix;  
53 - position: relative;  
54 - height: 100%;  
55 - width: 100%;  
56 -  
57 - &.mobile.openSidebar {  
58 - position: fixed;  
59 - top: 0;  
60 - }  
61 - } 58 +.app-wrapper {
  59 + @include clearfix;
  60 + position: relative;
  61 + height: 100%;
  62 + width: 100%;
62 63
63 - .drawer-bg {  
64 - background: #000;  
65 - opacity: 0.3;  
66 - width: 100%;  
67 - top: 0;  
68 - height: 100%;  
69 - position: absolute;  
70 - z-index: 999;  
71 - }  
72 -  
73 - .fixed-header { 64 + &.mobile.openSidebar {
74 position: fixed; 65 position: fixed;
75 top: 0; 66 top: 0;
76 - right: 0;  
77 - z-index: 9;  
78 - width: calc(100% - #{$sideBarWidth});  
79 - transition: width 0.28s;  
80 } 67 }
  68 +}
81 69
82 - .hideSidebar .fixed-header {  
83 - width: calc(100% - 54px)  
84 - } 70 +.drawer-bg {
  71 + background: #000;
  72 + opacity: 0.3;
  73 + width: 100%;
  74 + top: 0;
  75 + height: 100%;
  76 + position: absolute;
  77 + z-index: 999;
  78 +}
85 79
86 - .mobile .fixed-header {  
87 - width: 100%;  
88 - } 80 +.fixed-header {
  81 + position: fixed;
  82 + top: 0;
  83 + right: 0;
  84 + z-index: 9;
  85 + width: calc(100% - #{$sideBarWidth});
  86 + transition: width 0.28s;
  87 +}
  88 +
  89 +.hideSidebar .fixed-header {
  90 + width: calc(100% - 54px)
  91 +}
  92 +
  93 +.mobile .fixed-header {
  94 + width: 100%;
  95 +}
  96 +
  97 +.preview figure {
  98 + float: left;
  99 + width: 30%;
  100 + height: calc(30vw - 0px);
  101 + margin: 1.5%;
  102 +}
  103 +
  104 +.preview figure img {
  105 + width: 400px;
  106 +}
89 </style> 107 </style>
trash-ui/src/layout/index44.vue
1 <template> 1 <template>
2 - <div :class="classObj" class="app-wrapper">  
3 - <sidebar class="sidebar-container"/>  
4 - <div :class="{hasTagsView:needTagsView}" class="main-container">  
5 - <tags-view v-if="needTagsView"/>  
6 - <app-main/>  
7 -  
8 - </div>  
9 - </div> 2 + <app-main />
10 </template> 3 </template>
11 4
12 <script> 5 <script>
13 import RightPanel from '@/components/RightPanel' 6 import RightPanel from '@/components/RightPanel'
14 -import {AppMain, Navbar, Settings, Sidebar, TagsView} from './components' 7 +import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
15 import ResizeMixin from './mixin/ResizeHandler' 8 import ResizeMixin from './mixin/ResizeHandler'
16 -import {mapState} from 'vuex' 9 +import { mapState } from 'vuex'
17 10
18 export default { 11 export default {
19 name: 'Layout', 12 name: 'Layout',
@@ -45,63 +38,52 @@ export default { @@ -45,63 +38,52 @@ export default {
45 }, 38 },
46 methods: { 39 methods: {
47 handleClickOutside() { 40 handleClickOutside() {
48 - this.$store.dispatch('app/closeSideBar', {withoutAnimation: false}) 41 + this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
49 } 42 }
50 } 43 }
51 } 44 }
52 </script> 45 </script>
53 46
54 <style lang="scss" scoped> 47 <style lang="scss" scoped>
55 -@import "~@/assets/styles/mixin.scss";  
56 -@import "~@/assets/styles/variables.scss"; 48 + @import "~@/assets/styles/mixin.scss";
  49 + @import "~@/assets/styles/variables.scss";
57 50
58 -.app-wrapper {  
59 - @include clearfix;  
60 - position: relative;  
61 - height: 100%;  
62 - width: 100%; 51 + .app-wrapper {
  52 + @include clearfix;
  53 + position: relative;
  54 + height: 100%;
  55 + width: 100%;
63 56
64 - &.mobile.openSidebar {  
65 - position: fixed;  
66 - top: 0; 57 + &.mobile.openSidebar {
  58 + position: fixed;
  59 + top: 0;
  60 + }
67 } 61 }
68 -}  
69 62
70 -.drawer-bg {  
71 - background: #000;  
72 - opacity: 0.3;  
73 - width: 100%;  
74 - top: 0;  
75 - height: 100%;  
76 - position: absolute;  
77 - z-index: 999;  
78 -}  
79 -  
80 -.fixed-header {  
81 - position: fixed;  
82 - top: 0;  
83 - right: 0;  
84 - z-index: 9;  
85 - width: calc(100% - #{$sideBarWidth});  
86 - transition: width 0.28s;  
87 -}  
88 -  
89 -.hideSidebar .fixed-header {  
90 - width: calc(100% - 54px)  
91 -} 63 + .drawer-bg {
  64 + background: #000;
  65 + opacity: 0.3;
  66 + width: 100%;
  67 + top: 0;
  68 + height: 100%;
  69 + position: absolute;
  70 + z-index: 999;
  71 + }
92 72
93 -.mobile .fixed-header {  
94 - width: 100%;  
95 -} 73 + .fixed-header {
  74 + position: fixed;
  75 + top: 0;
  76 + right: 0;
  77 + z-index: 9;
  78 + width: calc(100% - #{$sideBarWidth});
  79 + transition: width 0.28s;
  80 + }
96 81
97 -.preview figure {  
98 - float: left;  
99 - width: 30%;  
100 - height:calc(30vw - 0px);  
101 - margin: 1.5%;  
102 -} 82 + .hideSidebar .fixed-header {
  83 + width: calc(100% - 54px)
  84 + }
103 85
104 -.preview figure img {  
105 - width: 400px;  
106 -} 86 + .mobile .fixed-header {
  87 + width: 100%;
  88 + }
107 </style> 89 </style>