Explorar el Código

项目初始化

shiwn hace 6 meses
commit
129b6ab479

+ 200 - 0
pom.xml

@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.4.5</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.sw</groupId>
+    <artifactId>bird</artifactId>
+    <version>0.0.1</version>
+    <name>bird</name>
+    <description>bird_sys</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <tomcat.version>9.0.64</tomcat.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!--        tomcat版本指定            -->
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>tomcat-juli</artifactId>
+            <version>${tomcat.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-logging-juli</artifactId>
+            <version>8.5.2</version>
+        </dependency>
+        <!--        thymeleaf-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.1.1</version>
+        </dependency>
+
+        <!--        lombok-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- mybatis启动器-->
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.1.1</version>
+        </dependency>
+        <!--mybatis分页插件-->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.2.5</version>
+        </dependency>
+        <!--        mybatis-plus-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generator</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <!-- 数据库驱动-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <!--数据库连接池-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.1.8</version>
+        </dependency>
+        <!--        Redis依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!--swagger用于定义API文档  -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <!--bootstrap ui下的swagger-->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>swagger-bootstrap-ui</artifactId>
+            <version>1.9.6</version>
+        </dependency>
+
+        <!--json处理-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.83</version>
+        </dependency>
+
+        <!--日志框架,SpringBoot默认的日志系统logback-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+        </dependency>
+
+        <!--        Apache commons io-->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.8.0</version>
+        </dependency>
+
+        <!-- redis依赖commons-pool 这个依赖一定要添加 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <!-- 工具包-->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.4</version>
+        </dependency>
+
+        <!-- log4j -->
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <!-- 自动导入本地jar包 -->
+                    <includeSystemScope>true</includeSystemScope>
+                    <fork>true</fork>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+
+            <!-- 解决webSocket打包冲突问题 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 15 - 0
src/main/java/com/sw/bird/BirdApplication.java

@@ -0,0 +1,15 @@
+package com.sw.bird;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@MapperScan(value = {"com.sw.bird.mapper"}) // 扫描mapper
+@SpringBootApplication
+public class BirdApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(BirdApplication.class, args);
+    }
+
+}

+ 126 - 0
src/main/java/com/sw/bird/common/ResultData.java

@@ -0,0 +1,126 @@
+package com.sw.bird.common;
+
+import com.sw.bird.exception.ErrorCode;
+
+/**
+ * Created by shiwn on 2021-05-08
+ */
+public class ResultData<T> {
+
+    /**
+     * 默认:0成功,1失败,205结果为null,500系统异常
+     */
+    private Integer code;
+    private String msg;
+    private T data;
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public ResultData() {
+        this.code = 0;
+        this.msg = "操作成功";
+    }
+
+    public ResultData(Integer code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public ResultData(Integer code, T obj) {
+        this.code = code;
+        this.data = obj;
+    }
+
+    private ResultData(T data) {
+        this.code = 0;
+        this.msg = "操作成功";
+        this.data = data;
+    }
+
+    private ResultData(ErrorCode data) {
+        this.code = data.getCode();
+        this.msg = data.getMsg();
+        this.data = null;
+    }
+
+    /**
+     * 操作成功,无返回数据
+     *
+     * @return 0
+     */
+    public static ResultData success() {
+        return new ResultData();
+    }
+
+    /**
+     * @Description: 操作执行成功,并判断返回值
+     * @Param: [data]
+     * @Author: shiwn
+     * @Date: 2020/8/3 15:56
+     */
+    public static ResultData success(Object data) {
+        //  判断空值
+        if (data != null) {
+            return new ResultData(data);
+        } else {
+            return ResultData.emptyData();
+        }
+    }
+
+
+    /**
+     * 操作失败
+     *
+     * @param code code
+     * @param msg  操作信息
+     * @return ResultData
+     */
+    public static ResultData fail(Integer code, String msg) {
+        return new ResultData(code, msg);
+    }
+
+    /**
+     * @Description: 操作成功,但返回值为null
+     * @Param: [data]
+     * @Author: shiwn
+     * @Date: 2020/8/3 15:57
+     */
+    public static ResultData emptyData() {
+        return new ResultData(205, "查询结果为空");
+    }
+
+    public static ResultData fail(String msg) {
+        return new ResultData(1, msg);
+    }
+
+    public static ResultData fail(ErrorCode errorCode) {
+        return new ResultData(errorCode);
+    }
+
+    public static ResultData fail() {
+        return new ResultData(1, "操作失败");
+    }
+
+}

+ 47 - 0
src/main/java/com/sw/bird/config/ACAFilter.java

@@ -0,0 +1,47 @@
+package com.sw.bird.config;
+
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 跨域的设置问题
+ * Created by shiwn on 2021-01-14.
+ */
+@Component
+public class ACAFilter implements Filter {
+
+
+    /**
+     * 初始化
+     */
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    /**
+     * 过滤器配置参数
+     */
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
+        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
+        response.setHeader("Access-Control-Max-Age", "3600");
+        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
+        response.setHeader("Access-Control-Allow-Credentials", "true");
+        //System.out.println("*********************************过滤器被使用**************************");
+        filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    /**
+     * 销毁
+     */
+    @Override
+    public void destroy() {
+    }
+}

+ 60 - 0
src/main/java/com/sw/bird/config/DruidConfig.java

@@ -0,0 +1,60 @@
+package com.sw.bird.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.support.http.StatViewServlet;
+import com.alibaba.druid.support.http.WebStatFilter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+/**
+ * 访问地址:http://localhost:8081/druid/login.html
+ * Updated by shiwn on 2021/11/22 10:19
+ */
+@Configuration
+public class DruidConfig {
+    /**
+     * 将所有前缀为spring.datasource下的配置项都加载DataSource中
+     */
+    @Bean
+    @ConfigurationProperties(prefix = "spring.datasource")
+    public DataSource druid() {
+        return new DruidDataSource();
+    }
+
+    //  配置druid的监控
+    @Bean
+    public ServletRegistrationBean registrationBean() {
+        ServletRegistrationBean registrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
+        // 白名单,默认是允许所有的访问
+        registrationBean.addInitParameter("allow", "localhost");
+        // 黑名单
+        registrationBean.addInitParameter("deny", "");
+        // 用户名
+        registrationBean.addInitParameter("loginUsername", "admin");
+        // 密码
+        registrationBean.addInitParameter("loginPassword", "123456");
+        // 是否可以重置数据源
+        registrationBean.addInitParameter("resetEnable", "false");
+        return registrationBean;
+    }
+
+
+    /**
+     * 配置监控的filter
+     */
+    @Bean
+    public FilterRegistrationBean webStatFilter() {
+        FilterRegistrationBean bean = new FilterRegistrationBean();
+        bean.setFilter(new WebStatFilter());
+        // 所有请求进行监控处理
+        bean.addUrlPatterns("/*");
+        // 排除名单
+        bean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
+        return bean;
+    }
+}

+ 17 - 0
src/main/java/com/sw/bird/config/MybatisPlusConfig.java

@@ -0,0 +1,17 @@
+package com.sw.bird.config;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * MybatisPlus分页配置
+ * Created by shiwn on 2021/5/10 16:43
+ */
+@Configuration
+public class MybatisPlusConfig {
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        return new PaginationInterceptor();
+    }
+}

