release 1.0.3 (#235)

release 1.0.3

Co-authored-by: John Niang <johnniang@riseup.net>
pull/286/head^2 v1.0.3
Ryan Wang 2019-07-09 21:48:31 +08:00 committed by GitHub
commit 117883fc8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
164 changed files with 1772 additions and 1422 deletions

View File

@ -1,148 +0,0 @@
![](https://i.loli.net/2018/12/21/5c1cd34849751.png)
> Halo may be the best Java blog system.
<p align="center">
<a href="https://ryanc.cc"><img alt="Author" src="https://img.shields.io/badge/author-ruibaby-red.svg?style=flat-square"/></a>
<a href="#"><img alt="JDK" src="https://img.shields.io/badge/JDK-1.8-yellow.svg?style=flat-square"/></a>
<a href="https://github.com/ruibaby/halo/releases"><img alt="GitHub release" src="https://img.shields.io/github/release/ruibaby/halo.svg?style=flat-square"/></a>
<a href="https://travis-ci.org/ruibaby/halo"><img alt="Travis CI" src="https://img.shields.io/travis/ruibaby/halo.svg?style=flat-square"/></a>
<a href="https://hub.docker.com/r/ruibaby/halo/"><img alt="Docker Build Status" src="https://img.shields.io/docker/build/ruibaby/halo.svg?style=flat-square"/></a>
</p>
------------------------------
🇨🇳[简体中文](README.md) | 🇺🇸English
## Introduction
**Halo** [ˈheɪloʊ], Become the best blogging system using Java.
Fast, concise, and powerful blogging system developed in Java.
> QQ Group: 162747721Telegram Group: [https://t.me/HaloBlog](https://t.me/HaloBlog) | Telegram Channel: [https://t.me/halo_dev](https://t.me/halo_dev) | [WeHalo 小程序](https://github.com/aquanlerou/WeHalo)。
## Demo
> Frontend: [https://demo.halo.run](https://demo.halo.run)
> Backend: [https://demo.halo.run/admin](https://demo.halo.run/admin)
> username: admin,password: 123456
## Quick start
Deploy with Docker
```bash
# pull docker images
$ docker pull ruibaby/halo
# create docker container and run it
$ docker run -d --name halo -p 8090:8090 -v ~/halo:/root/halo ruibaby/halo
# TipsDB_USER and DB_PASSWORD must be repaired and recorded
```
Deploy with Docker compose
```bash
# Download the nginx config file template
$ curl https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl > /etc/nginx/nginx.tmpl
# Get the docker-compose.yaml
$ yum install -y wget && wget -O docker-compose.yaml https://git.io/fpS8N
# Modify docker-compose.yaml
# 1. modify VIRTUAL_HOST, LETSENCRYPT_HOST for your own domain name.
# 2. modify LETSENCRYPT_EMAIL to your own mailbox.
# 3. modify DB_USER .
# 4. modify DB_PASSWORD .
# run
$ docker-compose up -d
```
Deploy with shell script
```bash
# install Halo
$ yum install -y wget && wget -O halo-cli.sh https://git.io/fxHqp && bash halo-cli.sh -i
# upgrade Halo
$ bash halo-cli.sh -u
```
> Tips: If you use Idea, Eclipse and other IDEs to run, you need to install the Lombok plugin, In addition, JDK10 is not supported at the moment, and there are problems with themes scanning and uploading.
> See the [Halo documentation](https://halo-doc.ryanc.cc/installation/) or [ Wiki](https://github.com/halo-dev/halo/wiki) for more details.
## Blogs with Halo
[Ryan0up'S Blog](https://ryanc.cc)
[SNAIL BLOG](https://slogc.cc)
[宋浩志博客](http://songhaozhi.com)
[KingYiFan'S Blog](https://blog.cnbuilder.cn)
[AquanBlog](https://blog.eunji.cn/)
## Themes
In addition to the built-in [Anatole](https://github.com/hi-caicai/farbox-theme-Anatole) and [Material](https://github.com/viosey/hexo-theme-material), there are the following The theme is not integrated in the project. If you need it, please download it and upload it through the background.
- [Vno](https://github.com/halo-dev/vno-halo) - From Jekyll,Author [Wei Wang](https://onevcat.com/).
- [Hux](https://github.com/halo-dev/hux-halo) - From Jekyll,Author [Xuan Huang](https://huangxuan.me/).
- [Story](https://github.com/halo-dev/story-halo) - From Typecho,Author [Trii Hsia](https://yumoe.com/).
- [NexT](https://github.com/halo-dev/next-halo) - From Hexo,Author [iissnan](https://notes.iissnan.com/).
- [Casper](https://github.com/halo-dev/casper-halo) - From Ghost,Author [Ghost](https://github.com/TryGhost).
- [Pinghsu](https://github.com/halo-dev/pinghsu-halo) - From Typecho,Author [Chakhsu.Lau](https://github.com/chakhsu).
> Disclaimer: Do not accept any comments or suggestions on the functionality of the **Porting Theme**.
## License
[![license](https://img.shields.io/github/license/halo-dev/halo.svg?style=flat-square)](https://github.com/halo-dev/halo/blob/master/LICENSE)
> Halo uses the GPL-v3.0 protocol to open source.
## Thanks
The birth of Halo is inseparable from the following projects
- [Spring Boot](https://github.com/spring-projects/spring-boot): Spring's rapid development framework
- [Freemarker](https://freemarker.apache.org/): Template engine to make pages static
- [H2 Database](https://github.com/h2database/h2database): Embedded database, no need to install
- [Spring-data-jpa](https://github.com/spring-projects/spring-data-jpa.git): a persistence layer framework that does not require writing sql statements
- [Ehcache](http://www.ehcache.org/): Cache Framework
- [Lombok](https://www.projectlombok.org/): Make the code simpler
- [oh-my-email](https://github.com/biezhi/oh-my-email): Probably the smallest Java mailing library, support for CC, attachments, templates, etc.
- [Hutool](https://github.com/looly/hutool): A Java Foundation Tools library
- [Thumbnailator](https://github.com/coobird/thumbnailator): thumbnail generation library
- [AdminLTE](https://github.com/almasaeed2010/AdminLTE): Bootstrap-based background template
- [Bootstrap](https://github.com/twbs/bootstrap.git): The most widely used front-end ui framework
- [Animate](https://github.com/daneden/animate.css.git): Very easy to use css effects library
- [SimpleMDE - Markdown Editor](https://github.com/sparksuite/simplemde-markdown-editor): Simple, functional, and lightweight Markdown editor
- [Bootstrap-FileInput](https://github.com/kartik-v/bootstrap-fileinput.git): Bootstrap-based file upload component
- [Font-awesome](https://github.com/FortAwesome/Font-Awesome.git): the most widely used font icon library
- [JQuery](https://github.com/jquery/jquery.git): The most widely used JavaScript framework
- [Layer](https://github.com/sentsin/layer.git): Personally think that the most practical and best-looking pop-up layer component, no one
- [JQuery-Toast](https://github.com/kamranahmedse/jquery-toast-plugin)
: message prompt component
- [Pjax](https://github.com/defunkt/jquery-pjax.git): pushState + ajax = pjax
## Donate
> If Halo is helpful to you, ask the author to have a ☕.
| AliPay/WeChat/QQ/PayPal |
| :------------: |
| <img src="https://i.loli.net/2018/12/23/5c1f68ce9b884.png" width="200"/> |
## Interface display
![](https://i.loli.net/2018/12/16/5c15b6edb9a49.png)
![](https://i.loli.net/2018/12/16/5c15b6ee08333.png)
![](https://i.loli.net/2018/12/16/5c15b6ec853af.png)
![](https://i.loli.net/2018/12/16/5c15b6ec50238.png)
![](https://i.loli.net/2018/12/16/5c15b6ed4057a.png)
![](https://i.loli.net/2018/12/16/5c15b6eb01f2d.png)
![](https://i.loli.net/2018/12/16/5c15b6eb98898.png)
![](https://i.loli.net/2018/12/16/5c15b6eb3b506.png)
![](https://i.loli.net/2018/12/16/5c15b6ebf29fd.png)

View File

@ -26,13 +26,13 @@
### 下载最新的 Halo 安装包 ### 下载最新的 Halo 安装包
```bash ```bash
curl -L https://github.com/halo-dev/halo/releases/download/v1.0.2/halo-1.0.2.jar --output halo-latest.jar curl -L https://github.com/halo-dev/halo/releases/download/v1.0.3/halo-1.0.3.jar --output halo-latest.jar
``` ```
或者 或者
```bash ```bash
wget https://github.com/halo-dev/halo/releases/download/v1.0.2/halo-1.0.2.jar -O halo-latest.jar wget https://github.com/halo-dev/halo/releases/download/v1.0.3/halo-1.0.3.jar -O halo-latest.jar
``` ```
### 启动 Halo ### 启动 Halo

View File

@ -9,7 +9,7 @@ apply plugin: 'io.spring.dependency-management'
group = 'run.halo.app' group = 'run.halo.app'
archivesBaseName = 'halo' archivesBaseName = 'halo'
version = '1.0.2' version = '1.0.3'
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
description = 'Halo, personal blog system developed in Java.' description = 'Halo, personal blog system developed in Java.'
@ -55,13 +55,6 @@ dependencies {
implementation 'com.qiniu:qiniu-java-sdk:7.2.18' implementation 'com.qiniu:qiniu-java-sdk:7.2.18'
implementation 'com.aliyun.oss:aliyun-sdk-oss:3.4.2' implementation 'com.aliyun.oss:aliyun-sdk-oss:3.4.2'
implementation 'net.coobird:thumbnailator:0.4.8' implementation 'net.coobird:thumbnailator:0.4.8'
implementation 'com.atlassian.commonmark:commonmark:0.12.1'
implementation 'com.atlassian.commonmark:commonmark-ext-gfm-tables:0.12.1'
implementation 'com.atlassian.commonmark:commonmark-ext-yaml-front-matter:0.12.1'
implementation 'com.atlassian.commonmark:commonmark-ext-autolink:0.12.1'
implementation 'com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:0.12.1'
implementation 'com.atlassian.commonmark:commonmark-ext-heading-anchor:0.12.1'
implementation 'com.atlassian.commonmark:commonmark-ext-ins:0.12.1'
implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2'
implementation 'org.apache.commons:commons-lang3:3.8.1' implementation 'org.apache.commons:commons-lang3:3.8.1'
@ -69,6 +62,20 @@ dependencies {
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.2' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.2'
implementation 'org.eclipse.jgit:org.eclipse.jgit:5.3.0.201903130848-r' implementation 'org.eclipse.jgit:org.eclipse.jgit:5.3.0.201903130848-r'
implementation 'com.vladsch.flexmark:flexmark:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-attributes:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-autolink:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-emoji:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-escaped-character:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-gfm-tasklist:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-ins:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-media-tags:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-tables:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-toc:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-ext-yaml-front-matter:0.42.12'
implementation 'com.vladsch.flexmark:flexmark-html-parser:0.42.12'
runtimeOnly 'com.h2database:h2' runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java' runtimeOnly 'mysql:mysql-connector-java'

View File

@ -147,18 +147,24 @@ public class SwaggerConfiguration {
private List<SecurityContext> contentSecurityContext() { private List<SecurityContext> contentSecurityContext() {
return Collections.singletonList( return Collections.singletonList(
SecurityContext.builder() SecurityContext.builder()
.securityReferences(defaultAuth()) .securityReferences(contentApiAuth())
.forPaths(PathSelectors.regex("/api/content/.*")) .forPaths(PathSelectors.regex("/api/content/.*"))
.build() .build()
); );
} }
private List<SecurityReference> defaultAuth() { private List<SecurityReference> defaultAuth() {
AuthorizationScope[] authorizationScopes = {new AuthorizationScope("global", "accessEverything")}; AuthorizationScope[] authorizationScopes = {new AuthorizationScope("Admin api", "Access admin api")};
return Arrays.asList(new SecurityReference("Token from header", authorizationScopes), return Arrays.asList(new SecurityReference("Token from header", authorizationScopes),
new SecurityReference("Token from query", authorizationScopes)); new SecurityReference("Token from query", authorizationScopes));
} }
private List<SecurityReference> contentApiAuth() {
AuthorizationScope[] authorizationScopes = {new AuthorizationScope("content api", "Access content api")};
return Arrays.asList(new SecurityReference("Access key from header", authorizationScopes),
new SecurityReference("Access key from query", authorizationScopes));
}
private ApiInfo apiInfo() { private ApiInfo apiInfo() {
return new ApiInfoBuilder() return new ApiInfoBuilder()
.title("Halo API Documentation") .title("Halo API Documentation")

View File

@ -81,13 +81,11 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + haloProperties.getWorkDir(); String workDir = FILE_PROTOCOL + haloProperties.getWorkDir();
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.addResourceLocations(workDir + "static/");
registry.addResourceHandler("/**") registry.addResourceHandler("/**")
.addResourceLocations(workDir + "templates/themes/") .addResourceLocations(workDir + "templates/themes/")
.addResourceLocations(workDir + "templates/admin/") .addResourceLocations(workDir + "templates/admin/")
.addResourceLocations("classpath:/admin/"); .addResourceLocations("classpath:/admin/")
.addResourceLocations(workDir + "static/");
registry.addResourceHandler("/upload/**") registry.addResourceHandler("/upload/**")
.addResourceLocations(workDir + "upload/"); .addResourceLocations(workDir + "upload/");
registry.addResourceHandler("/backup/**") registry.addResourceHandler("/backup/**")
@ -122,7 +120,7 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
configurer.setDefaultEncoding("UTF-8"); configurer.setDefaultEncoding("UTF-8");
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty("auto_import", "/common/macro/common_macro.ftl as common"); properties.setProperty("auto_import", "/common/macro/common_macro.ftl as common,/common/macro/global_macro.ftl as global");
configurer.setFreemarkerSettings(properties); configurer.setFreemarkerSettings(properties);

View File

@ -2,11 +2,13 @@ package run.halo.app.controller.admin.api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import run.halo.app.cache.lock.CacheLock; import run.halo.app.cache.lock.CacheLock;
import run.halo.app.model.dto.EnvironmentDTO; import run.halo.app.model.dto.EnvironmentDTO;
import run.halo.app.model.dto.StatisticDTO; import run.halo.app.model.dto.StatisticDTO;
import run.halo.app.model.params.LoginParam; import run.halo.app.model.params.LoginParam;
import run.halo.app.model.support.BaseResponse;
import run.halo.app.security.token.AuthToken; import run.halo.app.security.token.AuthToken;
import run.halo.app.service.AdminService; import run.halo.app.service.AdminService;
@ -16,6 +18,7 @@ import javax.validation.Valid;
* Admin controller. * Admin controller.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 3/19/19 * @date 3/19/19
*/ */
@Slf4j @Slf4j
@ -73,4 +76,9 @@ public class AdminController {
adminService.updateAdminAssets(); adminService.updateAdminAssets();
} }
@GetMapping("spring/logs")
@ApiOperation("Get application logs")
public BaseResponse<String> getSpringLogs() {
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(),adminService.getSpringLogs());
}
} }

View File

@ -40,7 +40,7 @@ public class RecoveryController {
@ApiParam("This file content type should be json") @ApiParam("This file content type should be json")
@RequestPart("file") MultipartFile file) { @RequestPart("file") MultipartFile file) {
if (optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false)) { if (optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false)) {
throw new BadRequestException("不能在博客初始化完成之后迁移数据"); throw new BadRequestException("无法在博客初始化完成之后迁移数据");
} }
recoveryService.migrateFromV0_4_3(file); recoveryService.migrateFromV0_4_3(file);

View File

@ -13,12 +13,15 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.vo.PostListVO; import run.halo.app.model.vo.PostListVO;
import run.halo.app.service.*; import run.halo.app.service.*;
import static org.springframework.data.domain.Sort.Direction.DESC; import static org.springframework.data.domain.Sort.Direction.DESC;
/** /**
* Category controller.
*
* @author ryanwang * @author ryanwang
* @date : 2019/3/20 * @date : 2019/3/20
*/ */
@ -85,10 +88,10 @@ public class ContentCategoryController {
@PathVariable("page") Integer page, @PathVariable("page") Integer page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) { @SortDefault(sort = "createTime", direction = DESC) Sort sort) {
// Get category by slug name // Get category by slug name
final Category category = categoryService.getBySlugName(slugName); final Category category = categoryService.getBySlugNameOfNonNull(slugName);
final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), sort); final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), sort);
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), pageable); Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
Page<PostListVO> posts = postService.convertToListVo(postPage); Page<PostListVO> posts = postService.convertToListVo(postPage);
final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3); final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);

View File

@ -22,7 +22,7 @@ import run.halo.app.service.ThemeService;
import static org.springframework.data.domain.Sort.Direction.DESC; import static org.springframework.data.domain.Sort.Direction.DESC;
/** /**
* Search Controller * Search controller.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-04-21 * @date : 2019-04-21

View File

@ -13,13 +13,14 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.Tag; import run.halo.app.model.entity.Tag;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.vo.PostListVO; import run.halo.app.model.vo.PostListVO;
import run.halo.app.service.*; import run.halo.app.service.*;
import static org.springframework.data.domain.Sort.Direction.DESC; import static org.springframework.data.domain.Sort.Direction.DESC;
/** /**
* Tag Controller * Tag controller.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-21 * @date : 2019-03-21
@ -91,7 +92,7 @@ public class ContentTagController {
final Tag tag = tagService.getBySlugNameOfNonNull(slugName); final Tag tag = tagService.getBySlugNameOfNonNull(slugName);
final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), sort); final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), sort);
Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), pageable); Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
Page<PostListVO> posts = postService.convertToListVo(postPage); Page<PostListVO> posts = postService.convertToListVo(postPage);
final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3); final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);

View File

@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
/** /**
* Admin page. * Main controller.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-04-23 * @date : 2019-04-23

View File

@ -11,6 +11,7 @@ import run.halo.app.model.dto.CategoryDTO;
import run.halo.app.model.dto.post.BasePostSimpleDTO; import run.halo.app.model.dto.post.BasePostSimpleDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.service.CategoryService; import run.halo.app.service.CategoryService;
import run.halo.app.service.PostCategoryService; import run.halo.app.service.PostCategoryService;
import run.halo.app.service.PostService; import run.halo.app.service.PostService;
@ -58,9 +59,9 @@ public class CategoryController {
public Page<BasePostSimpleDTO> listPostsBy(@PathVariable("slugName") String slugName, public Page<BasePostSimpleDTO> listPostsBy(@PathVariable("slugName") String slugName,
@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable) { @PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable) {
// Get category by slug name // Get category by slug name
Category category = categoryService.getBySlugName(slugName); Category category = categoryService.getBySlugNameOfNonNull(slugName);
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), pageable); Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
return postService.convertToSimple(postPage); return postService.convertToSimple(postPage);
} }
} }

View File

@ -12,6 +12,7 @@ import run.halo.app.model.dto.TagDTO;
import run.halo.app.model.dto.post.BasePostSimpleDTO; import run.halo.app.model.dto.post.BasePostSimpleDTO;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.Tag; import run.halo.app.model.entity.Tag;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.service.PostService; import run.halo.app.service.PostService;
import run.halo.app.service.PostTagService; import run.halo.app.service.PostTagService;
import run.halo.app.service.TagService; import run.halo.app.service.TagService;
@ -24,6 +25,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
* Portal tag controller. * Portal tag controller.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 4/2/19 * @date 4/2/19
*/ */
@RestController("ApiContentTagController") @RestController("ApiContentTagController")
@ -63,7 +65,7 @@ public class TagController {
Tag tag = tagService.getBySlugNameOfNonNull(slugName); Tag tag = tagService.getBySlugNameOfNonNull(slugName);
// Get posts, convert and return // Get posts, convert and return
Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), pageable); Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
return postService.convertToSimple(postPage); return postService.convertToSimple(postPage);
} }
} }

View File

@ -10,7 +10,7 @@ import static run.halo.app.utils.BeanUtils.updateProperties;
* <b>The implementation type must be equal to DTO type</b> * <b>The implementation type must be equal to DTO type</b>
* *
* @param <DTO> the implementation class type * @param <DTO> the implementation class type
* @param <DOMAIN> doamin type * @param <DOMAIN> domain type
* @author johnniang * @author johnniang
*/ */
public interface OutputConverter<DTO extends OutputConverter<DTO, DOMAIN>, DOMAIN> { public interface OutputConverter<DTO extends OutputConverter<DTO, DOMAIN>, DOMAIN> {

View File

@ -5,7 +5,6 @@ import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import run.halo.app.model.enums.PostCreateFrom; import run.halo.app.model.enums.PostCreateFrom;
import run.halo.app.model.enums.PostStatus; import run.halo.app.model.enums.PostStatus;
import run.halo.app.utils.MarkdownUtils;
import javax.persistence.*; import javax.persistence.*;
import java.util.Date; import java.util.Date;
@ -54,7 +53,7 @@ public class BasePost extends BaseEntity {
/** /**
* Rendered content. * Rendered content.
* *
* @see MarkdownUtils#renderMarkdown(String) * @see run.halo.app.utils.MarkdownUtils#renderHtml(String)
*/ */
@Column(name = "format_content", columnDefinition = "text not null") @Column(name = "format_content", columnDefinition = "text not null")
private String formatContent; private String formatContent;

View File

@ -45,6 +45,7 @@ public class CategoryTagDirective implements TemplateDirectiveModel {
case "listByPostId": case "listByPostId":
Integer postId = Integer.parseInt(params.get("postId").toString()); Integer postId = Integer.parseInt(params.get("postId").toString());
env.setVariable("categories", builder.build().wrap(postCategoryService.listCategoryBy(postId))); env.setVariable("categories", builder.build().wrap(postCategoryService.listCategoryBy(postId)));
break;
case "count": case "count":
env.setVariable("count", builder.build().wrap(categoryService.count())); env.setVariable("count", builder.build().wrap(categoryService.count()));
break; break;

View File

@ -3,6 +3,7 @@ package run.halo.app.model.freemarker.tag;
import freemarker.core.Environment; import freemarker.core.Environment;
import freemarker.template.*; import freemarker.template.*;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.support.HaloConst; import run.halo.app.model.support.HaloConst;
import run.halo.app.service.PostCategoryService; import run.halo.app.service.PostCategoryService;
import run.halo.app.service.PostService; import run.halo.app.service.PostService;
@ -57,11 +58,11 @@ public class PostTagDirective implements TemplateDirectiveModel {
break; break;
case "listByCategoryId": case "listByCategoryId":
Integer categoryId = Integer.parseInt(params.get("categoryId").toString()); Integer categoryId = Integer.parseInt(params.get("categoryId").toString());
env.setVariable("posts", builder.build().wrap(postCategoryService.listPostBy(categoryId))); env.setVariable("posts", builder.build().wrap(postCategoryService.listPostBy(categoryId, PostStatus.PUBLISHED)));
break; break;
case "listByTagId": case "listByTagId":
Integer tagId = Integer.parseInt(params.get("tagId").toString()); Integer tagId = Integer.parseInt(params.get("tagId").toString());
env.setVariable("posts", builder.build().wrap(postTagService.listPostsBy(tagId))); env.setVariable("posts", builder.build().wrap(postTagService.listPostsBy(tagId, PostStatus.PUBLISHED)));
break; break;
default: default:
break; break;

View File

@ -0,0 +1,41 @@
package run.halo.app.model.properties;
/**
* Api properties.
*
* @author ryanwang
* @date 2019-06-25
*/
public enum ApiProperties implements PropertyEnum {
API_ENABLED("api_enabled", Boolean.class, "false"),
API_ACCESS_KEY("api_access_key", String.class, "");
private final String value;
private final Class<?> type;
private final String defaultValue;
ApiProperties(String value, Class<?> type, String defaultValue) {
this.value = value;
this.type = type;
this.defaultValue = defaultValue;
}
@Override
public Class<?> getType() {
return type;
}
@Override
public String defaultValue() {
return defaultValue;
}
@Override
public String getValue() {
return value;
}
}

View File

@ -4,22 +4,14 @@ package run.halo.app.model.properties;
* Other properties. * Other properties.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 4/1/19 * @date 4/1/19
*/ */
public enum OtherProperties implements PropertyEnum { public enum OtherProperties implements PropertyEnum {
API_ENABLED("api_enabled", Boolean.class, "false"),
API_ACCESS_KEY("api_access_key", String.class, ""),
CUSTOM_HEAD("blog_custom_head",String.class,""), CUSTOM_HEAD("blog_custom_head",String.class,""),
STATISTICS_CODE("blog_statistics_code", String.class, ""), STATISTICS_CODE("blog_statistics_code", String.class, "");
/**
*
*/
SPIDER_DISABLED("spider_disabled", Boolean.class, "false");
private final String value; private final String value;

View File

@ -154,6 +154,7 @@ public interface PropertyEnum extends ValueEnum<String> {
propertyEnumClasses.add(QnYunProperties.class); propertyEnumClasses.add(QnYunProperties.class);
propertyEnumClasses.add(SeoProperties.class); propertyEnumClasses.add(SeoProperties.class);
propertyEnumClasses.add(UpYunProperties.class); propertyEnumClasses.add(UpYunProperties.class);
propertyEnumClasses.add(ApiProperties.class);
Map<String, PropertyEnum> result = new HashMap<>(); Map<String, PropertyEnum> result = new HashMap<>();

View File

@ -4,6 +4,7 @@ package run.halo.app.model.properties;
* SEO properties. * SEO properties.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 4/1/19 * @date 4/1/19
*/ */
public enum SeoProperties implements PropertyEnum { public enum SeoProperties implements PropertyEnum {
@ -14,13 +15,10 @@ public enum SeoProperties implements PropertyEnum {
BAIDU_TOKEN("seo_baidu_token", String.class, ""), BAIDU_TOKEN("seo_baidu_token", String.class, ""),
VERIFICATION_BAIDU("seo_verification_baidu", String.class, ""), /**
*
VERIFICATION_GOOGLE("seo_verification_google", String.class, ""), */
SPIDER_DISABLED("seo_spider_disabled", Boolean.class, "false");
VERIFICATION_BING("seo_verification_bing", String.class, ""),
VERIFICATION_QIHU("seo_verification_qihu", String.class, "");
private final String value; private final String value;

View File

@ -1,36 +0,0 @@
package run.halo.app.model.support;
/**
* <pre>
*
* </pre>
*
* @author ryanwang
* @date : 2018/1/19
*/
public interface LogsRecord {
String INSTALL = "初始化博客";
String LOGIN = "登录后台";
String LOGIN_SUCCESS = "登录成功";
String LOGIN_ERROR = "登录失败";
String LOGOUT = "退出登录";
String PUSH_POST = "发表文章";
String PUSH_PAGE = "发表页面";
String REMOVE_POST = "删除文章";
String CHANGE_THEME = "更换主题";
String UPLOAD_THEME = "上传主题";
String UPLOAD_FILE = "上传附件";
String REMOVE_FILE = "移除附件";
}

View File

@ -17,6 +17,7 @@ public class QiNiuPutSet {
* hash * hash
*/ */
public String hash; public String hash;
/** /**
* *
*/ */

View File

@ -3,6 +3,7 @@ package run.halo.app.repository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import run.halo.app.model.entity.PostCategory; import run.halo.app.model.entity.PostCategory;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.projection.CategoryPostCountProjection; import run.halo.app.model.projection.CategoryPostCountProjection;
import run.halo.app.repository.base.BaseRepository; import run.halo.app.repository.base.BaseRepository;
@ -14,6 +15,8 @@ import java.util.Set;
* Post category repository. * Post category repository.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 2019-03-19
*/ */
public interface PostCategoryRepository extends BaseRepository<PostCategory, Integer> { public interface PostCategoryRepository extends BaseRepository<PostCategory, Integer> {
@ -37,6 +40,17 @@ public interface PostCategoryRepository extends BaseRepository<PostCategory, Int
@Query("select postCategory.postId from PostCategory postCategory where postCategory.categoryId = ?1") @Query("select postCategory.postId from PostCategory postCategory where postCategory.categoryId = ?1")
Set<Integer> findAllPostIdsByCategoryId(@NonNull Integer categoryId); Set<Integer> findAllPostIdsByCategoryId(@NonNull Integer categoryId);
/**
* Finds all post ids by category id and post status.
*
* @param categoryId category id must not be null
* @param status post status must not be null
* @return a set of post id
*/
@NonNull
@Query("select postCategory.postId from PostCategory postCategory, Post post where postCategory.categoryId = ?1 and post.id = postCategory.postId and post.status = ?2")
Set<Integer> findAllPostIdsByCategoryId(@NonNull Integer categoryId, @NonNull PostStatus status);
/** /**
* Finds all post categories by post id in. * Finds all post categories by post id in.
* *

View File

@ -3,6 +3,7 @@ package run.halo.app.repository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import run.halo.app.model.entity.PostTag; import run.halo.app.model.entity.PostTag;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.projection.TagPostPostCountProjection; import run.halo.app.model.projection.TagPostPostCountProjection;
import run.halo.app.repository.base.BaseRepository; import run.halo.app.repository.base.BaseRepository;
@ -14,6 +15,8 @@ import java.util.Set;
* Post tag repository. * Post tag repository.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 2019-03-19
*/ */
public interface PostTagRepository extends BaseRepository<PostTag, Integer> { public interface PostTagRepository extends BaseRepository<PostTag, Integer> {
@ -55,6 +58,17 @@ public interface PostTagRepository extends BaseRepository<PostTag, Integer> {
@NonNull @NonNull
Set<Integer> findAllPostIdsByTagId(@NonNull Integer tagId); Set<Integer> findAllPostIdsByTagId(@NonNull Integer tagId);
/**
* Finds all post id by tag id and post status.
*
* @param tagId tag id must not be null
* @param status post status
* @return a set of post id
*/
@Query("select postTag.postId from PostTag postTag,Post post where postTag.tagId = ?1 and post.id = postTag.postId and post.status = ?2")
@NonNull
Set<Integer> findAllPostIdsByTagId(@NonNull Integer tagId, @NonNull PostStatus status);
/** /**
* Finds all tags by post id in. * Finds all tags by post id in.
* *

View File

@ -8,8 +8,8 @@ import org.springframework.util.Assert;
import run.halo.app.config.properties.HaloProperties; import run.halo.app.config.properties.HaloProperties;
import run.halo.app.exception.AuthenticationException; import run.halo.app.exception.AuthenticationException;
import run.halo.app.exception.ForbiddenException; import run.halo.app.exception.ForbiddenException;
import run.halo.app.model.properties.ApiProperties;
import run.halo.app.model.properties.CommentProperties; import run.halo.app.model.properties.CommentProperties;
import run.halo.app.model.properties.OtherProperties;
import run.halo.app.service.OptionService; import run.halo.app.service.OptionService;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
@ -48,7 +48,7 @@ public class ApiAuthenticationFilter extends AbstractAuthenticationFilter {
} }
// Get api_enable from option // Get api_enable from option
Boolean apiEnabled = optionService.getByPropertyOrDefault(OtherProperties.API_ENABLED, Boolean.class, false); Boolean apiEnabled = optionService.getByPropertyOrDefault(ApiProperties.API_ENABLED, Boolean.class, false);
if (!apiEnabled) { if (!apiEnabled) {
getFailureHandler().onFailure(request, response, new ForbiddenException("API has been disabled by blogger currently")); getFailureHandler().onFailure(request, response, new ForbiddenException("API has been disabled by blogger currently"));
@ -65,7 +65,7 @@ public class ApiAuthenticationFilter extends AbstractAuthenticationFilter {
} }
// Get access key from option // Get access key from option
Optional<String> optionalAccessKey = optionService.getByProperty(OtherProperties.API_ACCESS_KEY, String.class); Optional<String> optionalAccessKey = optionService.getByProperty(ApiProperties.API_ACCESS_KEY, String.class);
if (!optionalAccessKey.isPresent()) { if (!optionalAccessKey.isPresent()) {
// If the access key is not set // If the access key is not set

View File

@ -7,11 +7,11 @@ import run.halo.app.model.params.LoginParam;
import run.halo.app.security.token.AuthToken; import run.halo.app.security.token.AuthToken;
/** /**
* Admin service. * Admin service interface.
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 19-4-29 * @date 2019-04-29
*/ */
public interface AdminService { public interface AdminService {
@ -26,6 +26,8 @@ public interface AdminService {
String REFRESH_TOKEN_CACHE_PREFIX = "halo.admin.refresh_token."; String REFRESH_TOKEN_CACHE_PREFIX = "halo.admin.refresh_token.";
String LOGS_PATH = "logs/spring.log";
/** /**
* Authenticates. * Authenticates.
* *
@ -69,4 +71,10 @@ public interface AdminService {
* Updates halo admin assets. * Updates halo admin assets.
*/ */
void updateAdminAssets(); void updateAdminAssets();
/**
* Get spring logs.
* @return recently logs.
*/
String getSpringLogs();
} }

View File

@ -17,6 +17,7 @@ import java.util.List;
* Attachment service. * Attachment service.
* *
* @author johnniang * @author johnniang
* @date : 2019-03-14
*/ */
public interface AttachmentService extends CrudService<Attachment, Integer> { public interface AttachmentService extends CrudService<Attachment, Integer> {

View File

@ -9,7 +9,7 @@ import java.io.IOException;
* Backup service interface. * Backup service interface.
* *
* @author johnniang * @author johnniang
* @date 19-4-26 * @date 2019-04-26
*/ */
public interface BackupService { public interface BackupService {

View File

@ -15,7 +15,10 @@ import java.util.List;
* Category service. * Category service.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date : 2019-03-14
*/ */
@Transactional(readOnly = true)
public interface CategoryService extends CrudService<Category, Integer> { public interface CategoryService extends CrudService<Category, Integer> {
/** /**
@ -36,6 +39,15 @@ public interface CategoryService extends CrudService<Category, Integer> {
@NonNull @NonNull
Category getBySlugName(@NonNull String slugName); Category getBySlugName(@NonNull String slugName);
/**
* Get category by slug name
*
* @param slugName slug name
* @return Category
*/
@NonNull
Category getBySlugNameOfNonNull(String slugName);
/** /**
* Get Category by name. * Get Category by name.
* *

View File

@ -13,7 +13,7 @@ import java.util.List;
* Journal comment service interface. * Journal comment service interface.
* *
* @author johnniang * @author johnniang
* @date 19-4-25 * @date 2019-04-25
*/ */
public interface JournalCommentService extends BaseCommentService<JournalComment> { public interface JournalCommentService extends BaseCommentService<JournalComment> {

View File

@ -18,7 +18,7 @@ import java.util.List;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 19-4-24 * @date 2019-04-24
*/ */
public interface JournalService extends CrudService<Journal, Integer> { public interface JournalService extends CrudService<Journal, Integer> {

View File

@ -11,9 +11,10 @@ import run.halo.app.service.base.CrudService;
import java.util.List; import java.util.List;
/** /**
* Link service. * Link service interface.
* *
* @author johnniang * @author johnniang
* @date 2019-03-14
*/ */
public interface LinkService extends CrudService<Link, Integer> { public interface LinkService extends CrudService<Link, Integer> {

View File

@ -6,9 +6,10 @@ import run.halo.app.model.entity.Log;
import run.halo.app.service.base.CrudService; import run.halo.app.service.base.CrudService;
/** /**
* Log service. * Log service interface.
* *
* @author johnniang * @author johnniang
* @date 2019-03-14
*/ */
public interface LogService extends CrudService<Log, Long> { public interface LogService extends CrudService<Log, Long> {

View File

@ -3,10 +3,10 @@ package run.halo.app.service;
import java.util.Map; import java.util.Map;
/** /**
* Mail server * Mail service interface.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-17 * @date 2019-03-17
*/ */
public interface MailService { public interface MailService {

View File

@ -11,10 +11,11 @@ import run.halo.app.service.base.CrudService;
import java.util.List; import java.util.List;
/** /**
* Menu service. * Menu service interface.
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 2019-03-14
*/ */
public interface MenuService extends CrudService<Menu, Integer> { public interface MenuService extends CrudService<Menu, Integer> {

View File

@ -18,9 +18,10 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
* Option service. * Option service interface.
* *
* @author johnniang * @author johnniang
* @date 2019-03-14
*/ */
public interface OptionService extends CrudService<Option, Integer> { public interface OptionService extends CrudService<Option, Integer> {

View File

@ -14,9 +14,10 @@ import run.halo.app.service.base.CrudService;
import java.util.List; import java.util.List;
/** /**
* Photo service. * Photo service interface.
* *
* @author johnniang * @author johnniang
* @date 2019-03-14
*/ */
public interface PhotoService extends CrudService<Photo, Integer> { public interface PhotoService extends CrudService<Photo, Integer> {

View File

@ -10,6 +10,7 @@ import run.halo.app.model.dto.CategoryWithPostCountDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostCategory; import run.halo.app.model.entity.PostCategory;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.service.base.CrudService; import run.halo.app.service.base.CrudService;
import java.util.Collection; import java.util.Collection;
@ -21,7 +22,8 @@ import java.util.Set;
* Post category service interface. * Post category service interface.
* *
* @author johnniang * @author johnniang
* @date 3/19/19 * @author ryanwang
* @date 2019-03-19
*/ */
public interface PostCategoryService extends CrudService<PostCategory, Integer> { public interface PostCategoryService extends CrudService<PostCategory, Integer> {
@ -52,6 +54,16 @@ public interface PostCategoryService extends CrudService<PostCategory, Integer>
@NonNull @NonNull
List<Post> listPostBy(@NonNull Integer categoryId); List<Post> listPostBy(@NonNull Integer categoryId);
/**
* Lists post by category id and post status.
*
* @param categoryId category id must not be null
* @param status post status
* @return a list of post
*/
@NonNull
List<Post> listPostBy(@NonNull Integer categoryId, @NonNull PostStatus status);
/** /**
* Pages post by category slug name. * Pages post by category slug name.
* *
@ -62,6 +74,17 @@ public interface PostCategoryService extends CrudService<PostCategory, Integer>
@NonNull @NonNull
Page<Post> pagePostBy(@NonNull Integer categoryId, Pageable pageable); Page<Post> pagePostBy(@NonNull Integer categoryId, Pageable pageable);
/**
* Pages post by category slug name and post status.
*
* @param categoryId category id must not be null
* @param status post status
* @param pageable pageable
* @return page of post
*/
@NonNull
Page<Post> pagePostBy(@NonNull Integer categoryId, @NonNull PostStatus status, Pageable pageable);
/** /**
* Merges or creates post categories by post id and category id set if absent. * Merges or creates post categories by post id and category id set if absent.
* *

View File

@ -12,9 +12,10 @@ import run.halo.app.service.base.BaseCommentService;
import java.util.List; import java.util.List;
/** /**
* PostComment service. * Post comment service interface.
* *
* @author johnniang * @author johnniang
* @date 2019-03-14
*/ */
public interface PostCommentService extends BaseCommentService<PostComment> { public interface PostCommentService extends BaseCommentService<PostComment> {

View File

@ -17,10 +17,11 @@ import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
* Post service. * Post service interface.
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 2019-03-14
*/ */
public interface PostService extends BasePostService<Post> { public interface PostService extends BasePostService<Post> {

View File

@ -10,6 +10,7 @@ import run.halo.app.model.dto.TagWithPostCountDTO;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostTag; import run.halo.app.model.entity.PostTag;
import run.halo.app.model.entity.Tag; import run.halo.app.model.entity.Tag;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.service.base.CrudService; import run.halo.app.service.base.CrudService;
import java.util.Collection; import java.util.Collection;
@ -21,7 +22,8 @@ import java.util.Set;
* Post tag service interface. * Post tag service interface.
* *
* @author johnniang * @author johnniang
* @date 3/19/19 * @author ryanwang
* @date 2019-03-19
*/ */
public interface PostTagService extends CrudService<PostTag, Integer> { public interface PostTagService extends CrudService<PostTag, Integer> {
@ -61,6 +63,16 @@ public interface PostTagService extends CrudService<PostTag, Integer> {
@NonNull @NonNull
List<Post> listPostsBy(@NonNull Integer tagId); List<Post> listPostsBy(@NonNull Integer tagId);
/**
* Lists posts by tag id and post status.
*
* @param tagId tag id must not be null
* @param status post status
* @return a list of post
*/
@NonNull
List<Post> listPostsBy(@NonNull Integer tagId, @NonNull PostStatus status);
/** /**
* Pages posts by tag id. * Pages posts by tag id.
* *
@ -70,6 +82,16 @@ public interface PostTagService extends CrudService<PostTag, Integer> {
*/ */
Page<Post> pagePostsBy(@NonNull Integer tagId, Pageable pageable); Page<Post> pagePostsBy(@NonNull Integer tagId, Pageable pageable);
/**
* Pages posts by tag id and post status.
*
* @param tagId must not be null
* @param status post status
* @param pageable must not be null
* @return a page of post
*/
Page<Post> pagePostsBy(@NonNull Integer tagId, @NonNull PostStatus status, Pageable pageable);
/** /**
* Merges or creates post tags by post id and tag id set if absent. * Merges or creates post tags by post id and tag id set if absent.
* *

View File

@ -7,7 +7,7 @@ import org.springframework.web.multipart.MultipartFile;
* Recovery service interface. * Recovery service interface.
* *
* @author johnniang * @author johnniang
* @date 19-4-26 * @date 2019-04-26
*/ */
public interface RecoveryService { public interface RecoveryService {

View File

@ -13,7 +13,7 @@ import java.util.List;
* Sheet comment service interface. * Sheet comment service interface.
* *
* @author johnniang * @author johnniang
* @date 19-4-24 * @date 2019-04-24
*/ */
public interface SheetCommentService extends BaseCommentService<SheetComment> { public interface SheetCommentService extends BaseCommentService<SheetComment> {

View File

@ -15,7 +15,7 @@ import java.util.List;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 19-4-24 * @date 2019-04-24
*/ */
public interface SheetService extends BasePostService<Sheet> { public interface SheetService extends BasePostService<Sheet> {

View File

@ -8,11 +8,12 @@ import run.halo.app.service.base.CrudService;
import java.util.List; import java.util.List;
/** /**
* Tag service. * Tag service interface.
* *
* @author johnniang * @author johnniang
* @author ryanwang
* @date 2019-03-14
*/ */
public interface TagService extends CrudService<Tag, Integer> { public interface TagService extends CrudService<Tag, Integer> {
@ -25,6 +26,15 @@ public interface TagService extends CrudService<Tag, Integer> {
@NonNull @NonNull
Tag getBySlugNameOfNonNull(@NonNull String slugName); Tag getBySlugNameOfNonNull(@NonNull String slugName);
/**
* Get tag by slug name
*
* @param slugName slug name
* @return tag
*/
@NonNull
Tag getBySlugName(@NonNull String slugName);
/** /**
* Get tag by tag name. * Get tag by tag name.
* *

View File

@ -14,8 +14,10 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
/** /**
* Theme service interface.
*
* @author ryanwang * @author ryanwang
* @date : 2019/3/26 * @date 2019-03-26
*/ */
public interface ThemeService { public interface ThemeService {

View File

@ -12,7 +12,7 @@ import java.util.Map;
* Theme setting service interface. * Theme setting service interface.
* *
* @author johnniang * @author johnniang
* @date 4/8/19 * @date 2019-04-08
*/ */
public interface ThemeSettingService { public interface ThemeSettingService {

View File

@ -9,7 +9,7 @@ import java.util.List;
* Trace service interface. * Trace service interface.
* *
* @author johnniang * @author johnniang
* @date 19-6-18 * @date 2019-06-18
*/ */
public interface TraceService { public interface TraceService {

View File

@ -11,9 +11,10 @@ import run.halo.app.service.base.CrudService;
import java.util.Optional; import java.util.Optional;
/** /**
* User service. * User service interface.
* *
* @author johnniang * @author johnniang
* @date 2019-03-14
*/ */
public interface UserService extends CrudService<User, Integer> { public interface UserService extends CrudService<User, Integer> {

View File

@ -1,8 +1,10 @@
package run.halo.app.service.impl; package run.halo.app.service.impl;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.lang.Validator; import cn.hutool.core.lang.Validator;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -10,6 +12,7 @@ import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import run.halo.app.cache.StringCacheStore; import run.halo.app.cache.StringCacheStore;
import run.halo.app.config.properties.HaloProperties; import run.halo.app.config.properties.HaloProperties;
import run.halo.app.event.logger.LogEvent;
import run.halo.app.exception.BadRequestException; import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.NotFoundException; import run.halo.app.exception.NotFoundException;
import run.halo.app.exception.ServiceException; import run.halo.app.exception.ServiceException;
@ -17,6 +20,7 @@ import run.halo.app.model.dto.EnvironmentDTO;
import run.halo.app.model.dto.StatisticDTO; import run.halo.app.model.dto.StatisticDTO;
import run.halo.app.model.entity.User; import run.halo.app.model.entity.User;
import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.enums.LogType;
import run.halo.app.model.enums.Mode; import run.halo.app.model.enums.Mode;
import run.halo.app.model.enums.PostStatus; import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.params.LoginParam; import run.halo.app.model.params.LoginParam;
@ -29,6 +33,7 @@ import run.halo.app.service.*;
import run.halo.app.utils.FileUtils; import run.halo.app.utils.FileUtils;
import run.halo.app.utils.HaloUtils; import run.halo.app.utils.HaloUtils;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean; import java.lang.management.RuntimeMXBean;
@ -46,7 +51,7 @@ import static run.halo.app.model.support.HaloConst.*;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 19-4-29 * @date 2019-04-29
*/ */
@Slf4j @Slf4j
@Service @Service
@ -76,6 +81,8 @@ public class AdminServiceImpl implements AdminService {
private final HaloProperties haloProperties; private final HaloProperties haloProperties;
private final ApplicationEventPublisher eventPublisher;
private final String driverClassName; private final String driverClassName;
private final String mode; private final String mode;
@ -92,6 +99,7 @@ public class AdminServiceImpl implements AdminService {
StringCacheStore cacheStore, StringCacheStore cacheStore,
RestTemplate restTemplate, RestTemplate restTemplate,
HaloProperties haloProperties, HaloProperties haloProperties,
ApplicationEventPublisher eventPublisher,
@Value("${spring.datasource.driver-class-name}") String driverClassName, @Value("${spring.datasource.driver-class-name}") String driverClassName,
@Value("${spring.profiles.active:prod}") String mode) { @Value("${spring.profiles.active:prod}") String mode) {
this.postService = postService; this.postService = postService;
@ -106,6 +114,7 @@ public class AdminServiceImpl implements AdminService {
this.cacheStore = cacheStore; this.cacheStore = cacheStore;
this.restTemplate = restTemplate; this.restTemplate = restTemplate;
this.haloProperties = haloProperties; this.haloProperties = haloProperties;
this.eventPublisher = eventPublisher;
this.driverClassName = driverClassName; this.driverClassName = driverClassName;
this.mode = mode; this.mode = mode;
} }
@ -126,6 +135,8 @@ public class AdminServiceImpl implements AdminService {
userService.getByEmailOfNonNull(username) : userService.getByUsernameOfNonNull(username); userService.getByEmailOfNonNull(username) : userService.getByUsernameOfNonNull(username);
} catch (NotFoundException e) { } catch (NotFoundException e) {
log.error("Failed to find user by name: " + username, e); log.error("Failed to find user by name: " + username, e);
eventPublisher.publishEvent(new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED, loginParam.getUsername()));
throw new BadRequestException(mismatchTip); throw new BadRequestException(mismatchTip);
} }
@ -133,6 +144,8 @@ public class AdminServiceImpl implements AdminService {
if (!userService.passwordMatch(user, loginParam.getPassword())) { if (!userService.passwordMatch(user, loginParam.getPassword())) {
// If the password is mismatch // If the password is mismatch
eventPublisher.publishEvent(new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED, loginParam.getUsername()));
throw new BadRequestException(mismatchTip); throw new BadRequestException(mismatchTip);
} }
@ -141,6 +154,9 @@ public class AdminServiceImpl implements AdminService {
throw new BadRequestException("您已登录,请不要重复登录"); throw new BadRequestException("您已登录,请不要重复登录");
} }
// Log it then login successful
eventPublisher.publishEvent(new LogEvent(this, user.getUsername(), LogType.LOGGED_IN, user.getNickname()));
// Generate new token // Generate new token
return buildAuthToken(user); return buildAuthToken(user);
} }
@ -170,6 +186,8 @@ public class AdminServiceImpl implements AdminService {
cacheStore.delete(SecurityUtils.buildRefreshTokenKey(user)); cacheStore.delete(SecurityUtils.buildRefreshTokenKey(user));
}); });
eventPublisher.publishEvent(new LogEvent(this, user.getUsername(), LogType.LOGGED_OUT, user.getNickname()));
log.info("You have been logged out, looking forward to your next visit!"); log.info("You have been logged out, looking forward to your next visit!");
} }
@ -357,4 +375,14 @@ public class AdminServiceImpl implements AdminService {
return token; return token;
} }
@Override
public String getSpringLogs() {
File file = new File(haloProperties.getWorkDir(), LOGS_PATH);
if (!file.exists()) {
return "暂无日志";
}
FileReader reader = new FileReader(file);
return reader.readString();
}
} }

View File

@ -32,6 +32,7 @@ import java.util.Objects;
* AttachmentService implementation * AttachmentService implementation
* *
* @author ryanwang * @author ryanwang
* @author johnniang
* @date : 2019-03-14 * @date : 2019-03-14
*/ */
@Slf4j @Slf4j

View File

@ -14,7 +14,7 @@ import java.nio.charset.StandardCharsets;
* Backup service implementation. * Backup service implementation.
* *
* @author johnniang * @author johnniang
* @date 19-4-26 * @date 2019-04-26
*/ */
@Service @Service
public class BackupServiceImpl implements BackupService { public class BackupServiceImpl implements BackupService {

View File

@ -51,7 +51,7 @@ import java.util.stream.Collectors;
* Base comment service implementation. * Base comment service implementation.
* *
* @author johnniang * @author johnniang
* @date 19-4-24 * @date 2019-04-24
*/ */
@Slf4j @Slf4j
public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extends AbstractCrudService<COMMENT, Long> implements BaseCommentService<COMMENT> { public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extends AbstractCrudService<COMMENT, Long> implements BaseCommentService<COMMENT> {

View File

@ -7,7 +7,6 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import run.halo.app.exception.AlreadyExistsException; import run.halo.app.exception.AlreadyExistsException;
@ -24,6 +23,7 @@ import run.halo.app.service.OptionService;
import run.halo.app.service.base.AbstractCrudService; import run.halo.app.service.base.AbstractCrudService;
import run.halo.app.service.base.BasePostService; import run.halo.app.service.base.BasePostService;
import run.halo.app.utils.DateUtils; import run.halo.app.utils.DateUtils;
import run.halo.app.utils.HaloUtils;
import run.halo.app.utils.MarkdownUtils; import run.halo.app.utils.MarkdownUtils;
import run.halo.app.utils.ServiceUtils; import run.halo.app.utils.ServiceUtils;
@ -40,7 +40,8 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
* Base post service implementation. * Base post service implementation.
* *
* @author johnniang * @author johnniang
* @date 19-4-24 * @author ryanwang
* @date 2019-04-24
*/ */
@Slf4j @Slf4j
public abstract class BasePostServiceImpl<POST extends BasePost> extends AbstractCrudService<POST, Integer> implements BasePostService<POST> { public abstract class BasePostServiceImpl<POST extends BasePost> extends AbstractCrudService<POST, Integer> implements BasePostService<POST> {
@ -212,7 +213,7 @@ public abstract class BasePostServiceImpl<POST extends BasePost> extends Abstrac
Assert.notNull(post, "Post must not be null"); Assert.notNull(post, "Post must not be null");
// Render content // Render content
post.setFormatContent(MarkdownUtils.renderMarkdown(post.getOriginalContent())); post.setFormatContent(MarkdownUtils.renderHtml(post.getOriginalContent()));
// Create or update post // Create or update post
if (ServiceUtils.isEmptyId(post.getId())) { if (ServiceUtils.isEmptyId(post.getId())) {
@ -275,7 +276,7 @@ public abstract class BasePostServiceImpl<POST extends BasePost> extends Abstrac
// Set summary // Set summary
if (StringUtils.isBlank(basePostSimpleDTO.getSummary())) { if (StringUtils.isBlank(basePostSimpleDTO.getSummary())) {
basePostSimpleDTO.setSummary(convertToSummary(post.getOriginalContent())); basePostSimpleDTO.setSummary(generateSummary(post.getFormatContent()));
} }
return basePostSimpleDTO; return basePostSimpleDTO;
@ -347,15 +348,14 @@ public abstract class BasePostServiceImpl<POST extends BasePost> extends Abstrac
} }
@NonNull @NonNull
protected String convertToSummary(@Nullable String markdownContent) { protected String generateSummary(@NonNull String htmlContent) {
// Render text content Assert.notNull(htmlContent, "html content must not be null");
String textContent = MarkdownUtils.renderText(markdownContent);
String text = HaloUtils.cleanHtmlTag(htmlContent);
// Get summary length // Get summary length
Integer summaryLength = optionService.getByPropertyOrDefault(PostProperties.SUMMARY_LENGTH, Integer.class, 150); Integer summaryLength = optionService.getByPropertyOrDefault(PostProperties.SUMMARY_LENGTH, Integer.class, 150);
// Set summary return StringUtils.substring(text, 0, summaryLength);
return StringUtils.substring(textContent, 0, summaryLength);
} }
} }

View File

@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import run.halo.app.exception.AlreadyExistsException; import run.halo.app.exception.AlreadyExistsException;
@ -24,9 +25,10 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* CategoryService implementation class * CategoryService implementation class.
* *
* @author ryanwang * @author ryanwang
* @author johnniang
* @date : 2019-03-14 * @date : 2019-03-14
*/ */
@Slf4j @Slf4j
@ -45,6 +47,7 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
} }
@Override @Override
@Transactional
public Category create(Category category) { public Category create(Category category) {
Assert.notNull(category, "Category to create must not be null"); Assert.notNull(category, "Category to create must not be null");
@ -144,15 +147,14 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
return topCategory; return topCategory;
} }
/**
* Get category by slug name
*
* @param slugName slug name
* @return Category
*/
@Override @Override
public Category getBySlugName(String slugName) { public Category getBySlugName(String slugName) {
return categoryRepository.getBySlugName(slugName).orElseThrow(() -> new NotFoundException("该分类已存在").setErrorData(slugName)); return categoryRepository.getBySlugName(slugName).orElse(null);
}
@Override
public Category getBySlugNameOfNonNull(String slugName) {
return categoryRepository.getBySlugName(slugName).orElseThrow(() -> new NotFoundException("该分类不存在").setErrorData(slugName));
} }
@Override @Override
@ -161,6 +163,7 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
} }
@Override @Override
@Transactional
public void removeCategoryAndPostCategoryBy(Integer categoryId) { public void removeCategoryAndPostCategoryBy(Integer categoryId) {
// Remove category // Remove category
removeById(categoryId); removeById(categoryId);

View File

@ -28,7 +28,7 @@ import java.util.stream.Collectors;
* Journal comment service implementation. * Journal comment service implementation.
* *
* @author johnniang * @author johnniang
* @date 19-4-25 * @date 2019-04-25
*/ */
@Service @Service
public class JournalCommentServiceImpl extends BaseCommentServiceImpl<JournalComment> implements JournalCommentService { public class JournalCommentServiceImpl extends BaseCommentServiceImpl<JournalComment> implements JournalCommentService {

View File

@ -29,7 +29,7 @@ import java.util.stream.Collectors;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 19-4-24 * @date 2019-04-24
*/ */
@Service @Service
public class JournalServiceImpl extends AbstractCrudService<Journal, Integer> implements JournalService { public class JournalServiceImpl extends AbstractCrudService<Journal, Integer> implements JournalService {

View File

@ -24,7 +24,7 @@ import java.util.stream.Collectors;
* LinkService implementation class * LinkService implementation class
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @date 2019-03-14
*/ */
@Service @Service
public class LinkServiceImpl extends AbstractCrudService<Link, Integer> implements LinkService { public class LinkServiceImpl extends AbstractCrudService<Link, Integer> implements LinkService {
@ -36,12 +36,6 @@ public class LinkServiceImpl extends AbstractCrudService<Link, Integer> implemen
this.linkRepository = linkRepository; this.linkRepository = linkRepository;
} }
/**
* List link dtos.
*
* @param sort sort
* @return all links
*/
@Override @Override
public List<LinkDTO> listDtos(Sort sort) { public List<LinkDTO> listDtos(Sort sort) {
Assert.notNull(sort, "Sort info must not be null"); Assert.notNull(sort, "Sort info must not be null");

View File

@ -15,7 +15,7 @@ import run.halo.app.service.base.AbstractCrudService;
* LogService implementation class * LogService implementation class
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @date 2019-03-14
*/ */
@Service @Service
public class LogServiceImpl extends AbstractCrudService<Log, Long> implements LogService { public class LogServiceImpl extends AbstractCrudService<Log, Long> implements LogService {

View File

@ -20,7 +20,7 @@ import java.util.Properties;
* Mail service implementation. * Mail service implementation.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-17 * @date 2019-03-17
*/ */
@Slf4j @Slf4j
@Service @Service
@ -37,13 +37,6 @@ public class MailServiceImpl implements MailService {
} }
/**
* Sends a simple email
*
* @param to recipient
* @param subject subject
* @param content content
*/
@Override @Override
public void sendMail(String to, String subject, String content) { public void sendMail(String to, String subject, String content) {
loadConfig(); loadConfig();
@ -63,14 +56,6 @@ public class MailServiceImpl implements MailService {
} }
} }
/**
* Sends template mail
*
* @param to recipient
* @param subject subject
* @param content content
* @param templateName template name
*/
@Override @Override
public void sendTemplateMail(String to, String subject, Map<String, Object> content, String templateName) { public void sendTemplateMail(String to, String subject, Map<String, Object> content, String templateName) {
loadConfig(); loadConfig();
@ -93,15 +78,6 @@ public class MailServiceImpl implements MailService {
} }
} }
/**
* Sends mail with attachments
*
* @param to recipient
* @param subject subject
* @param content content
* @param templateName template name
* @param attachFilename attachment path
*/
@Override @Override
public void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilename) { public void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilename) {
loadConfig(); loadConfig();

View File

@ -21,10 +21,10 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* MenuService implementation class * MenuService implementation class.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @date 2019-03-14
*/ */
@Service @Service
public class MenuServiceImpl extends AbstractCrudService<Menu, Integer> implements MenuService { public class MenuServiceImpl extends AbstractCrudService<Menu, Integer> implements MenuService {
@ -51,12 +51,6 @@ public class MenuServiceImpl extends AbstractCrudService<Menu, Integer> implemen
return create(menuParam.convertTo()); return create(menuParam.convertTo());
} }
/**
* Lists as menu tree.
*
* @param sort sort info must not be null
* @return a menu tree
*/
@Override @Override
public List<MenuVO> listAsTree(Sort sort) { public List<MenuVO> listAsTree(Sort sort) {
Assert.notNull(sort, "Sort info must not be null"); Assert.notNull(sort, "Sort info must not be null");

View File

@ -30,7 +30,7 @@ import java.util.*;
* OptionService implementation class * OptionService implementation class
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @date 2019-03-14
*/ */
@Slf4j @Slf4j
@Service @Service

View File

@ -29,7 +29,7 @@ import java.util.stream.Collectors;
* PhotoService implementation class * PhotoService implementation class
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @date 2019-03-14
*/ */
@Service @Service
public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implements PhotoService { public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implements PhotoService {
@ -41,12 +41,6 @@ public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implem
this.photoRepository = photoRepository; this.photoRepository = photoRepository;
} }
/**
* List photo dtos.
*
* @param sort sort
* @return all photos
*/
@Override @Override
public List<PhotoDTO> listDtos(Sort sort) { public List<PhotoDTO> listDtos(Sort sort) {
Assert.notNull(sort, "Sort info must not be null"); Assert.notNull(sort, "Sort info must not be null");
@ -54,12 +48,6 @@ public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implem
return listAll(sort).stream().map(photo -> (PhotoDTO) new PhotoDTO().convertFrom(photo)).collect(Collectors.toList()); return listAll(sort).stream().map(photo -> (PhotoDTO) new PhotoDTO().convertFrom(photo)).collect(Collectors.toList());
} }
/**
* Lists photo team vos.
*
* @param sort must not be null
* @return a list of photo team vo
*/
@Override @Override
public List<PhotoTeamVO> listTeamVos(Sort sort) { public List<PhotoTeamVO> listTeamVos(Sort sort) {
Assert.notNull(sort, "Sort info must not be null"); Assert.notNull(sort, "Sort info must not be null");
@ -88,13 +76,6 @@ public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implem
return result; return result;
} }
/**
* List photos by team.
*
* @param team team
* @param sort sort
* @return list of photos
*/
@Override @Override
public List<PhotoDTO> listByTeam(String team, Sort sort) { public List<PhotoDTO> listByTeam(String team, Sort sort) {
List<Photo> photos = photoRepository.findByTeam(team, sort); List<Photo> photos = photoRepository.findByTeam(team, sort);

View File

@ -10,6 +10,7 @@ import run.halo.app.model.dto.CategoryWithPostCountDTO;
import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Category;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostCategory; import run.halo.app.model.entity.PostCategory;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.projection.CategoryPostCountProjection; import run.halo.app.model.projection.CategoryPostCountProjection;
import run.halo.app.repository.CategoryRepository; import run.halo.app.repository.CategoryRepository;
import run.halo.app.repository.PostCategoryRepository; import run.halo.app.repository.PostCategoryRepository;
@ -25,7 +26,8 @@ import java.util.stream.Collectors;
* Post category service implementation. * Post category service implementation.
* *
* @author johnniang * @author johnniang
* @date 3/19/19 * @author ryanwang
* @date 2019-03-19
*/ */
@Service @Service
public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, Integer> implements PostCategoryService { public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, Integer> implements PostCategoryService {
@ -93,6 +95,17 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
return postRepository.findAllById(postIds); return postRepository.findAllById(postIds);
} }
@Override
public List<Post> listPostBy(Integer categoryId, PostStatus status) {
Assert.notNull(categoryId, "Category id must not be null");
Assert.notNull(categoryId, "Post status must not be null");
// Find all post ids
Set<Integer> postIds = postCategoryRepository.findAllPostIdsByCategoryId(categoryId, status);
return postRepository.findAllById(postIds);
}
@Override @Override
public Page<Post> pagePostBy(Integer categoryId, Pageable pageable) { public Page<Post> pagePostBy(Integer categoryId, Pageable pageable) {
Assert.notNull(categoryId, "Category id must not be null"); Assert.notNull(categoryId, "Category id must not be null");
@ -104,6 +117,18 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
return postRepository.findAllByIdIn(postIds, pageable); return postRepository.findAllByIdIn(postIds, pageable);
} }
@Override
public Page<Post> pagePostBy(Integer categoryId, PostStatus status, Pageable pageable) {
Assert.notNull(categoryId, "Category id must not be null");
Assert.notNull(categoryId, "Post status must not be null");
Assert.notNull(pageable, "Page info must not be null");
// Find all post ids
Set<Integer> postIds = postCategoryRepository.findAllPostIdsByCategoryId(categoryId, status);
return postRepository.findAllByIdIn(postIds, pageable);
}
@Override @Override
public List<PostCategory> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> categoryIds) { public List<PostCategory> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> categoryIds) {
Assert.notNull(postId, "Post id must not be null"); Assert.notNull(postId, "Post id must not be null");

View File

@ -32,7 +32,8 @@ import java.util.stream.Collectors;
* PostCommentService implementation class * PostCommentService implementation class
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @author johnniang
* @date 2019-03-14
*/ */
@Slf4j @Slf4j
@Service @Service

View File

@ -45,6 +45,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 2019-03-14
*/ */
@Slf4j @Slf4j
@Service @Service
@ -280,7 +281,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
Assert.notNull(markdown, "Markdown document must not be null"); Assert.notNull(markdown, "Markdown document must not be null");
// Render markdown to html document. // Render markdown to html document.
String content = MarkdownUtils.renderMarkdown(markdown); String content = MarkdownUtils.renderHtml(markdown);
// Gets frontMatter // Gets frontMatter
Map<String, List<String>> frontMatter = MarkdownUtils.getFrontMatter(markdown); Map<String, List<String>> frontMatter = MarkdownUtils.getFrontMatter(markdown);
@ -462,8 +463,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
PostListVO postListVO = new PostListVO().convertFrom(post); PostListVO postListVO = new PostListVO().convertFrom(post);
if (StringUtils.isBlank(postListVO.getSummary())) { if (StringUtils.isBlank(postListVO.getSummary())) {
// Set summary postListVO.setSummary(generateSummary(post.getFormatContent()));
postListVO.setSummary(convertToSummary(post.getOriginalContent()));
} }
Optional.ofNullable(tagListMap.get(post.getId())).orElseGet(LinkedList::new); Optional.ofNullable(tagListMap.get(post.getId())).orElseGet(LinkedList::new);

View File

@ -10,6 +10,7 @@ import run.halo.app.model.dto.TagWithPostCountDTO;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.PostTag; import run.halo.app.model.entity.PostTag;
import run.halo.app.model.entity.Tag; import run.halo.app.model.entity.Tag;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.projection.TagPostPostCountProjection; import run.halo.app.model.projection.TagPostPostCountProjection;
import run.halo.app.repository.PostRepository; import run.halo.app.repository.PostRepository;
import run.halo.app.repository.PostTagRepository; import run.halo.app.repository.PostTagRepository;
@ -25,7 +26,8 @@ import java.util.stream.Collectors;
* Post tag service implementation. * Post tag service implementation.
* *
* @author johnniang * @author johnniang
* @date 3/19/19 * @author ryanwang
* @date 2019-03-19
*/ */
@Service @Service
public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> implements PostTagService { public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> implements PostTagService {
@ -113,6 +115,17 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
return postRepository.findAllById(postIds); return postRepository.findAllById(postIds);
} }
@Override
public List<Post> listPostsBy(Integer tagId, PostStatus status) {
Assert.notNull(tagId, "Tag id must not be null");
Assert.notNull(tagId, "Post status must not be null");
// Find all post ids
Set<Integer> postIds = postTagRepository.findAllPostIdsByTagId(tagId, status);
return postRepository.findAllById(postIds);
}
@Override @Override
public Page<Post> pagePostsBy(Integer tagId, Pageable pageable) { public Page<Post> pagePostsBy(Integer tagId, Pageable pageable) {
Assert.notNull(tagId, "Tag id must not be null"); Assert.notNull(tagId, "Tag id must not be null");
@ -124,6 +137,18 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
return postRepository.findAllByIdIn(postIds, pageable); return postRepository.findAllByIdIn(postIds, pageable);
} }
@Override
public Page<Post> pagePostsBy(Integer tagId, PostStatus status, Pageable pageable) {
Assert.notNull(tagId, "Tag id must not be null");
Assert.notNull(tagId, "Post status must not be null");
Assert.notNull(pageable, "Page info must not be null");
// Find all post ids
Set<Integer> postIds = postTagRepository.findAllPostIdsByTagId(tagId, status);
return postRepository.findAllByIdIn(postIds, pageable);
}
@Override @Override
public List<PostTag> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> tagIds) { public List<PostTag> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> tagIds) {
Assert.notNull(postId, "Post id must not be null"); Assert.notNull(postId, "Post id must not be null");

View File

@ -33,7 +33,8 @@ import java.util.stream.Collectors;
* Recovery service implementation. * Recovery service implementation.
* *
* @author johnniang * @author johnniang
* @date 19-4-26 * @author ryanwang
* @date 2019-04-26
*/ */
@Slf4j @Slf4j
@Service @Service
@ -64,6 +65,10 @@ public class RecoveryServiceImpl implements RecoveryService {
private final PhotoService photoService; private final PhotoService photoService;
private final PostCategoryService postCategoryService;
private final PostTagService postTagService;
public RecoveryServiceImpl(AttachmentService attachmentService, public RecoveryServiceImpl(AttachmentService attachmentService,
PostService postService, PostService postService,
LinkService linkService, LinkService linkService,
@ -75,7 +80,9 @@ public class RecoveryServiceImpl implements RecoveryService {
SheetCommentService sheetCommentService, SheetCommentService sheetCommentService,
SheetCommentRepository sheetCommentRepository, SheetCommentRepository sheetCommentRepository,
SheetService sheetService, SheetService sheetService,
PhotoService photoService) { PhotoService photoService,
PostCategoryService postCategoryService,
PostTagService postTagService) {
this.attachmentService = attachmentService; this.attachmentService = attachmentService;
this.postService = postService; this.postService = postService;
this.linkService = linkService; this.linkService = linkService;
@ -88,6 +95,8 @@ public class RecoveryServiceImpl implements RecoveryService {
this.sheetCommentRepository = sheetCommentRepository; this.sheetCommentRepository = sheetCommentRepository;
this.sheetService = sheetService; this.sheetService = sheetService;
this.photoService = photoService; this.photoService = photoService;
this.postCategoryService = postCategoryService;
this.postTagService = postTagService;
} }
@Override @Override
@ -215,9 +224,21 @@ public class RecoveryServiceImpl implements RecoveryService {
Post createdPost = postService.createOrUpdateBy(post); Post createdPost = postService.createOrUpdateBy(post);
Object commentsObject = postMap.get("comments"); Object commentsObject = postMap.get("comments");
Object categoriesObject = postMap.get("categories");
Object tagsObject = postMap.get("tags");
// Handle comments // Handle comments
List<BaseComment> baseComments = handleComment(commentsObject, createdPost.getId()); List<BaseComment> baseComments = handleComment(commentsObject, createdPost.getId());
// Handle categories
List<Category> categories = handleCategories(categoriesObject, createdPost.getId());
log.debug("Migrated categories of post [{}]: [{}]", categories, createdPost.getId());
// Handle tags
List<Tag> tags = handleTags(tagsObject, createdPost.getId());
log.debug("Migrated tags of post [{}]: [{}]", tags, createdPost.getId());
List<PostComment> postComments = baseComments.stream() List<PostComment> postComments = baseComments.stream()
.map(baseComment -> BeanUtils.transformFrom(baseComment, PostComment.class)) .map(baseComment -> BeanUtils.transformFrom(baseComment, PostComment.class))
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -372,6 +393,96 @@ public class RecoveryServiceImpl implements RecoveryService {
return result; return result;
} }
@NonNull
private List<Category> handleCategories(@Nullable Object categoriesObject, @NonNull Integer postId) {
Assert.notNull(postId, "Post id must not be null");
if (!(categoriesObject instanceof List)) {
return Collections.emptyList();
}
List<Object> categoryObjectList = (List<Object>) categoriesObject;
List<Category> result = new LinkedList<>();
categoryObjectList.forEach(categoryObject -> {
if (!(categoryObject instanceof Map)) {
return;
}
Map<String, Object> categoryMap = (Map<String, Object>) categoryObject;
String slugName = categoryMap.getOrDefault("cateUrl", "").toString();
Category category = categoryService.getBySlugName(slugName);
if (null == category) {
category = new Category();
category.setName(categoryMap.getOrDefault("cateName", "").toString());
category.setSlugName(slugName);
category.setDescription(categoryMap.getOrDefault("cateDesc", "").toString());
category = categoryService.create(category);
}
PostCategory postCategory = new PostCategory();
postCategory.setCategoryId(category.getId());
postCategory.setPostId(postId);
postCategoryService.create(postCategory);
try {
result.add(category);
} catch (Exception e) {
log.warn("Failed to migrate a category", e);
}
});
return result;
}
@NonNull
private List<Tag> handleTags(@Nullable Object tagsObject, @NonNull Integer postId) {
Assert.notNull(postId, "Post id must not be null");
if (!(tagsObject instanceof List)) {
return Collections.emptyList();
}
List<Object> tagObjectList = (List<Object>) tagsObject;
List<Tag> result = new LinkedList<>();
tagObjectList.forEach(tagObject -> {
if (!(tagObject instanceof Map)) {
return;
}
Map<String, Object> tagMap = (Map<String, Object>) tagObject;
String slugName = tagMap.getOrDefault("tagUrl", "").toString();
Tag tag = tagService.getBySlugName(slugName);
if (null == tag) {
tag = new Tag();
tag.setName(tagMap.getOrDefault("tagName", "").toString());
tag.setSlugName(slugName);
tag = tagService.create(tag);
}
PostTag postTag = new PostTag();
postTag.setTagId(tag.getId());
postTag.setPostId(postId);
postTagService.create(postTag);
try {
result.add(tag);
} catch (Exception e) {
log.warn("Failed to migrate a tag", e);
}
});
return result;
}
@NonNull @NonNull
private List<Menu> handleMenus(@Nullable Object menusObject) { private List<Menu> handleMenus(@Nullable Object menusObject) {

View File

@ -29,7 +29,7 @@ import java.util.stream.Collectors;
* Sheet comment service implementation. * Sheet comment service implementation.
* *
* @author johnniang * @author johnniang
* @date 19-4-24 * @date 2019-04-24
*/ */
@Service @Service
public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment> implements SheetCommentService { public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment> implements SheetCommentService {

View File

@ -31,7 +31,7 @@ import java.util.Set;
* *
* @author johnniang * @author johnniang
* @author ryanwang * @author ryanwang
* @date 19-4-24 * @date 2019-04-24
*/ */
@Service @Service
public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements SheetService { public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements SheetService {
@ -85,13 +85,6 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
return listAll(pageable); return listAll(pageable);
} }
/**
* Gets sheet by post status and url.
*
* @param status post status must not be null
* @param url sheet url must not be blank
* @return sheet info
*/
@Override @Override
public Sheet getBy(PostStatus status, String url) { public Sheet getBy(PostStatus status, String url) {
Sheet sheet = super.getBy(status, url); Sheet sheet = super.getBy(status, url);
@ -109,11 +102,12 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
Assert.notNull(markdown, "Markdown document must not be null"); Assert.notNull(markdown, "Markdown document must not be null");
// Render markdown to html document. // Render markdown to html document.
String content = MarkdownUtils.renderMarkdown(markdown); String content = MarkdownUtils.renderHtml(markdown);
// Gets frontMatter // Gets frontMatter
Map<String, List<String>> frontMatter = MarkdownUtils.getFrontMatter(markdown); Map<String, List<String>> frontMatter = MarkdownUtils.getFrontMatter(markdown);
// TODO
return null; return null;
} }

View File

@ -2,6 +2,7 @@ package run.halo.app.service.impl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import run.halo.app.exception.AlreadyExistsException; import run.halo.app.exception.AlreadyExistsException;
@ -17,10 +18,11 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* TagService implementation class * TagService implementation class.
* *
* @author johnniang
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @date 2019-03-14
*/ */
@Slf4j @Slf4j
@Service @Service
@ -34,6 +36,7 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
} }
@Override @Override
@Transactional
public Tag create(Tag tag) { public Tag create(Tag tag) {
// Check if the tag is exist // Check if the tag is exist
long count = tagRepository.countByNameOrSlugName(tag.getName(), tag.getSlugName()); long count = tagRepository.countByNameOrSlugName(tag.getName(), tag.getSlugName());
@ -49,17 +52,15 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
return super.create(tag); return super.create(tag);
} }
/**
* Get tag by slug name
*
* @param slugName slug name
* @return Tag
*/
@Override @Override
public Tag getBySlugNameOfNonNull(String slugName) { public Tag getBySlugNameOfNonNull(String slugName) {
return tagRepository.getBySlugName(slugName).orElseThrow(() -> new NotFoundException("该标签存在").setErrorData(slugName)); return tagRepository.getBySlugName(slugName).orElseThrow(() -> new NotFoundException("该标签不存在").setErrorData(slugName));
} }
@Override
public Tag getBySlugName(String slugName) {
return tagRepository.getBySlugName(slugName).orElse(null);
}
@Override @Override
public Tag getByName(String name) { public Tag getByName(String name) {

View File

@ -53,7 +53,7 @@ import static run.halo.app.model.support.HaloConst.DEFAULT_THEME_ID;
* Theme service implementation. * Theme service implementation.
* *
* @author ryanwang * @author ryanwang
* @date : 2019/3/26 * @date 2019-03-26
*/ */
@Slf4j @Slf4j
@Service @Service

View File

@ -24,7 +24,7 @@ import java.util.*;
* Theme setting service implementation. * Theme setting service implementation.
* *
* @author johnniang * @author johnniang
* @date 4/8/19 * @date 2019-04-08
*/ */
@Slf4j @Slf4j
@Service @Service

View File

@ -2,18 +2,16 @@ package run.halo.app.service.impl;
import org.springframework.boot.actuate.trace.http.HttpTrace; import org.springframework.boot.actuate.trace.http.HttpTrace;
import org.springframework.boot.actuate.trace.http.HttpTraceRepository; import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import run.halo.app.service.TraceService; import run.halo.app.service.TraceService;
import java.util.List; import java.util.List;
/** /**
* TraceService implementation class.
*
* @author johnniang * @author johnniang
* @date 19-6-18 * @date 2019-06-18
*/ */
@Service @Service
public class TraceServiceImpl implements TraceService { public class TraceServiceImpl implements TraceService {

View File

@ -31,10 +31,11 @@ import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* UserService implementation class * UserService implementation class.
* *
* @author ryanwang * @author ryanwang
* @date : 2019-03-14 * @author johnniang
* @date 2019-03-14
*/ */
@Service @Service
public class UserServiceImpl extends AbstractCrudService<User, Integer> implements UserService { public class UserServiceImpl extends AbstractCrudService<User, Integer> implements UserService {
@ -78,24 +79,11 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
return getByUsername(username).orElseThrow(() -> new NotFoundException("The username dose not exist").setErrorData(username)); return getByUsername(username).orElseThrow(() -> new NotFoundException("The username dose not exist").setErrorData(username));
} }
/**
* Gets user by email.
*
* @param email email must not be blank
* @return an optional user
*/
@Override @Override
public Optional<User> getByEmail(String email) { public Optional<User> getByEmail(String email) {
return userRepository.findByEmail(email); return userRepository.findByEmail(email);
} }
/**
* Gets non null user by email.
*
* @param email email
* @return user info
* @throws NotFoundException throws when the username does not exist
*/
@Override @Override
public User getByEmailOfNonNull(String email) { public User getByEmailOfNonNull(String email) {
return getByEmail(email).orElseThrow(() -> new NotFoundException("The email dose not exist").setErrorData(email)); return getByEmail(email).orElseThrow(() -> new NotFoundException("The email dose not exist").setErrorData(email));

View File

@ -8,7 +8,6 @@ import org.springframework.util.Assert;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.file.Path;
import java.util.UUID; import java.util.UUID;
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR; import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
@ -17,11 +16,14 @@ import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
* Common utils * Common utils
* *
* @author ryanwang * @author ryanwang
* @author johnniang
* @date : 2017/12/22 * @date : 2017/12/22
*/ */
@Slf4j @Slf4j
public class HaloUtils { public class HaloUtils {
private static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
/** /**
* Desensitizes the plain text. * Desensitizes the plain text.
* *
@ -192,4 +194,14 @@ public class HaloUtils {
} }
return machineAddress.getHostAddress(); return machineAddress.getHostAddress();
} }
/**
* Clean all html tag
*
* @param content html document
* @return text before cleaned
*/
public static String cleanHtmlTag(String content) {
return content.replaceAll(RE_HTML_MARK, "");
}
} }

View File

@ -1,147 +1,107 @@
package run.halo.app.utils; package run.halo.app.utils;
import com.vladsch.flexmark.convert.html.FlexmarkHtmlParser;
import com.vladsch.flexmark.ext.attributes.AttributesExtension;
import com.vladsch.flexmark.ext.autolink.AutolinkExtension;
import com.vladsch.flexmark.ext.emoji.EmojiExtension;
import com.vladsch.flexmark.ext.emoji.EmojiImageType;
import com.vladsch.flexmark.ext.emoji.EmojiShortcutType;
import com.vladsch.flexmark.ext.escaped.character.EscapedCharacterExtension;
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension;
import com.vladsch.flexmark.ext.ins.InsExtension;
import com.vladsch.flexmark.ext.media.tags.MediaTagsExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.ext.toc.TocExtension;
import com.vladsch.flexmark.ext.yaml.front.matter.AbstractYamlFrontMatterVisitor;
import com.vladsch.flexmark.ext.yaml.front.matter.YamlFrontMatterExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.options.DataHolder;
import com.vladsch.flexmark.util.options.MutableDataSet;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.commonmark.Extension;
import org.commonmark.ext.autolink.AutolinkExtension;
import org.commonmark.ext.front.matter.YamlFrontMatterExtension;
import org.commonmark.ext.front.matter.YamlFrontMatterVisitor;
import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.ext.heading.anchor.HeadingAnchorExtension;
import org.commonmark.ext.ins.InsExtension;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.commonmark.renderer.text.TextContentRenderer;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import run.halo.app.model.support.HaloConst; import run.halo.app.model.support.HaloConst;
import java.util.Collections; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Markdown utils * Markdown utils.
* *
* @author ryanwang * @author ryanwang
* @date : 2018/11/14 * @date : 2019/06/27
*/ */
public class MarkdownUtils { public class MarkdownUtils {
private static final DataHolder OPTIONS = new MutableDataSet()
.set(Parser.EXTENSIONS, Arrays.asList(
AttributesExtension.create(),
AutolinkExtension.create(),
EmojiExtension.create(),
EscapedCharacterExtension.create(),
StrikethroughExtension.create(),
TaskListExtension.create(),
InsExtension.create(),
MediaTagsExtension.create(),
TablesExtension.create(),
TocExtension.create(),
YamlFrontMatterExtension.create())
)
.set(TablesExtension.WITH_CAPTION, false)
.set(TablesExtension.COLUMN_SPANS, false)
.set(TablesExtension.MIN_HEADER_ROWS, 1)
.set(TablesExtension.MAX_HEADER_ROWS, 1)
.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
.set(EmojiExtension.USE_SHORTCUT_TYPE, EmojiShortcutType.GITHUB)
.set(EmojiExtension.USE_IMAGE_TYPE, EmojiImageType.IMAGE_ONLY);
/** private static final Parser PARSER = Parser.builder(OPTIONS).build();
* commonmark-java extension for autolinking
*/
private static final Set<Extension> EXTENSIONS_AUTO_LINK = Collections.singleton(AutolinkExtension.create());
/** private static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();
* commonmark-java extension for strikethrough
*/
private static final Set<Extension> EXTENSIONS_STRIKETHROUGH = Collections.singleton(StrikethroughExtension.create());
/**
* commonmark-java extension for tables
*/
private static final Set<Extension> EXTENSIONS_TABLES = Collections.singleton(TablesExtension.create());
/**
* commonmark-java extension for adding id attributes to h tags
*/
private static final Set<Extension> EXTENSIONS_HEADING_ANCHOR = Collections.singleton(HeadingAnchorExtension.create());
/**
* commonmark-java extension for &lt;ins&gt; (underline)
*/
private static final Set<Extension> EXTENSIONS_INS = Collections.singleton(InsExtension.create());
/**
* commonmark-java extension for YAML front matter
*/
private static final Set<Extension> EXTENSIONS_YAML_FRONT_MATTER = Collections.singleton(YamlFrontMatterExtension.create());
/**
* Parse Markdown content
*/
private static final Parser PARSER = Parser.builder()
.extensions(EXTENSIONS_AUTO_LINK)
.extensions(EXTENSIONS_STRIKETHROUGH)
.extensions(EXTENSIONS_TABLES)
.extensions(EXTENSIONS_HEADING_ANCHOR)
.extensions(EXTENSIONS_INS)
.extensions(EXTENSIONS_YAML_FRONT_MATTER)
.build();
/**
* Render HTML content
*/
private static final HtmlRenderer RENDERER = HtmlRenderer.builder()
.extensions(EXTENSIONS_AUTO_LINK)
.extensions(EXTENSIONS_STRIKETHROUGH)
.extensions(EXTENSIONS_TABLES)
.extensions(EXTENSIONS_HEADING_ANCHOR)
.extensions(EXTENSIONS_INS)
.extensions(EXTENSIONS_YAML_FRONT_MATTER)
.build();
/**
* Render text content
*/
private static final TextContentRenderer TEXT_CONTENT_RENDERER = TextContentRenderer.builder()
.extensions(EXTENSIONS_AUTO_LINK)
.extensions(EXTENSIONS_STRIKETHROUGH)
.extensions(EXTENSIONS_TABLES)
.extensions(EXTENSIONS_HEADING_ANCHOR)
.extensions(EXTENSIONS_INS)
.extensions(EXTENSIONS_YAML_FRONT_MATTER)
.build();
/** /**
* Render Markdown content * Render Markdown content
* *
* @param content content * @param content content
* @return String * @return String
* @see <a href="https://github.com/otale/tale/blob/master/src/main/java/com/tale/utils/TaleUtils.java">TaleUtils.java</a>
*/ */
public static String renderMarkdown(String content) { public static String renderHtml(String markdown) {
if (StringUtils.isBlank(markdown)) {
return "";
}
Node document = PARSER.parse(markdown);
String renderedContent = RENDERER.render(document);
final Node document = PARSER.parse(content); // Render netease music short url.
String renderContent = RENDERER.render(document); if (markdown.contains(HaloConst.NETEASE_MUSIC_PREFIX)) {
renderedContent = markdown.replaceAll(HaloConst.NETEASE_MUSIC_REG_PATTERN, HaloConst.NETEASE_MUSIC_IFRAME);
// render netease music short url
if (content.contains(HaloConst.NETEASE_MUSIC_PREFIX)) {
renderContent = content.replaceAll(HaloConst.NETEASE_MUSIC_REG_PATTERN, HaloConst.NETEASE_MUSIC_IFRAME);
} }
// render bilibili video short url // Render bilibili video short url.
if (content.contains(HaloConst.BILIBILI_VIDEO_PREFIX)) { if (markdown.contains(HaloConst.BILIBILI_VIDEO_PREFIX)) {
renderContent = content.replaceAll(HaloConst.BILIBILI_VIDEO_REG_PATTERN, HaloConst.BILIBILI_VIDEO_IFRAME); renderedContent = markdown.replaceAll(HaloConst.BILIBILI_VIDEO_REG_PATTERN, HaloConst.BILIBILI_VIDEO_IFRAME);
} }
// render youtube video short url // Render youtube video short url.
if (content.contains(HaloConst.YOUTUBE_VIDEO_PREFIX)) { if (markdown.contains(HaloConst.YOUTUBE_VIDEO_PREFIX)) {
renderContent = content.replaceAll(HaloConst.YOUTUBE_VIDEO_REG_PATTERN, HaloConst.YOUTUBE_VIDEO_IFRAME); renderedContent = markdown.replaceAll(HaloConst.YOUTUBE_VIDEO_REG_PATTERN, HaloConst.YOUTUBE_VIDEO_IFRAME);
} }
return renderContent; return renderedContent;
} }
/** /**
* Render text content. * Render html document to markdown document.
* *
* @param markdownContent markdown content * @param html html document
* @return text content or empty string if markdown content is blank * @return markdown document
*/ */
@NonNull public static String renderMarkdown(String html) {
public static String renderText(@Nullable String markdownContent) { return FlexmarkHtmlParser.parse(html);
if (StringUtils.isBlank(markdownContent)) {
return "";
}
return TEXT_CONTENT_RENDERER.render(PARSER.parse(markdownContent));
} }
/** /**
@ -150,10 +110,10 @@ public class MarkdownUtils {
* @param content content * @param content content
* @return Map * @return Map
*/ */
public static Map<String, List<String>> getFrontMatter(String content) { public static Map<String, List<String>> getFrontMatter(String markdown) {
final YamlFrontMatterVisitor visitor = new YamlFrontMatterVisitor(); AbstractYamlFrontMatterVisitor visitor = new AbstractYamlFrontMatterVisitor();
final Node document = PARSER.parse(content); Node document = PARSER.parse(markdown);
document.accept(visitor); visitor.visit(document);
return visitor.getData(); return visitor.getData();
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
body{height:100%;background-color:#f5f5f5}.container{background:#f7f7f7;position:absolute;top:45%;left:50%;margin:-160px 0 0 -160px;width:320px;padding:16px 32px 32px 32px;-webkit-box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1);box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1)}.container .tip{cursor:pointer;margin-top:.5rem;float:right}.loginLogo{margin-bottom:20px;text-align:center}.loginLogo span{vertical-align:text-bottom;font-size:36px;display:inline-block;font-weight:600;color:#1790fe;background-image:-webkit-gradient(linear,37.219838% 34.532506%,36.425669% 93.178216%,from(#36c8f5),to(#1790fe),color-stop(.37,#1790fe));-webkit-text-fill-color:transparent;-webkit-background-clip:text}

View File

@ -0,0 +1 @@
a[data-v-4b6b2ba0]{text-decoration:none}.sheet-title[data-v-4b6b2ba0]{max-width:300px;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

View File

@ -0,0 +1 @@
.ant-upload-select-picture-card i{font-size:32px;color:#999}.ant-upload-select-picture-card .ant-upload-text{margin-top:8px;color:#666}.ant-upload-list-picture-card{float:none}.more-options-btn[data-v-7111bbfe]{margin-left:15px;text-decoration:none}.photo-card[data-v-7111bbfe]{width:104px;display:inline-block;margin-right:5px}

View File

@ -1 +0,0 @@
.attach-detail-img img{width:100%}.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}@-webkit-keyframes scaleDraw-data-v-0ce6900e{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(1.3);transform:scale(1.3)}50%{-webkit-transform:scale(1);transform:scale(1)}75%{-webkit-transform:scale(1.3);transform:scale(1.3)}}@keyframes scaleDraw-data-v-0ce6900e{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(1.3);transform:scale(1.3)}50%{-webkit-transform:scale(1);transform:scale(1)}75%{-webkit-transform:scale(1.3);transform:scale(1.3)}}.upload-button[data-v-0ce6900e]{-webkit-animation:scaleDraw-data-v-0ce6900e 4s ease-in-out infinite;position:fixed;bottom:30px;right:30px}.theme-thumb[data-v-0ce6900e]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.theme-thumb img[data-v-0ce6900e]{width:100%;height:100%;position:absolute;top:0;left:0}

View File

@ -1 +1 @@
.analysis-card-container[data-v-698a5e37]{position:relative;overflow:hidden;width:100%}.analysis-card-container .meta[data-v-698a5e37]{position:relative;overflow:hidden;width:100%;color:rgba(0,0,0,.45);font-size:14px;line-height:22px}.analysis-card-container .meta .analysis-card-action[data-v-698a5e37]{cursor:pointer;position:absolute;top:0;right:0}.number[data-v-698a5e37]{overflow:hidden;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;color:#000;margin-top:4px;margin-bottom:0;font-size:32px;line-height:38px;height:38px} .analysis-card-container[data-v-698a5e37]{position:relative;overflow:hidden;width:100%}.analysis-card-container .meta[data-v-698a5e37]{position:relative;overflow:hidden;width:100%;color:rgba(0,0,0,.45);font-size:14px;line-height:22px}.analysis-card-container .meta .analysis-card-action[data-v-698a5e37]{cursor:pointer;position:absolute;top:0;right:0}.number[data-v-698a5e37]{overflow:hidden;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;color:#000;margin-top:4px;margin-bottom:0;font-size:32px;line-height:38px;height:38px}.ant-upload-select-picture-card i{font-size:32px;color:#999}.ant-upload-select-picture-card .ant-upload-text{margin-top:8px;color:#666}.ant-upload-list-picture-card{float:none}.more-options-btn[data-v-77a18f66]{margin-left:15px;text-decoration:none}a[data-v-77a18f66]{text-decoration:none}

View File

@ -0,0 +1 @@
.ant-divider-horizontal[data-v-604cba98]{margin:24px 0 12px 0}.search-box[data-v-604cba98]{padding-bottom:12px}.attach-thumb[data-v-604cba98]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.attach-thumb img[data-v-604cba98],.attach-thumb span[data-v-604cba98]{width:100%;height:100%;position:absolute;top:0;left:0}.attach-thumb span[data-v-604cba98]{display:-webkit-box;display:-ms-flexbox;display:flex;font-size:12px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;color:#9b9ea0}.ant-card-meta[data-v-604cba98]{padding:.8rem}.attach-detail-img img[data-v-604cba98]{width:100%}.table-operator[data-v-604cba98]{margin-bottom:0}

View File

@ -0,0 +1 @@
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}a[data-v-a379d92e]{text-decoration:none}.post-title[data-v-a379d92e]{max-width:150px;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

View File

@ -0,0 +1 @@
.v-note-wrapper[data-v-6a7e5dfd]{z-index:1000;min-height:580px}

View File

@ -0,0 +1 @@
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}@font-face{font-family:fontello;src:url(../fonts/fontello.e73a0647.eot);src:url(../fonts/fontello.e73a0647.eot#iefix) format("embedded-opentype"),url(../fonts/fontello.8d4a4e6f.woff2) format("woff2"),url(../fonts/fontello.a782baa8.woff) format("woff"),url(../fonts/fontello.068ca2b3.ttf) format("truetype"),url(../assets/fontello.9354499c.svg#fontello) format("svg");font-weight:400;font-style:normal}[class*=" fa-mavon-"]:before,[class^=fa-mavon-]:before{font-family:fontello;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-mavon-bold:before{content:"\E800"}.fa-mavon-italic:before{content:"\E801"}.fa-mavon-thumb-tack:before{content:"\E802"}.fa-mavon-link:before{content:"\E803"}.fa-mavon-picture-o:before{content:"\E804"}.fa-mavon-repeat:before{content:"\E805"}.fa-mavon-undo:before{content:"\E806"}.fa-mavon-trash-o:before{content:"\E807"}.fa-mavon-floppy-o:before{content:"\E808"}.fa-mavon-compress:before{content:"\E809"}.fa-mavon-eye:before{content:"\E80A"}.fa-mavon-eye-slash:before{content:"\E80B"}.fa-mavon-question-circle:before{content:"\E80C"}.fa-mavon-times:before{content:"\E80D"}.fa-mavon-align-left:before{content:"\E80F"}.fa-mavon-align-center:before{content:"\E810"}.fa-mavon-align-right:before{content:"\E811"}.fa-mavon-arrows-alt:before{content:"\F0B2"}.fa-mavon-bars:before{content:"\F0C9"}.fa-mavon-list-ul:before{content:"\F0CA"}.fa-mavon-list-ol:before{content:"\F0CB"}.fa-mavon-strikethrough:before{content:"\F0CC"}.fa-mavon-underline:before{content:"\F0CD"}.fa-mavon-table:before{content:"\F0CE"}.fa-mavon-columns:before{content:"\F0DB"}.fa-mavon-quote-left:before{content:"\F10D"}.fa-mavon-code:before{content:"\F121"}.fa-mavon-superscript:before{content:"\F12B"}.fa-mavon-subscript:before{content:"\F12C"}.fa-mavon-header:before{content:"\F1DC"}.fa-mavon-window-maximize:before{content:"\F2D0"}.markdown-body strong{font-weight:bolder}.markdown-body .hljs-center{text-align:center}.markdown-body .hljs-right{text-align:right}.markdown-body .hljs-left{text-align:left}

View File

@ -1 +0,0 @@
.attach-detail-img img{width:100%}.ant-divider-horizontal[data-v-18d41aa9]{margin:24px 0 12px 0}.search-box[data-v-18d41aa9]{padding-bottom:12px}.attach-thumb[data-v-18d41aa9]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.attach-thumb img[data-v-18d41aa9]{width:100%;height:100%;position:absolute;top:0;left:0}.ant-card-meta[data-v-18d41aa9]{padding:.8rem}.attach-detail-img img[data-v-18d41aa9]{width:100%}.table-operator[data-v-18d41aa9]{margin-bottom:0}

View File

@ -0,0 +1 @@
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}@-webkit-keyframes scaleDraw-data-v-290ad9ab{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(1.3);transform:scale(1.3)}50%{-webkit-transform:scale(1);transform:scale(1)}75%{-webkit-transform:scale(1.3);transform:scale(1.3)}}@keyframes scaleDraw-data-v-290ad9ab{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(1.3);transform:scale(1.3)}50%{-webkit-transform:scale(1);transform:scale(1)}75%{-webkit-transform:scale(1.3);transform:scale(1.3)}}.upload-button[data-v-290ad9ab]{-webkit-animation:scaleDraw-data-v-290ad9ab 4s ease-in-out infinite;position:fixed;bottom:30px;right:30px}.theme-thumb[data-v-290ad9ab]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.theme-thumb img[data-v-290ad9ab]{width:100%;height:100%;position:absolute;top:0;left:0}

View File

@ -1 +1 @@
.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.page-header-wrapper-grid-content-main[data-v-69ef61d6]{width:100%;height:100%;min-height:100%;-webkit-transition:.3s;transition:.3s}.page-header-wrapper-grid-content-main .profile-center-avatarHolder[data-v-69ef61d6]{text-align:center;margin-bottom:24px}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar[data-v-69ef61d6]{margin:0 auto;width:104px;height:104px;margin-bottom:20px;border-radius:50%;overflow:hidden;cursor:pointer}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar img[data-v-69ef61d6]{height:100%;width:100%}.page-header-wrapper-grid-content-main .profile-center-avatarHolder .username[data-v-69ef61d6]{color:rgba(0,0,0,.85);font-size:20px;line-height:28px;font-weight:500;margin-bottom:4px}.page-header-wrapper-grid-content-main .profile-center-detail p[data-v-69ef61d6]{margin-bottom:8px;padding-left:26px;position:relative}.page-header-wrapper-grid-content-main .profile-center-detail i[data-v-69ef61d6]{position:absolute;height:14px;width:14px;left:0;top:4px} .attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}.page-header-wrapper-grid-content-main[data-v-7e8f2146]{width:100%;height:100%;min-height:100%;-webkit-transition:.3s;transition:.3s}.page-header-wrapper-grid-content-main .profile-center-avatarHolder[data-v-7e8f2146]{text-align:center;margin-bottom:24px}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar[data-v-7e8f2146]{margin:0 auto;width:104px;height:104px;margin-bottom:20px;border-radius:50%;overflow:hidden;cursor:pointer}.page-header-wrapper-grid-content-main .profile-center-avatarHolder>.avatar img[data-v-7e8f2146]{height:100%;width:100%}.page-header-wrapper-grid-content-main .profile-center-avatarHolder .username[data-v-7e8f2146]{color:rgba(0,0,0,.85);font-size:20px;line-height:28px;font-weight:500;margin-bottom:4px}.page-header-wrapper-grid-content-main .profile-center-detail p[data-v-7e8f2146]{margin-bottom:8px;padding-left:26px;position:relative}.page-header-wrapper-grid-content-main .profile-center-detail i[data-v-7e8f2146]{position:absolute;height:14px;width:14px;left:0;top:4px}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
.v-note-wrapper[data-v-348cd59e]{z-index:1000;min-height:580px}.post-thum .img[data-v-348cd59e]{width:100%;cursor:pointer;border-radius:4px}.post-thum .post-thum-remove[data-v-348cd59e]{margin-top:16px}

View File

@ -1 +0,0 @@
.attach-detail-img img{width:100%}.attach-item{width:50%;margin:0 auto;position:relative;padding-bottom:28%;overflow:hidden;float:left;cursor:pointer}.attach-item img{width:100%;height:100%;position:absolute;top:0;left:0}@font-face{font-family:fontello;src:url(../fonts/fontello.e73a0647.eot);src:url(../fonts/fontello.e73a0647.eot#iefix) format("embedded-opentype"),url(../fonts/fontello.8d4a4e6f.woff2) format("woff2"),url(../fonts/fontello.a782baa8.woff) format("woff"),url(../fonts/fontello.068ca2b3.ttf) format("truetype"),url(../assets/fontello.9354499c.svg#fontello) format("svg");font-weight:400;font-style:normal}[class*=" fa-mavon-"]:before,[class^=fa-mavon-]:before{font-family:fontello;font-style:normal;font-weight:400;speak:none;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-mavon-bold:before{content:"\E800"}.fa-mavon-italic:before{content:"\E801"}.fa-mavon-thumb-tack:before{content:"\E802"}.fa-mavon-link:before{content:"\E803"}.fa-mavon-picture-o:before{content:"\E804"}.fa-mavon-repeat:before{content:"\E805"}.fa-mavon-undo:before{content:"\E806"}.fa-mavon-trash-o:before{content:"\E807"}.fa-mavon-floppy-o:before{content:"\E808"}.fa-mavon-compress:before{content:"\E809"}.fa-mavon-eye:before{content:"\E80A"}.fa-mavon-eye-slash:before{content:"\E80B"}.fa-mavon-question-circle:before{content:"\E80C"}.fa-mavon-times:before{content:"\E80D"}.fa-mavon-align-left:before{content:"\E80F"}.fa-mavon-align-center:before{content:"\E810"}.fa-mavon-align-right:before{content:"\E811"}.fa-mavon-arrows-alt:before{content:"\F0B2"}.fa-mavon-bars:before{content:"\F0C9"}.fa-mavon-list-ul:before{content:"\F0CA"}.fa-mavon-list-ol:before{content:"\F0CB"}.fa-mavon-strikethrough:before{content:"\F0CC"}.fa-mavon-underline:before{content:"\F0CD"}.fa-mavon-table:before{content:"\F0CE"}.fa-mavon-columns:before{content:"\F0DB"}.fa-mavon-quote-left:before{content:"\F10D"}.fa-mavon-code:before{content:"\F121"}.fa-mavon-superscript:before{content:"\F12B"}.fa-mavon-subscript:before{content:"\F12C"}.fa-mavon-header:before{content:"\F1DC"}.fa-mavon-window-maximize:before{content:"\F2D0"}.markdown-body strong{font-weight:bolder}.markdown-body .hljs-center{text-align:center}.markdown-body .hljs-right{text-align:right}.markdown-body .hljs-left{text-align:left}

View File

@ -1 +0,0 @@
body{height:100%;background-color:#f5f5f5}.container{background:#f7f7f7;position:absolute;top:45%;left:50%;margin:-160px 0 0 -160px;width:320px;padding:16px 32px 32px 32px;-webkit-box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1);box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1)}.loginLogo{margin-bottom:20px;text-align:center}.loginLogo span{vertical-align:text-bottom;font-size:36px;display:inline-block;font-weight:600;color:#1790fe;background-image:-webkit-gradient(linear,37.219838% 34.532506%,36.425669% 93.178216%,from(#36c8f5),to(#1790fe),color-stop(.37,#1790fe));-webkit-text-fill-color:transparent;-webkit-background-clip:text}

View File

@ -1 +1 @@
<!DOCTYPE html><html lang=zh-cmn-Hans><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta name=robots content=noindex,nofllow><meta name=generator content=Halo><link rel=icon href=/logo.png><title>Halo Dashboard</title><link href=/css/chunk-0337f7a6.4c6b622f.css rel=prefetch><link href=/css/chunk-1079f749.94b473ad.css rel=prefetch><link href=/css/chunk-14e0b302.32f796a8.css rel=prefetch><link href=/css/chunk-161dc990.5ac5144c.css rel=prefetch><link href=/css/chunk-1be69b35.43c1fc12.css rel=prefetch><link href=/css/chunk-31c8ea42.4a090118.css rel=prefetch><link href=/css/chunk-5000e55c.7fb9bc61.css rel=prefetch><link href=/css/chunk-6d8b31f6.ad8d17b2.css rel=prefetch><link href=/css/chunk-81d936d8.05888d95.css rel=prefetch><link href=/css/chunk-b2d0b040.389eca76.css rel=prefetch><link href=/css/chunk-bb4f0d4a.c1990d7c.css rel=prefetch><link href=/css/chunk-bfd5bbcc.6a83ae7d.css rel=prefetch><link href=/css/chunk-c0a1d3c4.09186be6.css rel=prefetch><link href=/css/chunk-cec31564.6f053d75.css rel=prefetch><link href=/css/fail.809a6bc5.css rel=prefetch><link href=/js/chunk-0337f7a6.11326d77.js rel=prefetch><link href=/js/chunk-0ba750a2.b786c9db.js rel=prefetch><link href=/js/chunk-1079f749.ec67c7db.js rel=prefetch><link href=/js/chunk-142c8832.0f8270b3.js rel=prefetch><link href=/js/chunk-14e0b302.a86d1254.js rel=prefetch><link href=/js/chunk-161dc990.5de9313f.js rel=prefetch><link href=/js/chunk-1be69b35.81559bfc.js rel=prefetch><link href=/js/chunk-2d0b64bf.61d5d7c3.js rel=prefetch><link href=/js/chunk-2d0d65a2.2249765a.js rel=prefetch><link href=/js/chunk-2d21a35c.eda7a11a.js rel=prefetch><link href=/js/chunk-2d228d13.85b46532.js rel=prefetch><link href=/js/chunk-31c8ea42.0b2feab9.js rel=prefetch><link href=/js/chunk-5000e55c.3bd9ce3a.js rel=prefetch><link href=/js/chunk-5bf599cc.6555f060.js rel=prefetch><link href=/js/chunk-6d8b31f6.b64e5366.js rel=prefetch><link href=/js/chunk-81d936d8.8bec77ac.js rel=prefetch><link href=/js/chunk-87e2df70.0ada7d4e.js rel=prefetch><link href=/js/chunk-b2d0b040.b0d70d07.js rel=prefetch><link href=/js/chunk-bb4f0d4a.ef7d1ded.js rel=prefetch><link href=/js/chunk-bfd5bbcc.d2ca1e80.js rel=prefetch><link href=/js/chunk-c0a1d3c4.41d0d3f8.js rel=prefetch><link href=/js/chunk-cec31564.cfe3fd85.js rel=prefetch><link href=/js/fail.61f30b0f.js rel=prefetch><link href=/css/app.852293da.css rel=preload as=style><link href=/css/chunk-vendors.ee4e8dbf.css rel=preload as=style><link href=/js/app.29b04043.js rel=preload as=script><link href=/js/chunk-vendors.2f7bce79.js rel=preload as=script><link href=/css/chunk-vendors.ee4e8dbf.css rel=stylesheet><link href=/css/app.852293da.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.2f7bce79.js></script><script src=/js/app.29b04043.js></script></body></html> <!DOCTYPE html><html lang=zh-cmn-Hans><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta name=robots content=noindex,nofllow><meta name=generator content=Halo><link rel=icon href=/logo.png><title>Halo Dashboard</title><link href=/css/chunk-0337f7a6.4c6b622f.css rel=prefetch><link href=/css/chunk-0a078271.3df10fb3.css rel=prefetch><link href=/css/chunk-0d3fb064.5797d58a.css rel=prefetch><link href=/css/chunk-1021dac6.d511bd53.css rel=prefetch><link href=/css/chunk-14ae239d.e9de712a.css rel=prefetch><link href=/css/chunk-14e0b302.32f796a8.css rel=prefetch><link href=/css/chunk-1be69b35.43c1fc12.css rel=prefetch><link href=/css/chunk-2430dc8c.3592751a.css rel=prefetch><link href=/css/chunk-31c8ea42.4a090118.css rel=prefetch><link href=/css/chunk-3939e374.206f7b3f.css rel=prefetch><link href=/css/chunk-3b51c5ec.8e8c628e.css rel=prefetch><link href=/css/chunk-423b6722.dc42f304.css rel=prefetch><link href=/css/chunk-6d8b31f6.ad8d17b2.css rel=prefetch><link href=/css/chunk-71df32ec.5ac5144c.css rel=prefetch><link href=/css/chunk-7af5ef16.684c5100.css rel=prefetch><link href=/css/chunk-aa61da20.bb28474a.css rel=prefetch><link href=/css/chunk-b2e922b4.35a0ae16.css rel=prefetch><link href=/css/chunk-bb4f0d4a.c1990d7c.css rel=prefetch><link href=/css/fail.809a6bc5.css rel=prefetch><link href=/js/chunk-0337f7a6.363f14d6.js rel=prefetch><link href=/js/chunk-0a078271.82e60fe7.js rel=prefetch><link href=/js/chunk-0ba750a2.43dc1b14.js rel=prefetch><link href=/js/chunk-0d3fb064.5a2b4eaa.js rel=prefetch><link href=/js/chunk-1021dac6.8b7c9616.js rel=prefetch><link href=/js/chunk-14ae239d.d15f85b1.js rel=prefetch><link href=/js/chunk-14e0b302.f32c7cb3.js rel=prefetch><link href=/js/chunk-1be69b35.399a467a.js rel=prefetch><link href=/js/chunk-2430dc8c.9c9f8538.js rel=prefetch><link href=/js/chunk-2d0b64bf.ed671024.js rel=prefetch><link href=/js/chunk-2d0d65a2.2f8a16de.js rel=prefetch><link href=/js/chunk-2d21a35c.69287534.js rel=prefetch><link href=/js/chunk-2d228d13.75eca9d7.js rel=prefetch><link href=/js/chunk-31c8ea42.7133cb21.js rel=prefetch><link href=/js/chunk-3939e374.cb5da37a.js rel=prefetch><link href=/js/chunk-3b51c5ec.80a40c78.js rel=prefetch><link href=/js/chunk-423b6722.af6d6aaa.js rel=prefetch><link href=/js/chunk-6d8b31f6.db21019b.js rel=prefetch><link href=/js/chunk-71df32ec.a5429fe8.js rel=prefetch><link href=/js/chunk-7af5ef16.6ad0d11c.js rel=prefetch><link href=/js/chunk-aa61da20.c3df7494.js rel=prefetch><link href=/js/chunk-b2e922b4.32665c80.js rel=prefetch><link href=/js/chunk-bb4f0d4a.4e789394.js rel=prefetch><link href=/js/fail.e23b7151.js rel=prefetch><link href=/css/app.05b5cd85.css rel=preload as=style><link href=/css/chunk-vendors.ee4e8dbf.css rel=preload as=style><link href=/js/app.f0c2e6d9.js rel=preload as=script><link href=/js/chunk-vendors.2f7bce79.js rel=preload as=script><link href=/css/chunk-vendors.ee4e8dbf.css rel=stylesheet><link href=/css/app.05b5cd85.css rel=stylesheet></head><body><noscript><strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.2f7bce79.js></script><script src=/js/app.f0c2e6d9.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More