mirror of https://github.com/halo-dev/halo
feat: supports setting the post path type and path suffix. (#563)
* feat: build full path for category and tag. * feat: build full path for post. * feat: build full path for sheet. * feat: build full path for post. * feat: change post url for rss sitemap pages. * feat: support set links/photos/journal page prefix. * feat: support set internal sheet's title. * refactor: build full path method. * refactor: archives post full path. * feat: support nextPageFullPath and prePageFullPath variable in pageable pages. * Update CommentEventListener.java * feat: make rss formats more standard. * feat: add some useful freemarker variable. * feat: add some useful freemarker variable. * feat: add some useful freemarker variable. * refactor: preview post and password post.pull/590/head^2
parent
8f36a5d124
commit
c224b68fbc
|
@ -11,6 +11,7 @@ import run.halo.app.model.dto.post.BasePostDetailDTO;
|
|||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.model.dto.post.BasePostSimpleDTO;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.enums.PostPermalinkType;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.params.PostContentParam;
|
||||
import run.halo.app.model.params.PostParam;
|
||||
|
@ -166,12 +167,32 @@ public class PostController {
|
|||
public String preview(@PathVariable("postId") Integer postId) throws UnsupportedEncodingException {
|
||||
Post post = postService.getById(postId);
|
||||
|
||||
post.setUrl(URLEncoder.encode(post.getUrl(), StandardCharsets.UTF_8.name()));
|
||||
|
||||
BasePostMinimalDTO postMinimalDTO = postService.convertToMinimal(post);
|
||||
|
||||
String token = IdUtil.simpleUUID();
|
||||
|
||||
// cache preview token
|
||||
cacheStore.putAny(token, token, 10, TimeUnit.MINUTES);
|
||||
|
||||
StringBuilder previewUrl = new StringBuilder();
|
||||
|
||||
if (!optionService.isEnabledAbsolutePath()) {
|
||||
previewUrl.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
previewUrl.append(postMinimalDTO.getFullPath());
|
||||
|
||||
if (optionService.getPostPermalinkType().equals(PostPermalinkType.ID)) {
|
||||
previewUrl.append("&token=")
|
||||
.append(token);
|
||||
} else {
|
||||
previewUrl.append("?token=")
|
||||
.append(token);
|
||||
}
|
||||
|
||||
// build preview post url and return
|
||||
return String.format("%s/archives/%s?token=%s", optionService.getBlogBaseUrl(), URLEncoder.encode(post.getUrl(), StandardCharsets.UTF_8.name()), token);
|
||||
return previewUrl.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.springframework.data.web.PageableDefault;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.cache.StringCacheStore;
|
||||
import run.halo.app.model.dto.InternalSheetDTO;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.params.SheetParam;
|
||||
|
@ -119,12 +120,26 @@ public class SheetController {
|
|||
public String preview(@PathVariable("sheetId") Integer sheetId) throws UnsupportedEncodingException {
|
||||
Sheet sheet = sheetService.getById(sheetId);
|
||||
|
||||
sheet.setUrl(URLEncoder.encode(sheet.getUrl(), StandardCharsets.UTF_8.name()));
|
||||
|
||||
BasePostMinimalDTO sheetMinimalDTO = sheetService.convertToMinimal(sheet);
|
||||
|
||||
String token = IdUtil.simpleUUID();
|
||||
|
||||
// cache preview token
|
||||
cacheStore.putAny(token, token, 10, TimeUnit.MINUTES);
|
||||
|
||||
StringBuilder previewUrl = new StringBuilder();
|
||||
|
||||
if (!optionService.isEnabledAbsolutePath()) {
|
||||
previewUrl.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
previewUrl.append(sheetMinimalDTO.getFullPath())
|
||||
.append("?token=")
|
||||
.append(token);
|
||||
|
||||
// build preview post url and return
|
||||
return String.format("%s/s/%s?token=%s", optionService.getBlogBaseUrl(), URLEncoder.encode(sheet.getUrl(), StandardCharsets.UTF_8.name()), token);
|
||||
return previewUrl.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.cache.StringCacheStore;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostService;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Blog archive page controller
|
||||
*
|
||||
* @author ryanwang
|
||||
* @author guqing
|
||||
* @author evanwang
|
||||
* @date 2019-03-17
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping(value = "/archives")
|
||||
public class ContentArchiveController {
|
||||
|
||||
private final PostService postService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final StringCacheStore cacheStore;
|
||||
|
||||
|
||||
public ContentArchiveController(PostService postService,
|
||||
OptionService optionService,
|
||||
StringCacheStore cacheStore) {
|
||||
this.postService = postService;
|
||||
this.optionService = optionService;
|
||||
this.cacheStore = cacheStore;
|
||||
}
|
||||
|
||||
@GetMapping(value = "{url:.*}/password")
|
||||
public String password(@PathVariable("url") String url,
|
||||
Model model) {
|
||||
model.addAttribute("url", url);
|
||||
return "common/template/post_password";
|
||||
}
|
||||
|
||||
@PostMapping(value = "{url:.*}/password")
|
||||
@CacheLock(traceRequest = true, expired = 2)
|
||||
public String password(@PathVariable("url") String url,
|
||||
@RequestParam(value = "password") String password) {
|
||||
Post post = postService.getBy(PostStatus.INTIMATE, url);
|
||||
|
||||
if (password.equals(post.getPassword())) {
|
||||
String token = IdUtil.simpleUUID();
|
||||
cacheStore.putAny(token, token, 10, TimeUnit.SECONDS);
|
||||
|
||||
String redirect = String.format("%s/archives/%s?token=%s", optionService.getBlogBaseUrl(), post.getUrl(), token);
|
||||
return "redirect:" + redirect;
|
||||
} else {
|
||||
String redirect = String.format("%s/archives/%s/password", optionService.getBlogBaseUrl(), post.getUrl());
|
||||
return "redirect:" + redirect;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +1,28 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import run.halo.app.controller.content.model.CategoryModel;
|
||||
import run.halo.app.controller.content.model.PostModel;
|
||||
import run.halo.app.controller.content.model.SheetModel;
|
||||
import run.halo.app.controller.content.model.TagModel;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import run.halo.app.cache.StringCacheStore;
|
||||
import run.halo.app.cache.lock.CacheLock;
|
||||
import run.halo.app.controller.content.model.*;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.enums.PostPermalinkType;
|
||||
import run.halo.app.model.properties.PermalinkProperties;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.SheetService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
|
@ -37,41 +41,60 @@ public class ContentContentController {
|
|||
|
||||
private final TagModel tagModel;
|
||||
|
||||
private final JournalModel journalModel;
|
||||
|
||||
private final PhotoModel photoModel;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final PostService postService;
|
||||
|
||||
private final SheetService sheetService;
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
private final StringCacheStore cacheStore;
|
||||
|
||||
public ContentContentController(PostModel postModel,
|
||||
SheetModel sheetModel,
|
||||
CategoryModel categoryModel,
|
||||
TagModel tagModel,
|
||||
JournalModel journalModel,
|
||||
PhotoModel photoModel,
|
||||
OptionService optionService,
|
||||
PostService postService,
|
||||
SheetService sheetService) {
|
||||
SheetService sheetService,
|
||||
ThemeService themeService,
|
||||
StringCacheStore cacheStore) {
|
||||
this.postModel = postModel;
|
||||
this.sheetModel = sheetModel;
|
||||
this.categoryModel = categoryModel;
|
||||
this.tagModel = tagModel;
|
||||
this.journalModel = journalModel;
|
||||
this.photoModel = photoModel;
|
||||
this.optionService = optionService;
|
||||
this.postService = postService;
|
||||
this.sheetService = sheetService;
|
||||
this.themeService = themeService;
|
||||
this.cacheStore = cacheStore;
|
||||
}
|
||||
|
||||
@GetMapping("{prefix}")
|
||||
public String content(@PathVariable("prefix") String prefix,
|
||||
Model model) {
|
||||
String archivesPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.ARCHIVES_PREFIX, String.class, PermalinkProperties.ARCHIVES_PREFIX.defaultValue());
|
||||
String categoriesPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.CATEGORIES_PREFIX, String.class, PermalinkProperties.CATEGORIES_PREFIX.defaultValue());
|
||||
String tagsPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.TAGS_PREFIX, String.class, PermalinkProperties.TAGS_PREFIX.defaultValue());
|
||||
|
||||
if (archivesPrefix.equals(prefix)) {
|
||||
if (optionService.getArchivesPrefix().equals(prefix)) {
|
||||
return postModel.list(1, model, "is_archives", "archives");
|
||||
} else if (categoriesPrefix.equals(prefix)) {
|
||||
} else if (optionService.getCategoriesPrefix().equals(prefix)) {
|
||||
return categoryModel.list(model);
|
||||
} else if (tagsPrefix.equals(prefix)) {
|
||||
} else if (optionService.getTagsPrefix().equals(prefix)) {
|
||||
return tagModel.list(model);
|
||||
} else if (optionService.getJournalsPrefix().equals(prefix)) {
|
||||
return journalModel.list(1, model);
|
||||
} else if (optionService.getPhotosPrefix().equals(prefix)) {
|
||||
return photoModel.list(1, model);
|
||||
} else if (optionService.getLinksPrefix().equals(prefix)) {
|
||||
model.addAttribute("is_links", true);
|
||||
return themeService.render("links");
|
||||
} else {
|
||||
throw new NotFoundException("Not Found");
|
||||
}
|
||||
|
@ -81,9 +104,12 @@ public class ContentContentController {
|
|||
public String content(@PathVariable("prefix") String prefix,
|
||||
@PathVariable(value = "page") Integer page,
|
||||
Model model) {
|
||||
String archivesPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.ARCHIVES_PREFIX, String.class, PermalinkProperties.ARCHIVES_PREFIX.defaultValue());
|
||||
if (archivesPrefix.equals(prefix)) {
|
||||
if (optionService.getArchivesPrefix().equals(prefix)) {
|
||||
return postModel.list(page, model, "is_archives", "archives");
|
||||
} else if (optionService.getJournalsPrefix().equals(prefix)) {
|
||||
return journalModel.list(page, model);
|
||||
} else if (optionService.getPhotosPrefix().equals(prefix)) {
|
||||
return photoModel.list(page, model);
|
||||
} else {
|
||||
throw new NotFoundException("Not Found");
|
||||
}
|
||||
|
@ -95,20 +121,16 @@ public class ContentContentController {
|
|||
@RequestParam(value = "token", required = false) String token,
|
||||
Model model) {
|
||||
PostPermalinkType postPermalinkType = optionService.getPostPermalinkType();
|
||||
String archivesPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.ARCHIVES_PREFIX, String.class, PermalinkProperties.ARCHIVES_PREFIX.defaultValue());
|
||||
String sheetPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.SHEET_PREFIX, String.class, PermalinkProperties.SHEET_PREFIX.defaultValue());
|
||||
String categoriesPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.CATEGORIES_PREFIX, String.class, PermalinkProperties.CATEGORIES_PREFIX.defaultValue());
|
||||
String tagsPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.TAGS_PREFIX, String.class, PermalinkProperties.TAGS_PREFIX.defaultValue());
|
||||
|
||||
if (postPermalinkType.equals(PostPermalinkType.DEFAULT) && archivesPrefix.equals(prefix)) {
|
||||
if (postPermalinkType.equals(PostPermalinkType.DEFAULT) && optionService.getArchivesPrefix().equals(prefix)) {
|
||||
Post post = postService.getByUrl(url);
|
||||
return postModel.content(post, token, model);
|
||||
} else if (sheetPrefix.equals(prefix)) {
|
||||
} else if (optionService.getSheetPrefix().equals(prefix)) {
|
||||
Sheet sheet = sheetService.getByUrl(url);
|
||||
return sheetModel.content(sheet, token, model);
|
||||
} else if (categoriesPrefix.equals(prefix)) {
|
||||
} else if (optionService.getCategoriesPrefix().equals(prefix)) {
|
||||
return categoryModel.listPost(model, url, 1);
|
||||
} else if (tagsPrefix.equals(prefix)) {
|
||||
} else if (optionService.getTagsPrefix().equals(prefix)) {
|
||||
return tagModel.listPost(model, url, 1);
|
||||
} else {
|
||||
throw new NotFoundException("Not Found");
|
||||
|
@ -120,12 +142,9 @@ public class ContentContentController {
|
|||
@PathVariable("url") String url,
|
||||
@PathVariable("page") Integer page,
|
||||
Model model) {
|
||||
String categoriesPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.CATEGORIES_PREFIX, String.class, PermalinkProperties.CATEGORIES_PREFIX.defaultValue());
|
||||
String tagsPrefix = optionService.getByPropertyOrDefault(PermalinkProperties.TAGS_PREFIX, String.class, PermalinkProperties.TAGS_PREFIX.defaultValue());
|
||||
|
||||
if (categoriesPrefix.equals(prefix)) {
|
||||
if (optionService.getCategoriesPrefix().equals(prefix)) {
|
||||
return categoryModel.listPost(model, url, page);
|
||||
} else if (tagsPrefix.equals(prefix)) {
|
||||
} else if (optionService.getTagsPrefix().equals(prefix)) {
|
||||
return tagModel.listPost(model, url, page);
|
||||
} else {
|
||||
throw new NotFoundException("Not Found");
|
||||
|
@ -162,4 +181,38 @@ public class ContentContentController {
|
|||
throw new NotFoundException("Not Found");
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "archives/{url:.*}/password")
|
||||
@CacheLock(traceRequest = true, expired = 2)
|
||||
public String password(@PathVariable("url") String url,
|
||||
@RequestParam(value = "password") String password) throws UnsupportedEncodingException {
|
||||
Post post = postService.getBy(PostStatus.INTIMATE, url);
|
||||
|
||||
post.setUrl(URLEncoder.encode(post.getUrl(), StandardCharsets.UTF_8.name()));
|
||||
|
||||
BasePostMinimalDTO postMinimalDTO = postService.convertToMinimal(post);
|
||||
|
||||
StringBuilder redirectUrl = new StringBuilder();
|
||||
|
||||
if (!optionService.isEnabledAbsolutePath()) {
|
||||
redirectUrl.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
redirectUrl.append(postMinimalDTO.getFullPath());
|
||||
|
||||
if (password.equals(post.getPassword())) {
|
||||
String token = IdUtil.simpleUUID();
|
||||
cacheStore.putAny(token, token, 10, TimeUnit.SECONDS);
|
||||
|
||||
if (optionService.getPostPermalinkType().equals(PostPermalinkType.ID)) {
|
||||
redirectUrl.append("&token=")
|
||||
.append(token);
|
||||
} else {
|
||||
redirectUrl.append("?token=")
|
||||
.append(token);
|
||||
}
|
||||
}
|
||||
|
||||
return "redirect:" + redirectUrl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import cn.hutool.core.util.PageUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import run.halo.app.model.entity.Journal;
|
||||
import run.halo.app.model.enums.JournalType;
|
||||
import run.halo.app.service.JournalService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Blog journal page controller
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date 2019-05-04
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping(value = "/journals")
|
||||
public class ContentJournalController {
|
||||
|
||||
private final JournalService journalService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
public ContentJournalController(JournalService journalService,
|
||||
OptionService optionService,
|
||||
ThemeService themeService) {
|
||||
this.journalService = journalService;
|
||||
this.optionService = optionService;
|
||||
this.themeService = themeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render journal page.
|
||||
*
|
||||
* @param model model
|
||||
* @return template path: themes/{theme}/journals.ftl
|
||||
*/
|
||||
@GetMapping
|
||||
public String journals(Model model) {
|
||||
return this.journals(model, 1, Sort.by(DESC, "createTime"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render journal page.
|
||||
*
|
||||
* @param model model
|
||||
* @param page current page number
|
||||
* @return template path: themes/{theme}/journals.ftl
|
||||
*/
|
||||
@GetMapping(value = "page/{page}")
|
||||
public String journals(Model model,
|
||||
@PathVariable(value = "page") Integer page,
|
||||
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
|
||||
log.debug("Requested journal page, sort info: [{}]", sort);
|
||||
|
||||
int pageSize = optionService.getPostPageSize();
|
||||
|
||||
Pageable pageable = PageRequest.of(page >= 1 ? page - 1 : page, pageSize, sort);
|
||||
|
||||
Page<Journal> journals = journalService.pageBy(JournalType.PUBLIC, pageable);
|
||||
|
||||
int[] rainbow = PageUtil.rainbow(page, journals.getTotalPages(), 3);
|
||||
|
||||
model.addAttribute("is_journals", true);
|
||||
model.addAttribute("journals", journalService.convertToCmtCountDto(journals));
|
||||
model.addAttribute("rainbow", rainbow);
|
||||
return themeService.render("journals");
|
||||
}
|
||||
}
|
|
@ -73,11 +73,49 @@ public class ContentSearchController {
|
|||
|
||||
final Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
||||
// TODO remove this variable
|
||||
final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);
|
||||
|
||||
// Next page and previous page url.
|
||||
StringBuilder nextPageFullPath = new StringBuilder();
|
||||
StringBuilder prePageFullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
nextPageFullPath.append(optionService.getBlogBaseUrl())
|
||||
.append("/");
|
||||
prePageFullPath.append(optionService.getBlogBaseUrl())
|
||||
.append("/");
|
||||
} else {
|
||||
nextPageFullPath.append("/");
|
||||
prePageFullPath.append("/");
|
||||
}
|
||||
|
||||
nextPageFullPath.append("search");
|
||||
prePageFullPath.append("search");
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(posts.getNumber() + 2)
|
||||
.append(optionService.getPathSuffix())
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
|
||||
if (posts.getNumber() == 1) {
|
||||
prePageFullPath.append("?keyword=")
|
||||
.append(keyword);
|
||||
} else {
|
||||
prePageFullPath.append("/page/")
|
||||
.append(posts.getNumber())
|
||||
.append(optionService.getPathSuffix())
|
||||
.append("?keyword=")
|
||||
.append(keyword);
|
||||
}
|
||||
|
||||
model.addAttribute("is_search", true);
|
||||
model.addAttribute("keyword", keyword);
|
||||
model.addAttribute("posts", posts);
|
||||
model.addAttribute("rainbow", rainbow);
|
||||
model.addAttribute("nextPageFullPath", nextPageFullPath.toString());
|
||||
model.addAttribute("prePageFullPath", prePageFullPath.toString());
|
||||
return themeService.render("search");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
package run.halo.app.controller.content;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import run.halo.app.model.dto.PhotoDTO;
|
||||
import run.halo.app.service.PhotoService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* Content sheet controller.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @author evanwang
|
||||
* @date 2019-03-21
|
||||
*/
|
||||
@Controller
|
||||
public class ContentSheetController {
|
||||
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
private final PhotoService photoService;
|
||||
|
||||
public ContentSheetController(ThemeService themeService,
|
||||
PhotoService photoService) {
|
||||
this.themeService = themeService;
|
||||
this.photoService = photoService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render photo page
|
||||
*
|
||||
* @return template path: themes/{theme}/photos.ftl
|
||||
*/
|
||||
@GetMapping(value = "/photos")
|
||||
public String photos(Model model,
|
||||
@RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
|
||||
return photos(model, 1, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render photo page
|
||||
*
|
||||
* @param model model
|
||||
* @param page current page
|
||||
* @param size current page size
|
||||
* @return template path: themes/{theme}/photos.ftl
|
||||
*/
|
||||
@GetMapping(value = "/photos/page/{page}")
|
||||
public String photos(Model model,
|
||||
@PathVariable(value = "page") Integer page,
|
||||
@RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
|
||||
Pageable pageable = PageRequest.of(page >= 1 ? page - 1 : page, size, Sort.by(DESC, "createTime"));
|
||||
Page<PhotoDTO> photos = photoService.pageBy(pageable);
|
||||
model.addAttribute("photos", photos);
|
||||
return themeService.render("photos");
|
||||
}
|
||||
|
||||
/**
|
||||
* Render links page
|
||||
*
|
||||
* @return template path: themes/{theme}/links.ftl
|
||||
*/
|
||||
@GetMapping(value = "/links")
|
||||
public String links() {
|
||||
return themeService.render("links");
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import org.springframework.data.domain.Pageable;
|
|||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.ui.Model;
|
||||
import run.halo.app.model.dto.CategoryDTO;
|
||||
import run.halo.app.model.entity.Category;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
|
@ -50,16 +51,37 @@ public class CategoryModel {
|
|||
public String listPost(Model model, String slugName, Integer page) {
|
||||
// Get category by slug name
|
||||
final Category category = categoryService.getBySlugNameOfNonNull(slugName);
|
||||
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
||||
|
||||
final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), Sort.by(DESC, "createTime"));
|
||||
Page<Post> postPage = postCategoryService.pagePostBy(category.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
||||
// TODO remove this variable
|
||||
final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);
|
||||
|
||||
// Next page and previous page url.
|
||||
StringBuilder nextPageFullPath = new StringBuilder(categoryDTO.getFullPath());
|
||||
StringBuilder prePageFullPath = new StringBuilder(categoryDTO.getFullPath());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(posts.getNumber() + 2)
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
if (posts.getNumber() == 1) {
|
||||
prePageFullPath.append("/");
|
||||
} else {
|
||||
prePageFullPath.append("/page/")
|
||||
.append(posts.getNumber())
|
||||
.append(optionService.getPathSuffix());
|
||||
}
|
||||
|
||||
model.addAttribute("is_category", true);
|
||||
model.addAttribute("posts", posts);
|
||||
model.addAttribute("rainbow", rainbow);
|
||||
model.addAttribute("category", category);
|
||||
model.addAttribute("category", categoryDTO);
|
||||
model.addAttribute("nextPageFullPath", nextPageFullPath.toString());
|
||||
model.addAttribute("prePageFullPath", prePageFullPath.toString());
|
||||
return themeService.render("category");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import cn.hutool.core.util.PageUtil;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.ui.Model;
|
||||
import run.halo.app.model.entity.Journal;
|
||||
import run.halo.app.model.enums.JournalType;
|
||||
import run.halo.app.model.properties.SheetProperties;
|
||||
import run.halo.app.service.JournalService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-02-11
|
||||
*/
|
||||
@Component
|
||||
public class JournalModel {
|
||||
|
||||
private final JournalService journalService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
public JournalModel(JournalService journalService,
|
||||
OptionService optionService,
|
||||
ThemeService themeService) {
|
||||
this.journalService = journalService;
|
||||
this.optionService = optionService;
|
||||
this.themeService = themeService;
|
||||
}
|
||||
|
||||
public String list(Integer page, Model model) {
|
||||
|
||||
int pageSize = optionService.getByPropertyOrDefault(SheetProperties.JOURNALS_PAGE_SIZE, Integer.class, Integer.parseInt(SheetProperties.JOURNALS_PAGE_SIZE.defaultValue()));
|
||||
|
||||
Pageable pageable = PageRequest.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(DESC, "createTime"));
|
||||
|
||||
Page<Journal> journals = journalService.pageBy(JournalType.PUBLIC, pageable);
|
||||
|
||||
// TODO remove this variable
|
||||
int[] rainbow = PageUtil.rainbow(page, journals.getTotalPages(), 3);
|
||||
|
||||
// Next page and previous page url.
|
||||
StringBuilder nextPageFullPath = new StringBuilder();
|
||||
StringBuilder prePageFullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
nextPageFullPath.append(optionService.getBlogBaseUrl())
|
||||
.append("/");
|
||||
prePageFullPath.append(optionService.getBlogBaseUrl())
|
||||
.append("/");
|
||||
} else {
|
||||
nextPageFullPath.append("/");
|
||||
prePageFullPath.append("/");
|
||||
}
|
||||
|
||||
nextPageFullPath.append(optionService.getJournalsPrefix());
|
||||
prePageFullPath.append(optionService.getJournalsPrefix());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(journals.getNumber() + 2)
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
if (journals.getNumber() == 1) {
|
||||
prePageFullPath.append("/");
|
||||
} else {
|
||||
prePageFullPath.append("/page/")
|
||||
.append(journals.getNumber())
|
||||
.append(optionService.getPathSuffix());
|
||||
}
|
||||
|
||||
model.addAttribute("is_journals", true);
|
||||
model.addAttribute("journals", journalService.convertToCmtCountDto(journals));
|
||||
model.addAttribute("rainbow", rainbow);
|
||||
model.addAttribute("nextPageFullPath", nextPageFullPath.toString());
|
||||
model.addAttribute("prePageFullPath", prePageFullPath.toString());
|
||||
return themeService.render("journals");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package run.halo.app.controller.content.model;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.ui.Model;
|
||||
import run.halo.app.model.dto.PhotoDTO;
|
||||
import run.halo.app.model.properties.SheetProperties;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PhotoService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-02-11
|
||||
*/
|
||||
@Component
|
||||
public class PhotoModel {
|
||||
|
||||
private final PhotoService photoService;
|
||||
|
||||
private final ThemeService themeService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public PhotoModel(PhotoService photoService,
|
||||
ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
this.photoService = photoService;
|
||||
this.themeService = themeService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
public String list(Integer page, Model model) {
|
||||
|
||||
int pageSize = optionService.getByPropertyOrDefault(SheetProperties.PHOTOS_PAGE_SIZE, Integer.class, Integer.parseInt(SheetProperties.PHOTOS_PAGE_SIZE.defaultValue()));
|
||||
|
||||
Pageable pageable = PageRequest.of(page >= 1 ? page - 1 : page, pageSize, Sort.by(DESC, "createTime"));
|
||||
|
||||
Page<PhotoDTO> photos = photoService.pageBy(pageable);
|
||||
|
||||
// Next page and previous page url.
|
||||
StringBuilder nextPageFullPath = new StringBuilder();
|
||||
StringBuilder prePageFullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
nextPageFullPath.append(optionService.getBlogBaseUrl())
|
||||
.append("/");
|
||||
prePageFullPath.append(optionService.getBlogBaseUrl())
|
||||
.append("/");
|
||||
} else {
|
||||
nextPageFullPath.append("/");
|
||||
prePageFullPath.append("/");
|
||||
}
|
||||
|
||||
nextPageFullPath.append(optionService.getPhotosPrefix());
|
||||
prePageFullPath.append(optionService.getPhotosPrefix());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(photos.getNumber() + 2)
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
if (photos.getNumber() == 1) {
|
||||
prePageFullPath.append("/");
|
||||
} else {
|
||||
prePageFullPath.append("/page/")
|
||||
.append(photos.getNumber())
|
||||
.append(optionService.getPathSuffix());
|
||||
}
|
||||
|
||||
model.addAttribute("is_photos", true);
|
||||
model.addAttribute("photos", photos);
|
||||
model.addAttribute("nextPageFullPath", nextPageFullPath.toString());
|
||||
model.addAttribute("prePageFullPath", prePageFullPath.toString());
|
||||
return themeService.render("photos");
|
||||
}
|
||||
}
|
|
@ -72,26 +72,26 @@ public class PostModel {
|
|||
public String content(Post post, String token, Model model) {
|
||||
|
||||
if (post.getStatus().equals(PostStatus.INTIMATE) && StringUtils.isEmpty(token)) {
|
||||
String redirect = String
|
||||
.format("%s/archives/%s/password", optionService.getBlogBaseUrl(),
|
||||
post.getUrl());
|
||||
return "redirect:" + redirect;
|
||||
model.addAttribute("url", post.getUrl());
|
||||
return "common/template/post_password";
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(token)) {
|
||||
if (StringUtils.isEmpty(token)) {
|
||||
post = postService.getBy(PostStatus.PUBLISHED, post.getUrl());
|
||||
} else {
|
||||
// verify token
|
||||
String cachedToken = cacheStore.getAny(token, String.class)
|
||||
.orElseThrow(() -> new ForbiddenException("您没有该文章的访问权限"));
|
||||
String cachedToken = cacheStore.getAny(token, String.class).orElseThrow(() -> new ForbiddenException("您没有该文章的访问权限"));
|
||||
if (!cachedToken.equals(token)) {
|
||||
throw new ForbiddenException("您没有该文章的访问权限");
|
||||
}
|
||||
post.setFormatContent(MarkdownUtils.renderHtml(post.getOriginalContent()));
|
||||
}
|
||||
|
||||
postService.publishVisitEvent(post.getId());
|
||||
|
||||
AdjacentPostVO adjacentPostVO = postService.getAdjacentPosts(post);
|
||||
adjacentPostVO.getOptionalPrePost().ifPresent(prePost -> model.addAttribute("prePost", prePost));
|
||||
adjacentPostVO.getOptionalNextPost().ifPresent(nextPost -> model.addAttribute("nextPost", nextPost));
|
||||
adjacentPostVO.getOptionalPrePost().ifPresent(prePost -> model.addAttribute("prePost", postService.convertToDetailVo(prePost)));
|
||||
adjacentPostVO.getOptionalNextPost().ifPresent(nextPost -> model.addAttribute("nextPost", postService.convertToDetailVo(nextPost)));
|
||||
|
||||
List<Category> categories = postCategoryService.listCategoriesBy(post.getId());
|
||||
List<Tag> tags = postTagService.listTagsBy(post.getId());
|
||||
|
@ -122,12 +122,36 @@ public class PostModel {
|
|||
Page<Post> postPage = postService.pageBy(PostStatus.PUBLISHED, pageable);
|
||||
Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
||||
// TODO remove this variable
|
||||
int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);
|
||||
|
||||
// Next page and previous page url.
|
||||
StringBuilder nextPageFullPath = new StringBuilder();
|
||||
StringBuilder prePageFullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
nextPageFullPath.append(optionService.getBlogBaseUrl());
|
||||
prePageFullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(posts.getNumber() + 2)
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
if (posts.getNumber() == 1) {
|
||||
prePageFullPath.append("/");
|
||||
} else {
|
||||
prePageFullPath.append("/page/")
|
||||
.append(posts.getNumber())
|
||||
.append(optionService.getPathSuffix());
|
||||
}
|
||||
|
||||
model.addAttribute(decide, true);
|
||||
model.addAttribute("posts", posts);
|
||||
model.addAttribute("rainbow", rainbow);
|
||||
model.addAttribute("pageRainbow", rainbow);
|
||||
model.addAttribute("nextPageFullPath", nextPageFullPath.toString());
|
||||
model.addAttribute("prePageFullPath", prePageFullPath.toString());
|
||||
return themeService.render(template);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.ui.Model;
|
|||
import run.halo.app.cache.StringCacheStore;
|
||||
import run.halo.app.exception.ForbiddenException;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.model.vo.SheetDetailVO;
|
||||
import run.halo.app.service.SheetService;
|
||||
|
@ -35,17 +36,19 @@ public class SheetModel {
|
|||
}
|
||||
|
||||
public String content(Sheet sheet, String token, Model model) {
|
||||
if (!StringUtils.isEmpty(token)) {
|
||||
// render markdown to html when preview sheet
|
||||
sheet.setFormatContent(MarkdownUtils.renderHtml(sheet.getOriginalContent()));
|
||||
|
||||
if (StringUtils.isEmpty(token)) {
|
||||
sheet = sheetService.getBy(PostStatus.PUBLISHED, sheet.getUrl());
|
||||
} else {
|
||||
// verify token
|
||||
String cachedToken = cacheStore.getAny(token, String.class).orElseThrow(() -> new ForbiddenException("您没有该页面的访问权限"));
|
||||
|
||||
if (!cachedToken.equals(token)) {
|
||||
throw new ForbiddenException("您没有该页面的访问权限");
|
||||
}
|
||||
// render markdown to html when preview sheet
|
||||
sheet.setFormatContent(MarkdownUtils.renderHtml(sheet.getOriginalContent()));
|
||||
}
|
||||
|
||||
sheetService.publishVisitEvent(sheet.getId());
|
||||
|
||||
SheetDetailVO sheetDetailVO = sheetService.convertToDetailVo(sheet);
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.data.domain.Pageable;
|
|||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.ui.Model;
|
||||
import run.halo.app.model.dto.TagDTO;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
|
@ -50,16 +51,37 @@ public class TagModel {
|
|||
public String listPost(Model model, String slugName, Integer page) {
|
||||
// Get tag by slug name
|
||||
final Tag tag = tagService.getBySlugNameOfNonNull(slugName);
|
||||
TagDTO tagDTO = tagService.convertTo(tag);
|
||||
|
||||
final Pageable pageable = PageRequest.of(page - 1, optionService.getPostPageSize(), Sort.by(DESC, "createTime"));
|
||||
Page<Post> postPage = postTagService.pagePostsBy(tag.getId(), PostStatus.PUBLISHED, pageable);
|
||||
Page<PostListVO> posts = postService.convertToListVo(postPage);
|
||||
|
||||
// TODO remove this variable
|
||||
final int[] rainbow = PageUtil.rainbow(page, posts.getTotalPages(), 3);
|
||||
|
||||
// Next page and previous page url.
|
||||
StringBuilder nextPageFullPath = new StringBuilder(tagDTO.getFullPath());
|
||||
StringBuilder prePageFullPath = new StringBuilder(tagDTO.getFullPath());
|
||||
|
||||
nextPageFullPath.append("/page/")
|
||||
.append(posts.getNumber() + 2)
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
if (posts.getNumber() == 1) {
|
||||
prePageFullPath.append("/");
|
||||
} else {
|
||||
prePageFullPath.append("/page/")
|
||||
.append(posts.getNumber())
|
||||
.append(optionService.getPathSuffix());
|
||||
}
|
||||
|
||||
model.addAttribute("is_tag", true);
|
||||
model.addAttribute("posts", posts);
|
||||
model.addAttribute("rainbow", rainbow);
|
||||
model.addAttribute("tag", tag);
|
||||
model.addAttribute("tag", tagDTO);
|
||||
model.addAttribute("nextPageFullPath", nextPageFullPath.toString());
|
||||
model.addAttribute("prePageFullPath", prePageFullPath.toString());
|
||||
return themeService.render("tag");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ import freemarker.core.Environment;
|
|||
import freemarker.template.*;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.Category;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
@ -44,7 +46,8 @@ public class CategoryTagDirective implements TemplateDirectiveModel {
|
|||
break;
|
||||
case "listByPostId":
|
||||
Integer postId = Integer.parseInt(params.get("postId").toString());
|
||||
env.setVariable("categories", builder.build().wrap(postCategoryService.listCategoriesBy(postId)));
|
||||
List<Category> categories = postCategoryService.listCategoriesBy(postId);
|
||||
env.setVariable("categories", builder.build().wrap(categoryService.convertTo(categories)));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(categoryService.count()));
|
||||
|
|
|
@ -3,6 +3,7 @@ package run.halo.app.core.freemarker.tag;
|
|||
import freemarker.core.Environment;
|
||||
import freemarker.template.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
|
@ -10,6 +11,7 @@ import run.halo.app.service.PostService;
|
|||
import run.halo.app.service.PostTagService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -45,7 +47,8 @@ public class PostTagDirective implements TemplateDirectiveModel {
|
|||
switch (method) {
|
||||
case "latest":
|
||||
int top = Integer.parseInt(params.get("top").toString());
|
||||
env.setVariable("posts", builder.build().wrap(postService.listLatest(top)));
|
||||
List<Post> posts = postService.listLatest(top);
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(posts)));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(postService.countByStatus(PostStatus.PUBLISHED)));
|
||||
|
@ -62,19 +65,19 @@ public class PostTagDirective implements TemplateDirectiveModel {
|
|||
break;
|
||||
case "listByCategoryId":
|
||||
Integer categoryId = Integer.parseInt(params.get("categoryId").toString());
|
||||
env.setVariable("posts", builder.build().wrap(postCategoryService.listPostBy(categoryId, PostStatus.PUBLISHED)));
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postCategoryService.listPostBy(categoryId, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
case "listByCategorySlug":
|
||||
String categorySlug = params.get("categorySlug").toString();
|
||||
env.setVariable("posts", builder.build().wrap(postCategoryService.listPostBy(categorySlug, PostStatus.PUBLISHED)));
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postCategoryService.listPostBy(categorySlug, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
case "listByTagId":
|
||||
Integer tagId = Integer.parseInt(params.get("tagId").toString());
|
||||
env.setVariable("posts", builder.build().wrap(postTagService.listPostsBy(tagId, PostStatus.PUBLISHED)));
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postTagService.listPostsBy(tagId, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
case "listByTagSlug":
|
||||
String tagSlug = params.get("tagSlug").toString();
|
||||
env.setVariable("posts", builder.build().wrap(postTagService.listPostsBy(tagSlug, PostStatus.PUBLISHED)));
|
||||
env.setVariable("posts", builder.build().wrap(postService.convertToListVo(postTagService.listPostsBy(tagSlug, PostStatus.PUBLISHED))));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -4,11 +4,13 @@ import freemarker.core.Environment;
|
|||
import freemarker.template.*;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.TagService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||
|
@ -44,7 +46,8 @@ public class TagTagDirective implements TemplateDirectiveModel {
|
|||
break;
|
||||
case "listByPostId":
|
||||
Integer postId = Integer.parseInt(params.get("postId").toString());
|
||||
env.setVariable("tags", builder.build().wrap(postTagService.listTagsBy(postId)));
|
||||
List<Tag> tags = postTagService.listTagsBy(postId);
|
||||
env.setVariable("tags", builder.build().wrap(tagService.convertTo(tags)));
|
||||
break;
|
||||
case "count":
|
||||
env.setVariable("count", builder.build().wrap(tagService.count()));
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
|
|||
import run.halo.app.event.comment.CommentNewEvent;
|
||||
import run.halo.app.event.comment.CommentReplyEvent;
|
||||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.mail.MailService;
|
||||
import run.halo.app.model.entity.*;
|
||||
import run.halo.app.model.properties.CommentProperties;
|
||||
|
@ -87,12 +88,9 @@ public class CommentEventListener {
|
|||
|
||||
log.debug("Got post comment: [{}]", postComment);
|
||||
|
||||
Post post = postService.getById(postComment.getPostId());
|
||||
BasePostMinimalDTO post = postService.convertToMinimal(postService.getById(postComment.getPostId()));
|
||||
|
||||
StrBuilder url = new StrBuilder(optionService.getBlogBaseUrl())
|
||||
.append("/archives/")
|
||||
.append(post.getUrl());
|
||||
data.put("url", url.toString());
|
||||
data.put("url", post.getFullPath());
|
||||
data.put("page", post.getTitle());
|
||||
data.put("author", postComment.getAuthor());
|
||||
data.put("content", postComment.getContent());
|
||||
|
@ -106,12 +104,9 @@ public class CommentEventListener {
|
|||
|
||||
log.debug("Got sheet comment: [{}]", sheetComment);
|
||||
|
||||
Sheet sheet = sheetService.getById(sheetComment.getPostId());
|
||||
BasePostMinimalDTO sheet = sheetService.convertToMinimal(sheetService.getById(sheetComment.getPostId()));
|
||||
|
||||
StrBuilder url = new StrBuilder(optionService.getBlogBaseUrl())
|
||||
.append("/s/")
|
||||
.append(sheet.getUrl());
|
||||
data.put("url", url.toString());
|
||||
data.put("url", sheet.getFullPath());
|
||||
data.put("page", sheet.getTitle());
|
||||
data.put("author", sheetComment.getAuthor());
|
||||
data.put("content", sheetComment.getContent());
|
||||
|
@ -127,7 +122,8 @@ public class CommentEventListener {
|
|||
Journal journal = journalService.getById(journalComment.getPostId());
|
||||
|
||||
StrBuilder url = new StrBuilder(optionService.getBlogBaseUrl())
|
||||
.append("/journals");
|
||||
.append("/")
|
||||
.append(optionService.getJournalsPrefix());
|
||||
data.put("url", url.toString());
|
||||
data.put("page", journal.getCreateTime());
|
||||
data.put("author", journalComment.getAuthor());
|
||||
|
@ -180,13 +176,9 @@ public class CommentEventListener {
|
|||
|
||||
baseAuthorEmail = baseComment.getEmail();
|
||||
|
||||
Post post = postService.getById(postComment.getPostId());
|
||||
BasePostMinimalDTO post = postService.convertToMinimal(postService.getById(postComment.getPostId()));
|
||||
|
||||
StrBuilder url = new StrBuilder(optionService.getBlogBaseUrl())
|
||||
.append("/archives/")
|
||||
.append(post.getUrl());
|
||||
|
||||
data.put("url", url);
|
||||
data.put("url", post.getFullPath());
|
||||
data.put("page", post.getTitle());
|
||||
data.put("baseAuthor", baseComment.getAuthor());
|
||||
data.put("baseContent", baseComment.getContent());
|
||||
|
@ -214,13 +206,9 @@ public class CommentEventListener {
|
|||
|
||||
baseAuthorEmail = baseComment.getEmail();
|
||||
|
||||
Sheet sheet = sheetService.getById(sheetComment.getPostId());
|
||||
BasePostMinimalDTO sheet = sheetService.convertToMinimal(sheetService.getById(sheetComment.getPostId()));
|
||||
|
||||
StrBuilder url = new StrBuilder(optionService.getBlogBaseUrl())
|
||||
.append("/s/")
|
||||
.append(sheet.getUrl());
|
||||
|
||||
data.put("url", url);
|
||||
data.put("url", sheet.getFullPath());
|
||||
data.put("page", sheet.getTitle());
|
||||
data.put("baseAuthor", baseComment.getAuthor());
|
||||
data.put("baseContent", baseComment.getContent());
|
||||
|
@ -250,7 +238,8 @@ public class CommentEventListener {
|
|||
Journal journal = journalService.getById(journalComment.getPostId());
|
||||
|
||||
StrBuilder url = new StrBuilder(optionService.getBlogBaseUrl())
|
||||
.append("/journals");
|
||||
.append("/")
|
||||
.append(optionService.getJournalsPrefix());
|
||||
data.put("url", url);
|
||||
data.put("page", journal.getContent());
|
||||
data.put("baseAuthor", baseComment.getAuthor());
|
||||
|
|
|
@ -13,7 +13,8 @@ import run.halo.app.event.theme.ThemeActivatedEvent;
|
|||
import run.halo.app.event.theme.ThemeUpdatedEvent;
|
||||
import run.halo.app.event.user.UserUpdatedEvent;
|
||||
import run.halo.app.handler.theme.config.support.ThemeProperty;
|
||||
import run.halo.app.model.properties.OtherProperties;
|
||||
import run.halo.app.model.properties.BlogProperties;
|
||||
import run.halo.app.model.properties.SeoProperties;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.ThemeService;
|
||||
|
@ -99,9 +100,30 @@ public class FreemarkerConfigAwareListener {
|
|||
}
|
||||
|
||||
private void loadOptionsConfig() throws TemplateModelException {
|
||||
|
||||
String context = optionService.isEnabledAbsolutePath() ? optionService.getBlogBaseUrl() + "/" : "/";
|
||||
|
||||
configuration.setSharedVariable("options", optionService.listOptions());
|
||||
configuration.setSharedVariable("context", optionService.getBlogBaseUrl());
|
||||
configuration.setSharedVariable("context", context);
|
||||
configuration.setSharedVariable("version", HaloConst.HALO_VERSION);
|
||||
|
||||
configuration.setSharedVariable("blog_title", optionService.getBlogTitle());
|
||||
configuration.setSharedVariable("blog_url", optionService.getBlogBaseUrl());
|
||||
configuration.setSharedVariable("blog_logo", optionService.getByPropertyOrDefault(BlogProperties.BLOG_LOGO, String.class, BlogProperties.BLOG_LOGO.defaultValue()));
|
||||
configuration.setSharedVariable("seo_keywords", optionService.getByPropertyOrDefault(SeoProperties.KEYWORDS, String.class, SeoProperties.KEYWORDS.defaultValue()));
|
||||
configuration.setSharedVariable("seo_description", optionService.getByPropertyOrDefault(SeoProperties.DESCRIPTION, String.class, SeoProperties.DESCRIPTION.defaultValue()));
|
||||
|
||||
configuration.setSharedVariable("rss_url", optionService.getBlogBaseUrl() + "/rss.xml");
|
||||
configuration.setSharedVariable("atom_url", optionService.getBlogBaseUrl() + "/atom.xml");
|
||||
configuration.setSharedVariable("sitemap_xml_url", optionService.getBlogBaseUrl() + "/sitemap.xml");
|
||||
configuration.setSharedVariable("sitemap_html_url", optionService.getBlogBaseUrl() + "/sitemap.html");
|
||||
configuration.setSharedVariable("links_url", context + optionService.getLinksPrefix());
|
||||
configuration.setSharedVariable("photos_url", context + optionService.getPhotosPrefix());
|
||||
configuration.setSharedVariable("journals_url", context + optionService.getJournalsPrefix());
|
||||
configuration.setSharedVariable("archives_url", context + optionService.getArchivesPrefix());
|
||||
configuration.setSharedVariable("categories_url", context + optionService.getCategoriesPrefix());
|
||||
configuration.setSharedVariable("tags_url", context + optionService.getTagsPrefix());
|
||||
|
||||
log.debug("Loaded options");
|
||||
}
|
||||
|
||||
|
@ -110,9 +132,7 @@ public class FreemarkerConfigAwareListener {
|
|||
// Get current activated theme.
|
||||
ThemeProperty activatedTheme = themeService.getActivatedTheme();
|
||||
|
||||
Boolean enabledAbsolutePath = optionService.getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class, true);
|
||||
|
||||
String themeBasePath = (enabledAbsolutePath ? optionService.getBlogBaseUrl() : "") + "/themes/" + activatedTheme.getFolderName();
|
||||
String themeBasePath = (optionService.isEnabledAbsolutePath() ? optionService.getBlogBaseUrl() : "") + "/themes/" + activatedTheme.getFolderName();
|
||||
|
||||
configuration.setSharedVariable("theme", activatedTheme);
|
||||
|
||||
|
|
|
@ -39,6 +39,24 @@ public enum PermalinkProperties implements PropertyEnum {
|
|||
*/
|
||||
SHEET_PREFIX("sheet_prefix", String.class, "s"),
|
||||
|
||||
/**
|
||||
* Links page prefix
|
||||
* default is links
|
||||
*/
|
||||
LINKS_PREFIX("links_prefix", String.class, "links"),
|
||||
|
||||
/**
|
||||
* Photos page prefix
|
||||
* default is photos
|
||||
*/
|
||||
PHOTOS_PREFIX("photos_prefix", String.class, "photos"),
|
||||
|
||||
/**
|
||||
* Journals page prefix
|
||||
* default is journals
|
||||
*/
|
||||
JOURNALS_PREFIX("journals_prefix", String.class, "journals"),
|
||||
|
||||
/**
|
||||
* Path suffix
|
||||
* such as: .html or .jsp
|
||||
|
|
|
@ -185,6 +185,7 @@ public interface PropertyEnum extends ValueEnum<String> {
|
|||
propertyEnumClasses.add(EmailProperties.class);
|
||||
propertyEnumClasses.add(OtherProperties.class);
|
||||
propertyEnumClasses.add(PostProperties.class);
|
||||
propertyEnumClasses.add(SheetProperties.class);
|
||||
propertyEnumClasses.add(PrimaryProperties.class);
|
||||
propertyEnumClasses.add(QiniuOssProperties.class);
|
||||
propertyEnumClasses.add(SeoProperties.class);
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package run.halo.app.model.properties;
|
||||
|
||||
/**
|
||||
* Sheet properties.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date 2020-02-11
|
||||
*/
|
||||
public enum SheetProperties implements PropertyEnum {
|
||||
|
||||
/**
|
||||
* Links page title.
|
||||
*/
|
||||
LINKS_TITLE("links_title", String.class, "友情链接"),
|
||||
|
||||
/**
|
||||
* Photos page title.
|
||||
*/
|
||||
PHOTOS_TITLE("photos_title", String.class, "图库"),
|
||||
|
||||
/**
|
||||
* Photos page size.
|
||||
*/
|
||||
PHOTOS_PAGE_SIZE("photos_page_size", Integer.class, "10"),
|
||||
|
||||
/**
|
||||
* Journals page title.
|
||||
*/
|
||||
JOURNALS_TITLE("journals_title", String.class, "日志"),
|
||||
|
||||
/**
|
||||
* Journals page size.
|
||||
*/
|
||||
JOURNALS_PAGE_SIZE("journals_page_size", Integer.class, "10");
|
||||
|
||||
private final String value;
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
private final String defaultValue;
|
||||
|
||||
SheetProperties(String value, Class<?> type, String defaultValue) {
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String defaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import java.util.Optional;
|
|||
* Option service interface.
|
||||
*
|
||||
* @author johnniang
|
||||
* @author ryanwang
|
||||
* @date 2019-03-14
|
||||
*/
|
||||
public interface OptionService extends CrudService<Option, Integer> {
|
||||
|
@ -358,6 +359,69 @@ public interface OptionService extends CrudService<Option, Integer> {
|
|||
*/
|
||||
PostPermalinkType getPostPermalinkType();
|
||||
|
||||
/**
|
||||
* Get sheet custom prefix.
|
||||
*
|
||||
* @return sheet prefix.
|
||||
*/
|
||||
String getSheetPrefix();
|
||||
|
||||
/**
|
||||
* Get links page custom prefix.
|
||||
*
|
||||
* @return links page prefix.
|
||||
*/
|
||||
String getLinksPrefix();
|
||||
|
||||
/**
|
||||
* Get photos page custom prefix.
|
||||
*
|
||||
* @return photos page prefix.
|
||||
*/
|
||||
String getPhotosPrefix();
|
||||
|
||||
/**
|
||||
* Get journals page custom prefix.
|
||||
*
|
||||
* @return journals page prefix.
|
||||
*/
|
||||
String getJournalsPrefix();
|
||||
|
||||
/**
|
||||
* Get archives custom prefix.
|
||||
*
|
||||
* @return archives prefix.
|
||||
*/
|
||||
String getArchivesPrefix();
|
||||
|
||||
/**
|
||||
* Get categories custom prefix.
|
||||
*
|
||||
* @return categories prefix.
|
||||
*/
|
||||
String getCategoriesPrefix();
|
||||
|
||||
/**
|
||||
* Get tags custom prefix.
|
||||
*
|
||||
* @return tags prefix.
|
||||
*/
|
||||
String getTagsPrefix();
|
||||
|
||||
/**
|
||||
* Get custom path suffix.
|
||||
*
|
||||
* @return path suffix.
|
||||
*/
|
||||
String getPathSuffix();
|
||||
|
||||
/**
|
||||
* Is enabled absolute path.
|
||||
*
|
||||
* @return true or false.
|
||||
*/
|
||||
Boolean isEnabledAbsolutePath();
|
||||
|
||||
/**
|
||||
* Replace option url in batch.
|
||||
*
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package run.halo.app.service;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import run.halo.app.model.entity.PostComment;
|
||||
import run.halo.app.model.params.CommentQuery;
|
||||
import run.halo.app.model.vo.PostCommentWithPostVO;
|
||||
import run.halo.app.service.base.BaseCommentService;
|
||||
|
||||
|
@ -47,9 +45,6 @@ public interface PostCommentService extends BaseCommentService<PostComment> {
|
|||
@NonNull
|
||||
List<PostCommentWithPostVO> convertToWithPostVo(@Nullable List<PostComment> postComments);
|
||||
|
||||
@NonNull
|
||||
Page<PostCommentWithPostVO> pageTreeBy(@NonNull CommentQuery commentQuery, @NonNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Validate CommentBlackList Status
|
||||
*/
|
||||
|
|
|
@ -213,6 +213,15 @@ public interface PostService extends BasePostService<Post> {
|
|||
@NonNull
|
||||
Page<PostListVO> convertToListVo(@NonNull Page<Post> postPage);
|
||||
|
||||
/**
|
||||
* Converts to a list of post list vo.
|
||||
*
|
||||
* @param posts post must not be null
|
||||
* @return a list of post list vo
|
||||
*/
|
||||
@NonNull
|
||||
List<PostListVO> convertToListVo(@NonNull List<Post> posts);
|
||||
|
||||
/**
|
||||
* Converts to a page of detail vo.
|
||||
*
|
||||
|
|
|
@ -131,6 +131,7 @@ public class AdminServiceImpl implements AdminService {
|
|||
this.mode = mode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AuthToken authenticate(LoginParam loginParam) {
|
||||
Assert.notNull(loginParam, "Login param must not be null");
|
||||
|
|
|
@ -18,7 +18,6 @@ import run.halo.app.model.entity.Attachment;
|
|||
import run.halo.app.model.enums.AttachmentType;
|
||||
import run.halo.app.model.params.AttachmentQuery;
|
||||
import run.halo.app.model.properties.AttachmentProperties;
|
||||
import run.halo.app.model.properties.OtherProperties;
|
||||
import run.halo.app.model.support.UploadResult;
|
||||
import run.halo.app.repository.AttachmentRepository;
|
||||
import run.halo.app.service.AttachmentService;
|
||||
|
@ -158,7 +157,7 @@ public class AttachmentServiceImpl extends AbstractCrudService<Attachment, Integ
|
|||
// Get blog base url
|
||||
String blogBaseUrl = optionService.getBlogBaseUrl();
|
||||
|
||||
Boolean enabledAbsolutePath = optionService.getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class, true);
|
||||
Boolean enabledAbsolutePath = optionService.isEnabledAbsolutePath();
|
||||
|
||||
// Convert to output dto
|
||||
AttachmentDTO attachmentDTO = new AttachmentDTO().convertFrom(attachment);
|
||||
|
|
|
@ -15,6 +15,7 @@ import run.halo.app.model.entity.Category;
|
|||
import run.halo.app.model.vo.CategoryVO;
|
||||
import run.halo.app.repository.CategoryRepository;
|
||||
import run.halo.app.service.CategoryService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.base.AbstractCrudService;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
|
@ -39,11 +40,15 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
|
|||
|
||||
private final PostCategoryService postCategoryService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public CategoryServiceImpl(CategoryRepository categoryRepository,
|
||||
PostCategoryService postCategoryService) {
|
||||
PostCategoryService postCategoryService,
|
||||
OptionService optionService) {
|
||||
super(categoryRepository);
|
||||
this.categoryRepository = categoryRepository;
|
||||
this.postCategoryService = postCategoryService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -188,7 +193,23 @@ public class CategoryServiceImpl extends AbstractCrudService<Category, Integer>
|
|||
public CategoryDTO convertTo(Category category) {
|
||||
Assert.notNull(category, "Category must not be null");
|
||||
|
||||
return new CategoryDTO().convertFrom(category);
|
||||
CategoryDTO categoryDTO = new CategoryDTO().convertFrom(category);
|
||||
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/")
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append("/")
|
||||
.append(category.getSlugName())
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
categoryDTO.setFullPath(fullPath.toString());
|
||||
|
||||
return categoryDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -472,6 +472,51 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
|
|||
return getEnumByPropertyOrDefault(PermalinkProperties.POST_PERMALINK_TYPE, PostPermalinkType.class, PostPermalinkType.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSheetPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.SHEET_PREFIX, String.class, PermalinkProperties.SHEET_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLinksPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.LINKS_PREFIX, String.class, PermalinkProperties.LINKS_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPhotosPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.PHOTOS_PREFIX, String.class, PermalinkProperties.PHOTOS_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJournalsPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.JOURNALS_PREFIX, String.class, PermalinkProperties.JOURNALS_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArchivesPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.ARCHIVES_PREFIX, String.class, PermalinkProperties.ARCHIVES_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategoriesPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.CATEGORIES_PREFIX, String.class, PermalinkProperties.CATEGORIES_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagsPrefix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.TAGS_PREFIX, String.class, PermalinkProperties.TAGS_PREFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathSuffix() {
|
||||
return getByPropertyOrDefault(PermalinkProperties.PATH_SUFFIX, String.class, PermalinkProperties.PATH_SUFFIX.defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isEnabledAbsolutePath() {
|
||||
return getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionDTO> replaceUrl(String oldUrl, String newUrl) {
|
||||
List<Option> options = listAll();
|
||||
|
|
|
@ -16,6 +16,7 @@ import run.halo.app.model.projection.CategoryPostCountProjection;
|
|||
import run.halo.app.repository.CategoryRepository;
|
||||
import run.halo.app.repository.PostCategoryRepository;
|
||||
import run.halo.app.repository.PostRepository;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostCategoryService;
|
||||
import run.halo.app.service.base.AbstractCrudService;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
|
@ -40,13 +41,17 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
|
|||
|
||||
private final CategoryRepository categoryRepository;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public PostCategoryServiceImpl(PostCategoryRepository postCategoryRepository,
|
||||
PostRepository postRepository,
|
||||
CategoryRepository categoryRepository) {
|
||||
CategoryRepository categoryRepository,
|
||||
OptionService optionService) {
|
||||
super(postCategoryRepository);
|
||||
this.postCategoryRepository = postCategoryRepository;
|
||||
this.postRepository = postRepository;
|
||||
this.categoryRepository = categoryRepository;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -241,6 +246,21 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
|
|||
CategoryWithPostCountDTO categoryWithPostCountDTO = new CategoryWithPostCountDTO().convertFrom(category);
|
||||
// Set post count
|
||||
categoryWithPostCountDTO.setPostCount(categoryPostCountMap.getOrDefault(category.getId(), 0L));
|
||||
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/")
|
||||
.append(optionService.getCategoriesPrefix())
|
||||
.append("/")
|
||||
.append(category.getSlugName())
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
categoryWithPostCountDTO.setFullPath(fullPath.toString());
|
||||
|
||||
return categoryWithPostCountDTO;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
@ -15,7 +15,7 @@ import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
|||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.entity.PostComment;
|
||||
import run.halo.app.model.enums.CommentViolationTypeEnum;
|
||||
import run.halo.app.model.params.CommentQuery;
|
||||
import run.halo.app.model.enums.PostPermalinkType;
|
||||
import run.halo.app.model.properties.CommentProperties;
|
||||
import run.halo.app.model.vo.PostCommentWithPostVO;
|
||||
import run.halo.app.repository.PostCommentRepository;
|
||||
|
@ -44,8 +44,6 @@ import java.util.stream.Collectors;
|
|||
@Service
|
||||
public class PostCommentServiceImpl extends BaseCommentServiceImpl<PostComment> implements PostCommentService {
|
||||
|
||||
private final PostCommentRepository postCommentRepository;
|
||||
|
||||
private final PostRepository postRepository;
|
||||
|
||||
private final CommentBlackListService commentBlackListService;
|
||||
|
@ -57,7 +55,6 @@ public class PostCommentServiceImpl extends BaseCommentServiceImpl<PostComment>
|
|||
CommentBlackListService commentBlackListService,
|
||||
ApplicationEventPublisher eventPublisher) {
|
||||
super(postCommentRepository, optionService, userService, eventPublisher);
|
||||
this.postCommentRepository = postCommentRepository;
|
||||
this.postRepository = postRepository;
|
||||
this.commentBlackListService = commentBlackListService;
|
||||
}
|
||||
|
@ -74,7 +71,10 @@ public class PostCommentServiceImpl extends BaseCommentServiceImpl<PostComment>
|
|||
public PostCommentWithPostVO convertToWithPostVo(PostComment comment) {
|
||||
Assert.notNull(comment, "PostComment must not be null");
|
||||
PostCommentWithPostVO postCommentWithPostVO = new PostCommentWithPostVO().convertFrom(comment);
|
||||
postCommentWithPostVO.setPost(new BasePostMinimalDTO().convertFrom(postRepository.getOne(comment.getPostId())));
|
||||
|
||||
BasePostMinimalDTO basePostMinimalDTO = new BasePostMinimalDTO().convertFrom(postRepository.getOne(comment.getPostId()));
|
||||
|
||||
postCommentWithPostVO.setPost(buildPostFullPath(basePostMinimalDTO));
|
||||
return postCommentWithPostVO;
|
||||
}
|
||||
|
||||
|
@ -96,18 +96,58 @@ public class PostCommentServiceImpl extends BaseCommentServiceImpl<PostComment>
|
|||
// Convert to vo
|
||||
PostCommentWithPostVO postCommentWithPostVO = new PostCommentWithPostVO().convertFrom(comment);
|
||||
|
||||
// Get post and set to the vo
|
||||
postCommentWithPostVO.setPost(new BasePostMinimalDTO().convertFrom(postMap.get(comment.getPostId())));
|
||||
BasePostMinimalDTO basePostMinimalDTO = new BasePostMinimalDTO().convertFrom(postMap.get(comment.getPostId()));
|
||||
|
||||
postCommentWithPostVO.setPost(buildPostFullPath(basePostMinimalDTO));
|
||||
|
||||
return postCommentWithPostVO;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PostCommentWithPostVO> pageTreeBy(CommentQuery commentQuery, Pageable pageable) {
|
||||
Page<PostComment> postCommentPage = pageBy(commentQuery, pageable);
|
||||
private BasePostMinimalDTO buildPostFullPath(BasePostMinimalDTO basePostMinimalDTO) {
|
||||
PostPermalinkType permalinkType = optionService.getPostPermalinkType();
|
||||
|
||||
return null;
|
||||
String pathSuffix = optionService.getPathSuffix();
|
||||
|
||||
String archivesPrefix = optionService.getArchivesPrefix();
|
||||
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/");
|
||||
|
||||
if (permalinkType.equals(PostPermalinkType.DEFAULT)) {
|
||||
fullPath.append(archivesPrefix)
|
||||
.append("/")
|
||||
.append(basePostMinimalDTO.getUrl())
|
||||
.append(pathSuffix);
|
||||
} else if (permalinkType.equals(PostPermalinkType.ID)) {
|
||||
fullPath.append("?p=")
|
||||
.append(basePostMinimalDTO.getId());
|
||||
} else if (permalinkType.equals(PostPermalinkType.DATE)) {
|
||||
fullPath.append(DateUtil.year(basePostMinimalDTO.getCreateTime()))
|
||||
.append("/")
|
||||
.append(DateUtil.month(basePostMinimalDTO.getCreateTime()) + 1)
|
||||
.append("/")
|
||||
.append(basePostMinimalDTO.getUrl())
|
||||
.append(pathSuffix);
|
||||
} else if (permalinkType.equals(PostPermalinkType.DAY)) {
|
||||
fullPath.append(DateUtil.year(basePostMinimalDTO.getCreateTime()))
|
||||
.append("/")
|
||||
.append(DateUtil.month(basePostMinimalDTO.getCreateTime()) + 1)
|
||||
.append("/")
|
||||
.append(DateUtil.dayOfMonth(basePostMinimalDTO.getCreateTime()))
|
||||
.append("/")
|
||||
.append(basePostMinimalDTO.getUrl())
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
basePostMinimalDTO.setFullPath(fullPath.toString());
|
||||
|
||||
return basePostMinimalDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,15 +21,17 @@ import run.halo.app.event.logger.LogEvent;
|
|||
import run.halo.app.event.post.PostVisitEvent;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.model.dto.BaseMetaDTO;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.model.dto.post.BasePostSimpleDTO;
|
||||
import run.halo.app.model.entity.*;
|
||||
import run.halo.app.model.enums.LogType;
|
||||
import run.halo.app.model.enums.PostPermalinkType;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.params.PostQuery;
|
||||
import run.halo.app.model.properties.PermalinkProperties;
|
||||
import run.halo.app.model.properties.PostProperties;
|
||||
import run.halo.app.model.vo.*;
|
||||
import run.halo.app.repository.PostRepository;
|
||||
import run.halo.app.repository.base.BasePostRepository;
|
||||
import run.halo.app.service.*;
|
||||
import run.halo.app.utils.DateUtils;
|
||||
import run.halo.app.utils.MarkdownUtils;
|
||||
|
@ -76,7 +78,9 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
|
||||
private final OptionService optionService;
|
||||
|
||||
public PostServiceImpl(PostRepository postRepository,
|
||||
public PostServiceImpl(BasePostRepository<Post> basePostRepository,
|
||||
OptionService optionService,
|
||||
PostRepository postRepository,
|
||||
TagService tagService,
|
||||
CategoryService categoryService,
|
||||
PostTagService postTagService,
|
||||
|
@ -84,8 +88,8 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
PostCommentService postCommentService,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
PostMetaService postMetaService,
|
||||
OptionService optionService) {
|
||||
super(postRepository, optionService);
|
||||
OptionService optionService1) {
|
||||
super(basePostRepository, optionService);
|
||||
this.postRepository = postRepository;
|
||||
this.tagService = tagService;
|
||||
this.categoryService = categoryService;
|
||||
|
@ -94,7 +98,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
this.postCommentService = postCommentService;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.postMetaService = postMetaService;
|
||||
this.optionService = optionService;
|
||||
this.optionService = optionService1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -506,16 +510,6 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
// Get post meta list map
|
||||
Map<Integer, List<PostMeta>> postMetaListMap = postMetaService.listPostMetaAsMap(postIds);
|
||||
|
||||
String blogUrl = optionService.getBlogBaseUrl();
|
||||
|
||||
PostPermalinkType permalinkType = optionService.getPostPermalinkType();
|
||||
|
||||
String pathSuffix = optionService
|
||||
.getByPropertyOrDefault(PermalinkProperties.PATH_SUFFIX, String.class, "");
|
||||
|
||||
String archivesPrefix = optionService
|
||||
.getByPropertyOrDefault(PermalinkProperties.ARCHIVES_PREFIX, String.class, "");
|
||||
|
||||
return postPage.map(post -> {
|
||||
PostListVO postListVO = new PostListVO().convertFrom(post);
|
||||
|
||||
|
@ -552,46 +546,116 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
// Set comment count
|
||||
postListVO.setCommentCount(commentCountMap.getOrDefault(post.getId(), 0L));
|
||||
|
||||
StringBuilder fullPath = new StringBuilder(blogUrl)
|
||||
.append("/");
|
||||
if (permalinkType.equals(PostPermalinkType.DEFAULT)) {
|
||||
fullPath.append(archivesPrefix)
|
||||
.append("/")
|
||||
.append(postListVO.getUrl())
|
||||
.append(pathSuffix);
|
||||
} else if (permalinkType.equals(PostPermalinkType.ID)) {
|
||||
fullPath.append("?p=")
|
||||
.append(postListVO.getId());
|
||||
} else if (permalinkType.equals(PostPermalinkType.DATE)) {
|
||||
fullPath.append(DateUtil.year(postListVO.getCreateTime()))
|
||||
.append("/")
|
||||
.append(DateUtil.month(postListVO.getCreateTime()) + 1)
|
||||
.append("/")
|
||||
.append(postListVO.getUrl())
|
||||
.append(pathSuffix);
|
||||
} else if (permalinkType.equals(PostPermalinkType.DAY)) {
|
||||
fullPath.append(DateUtil.year(postListVO.getCreateTime()))
|
||||
.append("/")
|
||||
.append(DateUtil.month(postListVO.getCreateTime()) + 1)
|
||||
.append("/")
|
||||
.append(DateUtil.dayOfMonth(postListVO.getCreateTime()))
|
||||
.append("/")
|
||||
.append(postListVO.getUrl())
|
||||
.append(pathSuffix);
|
||||
}
|
||||
|
||||
postListVO.setFullPath(fullPath.toString());
|
||||
postListVO.setFullPath(buildFullPath(post));
|
||||
|
||||
return postListVO;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostListVO> convertToListVo(List<Post> posts) {
|
||||
Assert.notNull(posts, "Post page must not be null");
|
||||
|
||||
Set<Integer> postIds = ServiceUtils.fetchProperty(posts, Post::getId);
|
||||
|
||||
// Get tag list map
|
||||
Map<Integer, List<Tag>> tagListMap = postTagService.listTagListMapBy(postIds);
|
||||
|
||||
// Get category list map
|
||||
Map<Integer, List<Category>> categoryListMap = postCategoryService
|
||||
.listCategoryListMap(postIds);
|
||||
|
||||
// Get comment count
|
||||
Map<Integer, Long> commentCountMap = postCommentService.countByPostIds(postIds);
|
||||
|
||||
// Get post meta list map
|
||||
Map<Integer, List<PostMeta>> postMetaListMap = postMetaService.listPostMetaAsMap(postIds);
|
||||
|
||||
return posts.stream().map(post -> {
|
||||
PostListVO postListVO = new PostListVO().convertFrom(post);
|
||||
|
||||
if (StringUtils.isBlank(postListVO.getSummary())) {
|
||||
postListVO.setSummary(generateSummary(post.getFormatContent()));
|
||||
}
|
||||
|
||||
Optional.ofNullable(tagListMap.get(post.getId())).orElseGet(LinkedList::new);
|
||||
|
||||
// Set tags
|
||||
postListVO.setTags(Optional.ofNullable(tagListMap.get(post.getId()))
|
||||
.orElseGet(LinkedList::new)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(tagService::convertTo)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
// Set categories
|
||||
postListVO.setCategories(Optional.ofNullable(categoryListMap.get(post.getId()))
|
||||
.orElseGet(LinkedList::new)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(categoryService::convertTo)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
// Set post metas
|
||||
postListVO.setPostMetas(Optional.ofNullable(postMetaListMap.get(post.getId()))
|
||||
.orElseGet(LinkedList::new)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(postMeta -> (BaseMetaDTO) new BaseMetaDTO().convertFrom(postMeta))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
// Set comment count
|
||||
postListVO.setCommentCount(commentCountMap.getOrDefault(post.getId(), 0L));
|
||||
|
||||
postListVO.setFullPath(buildFullPath(post));
|
||||
|
||||
return postListVO;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PostDetailVO> convertToDetailVo(Page<Post> postPage) {
|
||||
Assert.notNull(postPage, "Post page must not be null");
|
||||
return postPage.map(this::convertToDetailVo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePostMinimalDTO convertToMinimal(Post post) {
|
||||
Assert.notNull(post, "Post must not be null");
|
||||
BasePostMinimalDTO basePostMinimalDTO = new BasePostMinimalDTO().convertFrom(post);
|
||||
|
||||
basePostMinimalDTO.setFullPath(buildFullPath(post));
|
||||
|
||||
return basePostMinimalDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BasePostMinimalDTO> convertToMinimal(List<Post> posts) {
|
||||
if (CollectionUtils.isEmpty(posts)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return posts.stream()
|
||||
.map(this::convertToMinimal)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePostSimpleDTO convertToSimple(Post post) {
|
||||
Assert.notNull(post, "Post must not be null");
|
||||
|
||||
BasePostSimpleDTO basePostSimpleDTO = new BasePostSimpleDTO().convertFrom(post);
|
||||
|
||||
// Set summary
|
||||
if (StringUtils.isBlank(basePostSimpleDTO.getSummary())) {
|
||||
basePostSimpleDTO.setSummary(generateSummary(post.getFormatContent()));
|
||||
}
|
||||
|
||||
basePostSimpleDTO.setFullPath(buildFullPath(post));
|
||||
|
||||
return basePostSimpleDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to post detail vo.
|
||||
*
|
||||
|
@ -632,6 +696,8 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
|
||||
postDetailVO.setCommentCount(postCommentService.countByPostId(post.getId()));
|
||||
|
||||
postDetailVO.setFullPath(buildFullPath(post));
|
||||
|
||||
return postDetailVO;
|
||||
}
|
||||
|
||||
|
@ -731,8 +797,8 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
// get pageable post list
|
||||
List<Post> postList = new ArrayList<>();
|
||||
// init fist page && default page size
|
||||
Integer page = 1;
|
||||
Integer defaultPageSize = 500;
|
||||
int page = 1;
|
||||
int defaultPageSize = 500;
|
||||
boolean needNext = true;
|
||||
|
||||
// get custom sort type
|
||||
|
@ -768,7 +834,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
|
||||
// get current post index in post list
|
||||
List<Integer> idList = postList.stream().map(Post::getId).collect(Collectors.toList());
|
||||
Integer index = idList.indexOf(currentPost.getId());
|
||||
int index = idList.indexOf(currentPost.getId());
|
||||
|
||||
if (index == -1) {
|
||||
// if not found, return empty object
|
||||
|
@ -777,8 +843,7 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
|
||||
AdjacentPostVO adjacentPostVO = new AdjacentPostVO();
|
||||
|
||||
//setup pre
|
||||
//TODO convert POST to PostVO (with fullPath)
|
||||
// setup pre
|
||||
if (index > 0) {
|
||||
adjacentPostVO.setPrePost(postList.get(index - 1));
|
||||
}
|
||||
|
@ -796,4 +861,48 @@ public class PostServiceImpl extends BasePostServiceImpl<Post> implements PostSe
|
|||
.toString();
|
||||
return Sort.by(DESC, "topPriority").and(Sort.by(DESC, indexSort)).and(Sort.by(DESC, "id"));
|
||||
}
|
||||
|
||||
private String buildFullPath(Post post) {
|
||||
|
||||
PostPermalinkType permalinkType = optionService.getPostPermalinkType();
|
||||
|
||||
String pathSuffix = optionService.getPathSuffix();
|
||||
|
||||
String archivesPrefix = optionService.getArchivesPrefix();
|
||||
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/");
|
||||
|
||||
if (permalinkType.equals(PostPermalinkType.DEFAULT)) {
|
||||
fullPath.append(archivesPrefix)
|
||||
.append("/")
|
||||
.append(post.getUrl())
|
||||
.append(pathSuffix);
|
||||
} else if (permalinkType.equals(PostPermalinkType.ID)) {
|
||||
fullPath.append("?p=")
|
||||
.append(post.getId());
|
||||
} else if (permalinkType.equals(PostPermalinkType.DATE)) {
|
||||
fullPath.append(DateUtil.year(post.getCreateTime()))
|
||||
.append("/")
|
||||
.append(DateUtil.month(post.getCreateTime()) + 1)
|
||||
.append("/")
|
||||
.append(post.getUrl())
|
||||
.append(pathSuffix);
|
||||
} else if (permalinkType.equals(PostPermalinkType.DAY)) {
|
||||
fullPath.append(DateUtil.year(post.getCreateTime()))
|
||||
.append("/")
|
||||
.append(DateUtil.month(post.getCreateTime()) + 1)
|
||||
.append("/")
|
||||
.append(DateUtil.dayOfMonth(post.getCreateTime()))
|
||||
.append("/")
|
||||
.append(post.getUrl())
|
||||
.append(pathSuffix);
|
||||
}
|
||||
return fullPath.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import run.halo.app.model.projection.TagPostPostCountProjection;
|
|||
import run.halo.app.repository.PostRepository;
|
||||
import run.halo.app.repository.PostTagRepository;
|
||||
import run.halo.app.repository.TagRepository;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.base.AbstractCrudService;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
|
@ -39,13 +40,17 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
|
|||
|
||||
private final TagRepository tagRepository;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public PostTagServiceImpl(PostTagRepository postTagRepository,
|
||||
PostRepository postRepository,
|
||||
TagRepository tagRepository) {
|
||||
TagRepository tagRepository,
|
||||
OptionService optionService) {
|
||||
super(postTagRepository);
|
||||
this.postTagRepository = postTagRepository;
|
||||
this.postRepository = postRepository;
|
||||
this.tagRepository = tagRepository;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,6 +78,21 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
|
|||
tag -> {
|
||||
TagWithPostCountDTO tagWithCountOutputDTO = new TagWithPostCountDTO().convertFrom(tag);
|
||||
tagWithCountOutputDTO.setPostCount(tagPostCountMap.getOrDefault(tag.getId(), 0L));
|
||||
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/")
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append("/")
|
||||
.append(tag.getSlugName())
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
tagWithCountOutputDTO.setFullPath(fullPath.toString());
|
||||
|
||||
return tagWithCountOutputDTO;
|
||||
}
|
||||
).collect(Collectors.toList());
|
||||
|
|
|
@ -35,8 +35,6 @@ import java.util.stream.Collectors;
|
|||
@Service
|
||||
public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment> implements SheetCommentService {
|
||||
|
||||
private final SheetCommentRepository sheetCommentRepository;
|
||||
|
||||
private final SheetRepository sheetRepository;
|
||||
|
||||
public SheetCommentServiceImpl(SheetCommentRepository sheetCommentRepository,
|
||||
|
@ -45,7 +43,6 @@ public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment
|
|||
ApplicationEventPublisher eventPublisher,
|
||||
SheetRepository sheetRepository) {
|
||||
super(sheetCommentRepository, optionService, userService, eventPublisher);
|
||||
this.sheetCommentRepository = sheetCommentRepository;
|
||||
this.sheetRepository = sheetRepository;
|
||||
}
|
||||
|
||||
|
@ -63,7 +60,10 @@ public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment
|
|||
public SheetCommentWithSheetVO convertToWithSheetVo(SheetComment comment) {
|
||||
Assert.notNull(comment, "SheetComment must not be null");
|
||||
SheetCommentWithSheetVO sheetCommentWithSheetVO = new SheetCommentWithSheetVO().convertFrom(comment);
|
||||
sheetCommentWithSheetVO.setSheet(new BasePostMinimalDTO().convertFrom(sheetRepository.getOne(comment.getPostId())));
|
||||
|
||||
BasePostMinimalDTO basePostMinimalDTO = new BasePostMinimalDTO().convertFrom(sheetRepository.getOne(comment.getPostId()));
|
||||
|
||||
sheetCommentWithSheetVO.setSheet(buildSheetFullPath(basePostMinimalDTO));
|
||||
return sheetCommentWithSheetVO;
|
||||
}
|
||||
|
||||
|
@ -81,12 +81,32 @@ public class SheetCommentServiceImpl extends BaseCommentServiceImpl<SheetComment
|
|||
.filter(comment -> sheetMap.containsKey(comment.getPostId()))
|
||||
.map(comment -> {
|
||||
SheetCommentWithSheetVO sheetCmtWithPostVO = new SheetCommentWithSheetVO().convertFrom(comment);
|
||||
sheetCmtWithPostVO.setSheet(new BasePostMinimalDTO().convertFrom(sheetMap.get(comment.getPostId())));
|
||||
|
||||
BasePostMinimalDTO postMinimalDTO = new BasePostMinimalDTO().convertFrom(sheetMap.get(comment.getPostId()));
|
||||
|
||||
sheetCmtWithPostVO.setSheet(buildSheetFullPath(postMinimalDTO));
|
||||
return sheetCmtWithPostVO;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private BasePostMinimalDTO buildSheetFullPath(BasePostMinimalDTO basePostMinimalDTO) {
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/")
|
||||
.append(optionService.getSheetPrefix())
|
||||
.append("/")
|
||||
.append(basePostMinimalDTO.getUrl())
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
basePostMinimalDTO.setFullPath(fullPath.toString());
|
||||
return basePostMinimalDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<SheetCommentWithSheetVO> convertToWithSheetVo(Page<SheetComment> sheetCommentPage) {
|
||||
Assert.notNull(sheetCommentPage, "Sheet comment page must not be null");
|
||||
|
|
|
@ -9,11 +9,13 @@ import org.springframework.data.domain.Pageable;
|
|||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import run.halo.app.event.logger.LogEvent;
|
||||
import run.halo.app.event.post.SheetVisitEvent;
|
||||
import run.halo.app.exception.AlreadyExistsException;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.model.dto.InternalSheetDTO;
|
||||
import run.halo.app.model.dto.post.BasePostMinimalDTO;
|
||||
import run.halo.app.model.entity.Sheet;
|
||||
import run.halo.app.model.entity.SheetComment;
|
||||
import run.halo.app.model.entity.SheetMeta;
|
||||
|
@ -27,6 +29,7 @@ import run.halo.app.utils.MarkdownUtils;
|
|||
import run.halo.app.utils.ServiceUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Sheet service implementation.
|
||||
|
@ -50,18 +53,21 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
|
||||
private final ThemeService themeService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public SheetServiceImpl(SheetRepository sheetRepository,
|
||||
ApplicationEventPublisher eventPublisher,
|
||||
SheetCommentService sheetCommentService,
|
||||
OptionService optionService,
|
||||
SheetMetaService sheetMetaService,
|
||||
ThemeService themeService) {
|
||||
ThemeService themeService,
|
||||
OptionService optionService) {
|
||||
super(sheetRepository, optionService);
|
||||
this.sheetRepository = sheetRepository;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.sheetCommentService = sheetCommentService;
|
||||
this.sheetMetaService = sheetMetaService;
|
||||
this.themeService = themeService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -129,9 +135,7 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
public Sheet getByUrl(String url) {
|
||||
Assert.hasText(url, "Url must not be blank");
|
||||
|
||||
Sheet sheet = sheetRepository.getByUrl(url).orElseThrow(() -> new NotFoundException("查询不到该页面的信息").setErrorData(url));
|
||||
|
||||
return sheet;
|
||||
return sheetRepository.getByUrl(url).orElseThrow(() -> new NotFoundException("查询不到该页面的信息").setErrorData(url));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -141,9 +145,7 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
|
||||
Optional<Sheet> postOptional = sheetRepository.getByUrlAndStatus(url, status);
|
||||
|
||||
Sheet sheet = postOptional.orElseThrow(() -> new NotFoundException("查询不到该页面的信息").setErrorData(url));
|
||||
|
||||
return sheet;
|
||||
return postOptional.orElseThrow(() -> new NotFoundException("查询不到该页面的信息").setErrorData(url));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -196,21 +198,21 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
InternalSheetDTO linkSheet = new InternalSheetDTO();
|
||||
linkSheet.setId(1);
|
||||
linkSheet.setTitle("友情链接");
|
||||
linkSheet.setUrl("/links");
|
||||
linkSheet.setUrl((optionService.isEnabledAbsolutePath() ? optionService.getBlogBaseUrl() : "") + "/" + optionService.getLinksPrefix());
|
||||
linkSheet.setStatus(themeService.templateExists("links.ftl"));
|
||||
|
||||
// photos sheet
|
||||
InternalSheetDTO photoSheet = new InternalSheetDTO();
|
||||
photoSheet.setId(2);
|
||||
photoSheet.setTitle("图库页面");
|
||||
photoSheet.setUrl("/photos");
|
||||
photoSheet.setUrl((optionService.isEnabledAbsolutePath() ? optionService.getBlogBaseUrl() : "") + "/" + optionService.getPhotosPrefix());
|
||||
photoSheet.setStatus(themeService.templateExists("photos.ftl"));
|
||||
|
||||
// journals sheet
|
||||
InternalSheetDTO journalSheet = new InternalSheetDTO();
|
||||
journalSheet.setId(3);
|
||||
journalSheet.setTitle("日志页面");
|
||||
journalSheet.setUrl("/journals");
|
||||
journalSheet.setUrl((optionService.isEnabledAbsolutePath() ? optionService.getBlogBaseUrl() : "") + "/" + optionService.getJournalsPrefix());
|
||||
journalSheet.setStatus(themeService.templateExists("journals.ftl"));
|
||||
|
||||
internalSheetDTOS.add(linkSheet);
|
||||
|
@ -254,6 +256,9 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
return sheetPage.map(sheet -> {
|
||||
SheetListVO sheetListVO = new SheetListVO().convertFrom(sheet);
|
||||
sheetListVO.setCommentCount(sheetCommentCountMap.getOrDefault(sheet.getId(), 0L));
|
||||
|
||||
sheetListVO.setFullPath(buildFullPath(sheet));
|
||||
|
||||
return sheetListVO;
|
||||
});
|
||||
}
|
||||
|
@ -271,6 +276,27 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
return convertTo(sheet, sheetMetas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePostMinimalDTO convertToMinimal(Sheet sheet) {
|
||||
Assert.notNull(sheet, "Sheet must not be null");
|
||||
BasePostMinimalDTO basePostMinimalDTO = new BasePostMinimalDTO().convertFrom(sheet);
|
||||
|
||||
basePostMinimalDTO.setFullPath(buildFullPath(sheet));
|
||||
|
||||
return basePostMinimalDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BasePostMinimalDTO> convertToMinimal(List<Sheet> sheets) {
|
||||
if (CollectionUtils.isEmpty(sheets)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return sheets.stream()
|
||||
.map(this::convertToMinimal)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private SheetDetailVO convertTo(@NonNull Sheet sheet, List<SheetMeta> sheetMetas) {
|
||||
Assert.notNull(sheet, "Sheet must not be null");
|
||||
|
@ -289,6 +315,9 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
}
|
||||
|
||||
sheetDetailVO.setCommentCount(sheetCommentService.countByPostId(sheet.getId()));
|
||||
|
||||
sheetDetailVO.setFullPath(buildFullPath(sheet));
|
||||
|
||||
return sheetDetailVO;
|
||||
}
|
||||
|
||||
|
@ -311,4 +340,20 @@ public class SheetServiceImpl extends BasePostServiceImpl<Sheet> implements Shee
|
|||
throw new AlreadyExistsException("页面路径 " + sheet.getUrl() + " 已存在");
|
||||
}
|
||||
}
|
||||
|
||||
private String buildFullPath(Sheet sheet) {
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/")
|
||||
.append(optionService.getSheetPrefix())
|
||||
.append("/")
|
||||
.append(sheet.getUrl())
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
return fullPath.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import run.halo.app.exception.NotFoundException;
|
|||
import run.halo.app.model.dto.TagDTO;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.repository.TagRepository;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.TagService;
|
||||
import run.halo.app.service.base.AbstractCrudService;
|
||||
|
||||
|
@ -30,9 +31,13 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
|
|||
|
||||
private final TagRepository tagRepository;
|
||||
|
||||
public TagServiceImpl(TagRepository tagRepository) {
|
||||
private final OptionService optionService;
|
||||
|
||||
public TagServiceImpl(TagRepository tagRepository,
|
||||
OptionService optionService) {
|
||||
super(tagRepository);
|
||||
this.tagRepository = tagRepository;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +76,23 @@ public class TagServiceImpl extends AbstractCrudService<Tag, Integer> implements
|
|||
public TagDTO convertTo(Tag tag) {
|
||||
Assert.notNull(tag, "Tag must not be null");
|
||||
|
||||
return new TagDTO().convertFrom(tag);
|
||||
TagDTO tagDTO = new TagDTO().convertFrom(tag);
|
||||
|
||||
StringBuilder fullPath = new StringBuilder();
|
||||
|
||||
if (optionService.isEnabledAbsolutePath()) {
|
||||
fullPath.append(optionService.getBlogBaseUrl());
|
||||
}
|
||||
|
||||
fullPath.append("/")
|
||||
.append(optionService.getTagsPrefix())
|
||||
.append("/")
|
||||
.append(tag.getSlugName())
|
||||
.append(optionService.getPathSuffix());
|
||||
|
||||
tagDTO.setFullPath(fullPath.toString());
|
||||
|
||||
return tagDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="alternate" type="application/rss+xml" title="atom 1.0" href="${context!}/atom.xml">
|
||||
<link rel="alternate" type="application/rss+xml" title="atom 1.0" href="${atom_url!}">
|
||||
<title>${error.status!} | ${error.error!}</title>
|
||||
|
||||
<style type="text/css">
|
||||
|
@ -125,7 +125,7 @@
|
|||
<h1 class="title">${error.error!}.</h1>
|
||||
<p>${error.message!}</p>
|
||||
<div class="back-home">
|
||||
<button onclick="window.location.href='${context!}'">首页</button>
|
||||
<button onclick="window.location.href='${blog_url!}'">首页</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="emailcontent" style="width:100%;max-width:720px;text-align: left;margin: 0 auto;padding-top: 20px;padding-bottom: 80px">
|
||||
<div class="emailtitle" style="border-radius: 5px;border:1px solid #eee;overflow: hidden;">
|
||||
<h1 style="color:#fff;background: #3798e8;line-height:70px;font-size:24px;font-weight:normal;padding-left:40px;margin:0">
|
||||
您在 ${options.blog_title!} 上的留言有回复啦!
|
||||
您在 ${blog_title!} 上的留言有回复啦!
|
||||
</h1>
|
||||
<div class="emailtext" style="background:#fff;padding:20px 32px 40px;">
|
||||
|
||||
|
@ -17,13 +17,13 @@
|
|||
<a href="${url!}">查看完整内容</a>
|
||||
</p>
|
||||
<p style="color: #6e6e6e;font-size:13px;line-height:24px;">欢迎再度光临
|
||||
<a href="${context!}">${options.blog_title!}</a>
|
||||
<a href="${blog_url!}">${blog_title!}</a>
|
||||
</p>
|
||||
|
||||
<p style="color: #6e6e6e;font-size:13px;line-height:24px;">(此邮件由系统自动发出, 请勿回复。如有打扰,请见谅。)</p>
|
||||
</div>
|
||||
<p style="color: #6e6e6e;font-size:13px;line-height:24px;text-align:right;padding:0 32px">邮件发自:
|
||||
<a href="${context!}" style="color:#51a0e3;text-decoration:none">${options.blog_title!}</a>
|
||||
<a href="${blog_url!}" style="color:#51a0e3;text-decoration:none">${blog_title!}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<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"/>
|
||||
<title>私密文章访问 - ${options.blog_title!}</title>
|
||||
<title>私密文章访问 - ${blog_title!}</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: #080821;
|
||||
|
@ -152,7 +152,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<form method="post" action="${context!}/archives/${url}/password">
|
||||
<form method="post" action="${context!}/archives/${url!}/password">
|
||||
<div class="password-input">
|
||||
<input type="password" name="password" placeholder="请输入文章访问密码">
|
||||
<span class="bottom"></span>
|
||||
|
|
|
@ -1,41 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0"
|
||||
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
||||
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
|
||||
xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
|
||||
<channel>
|
||||
<title>${options.blog_title!}</title>
|
||||
<atom:link href="${context!}/atom.xml" rel="self" type="application/rss+xml"/>
|
||||
<link>${context!}</link>
|
||||
<description>${user.description!}</description>
|
||||
<language>zh-CN</language>
|
||||
<sy:updatePeriod>hourly</sy:updatePeriod>
|
||||
<sy:updateFrequency>1</sy:updateFrequency>
|
||||
<generator>https://halo.run</generator>
|
||||
</channel>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title type="text">${blog_title!}</title>
|
||||
<#if user.description??>
|
||||
<subtitle type="text">${user.description!}</subtitle>
|
||||
</#if>
|
||||
<updated>${.now?iso_local}</updated>
|
||||
<id>${blog_url!}</id>
|
||||
<link rel="alternate" type="text/html" href="${blog_url!}" />
|
||||
<link rel="self" type="application/atom+xml" href="${atom_url!}" />
|
||||
<rights>Copyright © ${.now?string('yyyy')}, ${blog_title!}</rights>
|
||||
<generator uri="https://halo.run/" version="${version!}">Halo</generator>
|
||||
<#if posts?? && posts?size gt 0>
|
||||
<#list posts as post>
|
||||
<item>
|
||||
<entry>
|
||||
<title><![CDATA[${post.title!}]]></title>
|
||||
<link>${context!}/archives/${post.url!}</link>
|
||||
<comments>${context!}/archives/${post.url!}#comments</comments>
|
||||
<pubDate>${post.createTime!}</pubDate>
|
||||
<dc:creator><![CDATA[${user.nickname!}]]></dc:creator>
|
||||
|
||||
<#if post.categories?? && post.categories?size gt 0>
|
||||
<#list post.categories as category>
|
||||
<category><![CDATA[${category.name!}]]></category>
|
||||
</#list>
|
||||
</#if>
|
||||
<description>
|
||||
<![CDATA[
|
||||
${post.summary!}
|
||||
]]>
|
||||
</description>
|
||||
<content:encoded>
|
||||
<link rel="alternate" type="text/html" href="${post.fullPath!}" />
|
||||
<id>tag:${blog_url!},${post.createTime?string('yyyy-MM-dd')}:${post.url!}</id>
|
||||
<published>${post.createTime?iso_local}</published>
|
||||
<updated>${post.editTime?iso_local}</updated>
|
||||
<author>
|
||||
<name>${user.nickname!}</name>
|
||||
<uri>${blog_url!}</uri>
|
||||
</author>
|
||||
<content type="html" xml:base="${blog_url!}" xml:lang="en">
|
||||
<![CDATA[
|
||||
<#if (options.rss_content_type!'full') == 'full'>
|
||||
${post.formatContent!}
|
||||
|
@ -43,8 +30,8 @@
|
|||
${post.summary!}
|
||||
</#if>
|
||||
]]>
|
||||
</content:encoded>
|
||||
</item>
|
||||
</content>
|
||||
</entry>
|
||||
</#list>
|
||||
</#if>
|
||||
</rss>
|
||||
</feed>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div style="text-align:center">
|
||||
<img src="${user.avatar!}" width="100" height="100" alt="${user.nickname!}">
|
||||
<h3>${options.blog_title!}</h3>
|
||||
<h3>${blog_title!}</h3>
|
||||
<h4>
|
||||
<a href="${context!}" target="_blank">${context!}</a>
|
||||
<a href="${blog_url!}" target="_blank">${blog_url!}</a>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
|||
<#list archives as archive>
|
||||
## ${archive.year?c}
|
||||
<#list archive.posts?sort_by("createTime")?reverse as post>
|
||||
- <a href="${context!}/archives/${post.url!}" title="${post.title!}" target="_blank">${post.title!}</a>
|
||||
- <a href="${post.fullPath!}" title="${post.title!}" target="_blank">${post.title!}</a>
|
||||
</#list>
|
||||
</#list>
|
||||
</@postTag>
|
||||
|
@ -20,13 +20,13 @@
|
|||
## 分类目录
|
||||
<@categoryTag method="list">
|
||||
<#list categories as category>
|
||||
- <a href="${context!}/categories/${category.slugName!}" target="_blank">${category.name!}</a>
|
||||
- <a href="${category.fullPath!}" target="_blank">${category.name!}</a>
|
||||
</#list>
|
||||
</@categoryTag>
|
||||
|
||||
## 标签
|
||||
<@tagTag method="list">
|
||||
<#list tags as tag>
|
||||
- <a href="${context!}/tags/${tag.slugName!}" target="_blank">${tag.name!}</a>
|
||||
- <a href="${tag.fullPath!}" target="_blank">${tag.name!}</a>
|
||||
</#list>
|
||||
</@tagTag>
|
|
@ -3,6 +3,6 @@ User-agent: *
|
|||
Disallow: /
|
||||
<#else>
|
||||
User-agent: *
|
||||
Sitemap: ${context!}/sitemap.xml
|
||||
Sitemap: ${context!}/sitemap.html
|
||||
Sitemap: ${sitemap_xml_url!}
|
||||
Sitemap: ${sitemap_html_url!}
|
||||
</#if>
|
|
@ -1,12 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title>${options.blog_title!}</title>
|
||||
<link>${context!}</link>
|
||||
<title>${blog_title!}</title>
|
||||
<link>${blog_url!}</link>
|
||||
<#if user.description??>
|
||||
<description>${user.description!}</description>
|
||||
</#if>
|
||||
<language>zh-CN</language>
|
||||
<generator>Halo ${version!}</generator>
|
||||
<#if posts?? && posts?size gt 0>
|
||||
<#list posts as post>
|
||||
<item>
|
||||
|
@ -15,8 +16,8 @@
|
|||
${post.title!}
|
||||
]]>
|
||||
</title>
|
||||
<link>${options.blog_url}/archives/${post.url!}</link>
|
||||
<content:encoded>
|
||||
<link>${post.fullPath!}</link>
|
||||
<description>
|
||||
<![CDATA[
|
||||
<#if (options.rss_content_type!'full') == 'full'>
|
||||
${post.formatContent!}
|
||||
|
@ -24,8 +25,8 @@
|
|||
${post.summary!}
|
||||
</#if>
|
||||
]]>
|
||||
</content:encoded>
|
||||
<pubDate>${post.createTime}</pubDate>
|
||||
</description>
|
||||
<pubDate>${post.createTime?iso_local}</pubDate>
|
||||
</item>
|
||||
</#list>
|
||||
</#if>
|
||||
|
|
|
@ -7,7 +7,7 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>${options.blog_title!} 网站地图</title>
|
||||
<title>${blog_title!} 网站地图</title>
|
||||
<meta name="robots" content="index,follow"/>
|
||||
<style type="text/css">
|
||||
body {
|
||||
|
@ -119,8 +119,8 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center; margin-top: 20px">${options.blog_title!} 网站地图 </h2>
|
||||
<div id="nav"><a href="${context!}"><strong>${options.blog_title!}</strong></a> » <a href="${context!}/sitemap.html">站点地图</a></div>
|
||||
<h2 style="text-align: center; margin-top: 20px">${blog_title!} 网站地图 </h2>
|
||||
<div id="nav"><a href="${blog_url!}"><strong>${blog_title!}</strong></a> » <a href="${sitemap_html_url!}">站点地图</a></div>
|
||||
<div id="content">
|
||||
<h3>最新文章</h3>
|
||||
<ul id="contentTable">
|
||||
|
@ -132,8 +132,8 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
</li>
|
||||
<div class="clear"></div>
|
||||
<li>
|
||||
<div class="T1 pull-left"><a href="${context!}" title="${options.blog_title!}">${options.blog_title!}</a></div>
|
||||
<div class="T2 pull-right">${options.blog_start!}</div>
|
||||
<div class="T1 pull-left"><a href="${blog_url!}" title="${blog_title!}">${blog_title!}</a></div>
|
||||
<div class="T2 pull-right">${(options.birthday)?number_to_date?string("yyyy-MM-dd")} </div>
|
||||
<div class="T3 pull-right">daily</div>
|
||||
<div class="T4 pull-right">1</div>
|
||||
</li>
|
||||
|
@ -141,7 +141,7 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
<#if posts?? && posts?size gt 0>
|
||||
<#list posts as post>
|
||||
<li>
|
||||
<div class="T1 pull-left"><a href="${context!}/archives/${post.url!}" title="${post.title!}">${post.title!} | ${options.blog_title!}</a></div>
|
||||
<div class="T1 pull-left"><a href="${post.fullPath!}" title="${post.title!}">${post.title!} | ${blog_title!}</a></div>
|
||||
<div class="T2 pull-right">${post.createTime?string('yyyy-MM-dd')}</div>
|
||||
<div class="T3 pull-right">daily</div>
|
||||
<div class="T4 pull-right">0.6</div>
|
||||
|
@ -156,10 +156,10 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
<ul id="contentTable">
|
||||
<@categoryTag method="list">
|
||||
<#if categories?? && categories?size gt 0>
|
||||
<#list categories as cate>
|
||||
<#list categories as category>
|
||||
<li>
|
||||
<div class="T1 pull-left"><a href="${options.blog_url}/categories/${cate.slugName!}" title="${cate.name}">${cate.name} | ${options.blog_title!}</a></div>
|
||||
<div class="T2 pull-right">${cate.createTime?string('yyyy-MM-dd')}</div>
|
||||
<div class="T1 pull-left"><a href="${category.fullPath!}" title="${category.name}">${category.name} | ${blog_title!}</a></div>
|
||||
<div class="T2 pull-right">${category.createTime?string('yyyy-MM-dd')}</div>
|
||||
<div class="T3 pull-right">daily</div>
|
||||
<div class="T4 pull-right">0.6</div>
|
||||
</li>
|
||||
|
@ -176,7 +176,7 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
<#if tags?? && tags?size gt 0>
|
||||
<#list tags as tag>
|
||||
<li>
|
||||
<div class="T1 pull-left"><a href="${options.blog_url}/tags/${tag.slugName!}" title="${tag.name}">${tag.name} | ${options.blog_title!}</a></div>
|
||||
<div class="T1 pull-left"><a href="${tag.fullPath!}" title="${tag.name}">${tag.name} | ${blog_title!}</a></div>
|
||||
<div class="T2 pull-right">${tag.createTime?string('yyyy-MM-dd')}</div>
|
||||
<div class="T3 pull-right">daily</div>
|
||||
<div class="T4 pull-right">0.6</div>
|
||||
|
@ -188,7 +188,7 @@ see https://gitee.com/yadong.zhang/DBlog/blob/master/blog-web/src/main/java/com/
|
|||
</ul>
|
||||
</div>
|
||||
<div id="footer">
|
||||
该文件由 <a href="${context!}" title="${options.blog_title!}">${options.blog_title!}</a> 网站自动生成。
|
||||
该文件由 <a href="${blog_url!}" title="${blog_title!}">${blog_title!}</a> 网站自动生成。
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<#if posts?? && posts?size gt 0>
|
||||
<#list posts as post>
|
||||
<url>
|
||||
<loc>${context!}/archives/${post.url!}</loc>
|
||||
<loc>${post.fullPath!}</loc>
|
||||
<lastmod>${post.createTime?iso_local}</lastmod>
|
||||
</url>
|
||||
</#list>
|
||||
|
|
Loading…
Reference in New Issue