├── .gitignore ├── LICENSE ├── README.md ├── blog-springboot ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── zzx │ │ ├── Application.java │ │ ├── config │ │ ├── BeanConfig.java │ │ ├── ErrorConfig.java │ │ ├── ImgUploadConfig.java │ │ ├── JwtConfig.java │ │ ├── MailConfig.java │ │ ├── RabbitMqConfig.java │ │ ├── RedisConfig.java │ │ ├── SiteIntroductionConfig.java │ │ ├── SwaggerConfig.java │ │ ├── WebMvcConfig.java │ │ └── WebSecurityConfig.java │ │ ├── controller │ │ ├── AnnouncementController.java │ │ ├── BlogController.java │ │ ├── CodeController.java │ │ ├── DiscussController.java │ │ ├── ErrorController.java │ │ ├── LogController.java │ │ ├── MessageController.java │ │ ├── ReplyController.java │ │ ├── SiteController.java │ │ ├── TagController.java │ │ ├── UserController.java │ │ └── UserLikeController.java │ │ ├── dao │ │ ├── AnnouncementDao.java │ │ ├── BlogDao.java │ │ ├── CodeDao.java │ │ ├── DiscussDao.java │ │ ├── LoginDao.java │ │ ├── MessageDao.java │ │ ├── ReplyDao.java │ │ ├── RoleDao.java │ │ ├── TagDao.java │ │ ├── UserDao.java │ │ ├── UserLikeDao.java │ │ └── mongo │ │ │ ├── ControllerLogDAO.java │ │ │ └── SqlLogDAO.java │ │ ├── exception │ │ ├── DbMakerConfigException.java │ │ └── GlobalExceptionHandler.java │ │ ├── filter │ │ └── JwtTokenFilter.java │ │ ├── log │ │ ├── ControllerLog.java │ │ └── MybatisSqlLog.java │ │ ├── model │ │ ├── entity │ │ │ ├── BaseLog.java │ │ │ ├── ControllerLog.java │ │ │ ├── MailMessage.java │ │ │ ├── PageResult.java │ │ │ ├── Result.java │ │ │ ├── SqlLog.java │ │ │ └── StatusCode.java │ │ ├── pojo │ │ │ ├── Announcement.java │ │ │ ├── Blog.java │ │ │ ├── Code.java │ │ │ ├── Discuss.java │ │ │ ├── Login.java │ │ │ ├── Message.java │ │ │ ├── Reply.java │ │ │ ├── Role.java │ │ │ ├── Tag.java │ │ │ ├── User.java │ │ │ └── UserLike.java │ │ └── vo │ │ │ └── NewestLogVO.java │ │ ├── mq │ │ ├── BlogListener.java │ │ ├── ControllerLogListener.java │ │ ├── MailListener.java │ │ └── SqlLogListener.java │ │ ├── schedule │ │ ├── BlogTask.java │ │ └── UserLikeTask.java │ │ ├── service │ │ ├── AnnouncementService.java │ │ ├── BlogService.java │ │ ├── CodeService.java │ │ ├── DiscussService.java │ │ ├── LogService.java │ │ ├── LoginService.java │ │ ├── MessageService.java │ │ ├── RedisService.java │ │ ├── ReplyService.java │ │ ├── RoleService.java │ │ ├── TagService.java │ │ ├── UserLikeService.java │ │ └── UserService.java │ │ └── utils │ │ ├── DateUtil.java │ │ ├── FileUtil.java │ │ ├── FormatUtil.java │ │ ├── IPUtil.java │ │ ├── JwtTokenUtil.java │ │ ├── LoggerUtil.java │ │ ├── RandomUtil.java │ │ ├── RequestUtil.java │ │ └── UUIDUtil.java │ └── resources │ ├── application-pro.yml │ ├── application.yml │ ├── ip2region.db │ └── mapper │ ├── AnnouncementMapper.xml │ ├── BlogMapper.xml │ ├── CodeMapper.xml │ ├── DiscussMapper.xml │ ├── LoginMapper.xml │ ├── MessageMapper.xml │ ├── ReplyMapper.xml │ ├── RoleMapper.xml │ ├── TagMapper.xml │ ├── UserLikeMapper.xml │ └── UserMapper.xml ├── blog-vue ├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── README.md ├── build │ ├── build.js │ ├── check-versions.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── App.vue │ ├── api │ │ ├── announcement.js │ │ ├── blog.js │ │ ├── code.js │ │ ├── discuss.js │ │ ├── log.js │ │ ├── message.js │ │ ├── other.js │ │ ├── reply.js │ │ ├── site.js │ │ ├── tag.js │ │ ├── user.js │ │ └── userLike.js │ ├── assets │ │ ├── 404page.png │ │ ├── logo.png │ │ └── qq.png │ ├── components │ │ ├── HelloWorld.vue │ │ ├── bar.vue │ │ ├── blogOverView.vue │ │ ├── bottom.vue │ │ ├── hotBlog.vue │ │ ├── indexBlogList.vue │ │ ├── introduction.vue │ │ ├── myBlogList.vue │ │ ├── myTag.vue │ │ ├── newDiscuss.vue │ │ ├── statisticalBlog.vue │ │ └── userNewDiscuss.vue │ ├── main.js │ ├── router │ │ └── router.js │ ├── store │ │ └── store.js │ ├── utils │ │ ├── date.js │ │ ├── file.js │ │ └── request.js │ └── views │ │ ├── account.vue │ │ ├── admins.vue │ │ ├── announcement.vue │ │ ├── announcementManage.vue │ │ ├── blog.vue │ │ ├── blogManage.vue │ │ ├── codeManage.vue │ │ ├── editBlog.vue │ │ ├── forgetPwd.vue │ │ ├── index.vue │ │ ├── logManage.vue │ │ ├── message.vue │ │ ├── myBlog.vue │ │ ├── newBlog.vue │ │ ├── notfound.vue │ │ ├── searchBlog.vue │ │ └── userManage.vue └── static │ ├── .gitkeep │ └── favicon.ico ├── blog.sql ├── conf └── nginx.conf ├── img ├── account.png ├── admin.png ├── admin_demo.png ├── announcement.png ├── blog.png ├── blog_demo.png ├── index_demo.png ├── index_nologin.png ├── init_admin.png ├── jetbrains-training-partner.png ├── log.png ├── login.png ├── messageBoard.png ├── myblog_login.png ├── register.png └── writeNewBlog.png └── other ├── prototype.md ├── 博客缓存.png └── 后端功能说明.png /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | *.iml 4 | *-dev.yml 5 | blog-vue/node_modules 6 | blog-vue/yarn.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Blog 2 | 3 | #### 前端 4 | 5 | * Vue(Vuex+Vue router) 6 | * Element-UI 7 | 8 | #### 后端 9 | 10 | * SpringBoot 11 | * MyBatis 12 | * Spring security 13 | * JWT 14 | * Mongo 15 | * Redis 16 | * RabbitMQ 17 | * Swagger-UI 18 | * [ip2region](https://github.com/lionsoul2014/ip2region) 19 | 20 | #### 项目目录 21 | 22 | * blog-springboot 后端工程 [后端文档](blog-springboot/README.md) 23 | * blog-vue 前端工程 [前端文档](blog-vue/README.md) 24 | * img 文档相关图片 25 | * other 其他文档 26 | * prototype.md 原型文档 27 | * 博客缓存.png redis博客缓存说明 28 | * 后端功能说明.png 后端功能说明 29 | * conf 已配置的项目压缩文件 30 | * nginx.conf nginx配置文件,已配置好 31 | * blog.sql mysql数据库结构 32 | 33 | #### 预览 34 | 35 | * 主页![主页](img/index_demo.png) 36 | * 博客 ![博客](img/blog_demo.png) 37 | * 后台 ![后台](img/admin_demo.png) 38 | * 实时日志 ![实时日志](img/log.png) 39 | 40 | #### docker 部署教程 41 | [Docker 部署本站 详细全过程 附代码](https://blog.22xcode.com/article/537088126162567169) 42 | 43 | ##### Tips 44 | 45 | 46 | 1. 水平所限,部分代码可能有坑 47 | 2. 管理员账号 admin 密码 1 48 | 49 | ... 50 | 51 | 52 | 有任何项目相关的可以联系 `1970432392@qq.com` (毕设除外) 53 | 54 | 55 | -------------------------------------------------------------------------------- /blog-springboot/README.md: -------------------------------------------------------------------------------- 1 | ### Blog-Springboot 2 | 3 | #### 技术栈 4 | 5 | * SpringBoot 6 | * MyBatis 7 | * Spring Security 8 | * JWT 9 | * MySQL 10 | * Swagger-UI 11 | * SpringBoot Mail 12 | * Druid 13 | * Mongo 14 | * Redis 15 | * RabbitMQ 16 | * RestFul API 17 | * 前后端分离 18 | 19 | #### Tip 20 | maven 项目 需要maven环境 21 | 22 | #### Run 23 | ``` 24 | blog-springboot/src/main/java/com/zzx/Application.java 25 | ``` 26 | 27 | 项目打包 28 | ``` 29 | mvn clean package 30 | ``` 31 | 32 | ... 33 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/Application.java: -------------------------------------------------------------------------------- 1 | package com.zzx; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @SpringBootApplication 8 | public class Application { 9 | public static void main(String[] args) { 10 | 11 | SpringApplication.run(Application.class); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/BeanConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 9 | import org.springframework.stereotype.Component; 10 | 11 | 12 | /** 13 | * 将一些不方便加@Component注解的类放在此处 14 | * 加入spring容器 15 | */ 16 | 17 | @Component 18 | public class BeanConfig { 19 | 20 | 21 | /** 22 | * spring-security加密方法 23 | * 24 | * @return 25 | */ 26 | @Bean 27 | public BCryptPasswordEncoder encoder() { 28 | return new BCryptPasswordEncoder(); 29 | } 30 | 31 | 32 | /** 33 | * spring-boot内置的json工具 34 | * 35 | * @return 36 | */ 37 | @Bean 38 | public ObjectMapper objectMapper() { 39 | 40 | return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); 41 | } 42 | 43 | 44 | /** 45 | * 新建一个用于发送邮件的消息队列 46 | * 47 | * @return 48 | */ 49 | @Bean 50 | public Queue sendSmsQueue() { 51 | return new Queue(RabbitMqConfig.MAIL_QUEUE); 52 | } 53 | 54 | /** 55 | * 新建一个用于更新博客的消息队列 56 | * 57 | * @return 58 | */ 59 | @Bean 60 | public Queue updateBlogQueue() { 61 | return new Queue(RabbitMqConfig.BLOG_QUEUE); 62 | } 63 | 64 | 65 | @Bean 66 | public Queue controllerLogQueue() { 67 | return new Queue(RabbitMqConfig.CONTROLLER_LOG_QUEUE); 68 | } 69 | 70 | @Bean 71 | public Queue sqlLogQueue() { 72 | return new Queue(RabbitMqConfig.SQL_LOG_QUEUE); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/ErrorConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | import org.springframework.boot.web.server.ErrorPage; 4 | import org.springframework.boot.web.server.ErrorPageRegistrar; 5 | import org.springframework.boot.web.server.ErrorPageRegistry; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.http.HttpStatus; 8 | 9 | @Configuration 10 | public class ErrorConfig implements ErrorPageRegistrar { 11 | 12 | /** 13 | * 有匹配的路径,但是该路径下的资源不存在 14 | * 15 | * @param registry 16 | */ 17 | @Override 18 | public void registerErrorPages(ErrorPageRegistry registry) { 19 | registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound")); 20 | } 21 | 22 | 23 | 24 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/ImgUploadConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.io.File; 7 | import java.util.LinkedList; 8 | import java.util.concurrent.ConcurrentLinkedQueue; 9 | 10 | /** 11 | * 文件上传相关属性 12 | */ 13 | @Component 14 | @ConfigurationProperties(prefix = "upload") 15 | public class ImgUploadConfig { 16 | 17 | /** 18 | * 静态资源对外暴露的访问路径 19 | */ 20 | private String staticAccessPath; 21 | /** 22 | * 文件上传目录 23 | */ 24 | private String uploadFolder; 25 | /** 26 | * 文件夹层数 27 | */ 28 | private Integer layerCount; 29 | /** 30 | * 文件夹内单位数 31 | */ 32 | private Integer folderSize; 33 | 34 | private static final ConcurrentLinkedQueue AVAILABLE_PATH = new ConcurrentLinkedQueue<>(); 35 | 36 | public static ConcurrentLinkedQueue getAvailablePath() { 37 | return AVAILABLE_PATH; 38 | } 39 | 40 | public String getStaticAccessPath() { 41 | return staticAccessPath; 42 | } 43 | 44 | public void setStaticAccessPath(String staticAccessPath) { 45 | this.staticAccessPath = staticAccessPath; 46 | } 47 | 48 | public String getUploadFolder() { 49 | return uploadFolder; 50 | } 51 | 52 | public void setUploadFolder(String uploadFolder) { 53 | this.uploadFolder = uploadFolder; 54 | } 55 | 56 | public Integer getLayerCount() { 57 | return layerCount; 58 | } 59 | 60 | public void setLayerCount(Integer layerCount) { 61 | this.layerCount = layerCount; 62 | } 63 | 64 | public Integer getFolderSize() { 65 | return folderSize; 66 | } 67 | 68 | public void setFolderSize(Integer folderSize) { 69 | this.folderSize = folderSize; 70 | } 71 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/JwtConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | 8 | @ConfigurationProperties(prefix = "jwt") 9 | @Component 10 | public class JwtConfig { 11 | public static final String REDIS_TOKEN_KEY_PREFIX = "TOKEN_"; 12 | private long time; // 5天(以秒s计)过期时间 13 | private String secret;// JWT密码 14 | private String prefix; // Token前缀 15 | private String header; // 存放Token的Header Key 16 | 17 | public long getTime() { 18 | return time; 19 | } 20 | 21 | public void setTime(long time) { 22 | this.time = time; 23 | } 24 | 25 | public String getSecret() { 26 | return secret; 27 | } 28 | 29 | public void setSecret(String secret) { 30 | this.secret = secret; 31 | } 32 | 33 | public String getPrefix() { 34 | return prefix; 35 | } 36 | 37 | public void setPrefix(String prefix) { 38 | this.prefix = prefix; 39 | } 40 | 41 | public String getHeader() { 42 | return header; 43 | } 44 | 45 | public void setHeader(String header) { 46 | this.header = header; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/MailConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | public class MailConfig { 4 | 5 | 6 | 7 | /** 8 | * redis 中 mail key 的前缀 9 | */ 10 | public static final String REDIS_MAIL_KEY_PREFIX = "MAIL_"; 11 | /** 12 | * redis中 mail code 的过期时间 13 | */ 14 | public static final int EXPIRED_TIME = 5; 15 | 16 | /** 17 | * 邮件发送状态 18 | * 已加入消息队列,等待发送 19 | */ 20 | public static final int MAIL_STATE_WAIT = 0; 21 | 22 | /** 23 | * 邮件发送状态 24 | * 发送成功 25 | */ 26 | public static final int MAIL_STATE_OK = 1; 27 | 28 | /** 29 | * 邮件发送状态 30 | * 发送失败 31 | */ 32 | public static final int MAIL_STATE_ERROR = 2; 33 | 34 | /** 35 | * 邮件状态中间字符 36 | */ 37 | public static final String MAIL_STATE_MID_CHAR = "_"; 38 | } 39 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/RabbitMqConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | /** 4 | * @blame MQPearth 5 | */ 6 | public class RabbitMqConfig { 7 | /** 8 | * 邮件消息队列 名 9 | */ 10 | public static final String MAIL_QUEUE = "MAIL"; 11 | 12 | /** 13 | * 博客数据更新 消息队列 名 14 | */ 15 | public static final String BLOG_QUEUE = "BLOG"; 16 | 17 | /** 18 | * controller日志log 19 | */ 20 | public static final String CONTROLLER_LOG_QUEUE = "CONTROLLER_LOG"; 21 | 22 | 23 | /** 24 | * sql日志log 25 | */ 26 | public static final String SQL_LOG_QUEUE = "SQL_LOG"; 27 | } 28 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | /** 4 | * 配置redis的存取 5 | * 6 | * @blame mqpearth 7 | */ 8 | public class RedisConfig { 9 | 10 | /** 11 | * redis中存放 最新博客 数量 的最大值 12 | */ 13 | public static final int REDIS_NEW_BLOG_COUNT = 10; 14 | 15 | /** 16 | * redis中存放 热门博客 数量 的最大值 17 | */ 18 | public static final int REDIS_HOT_BLOG_COUNT = 6; 19 | 20 | /** 21 | * redis中存放 热门博客 的 key 22 | */ 23 | public static final String REDIS_HOT_BLOG = "HOTBLOG"; 24 | 25 | 26 | /** 27 | * redis中存放 最新博客 的 key 28 | */ 29 | public static final String REDIS_NEW_BLOG = "NEWBLOG"; 30 | 31 | /** 32 | * redis中存放blog的前缀 33 | */ 34 | public static final String REDIS_BLOG_PREFIX = "BLOG_"; 35 | 36 | 37 | /** 38 | * 博客归档缓存key 39 | */ 40 | public static final String REDIS_STATISTICAL = "STATISTICAL"; 41 | 42 | /** 43 | * IP_127.0.0.1 44 | */ 45 | public static final String REDIS_IP_PREFIX = "IP_"; 46 | 47 | 48 | /** 49 | * 请求频率限制 缓存时间 50 | */ 51 | public static final long REDIS_LIMIT_REQUEST_FREQUENCY_TIME = 100L; 52 | 53 | /** 54 | * 用户点赞状态key 55 | */ 56 | public static final String MAP_BLOG_LIKE_COUNT_KEY = "MAP_BLOG_LIKE_COUNT"; 57 | 58 | /** 59 | * MAP_USER_LIKE_KEY 行内key 的中间字符 60 | * blogId::userId 61 | */ 62 | public static final String REDIS_LIKE_MID = "::"; 63 | 64 | /** 65 | * 博文点赞数key 66 | */ 67 | public static final String MAP_USER_LIKE_KEY = "MAP_USER_LIKE_KEY"; 68 | 69 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/SiteIntroductionConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * 站点介绍 8 | */ 9 | @ConfigurationProperties(prefix = "site") 10 | @Component 11 | public class SiteIntroductionConfig { 12 | 13 | private String introduction;//介绍 14 | 15 | public String getIntroduction() { 16 | return introduction; 17 | } 18 | 19 | public void setIntroduction(String introduction) { 20 | this.introduction = introduction; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | import io.swagger.annotations.ApiOperation; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import springfox.documentation.builders.RequestHandlerSelectors; 8 | import springfox.documentation.spi.DocumentationType; 9 | import springfox.documentation.spring.web.plugins.Docket; 10 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 11 | 12 | @Configuration 13 | @EnableSwagger2 14 | public class SwaggerConfig { 15 | 16 | @Value("${swagger.enable}") 17 | private boolean enableSwagger; 18 | 19 | @Bean 20 | public Docket swaggerSpringMvcPlugin() { 21 | return new Docket(DocumentationType.SWAGGER_2).enable(enableSwagger) 22 | .select() 23 | .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) 24 | .build(); 25 | } 26 | 27 | public boolean isEnableSwagger() { 28 | return enableSwagger; 29 | } 30 | 31 | public void setEnableSwagger(boolean enableSwagger) { 32 | this.enableSwagger = enableSwagger; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | 4 | import com.zzx.utils.FileUtil; 5 | import com.zzx.utils.LoggerUtil; 6 | import org.slf4j.Logger; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | import org.springframework.web.servlet.config.annotation.*; 12 | 13 | import java.io.File; 14 | import java.util.ArrayList; 15 | import java.util.LinkedList; 16 | import java.util.List; 17 | import java.util.concurrent.ConcurrentLinkedQueue; 18 | 19 | @Configuration 20 | public class WebMvcConfig implements WebMvcConfigurer { 21 | 22 | @Autowired 23 | private SwaggerConfig swaggerConfig; 24 | 25 | @Autowired 26 | private ImgUploadConfig imgUploadConfig; 27 | 28 | @Autowired 29 | private FileUtil fileUtil; 30 | 31 | private Logger logger = LoggerUtil.loggerFactory(this.getClass()); 32 | 33 | 34 | @Override 35 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 36 | 37 | //是否将swagger-ui.html 添加 到 resources目录下 38 | if (swaggerConfig.isEnableSwagger()) { 39 | registry.addResourceHandler("swagger-ui.html") 40 | .addResourceLocations("classpath:/META-INF/resources/"); 41 | 42 | registry.addResourceHandler("/webjars/**") 43 | .addResourceLocations("classpath:/META-INF/resources/webjars/"); 44 | 45 | registry.addResourceHandler("/web_frontend/**") 46 | .addResourceLocations("classpath:/web_frontend/"); 47 | } 48 | 49 | //以下注释部分用于生产环境下,文件夹单位较大,层数较多的情况 50 | //文件上传配置 51 | File root = new File(imgUploadConfig.getUploadFolder()); 52 | ArrayList files = null; 53 | //有此文件夹默认上传文件夹初始化过 54 | if (root.exists()) { 55 | //将最下层文件夹进行资源映射 56 | logger.info("上传文件夹已存在,资源映射较耗时"); 57 | files = new ArrayList<>(fileUtil.getAllFolder()); 58 | } else { //没有被初始化过 59 | logger.info("上传文件夹初始化中"); 60 | files = new ArrayList<>(fileUtil.initUploadFolder()); 61 | 62 | } 63 | // 将生成的文件夹进行资源映射 64 | ConcurrentLinkedQueue availablePath = ImgUploadConfig.getAvailablePath(); 65 | String[] paths = new String[files.size()]; 66 | for (int i = 0; i < paths.length; i++) { 67 | File file = files.get(i); 68 | paths[i] = "file:" + file.getPath() + "/"; 69 | if (file.listFiles().length < imgUploadConfig.getFolderSize()) { 70 | availablePath.add(file); 71 | } 72 | } 73 | logger.info("资源文件夹映射完成"); 74 | registry.addResourceHandler(imgUploadConfig.getStaticAccessPath()) 75 | .addResourceLocations(paths); 76 | 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.zzx.config; 2 | 3 | 4 | import com.zzx.filter.JwtTokenFilter; 5 | import com.zzx.service.UserService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.HttpMethod; 10 | import org.springframework.security.authentication.AuthenticationManager; 11 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 12 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 14 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 15 | import org.springframework.security.config.http.SessionCreationPolicy; 16 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 17 | 18 | 19 | @Configuration 20 | @EnableWebSecurity 21 | @EnableGlobalMethodSecurity(prePostEnabled = true) 22 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 23 | 24 | @Autowired 25 | private UserService userService; 26 | 27 | @Bean 28 | public JwtTokenFilter authenticationTokenFilterBean() throws Exception { 29 | return new JwtTokenFilter(); 30 | } 31 | 32 | @Override 33 | @Bean 34 | public AuthenticationManager authenticationManagerBean() throws Exception { 35 | return super.authenticationManagerBean(); 36 | } 37 | 38 | // @Override 39 | // protected void configure(AuthenticationManagerBuilder auth) throws Exception { 40 | // auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder()); 41 | // } 42 | 43 | @Override 44 | protected void configure(HttpSecurity httpSecurity) throws Exception { 45 | 46 | //禁用csrf 47 | //options全部放行 48 | //post put delete get 全部拦截校验 49 | httpSecurity.csrf().disable() 50 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 51 | .authorizeRequests() 52 | .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 53 | .antMatchers(HttpMethod.POST).authenticated() 54 | .antMatchers(HttpMethod.PUT).authenticated() 55 | .antMatchers(HttpMethod.DELETE).authenticated() 56 | .antMatchers(HttpMethod.GET).authenticated(); 57 | 58 | httpSecurity 59 | .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); 60 | httpSecurity.headers().cacheControl(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/AnnouncementController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.model.entity.PageResult; 4 | import com.zzx.model.entity.Result; 5 | import com.zzx.model.entity.StatusCode; 6 | import com.zzx.model.pojo.Announcement; 7 | import com.zzx.service.AnnouncementService; 8 | import com.zzx.utils.FormatUtil; 9 | import io.swagger.annotations.Api; 10 | import io.swagger.annotations.ApiOperation; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.security.access.prepost.PreAuthorize; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | @Api(tags = "公告api", description = "公告api", basePath = "/announcement") 16 | @RestController 17 | @RequestMapping("/announcement") 18 | public class AnnouncementController { 19 | @Autowired 20 | private AnnouncementService announcementService; 21 | 22 | @Autowired 23 | private FormatUtil formatUtil; 24 | 25 | 26 | @ApiOperation(value = "发布公告", notes = "公告标题+公告内容") 27 | @PreAuthorize("hasAuthority('ADMIN')") 28 | @PostMapping 29 | public Result newAnnouncement(String title, String body) { 30 | if (!formatUtil.checkStringNull(title, body)) { 31 | return Result.create(StatusCode.ERROR, "参数错误"); 32 | } 33 | 34 | if (title.length() > 255) { 35 | return Result.create(StatusCode.ERROR, "参数错误"); 36 | } 37 | 38 | announcementService.saveAnnouncement(title, body); 39 | return Result.create(StatusCode.OK, "发布成功"); 40 | } 41 | 42 | @ApiOperation(value = "删除公告", notes = "公告id") 43 | @PreAuthorize("hasAuthority('ADMIN')") 44 | @DeleteMapping("/{announcementId}") 45 | public Result deleteAnnouncement(@PathVariable Integer announcementId) { 46 | if (!formatUtil.checkPositive(announcementId)) { 47 | return Result.create(StatusCode.ERROR, "参数错误"); 48 | } 49 | 50 | announcementService.deleteAnnouncementById(announcementId); 51 | return Result.create(StatusCode.OK, "删除成功"); 52 | } 53 | 54 | //置顶 55 | @ApiOperation(value = "置顶/取消置顶公告", notes = "公告id+置顶状态 0置顶 1正常") 56 | @PreAuthorize("hasAuthority('ADMIN')") 57 | @PutMapping("/top/{announcementId}/{top}") 58 | public Result top(@PathVariable Integer announcementId, @PathVariable Integer top) { 59 | if (!formatUtil.checkPositive(announcementId)) { 60 | return Result.create(StatusCode.ERROR, "参数错误"); 61 | } 62 | if (!formatUtil.checkObjectNull(top)) { 63 | return Result.create(StatusCode.ERROR, "参数错误"); 64 | } 65 | 66 | announcementService.updateAnnouncementTop(announcementId, top); 67 | return Result.create(StatusCode.OK, "操作成功"); 68 | } 69 | 70 | 71 | //分页获取公告 72 | 73 | @ApiOperation(value = "分页查询公告", notes = "页码+显示条数") 74 | @GetMapping("/{page}/{showCount}") 75 | public Result getAnnouncement(@PathVariable Integer page, @PathVariable Integer showCount) { 76 | if (!formatUtil.checkPositive(page, showCount)) { 77 | return Result.create(StatusCode.ERROR, "参数错误"); 78 | } 79 | 80 | PageResult pageResult = 81 | new PageResult<>(announcementService.getAnnouncementCount(), announcementService.findAnnouncement(page, showCount)); 82 | 83 | return Result.create(StatusCode.OK, "查询成功", pageResult); 84 | } 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/CodeController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | 4 | import com.zzx.model.entity.PageResult; 5 | import com.zzx.model.entity.Result; 6 | import com.zzx.model.entity.StatusCode; 7 | import com.zzx.model.pojo.Code; 8 | import com.zzx.service.CodeService; 9 | import com.zzx.utils.FormatUtil; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.access.prepost.PreAuthorize; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | @Api(tags = "邀请码api", description = "邀请码api", basePath = "/code") 17 | @PreAuthorize("hasAuthority('ADMIN')") 18 | @RestController 19 | @RequestMapping("/code") 20 | public class CodeController { 21 | @Autowired 22 | private CodeService codeService; 23 | 24 | @Autowired 25 | private FormatUtil formatUtil; 26 | 27 | //生成激活码 将生成的激活码返回 28 | @ApiOperation(value = "生成激活码", notes = "生成激活码") 29 | @PostMapping 30 | public Result generateCode() { 31 | return Result.create(StatusCode.OK, "生成成功", codeService.generateCode()); 32 | } 33 | 34 | //分页查询激活码 35 | @ApiOperation(value = "分页查询激活码", notes = "页码+显示条数") 36 | @GetMapping("/{page}/{showCount}") 37 | public Result findCode(@PathVariable Integer page, @PathVariable Integer showCount) { 38 | if (!formatUtil.checkPositive(page, showCount)) { 39 | return Result.create(StatusCode.ERROR, "参数错误"); 40 | } 41 | 42 | PageResult pageResult = 43 | new PageResult<>(codeService.getCodeCount(), codeService.findCode(page, showCount)); 44 | return Result.create(StatusCode.OK, "查询成功", pageResult); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/ErrorController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.model.entity.Result; 4 | import com.zzx.model.entity.StatusCode; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | @RestController 13 | public class ErrorController { 14 | 15 | 16 | public static final String FREQUENT_OPERATION = "/frequentOperation"; 17 | 18 | @Autowired 19 | private HttpServletResponse response; 20 | 21 | /** 22 | * 有匹配的路径,但是路径下的资源不存在 23 | * 如/img/xxx.jpg 24 | * 25 | * @return 26 | */ 27 | @RequestMapping("/notfound") 28 | public Result notfound() { 29 | response.setStatus(HttpServletResponse.SC_NOT_FOUND); 30 | return Result.create(StatusCode.NOTFOUND, "文件不存在"); 31 | } 32 | 33 | 34 | @RequestMapping(FREQUENT_OPERATION) 35 | public Result frequentOperation() { 36 | 37 | return Result.create(StatusCode.REPERROR, "操作过于频繁"); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/LogController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.model.entity.Result; 4 | import com.zzx.model.entity.StatusCode; 5 | import com.zzx.model.vo.NewestLogVO; 6 | import com.zzx.service.LogService; 7 | import io.swagger.annotations.Api; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.security.access.prepost.PreAuthorize; 10 | import org.springframework.util.ObjectUtils; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | /** 14 | * 日志api 15 | * 16 | * @author zzx 17 | * @date 2021-05-29 13:26 18 | */ 19 | @Api(tags = "日志api") 20 | @RestController 21 | @RequestMapping("/log") 22 | public class LogController { 23 | 24 | @Autowired 25 | LogService logService; 26 | 27 | @PostMapping("/findNewestLog") 28 | @PreAuthorize("hasAuthority('ADMIN')") 29 | public Result findNewestLog(NewestLogVO vo) { 30 | if (ObjectUtils.isEmpty(vo.getSize())) { 31 | vo.setSize(10); 32 | } 33 | if (1 == vo.getType()) { 34 | return Result.create(StatusCode.OK, "ok", logService.findControllerNewestLog 35 | (vo.getLeft(), vo.getRight(), vo.getSize())); 36 | } else { 37 | return Result.create(StatusCode.OK, "ok", logService.findSqlNewestLog 38 | (vo.getLeft(), vo.getRight(), vo.getSize())); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/MessageController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | 4 | import com.zzx.model.entity.PageResult; 5 | import com.zzx.model.entity.Result; 6 | import com.zzx.model.entity.StatusCode; 7 | import com.zzx.model.pojo.Message; 8 | import com.zzx.service.MessageService; 9 | import com.zzx.utils.FormatUtil; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.access.prepost.PreAuthorize; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | @Api(tags = "留言api", description = "留言api", basePath = "/message") 17 | @RestController 18 | @RequestMapping("/message") 19 | public class MessageController { 20 | 21 | @Autowired 22 | private MessageService messageService; 23 | 24 | @Autowired 25 | private FormatUtil formatUtil; 26 | 27 | 28 | @ApiOperation(value = "留言", notes = "留言内容") 29 | @PostMapping 30 | public Result message(String messageBody) { 31 | if (!formatUtil.checkStringNull(messageBody)) { 32 | return Result.create(StatusCode.ERROR, "参数错误"); 33 | } 34 | 35 | try { 36 | messageService.saveMessage(messageBody); 37 | return Result.create(StatusCode.OK, "留言成功"); 38 | } catch (RuntimeException e) { 39 | return Result.create(StatusCode.ERROR, "留言失败" + (e.getMessage() == null ? "" : e.getMessage())); 40 | } 41 | } 42 | 43 | 44 | //管理员删除 45 | 46 | @ApiOperation(value = "管理员删除留言", notes = "留言id") 47 | @PreAuthorize("hasAuthority('ADMIN')") 48 | @DeleteMapping("/{messageId}") 49 | public Result deleteMessage(@PathVariable Integer messageId) { 50 | if (!formatUtil.checkPositive(messageId)) { 51 | return Result.create(StatusCode.ERROR, "参数错误"); 52 | } 53 | messageService.deleteMessageById(messageId); 54 | return Result.create(StatusCode.OK, "删除成功"); 55 | } 56 | 57 | /** 58 | * 分页查询留言 59 | * 60 | * @param page 起始页 61 | * @param showCount 显示条数 62 | * @return 查询结果 63 | */ 64 | @ApiOperation(value = "分页查询留言", notes = "页码+显示数量") 65 | @GetMapping("/{page}/{showCount}") 66 | public Result getMessage(@PathVariable Integer page, @PathVariable Integer showCount) { 67 | if (!formatUtil.checkPositive(page, showCount)) { 68 | return Result.create(StatusCode.ERROR, "参数错误"); 69 | } 70 | 71 | PageResult pageResult = 72 | new PageResult<>(messageService.getMessageCount(), messageService.findMessage(page, showCount)); 73 | 74 | return Result.create(StatusCode.OK, "查询成功", pageResult); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/ReplyController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.model.entity.Result; 4 | import com.zzx.model.entity.StatusCode; 5 | import com.zzx.service.ReplyService; 6 | import com.zzx.utils.FormatUtil; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | @Api(tags = "回复api", description = "回复api", basePath = "/reply") 14 | @RestController 15 | @RequestMapping("/reply") 16 | public class ReplyController { 17 | 18 | @Autowired 19 | private ReplyService replyService; 20 | 21 | @Autowired 22 | private FormatUtil formatUtil; 23 | 24 | @ApiOperation(value = "发布回复", notes = "回复内容+评论id (父回复节点)?") 25 | @PreAuthorize("hasAuthority('USER')") 26 | @PostMapping("/{discussId}") 27 | public Result reply(@PathVariable Integer discussId, String replyBody, Integer rootId) { 28 | 29 | if (!formatUtil.checkStringNull(replyBody)) { 30 | return Result.create(StatusCode.ERROR, "参数异常"); 31 | } 32 | if (!formatUtil.checkPositive(discussId)) { 33 | return Result.create(StatusCode.ERROR, "参数异常"); 34 | } 35 | 36 | try { 37 | replyService.saveReply(discussId, replyBody, rootId); 38 | return Result.create(StatusCode.OK, "回复成功"); 39 | } catch (RuntimeException e) { 40 | return Result.create(StatusCode.ERROR, "回复失败" + e.getMessage()); 41 | } 42 | } 43 | 44 | @ApiOperation(value = "删除回复", notes = "回复id") 45 | @PreAuthorize("hasAuthority('USER')") 46 | @DeleteMapping("/{replyId}") 47 | public Result deleteReply(@PathVariable Integer replyId) { 48 | if (!formatUtil.checkPositive(replyId)) { 49 | return Result.create(StatusCode.ERROR, "参数错误"); 50 | } 51 | 52 | try { 53 | replyService.deleteReply(replyId); 54 | return Result.create(StatusCode.OK, "删除成功"); 55 | } catch (RuntimeException e) { 56 | return Result.create(StatusCode.ERROR, "删除失败" + e.getMessage()); 57 | } 58 | } 59 | 60 | @ApiOperation(value = "管理员删除回复", notes = "回复id") 61 | @PreAuthorize("hasAuthority('ADMIN')") 62 | @DeleteMapping("/admin/{replyId}") 63 | public Result adminDeleteDiscuss(@PathVariable Integer replyId) { 64 | if (!formatUtil.checkPositive(replyId)) { 65 | return Result.create(StatusCode.ERROR, "参数错误"); 66 | } 67 | 68 | try { 69 | replyService.adminDeleteReply(replyId); 70 | return Result.create(StatusCode.OK, "删除成功"); 71 | } catch (RuntimeException e) { 72 | return Result.create(StatusCode.ERROR, "删除失败" + e.getMessage()); 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/SiteController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.config.SiteIntroductionConfig; 4 | import com.zzx.model.entity.Result; 5 | import com.zzx.model.entity.StatusCode; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.CrossOrigin; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponseWrapper; 16 | 17 | @Api(tags = "站点api", description = "站点api", basePath = "/site") 18 | @RestController 19 | @RequestMapping("/site") 20 | public class SiteController { 21 | 22 | @Autowired 23 | private SiteIntroductionConfig siteIntroductionConfig; 24 | 25 | 26 | @ApiOperation(value = "站点介绍", notes = "站点介绍") 27 | @GetMapping 28 | public Result getIntroduction() { 29 | 30 | return Result.create(StatusCode.OK, "获取成功", siteIntroductionConfig.getIntroduction()); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/TagController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.model.entity.Result; 4 | import com.zzx.model.entity.StatusCode; 5 | import com.zzx.service.TagService; 6 | import com.zzx.utils.FormatUtil; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | 14 | @Api(tags = "标签api", description = "标签api", basePath = "/tag") 15 | @RestController 16 | @RequestMapping("/tag") 17 | public class TagController { 18 | 19 | 20 | @Autowired 21 | private TagService tagService; 22 | 23 | @Autowired 24 | private FormatUtil formatUtil; 25 | 26 | /** 27 | * 新增一个标签 28 | * 29 | * @param tagName 标签名 30 | * @return 31 | */ 32 | @ApiOperation(value = "新增标签", notes = "标签名") 33 | @PreAuthorize("hasAuthority('USER')") 34 | @PostMapping 35 | public Result newTag(String tagName) { 36 | if (!formatUtil.checkStringNull(tagName)) { 37 | return Result.create(StatusCode.ERROR, "参数异常"); 38 | } 39 | try { 40 | tagService.saveTag(tagName); 41 | return Result.create(StatusCode.OK, "新增成功"); 42 | } catch (RuntimeException e) { 43 | return Result.create(StatusCode.ERROR, "新增失败," + e.getMessage()); 44 | } 45 | } 46 | 47 | /** 48 | * 删除一个标签 49 | * 50 | * @param tagId 标签id 51 | * @return 52 | */ 53 | @ApiOperation(value = "删除标签", notes = "标签id") 54 | @PreAuthorize("hasAuthority('USER')") 55 | @DeleteMapping("/{tagId}") 56 | public Result deleteTag(@PathVariable Integer tagId) { 57 | if (!formatUtil.checkObjectNull(tagId)) { 58 | return Result.create(StatusCode.ERROR, "参数异常"); 59 | } 60 | try { 61 | tagService.deleteTagById(tagId); 62 | return Result.create(StatusCode.OK, "删除成功"); 63 | } catch (RuntimeException e) { 64 | return Result.create(StatusCode.ERROR, e.getMessage()); 65 | } 66 | } 67 | 68 | 69 | /** 70 | * 修改一个标签 71 | * 72 | * @param tagId 标签id 73 | * @param tagName 新标签名 74 | * @return 75 | */ 76 | @ApiOperation(value = "修改标签", notes = "标签id+新标签名") 77 | @PreAuthorize("hasAuthority('USER')") 78 | @PutMapping 79 | public Result updateTag(Integer tagId, String tagName) { 80 | if (!formatUtil.checkObjectNull(tagId)) { 81 | return Result.create(StatusCode.ERROR, "参数异常"); 82 | } 83 | if (!formatUtil.checkStringNull(tagName)) { 84 | return Result.create(StatusCode.ERROR, "参数异常"); 85 | } 86 | 87 | try { 88 | tagService.updateTag(tagId, tagName); 89 | return Result.create(StatusCode.OK, "修改成功"); 90 | } catch (RuntimeException e) { 91 | return Result.create(StatusCode.ERROR, e.getMessage()); 92 | } 93 | } 94 | 95 | 96 | /** 97 | * 获取某用户下的所有标签 98 | * 99 | * @return 100 | */ 101 | @ApiOperation(value = "获取用户标签", notes = "用户id") 102 | @PreAuthorize("hasAuthority('USER')") 103 | @GetMapping 104 | public Result findTagByUserId() { 105 | return Result.create(StatusCode.OK, "查询成功", tagService.findTagByUserId()); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/controller/UserLikeController.java: -------------------------------------------------------------------------------- 1 | package com.zzx.controller; 2 | 3 | import com.zzx.model.entity.Result; 4 | import com.zzx.model.entity.StatusCode; 5 | import com.zzx.model.pojo.UserLike; 6 | import com.zzx.service.UserLikeService; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | /** 14 | * @description: 用户点赞 15 | * @author: Tyson 16 | * @time: 2020-05-26 13:26 17 | */ 18 | @Api(tags = "用户点赞api", description = "用户点赞api", basePath = "/userLike") 19 | @RestController 20 | @RequestMapping("/userLike") 21 | public class UserLikeController { 22 | 23 | @Autowired 24 | private UserLikeService userLikeService; 25 | 26 | /** 27 | * @Description: 保存点赞数据 28 | * @Param: userLike 29 | * @return: Result 30 | * @Author: Tyson 31 | * @Date: 2020/5/26/0026 32 | */ 33 | @ApiOperation(value = "保存点赞数据") 34 | @PostMapping("/saveUserLike") 35 | @PreAuthorize("hasAuthority('USER')") 36 | public Result saveUserLike(UserLike userLike) { 37 | if (userLikeService.getUserLike(userLike.getBlog().getId())) { 38 | return Result.create(StatusCode.ERROR, "你已点过赞"); 39 | } 40 | 41 | try { 42 | 43 | userLikeService.saveUserLike(userLike); 44 | return Result.create(StatusCode.OK, "点赞记录保存成功"); 45 | } catch (RuntimeException re) { 46 | return Result.create(StatusCode.ERROR, re.getMessage()); 47 | } 48 | } 49 | 50 | /** 51 | * @Description: 判断用户是否点过赞 52 | * @Param: [blogId] 53 | * @return: com.zzx.model.entity.Result 54 | * @Author: Tyson 55 | * @Date: 2020/5/30/0030 14:01 56 | */ 57 | @ApiOperation(value = "用户是否点过赞") 58 | @GetMapping("/isUserLike/{blogId}") 59 | @PreAuthorize("hasAuthority('USER')") 60 | public Result getUserLike(@PathVariable Integer blogId) { 61 | try { 62 | return Result.create(StatusCode.OK, "获取点赞记录成功", userLikeService.getUserLike(blogId)); 63 | } catch (RuntimeException re) { 64 | return Result.create(StatusCode.ERROR, re.getMessage()); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/AnnouncementDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.Announcement; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * 按代码规范, 此类名应该为AnnouncementDAO, 历史遗留代码, 就不改了 12 | */ 13 | @Repository 14 | @Mapper 15 | public interface AnnouncementDao { 16 | 17 | /** 18 | * 保存公告 19 | * 20 | * @param announcement 21 | */ 22 | void saveAnnouncement(Announcement announcement); 23 | 24 | /** 25 | * 更新公告删除状态 26 | * 27 | * @param announcementId 28 | */ 29 | void deleteAnnouncementById(Integer announcementId); 30 | 31 | /** 32 | * 更新公告置顶状态 33 | * 34 | * @param announcement 35 | */ 36 | void updateAnnouncementTop(Announcement announcement); 37 | 38 | /** 39 | * 获取公告数量 40 | * 41 | * @return 42 | */ 43 | Long getAnnouncementCount(); 44 | 45 | /** 46 | * 分页查询公告 47 | * 48 | * @param start 49 | * @param showCount 50 | * @return 51 | */ 52 | List findAnnouncement(@Param("start") Integer start, @Param("showCount") Integer showCount); 53 | } 54 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/CodeDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | 4 | import com.zzx.model.pojo.Code; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | import org.apache.ibatis.annotations.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | 12 | @Repository 13 | @Mapper 14 | public interface CodeDao { 15 | 16 | /** 17 | * 根据id查询 邀请码 18 | * 19 | * @param inviteCode 20 | * @return 21 | */ 22 | Code findCodeById(String inviteCode); 23 | 24 | /** 25 | * 根据 id 更新邀请码状态 26 | * 27 | * @param code 28 | */ 29 | void updateCode(Code code); 30 | 31 | /** 32 | * 保存激活码 33 | * 34 | * @param code 35 | */ 36 | void saveCode(Code code); 37 | 38 | /** 39 | * 获取记录条数 40 | * 41 | * @return 42 | */ 43 | Long getCodeCount(); 44 | 45 | /**分页查询激活码 46 | * @param start 47 | * @param showCount 48 | * @return 49 | */ 50 | List findCode(@Param("start") Integer start, @Param("showCount") Integer showCount); 51 | } 52 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/DiscussDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.Discuss; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 评论dao 13 | */ 14 | @Repository 15 | @Mapper 16 | public interface DiscussDao { 17 | /** 18 | * 保存回复 19 | * 20 | * @param discuss 21 | */ 22 | void saveDiscuss(Discuss discuss); 23 | 24 | /** 25 | * 根据id查询评论 26 | * 27 | * @param discussId 28 | * @return 29 | */ 30 | Discuss findDiscussById(Integer discussId); 31 | 32 | /** 33 | * 根据id删除评论 34 | * 35 | * @param discussId 36 | */ 37 | void deleteDiscussById(Integer discussId); 38 | 39 | /** 40 | * 查询博文下的评论 41 | * 42 | * @param blogId 43 | * @return 44 | */ 45 | List findDiscussByBlogId(@Param("blogId") Integer blogId, @Param("start") Integer start, @Param("showCount") Integer showCount); 46 | 47 | /** 48 | * 获取博文下评论数量 49 | * 50 | * @param blogId 51 | * @return 52 | */ 53 | Long getDiscussCountByBlogId(Integer blogId); 54 | 55 | /** 56 | * 获取最新count 条评论 57 | * 58 | * @param count 59 | * @return 60 | */ 61 | List findNewDiscuss(Integer count); 62 | 63 | /** 64 | * 查询 65 | * 66 | * @param userId 用户id 67 | * @param count 显示数量 68 | * @return 69 | */ 70 | List findUserNewDiscuss(@Param("userId") Integer userId,@Param("count") Integer count); 71 | } 72 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/LoginDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.Login; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | @Mapper 10 | public interface LoginDao { 11 | 12 | 13 | /** 14 | * 根据用户id删除登录记录 15 | * @param id 16 | */ 17 | void deleteLoginByUserId(Integer id); 18 | 19 | 20 | /** 21 | * 保存登录信息 22 | */ 23 | void saveLogin(Login login); 24 | 25 | 26 | /** 27 | * 根据用户id修改登录操作表 28 | * @param login 29 | */ 30 | void updateLogin(Login login); 31 | 32 | /** 33 | * 根据用户id找登录操作表 34 | * @param userId 35 | */ 36 | Login findLoginByUserId(Integer userId); 37 | } 38 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/MessageDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | 4 | import com.zzx.model.pojo.Message; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | 12 | @Repository 13 | @Mapper 14 | public interface MessageDao { 15 | 16 | /** 17 | * 根据name查询留言 18 | * 19 | * @param name 20 | * @return 21 | */ 22 | Message findMessageByName(String name); 23 | 24 | /** 25 | * 保存留言 26 | * 27 | * @param message 28 | */ 29 | void saveMessage(Message message); 30 | 31 | /** 32 | * 根据id删除留言 33 | * 34 | * @param messageId 35 | */ 36 | void deleteMessageById(Integer messageId); 37 | 38 | /** 39 | * 获取留言数量 40 | * 41 | * @return 42 | */ 43 | Long getMessageCount(); 44 | 45 | /** 46 | * 分页查询留言 47 | * @param start 48 | * @param showCount 49 | * @return 50 | */ 51 | List findMessage(@Param("start") Integer start, @Param("showCount") Integer showCount); 52 | } 53 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/ReplyDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.Reply; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | @Repository 10 | @Mapper 11 | public interface ReplyDao { 12 | /** 13 | * 保存回复 14 | * @param reply 15 | */ 16 | void saveReply(Reply reply); 17 | 18 | /** 19 | * 根据id查询回复 20 | * @param replyId 21 | * @return 22 | */ 23 | Reply findReplyById(Integer replyId); 24 | 25 | /** 26 | * 根据id删除回复 27 | * @param replyId 28 | */ 29 | void deleteReplyById(Integer replyId); 30 | 31 | /** 32 | * 根据评论id查询回复 33 | * @param id 34 | * @return 35 | */ 36 | List findReplyByDiscussId(Integer id); 37 | 38 | /** 39 | * 根据评论id删除回复 40 | * @param discussId 41 | * @return 受影响行数 42 | */ 43 | Integer deleteReplyByDiscussId(Integer discussId); 44 | } 45 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/RoleDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.Role; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | @Repository 12 | @Mapper 13 | public interface RoleDao { 14 | /** 15 | * 根据用户id查询角色 16 | * @param id 17 | * @return 18 | */ 19 | List findUserRoles(Integer id); 20 | 21 | /** 22 | * 保存用户角色 23 | * @param uesrId 24 | * @param roleId 25 | */ 26 | void saveUserRoles(@Param("userId") Integer uesrId,@Param("roleId") Integer roleId); 27 | 28 | /** 29 | * 根据角色名查询角色 30 | * @param name 31 | * @return 32 | */ 33 | Role findRoleByName(String name); 34 | 35 | 36 | /** 37 | * 查询角色数量 38 | * 返回值建议使用Integer包装类型,Integer 默认值为null 39 | * @return 40 | */ 41 | Integer findAdminRoleCount(String roleName); 42 | 43 | /** 44 | * 查询所有角色 45 | * @return 46 | */ 47 | List findAllRole(); 48 | } 49 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/TagDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | 4 | import com.zzx.model.pojo.Tag; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | @Repository 12 | @Mapper 13 | public interface TagDao { 14 | 15 | /** 16 | * 新增标签 17 | * @param tag 18 | */ 19 | void saveTag(Tag tag); 20 | 21 | /** 22 | * 根据tag id更改标签 23 | * @param tag 24 | */ 25 | void updateTagName(Tag tag); 26 | 27 | /** 28 | *根据tag id删除标签 29 | * @param id 30 | */ 31 | void deleteTag(Integer id); 32 | 33 | /** 34 | * 根据id查询标签 35 | * @param tagId 36 | * @return 37 | */ 38 | Tag findTagById(Integer tagId); 39 | 40 | 41 | /** 42 | * 查询该user id下的所有标签 43 | * @param userId 44 | */ 45 | List findTagByUserId(Integer userId); 46 | 47 | /** 48 | * 查询博文的所有标签 49 | * @param blogId 50 | * @return 51 | */ 52 | List findTagByBlogId(Integer blogId); 53 | 54 | /** 55 | * 根据博文id删除标签 56 | * @param blogId 57 | */ 58 | void deleteTagByBlogId(Integer blogId); 59 | 60 | /** 61 | * 根据tagId删除blog_tag 的记录 62 | * @param tagId 63 | */ 64 | void deleteTagByTagId(Integer tagId); 65 | 66 | /** 67 | * 根据标签名查询标签 68 | * @return 69 | */ 70 | Tag findTagByTagName(String tagName); 71 | } 72 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.User; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | @Repository 11 | @Mapper 12 | public interface UserDao { 13 | 14 | /** 15 | * 根据用户名查询用户 16 | * 17 | * @param name 18 | * @return 19 | */ 20 | User findUserByName(String name); 21 | 22 | /** 23 | * 保存用户 24 | * 25 | * @param user 26 | */ 27 | void saveUser(User user); 28 | 29 | 30 | 31 | 32 | 33 | /** 34 | * 根据邮箱查询用户 35 | * 36 | * @param mail 37 | * @return 38 | */ 39 | User findUserByMail(String mail); 40 | 41 | 42 | 43 | 44 | 45 | /** 46 | * 根据id查询用户 47 | * 48 | * @param id 49 | * @return 50 | */ 51 | User findUserById(Integer id); 52 | 53 | /** 54 | * 根据用户名搜索用户 55 | * 56 | * @param userName 57 | * @return 58 | */ 59 | List searchUserByName(@Param("userName") String userName, @Param("start") Integer start, @Param("showCount") Integer showCount); 60 | 61 | /** 62 | * 查询用户数 63 | * 64 | * @return 65 | */ 66 | Long getUserCount(); 67 | 68 | /** 69 | * 分页查询用户 70 | * 71 | * @param start 72 | * @param showCount 73 | * @return 74 | */ 75 | List findUser(@Param("start") Integer start, @Param("showCount") Integer showCount); 76 | 77 | 78 | /** 79 | * 模糊查询用户名 返回记录数 80 | * 81 | * @param userName 82 | * @return 83 | */ 84 | Long getUserCountByName(String userName); 85 | 86 | /** 87 | * 根据id 修改用户信息 88 | * @param user 89 | */ 90 | void updateUser(User user); 91 | } 92 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/UserLikeDao.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao; 2 | 3 | import com.zzx.model.pojo.UserLike; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | @Mapper 9 | public interface UserLikeDao { 10 | 11 | /** 12 | * @Description: 保存点赞记录 13 | * @Param: [userLike] 14 | * @return: com.zzx.model.pojo.UserLike 15 | * @Author: Tyson 16 | * @Date: 2020/5/26/0026 17 | */ 18 | void saveUserLike(UserLike userLike); 19 | 20 | /** 21 | * @Description: 获取点赞记录 22 | * @Param: [blogId, userId] 23 | * @return: com.zzx.model.pojo.UserLike 24 | * @Author: Tyson 25 | * @Date: 2020/5/30/0030 14:47 26 | */ 27 | UserLike getUserLike(Integer blogId, Integer userId); 28 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/mongo/ControllerLogDAO.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao.mongo; 2 | 3 | import com.zzx.model.entity.ControllerLog; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.domain.Sort; 6 | import org.springframework.data.mongodb.core.MongoTemplate; 7 | import org.springframework.data.mongodb.core.query.Criteria; 8 | import org.springframework.data.mongodb.core.query.Query; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.util.ObjectUtils; 11 | 12 | import java.util.Date; 13 | import java.util.List; 14 | 15 | /** 16 | * ControllerLogDAO 17 | * 18 | * @author zzx 19 | * @date 2021.5.29 16:14 20 | */ 21 | @Component 22 | public class ControllerLogDAO { 23 | 24 | 25 | @Autowired 26 | private MongoTemplate mongoTemplate; 27 | 28 | /** 29 | * 创建对象 30 | */ 31 | public void saveControllerLog(ControllerLog log) { 32 | mongoTemplate.save(log); 33 | } 34 | 35 | /** 36 | * 查询在此时间之后的记录 37 | * 38 | * @return 39 | */ 40 | public List findNewestLog(Date left, Date right, int size) { 41 | Criteria condition = new Criteria(); 42 | if (!ObjectUtils.isEmpty(left) || !ObjectUtils.isEmpty(right)) { 43 | condition = condition.and("date"); 44 | if (!ObjectUtils.isEmpty(left)) { 45 | condition.gt(left); 46 | } 47 | if (!ObjectUtils.isEmpty(right)) { 48 | condition.lte(right); 49 | } 50 | } 51 | Query query = new Query(condition).limit(size) 52 | .with(Sort.by(Sort.Order.desc("date"))); 53 | return mongoTemplate.find(query, ControllerLog.class); 54 | } 55 | } 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/dao/mongo/SqlLogDAO.java: -------------------------------------------------------------------------------- 1 | package com.zzx.dao.mongo; 2 | 3 | import com.zzx.model.entity.ControllerLog; 4 | import com.zzx.model.entity.SqlLog; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Sort; 7 | import org.springframework.data.mongodb.core.MongoTemplate; 8 | import org.springframework.data.mongodb.core.query.Criteria; 9 | import org.springframework.data.mongodb.core.query.Query; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.ObjectUtils; 12 | 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | /** 17 | * SqlLogDAO 18 | * 19 | * @author zzx 20 | * @date 2021.5.29 16:14 21 | */ 22 | @Component 23 | public class SqlLogDAO { 24 | 25 | @Autowired 26 | private MongoTemplate mongoTemplate; 27 | 28 | /** 29 | * 创建对象 30 | */ 31 | public void saveSqlLog(SqlLog log) { 32 | mongoTemplate.save(log); 33 | } 34 | 35 | 36 | /** 37 | * 查询在此时间之后的记录 38 | * @return 39 | */ 40 | public List findNewestLog(Date left, Date right, int size) { 41 | Criteria condition = new Criteria(); 42 | if (!ObjectUtils.isEmpty(left) || !ObjectUtils.isEmpty(right)) { 43 | condition = condition.and("date"); 44 | if (!ObjectUtils.isEmpty(left)) { 45 | condition.gt(left); 46 | } 47 | if (!ObjectUtils.isEmpty(right)) { 48 | condition.lte(right); 49 | } 50 | } 51 | 52 | Query query = new Query(condition).limit(size) 53 | .with(Sort.by(Sort.Order.desc("date"))); 54 | return mongoTemplate.find(query, SqlLog.class); 55 | } 56 | 57 | 58 | } 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/exception/DbMakerConfigException.java: -------------------------------------------------------------------------------- 1 | package com.zzx.exception; 2 | 3 | public class DbMakerConfigException extends Exception { 4 | private static final long serialVersionUID = 4495714680349884838L; 5 | 6 | public DbMakerConfigException(String var1) { 7 | super(var1); 8 | } 9 | 10 | public DbMakerConfigException(Throwable var1) { 11 | super(var1); 12 | } 13 | 14 | public DbMakerConfigException(String var1, Throwable var2) { 15 | super(var1, var2); 16 | } 17 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.zzx.exception; 2 | 3 | import com.zzx.model.entity.Result; 4 | import com.zzx.model.entity.StatusCode; 5 | import org.apache.catalina.connector.ClientAbortException; 6 | import org.springframework.security.access.AccessDeniedException; 7 | import org.springframework.security.web.firewall.RequestRejectedException; 8 | import org.springframework.validation.BindException; 9 | import org.springframework.web.HttpRequestMethodNotSupportedException; 10 | import org.springframework.web.bind.MissingServletRequestParameterException; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; 14 | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; 15 | import org.springframework.web.multipart.MaxUploadSizeExceededException; 16 | import org.springframework.web.servlet.NoHandlerFoundException; 17 | 18 | 19 | /** 20 | * 异常处理 21 | */ 22 | @RestControllerAdvice 23 | public class GlobalExceptionHandler { 24 | 25 | 26 | /** 27 | * 找不到资源 -> com.zzx.config.ErrorConfig 28 | * 未找到处理器 异常 29 | * 30 | * @param e 31 | * @return 32 | */ 33 | @ExceptionHandler(NoHandlerFoundException.class) 34 | public Result noHandlerFoundExceptionHander(Exception e) { 35 | // e.printStackTrace(); 36 | return Result.create(StatusCode.NOTFOUND, "接口不存在"); 37 | } 38 | 39 | 40 | /** 41 | * 权限不足 42 | * 43 | * @param e 44 | * @return 45 | */ 46 | @ExceptionHandler(AccessDeniedException.class) 47 | public Result accessDeniedExceptionHander(Exception e) { 48 | // e.printStackTrace(); 49 | return Result.create(StatusCode.ACCESSERROR, "拒绝访问"); 50 | } 51 | 52 | /** 53 | * 请求方式错误 54 | * 55 | * @param e 56 | * @return 57 | */ 58 | @ExceptionHandler(HttpRequestMethodNotSupportedException.class) 59 | public Result httpRequestMethodNotSupportedExceptionHandler(Exception e) { 60 | // e.printStackTrace(); 61 | return Result.create(StatusCode.ERROR, "请求方式错误"); 62 | } 63 | 64 | 65 | /** 66 | * controller参数异常/缺少 67 | * 68 | * @param e 69 | * @return 70 | */ 71 | @ExceptionHandler({ 72 | MissingServletRequestParameterException.class, 73 | MethodArgumentTypeMismatchException.class, 74 | RequestRejectedException.class, 75 | BindException.class} 76 | ) 77 | public Result missingServletRequestParameterException(Exception e) { 78 | // e.printStackTrace(); 79 | return Result.create(StatusCode.ERROR, "参数异常"); 80 | 81 | } 82 | 83 | /** 84 | * 单次上传文件过大 85 | * 86 | * @param e 87 | * @return 88 | */ 89 | @ExceptionHandler(MaxUploadSizeExceededException.class) 90 | public Result maxUploadSizeExceededException(Exception e) { 91 | // e.printStackTrace(); 92 | return Result.create(StatusCode.ERROR, "文件过大"); 93 | } 94 | 95 | /** 96 | * 客户端错误 97 | * 98 | * @param e 99 | * @return 100 | */ 101 | @ExceptionHandler(ClientAbortException.class) 102 | public Result clientAbortExceptionException(Exception e) { 103 | // e.printStackTrace(); 104 | return Result.create(StatusCode.ERROR, "客户端错误"); 105 | } 106 | 107 | 108 | /** 109 | * 其他异常 110 | * 111 | * @param e 112 | * @return 113 | */ 114 | @ExceptionHandler(Exception.class) 115 | public Result exceptionHandler(Exception e) { 116 | e.printStackTrace(); 117 | return Result.create(StatusCode.SERVICEERROR, "服务异常 请联系管理员"); 118 | } 119 | 120 | } 121 | 122 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/log/ControllerLog.java: -------------------------------------------------------------------------------- 1 | package com.zzx.log; 2 | 3 | import com.zzx.config.RabbitMqConfig; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.*; 7 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.util.*; 13 | 14 | /** 15 | * 控制层 日志 切面 16 | */ 17 | @Aspect 18 | @Component 19 | @Slf4j 20 | public class ControllerLog { 21 | 22 | 23 | @Autowired 24 | private HttpServletRequest request; 25 | 26 | @Autowired 27 | private RabbitTemplate rabbitTemplate; 28 | 29 | 30 | /** 31 | * 拦截控制层的所有public方法 32 | */ 33 | @Pointcut("execution(public * com.zzx.controller.*.*(..))") 34 | public void log() { 35 | } 36 | 37 | /** 38 | * 不打印日志的路径 39 | */ 40 | private static final Set PASS_PATH = new HashSet<>(1); 41 | 42 | static { 43 | PASS_PATH.add("/user/getMailSendState"); 44 | PASS_PATH.add("/log/findNewestLog"); 45 | } 46 | 47 | /** 48 | * 方法执行前后 拦截 49 | * 50 | * @param pjp 51 | * @return 52 | * @throws Throwable 53 | */ 54 | @Around("log()") 55 | public Object around(ProceedingJoinPoint pjp) throws Throwable { 56 | String requestUri = request.getRequestURI(); 57 | 58 | //方法消耗时间 59 | long start = System.currentTimeMillis(); 60 | Object obj = pjp.proceed(); 61 | long end = System.currentTimeMillis(); 62 | 63 | String value = obj == null ? "null" : obj.toString(); 64 | long time = end - start; 65 | if (!PASS_PATH.contains(requestUri)) { 66 | String logInfo = "{URL:[" + requestUri + "]," + 67 | "RequestMethod:[" + request.getMethod() + "]," + 68 | "Args:" + Arrays.toString(pjp.getArgs()) + "," + 69 | "ReturnValue:[" + value + "]," + 70 | "Time:[" + time + "ms]," + 71 | "MethodName:[" + pjp.getSignature() + "]}"; 72 | log.info(logInfo); 73 | 74 | try { 75 | com.zzx.model.entity.ControllerLog controllerLog = new com.zzx.model.entity.ControllerLog(); 76 | controllerLog.setUrl(requestUri); 77 | controllerLog.setRequestMethod(request.getMethod()); 78 | controllerLog.setArgs(Arrays.toString(pjp.getArgs())); 79 | controllerLog.setReturnValue(value); 80 | controllerLog.setTime(Long.valueOf(time).intValue()); 81 | controllerLog.setMethodName(pjp.getSignature().toString()); 82 | controllerLog.setDate(new Date()); 83 | 84 | rabbitTemplate.convertAndSend(RabbitMqConfig.CONTROLLER_LOG_QUEUE, controllerLog); 85 | } catch (Throwable t) { 86 | log.error("日志消息发送失败", t); 87 | } 88 | } 89 | 90 | return obj; 91 | 92 | } 93 | 94 | 95 | } 96 | 97 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/BaseLog.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | import lombok.Data; 4 | import org.springframework.data.mongodb.core.mapping.MongoId; 5 | 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | 9 | /** 10 | * BaseLog 11 | * 12 | * @author zzx 13 | * @date 2021.5.29 15:57 14 | */ 15 | @Data 16 | public class BaseLog implements Serializable { 17 | 18 | @MongoId 19 | private String id; 20 | 21 | /** 22 | * 执行时间 23 | */ 24 | private Integer time; 25 | 26 | private Date date; 27 | } 28 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/ControllerLog.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.data.mongodb.core.mapping.Document; 8 | 9 | /** 10 | * ControllerLog 11 | * 12 | * @author zzx 13 | * @date 2021.5.29 15:54 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Document(value = "controller_log") 20 | public class ControllerLog extends BaseLog { 21 | private String url; 22 | private String requestMethod; 23 | private String methodName; 24 | private String args; 25 | private String returnValue; 26 | } 27 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/MailMessage.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.mail.SimpleMailMessage; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * 对SimpleMailMessage进行一层封装 9 | */ 10 | @Component 11 | public class MailMessage { 12 | 13 | @Value("${spring.mail.username}") 14 | private String fromMail; 15 | 16 | private MailMessage() { 17 | } 18 | 19 | public SimpleMailMessage create(String toMail, String subject, String text) { 20 | SimpleMailMessage message = new SimpleMailMessage(); 21 | message.setFrom(fromMail); 22 | message.setTo(toMail); 23 | message.setSubject(subject); 24 | message.setText(text); 25 | return message; 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/PageResult.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 分页结果类 11 | * 12 | * @param 13 | */ 14 | @Data 15 | @ToString 16 | public class PageResult { 17 | private Long total; //数据条数 18 | private List rows; //数据 19 | 20 | public PageResult(Long total, List rows) { 21 | super(); 22 | this.total = total; 23 | this.rows = rows; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/Result.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | import lombok.ToString; 9 | 10 | /** 11 | * 返回结果实体类 12 | */ 13 | 14 | @ApiModel("响应实体") 15 | 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | @Data 18 | @ToString 19 | public class Result { 20 | 21 | @ApiModelProperty(value = "返回码", dataType = "Integer") 22 | private Integer code;// 返回码 23 | 24 | @ApiModelProperty(value = "返回信息", dataType = "String") 25 | private String message;//返回信息 26 | 27 | @ApiModelProperty(value = "返回数据", dataType = "object") 28 | private Object data;// 返回数据 29 | 30 | private Result() { 31 | } 32 | 33 | 34 | private Result(Integer code, String message) { 35 | super(); 36 | this.code = code; 37 | this.message = message; 38 | } 39 | 40 | private Result(Integer code, String message, Object data) { 41 | super(); 42 | this.code = code; 43 | this.message = message; 44 | this.data = data; 45 | } 46 | 47 | public static Result create(Integer code, String message) { 48 | return new Result(code, message); 49 | } 50 | 51 | public static Result create(Integer code, String message, Object data) { 52 | return new Result(code, message, data); 53 | } 54 | 55 | 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/SqlLog.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.data.mongodb.core.mapping.Document; 8 | 9 | /** 10 | * SqlLog 11 | * 12 | * @author zzx 13 | * @date 2021.5.29 17:01 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Document(value = "sql_log") 20 | public class SqlLog extends BaseLog { 21 | private String sql; 22 | } 23 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/entity/StatusCode.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.entity; 2 | 3 | /** 4 | * 状态码 5 | */ 6 | public class StatusCode { 7 | /** 8 | * 操作成功 9 | */ 10 | public static final int OK = 200; 11 | /** 12 | * 失败 13 | */ 14 | public static final int ERROR = 201; 15 | /** 16 | * 用户名或密码错误 17 | */ 18 | public static final int LOGINERROR = 202; 19 | /** 20 | * token过期 21 | */ 22 | public static final int TOKENEXPIREE = 203; 23 | /** 24 | * 权限不足 25 | */ 26 | public static final int ACCESSERROR = 403; 27 | /** 28 | * 远程调用失败 29 | */ 30 | public static final int REMOTEERROR = 204; 31 | /** 32 | * 重复操作 33 | */ 34 | public static final int REPERROR = 205; 35 | /** 36 | * 业务层错误 37 | */ 38 | public static final int SERVICEERROR = 500; 39 | /** 40 | * 资源不存在 41 | */ 42 | public static final int NOTFOUND = 404; 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Announcement.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * 按代码规范, 包名应该为po, 历史遗留代码, 就不改了 10 | * 公告 11 | */ 12 | @Data 13 | @ToString 14 | public class Announcement { 15 | //id 16 | private Integer id; 17 | //公告标题 18 | private String title; 19 | //公告内容 20 | private String body; 21 | //是否置顶0 置顶 1未置顶 22 | private Integer top; 23 | //发布时间 24 | private Date time; 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Blog.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | /** 11 | * 博文 12 | */ 13 | @Data 14 | @ToString(exclude = "body") 15 | public class Blog implements Serializable { 16 | /** 17 | * blog(36) => 541312(10) 18 | */ 19 | private static final long serialVersionUID = 541312L; 20 | /** 21 | * id 22 | */ 23 | private Integer id; 24 | /** 25 | * 标题 26 | */ 27 | private String title; 28 | /** 29 | * 内容 30 | */ 31 | private String body; 32 | 33 | /** 34 | * 评论数 35 | */ 36 | private Integer discussCount; 37 | 38 | /** 39 | * 浏览数 40 | */ 41 | private Integer blogViews; 42 | 43 | /** 44 | * 发布时间 45 | */ 46 | private Date time; 47 | /** 48 | * 博文状态--0删除 1正常 49 | */ 50 | private Integer state; 51 | 52 | /** 53 | * 所属用户 54 | */ 55 | private User user; 56 | /** 57 | * 博文对应的标签 58 | */ 59 | private List tags; 60 | 61 | /** 62 | * 博文点赞数 63 | */ 64 | private Integer likeCount; 65 | 66 | public Blog() { 67 | } 68 | 69 | public Blog(int blogId, int likeCount) { 70 | this.id = blogId; 71 | this.likeCount = likeCount; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Code.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | /** 7 | * 邀请码 8 | */ 9 | @Data 10 | @ToString 11 | public class Code { 12 | private String id;//id 13 | private Integer state;//状态 0 未使用 1已使用 2 已删除 14 | private User user; 15 | 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Discuss.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | import java.util.Date; 7 | import java.util.List; 8 | 9 | /** 10 | * 评论 11 | */ 12 | @Data 13 | @ToString 14 | public class Discuss { 15 | private Integer id;//id 16 | private String body;//评论内容 17 | private Date time;//评论时间 18 | private User user;//评论用户 19 | private Blog blog;//评论博文 20 | private List replyList; 21 | 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Login.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * 登录表 10 | */ 11 | @Data 12 | @ToString 13 | public class Login { 14 | 15 | private Date time;//最后登录时间 16 | private String ip;//最后登录ip 17 | private User user;//用户 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Message.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * 留言 10 | */ 11 | @Data 12 | @ToString 13 | public class Message { 14 | private Integer id;//id 15 | private String name;//游客显示为ip地址 16 | private String body;//留言内容 17 | private Date time;//留言时间 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Reply.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * 回复 10 | */ 11 | @Data 12 | @ToString 13 | 14 | public class Reply { 15 | private Integer id;//id 16 | private String body;//回复内容 17 | private Date time;//回复时间 18 | private User user;//用户 19 | private Discuss discuss;//评论 20 | private Reply reply;//父节点回复 21 | 22 | 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Role.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | /** 8 | * 角色 9 | */ 10 | @Data 11 | @ToString 12 | 13 | public class Role { 14 | 15 | private Integer id;//角色id 16 | private String name;//角色名 17 | 18 | public Role() { 19 | } 20 | public Role(String name) { 21 | this.name = name; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/Tag.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 标签 11 | */ 12 | @Data 13 | @ToString 14 | 15 | public class Tag implements Serializable { 16 | 17 | /** 18 | * tag(36) => 37960(10) 19 | */ 20 | private static final long serialVersionUID = 37960L; 21 | private Integer id;//id 22 | private String name;//标签名 23 | 24 | @JsonIgnore 25 | private User user;//用户 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/User.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | import lombok.ToString; 9 | 10 | import java.io.Serializable; 11 | import java.util.List; 12 | 13 | /** 14 | * 用户 15 | */ 16 | @Data 17 | @ToString 18 | @ApiModel("用户") 19 | public class User implements Serializable { 20 | 21 | /** 22 | * user(36) => 1436499(10) 23 | */ 24 | private static final long serialVersionUID = 1436499L; 25 | 26 | 27 | @ApiModelProperty(value = "用户id", dataType = "Integer") 28 | private Integer id; 29 | 30 | @ApiModelProperty(value = "用户名", dataType = "String") 31 | private String name; 32 | 33 | @ApiModelProperty(value = "密码", dataType = "String") 34 | private String password; 35 | 36 | @ApiModelProperty(value = "邮箱", dataType = "String") 37 | private String mail; 38 | 39 | @ApiModelProperty(value = "用户状态", dataType = "Integer") 40 | private Integer state; 41 | 42 | @ApiModelProperty(value = "打赏码路径", dataType = "String") 43 | private String reward; 44 | 45 | @ApiModelProperty(hidden = true) 46 | @JsonIgnore 47 | private List roles; 48 | 49 | private Login login; 50 | 51 | 52 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/pojo/UserLike.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.pojo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * @description: 用户点赞状态 12 | * @author: Tyson 13 | * @time: 2020-05-29 00:00 14 | */ 15 | @Data 16 | @ToString 17 | @ApiModel("用户") 18 | public class UserLike implements Serializable { 19 | 20 | private static final long serialVersionUID = -3956628880213302317L; 21 | 22 | /** 23 | * 主键id 24 | */ 25 | private Integer id; 26 | 27 | /** 28 | * 点赞的用户 29 | */ 30 | private User user; 31 | 32 | /** 33 | * 被点赞的用户的博文 34 | */ 35 | private Blog blog; 36 | 37 | /** 38 | * 点赞的状态.默认未点赞 39 | */ 40 | private Integer status = 0; 41 | 42 | /** 43 | * 创建时间 44 | */ 45 | private Date createTime; 46 | 47 | /** 48 | * 更新时间 49 | */ 50 | private Date updateTime; 51 | 52 | public UserLike() { 53 | } 54 | 55 | public UserLike(int blogId, int userId, int status) { 56 | Blog blog = new Blog(); 57 | blog.setId(blogId); 58 | 59 | User user = new User(); 60 | user.setId(userId); 61 | 62 | this.blog = blog; 63 | this.user = user; 64 | this.status = status; 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/model/vo/NewestLogVO.java: -------------------------------------------------------------------------------- 1 | package com.zzx.model.vo; 2 | 3 | import lombok.Data; 4 | import org.springframework.format.annotation.DateTimeFormat; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * NewestLogVO 10 | * 11 | * @author zzx 12 | * @date 2021.5.29 22:30 13 | */ 14 | @Data 15 | public class NewestLogVO { 16 | private Integer type; 17 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS", iso = DateTimeFormat.ISO.DATE_TIME) 18 | private Date left; 19 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS", iso = DateTimeFormat.ISO.DATE_TIME) 20 | private Date right; 21 | private Integer size; 22 | } 23 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/mq/BlogListener.java: -------------------------------------------------------------------------------- 1 | package com.zzx.mq; 2 | 3 | 4 | import com.zzx.config.RabbitMqConfig; 5 | import com.zzx.dao.BlogDao; 6 | import com.zzx.model.pojo.Blog; 7 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 8 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.Map; 13 | 14 | /** 15 | * 更新博客的队列消费者 16 | * 17 | * @blame mqpearh 18 | */ 19 | @Component 20 | @RabbitListener(queues = RabbitMqConfig.BLOG_QUEUE) 21 | public class BlogListener { 22 | 23 | @Autowired 24 | private BlogDao blogDao; 25 | 26 | @RabbitHandler 27 | public void updateBlog(Blog blog) { 28 | blogDao.updateBlog(blog); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/mq/ControllerLogListener.java: -------------------------------------------------------------------------------- 1 | package com.zzx.mq; 2 | 3 | 4 | import com.zzx.config.RabbitMqConfig; 5 | import com.zzx.dao.mongo.ControllerLogDAO; 6 | import com.zzx.model.entity.ControllerLog; 7 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 8 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * 14 | * @author mqpearh 15 | */ 16 | @Component 17 | @RabbitListener(queues = RabbitMqConfig.CONTROLLER_LOG_QUEUE) 18 | public class ControllerLogListener { 19 | 20 | @Autowired 21 | ControllerLogDAO controllerLogDAO; 22 | 23 | @RabbitHandler 24 | public void save(ControllerLog log) { 25 | controllerLogDAO.saveControllerLog(log); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/mq/MailListener.java: -------------------------------------------------------------------------------- 1 | package com.zzx.mq; 2 | 3 | 4 | import com.zzx.config.MailConfig; 5 | import com.zzx.config.RabbitMqConfig; 6 | import com.zzx.model.entity.MailMessage; 7 | import com.zzx.service.UserService; 8 | import com.zzx.utils.DateUtil; 9 | import com.zzx.utils.LoggerUtil; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.slf4j.Logger; 12 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 13 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.mail.javamail.JavaMailSender; 17 | import org.springframework.stereotype.Component; 18 | 19 | import java.util.Date; 20 | import java.util.Map; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | 24 | /** 25 | * 发送邮件的队列消费者 26 | */ 27 | @Component 28 | @RabbitListener(queues = RabbitMqConfig.MAIL_QUEUE) 29 | @Slf4j 30 | public class MailListener { 31 | 32 | 33 | @Autowired 34 | private JavaMailSender mailSender; 35 | 36 | @Autowired 37 | private UserService userService; 38 | 39 | @Autowired 40 | private MailMessage mailMessage; 41 | 42 | 43 | @RabbitHandler 44 | public void executeSms(Map map) { 45 | String mail = map.get("mail"); 46 | String code = map.get("code"); 47 | 48 | try { 49 | // this.sendMail(mail, code); 50 | Thread.sleep(6000); 51 | userService.updateMailSendState(mail, code, MailConfig.MAIL_STATE_OK); 52 | log.info(mail + "-" + code + "-发送成功"); 53 | } catch (Exception e) { 54 | userService.updateMailSendState(mail, code, MailConfig.MAIL_STATE_ERROR); 55 | log.error(mail + code + "发送失败-" + e.getMessage()); 56 | } 57 | } 58 | 59 | private void sendMail(String mail, String code) { 60 | //发送邮件 61 | mailSender.send(mailMessage 62 | .create(mail, "邮箱验证码", "邮箱验证码:" + code + "," + MailConfig.EXPIRED_TIME + "分钟内有效")); 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/mq/SqlLogListener.java: -------------------------------------------------------------------------------- 1 | package com.zzx.mq; 2 | 3 | 4 | import com.zzx.config.RabbitMqConfig; 5 | import com.zzx.dao.mongo.SqlLogDAO; 6 | import com.zzx.model.entity.SqlLog; 7 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 8 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author mqpearh 14 | */ 15 | @Component 16 | @RabbitListener(queues = RabbitMqConfig.SQL_LOG_QUEUE) 17 | public class SqlLogListener { 18 | 19 | @Autowired 20 | SqlLogDAO sqlLogDAO; 21 | 22 | @RabbitHandler 23 | public void log(SqlLog log) { 24 | sqlLogDAO.saveSqlLog(log); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/schedule/UserLikeTask.java: -------------------------------------------------------------------------------- 1 | package com.zzx.schedule; 2 | 3 | import com.zzx.service.BlogService; 4 | import com.zzx.service.UserLikeService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | import org.springframework.scheduling.annotation.Scheduled; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @description: 定时将Redis点赞相关数据写进数据库 14 | * @author: Tyson 15 | * @time: 2020-05-28 23:57 16 | */ 17 | @Component 18 | @Configuration 19 | @EnableScheduling 20 | @Slf4j 21 | public class UserLikeTask { 22 | 23 | @Autowired 24 | private BlogService blogService; 25 | 26 | @Autowired 27 | private UserLikeService userLikeService; 28 | 29 | /** 30 | * @Description: 2小时执行一次 31 | * @Param: [] 32 | * @return: void 33 | * @Author: Tyson 34 | * @Date: 2020/5/30/0030 14:51 35 | */ 36 | @Scheduled(fixedRate = 1000 * 60 * 60 * 2) 37 | private void userLikeTask() { 38 | log.info("execute userLike task"); 39 | blogService.transLikeCountFromRedis2DB(); 40 | userLikeService.transUserLikeFromRedis2DB(); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/AnnouncementService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.dao.AnnouncementDao; 4 | import com.zzx.model.pojo.Announcement; 5 | import com.zzx.utils.DateUtil; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | public class AnnouncementService { 13 | @Autowired 14 | private AnnouncementDao announcementDao; 15 | 16 | @Autowired 17 | private DateUtil dateUtil; 18 | 19 | public void saveAnnouncement(String announcementTitle, String announcementBody) { 20 | announcementBody = announcementBody.replaceAll("\n", "
"); 21 | Announcement announcement = new Announcement(); 22 | announcement.setTitle(announcementTitle); 23 | announcement.setBody(announcementBody); 24 | announcement.setTime(dateUtil.getCurrentDate()); 25 | announcement.setTop(1); 26 | announcementDao.saveAnnouncement(announcement); 27 | } 28 | 29 | /** 30 | * 根据公告id删除公告 31 | * 32 | * @param announcementId 33 | */ 34 | public void deleteAnnouncementById(Integer announcementId) { 35 | announcementDao.deleteAnnouncementById(announcementId); 36 | } 37 | 38 | 39 | /** 40 | * 置顶或取消置顶公告 41 | * 42 | * @param announcementId 43 | * @param top 44 | */ 45 | public void updateAnnouncementTop(Integer announcementId, Integer top) { 46 | Announcement announcement = new Announcement(); 47 | announcement.setId(announcementId); 48 | announcement.setTop(top); 49 | announcementDao.updateAnnouncementTop(announcement); 50 | } 51 | 52 | 53 | /** 54 | * 获取公告数量 55 | * 56 | * @return 57 | */ 58 | public Long getAnnouncementCount() { 59 | return announcementDao.getAnnouncementCount(); 60 | } 61 | 62 | /** 63 | * 分页查询公告 64 | * 65 | * @param page 66 | * @param showCount 67 | * @return 68 | */ 69 | public List findAnnouncement(Integer page, Integer showCount) { 70 | return announcementDao.findAnnouncement((page - 1) * showCount, showCount); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/CodeService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.dao.CodeDao; 4 | import com.zzx.model.pojo.Code; 5 | import com.zzx.utils.UUIDUtil; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | public class CodeService { 13 | 14 | @Autowired 15 | private CodeDao codeDao; 16 | 17 | @Autowired 18 | private UUIDUtil uuidUtil; 19 | 20 | /** 21 | * 生成激活码 22 | * 23 | * @return 24 | */ 25 | public Code generateCode() { 26 | Code code = new Code(); 27 | code.setState(0); 28 | code.setId(uuidUtil.generateUUID().toUpperCase()); 29 | codeDao.saveCode(code); 30 | return code; 31 | } 32 | 33 | 34 | /** 35 | * 获取激活码记录条数 36 | * 37 | * @return 38 | */ 39 | public Long getCodeCount() { 40 | return codeDao.getCodeCount(); 41 | } 42 | 43 | public List findCode(Integer page, Integer showCount) { 44 | return codeDao.findCode((page - 1) * showCount, showCount); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/LogService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.dao.mongo.ControllerLogDAO; 4 | import com.zzx.dao.mongo.SqlLogDAO; 5 | import com.zzx.model.entity.ControllerLog; 6 | import com.zzx.model.entity.SqlLog; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | /** 14 | * LogService 15 | * 16 | * @author zzx 17 | * @date 2021.5.29 17:57 18 | */ 19 | @Service 20 | public class LogService { 21 | 22 | @Autowired 23 | ControllerLogDAO controllerLogDAO; 24 | 25 | @Autowired 26 | SqlLogDAO sqlLogDAO; 27 | 28 | public List findControllerNewestLog(Date left, Date right, Integer size) { 29 | return controllerLogDAO.findNewestLog(left, right, size); 30 | } 31 | 32 | public List findSqlNewestLog(Date left, Date right, Integer size) { 33 | return sqlLogDAO.findNewestLog(left, right, size); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.dao.LoginDao; 4 | import com.zzx.dao.UserDao; 5 | import com.zzx.model.pojo.Login; 6 | import com.zzx.model.pojo.User; 7 | import com.zzx.utils.DateUtil; 8 | import com.zzx.utils.RequestUtil; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | 16 | 17 | @Service 18 | public class LoginService { 19 | 20 | @Autowired 21 | private LoginDao loginDao; 22 | 23 | @Autowired 24 | private UserService userService; 25 | 26 | @Autowired 27 | private UserDao userDao; 28 | 29 | @Autowired 30 | private HttpServletRequest request; 31 | 32 | @Autowired 33 | private DateUtil dateUtil; 34 | 35 | @Autowired 36 | private RequestUtil requestUtil; 37 | 38 | /** 39 | * 保存登录信息 40 | * 41 | * @param user 42 | */ 43 | @Transactional(rollbackFor = Exception.class) 44 | public void saveLoginInfo(User user) { 45 | 46 | user = userDao.findUserByName(user.getName()); 47 | Login login = new Login(); 48 | login.setUser(user);//绑定用户 49 | login.setIp(requestUtil.getIpAddress(request));//获取操作ip 50 | login.setTime(dateUtil.getCurrentDate());//操作时间 51 | 52 | if (null == loginDao.findLoginByUserId(user.getId())) { 53 | loginDao.saveLogin(login); 54 | } else { 55 | loginDao.updateLogin(login); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/MessageService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | 4 | import com.zzx.config.JwtConfig; 5 | import com.zzx.dao.MessageDao; 6 | import com.zzx.dao.UserDao; 7 | import com.zzx.model.pojo.Message; 8 | import com.zzx.model.pojo.User; 9 | import com.zzx.utils.DateUtil; 10 | import com.zzx.utils.FormatUtil; 11 | import com.zzx.utils.JwtTokenUtil; 12 | import com.zzx.utils.RequestUtil; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import java.util.List; 18 | 19 | @Service 20 | public class MessageService { 21 | @Autowired 22 | private MessageDao messageDao; 23 | 24 | @Autowired 25 | private UserDao userDao; 26 | 27 | @Autowired 28 | private JwtTokenUtil jwtTokenUtil; 29 | 30 | @Autowired 31 | private RequestUtil requestUtil; 32 | 33 | @Autowired 34 | private JwtConfig jwtConfig; 35 | 36 | @Autowired 37 | private HttpServletRequest request; 38 | 39 | @Autowired 40 | private FormatUtil formatUtil; 41 | 42 | @Autowired 43 | private DateUtil dateUtil; 44 | 45 | /** 46 | * 留言 47 | * 48 | * @param messageBody 49 | */ 50 | public void saveMessage(String messageBody) { 51 | 52 | String name = null; 53 | try { 54 | User user = userDao.findUserByName(jwtTokenUtil.getUsernameFromRequest(request));//已登录 55 | name = user.getName(); 56 | } catch (NullPointerException e) { //token 校验失败 游客身份 57 | name = requestUtil.getIpAddress(request); 58 | } 59 | //查询此ip/name 是否留言过 60 | if (messageDao.findMessageByName(name) != null) { 61 | throw new RuntimeException("你已留过言"); 62 | } 63 | 64 | Message message = new Message(); 65 | message.setName(name); 66 | message.setBody(messageBody); 67 | message.setTime(dateUtil.getCurrentDate()); 68 | messageDao.saveMessage(message); 69 | } 70 | 71 | /** 72 | * 根据id删除留言 73 | * 74 | * @param messageId 75 | */ 76 | public void deleteMessageById(Integer messageId) { 77 | messageDao.deleteMessageById(messageId); 78 | } 79 | 80 | /** 81 | * 获取留言数量 82 | * 83 | * @return 84 | */ 85 | public Long getMessageCount() { 86 | return messageDao.getMessageCount(); 87 | } 88 | 89 | public List findMessage(Integer page, Integer showCount) { 90 | List messages = messageDao.findMessage((page - 1) * showCount, showCount); 91 | for (Message message : messages) { 92 | String ip = message.getName(); 93 | if (formatUtil.checkIP(ip)) {//该name是ip 94 | //保留ip 前16位 ( [127.0].0.1 ) [] 内为前16位 95 | String[] subStrs = ip.split("\\."); 96 | StringBuffer buffer = new StringBuffer(); 97 | for (int i = 0; i < subStrs.length && i < 2; i++) { 98 | buffer.append(subStrs[i]).append("."); 99 | } 100 | buffer.append("*.*"); 101 | message.setName(buffer.toString()); 102 | } 103 | } 104 | 105 | return messages; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/RedisService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.config.RedisConfig; 4 | import com.zzx.model.pojo.Blog; 5 | import com.zzx.model.pojo.UserLike; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.redis.core.Cursor; 8 | import org.springframework.data.redis.core.RedisTemplate; 9 | import org.springframework.data.redis.core.ScanOptions; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.io.IOException; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * @description: 19 | * @author: Tyson 20 | * @time: 2020-05-29 00:07 21 | */ 22 | @Service 23 | public class RedisService { 24 | 25 | @Autowired 26 | RedisTemplate redisTemplate; 27 | 28 | /** 29 | * @Description: 从Redis获取用户点赞数据 30 | * @Param: [] 31 | * @return: java.util.List 32 | * @Author: Tyson 33 | * @Date: 2020/5/30/0030 11:37 34 | */ 35 | public List getUserLikeFromRedis() { 36 | List userLikeList = new ArrayList<>(); 37 | try { 38 | Cursor> cursor = redisTemplate.opsForHash().scan(RedisConfig.MAP_USER_LIKE_KEY, ScanOptions.NONE); 39 | while (cursor.hasNext()) { 40 | Map.Entry entry = cursor.next(); 41 | 42 | String key = (String)entry.getKey(); 43 | //拆分key,blogId::userId 44 | String[] keyArr = key.split(RedisConfig.REDIS_LIKE_MID); 45 | int blogId = Integer.parseInt(keyArr[0]); 46 | int userId= Integer.parseInt(keyArr[1]); 47 | int status = Integer.parseInt((String)entry.getValue()); 48 | 49 | UserLike userLike = new UserLike(blogId, userId, status); 50 | 51 | userLikeList.add(userLike); 52 | //从redis删除key 53 | redisTemplate.opsForHash().delete(RedisConfig.MAP_USER_LIKE_KEY, key); 54 | } 55 | cursor.close(); 56 | } catch (IOException ex) { 57 | ex.printStackTrace(); 58 | } 59 | return userLikeList; 60 | } 61 | 62 | /** 63 | * @Description: 从Redis获取博文点赞数 64 | * @Param: [] 65 | * @return: java.util.List 66 | * @Author: Tyson 67 | * @Date: 2020/5/30/0030 11:35 68 | */ 69 | public List getBlogLikeCountFromRedis() { 70 | List blogList = new ArrayList<>(); 71 | try { 72 | Cursor> cursor = redisTemplate.opsForHash().scan(RedisConfig.MAP_BLOG_LIKE_COUNT_KEY, ScanOptions.NONE); 73 | while (cursor.hasNext()) { 74 | Map.Entry entry = cursor.next(); 75 | 76 | String key = (String)entry.getKey(); 77 | int blogId = Integer.parseInt(key); 78 | int count = Integer.parseInt((String)entry.getValue()); 79 | 80 | Blog blog = new Blog(blogId, count); 81 | 82 | blogList.add(blog); 83 | //从redis删除key 84 | redisTemplate.opsForHash().delete(RedisConfig.MAP_BLOG_LIKE_COUNT_KEY, key); 85 | } 86 | cursor.close(); 87 | } catch (IOException ex) { 88 | ex.printStackTrace(); 89 | } 90 | return blogList; 91 | } 92 | } -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/RoleService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.dao.RoleDao; 4 | import com.zzx.model.pojo.Role; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.List; 9 | 10 | 11 | @Service 12 | public class RoleService { 13 | 14 | @Autowired 15 | private RoleDao roleDao; 16 | 17 | /** 18 | * 查询角色数量 19 | * @return 20 | */ 21 | public Integer findAdminRoleCount(String roleName){ 22 | return roleDao.findAdminRoleCount(roleName); 23 | } 24 | 25 | 26 | /** 27 | * 根据角色名查询 28 | * @param roleName 29 | * @return 30 | */ 31 | public Role findRoleByName(String roleName){ 32 | return roleDao.findRoleByName(roleName); 33 | } 34 | 35 | /** 36 | * 查询所有角色 37 | * @return 38 | */ 39 | public List findAllRole() { 40 | return roleDao.findAllRole(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/service/TagService.java: -------------------------------------------------------------------------------- 1 | package com.zzx.service; 2 | 3 | import com.zzx.dao.BlogDao; 4 | import com.zzx.dao.TagDao; 5 | import com.zzx.dao.UserDao; 6 | import com.zzx.model.pojo.Tag; 7 | import com.zzx.model.pojo.User; 8 | import com.zzx.utils.JwtTokenUtil; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.util.List; 15 | 16 | @Service 17 | public class TagService { 18 | 19 | @Autowired 20 | private TagDao tagDao; 21 | 22 | @Autowired 23 | private BlogDao blogDao; 24 | 25 | @Autowired 26 | private HttpServletRequest request; 27 | 28 | @Autowired 29 | private UserDao userDao; 30 | 31 | @Autowired 32 | private JwtTokenUtil jwtTokenUtil; 33 | 34 | /** 35 | * 新增标签 36 | * 37 | * @param tagName 38 | */ 39 | public void saveTag(String tagName) { 40 | String username = jwtTokenUtil.getUsernameFromRequest(request); 41 | User user = userDao.findUserByName(username); 42 | 43 | 44 | if (tagDao.findTagByTagName(tagName) != null) //mysql where tag_name 忽略大小写 45 | { 46 | throw new RuntimeException("标签重复"); 47 | } 48 | 49 | Tag tag = new Tag(); 50 | tag.setUser(user); 51 | tag.setName(tagName); 52 | tagDao.saveTag(tag); 53 | } 54 | 55 | /** 56 | * 删除标签 57 | * 58 | * @param tagId 59 | */ 60 | @Transactional(rollbackFor = Exception.class) 61 | public void deleteTagById(Integer tagId) { 62 | String username = jwtTokenUtil.getUsernameFromRequest(request); 63 | User user = userDao.findUserByName(username); 64 | Tag tag = tagDao.findTagById(tagId); 65 | if (!user.getId().equals(tag.getUser().getId())) { 66 | throw new RuntimeException("无权删除此标签"); 67 | } 68 | 69 | //查询此标签下是否有博文 70 | if (blogDao.findBlogCountByTagId(tagId) > 0) { 71 | throw new RuntimeException("此标签关联了博客"); 72 | } 73 | 74 | tagDao.deleteTag(tagId); 75 | } 76 | 77 | /** 78 | * 更改标签 79 | * 80 | * @param tagId 81 | * @param tagName 82 | */ 83 | public void updateTag(Integer tagId, String tagName) { 84 | String username = jwtTokenUtil.getUsernameFromRequest(request); 85 | User user = userDao.findUserByName(username); 86 | Tag tag = tagDao.findTagById(tagId); 87 | if (!user.getId().equals(tag.getUser().getId())) { 88 | throw new RuntimeException("无权修改此标签"); 89 | } 90 | tag.setName(tagName); 91 | tagDao.updateTagName(tag); 92 | } 93 | 94 | /** 95 | * 查询该user下的所有标签 96 | */ 97 | public List findTagByUserId() { 98 | String username = jwtTokenUtil.getUsernameFromRequest(request); 99 | User user = userDao.findUserByName(username); 100 | return tagDao.findTagByUserId(user.getId()); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/utils/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.zzx.utils; 2 | 3 | import com.zzx.config.ImgUploadConfig; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.io.File; 8 | import java.util.*; 9 | import java.util.concurrent.ConcurrentLinkedQueue; 10 | 11 | /** 12 | * 文件操作工具 13 | */ 14 | @Component 15 | public class FileUtil { 16 | @Autowired 17 | private ImgUploadConfig imgUploadConfig; 18 | 19 | /** 20 | * 获取可用的文件保存路径 21 | * 当所有路径文件夹单位数都超过FolderSize时,返回null 22 | * 23 | * @return 24 | */ 25 | public String getSavePath() { 26 | 27 | ConcurrentLinkedQueue availablePath = ImgUploadConfig.getAvailablePath(); 28 | Iterator iterator = availablePath.iterator(); 29 | 30 | while (iterator.hasNext()) { 31 | File file = iterator.next(); 32 | if (file.listFiles().length < imgUploadConfig.getFolderSize()) { 33 | return file.getPath(); 34 | } else { 35 | availablePath.remove(file); 36 | } 37 | } 38 | return null; 39 | } 40 | 41 | /** 42 | * 初始化上传文件夹 43 | * !操作非常耗时 44 | * 45 | * @return 46 | */ 47 | public List initUploadFolder() { 48 | File root = new File(imgUploadConfig.getUploadFolder()); 49 | root.mkdirs(); 50 | LinkedList files = new LinkedList<>(); 51 | files.add(root); 52 | 53 | for (int i = 0; i < imgUploadConfig.getLayerCount(); i++) { 54 | LinkedList filesClone = (LinkedList)files.clone(); 55 | for (File file : filesClone) { 56 | files.addAll(createFolder(file.getPath(), imgUploadConfig.getFolderSize()));//addAll 添加到链表末尾 57 | } 58 | } 59 | 60 | return files; 61 | } 62 | 63 | /** 64 | * 创建文件夹 65 | * 66 | * @param path 67 | * @param folderSize 文件夹个数 68 | */ 69 | private List createFolder(String path, int folderSize) { 70 | LinkedList files = new LinkedList<>(); 71 | for (int i = 1; i <= folderSize; i++) { 72 | File file = new File(path + "/" + i); 73 | file.mkdirs(); 74 | files.add(file); 75 | } 76 | //返回创建的文件夹 77 | return files; 78 | } 79 | 80 | 81 | /** 82 | * 获取上传文件夹的最下层路径 83 | * 84 | * @return 85 | */ 86 | public List getAllFolder() { 87 | LinkedList files = new LinkedList<>(); 88 | File root = new File(imgUploadConfig.getUploadFolder()); 89 | files.add(root); 90 | for (int i = 0; i < imgUploadConfig.getLayerCount(); i++) { 91 | LinkedList filesClone = (LinkedList)files.clone(); 92 | for (File file : filesClone) { 93 | files.removeFirst(); 94 | Collections.addAll(files, file.listFiles()); 95 | } 96 | } 97 | return files; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/utils/FormatUtil.java: -------------------------------------------------------------------------------- 1 | package com.zzx.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.util.Collection; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | @Component 11 | public class FormatUtil { 12 | 13 | 14 | private static final Pattern MAIL_PATTERN = Pattern.compile("\\w+@\\w+(\\.\\w{2,3})*\\.\\w{2,3}");//邮箱格式 15 | 16 | private static final Pattern IP_PATTERN = Pattern.compile("([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}");//ip格式 17 | 18 | /** 19 | * 邮箱格式校验 20 | * 21 | * @param mail 22 | * @return 23 | */ 24 | public boolean checkMail(String mail) { 25 | Matcher m = MAIL_PATTERN.matcher(mail); 26 | return m.matches(); 27 | } 28 | 29 | /** 30 | * 一般只适用于controller的参数校验 31 | * 检查字符串是否 为 null 为 "" 32 | * 为null 或 ""都返回 false 33 | * 34 | * @param strs 动态参数 35 | */ 36 | public boolean checkStringNull(String... strs) { 37 | for (String str : strs) { 38 | if (str == null || "".equals(str)) { 39 | return false; 40 | } 41 | } 42 | return true; 43 | } 44 | 45 | /** 46 | * 用于controller的参数校验 47 | * 检查对象是否 为 null 48 | * 49 | * @param objs 动态参数 50 | */ 51 | public boolean checkObjectNull(Object... objs) { 52 | for (Object obj : objs) { 53 | if (obj == null) { 54 | return false; 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | 61 | /** 62 | * 获取文件格式 63 | * 64 | * @param fileName 完整文件名 65 | * @return 66 | */ 67 | public String getFileFormat(String fileName) { 68 | if (null == fileName) { 69 | return null; 70 | } 71 | String[] formatNames = fileName.split("\\."); 72 | if (formatNames.length <= 1) { 73 | return null; 74 | } 75 | String format = "." + formatNames[formatNames.length - 1]; 76 | return format; 77 | } 78 | 79 | 80 | /** 81 | * 检查数字是否为非负数 >= 0 82 | * 83 | * @param numbers 84 | * @return true -> 全部数字为非负数 85 | */ 86 | public boolean checkNotNegative(Integer... numbers) { 87 | for (Integer number : numbers) { 88 | if (number < 0) { 89 | return false; 90 | } 91 | } 92 | return true; 93 | } 94 | 95 | /** 96 | * 检查数字是否为正数 >0 97 | * 98 | * @param numbers 99 | * @return true -> 全部数字为正数 100 | */ 101 | public boolean checkPositive(Integer... numbers) { 102 | for (Integer number : numbers) { 103 | if (number <= 0) { 104 | return false; 105 | } 106 | } 107 | return true; 108 | } 109 | 110 | public boolean hasObject(Collection collections, Object obj) { 111 | 112 | for (Object o : collections) { 113 | 114 | } 115 | 116 | return false; 117 | } 118 | 119 | public boolean checkIP(String name) { 120 | Matcher m = IP_PATTERN.matcher(name); 121 | return m.matches(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/utils/LoggerUtil.java: -------------------------------------------------------------------------------- 1 | package com.zzx.utils; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | 8 | /** 9 | * 日志工具 10 | */ 11 | public class LoggerUtil { 12 | 13 | 14 | /** 15 | * 日志工具bean 16 | * 17 | * @param clazz 18 | * @return 19 | */ 20 | public static Logger loggerFactory(Class clazz) { 21 | return LoggerFactory.getLogger(clazz); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/utils/RandomUtil.java: -------------------------------------------------------------------------------- 1 | package com.zzx.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.util.Random; 6 | 7 | @Component 8 | public class RandomUtil { 9 | 10 | private Random random = new Random(); 11 | 12 | 13 | /** 14 | * 返回指定范围内的随机数 15 | * 16 | * @param start 开始 --包括 17 | * @param end 结束 -- 包括 18 | * @return 19 | */ 20 | public synchronized int nextInt(int start, int end) { 21 | // +1:包括右界值 22 | return random.nextInt(end - start) + start + 1; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/utils/RequestUtil.java: -------------------------------------------------------------------------------- 1 | package com.zzx.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | @Component 8 | public class RequestUtil { 9 | 10 | /** 11 | * 从http中获取请求ip 12 | * @param request 13 | * @return 14 | */ 15 | public String getIpAddress(HttpServletRequest request) { 16 | String ip = request.getHeader("x-forwarded-for"); 17 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 18 | ip = request.getHeader("Proxy-Client-IP"); 19 | } 20 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 21 | ip = request.getHeader("WL-Proxy-Client-IP"); 22 | } 23 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 24 | ip = request.getHeader("HTTP_CLIENT_IP"); 25 | } 26 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 27 | ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 28 | } 29 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 30 | ip = request.getRemoteAddr(); 31 | } 32 | // 如果是多级代理,那么取第一个ip为客户端ip 33 | if (ip != null && ip.indexOf(",") != -1) { 34 | ip = ip.substring(0, ip.indexOf(",")).trim(); 35 | } 36 | return ip; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /blog-springboot/src/main/java/com/zzx/utils/UUIDUtil.java: -------------------------------------------------------------------------------- 1 | package com.zzx.utils; 2 | 3 | 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.UUID; 7 | 8 | @Component 9 | public class UUIDUtil { 10 | 11 | public String generateUUID() { 12 | return UUID.randomUUID().toString().replaceAll("-", ""); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/application-pro.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:mysql://192.168.125.136:3306/blog?useUnicode=true&characterEncoding=utf8&useSSL=false 4 | username: root 5 | password: admin 6 | driverClassName: com.mysql.jdbc.Driver 7 | druid: 8 | initial-size: 5 9 | max-active: 20 10 | min-idle: 5 11 | max-wait: 60000 12 | validation-query: SELECT 1 13 | validation-query-timeout: 2000 14 | ####找不到处理器直接抛出异常 15 | mvc: 16 | throw-exception-if-no-handler-found: true 17 | ####是否为工程中的资源文件建立映射 18 | resources: 19 | add-mappings: false 20 | ###邮箱配置 21 | mail: 22 | host: smtp.qq.com 23 | port: 465 24 | username: 11@qq.com 25 | password: sdf 26 | default-encoding: UTF-8 27 | properties: 28 | mail: 29 | smtp: 30 | auth: true 31 | starttls: 32 | enable: true 33 | required: true 34 | ### 如果使用qq邮箱,且部署在阿里云,需要启动ssl,且端口配置为465 35 | # ssl: 36 | # enable: true 37 | 38 | data: 39 | mongodb: 40 | username: 'log' 41 | password: '123456' 42 | host: 192.168.125.136 43 | port: 27017 44 | database: log 45 | field-naming-strategy: org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy 46 | 47 | ###Redis 48 | redis: 49 | host: 192.168.125.136 50 | port: 6379 51 | timeout: 1000 52 | jedis: 53 | pool: 54 | max-active: 10 55 | max-idle: 8 56 | min-idle: 2 57 | max-wait: 100 58 | ###RabbitMQ 59 | rabbitmq: 60 | host: 192.168.125.136 61 | port: 5672 62 | username: guest 63 | password: guest 64 | 65 | mybatis: 66 | ###数据库模型对象 67 | type-aliases-package: com.zzx.model.pojo 68 | mapper-locations: mapper/*.xml 69 | ###打印sql 70 | # configuration: 71 | # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 72 | 73 | ###是否启用swagger 74 | swagger: 75 | enable: false 76 | 77 | logging: 78 | level: 79 | org.springframework.security: info 80 | root: info 81 | file: 82 | path: e:/springboot-blog 83 | 84 | 85 | 86 | 87 | 88 | 89 | ### jwt 90 | jwt: 91 | ###过期时间 s数432000 5天 92 | time: 432000 93 | ###安全密钥 94 | secret: "BlogSecret" 95 | ###token前缀 96 | prefix: "Bearer " 97 | ###http头key 98 | header: "Authorization" 99 | 100 | ###图片上传配置 101 | upload: 102 | #静态资源对外暴露的访问路径 一个* 代表只匹配该路径下的一级子路径 103 | staticAccessPath: /img/* 104 | #文件上传目录 105 | uploadFolder: E:/blog 106 | #文件夹层数 107 | layerCount: 2 108 | #文件夹内单位数 109 | folderSize: 16 110 | 111 | ###站点介绍 112 | site: 113 | introduction: "分享知识" 114 | 115 | server: 116 | port: 8001 -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: pro -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/ip2region.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/blog-springboot/src/main/resources/ip2region.db -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/AnnouncementMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | INSERT INTO announcement 17 | VALUES (null,#{title},#{body},#{top},#{time}) 18 | 19 | 20 | 21 | DELETE FROM announcement 22 | WHERE announcement_id = #{value} 23 | 24 | 25 | 26 | UPDATE announcement 27 | SET announcement_top = #{top} 28 | WHERE announcement_id = #{id} 29 | 30 | 31 | 35 | 36 | 42 | 43 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/CodeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | UPDATE code 23 | SET code_state = #{state}, user_id = #{user.id} 24 | WHERE code_id = #{id} 25 | 26 | 27 | 28 | INSERT INTO code 29 | VALUES (#{id},#{state},null) 30 | 31 | 32 | 36 | 37 | 43 | 44 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/DiscussMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | INSERT INTO discuss 21 | VALUES (null,#{body},#{time},#{user.id},#{blog.id}) 22 | 23 | 24 | 29 | 30 | 31 | DELETE FROM discuss 32 | WHERE discuss_id = #{value} 33 | 34 | 35 | 42 | 43 | 48 | 49 | 56 | 57 | 64 | 65 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/LoginMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | DELETE FROM login WHERE user_id = #{value} 16 | 17 | 18 | 19 | INSERT INTO login values(#{time},#{ip},#{user.id}) 20 | 21 | 22 | 23 | update login 24 | set login_ip = #{ip}, 25 | login_time = #{time} 26 | where user_id = #{user.id} 27 | 28 | 29 | 34 | 35 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/MessageMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | INSERT INTO message 24 | VALUES (null,#{name},#{body},#{time}) 25 | 26 | 27 | 28 | DELETE FROM message 29 | WHERE message_id = #{value} 30 | 31 | 32 | 36 | 37 | 43 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/ReplyMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | INSERT INTO reply 20 | VALUES (null,#{body},#{time},#{user.id},#{discuss.id},#{reply.id}) 21 | 22 | 23 | 28 | 29 | 30 | DELETE FROM reply 31 | WHERE reply_id = #{value} 32 | 33 | 34 | 40 | 41 | 42 | DELETE FROM reply 43 | WHERE discuss_id = #{value} 44 | 45 | 46 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/RoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | INSERT INTO user_role values(null,#{userId},#{roleId}) 19 | 20 | 21 | 24 | 25 | 29 | 30 | 34 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/TagMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | INSERT INTO tag 16 | VALUES(null,#{name},#{user.id}) 17 | 18 | 19 | 20 | UPDATE tag 21 | SET tag_name = #{name} 22 | WHERE tag_id = #{id} 23 | 24 | 25 | 26 | DELETE FROM tag 27 | WHERE tag_id = #{value} 28 | 29 | 30 | 35 | 36 | 41 | 42 | 47 | 48 | 49 | DELETE FROM blog_tag 50 | WHERE blog_id = #{value} 51 | 52 | 53 | 54 | DELETE FROM blog_tag 55 | WHERE tag_id = #{value} 56 | 57 | 58 | 59 | 64 | 65 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/UserLikeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | INSERT INTO user_like(id, user_id, blog_id, status) 17 | VALUES(#{id}, #{user.id}, #{blog.id}, #{status}) 18 | ON DUPLICATE KEY UPDATE status = #{status} 19 | 20 | 21 | 26 | 27 | -------------------------------------------------------------------------------- /blog-springboot/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 | 30 | 31 | 32 | 33 | INSERT INTO user VALUES (null,#{name},#{password},#{mail},#{state},#{reward}) 34 | 35 | 36 | 37 | 42 | 43 | 47 | 48 | 53 | 54 | 60 | 61 | 62 | 67 | 68 | 69 | UPDATE user 70 | 71 | 72 | user_name = #{name}, 73 | 74 | 75 | user_password = #{password}, 76 | 77 | 78 | user_mail = #{mail}, 79 | 80 | 81 | user_state = #{state}, 82 | 83 | 84 | user_reward = #{reward}, 85 | 86 | 87 | WHERE user_id = #{id} 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /blog-vue/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"], 12 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /blog-vue/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /blog-vue/.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | /test/unit/coverage/ 6 | -------------------------------------------------------------------------------- /blog-vue/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parserOptions: { 6 | parser: 'babel-eslint' 7 | }, 8 | env: { 9 | browser: true, 10 | }, 11 | extends: [ 12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 14 | 'plugin:vue/essential', 15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 16 | 'standard' 17 | ], 18 | // required to lint *.vue files 19 | plugins: [ 20 | 'vue' 21 | ], 22 | // add your custom rules here 23 | rules: { 24 | // allow async-await 25 | 'generator-star-spacing': 'off', 26 | // allow debugger during development 27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /blog-vue/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/ 8 | selenium-debug.log 9 | 10 | # Editor directories and files 11 | .idea 12 | .vscode 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | blog-vue.iml 18 | .babelrc 19 | .editorconfig 20 | .eslintignore 21 | .eslintrc.js 22 | .postcssrc.js -------------------------------------------------------------------------------- /blog-vue/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /blog-vue/README.md: -------------------------------------------------------------------------------- 1 | ### Blog-Vue 2 | 3 | #### 技术栈 4 | 5 | * vue 6 | * vuex 7 | * vue router 8 | * axios 9 | * element-ui 10 | * mavon-editor [开源md编辑器](https://github.com/hinesboy/mavonEditor) 11 | * qs 12 | 13 | #### Run 14 | 15 | 安装依赖 16 | ``` 17 | npm install 18 | ``` 19 | npm 失败的话,试试cnpm 20 | ``` 21 | npm install -g cnpm --registry=https://registry.npm.taobao.org 22 | cnpm install 23 | ``` 24 | 运行 25 | ``` 26 | npm run dev 27 | ``` 28 | 29 | ... 30 | -------------------------------------------------------------------------------- /blog-vue/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /blog-vue/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /blog-vue/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /blog-vue/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blog-vue/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | const createLintingRule = () => ({ 12 | test: /\.(js|vue)$/, 13 | loader: 'eslint-loader', 14 | enforce: 'pre', 15 | include: [resolve('src'), resolve('test')], 16 | options: { 17 | formatter: require('eslint-friendly-formatter'), 18 | emitWarning: !config.dev.showEslintErrorsInOverlay 19 | } 20 | }) 21 | 22 | module.exports = { 23 | context: path.resolve(__dirname, '../'), 24 | entry: { 25 | app: './src/main.js' 26 | }, 27 | output: { 28 | path: config.build.assetsRoot, 29 | filename: '[name].js', 30 | publicPath: process.env.NODE_ENV === 'production' 31 | ? config.build.assetsPublicPath 32 | : config.dev.assetsPublicPath 33 | }, 34 | resolve: { 35 | extensions: ['.js', '.vue', '.json'], 36 | alias: { 37 | 'vue$': 'vue/dist/vue.esm.js', 38 | '@': resolve('src'), 39 | } 40 | }, 41 | module: { 42 | rules: [ 43 | // ...(config.dev.useEslint ? [createLintingRule()] : []),//注释掉,不使用eslint语法检查 44 | { 45 | test: /\.vue$/, 46 | loader: 'vue-loader', 47 | options: vueLoaderConfig 48 | }, 49 | { 50 | test: /\.js$/, 51 | loader: 'babel-loader', 52 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 53 | }, 54 | { 55 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 56 | loader: 'url-loader', 57 | options: { 58 | limit: 10000000, 59 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 60 | } 61 | }, 62 | { 63 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 64 | loader: 'url-loader', 65 | options: { 66 | limit: 10000000, 67 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 68 | } 69 | }, 70 | { 71 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 72 | loader: 'url-loader', 73 | options: { 74 | limit: 10000000, 75 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 76 | } 77 | } 78 | ] 79 | }, 80 | node: { 81 | // prevent webpack from injecting useless setImmediate polyfill because Vue 82 | // source contains it (although only uses it if it's native). 83 | setImmediate: false, 84 | // prevent webpack from injecting mocks to Node native modules 85 | // that does not make sense for the client 86 | dgram: 'empty', 87 | fs: 'empty', 88 | net: 'empty', 89 | tls: 'empty', 90 | child_process: 'empty' 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /blog-vue/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /blog-vue/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /blog-vue/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | 5 | module.exports = { 6 | dev: { 7 | 8 | // Paths 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | proxyTable: {// 在这里配置如下代码 此配置只在npm run dev 下生效 12 | '/api': { 13 | target: 'http://127.0.0.1:8001/', // 14 | changeOrigin: true, // 15 | pathRewrite: { 16 | // 路径重写, 17 | '^/api': '/' 18 | } 19 | }, 20 | '/img': { //图片资源默认以8001端口发起请求 21 | target: 'http://127.0.0.1:8001/', // 22 | changeOrigin: true, // 23 | pathRewrite: { 24 | // 路径重写, 25 | '^/': '/' 26 | } 27 | } 28 | }, 29 | 30 | // Various Dev Server settings 31 | host: 'localhost', // can be overwritten by process.env.HOST 32 | port: 80, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 33 | autoOpenBrowser: false, 34 | errorOverlay: true, 35 | notifyOnErrors: true, 36 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 37 | 38 | // Use Eslint Loader? 39 | // If true, your code will be linted during bundling and 40 | // linting errors and warnings will be shown in the console. 41 | useEslint: true, 42 | // If true, eslint errors and warnings will also be shown in the error overlay 43 | // in the browser. 44 | showEslintErrorsInOverlay: false, 45 | 46 | /** 47 | * Source Maps 48 | */ 49 | 50 | // https://webpack.js.org/configuration/devtool/#development 51 | devtool: 'cheap-module-eval-source-map', 52 | 53 | // If you have problems debugging vue-files in devtools, 54 | // set this to false - it *may* help 55 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 56 | cacheBusting: true, 57 | 58 | cssSourceMap: true 59 | }, 60 | 61 | build: { 62 | // Template for index.html 63 | index: path.resolve(__dirname, '../dist/index.html'), 64 | 65 | // Paths 66 | assetsRoot: path.resolve(__dirname, '../dist'), 67 | assetsSubDirectory: 'static', 68 | assetsPublicPath: './', 69 | 70 | /** 71 | * Source Maps 72 | */ 73 | 74 | productionSourceMap: true, 75 | // https://webpack.js.org/configuration/devtool/#production 76 | devtool: '#source-map', 77 | 78 | // Gzip off by default as many popular static hosts such as 79 | // Surge or Netlify already gzip all static assets for you. 80 | // Before setting to `true`, make sure to: 81 | // npm install --save-dev compression-webpack-plugin 82 | productionGzip: false, 83 | productionGzipExtensions: ['js', 'css'], 84 | 85 | // Run the build command with an extra argument to 86 | // View the bundle analyzer report after build finishes: 87 | // `npm run build --report` 88 | // Set to `true` or `false` to always turn it on or off 89 | bundleAnalyzerReport: process.env.npm_config_report 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /blog-vue/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /blog-vue/config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /blog-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 博客客客客 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /blog-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "MQPearth ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "unit": "jest --config test/unit/jest.conf.js --coverage", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e", 13 | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs", 14 | "build": "node build/build.js" 15 | }, 16 | "dependencies": { 17 | "axios": "^0.19.0", 18 | "element-ui": "^2.9.1", 19 | "mavon-editor": "^2.7.4", 20 | "qs": "^6.7.0", 21 | "vue": "^2.5.2", 22 | "vue-cookies": "^1.5.13", 23 | "vue-router": "^3.0.1", 24 | "vuex": "^3.1.1", 25 | "webpack-dev-server": "^2.9.1" 26 | }, 27 | "devDependencies": { 28 | "autoprefixer": "^7.1.2", 29 | "babel-core": "^6.22.1", 30 | "babel-eslint": "^8.2.1", 31 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 32 | "babel-jest": "^21.0.2", 33 | "babel-loader": "^7.1.1", 34 | "babel-plugin-dynamic-import-node": "^1.2.0", 35 | "babel-plugin-syntax-jsx": "^6.18.0", 36 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 37 | "babel-plugin-transform-runtime": "^6.22.0", 38 | "babel-plugin-transform-vue-jsx": "^3.5.0", 39 | "babel-preset-env": "^1.3.2", 40 | "babel-preset-stage-2": "^6.22.0", 41 | "babel-register": "^6.22.0", 42 | "chalk": "^2.0.1", 43 | "chromedriver": "^2.27.2", 44 | "copy-webpack-plugin": "^4.0.1", 45 | "cross-spawn": "^5.0.1", 46 | "css-loader": "^0.28.0", 47 | "eslint": "^4.15.0", 48 | "eslint-config-standard": "^10.2.1", 49 | "eslint-friendly-formatter": "^3.0.0", 50 | "eslint-loader": "^1.7.1", 51 | "eslint-plugin-import": "^2.7.0", 52 | "eslint-plugin-node": "^5.2.0", 53 | "eslint-plugin-promise": "^3.4.0", 54 | "eslint-plugin-standard": "^3.0.1", 55 | "eslint-plugin-vue": "^4.0.0", 56 | "extract-text-webpack-plugin": "^3.0.0", 57 | "file-loader": "^1.1.4", 58 | "friendly-errors-webpack-plugin": "^1.6.1", 59 | "html-webpack-plugin": "^2.30.1", 60 | "jest": "^22.0.4", 61 | "jest-serializer-vue": "^0.3.0", 62 | "nightwatch": "^0.9.12", 63 | "node-notifier": "^5.1.2", 64 | "optimize-css-assets-webpack-plugin": "^3.2.0", 65 | "ora": "^1.2.0", 66 | "portfinder": "^1.0.13", 67 | "postcss-import": "^11.0.0", 68 | "postcss-loader": "^2.0.8", 69 | "postcss-url": "^7.2.1", 70 | "rimraf": "^2.6.0", 71 | "selenium-server": "^3.0.1", 72 | "semver": "^5.3.0", 73 | "shelljs": "^0.7.6", 74 | "uglifyjs-webpack-plugin": "^1.1.1", 75 | "url-loader": "^0.5.8", 76 | "vue-jest": "^1.0.2", 77 | "vue-loader": "^13.3.0", 78 | "vue-style-loader": "^3.0.1", 79 | "vue-template-compiler": "^2.5.2", 80 | "webpack": "^3.6.0", 81 | "webpack-bundle-analyzer": "^3.3.2", 82 | "webpack-cli": "^3.3.3", 83 | "webpack-merge": "^4.1.0" 84 | }, 85 | "engines": { 86 | "node": ">= 6.0.0", 87 | "npm": ">= 3.0.0" 88 | }, 89 | "browserslist": [ 90 | "> 1%", 91 | "last 2 versions", 92 | "not ie <= 8" 93 | ] 94 | } 95 | -------------------------------------------------------------------------------- /blog-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 29 | -------------------------------------------------------------------------------- /blog-vue/src/api/announcement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs' 3 | 4 | export default { 5 | getAnnouncement(page, showCount) { 6 | return request({ 7 | url: '/announcement/' + page + '/' + showCount, 8 | method: 'get' 9 | }) 10 | }, 11 | sendAnnouncement(title, body) { 12 | return request({ 13 | url: '/announcement', 14 | method: 'post', 15 | data: qs.stringify({'title': title, 'body': body}) 16 | }) 17 | }, 18 | top(announcementId, isTop) { 19 | return request({ 20 | url: '/announcement/top/' + announcementId + '/' + isTop, 21 | method: 'put' 22 | }) 23 | }, 24 | deleteAnnouncement(id) { 25 | return request({ 26 | url: '/announcement/' + id, 27 | method: 'delete' 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /blog-vue/src/api/blog.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | getHotBlog() { 6 | return request({ 7 | url: '/blog/hotBlog', 8 | method: 'get' 9 | }) 10 | }, 11 | getStatisticalBlogByMonth() { 12 | return request({ 13 | url: '/blog/statisticalBlogByMonth', 14 | method: 'get' 15 | }) 16 | }, 17 | getBlogHome(page, showCount) { 18 | return request({ 19 | url: '/blog/home/' + page + '/' + showCount, 20 | method: 'get' 21 | }) 22 | }, 23 | getBlogById(id, isClick) { 24 | return request({ 25 | url: '/blog/' + id + '/' + isClick, 26 | method: 'get' 27 | }) 28 | }, 29 | getMyBlog(page, showCount) { 30 | return request({ 31 | url: '/blog/myblog/' + page + '/' + showCount, 32 | method: 'get' 33 | }) 34 | }, 35 | sendBlog(blogTitle, blogBody, tagId) { //发布博客 36 | // alert(qs.stringify({'blogTitle': blogTitle, 'blogBody': blogBody,'tagId':tagId})) 37 | return request({ 38 | url: '/blog', 39 | method: 'post', 40 | data: qs.stringify({'blogTitle': blogTitle, 'blogBody': blogBody, 'tagId': tagId}) 41 | }) 42 | }, 43 | uploadImg(formdata) { 44 | return request({ 45 | url: '/blog/uploadImg', 46 | method: 'post', 47 | data: formdata, 48 | headers: {'Content-Type': 'multipart/form-data'}, 49 | }) 50 | }, 51 | editBlog(blogId, blogTitle, blogBody, tagId) { //发布博客 52 | return request({ 53 | url: '/blog/' + blogId, 54 | method: 'put', 55 | data: qs.stringify({'blogTitle': blogTitle, 'blogBody': blogBody, 'tagId': tagId}) 56 | }) 57 | }, 58 | adminDeleteBlog(blogId) { //管理员删除博客 59 | return request({ 60 | url: '/blog/admin/' + blogId, 61 | method: 'delete' 62 | }) 63 | }, 64 | userDeleteBlog(blogId) { //普通用户删除博客 65 | return request({ 66 | url: '/blog/' + blogId, 67 | method: 'delete' 68 | }) 69 | }, 70 | adminGetBlog(page, showCount) { 71 | return request({ 72 | url: '/blog/AllBlog/' + page + '/' + showCount, 73 | method: 'get' 74 | }) 75 | }, 76 | adminSearchBlog(searchTxt, page, showCount) { 77 | return request({ 78 | url: '/blog/searchAllBlog/' + page + '/' + showCount + '?search=' + searchTxt, 79 | method: 'get' 80 | }) 81 | }, 82 | userSearchBlog(searchTxt, page, showCount) { 83 | return request({ 84 | url: '/blog/searchBlog/' + page + '/' + showCount + '?search=' + searchTxt, 85 | method: 'get' 86 | }) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /blog-vue/src/api/code.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | 4 | export default { 5 | getCode(page, showCount) { 6 | return request({ 7 | url: '/code/' + page + '/' + showCount, 8 | method: 'get' 9 | }) 10 | }, 11 | generateCode() { 12 | return request({ 13 | url: '/code', 14 | method: 'post' 15 | }) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /blog-vue/src/api/discuss.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | getNewDiscuss() { 6 | return request({ 7 | url: '/discuss/newDiscuss', 8 | method: 'get' 9 | }) 10 | }, 11 | getDiscussByBlogId(blogId, page, showCount) { 12 | return request({ 13 | url: '/discuss/' + blogId + '/' + page + '/' + showCount, 14 | method: 'get' 15 | }) 16 | }, 17 | sendDiscuss(blogId, discussBody) { //发送评论 18 | return request({ 19 | url: '/discuss/' + blogId, 20 | method: 'post', 21 | data: qs.stringify({'discussBody': discussBody}) 22 | }) 23 | }, 24 | adminDeleteDiscuss(discussId) { //管理员删除评论 25 | return request({ 26 | url: '/discuss/admin/' + discussId, 27 | method: 'delete' 28 | }) 29 | }, 30 | userDeleteDiscuss(discussId) { //用户删除评论 31 | return request({ 32 | url: '/discuss/' + discussId, 33 | method: 'delete' 34 | }) 35 | }, 36 | adminDeleteReply(replyId) { //管理员删除回复 37 | return request({ 38 | url: '/reply/admin/' + replyId, 39 | method: 'delete' 40 | }) 41 | }, 42 | userDeleteReply(replyId) { //用户删除回复 43 | return request({ 44 | url: '/reply/' + replyId, 45 | method: 'delete' 46 | }) 47 | }, 48 | getUserNewDiscuss(){ //用户删除回复 49 | return request({ 50 | url: '/discuss/userNewDiscuss', 51 | method: 'get' 52 | }) 53 | }, 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /blog-vue/src/api/log.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from "qs"; 3 | 4 | 5 | export default { 6 | findNewestLog(type, left, right, size) { 7 | return request({ 8 | url: '/log/findNewestLog', 9 | method: 'post', 10 | data: qs.stringify({'type': type, 'left': left, 'right': right, 'size': size}) 11 | }) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /blog-vue/src/api/message.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | getMessage(page, showCount) { 6 | return request({ 7 | url: '/message/' + page + '/' + showCount, 8 | method: 'get' 9 | }) 10 | }, 11 | sendMessage(messageBody) { 12 | return request({ 13 | url: '/message', 14 | method: 'post', 15 | data: qs.stringify({'messageBody': messageBody}) 16 | }) 17 | }, 18 | deleteMessage(messageId) { 19 | return request({ 20 | url: '/message/' + messageId, 21 | method: 'delete' 22 | }) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /blog-vue/src/api/other.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | getIPInfo(ip) { 6 | return request({ 7 | url: '/user/ip', 8 | method: 'post', 9 | data: qs.stringify({'ip': ip}) 10 | }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /blog-vue/src/api/reply.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | sendReply(discussId, replyBody, rootId) { 6 | return request({ 7 | url: '/reply/' + discussId, 8 | method: 'post', 9 | data: qs.stringify({'replyBody': replyBody, 'rootId': rootId}) 10 | }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /blog-vue/src/api/site.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export default { 4 | getSite () { 5 | return request({ 6 | url: '/site', 7 | method: 'get' 8 | }) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /blog-vue/src/api/tag.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | getTag() { 6 | return request({ 7 | url: '/tag', 8 | method: 'get' 9 | }) 10 | }, 11 | addTag(tagName) { 12 | return request({ 13 | url: '/tag', 14 | method: 'post', 15 | data: qs.stringify({'tagName': tagName}) 16 | }) 17 | }, 18 | deleteTag(tagId) { 19 | return request({ 20 | url: '/tag/' + tagId, 21 | method: 'delete', 22 | }) 23 | }, 24 | updateTag(tagId, tagName) { 25 | return request({ 26 | url: '/tag', 27 | method: 'put', 28 | data: qs.stringify({'tagId': tagId, 'tagName': tagName}) 29 | }) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /blog-vue/src/api/user.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | login(name, password) { 6 | return request({ 7 | url: '/user/login', 8 | method: 'post', 9 | // header: 'Content-Type:application/x-www-form-urlencoded', 10 | data: qs.stringify({'name': name, 'password': password}) 11 | }) 12 | }, 13 | sendMail(mail) { 14 | return request({ 15 | url: '/user/sendMail', 16 | method: 'post', 17 | // header: 'Content-Type:application/x-www-form-urlencoded', 18 | data: qs.stringify({'mail': mail}) 19 | }) 20 | }, 21 | register(name, password, mail, mailCode, inviteCode) { 22 | return request({ 23 | url: '/user/register', 24 | method: 'post', 25 | // header: 'Content-Type:application/x-www-form-urlencoded', 26 | data: qs.stringify({ 27 | 'name': name, 'password': password, 28 | 'mail': mail, 'mailCode': mailCode, 29 | 'inviteCode': inviteCode 30 | }) 31 | }) 32 | }, 33 | forgetPassword(userName, mailCode, newPassword) { 34 | return request({ 35 | url: '/user/forgetPassword', 36 | method: 'post', 37 | data: qs.stringify({'userName': userName, 'mailCode': mailCode, 'newPassword': newPassword}) 38 | }) 39 | }, 40 | getUserMail() { 41 | return request({ 42 | url: '/user/mail', 43 | method: 'get', 44 | }) 45 | }, 46 | updateReward(filePath) { 47 | return request({ 48 | url: '/user/updateReward', 49 | method: 'put', 50 | data: qs.stringify({'imgPath': filePath}) 51 | }) 52 | }, 53 | getUserReward() { 54 | return request({ 55 | url: '/user/getReward', 56 | method: 'get', 57 | }) 58 | }, 59 | updatePassword(oldPassword, newPassword, mailCode) { 60 | return request({ 61 | url: '/user/updatePassword', 62 | method: 'post', 63 | data: qs.stringify({'oldPassword': oldPassword, 'newPassword': newPassword, 'code': mailCode}) 64 | }) 65 | }, 66 | updateMail(newMail, oldMailCode, newMailCode) { 67 | return request({ 68 | url: '/user/updateMail', 69 | method: 'post', 70 | data: qs.stringify({'newMail': newMail, 'oldMailCode': oldMailCode, 'newMailCode': newMailCode}) 71 | }) 72 | }, 73 | getUser(page, showCount) { //管理员分页查询用户数据 74 | return request({ 75 | url: '/user/' + page + '/' + showCount, 76 | method: 'get', 77 | }) 78 | }, 79 | getUserByName(searchName, page, showCount) { //管理层分页模糊查询用户名 80 | return request({ 81 | url: '/user/search/' + page + '/' + showCount + '?userName=' + searchName, 82 | method: 'get', 83 | }) 84 | }, 85 | banUser(userId, userState) { 86 | return request({ 87 | url: '/user/ban/' + userId + '/' + userState, 88 | method: 'get', 89 | }) 90 | }, 91 | logout(){ 92 | return request({ 93 | url: '/user/logout', 94 | method: 'get', 95 | }) 96 | }, 97 | getMailSendState(mail) { 98 | return request({ 99 | url: '/user/getMailSendState', 100 | method: 'post', 101 | data: qs.stringify({'mail': mail}) 102 | }) 103 | } 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /blog-vue/src/api/userLike.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | import qs from 'qs'; 3 | 4 | export default { 5 | saveUserLike(blogId, status) { 6 | return request({ 7 | url: '/userLike/saveUserLike', 8 | method: 'post', 9 | header: 'Content-Type:application/json', 10 | data: qs.stringify({"blog.id": blogId, "status": status}) 11 | }) 12 | }, 13 | getBlogLikeCount(blogId) { 14 | return request({ 15 | url: '/blog/getBlogLikeCount'+ '/' + blogId, 16 | method: 'get' 17 | }) 18 | }, 19 | isUserLike(blogId) { 20 | return request({ 21 | url: '/userLike/isUserLike'+ '/' + blogId, 22 | method: 'get' 23 | }) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /blog-vue/src/assets/404page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/blog-vue/src/assets/404page.png -------------------------------------------------------------------------------- /blog-vue/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/blog-vue/src/assets/logo.png -------------------------------------------------------------------------------- /blog-vue/src/assets/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/blog-vue/src/assets/qq.png -------------------------------------------------------------------------------- /blog-vue/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | -------------------------------------------------------------------------------- /blog-vue/src/components/bottom.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 38 | -------------------------------------------------------------------------------- /blog-vue/src/components/hotBlog.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 43 | 53 | -------------------------------------------------------------------------------- /blog-vue/src/components/indexBlogList.vue: -------------------------------------------------------------------------------- 1 | 31 | 80 | 86 | -------------------------------------------------------------------------------- /blog-vue/src/components/introduction.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 31 | 41 | -------------------------------------------------------------------------------- /blog-vue/src/components/myBlogList.vue: -------------------------------------------------------------------------------- 1 | 32 | 76 | 81 | -------------------------------------------------------------------------------- /blog-vue/src/components/myTag.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 104 | 113 | -------------------------------------------------------------------------------- /blog-vue/src/components/newDiscuss.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 43 | 53 | -------------------------------------------------------------------------------- /blog-vue/src/components/statisticalBlog.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 32 | 33 | 43 | -------------------------------------------------------------------------------- /blog-vue/src/components/userNewDiscuss.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 42 | 50 | -------------------------------------------------------------------------------- /blog-vue/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import VueCookies from 'vue-cookies' 4 | 5 | 6 | import ElementUI from 'element-ui' 7 | import 'element-ui/lib/theme-chalk/index.css' 8 | import axios from 'axios' 9 | import store from './store/store' 10 | 11 | import mavonEditor from 'mavon-editor' 12 | import 'mavon-editor/dist/css/index.css' 13 | 14 | import router from './router/router' 15 | 16 | Vue.config.productionTip = false 17 | 18 | Vue.use(VueCookies) 19 | Vue.use(ElementUI) 20 | Vue.use(mavonEditor) 21 | 22 | Vue.prototype.$http = axios 23 | 24 | 25 | /* eslint-disable no-new */ 26 | new Vue({ 27 | el: '#app', 28 | router, 29 | store, 30 | components: {App}, 31 | template: '' 32 | }) 33 | -------------------------------------------------------------------------------- /blog-vue/src/router/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | import index from '@/views/index' 5 | import message from '@/views/message' 6 | import announcement from '@/views/announcement' 7 | import newBlog from '@/views/newBlog' 8 | import account from '@/views/account' 9 | import admins from '@/views/admins' 10 | import forgetPwd from '@/views/forgetPwd' 11 | import searchBlog from '@/views/searchBlog' 12 | import blog from '@/views/blog' 13 | import myBlog from '@/views/myBlog' 14 | import editBlog from '@/views/editBlog' 15 | import notfound from '@/views/notfound' 16 | 17 | import userManage from '@/views/userManage' 18 | import codeManage from '@/views/codeManage' 19 | import announcementManage from '@/views/announcementManage' 20 | import blogManage from '@/views/blogManage' 21 | import logManage from '@/views/logManage' 22 | 23 | Vue.use(Router) 24 | 25 | export default new Router({ 26 | routes: [ 27 | { 28 | path: '/', 29 | name: 'index', 30 | component: index 31 | }, 32 | { 33 | path: '/message', 34 | name: 'message', 35 | component: message 36 | }, 37 | { 38 | path: '/announcement', 39 | name: 'announcement', 40 | component: announcement 41 | }, 42 | { 43 | path: '/newBlog', 44 | name: 'newBlog', 45 | component: newBlog 46 | }, 47 | { 48 | path: '/account', 49 | name: 'account', 50 | component: account 51 | }, 52 | { 53 | path: '/admins', 54 | name: 'admins', 55 | component: admins, 56 | children: [ //这里就是二级路由的配置 57 | { 58 | path: 'userManage', 59 | name: 'userManage', 60 | component: userManage 61 | }, 62 | { 63 | path: 'codeManage', 64 | name: 'codeManage', 65 | component: codeManage 66 | }, 67 | { 68 | path: 'announcementManage', 69 | name: 'announcementManage', 70 | component: announcementManage 71 | }, 72 | { 73 | path: 'blogManage', 74 | name: 'blogManage', 75 | component: blogManage 76 | }, 77 | { 78 | path: 'logManage', 79 | name: 'logManage', 80 | component: logManage 81 | } 82 | ] 83 | }, 84 | { 85 | path: '/forgetPwd', 86 | name: 'forgetPwd', 87 | component: forgetPwd 88 | }, 89 | { 90 | path: '/searchBlog/:searchTxt', 91 | name: 'searchBlog', 92 | component: searchBlog 93 | }, 94 | { 95 | path: '/blog/:blogId', 96 | name: 'blog', 97 | component: blog 98 | }, 99 | { 100 | path: '/myBlog', 101 | name: 'myBlog', 102 | component: myBlog 103 | }, 104 | { 105 | path: '/editBlog/:blogId', 106 | name: 'editBlog', 107 | component: editBlog 108 | }, 109 | { 110 | path: '*', 111 | name: 'notfound', 112 | component: notfound 113 | } 114 | ] 115 | }) 116 | -------------------------------------------------------------------------------- /blog-vue/src/store/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | roles: localStorage.getItem('roles') == null ? '' : localStorage.getItem('roles'), 9 | token: localStorage.getItem('token') == null ? '' : localStorage.getItem('token'), 10 | name: localStorage.getItem('name') == null ? '' : localStorage.getItem('name') 11 | 12 | }, mutations: { 13 | login(state, data) { 14 | // 变更状态 15 | this.state.token = data.token; 16 | localStorage.setItem('token', data.token); 17 | //存储用户名 18 | this.state.name = data.name; 19 | localStorage.setItem('name', data.name) 20 | 21 | this.state.roles = data.roles; 22 | localStorage.setItem('roles', data.roles) 23 | }, 24 | logout(state) { 25 | localStorage.removeItem('token'); 26 | this.state.token = ''; 27 | localStorage.removeItem('name'); 28 | this.state.name = ''; 29 | localStorage.removeItem('roles'); 30 | this.state.roles = ''; 31 | }, 32 | refresh(state, token) { //刷新token 33 | this.state.token = token; 34 | localStorage.setItem('token', token); 35 | } 36 | } 37 | }) 38 | -------------------------------------------------------------------------------- /blog-vue/src/utils/date.js: -------------------------------------------------------------------------------- 1 | function timeago(timestamp) { //将时间转化成离现在几分钟,几小时的格式 2 | 3 | 4 | var date = new Date(timestamp); 5 | var diffMs = Date.now() - timestamp;//相差的毫秒数 6 | var diff = (diffMs) / 1000 / 60 / 60; //相差的时间 小时数 7 | if (diff >= 24) { //时间差大于24个小时 显示标准时间 例:2019.6.5 00:26:11 8 | // alert(date.toLocaleString()) 9 | var year = date.getFullYear(); 10 | var month = date.getMonth() + 1; 11 | var day = date.getDate(); 12 | var hours = date.getHours(); 13 | if (hours < 10) 14 | hours = '0' + hours; 15 | var minutes = date.getMinutes(); 16 | if (minutes < 10) 17 | minutes = '0' + minutes; 18 | var seconds = date.getSeconds(); 19 | if (seconds < 10) 20 | seconds = '0' + seconds; 21 | 22 | return year + '.' + month + '.' + day + ' ' + hours + ':' + minutes + ':' + seconds; 23 | } 24 | else { //小于24小时 显示 时间差 例:2小时前 25 | 26 | var mistiming = Math.round((diffMs) / 1000); 27 | var arrr = ['年', '个月', '星期', '天', '小时', '分钟', '秒']; 28 | var arrn = [31536000, 2592000, 604800, 86400, 3600, 60, 1]; 29 | for (var i = 0; i < arrn.length; i++) { 30 | var inm = Math.floor(mistiming / arrn[i]); 31 | if (arrr[i] == arrr[6]) { 32 | if (inm < 1) { 33 | return '刚刚'; 34 | } 35 | } 36 | if (inm != 0) 37 | return inm + arrr[i] + '前'; 38 | } 39 | } 40 | } 41 | 42 | function format(date) { 43 | 44 | const year = date.getFullYear(); 45 | const month = date.getMonth() + 1; 46 | const day = date.getDate(); 47 | let hours = date.getHours(); 48 | if (hours < 10) 49 | hours = '0' + hours; 50 | let minutes = date.getMinutes(); 51 | if (minutes < 10) 52 | minutes = '0' + minutes; 53 | let seconds = date.getSeconds(); 54 | if (seconds < 10) 55 | seconds = '0' + seconds; 56 | let ms = date.getMilliseconds(); 57 | if (ms < 10) { 58 | ms = '00' + ms; 59 | } else if (ms < 100) { 60 | ms = '0' + ms; 61 | } 62 | 63 | return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds + ':' + ms; 64 | } 65 | 66 | 67 | export default { 68 | timeago, 69 | format 70 | } 71 | -------------------------------------------------------------------------------- /blog-vue/src/utils/file.js: -------------------------------------------------------------------------------- 1 | function generateTxt(filename, text) { 2 | var element = document.createElement('a'); 3 | element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); 4 | element.setAttribute('download', filename); 5 | 6 | element.style.display = 'none'; 7 | document.body.appendChild(element); 8 | 9 | element.click(); 10 | 11 | document.body.removeChild(element); 12 | } 13 | 14 | export default { 15 | generateTxt 16 | } 17 | 18 | -------------------------------------------------------------------------------- /blog-vue/src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import {Message, MessageBox} from 'element-ui' 3 | import store from '@/store/store' 4 | import router from '@/router/router' 5 | 6 | 7 | // 创建axios实例 8 | var prod 9 | const service = axios.create({ 10 | baseURL: '/api', // api的base_url 11 | timeout: 15000, // 请求超时时间, 12 | header: 'Content-Type:application/x-www-form-urlencoded' 13 | }) 14 | 15 | // request拦截器 16 | service.interceptors.request.use(config => { 17 | // alert(store.state.token) //token可以通过此方式拿到 18 | if (store.state.token != '') { 19 | config.headers['Authorization'] = store.state.token // 让每个请求携带自定义token 请根据实际情况自行修改 20 | } 21 | return config 22 | }, error => { 23 | // Do something with request error 24 | console.log(error) // for debug 25 | Promise.reject(error) 26 | }) 27 | 28 | // respone拦截器 29 | service.interceptors.response.use( 30 | response => { 31 | /** 32 | * code为非200是抛错 可结合自己业务进行修改 33 | * 如果非200,响应在此被拦截,具体调用代码中无需再判断是否为200 34 | */ 35 | const res = response.data 36 | 37 | if ((typeof (res.code) != "undefined" && res.code != 200) || (typeof (res.status) != "undefined" && res.status != true)) { 38 | 39 | if (typeof (res.code) != "undefined" && res.code != 403) { 40 | //开发环境 41 | // Message({ 42 | // message: res.code + ' : ' + res.message, 43 | // type: 'error', 44 | // duration: 5 * 1000 45 | // }) 46 | 47 | //生产环境 48 | Message({ 49 | message: res.message, 50 | type: 'error', 51 | duration: 5 * 1000 52 | }) 53 | } 54 | 55 | if (typeof (res.status) != "undefined" && res.status != true) { 56 | Message({ 57 | message: '远程接口错误', 58 | type: 'error', 59 | duration: 5 * 1000 60 | }) 61 | } 62 | // 403:Token过期 或 权限不足(恶意访问/被封禁) ; 63 | if (res.code === 403) { 64 | store.commit('logout'); 65 | MessageBox.confirm('你已被登出,点击确定返回首页', '状态异常', { 66 | confirmButtonText: '确 定', 67 | cancelButtonText: '确 定', 68 | type: 'warning' 69 | }).then(() => { 70 | // window.location.href = '#/' 71 | router.push({ //路由跳转 72 | path: '/' 73 | }) 74 | location.reload() 75 | }).catch(() => { 76 | 77 | router.push({ //路由跳转 78 | path: '/' 79 | }) 80 | location.reload() 81 | }) 82 | } 83 | return Promise.reject('error') 84 | } else { 85 | return response.data 86 | } 87 | }, 88 | error => { 89 | console.log('错误:' + error.message)// for debug 90 | var message; 91 | if (error.response.status == 504) { 92 | message = '连接超时' 93 | } else { 94 | message = error.message 95 | } 96 | Message({ 97 | message: message, 98 | type: 'error', 99 | duration: 5 * 1000 100 | }) 101 | return Promise.reject(error) 102 | } 103 | ) 104 | 105 | export default service 106 | -------------------------------------------------------------------------------- /blog-vue/src/views/announcement.vue: -------------------------------------------------------------------------------- 1 | 38 | 86 | 102 | -------------------------------------------------------------------------------- /blog-vue/src/views/codeManage.vue: -------------------------------------------------------------------------------- 1 | 49 | 91 | -------------------------------------------------------------------------------- /blog-vue/src/views/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 32 | 35 | -------------------------------------------------------------------------------- /blog-vue/src/views/myBlog.vue: -------------------------------------------------------------------------------- 1 | 20 | 30 | 35 | -------------------------------------------------------------------------------- /blog-vue/src/views/notfound.vue: -------------------------------------------------------------------------------- 1 | 19 | 29 | 88 | -------------------------------------------------------------------------------- /blog-vue/src/views/searchBlog.vue: -------------------------------------------------------------------------------- 1 | 31 | 80 | 86 | -------------------------------------------------------------------------------- /blog-vue/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/blog-vue/static/.gitkeep -------------------------------------------------------------------------------- /blog-vue/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/blog-vue/static/favicon.ico -------------------------------------------------------------------------------- /conf/nginx.conf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/conf/nginx.conf -------------------------------------------------------------------------------- /img/account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/account.png -------------------------------------------------------------------------------- /img/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/admin.png -------------------------------------------------------------------------------- /img/admin_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/admin_demo.png -------------------------------------------------------------------------------- /img/announcement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/announcement.png -------------------------------------------------------------------------------- /img/blog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/blog.png -------------------------------------------------------------------------------- /img/blog_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/blog_demo.png -------------------------------------------------------------------------------- /img/index_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/index_demo.png -------------------------------------------------------------------------------- /img/index_nologin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/index_nologin.png -------------------------------------------------------------------------------- /img/init_admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/init_admin.png -------------------------------------------------------------------------------- /img/jetbrains-training-partner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/jetbrains-training-partner.png -------------------------------------------------------------------------------- /img/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/log.png -------------------------------------------------------------------------------- /img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/login.png -------------------------------------------------------------------------------- /img/messageBoard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/messageBoard.png -------------------------------------------------------------------------------- /img/myblog_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/myblog_login.png -------------------------------------------------------------------------------- /img/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/register.png -------------------------------------------------------------------------------- /img/writeNewBlog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/img/writeNewBlog.png -------------------------------------------------------------------------------- /other/博客缓存.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/other/博客缓存.png -------------------------------------------------------------------------------- /other/后端功能说明.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MQPearth/Blog/ad706c1b6583445dce0efd4eb3c0103f098fd196/other/后端功能说明.png --------------------------------------------------------------------------------