From ba8c1e3be3f9f9e727c6debe6dbcab5cfdbe93d6 Mon Sep 17 00:00:00 2001 From: Chuyaoyuan Date: Sat, 9 May 2026 11:35:30 +0800 Subject: [PATCH] update fix --- ...7\v\002\016\0340\006I\020@\001\020\020" | 0 "\0032p" | 0 .../controller/UserPostController.java | 3 + .../controller/UserSystemController.java | 1 + .../controller/api/RestUserController.java | 46 ++++--- .../yaoyuan/jiscuss/entity/Discussion.java | 3 + .../java/com/yaoyuan/jiscuss/entity/User.java | 4 +- .../com/yaoyuan/jiscuss/entity/UserInfo.java | 5 +- .../repository/DiscussionsRepository.java | 7 +- .../jiscuss/service/IDiscussionsService.java | 2 + .../service/impl/DiscussionsServiceImpl.java | 9 +- .../db/migration/V6__add_indexes.sql | 26 ++++ .../resources/db/migration/V7__view_count.sql | 5 + src/main/resources/templates/discussions.ftl | 6 +- src/main/resources/templates/index.ftl | 125 ++++++++++-------- 15 files changed, 158 insertions(+), 84 deletions(-) create mode 100644 "\003,\0030p>\003;\b\0038p>\003\002=\0021p>\003\002:\002(p>\0032p?\003p>\003\002?\0027p>\003\002;\0029p>\003\0023\0025p>\003\002\0033p>\003\002<\0023p>\003Rich2p>\003PEd\006o=\177\v\002\016\0340\006I\020@\001\020\020" create mode 100644 "\0032p" create mode 100644 src/main/resources/db/migration/V6__add_indexes.sql create mode 100644 src/main/resources/db/migration/V7__view_count.sql diff --git "a/\003,\0030p>\003;\b\0038p>\003\002=\0021p>\003\002:\002(p>\0032p?\003p>\003\002?\0027p>\003\002;\0029p>\003\0023\0025p>\003\002\0033p>\003\002<\0023p>\003Rich2p>\003PEd\006o=\177\v\002\016\0340\006I\020@\001\020\020" "b/\003,\0030p>\003;\b\0038p>\003\002=\0021p>\003\002:\002(p>\0032p?\003p>\003\002?\0027p>\003\002;\0029p>\003\0023\0025p>\003\002\0033p>\003\002<\0023p>\003Rich2p>\003PEd\006o=\177\v\002\016\0340\006I\020@\001\020\020" new file mode 100644 index 0000000..e69de29 diff --git "a/\0032p" "b/\0032p" new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java index 09bdd59..f4dbcfc 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java @@ -73,6 +73,9 @@ public class UserPostController extends BaseController { public String getDiscussionsById(HttpServletRequest request, ModelMap map, @RequestParam("id") Integer id) { logger.info(">>> getDiscussionsById{}", id); + // Atomically increment view count before loading the discussion + discussionsService.incrementViewCount(id); + Discussion discussion = discussionsService.findOne(id); // 获取此主题下的评论 List posts = postsService.findOneBy(id); diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java index c052e41..3a8872c 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java @@ -112,6 +112,7 @@ public class UserSystemController extends BaseController { map.put("pageTotal", total); map.put("pageNum", pageNum); map.put("pageTotalPages", allDiscussionsPage.getTotalPages()); + map.put("pageNumAll", allDiscussionsPage.getTotalPages()); UserInfo user = getUserInfo(request); if (user != null) { map.put("username", user.getUsername()); diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/api/RestUserController.java b/src/main/java/com/yaoyuan/jiscuss/controller/api/RestUserController.java index 6e91968..072c109 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/api/RestUserController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/api/RestUserController.java @@ -1,11 +1,16 @@ package com.yaoyuan.jiscuss.controller.api; +import com.yaoyuan.jiscuss.dto.UserCreateRequest; +import com.yaoyuan.jiscuss.dto.UserMapper; +import com.yaoyuan.jiscuss.dto.UserResponse; import com.yaoyuan.jiscuss.entity.User; import com.yaoyuan.jiscuss.exception.BaseException; +import com.yaoyuan.jiscuss.response.ApiResponse; import com.yaoyuan.jiscuss.response.ResponseCode; import com.yaoyuan.jiscuss.service.IUsersService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -30,46 +35,51 @@ public class RestUserController { @Autowired private IUsersService usersService; + @Autowired + private UserMapper userMapper; + @PostMapping("/user") @Operation(summary = "新增用户") - public User save(@RequestBody User user) { - User saveUser = usersService.insert(user); - if (saveUser != null) { - return saveUser; - } else { - throw new BaseException(ResponseCode.RESOURCES_NOT_EXIST); + public ApiResponse save(@Valid @RequestBody UserCreateRequest request) { + User user = userMapper.fromCreateRequest(request); + User saved = usersService.insert(user); + if (saved != null) { + return ApiResponse.ok(userMapper.toResponse(saved)); } + throw new BaseException(ResponseCode.RESOURCES_NOT_EXIST); } @DeleteMapping("/user/{id}") @Operation(summary = "删除用户") - public Boolean delete(@PathVariable Integer id) { + public ApiResponse delete(@PathVariable Integer id) { usersService.remove(id); - return true; + return ApiResponse.ok(true); } @PutMapping("/user/{id}") @Operation(summary = "修改用户") - public User update(@RequestBody User user, @PathVariable Integer id) { - User updateuser = usersService.update(user, id); - if (updateuser != null) { - return updateuser; - } else { - throw new BaseException(ResponseCode.RESOURCES_NOT_EXIST); + public ApiResponse update(@RequestBody User user, @PathVariable Integer id) { + User updated = usersService.update(user, id); + if (updated != null) { + return ApiResponse.ok(userMapper.toResponse(updated)); } + throw new BaseException(ResponseCode.RESOURCES_NOT_EXIST); } @GetMapping("/user/{id}") @Operation(summary = "获取用户") - public User getUser(@PathVariable Integer id) { + public ApiResponse getUser(@PathVariable Integer id) { User user = usersService.findOne(id); logger.info("获取用户==>:{}", user); - return user; + return ApiResponse.ok(userMapper.toResponse(user)); } @GetMapping("/user") @Operation(summary = "获取全部用户") - public List getAllUsers() { - return usersService.getAllList(); + public ApiResponse> getAllUsers() { + List list = usersService.getAllList().stream() + .map(userMapper::toResponse) + .toList(); + return ApiResponse.ok(list); } } diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/Discussion.java b/src/main/java/com/yaoyuan/jiscuss/entity/Discussion.java index 4a28940..4758111 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/Discussion.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/Discussion.java @@ -77,5 +77,8 @@ public class Discussion implements Serializable { @Column(name = "create_time") private Date createTime; + + @Column(name = "view_count") + private Integer viewCount = 0; } diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/User.java b/src/main/java/com/yaoyuan/jiscuss/entity/User.java index 3c072cf..185a2ae 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/User.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/User.java @@ -1,5 +1,6 @@ package com.yaoyuan.jiscuss.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -39,7 +40,8 @@ public class User implements Serializable { @Column(name = "email") private String email; - /** BCrypt-hashed password. Column length must be >= 68 (see V2 migration). */ + /** BCrypt-hashed password. Column length must be >= 68 (see V2 migration). Never serialized to JSON. */ + @JsonIgnore @Column(name = "password") private String password; diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java b/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java index 3fcab82..5b57617 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java @@ -77,10 +77,9 @@ public class UserInfo implements UserDetails { @Override public String toString() { return "UserInfo{" + - "authorities=" + authorities + - ", password='" + password + '\'' + - ", username='" + username + '\'' + + "username='" + username + '\'' + ", id='" + id + '\'' + + ", authorities=" + authorities + '}'; } } diff --git a/src/main/java/com/yaoyuan/jiscuss/repository/DiscussionsRepository.java b/src/main/java/com/yaoyuan/jiscuss/repository/DiscussionsRepository.java index c1df9d7..bccaef5 100644 --- a/src/main/java/com/yaoyuan/jiscuss/repository/DiscussionsRepository.java +++ b/src/main/java/com/yaoyuan/jiscuss/repository/DiscussionsRepository.java @@ -4,8 +4,10 @@ import com.yaoyuan.jiscuss.entity.Discussion; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; @Repository public interface DiscussionsRepository extends JpaRepository { @@ -14,5 +16,8 @@ public interface DiscussionsRepository extends JpaRepository findByQuery(String tagId, Pageable pageable); - + @Modifying + @Transactional + @Query("UPDATE Discussion d SET d.viewCount = d.viewCount + 1 WHERE d.id = :id") + void incrementViewCount(@org.springframework.data.repository.query.Param("id") Integer id); } diff --git a/src/main/java/com/yaoyuan/jiscuss/service/IDiscussionsService.java b/src/main/java/com/yaoyuan/jiscuss/service/IDiscussionsService.java index 04459dd..2345f6f 100644 --- a/src/main/java/com/yaoyuan/jiscuss/service/IDiscussionsService.java +++ b/src/main/java/com/yaoyuan/jiscuss/service/IDiscussionsService.java @@ -14,4 +14,6 @@ public interface IDiscussionsService { Discussion findOne(Integer id); Page queryAllDiscussionsList(Discussion discussion, int pageNumNew, int pageSiz, String tag, String type); + + void incrementViewCount(Integer id); } diff --git a/src/main/java/com/yaoyuan/jiscuss/service/impl/DiscussionsServiceImpl.java b/src/main/java/com/yaoyuan/jiscuss/service/impl/DiscussionsServiceImpl.java index ed865be..c75f582 100644 --- a/src/main/java/com/yaoyuan/jiscuss/service/impl/DiscussionsServiceImpl.java +++ b/src/main/java/com/yaoyuan/jiscuss/service/impl/DiscussionsServiceImpl.java @@ -35,8 +35,7 @@ public class DiscussionsServiceImpl implements IDiscussionsService { @Transactional(readOnly = true) @Override public Discussion findOne(Integer id) { - // getReferenceById replaces removed JpaRepository.getOne() - return discussionsRepository.getReferenceById(id); + return discussionsRepository.findById(id).orElse(null); } @Transactional(readOnly = true) @@ -55,4 +54,10 @@ public class DiscussionsServiceImpl implements IDiscussionsService { return discussionsRepository.findAll(example, pageable); } } + + @Transactional + @Override + public void incrementViewCount(Integer id) { + discussionsRepository.incrementViewCount(id); + } } diff --git a/src/main/resources/db/migration/V6__add_indexes.sql b/src/main/resources/db/migration/V6__add_indexes.sql new file mode 100644 index 0000000..3bb3658 --- /dev/null +++ b/src/main/resources/db/migration/V6__add_indexes.sql @@ -0,0 +1,26 @@ +-- V6: Add indexes for high-frequency query columns. +-- All indexes use IF NOT EXISTS for idempotent migrations. + +-- post table: most reads filter/sort by discussion_id, parent_id, create_time +CREATE INDEX IF NOT EXISTS idx_post_discussion_id ON post(discussion_id); +CREATE INDEX IF NOT EXISTS idx_post_parent_id ON post(parent_id); +CREATE INDEX IF NOT EXISTS idx_post_create_time ON post(create_time); +CREATE INDEX IF NOT EXISTS idx_post_create_id ON post(create_id); + +-- discussion table: sorted by id/create_time/start_time/like_count; joined on start_user_id/last_user_id +CREATE INDEX IF NOT EXISTS idx_discussion_create_time ON discussion(create_time); +CREATE INDEX IF NOT EXISTS idx_discussion_start_time ON discussion(start_time); +CREATE INDEX IF NOT EXISTS idx_discussion_like_count ON discussion(like_count); +CREATE INDEX IF NOT EXISTS idx_discussion_start_user_id ON discussion(start_user_id); +CREATE INDEX IF NOT EXISTS idx_discussion_last_user_id ON discussion(last_user_id); + +-- discussiontag table: used in tag-filter queries and cascade deletes +CREATE INDEX IF NOT EXISTS idx_discussiontag_discussion_id ON discussiontag(discussion_id); +CREATE INDEX IF NOT EXISTS idx_discussiontag_tag_id ON discussiontag(tag_id); + +-- user table: login and username-lookup path +CREATE INDEX IF NOT EXISTS idx_user_username ON user(username); + +-- likecollect table: user activity queries +CREATE INDEX IF NOT EXISTS idx_likecollect_user_id ON likecollect(user_id); +CREATE INDEX IF NOT EXISTS idx_likecollect_discussion_id ON likecollect(discussion_id); diff --git a/src/main/resources/db/migration/V7__view_count.sql b/src/main/resources/db/migration/V7__view_count.sql new file mode 100644 index 0000000..9826ece --- /dev/null +++ b/src/main/resources/db/migration/V7__view_count.sql @@ -0,0 +1,5 @@ +-- V7: Add view_count to discussion table. +-- Tracks how many times a discussion has been viewed. +ALTER TABLE discussion ADD COLUMN IF NOT EXISTS view_count INTEGER NOT NULL DEFAULT 0; + +CREATE INDEX IF NOT EXISTS idx_discussion_view_count ON discussion(view_count); diff --git a/src/main/resources/templates/discussions.ftl b/src/main/resources/templates/discussions.ftl index 83253c6..cf4dfb1 100644 --- a/src/main/resources/templates/discussions.ftl +++ b/src/main/resources/templates/discussions.ftl @@ -49,9 +49,13 @@ 赞这个主题 - 1,048 + ${discussions.likeCount!0} + + ${discussions.viewCount!0} 浏览 +    ${discussions.commentsCount!0} 回复 +
diff --git a/src/main/resources/templates/index.ftl b/src/main/resources/templates/index.ftl index 6845ee7..2bcca4a 100644 --- a/src/main/resources/templates/index.ftl +++ b/src/main/resources/templates/index.ftl @@ -347,10 +347,13 @@
@@ -397,10 +400,13 @@ @@ -446,10 +452,13 @@ @@ -461,68 +470,68 @@ + <#-- Pagination: preserves tag and type query parameters --> - - <#---->
-
Jiscuss手机可见,内容正在编写中,pc端可正常访问
+
+ <#list allDiscussions as discussions> +
+
+
+ + ${discussions.title} + +
${discussions.startTime}
+
+
+ ${discussions.username} •  + ${discussions.commentsCount!0} 回复  + ${discussions.viewCount!0} 浏览 +
+
+
+
+ +