gravatarHashBucket = redisson.getBucket(getGravatarKey(EMAIL_HASH_PREFIX + email));
diff --git a/src/main/java/me/qwq/doghouse/config/DoghouseConfig.java b/src/main/java/me/qwq/doghouse/config/DoghouseConfig.java
index 6752ac1..230b88f 100644
--- a/src/main/java/me/qwq/doghouse/config/DoghouseConfig.java
+++ b/src/main/java/me/qwq/doghouse/config/DoghouseConfig.java
@@ -3,6 +3,7 @@ package me.qwq.doghouse.config;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@@ -21,11 +22,13 @@ import me.qwq.doghouse.service.ConfigService;
/**
* Doghouse 配置项
+ *
+ * 指定 RedisCacheManager 序列化器后需要重新指定启用 CacheProperties 的自动装配
* @author Doghole
*
*/
@Configuration
-@EnableConfigurationProperties(DoghouseProperties.class)
+@EnableConfigurationProperties({DoghouseProperties.class, CacheProperties.class})
@Import(ConfigAutoRegistrar.class)
public class DoghouseConfig implements WebMvcConfigurer {
@@ -90,4 +93,5 @@ public class DoghouseConfig implements WebMvcConfigurer {
resolver.setCheckExistence(true); // 文件不存在就跳过,交给下一个 resolver
return resolver;
}
+
}
diff --git a/src/main/java/me/qwq/doghouse/controller/admin/AssetController.java b/src/main/java/me/qwq/doghouse/controller/admin/AssetController.java
index 1c9c020..60dc615 100644
--- a/src/main/java/me/qwq/doghouse/controller/admin/AssetController.java
+++ b/src/main/java/me/qwq/doghouse/controller/admin/AssetController.java
@@ -1,6 +1,5 @@
package me.qwq.doghouse.controller.admin;
-import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
@@ -18,6 +17,8 @@ import me.qwq.doghouse.pojo.dto.LayPageReq;
import me.qwq.doghouse.pojo.dto.LayPageResp;
import me.qwq.doghouse.pojo.dto.R;
import me.qwq.doghouse.service.AssetService;
+import me.qwq.doghouse.util.DateUtils;
+
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
diff --git a/src/main/java/me/qwq/doghouse/controller/admin/post/AbstractAdminPostController.java b/src/main/java/me/qwq/doghouse/controller/admin/post/AbstractAdminPostController.java
index 5bb8724..bf72e45 100644
--- a/src/main/java/me/qwq/doghouse/controller/admin/post/AbstractAdminPostController.java
+++ b/src/main/java/me/qwq/doghouse/controller/admin/post/AbstractAdminPostController.java
@@ -1,10 +1,11 @@
package me.qwq.doghouse.controller.admin.post;
-import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import jakarta.validation.Valid;
@@ -56,12 +57,18 @@ public abstract class AbstractAdminPostController,
@Autowired
AssetService assetService;
+
@Autowired
MetaService metaService;
+
@Autowired
RelationshipService relationshipService;
+
@Autowired
PostTypeComponent postTypeComponent;
+
+ @Autowired
+ ObjectMapper objectMapper;
C postTypeConfig;
@@ -136,9 +143,10 @@ public abstract class AbstractAdminPostController,
/**
* 编辑
+ * @throws JsonProcessingException
*/
@GetMapping("/edit")
- public String edit(@RequestParam(required = false) Long postId) {
+ public String edit(@RequestParam(required = false) Long postId) throws JsonProcessingException {
PostTypeEnum postType = getPostTypeConfig().getPostType();
@@ -148,7 +156,7 @@ public abstract class AbstractAdminPostController,
request.setAttribute("title", "编辑 - " + post.getPostTitle());
List assets = assetService.list(
new LambdaQueryWrapper().eq(Asset::getFromPostId, postId));
- request.setAttribute("assets", StringEscapeUtils.escapeEcmaScript(JSONObject.toJSONString(assets)));
+ request.setAttribute("assets", StringEscapeUtils.escapeEcmaScript(objectMapper.writeValueAsString(assets)));
}
else {
request.setAttribute("title", "新增" + postType.getNote());
diff --git a/src/main/java/me/qwq/doghouse/controller/api/v1/ApiControllerV1.java b/src/main/java/me/qwq/doghouse/controller/api/v1/ApiControllerV1.java
index 519de15..3fca152 100644
--- a/src/main/java/me/qwq/doghouse/controller/api/v1/ApiControllerV1.java
+++ b/src/main/java/me/qwq/doghouse/controller/api/v1/ApiControllerV1.java
@@ -20,14 +20,13 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import com.alibaba.fastjson2.JSONObject;
-
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import me.qwq.dogface.Dogface;
import me.qwq.doghouse.component.Rk;
import me.qwq.doghouse.exception.PageNotFoundException;
+import me.qwq.doghouse.pojo.dto.DailyPostCommentStats;
import me.qwq.doghouse.pojo.dto.R;
import me.qwq.doghouse.service.CommentService;
import me.qwq.doghouse.service.StatisticsService;
@@ -132,7 +131,7 @@ public class ApiControllerV1 {
}
@GetMapping(path="/getPassDaysStatistics", produces="application/json")
- public JSONObject getPassDaysStatistics(Integer passDays) {
+ public DailyPostCommentStats getPassDaysStatistics(Integer passDays) {
return statisticsService.getPostAndCommentCountsWithDates(passDays, null);
}
@@ -163,11 +162,11 @@ public class ApiControllerV1 {
svgRoot.setAttribute("viewBox", String.format("0 0 %d %d", w, h));
// 获取 n 日以来的文章和评论统计
- JSONObject jo = statisticsService.getPostAndCommentCountsWithDates(total, null);
+ DailyPostCommentStats s = statisticsService.getPostAndCommentCountsWithDates(total, null);
- List dates = jo.getList("dates", String.class);
- List postCounts = jo.getList("postCounts", Integer.class);
- List commentCounts = jo.getList("commentCounts", Integer.class);
+ List dates = s.dates();
+ List postCounts = s.postCounts();
+ List commentCounts = s.commentCounts();
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
diff --git a/src/main/java/me/qwq/doghouse/controller/api/v2/CommentApiControllerV2.java b/src/main/java/me/qwq/doghouse/controller/api/v2/CommentApiControllerV2.java
index 9c2f1a3..badb987 100644
--- a/src/main/java/me/qwq/doghouse/controller/api/v2/CommentApiControllerV2.java
+++ b/src/main/java/me/qwq/doghouse/controller/api/v2/CommentApiControllerV2.java
@@ -1,5 +1,8 @@
package me.qwq.doghouse.controller.api.v2;
+import java.util.HashMap;
+import java.util.Map;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -8,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
import me.qwq.dogface.Dogface;
import me.qwq.doghouse.controller.common.BaseController;
@@ -38,8 +41,8 @@ public class CommentApiControllerV2 extends BaseController {
Dogface dogface;
@PostMapping("/preview")
- public R> preview(@RequestBody JSONObject jo) {
- String markDown = MarkDownUtils.commentToHtml(jo.getString("content"));
+ public R> preview(@RequestBody JsonNode jo) {
+ String markDown = MarkDownUtils.commentToHtml(jo.get("content").asText());
return R.ok(markDown);
}
@@ -54,16 +57,16 @@ public class CommentApiControllerV2 extends BaseController {
throw RException.badRequest("非法请求");
}
- JSONObject jo = new JSONObject();
- jo.put("author", commentForEdit.getAuthor());
- jo.put("isMarkdown", commentForEdit.isMarkdown());
- jo.put("email", commentForEdit.getEmail());
- jo.put("url", commentForEdit.getUrl());
- jo.put("content", commentForEdit.getContent());
- jo.put("subscribeReply", commentForEdit.isSubscribeReply());
- jo.put("commentStatu", commentForEdit.getCommentStatus());
- jo.put("id", commentForEdit.getId());
+ Map dto = new HashMap<>();
+ dto.put("author", commentForEdit.getAuthor());
+ dto.put("isMarkdown", commentForEdit.isMarkdown());
+ dto.put("email", commentForEdit.getEmail());
+ dto.put("url", commentForEdit.getUrl());
+ dto.put("content", commentForEdit.getContent());
+ dto.put("subscribeReply", commentForEdit.isSubscribeReply());
+ dto.put("commentStatu", commentForEdit.getCommentStatus());
+ dto.put("id", commentForEdit.getId());
- return R.ok(jo);
+ return R.ok(dto);
}
}
diff --git a/src/main/java/me/qwq/doghouse/controller/blog/SitemapController.java b/src/main/java/me/qwq/doghouse/controller/blog/SitemapController.java
index 24d4dd5..0b89741 100644
--- a/src/main/java/me/qwq/doghouse/controller/blog/SitemapController.java
+++ b/src/main/java/me/qwq/doghouse/controller/blog/SitemapController.java
@@ -1,7 +1,6 @@
package me.qwq.doghouse.controller.blog;
-import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -18,6 +17,7 @@ import me.qwq.doghouse.interfaces.IPostTypeConfig;
import me.qwq.doghouse.pojo.dto.PageQuery;
import me.qwq.doghouse.service.*;
import me.qwq.doghouse.service.post.PostService;
+import me.qwq.doghouse.util.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
diff --git a/src/main/java/me/qwq/doghouse/controller/blog/post/WikiPaginationController.java b/src/main/java/me/qwq/doghouse/controller/blog/post/WikiPaginationController.java
index c9df5da..f44fe6a 100644
--- a/src/main/java/me/qwq/doghouse/controller/blog/post/WikiPaginationController.java
+++ b/src/main/java/me/qwq/doghouse/controller/blog/post/WikiPaginationController.java
@@ -1,7 +1,9 @@
package me.qwq.doghouse.controller.blog.post;
-import com.alibaba.fastjson2.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.entity.config.WikiConfig;
import me.qwq.doghouse.entity.Post;
@@ -9,6 +11,7 @@ import me.qwq.doghouse.pojo.bo.PostPassJar;
import me.qwq.doghouse.service.post.WikiService;
import me.qwq.doghouse.util.EscapeUnescapeUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -28,6 +31,9 @@ import java.util.List;
@RequestMapping("/wiki")
public class WikiPaginationController extends AbstractPaginationController {
+ @Autowired
+ ObjectMapper objectMapper;
+
/**
* 首页
*/
@@ -44,9 +50,10 @@ public class WikiPaginationController extends AbstractPaginationController listFrontWikis(Long postId) {
+ public List listFrontWikis(Long postId) throws JsonProcessingException {
List unfolded = WikiService.getUnfoldedWikis(request);
- String unfoldedStr = unfolded == null ? "[]" : JSON.toJSONString(unfolded);
+ String unfoldedStr = unfolded == null ? "[]" : objectMapper.writeValueAsString(unfolded);
unfoldedStr = EscapeUnescapeUtils.escape(unfoldedStr);
Cookie unfoldedCookie = new Cookie(WikiService.UNFOLDED_WIKIS, unfoldedStr);
unfoldedCookie.setPath("/");
diff --git a/src/main/java/me/qwq/doghouse/entity/Post.java b/src/main/java/me/qwq/doghouse/entity/Post.java
index 8e72222..a308e54 100644
--- a/src/main/java/me/qwq/doghouse/entity/Post.java
+++ b/src/main/java/me/qwq/doghouse/entity/Post.java
@@ -27,7 +27,6 @@ import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import me.qwq.doghouse.enums.PostStatusEnum;
import me.qwq.doghouse.enums.PostTypeEnum;
-import me.qwq.doghouse.interfaces.IAvatarUrl;
import me.qwq.doghouse.interfaces.IFriendlyName;
import me.qwq.doghouse.interfaces.IPostPassMess;
import me.qwq.doghouse.validator.FriendlyNameValid;
@@ -41,7 +40,7 @@ import me.qwq.doghouse.validator.FriendlyNameValid;
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@FriendlyNameValid
-public class Post extends Model implements Serializable, IPostPassMess, ITreeView, IAvatarUrl, IFriendlyName {
+public class Post extends Model implements Serializable, IPostPassMess, ITreeView, IFriendlyName {
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/me/qwq/doghouse/entity/config/MarkdownConfig.java b/src/main/java/me/qwq/doghouse/entity/config/MarkdownConfig.java
deleted file mode 100644
index 33d71fe..0000000
--- a/src/main/java/me/qwq/doghouse/entity/config/MarkdownConfig.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package me.qwq.doghouse.entity.config;
-
-import java.io.Serializable;
-
-import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-
-import jodd.io.FileUtil;
-import lombok.Data;
-import lombok.experimental.Accessors;
-import lombok.extern.slf4j.Slf4j;
-import me.qwq.doghouse.annotation.ConfigInfo;
-import me.qwq.doghouse.interfaces.IConfig;
-
-@SuppressWarnings("serial")
-@Data
-@Accessors(chain=true)
-@ConfigInfo(field="markdown", name="Markdown 设置", initDefault=true)
-@Slf4j
-public class MarkdownConfig implements Serializable, IConfig {
-
-
- private static final String DEFAULT_MERMAID_CONFIG = "";
-
- private String mermaidConfig = DEFAULT_MERMAID_CONFIG;
-
- public MarkdownConfig afterSaving() {
- if (StringUtils.isNotBlank(mermaidConfig)) {
- try {
- JSONObject jo = JSONObject.parse(mermaidConfig);
- FileUtil.writeString("./conf/mermaid/config.json", jo.toJSONString());
- } catch (Exception e) {
- log.warn("Save mermaid self-defined css failed", e);
- }
- }
- return this;
- }
-
-}
diff --git a/src/main/java/me/qwq/doghouse/pojo/dto/DailyPostCommentStats.java b/src/main/java/me/qwq/doghouse/pojo/dto/DailyPostCommentStats.java
new file mode 100644
index 0000000..fe4cc1c
--- /dev/null
+++ b/src/main/java/me/qwq/doghouse/pojo/dto/DailyPostCommentStats.java
@@ -0,0 +1,10 @@
+package me.qwq.doghouse.pojo.dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+public record DailyPostCommentStats(
+ List dates,
+ List postCounts,
+ List commentCounts
+) implements Serializable {}
\ No newline at end of file
diff --git a/src/main/java/me/qwq/doghouse/service/ConfigService.java b/src/main/java/me/qwq/doghouse/service/ConfigService.java
index e650ee3..a211757 100644
--- a/src/main/java/me/qwq/doghouse/service/ConfigService.java
+++ b/src/main/java/me/qwq/doghouse/service/ConfigService.java
@@ -7,7 +7,8 @@ import me.qwq.doghouse.entity.RawConfig;
import me.qwq.doghouse.interfaces.IConfig;
import me.qwq.doghouse.util.SpringContextHolder;
-import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
@@ -40,6 +41,9 @@ public class ConfigService extends BaseServiceImpl {
@Autowired
Reflections reflections;
+ @Autowired
+ private ObjectMapper objectMapper;
+
/**
* 从
* field
@@ -198,8 +202,15 @@ public class ConfigService extends BaseServiceImpl {
}
return null;
}
- T iConfig =
- JSONObject.parseObject(rawConfig.getConfigValue(), clazz);
+ T iConfig;
+ try {
+ iConfig = objectMapper.readValue(rawConfig.getConfigValue(), clazz);
+ }
+ catch (JsonProcessingException e) {
+ throw new IllegalStateException(
+ "Failed to deserialize config: " + info.field(), e
+ );
+ }
setCache(iConfig);
return iConfig;
}
@@ -222,7 +233,15 @@ public class ConfigService extends BaseServiceImpl {
else {
rawConfig.setUpdateTime(LocalDateTime.now());
}
- rawConfig.setConfigValue(JSONObject.toJSONString(iConfig));
+ try {
+ rawConfig.setConfigValue(
+ objectMapper.writeValueAsString(iConfig)
+ );
+ } catch (JsonProcessingException e) {
+ throw new IllegalStateException(
+ "Failed to serialize config: " + info.field(), e
+ );
+ }
iConfig.beforeSaving();
if (saveOrUpdate(rawConfig)) {
diff --git a/src/main/java/me/qwq/doghouse/service/StatisticsService.java b/src/main/java/me/qwq/doghouse/service/StatisticsService.java
index 93599b5..4b177e0 100644
--- a/src/main/java/me/qwq/doghouse/service/StatisticsService.java
+++ b/src/main/java/me/qwq/doghouse/service/StatisticsService.java
@@ -4,15 +4,13 @@ import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
-
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
-import com.alibaba.fastjson2.JSONObject;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.Getter;
@@ -25,6 +23,7 @@ import me.qwq.doghouse.entity.Post;
import me.qwq.doghouse.enums.CommentStatusEnum;
import me.qwq.doghouse.enums.PostStatusEnum;
import me.qwq.doghouse.enums.PostTypeEnum;
+import me.qwq.doghouse.pojo.dto.DailyPostCommentStats;
import me.qwq.doghouse.service.post.PostService;
@Service
@@ -86,15 +85,24 @@ public class StatisticsService {
*/
@CacheEvictionTask
@Cacheable(value=CacheConstants.Statistics.DAILY_POST_AND_COMMENT_COUNTS)
- public JSONObject getPostAndCommentCountsWithDates(Integer passDays, PostTypeEnum postType) {
- JSONObject jo = new JSONObject();
- Map map = mapper.getPostAndCommentCountsWithDates(passDays, postType);
- jo.put("dates", map.get("dates").split(","));
- jo.put("postCounts", Arrays.asList(map.get("postCounts").split(",")).stream()
- .map(s -> Integer.valueOf(s)).collect(Collectors.toList()));
- jo.put("commentCounts", Arrays.asList(map.get("commentCounts").split(",")).stream()
- .map(s -> Integer.valueOf(s)).collect(Collectors.toList()));
- return jo;
+ public DailyPostCommentStats getPostAndCommentCountsWithDates(Integer passDays, PostTypeEnum postType) {
+ Map map =
+ mapper.getPostAndCommentCountsWithDates(passDays, postType);
+
+ List dates =
+ Arrays.asList(map.get("dates").split(","));
+
+ List postCounts =
+ Arrays.stream(map.get("postCounts").split(","))
+ .map(Integer::valueOf)
+ .toList();
+
+ List commentCounts =
+ Arrays.stream(map.get("commentCounts").split(","))
+ .map(Integer::valueOf)
+ .toList();
+
+ return new DailyPostCommentStats(dates, postCounts, commentCounts);
}
public PostStatistic getPostStatistic(Post post) {
diff --git a/src/main/java/me/qwq/doghouse/service/ThemeService.java b/src/main/java/me/qwq/doghouse/service/ThemeService.java
index 9d12cc7..dbe9373 100644
--- a/src/main/java/me/qwq/doghouse/service/ThemeService.java
+++ b/src/main/java/me/qwq/doghouse/service/ThemeService.java
@@ -25,7 +25,8 @@ import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import org.springframework.util.function.ThrowingSupplier;
-import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.config.DoghouseProperties;
@@ -43,6 +44,8 @@ public class ThemeService {
private volatile List cachedThemes = Collections.emptyList();
private List internalThemes = new ArrayList<>();
+ @Autowired
+ private ObjectMapper objectMapper;
@Autowired
DoghouseProperties doghouseProperties;
@@ -294,7 +297,7 @@ public class ThemeService {
*/
private ThemeInfo getThemeInfo(Resource config) throws IOException {
String json = config.getContentAsString(StandardCharsets.UTF_8);
- ThemeInfo themeInfo = JSONObject.parseObject(json, ThemeInfo.class);
+ ThemeInfo themeInfo = objectMapper.readValue(json, ThemeInfo.class);
// uri: .../templates/blog/bleaching/config.json
// folderName: bleaching
@@ -331,7 +334,7 @@ public class ThemeService {
*/
private ThemeInfo getThemeInfo(Path configPath) throws IOException {
String json = Files.readString(configPath);
- ThemeInfo themeInfo = JSONObject.parseObject(json, ThemeInfo.class);
+ ThemeInfo themeInfo = objectMapper.readValue(json, ThemeInfo.class);
Path path = configPath.getParent();
themeInfo.setDirectory(path.toString());
diff --git a/src/main/java/me/qwq/doghouse/service/post/WikiService.java b/src/main/java/me/qwq/doghouse/service/post/WikiService.java
index 2cdf946..3aff424 100644
--- a/src/main/java/me/qwq/doghouse/service/post/WikiService.java
+++ b/src/main/java/me/qwq/doghouse/service/post/WikiService.java
@@ -13,10 +13,11 @@ import me.qwq.doghouse.pojo.dto.LayPageReq;
import me.qwq.doghouse.util.CookieUtils;
import me.qwq.doghouse.util.SessionUtils;
-import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.enums.DefaultFuncEnum;
@@ -669,8 +670,10 @@ public class WikiService extends AbstractPostService {
Cookie cookie = CookieUtils.getCookie(request, UNFOLDED_WIKIS);
if (cookie == null) new ArrayList<>();
try {
- JSONArray ja = JSONArray.parse(cookie.getValue());
- return ja.toJavaList(Long.class);
+ return new ObjectMapper().readValue(
+ cookie.getValue(),
+ new TypeReference>() {}
+ );
}
catch (Exception e) {
return null;
diff --git a/src/main/java/me/qwq/doghouse/util/DateUtils.java b/src/main/java/me/qwq/doghouse/util/DateUtils.java
new file mode 100644
index 0000000..6de8115
--- /dev/null
+++ b/src/main/java/me/qwq/doghouse/util/DateUtils.java
@@ -0,0 +1,37 @@
+package me.qwq.doghouse.util;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public final class DateUtils {
+
+ // 缓存 formatter,行为接近 fastjson2
+ private static final Map FORMATTER_CACHE =
+ new ConcurrentHashMap<>();
+
+ private DateUtils() {
+ }
+
+ /**
+ * 格式化 LocalDateTime
+ *
+ * @param dateTime LocalDateTime
+ * @param pattern 日期格式,如 yyyy-MM-dd HH:mm:ss
+ * @return 格式化后的字符串
+ */
+ public static String format(LocalDateTime dateTime, String pattern) {
+ if (dateTime == null) {
+ return null;
+ }
+ if (pattern == null || pattern.isEmpty()) {
+ throw new IllegalArgumentException("pattern must not be null or empty");
+ }
+
+ DateTimeFormatter formatter =
+ FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
+
+ return dateTime.format(formatter);
+ }
+}
diff --git a/src/main/java/me/qwq/doghouse/util/ImageBase64Utils.java b/src/main/java/me/qwq/doghouse/util/ImageBase64Utils.java
deleted file mode 100644
index 6c70f35..0000000
--- a/src/main/java/me/qwq/doghouse/util/ImageBase64Utils.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package me.qwq.doghouse.util;
-import java.io.*;
-import java.nio.file.*;
-import java.util.Base64;
-
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.util.StreamUtils;
-
-public class ImageBase64Utils {
-
- /**
- * 从文件系统路径读取图片并转 base64
- */
- public static String fromFileSystem(Path imagePath) throws IOException {
- if (imagePath == null || !Files.exists(imagePath)) {
- return null;
- }
-
- byte[] bytes = Files.readAllBytes(imagePath);
- String mimeType = Files.probeContentType(imagePath);
-
- return toDataUrl(bytes, mimeType);
- }
-
- /**
- * 从 classpath 读取图片并转 base64(支持 jar 内)
- */
- public static String fromClasspath(String classpathLocation) throws IOException {
- ClassPathResource resource = new ClassPathResource(classpathLocation);
- if (!resource.exists()) {
- return null;
- }
-
- byte[] bytes;
- try (InputStream is = resource.getInputStream()) {
- bytes = StreamUtils.copyToByteArray(is);
- }
-
- String mimeType = guessMimeType(classpathLocation);
- return toDataUrl(bytes, mimeType);
- }
-
- /**
- * 生成 data:image/...;base64,...
- */
- private static String toDataUrl(byte[] bytes, String mimeType) {
- if (bytes == null || bytes.length == 0) {
- return null;
- }
-
- if (mimeType == null) {
- mimeType = "image/png"; // 兜底
- }
-
- String base64 = Base64.getEncoder().encodeToString(bytes);
- return "data:" + mimeType + ";base64," + base64;
- }
-
- /**
- * 根据文件名猜测 MIME
- */
- private static String guessMimeType(String filename) {
- String lower = filename.toLowerCase();
- if (lower.endsWith(".png")) return "image/png";
- if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
- if (lower.endsWith(".gif")) return "image/gif";
- if (lower.endsWith(".webp")) return "image/webp";
- return "image/png";
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/qwq/doghouse/util/JsonUtils.java b/src/main/java/me/qwq/doghouse/util/JsonUtils.java
new file mode 100644
index 0000000..ee6f649
--- /dev/null
+++ b/src/main/java/me/qwq/doghouse/util/JsonUtils.java
@@ -0,0 +1,18 @@
+package me.qwq.doghouse.util;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import me.qwq.doghouse.annotation.StaticAttribute;
+
+@StaticAttribute
+public final class JsonUtils {
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ public static String toJson(Object o) {
+ try {
+ return MAPPER.writeValueAsString(o);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/admin/tag/index.html b/src/main/resources/templates/admin/tag/index.html
index fbadefb..4f11cc6 100644
--- a/src/main/resources/templates/admin/tag/index.html
+++ b/src/main/resources/templates/admin/tag/index.html
@@ -80,7 +80,7 @@