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 安装包
```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
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

View File

@ -9,7 +9,7 @@ apply plugin: 'io.spring.dependency-management'
group = 'run.halo.app'
archivesBaseName = 'halo'
version = '1.0.2'
version = '1.0.3'
sourceCompatibility = '1.8'
description = 'Halo, personal blog system developed in Java.'
@ -55,13 +55,6 @@ dependencies {
implementation 'com.qiniu:qiniu-java-sdk:7.2.18'
implementation 'com.aliyun.oss:aliyun-sdk-oss:3.4.2'
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-swagger-ui:2.9.2'
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 '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 'mysql:mysql-connector-java'

View File

@ -147,18 +147,24 @@ public class SwaggerConfiguration {
private List<SecurityContext> contentSecurityContext() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(defaultAuth())
.securityReferences(contentApiAuth())
.forPaths(PathSelectors.regex("/api/content/.*"))
.build()
);
}
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),
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() {
return new ApiInfoBuilder()
.title("Halo API Documentation")

View File

@ -81,13 +81,11 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + haloProperties.getWorkDir();
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.addResourceLocations(workDir + "static/");
registry.addResourceHandler("/**")
.addResourceLocations(workDir + "templates/themes/")
.addResourceLocations(workDir + "templates/admin/")
.addResourceLocations("classpath:/admin/");
.addResourceLocations("classpath:/admin/")
.addResourceLocations(workDir + "static/");
registry.addResourceHandler("/upload/**")
.addResourceLocations(workDir + "upload/");
registry.addResourceHandler("/backup/**")
@ -122,7 +120,7 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
configurer.setDefaultEncoding("UTF-8");
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);

View File

@ -2,11 +2,13 @@ package run.halo.app.controller.admin.api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import run.halo.app.cache.lock.CacheLock;
import run.halo.app.model.dto.EnvironmentDTO;
import run.halo.app.model.dto.StatisticDTO;
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.service.AdminService;
@ -16,6 +18,7 @@ import javax.validation.Valid;
* Admin controller.
*
* @author johnniang
* @author ryanwang
* @date 3/19/19
*/
@Slf4j
@ -73,4 +76,9 @@ public class AdminController {
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")
@RequestPart("file") MultipartFile file) {
if (optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false)) {
throw new BadRequestException("不能在博客初始化完成之后迁移数据");
throw new BadRequestException("无法在博客初始化完成之后迁移数据");
}
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 run.halo.app.model.entity.Category;
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.service.*;
import static org.springframework.data.domain.Sort.Direction.DESC;
/**
* Category controller.
*
* @author ryanwang
* @date : 2019/3/20
*/
@ -85,10 +88,10 @@ public class ContentCategoryController {
@PathVariable("page") Integer page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
// 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);
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), pageable);
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
Page<PostListVO> posts = postService.convertToListVo(postPage);
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;
/**
* Search Controller
* Search controller.
*
* @author ryanwang
* @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 run.halo.app.model.entity.Post;
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.service.*;
import static org.springframework.data.domain.Sort.Direction.DESC;
/**
* Tag Controller
* Tag controller.
*
* @author ryanwang
* @date : 2019-03-21
@ -91,7 +92,7 @@ public class ContentTagController {
final Tag tag = tagService.getBySlugNameOfNonNull(slugName);
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);
final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);

View File

@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Admin page.
* Main controller.
*
* @author ryanwang
* @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.entity.Category;
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.PostCategoryService;
import run.halo.app.service.PostService;
@ -58,9 +59,9 @@ public class CategoryController {
public Page<BasePostSimpleDTO> listPostsBy(@PathVariable("slugName") String slugName,
@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable) {
// 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);
}
}

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.entity.Post;
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.PostTagService;
import run.halo.app.service.TagService;
@ -24,6 +25,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
* Portal tag controller.
*
* @author johnniang
* @author ryanwang
* @date 4/2/19
*/
@RestController("ApiContentTagController")
@ -63,7 +65,7 @@ public class TagController {
Tag tag = tagService.getBySlugNameOfNonNull(slugName);
// 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);
}
}

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>
*
* @param <DTO> the implementation class type
* @param <DOMAIN> doamin type
* @param <DOMAIN> domain type
* @author johnniang
*/
public interface OutputConverter<DTO extends OutputConverter<DTO, DOMAIN>, DOMAIN> {

View File

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

View File

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

View File

@ -3,6 +3,7 @@ package run.halo.app.model.freemarker.tag;
import freemarker.core.Environment;
import freemarker.template.*;
import org.springframework.stereotype.Component;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.support.HaloConst;
import run.halo.app.service.PostCategoryService;
import run.halo.app.service.PostService;
@ -57,11 +58,11 @@ public class PostTagDirective implements TemplateDirectiveModel {
break;
case "listByCategoryId":
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;
case "listByTagId":
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;
default:
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.
*
* @author johnniang
* @author ryanwang
* @date 4/1/19
*/
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,""),
STATISTICS_CODE("blog_statistics_code", String.class, ""),
/**
*
*/
SPIDER_DISABLED("spider_disabled", Boolean.class, "false");
STATISTICS_CODE("blog_statistics_code", String.class, "");
private final String value;

View File

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

View File

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

View File

@ -3,6 +3,7 @@ package run.halo.app.repository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull;
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.repository.base.BaseRepository;
@ -14,6 +15,8 @@ import java.util.Set;
* Post category repository.
*
* @author johnniang
* @author ryanwang
* @date 2019-03-19
*/
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")
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.
*

View File

@ -3,6 +3,7 @@ package run.halo.app.repository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull;
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.repository.base.BaseRepository;
@ -14,6 +15,8 @@ import java.util.Set;
* Post tag repository.
*
* @author johnniang
* @author ryanwang
* @date 2019-03-19
*/
public interface PostTagRepository extends BaseRepository<PostTag, Integer> {
@ -55,6 +58,17 @@ public interface PostTagRepository extends BaseRepository<PostTag, Integer> {
@NonNull
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.
*

View File

@ -8,8 +8,8 @@ import org.springframework.util.Assert;
import run.halo.app.config.properties.HaloProperties;
import run.halo.app.exception.AuthenticationException;
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.OtherProperties;
import run.halo.app.service.OptionService;
import javax.servlet.FilterChain;
@ -48,7 +48,7 @@ public class ApiAuthenticationFilter extends AbstractAuthenticationFilter {
}
// 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) {
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
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 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;
/**
* Admin service.
* Admin service interface.
*
* @author johnniang
* @author ryanwang
* @date 19-4-29
* @date 2019-04-29
*/
public interface AdminService {
@ -26,6 +26,8 @@ public interface AdminService {
String REFRESH_TOKEN_CACHE_PREFIX = "halo.admin.refresh_token.";
String LOGS_PATH = "logs/spring.log";
/**
* Authenticates.
*
@ -69,4 +71,10 @@ public interface AdminService {
* Updates halo admin assets.
*/
void updateAdminAssets();
/**
* Get spring logs.
* @return recently logs.
*/
String getSpringLogs();
}

View File

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

View File

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

View File

@ -15,7 +15,10 @@ import java.util.List;
* Category service.
*
* @author johnniang
* @author ryanwang
* @date : 2019-03-14
*/
@Transactional(readOnly = true)
public interface CategoryService extends CrudService<Category, Integer> {
/**
@ -36,6 +39,15 @@ public interface CategoryService extends CrudService<Category, Integer> {
@NonNull
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.
*

View File

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

View File

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

View File

@ -11,9 +11,10 @@ import run.halo.app.service.base.CrudService;
import java.util.List;
/**
* Link service.
* Link service interface.
*
* @author johnniang
* @date 2019-03-14
*/
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;
/**
* Log service.
* Log service interface.
*
* @author johnniang
* @date 2019-03-14
*/
public interface LogService extends CrudService<Log, Long> {

View File

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

View File

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

View File

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

View File

@ -14,9 +14,10 @@ import run.halo.app.service.base.CrudService;
import java.util.List;
/**
* Photo service.
* Photo service interface.
*
* @author johnniang
* @date 2019-03-14
*/
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.Post;
import run.halo.app.model.entity.PostCategory;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.service.base.CrudService;
import java.util.Collection;
@ -21,7 +22,8 @@ import java.util.Set;
* Post category service interface.
*
* @author johnniang
* @date 3/19/19
* @author ryanwang
* @date 2019-03-19
*/
public interface PostCategoryService extends CrudService<PostCategory, Integer> {
@ -52,6 +54,16 @@ public interface PostCategoryService extends CrudService<PostCategory, Integer>
@NonNull
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.
*
@ -62,6 +74,17 @@ public interface PostCategoryService extends CrudService<PostCategory, Integer>
@NonNull
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.
*

View File

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

View File

@ -17,10 +17,11 @@ import java.util.List;
import java.util.Set;
/**
* Post service.
* Post service interface.
*
* @author johnniang
* @author ryanwang
* @date 2019-03-14
*/
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.PostTag;
import run.halo.app.model.entity.Tag;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.service.base.CrudService;
import java.util.Collection;
@ -21,7 +22,8 @@ import java.util.Set;
* Post tag service interface.
*
* @author johnniang
* @date 3/19/19
* @author ryanwang
* @date 2019-03-19
*/
public interface PostTagService extends CrudService<PostTag, Integer> {
@ -61,6 +63,16 @@ public interface PostTagService extends CrudService<PostTag, Integer> {
@NonNull
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.
*
@ -70,6 +82,16 @@ public interface PostTagService extends CrudService<PostTag, Integer> {
*/
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.
*

View File

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

View File

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

View File

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

View File

@ -8,11 +8,12 @@ import run.halo.app.service.base.CrudService;
import java.util.List;
/**
* Tag service.
* Tag service interface.
*
* @author johnniang
* @author ryanwang
* @date 2019-03-14
*/
public interface TagService extends CrudService<Tag, Integer> {
@ -25,6 +26,15 @@ public interface TagService extends CrudService<Tag, Integer> {
@NonNull
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.
*

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,10 @@
package run.halo.app.service.impl;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.lang.Validator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
@ -10,6 +12,7 @@ import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import run.halo.app.cache.StringCacheStore;
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.NotFoundException;
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.entity.User;
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.PostStatus;
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.HaloUtils;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
@ -46,7 +51,7 @@ import static run.halo.app.model.support.HaloConst.*;
*
* @author johnniang
* @author ryanwang
* @date 19-4-29
* @date 2019-04-29
*/
@Slf4j
@Service
@ -76,6 +81,8 @@ public class AdminServiceImpl implements AdminService {
private final HaloProperties haloProperties;
private final ApplicationEventPublisher eventPublisher;
private final String driverClassName;
private final String mode;
@ -92,6 +99,7 @@ public class AdminServiceImpl implements AdminService {
StringCacheStore cacheStore,
RestTemplate restTemplate,
HaloProperties haloProperties,
ApplicationEventPublisher eventPublisher,
@Value("${spring.datasource.driver-class-name}") String driverClassName,
@Value("${spring.profiles.active:prod}") String mode) {
this.postService = postService;
@ -106,6 +114,7 @@ public class AdminServiceImpl implements AdminService {
this.cacheStore = cacheStore;
this.restTemplate = restTemplate;
this.haloProperties = haloProperties;
this.eventPublisher = eventPublisher;
this.driverClassName = driverClassName;
this.mode = mode;
}
@ -126,6 +135,8 @@ public class AdminServiceImpl implements AdminService {
userService.getByEmailOfNonNull(username) : userService.getByUsernameOfNonNull(username);
} catch (NotFoundException 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);
}
@ -133,6 +144,8 @@ public class AdminServiceImpl implements AdminService {
if (!userService.passwordMatch(user, loginParam.getPassword())) {
// If the password is mismatch
eventPublisher.publishEvent(new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED, loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
@ -141,6 +154,9 @@ public class AdminServiceImpl implements AdminService {
throw new BadRequestException("您已登录,请不要重复登录");
}
// Log it then login successful
eventPublisher.publishEvent(new LogEvent(this, user.getUsername(), LogType.LOGGED_IN, user.getNickname()));
// Generate new token
return buildAuthToken(user);
}
@ -170,6 +186,8 @@ public class AdminServiceImpl implements AdminService {
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!");
}
@ -357,4 +375,14 @@ public class AdminServiceImpl implements AdminService {
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
*
* @author ryanwang
* @author johnniang
* @date : 2019-03-14
*/
@Slf4j

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,7 +24,7 @@ import java.util.stream.Collectors;
* LinkService implementation class
*
* @author ryanwang
* @date : 2019-03-14
* @date 2019-03-14
*/
@Service
public class LinkServiceImpl extends AbstractCrudService<Link, Integer> implements LinkService {
@ -36,12 +36,6 @@ public class LinkServiceImpl extends AbstractCrudService<Link, Integer> implemen
this.linkRepository = linkRepository;
}
/**
* List link dtos.
*
* @param sort sort
* @return all links
*/
@Override
public List<LinkDTO> listDtos(Sort sort) {
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
*
* @author ryanwang
* @date : 2019-03-14
* @date 2019-03-14
*/
@Service
public class LogServiceImpl extends AbstractCrudService<Log, Long> implements LogService {

View File

@ -20,7 +20,7 @@ import java.util.Properties;
* Mail service implementation.
*
* @author ryanwang
* @date : 2019-03-17
* @date 2019-03-17
*/
@Slf4j
@Service
@ -37,13 +37,6 @@ public class MailServiceImpl implements MailService {
}
/**
* Sends a simple email
*
* @param to recipient
* @param subject subject
* @param content content
*/
@Override
public void sendMail(String to, String subject, String content) {
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
public void sendTemplateMail(String to, String subject, Map<String, Object> content, String templateName) {
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
public void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilename) {
loadConfig();

View File

@ -21,10 +21,10 @@ import java.util.List;
import java.util.stream.Collectors;
/**
* MenuService implementation class
* MenuService implementation class.
*
* @author ryanwang
* @date : 2019-03-14
* @date 2019-03-14
*/
@Service
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());
}
/**
* Lists as menu tree.
*
* @param sort sort info must not be null
* @return a menu tree
*/
@Override
public List<MenuVO> listAsTree(Sort sort) {
Assert.notNull(sort, "Sort info must not be null");

View File

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

View File

@ -29,7 +29,7 @@ import java.util.stream.Collectors;
* PhotoService implementation class
*
* @author ryanwang
* @date : 2019-03-14
* @date 2019-03-14
*/
@Service
public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implements PhotoService {
@ -41,12 +41,6 @@ public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implem
this.photoRepository = photoRepository;
}
/**
* List photo dtos.
*
* @param sort sort
* @return all photos
*/
@Override
public List<PhotoDTO> listDtos(Sort sort) {
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());
}
/**
* Lists photo team vos.
*
* @param sort must not be null
* @return a list of photo team vo
*/
@Override
public List<PhotoTeamVO> listTeamVos(Sort sort) {
Assert.notNull(sort, "Sort info must not be null");
@ -88,13 +76,6 @@ public class PhotoServiceImpl extends AbstractCrudService<Photo, Integer> implem
return result;
}
/**
* List photos by team.
*
* @param team team
* @param sort sort
* @return list of photos
*/
@Override
public List<PhotoDTO> listByTeam(String team, Sort 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.Post;
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.repository.CategoryRepository;
import run.halo.app.repository.PostCategoryRepository;
@ -25,7 +26,8 @@ import java.util.stream.Collectors;
* Post category service implementation.
*
* @author johnniang
* @date 3/19/19
* @author ryanwang
* @date 2019-03-19
*/
@Service
public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, Integer> implements PostCategoryService {
@ -93,6 +95,17 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
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
public Page<Post> pagePostBy(Integer categoryId, Pageable pageable) {
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);
}
@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
public List<PostCategory> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> categoryIds) {
Assert.notNull(postId, "Post id must not be null");

View File

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

View File

@ -45,6 +45,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
*
* @author johnniang
* @author ryanwang
* @date 2019-03-14
*/
@Slf4j
@Service
@ -280,7 +281,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
Assert.notNull(markdown, "Markdown document must not be null");
// Render markdown to html document.
String content = MarkdownUtils.renderMarkdown(markdown);
String content = MarkdownUtils.renderHtml(markdown);
// Gets frontMatter
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);
if (StringUtils.isBlank(postListVO.getSummary())) {
// Set summary
postListVO.setSummary(convertToSummary(post.getOriginalContent()));
postListVO.setSummary(generateSummary(post.getFormatContent()));
}
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.PostTag;
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.repository.PostRepository;
import run.halo.app.repository.PostTagRepository;
@ -25,7 +26,8 @@ import java.util.stream.Collectors;
* Post tag service implementation.
*
* @author johnniang
* @date 3/19/19
* @author ryanwang
* @date 2019-03-19
*/
@Service
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);
}
@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
public Page<Post> pagePostsBy(Integer tagId, Pageable pageable) {
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);
}
@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
public List<PostTag> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> tagIds) {
Assert.notNull(postId, "Post id must not be null");

View File

@ -33,7 +33,8 @@ import java.util.stream.Collectors;
* Recovery service implementation.
*
* @author johnniang
* @date 19-4-26
* @author ryanwang
* @date 2019-04-26
*/
@Slf4j
@Service
@ -64,6 +65,10 @@ public class RecoveryServiceImpl implements RecoveryService {
private final PhotoService photoService;
private final PostCategoryService postCategoryService;
private final PostTagService postTagService;
public RecoveryServiceImpl(AttachmentService attachmentService,
PostService postService,
LinkService linkService,
@ -75,7 +80,9 @@ public class RecoveryServiceImpl implements RecoveryService {
SheetCommentService sheetCommentService,
SheetCommentRepository sheetCommentRepository,
SheetService sheetService,
PhotoService photoService) {
PhotoService photoService,
PostCategoryService postCategoryService,
PostTagService postTagService) {
this.attachmentService = attachmentService;
this.postService = postService;
this.linkService = linkService;
@ -88,6 +95,8 @@ public class RecoveryServiceImpl implements RecoveryService {
this.sheetCommentRepository = sheetCommentRepository;
this.sheetService = sheetService;
this.photoService = photoService;
this.postCategoryService = postCategoryService;
this.postTagService = postTagService;
}
@Override
@ -215,9 +224,21 @@ public class RecoveryServiceImpl implements RecoveryService {
Post createdPost = postService.createOrUpdateBy(post);
Object commentsObject = postMap.get("comments");
Object categoriesObject = postMap.get("categories");
Object tagsObject = postMap.get("tags");
// Handle comments
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()
.map(baseComment -> BeanUtils.transformFrom(baseComment, PostComment.class))
.collect(Collectors.toList());
@ -372,6 +393,96 @@ public class RecoveryServiceImpl implements RecoveryService {
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
private List<Menu> handleMenus(@Nullable Object menusObject) {

View File

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

View File

@ -31,7 +31,7 @@ import java.util.Set;
*
* @author johnniang
* @author ryanwang
* @date 19-4-24
* @date 2019-04-24
*/
@Service
public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements SheetService {
@ -85,13 +85,6 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
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
public Sheet getBy(PostStatus status, String 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");
// Render markdown to html document.
String content = MarkdownUtils.renderMarkdown(markdown);
String content = MarkdownUtils.renderHtml(markdown);
// Gets frontMatter
Map<String, List<String>> frontMatter = MarkdownUtils.getFrontMatter(markdown);
// TODO
return null;
}

View File

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

View File

@ -24,7 +24,7 @@ import java.util.*;
* Theme setting service implementation.
*
* @author johnniang
* @date 4/8/19
* @date 2019-04-08
*/
@Slf4j
@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.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.util.Assert;
import run.halo.app.service.TraceService;
import java.util.List;
/**
* TraceService implementation class.
*
* @author johnniang
* @date 19-6-18
* @date 2019-06-18
*/
@Service
public class TraceServiceImpl implements TraceService {

View File

@ -31,10 +31,11 @@ import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* UserService implementation class
* UserService implementation class.
*
* @author ryanwang
* @date : 2019-03-14
* @author johnniang
* @date 2019-03-14
*/
@Service
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));
}
/**
* Gets user by email.
*
* @param email email must not be blank
* @return an optional user
*/
@Override
public Optional<User> getByEmail(String 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
public User getByEmailOfNonNull(String 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.UnknownHostException;
import java.nio.file.Path;
import java.util.UUID;
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
*
* @author ryanwang
* @author johnniang
* @date : 2017/12/22
*/
@Slf4j
public class HaloUtils {
private static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
/**
* Desensitizes the plain text.
*
@ -192,4 +194,14 @@ public class HaloUtils {
}
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;
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.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 java.util.Collections;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Markdown utils
* Markdown utils.
*
* @author ryanwang
* @date : 2018/11/14
* @date : 2019/06/27
*/
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);
/**
* commonmark-java extension for autolinking
*/
private static final Set<Extension> EXTENSIONS_AUTO_LINK = Collections.singleton(AutolinkExtension.create());
private static final Parser PARSER = Parser.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();
private static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();
/**
* Render Markdown content
*
* @param content content
* @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);
String renderContent = RENDERER.render(document);
// 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 netease music short url.
if (markdown.contains(HaloConst.NETEASE_MUSIC_PREFIX)) {
renderedContent = markdown.replaceAll(HaloConst.NETEASE_MUSIC_REG_PATTERN, HaloConst.NETEASE_MUSIC_IFRAME);
}
// render bilibili video short url
if (content.contains(HaloConst.BILIBILI_VIDEO_PREFIX)) {
renderContent = content.replaceAll(HaloConst.BILIBILI_VIDEO_REG_PATTERN, HaloConst.BILIBILI_VIDEO_IFRAME);
// Render bilibili video short url.
if (markdown.contains(HaloConst.BILIBILI_VIDEO_PREFIX)) {
renderedContent = markdown.replaceAll(HaloConst.BILIBILI_VIDEO_REG_PATTERN, HaloConst.BILIBILI_VIDEO_IFRAME);
}
// render youtube video short url
if (content.contains(HaloConst.YOUTUBE_VIDEO_PREFIX)) {
renderContent = content.replaceAll(HaloConst.YOUTUBE_VIDEO_REG_PATTERN, HaloConst.YOUTUBE_VIDEO_IFRAME);
// Render youtube video short url.
if (markdown.contains(HaloConst.YOUTUBE_VIDEO_PREFIX)) {
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
* @return text content or empty string if markdown content is blank
* @param html html document
* @return markdown document
*/
@NonNull
public static String renderText(@Nullable String markdownContent) {
if (StringUtils.isBlank(markdownContent)) {
return "";
}
return TEXT_CONTENT_RENDERER.render(PARSER.parse(markdownContent));
public static String renderMarkdown(String html) {
return FlexmarkHtmlParser.parse(html);
}
/**
@ -150,10 +110,10 @@ public class MarkdownUtils {
* @param content content
* @return Map
*/
public static Map<String, List<String>> getFrontMatter(String content) {
final YamlFrontMatterVisitor visitor = new YamlFrontMatterVisitor();
final Node document = PARSER.parse(content);
document.accept(visitor);
public static Map<String, List<String>> getFrontMatter(String markdown) {
AbstractYamlFrontMatterVisitor visitor = new AbstractYamlFrontMatterVisitor();
Node document = PARSER.parse(markdown);
visitor.visit(document);
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