+ 65 - 0
src/main/java/com/sw/bird/config/Swagger2.java

@@ -0,0 +1,65 @@
+package com.sw.bird.config;
+
+import com.google.common.base.Predicate;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.RequestHandler;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+
+/**
+ * swagger文档配置
+ *
+ * 访问地址:http://localhost:8080/swagger-ui.html
+ * 优化后地址:http://localhost:8080/doc.html
+ *
+ * 参照:https://www.jianshu.com/p/7e543f0f0bd8
+ *
+ */
+@Configuration
+@EnableSwagger2
+public class Swagger2 {
+
+	@Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(basePackage("com.sw.bird.controller"))
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("驱鸟系统")
+                .description("驱鸟系统-doc")
+                .termsOfServiceUrl("http://localhost:8090/doc.html")
+                .version("1.0")
+                .build();
+    }
+
+    // 定义分隔符
+    private static final String splitor = ";";
+
+    private static Predicate<RequestHandler> basePackage(final String basePackage) {
+        return input -> {
+            // 循环判断匹配
+            for (String everyPackage : basePackage.split(splitor)) {
+                boolean isMatch = declaringClass(input).getPackage().getName().startsWith(everyPackage);
+                if (isMatch) {
+                    return true;
+                }
+            }
+            return false;
+        };
+    }
+
+    private static Class<?> declaringClass(RequestHandler input) {
+        return input.getHandlerMethod().getMethod().getDeclaringClass();
+    }
+
+}

+ 45 - 0
src/main/java/com/sw/bird/controller/SystemController.java

@@ -0,0 +1,45 @@
+package com.sw.bird.controller;
+
+import com.sw.bird.common.ResultData;
+import com.sw.bird.controller.api.SystemApi;
+import com.sw.bird.exception.BusinessException;
+import com.sw.bird.exception.ErrorCode;
+import com.sw.bird.service.SystemService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * Created by shiwn on 2024/5/29 16:19
+ */
+@RestController
+@RequestMapping("system")
+public class SystemController implements SystemApi {
+    @Autowired
+    private SystemService systemService;
+
+    @Override
+    @PostMapping("login")
+    public ResultData login(@RequestBody Map map, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        if (map.get("account") == null) {
+            throw new BusinessException(ErrorCode.ACCOUNT_NULL);
+        }
+        if (map.get("passWord") == null) {
+            throw new BusinessException(ErrorCode.PASSWORD_NULL);
+        }
+        String account = map.get("account").toString();
+        String passWord = map.get("passWord").toString();
+        return ResultData.success(systemService.login(account, passWord, request, response));
+    }
+
+    @Override
+    @GetMapping("/quit")
+    public ResultData quit(HttpServletRequest request) {
+        request.getSession().removeAttribute("loginUserDTO");
+        request.getSession().removeAttribute("loginUser");
+        return ResultData.success("");
+    }
+}

+ 27 - 0
src/main/java/com/sw/bird/controller/api/SystemApi.java

@@ -0,0 +1,27 @@
+package com.sw.bird.controller.api;
+
+import com.sw.bird.common.ResultData;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * Created by shiwn on 2024/5/29 16:19
+ */
+@Api(tags = {"系统管理"})
+public interface SystemApi {
+    @ApiOperation(value = "登录")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "map", value = "{ account:用户名,passWord:密码 }")
+    })
+    ResultData login(@RequestBody Map map, HttpServletRequest request, HttpServletResponse response) throws Exception;
+
+    @ApiOperation(value = "退出登录")
+    ResultData quit(HttpServletRequest request);
+}

+ 82 - 0
src/main/java/com/sw/bird/domain/dto/SystemDictDTO.java

