mirror of https://github.com/halo-dev/halo
commit
d6bfa0748c
|
@ -5,7 +5,8 @@
|
|||
|
||||
**我确定我已经查看了** (标注`[ ]`为`[x]`)
|
||||
|
||||
- [ ] [Halo 使用文档](https://docs.halo.run/)
|
||||
- [ ] [Halo 使用文档](https://halo.run/docs)
|
||||
- [ ] [Halo 论坛](https://bbs.halo.run)
|
||||
- [ ] [Github Wiki 常见问题](https://github.com/halo-dev/halo/wiki/4.-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)
|
||||
- [ ] [其他 Issues](https://github.com/halo-dev/halo/issues)
|
||||
|
||||
|
|
|
@ -35,9 +35,10 @@
|
|||
|
||||
## 周边
|
||||
|
||||
- 后台管理源码:<[https://github.com/halo-dev/halo-admin](https://github.com/halo-dev/halo-admin)>
|
||||
- 后台管理(halo-admin):<[https://github.com/halo-dev/halo-admin](https://github.com/halo-dev/halo-admin)>
|
||||
- 独立评论模块(halo-comment):<[https://github.com/halo-dev/halo-comment](https://github.com/halo-dev/halo-comment)>
|
||||
- 管理 APP(halo-app):<[https://github.com/halo-dev/halo-app](https://github.com/halo-dev/halo-app)>
|
||||
- 主题仓库:<[https://halo.run/theme](https://halo.run/theme)>
|
||||
- 管理 APP:<[https://github.com/halo-dev/halo-app](https://github.com/halo-dev/halo-app)>
|
||||
|
||||
## 许可证
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ apply plugin: 'io.spring.dependency-management'
|
|||
|
||||
group = 'run.halo.app'
|
||||
archivesBaseName = 'halo'
|
||||
version = '1.0.0-beta.7'
|
||||
version = '1.0.0-beta.8'
|
||||
sourceCompatibility = '1.8'
|
||||
description = 'Halo, personal blog system developed in Java.'
|
||||
|
||||
|
@ -56,6 +56,10 @@ dependencies {
|
|||
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'
|
||||
|
|
|
@ -113,7 +113,8 @@ public class HaloConfiguration {
|
|||
ApiAuthenticationFilter apiFilter = new ApiAuthenticationFilter(haloProperties, optionService);
|
||||
apiFilter.addExcludeUrlPatterns(
|
||||
"/api/content/*/comments",
|
||||
"/api/content/**/comments/**"
|
||||
"/api/content/**/comments/**",
|
||||
"/api/content/options/comment"
|
||||
);
|
||||
|
||||
DefaultAuthenticationFailureHandler failureHandler = new DefaultAuthenticationFailureHandler();
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
import run.halo.app.service.BackupService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Backup controller
|
||||
*
|
||||
|
@ -19,4 +28,15 @@ public class BackupController {
|
|||
public BackupController(BackupService backupService) {
|
||||
this.backupService = backupService;
|
||||
}
|
||||
|
||||
@PostMapping("import/markdowns")
|
||||
@ApiOperation("Import markdowns")
|
||||
public List<BasePostDetailDTO> backupMarkdowns(@RequestPart("files") MultipartFile[] files) throws IOException {
|
||||
List<BasePostDetailDTO> result = new LinkedList<>();
|
||||
for (MultipartFile file : files) {
|
||||
BasePostDetailDTO post = backupService.importMarkdowns(file);
|
||||
result.add(post);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class JournalController {
|
|||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Gets latest journals")
|
||||
@ApiOperation("Lists journals")
|
||||
public Page<JournalWithCmtCountDTO> pageBy(@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable,
|
||||
JournalQuery journalQuery) {
|
||||
Page<Journal> journalPage = journalService.pageBy(journalQuery, pageable);
|
||||
|
|
|
@ -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("You cannot migrate after blog installing");
|
||||
throw new BadRequestException("不能在博客初始化完成之后迁移数据");
|
||||
}
|
||||
|
||||
recoveryService.migrateFromV0_4_3(file);
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.springframework.data.domain.Page;
|
|||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.model.dto.InternalSheetDTO;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
|
@ -13,6 +14,7 @@ import run.halo.app.model.vo.SheetListVO;
|
|||
import run.halo.app.service.SheetService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
|
@ -20,6 +22,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
|
|||
* Sheet controller.
|
||||
*
|
||||
* @author johnniang
|
||||
* @author ryanwang
|
||||
* @date 19-4-24
|
||||
*/
|
||||
@RestController
|
||||
|
@ -46,6 +49,12 @@ public class SheetController {
|
|||
return sheetService.convertToListVo(sheetPage);
|
||||
}
|
||||
|
||||
@GetMapping("internal")
|
||||
@ApiOperation("Lists internal sheets")
|
||||
public List<InternalSheetDTO> internalSheets() {
|
||||
return sheetService.listInternal();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ApiOperation("Creates a sheet")
|
||||
public BasePostDetailDTO createBy(@RequestBody @Valid SheetParam sheetParam,
|
||||
|
|
|
@ -117,6 +117,13 @@ public class ThemeController {
|
|||
themeSettingService.save(settings, themeId);
|
||||
}
|
||||
|
||||
@PutMapping("{themeId}")
|
||||
public ThemeProperty updateTheme(@PathVariable("themeId") String themeId,
|
||||
@RequestPart(name = "file", required = false) MultipartFile file) {
|
||||
|
||||
return themeService.update(themeId);
|
||||
}
|
||||
|
||||
@DeleteMapping("{themeId}")
|
||||
@ApiOperation("Deletes a theme")
|
||||
public void deleteBy(@PathVariable("themeId") String themeId) {
|
||||
|
@ -145,4 +152,5 @@ public class ThemeController {
|
|||
public BaseResponse exists(@RequestParam(value = "template") String template) {
|
||||
return BaseResponse.ok(themeService.templateExists(template));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import run.halo.app.model.dto.UserDTO;
|
|||
import run.halo.app.model.entity.User;
|
||||
import run.halo.app.model.params.PasswordParam;
|
||||
import run.halo.app.model.params.UserParam;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.model.support.UpdateCheck;
|
||||
import run.halo.app.service.UserService;
|
||||
import run.halo.app.utils.ValidationUtils;
|
||||
|
@ -45,7 +46,8 @@ public class UserController {
|
|||
}
|
||||
|
||||
@PutMapping("profiles/password")
|
||||
public void updatePassword(@RequestBody @Valid PasswordParam passwordParam, User user) {
|
||||
public BaseResponse updatePassword(@RequestBody @Valid PasswordParam passwordParam, User user) {
|
||||
userService.updatePassword(passwordParam.getOldPassword(), passwordParam.getNewPassword(), user.getId());
|
||||
return BaseResponse.ok("密码修改成功");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,18 @@ import org.springframework.data.web.SortDefault;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
import run.halo.app.model.entity.JournalComment;
|
||||
import run.halo.app.model.enums.CommentStatus;
|
||||
import run.halo.app.model.params.JournalCommentParam;
|
||||
import run.halo.app.model.vo.BaseCommentVO;
|
||||
import run.halo.app.model.vo.BaseCommentWithParentVO;
|
||||
import run.halo.app.model.vo.CommentWithHasChildrenVO;
|
||||
import run.halo.app.service.JournalCommentService;
|
||||
import run.halo.app.service.JournalService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
|
@ -39,12 +44,32 @@ public class JournalController {
|
|||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/top_view")
|
||||
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
Page<CommentWithHasChildrenVO> result = journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return journalCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/{commentParentId:\\d+}/children")
|
||||
public List<BaseCommentDTO> listChildrenBy(@PathVariable("journalId") Integer journalId,
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
// Find all children comments
|
||||
List<JournalComment> postComments = journalCommentService.listChildrenBy(journalId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
// Convert to base comment dto
|
||||
List<BaseCommentDTO> result = journalCommentService.convertTo(postComments);
|
||||
return journalCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/tree_view")
|
||||
@ApiOperation("Lists comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentsTree(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageVosBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
Page<BaseCommentVO> result = journalCommentService.pageVosBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return journalCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{journalId:\\d+}/comments/list_view")
|
||||
|
@ -52,7 +77,8 @@ public class JournalController {
|
|||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("journalId") Integer journalId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return journalCommentService.pageWithParentVoBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
Page<BaseCommentWithParentVO> result = journalCommentService.pageWithParentVoBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return journalCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@PostMapping("comments")
|
||||
|
|
|
@ -8,6 +8,7 @@ import run.halo.app.model.dto.OptionDTO;
|
|||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -48,4 +49,14 @@ public class OptionController {
|
|||
public BaseResponse<Object> getBy(@PathVariable("key") String key) {
|
||||
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), optionService.getByKey(key).orElse(null));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("comment")
|
||||
@ApiOperation("Options for comment")
|
||||
public Map<String, Object> comment() {
|
||||
List<String> keys = new ArrayList<>();
|
||||
keys.add("comment_gavatar_default");
|
||||
keys.add("comment_content_placeholder");
|
||||
return optionService.listOptions(keys);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,10 @@ public class PostController {
|
|||
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
|
||||
Page<CommentWithHasChildrenVO> result = postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
|
||||
return postCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,7 +97,10 @@ public class PostController {
|
|||
// Find all children comments
|
||||
List<PostComment> postComments = postCommentService.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
// Convert to base comment dto
|
||||
return postCommentService.convertTo(postComments);
|
||||
|
||||
List<BaseCommentDTO> result = postCommentService.convertTo(postComments);
|
||||
|
||||
return postCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{postId:\\d+}/comments/tree_view")
|
||||
|
@ -102,7 +108,8 @@ public class PostController {
|
|||
public Page<BaseCommentVO> listCommentsTree(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageVosBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
Page<BaseCommentVO> result = postCommentService.pageVosBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return postCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{postId:\\d+}/comments/list_view")
|
||||
|
@ -110,7 +117,8 @@ public class PostController {
|
|||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("postId") Integer postId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return postCommentService.pageWithParentVoBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
Page<BaseCommentWithParentVO> result = postCommentService.pageWithParentVoBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return postCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@PostMapping("comments")
|
||||
|
|
|
@ -8,13 +8,18 @@ import org.springframework.data.web.SortDefault;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.model.dto.BaseCommentDTO;
|
||||
import run.halo.app.model.entity.SheetComment;
|
||||
import run.halo.app.model.enums.CommentStatus;
|
||||
import run.halo.app.model.params.SheetCommentParam;
|
||||
import run.halo.app.model.vo.BaseCommentVO;
|
||||
import run.halo.app.model.vo.BaseCommentWithParentVO;
|
||||
import run.halo.app.model.vo.CommentWithHasChildrenVO;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.SheetCommentService;
|
||||
import run.halo.app.service.SheetService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
|
@ -39,13 +44,33 @@ public class SheetController {
|
|||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/comments/top_view")
|
||||
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
Page<CommentWithHasChildrenVO> result = sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return sheetCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/comments/{commentParentId:\\d+}/children")
|
||||
public List<BaseCommentDTO> listChildrenBy(@PathVariable("sheetId") Integer sheetId,
|
||||
@PathVariable("commentParentId") Long commentParentId,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
// Find all children comments
|
||||
List<SheetComment> sheetComments = sheetCommentService.listChildrenBy(sheetId, commentParentId, CommentStatus.PUBLISHED, sort);
|
||||
// Convert to base comment dto
|
||||
List<BaseCommentDTO> result = sheetCommentService.convertTo(sheetComments);
|
||||
return sheetCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/comments/tree_view")
|
||||
@ApiOperation("Lists comments with tree view")
|
||||
public Page<BaseCommentVO> listCommentsTree(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageVosBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
Page<BaseCommentVO> result = sheetCommentService.pageVosBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return sheetCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@GetMapping("{sheetId:\\d+}/comments/list_view")
|
||||
|
@ -53,7 +78,8 @@ public class SheetController {
|
|||
public Page<BaseCommentWithParentVO> listComments(@PathVariable("sheetId") Integer sheetId,
|
||||
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
return sheetCommentService.pageWithParentVoBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
Page<BaseCommentWithParentVO> result = sheetCommentService.pageWithParentVoBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
|
||||
return sheetCommentService.filterIpAddress(result);
|
||||
}
|
||||
|
||||
@PostMapping("comments")
|
||||
|
|
|
@ -57,11 +57,7 @@ public class CommonController implements ErrorController {
|
|||
}
|
||||
}
|
||||
|
||||
if (statusCode == 500) {
|
||||
return "redirect:/500";
|
||||
} else {
|
||||
return "redirect:/404";
|
||||
}
|
||||
return statusCode == 500 ? "redirect:/500" : "redirect:/404";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package run.halo.app.exception;
|
||||
|
||||
/**
|
||||
* Theme update exception.
|
||||
*
|
||||
* @author johnniang
|
||||
* @date 19-5-30
|
||||
*/
|
||||
public class ThemeUpdateException extends ServiceException {
|
||||
|
||||
public ThemeUpdateException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ThemeUpdateException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ public class AliYunFileHandler implements FileHandler {
|
|||
String ossAccessKey = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ACCESS_KEY).toString();
|
||||
String ossAccessSecret = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ACCESS_SECRET).toString();
|
||||
String ossBucketName = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_BUCKET_NAME).toString();
|
||||
String ossStyleRule = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_STYLE_RULE).toString();
|
||||
String ossSource = StringUtils.join("https://", ossBucketName, "." + ossEndPoint);
|
||||
|
||||
// Init OSS client
|
||||
|
@ -61,7 +62,7 @@ public class AliYunFileHandler implements FileHandler {
|
|||
// Upload
|
||||
PutObjectResult putObjectResult = ossClient.putObject(ossBucketName, upFilePath, file.getInputStream());
|
||||
if (putObjectResult == null) {
|
||||
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to AliYun " + upFilePath);
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ");
|
||||
}
|
||||
|
||||
// Response result
|
||||
|
@ -78,7 +79,7 @@ public class AliYunFileHandler implements FileHandler {
|
|||
BufferedImage image = ImageIO.read(file.getInputStream());
|
||||
uploadResult.setWidth(image.getWidth());
|
||||
uploadResult.setHeight(image.getHeight());
|
||||
uploadResult.setThumbPath(filePath);
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(ossStyleRule) ? filePath : filePath + ossStyleRule);
|
||||
}
|
||||
|
||||
return uploadResult;
|
||||
|
@ -113,7 +114,7 @@ public class AliYunFileHandler implements FileHandler {
|
|||
try {
|
||||
ossClient.deleteObject(new DeleteObjectsRequest(ossBucketName).withKey(key));
|
||||
} catch (Exception e) {
|
||||
throw new FileOperationException("Failed to delete file " + key + " from AliYun", e);
|
||||
throw new FileOperationException("附件 " + key + " 从阿里云删除失败", e);
|
||||
} finally {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ public class LocalFileHandler implements FileHandler {
|
|||
return uploadResult;
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to upload file to local: " + uploadPath, e);
|
||||
throw new ServiceException("Failed to upload file to local").setErrorData(uploadPath);
|
||||
throw new ServiceException("上传附件失败").setErrorData(uploadPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ public class LocalFileHandler implements FileHandler {
|
|||
try {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
throw new FileOperationException("Failed to delete " + key + " file", e);
|
||||
throw new FileOperationException("附件 " + key + " 删除失败", e);
|
||||
}
|
||||
|
||||
// Delete thumb if necessary
|
||||
|
@ -197,7 +197,7 @@ public class LocalFileHandler implements FileHandler {
|
|||
log.warn("Thumbnail: [{}] way not exist", thumbnailPath.toString());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FileOperationException("Failed to delete " + thumbnailName + " thumbnail", e);
|
||||
throw new FileOperationException("附件缩略图 " + thumbnailName + " 删除失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@ public class QnYunFileHandler implements FileHandler {
|
|||
|
||||
// Get all config
|
||||
Zone zone = optionService.getQnYunZone();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(QnYunProperties.ACCESS_KEY).toString();
|
||||
String secretKey = optionService.getByPropertyOfNonNull(QnYunProperties.SECRET_KEY).toString();
|
||||
String bucket = optionService.getByPropertyOfNonNull(QnYunProperties.BUCKET).toString();
|
||||
String domain = optionService.getByPropertyOfNonNull(QnYunProperties.DOMAIN).toString();
|
||||
String smallUrl = optionService.getByPropertyOrDefault(QnYunProperties.SMALL_URL, String.class, "");
|
||||
String accessKey = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_ACCESS_KEY).toString();
|
||||
String secretKey = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_SECRET_KEY).toString();
|
||||
String bucket = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_BUCKET).toString();
|
||||
String domain = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_DOMAIN).toString();
|
||||
String styleRule = optionService.getByPropertyOrDefault(QnYunProperties.OSS_STYLE_RULE, String.class, "");
|
||||
|
||||
// Create configuration
|
||||
Configuration configuration = new Configuration(zone);
|
||||
|
@ -109,9 +109,10 @@ public class QnYunFileHandler implements FileHandler {
|
|||
result.setWidth(putSet.getWidth());
|
||||
result.setHeight(putSet.getHeight());
|
||||
result.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||
result.setSize(file.getSize());
|
||||
|
||||
if (isImageType(result.getMediaType())) {
|
||||
result.setThumbPath(StringUtils.isBlank(smallUrl) ? filePath : filePath + smallUrl);
|
||||
result.setThumbPath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -120,7 +121,7 @@ public class QnYunFileHandler implements FileHandler {
|
|||
log.error("QnYun error response: [{}]", ((QiniuException) e).response);
|
||||
}
|
||||
|
||||
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to QnYun", e);
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到七牛云失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,9 +131,9 @@ public class QnYunFileHandler implements FileHandler {
|
|||
|
||||
// Get all config
|
||||
Zone zone = optionService.getQnYunZone();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(QnYunProperties.ACCESS_KEY).toString();
|
||||
String secretKey = optionService.getByPropertyOfNonNull(QnYunProperties.SECRET_KEY).toString();
|
||||
String bucket = optionService.getByPropertyOfNonNull(QnYunProperties.BUCKET).toString();
|
||||
String accessKey = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_ACCESS_KEY).toString();
|
||||
String secretKey = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_SECRET_KEY).toString();
|
||||
String bucket = optionService.getByPropertyOfNonNull(QnYunProperties.OSS_BUCKET).toString();
|
||||
|
||||
// Create configuration
|
||||
Configuration configuration = new Configuration(zone);
|
||||
|
|
|
@ -50,7 +50,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
|
||||
if (!FileHandler.isImageType(file.getContentType())) {
|
||||
log.error("Invalid extension: [{}]", file.getContentType());
|
||||
throw new FileOperationException("Invalid extension for file " + file.getOriginalFilename() + ". Only \"jpeg, jpg, png, gif, bmp\" files are supported");
|
||||
throw new FileOperationException("不支持的文件类型,仅支持 \"jpeg, jpg, png, gif, bmp\" 格式的图片");
|
||||
}
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
@ -65,7 +65,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
body.add("smfile", new HttpClientUtils.MultipartFileResource(file.getBytes(), file.getOriginalFilename()));
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to get file input stream", e);
|
||||
throw new FileOperationException("Failed to upload " + file.getOriginalFilename() + " file", e);
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到 SM.MS 失败", e);
|
||||
}
|
||||
|
||||
body.add("ssl", false);
|
||||
|
@ -79,7 +79,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
// Check status
|
||||
if (mapResponseEntity.getStatusCode().isError()) {
|
||||
log.error("Server response detail: [{}]", mapResponseEntity.toString());
|
||||
throw new FileOperationException("Smms server response error. status: " + mapResponseEntity.getStatusCodeValue());
|
||||
throw new FileOperationException("SM.MS 服务状态异常,状态码: " + mapResponseEntity.getStatusCodeValue());
|
||||
}
|
||||
|
||||
// Get smms response
|
||||
|
@ -88,7 +88,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
// Check error
|
||||
if (!isResponseSuccessfully(smmsResponse)) {
|
||||
log.error("Smms response detail: [{}]", smmsResponse);
|
||||
throw new FileOperationException(smmsResponse == null ? "Smms response is null" : smmsResponse.getMsg()).setErrorData(smmsResponse);
|
||||
throw new FileOperationException(smmsResponse == null ? "SM.MS 服务返回内容为空" : smmsResponse.getMsg()).setErrorData(smmsResponse);
|
||||
}
|
||||
|
||||
// Get response data
|
||||
|
@ -128,7 +128,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
|
||||
if (responseEntity.getStatusCode().isError()) {
|
||||
log.debug("Smms server response error: [{}]", responseEntity.toString());
|
||||
throw new FileOperationException("Smms server response error");
|
||||
throw new FileOperationException("SM.MS 服务状态异常");
|
||||
}
|
||||
|
||||
log.debug("Smms response detail: [{}]", responseEntity.getBody());
|
||||
|
@ -155,7 +155,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
@Data
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
static class SmmsResponse {
|
||||
private static class SmmsResponse {
|
||||
|
||||
private String code;
|
||||
|
||||
|
@ -168,7 +168,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
static class SmmsResponseData {
|
||||
private static class SmmsResponseData {
|
||||
|
||||
private String filename;
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ public class UpYunFileHandler implements FileHandler {
|
|||
String ossBucket = optionService.getByPropertyOfNonNull(UpYunProperties.OSS_BUCKET).toString();
|
||||
String ossDomain = optionService.getByPropertyOfNonNull(UpYunProperties.OSS_DOMAIN).toString();
|
||||
String ossOperator = optionService.getByPropertyOfNonNull(UpYunProperties.OSS_OPERATOR).toString();
|
||||
// small url can be null
|
||||
String ossSmallUrl = optionService.getByPropertyOrDefault(UpYunProperties.OSS_SMALL_URL, String.class, "");
|
||||
// style rule can be null
|
||||
String ossStyleRule = optionService.getByPropertyOrDefault(UpYunProperties.OSS_STYLE_RULE, String.class, "");
|
||||
|
||||
// Create up yun
|
||||
UpYun upYun = new UpYun(ossBucket, ossOperator, ossPassword);
|
||||
|
@ -67,7 +67,7 @@ public class UpYunFileHandler implements FileHandler {
|
|||
// Write file
|
||||
boolean uploadSuccess = upYun.writeFile(upFilePath, file.getInputStream(), true, null);
|
||||
if (!uploadSuccess) {
|
||||
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to UpYun " + upFilePath);
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到又拍云失败" + upFilePath);
|
||||
}
|
||||
|
||||
String filePath = StringUtils.removeEnd(ossDomain, "/") + upFilePath;
|
||||
|
@ -86,12 +86,12 @@ public class UpYunFileHandler implements FileHandler {
|
|||
BufferedImage image = ImageIO.read(file.getInputStream());
|
||||
uploadResult.setWidth(image.getWidth());
|
||||
uploadResult.setHeight(image.getHeight());
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(ossSmallUrl) ? filePath : filePath + ossSmallUrl);
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(ossStyleRule) ? filePath : filePath + ossStyleRule);
|
||||
}
|
||||
|
||||
return uploadResult;
|
||||
} catch (Exception e) {
|
||||
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to UpYun", e);
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到又拍云失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ public class UpYunFileHandler implements FileHandler {
|
|||
log.warn("Failed to delete file " + filePath + " from UpYun");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new FileOperationException("Failed to delete file " + key + " from UpYun", e);
|
||||
throw new FileOperationException("附件从又拍云删除失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package run.halo.app.handler.theme.config.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -18,7 +20,12 @@ import java.io.IOException;
|
|||
@Service
|
||||
public class YamlThemePropertyResolver implements ThemePropertyResolver {
|
||||
|
||||
private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
|
||||
private final ObjectMapper yamlMapper;
|
||||
|
||||
public YamlThemePropertyResolver() {
|
||||
yamlMapper = new ObjectMapper(new YAMLFactory());
|
||||
yamlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThemeProperty resolve(String content) throws IOException {
|
||||
|
|
|
@ -28,6 +28,16 @@ public class ThemeProperty {
|
|||
*/
|
||||
private String website;
|
||||
|
||||
/**
|
||||
* Theme remote branch.(default is master)
|
||||
*/
|
||||
private String branch;
|
||||
|
||||
/**
|
||||
* Theme repo url.
|
||||
*/
|
||||
private String repo;
|
||||
|
||||
/**
|
||||
* Theme description.
|
||||
*/
|
||||
|
@ -49,7 +59,7 @@ public class ThemeProperty {
|
|||
private Author author;
|
||||
|
||||
/**
|
||||
* Theme path.
|
||||
* Theme full path.
|
||||
*/
|
||||
private String themePath;
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package run.halo.app.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2019-05-25
|
||||
*/
|
||||
@Data
|
||||
public class BackupDTO {
|
||||
|
||||
private String fileName;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private String fileSize;
|
||||
|
||||
private String fileType;
|
||||
|
||||
private String type;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package run.halo.app.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Theme controller.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date : 2019/5/4
|
||||
*/
|
||||
@Data
|
||||
public class InternalSheetDTO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String url;
|
||||
|
||||
private boolean status;
|
||||
}
|
|
@ -12,6 +12,7 @@ import run.halo.app.utils.HaloUtils;
|
|||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +51,8 @@ public class PostParam implements InputConverter<Post> {
|
|||
@Min(value = 0, message = "Post top priority must not be less than {value}")
|
||||
private Integer topPriority = 0;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private PostCreateFrom createFrom = PostCreateFrom.ADMIN;
|
||||
|
||||
private Set<Integer> tagIds;
|
||||
|
|
|
@ -26,7 +26,12 @@ public enum AliYunProperties implements PropertyEnum {
|
|||
/**
|
||||
* Aliyun oss access secret.
|
||||
*/
|
||||
OSS_ACCESS_SECRET("oss_aliyun_access_secret", String.class, "");
|
||||
OSS_ACCESS_SECRET("oss_aliyun_access_secret", String.class, ""),
|
||||
|
||||
/**
|
||||
* Aliyun oss style rule
|
||||
*/
|
||||
OSS_STYLE_RULE("oss_aliyun_style_rule", String.class, "");
|
||||
|
||||
private final String value;
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ package run.halo.app.model.properties;
|
|||
* Comment properties.
|
||||
*
|
||||
* @author johnniang
|
||||
* @date 4/1/19
|
||||
* @author ryanwang
|
||||
* @date 2019-04-01
|
||||
*/
|
||||
public enum CommentProperties implements PropertyEnum {
|
||||
|
||||
|
@ -22,9 +23,7 @@ public enum CommentProperties implements PropertyEnum {
|
|||
|
||||
PAGE_SIZE("comment_page_size", Integer.class, "10"),
|
||||
|
||||
CONTENT_PLACEHOLDER("comment_content_placeholder", String.class, ""),
|
||||
|
||||
CUSTOM_STYLE("comment_custom_style", String.class, "");
|
||||
CONTENT_PLACEHOLDER("comment_content_placeholder", String.class, "");
|
||||
|
||||
private final String value;
|
||||
|
||||
|
|
|
@ -8,17 +8,17 @@ package run.halo.app.model.properties;
|
|||
*/
|
||||
public enum QnYunProperties implements PropertyEnum {
|
||||
|
||||
ZONE("oss_qiniu_zone", String.class, "auto"),
|
||||
OSS_ZONE("oss_qiniu_zone", String.class, "auto"),
|
||||
|
||||
ACCESS_KEY("oss_qiniu_access_key", String.class, ""),
|
||||
OSS_ACCESS_KEY("oss_qiniu_access_key", String.class, ""),
|
||||
|
||||
SECRET_KEY("oss_qiniu_secret_key", String.class, ""),
|
||||
OSS_SECRET_KEY("oss_qiniu_secret_key", String.class, ""),
|
||||
|
||||
DOMAIN("oss_qiniu_domain", String.class, ""),
|
||||
OSS_DOMAIN("oss_qiniu_domain", String.class, ""),
|
||||
|
||||
BUCKET("oss_qiniu_bucket", String.class, ""),
|
||||
OSS_BUCKET("oss_qiniu_bucket", String.class, ""),
|
||||
|
||||
SMALL_URL("oss_qiniu_small_url", String.class, "");
|
||||
OSS_STYLE_RULE("oss_qiniu_style_rule", String.class, "");
|
||||
|
||||
private final String value;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ public enum UpYunProperties implements PropertyEnum {
|
|||
|
||||
OSS_OPERATOR("oss_upyun_operator", String.class, ""),
|
||||
|
||||
OSS_SMALL_URL("oss_upyun_small_url", String.class, "");
|
||||
OSS_STYLE_RULE("oss_upyun_style_rule", String.class, "");
|
||||
|
||||
private final String defaultValue;
|
||||
private String value;
|
||||
|
|
|
@ -36,4 +36,12 @@ public interface CategoryRepository extends BaseRepository<Category, Integer> {
|
|||
* @return Optional of Category
|
||||
*/
|
||||
Optional<Category> getBySlugName(@NonNull String slugName);
|
||||
|
||||
/**
|
||||
* Get category by name.
|
||||
*
|
||||
* @param name name
|
||||
* @return Optional of Category
|
||||
*/
|
||||
Optional<Category> getByName(@NonNull String name);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package run.halo.app.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.lang.NonNull;
|
||||
import run.halo.app.model.entity.JournalComment;
|
||||
import run.halo.app.model.projection.CommentChildrenCountProjection;
|
||||
import run.halo.app.model.projection.CommentCountProjection;
|
||||
import run.halo.app.repository.base.BaseCommentRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Journal comment repository.
|
||||
*
|
||||
|
@ -11,8 +17,18 @@ import run.halo.app.repository.base.BaseCommentRepository;
|
|||
*/
|
||||
public interface JournalCommentRepository extends BaseCommentRepository<JournalComment> {
|
||||
|
||||
// @Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) from JournalComment comment where comment.postId in ?1 group by comment.postId")
|
||||
// @NonNull
|
||||
// @Override
|
||||
// List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
|
||||
@Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) " +
|
||||
"from JournalComment comment " +
|
||||
"where comment.postId in ?1 group by comment.postId")
|
||||
@NonNull
|
||||
@Override
|
||||
List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
|
||||
|
||||
@Query("select new run.halo.app.model.projection.CommentChildrenCountProjection(count(comment.id), comment.parentId) " +
|
||||
"from JournalComment comment " +
|
||||
"where comment.parentId in ?1 " +
|
||||
"group by comment.parentId")
|
||||
@NonNull
|
||||
@Override
|
||||
List<CommentChildrenCountProjection> findDirectChildrenCount(@NonNull Iterable<Long> commentIds);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package run.halo.app.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.lang.NonNull;
|
||||
import run.halo.app.model.entity.PostComment;
|
||||
import run.halo.app.model.projection.CommentChildrenCountProjection;
|
||||
import run.halo.app.model.projection.CommentCountProjection;
|
||||
import run.halo.app.repository.base.BaseCommentRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PostComment repository.
|
||||
*
|
||||
|
@ -11,9 +17,17 @@ import run.halo.app.repository.base.BaseCommentRepository;
|
|||
*/
|
||||
public interface PostCommentRepository extends BaseCommentRepository<PostComment> {
|
||||
|
||||
// @Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) from PostComment comment where comment.postId in ?1 group by comment.postId")
|
||||
// @NonNull
|
||||
// @Override
|
||||
// List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
|
||||
@Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) " +
|
||||
"from PostComment comment " +
|
||||
"where comment.postId in ?1 group by comment.postId")
|
||||
@NonNull
|
||||
@Override
|
||||
List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
|
||||
|
||||
@Query("select new run.halo.app.model.projection.CommentChildrenCountProjection(count(comment.id), comment.parentId) " +
|
||||
"from PostComment comment " +
|
||||
"where comment.parentId in ?1 " +
|
||||
"group by comment.parentId")
|
||||
@NonNull
|
||||
List<CommentChildrenCountProjection> findDirectChildrenCount(@NonNull Iterable<Long> commentIds);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package run.halo.app.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.lang.NonNull;
|
||||
import run.halo.app.model.entity.SheetComment;
|
||||
import run.halo.app.model.projection.CommentChildrenCountProjection;
|
||||
import run.halo.app.model.projection.CommentCountProjection;
|
||||
import run.halo.app.repository.base.BaseCommentRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sheet comment repository.
|
||||
*
|
||||
|
@ -10,9 +16,18 @@ import run.halo.app.repository.base.BaseCommentRepository;
|
|||
* @date 19-4-24
|
||||
*/
|
||||
public interface SheetCommentRepository extends BaseCommentRepository<SheetComment> {
|
||||
//
|
||||
// @Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) from SheetComment comment where comment.postId in ?1 group by comment.postId")
|
||||
// @NonNull
|
||||
// @Override
|
||||
// List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
|
||||
|
||||
@Query("select new run.halo.app.model.projection.CommentCountProjection(count(comment.id), comment.postId) " +
|
||||
"from SheetComment comment " +
|
||||
"where comment.postId in ?1 group by comment.postId")
|
||||
@NonNull
|
||||
@Override
|
||||
List<CommentCountProjection> countByPostIds(@NonNull Iterable<Integer> postIds);
|
||||
|
||||
@Query("select new run.halo.app.model.projection.CommentChildrenCountProjection(count(comment.id), comment.parentId) " +
|
||||
"from SheetComment comment " +
|
||||
"where comment.parentId in ?1 " +
|
||||
"group by comment.parentId")
|
||||
@NonNull
|
||||
List<CommentChildrenCountProjection> findDirectChildrenCount(@NonNull Iterable<Long> commentIds);
|
||||
}
|
||||
|
|
|
@ -29,4 +29,11 @@ public interface TagRepository extends BaseRepository<Tag, Integer> {
|
|||
* @return Tag
|
||||
*/
|
||||
Optional<Tag> getBySlugName(@NonNull String slugName);
|
||||
|
||||
/**
|
||||
* Get tag by name
|
||||
* @param name name
|
||||
* @return Tag
|
||||
*/
|
||||
Optional<Tag> getByName(@NonNull String name);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
package run.halo.app.service;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Backup service interface.
|
||||
*
|
||||
|
@ -7,4 +12,12 @@ package run.halo.app.service;
|
|||
* @date 19-4-26
|
||||
*/
|
||||
public interface BackupService {
|
||||
|
||||
/**
|
||||
* Backup posts and sheets
|
||||
*
|
||||
* @param file file
|
||||
* @return post info
|
||||
*/
|
||||
BasePostDetailDTO importMarkdowns(MultipartFile file) throws IOException;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,14 @@ public interface CategoryService extends CrudService<Category, Integer> {
|
|||
@NonNull
|
||||
Category getBySlugName(@NonNull String slugName);
|
||||
|
||||
/**
|
||||
* Get Category by name.
|
||||
*
|
||||
* @param name name
|
||||
* @return Category
|
||||
*/
|
||||
Category getByName(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Removes category and post categories.
|
||||
*
|
||||
|
|
|
@ -101,10 +101,11 @@ public interface PostService extends BasePostService<Post> {
|
|||
* Import post from markdown document.
|
||||
*
|
||||
* @param markdown markdown document.
|
||||
* @param filename filename
|
||||
* @return imported post
|
||||
*/
|
||||
@NonNull
|
||||
Post importMarkdown(@NonNull String markdown);
|
||||
PostDetailVO importMarkdown(@NonNull String markdown, String filename);
|
||||
|
||||
/**
|
||||
* Export post to markdown file by post id.
|
||||
|
|
|
@ -2,15 +2,19 @@ package run.halo.app.service;
|
|||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.lang.NonNull;
|
||||
import run.halo.app.model.dto.InternalSheetDTO;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.vo.SheetListVO;
|
||||
import run.halo.app.service.base.BasePostService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sheet service interface.
|
||||
*
|
||||
* @author johnniang
|
||||
* @author ryanwang
|
||||
* @date 19-4-24
|
||||
*/
|
||||
public interface SheetService extends BasePostService<Sheet> {
|
||||
|
@ -72,6 +76,14 @@ public interface SheetService extends BasePostService<Sheet> {
|
|||
@NonNull
|
||||
String exportMarkdown(@NonNull Sheet sheet);
|
||||
|
||||
/**
|
||||
* List internal sheets.
|
||||
*
|
||||
* @return list of internal sheets
|
||||
*/
|
||||
@NonNull
|
||||
List<InternalSheetDTO> listInternal();
|
||||
|
||||
/**
|
||||
* Converts to list dto page.
|
||||
*
|
||||
|
|
|
@ -25,6 +25,15 @@ public interface TagService extends CrudService<Tag, Integer> {
|
|||
@NonNull
|
||||
Tag getBySlugNameOfNonNull(@NonNull String slugName);
|
||||
|
||||
/**
|
||||
* Get tag by tag name.
|
||||
*
|
||||
* @param name name
|
||||
* @return Tag
|
||||
*/
|
||||
@Nullable
|
||||
Tag getByName(@NonNull String name);
|
||||
|
||||
/**
|
||||
* Converts to tag dto.
|
||||
*
|
||||
|
|
|
@ -71,6 +71,16 @@ public interface ThemeService {
|
|||
*/
|
||||
String CUSTOM_SHEET_PREFIX = "sheet_";
|
||||
|
||||
/**
|
||||
* Theme provider remote name.
|
||||
*/
|
||||
String THEME_PROVIDER_REMOTE_NAME = "theme-provider";
|
||||
|
||||
/**
|
||||
* Default remote branch name.
|
||||
*/
|
||||
String DEFAULT_REMOTE_BRANCH = "master";
|
||||
|
||||
/**
|
||||
* Get theme property by theme id.
|
||||
*
|
||||
|
@ -241,4 +251,13 @@ public interface ThemeService {
|
|||
* Reloads themes
|
||||
*/
|
||||
void reload();
|
||||
|
||||
/**
|
||||
* Updates theme by theme id.
|
||||
*
|
||||
* @param themeId theme id must not be blank
|
||||
* @return theme property
|
||||
*/
|
||||
@NonNull
|
||||
ThemeProperty update(@NonNull String themeId);
|
||||
}
|
||||
|
|
|
@ -214,4 +214,26 @@ public interface BaseCommentService<COMMENT extends BaseComment> extends CrudSer
|
|||
*/
|
||||
@NonNull
|
||||
List<COMMENT> listChildrenBy(@NonNull Integer targetId, @NonNull Long commentParentId, @NonNull CommentStatus status, @NonNull Sort sort);
|
||||
|
||||
/**
|
||||
* Filters comment ip address.
|
||||
*
|
||||
* @param comment comment dto must not be null
|
||||
*/
|
||||
<T extends BaseCommentDTO> T filterIpAddress(@NonNull T comment);
|
||||
|
||||
/**
|
||||
* Filters comment ip address.
|
||||
*
|
||||
* @param comments comment dto list
|
||||
*/
|
||||
<T extends BaseCommentDTO> List<T> filterIpAddress(@Nullable List<T> comments);
|
||||
|
||||
/**
|
||||
* Filters comment ip address.
|
||||
*
|
||||
* @param commentPage comment page
|
||||
*/
|
||||
<T extends BaseCommentDTO> Page<T> filterIpAddress(@NonNull Page<T> commentPage);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package run.halo.app.service.impl;
|
|||
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.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -58,6 +59,8 @@ public class AdminServiceImpl implements AdminService {
|
|||
|
||||
private final StringCacheStore cacheStore;
|
||||
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
private final String driverClassName;
|
||||
|
||||
public AdminServiceImpl(PostService postService,
|
||||
|
@ -70,6 +73,7 @@ public class AdminServiceImpl implements AdminService {
|
|||
UserService userService,
|
||||
LinkService linkService,
|
||||
StringCacheStore cacheStore,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
@Value("${spring.datasource.driver-class-name}") String driverClassName) {
|
||||
this.postService = postService;
|
||||
this.sheetService = sheetService;
|
||||
|
@ -81,6 +85,7 @@ public class AdminServiceImpl implements AdminService {
|
|||
this.userService = userService;
|
||||
this.linkService = linkService;
|
||||
this.cacheStore = cacheStore;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
|
@ -112,7 +117,7 @@ public class AdminServiceImpl implements AdminService {
|
|||
|
||||
if (SecurityContextHolder.getContext().isAuthenticated()) {
|
||||
// If the user has been logged in
|
||||
throw new BadRequestException("You have been logged in, do not log in repeatedly please");
|
||||
throw new BadRequestException("您已登录,请不要重复登录");
|
||||
}
|
||||
|
||||
// Generate new token
|
||||
|
@ -125,7 +130,7 @@ public class AdminServiceImpl implements AdminService {
|
|||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
if (authentication == null) {
|
||||
throw new BadRequestException("You haven't logged in yet, so you can't log out");
|
||||
throw new BadRequestException("您尚未登录,因此无法注销");
|
||||
}
|
||||
|
||||
// Get current user
|
||||
|
|
|
@ -188,7 +188,7 @@ public class AttachmentServiceImpl extends AbstractCrudService<Attachment, Integ
|
|||
long pathCount = attachmentRepository.countByPath(attachment.getPath());
|
||||
|
||||
if (pathCount > 0) {
|
||||
throw new AlreadyExistsException("The attachment with path " + attachment.getPath() + " exists already");
|
||||
throw new AlreadyExistsException("附件路径为 " + attachment.getPath() + " 已经存在");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
import run.halo.app.service.BackupService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Backup service implementation.
|
||||
|
@ -12,4 +18,20 @@ import run.halo.app.service.BackupService;
|
|||
@Service
|
||||
public class BackupServiceImpl implements BackupService {
|
||||
|
||||
private final PostService postService;
|
||||
|
||||
public BackupServiceImpl(PostService postService) {
|
||||
this.postService = postService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePostDetailDTO importMarkdowns(MultipartFile file) throws IOException {
|
||||
|
||||
// Read markdown content.
|
||||
String markdown = IoUtil.read(file.getInputStream(), "UTF-8");
|
||||
|
||||
// TODO sheet import
|
||||
|
||||
return postService.importMarkdown(markdown, file.getOriginalFilename());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -470,6 +470,53 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
|
|||
return childrenList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BaseCommentDTO> T filterIpAddress(@NonNull T comment) {
|
||||
Assert.notNull(comment, "Base comment dto must not be null");
|
||||
|
||||
// Clear ip address
|
||||
comment.setIpAddress("");
|
||||
|
||||
// Handle base comment vo
|
||||
if (comment instanceof BaseCommentVO) {
|
||||
BaseCommentVO baseCommentVO = (BaseCommentVO) comment;
|
||||
Queue<BaseCommentVO> commentQueue = new LinkedList<>();
|
||||
commentQueue.offer(baseCommentVO);
|
||||
while (!commentQueue.isEmpty()) {
|
||||
BaseCommentVO current = commentQueue.poll();
|
||||
|
||||
// Clear ip address
|
||||
current.setIpAddress("");
|
||||
|
||||
if (!CollectionUtils.isEmpty(current.getChildren())) {
|
||||
// Add children
|
||||
commentQueue.addAll(current.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BaseCommentDTO> List<T> filterIpAddress(List<T> comments) {
|
||||
if (CollectionUtils.isEmpty(comments)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
comments.forEach(this::filterIpAddress);
|
||||
|
||||
return comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BaseCommentDTO> Page<T> filterIpAddress(Page<T> commentPage) {
|
||||
Assert.notNull(commentPage, "Comment page must not be null");
|
||||
commentPage.forEach(this::filterIpAddress);
|
||||
|
||||
return commentPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get children comments recursively.
|
||||
*
|
||||
|
|
|
@ -342,7 +342,7 @@ public abstract class BasePostServiceImpl<POST extends BasePost> extends Abstrac
|
|||
}
|
||||
|
||||
if (exist) {
|
||||
throw new AlreadyExistsException("The post url " + post.getUrl() + " has been exist");
|
||||
throw new AlreadyExistsException("文章路径 " + post.getUrl() + " 已存在");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import run.halo.app.repository.CategoryRepository;
|
|||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.base.AbstractCrudService;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
@ -52,11 +53,11 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
|
|||
|
||||
if (count > 0) {
|
||||
log.error("Category has exist already: [{}]", category);
|
||||
throw new AlreadyExistsException("The category has exist already");
|
||||
throw new AlreadyExistsException("该分类已存在");
|
||||
}
|
||||
|
||||
// Check parent id
|
||||
if (category.getParentId() > 0) {
|
||||
if (!ServiceUtils.isEmptyId(category.getParentId())) {
|
||||
count = categoryRepository.countById(category.getParentId());
|
||||
|
||||
if (count == 0) {
|
||||
|
@ -154,6 +155,11 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
|
|||
return categoryRepository.getBySlugName(slugName).orElseThrow(() -> new NotFoundException("The Category does not exist").setErrorData(slugName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getByName(String name) {
|
||||
return categoryRepository.getByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCategoryAndPostCategoryBy(Integer categoryId) {
|
||||
// Remove category
|
||||
|
|
|
@ -86,7 +86,7 @@ public class LinkServiceImpl extends AbstractCrudService<Link, Integer> implemen
|
|||
boolean exist = existByName(linkParam.getName());
|
||||
|
||||
if (exist) {
|
||||
throw new AlreadyExistsException("Link name " + linkParam.getName() + " has already existed").setErrorData(linkParam.getName());
|
||||
throw new AlreadyExistsException("友情链接 " + linkParam.getName() + " 已存在").setErrorData(linkParam.getName());
|
||||
}
|
||||
|
||||
return create(linkParam.convertTo());
|
||||
|
|
|
@ -171,7 +171,7 @@ public class MenuServiceImpl extends AbstractCrudService<Menu, Integer> implemen
|
|||
}
|
||||
|
||||
if (exist) {
|
||||
throw new AlreadyExistsException("The menu name " + menu.getName() + " already exists");
|
||||
throw new AlreadyExistsException("菜单 " + menu.getName() + " 已存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
|
|||
|
||||
@Override
|
||||
public Zone getQnYunZone() {
|
||||
return getByProperty(QnYunProperties.ZONE).map(qiniuZone -> {
|
||||
return getByProperty(QnYunProperties.OSS_ZONE).map(qiniuZone -> {
|
||||
|
||||
Zone zone;
|
||||
switch (qiniuZone.toString()) {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
@ -29,6 +32,7 @@ import run.halo.app.service.*;
|
|||
import run.halo.app.utils.DateUtils;
|
||||
import run.halo.app.utils.MarkdownUtils;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
import run.halo.app.utils.SlugUtils;
|
||||
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
@ -275,7 +279,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
}
|
||||
|
||||
@Override
|
||||
public Post importMarkdown(String markdown) {
|
||||
public PostDetailVO importMarkdown(String markdown, String filename) {
|
||||
Assert.notNull(markdown, "Markdown document must not be null");
|
||||
|
||||
// Render markdown to html document.
|
||||
|
@ -284,7 +288,80 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
// Gets frontMatter
|
||||
Map<String, List<String>> frontMatter = MarkdownUtils.getFrontMatter(markdown);
|
||||
|
||||
return null;
|
||||
Post post = new Post();
|
||||
|
||||
List<String> elementValue;
|
||||
|
||||
Set<Integer> tagIds = new HashSet<>();
|
||||
|
||||
Set<Integer> categoryIds = new HashSet<>();
|
||||
if (frontMatter.size() > 0) {
|
||||
for (String key : frontMatter.keySet()) {
|
||||
elementValue = frontMatter.get(key);
|
||||
for (String ele : elementValue) {
|
||||
switch (key) {
|
||||
case "title":
|
||||
post.setTitle(ele);
|
||||
break;
|
||||
case "date":
|
||||
post.setCreateTime(DateUtil.parse(ele));
|
||||
break;
|
||||
case "updated":
|
||||
post.setUpdateTime(DateUtil.parse(ele));
|
||||
break;
|
||||
case "permalink":
|
||||
post.setUrl(ele);
|
||||
break;
|
||||
case "thumbnail":
|
||||
post.setThumbnail(ele);
|
||||
break;
|
||||
case "status":
|
||||
post.setStatus(PostStatus.valueOf(ele));
|
||||
break;
|
||||
case "comments":
|
||||
post.setDisallowComment(Boolean.parseBoolean(ele));
|
||||
break;
|
||||
case "tags":
|
||||
Tag tag = tagService.getByName(ele);
|
||||
if (null == tag) {
|
||||
tag = new Tag();
|
||||
tag.setName(ele);
|
||||
tag.setSlugName(SlugUtils.slugify(ele));
|
||||
tag = tagService.create(tag);
|
||||
}
|
||||
tagIds.add(tag.getId());
|
||||
case "categories":
|
||||
Category category = categoryService.getByName(ele);
|
||||
if (null == category) {
|
||||
category = new Category();
|
||||
category.setName(ele);
|
||||
category.setSlugName(SlugUtils.slugify(ele));
|
||||
category.setDescription(ele);
|
||||
category = categoryService.create(category);
|
||||
}
|
||||
categoryIds.add(category.getId());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null == post.getStatus()) {
|
||||
post.setStatus(PostStatus.PUBLISHED);
|
||||
}
|
||||
|
||||
if (StrUtil.isEmpty(post.getTitle())) {
|
||||
post.setTitle(filename);
|
||||
}
|
||||
|
||||
if (StrUtil.isEmpty(post.getUrl())) {
|
||||
post.setUrl(DateUtil.format(new Date(), "yyyyMMddHHmmss" + RandomUtil.randomNumbers(5)));
|
||||
}
|
||||
|
||||
post.setOriginalContent(markdown);
|
||||
|
||||
return createBy(post, tagIds, categoryIds, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -128,7 +128,7 @@ public class RecoveryServiceImpl implements RecoveryService {
|
|||
log.debug("Migrated posts: [{}]", posts);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("Failed to read multipart file " + file.getOriginalFilename(), e);
|
||||
throw new ServiceException("备份文件 " + file.getOriginalFilename() + " 读取失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.util.Assert;
|
||||
import run.halo.app.event.logger.LogEvent;
|
||||
import run.halo.app.event.post.SheetVisitEvent;
|
||||
import run.halo.app.model.dto.InternalSheetDTO;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.enums.LogType;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
|
@ -16,9 +17,11 @@ import run.halo.app.repository.SheetRepository;
|
|||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.SheetCommentService;
|
||||
import run.halo.app.service.SheetService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
import run.halo.app.utils.MarkdownUtils;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -27,6 +30,7 @@ import java.util.Set;
|
|||
* Sheet service implementation.
|
||||
*
|
||||
* @author johnniang
|
||||
* @author ryanwang
|
||||
* @date 19-4-24
|
||||
*/
|
||||
@Service
|
||||
|
@ -38,14 +42,18 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
|
||||
private final SheetCommentService sheetCommentService;
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
public SheetServiceImpl(SheetRepository sheetRepository,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
SheetCommentService sheetCommentService,
|
||||
OptionService optionService) {
|
||||
OptionService optionService,
|
||||
ThemeService themeService) {
|
||||
super(sheetRepository, optionService);
|
||||
this.sheetRepository = sheetRepository;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.sheetCommentService = sheetCommentService;
|
||||
this.themeService = themeService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,6 +144,39 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
return content.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InternalSheetDTO> listInternal() {
|
||||
|
||||
List<InternalSheetDTO> internalSheetDTOS = new ArrayList<>();
|
||||
|
||||
// links sheet
|
||||
InternalSheetDTO linkSheet = new InternalSheetDTO();
|
||||
linkSheet.setId(1);
|
||||
linkSheet.setTitle("友情链接");
|
||||
linkSheet.setUrl("/links");
|
||||
linkSheet.setStatus(themeService.templateExists("links.ftl"));
|
||||
|
||||
// photos sheet
|
||||
InternalSheetDTO photoSheet = new InternalSheetDTO();
|
||||
photoSheet.setId(2);
|
||||
photoSheet.setTitle("图库页面");
|
||||
photoSheet.setUrl("/photos");
|
||||
photoSheet.setStatus(themeService.templateExists("photos.ftl"));
|
||||
|
||||
// journals sheet
|
||||
InternalSheetDTO journalSheet = new InternalSheetDTO();
|
||||
journalSheet.setId(3);
|
||||
journalSheet.setTitle("日志页面");
|
||||
journalSheet.setUrl("/journals");
|
||||
journalSheet.setStatus(themeService.templateExists("journals.ftl"));
|
||||
|
||||
internalSheetDTOS.add(linkSheet);
|
||||
internalSheetDTOS.add(photoSheet);
|
||||
internalSheetDTOS.add(journalSheet);
|
||||
|
||||
return internalSheetDTOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sheet removeById(Integer id) {
|
||||
Sheet sheet = super.removeById(id);
|
||||
|
|
|
@ -42,7 +42,7 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
|
|||
|
||||
if (count > 0) {
|
||||
// If the tag has exist already
|
||||
throw new AlreadyExistsException("The tag has already exist").setErrorData(tag);
|
||||
throw new AlreadyExistsException("该标签已存在").setErrorData(tag);
|
||||
}
|
||||
|
||||
// Get tag name
|
||||
|
@ -60,6 +60,12 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
|
|||
return tagRepository.getBySlugName(slugName).orElseThrow(() -> new NotFoundException("The tag does not exist").setErrorData(slugName));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Tag getByName(String name) {
|
||||
return tagRepository.getByName(name).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagDTO convertTo(Tag tag) {
|
||||
Assert.notNull(tag, "Tag must not be null");
|
||||
|
|
|
@ -3,7 +3,12 @@ package run.halo.app.service.impl;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.PullResult;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.transport.RemoteConfig;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
@ -32,7 +37,9 @@ import run.halo.app.utils.FilenameUtils;
|
|||
import run.halo.app.utils.HaloUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
@ -241,7 +248,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
if (themeId.equals(getActivatedThemeId())) {
|
||||
// Prevent to delete the activated theme
|
||||
throw new BadRequestException("You can't delete the activated theme").setErrorData(themeId);
|
||||
throw new BadRequestException("不能删除正在使用的主题").setErrorData(themeId);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -251,7 +258,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
// Delete theme cache
|
||||
eventPublisher.publishEvent(new ThemeUpdatedEvent(this));
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("Failed to delete theme folder", e).setErrorData(themeId);
|
||||
throw new ServiceException("主题删除失败", e).setErrorData(themeId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +295,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
|
||||
return Collections.emptyList();
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("Failed to read options file", e);
|
||||
throw new ServiceException("读取主题配置文件失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,7 +369,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
Assert.notNull(file, "Multipart file must not be null");
|
||||
|
||||
if (!StringUtils.endsWithIgnoreCase(file.getOriginalFilename(), ".zip")) {
|
||||
throw new UnsupportedMediaTypeException("Unsupported theme media type: " + file.getContentType()).setErrorData(file.getOriginalFilename());
|
||||
throw new UnsupportedMediaTypeException("不支持的文件类型: " + file.getContentType()).setErrorData(file.getOriginalFilename());
|
||||
}
|
||||
|
||||
ZipInputStream zis = null;
|
||||
|
@ -386,7 +393,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
// Go to the base folder and add the theme into system
|
||||
return add(FileUtils.skipZipParentFolder(themeTempPath));
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("Failed to upload theme file: " + file.getOriginalFilename(), e);
|
||||
throw new ServiceException("上传主题失败: " + file.getOriginalFilename(), e);
|
||||
} finally {
|
||||
// Close zip input stream
|
||||
FileUtils.closeQuietly(zis);
|
||||
|
@ -440,15 +447,16 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
// Create temp path
|
||||
Path themeTmpPath = tmpPath.resolve(HaloUtils.randomUUIDWithoutDash());
|
||||
|
||||
if (StringUtils.endsWithIgnoreCase(uri, ".git")) {
|
||||
cloneFromGit(uri, themeTmpPath);
|
||||
} else {
|
||||
if (StringUtils.endsWithIgnoreCase(uri, ".zip")) {
|
||||
downloadZipAndUnzip(uri, themeTmpPath);
|
||||
} else {
|
||||
uri = StringUtils.appendIfMissingIgnoreCase(uri, ".git", ".git");
|
||||
cloneFromGit(uri, themeTmpPath);
|
||||
}
|
||||
|
||||
return add(themeTmpPath);
|
||||
} catch (IOException | GitAPIException e) {
|
||||
throw new ServiceException("Failed to fetch theme from remote " + uri, e);
|
||||
throw new ServiceException("主题拉取失败 " + uri, e);
|
||||
} finally {
|
||||
FileUtils.deleteFolderQuietly(tmpPath);
|
||||
}
|
||||
|
@ -459,12 +467,93 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
eventPublisher.publishEvent(new ThemeUpdatedEvent(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThemeProperty update(String themeId) {
|
||||
Assert.hasText(themeId, "Theme id must not be blank");
|
||||
|
||||
ThemeProperty updatingTheme = getThemeOfNonNullBy(themeId);
|
||||
|
||||
try {
|
||||
pullFromGit(updatingTheme);
|
||||
} catch (Exception e) {
|
||||
throw new ThemeUpdateException("主题更新失败!您与主题作者可能同时更改了同一个文件,您也可以尝试删除主题并重新拉取最新的主题", e).setErrorData(themeId);
|
||||
}
|
||||
|
||||
eventPublisher.publishEvent(new ThemeUpdatedEvent(this));
|
||||
|
||||
return getThemeOfNonNullBy(themeId);
|
||||
}
|
||||
|
||||
private void pullFromGit(@NonNull ThemeProperty themeProperty) throws IOException, GitAPIException, URISyntaxException {
|
||||
Assert.notNull(themeProperty, "Theme property must not be null");
|
||||
|
||||
// Get branch
|
||||
String branch = StringUtils.isBlank(themeProperty.getBranch()) ?
|
||||
DEFAULT_REMOTE_BRANCH : themeProperty.getBranch();
|
||||
|
||||
File themeFolder = Paths.get(themeProperty.getThemePath()).toFile();
|
||||
// Open the theme path
|
||||
Git git;
|
||||
|
||||
try {
|
||||
git = Git.open(themeFolder);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
// Repository is not initialized
|
||||
git = Git.init().setDirectory(themeFolder).call();
|
||||
}
|
||||
|
||||
// Force to set remote name
|
||||
git.remoteRemove().setRemoteName(THEME_PROVIDER_REMOTE_NAME).call();
|
||||
RemoteConfig remoteConfig = git.remoteAdd()
|
||||
.setName(THEME_PROVIDER_REMOTE_NAME)
|
||||
.setUri(new URIish(themeProperty.getRepo()))
|
||||
.call();
|
||||
|
||||
// Add all changes
|
||||
git.add()
|
||||
.addFilepattern(".")
|
||||
.call();
|
||||
// Commit the changes
|
||||
git.commit().setMessage("Commit by halo automatically").call();
|
||||
|
||||
// Check out to specified branch
|
||||
if (!StringUtils.equalsIgnoreCase(branch, git.getRepository().getBranch())) {
|
||||
boolean present = git.branchList()
|
||||
.call()
|
||||
.stream()
|
||||
.map(Ref::getName)
|
||||
.anyMatch(name -> StringUtils.equalsIgnoreCase(name, branch));
|
||||
|
||||
git.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setForced(!present)
|
||||
.setName(branch)
|
||||
.call();
|
||||
}
|
||||
|
||||
// Pull with rebasing
|
||||
PullResult pullResult = git.pull()
|
||||
.setRemote(remoteConfig.getName())
|
||||
.setRemoteBranchName(branch)
|
||||
.setRebase(true)
|
||||
.call();
|
||||
|
||||
if (!pullResult.isSuccessful()) {
|
||||
log.debug("Rebase result: [{}]", pullResult.getRebaseResult());
|
||||
log.debug("Merge result: [{}]", pullResult.getMergeResult());
|
||||
|
||||
throw new ThemeUpdateException("拉取失败!您与主题作者可能同时更改了同一个文件");
|
||||
}
|
||||
// Close git
|
||||
git.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones theme from git.
|
||||
*
|
||||
* @param gitUrl git url must not be blank
|
||||
* @param targetPath target path must not be null
|
||||
* @throws GitAPIException
|
||||
* @throws GitAPIException throws when clone error
|
||||
*/
|
||||
private void cloneFromGit(@NonNull String gitUrl, @NonNull Path targetPath) throws GitAPIException {
|
||||
Assert.hasText(gitUrl, "Git url must not be blank");
|
||||
|
@ -486,7 +575,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
*
|
||||
* @param zipUrl zip url must not be null
|
||||
* @param targetPath target path must not be null
|
||||
* @throws IOException
|
||||
* @throws IOException throws when download zip or unzip error
|
||||
*/
|
||||
private void downloadZipAndUnzip(@NonNull String zipUrl, @NonNull Path targetPath) throws IOException {
|
||||
Assert.hasText(zipUrl, "Zip url must not be blank");
|
||||
|
@ -498,7 +587,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
log.debug("Download response: [{}]", downloadResponse.getStatusCode());
|
||||
|
||||
if (downloadResponse.getStatusCode().isError() || downloadResponse.getBody() == null) {
|
||||
throw new ServiceException("Failed to download " + zipUrl + ", status: " + downloadResponse.getStatusCode());
|
||||
throw new ServiceException("下载失败 " + zipUrl + ", 状态码: " + downloadResponse.getStatusCode());
|
||||
}
|
||||
|
||||
log.debug("Downloaded [{}]", zipUrl);
|
||||
|
@ -514,7 +603,7 @@ public class ThemeServiceImpl implements ThemeService {
|
|||
* Creates temporary path.
|
||||
*
|
||||
* @return temporary path
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs or the temporary-file directory does not exist
|
||||
*/
|
||||
@NonNull
|
||||
private Path createTempPath() throws IOException {
|
||||
|
|
|
@ -105,7 +105,7 @@ public class ThemeSettingServiceImpl extends AbstractCrudService<ThemeSetting, I
|
|||
try {
|
||||
configuration.setSharedVariable("settings", listAsMapBy(themeService.getActivatedThemeId()));
|
||||
} catch (TemplateModelException e) {
|
||||
throw new ServiceException("Save theme settings error", e);
|
||||
throw new ServiceException("主题设置保存失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
|
|||
Assert.notNull(userId, "User id must not be blank");
|
||||
|
||||
if (oldPassword.equals(newPassword)) {
|
||||
throw new BadRequestException("There is nothing changed because new password is equal to old password");
|
||||
throw new BadRequestException("新密码和旧密码不能相同");
|
||||
}
|
||||
|
||||
// Get the user
|
||||
|
@ -114,7 +114,7 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
|
|||
|
||||
// Check the user old password
|
||||
if (!BCrypt.checkpw(oldPassword, user.getPassword())) {
|
||||
throw new BadRequestException("Old password is mismatch").setErrorData(oldPassword);
|
||||
throw new BadRequestException("旧密码错误").setErrorData(oldPassword);
|
||||
}
|
||||
|
||||
// Set new password
|
||||
|
@ -148,7 +148,7 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
|
|||
if (user.getExpireTime() != null && user.getExpireTime().after(now)) {
|
||||
long seconds = TimeUnit.MILLISECONDS.toSeconds(user.getExpireTime().getTime() - now.getTime());
|
||||
// If expired
|
||||
throw new ForbiddenException("You have been temporarily disabled,please try again " + HaloUtils.timeFormat(seconds) + " later").setErrorData(seconds);
|
||||
throw new ForbiddenException("账号已被停用,请 " + HaloUtils.timeFormat(seconds) + " 后重试").setErrorData(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ public class UserServiceImpl extends AbstractCrudService<User, Integer> implemen
|
|||
public User create(User user) {
|
||||
// Check user
|
||||
if (count() != 0) {
|
||||
throw new BadRequestException("This blog already exists a blogger");
|
||||
throw new BadRequestException("当前博客已有用户");
|
||||
}
|
||||
|
||||
User createdUser = super.create(user);
|
||||
|
|
|
@ -64,7 +64,7 @@ public class FileUtils {
|
|||
*
|
||||
* @param deletingPath deleting path must not be null
|
||||
*/
|
||||
public static void deleteFolder(Path deletingPath) throws IOException {
|
||||
public static void deleteFolder(@NonNull Path deletingPath) throws IOException {
|
||||
Assert.notNull(deletingPath, "Deleting path must not be null");
|
||||
|
||||
log.debug("Deleting [{}]", deletingPath);
|
||||
|
@ -249,9 +249,9 @@ public class FileUtils {
|
|||
/**
|
||||
* Deletes folder quietly.
|
||||
*
|
||||
* @param deletingPath deleting path must not be null
|
||||
* @param deletingPath deleting path
|
||||
*/
|
||||
public static void deleteFolderQuietly(@NonNull Path deletingPath) {
|
||||
public static void deleteFolderQuietly(@Nullable Path deletingPath) {
|
||||
try {
|
||||
if (deletingPath != null) {
|
||||
FileUtils.deleteFolder(deletingPath);
|
||||
|
|
|
@ -1,31 +1,19 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 常用工具
|
||||
* </pre>
|
||||
* Common utils
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date : 2017/12/22
|
||||
|
@ -165,187 +153,4 @@ public class HaloUtils {
|
|||
}
|
||||
return machineAddress.getHostAddress();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取备份文件信息
|
||||
// *
|
||||
// * @param dir dir
|
||||
// * @return List
|
||||
// */
|
||||
// public static List<BackupDto> getBackUps(String dir) {
|
||||
// final StrBuilder srcPathStr = new StrBuilder(System.getProperties().getProperty("user.home"));
|
||||
// srcPathStr.append("/halo/backup/");
|
||||
// srcPathStr.append(dir);
|
||||
// final File srcPath = new File(srcPathStr.toString());
|
||||
// final File[] files = srcPath.listFiles();
|
||||
// final List<BackupDto> backupDtos = new ArrayList<>();
|
||||
// BackupDto backupDto;
|
||||
// // 遍历文件
|
||||
// if (null != files) {
|
||||
// for (File file : files) {
|
||||
// if (file.isFile()) {
|
||||
// if (StrUtil.equals(file.getName(), ".DS_Store")) {
|
||||
// continue;
|
||||
// }
|
||||
// backupDto = new BackupDto();
|
||||
// backupDto.setFileName(file.getName());
|
||||
// backupDto.setCreateAt(getCreateTime(file.getAbsolutePath()));
|
||||
// backupDto.setFileType(FileUtil.getType(file));
|
||||
// backupDto.setFileSize(parseSize(file.length()));
|
||||
// backupDto.setBackupType(dir);
|
||||
// backupDtos.add(backupDto);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return backupDtos;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 转换文件大小
|
||||
// *
|
||||
// * @param size size
|
||||
// * @return String
|
||||
// */
|
||||
// public static String parseSize(long size) {
|
||||
// if (size < CommonParamsEnum.BYTE.getValue()) {
|
||||
// return size + "B";
|
||||
// } else {
|
||||
// size = size / 1024;
|
||||
// }
|
||||
// if (size < CommonParamsEnum.BYTE.getValue()) {
|
||||
// return size + "KB";
|
||||
// } else {
|
||||
// size = size / 1024;
|
||||
// }
|
||||
// if (size < CommonParamsEnum.BYTE.getValue()) {
|
||||
// size = size * 100;
|
||||
// return size / 100 + "." + size % 100 + "MB";
|
||||
// } else {
|
||||
// size = size * 100 / 1024;
|
||||
// return size / 100 + "." + size % 100 + "GB";
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取文件创建时间
|
||||
*
|
||||
* @param srcPath 文件绝对路径
|
||||
* @return 时间
|
||||
*/
|
||||
public static Date getCreateTime(String srcPath) {
|
||||
try {
|
||||
BasicFileAttributes basicFileAttributes = Files.readAttributes(Paths.get(srcPath), BasicFileAttributes.class);
|
||||
return new Date(basicFileAttributes.creationTime().toMillis());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to open the " + srcPath + " file", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件长和宽
|
||||
*
|
||||
* @param file file
|
||||
* @return String
|
||||
*/
|
||||
public static String getImageWh(File file) {
|
||||
try {
|
||||
final BufferedImage image = ImageIO.read(new FileInputStream(file));
|
||||
return image.getWidth() + "x" + image.getHeight();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to get read image file", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出为文件
|
||||
*
|
||||
* @param data 内容
|
||||
* @param filePath 保存路径
|
||||
* @param fileName 文件名
|
||||
*/
|
||||
public static void postToFile(String data, String filePath, String fileName) throws IOException {
|
||||
FileWriter fileWriter = null;
|
||||
BufferedWriter bufferedWriter = null;
|
||||
try {
|
||||
final File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
fileWriter = new FileWriter(file.getAbsoluteFile() + "/" + fileName, true);
|
||||
bufferedWriter = new BufferedWriter(fileWriter);
|
||||
bufferedWriter.write(data);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to export file", e);
|
||||
} finally {
|
||||
if (null != bufferedWriter) {
|
||||
bufferedWriter.close();
|
||||
}
|
||||
if (null != fileWriter) {
|
||||
fileWriter.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 百度主动推送
|
||||
*
|
||||
* @param blogUrl 博客地址
|
||||
* @param token 百度推送token
|
||||
* @param urls 文章路径
|
||||
* @return String
|
||||
*/
|
||||
public static String baiduPost(String blogUrl, String token, String urls) {
|
||||
Assert.hasText(blogUrl, "blog url must not be blank");
|
||||
Assert.hasText(token, "token must not be blank");
|
||||
Assert.hasText(urls, "urls must not be blank");
|
||||
|
||||
final StrBuilder url = new StrBuilder("http://data.zz.baidu.com/urls?site=");
|
||||
url.append(blogUrl);
|
||||
url.append("&token=");
|
||||
url.append(token);
|
||||
|
||||
final StrBuilder result = new StrBuilder();
|
||||
PrintWriter out = null;
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
// 建立URL之间的连接
|
||||
final URLConnection conn = new URL(url.toString()).openConnection();
|
||||
// 设置通用的请求属性
|
||||
conn.setRequestProperty("Host", "data.zz.baidu.com");
|
||||
conn.setRequestProperty("User-Agent", "curl/7.12.1");
|
||||
conn.setRequestProperty("Content-Length", "83");
|
||||
conn.setRequestProperty("Content-Type", "text/plain");
|
||||
|
||||
// 发送POST请求必须设置如下两行
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
// 获取conn对应的输出流
|
||||
out = new PrintWriter(conn.getOutputStream());
|
||||
out.print(urls.trim());
|
||||
// 进行输出流的缓冲
|
||||
out.flush();
|
||||
// 通过BufferedReader输入流来读取Url的响应
|
||||
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
result.append(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to push posts to baidu", e);
|
||||
} finally {
|
||||
try {
|
||||
if (null != out) {
|
||||
out.close();
|
||||
}
|
||||
if (null != in) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// Ignore this exception
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,13 @@ package run.halo.app.utils;
|
|||
|
||||
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;
|
||||
|
@ -26,30 +30,73 @@ import java.util.Set;
|
|||
*/
|
||||
public class MarkdownUtils {
|
||||
|
||||
/**
|
||||
* Front-matter extension
|
||||
*/
|
||||
private static final Set<Extension> EXTENSIONS_YAML = Collections.singleton(YamlFrontMatterExtension.create());
|
||||
|
||||
/**
|
||||
* Table extension
|
||||
* commonmark-java extension for autolinking
|
||||
*/
|
||||
private static final Set<Extension> EXTENSIONS_TABLE = Collections.singleton(TablesExtension.create());
|
||||
private static final Set<Extension> EXTENSIONS_AUTO_LINK = Collections.singleton(AutolinkExtension.create());
|
||||
|
||||
/**
|
||||
* 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 <ins> (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_YAML).extensions(EXTENSIONS_TABLE).build();
|
||||
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_YAML).extensions(EXTENSIONS_TABLE).build();
|
||||
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_YAML).extensions(EXTENSIONS_TABLE).build();
|
||||
private static final TextContentRenderer TEXT_CONTENT_RENDERER = TextContentRenderer.builder()
|
||||
.extensions(EXTENSIONS_AUTO_LINK)
|
||||
.extensions(EXTENSIONS_STRIKETHROUGH)
|
||||
.extensions(EXTENSIONS_TABLES)
|
||||
.extensions(EXTENSIONS_HEADING_ANCHOR)
|
||||
.extensions(EXTENSIONS_INS)
|
||||
.extensions(EXTENSIONS_YAML_FRONT_MATTER)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Render Markdown content
|
||||
|
@ -59,20 +106,25 @@ public class MarkdownUtils {
|
|||
* @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) {
|
||||
|
||||
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 bilibili video short url
|
||||
if (content.contains(HaloConst.BILIBILI_VIDEO_PREFIX)) {
|
||||
renderContent = content.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);
|
||||
}
|
||||
|
||||
return renderContent;
|
||||
}
|
||||
|
||||
|
@ -84,6 +136,7 @@ public class MarkdownUtils {
|
|||
*/
|
||||
@NonNull
|
||||
public static String renderText(@Nullable String markdownContent) {
|
||||
|
||||
if (StringUtils.isBlank(markdownContent)) {
|
||||
return "";
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
.category-tree[data-v-3d736771]{margin-top:1rem}
|
|
@ -1 +0,0 @@
|
|||
.category-tree[data-v-42549218]{margin-top:1rem}
|
|
@ -1 +1 @@
|
|||
.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}.upload-button[data-v-6d086f28]{position:fixed;bottom:30px;right:30px}.theme-thumb[data-v-6d086f28]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.theme-thumb img[data-v-6d086f28]{width:100%;height:100%;position:absolute;top:0;left: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}.upload-button[data-v-76b16ba4]{position:fixed;bottom:30px;right:30px}.theme-thumb[data-v-76b16ba4]{width:100%;margin:0 auto;position:relative;padding-bottom:56%;overflow:hidden}.theme-thumb img[data-v-76b16ba4]{width:100%;height:100%;position:absolute;top:0;left:0}
|
|
@ -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-0aab7d1a.701a4459.css rel=prefetch><link href=/css/chunk-14e8932a.b6783003.css rel=prefetch><link href=/css/chunk-1c8b985a.c1990d7c.css rel=prefetch><link href=/css/chunk-31829c73.f3153164.css rel=prefetch><link href=/css/chunk-4d54295e.43661ea3.css rel=prefetch><link href=/css/chunk-4fb0639b.210847fe.css rel=prefetch><link href=/css/chunk-5d83fd61.7cf84e9e.css rel=prefetch><link href=/css/chunk-75751d79.7d0c0e85.css rel=prefetch><link href=/css/chunk-898a93f6.909d3d1b.css rel=prefetch><link href=/css/chunk-92a6af22.ca1bfaac.css rel=prefetch><link href=/css/chunk-9449c032.dafef2de.css rel=prefetch><link href=/css/chunk-b6cd2e50.0090ea54.css rel=prefetch><link href=/css/chunk-c5b09f02.5e377c2d.css rel=prefetch><link href=/css/chunk-cc47e7d0.bb8e6a18.css rel=prefetch><link href=/css/fail.e9c3e2d8.css rel=prefetch><link href=/js/chunk-0aab7d1a.dba028d3.js rel=prefetch><link href=/js/chunk-142c8832.ac1f84d9.js rel=prefetch><link href=/js/chunk-14e8932a.c6563b86.js rel=prefetch><link href=/js/chunk-1c8b985a.8f4810a0.js rel=prefetch><link href=/js/chunk-2d0b64bf.14e99e26.js rel=prefetch><link href=/js/chunk-2d0d65a2.f7c7af76.js rel=prefetch><link href=/js/chunk-2d21a35c.19f1174e.js rel=prefetch><link href=/js/chunk-31829c73.36a05806.js rel=prefetch><link href=/js/chunk-407d6578.b0b0e2da.js rel=prefetch><link href=/js/chunk-4d54295e.e29bba1d.js rel=prefetch><link href=/js/chunk-4fb0639b.1668db6b.js rel=prefetch><link href=/js/chunk-5bf599cc.b6b7c7ec.js rel=prefetch><link href=/js/chunk-5d83fd61.71621386.js rel=prefetch><link href=/js/chunk-71fa6d51.79e1ddb2.js rel=prefetch><link href=/js/chunk-75751d79.f0f603bc.js rel=prefetch><link href=/js/chunk-87e2df70.8d9028cf.js rel=prefetch><link href=/js/chunk-898a93f6.c0e9bb6c.js rel=prefetch><link href=/js/chunk-92a6af22.b84ae833.js rel=prefetch><link href=/js/chunk-9449c032.9e9ce69b.js rel=prefetch><link href=/js/chunk-b6cd2e50.d2c0d717.js rel=prefetch><link href=/js/chunk-c5b09f02.3952a273.js rel=prefetch><link href=/js/chunk-cc47e7d0.30a4457f.js rel=prefetch><link href=/js/fail.b90b115d.js rel=prefetch><link href=/css/app.d74a405f.css rel=preload as=style><link href=/css/chunk-vendors.6b95225a.css rel=preload as=style><link href=/js/app.25d2f925.js rel=preload as=script><link href=/js/chunk-vendors.fb9e7626.js rel=preload as=script><link href=/css/chunk-vendors.6b95225a.css rel=stylesheet><link href=/css/app.d74a405f.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.fb9e7626.js></script><script src=/js/app.25d2f925.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-02f1697e.7cf84e9e.css rel=prefetch><link href=/css/chunk-0aab7d1a.701a4459.css rel=prefetch><link href=/css/chunk-14e8932a.b6783003.css rel=prefetch><link href=/css/chunk-1c8b985a.c1990d7c.css rel=prefetch><link href=/css/chunk-1ea08528.db89d50a.css rel=prefetch><link href=/css/chunk-31829c73.f3153164.css rel=prefetch><link href=/css/chunk-4fb0639b.743bdcba.css rel=prefetch><link href=/css/chunk-75751d79.7d0c0e85.css rel=prefetch><link href=/css/chunk-898a93f6.909d3d1b.css rel=prefetch><link href=/css/chunk-9449c032.dafef2de.css rel=prefetch><link href=/css/chunk-b6cd2e50.0090ea54.css rel=prefetch><link href=/css/chunk-c5b09f02.5e377c2d.css rel=prefetch><link href=/css/chunk-edd856c6.ca1bfaac.css rel=prefetch><link href=/css/chunk-efde06fa.aaca0f75.css rel=prefetch><link href=/css/fail.e9c3e2d8.css rel=prefetch><link href=/js/chunk-02f1697e.fbb91c62.js rel=prefetch><link href=/js/chunk-0aab7d1a.dba028d3.js rel=prefetch><link href=/js/chunk-142c8832.0d298dce.js rel=prefetch><link href=/js/chunk-14e8932a.c6563b86.js rel=prefetch><link href=/js/chunk-1c8b985a.d1e58af8.js rel=prefetch><link href=/js/chunk-1ea08528.6dd705ab.js rel=prefetch><link href=/js/chunk-2d0b64bf.14e99e26.js rel=prefetch><link href=/js/chunk-2d0d65a2.d68d48c2.js rel=prefetch><link href=/js/chunk-2d21a35c.19f1174e.js rel=prefetch><link href=/js/chunk-31829c73.620e8a22.js rel=prefetch><link href=/js/chunk-407d6578.1ef8e454.js rel=prefetch><link href=/js/chunk-4fb0639b.1be7f2f2.js rel=prefetch><link href=/js/chunk-5bf599cc.b6b7c7ec.js rel=prefetch><link href=/js/chunk-71fa6d51.79e1ddb2.js rel=prefetch><link href=/js/chunk-75751d79.1b49b36e.js rel=prefetch><link href=/js/chunk-87e2df70.8d9028cf.js rel=prefetch><link href=/js/chunk-898a93f6.c0e9bb6c.js rel=prefetch><link href=/js/chunk-9449c032.9e9ce69b.js rel=prefetch><link href=/js/chunk-b6cd2e50.cc4cab63.js rel=prefetch><link href=/js/chunk-c5b09f02.3952a273.js rel=prefetch><link href=/js/chunk-edd856c6.20633ba8.js rel=prefetch><link href=/js/chunk-efde06fa.9e1e510c.js rel=prefetch><link href=/js/fail.b90b115d.js rel=prefetch><link href=/css/app.803dd628.css rel=preload as=style><link href=/css/chunk-vendors.80056587.css rel=preload as=style><link href=/js/app.63c77087.js rel=preload as=script><link href=/js/chunk-vendors.fb9e7626.js rel=preload as=script><link href=/css/chunk-vendors.80056587.css rel=stylesheet><link href=/css/app.803dd628.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.fb9e7626.js></script><script src=/js/app.63c77087.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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-407d6578"],{aa1e9:function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"page-header-index-wide"},[e("a-row",{attrs:{gutter:12}},[e("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:10,lg:10,md:10,sm:24,xs:24}},[e("a-card",{attrs:{title:"添加标签"}},[e("a-form",{attrs:{layout:"horizontal"}},[e("a-form-item",{attrs:{label:"名称:",help:"* 页面上所显示的名称"}},[e("a-input",{model:{value:t.tagToCreate.name,callback:function(a){t.$set(t.tagToCreate,"name",a)},expression:"tagToCreate.name"}})],1),e("a-form-item",{attrs:{label:"别名",help:"* 一般为单个标签页面的标识,最好为英文"}},[e("a-input",{model:{value:t.tagToCreate.slugName,callback:function(a){t.$set(t.tagToCreate,"slugName",a)},expression:"tagToCreate.slugName"}})],1),e("a-form-item",[e("a-button",{attrs:{type:"primary"},on:{click:t.handleCreateTag}},[t._v("保存")])],1)],1)],1)],1),e("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:14,lg:14,md:14,sm:24,xs:24}},[e("a-card",{attrs:{title:"所有标签"}},t._l(t.tags,function(a){return e("a-tooltip",{key:a.id,attrs:{placement:"topLeft"}},[e("template",{slot:"title"},[e("span",[t._v(t._s(a.postCount)+" 篇文章")])]),e("a-tag",{attrs:{closable:"",color:"blue"},on:{close:function(e){return t.handleDeleteTag(a.id)}}},[t._v(t._s(a.name))])],2)}),1)],1)],1)],1)},o=[],l=e("d28db"),r={data:function(){return{tags:[],tagToCreate:{},tagToUpdate:{}}},created:function(){this.loadTags()},methods:{loadTags:function(){var t=this;l["a"].listAll(!0).then(function(a){t.tags=a.data.data})},handleCreateTag:function(){var t=this;l["a"].create(this.tagToCreate).then(function(a){t.loadTags()})},handleUpdateTag:function(t){var a=this;l["a"].update(t,this.tagToUpdate).then(function(t){a.loadTags()})},handleDeleteTag:function(t){var a=this;l["a"].delete(t).then(function(t){a.$message.success("删除成功!"),a.loadTags()})}}},s=r,c=e("17cc"),i=Object(c["a"])(s,n,o,!1,null,null,null);a["default"]=i.exports},d28db:function(t,a,e){"use strict";var n=e("9efd"),o="/api/admin/tags",l={listAll:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Object(n["a"])({url:o,params:{more:t},method:"get"})},createWithName:function(t){return Object(n["a"])({url:o,data:{name:t},method:"post"})},create:function(t){return Object(n["a"])({url:o,data:t,method:"post"})},update:function(t,a){return Object(n["a"])({url:"".concat(o,"/").concat(t),data:a,method:"put"})},delete:function(t){return Object(n["a"])({url:"".concat(o,"/").concat(t),method:"delete"})}};a["a"]=l}}]);
|
|
@ -1 +0,0 @@
|
|||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-407d6578"],{aa1e9:function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"page-header-index-wide"},[e("a-row",{attrs:{gutter:12}},[e("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:10,lg:10,md:10,sm:24,xs:24}},[e("a-card",{attrs:{title:"添加标签"}},[e("a-form",{attrs:{layout:"horizontal"}},[e("a-form-item",{attrs:{label:"名称:",help:"* 页面上所显示的名称"}},[e("a-input",{model:{value:t.tagToCreate.name,callback:function(a){t.$set(t.tagToCreate,"name",a)},expression:"tagToCreate.name"}})],1),e("a-form-item",{attrs:{label:"路径名称:",help:"* 这是文章路径上显示的名称,最好为英文"}},[e("a-input",{model:{value:t.tagToCreate.slugName,callback:function(a){t.$set(t.tagToCreate,"slugName",a)},expression:"tagToCreate.slugName"}})],1),e("a-form-item",[e("a-button",{attrs:{type:"primary"},on:{click:t.handleCreateTag}},[t._v("保存")])],1)],1)],1)],1),e("a-col",{style:{"padding-bottom":"12px"},attrs:{xl:14,lg:14,md:14,sm:24,xs:24}},[e("a-card",{attrs:{title:"所有标签"}},t._l(t.tags,function(a){return e("a-tooltip",{key:a.id,attrs:{placement:"topLeft"}},[e("template",{slot:"title"},[e("span",[t._v(t._s(a.postCount)+" 篇文章")])]),e("a-tag",{attrs:{closable:"",color:"blue"},on:{close:function(e){return t.handleDeleteTag(a.id)}}},[t._v(t._s(a.name))])],2)}),1)],1)],1)],1)},o=[],l=e("d28db"),r={data:function(){return{tags:[],tagToCreate:{},tagToUpdate:{}}},created:function(){this.loadTags()},methods:{loadTags:function(){var t=this;l["a"].listAll(!0).then(function(a){t.tags=a.data.data})},handleCreateTag:function(){var t=this;l["a"].create(this.tagToCreate).then(function(a){t.loadTags()})},handleUpdateTag:function(t){var a=this;l["a"].update(t,this.tagToUpdate).then(function(t){a.loadTags()})},handleDeleteTag:function(t){var a=this;l["a"].delete(t).then(function(t){a.$message.success("删除成功!"),a.loadTags()})}}},s=r,c=e("17cc"),i=Object(c["a"])(s,n,o,!1,null,null,null);a["default"]=i.exports},d28db:function(t,a,e){"use strict";var n=e("9efd"),o="/api/admin/tags",l={listAll:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return Object(n["a"])({url:o,params:{more:t},method:"get"})},createWithName:function(t){return Object(n["a"])({url:o,data:{name:t},method:"post"})},create:function(t){return Object(n["a"])({url:o,data:t,method:"post"})},update:function(t,a){return Object(n["a"])({url:"".concat(o,"/").concat(t),data:a,method:"put"})},delete:function(t){return Object(n["a"])({url:"".concat(o,"/").concat(t),method:"delete"})}};a["a"]=l}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -13,23 +13,25 @@ server:
|
|||
enabled: true
|
||||
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
|
||||
spring:
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
output:
|
||||
ansi:
|
||||
enabled: always
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
|
||||
# H2database 配置
|
||||
# H2 Database 配置
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:file:~/halo-dev/db/halo
|
||||
username: admin
|
||||
password: 123456
|
||||
|
||||
# MySql 配置
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
# MySQL 配置
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
|
||||
h2:
|
||||
console:
|
||||
|
@ -44,8 +46,8 @@ spring:
|
|||
open-in-view: false
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
max-file-size: 10240MB
|
||||
max-request-size: 10240MB
|
||||
|
||||
cache:
|
||||
type: none
|
||||
|
|
|
@ -13,23 +13,25 @@ server:
|
|||
enabled: true
|
||||
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
|
||||
spring:
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
output:
|
||||
ansi:
|
||||
enabled: always
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
|
||||
# H2database 配置
|
||||
# H2 Database 配置
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:file:~/halo-test/db/halo
|
||||
username: admin
|
||||
password: 123456
|
||||
|
||||
# MySql 配置
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
# MySQL 配置
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
|
||||
h2:
|
||||
console:
|
||||
|
|
|
@ -4,19 +4,19 @@ spring:
|
|||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
|
||||
# H2Database 配置,如果你需要使用 MySQL,请注释掉该配置并取消注释 MySQL 的配置。
|
||||
# H2 Database 配置,如果你需要使用 MySQL,请注释掉该配置并取消注释 MySQL 的配置。
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:file:~/.halo/db/halo
|
||||
username: admin
|
||||
password: 123456
|
||||
|
||||
# MySql 配置,如果你需要使用 H2Database,请注释掉该配置并取消注释上方 H2Database 的配置。
|
||||
# MySQL 配置,如果你需要使用 H2 Database,请注释掉该配置并取消注释上方 H2 Database 的配置。
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
|
||||
# H2Database 的控制台相关配置,如果你使用的是 MySQL ,请注释掉下方内容。
|
||||
# H2 Database 的控制台相关配置,如果你使用的是 MySQL ,请注释掉下方内容。
|
||||
h2:
|
||||
console:
|
||||
settings:
|
||||
|
|
|
@ -13,6 +13,8 @@ server:
|
|||
enabled: true
|
||||
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
|
||||
spring:
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
devtools:
|
||||
add-properties: false
|
||||
output:
|
||||
|
@ -21,17 +23,17 @@ spring:
|
|||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
|
||||
# H2database 配置
|
||||
# H2 Database 配置
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:file:~/.halo/db/halo
|
||||
username: admin
|
||||
password: 123456
|
||||
|
||||
# MySql 配置
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
# MySQL 配置
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/halodb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 123456
|
||||
|
||||
h2:
|
||||
console:
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<link rel="alternate" type="application/rss+xml" title="atom 1.0" href="/atom.xml">
|
||||
<title>Not Found</title>
|
||||
<link href="${static!}/source/css/style.min.css" type="text/css" rel="stylesheet"/>
|
||||
</head>
|
||||
<div class="page_404">
|
||||
<p>The page you are looking for is missing</p>
|
||||
</div>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<link rel="alternate" type="application/rss+xml" title="atom 1.0" href="/atom.xml">
|
||||
<title>Internal Error</title>
|
||||
<link href="${static!}/source/css/style.min.css" type="text/css" rel="stylesheet"/>
|
||||
</head>
|
||||
<div class="page_404">
|
||||
<p>The page you are looking for is error</p>
|
||||
</div>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<h1><a href="https://github.com/halo-dev" target="_blank">halo-theme-anatole</a></h1>
|
||||
|
||||
## 说明
|
||||
|
||||
该主题的原作者为 [Caicai](https://www.caicai.me),非常感谢做出这么优秀的主题。
|
||||
|
||||
原主题地址:[https://github.com/hi-caicai/farbox-theme-Anatole](https://github.com/hi-caicai/farbox-theme-Anatole)
|
||||
|
||||
## 预览截图
|
||||
|
||||

|
||||

|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 克隆或者[下载](https://github.com/halo-dev/halo-theme-anatole/releases)。
|
||||
2. 压缩为 zip 压缩包之后在后台的主题设置直接上传即可使用。
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue