diff --git a/novel-admin/pom.xml b/novel-admin/pom.xml index 6d44b43..bef14df 100644 --- a/novel-admin/pom.xml +++ b/novel-admin/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel-admin - 5.2.3 + 5.2.6 jar novel-admin diff --git a/novel-admin/src/main/build/scripts/novel-admin.bat b/novel-admin/src/main/build/scripts/novel-admin.bat new file mode 100644 index 0000000..9ebcf5c --- /dev/null +++ b/novel-admin/src/main/build/scripts/novel-admin.bat @@ -0,0 +1,4 @@ +@echo off +cd /d "%~dp0.." +java -jar -Dspring.profiles.active=prod novel-admin.jar +pause \ No newline at end of file diff --git a/novel-admin/src/main/build/scripts/novel-admin.sh b/novel-admin/src/main/build/scripts/novel-admin.sh index 354f43f..2956619 100644 --- a/novel-admin/src/main/build/scripts/novel-admin.sh +++ b/novel-admin/src/main/build/scripts/novel-admin.sh @@ -5,9 +5,12 @@ JAR_NAME=$APP_NAME\.jar PID=$APP_NAME\.pid -#使用说明,用来提示输入参数 +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +cd "$SCRIPT_DIR"/.. || exit 1 + +# 使用说明 usage() { - echo "Usage: ./novel-admin.sh [start|stop|restart|status]" + echo "Usage: $0 [start|stop|restart|status]" exit 1 } diff --git a/novel-admin/src/main/java/com/java2nb/common/config/CacheKey.java b/novel-admin/src/main/java/com/java2nb/common/config/CacheKey.java index af20c35..f41eb41 100644 --- a/novel-admin/src/main/java/com/java2nb/common/config/CacheKey.java +++ b/novel-admin/src/main/java/com/java2nb/common/config/CacheKey.java @@ -8,7 +8,7 @@ public interface CacheKey { /** * 首页小说设置 */ - String INDEX_BOOK_SETTINGS_KEY = "indexBookSettingsKey"; + String INDEX_BOOK_SETTINGS_KEY = "indexBookSettingsKey:v2"; /** * 首页新闻 diff --git a/novel-admin/src/main/java/com/java2nb/novel/controller/FriendLinkController.java b/novel-admin/src/main/java/com/java2nb/novel/controller/FriendLinkController.java index dd86893..0847fc4 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/controller/FriendLinkController.java +++ b/novel-admin/src/main/java/com/java2nb/novel/controller/FriendLinkController.java @@ -9,7 +9,7 @@ import com.java2nb.novel.service.FriendLinkService; import io.swagger.annotations.ApiOperation; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.annotation.Validated; @@ -31,7 +31,7 @@ public class FriendLinkController { @Autowired private FriendLinkService friendLinkService; @Autowired - private RedisTemplate redisTemplate; + private StringRedisTemplate redisTemplate; @GetMapping() @RequiresPermissions("novel:friendLink:friendLink") diff --git a/novel-admin/src/main/java/com/java2nb/novel/controller/NewsController.java b/novel-admin/src/main/java/com/java2nb/novel/controller/NewsController.java index 04231b3..c1a78d4 100644 --- a/novel-admin/src/main/java/com/java2nb/novel/controller/NewsController.java +++ b/novel-admin/src/main/java/com/java2nb/novel/controller/NewsController.java @@ -9,7 +9,7 @@ import com.java2nb.novel.service.NewsService; import io.swagger.annotations.ApiOperation; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; @@ -32,7 +32,7 @@ public class NewsController { @Autowired private NewsService newsService; @Autowired - private RedisTemplate redisTemplate; + private StringRedisTemplate redisTemplate; @GetMapping() @RequiresPermissions("novel:news:news") diff --git a/novel-common/pom.xml b/novel-common/pom.xml index 17f1858..98c2c8c 100644 --- a/novel-common/pom.xml +++ b/novel-common/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.2.3 + 5.2.6 4.0.0 diff --git a/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheKey.java b/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheKey.java index d1b5811..457b50d 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheKey.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheKey.java @@ -8,7 +8,7 @@ public interface CacheKey { /** * 首页小说设置 * */ - String INDEX_BOOK_SETTINGS_KEY = "indexBookSettingsKey"; + String INDEX_BOOK_SETTINGS_KEY = "indexBookSettingsKey:v2"; /** * 首页新闻 diff --git a/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheService.java b/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheService.java index 05d7423..480fee0 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheService.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/cache/CacheService.java @@ -1,55 +1,61 @@ package com.java2nb.novel.core.cache; +import com.fasterxml.jackson.core.JsonProcessingException; + +import java.util.List; + /** * @author 11797 */ public interface CacheService { - /** - * 根据key获取缓存的String类型数据 - */ - String get(String key); + /** + * 根据key获取缓存的String类型数据 + */ + String get(String key); - /** - * 设置String类型的缓存 - */ - void set(String key, String value); + /** + * 设置String类型的缓存 + */ + void set(String key, String value); - /** - * 设置一个有过期时间的String类型的缓存,单位秒 - */ - void set(String key, String value, long timeout); - - /** - * 根据key获取缓存的Object类型数据 - */ - Object getObject(String key); - - /** - * 设置Object类型的缓存 - */ - void setObject(String key, Object value); - - /** - * 设置一个有过期时间的Object类型的缓存,单位秒 - */ + /** + * 设置一个有过期时间的String类型的缓存,单位秒 + */ + void set(String key, String value, long timeout); + + /** + * 根据key获取缓存的Object类型数据 + */ + T getObject(String key, Class clazz); + + List getList(String key, Class clazz); + + /** + * 设置Object类型的缓存 + */ + void setObject(String key, Object value); + + /** + * 设置一个有过期时间的Object类型的缓存,单位秒 + */ void setObject(String key, Object value, long timeout); - /** - * 根据key删除缓存的数据 - */ - void del(String key); + /** + * 根据key删除缓存的数据 + */ + void del(String key); - - /** - * 判断是否存在一个key - * */ - boolean contains(String key); - - /** - * 设置key过期时间 - * */ - void expire(String key, long timeout); + + /** + * 判断是否存在一个key + */ + boolean contains(String key); + + /** + * 设置key过期时间 + */ + void expire(String key, long timeout); } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/cache/impl/RedisServiceImpl.java b/novel-common/src/main/java/com/java2nb/novel/core/cache/impl/RedisServiceImpl.java index aad1a04..ad16d29 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/cache/impl/RedisServiceImpl.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/cache/impl/RedisServiceImpl.java @@ -1,23 +1,35 @@ package com.java2nb.novel.core.cache.impl; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.java2nb.novel.core.cache.CacheService; +import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import java.util.List; import java.util.concurrent.TimeUnit; /** * @author xxy */ +@Slf4j @RequiredArgsConstructor @Service public class RedisServiceImpl implements CacheService { private final StringRedisTemplate stringRedisTemplate; - private final RedisTemplate redisTemplate; + private ObjectMapper objectMapper; + + @PostConstruct + public void init() { + objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } @Override @@ -37,34 +49,66 @@ public class RedisServiceImpl implements CacheService { } @Override - public Object getObject(String key) { - return redisTemplate.opsForValue().get(key); + public T getObject(String key, Class clazz) { + String result = get(key); + if (result != null) { + try { + return objectMapper.readValue(result, clazz); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + return null; + } + + @Override + public List getList(String key, Class clazz) { + String result = get(key); + if (result != null) { + try { + return objectMapper.readValue(result, + objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + return null; } @Override public void setObject(String key, Object value) { - redisTemplate.opsForValue().set(key, value); + if (value != null) { + try { + set(key, objectMapper.writeValueAsString(value)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } } @Override public void setObject(String key, Object value, long timeout) { - redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); + if (value != null) { + try { + set(key, objectMapper.writeValueAsString(value), timeout); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } } @Override public void del(String key) { - redisTemplate.delete(key); stringRedisTemplate.delete(key); } @Override public boolean contains(String key) { - return redisTemplate.hasKey(key) || stringRedisTemplate.hasKey(key); + return stringRedisTemplate.hasKey(key); } @Override public void expire(String key, long timeout) { - redisTemplate.expire(key, timeout, TimeUnit.SECONDS); stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS); } diff --git a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java index b7de405..e0df42e 100644 --- a/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java +++ b/novel-common/src/main/java/com/java2nb/novel/core/utils/RestTemplates.java @@ -63,6 +63,8 @@ public class RestTemplates { connectionManager.setDefaultMaxPerRoute(300); HttpClientBuilder clientBuilder = HttpClients.custom(); + // 禁用 Cookie 管理 + clientBuilder.disableCookieManagement(); if (Objects.nonNull(httpProxyProperties) && Boolean.TRUE.equals(httpProxyProperties.getEnabled())) { HttpHost proxy = new HttpHost(httpProxyProperties.getIp(), httpProxyProperties.getPort()); clientBuilder.setProxy(proxy); diff --git a/novel-common/src/main/resources/application-common-dev.yml b/novel-common/src/main/resources/application-common-dev.yml index 003144c..7743f29 100644 --- a/novel-common/src/main/resources/application-common-dev.yml +++ b/novel-common/src/main/resources/application-common-dev.yml @@ -25,10 +25,10 @@ http: # 是否开启 HTTP 代理,true-开启,false-不开启 enabled: false # 代理 IP - ip: us.swiftproxy.net + ip: proxy.bestproxy.com # 代理端口号 - port: 7878 + port: 2312 # 代理用户名 - username: swiftproxy_u + username: bestproxy_u # 代理密码 - password: swiftproxy_p \ No newline at end of file + password: bestproxy_p \ No newline at end of file diff --git a/novel-crawl/pom.xml b/novel-crawl/pom.xml index 7a77d01..3cfe319 100644 --- a/novel-crawl/pom.xml +++ b/novel-crawl/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.2.3 + 5.2.6 4.0.0 diff --git a/novel-crawl/src/main/build/config/application.yml b/novel-crawl/src/main/build/config/application.yml index 370d2b4..6faca6a 100644 --- a/novel-crawl/src/main/build/config/application.yml +++ b/novel-crawl/src/main/build/config/application.yml @@ -38,10 +38,10 @@ http: # 是否开启 HTTP 代理,true-开启,false-不开启 enabled: false # 代理 IP - ip: us.swiftproxy.net + ip: proxy.bestproxy.com # 代理端口号 - port: 7878 + port: 2312 # 代理用户名 - username: swiftproxy_u + username: bestproxy_u # 代理密码 - password: swiftproxy_p \ No newline at end of file + password: bestproxy_p \ No newline at end of file diff --git a/novel-crawl/src/main/build/scripts/novel-crawl.bat b/novel-crawl/src/main/build/scripts/novel-crawl.bat new file mode 100644 index 0000000..c0d7873 --- /dev/null +++ b/novel-crawl/src/main/build/scripts/novel-crawl.bat @@ -0,0 +1,4 @@ +@echo off +cd /d "%~dp0.." +java -jar -Dspring.profiles.active=prod novel-crawl.jar +pause \ No newline at end of file diff --git a/novel-crawl/src/main/build/scripts/novel-crawl.sh b/novel-crawl/src/main/build/scripts/novel-crawl.sh index 1e7f148..a958ac4 100644 --- a/novel-crawl/src/main/build/scripts/novel-crawl.sh +++ b/novel-crawl/src/main/build/scripts/novel-crawl.sh @@ -5,9 +5,12 @@ JAR_NAME=$APP_NAME\.jar PID=$APP_NAME\.pid -#使用说明,用来提示输入参数 +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +cd "$SCRIPT_DIR"/.. || exit 1 + +# 使用说明 usage() { - echo "Usage: ./novel-crawl.sh [start|stop|restart|status]" + echo "Usage: $0 [start|stop|restart|status]" exit 1 } diff --git a/novel-crawl/src/main/java/com/java2nb/novel/controller/CrawlController.java b/novel-crawl/src/main/java/com/java2nb/novel/controller/CrawlController.java index 84f8de0..fefffec 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/controller/CrawlController.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/controller/CrawlController.java @@ -72,17 +72,15 @@ public class CrawlController { if(url.startsWith("https://")||url.startsWith("http://")){ String refreshCache="1"; if(!refreshCache.equals(isRefresh)) { - Object cache = cacheService.getObject(CacheKey.BOOK_TEST_PARSE + url); - if (cache == null) { + html = cacheService.get(CacheKey.BOOK_TEST_PARSE + url); + if (html == null) { isRefresh="1"; - }else { - html = (String) cache; } } if(refreshCache.equals(isRefresh)){ html = HttpUtil.getByHttpClientWithChrome(url); if (html != null) { - cacheService.setObject(CacheKey.BOOK_TEST_PARSE + url, html, 60 * 10); + cacheService.set(CacheKey.BOOK_TEST_PARSE + url, html, 60 * 10); }else{ resultMap.put("msg","html is null"); return RestResult.ok(resultMap); diff --git a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java index 1cb6aaf..1a7971c 100644 --- a/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java +++ b/novel-crawl/src/main/java/com/java2nb/novel/core/crawl/CrawlParser.java @@ -12,7 +12,6 @@ import io.github.xxyopen.util.IdWorker; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 92e860f..ed29188 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -5,7 +5,7 @@ novel com.java2nb - 5.2.3 + 5.2.6 4.0.0 @@ -96,6 +96,16 @@ + + + + + + + + + + diff --git a/novel-front/src/main/build/config/application.yml b/novel-front/src/main/build/config/application.yml index f268f5f..792c565 100644 --- a/novel-front/src/main/build/config/application.yml +++ b/novel-front/src/main/build/config/application.yml @@ -41,13 +41,13 @@ http: # 是否开启 HTTP 代理,true-开启,false-不开启 enabled: false # 代理 IP - ip: us.swiftproxy.net + ip: proxy.bestproxy.com # 代理端口号 - port: 7878 + port: 2312 # 代理用户名 - username: swiftproxy_u + username: bestproxy_u # 代理密码 - password: swiftproxy_p + password: bestproxy_p --- #--------------------- Spring AI 配置---------------------- diff --git a/novel-front/src/main/build/scripts/novel-front.bat b/novel-front/src/main/build/scripts/novel-front.bat new file mode 100644 index 0000000..0589f30 --- /dev/null +++ b/novel-front/src/main/build/scripts/novel-front.bat @@ -0,0 +1,4 @@ +@echo off +cd /d "%~dp0.." +java -jar -Dspring.profiles.active=prod novel-front.jar +pause \ No newline at end of file diff --git a/novel-front/src/main/build/scripts/novel-front.sh b/novel-front/src/main/build/scripts/novel-front.sh index c663072..f4eb4c7 100644 --- a/novel-front/src/main/build/scripts/novel-front.sh +++ b/novel-front/src/main/build/scripts/novel-front.sh @@ -4,10 +4,12 @@ JAR_NAME=$APP_NAME\.jar #PID 代表是PID文件 PID=$APP_NAME\.pid +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +cd "$SCRIPT_DIR"/.. || exit 1 -#使用说明,用来提示输入参数 +# 使用说明 usage() { - echo "Usage: ./novel-front.sh [start|stop|restart|status]" + echo "Usage: $0 [start|stop|restart|status]" exit 1 } diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java b/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java index 510deee..eacaca6 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/AuthorController.java @@ -110,20 +110,6 @@ public class AuthorController extends BaseController { return RestResult.ok(); } - /** - * 更新章节名 - */ - @PostMapping("updateIndexName") - public RestResult updateIndexName(Long indexId, String indexName, HttpServletRequest request) { - - Author author = checkAuthor(request); - - //更新章节名 - bookService.updateIndexName(indexId, indexName, author.getId()); - - return RestResult.ok(); - } - /** * 发布章节内容 diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java index 3d86237..d10d2a7 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java @@ -43,7 +43,7 @@ public class BookController extends BaseController { * 查询首页小说设置列表数据 */ @GetMapping("listBookSetting") - public RestResult>> listBookSetting() { + public RestResult>> listBookSetting() { return RestResult.ok(bookService.listBookSettingVO()); } diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java b/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java index 11b9e14..26584c0 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java @@ -82,7 +82,7 @@ public class PageController extends BaseController { @RequestMapping(path = {"/", "/index", "/index.html"}) public String index(Model model) { //加载小说首页小说基本信息线程 - CompletableFuture>> bookCompletableFuture = CompletableFuture.supplyAsync( + CompletableFuture>> bookCompletableFuture = CompletableFuture.supplyAsync( bookService::listBookSettingVO, threadPoolExecutor); //加载首页新闻线程 CompletableFuture> newsCompletableFuture = CompletableFuture.supplyAsync(newsService::listIndexNews, diff --git a/novel-front/src/main/java/com/java2nb/novel/service/BookService.java b/novel-front/src/main/java/com/java2nb/novel/service/BookService.java index 900ebca..b150092 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/BookService.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/BookService.java @@ -16,9 +16,10 @@ public interface BookService { /** * 查询首页小说设置列表数据 + * * @return - * */ - Map> listBookSettingVO(); + */ + Map> listBookSettingVO(); /** * 查询首页点击榜单数据 diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java index a322497..ab917e4 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java @@ -1,6 +1,5 @@ package com.java2nb.novel.service.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheService; @@ -25,7 +24,6 @@ import io.github.xxyopen.web.util.BeanUtil; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.DateUtils; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.render.RenderingStrategies; @@ -48,7 +46,6 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Collectors; import static com.java2nb.novel.mapper.BookCategoryDynamicSqlSupport.bookCategory; -import static com.java2nb.novel.mapper.BookCategoryDynamicSqlSupport.sort; import static com.java2nb.novel.mapper.BookCommentDynamicSqlSupport.bookComment; import static com.java2nb.novel.mapper.BookContentDynamicSqlSupport.bookContent; import static com.java2nb.novel.mapper.BookContentDynamicSqlSupport.content; @@ -108,19 +105,19 @@ public class BookServiceImpl implements BookService { @SneakyThrows @Override - public Map> listBookSettingVO() { - String result = cacheService.get(CacheKey.INDEX_BOOK_SETTINGS_KEY); - if (result == null || result.length() < Constants.OBJECT_JSON_CACHE_EXIST_LENGTH) { - List list = bookSettingMapper.listVO(); - if (list.size() == 0) { + public Map> listBookSettingVO() { + List list = cacheService.getList(CacheKey.INDEX_BOOK_SETTINGS_KEY, BookSettingVO.class); + if (list == null || list.isEmpty()) { + list = bookSettingMapper.listVO(); + if (list.isEmpty()) { //如果首页小说没有被设置,则初始化首页小说设置 list = initIndexBookSetting(); } - result = new ObjectMapper().writeValueAsString( - list.stream().collect(Collectors.groupingBy(BookSettingVO::getType))); - cacheService.set(CacheKey.INDEX_BOOK_SETTINGS_KEY, result, 3600 * 24); + cacheService.setObject(CacheKey.INDEX_BOOK_SETTINGS_KEY, list, 3600 * 24); } - return new ObjectMapper().readValue(result, Map.class); + return list.stream().collect( + Collectors.groupingBy(book -> book.getType().toString()) + ); } @@ -170,11 +167,10 @@ public class BookServiceImpl implements BookService { return new ArrayList<>(0); } - @Override public List listClickRank() { - List result = (List) cacheService.getObject(CacheKey.INDEX_CLICK_BANK_BOOK_KEY); - if (result == null || result.size() == 0) { + List result = cacheService.getList(CacheKey.INDEX_CLICK_BANK_BOOK_KEY, Book.class); + if (result == null || result.isEmpty()) { result = listRank((byte) 0, 10); cacheService.setObject(CacheKey.INDEX_CLICK_BANK_BOOK_KEY, result, 5000); } @@ -183,8 +179,8 @@ public class BookServiceImpl implements BookService { @Override public List listNewRank() { - List result = (List) cacheService.getObject(CacheKey.INDEX_NEW_BOOK_KEY); - if (result == null || result.size() == 0) { + List result = cacheService.getList(CacheKey.INDEX_NEW_BOOK_KEY, Book.class); + if (result == null || result.isEmpty()) { result = listRank((byte) 1, 10); cacheService.setObject(CacheKey.INDEX_NEW_BOOK_KEY, result, 3600); } @@ -193,8 +189,8 @@ public class BookServiceImpl implements BookService { @Override public List listUpdateRank() { - List result = (List) cacheService.getObject(CacheKey.INDEX_UPDATE_BOOK_KEY); - if (result == null || result.size() == 0) { + List result = cacheService.getList(CacheKey.INDEX_UPDATE_BOOK_KEY, BookVO.class); + if (result == null || result.isEmpty()) { List bookPOList = listRank((byte) 2, 23); result = BeanUtil.copyList(bookPOList, BookVO.class); cacheService.setObject(CacheKey.INDEX_UPDATE_BOOK_KEY, result, 60 * 10); diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/FriendLinkServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/FriendLinkServiceImpl.java index cea174d..55ff591 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/FriendLinkServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/FriendLinkServiceImpl.java @@ -1,6 +1,5 @@ package com.java2nb.novel.service.impl; -import io.github.xxyopen.web.util.BeanUtil; import com.java2nb.novel.service.FriendLinkService; import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheService; @@ -31,16 +30,16 @@ public class FriendLinkServiceImpl implements FriendLinkService { @Override public List listIndexLink() { - List result = (List) cacheService.getObject(CacheKey.INDEX_LINK_KEY); - if(result == null || result.size() == 0) { - SelectStatementProvider selectStatement = select(linkName,linkUrl) - .from(friendLink) - .where(isOpen,isEqualTo((byte)1)) - .orderBy(sort) - .build() - .render(RenderingStrategies.MYBATIS3); - result = friendLinkMapper.selectMany(selectStatement); - cacheService.setObject(CacheKey.INDEX_LINK_KEY,result,60 * 60 * 24); + List result = cacheService.getList(CacheKey.INDEX_LINK_KEY, FriendLink.class); + if (result == null || result.isEmpty()) { + SelectStatementProvider selectStatement = select(linkName, linkUrl) + .from(friendLink) + .where(isOpen, isEqualTo((byte) 1)) + .orderBy(sort) + .build() + .render(RenderingStrategies.MYBATIS3); + result = friendLinkMapper.selectMany(selectStatement); + cacheService.setObject(CacheKey.INDEX_LINK_KEY, result, 60 * 60 * 24); } return result; } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/LikeServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/LikeServiceImpl.java index 23498d6..94ecf18 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/LikeServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/LikeServiceImpl.java @@ -4,7 +4,7 @@ import com.java2nb.novel.service.LikeService; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.scripting.support.StaticScriptSource; import org.springframework.stereotype.Service; @@ -20,7 +20,7 @@ import java.util.Collections; @Slf4j public class LikeServiceImpl implements LikeService { - private final RedisTemplate redisTemplate; + private final StringRedisTemplate redisTemplate; private DefaultRedisScript toggleLikeScript; @@ -33,19 +33,19 @@ public class LikeServiceImpl implements LikeService { public void init() { // Lua 脚本保证原子性操作 String script = """ - local key = KEYS[1] - local userId = ARGV[1] - - local isLiked = redis.call('SISMEMBER', key, userId) - - if isLiked == 1 then - redis.call('SREM', key, userId) - else - redis.call('SADD', key, userId) - end - - return redis.call('SCARD', key) - """; + local key = KEYS[1] + local userId = ARGV[1] + + local isLiked = redis.call('SISMEMBER', key, userId) + + if isLiked == 1 then + redis.call('SREM', key, userId) + else + redis.call('SADD', key, userId) + end + + return redis.call('SCARD', key) + """; toggleLikeScript = new DefaultRedisScript<>(); toggleLikeScript.setScriptSource(new StaticScriptSource(script)); @@ -89,6 +89,6 @@ public class LikeServiceImpl implements LikeService { } private Long executeToggle(String key, Long userId) { - return redisTemplate.execute(toggleLikeScript, Collections.singletonList(key), userId); + return redisTemplate.execute(toggleLikeScript, Collections.singletonList(key), String.valueOf(userId)); } } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/NewsServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/NewsServiceImpl.java index ce4ba9c..8079c74 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/NewsServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/NewsServiceImpl.java @@ -36,16 +36,16 @@ public class NewsServiceImpl implements NewsService { @Override public List listIndexNews() { - List result = (List) cacheService.getObject(CacheKey.INDEX_NEWS_KEY); - if(result == null || result.size() == 0) { - SelectStatementProvider selectStatement = select(id, catName, catId, title,createTime) - .from(news) - .orderBy(createTime.descending()) - .limit(2) - .build() - .render(RenderingStrategies.MYBATIS3); + List result = cacheService.getList(CacheKey.INDEX_NEWS_KEY, News.class); + if (result == null || result.isEmpty()) { + SelectStatementProvider selectStatement = select(id, catName, catId, title, createTime) + .from(news) + .orderBy(createTime.descending()) + .limit(2) + .build() + .render(RenderingStrategies.MYBATIS3); result = newsMapper.selectMany(selectStatement); - cacheService.setObject(CacheKey.INDEX_NEWS_KEY,result,60 * 60 * 12); + cacheService.setObject(CacheKey.INDEX_NEWS_KEY, result, 60 * 60 * 12); } return result; } @@ -53,25 +53,25 @@ public class NewsServiceImpl implements NewsService { @Override public News queryNewsInfo(Long newsId) { SelectStatementProvider selectStatement = select(news.allColumns()) - .from(news) - .where(id,isEqualTo(newsId)) - .build() - .render(RenderingStrategies.MYBATIS3); + .from(news) + .where(id, isEqualTo(newsId)) + .build() + .render(RenderingStrategies.MYBATIS3); return newsMapper.selectMany(selectStatement).get(0); } @Override public PageBean listByPage(int page, int pageSize) { - PageHelper.startPage(page,pageSize); - SelectStatementProvider selectStatement = select(id, catName, catId, title,createTime) - .from(news) - .orderBy(createTime.descending()) - .build() - .render(RenderingStrategies.MYBATIS3); + PageHelper.startPage(page, pageSize); + SelectStatementProvider selectStatement = select(id, catName, catId, title, createTime) + .from(news) + .orderBy(createTime.descending()) + .build() + .render(RenderingStrategies.MYBATIS3); List news = newsMapper.selectMany(selectStatement); PageBean pageBean = PageBuilder.build(news); - pageBean.setList(BeanUtil.copyList(news,NewsVO.class)); + pageBean.setList(BeanUtil.copyList(news, NewsVO.class)); return pageBean; } diff --git a/novel-front/src/main/resources/templates/mobile/book/book_ranking.html b/novel-front/src/main/resources/templates/mobile/book/book_ranking.html index f43f4ab..18de2e8 100644 --- a/novel-front/src/main/resources/templates/mobile/book/book_ranking.html +++ b/novel-front/src/main/resources/templates/mobile/book/book_ranking.html @@ -1,6 +1,4 @@ - - @@ -16,8 +14,6 @@
- - @@ -187,19 +192,19 @@ book.bookDesc = book.bookDesc.replace(/<[^>]+>/g, "").replace(/\s+/g, "").replace(/ /g, ""); } - bookListHtml += ("
\n" + + bookListHtml += ("
\n" + " \n" + - "
\n" + - " \n" + + " \n" + "\n" + "
\n" + "
\n" + - "
\n" + + "
\n" + " \n" + "
" + book.bookName + "
\n" + "
\n" + - "
\n" + + "
\n" + " \n" + "
作者:" + book.authorName + "
\n" + "
\n" + @@ -207,7 +212,7 @@ "
状态:" + (book.bookStatus == 0 ? '连载' : '完结') + "
\n" + "
更新:" + book.lastIndexUpdateTime.substr(0, 11) + "\n" + "
\n" + - "
简介:" + (book.bookDesc ? (book.bookDesc.length > 15 ? (book.bookDesc.substr(0, 15) + "...") : book.bookDesc) : book.bookDesc) + "
\n" + + "
简介:" + (book.bookDesc) + "
\n" + "\n" + "\n" + "
\n" + diff --git a/novel-front/src/main/resources/templates/mobile/common/css.html b/novel-front/src/main/resources/templates/mobile/common/css.html index e40c070..a6da973 100644 --- a/novel-front/src/main/resources/templates/mobile/common/css.html +++ b/novel-front/src/main/resources/templates/mobile/common/css.html @@ -26,6 +26,15 @@ } } + .book_name { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + white-space: pre-wrap; + } + #footer { position: absolute; bottom: 0px; diff --git a/novel-front/src/main/resources/templates/mobile/index.html b/novel-front/src/main/resources/templates/mobile/index.html index 0cc9db3..799ca61 100644 --- a/novel-front/src/main/resources/templates/mobile/index.html +++ b/novel-front/src/main/resources/templates/mobile/index.html @@ -53,6 +53,44 @@ color: #3eaf7c; } + .container { + display: flex; + overflow-x: auto; /* 允许内容水平滚动 */ + white-space: nowrap; /* 禁止换行 */ + scroll-snap-type: x mandatory; /* 在滚动时强制对齐 snap-points */ + -ms-overflow-style: none; /* Internet Explorer 10+ */ + scrollbar-width: none; /* Firefox */ + } + + .container::-webkit-scrollbar { + width: 0; + height: 0; + } + + .container::-webkit-scrollbar-track, + .container::-webkit-scrollbar-thumb { + display: none; + } + + + .item { + flex: 0 0 calc(100% / 10); /* 每个元素宽度为容器的十分之一 */ + scroll-snap-align: start; + box-sizing: border-box; + text-align: center; + border-radius: 5px; + margin-right: 5px; + } + + .book_desc { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + white-space: pre-wrap; + } + @@ -107,60 +145,58 @@ 精品推荐 +
- -
-
- 热门推荐 -
- - - -
+
+
+
+ 热门推荐 +
+ +
+ + +
+
@@ -184,7 +220,6 @@
-
@@ -226,7 +261,7 @@ "\n" + "
\n" + "
简介:  " + updateRankBook.bookDesc + "" + + " class=\"layui-elip layui-col-md11 layui-col-sm11 layui-col-lg11\">简介:" + updateRankBook.bookDesc + "" + "
\n" + "
"); diff --git a/pom.xml b/pom.xml index 10c11a7..ad93dfb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.java2nb novel - 5.2.3 + 5.2.6 novel-common novel-front diff --git a/templates/green/html/book/book_comment_reply.html b/templates/green/html/book/book_comment_reply.html new file mode 100644 index 0000000..0774fe5 --- /dev/null +++ b/templates/green/html/book/book_comment_reply.html @@ -0,0 +1,216 @@ + + + + + + + + + + + +
+
+ +
+
+ +
+
+
+ +
+
+
+

评论回复区

(0条) +
+ 发表回复 +
+
+
+ +
+ +
+
+
+ +
+
+ 发表回复 + + +
+ +
+ 0/1000 + 发表 +
+
+
+ +
+
+
+ + + + + +
+
+ +
+
+
+ + + + diff --git a/templates/green/html/mobile/book/book_ranking.html b/templates/green/html/mobile/book/book_ranking.html index f43f4ab..18de2e8 100644 --- a/templates/green/html/mobile/book/book_ranking.html +++ b/templates/green/html/mobile/book/book_ranking.html @@ -1,6 +1,4 @@ - - @@ -16,8 +14,6 @@
- - @@ -187,19 +192,19 @@ book.bookDesc = book.bookDesc.replace(/<[^>]+>/g, "").replace(/\s+/g, "").replace(/ /g, ""); } - bookListHtml += ("
\n" + + bookListHtml += ("
\n" + " \n" + - "
\n" + - " \n" + + " \n" + "\n" + "
\n" + "
\n" + - "
\n" + + "
\n" + " \n" + "
" + book.bookName + "
\n" + "
\n" + - "
\n" + + "
\n" + " \n" + "
作者:" + book.authorName + "
\n" + "
\n" + @@ -207,7 +212,7 @@ "
状态:" + (book.bookStatus == 0 ? '连载' : '完结') + "
\n" + "
更新:" + book.lastIndexUpdateTime.substr(0, 11) + "\n" + "
\n" + - "
简介:" + (book.bookDesc ? (book.bookDesc.length > 15 ? (book.bookDesc.substr(0, 15) + "...") : book.bookDesc) : book.bookDesc) + "
\n" + + "
简介:" + (book.bookDesc) + "
\n" + "\n" + "\n" + "
\n" + diff --git a/templates/green/html/mobile/common/css.html b/templates/green/html/mobile/common/css.html index e40c070..a6da973 100644 --- a/templates/green/html/mobile/common/css.html +++ b/templates/green/html/mobile/common/css.html @@ -26,6 +26,15 @@ } } + .book_name { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + white-space: pre-wrap; + } + #footer { position: absolute; bottom: 0px; diff --git a/templates/green/html/mobile/index.html b/templates/green/html/mobile/index.html index 0cc9db3..799ca61 100644 --- a/templates/green/html/mobile/index.html +++ b/templates/green/html/mobile/index.html @@ -53,6 +53,44 @@ color: #3eaf7c; } + .container { + display: flex; + overflow-x: auto; /* 允许内容水平滚动 */ + white-space: nowrap; /* 禁止换行 */ + scroll-snap-type: x mandatory; /* 在滚动时强制对齐 snap-points */ + -ms-overflow-style: none; /* Internet Explorer 10+ */ + scrollbar-width: none; /* Firefox */ + } + + .container::-webkit-scrollbar { + width: 0; + height: 0; + } + + .container::-webkit-scrollbar-track, + .container::-webkit-scrollbar-thumb { + display: none; + } + + + .item { + flex: 0 0 calc(100% / 10); /* 每个元素宽度为容器的十分之一 */ + scroll-snap-align: start; + box-sizing: border-box; + text-align: center; + border-radius: 5px; + margin-right: 5px; + } + + .book_desc { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + white-space: pre-wrap; + } + @@ -107,60 +145,58 @@ 精品推荐 +
- -
-
- 热门推荐 -
- - - -
+
+
+
+ 热门推荐 +
+ +
+ + +
+
@@ -184,7 +220,6 @@
-
@@ -226,7 +261,7 @@ "\n" + "
\n" + "
简介:  " + updateRankBook.bookDesc + "" + + " class=\"layui-elip layui-col-md11 layui-col-sm11 layui-col-lg11\">简介:" + updateRankBook.bookDesc + "" + "
\n" + "
"); diff --git a/templates/green/static/javascript/bookdetail.js b/templates/green/static/javascript/bookdetail.js index 3f6acd3..7760961 100644 --- a/templates/green/static/javascript/bookdetail.js +++ b/templates/green/static/javascript/bookdetail.js @@ -133,6 +133,52 @@ }) + }, + + SaveCommentReply: function (cmtBId, cmtCId, cmtDetail) { + if (!isLogin) { + layer.alert('请先登录'); + return; + } + var cmtDetailTemp = cmtDetail.replace(/(^\s*)/g, ""); + if (cmtDetailTemp == '') { + layer.alert('回复内容必须填写'); + return; + } + if (cmtDetailTemp.length < 5) { + layer.alert('回复内容必须大于5个字'); + return; + } + if (cmtDetail.length < 5) { + layer.alert('回复内容必须大于5个字'); + return; + } + $.ajax({ + type: "POST", + url: "/book/addCommentReply", + data: {'commentId': $("#commentId").val(), 'replyContent': cmtDetail}, + dataType: "json", + success: function (data) { + if (data.code == 200) { + $('#txtComment').val("") + layer.alert('回复成功!'); + loadCommentList(1, 20); + + } else if (data.code == 1001) { + //未登录 + location.href = '/user/login.html?originUrl=' + encodeURIComponent(location.href); + + } else { + layer.alert(data.msg); + } + + }, + error: function () { + layer.alert('网络异常'); + } + }) + + }, GetFavoritesBook: function (BId) { },