@@ -0,0 +1,82 @@
+package com.sw.bird.domain.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @author machao
+ * @version 1.0
+ * @description: 字典实体类
+ * @date 2021/5/17 13:47
+ */
+@TableName("system_dict")
+public class SystemDictDTO {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("字段名称")
+    private String typeName;
+
+    @ApiModelProperty("字典类型(1:系统字典;2:驱鸟相关字典)")
+    private Integer type;
+
+    @ApiModelProperty("字典名称")
+    private String dictName;
+
+    @ApiModelProperty("字典key值")
+    private String textName;
+
+    @ApiModelProperty("字典value值")
+    private Integer textValue;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getTypeName() {
+        return typeName;
+    }
+
+    public void setTypeName(String typeName) {
+        this.typeName = typeName;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public String getDictName() {
+        return dictName;
+    }
+
+    public void setDictName(String dictName) {
+        this.dictName = dictName;
+    }
+
+    public String getTextName() {
+        return textName;
+    }
+
+    public void setTextName(String textName) {
+        this.textName = textName;
+    }
+
+    public Integer getTextValue() {
+        return textValue;
+    }
+
+    public void setTextValue(Integer textValue) {
+        this.textValue = textValue;
+    }
+}

+ 82 - 0
src/main/java/com/sw/bird/domain/dto/UserDTO.java

@@ -0,0 +1,82 @@
+package com.sw.bird.domain.dto;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * @author machao
+ * @version 1.0
+ * @description: 用户表实体类
+ * @date 2021/5/10 13:55
+ */
+@Data
+@Accessors(chain = true)
+@TableName("user")
+public class UserDTO {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "用户名")
+    private String account;
+
+    @ApiModelProperty(value = "密码")
+    private String password;
+
+    @ApiModelProperty(value = "姓名")
+    private String name;
+
+    @ApiModelProperty(value = "手机号")
+    private String mobile;
+
+    @ApiModelProperty(value = "邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "备注")
+    private String note;
+
+    @ApiModelProperty(value = "部门id")
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Integer deptId;
+
+    @ApiModelProperty(value = "角色id")
+    private Integer roleId;
+
+    @ApiModelProperty(value = "登录ip")
+    private String loginIp;
+
+    @ApiModelProperty(value = "登录时间")
+    private String loginTime;
+
+    @ApiModelProperty(value = "账户状态 0:停用 1:启用")
+    private Integer status;
+
+    @ApiModelProperty(value = "信息提醒状态 0:关闭 1:接收短信 2:接收邮箱 3:全部接收")
+    private Integer msgStatus;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty(value = "创建人用户id")
+    private Integer createUserId;
+
+    @ApiModelProperty(value = "更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "更新人用户id")
+    private Integer updateUserId;
+
+    @ApiModelProperty(value = "逻辑删除标志 Y:已删除 N:正常")
+    private String delFlag;
+
+    @ApiModelProperty(value = "app头像")
+    private String icon;
+
+}

+ 31 - 0
src/main/java/com/sw/bird/exception/BusinessException.java

@@ -0,0 +1,31 @@
+package com.sw.bird.exception;
+
+/**
+ * @Description: 自定义异常类
+ * @Author: shiwn
+ * @Date: 2020/1/17 11:13
+ */
+public final class BusinessException extends RuntimeException {
+
+    private int code;
+
+    public BusinessException(int exceptionCode, String message, Throwable clause) {
+        super(message, clause);
+        code = exceptionCode;
+    }
+
+    public BusinessException(int exceptionCode, String message) {
+        super(message);
+
+        code = exceptionCode;
+    }
+
+    public BusinessException(ErrorCode errorCode) {
+        super(errorCode.getMsg());
+        code = errorCode.getCode();
+    }
+
+    public final int getCode() {
+        return code;
+    }
+}

+ 103 - 0
src/main/java/com/sw/bird/exception/ControllerAdviceHandle.java

@@ -0,0 +1,103 @@
+package com.sw.bird.exception;
+
+import com.sw.bird.common.ResultData;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 自定义异常处理
+ * @Author: shiwn
+ * @Date: 2020/1/17 11:19
+ */
+@RestController
+@ControllerAdvice
+public class ControllerAdviceHandle {
+
+    /**
+     * @Description: 处理自定义异常
+     * @Param: [request, e]
+     * @Author: shiwn
+     * @Date: 2020/1/17 11:36
+     */
+    @ExceptionHandler({BusinessException.class})
+    public ResultData businessExceptionHandler(BusinessException e) throws BusinessException {
+        return ResultData.fail(e.getCode(), e.getMessage());
+    }
+
+    /**
+     * @Description: 处理全局异常
+     * @Param: [request, e]
+     * @Author: shiwn
+     * @Date: 2020/1/17 11:36
+     */
+    @ExceptionHandler(value = Exception.class)
+    public ResultData handleException(Exception e) throws Exception {
+        return ResultData.fail(e.getMessage());
+    }
+
+
+    // 新增如下代码:[捕获全局 参数校验异常 配合Valid使用]
+
+    /**
+     * 处理所有校验失败的异常(MethodArgumentNotValidException异常)
+     *
+     * @param ex
+     * @return
+     */
+    @ExceptionHandler(value = MethodArgumentNotValidException.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public ResultData handleBindGetException(MethodArgumentNotValidException ex) {
+        // 获取所有异常
+        List<String> errors = ex.getBindingResult()
+                .getFieldErrors()
+                .stream()
+                .map(x -> x.getDefaultMessage())
+                .collect(Collectors.toList());
+        return ResultData.fail(1, String.join(",", errors));
+    }
+
+    /**
+     * 处理所有参数校验时抛出的异常
+     *
+     * @param ex
+     * @return
+     */
+    @ExceptionHandler(value = ValidationException.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public ResultData handleBindException(ValidationException ex) {
+        // 获取所有异常
+        List<String> errors = new LinkedList<String>();
+        if (ex instanceof ConstraintViolationException) {
+            ConstraintViolationException exs = (ConstraintViolationException) ex;
+            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
+            for (ConstraintViolation<?> item : violations) {
+                errors.add(item.getMessage());
+            }
+        }
+        return ResultData.fail(1, String.join(",", errors));
+    }
+
+    /**
+     * Controller参数绑定错误
+     *
+     * @param ex
+     * @return
+     */
+    @ExceptionHandler(MissingServletRequestParameterException.class)
+    public ResultData handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
+        return ResultData.fail(1, ex.getMessage());
+    }
+}

+ 65 - 0
src/main/java/com/sw/bird/exception/ErrorCode.java

@@ -0,0 +1,65 @@
+package com.sw.bird.exception;
+
+/**
+ * 异常状态编码
+ * Created by shiwn on 2021/1/12 11:33
+ */
+public enum ErrorCode {
+    SUCCESS(0, "成功"),
+
+    //    系统用户相关
+    ACCOUNT_NOT_EXIST(1, "用户不存在"),
+
+    ACCOUNT_NULL(1, "用户名不能为空"),
+
+    ACCOUNT_DUPLICATE(1, "用户名重复"),
+
+    MOBILE_DUPLICATE(1, "手机号重复"),
+
+    LOGIN_ERROR(1, "用户名或密码错误"),
+
+    LOGIN_FAIL(1, "登录失败"),
+
+    LOGIN_INVALIDATION(1, "登录失效"),
+
+    PASSWORD_ERROR(1, "密码错误"),
+
+    PASSWORD_NULL(1, "请输入密码"),
+
+    CONFIRM_PASSWORD_NULL(1, "请输入确认密码"),
+
+    CONFIRM_PASSWORD_ERROR(1, "两次密码输入不一致"),
+
+
+    //API通用状态码
+    KEYID_ERROR(202, "无效key"),
+
+    SNS_ERROR(202, "无效SNS"),
+
+    ACCOUNT_PWD_ERROR(204, "用户名或密码错误"),
+
+    GH_DATA_NULL(205, "返回结果为空"),
+
+    PARAMETER_ERROR(402, "参数错误"),
+
+    DATA_TOO_LARGE(1, "查询数据量太大,请缩小查询范围"),
+
+    SERVER_ID_ERROR(403, "无权限访问");
+
+
+    private int code;
+    private String msg;
+
+    ErrorCode(int code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 16 - 0
src/main/java/com/sw/bird/mapper/SystemDictMapper.java

@@ -0,0 +1,16 @@
+package com.sw.bird.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sw.bird.domain.dto.SystemDictDTO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * Created by shiwn on 2024/5/29 16:31
+ */
+@Component
+public interface SystemDictMapper extends BaseMapper<SystemDictDTO> {
+    List<SystemDictDTO> getList(@Param("type") Integer type);
+}

+ 25 - 0
src/main/java/com/sw/bird/mapper/UserMapper.java

@@ -0,0 +1,25 @@
+package com.sw.bird.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sw.bird.domain.dto.UserDTO;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * Created by shiwn on 2024/5/29 16:30
+ */
+@Component
+public interface UserMapper extends BaseMapper<UserDTO> {
+    /**
+     * @Description: 获取用户信息 by 用户名 + 密码 (登录判断使用)
+     * @Param: [username, password]
+     * @Author: shiwn
+     * @Date: 2020/7/31 9:30
+     */
+    @Select("select * from user where  (account = #{username} or mobile= #{username}) and password = #{password} and status = 1 and del_flag='N'")
+    UserDTO findUserByNameAndPassword(@Param("username") String username, @Param("password") String password);
+}

+ 12 - 0
src/main/java/com/sw/bird/service/SystemService.java

@@ -0,0 +1,12 @@
+package com.sw.bird.service;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * Created by shiwn on 2024/5/29 16:25
+ */
+public interface SystemService {
+    Map login(String account, String passWord, HttpServletRequest request, HttpServletResponse response) throws Exception;
+}

+ 90 - 0
src/main/java/com/sw/bird/service/impl/SystemServiceImpl.java

@@ -0,0 +1,90 @@
+package com.sw.bird.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sw.bird.domain.dto.SystemDictDTO;
+import com.sw.bird.domain.dto.UserDTO;
+import com.sw.bird.exception.BusinessException;
+import com.sw.bird.exception.ErrorCode;
+import com.sw.bird.mapper.SystemDictMapper;
+import com.sw.bird.mapper.UserMapper;
+import com.sw.bird.service.SystemService;
+import com.sw.bird.util.DateUtil;
+import com.sw.bird.util.MD5Util;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.sw.bird.util.DateUtil.DateFormat_yyyyMMddHHmmss;
+
+/**
+ * Created by shiwn on 2024/5/29 16:26
+ */
+@Service
+public class SystemServiceImpl implements SystemService {
+    @Autowired
+    private UserMapper userMapper;
+    @Autowired
+    private SystemDictMapper systemDictMapper;
+
+
+    /**
+     * @Description: 登录
+     * @Param: [account, passWord, request, response]
+     * @Author: shiwn
+     * @Date: 2021/2/2 9:22
+     */
+    @Override
+    public Map login(String account, String passWord, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        //初始化结果集
+        Map map = new HashMap();
+
+        try {
+            //  用户名、密码验证
+            if (StringUtils.isBlank(account)) {
+                throw new BusinessException(ErrorCode.ACCOUNT_NULL);
+            }
+            if (StringUtils.isBlank(passWord)) {
+                throw new BusinessException(ErrorCode.PASSWORD_NULL);
+            }
+            UserDTO user = userMapper.findUserByNameAndPassword(account, MD5Util.encode(passWord));
+            if (user == null) {
+                throw new BusinessException(ErrorCode.LOGIN_ERROR);
+            }
+            //  更新用户表的最后登录时间和ip字段
+            user.setLoginTime(DateUtil.parseToString(new Date(), DateFormat_yyyyMMddHHmmss))
+                    .setLoginIp(request.getRemoteAddr());
+            userMapper.updateById(user);
+            //  设置cookes
+            Cookie cookes = new Cookie("user", user.getAccount());
+            cookes.setMaxAge(60 * 60 * 24 * 365);
+            response.addCookie(cookes);
+            HttpSession session = request.getSession();
+            //  将用户信息保存在Session中
+            session.setAttribute("loginUser", user.getAccount());
+            session.setAttribute("loginUserDTO", user);
+            //  设置session过期时间。单位:秒
+            //session.setMaxInactiveInterval(30 * 60);
+            session.setMaxInactiveInterval(-1);
+            //  查询系统字典
+            List<SystemDictDTO> listDict = systemDictMapper.selectList(new QueryWrapper<>());
+
+            //  封装返回信息
+            map.put("userInfo", user);
+            map.put("dictInfo", listDict);
+            return map;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BusinessException(ErrorCode.LOGIN_FAIL);
+        }
+    }
+}

+ 566 - 0
src/main/java/com/sw/bird/util/DateUtil.java

@@ -0,0 +1,566 @@
+package com.sw.bird.util;
+
+import com.sw.bird.exception.BusinessException;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.DayOfWeek;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * 日期时间工具方法
+ * <p>
+ * Created by shiyanfei on 2018-01-09.
+ */
+public class DateUtil {
+
+    /**
+     * 格式 2015-08-07
+     */
+    //public static final String DateFormat_yyyyMMdd = "yyyy-MM-dd";
+    /**
+     * 格式 15:25:30
+     */
+    public static final String DateFormat_HHmmss = "HH:mm:ss";
+
+    /**
+     * 格式 15:25
+     */
+    public static final String DateFormat_HHmm = "HH:mm";
+
+    /**
+     * 格式 2015-08
+     */
+    public static final String DateFormat_yyyyMM = "yyyy-MM";
+
+    /**
+     * 格式 2015-08
+     */
+    public static final String DateFormat_yyyy_MM_dd = "yyyy-MM-dd";
+
+    /**
+     * 格式 2015-08-05 23
+     */
+    public static final String DateFormat_yyyy_MM_dd_HH = "yyyy-MM-dd HH";
+
+    /**
+     * 格式 2015-08-07 11:44:18
+     */
+    public static final String DateFormat_yyyyMMddHHmmss = "yyyy-MM-dd HH:mm:ss";
+
+    /**
+     * 格式 2015-08-07 11:44:18:591
+     */
+    public static final String DateFormat_yyyyMMddHHmmssSSS = "yyyy-MM-dd HH:mm:ss.SSS";
+
+    /**
+     * 格式 20200115
+     */
+    public static final String DateFormat_yyyyMMdd = "yyyyMMdd";
+
+    /**
+     * 格式 150807114418
+     */
+    public static final String DateFormat_yyMMddHHmmss = "yyMMddHHmmss";
+
+    /**
+     * 格式 20140416142030
+     */
+    public static final String DateFormat_TimeStemp_yyyyMMddHHmmss = "yyyyMMddHHmmss";
+
+    /**
+     * 格式 142030
+     */
+    public static final String DateFormat_TimeStemp_HHmmss = "HHmmss";
+
+    /**
+     * 格式 20150807114418591
+     */
+    public static final String DateFormat_TimeStemp = "yyyyMMddHHmmssSSS";
+
+    /**
+     * 格式 2015-08-13T16:49:02.039+0800
+     */
+    public static final String DateFormat_yyyyMMddTHHmmssSSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
+
+    /**
+     * 格式 2015-11-09T00:00:08.000+08:00
+     */
+    public static final String DateFormat_yyyyMMddTHHmmssSSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+
+
+    /**
+     * 日期转化为字符串
+     *
+     * @param format
+     * @return
+     */
+    public static String parseToString(Date date, String format) {
+        if (date != null) {
+            DateFormat df = new SimpleDateFormat(format);
+            String strDate = df.format(date);
+            return strDate;
+        } else {
+            return "-";
+        }
+    }
+
+    /**
+     * 格式化日期
+     */
+    public static Date getFormatDate(Date date, String format) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(format);
+            String strDate = sdf.format(date);
+            Date newDate = sdf.parse(strDate);
+            return newDate;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static long compareDate(Date date1, Date date2) {
+        long l = date2.getTime() - date1.getTime();
+        return l / (1000 * 60);
+    }
+
+    /**
+     * 将字符串转为时间戳
+     *
+     * @param time
+     * @return
+     */
+    public static Long getTime(String time) {
+        try {
+            String re_time = null;
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            Date d = sdf.parse(time);
+            long l = d.getTime();
+            re_time = String.valueOf(l);
+            return Long.parseLong(re_time);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 将时间戳转为字符串
+     *
+     * @param time
+     * @return
+     */
+    public static String getStrTime(String time) {
+        String re_StrTime = null;
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        long lcc_time = Long.valueOf(time);
+        re_StrTime = sdf.format(new Date(lcc_time));
+        return re_StrTime;
+    }
+
+    /**
+     * 将时间戳转为字符串
+     *
+     * @param time
+     * @return
+     */
+    public static String getStrDate(Long time, String format) {
+        String re_StrTime = null;
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        long lcc_time = Long.valueOf(time);
+        re_StrTime = sdf.format(new Date(lcc_time));
+        return re_StrTime;
+    }
+
+    /**
+     * 将时间戳转为字符串
+     *
+     * @param time
+     * @return
+     */
+    public static Date getLongDate(Long time, String format) {
+
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        long lcc_time = Long.valueOf(time);
+        String re_StrTime = sdf.format(new Date(lcc_time));
+
+        Date parse = null;
+        try {
+            parse = sdf.parse(re_StrTime);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return parse;
+    }
+
+    /**
+     * String转date
+     *
+     * @param dateStr
+     * @return
+     */
+    public static Date strToDate(String dateStr) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            return sdf.parse(dateStr);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * @Description: string 转 date
+     * @Param: [dateStr, format]
+     * @Author: shiwn
+     * @Date: 2021/1/27 14:47
+     */
+    public static Date strToDate(String dateStr, String format) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(format);
+            return sdf.parse(dateStr);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * @Description: 获取某年某月有多少天
+     * @Param: [year:年份, month:月份]
+     * @Author: shiwn
+     * @Date: 2020/1/20 11:09
+     */
+    public static int getDayByYearMonth(int year, int month) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(year, month, 0);
+        return calendar.get(Calendar.DAY_OF_MONTH);
+    }
+
+    /**
+     * @Description: 根据输入的参数生成固定时间
+     * @Param: [year:年份, month:月份, day:日期, time:时间]
+     * @Author: shiwn
+     * @Date: 2020/1/20 15:48
+     */
+    public static Date buildDate(String year, String month, String day, String time) {
+        if (time == null) {
+            time = "00:00:01";
+        }
+        if (day == null) {
+            day = "01";
+        }
+        //  判断日期是否满足条件
+        int maxDay = getMaxDayOfMonth(Integer.parseInt(year), Integer.parseInt(month));
+        if (maxDay < Integer.parseInt(day)) {
+            return null;
+        }
+        try {
+            day = formatDay(day);
+            String dateStr = year + "-" + month + "-" + day + " " + time;
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            Date date = sdf.parse(dateStr);
+            return date;
+        } catch (ParseException e) {
+            return null;
+        }
+    }
+
+    /**
+     * @Description: 获取每月有多少天
+     * @Param: [year:年份, month:月份]
+     * @Author: shiwn
+     * @Date: 2020/1/22 11:43
+     */
+    public static int getMaxDayOfMonth(int year, int month) {
+        //  获取每月有多少天
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.YEAR, year);
+        //  java月份从0开始
+        calendar.set(Calendar.MONTH, month - 1);
+        return calendar.getActualMaximum(Calendar.DATE);
+    }
+
+    /**
+     * @Description: 获取该月有几周
+     * @Param: [year:年份, month:月份]
+     * @Author: shiwn
+     * @Date: 2020/1/22 10:49
+     */
+    public static int getMonthWeek(int year, int month) {
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.YEAR, year);
+        //  java月份从0开始
+        c.set(Calendar.MONTH, month - 1);
+        return c.getActualMaximum(Calendar.WEEK_OF_MONTH);
+    }
+
+    /**
+     * @Description: 返回DayOfWeek格式的星期几
+     * @Param: [weekDay:星期几]
+     * @Author: shiwn
+     * @Date: 2020/1/22 11:13
+     */
+    public static DayOfWeek getWeekDay(int weekDay) {
+        switch (weekDay) {
+            case 0:
+                return DayOfWeek.SUNDAY;
+            case 1:
+                return DayOfWeek.MONDAY;
+            case 2:
+                return DayOfWeek.TUESDAY;
+            case 3:
+                return DayOfWeek.WEDNESDAY;
+            case 4:
+                return DayOfWeek.THURSDAY;
+            case 5:
+                return DayOfWeek.FRIDAY;
+            case 6:
+                return DayOfWeek.SATURDAY;
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * @Description: 根据出生日期计算周岁年龄
+     * @Param: [birthDay]
+     * @Author: shiwn
+     * @Date: 2021/1/18 13:17
+     */
+    public static int getAgeByBirth(Date birthDay) {
+        int age = 0;
+        //  判断参数
+        if (birthDay == null) {
+            return 0;
+        }
+        Calendar cal = Calendar.getInstance();
+        //  出生日期晚于当前时间,无法计算
+        if (cal.before(birthDay)) {
+            throw new BusinessException(1, "The birthDay is before now.It's unbelievable!");
+        }
+        //  当前年份
+        int yearNow = cal.get(Calendar.YEAR);
+        //  当前月份
+        int monthNow = cal.get(Calendar.MONTH);
+        //  当前日期
+        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
+        cal.setTime(birthDay);
+        int yearBirth = cal.get(Calendar.YEAR);
+        int monthBirth = cal.get(Calendar.MONTH);
+        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
+        //  计算整岁数
+        age = yearNow - yearBirth;
+        if (monthNow <= monthBirth) {
+            if (monthNow == monthBirth) {
+                if (dayOfMonthNow < dayOfMonthBirth) {
+                    //  当前日期在生日之前,年龄减一
+                    age--;
+                }
+            } else {
+                //  当前月份在生日之前,年龄减一
+                age--;
+            }
+        }
+        return age;
+    }
+
+    /**
+     * @Description: 日期的天数加减计算
+     * @Param: [date:时间, days:间隔天数]
+     * @Author: shiwn
+     * @Date: 2021/1/21 15:24
+     */
+    public static Date getDateByDays(Date date, Integer days) {
+        Calendar calendar = Calendar.getInstance();
+        //设置起时间
+        calendar.setTime(date);
+        calendar.add(Calendar.DATE, days);
+        return calendar.getTime();
+    }
+
+
+    /**
+     * @Description: 计算两个时间点的间隔天数
+     * @Param: [start, end]
+     * @Author: shiwn
+     * @Date: 2021/1/25 14:21
+     */
+    public static Integer getDayInterval(Date start, Date end) {
+        final long nd = 1000 * 24 * 60 * 60;
+        Date startDay = new Date(start.getTime() - start.getTime() % nd);
+        Date endDay = new Date(end.getTime() - end.getTime() % nd);
+        return (int) ((endDay.getTime() - startDay.getTime()) / nd);
+    }
+
+    /**
+     * @Description: 计算两个时间点的间隔秒数
+     * @Param: [start, end]
+     * @Author: shiwn
+     * @Date: 2021/1/25 15:54
+     */
+    public static Integer getSecondInterval(Date start, Date end) {
+        final long nd = 1000;
+        long diff = end.getTime() - start.getTime();
+        return (int) (diff / nd);
+    }
+
+    /**
+     * @Description: 计算两个时间点的间隔分钟数
+     * @Param: [start, end]
+     * @Author: shiwn
+     * @Date: 2021/1/25 15:54
+     */
+    public static Integer getMinuteInterval(Date start, Date end) {
+        if (start == null || end == null) {
+            return 0;
+        }
+        final Float nd = 60000F;
+        Float diff = Float.valueOf(end.getTime() - start.getTime());
+        return (int) Math.ceil(diff / nd);
+    }
+
+
+    /**
+     * @Description: 获取本周的开始日期
+     * @Author: shiwn
+     * @Date: 2021/1/28 10:35
+     */
+    public static Date getBeginDateOfWeek() {
+        Date date = new Date();
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
+        if (dayOfWeek == 1) {
+            dayOfWeek += 7;
+        }
+        calendar.add(Calendar.DATE, 2 - dayOfWeek);
+        return calendar.getTime();
+    }
+
+    /**
+     * @Description: 获取本周的结束日期
+     * @Author: shiwn
+     * @Date: 2021/1/28 10:53
+     */
+    public static Date getEndDateOfWeek() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(getBeginDateOfWeek());
+        calendar.add(Calendar.DAY_OF_WEEK, 6);
+        return calendar.getTime();
+    }
+
+    /**
+     * @Description: 将 字符串格式的时间戳 转为 时间格式的字符串
+     * @Param: [timeStamp]
+     * @Author: shiwn
+     * @Date: 2021/1/14 17:16
+     */
+    public static String getStringByTimeStamp(String timeStamp) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sd = sdf.format(new Date(Long.parseLong(String.valueOf(timeStamp))));
+        return sd;
+    }
+
+    /**
+     * @description: 当前日期年数加减计算
+     * @author machao
+     * @date: 2021/5/14 10:00
+     */
+    public static String getYearTime(Integer year) {
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Calendar c = Calendar.getInstance();
+        //过去一年
+        c.setTime(new Date());
+        c.add(Calendar.YEAR, year);
+        Date y = c.getTime();
+        return format.format(y);
+    }
+
+    /**
+     * @Description: 获取昨天的开始时间
+     * @Date: 2021/12/6 10:41
+     * @Author: shiwn
+     * @Return:
+     */
+    public static Date getYesterdayStartTime() {
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 1);
+        c.add(Calendar.DATE, -1);
+        return c.getTime();
+    }
+
+    /**
+     * @Description: 获取昨天的结束时间
+     * @Date: 2021/12/6 10:41
+     * @Author: shiwn
+     * @Return:
+     */
+    public static Date getYesterdayEndTime() {
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.HOUR_OF_DAY, 23);
+        c.set(Calendar.MINUTE, 59);
+        c.set(Calendar.SECOND, 59);
+        c.set(Calendar.MILLISECOND, 999);
+        c.add(Calendar.DATE, -1);
+        return c.getTime();
+    }
+
+    /**
+     * @Description: 获取上月的开始时间
+     * @Date: 2021/12/6 10:43
+     * @Author: shiwn
+     * @Return:
+     */
+    public static Date getLastMonthdayStartTime() {
+        Calendar c = Calendar.getInstance();
+        c.add(Calendar.MONTH, -1);
+        c.set(Calendar.DATE, 1);
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 1);
+        return c.getTime();
+    }
+
+    /**
+     * @Description: 获取上月的开始时间
+     * @Date: 2021/12/6 11:12
+     * @Author: shiwn
+     * @Return:
+     */
+    public static Date getLastMonthdayEndTime() {
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.DATE, 1);
+        c.add(Calendar.MONTH, -1);
+        //  取上月结束日期
+        int lastMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
+        //  设置
+        c.set(Calendar.DATE, lastMonthMaxDay);
+        c.set(Calendar.HOUR_OF_DAY, 23);
+        c.set(Calendar.MINUTE, 59);
+        c.set(Calendar.SECOND, 59);
+        c.set(Calendar.MILLISECOND, 999);
+        return c.getTime();
+    }
+
+    // ———————————————————————— 以下为私有方法  ————————————————————————
+
+    /**
+     * @Description: 日期格式化,如:1转为01
+     * @Param: [day:日期]
+     * @Author: shiwn
+     * @Date: 2020/1/20 15:53
+     */
+    private static String formatDay(String day) {
+        if (day.length() == 1) {
+            day = "0" + day;
+        }
+        return day;
+    }
+}

+ 78 - 0
src/main/java/com/sw/bird/util/MD5Util.java

@@ -0,0 +1,78 @@
+package com.sw.bird.util;
+
+import sun.misc.BASE64Decoder;
+import sun.misc.BASE64Encoder;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.Base64;
+import java.util.UUID;
+
+/**
+ * MD5加密和解密
+ * <p>
+ * Created by shiyanfei on 2018-01-27.
+ */
+public class MD5Util {
+
+//    public static void main(String[] args) throws Exception {
+//        String str = MD5Util.encode("admin");
+//        String md5 = getMD5("21232f297a57a5a743894aeF4a801fc3");
+//        System.out.println(str);
+//        System.out.printf(md5);
+//    }
+
+    public static String getMD5(String MD5str) throws Exception {
+        MessageDigest md = MessageDigest.getInstance("md5");
+        byte[] buf = md.digest(MD5str.getBytes());
+        BASE64Encoder encoder = new BASE64Encoder();
+        String mds = encoder.encode(buf);
+        return mds;
+    }
+
+    // 密码加密
+    public static String encode(String MD5str) throws Exception {
+        StringBuilder result = new StringBuilder();
+        if (MD5str != null) {
+            // 指定加密的方式为MD5
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            // 进行加密运算
+            byte bytes[] = md.digest(MD5str.getBytes("ISO8859-1"));
+            for (int i = 0; i < bytes.length; i++) {
+                // 将整数转换成十六进制形式的字符串 这里与0xff进行与运算的原因是保证转换结果为32位
+                String str = Integer.toHexString(bytes[i] & 0xFF);
+                if (str.length() == 1) {
+                    str += "F";
+                }
+                result.append(str);
+            }
+
+        }
+        return result.toString();
+    }
+
+    // BASE加密和解密
+    public static void de(String base) {
+        BASE64Encoder encoder = new BASE64Encoder();
+        String bb = encoder.encode(base.getBytes());
+        //System.out.println(bb);
+        BASE64Decoder decoder = new BASE64Decoder();
+        try {
+            byte[] b1 = decoder.decodeBuffer(bb);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    // 利用MD5进行加密
+    public static String encoderByMd5(String str) {
+        try {
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            //加密后的字符串
+            return Base64.getEncoder().encodeToString(md5.digest(str.getBytes("UTF-8")));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return UUID.randomUUID().toString();
+    }
+}

+ 38 - 0
src/main/resources/application-dev.properties

@@ -0,0 +1,38 @@
+### Mysql数据库配置信息(用户数据持久化存储)
+spring.datasource.drive-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.url=jdbc:mysql://192.168.1.144:3306/bird_db_v1?serverTimezone=GMT%2B8&characterSetResults=UTF-8&characterEncoding=UTF-8&useUnicode=yes&useSSL=false
+#数据库账号
+spring.datasource.username=root
+#数据库访问密码
+spring.datasource.password=pass123
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+
+#############连接池的配置信息
+# 初始化大小,最小,最大
+spring.datasource.initialSize=5
+spring.datasource.minIdle=5
+spring.datasource.maxActive=20
+# 配置获取连接等待超时的时间
+spring.datasource.maxWait=60000
+# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+spring.datasource.timeBetweenEvictionRunsMillis=60000
+# 配置一个连接在池中最小生存的时间,单位是毫秒
+spring.datasource.minEvictableIdleTimeMillis=300000
+# 配置自动检测一些连接是否有效
+spring.datasource.validationQuery=SELECT 1 FROM DUAL
+spring.datasource.testWhileIdle=true
+spring.datasource.testOnBorrow=false
+spring.datasource.testOnReturn=false
+# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙(不推荐加上)
+spring.datasource.filters=stat,log4j
+# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
+#spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+# 合并多个DruidDataSource的监控数据
+spring.datasource.useGlobalDataSourceStat=true
+
+
+
+
+
+
+

+ 38 - 0
src/main/resources/application-prod.properties

@@ -0,0 +1,38 @@
+### Mysql数据库配置信息(用户数据持久化存储)
+spring.datasource.drive-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.url=jdbc:mysql://192.168.1.144:3306/bird_db_v1?serverTimezone=GMT%2B8&characterSetResults=UTF-8&characterEncoding=UTF-8&useUnicode=yes&useSSL=false
+#数据库账号
+spring.datasource.username=root
+#数据库访问密码
+spring.datasource.password=pass123
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+
+#############连接池的配置信息
+# 初始化大小,最小,最大
+spring.datasource.initialSize=5
+spring.datasource.minIdle=5
+spring.datasource.maxActive=20
+# 配置获取连接等待超时的时间
+spring.datasource.maxWait=60000
+# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+spring.datasource.timeBetweenEvictionRunsMillis=60000
+# 配置一个连接在池中最小生存的时间,单位是毫秒
+spring.datasource.minEvictableIdleTimeMillis=300000
+# 配置自动检测一些连接是否有效
+spring.datasource.validationQuery=SELECT 1 FROM DUAL
+spring.datasource.testWhileIdle=true
+spring.datasource.testOnBorrow=false
+spring.datasource.testOnReturn=false
+# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙(不推荐加上)
+spring.datasource.filters=stat,log4j
+# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
+#spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+# 合并多个DruidDataSource的监控数据
+spring.datasource.useGlobalDataSourceStat=true
+
+
+
+
+
+
+

+ 45 - 0
src/main/resources/application.properties

@@ -0,0 +1,45 @@
+# 配置项目信息
+server.servlet.context-path=/
+server.port=8081
+# 获取pom文件中project.version值
+version=@project.version@
+
+# 配置数据源
+spring.profiles.active=dev
+
+# 配置时区
+spring.jackson.time-zone=GMT+8
+# 配置文件请求大小设置
+spring.servlet.multipart.max-file-size=50MB
+spring.servlet.multipart.max-request-size=50MB
+
+# page helper分页插件配置
+pagehelper.helperDialect=mysql
+pagehelper.reasonable=true
+pagehelper.supportMethodsArguments=true
+pagehelper.params=count=countSql
+
+# 配置日志
+logging.level.com.sw=warn
+logging.file.path=./logs/pmp
+# ***解决swagger2.9.2版本“@ApiModelProperty”注解“example”属性不填时的报错问题
+logging.level.io.swagger.models.parameters.AbstractSerializableParameter:error
+
+# 配置请求信息
+spring.session.timeout=0
+server.max-http-header-size=1024000
+
+############# 配置mybatis #############
+# 驼峰转换
+mybatis-plus.configuration.map-underscore-to-camel-case=true
+# 实体类地址
+mybatis-plus.typeAliasesPackage=com.sw.bird.mapper
+# xml文件地址
+mybatis-plus.mapper-locations=classpath:/mapper/*.xml
+# 接收null字段
+mybatis-plus.configuration.call-setters-on-nulls=true
+# 删除值
+mybatis-plus.global-config.db-config.logic-delete-value=1
+mybatis-plus.global-config.db-config.logic-not-delete-value=0
+
+

+ 19 - 0
src/main/resources/mapper/SysDictMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sw.bird.mapper.SystemDictMapper">
+
+    <select id="getList" resultType="com.sw.bird.domain.dto.SystemDictDTO">
+
+        select
+        *
+        from
+        system_dict
+        where 1=1
+        <if test="type!=null">
+            and type =#{type}
+        </if>
+
+    </select>
+
+
+</mapper>