├── README.md ├── blog-api ├── blog-api.iml ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── rawchen │ │ │ ├── BlogApiApplication.java │ │ │ ├── annotation │ │ │ ├── AccessLimit.java │ │ │ ├── OperationLogger.java │ │ │ └── VisitLogger.java │ │ │ ├── aspect │ │ │ ├── ExceptionLogAspect.java │ │ │ ├── OperationLogAspect.java │ │ │ └── VisitLogAspect.java │ │ │ ├── config │ │ │ ├── JwtFilter.java │ │ │ ├── JwtLoginFilter.java │ │ │ ├── MyAuthenticationEntryPoint.java │ │ │ ├── RedisKeyConfig.java │ │ │ ├── RedisSerializeConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── WebConfig.java │ │ │ ├── controller │ │ │ ├── AboutController.java │ │ │ ├── ArchiveController.java │ │ │ ├── BlogController.java │ │ │ ├── CategoryController.java │ │ │ ├── CommentController.java │ │ │ ├── FriendController.java │ │ │ ├── IndexController.java │ │ │ ├── LoginController.java │ │ │ ├── MomentController.java │ │ │ ├── TagController.java │ │ │ └── admin │ │ │ │ ├── AboutAdminController.java │ │ │ │ ├── BlogAdminController.java │ │ │ │ ├── CategoryAdminController.java │ │ │ │ ├── CommentAdminController.java │ │ │ │ ├── DashboardAdminController.java │ │ │ │ ├── ExceptionLogController.java │ │ │ │ ├── FriendAdminController.java │ │ │ │ ├── LoginLogController.java │ │ │ │ ├── MomentAdminController.java │ │ │ │ ├── OperationLogController.java │ │ │ │ ├── ScheduleJobController.java │ │ │ │ ├── SiteSettingAdminController.java │ │ │ │ ├── TagAdminController.java │ │ │ │ ├── VisitLogController.java │ │ │ │ └── VisitorAdminController.java │ │ │ ├── entity │ │ │ ├── About.java │ │ │ ├── Blog.java │ │ │ ├── Category.java │ │ │ ├── CityVisitor.java │ │ │ ├── Comment.java │ │ │ ├── ExceptionLog.java │ │ │ ├── Friend.java │ │ │ ├── LoginLog.java │ │ │ ├── Moment.java │ │ │ ├── OperationLog.java │ │ │ ├── ScheduleJob.java │ │ │ ├── ScheduleJobLog.java │ │ │ ├── SiteSetting.java │ │ │ ├── Tag.java │ │ │ ├── User.java │ │ │ ├── VisitLog.java │ │ │ ├── VisitRecord.java │ │ │ └── Visitor.java │ │ │ ├── exception │ │ │ ├── BadRequestException.java │ │ │ ├── NotFoundException.java │ │ │ └── PersistenceException.java │ │ │ ├── handler │ │ │ └── ControllerExceptionHandler.java │ │ │ ├── interceptor │ │ │ └── AccessLimitInterceptor.java │ │ │ ├── mapper │ │ │ ├── AboutMapper.java │ │ │ ├── BlogMapper.java │ │ │ ├── CategoryMapper.java │ │ │ ├── CityVisitorMapper.java │ │ │ ├── CommentMapper.java │ │ │ ├── ExceptionLogMapper.java │ │ │ ├── FriendMapper.java │ │ │ ├── LoginLogMapper.java │ │ │ ├── MomentMapper.java │ │ │ ├── OperationLogMapper.java │ │ │ ├── ScheduleJobLogMapper.java │ │ │ ├── ScheduleJobMapper.java │ │ │ ├── SiteSettingMapper.java │ │ │ ├── TagMapper.java │ │ │ ├── UserMapper.java │ │ │ ├── VisitLogMapper.java │ │ │ ├── VisitRecordMapper.java │ │ │ └── VisitorMapper.java │ │ │ ├── model │ │ │ ├── bean │ │ │ │ ├── Badge.java │ │ │ │ ├── Copyright.java │ │ │ │ └── Favorite.java │ │ │ ├── dto │ │ │ │ ├── Blog.java │ │ │ │ ├── BlogPassword.java │ │ │ │ ├── BlogView.java │ │ │ │ ├── BlogVisibility.java │ │ │ │ ├── Comment.java │ │ │ │ ├── Friend.java │ │ │ │ ├── LoginInfo.java │ │ │ │ └── VisitLogUuidTime.java │ │ │ └── vo │ │ │ │ ├── ArchiveBlog.java │ │ │ │ ├── BlogDetail.java │ │ │ │ ├── BlogIdAndTitle.java │ │ │ │ ├── BlogInfo.java │ │ │ │ ├── CategoryBlogCount.java │ │ │ │ ├── Friend.java │ │ │ │ ├── FriendInfo.java │ │ │ │ ├── Introduction.java │ │ │ │ ├── NewBlog.java │ │ │ │ ├── PageComment.java │ │ │ │ ├── PageResult.java │ │ │ │ ├── RandomBlog.java │ │ │ │ ├── Result.java │ │ │ │ ├── SearchBlog.java │ │ │ │ └── TagBlogCount.java │ │ │ ├── service │ │ │ ├── AboutService.java │ │ │ ├── BlogService.java │ │ │ ├── CategoryService.java │ │ │ ├── CityVisitorService.java │ │ │ ├── CommentService.java │ │ │ ├── DashboardService.java │ │ │ ├── ExceptionLogService.java │ │ │ ├── FriendService.java │ │ │ ├── LoginLogService.java │ │ │ ├── MomentService.java │ │ │ ├── OperationLogService.java │ │ │ ├── RedisService.java │ │ │ ├── ScheduleJobService.java │ │ │ ├── SiteSettingService.java │ │ │ ├── TagService.java │ │ │ ├── UserService.java │ │ │ ├── VisitLogService.java │ │ │ ├── VisitRecordService.java │ │ │ ├── VisitorService.java │ │ │ └── impl │ │ │ │ ├── AboutServiceImpl.java │ │ │ │ ├── BlogServiceImpl.java │ │ │ │ ├── CategoryServiceImpl.java │ │ │ │ ├── CityVisitorServiceImpl.java │ │ │ │ ├── CommentServiceImpl.java │ │ │ │ ├── DashboardServiceImpl.java │ │ │ │ ├── ExceptionLogServiceImpl.java │ │ │ │ ├── FriendServiceImpl.java │ │ │ │ ├── LoginLogServiceImpl.java │ │ │ │ ├── MomentServiceImpl.java │ │ │ │ ├── OperationLogServiceImpl.java │ │ │ │ ├── RedisServiceImpl.java │ │ │ │ ├── ScheduleJobServiceImpl.java │ │ │ │ ├── SiteSettingServiceImpl.java │ │ │ │ ├── TagServiceImpl.java │ │ │ │ ├── UserServiceImpl.java │ │ │ │ ├── VisitLogServiceImpl.java │ │ │ │ ├── VisitRecordServiceImpl.java │ │ │ │ └── VisitorServiceImpl.java │ │ │ ├── task │ │ │ ├── RedisSyncScheduleTask.java │ │ │ └── VisitorSyncScheduleTask.java │ │ │ └── util │ │ │ ├── AopUtils.java │ │ │ ├── HashUtils.java │ │ │ ├── IpAddressUtils.java │ │ │ ├── JacksonUtils.java │ │ │ ├── JwtUtils.java │ │ │ ├── MailUtils.java │ │ │ ├── PictureUtil.java │ │ │ ├── QQInfoUtils.java │ │ │ ├── StringUtils.java │ │ │ ├── UserAgentUtils.java │ │ │ ├── common │ │ │ ├── SpringContextUtils.java │ │ │ └── ValidatorUtils.java │ │ │ ├── markdown │ │ │ ├── MarkdownUtils.java │ │ │ └── ext │ │ │ │ ├── cover │ │ │ │ ├── Cover.java │ │ │ │ ├── CoverExtension.java │ │ │ │ └── internal │ │ │ │ │ ├── AbstractCoverNodeRenderer.java │ │ │ │ │ ├── CoverDelimiterProcessor.java │ │ │ │ │ ├── CoverHtmlNodeRenderer.java │ │ │ │ │ └── CoverTextContentNodeRenderer.java │ │ │ │ └── heimu │ │ │ │ ├── Heimu.java │ │ │ │ ├── HeimuExtension.java │ │ │ │ └── internal │ │ │ │ ├── AbstractHeimuNodeRenderer.java │ │ │ │ ├── HeimuDelimiterProcessor.java │ │ │ │ ├── HeimuHtmlNodeRenderer.java │ │ │ │ └── HeimuTextContentNodeRenderer.java │ │ │ └── quartz │ │ │ ├── ScheduleJob.java │ │ │ ├── ScheduleRunnable.java │ │ │ └── ScheduleUtils.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application.properties │ │ ├── ipdb │ │ └── ip2region.db │ │ ├── logback-spring.xml │ │ ├── mapper │ │ ├── AboutMapper.xml │ │ ├── BlogMapper.xml │ │ ├── CategoryMapper.xml │ │ ├── CityVisitorMapper.xml │ │ ├── CommentMapper.xml │ │ ├── ExceptionLogMapper.xml │ │ ├── FriendMapper.xml │ │ ├── LoginLogMapper.xml │ │ ├── MomentMapper.xml │ │ ├── OperationLogMapper.xml │ │ ├── ScheduleJobLogMapper.xml │ │ ├── ScheduleJobMapper.xml │ │ ├── SiteSettingMapper.xml │ │ ├── TagMapper.xml │ │ ├── UserMapper.xml │ │ ├── VisitLogMapper.xml │ │ ├── VisitRecordMapper.xml │ │ └── VisitorMapper.xml │ │ └── templates │ │ ├── guest.html │ │ └── owner.html │ └── test │ └── java │ └── com │ └── rawchen │ └── BlogApiApplicationTests.java ├── blog-cms ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── img │ │ ├── avatar.jpg │ │ ├── comment-avatar │ │ │ ├── 1.jpg │ │ │ └── 2.jpg │ │ └── visitor.jpg │ └── index.html ├── src │ ├── App.vue │ ├── api │ │ ├── ExceptionLog.js │ │ ├── about.js │ │ ├── blog.js │ │ ├── category.js │ │ ├── comment.js │ │ ├── dashboard.js │ │ ├── friend.js │ │ ├── login.js │ │ ├── loginLog.js │ │ ├── moment.js │ │ ├── operationLog.js │ │ ├── schedule.js │ │ ├── siteSetting.js │ │ ├── tag.js │ │ ├── visitLog.js │ │ └── visitor.js │ ├── assets │ │ ├── css │ │ │ ├── base.css │ │ │ └── icon │ │ │ │ ├── demo.css │ │ │ │ ├── demo_index.html │ │ │ │ ├── iconfont.css │ │ │ │ ├── iconfont.eot │ │ │ │ ├── iconfont.js │ │ │ │ ├── iconfont.json │ │ │ │ ├── iconfont.svg │ │ │ │ ├── iconfont.ttf │ │ │ │ ├── iconfont.woff │ │ │ │ └── iconfont.woff2 │ │ └── img │ │ │ └── logo.png │ ├── common │ │ ├── city2coord.json │ │ └── reg.js │ ├── components │ │ ├── Breadcrumb.vue │ │ ├── DateTimeRangePicker.vue │ │ └── SvgIcon.vue │ ├── main.js │ ├── plugins │ │ └── axios.js │ ├── router │ │ └── index.js │ ├── store │ │ ├── index.js │ │ └── mutations-types.js │ ├── util │ │ └── dateTimeFormatUtils.js │ └── views │ │ ├── Home.vue │ │ ├── Login.vue │ │ ├── blog │ │ ├── blog │ │ │ ├── BlogList.vue │ │ │ └── WriteBlog.vue │ │ ├── category │ │ │ └── CategoryList.vue │ │ ├── comment │ │ │ └── CommentList.vue │ │ ├── moment │ │ │ ├── MomentList.vue │ │ │ └── WriteMoment.vue │ │ └── tag │ │ │ └── TagList.vue │ │ ├── dashboard │ │ └── Dashboard.vue │ │ ├── log │ │ ├── ExceptionLog.vue │ │ ├── LoginLog.vue │ │ ├── OperationLog.vue │ │ ├── ScheduleJobLog.vue │ │ └── VisitLog.vue │ │ ├── page │ │ ├── About.vue │ │ ├── FriendList.vue │ │ └── SiteSetting.vue │ │ ├── statistics │ │ └── Visitor.vue │ │ └── system │ │ └── ScheduleJobList.vue └── vue.config.js ├── blog-view ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── img │ │ ├── avatar.jpg │ │ ├── comment-avatar │ │ │ ├── 1.jpg │ │ │ └── 2.jpg │ │ ├── error.png │ │ ├── paper-plane.png │ │ ├── qr.png │ │ └── reward.jpg │ └── index.html ├── src │ ├── App.vue │ ├── api │ │ ├── about.js │ │ ├── archives.js │ │ ├── blog.js │ │ ├── category.js │ │ ├── comment.js │ │ ├── friend.js │ │ ├── home.js │ │ ├── index.js │ │ ├── login.js │ │ ├── moment.js │ │ └── tag.js │ ├── assets │ │ └── css │ │ │ ├── badge.css │ │ │ ├── base.css │ │ │ ├── icon │ │ │ ├── iconfont.css │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.js │ │ │ ├── iconfont.json │ │ │ ├── iconfont.svg │ │ │ ├── iconfont.ttf │ │ │ ├── iconfont.woff │ │ │ └── iconfont.woff2 │ │ │ └── typo.css │ ├── common │ │ └── reg.js │ ├── components │ │ ├── blog │ │ │ ├── BlogItem.vue │ │ │ ├── BlogList.vue │ │ │ └── Pagination.vue │ │ ├── comment │ │ │ ├── Comment.vue │ │ │ ├── CommentForm.vue │ │ │ ├── CommentList.vue │ │ │ └── Pagination.vue │ │ ├── index │ │ │ ├── BlogPasswordDialog.vue │ │ │ ├── Footer.vue │ │ │ ├── Header.vue │ │ │ ├── MyAPlayer.vue │ │ │ └── Nav.vue │ │ └── sidebar │ │ │ ├── Introduction.vue │ │ │ ├── RandomBlog.vue │ │ │ ├── Tags.vue │ │ │ └── Tocbot.vue │ ├── main.js │ ├── plugins │ │ ├── aruMapper.json │ │ ├── axios.js │ │ ├── paopaoMapper.json │ │ └── tvMapper.json │ ├── router │ │ └── index.js │ ├── store │ │ ├── actions.js │ │ ├── getters.js │ │ ├── index.js │ │ ├── mutations-types.js │ │ ├── mutations.js │ │ └── state.js │ ├── util │ │ ├── dateTimeFormatUtils.js │ │ └── directive.js │ └── views │ │ ├── Index.vue │ │ ├── Login.vue │ │ ├── about │ │ └── About.vue │ │ ├── archives │ │ └── Archives.vue │ │ ├── blog │ │ └── Blog.vue │ │ ├── category │ │ └── Category.vue │ │ ├── friends │ │ └── Friends.vue │ │ ├── home │ │ └── Home.vue │ │ ├── moments │ │ └── Moments.vue │ │ └── tag │ │ └── Tag.vue └── vue.config.js └── blog.sql /blog-api/src/main/java/com/rawchen/BlogApiApplication.java: -------------------------------------------------------------------------------- 1 | package com.rawchen; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class BlogApiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(BlogApiApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/annotation/AccessLimit.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @Description: 访问控制 10 | * @Date: 2021-04-04 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface AccessLimit { 15 | /** 16 | * 限制周期(秒) 17 | */ 18 | int seconds(); 19 | 20 | /** 21 | * 规定周期内限制次数 22 | */ 23 | int maxCount(); 24 | 25 | /** 26 | * 触发限制时的消息提示 27 | */ 28 | String msg() default "操作频率过高"; 29 | } -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/annotation/OperationLogger.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @Description: 用于需要记录操作日志的方法 10 | * @Date: 2020-11-29 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface OperationLogger { 15 | /** 16 | * 操作描述 17 | */ 18 | String value() default ""; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/annotation/VisitLogger.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @Description: 用于需要记录访客访问日志的方法 10 | * @Date: 2020-12-04 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface VisitLogger { 15 | /** 16 | * 访问行为 17 | */ 18 | String behavior() default ""; 19 | 20 | /** 21 | * 访问内容 22 | */ 23 | String content() default ""; 24 | } 25 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/config/MyAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.config; 2 | 3 | import com.rawchen.model.vo.Result; 4 | import org.springframework.security.core.AuthenticationException; 5 | import org.springframework.security.web.AuthenticationEntryPoint; 6 | import org.springframework.stereotype.Component; 7 | import com.rawchen.util.JacksonUtils; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | import java.io.PrintWriter; 14 | 15 | /** 16 | * @Description: 未登录 拒绝访问 17 | * @Date: 2020-07-21 18 | */ 19 | @Component 20 | public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { 21 | @Override 22 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) 23 | throws IOException, ServletException { 24 | response.setContentType("application/json;charset=utf-8"); 25 | PrintWriter out = response.getWriter(); 26 | Result result = Result.create(403, "请登录"); 27 | out.write(JacksonUtils.writeValueAsString(result)); 28 | out.flush(); 29 | out.close(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/config/RedisKeyConfig.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.config; 2 | 3 | /** 4 | * @Description: Redis key配置 5 | * @Date: 2020-09-27 6 | */ 7 | public class RedisKeyConfig { 8 | //首页博客简介列表 分页对象key:homeBlogInfoList : {{1,"第一页的缓存"},{2,"第二页的缓存"}} 9 | public static final String HOME_BLOG_INFO_LIST = "homeBlogInfoList"; 10 | 11 | //分类名列表key 12 | public static final String CATEGORY_NAME_LIST = "categoryNameList"; 13 | 14 | //标签云列表key 15 | public static final String TAG_CLOUD_LIST = "tagCloudList"; 16 | 17 | //站点信息key 18 | public static final String SITE_INFO_MAP = "siteInfoMap"; 19 | 20 | //最新推荐博客key 21 | public static final String NEW_BLOG_LIST = "newBlogList"; 22 | 23 | //关于我页面key 24 | public static final String ABOUT_INFO_MAP = "aboutInfoMap"; 25 | 26 | //友链页面信息key 27 | public static final String FRIEND_INFO_MAP = "friendInfoMap"; 28 | 29 | //博客归档key 30 | public static final String ARCHIVE_BLOG_MAP = "archiveBlogMap"; 31 | 32 | //博客访问量key 33 | public static final String BLOG_VIEWS_MAP = "blogViewsMap"; 34 | 35 | //访客标识码key 36 | public static final String IDENTIFICATION_SET = "identificationSet"; 37 | } 38 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/config/RedisSerializeConfig.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.redis.connection.RedisConnectionFactory; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 8 | 9 | /** 10 | * @Description: Redis序列化配置 11 | * @Date: 2020-09-27 12 | */ 13 | @Configuration 14 | public class RedisSerializeConfig { 15 | 16 | /** 17 | * 使用JSON序列化方式 18 | * 19 | * @param redisConnectionFactory 20 | * @return 21 | */ 22 | @Bean 23 | public RedisTemplate jsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) { 24 | RedisTemplate template = new RedisTemplate<>(); 25 | template.setConnectionFactory(redisConnectionFactory); 26 | Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); 27 | template.setDefaultSerializer(serializer); 28 | return template; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.config; 2 | 3 | import com.rawchen.interceptor.AccessLimitInterceptor; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | /** 11 | * @Description: CORS跨域支持 12 | * @Date: 2020-07-22 13 | */ 14 | 15 | @Configuration 16 | public class WebConfig implements WebMvcConfigurer { 17 | 18 | @Autowired 19 | AccessLimitInterceptor accessLimitInterceptor; 20 | 21 | @Override 22 | public void addCorsMappings(CorsRegistry registry) { 23 | registry.addMapping("/**") 24 | .allowedOrigins("*") 25 | .allowedHeaders("*") 26 | .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS") 27 | .maxAge(3600); 28 | } 29 | 30 | @Override 31 | public void addInterceptors(InterceptorRegistry registry) { 32 | registry.addInterceptor(accessLimitInterceptor); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/AboutController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.annotation.VisitLogger; 4 | import com.rawchen.model.vo.Result; 5 | import com.rawchen.service.AboutService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * @Description: 关于我页面 12 | * @Date: 2020-08-31 13 | */ 14 | @RestController 15 | public class AboutController { 16 | @Autowired 17 | AboutService aboutService; 18 | 19 | /** 20 | * 获取关于我页面信息 21 | * 22 | * @return 23 | */ 24 | @VisitLogger(behavior = "访问页面", content = "关于我") 25 | @GetMapping("/about") 26 | public Result about() { 27 | return Result.ok("获取成功", aboutService.getAboutInfo()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/ArchiveController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.annotation.VisitLogger; 4 | import com.rawchen.model.vo.Result; 5 | import com.rawchen.service.BlogService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * @Description: 归档页面 14 | * @Date: 2020-08-12 15 | */ 16 | @RestController 17 | public class ArchiveController { 18 | @Autowired 19 | BlogService blogService; 20 | 21 | /** 22 | * 按年月分组归档公开博客 统计公开博客总数 23 | * 24 | * @return 25 | */ 26 | @VisitLogger(behavior = "访问页面", content = "文章归档") 27 | @GetMapping("/archives") 28 | public Result archives() { 29 | Map archiveBlogMap = blogService.getArchiveBlogAndCountByIsPublished(); 30 | return Result.ok("请求成功", archiveBlogMap); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/CategoryController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.annotation.VisitLogger; 4 | import com.rawchen.model.vo.BlogInfo; 5 | import com.rawchen.model.vo.PageResult; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.BlogService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * @Description: 分类 15 | * @Date: 2020-08-19 16 | */ 17 | @RestController 18 | public class CategoryController { 19 | @Autowired 20 | BlogService blogService; 21 | 22 | /** 23 | * 根据分类name分页查询公开博客列表 24 | * 25 | * @param categoryName 分类name 26 | * @param pageNum 页码 27 | * @return 28 | */ 29 | @VisitLogger(behavior = "查看分类") 30 | @GetMapping("/category") 31 | public Result category(@RequestParam String categoryName, 32 | @RequestParam(defaultValue = "1") Integer pageNum) { 33 | PageResult pageResult = blogService.getBlogInfoListByCategoryNameAndIsPublished(categoryName, pageNum); 34 | return Result.ok("请求成功", pageResult); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/FriendController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.annotation.VisitLogger; 4 | import com.rawchen.model.vo.Friend; 5 | import com.rawchen.model.vo.FriendInfo; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.FriendService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * @Description: 友链 20 | * @Date: 2020-09-08 21 | */ 22 | @RestController 23 | public class FriendController { 24 | @Autowired 25 | FriendService friendService; 26 | 27 | /** 28 | * 获取友链页面 29 | * 30 | * @return 31 | */ 32 | @VisitLogger(behavior = "访问页面", content = "友链") 33 | @GetMapping("/friends") 34 | public Result friends() { 35 | List friendList = friendService.getFriendVOList(); 36 | FriendInfo friendInfo = friendService.getFriendInfo(true, true); 37 | Map map = new HashMap<>(); 38 | map.put("friendList", friendList); 39 | map.put("friendInfo", friendInfo); 40 | return Result.ok("获取成功", map); 41 | } 42 | 43 | /** 44 | * 按昵称增加友链浏览次数 45 | * 46 | * @param nickname 友链昵称 47 | * @return 48 | */ 49 | @VisitLogger(behavior = "点击友链") 50 | @PostMapping("/friend") 51 | public Result addViews(@RequestParam String nickname) { 52 | friendService.updateViewsByNickname(nickname); 53 | return Result.ok("请求成功"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.entity.Category; 4 | import com.rawchen.entity.Tag; 5 | import com.rawchen.model.vo.NewBlog; 6 | import com.rawchen.model.vo.RandomBlog; 7 | import com.rawchen.model.vo.Result; 8 | import com.rawchen.service.BlogService; 9 | import com.rawchen.service.CategoryService; 10 | import com.rawchen.service.SiteSettingService; 11 | import com.rawchen.service.TagService; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * @Description: 站点相关 21 | * @Date: 2020-08-09 22 | */ 23 | 24 | @RestController 25 | public class IndexController { 26 | @Autowired 27 | SiteSettingService siteSettingService; 28 | @Autowired 29 | BlogService blogService; 30 | @Autowired 31 | CategoryService categoryService; 32 | @Autowired 33 | TagService tagService; 34 | 35 | /** 36 | * 获取站点配置信息、最新推荐博客、分类列表、标签云、随机博客 37 | * 38 | * @return 39 | */ 40 | @GetMapping("/site") 41 | public Result site() { 42 | Map map = siteSettingService.getSiteInfo(); 43 | List newBlogList = blogService.getNewBlogListByIsPublished(); 44 | List categoryList = categoryService.getCategoryNameList(); 45 | List tagList = tagService.getTagListNotId(); 46 | List randomBlogList = blogService.getRandomBlogListByLimitNumAndIsPublishedAndIsRecommend(); 47 | map.put("newBlogList", newBlogList); 48 | map.put("categoryList", categoryList); 49 | map.put("tagList", tagList); 50 | map.put("randomBlogList", randomBlogList); 51 | return Result.ok("请求成功", map); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.entity.User; 4 | import com.rawchen.model.dto.LoginInfo; 5 | import com.rawchen.model.vo.Result; 6 | import com.rawchen.service.UserService; 7 | import com.rawchen.util.JwtUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | /** 17 | * @Description: 前台登录 18 | * @Date: 2020-09-02 19 | */ 20 | @RestController 21 | public class LoginController { 22 | @Autowired 23 | UserService userService; 24 | 25 | /** 26 | * 登录成功后,签发博主身份Token 27 | * 28 | * @param loginInfo 29 | * @return 30 | */ 31 | @PostMapping("/login") 32 | public Result login(@RequestBody LoginInfo loginInfo) { 33 | User user = userService.findUserByUsernameAndPassword(loginInfo.getUsername(), loginInfo.getPassword()); 34 | if (!"ROLE_admin".equals(user.getRole())) { 35 | return Result.create(403, "无权限"); 36 | } 37 | user.setPassword(null); 38 | String jwt = JwtUtils.generateToken("admin:" + user.getUsername()); 39 | Map map = new HashMap<>(); 40 | map.put("user", user); 41 | map.put("token", jwt); 42 | return Result.ok("登录成功", map); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/TagController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller; 2 | 3 | import com.rawchen.annotation.VisitLogger; 4 | import com.rawchen.model.vo.BlogInfo; 5 | import com.rawchen.model.vo.PageResult; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.BlogService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * @Description: 标签 15 | * @Date: 2020-08-17 16 | */ 17 | @RestController 18 | public class TagController { 19 | @Autowired 20 | BlogService blogService; 21 | 22 | /** 23 | * 根据标签name分页查询公开博客列表 24 | * 25 | * @param tagName 标签name 26 | * @param pageNum 页码 27 | * @return 28 | */ 29 | @VisitLogger(behavior = "查看标签") 30 | @GetMapping("/tag") 31 | public Result tag(@RequestParam String tagName, 32 | @RequestParam(defaultValue = "1") Integer pageNum) { 33 | PageResult pageResult = blogService.getBlogInfoListByTagNameAndIsPublished(tagName, pageNum); 34 | return Result.ok("请求成功", pageResult); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/AboutAdminController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.rawchen.annotation.OperationLogger; 4 | import com.rawchen.model.vo.Result; 5 | import com.rawchen.service.AboutService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PutMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.Map; 14 | 15 | /** 16 | * @Description: 关于我页面后台管理 17 | * @Date: 2020-09-01 18 | */ 19 | @RestController 20 | @RequestMapping("/admin") 21 | public class AboutAdminController { 22 | @Autowired 23 | AboutService aboutService; 24 | 25 | /** 26 | * 获取关于我页面配置 27 | * 28 | * @return 29 | */ 30 | @GetMapping("/about") 31 | public Result about() { 32 | return Result.ok("请求成功", aboutService.getAboutSetting()); 33 | } 34 | 35 | /** 36 | * 修改关于我页面 37 | * 38 | * @param map 39 | * @return 40 | */ 41 | @OperationLogger("修改关于我页面") 42 | @PutMapping("/about") 43 | public Result updateAbout(@RequestBody Map map) { 44 | aboutService.updateAbout(map); 45 | return Result.ok("修改成功"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/DashboardAdminController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.rawchen.config.RedisKeyConfig; 4 | import com.rawchen.entity.CityVisitor; 5 | import com.rawchen.model.vo.Result; 6 | import com.rawchen.service.DashboardService; 7 | import com.rawchen.service.RedisService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * @Description: 后台管理仪表盘 19 | * @Date: 2020-10-08 20 | */ 21 | @RestController 22 | @RequestMapping("/admin") 23 | public class DashboardAdminController { 24 | @Autowired 25 | DashboardService dashboardService; 26 | @Autowired 27 | RedisService redisService; 28 | 29 | @GetMapping("/dashboard") 30 | public Result dashboard() { 31 | int todayPV = dashboardService.countVisitLogByToday(); 32 | int todayUV = redisService.countBySet(RedisKeyConfig.IDENTIFICATION_SET); 33 | int blogCount = dashboardService.getBlogCount(); 34 | int commentCount = dashboardService.getCommentCount(); 35 | Map categoryBlogCountMap = dashboardService.getCategoryBlogCountMap(); 36 | Map tagBlogCountMap = dashboardService.getTagBlogCountMap(); 37 | Map visitRecordMap = dashboardService.getVisitRecordMap(); 38 | List cityVisitorList = dashboardService.getCityVisitorList(); 39 | 40 | Map map = new HashMap<>(); 41 | map.put("pv", todayPV); 42 | map.put("uv", todayUV); 43 | map.put("blogCount", blogCount); 44 | map.put("commentCount", commentCount); 45 | map.put("category", categoryBlogCountMap); 46 | map.put("tag", tagBlogCountMap); 47 | map.put("visitRecord", visitRecordMap); 48 | map.put("cityVisitor", cityVisitorList); 49 | return Result.ok("获取成功", map); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/ExceptionLogController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.github.pagehelper.PageInfo; 5 | import com.rawchen.entity.ExceptionLog; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.ExceptionLogService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @Description: 异常日志后台管理 17 | * @Date: 2020-12-04 18 | */ 19 | @RestController 20 | @RequestMapping("/admin") 21 | public class ExceptionLogController { 22 | @Autowired 23 | ExceptionLogService exceptionLogService; 24 | 25 | /** 26 | * 分页查询异常日志列表 27 | * 28 | * @param date 按操作时间查询 29 | * @param pageNum 页码 30 | * @param pageSize 每页个数 31 | * @return 32 | */ 33 | @GetMapping("/exceptionLogs") 34 | public Result exceptionLogs(@RequestParam(defaultValue = "") String[] date, 35 | @RequestParam(defaultValue = "1") Integer pageNum, 36 | @RequestParam(defaultValue = "10") Integer pageSize) { 37 | String startDate = null; 38 | String endDate = null; 39 | if (date.length == 2) { 40 | startDate = date[0]; 41 | endDate = date[1]; 42 | } 43 | String orderBy = "create_time desc"; 44 | PageHelper.startPage(pageNum, pageSize, orderBy); 45 | PageInfo pageInfo = new PageInfo<>(exceptionLogService.getExceptionLogListByDate(startDate, endDate)); 46 | return Result.ok("请求成功", pageInfo); 47 | } 48 | 49 | /** 50 | * 按id删除异常日志 51 | * 52 | * @param id 日志id 53 | * @return 54 | */ 55 | @DeleteMapping("/exceptionLog") 56 | public Result delete(@RequestParam Long id) { 57 | exceptionLogService.deleteExceptionLogById(id); 58 | return Result.ok("删除成功"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/LoginLogController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.github.pagehelper.PageInfo; 5 | import com.rawchen.entity.LoginLog; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.LoginLogService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @Description: 登录日志后台管理 17 | * @Date: 2020-12-03 18 | */ 19 | @RestController 20 | @RequestMapping("/admin") 21 | public class LoginLogController { 22 | @Autowired 23 | LoginLogService loginLogService; 24 | 25 | /** 26 | * 分页查询登录日志列表 27 | * 28 | * @param date 按操作时间查询 29 | * @param pageNum 页码 30 | * @param pageSize 每页个数 31 | * @return 32 | */ 33 | @GetMapping("/loginLogs") 34 | public Result loginLogs(@RequestParam(defaultValue = "") String[] date, 35 | @RequestParam(defaultValue = "1") Integer pageNum, 36 | @RequestParam(defaultValue = "10") Integer pageSize) { 37 | String startDate = null; 38 | String endDate = null; 39 | if (date.length == 2) { 40 | startDate = date[0]; 41 | endDate = date[1]; 42 | } 43 | String orderBy = "create_time desc"; 44 | PageHelper.startPage(pageNum, pageSize, orderBy); 45 | PageInfo pageInfo = new PageInfo<>(loginLogService.getLoginLogListByDate(startDate, endDate)); 46 | return Result.ok("请求成功", pageInfo); 47 | } 48 | 49 | /** 50 | * 按id删除登录日志 51 | * 52 | * @param id 日志id 53 | * @return 54 | */ 55 | @DeleteMapping("/loginLog") 56 | public Result delete(@RequestParam Long id) { 57 | loginLogService.deleteLoginLogById(id); 58 | return Result.ok("删除成功"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/OperationLogController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.github.pagehelper.PageInfo; 5 | import com.rawchen.entity.OperationLog; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.OperationLogService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @Description: 操作日志后台管理 17 | * @Date: 2020-12-01 18 | */ 19 | @RestController 20 | @RequestMapping("/admin") 21 | public class OperationLogController { 22 | @Autowired 23 | OperationLogService operationLogService; 24 | 25 | /** 26 | * 分页查询操作日志列表 27 | * 28 | * @param date 按操作时间查询 29 | * @param pageNum 页码 30 | * @param pageSize 每页个数 31 | * @return 32 | */ 33 | @GetMapping("/operationLogs") 34 | public Result operationLogs(@RequestParam(defaultValue = "") String[] date, 35 | @RequestParam(defaultValue = "1") Integer pageNum, 36 | @RequestParam(defaultValue = "10") Integer pageSize) { 37 | String startDate = null; 38 | String endDate = null; 39 | if (date.length == 2) { 40 | startDate = date[0]; 41 | endDate = date[1]; 42 | } 43 | String orderBy = "create_time desc"; 44 | PageHelper.startPage(pageNum, pageSize, orderBy); 45 | PageInfo pageInfo = new PageInfo<>(operationLogService.getOperationLogListByDate(startDate, endDate)); 46 | return Result.ok("请求成功", pageInfo); 47 | } 48 | 49 | /** 50 | * 按id删除操作日志 51 | * 52 | * @param id 日志id 53 | * @return 54 | */ 55 | @DeleteMapping("/operationLog") 56 | public Result delete(@RequestParam Long id) { 57 | operationLogService.deleteOperationLogById(id); 58 | return Result.ok("删除成功"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/SiteSettingAdminController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.rawchen.annotation.OperationLogger; 4 | import com.rawchen.model.vo.Result; 5 | import com.rawchen.service.SiteSettingService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | import com.rawchen.entity.SiteSetting; 13 | 14 | import java.util.LinkedHashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * @Description: 站点设置后台管理 20 | * @Date: 2020-08-09 21 | */ 22 | @RestController 23 | @RequestMapping("/admin") 24 | public class SiteSettingAdminController { 25 | @Autowired 26 | SiteSettingService siteSettingService; 27 | 28 | /** 29 | * 获取所有站点配置信息 30 | * 31 | * @return 32 | */ 33 | @GetMapping("/siteSettings") 34 | public Result siteSettings() { 35 | Map> typeMap = siteSettingService.getList(); 36 | return Result.ok("请求成功", typeMap); 37 | } 38 | 39 | /** 40 | * 修改、删除(部分配置可为空,但不可删除)、添加(只能添加部分)站点配置 41 | * 42 | * @param map 包含所有站点信息更新后的数据 map => {settings=[更新后的所有配置List], deleteIds=[要删除的配置id List]} 43 | * @return 44 | */ 45 | @OperationLogger("更新站点配置信息") 46 | @PostMapping("/siteSettings") 47 | public Result updateAll(@RequestBody Map map) { 48 | List siteSettings = (List) map.get("settings"); 49 | List deleteIds = (List) map.get("deleteIds"); 50 | siteSettingService.updateSiteSetting(siteSettings, deleteIds); 51 | return Result.ok("更新成功"); 52 | } 53 | 54 | /** 55 | * 查询网页标题后缀 56 | * 57 | * @return 58 | */ 59 | @GetMapping("/webTitleSuffix") 60 | public Result getWebTitleSuffix() { 61 | return Result.ok("请求成功", siteSettingService.getWebTitleSuffix()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/controller/admin/VisitorAdminController.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.controller.admin; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.github.pagehelper.PageInfo; 5 | import com.rawchen.entity.Visitor; 6 | import com.rawchen.model.vo.Result; 7 | import com.rawchen.service.VisitorService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @Description: 访客统计 17 | * @Date: 2021-02-02 18 | */ 19 | @RestController 20 | @RequestMapping("/admin") 21 | public class VisitorAdminController { 22 | @Autowired 23 | VisitorService visitorService; 24 | 25 | /** 26 | * 分页查询访客列表 27 | * 28 | * @param date 按最后访问时间查询 29 | * @param pageNum 页码 30 | * @param pageSize 每页个数 31 | * @return 32 | */ 33 | @GetMapping("/visitors") 34 | public Result visitors(@RequestParam(defaultValue = "") String[] date, 35 | @RequestParam(defaultValue = "1") Integer pageNum, 36 | @RequestParam(defaultValue = "10") Integer pageSize) { 37 | String startDate = null; 38 | String endDate = null; 39 | if (date.length == 2) { 40 | startDate = date[0]; 41 | endDate = date[1]; 42 | } 43 | String orderBy = "create_time desc"; 44 | PageHelper.startPage(pageNum, pageSize, orderBy); 45 | PageInfo pageInfo = new PageInfo<>(visitorService.getVisitorListByDate(startDate, endDate)); 46 | return Result.ok("请求成功", pageInfo); 47 | } 48 | 49 | /** 50 | * 按id删除访客 51 | * 按uuid删除Redis缓存 52 | * 53 | * @param id 访客id 54 | * @param uuid 访客uuid 55 | * @return 56 | */ 57 | @DeleteMapping("/visitor") 58 | public Result delete(@RequestParam Long id, @RequestParam String uuid) { 59 | visitorService.deleteVisitor(id, uuid); 60 | return Result.ok("删除成功"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/About.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 关于我 10 | * @Date: 2020-08-31 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class About { 17 | private Long id; 18 | private String nameEn; 19 | private String nameZh; 20 | private String value; 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Blog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | /** 13 | * @Description: 博客文章 14 | * @Date: 2020-07-26 15 | */ 16 | @NoArgsConstructor 17 | @Getter 18 | @Setter 19 | @ToString 20 | public class Blog { 21 | private Long id; 22 | private String title;//文章标题 23 | private String firstPicture;//文章首图,用于随机文章展示 24 | private String content;//文章正文 25 | private String description;//描述 26 | private Boolean published;//公开或私密 27 | private Boolean recommend;//推荐开关 28 | private Boolean appreciation;//赞赏开关 29 | private Boolean commentEnabled;//评论开关 30 | private Boolean top;//是否置顶 31 | private Date createTime;//创建时间 32 | private Date updateTime;//更新时间 33 | private Integer views;//浏览次数 34 | private String password;//密码保护 35 | 36 | private User user;//文章作者(因为是个人博客,也可以不加作者字段,暂且加上) 37 | private Category category;//文章分类 38 | private List tags = new ArrayList<>();//文章标签 39 | } 40 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Category.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * @Description: 博客分类 13 | * @Date: 2020-07-26 14 | */ 15 | @NoArgsConstructor 16 | @Getter 17 | @Setter 18 | @ToString 19 | public class Category { 20 | private Long id; 21 | private String name;//分类名称 22 | private List blogs = new ArrayList<>();//该分类下的博客文章 23 | } 24 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/CityVisitor.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | /** 10 | * @Description: 城市访客数量 11 | * @Date: 2021-02-26 12 | */ 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class CityVisitor { 19 | private String city;//城市名称 20 | private Integer uv;//独立访客数量 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Comment.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import com.rawchen.model.vo.BlogIdAndTitle; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | /** 14 | * @Description: 博客评论 15 | * @Date: 2020-07-27 16 | */ 17 | @NoArgsConstructor 18 | @Getter 19 | @Setter 20 | @ToString 21 | public class Comment { 22 | private Long id; 23 | private String nickname;//昵称 24 | private String email;//邮箱 25 | private String content;//评论内容 26 | private String avatar;//头像(图片路径) 27 | private Date createTime;//评论时间 28 | private String website;//个人网站 29 | private String ip;//评论者ip地址 30 | private Boolean published;//公开或回收站 31 | private Boolean adminComment;//博主回复 32 | private Integer page;//0普通文章,1关于我页面 33 | private Boolean notice;//接收邮件提醒 34 | private Long parentCommentId;//父评论id 35 | private String qq;//如果评论昵称为QQ号,则将昵称和头像置为QQ昵称和QQ头像,并将此字段置为QQ号备份 36 | 37 | private BlogIdAndTitle blog;//所属的文章 38 | private List replyComments = new ArrayList<>();//回复该评论的评论 39 | } 40 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/ExceptionLog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 异常日志 12 | * @Date: 2020-12-03 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class ExceptionLog { 19 | private Long id; 20 | private String uri;//请求接口 21 | private String method;//请求方式 22 | private String param;//请求参数 23 | private String description;//操作描述 24 | private String error;//异常信息 25 | private String ip;//ip 26 | private String ipSource;//ip来源 27 | private String os;//操作系统 28 | private String browser;//浏览器 29 | private Date createTime;//操作时间 30 | private String userAgent; 31 | 32 | public ExceptionLog(String uri, String method, String description, String error, String ip, String userAgent) { 33 | this.uri = uri; 34 | this.method = method; 35 | this.description = description; 36 | this.error = error; 37 | this.ip = ip; 38 | this.createTime = new Date(); 39 | this.userAgent = userAgent; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Friend.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 友链 12 | * @Date: 2020-09-08 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class Friend { 19 | private Long id; 20 | private String nickname;//昵称 21 | private String description;//描述 22 | private String website;//站点 23 | private String avatar;//头像 24 | private Boolean published;//公开或隐藏 25 | private Integer views;//浏览次数 26 | private Date createTime;//创建时间 27 | } 28 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/LoginLog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 登录日志 12 | * @Date: 2020-12-03 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class LoginLog { 19 | private Long id; 20 | private String username;//用户名称 21 | private String ip;//ip 22 | private String ipSource;//ip来源 23 | private String os;//操作系统 24 | private String browser;//浏览器 25 | private Boolean status;//登录状态 26 | private String description;//操作信息 27 | private Date createTime;//操作时间 28 | private String userAgent; 29 | 30 | public LoginLog(String username, String ip, boolean status, String description, String userAgent) { 31 | this.username = username; 32 | this.ip = ip; 33 | this.status = status; 34 | this.description = description; 35 | this.createTime = new Date(); 36 | this.userAgent = userAgent; 37 | } 38 | } -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Moment.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 博客动态 12 | * @Date: 2020-08-24 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class Moment { 19 | private Long id; 20 | private String content;//动态内容 21 | private Date createTime;//创建时间 22 | private Integer likes;//点赞数量 23 | private Boolean published;//是否公开 24 | } 25 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/OperationLog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 操作日志 12 | * @Date: 2020-11-30 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class OperationLog { 19 | private Long id; 20 | private String username;//操作者用户名 21 | private String uri;//请求接口 22 | private String method;//请求方式 23 | private String param;//请求参数 24 | private String description;//操作描述 25 | private String ip;//ip 26 | private String ipSource;//ip来源 27 | private String os;//操作系统 28 | private String browser;//浏览器 29 | private Integer times;//请求耗时(毫秒) 30 | private Date createTime;//操作时间 31 | private String userAgent; 32 | 33 | public OperationLog(String username, String uri, String method, String description, String ip, Integer times, String userAgent) { 34 | this.username = username; 35 | this.uri = uri; 36 | this.method = method; 37 | this.description = description; 38 | this.ip = ip; 39 | this.times = times; 40 | this.createTime = new Date(); 41 | this.userAgent = userAgent; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/ScheduleJob.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 定时任务 12 | * @Date: 2020-11-01 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class ScheduleJob { 19 | public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY"; //任务调度参数key 20 | 21 | private Long jobId;//任务id 22 | private String beanName;//spring bean名称 23 | private String methodName;//方法名 24 | private String params;//参数 25 | private String cron;//cron表达式 26 | private Boolean status;//任务状态 27 | private String remark;//备注 28 | private Date createTime;//创建时间 29 | } 30 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/ScheduleJobLog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 定时任务日志 12 | * @Date: 2020-11-01 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class ScheduleJobLog { 19 | private Long logId;//日志id 20 | private Long jobId;//任务id 21 | private String beanName;//spring bean名称 22 | private String methodName;//方法名 23 | private String params;//参数 24 | private Boolean status;//任务执行结果 25 | private String error;//异常信息 26 | private Integer times;//耗时(单位:毫秒) 27 | private Date createTime;//创建时间 28 | } 29 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/SiteSetting.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 站点设置 10 | * @Date: 2020-08-09 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class SiteSetting { 17 | private Long id; 18 | private String nameEn; 19 | private String nameZh; 20 | private String value; 21 | private Integer type; 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Tag.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * @Description: 博客标签 13 | * @Date: 2020-07-27 14 | */ 15 | @NoArgsConstructor 16 | @Getter 17 | @Setter 18 | @ToString 19 | public class Tag { 20 | private Long id; 21 | private String name;//标签名称 22 | private String color;//标签颜色(与Semantic UI提供的颜色对应,可选) 23 | private List blogs = new ArrayList<>();//该标签下的博客文章 24 | } 25 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.Date; 15 | import java.util.List; 16 | 17 | /** 18 | * @Description: 用户实体类 19 | * @Date: 2020-07-19 20 | */ 21 | 22 | @NoArgsConstructor 23 | @Getter 24 | @Setter 25 | @ToString 26 | public class User implements UserDetails { 27 | private Long id; 28 | private String username; 29 | private String password; 30 | private String nickname; 31 | private String avatar; 32 | private String email; 33 | private Date createTime; 34 | private Date updateTime; 35 | private String role; 36 | 37 | @JsonIgnore 38 | @Override 39 | public Collection getAuthorities() { 40 | List authorityList = new ArrayList<>(); 41 | authorityList.add(new SimpleGrantedAuthority(role)); 42 | return authorityList; 43 | } 44 | 45 | @JsonIgnore 46 | @Override 47 | public boolean isAccountNonExpired() { 48 | return true; 49 | } 50 | 51 | @JsonIgnore 52 | @Override 53 | public boolean isAccountNonLocked() { 54 | return true; 55 | } 56 | 57 | @JsonIgnore 58 | @Override 59 | public boolean isCredentialsNonExpired() { 60 | return true; 61 | } 62 | 63 | @JsonIgnore 64 | @Override 65 | public boolean isEnabled() { 66 | return true; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/VisitLog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 访问日志 12 | * @Date: 2020-12-04 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class VisitLog { 19 | private Long id; 20 | private String uuid;//访客标识码 21 | private String uri;//请求接口 22 | private String method;//请求方式 23 | private String param;//请求参数 24 | private String behavior;//访问行为 25 | private String content;//访问内容 26 | private String remark;//备注 27 | private String ip;//ip 28 | private String ipSource;//ip来源 29 | private String os;//操作系统 30 | private String browser;//浏览器 31 | private Integer times;//请求耗时(毫秒) 32 | private Date createTime;//访问时间 33 | private String userAgent; 34 | 35 | public VisitLog(String uuid, String uri, String method, String behavior, String content, String remark, String ip, Integer times, String userAgent) { 36 | this.uuid = uuid; 37 | this.uri = uri; 38 | this.method = method; 39 | this.behavior = behavior; 40 | this.content = content; 41 | this.remark = remark; 42 | this.ip = ip; 43 | this.times = times; 44 | this.createTime = new Date(); 45 | this.userAgent = userAgent; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/VisitRecord.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 访问记录 10 | * @Date: 2021-02-23 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class VisitRecord { 17 | private Long id; 18 | private Integer pv;//访问量 19 | private Integer uv;//独立用户 20 | private String date;//日期"02-23" 21 | 22 | public VisitRecord(Integer pv, Integer uv, String date) { 23 | this.pv = pv; 24 | this.uv = uv; 25 | this.date = date; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/entity/Visitor.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 访客记录 12 | * @Date: 2021-01-31 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class Visitor { 19 | private Long id; 20 | private String uuid;//访客标识码 21 | private String ip;//ip 22 | private String ipSource;//ip来源 23 | private String os;//操作系统 24 | private String browser;//浏览器 25 | private Date createTime;//首次访问时间 26 | private Date lastTime;//最后访问时间 27 | private Integer pv;//访问页数统计 28 | private String userAgent; 29 | 30 | public Visitor(String uuid, String ip, String userAgent) { 31 | this.uuid = uuid; 32 | this.ip = ip; 33 | Date date = new Date(); 34 | this.createTime = date; 35 | this.lastTime = date; 36 | this.pv = 0; 37 | this.userAgent = userAgent; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/exception/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.exception; 2 | 3 | /** 4 | * @Description: 非法请求异常 5 | * @Date: 2020-07-23 6 | */ 7 | 8 | public class BadRequestException extends RuntimeException { 9 | public BadRequestException() { 10 | } 11 | 12 | public BadRequestException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadRequestException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/exception/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.exception; 2 | 3 | /** 4 | * @Description: 404异常 5 | * @Date: 2020-08-14 6 | */ 7 | 8 | public class NotFoundException extends RuntimeException { 9 | public NotFoundException() { 10 | } 11 | 12 | public NotFoundException(String message) { 13 | super(message); 14 | } 15 | 16 | public NotFoundException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/exception/PersistenceException.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.exception; 2 | 3 | /** 4 | * @Description: 持久化异常 5 | * @Date: 2020-08-14 6 | */ 7 | 8 | public class PersistenceException extends RuntimeException { 9 | public PersistenceException() { 10 | } 11 | 12 | public PersistenceException(String message) { 13 | super(message); 14 | } 15 | 16 | public PersistenceException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/AboutMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.About; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 关于我持久层接口 11 | * @Date: 2020-08-31 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface AboutMapper { 16 | List getList(); 17 | 18 | int updateAbout(String nameEn, String value); 19 | 20 | String getAboutCommentEnabled(); 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.Category; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 博客分类持久层接口 11 | * @Date: 2020-07-29 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface CategoryMapper { 16 | List getCategoryList(); 17 | 18 | List getCategoryNameList(); 19 | 20 | int saveCategory(Category category); 21 | 22 | Category getCategoryById(Long id); 23 | 24 | Category getCategoryByName(String name); 25 | 26 | int deleteCategoryById(Long id); 27 | 28 | int updateCategory(Category category); 29 | } 30 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/CityVisitorMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.CityVisitor; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 城市访客数量统计持久层接口 11 | * @Date: 2021-02-26 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface CityVisitorMapper { 16 | List getCityVisitorList(); 17 | 18 | int saveCityVisitor(CityVisitor cityVisitor); 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/CommentMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.Comment; 4 | import com.rawchen.model.vo.PageComment; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Description: 博客评论持久层接口 12 | * @Date: 2020-08-03 13 | */ 14 | @Mapper 15 | @Repository 16 | public interface CommentMapper { 17 | List getListByPageAndParentCommentId(Integer page, Long blogId, Long parentCommentId); 18 | 19 | List getListByParentCommentId(Long parentCommentId); 20 | 21 | List getPageCommentListByPageAndParentCommentId(Integer page, Long blogId, Long parentCommentId); 22 | 23 | Comment getCommentById(Long id); 24 | 25 | int updateCommentPublishedById(Long commentId, Boolean published); 26 | 27 | int updateCommentNoticeById(Long commentId, Boolean notice); 28 | 29 | int deleteCommentById(Long commentId); 30 | 31 | int deleteCommentsByBlogId(Long blogId); 32 | 33 | int updateComment(Comment comment); 34 | 35 | int countByPageAndIsPublished(Integer page, Long blogId); 36 | 37 | int countComment(); 38 | 39 | int saveComment(com.rawchen.model.dto.Comment comment); 40 | } 41 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/ExceptionLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.ExceptionLog; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 异常日志持久层接口 11 | * @Date: 2020-12-03 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface ExceptionLogMapper { 16 | List getExceptionLogListByDate(String startDate, String endDate); 17 | 18 | int saveExceptionLog(ExceptionLog log); 19 | 20 | int deleteExceptionLogById(Long id); 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/FriendMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.Friend; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 友链持久层接口 11 | * @Date: 2020-09-08 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface FriendMapper { 16 | List getFriendList(); 17 | 18 | List getFriendVOList(); 19 | 20 | int updateFriendPublishedById(Long id, Boolean published); 21 | 22 | int saveFriend(Friend friend); 23 | 24 | int updateFriend(com.rawchen.model.dto.Friend friend); 25 | 26 | int deleteFriend(Long id); 27 | 28 | int updateViewsByNickname(String nickname); 29 | } 30 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/LoginLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.LoginLog; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 登录日志持久层接口 11 | * @Date: 2020-12-03 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface LoginLogMapper { 16 | List getLoginLogListByDate(String startDate, String endDate); 17 | 18 | int saveLoginLog(LoginLog log); 19 | 20 | int deleteLoginLogById(Long id); 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/MomentMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.Moment; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 博客动态持久层接口 11 | * @Date: 2020-08-24 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface MomentMapper { 16 | List getMomentList(); 17 | 18 | int addLikeByMomentId(Long momentId); 19 | 20 | int updateMomentPublishedById(Long momentId, Boolean published); 21 | 22 | Moment getMomentById(Long id); 23 | 24 | int deleteMomentById(Long id); 25 | 26 | int saveMoment(Moment moment); 27 | 28 | int updateMoment(Moment moment); 29 | } 30 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/OperationLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.OperationLog; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 操作日志持久层接口 11 | * @Date: 2020-11-30 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface OperationLogMapper { 16 | List getOperationLogListByDate(String startDate, String endDate); 17 | 18 | int saveOperationLog(OperationLog log); 19 | 20 | int deleteOperationLogById(Long id); 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/ScheduleJobLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.ScheduleJobLog; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 定时任务日志持久层接口 11 | * @Date: 2020-11-01 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface ScheduleJobLogMapper { 16 | List getJobLogListByDate(String startDate, String endDate); 17 | 18 | int saveJobLog(ScheduleJobLog jobLog); 19 | 20 | int deleteJobLogByLogId(Long logId); 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/ScheduleJobMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.ScheduleJob; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 定时任务持久层接口 11 | * @Date: 2020-11-01 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface ScheduleJobMapper { 16 | List getJobList(); 17 | 18 | ScheduleJob getJobById(Long jobId); 19 | 20 | int saveJob(ScheduleJob scheduleJob); 21 | 22 | int updateJob(ScheduleJob scheduleJob); 23 | 24 | int deleteJobById(Long jobId); 25 | 26 | int updateJobStatusById(Long jobId, Boolean status); 27 | } 28 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/SiteSettingMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import org.apache.ibatis.annotations.Mapper; 4 | import org.springframework.stereotype.Repository; 5 | import com.rawchen.entity.SiteSetting; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 站点设置持久层接口 11 | * @Date: 2020-08-03 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface SiteSettingMapper { 16 | List getList(); 17 | 18 | List getFriendInfo(); 19 | 20 | String getWebTitleSuffix(); 21 | 22 | int updateSiteSetting(SiteSetting siteSetting); 23 | 24 | int deleteSiteSettingById(Integer id); 25 | 26 | int saveSiteSetting(SiteSetting siteSetting); 27 | 28 | int updateFriendInfoContent(String content); 29 | 30 | int updateFriendInfoCommentEnabled(Boolean commentEnabled); 31 | } 32 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/TagMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.Tag; 4 | import com.rawchen.model.vo.TagBlogCount; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Description: 博客标签持久层接口 12 | * @Date: 2020-07-30 13 | */ 14 | @Mapper 15 | @Repository 16 | public interface TagMapper { 17 | List getTagList(); 18 | 19 | List getTagListNotId(); 20 | 21 | List getTagListByBlogId(Long blogId); 22 | 23 | int saveTag(Tag tag); 24 | 25 | Tag getTagById(Long id); 26 | 27 | Tag getTagByName(String name); 28 | 29 | int deleteTagById(Long id); 30 | 31 | int updateTag(Tag tag); 32 | 33 | List getTagBlogCount(); 34 | } 35 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.User; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * @Description: 用户持久层接口 9 | * @Date: 2020-07-19 10 | */ 11 | @Mapper 12 | @Repository 13 | public interface UserMapper { 14 | User findByUsername(String username); 15 | } 16 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/VisitLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.VisitLog; 4 | import com.rawchen.model.dto.VisitLogUuidTime; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Description: 访问日志持久层接口 12 | * @Date: 2020-12-04 13 | */ 14 | @Mapper 15 | @Repository 16 | public interface VisitLogMapper { 17 | List getVisitLogListByUUIDAndDate(String uuid, String startDate, String endDate); 18 | 19 | List getUUIDAndCreateTimeByYesterday(); 20 | 21 | int saveVisitLog(VisitLog log); 22 | 23 | int deleteVisitLogById(Long id); 24 | 25 | int countVisitLogByToday(); 26 | } 27 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/VisitRecordMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.VisitRecord; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Description: 访问记录持久层接口 11 | * @Date: 2021-02-23 12 | */ 13 | @Mapper 14 | @Repository 15 | public interface VisitRecordMapper { 16 | List getVisitRecordListByLimit(Integer limit); 17 | 18 | int saveVisitRecord(VisitRecord visitRecord); 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/mapper/VisitorMapper.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.mapper; 2 | 3 | import com.rawchen.entity.Visitor; 4 | import com.rawchen.model.dto.VisitLogUuidTime; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Description: 访客统计持久层接口 12 | * @Date: 2021-01-31 13 | */ 14 | @Mapper 15 | @Repository 16 | public interface VisitorMapper { 17 | List getVisitorListByDate(String startDate, String endDate); 18 | 19 | List getNewVisitorIpSourceByYesterday(); 20 | 21 | int hasUUID(String uuid); 22 | 23 | int saveVisitor(Visitor visitor); 24 | 25 | int updatePVAndLastTimeByUUID(VisitLogUuidTime dto); 26 | 27 | int deleteVisitorById(Long id); 28 | } 29 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/bean/Badge.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: GitHub徽标 10 | * @Date: 2020-08-09 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class Badge { 17 | private String title; 18 | private String url; 19 | private String subject; 20 | private String value; 21 | private String color; 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/bean/Copyright.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: copyright 10 | * @Date: 2020-08-09 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class Copyright { 17 | private String title; 18 | private String siteName; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/bean/Favorite.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 自定义爱好 10 | * @Date: 2020-08-09 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class Favorite { 17 | private String title; 18 | private String content; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/Blog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import com.rawchen.entity.Category; 8 | import com.rawchen.entity.Tag; 9 | import com.rawchen.entity.User; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Date; 13 | import java.util.List; 14 | 15 | /** 16 | * @Description: 博客DTO 17 | * @Date: 2020-08-27 18 | */ 19 | @NoArgsConstructor 20 | @Getter 21 | @Setter 22 | @ToString 23 | public class Blog { 24 | private Long id; 25 | private String title;//文章标题 26 | private String firstPicture;//文章首图,用于随机文章展示 27 | private String content;//文章正文 28 | private String description;//描述 29 | private Boolean published;//公开或私密 30 | private Boolean recommend;//推荐开关 31 | private Boolean appreciation;//赞赏开关 32 | private Boolean commentEnabled;//评论开关 33 | private Boolean top;//是否置顶 34 | private Date createTime;//创建时间 35 | private Date updateTime;//更新时间 36 | private Integer views;//浏览次数 37 | private String password;//密码保护 38 | 39 | private User user;//文章作者(因为是个人博客,也可以不加作者字段,暂且加上) 40 | private Category category;//文章分类 41 | private List tags = new ArrayList<>();//文章标签 42 | 43 | private Object cate;//页面展示层传输的分类对象:正常情况下为 字符串 或 分类id 44 | private List tagList;//页面展示层传输的标签对象:正常情况下为 List标签id 或 List标签名 45 | } 46 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/BlogPassword.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 受保护文章密码DTO 10 | * @Date: 2020-09-05 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class BlogPassword { 17 | private Long blogId; 18 | private String password; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/BlogView.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 博客浏览量 10 | * @Date: 2020-10-06 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class BlogView { 17 | private Long id; 18 | private Integer views; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/BlogVisibility.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 博客可见性DTO 10 | * @Date: 2020-09-04 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class BlogVisibility { 17 | private Boolean appreciation;//赞赏开关 18 | private Boolean recommend;//推荐开关 19 | private Boolean commentEnabled;//评论开关 20 | private Boolean top;//是否置顶 21 | private Boolean published;//公开或私密 22 | private String password;//密码保护 23 | } 24 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/Comment.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 评论DTO 12 | * @Date: 2020-08-27 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class Comment { 19 | private Long id; 20 | private String nickname;//昵称 21 | private String email;//邮箱 22 | private String content;//评论内容 23 | private String avatar;//头像(图片路径) 24 | private Date createTime;//评论时间 25 | private String website;//个人网站 26 | private String ip;//评论者ip地址 27 | private Boolean published;//公开或回收站 28 | private Boolean adminComment;//博主回复 29 | private Integer page;//0普通文章,1关于我页面 30 | private Boolean notice;//接收邮件提醒 31 | private Long parentCommentId;//父评论id 32 | private Long blogId;//所属的文章id 33 | private String qq;//如果评论昵称为QQ号,则将昵称和头像置为QQ昵称和QQ头像,并将此字段置为QQ号备份 34 | } 35 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/Friend.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 友链DTO 10 | * @Date: 2020-09-08 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class Friend { 17 | private Long id; 18 | private String nickname;//昵称 19 | private String description;//描述 20 | private String website;//站点 21 | private String avatar;//头像 22 | private Boolean published;//公开或隐藏 23 | } 24 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/LoginInfo.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 登录账号密码 10 | * @Date: 2020-09-02 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class LoginInfo { 17 | private String username; 18 | private String password; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/dto/VisitLogUuidTime.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * @Description: 访客更新DTO 13 | * @Date: 2021-02-05 14 | */ 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Getter 18 | @Setter 19 | @ToString 20 | public class VisitLogUuidTime { 21 | private String uuid; 22 | private Date time; 23 | private Integer pv; 24 | } 25 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/ArchiveBlog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 归档页面博客简要信息 10 | * @Date: 2020-08-12 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class ArchiveBlog { 17 | private Long id; 18 | private String title; 19 | private String day; 20 | private String password; 21 | private Boolean privacy; 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/BlogDetail.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import com.rawchen.entity.Category; 8 | import com.rawchen.entity.Tag; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * @Description: 博客详情 16 | * @Date: 2020-08-12 17 | */ 18 | @NoArgsConstructor 19 | @Getter 20 | @Setter 21 | @ToString 22 | public class BlogDetail { 23 | private Long id; 24 | private String title;//文章标题 25 | private String content;//文章正文 26 | private Boolean appreciation;//赞赏开关 27 | private Boolean commentEnabled;//评论开关 28 | private Boolean top;//是否置顶 29 | private Date createTime;//创建时间 30 | private Date updateTime;//更新时间 31 | private Integer views;//浏览次数 32 | private String password;//密码保护 33 | 34 | private Category category;//文章分类 35 | private List tags = new ArrayList<>();//文章标签 36 | } 37 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/BlogIdAndTitle.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 评论管理页面按博客title查询评论 10 | * @Date: 2020-08-03 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class BlogIdAndTitle { 17 | private Long id; 18 | private String title; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/BlogInfo.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.*; 4 | import com.rawchen.entity.Category; 5 | import com.rawchen.entity.Tag; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | /** 12 | * @Description: 博客简要信息 13 | * @Date: 2020-08-08 14 | */ 15 | @NoArgsConstructor 16 | @Getter 17 | @Setter 18 | @ToString 19 | public class BlogInfo { 20 | private Long id; 21 | private String title;//文章标题 22 | private String description;//描述 23 | private Date createTime;//创建时间 24 | private Integer views;//浏览次数 25 | private Boolean top;//是否置顶 26 | private String password;//文章密码 27 | private Boolean privacy;//是否私密文章 28 | private String firstPicture;//首图 29 | 30 | private Category category;//文章分类 31 | private List tags = new ArrayList<>();//文章标签 32 | } 33 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/CategoryBlogCount.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 分类和博客数量 10 | * @Date: 2020-10-08 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class CategoryBlogCount { 17 | private Long id; 18 | private String name;//分类名 19 | private Integer value;//分类下博客数量 20 | } 21 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/Friend.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 友链VO 10 | * @Date: 2020-09-08 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class Friend { 17 | private String nickname;//昵称 18 | private String description;//描述 19 | private String website;//站点 20 | private String avatar;//头像 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/FriendInfo.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 友链页面信息 10 | * @Date: 2020-09-09 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class FriendInfo { 17 | private String content; 18 | private Boolean commentEnabled; 19 | } 20 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/Introduction.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import com.rawchen.model.bean.Favorite; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * @Description: 侧边栏资料卡 14 | * @Date: 2020-08-09 15 | */ 16 | @NoArgsConstructor 17 | @Getter 18 | @Setter 19 | @ToString 20 | public class Introduction { 21 | private String avatar; 22 | private String name; 23 | private String github; 24 | private String qq; 25 | private String bilibili; 26 | private String netease; 27 | private String email; 28 | 29 | private List rollText = new ArrayList<>(); 30 | private List favorites = new ArrayList<>(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/NewBlog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 最新推荐博客 10 | * @Date: 2020-09-05 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class NewBlog { 17 | private Long id; 18 | private String title; 19 | private String password; 20 | private Boolean privacy; 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/PageComment.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | /** 13 | * @Description: 页面评论 14 | * @Date: 2020-08-15 15 | */ 16 | @NoArgsConstructor 17 | @Getter 18 | @Setter 19 | @ToString 20 | public class PageComment { 21 | private Long id; 22 | private String nickname;//昵称 23 | private String content;//评论内容 24 | private String avatar;//头像(图片路径) 25 | private Date createTime;//评论时间 26 | private String website;//个人网站 27 | private Boolean adminComment;//博主回复 28 | private String parentCommentId;//父评论id 29 | private String parentCommentNickname;//父评论昵称 30 | 31 | private List replyComments = new ArrayList<>();//回复该评论的评论 32 | } 33 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/PageResult.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Description: 分页结果 12 | * @Date: 2020-08-08 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class PageResult { 19 | private Integer totalPage;//总页数 20 | private List list;//数据 21 | 22 | public PageResult(Integer totalPage, List list) { 23 | this.totalPage = totalPage; 24 | this.list = list; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/RandomBlog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @Description: 随机博客 12 | * @Date: 2020-08-17 13 | */ 14 | @NoArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class RandomBlog { 19 | private Long id; 20 | private String title;//文章标题 21 | private String firstPicture;//文章首图,用于随机文章展示 22 | private Date createTime;//创建时间 23 | private String password;//文章密码 24 | private Boolean privacy;//是否私密文章 25 | } 26 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/Result.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 封装响应结果 10 | * @Date: 2020-07-19 11 | */ 12 | 13 | @NoArgsConstructor 14 | @Getter 15 | @Setter 16 | @ToString 17 | public class Result { 18 | private Integer code; 19 | private String msg; 20 | private Object data; 21 | 22 | private Result(Integer code, String msg) { 23 | this.code = code; 24 | this.msg = msg; 25 | this.data = null; 26 | } 27 | 28 | private Result(Integer code, String msg, Object data) { 29 | this.code = code; 30 | this.msg = msg; 31 | this.data = data; 32 | } 33 | 34 | public static Result ok(String msg, Object data) { 35 | return new Result(200, msg, data); 36 | } 37 | 38 | public static Result ok(String msg) { 39 | return new Result(200, msg); 40 | } 41 | 42 | public static Result error(String msg) { 43 | return new Result(500, msg); 44 | } 45 | 46 | public static Result error() { 47 | return new Result(500, "异常错误"); 48 | } 49 | 50 | public static Result create(Integer code, String msg, Object data) { 51 | return new Result(code, msg, data); 52 | } 53 | 54 | public static Result create(Integer code, String msg) { 55 | return new Result(code, msg); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/SearchBlog.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 关键字搜索博客 10 | * @Date: 2020-09-06 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class SearchBlog { 17 | private Long id; 18 | private String title; 19 | private String content; 20 | } 21 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/model/vo/TagBlogCount.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.model.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | /** 9 | * @Description: 标签和博客数量 10 | * @Date: 2020-10-08 11 | */ 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class TagBlogCount { 17 | private Long id; 18 | private String name;//标签名 19 | private Integer value;//标签下博客数量 20 | } 21 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/AboutService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import java.util.Map; 4 | 5 | public interface AboutService { 6 | Map getAboutInfo(); 7 | 8 | Map getAboutSetting(); 9 | 10 | void updateAbout(Map map); 11 | 12 | boolean getAboutCommentEnabled(); 13 | } 14 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.Category; 4 | 5 | import java.util.List; 6 | 7 | public interface CategoryService { 8 | List getCategoryList(); 9 | 10 | List getCategoryNameList(); 11 | 12 | void saveCategory(Category category); 13 | 14 | Category getCategoryById(Long id); 15 | 16 | Category getCategoryByName(String name); 17 | 18 | void deleteCategoryById(Long id); 19 | 20 | void updateCategory(Category category); 21 | } 22 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/CityVisitorService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.CityVisitor; 4 | 5 | public interface CityVisitorService { 6 | void saveCityVisitor(CityVisitor cityVisitor); 7 | } 8 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.Comment; 4 | import com.rawchen.model.vo.PageComment; 5 | 6 | import java.util.List; 7 | 8 | public interface CommentService { 9 | List getListByPageAndParentCommentId(Integer page, Long blogId, Long parentCommentId); 10 | 11 | List getPageCommentList(Integer page, Long blogId, Long parentCommentId); 12 | 13 | Comment getCommentById(Long id); 14 | 15 | void updateCommentPublishedById(Long commentId, Boolean published); 16 | 17 | void updateCommentNoticeById(Long commentId, Boolean notice); 18 | 19 | void deleteCommentById(Long commentId); 20 | 21 | void deleteCommentsByBlogId(Long blogId); 22 | 23 | void updateComment(Comment comment); 24 | 25 | int countByPageAndIsPublished(Integer page, Long blogId); 26 | 27 | void saveComment(com.rawchen.model.dto.Comment comment); 28 | } 29 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/DashboardService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.CityVisitor; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public interface DashboardService { 9 | int countVisitLogByToday(); 10 | 11 | int getBlogCount(); 12 | 13 | int getCommentCount(); 14 | 15 | Map getCategoryBlogCountMap(); 16 | 17 | Map getTagBlogCountMap(); 18 | 19 | Map getVisitRecordMap(); 20 | 21 | List getCityVisitorList(); 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/ExceptionLogService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.ExceptionLog; 4 | import org.springframework.scheduling.annotation.Async; 5 | 6 | import java.util.List; 7 | 8 | public interface ExceptionLogService { 9 | List getExceptionLogListByDate(String startDate, String endDate); 10 | 11 | @Async 12 | void saveExceptionLog(ExceptionLog log); 13 | 14 | void deleteExceptionLogById(Long id); 15 | } 16 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/FriendService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.Friend; 4 | import com.rawchen.model.vo.FriendInfo; 5 | 6 | import java.util.List; 7 | 8 | public interface FriendService { 9 | List getFriendList(); 10 | 11 | List getFriendVOList(); 12 | 13 | void updateFriendPublishedById(Long friendId, Boolean published); 14 | 15 | void saveFriend(Friend friend); 16 | 17 | void updateFriend(com.rawchen.model.dto.Friend friend); 18 | 19 | void deleteFriend(Long id); 20 | 21 | void updateViewsByNickname(String nickname); 22 | 23 | FriendInfo getFriendInfo(boolean cache, boolean md); 24 | 25 | void updateFriendInfoContent(String content); 26 | 27 | void updateFriendInfoCommentEnabled(Boolean commentEnabled); 28 | } 29 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/LoginLogService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.LoginLog; 4 | import org.springframework.scheduling.annotation.Async; 5 | 6 | import java.util.List; 7 | 8 | public interface LoginLogService { 9 | List getLoginLogListByDate(String startDate, String endDate); 10 | 11 | @Async 12 | void saveLoginLog(LoginLog log); 13 | 14 | void deleteLoginLogById(Long id); 15 | } 16 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/MomentService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.Moment; 4 | 5 | import java.util.List; 6 | 7 | public interface MomentService { 8 | List getMomentList(); 9 | 10 | List getMomentVOList(Integer pageNum, boolean adminIdentity); 11 | 12 | void addLikeByMomentId(Long momentId); 13 | 14 | void updateMomentPublishedById(Long momentId, Boolean published); 15 | 16 | Moment getMomentById(Long id); 17 | 18 | void deleteMomentById(Long id); 19 | 20 | void saveMoment(Moment moment); 21 | 22 | void updateMoment(Moment moment); 23 | } 24 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/OperationLogService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.OperationLog; 4 | import org.springframework.scheduling.annotation.Async; 5 | 6 | import java.util.List; 7 | 8 | public interface OperationLogService { 9 | List getOperationLogListByDate(String startDate, String endDate); 10 | 11 | @Async 12 | void saveOperationLog(OperationLog log); 13 | 14 | void deleteOperationLogById(Long id); 15 | } 16 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/ScheduleJobService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.ScheduleJob; 4 | import com.rawchen.entity.ScheduleJobLog; 5 | 6 | import java.util.List; 7 | 8 | public interface ScheduleJobService { 9 | List getJobList(); 10 | 11 | void saveJob(ScheduleJob scheduleJob); 12 | 13 | void updateJob(ScheduleJob scheduleJob); 14 | 15 | void deleteJobById(Long jobId); 16 | 17 | void runJobById(Long jobId); 18 | 19 | void updateJobStatusById(Long jobId, Boolean status); 20 | 21 | List getJobLogListByDate(String startDate, String endDate); 22 | 23 | void saveJobLog(ScheduleJobLog log); 24 | 25 | void deleteJobLogByLogId(Long logId); 26 | } 27 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/SiteSettingService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.SiteSetting; 4 | 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public interface SiteSettingService { 10 | Map> getList(); 11 | 12 | Map getSiteInfo(); 13 | 14 | String getWebTitleSuffix(); 15 | 16 | void updateSiteSetting(List siteSettings, List deleteIds); 17 | } 18 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/TagService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.Tag; 4 | 5 | import java.util.List; 6 | 7 | public interface TagService { 8 | List getTagList(); 9 | 10 | List getTagListNotId(); 11 | 12 | List getTagListByBlogId(Long blogId); 13 | 14 | void saveTag(Tag tag); 15 | 16 | Tag getTagById(Long id); 17 | 18 | Tag getTagByName(String name); 19 | 20 | void deleteTagById(Long id); 21 | 22 | void updateTag(Tag tag); 23 | } 24 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.User; 4 | 5 | public interface UserService { 6 | User findUserByUsernameAndPassword(String username, String password); 7 | } 8 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/VisitLogService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.VisitLog; 4 | import com.rawchen.model.dto.VisitLogUuidTime; 5 | import org.springframework.scheduling.annotation.Async; 6 | 7 | import java.util.List; 8 | 9 | public interface VisitLogService { 10 | List getVisitLogListByUUIDAndDate(String uuid, String startDate, String endDate); 11 | 12 | List getUUIDAndCreateTimeByYesterday(); 13 | 14 | @Async 15 | void saveVisitLog(VisitLog log); 16 | 17 | void deleteVisitLogById(Long id); 18 | } 19 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/VisitRecordService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.VisitRecord; 4 | 5 | public interface VisitRecordService { 6 | void saveVisitRecord(VisitRecord visitRecord); 7 | } 8 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/VisitorService.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service; 2 | 3 | import com.rawchen.entity.Visitor; 4 | import com.rawchen.model.dto.VisitLogUuidTime; 5 | import org.springframework.scheduling.annotation.Async; 6 | 7 | import java.util.List; 8 | 9 | public interface VisitorService { 10 | List getVisitorListByDate(String startDate, String endDate); 11 | 12 | List getNewVisitorIpSourceByYesterday(); 13 | 14 | boolean hasUUID(String uuid); 15 | 16 | @Async 17 | void saveVisitor(Visitor visitor); 18 | 19 | void updatePVAndLastTimeByUUID(VisitLogUuidTime dto); 20 | 21 | void deleteVisitor(Long id, String uuid); 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/CityVisitorServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.CityVisitor; 4 | import com.rawchen.mapper.CityVisitorMapper; 5 | import com.rawchen.service.CityVisitorService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @Description: 城市访客数量统计业务层实现 11 | * @Date: 2021-02-26 12 | */ 13 | @Service 14 | public class CityVisitorServiceImpl implements CityVisitorService { 15 | @Autowired 16 | CityVisitorMapper cityVisitorMapper; 17 | 18 | @Override 19 | public void saveCityVisitor(CityVisitor cityVisitor) { 20 | cityVisitorMapper.saveCityVisitor(cityVisitor); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/ExceptionLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.ExceptionLog; 4 | import com.rawchen.mapper.ExceptionLogMapper; 5 | import com.rawchen.service.ExceptionLogService; 6 | import com.rawchen.util.IpAddressUtils; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import com.rawchen.exception.PersistenceException; 11 | import com.rawchen.util.UserAgentUtils; 12 | 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * @Description: 异常日志业务层实现 18 | * @Date: 2020-12-03 19 | */ 20 | @Service 21 | public class ExceptionLogServiceImpl implements ExceptionLogService { 22 | @Autowired 23 | ExceptionLogMapper exceptionLogMapper; 24 | @Autowired 25 | UserAgentUtils userAgentUtils; 26 | 27 | @Override 28 | public List getExceptionLogListByDate(String startDate, String endDate) { 29 | return exceptionLogMapper.getExceptionLogListByDate(startDate, endDate); 30 | } 31 | 32 | @Transactional 33 | @Override 34 | public void saveExceptionLog(ExceptionLog log) { 35 | String ipSource = IpAddressUtils.getCityInfo(log.getIp()); 36 | Map userAgentMap = userAgentUtils.parseOsAndBrowser(log.getUserAgent()); 37 | String os = userAgentMap.get("os"); 38 | String browser = userAgentMap.get("browser"); 39 | log.setIpSource(ipSource); 40 | log.setOs(os); 41 | log.setBrowser(browser); 42 | if (exceptionLogMapper.saveExceptionLog(log) != 1) { 43 | throw new PersistenceException("日志添加失败"); 44 | } 45 | } 46 | 47 | @Transactional 48 | @Override 49 | public void deleteExceptionLogById(Long id) { 50 | if (exceptionLogMapper.deleteExceptionLogById(id) != 1) { 51 | throw new PersistenceException("删除日志失败"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/LoginLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.LoginLog; 4 | import com.rawchen.mapper.LoginLogMapper; 5 | import com.rawchen.service.LoginLogService; 6 | import com.rawchen.util.IpAddressUtils; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | import com.rawchen.exception.PersistenceException; 11 | import com.rawchen.util.UserAgentUtils; 12 | 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * @Description: 登录日志业务层实现 18 | * @Date: 2020-12-03 19 | */ 20 | @Service 21 | public class LoginLogServiceImpl implements LoginLogService { 22 | @Autowired 23 | LoginLogMapper loginLogMapper; 24 | @Autowired 25 | UserAgentUtils userAgentUtils; 26 | 27 | @Override 28 | public List getLoginLogListByDate(String startDate, String endDate) { 29 | return loginLogMapper.getLoginLogListByDate(startDate, endDate); 30 | } 31 | 32 | @Transactional 33 | @Override 34 | public void saveLoginLog(LoginLog log) { 35 | String ipSource = IpAddressUtils.getCityInfo(log.getIp()); 36 | Map userAgentMap = userAgentUtils.parseOsAndBrowser(log.getUserAgent()); 37 | String os = userAgentMap.get("os"); 38 | String browser = userAgentMap.get("browser"); 39 | log.setIpSource(ipSource); 40 | log.setOs(os); 41 | log.setBrowser(browser); 42 | if (loginLogMapper.saveLoginLog(log) != 1) { 43 | throw new PersistenceException("日志添加失败"); 44 | } 45 | } 46 | 47 | @Transactional 48 | @Override 49 | public void deleteLoginLogById(Long id) { 50 | if (loginLogMapper.deleteLoginLogById(id) != 1) { 51 | throw new PersistenceException("删除日志失败"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/OperationLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.OperationLog; 4 | import com.rawchen.exception.PersistenceException; 5 | import com.rawchen.mapper.OperationLogMapper; 6 | import com.rawchen.service.OperationLogService; 7 | import com.rawchen.util.IpAddressUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | import com.rawchen.util.UserAgentUtils; 12 | 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | /** 17 | * @Description: 操作日志业务层实现 18 | * @Date: 2020-11-30 19 | */ 20 | @Service 21 | public class OperationLogServiceImpl implements OperationLogService { 22 | @Autowired 23 | OperationLogMapper operationLogMapper; 24 | @Autowired 25 | UserAgentUtils userAgentUtils; 26 | 27 | @Override 28 | public List getOperationLogListByDate(String startDate, String endDate) { 29 | return operationLogMapper.getOperationLogListByDate(startDate, endDate); 30 | } 31 | 32 | @Transactional 33 | @Override 34 | public void saveOperationLog(OperationLog log) { 35 | String ipSource = IpAddressUtils.getCityInfo(log.getIp()); 36 | Map userAgentMap = userAgentUtils.parseOsAndBrowser(log.getUserAgent()); 37 | String os = userAgentMap.get("os"); 38 | String browser = userAgentMap.get("browser"); 39 | log.setIpSource(ipSource); 40 | log.setOs(os); 41 | log.setBrowser(browser); 42 | if (operationLogMapper.saveOperationLog(log) != 1) { 43 | throw new PersistenceException("日志添加失败"); 44 | } 45 | } 46 | 47 | @Transactional 48 | @Override 49 | public void deleteOperationLogById(Long id) { 50 | if (operationLogMapper.deleteOperationLogById(id) != 1) { 51 | throw new PersistenceException("删除日志失败"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.User; 4 | import com.rawchen.mapper.UserMapper; 5 | import com.rawchen.service.UserService; 6 | import com.rawchen.util.HashUtils; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | /** 14 | * @Description: 用户业务层接口实现类 15 | * @Date: 2020-07-19 16 | */ 17 | @Service 18 | public class UserServiceImpl implements UserService, UserDetailsService { 19 | @Autowired 20 | private UserMapper userMapper; 21 | 22 | @Override 23 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 24 | User user = userMapper.findByUsername(username); 25 | if (user == null) { 26 | throw new UsernameNotFoundException("用户不存在"); 27 | } 28 | return user; 29 | } 30 | 31 | @Override 32 | public User findUserByUsernameAndPassword(String username, String password) { 33 | User user = userMapper.findByUsername(username); 34 | if (user == null) { 35 | throw new UsernameNotFoundException("用户不存在"); 36 | } 37 | if (!HashUtils.matchBC(password, user.getPassword())) { 38 | throw new UsernameNotFoundException("密码错误"); 39 | } 40 | return user; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/VisitLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.VisitLog; 4 | import com.rawchen.exception.PersistenceException; 5 | import com.rawchen.mapper.VisitLogMapper; 6 | import com.rawchen.model.dto.VisitLogUuidTime; 7 | import com.rawchen.service.VisitLogService; 8 | import com.rawchen.util.IpAddressUtils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | import com.rawchen.util.UserAgentUtils; 13 | 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * @Description: 访问日志业务层实现 19 | * @Date: 2020-12-04 20 | */ 21 | @Service 22 | public class VisitLogServiceImpl implements VisitLogService { 23 | @Autowired 24 | VisitLogMapper visitLogMapper; 25 | @Autowired 26 | UserAgentUtils userAgentUtils; 27 | 28 | @Override 29 | public List getVisitLogListByUUIDAndDate(String uuid, String startDate, String endDate) { 30 | return visitLogMapper.getVisitLogListByUUIDAndDate(uuid, startDate, endDate); 31 | } 32 | 33 | @Override 34 | public List getUUIDAndCreateTimeByYesterday() { 35 | return visitLogMapper.getUUIDAndCreateTimeByYesterday(); 36 | } 37 | 38 | @Transactional 39 | @Override 40 | public void saveVisitLog(VisitLog log) { 41 | String ipSource = IpAddressUtils.getCityInfo(log.getIp()); 42 | Map userAgentMap = userAgentUtils.parseOsAndBrowser(log.getUserAgent()); 43 | String os = userAgentMap.get("os"); 44 | String browser = userAgentMap.get("browser"); 45 | log.setIpSource(ipSource); 46 | log.setOs(os); 47 | log.setBrowser(browser); 48 | if (visitLogMapper.saveVisitLog(log) != 1) { 49 | throw new PersistenceException("日志添加失败"); 50 | } 51 | } 52 | 53 | @Transactional 54 | @Override 55 | public void deleteVisitLogById(Long id) { 56 | if (visitLogMapper.deleteVisitLogById(id) != 1) { 57 | throw new PersistenceException("删除日志失败"); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/service/impl/VisitRecordServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.service.impl; 2 | 3 | import com.rawchen.entity.VisitRecord; 4 | import com.rawchen.mapper.VisitRecordMapper; 5 | import com.rawchen.service.VisitRecordService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @Description: 访问记录业务层实现 11 | * @Date: 2021-02-23 12 | */ 13 | @Service 14 | public class VisitRecordServiceImpl implements VisitRecordService { 15 | @Autowired 16 | VisitRecordMapper visitRecordMapper; 17 | 18 | @Override 19 | public void saveVisitRecord(VisitRecord visitRecord) { 20 | visitRecordMapper.saveVisitRecord(visitRecord); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/task/RedisSyncScheduleTask.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.task; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import com.rawchen.config.RedisKeyConfig; 6 | import com.rawchen.service.BlogService; 7 | import com.rawchen.service.RedisService; 8 | 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | /** 13 | * @Description: Redis相关定时任务 14 | * @Date: 2020-11-02 15 | */ 16 | @Component 17 | public class RedisSyncScheduleTask { 18 | @Autowired 19 | RedisService redisService; 20 | @Autowired 21 | BlogService blogService; 22 | 23 | /** 24 | * 从Redis同步博客文章浏览量到数据库 25 | */ 26 | public void syncBlogViewsToDatabase() { 27 | String redisKey = RedisKeyConfig.BLOG_VIEWS_MAP; 28 | Map blogViewsMap = redisService.getMapByHash(redisKey); 29 | Set keys = blogViewsMap.keySet(); 30 | for (Integer key : keys) { 31 | Integer views = (Integer) blogViewsMap.get(key); 32 | blogService.updateViews(key.longValue(), views); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/AopUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | import org.aspectj.lang.JoinPoint; 4 | import org.aspectj.lang.reflect.MethodSignature; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.util.LinkedHashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * @Description: AOP工具类 14 | * @Date: 2020-12-02 15 | */ 16 | public class AopUtils { 17 | /** 18 | * 获取请求参数 19 | * 20 | * @param joinPoint 21 | * @return 22 | */ 23 | public static Map getRequestParams(JoinPoint joinPoint) { 24 | Map map = new LinkedHashMap<>(); 25 | String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); 26 | Object[] args = joinPoint.getArgs(); 27 | for (int i = 0; i < args.length; i++) { 28 | if (!isFilterObject(args[i])) { 29 | map.put(parameterNames[i], args[i]); 30 | } 31 | } 32 | return map; 33 | } 34 | 35 | /** 36 | * consider if the data is file, httpRequest or response 37 | * 38 | * @param o the data 39 | * @return if match return true, else return false 40 | */ 41 | private static boolean isFilterObject(final Object o) { 42 | return o instanceof HttpServletRequest || o instanceof HttpServletResponse || o instanceof MultipartFile; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/HashUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | import org.apache.commons.codec.digest.MurmurHash3; 4 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 5 | import org.springframework.util.DigestUtils; 6 | 7 | /** 8 | * @Description: Hash工具类 9 | * @Date: 2020-11-17 10 | */ 11 | public class HashUtils { 12 | private static final BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); 13 | 14 | public static String getMd5(CharSequence str) { 15 | return DigestUtils.md5DigestAsHex(str.toString().getBytes()); 16 | } 17 | 18 | public static long getMurmurHash32(String str) { 19 | int i = MurmurHash3.hash32(str); 20 | long num = i < 0 ? Integer.MAX_VALUE - (long) i : i; 21 | return num; 22 | } 23 | 24 | public static String getBC(CharSequence rawPassword) { 25 | return bCryptPasswordEncoder.encode(rawPassword); 26 | } 27 | 28 | public static boolean matchBC(CharSequence rawPassword, String encodedPassword) { 29 | return bCryptPasswordEncoder.matches(rawPassword, encodedPassword); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/JacksonUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * @Description: Jackson Object Mapper 12 | * @Date: 2020-11-07 13 | */ 14 | public class JacksonUtils { 15 | private static ObjectMapper objectMapper = new ObjectMapper(); 16 | 17 | public static String writeValueAsString(Object value) { 18 | try { 19 | return objectMapper.writeValueAsString(value); 20 | } catch (JsonProcessingException e) { 21 | e.printStackTrace(); 22 | return ""; 23 | } 24 | } 25 | 26 | public static T readValue(String content, Class valueType) { 27 | try { 28 | return objectMapper.readValue(content, valueType); 29 | } catch (IOException e) { 30 | e.printStackTrace(); 31 | return null; 32 | } 33 | } 34 | 35 | public static T readValue(String content, TypeReference valueTypeRef) { 36 | try { 37 | return objectMapper.readValue(content, valueTypeRef); 38 | } catch (IOException e) { 39 | e.printStackTrace(); 40 | return null; 41 | } 42 | } 43 | 44 | public static T readValue(InputStream src, Class valueType) { 45 | try { 46 | return objectMapper.readValue(src, valueType); 47 | } catch (IOException e) { 48 | e.printStackTrace(); 49 | return null; 50 | } 51 | } 52 | 53 | public static T convertValue(Object fromValue, Class toValueType) { 54 | return objectMapper.convertValue(fromValue, toValueType); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/PictureUtil.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | public class PictureUtil { 4 | 5 | public static String randomBlogFirstPicture() { 6 | int m = 0; 7 | int n = 9; 8 | int temp=m+(int)(Math.random()*(n+1-m)); 9 | return "https://cdn.jsdelivr.net/gh/rawchen/JsDelivr/ContentThumb/"+temp+".jpg"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/QQInfoUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | import org.springframework.web.client.RestTemplate; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | 7 | /** 8 | * @Description: 获取QQ昵称头像信息 9 | * @Date: 2020-09-10 10 | */ 11 | public class QQInfoUtils { 12 | private static RestTemplate restTemplate = new RestTemplate(); 13 | private static final String QQ_NICKNAME_URL = "https://r.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins={1}"; 14 | private static final String QQ_AVATAR_URL = "https://q.qlogo.cn/g?b=qq&nk=%s&s=100"; 15 | 16 | public static String getQQNickname(String qq) throws UnsupportedEncodingException { 17 | String res = restTemplate.getForObject(QQ_NICKNAME_URL, String.class, qq); 18 | byte[] bytes = res.getBytes("iso-8859-1"); 19 | String nickname = new String(bytes, "gb18030").split(",")[6].replace("\"", ""); 20 | if ("".equals(nickname)) { 21 | return "nickname"; 22 | } 23 | return nickname; 24 | } 25 | 26 | public static String getQQAvatarURL(String qq) { 27 | return String.format(QQ_AVATAR_URL, qq); 28 | } 29 | 30 | public static boolean isQQNumber(String nickname) { 31 | return nickname.matches("^[1-9][0-9]{4,10}$"); 32 | } 33 | } -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | 6 | /** 7 | * @Description: 字符串校验 8 | * @Date: 2020-08-02 9 | */ 10 | public class StringUtils { 11 | /** 12 | * 判断字符串是否为空 13 | * 14 | * @param str 待校验字符串 15 | * @return 16 | */ 17 | public static boolean isEmpty(String... str) { 18 | for (String s : str) { 19 | if (s == null || "".equals(s.trim())) { 20 | return true; 21 | } 22 | } 23 | return false; 24 | } 25 | 26 | /** 27 | * 判断字符串中是否包含特殊字符 28 | * 29 | * @param str 待校验字符串 30 | * @return 31 | */ 32 | public static boolean hasSpecialChar(String... str) { 33 | for (String s : str) { 34 | if (s.contains("%") || s.contains("_") || s.contains("[") || s.contains("#") || s.contains("*")) { 35 | return true; 36 | } 37 | } 38 | return false; 39 | } 40 | 41 | /** 42 | * 截取字符串 43 | * 44 | * @param str 原始字符串 45 | * @param start 起始位置 46 | * @param end 结束位置 47 | * @return 48 | */ 49 | public static String substring(String str, int start, int end) { 50 | if (str == null || "".equals(str)) { 51 | return ""; 52 | } 53 | if (start < 0 || end < 0) { 54 | return str; 55 | } 56 | if (end > str.length()) { 57 | end = str.length(); 58 | } 59 | if (start >= end) { 60 | return ""; 61 | } 62 | return str.substring(start, end); 63 | } 64 | 65 | /** 66 | * 获取堆栈信息 67 | * 68 | * @param throwable 异常 69 | * @return 70 | */ 71 | public static String getStackTrace(Throwable throwable) { 72 | StringWriter sw = new StringWriter(); 73 | try (PrintWriter pw = new PrintWriter(sw)) { 74 | throwable.printStackTrace(pw); 75 | return sw.toString(); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/UserAgentUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util; 2 | 3 | import nl.basjes.parse.useragent.UserAgent; 4 | import nl.basjes.parse.useragent.UserAgentAnalyzer; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @Description: UserAgent解析工具类 12 | * @Date: 2020-11-30 13 | */ 14 | @Component 15 | public class UserAgentUtils { 16 | private UserAgentAnalyzer uaa; 17 | 18 | public UserAgentUtils() { 19 | this.uaa = UserAgentAnalyzer 20 | .newBuilder() 21 | .hideMatcherLoadStats() 22 | .withField("OperatingSystemNameVersionMajor") 23 | .withField("AgentNameVersion") 24 | .build(); 25 | } 26 | 27 | /** 28 | * 从User-Agent解析客户端操作系统和浏览器版本 29 | * 30 | * @param userAgent 31 | * @return 32 | */ 33 | public Map parseOsAndBrowser(String userAgent) { 34 | UserAgent agent = uaa.parse(userAgent); 35 | String os = agent.getValue("OperatingSystemNameVersionMajor"); 36 | String browser = agent.getValue("AgentNameVersion"); 37 | Map map = new HashMap<>(); 38 | map.put("os", os); 39 | map.put("browser", browser); 40 | return map; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/common/SpringContextUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.common; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @Description: 10 | * @Date: 2020-11-01 11 | */ 12 | @Component 13 | public class SpringContextUtils implements ApplicationContextAware { 14 | public static ApplicationContext applicationContext; 15 | 16 | @Override 17 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 18 | SpringContextUtils.applicationContext = applicationContext; 19 | } 20 | 21 | public static Object getBean(String name) { 22 | return applicationContext.getBean(name); 23 | } 24 | 25 | public static T getBean(String name, Class requiredType) { 26 | return applicationContext.getBean(name, requiredType); 27 | } 28 | 29 | public static boolean containsBean(String name) { 30 | return applicationContext.containsBean(name); 31 | } 32 | 33 | public static boolean isSingleton(String name) { 34 | return applicationContext.isSingleton(name); 35 | } 36 | 37 | public static Class getType(String name) { 38 | return applicationContext.getType(name); 39 | } 40 | 41 | /** 42 | * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. 43 | */ 44 | public static T getBean(Class requiredType) { 45 | return applicationContext.getBean(requiredType); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/common/ValidatorUtils.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.common; 2 | 3 | import javax.validation.ConstraintViolation; 4 | import javax.validation.Validation; 5 | import javax.validation.Validator; 6 | import java.util.Set; 7 | 8 | /** 9 | * @Description: 10 | * @Date: 2020-11-01 11 | */ 12 | public class ValidatorUtils { 13 | private static Validator validator; 14 | 15 | static { 16 | validator = Validation.buildDefaultValidatorFactory().getValidator(); 17 | } 18 | 19 | /** 20 | * 校验对象 21 | * 22 | * @param object 待校验对象 23 | * @param groups 待校验的组 24 | * @throws RuntimeException 校验不通过,则报BusinessException异常 25 | */ 26 | public static void validateEntity(Object object, Class... groups) throws RuntimeException { 27 | Set> constraintViolations = validator.validate(object, groups); 28 | if (!constraintViolations.isEmpty()) { 29 | ConstraintViolation constraint = constraintViolations.iterator().next(); 30 | throw new RuntimeException(constraint.getMessage()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/cover/Cover.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.cover; 2 | 3 | import org.commonmark.node.CustomNode; 4 | import org.commonmark.node.Delimited; 5 | 6 | /** 7 | * @Description: A cover node containing text and other inline nodes nodes as children. 8 | * @Date: 2020-05-13 9 | */ 10 | public class Cover extends CustomNode implements Delimited { 11 | private static final String DELIMITER = "%%"; 12 | 13 | @Override 14 | public String getOpeningDelimiter() { 15 | return DELIMITER; 16 | } 17 | 18 | @Override 19 | public String getClosingDelimiter() { 20 | return DELIMITER; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/cover/CoverExtension.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.cover; 2 | 3 | import org.commonmark.Extension; 4 | import org.commonmark.parser.Parser; 5 | import org.commonmark.renderer.NodeRenderer; 6 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 7 | import org.commonmark.renderer.html.HtmlNodeRendererFactory; 8 | import org.commonmark.renderer.html.HtmlRenderer; 9 | import org.commonmark.renderer.text.TextContentNodeRendererContext; 10 | import org.commonmark.renderer.text.TextContentNodeRendererFactory; 11 | import org.commonmark.renderer.text.TextContentRenderer; 12 | import com.rawchen.util.markdown.ext.cover.internal.CoverDelimiterProcessor; 13 | import com.rawchen.util.markdown.ext.cover.internal.CoverHtmlNodeRenderer; 14 | import com.rawchen.util.markdown.ext.cover.internal.CoverTextContentNodeRenderer; 15 | 16 | /** 17 | * @Description: 自定义遮盖层拓展 18 | * @Date: 2020-05-13 19 | */ 20 | public class CoverExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, TextContentRenderer.TextContentRendererExtension { 21 | private CoverExtension() { 22 | } 23 | 24 | public static Extension create() { 25 | return new CoverExtension(); 26 | } 27 | 28 | @Override 29 | public void extend(Parser.Builder parserBuilder) { 30 | parserBuilder.customDelimiterProcessor(new CoverDelimiterProcessor()); 31 | } 32 | 33 | @Override 34 | public void extend(HtmlRenderer.Builder rendererBuilder) { 35 | rendererBuilder.nodeRendererFactory(new HtmlNodeRendererFactory() { 36 | @Override 37 | public NodeRenderer create(HtmlNodeRendererContext context) { 38 | return new CoverHtmlNodeRenderer(context); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public void extend(TextContentRenderer.Builder rendererBuilder) { 45 | rendererBuilder.nodeRendererFactory(new TextContentNodeRendererFactory() { 46 | @Override 47 | public NodeRenderer create(TextContentNodeRendererContext context) { 48 | return new CoverTextContentNodeRenderer(context); 49 | } 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/cover/internal/AbstractCoverNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.cover.internal; 2 | 3 | import com.rawchen.util.markdown.ext.cover.Cover; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.NodeRenderer; 6 | 7 | import java.util.Collections; 8 | import java.util.Set; 9 | 10 | abstract class AbstractCoverNodeRenderer implements NodeRenderer { 11 | @Override 12 | public Set> getNodeTypes() { 13 | return Collections.>singleton(Cover.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/cover/internal/CoverDelimiterProcessor.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.cover.internal; 2 | 3 | import com.rawchen.util.markdown.ext.cover.Cover; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.node.Text; 6 | import org.commonmark.parser.delimiter.DelimiterProcessor; 7 | import org.commonmark.parser.delimiter.DelimiterRun; 8 | 9 | /** 10 | * @Description: 定界 11 | * @Date: 2020-05-13 12 | */ 13 | public class CoverDelimiterProcessor implements DelimiterProcessor { 14 | @Override 15 | public char getOpeningCharacter() { 16 | return '%'; 17 | } 18 | 19 | @Override 20 | public char getClosingCharacter() { 21 | return '%'; 22 | } 23 | 24 | @Override 25 | public int getMinLength() { 26 | return 2; 27 | } 28 | 29 | @Override 30 | public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { 31 | if (opener.length() >= 2 && closer.length() >= 2) { 32 | // Use exactly two delimiters even if we have more, and don't care about internal openers/closers. 33 | return 2; 34 | } else { 35 | return 0; 36 | } 37 | } 38 | 39 | @Override 40 | public void process(Text opener, Text closer, int delimiterCount) { 41 | // Wrap nodes between delimiters in cover. 42 | Node cover = new Cover(); 43 | 44 | Node tmp = opener.getNext(); 45 | while (tmp != null && tmp != closer) { 46 | Node next = tmp.getNext(); 47 | cover.appendChild(tmp); 48 | tmp = next; 49 | } 50 | 51 | opener.insertAfter(cover); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/cover/internal/CoverHtmlNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.cover.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 5 | import org.commonmark.renderer.html.HtmlWriter; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @Description: HTML节点渲染 12 | * @Date: 2020-05-13 13 | */ 14 | public class CoverHtmlNodeRenderer extends AbstractCoverNodeRenderer { 15 | private final HtmlNodeRendererContext context; 16 | private final HtmlWriter html; 17 | 18 | public CoverHtmlNodeRenderer(HtmlNodeRendererContext context) { 19 | this.context = context; 20 | this.html = context.getWriter(); 21 | } 22 | 23 | @Override 24 | public void render(Node node) { 25 | Map attributes = new HashMap<>(); 26 | attributes.put("class", "m-text-cover"); 27 | html.tag("span", context.extendAttributes(node, "span", attributes)); 28 | renderChildren(node); 29 | html.tag("/span"); 30 | } 31 | 32 | private void renderChildren(Node parent) { 33 | Node node = parent.getFirstChild(); 34 | while (node != null) { 35 | Node next = node.getNext(); 36 | context.render(node); 37 | node = next; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/cover/internal/CoverTextContentNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.cover.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.text.TextContentNodeRendererContext; 5 | import org.commonmark.renderer.text.TextContentWriter; 6 | 7 | /** 8 | * @Description: 文本节点渲染 9 | * @Date: 2020-05-13 10 | */ 11 | public class CoverTextContentNodeRenderer extends AbstractCoverNodeRenderer { 12 | private final TextContentNodeRendererContext context; 13 | private final TextContentWriter textContent; 14 | 15 | public CoverTextContentNodeRenderer(TextContentNodeRendererContext context) { 16 | this.context = context; 17 | this.textContent = context.getWriter(); 18 | } 19 | 20 | @Override 21 | public void render(Node node) { 22 | textContent.write('/'); 23 | renderChildren(node); 24 | textContent.write('/'); 25 | } 26 | 27 | private void renderChildren(Node parent) { 28 | Node node = parent.getFirstChild(); 29 | while (node != null) { 30 | Node next = node.getNext(); 31 | context.render(node); 32 | node = next; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/heimu/Heimu.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.heimu; 2 | 3 | import org.commonmark.node.CustomNode; 4 | import org.commonmark.node.Delimited; 5 | 6 | /** 7 | * @Description: A heimu node containing text and other inline nodes nodes as children. 8 | * @Date: 2020-05-13 9 | */ 10 | public class Heimu extends CustomNode implements Delimited { 11 | private static final String DELIMITER = "@@"; 12 | 13 | @Override 14 | public String getOpeningDelimiter() { 15 | return DELIMITER; 16 | } 17 | 18 | @Override 19 | public String getClosingDelimiter() { 20 | return DELIMITER; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/heimu/HeimuExtension.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.heimu; 2 | 3 | import com.rawchen.util.markdown.ext.heimu.internal.HeimuHtmlNodeRenderer; 4 | import org.commonmark.Extension; 5 | import org.commonmark.parser.Parser; 6 | import org.commonmark.renderer.NodeRenderer; 7 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 8 | import org.commonmark.renderer.html.HtmlNodeRendererFactory; 9 | import org.commonmark.renderer.html.HtmlRenderer; 10 | import org.commonmark.renderer.text.TextContentNodeRendererContext; 11 | import org.commonmark.renderer.text.TextContentNodeRendererFactory; 12 | import org.commonmark.renderer.text.TextContentRenderer; 13 | import com.rawchen.util.markdown.ext.heimu.internal.HeimuDelimiterProcessor; 14 | import com.rawchen.util.markdown.ext.heimu.internal.HeimuTextContentNodeRenderer; 15 | 16 | /** 17 | * @Description: 自定义黑幕拓展 18 | * @Date: 2020-05-13 19 | */ 20 | public class HeimuExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension, TextContentRenderer.TextContentRendererExtension { 21 | private HeimuExtension() { 22 | } 23 | 24 | public static Extension create() { 25 | return new HeimuExtension(); 26 | } 27 | 28 | @Override 29 | public void extend(Parser.Builder parserBuilder) { 30 | parserBuilder.customDelimiterProcessor(new HeimuDelimiterProcessor()); 31 | } 32 | 33 | @Override 34 | public void extend(HtmlRenderer.Builder rendererBuilder) { 35 | rendererBuilder.nodeRendererFactory(new HtmlNodeRendererFactory() { 36 | @Override 37 | public NodeRenderer create(HtmlNodeRendererContext context) { 38 | return new HeimuHtmlNodeRenderer(context); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public void extend(TextContentRenderer.Builder rendererBuilder) { 45 | rendererBuilder.nodeRendererFactory(new TextContentNodeRendererFactory() { 46 | @Override 47 | public NodeRenderer create(TextContentNodeRendererContext context) { 48 | return new HeimuTextContentNodeRenderer(context); 49 | } 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/heimu/internal/AbstractHeimuNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.heimu.internal; 2 | 3 | import com.rawchen.util.markdown.ext.heimu.Heimu; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.renderer.NodeRenderer; 6 | 7 | import java.util.Collections; 8 | import java.util.Set; 9 | 10 | abstract class AbstractHeimuNodeRenderer implements NodeRenderer { 11 | @Override 12 | public Set> getNodeTypes() { 13 | return Collections.>singleton(Heimu.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/heimu/internal/HeimuDelimiterProcessor.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.heimu.internal; 2 | 3 | import com.rawchen.util.markdown.ext.heimu.Heimu; 4 | import org.commonmark.node.Node; 5 | import org.commonmark.node.Text; 6 | import org.commonmark.parser.delimiter.DelimiterProcessor; 7 | import org.commonmark.parser.delimiter.DelimiterRun; 8 | 9 | /** 10 | * @Description: 定界 11 | * @Date: 2020-05-13 12 | */ 13 | public class HeimuDelimiterProcessor implements DelimiterProcessor { 14 | @Override 15 | public char getOpeningCharacter() { 16 | return '@'; 17 | } 18 | 19 | @Override 20 | public char getClosingCharacter() { 21 | return '@'; 22 | } 23 | 24 | @Override 25 | public int getMinLength() { 26 | return 2; 27 | } 28 | 29 | @Override 30 | public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { 31 | if (opener.length() >= 2 && closer.length() >= 2) { 32 | // Use exactly two delimiters even if we have more, and don't care about internal openers/closers. 33 | return 2; 34 | } else { 35 | return 0; 36 | } 37 | } 38 | 39 | @Override 40 | public void process(Text opener, Text closer, int delimiterCount) { 41 | // Wrap nodes between delimiters in heimu. 42 | Node heimu = new Heimu(); 43 | 44 | Node tmp = opener.getNext(); 45 | while (tmp != null && tmp != closer) { 46 | Node next = tmp.getNext(); 47 | heimu.appendChild(tmp); 48 | tmp = next; 49 | } 50 | 51 | opener.insertAfter(heimu); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/heimu/internal/HeimuHtmlNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.heimu.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.html.HtmlNodeRendererContext; 5 | import org.commonmark.renderer.html.HtmlWriter; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @Description: HTML节点渲染 12 | * @Date: 2020-05-13 13 | */ 14 | public class HeimuHtmlNodeRenderer extends AbstractHeimuNodeRenderer { 15 | private final HtmlNodeRendererContext context; 16 | private final HtmlWriter html; 17 | 18 | public HeimuHtmlNodeRenderer(HtmlNodeRendererContext context) { 19 | this.context = context; 20 | this.html = context.getWriter(); 21 | } 22 | 23 | @Override 24 | public void render(Node node) { 25 | Map attributes = new HashMap<>(); 26 | attributes.put("class", "m-text-heimu"); 27 | attributes.put("title", "你知道的太多了"); 28 | html.tag("span", context.extendAttributes(node, "span", attributes)); 29 | renderChildren(node); 30 | html.tag("/span"); 31 | } 32 | 33 | private void renderChildren(Node parent) { 34 | Node node = parent.getFirstChild(); 35 | while (node != null) { 36 | Node next = node.getNext(); 37 | context.render(node); 38 | node = next; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/markdown/ext/heimu/internal/HeimuTextContentNodeRenderer.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.markdown.ext.heimu.internal; 2 | 3 | import org.commonmark.node.Node; 4 | import org.commonmark.renderer.text.TextContentNodeRendererContext; 5 | import org.commonmark.renderer.text.TextContentWriter; 6 | 7 | /** 8 | * @Description: 文本节点渲染 9 | * @Date: 2020-05-13 10 | */ 11 | public class HeimuTextContentNodeRenderer extends AbstractHeimuNodeRenderer { 12 | private final TextContentNodeRendererContext context; 13 | private final TextContentWriter textContent; 14 | 15 | public HeimuTextContentNodeRenderer(TextContentNodeRendererContext context) { 16 | this.context = context; 17 | this.textContent = context.getWriter(); 18 | } 19 | 20 | @Override 21 | public void render(Node node) { 22 | textContent.write('/'); 23 | renderChildren(node); 24 | textContent.write('/'); 25 | } 26 | 27 | private void renderChildren(Node parent) { 28 | Node node = parent.getFirstChild(); 29 | while (node != null) { 30 | Node next = node.getNext(); 31 | context.render(node); 32 | node = next; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /blog-api/src/main/java/com/rawchen/util/quartz/ScheduleRunnable.java: -------------------------------------------------------------------------------- 1 | package com.rawchen.util.quartz; 2 | 3 | import com.rawchen.util.common.SpringContextUtils; 4 | import org.springframework.util.ReflectionUtils; 5 | import org.springframework.util.StringUtils; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * @Description: 执行定时任务 11 | * @Date: 2020-11-01 12 | */ 13 | public class ScheduleRunnable implements Runnable { 14 | private Object target; 15 | private Method method; 16 | private String params; 17 | 18 | public ScheduleRunnable(String beanName, String methodName, String params) throws NoSuchMethodException, SecurityException { 19 | this.target = SpringContextUtils.getBean(beanName); 20 | this.params = params; 21 | if (StringUtils.hasText(params)) { 22 | this.method = target.getClass().getDeclaredMethod(methodName, String.class); 23 | } else { 24 | this.method = target.getClass().getDeclaredMethod(methodName); 25 | } 26 | } 27 | 28 | @Override 29 | public void run() { 30 | try { 31 | ReflectionUtils.makeAccessible(method); 32 | if (StringUtils.hasText(params)) { 33 | method.invoke(target, params); 34 | } else { 35 | method.invoke(target); 36 | } 37 | } catch (Exception e) { 38 | throw new RuntimeException("执行定时任务失败", e); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | server.port=8090 2 | # 部署上线需要修改为服务器ip,如有域名则改为例如 https://xxx.xxx 3 | custom.blog.name=RawChen'Blog 4 | # 后台cms 5 | custom.url.cms=http://localhost:8080 6 | # 前台站点 7 | custom.url.website=http://localhost:8081 8 | 9 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 10 | spring.datasource.url=jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 11 | spring.datasource.username=root 12 | spring.datasource.password=root 13 | 14 | spring.redis.host=127.0.0.1 15 | spring.redis.password= 16 | spring.redis.port=6379 17 | spring.redis.database=0 18 | spring.redis.timeout=10000ms 19 | 20 | mybatis.mapper-locations=classpath:mapper/*.xml 21 | mybatis.configuration.map-underscore-to-camel-case=true 22 | 23 | logging.level.root=info 24 | logging.level.com.rawchen=debug 25 | logging.file.path=log/blog-dev 26 | 27 | # 1000 * 60 * 60 * 24 * 3 = 3天 28 | token.expireTime=259200000 29 | # 部署上线务必修改此配置,否则无法保证token安全性 30 | token.secretKey=abcdefghijklmnopqrstuvwxyz 31 | 32 | spring.mail.host=smtp.qq.com 33 | spring.mail.port=587 34 | 35 | spring.mail.properties.mail.smtp.auth=true 36 | spring.mail.properties.mail.smtp.starttls.enable=true 37 | spring.mail.properties.mail.smtp.starttls.required=true 38 | spring.mail.username=2221999792@qq.com 39 | spring.mail.password=xxx -------------------------------------------------------------------------------- /blog-api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev -------------------------------------------------------------------------------- /blog-api/src/main/resources/ipdb/ip2region.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-api/src/main/resources/ipdb/ip2region.db -------------------------------------------------------------------------------- /blog-api/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ${FILE_LOG_PATTERN} 12 | 13 | 14 | 15 | 16 | ${LOG_FILE}-%d{yyyy-MM-dd}-%i.log 17 | 365 18 | 19 | 20 | 10MB 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/AboutMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | update about 13 | set value=#{value} 14 | where name_en = #{nameEn} 15 | 16 | 17 | 18 | 23 | 24 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/CategoryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | insert into category (category_name) 27 | values (#{name}) 28 | 29 | 30 | 31 | 36 | 37 | 38 | 43 | 44 | 45 | 46 | delete 47 | from category 48 | where id = #{id} 49 | 50 | 51 | 52 | 53 | update category 54 | set category_name=#{name} 55 | where id = #{id} 56 | 57 | 58 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/CityVisitorMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | insert into city_visitor (city, uv) 20 | values (#{city}, #{uv}) 21 | on duplicate key update uv=uv + #{uv} 22 | 23 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/ExceptionLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 30 | 31 | 32 | 34 | insert into exception_log (uri, method, param, description, error, ip, ip_source, os, browser, create_time, 35 | user_agent) 36 | values (#{uri}, #{method}, #{param}, #{description}, #{error}, #{ip}, #{ipSource}, #{os}, #{browser}, 37 | #{createTime}, #{userAgent}) 38 | 39 | 40 | 41 | 42 | delete 43 | from exception_log 44 | where id = #{id} 45 | 46 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/LoginLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | 29 | 30 | 31 | insert into login_log (username, ip, ip_source, os, browser, status, description, create_time, user_agent) 32 | values (#{username}, #{ip}, #{ipSource}, #{os}, #{browser}, #{status}, #{description}, #{createTime}, 33 | #{userAgent}) 34 | 35 | 36 | 37 | 38 | delete 39 | from login_log 40 | where id = #{id} 41 | 42 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/MomentMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | update moment 22 | set likes=likes + 1 23 | where id = #{momentId} 24 | 25 | 26 | 27 | 28 | update moment 29 | set is_published=#{published} 30 | where id = #{momentId} 31 | 32 | 33 | 34 | 39 | 40 | 41 | 42 | delete 43 | from moment 44 | where id = #{id} 45 | 46 | 47 | 48 | 49 | insert into moment (content, create_time, likes, is_published) 50 | values (#{content}, #{createTime}, #{likes}, #{published}) 51 | 52 | 53 | 54 | 55 | update moment 56 | set content=#{content}, 57 | create_time=#{createTime}, 58 | likes=#{likes}, 59 | is_published=#{published} 60 | where id = #{id} 61 | 62 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/OperationLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 31 | 32 | 33 | 35 | insert into operation_log (username, uri, method, param, description, ip, ip_source, os, browser, times, 36 | create_time, user_agent) 37 | values (#{username}, #{uri}, #{method}, #{param}, #{description}, #{ip}, #{ipSource}, #{os}, #{browser}, 38 | #{times}, #{createTime}, #{userAgent}) 39 | 40 | 41 | 42 | 43 | delete 44 | from operation_log 45 | where id = #{id} 46 | 47 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/ScheduleJobLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 26 | 27 | 29 | insert into schedule_job_log (job_id, bean_name, method_name, params, status, error, times, create_time) 30 | values (#{jobId}, #{beanName}, #{methodName}, #{params}, #{status}, #{error}, #{times}, #{createTime}) 31 | 32 | 33 | 34 | delete 35 | from schedule_job_log 36 | where log_id = #{logId} 37 | 38 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/SiteSettingMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | update site_setting 28 | set value=#{value} 29 | where id = #{id} 30 | 31 | 32 | 33 | 34 | delete 35 | from site_setting 36 | where id = #{id} 37 | 38 | 39 | 40 | 41 | insert into site_setting (name_en, name_zh, value, type) 42 | values (#{nameEn}, #{nameZh}, #{value}, #{type}) 43 | 44 | 45 | 46 | 47 | update site_setting 48 | set value=#{content} 49 | where name_en = 'friendContent' 50 | 51 | 52 | 53 | 54 | update site_setting 55 | set value=#{commentEnabled} 56 | where name_en = 'friendCommentEnabled' 57 | 58 | 59 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /blog-api/src/main/resources/mapper/VisitRecordMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 23 | insert into visit_record (pv, uv, date) 24 | values (#{pv}, #{uv}, #{date}) 25 | 26 | -------------------------------------------------------------------------------- /blog-api/src/test/java/com/rawchen/BlogApiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.rawchen; 2 | 3 | import com.rawchen.util.IpAddressUtils; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | import org.springframework.util.ClassUtils; 8 | 9 | 10 | @SpringBootTest 11 | class BlogApiApplicationTests { 12 | 13 | @Test 14 | void contextLoads() { 15 | } 16 | 17 | @Test 18 | void test01() { 19 | System.out.println(new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A).encode("admin")); 20 | } 21 | 22 | @Test 23 | void test02() { 24 | System.out.println(String.class.getTypeName()); 25 | System.out.println(ClassUtils.getShortNameAsProperty(String.class)); 26 | // System.out.println(ClassUtils.getMethod(String.class, "valueOf", String.class)); 27 | } 28 | 29 | @Test 30 | void test03() { 31 | String cityInfo = IpAddressUtils.getCityInfo("119.23.60.193"); 32 | System.out.println(cityInfo); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /blog-cms/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /blog-cms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog-cms", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.21.1", 11 | "core-js": "^3.6.5", 12 | "echarts": "^4.9.0", 13 | "element-ui": "^2.13.2", 14 | "lodash": "^4.17.19", 15 | "moment": "^2.27.0", 16 | "nprogress": "^0.2.0", 17 | "vditor": "^3.4.0", 18 | "vue": "^2.6.11", 19 | "vue-router": "^3.2.0", 20 | "vuex": "^3.4.0" 21 | }, 22 | "devDependencies": { 23 | "@vue/cli-plugin-babel": "~4.4.0", 24 | "@vue/cli-plugin-router": "~4.4.0", 25 | "@vue/cli-plugin-vuex": "~4.4.0", 26 | "@vue/cli-service": "~4.4.0", 27 | "vue-template-compiler": "^2.6.11" 28 | }, 29 | "browserslist": [ 30 | "> 1%", 31 | "last 2 versions", 32 | "not dead" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /blog-cms/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/public/favicon.ico -------------------------------------------------------------------------------- /blog-cms/public/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/public/img/avatar.jpg -------------------------------------------------------------------------------- /blog-cms/public/img/comment-avatar/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/public/img/comment-avatar/1.jpg -------------------------------------------------------------------------------- /blog-cms/public/img/comment-avatar/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/public/img/comment-avatar/2.jpg -------------------------------------------------------------------------------- /blog-cms/public/img/visitor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/public/img/visitor.jpg -------------------------------------------------------------------------------- /blog-cms/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 后台管理 - Blog 9 | 10 | 11 | 12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /blog-cms/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 27 | 28 | 31 | -------------------------------------------------------------------------------- /blog-cms/src/api/ExceptionLog.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getExceptionLogList(queryInfo) { 4 | return axios({ 5 | url: 'exceptionLogs', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function deleteExceptionLogById(id) { 14 | return axios({ 15 | url: 'exceptionLog', 16 | method: 'DELETE', 17 | params: { 18 | id 19 | } 20 | }) 21 | } -------------------------------------------------------------------------------- /blog-cms/src/api/about.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getAbout() { 4 | return axios({ 5 | url: 'about', 6 | method: 'GET' 7 | }) 8 | } 9 | 10 | export function updateAbout(form) { 11 | return axios({ 12 | url: 'about', 13 | method: 'PUT', 14 | data: { 15 | ...form 16 | } 17 | }) 18 | } -------------------------------------------------------------------------------- /blog-cms/src/api/blog.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getDataByQuery(queryInfo) { 4 | return axios({ 5 | url: 'blogs', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function deleteBlogById(id) { 14 | return axios({ 15 | url: 'blog', 16 | method: 'DELETE', 17 | params: { 18 | id 19 | } 20 | }) 21 | } 22 | 23 | export function getCategoryAndTag() { 24 | return axios({ 25 | url: 'categoryAndTag', 26 | method: 'GET' 27 | }) 28 | } 29 | 30 | export function saveBlog(blog) { 31 | return axios({ 32 | url: 'blog', 33 | method: 'POST', 34 | data: { 35 | ...blog 36 | } 37 | }) 38 | } 39 | 40 | export function updateTop(id, top) { 41 | return axios({ 42 | url: 'blog/top', 43 | method: 'PUT', 44 | params: { 45 | id, 46 | top 47 | } 48 | }) 49 | } 50 | 51 | export function updateRecommend(id, recommend) { 52 | return axios({ 53 | url: 'blog/recommend', 54 | method: 'PUT', 55 | params: { 56 | id, 57 | recommend 58 | } 59 | }) 60 | } 61 | 62 | export function updateVisibility(id, form) { 63 | return axios({ 64 | url: `blog/${id}/visibility`, 65 | method: 'PUT', 66 | data: { 67 | ...form 68 | } 69 | }) 70 | } 71 | 72 | export function getBlogById(id) { 73 | return axios({ 74 | url: 'blog', 75 | method: 'GET', 76 | params: { 77 | id 78 | } 79 | }) 80 | } 81 | 82 | export function updateBlog(blog) { 83 | return axios({ 84 | url: 'blog', 85 | method: 'PUT', 86 | data: { 87 | ...blog 88 | } 89 | }) 90 | } -------------------------------------------------------------------------------- /blog-cms/src/api/category.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getData(queryInfo) { 4 | return axios({ 5 | url: 'categories', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function addCategory(form) { 14 | return axios({ 15 | url: 'category', 16 | method: 'POST', 17 | data: { 18 | ...form 19 | } 20 | }) 21 | } 22 | 23 | export function editCategory(form) { 24 | return axios({ 25 | url: 'category', 26 | method: 'PUT', 27 | data: { 28 | ...form 29 | } 30 | }) 31 | } 32 | 33 | export function deleteCategoryById(id) { 34 | return axios({ 35 | url: 'category', 36 | method: 'DELETE', 37 | params: { 38 | id 39 | } 40 | }) 41 | } -------------------------------------------------------------------------------- /blog-cms/src/api/comment.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getCommentListByQuery(queryInfo) { 4 | return axios({ 5 | url: 'comments', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function getBlogList() { 14 | return axios({ 15 | url: 'blogIdAndTitle', 16 | method: 'GET' 17 | }) 18 | } 19 | 20 | export function updatePublished(id, published) { 21 | return axios({ 22 | url: 'comment/published', 23 | method: 'PUT', 24 | params: { 25 | id, 26 | published 27 | } 28 | }) 29 | } 30 | 31 | export function updateNotice(id, notice) { 32 | return axios({ 33 | url: 'comment/notice', 34 | method: 'PUT', 35 | params: { 36 | id, 37 | notice 38 | } 39 | }) 40 | } 41 | 42 | export function deleteCommentById(id) { 43 | return axios({ 44 | url: 'comment', 45 | method: 'DELETE', 46 | params: { 47 | id 48 | } 49 | }) 50 | } 51 | 52 | export function editComment(form) { 53 | return axios({ 54 | url: 'comment', 55 | method: 'PUT', 56 | data: { 57 | ...form 58 | } 59 | }) 60 | } -------------------------------------------------------------------------------- /blog-cms/src/api/dashboard.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getDashboard() { 4 | return axios({ 5 | url: 'dashboard', 6 | method: 'GET' 7 | }) 8 | } -------------------------------------------------------------------------------- /blog-cms/src/api/friend.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getFriendsByQuery(queryInfo) { 4 | return axios({ 5 | url: 'friends', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function updatePublished(id, published) { 14 | return axios({ 15 | url: 'friend/published', 16 | method: 'PUT', 17 | params: { 18 | id, 19 | published 20 | } 21 | }) 22 | } 23 | 24 | export function saveFriend(form) { 25 | return axios({ 26 | url: 'friend', 27 | method: 'POST', 28 | data: { 29 | ...form 30 | } 31 | }) 32 | } 33 | 34 | export function updateFriend(form) { 35 | return axios({ 36 | url: 'friend', 37 | method: 'PUT', 38 | data: { 39 | ...form 40 | } 41 | }) 42 | } 43 | 44 | export function deleteFriendById(id) { 45 | return axios({ 46 | url: 'friend', 47 | method: 'DELETE', 48 | params: { 49 | id 50 | } 51 | }) 52 | } 53 | 54 | export function getFriendInfo() { 55 | return axios({ 56 | url: 'friendInfo', 57 | method: 'GET' 58 | }) 59 | } 60 | 61 | export function updateCommentEnabled(commentEnabled) { 62 | return axios({ 63 | url: 'friendInfo/commentEnabled', 64 | method: 'PUT', 65 | params: { 66 | commentEnabled 67 | } 68 | }) 69 | } 70 | 71 | export function updateContent(content) { 72 | return axios({ 73 | url: 'friendInfo/content', 74 | method: 'PUT', 75 | data: { 76 | content 77 | } 78 | }) 79 | } -------------------------------------------------------------------------------- /blog-cms/src/api/login.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function login(loginForm) { 4 | return axios({ 5 | url: 'login', 6 | method: 'POST', 7 | data: { 8 | ...loginForm 9 | } 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /blog-cms/src/api/loginLog.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getLoginLogList(queryInfo) { 4 | return axios({ 5 | url: 'loginLogs', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function deleteLoginLogById(id) { 14 | return axios({ 15 | url: 'loginLog', 16 | method: 'DELETE', 17 | params: { 18 | id 19 | } 20 | }) 21 | } -------------------------------------------------------------------------------- /blog-cms/src/api/moment.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getMomentListByQuery(queryInfo) { 4 | return axios({ 5 | url: 'moments', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function updatePublished(id, published) { 14 | return axios({ 15 | url: 'moment/published', 16 | method: 'PUT', 17 | params: { 18 | id, 19 | published 20 | } 21 | }) 22 | } 23 | 24 | export function getMomentById(id) { 25 | return axios({ 26 | url: 'moment', 27 | method: 'GET', 28 | params: { 29 | id 30 | } 31 | }) 32 | } 33 | 34 | export function deleteMomentById(id) { 35 | return axios({ 36 | url: 'moment', 37 | method: 'DELETE', 38 | params: { 39 | id 40 | } 41 | }) 42 | } 43 | 44 | export function saveMoment(moment) { 45 | return axios({ 46 | url: 'moment', 47 | method: 'POST', 48 | data: { 49 | ...moment 50 | } 51 | }) 52 | } 53 | 54 | export function updateMoment(moment) { 55 | return axios({ 56 | url: 'moment', 57 | method: 'PUT', 58 | data: { 59 | ...moment 60 | } 61 | }) 62 | } -------------------------------------------------------------------------------- /blog-cms/src/api/operationLog.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getOperationLogList(queryInfo) { 4 | return axios({ 5 | url: 'operationLogs', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function deleteOperationLogById(id) { 14 | return axios({ 15 | url: 'operationLog', 16 | method: 'DELETE', 17 | params: { 18 | id 19 | } 20 | }) 21 | } -------------------------------------------------------------------------------- /blog-cms/src/api/schedule.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getJobList(queryInfo) { 4 | return axios({ 5 | url: 'jobs', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function updateJobStatus(jobId, status) { 14 | return axios({ 15 | url: 'job/status', 16 | method: 'PUT', 17 | params: { 18 | jobId, 19 | status 20 | } 21 | }) 22 | } 23 | 24 | export function runJobOnce(jobId) { 25 | return axios({ 26 | url: 'job/run', 27 | method: 'POST', 28 | params: { 29 | jobId 30 | } 31 | }) 32 | } 33 | 34 | export function deleteJobById(jobId) { 35 | return axios({ 36 | url: 'job', 37 | method: 'DELETE', 38 | params: { 39 | jobId 40 | } 41 | }) 42 | } 43 | 44 | export function addJob(job) { 45 | return axios({ 46 | url: 'job', 47 | method: 'POST', 48 | data: { 49 | ...job 50 | } 51 | }) 52 | } 53 | 54 | export function editJob(job) { 55 | return axios({ 56 | url: 'job', 57 | method: 'PUT', 58 | data: { 59 | ...job 60 | } 61 | }) 62 | } 63 | 64 | export function getJobLogList(queryInfo) { 65 | return axios({ 66 | url: 'job/logs', 67 | method: 'GET', 68 | params: { 69 | ...queryInfo 70 | } 71 | }) 72 | } 73 | 74 | export function deleteJobLogByLogId(logId) { 75 | return axios({ 76 | url: 'job/log', 77 | method: 'DELETE', 78 | params: { 79 | logId 80 | } 81 | }) 82 | } -------------------------------------------------------------------------------- /blog-cms/src/api/siteSetting.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getSiteSettingData() { 4 | return axios({ 5 | url: 'siteSettings', 6 | method: 'GET' 7 | }) 8 | } 9 | 10 | export function update(settings, deleteIds) { 11 | return axios({ 12 | url: 'siteSettings', 13 | method: 'POST', 14 | data: { 15 | settings, 16 | deleteIds 17 | } 18 | }) 19 | } 20 | 21 | export function getWebTitleSuffix() { 22 | return axios({ 23 | url: 'webTitleSuffix', 24 | method: 'GET' 25 | }) 26 | } -------------------------------------------------------------------------------- /blog-cms/src/api/tag.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getData(queryInfo) { 4 | return axios({ 5 | url: 'tags', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function addTag(form) { 14 | return axios({ 15 | url: 'tag', 16 | method: 'POST', 17 | data: { 18 | ...form 19 | } 20 | }) 21 | } 22 | 23 | export function editTag(form) { 24 | return axios({ 25 | url: 'tag', 26 | method: 'PUT', 27 | data: { 28 | ...form 29 | } 30 | }) 31 | } 32 | 33 | export function deleteTagById(id) { 34 | return axios({ 35 | url: 'tag', 36 | method: 'DELETE', 37 | params: { 38 | id 39 | } 40 | }) 41 | } -------------------------------------------------------------------------------- /blog-cms/src/api/visitLog.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getVisitLogList(queryInfo) { 4 | return axios({ 5 | url: 'visitLogs', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function deleteVisitLogById(id) { 14 | return axios({ 15 | url: 'visitLog', 16 | method: 'DELETE', 17 | params: { 18 | id 19 | } 20 | }) 21 | } -------------------------------------------------------------------------------- /blog-cms/src/api/visitor.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getVisitorList(queryInfo) { 4 | return axios({ 5 | url: 'visitors', 6 | method: 'GET', 7 | params: { 8 | ...queryInfo 9 | } 10 | }) 11 | } 12 | 13 | export function deleteVisitor(id, uuid) { 14 | return axios({ 15 | url: 'visitor', 16 | method: 'DELETE', 17 | params: { 18 | id, 19 | uuid 20 | } 21 | }) 22 | } -------------------------------------------------------------------------------- /blog-cms/src/assets/css/base.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | #app { 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | 9 | input::-webkit-outer-spin-button, 10 | input::-webkit-inner-spin-button { 11 | -webkit-appearance: none; 12 | } 13 | 14 | input[type="number"] { 15 | -moz-appearance: textfield; 16 | } 17 | 18 | .el-breadcrumb { 19 | margin-bottom: 15px; 20 | } 21 | 22 | .el-card { 23 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) !important; 24 | } 25 | 26 | .el-table { 27 | margin-top: 15px; 28 | margin-bottom: 15px; 29 | } 30 | 31 | .el-table th, .el-table td { 32 | text-align: center !important; 33 | } 34 | 35 | .el-table th { 36 | background-color: #f8f8f9 !important; 37 | } 38 | 39 | .el-table .table-expand label { 40 | font-weight: 700; 41 | } 42 | 43 | .el-table .table-expand .el-form-item { 44 | margin-bottom: 0; 45 | } 46 | 47 | .el-table .table-expand .el-form-item__content { 48 | text-align: left; 49 | } 50 | 51 | .me-red { 52 | background: #DD3C3C; 53 | } 54 | 55 | .me-orange { 56 | background: #F27E31; 57 | } 58 | 59 | .me-yellow { 60 | background: #FAC21F; 61 | } 62 | 63 | .me-olive { 64 | background: #BBCF2D; 65 | } 66 | 67 | .me-green { 68 | background: #36BF56; 69 | } 70 | 71 | .me-teal { 72 | background: #18BBB3; 73 | } 74 | 75 | .me-blue { 76 | background: #368FD3; 77 | } 78 | 79 | .me-violet { 80 | background: #7248CD; 81 | } 82 | 83 | .me-purple { 84 | background: #AB46CC; 85 | } 86 | 87 | .me-pink { 88 | background: #E14BA0; 89 | } 90 | 91 | .me-brown { 92 | background: #AC7551; 93 | } 94 | 95 | .me-grey { 96 | background: #828282; 97 | } 98 | 99 | .me-black { 100 | background: #303132; 101 | } -------------------------------------------------------------------------------- /blog-cms/src/assets/css/icon/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/src/assets/css/icon/iconfont.eot -------------------------------------------------------------------------------- /blog-cms/src/assets/css/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/src/assets/css/icon/iconfont.ttf -------------------------------------------------------------------------------- /blog-cms/src/assets/css/icon/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/src/assets/css/icon/iconfont.woff -------------------------------------------------------------------------------- /blog-cms/src/assets/css/icon/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/src/assets/css/icon/iconfont.woff2 -------------------------------------------------------------------------------- /blog-cms/src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-cms/src/assets/img/logo.png -------------------------------------------------------------------------------- /blog-cms/src/common/reg.js: -------------------------------------------------------------------------------- 1 | export const checkEmail = (rule, value, callback) => { 2 | const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 3 | if (reg.test(value)) { 4 | return callback() 5 | } 6 | callback(new Error('请输入合法的邮箱')) 7 | } 8 | 9 | export const checkIpv4 = (rule, value, callback) => { 10 | const reg = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ 11 | if (reg.test(value)) { 12 | return callback() 13 | } 14 | callback(new Error('请输入合法的 ipv4 地址')) 15 | } 16 | 17 | export const checkIpv6 = (rule, value, callback) => { 18 | const reg = /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i 19 | if (reg.test(value)) { 20 | return callback() 21 | } 22 | callback(new Error('请输入合法的 ipv6 地址')) 23 | } 24 | 25 | export const checkNumber = (rule, value, callback) => { 26 | const reg = /^\d{1,}$/ 27 | if (reg.test(value)) { 28 | return callback() 29 | } 30 | callback(new Error('请输入纯数字')) 31 | } -------------------------------------------------------------------------------- /blog-cms/src/components/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /blog-cms/src/components/SvgIcon.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | 24 | -------------------------------------------------------------------------------- /blog-cms/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import './assets/css/base.css' 6 | import './assets/css/icon/iconfont.css' 7 | 8 | //element-ui 9 | import Element from 'element-ui' 10 | import 'element-ui/lib/theme-chalk/index.css' 11 | //moment 12 | import './util/dateTimeFormatUtils.js' 13 | 14 | Vue.use(Element) 15 | 16 | 17 | Vue.prototype.msgSuccess = function (msg) { 18 | this.$message.success(msg) 19 | } 20 | 21 | Vue.prototype.msgError = function (msg) { 22 | this.$message.error(msg) 23 | } 24 | 25 | Vue.prototype.msgInfo = function (msg) { 26 | this.$message.info(msg); 27 | } 28 | 29 | 30 | Vue.config.productionTip = false 31 | 32 | new Vue({ 33 | router, 34 | store, 35 | render: h => h(App) 36 | }).$mount('#app') 37 | -------------------------------------------------------------------------------- /blog-cms/src/plugins/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import NProgress from 'nprogress' 3 | import 'nprogress/nprogress.css' 4 | import {Message} from "element-ui" 5 | 6 | const request = axios.create({ 7 | baseURL: 'http://localhost:8090/admin/', 8 | timeout: 10000, 9 | }) 10 | 11 | let CancelToken = axios.CancelToken 12 | 13 | // 请求拦截 14 | request.interceptors.request.use( 15 | config => { 16 | //对于访客模式,除GET请求外,都拦截并提示 17 | const userJson = window.localStorage.getItem('user') || '{}' 18 | const user = JSON.parse(userJson) 19 | if (userJson !== '{}' && user.role !== 'ROLE_admin' && config.method !== 'get') { 20 | config.cancelToken = new CancelToken(function executor(cancel) { 21 | cancel('演示模式,不允许操作') 22 | }) 23 | return config 24 | } 25 | NProgress.start() 26 | const token = window.localStorage.getItem('token') 27 | if (token) { 28 | config.headers.Authorization = token 29 | } 30 | return config 31 | } 32 | ) 33 | 34 | // 响应拦截 35 | request.interceptors.response.use( 36 | config => { 37 | NProgress.done() 38 | return config.data 39 | }, error => { 40 | if (error.message === '演示模式,不允许操作') { 41 | Message.error(error) 42 | } 43 | } 44 | ) 45 | 46 | export default request -------------------------------------------------------------------------------- /blog-cms/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import {SAVE_NAV_STATE, SAVE_WEB_TITLE_SUFFIX} from './mutations-types' 4 | 5 | Vue.use(Vuex) 6 | 7 | const state = { 8 | activePath: '', 9 | webTitleSuffix: '' 10 | } 11 | 12 | const actions = {} 13 | 14 | const mutations = { 15 | [SAVE_NAV_STATE](state, activePath) { 16 | state.activePath = activePath 17 | }, 18 | [SAVE_WEB_TITLE_SUFFIX](state, webTitleSuffix) { 19 | state.webTitleSuffix = webTitleSuffix 20 | } 21 | } 22 | 23 | export default new Vuex.Store({ 24 | state, 25 | actions, 26 | mutations, 27 | modules: {} 28 | }) 29 | -------------------------------------------------------------------------------- /blog-cms/src/store/mutations-types.js: -------------------------------------------------------------------------------- 1 | export const SAVE_NAV_STATE = 'saveNavState' 2 | export const SAVE_WEB_TITLE_SUFFIX = 'saveWebTitleSuffix' -------------------------------------------------------------------------------- /blog-cms/src/util/dateTimeFormatUtils.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import moment from 'moment' 3 | 4 | Vue.filter('dateFormat', function (value, format = 'YYYY-MM-DD HH:mm:ss') { 5 | return moment(value).format(format) 6 | }) -------------------------------------------------------------------------------- /blog-cms/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | configureWebpack: { 3 | resolve: { 4 | alias: { 5 | 'assets': '@/assets', 6 | 'common': '@/common', 7 | 'components': '@/components', 8 | 'api': '@/api', 9 | 'views': '@/views', 10 | 'plugins': '@/plugins' 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /blog-view/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /blog-view/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog-view", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.21.1", 11 | "core-js": "^3.6.5", 12 | "element-ui": "^2.13.2", 13 | "moment": "^2.27.0", 14 | "nprogress": "^0.2.0", 15 | "sanitize-html": "^2.3.3", 16 | "semantic-ui-css": "^2.4.1", 17 | "semantic-ui-vue": "^0.11.0", 18 | "v-viewer": "^1.5.1", 19 | "vue": "^2.6.11", 20 | "vue-router": "^3.2.0", 21 | "vuex": "^3.4.0" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "~4.4.0", 25 | "@vue/cli-plugin-router": "~4.4.0", 26 | "@vue/cli-plugin-vuex": "~4.4.0", 27 | "@vue/cli-service": "~4.4.0", 28 | "vue-template-compiler": "^2.6.11" 29 | }, 30 | "browserslist": [ 31 | "> 1%", 32 | "last 2 versions", 33 | "not dead" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /blog-view/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/favicon.ico -------------------------------------------------------------------------------- /blog-view/public/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/avatar.jpg -------------------------------------------------------------------------------- /blog-view/public/img/comment-avatar/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/comment-avatar/1.jpg -------------------------------------------------------------------------------- /blog-view/public/img/comment-avatar/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/comment-avatar/2.jpg -------------------------------------------------------------------------------- /blog-view/public/img/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/error.png -------------------------------------------------------------------------------- /blog-view/public/img/paper-plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/paper-plane.png -------------------------------------------------------------------------------- /blog-view/public/img/qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/qr.png -------------------------------------------------------------------------------- /blog-view/public/img/reward.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/public/img/reward.jpg -------------------------------------------------------------------------------- /blog-view/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Blog 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /blog-view/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /blog-view/src/api/about.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getAbout() { 4 | return axios({ 5 | url: 'about', 6 | method: 'GET' 7 | }) 8 | } -------------------------------------------------------------------------------- /blog-view/src/api/archives.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getArchives() { 4 | return axios({ 5 | url: 'archives', 6 | method: 'GET' 7 | }) 8 | } -------------------------------------------------------------------------------- /blog-view/src/api/blog.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getBlogById(token, id) { 4 | return axios({ 5 | url: 'blog', 6 | method: 'GET', 7 | headers: { 8 | Authorization: token, 9 | }, 10 | params: { 11 | id 12 | } 13 | }) 14 | } 15 | 16 | export function checkBlogPassword(blogPasswordForm) { 17 | return axios({ 18 | url: 'checkBlogPassword', 19 | method: 'POST', 20 | data: { 21 | ...blogPasswordForm 22 | } 23 | }) 24 | } 25 | 26 | export function getSearchBlogList(query) { 27 | return axios({ 28 | url: 'searchBlog', 29 | method: 'GET', 30 | params: { 31 | query 32 | } 33 | }) 34 | } -------------------------------------------------------------------------------- /blog-view/src/api/category.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getBlogListByCategoryName(categoryName, pageNum) { 4 | return axios({ 5 | url: 'category', 6 | method: 'GET', 7 | params: { 8 | categoryName, 9 | pageNum 10 | } 11 | }) 12 | } -------------------------------------------------------------------------------- /blog-view/src/api/comment.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getCommentListByQuery(token, query) { 4 | return axios({ 5 | url: 'comments', 6 | method: 'GET', 7 | headers: { 8 | Authorization: token, 9 | }, 10 | params: { 11 | ...query 12 | } 13 | }) 14 | } 15 | 16 | export function submitComment(token, form) { 17 | return axios({ 18 | url: 'comment', 19 | method: 'POST', 20 | headers: { 21 | Authorization: token, 22 | }, 23 | data: { 24 | ...form 25 | } 26 | }) 27 | } -------------------------------------------------------------------------------- /blog-view/src/api/friend.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getData() { 4 | return axios({ 5 | url: 'friends', 6 | method: 'GET' 7 | }) 8 | } 9 | 10 | export function addViewsByNickname(nickname) { 11 | return axios({ 12 | url: 'friend', 13 | method: 'POST', 14 | params: { 15 | nickname 16 | } 17 | }) 18 | } -------------------------------------------------------------------------------- /blog-view/src/api/home.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getBlogList(pageNum) { 4 | return axios({ 5 | url: 'blogs', 6 | method: 'GET', 7 | params: { 8 | pageNum 9 | } 10 | }) 11 | } -------------------------------------------------------------------------------- /blog-view/src/api/index.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getHitokoto() { 4 | return axios({ 5 | url: 'https://v1.hitokoto.cn/?c=a', 6 | method: 'GET' 7 | }) 8 | } 9 | 10 | export function getSite() { 11 | return axios({ 12 | url: 'site', 13 | method: 'GET' 14 | }) 15 | } -------------------------------------------------------------------------------- /blog-view/src/api/login.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function login(loginForm) { 4 | return axios({ 5 | url: 'login', 6 | method: 'POST', 7 | data: { 8 | ...loginForm 9 | } 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /blog-view/src/api/moment.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getMomentListByPageNum(token, pageNum) { 4 | return axios({ 5 | url: 'moments', 6 | method: 'GET', 7 | headers: { 8 | Authorization: token, 9 | }, 10 | params: { 11 | pageNum 12 | } 13 | }) 14 | } 15 | 16 | export function likeMoment(id) { 17 | return axios({ 18 | url: `moment/like/${id}`, 19 | method: 'POST', 20 | }) 21 | } -------------------------------------------------------------------------------- /blog-view/src/api/tag.js: -------------------------------------------------------------------------------- 1 | import axios from '@/plugins/axios' 2 | 3 | export function getBlogListByTagName(tagName, pageNum) { 4 | return axios({ 5 | url: 'tag', 6 | method: 'GET', 7 | params: { 8 | tagName, 9 | pageNum 10 | } 11 | }) 12 | } -------------------------------------------------------------------------------- /blog-view/src/assets/css/badge.css: -------------------------------------------------------------------------------- 1 | .github-badge { 2 | display: inline-block; 3 | border-radius: 4px; 4 | text-shadow: none; 5 | font-size: 12px; 6 | color: #fff; 7 | line-height: 15px; 8 | background-color: #000; 9 | margin: 5px 8px 10 | } 11 | 12 | .github-badge .badge-subject { 13 | display: inline-block; 14 | background-color: #505050; 15 | padding: 4px 6px 4px 6px; 16 | border-top-left-radius: 4px; 17 | border-bottom-left-radius: 4px; 18 | } 19 | 20 | .github-badge .badge-value { 21 | display: inline-block; 22 | padding: 4px 6px 4px 6px; 23 | border-top-right-radius: 4px; 24 | border-bottom-right-radius: 4px 25 | } 26 | 27 | .github-badge .bg-brightgreen { 28 | background-color: #4dc820 !important 29 | } 30 | 31 | .github-badge .bg-orange { 32 | background-color: orange !important 33 | } 34 | 35 | .github-badge .bg-yellow { 36 | background-color: #d8b024 !important 37 | } 38 | 39 | .github-badge .bg-blueviolet { 40 | background-color: #8833d7 !important 41 | } 42 | 43 | .github-badge .bg-pink { 44 | background-color: #f26bae !important 45 | } 46 | 47 | .github-badge .bg-red { 48 | background-color: #e05d44 !important 49 | } 50 | 51 | .github-badge .bg-blue { 52 | background-color: #007ec6 !important 53 | } 54 | 55 | .github-badge .bg-semantic-ui { 56 | background-color: #35bdb2 !important 57 | } 58 | 59 | .github-badge .bg-github { 60 | background-color: #747d8c !important 61 | } 62 | 63 | .github-badge .bg-lightgray { 64 | background-color: #9f9f9f !important 65 | } 66 | 67 | .github-badge .bg-gray { 68 | background-color: #555555 !important 69 | } 70 | 71 | .github-badge .bg-lightgray { 72 | background-color: #9f9f9f !important 73 | } -------------------------------------------------------------------------------- /blog-view/src/assets/css/icon/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/src/assets/css/icon/iconfont.eot -------------------------------------------------------------------------------- /blog-view/src/assets/css/icon/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1993827", 3 | "name": "blog-view", 4 | "font_family": "ali-iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "1139074", 10 | "name": "箭头下", 11 | "font_class": "down", 12 | "unicode": "e624", 13 | "unicode_decimal": 58916 14 | }, 15 | { 16 | "icon_id": "3176645", 17 | "name": "GitHub", 18 | "font_class": "github", 19 | "unicode": "ea0a", 20 | "unicode_decimal": 59914 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /blog-view/src/assets/css/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/src/assets/css/icon/iconfont.ttf -------------------------------------------------------------------------------- /blog-view/src/assets/css/icon/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/src/assets/css/icon/iconfont.woff -------------------------------------------------------------------------------- /blog-view/src/assets/css/icon/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rawchen/Blog/af84856da254e726f7f26c14991de8753b1c3b94/blog-view/src/assets/css/icon/iconfont.woff2 -------------------------------------------------------------------------------- /blog-view/src/common/reg.js: -------------------------------------------------------------------------------- 1 | export const checkEmail = (rule, value, callback) => { 2 | const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 3 | if (reg.test(value)) { 4 | return callback() 5 | } 6 | callback(new Error('请输入合法的邮箱')) 7 | } 8 | 9 | export const checkUrl = (rule, value, callback) => { 10 | const reg = /^(((ht)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?$/ 11 | if (reg.test(value)) { 12 | return callback() 13 | } 14 | callback(new Error('请输入合法的 URL')) 15 | } -------------------------------------------------------------------------------- /blog-view/src/components/blog/BlogList.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 33 | 34 | -------------------------------------------------------------------------------- /blog-view/src/components/blog/Pagination.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 57 | 58 | -------------------------------------------------------------------------------- /blog-view/src/components/comment/CommentList.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 48 | 49 | -------------------------------------------------------------------------------- /blog-view/src/components/comment/Pagination.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 27 | 28 | -------------------------------------------------------------------------------- /blog-view/src/components/index/BlogPasswordDialog.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 62 | 63 | -------------------------------------------------------------------------------- /blog-view/src/components/index/MyAPlayer.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /blog-view/src/components/sidebar/Tags.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | -------------------------------------------------------------------------------- /blog-view/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | //自定义css 6 | import './assets/css/base.css' 7 | //阿里icon 8 | import './assets/css/icon/iconfont.css' 9 | //typo.css 10 | import "./assets/css/typo.css"; 11 | //semantic-ui-vue 12 | import SuiVue from 'semantic-ui-vue' 13 | import 'semantic-ui-css/semantic.min.css' 14 | //element-ui 15 | import Element from 'element-ui' 16 | import 'element-ui/lib/theme-chalk/index.css' 17 | //moment 18 | import './util/dateTimeFormatUtils.js' 19 | //v-viewer 20 | import 'viewerjs/dist/viewer.css' 21 | import Viewer from 'v-viewer' 22 | //directive 23 | import './util/directive' 24 | 25 | console.log("\n %c YOYLING's Blog %c https://yoyling.com \n", "color: #48dbfb; background: #1b1c1d; padding:5px 0;", "background: #fadfa3; padding:5px 0;") 26 | 27 | Vue.use(SuiVue) 28 | Vue.use(Element) 29 | Vue.use(Viewer) 30 | 31 | Vue.prototype.msgSuccess = function (msg) { 32 | this.$message.success(msg) 33 | } 34 | 35 | Vue.prototype.msgError = function (msg) { 36 | this.$message.error(msg) 37 | } 38 | 39 | Vue.prototype.msgInfo = function (msg) { 40 | this.$message.info(msg); 41 | } 42 | 43 | const cubic = value => Math.pow(value, 3); 44 | const easeInOutCubic = value => value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2; 45 | //滚动至页面顶部,使用 Element-ui 回到顶部 组件中的算法 46 | Vue.prototype.scrollToTop = function () { 47 | const el = document.documentElement 48 | const beginTime = Date.now() 49 | const beginValue = el.scrollTop 50 | const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16)) 51 | const frameFunc = () => { 52 | const progress = (Date.now() - beginTime) / 500; 53 | if (progress < 1) { 54 | el.scrollTop = beginValue * (1 - easeInOutCubic(progress)) 55 | rAF(frameFunc) 56 | } else { 57 | el.scrollTop = 0 58 | } 59 | } 60 | rAF(frameFunc) 61 | } 62 | 63 | 64 | Vue.config.productionTip = false 65 | 66 | new Vue({ 67 | router, 68 | store, 69 | render: h => h(App) 70 | }).$mount('#app') 71 | -------------------------------------------------------------------------------- /blog-view/src/plugins/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import NProgress from 'nprogress' 3 | import 'nprogress/nprogress.css' 4 | 5 | const request = axios.create({ 6 | baseURL: 'http://localhost:8090/', 7 | timeout: 10000, 8 | }) 9 | 10 | // 请求拦截 11 | request.interceptors.request.use( 12 | config => { 13 | NProgress.start() 14 | const identification = window.localStorage.getItem('identification') 15 | //identification存在,且是基于baseURL的请求 16 | if (identification && !(config.url.startsWith('http://') || config.url.startsWith('https://'))) { 17 | config.headers.identification = identification 18 | } 19 | return config 20 | } 21 | ) 22 | 23 | // 响应拦截 24 | request.interceptors.response.use( 25 | config => { 26 | NProgress.done() 27 | const identification = config.headers.identification 28 | if (identification) { 29 | //保存身份标识到localStorage 30 | window.localStorage.setItem('identification', identification) 31 | } 32 | return config.data 33 | } 34 | ) 35 | 36 | export default request -------------------------------------------------------------------------------- /blog-view/src/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 3 | } -------------------------------------------------------------------------------- /blog-view/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import state from './state' 4 | import actions from './actions' 5 | import mutations from './mutations' 6 | import getters from './getters' 7 | 8 | Vue.use(Vuex) 9 | 10 | export default new Vuex.Store({ 11 | state, 12 | actions, 13 | mutations, 14 | getters 15 | }) 16 | -------------------------------------------------------------------------------- /blog-view/src/store/mutations-types.js: -------------------------------------------------------------------------------- 1 | export const SAVE_INTRODUCTION = 'saveIntroduction' 2 | export const SAVE_SITE_INFO = 'saveSiteInfo' 3 | export const SAVE_COMMENT_RESULT = 'saveCommentResult' 4 | export const SET_COMMENT_QUERY_PAGE = 'setCommentQueryPage' 5 | export const SET_COMMENT_QUERY_BLOG_ID = 'setCommentQueryBlogId' 6 | export const SET_COMMENT_QUERY_PAGE_NUM = 'setCommentQueryPageNum' 7 | export const SET_PARENT_COMMENT_ID = 'setParentCommentId' 8 | export const RESET_COMMENT_FORM = 'resetCommentForm' 9 | export const RESTORE_COMMENT_FORM = 'restoreCommentForm' 10 | export const SET_IS_BLOG_RENDER_COMPLETE = 'setIsBlogRenderComplete' 11 | export const SET_BLOG_PASSWORD_DIALOG_VISIBLE = 'setBlogPasswordDialogVisible' 12 | export const SET_BLOG_PASSWORD_FORM = 'setBlogPasswordForm' 13 | export const SET_FOCUS_MODE = 'setFocusMode' 14 | export const SET_IS_BLOG_TO_HOME = 'setIsBlogToHome' 15 | export const SAVE_CLIENT_SIZE = 'saveClientSize' -------------------------------------------------------------------------------- /blog-view/src/store/state.js: -------------------------------------------------------------------------------- 1 | export default { 2 | siteInfo: '', 3 | introduction: { 4 | avatar: '', 5 | name: '', 6 | rollText: [], 7 | }, 8 | //用于后端判断该评论所在页面类型(文章、友链、关于我) 9 | commentQuery: { 10 | page: 0, 11 | blogId: null, 12 | pageNum: 1, 13 | pageSize: 5 14 | }, 15 | commentCount: 0, 16 | commentTotalPage: 0, 17 | comments: [], 18 | parentCommentId: -1, 19 | commentForm: { 20 | content: '', 21 | nickname: '', 22 | email: '', 23 | website: '', 24 | notice: true 25 | }, 26 | //博客文章渲染完成的标记 27 | isBlogRenderComplete: false, 28 | //受保护文章密码对话框 29 | blogPasswordDialogVisible: false, 30 | blogPasswordForm: { 31 | blogId: 0, 32 | password: '' 33 | }, 34 | //专注模式 35 | focusMode: false, 36 | //文章页面路由到首页的标记 37 | isBlogToHome: false, 38 | //可视窗口大小 39 | clientSize: { 40 | clientHeight: 0, 41 | clientWidth: 1080 42 | } 43 | } -------------------------------------------------------------------------------- /blog-view/src/util/dateTimeFormatUtils.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import moment from 'moment' 3 | 4 | //设置moment国际化语言 5 | moment.locale('zh-cn') 6 | 7 | Vue.filter('dateFormat', function (value, format = 'YYYY-MM-DD HH:mm:ss') { 8 | return moment(value).format(format) 9 | }) 10 | 11 | Vue.filter('dateFromNow', function (value) { 12 | //相对时间大于一个月,显示详细时间 13 | if (moment().diff(moment(value)) > 2592000000) { 14 | return moment(value).format('YYYY-MM-DD HH:mm') 15 | } 16 | return moment(value).fromNow() 17 | }) -------------------------------------------------------------------------------- /blog-view/src/util/directive.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | /** 4 | * 防抖 单位时间只触发最后一次 5 | * 例:刷新 6 | * 简写:刷新 7 | */ 8 | Vue.directive('debounce', { 9 | inserted: function (el, binding) { 10 | let [fn, event = "click", time = 300] = binding.value 11 | let timer 12 | el.addEventListener(event, () => { 13 | timer && clearTimeout(timer) 14 | timer = setTimeout(() => fn(), time) 15 | }) 16 | } 17 | }) 18 | 19 | /** 20 | * 节流 每单位时间可触发一次 21 | * 例:刷新 22 | * 传递参数:刷新 23 | */ 24 | Vue.directive('throttle', { 25 | inserted: function (el, binding) { 26 | let [fn, event = "click", time = 300] = binding.value 27 | let now, preTime 28 | el.addEventListener(event, () => { 29 | now = new Date() 30 | if (!preTime || now - preTime > time) { 31 | preTime = now 32 | fn() 33 | } 34 | }) 35 | } 36 | }) 37 | -------------------------------------------------------------------------------- /blog-view/src/views/about/About.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 51 | 52 | -------------------------------------------------------------------------------- /blog-view/src/views/category/Category.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 58 | 59 | -------------------------------------------------------------------------------- /blog-view/src/views/home/Home.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 59 | 60 | -------------------------------------------------------------------------------- /blog-view/src/views/tag/Tag.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 58 | 59 | -------------------------------------------------------------------------------- /blog-view/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | configureWebpack: { 3 | resolve: { 4 | alias: { 5 | 'assets': '@/assets', 6 | 'common': '@/common', 7 | 'components': '@/components', 8 | 'api': '@/api', 9 | 'views': '@/views', 10 | 'plugins': '@/plugins' 11 | } 12 | } 13 | } 14 | } --------------------------------------------------------------------------------