Update Search footer header index user

This commit is contained in:
2026-05-13 17:40:26 +08:00
parent cda8a3e0ee
commit aeb0866ec1
12 changed files with 477 additions and 107 deletions
@@ -88,7 +88,7 @@ public class WebSecurityConfig {
auth.requestMatchers(
"/css/**", "/js/**", "/images/**", "/static/**", "/favicon.ico",
"/login/**", "/register", "/registerDo", "/initUserData",
"/", "/main", "/index", "/getdiscussionsbyid",
"/", "/main", "/index", "/getdiscussionsbyid", "/search", "/profile",
// SpringDoc OpenAPI UI and spec endpoint (developer tools, no sensitive data)
"/swagger-ui/**", "/swagger-ui.html", "/v3/api-docs/**"
).permitAll();
@@ -0,0 +1,30 @@
package com.yaoyuan.jiscuss.controller;
import com.yaoyuan.jiscuss.entity.UserInfo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
/**
* Injects common model attributes (e.g. isAdmin) into every rendered view.
*/
@ControllerAdvice
public class GlobalModelAdvice {
@ModelAttribute("isAdmin")
public boolean isAdmin(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) return false;
Object ctx = session.getAttribute("SPRING_SECURITY_CONTEXT");
if (!(ctx instanceof SecurityContext sc)) return false;
Authentication auth = sc.getAuthentication();
if (auth == null || !(auth.getPrincipal() instanceof UserInfo)) return false;
return auth.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.anyMatch(a -> a.equals("ROLE_ADMIN"));
}
}
@@ -18,6 +18,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -100,6 +101,54 @@ public class UserPageController extends BaseController {
map.put("likedDiscussions", liked);
}
map.put("isOwn", true);
return "user";
}
/**
* 公开用户主页 /profile?uid=xxx (无需登录)
*/
@GetMapping("/profile")
public String profile(@RequestParam Integer uid,
@RequestParam(defaultValue = "discussion") String type,
HttpServletRequest request, ModelMap map) {
User userEntity = usersService.findOne(uid);
if (userEntity == null) return "redirect:/";
long liveDiscCount = discussionsRepository.countByStartUserId(uid);
long liveReplyCount = postsRepository.countByCreateId(uid);
map.put("username", userEntity.getUsername());
map.put("userEntity", userEntity);
map.put("liveDiscCount", liveDiscCount);
map.put("liveReplyCount", liveReplyCount);
map.put("type", type);
map.put("isOwn", false);
if ("discussion".equals(type)) {
Page<Discussion> discussions = discussionsRepository.findByStartUserIdOrderByStartTimeDesc(
uid, PageRequest.of(0, 20));
map.put("discussions", discussions.getContent());
} else if ("reply".equals(type)) {
Page<Post> posts = postsRepository.findByCreateIdOrderByCreateTimeDesc(
uid, PageRequest.of(0, 20));
map.put("posts", posts.getContent());
List<String> discTitles = new ArrayList<>();
for (Post p : posts.getContent()) {
Discussion d = p.getDiscussionId() != null
? discussionsRepository.findById(p.getDiscussionId()).orElse(null) : null;
discTitles.add(d != null ? d.getTitle() : "");
}
map.put("discTitles", discTitles);
} else if ("like".equals(type)) {
List<Integer> likedIds = likeCollectRepository.findLikedDiscussionIdsByUser(uid);
List<Discussion> liked = new ArrayList<>();
for (Integer id : likedIds) {
Discussion d = discussionsRepository.findById(id).orElse(null);
if (d != null) liked.add(d);
}
map.put("likedDiscussions", liked);
}
return "user";
}
}
@@ -7,6 +7,8 @@ import com.yaoyuan.jiscuss.entity.Tag;
import com.yaoyuan.jiscuss.entity.User;
import com.yaoyuan.jiscuss.entity.UserInfo;
import com.yaoyuan.jiscuss.entity.custom.DiscussionCustom;
import com.yaoyuan.jiscuss.repository.DiscussionsRepository;
import com.yaoyuan.jiscuss.repository.PostsRepository;
import com.yaoyuan.jiscuss.service.IDiscussionsService;
import com.yaoyuan.jiscuss.service.IDiscussionsTagsService;
import com.yaoyuan.jiscuss.service.IPostsService;
@@ -19,6 +21,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
@@ -59,6 +62,12 @@ public class UserPostController extends BaseController {
@Autowired
private IUsersService usersService;
@Autowired
private DiscussionsRepository discussionsRepository;
@Autowired
private PostsRepository postsRepository;
@Autowired
private IpRegionService ipRegionService;
@@ -112,6 +121,19 @@ public class UserPostController extends BaseController {
map.put("discussions", newdd);
map.put("posts", postsObj);
map.put("sort", sort);
// Sidebar: author stats and top discussions
if (newdd.getStartUserId() != null) {
Integer authorId = newdd.getStartUserId();
long authorDiscCount = discussionsRepository.countByStartUserId(authorId);
long authorReplyCount = postsRepository.countByCreateId(authorId);
java.util.List<Discussion> authorTopDiscs = discussionsRepository
.findTopByStartUserIdOrderByLikes(authorId, PageRequest.of(0, 5));
map.put("authorDiscCount", authorDiscCount);
map.put("authorReplyCount", authorReplyCount);
map.put("authorTopDiscs", authorTopDiscs);
}
UserInfo user = getUserInfo(request);
if (user != null) {
map.put("username", user.getUsername());
@@ -6,6 +6,7 @@ import com.yaoyuan.jiscuss.entity.User;
import com.yaoyuan.jiscuss.entity.UserInfo;
import com.yaoyuan.jiscuss.entity.custom.DiscussionCustom;
import com.yaoyuan.jiscuss.entity.custom.TagCustom;
import com.yaoyuan.jiscuss.repository.DiscussionsRepository;
import com.yaoyuan.jiscuss.service.IDiscussionsService;
import com.yaoyuan.jiscuss.service.ITagsService;
import com.yaoyuan.jiscuss.service.IUsersService;
@@ -54,6 +55,9 @@ public class UserSystemController extends BaseController {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private DiscussionsRepository discussionsRepository;
/**
* 首页index
* @param tag
@@ -276,6 +280,36 @@ public class UserSystemController extends BaseController {
return "register";
}
/**
* 搜索页
*/
@GetMapping("/search")
public String search(@RequestParam(defaultValue = "") String q,
@RequestParam(defaultValue = "1") Integer pageNum,
HttpServletRequest request, ModelMap map) {
String keyword = q.trim();
int pageSize = 10;
int page = Math.max(pageNum - 1, 0);
Page<Discussion> resultPage = keyword.isEmpty()
? Page.empty()
: discussionsRepository.searchByKeyword(keyword,
org.springframework.data.domain.PageRequest.of(page, pageSize));
List<DiscussionCustom> results = new ArrayList<>();
if (!keyword.isEmpty()) {
setTagAndUserList(results, resultPage.getContent());
}
map.put("q", keyword);
map.put("results", results);
map.put("totalPages", resultPage.getTotalPages());
map.put("totalElements", resultPage.getTotalElements());
map.put("pageNum", pageNum);
UserInfo user = getUserInfo(request);
if (user != null) map.put("username", user.getUsername());
return "search";
}
//获取设置信息
//获取首页统计
@@ -10,6 +10,7 @@ import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Repository
public interface DiscussionsRepository extends JpaRepository<Discussion, Integer> {
@@ -49,4 +50,14 @@ public interface DiscussionsRepository extends JpaRepository<Discussion, Integer
@org.springframework.data.repository.query.Param("userId") Integer userId,
org.springframework.data.domain.Pageable pageable);
long countByStartUserId(Integer startUserId);
/** Author's top discussions ordered by likeCount (for sidebar). */
@Query("SELECT d FROM Discussion d WHERE d.startUserId = :userId ORDER BY COALESCE(d.likeCount, 0) DESC, d.startTime DESC")
List<Discussion> findTopByStartUserIdOrderByLikes(
@org.springframework.data.repository.query.Param("userId") Integer userId,
Pageable pageable);
/** Full-text search by title or content. */
@Query("SELECT d FROM Discussion d WHERE d.title LIKE %:q% OR d.content LIKE %:q% ORDER BY d.startTime DESC")
Page<Discussion> searchByKeyword(@org.springframework.data.repository.query.Param("q") String q, Pageable pageable);
}