using FreeSql; using LiveForum.Code.Base; using LiveForum.Code.JwtInfrastructure; using LiveForum.IService.Others; using LiveForum.Model; using LiveForum.Model.Dto.Others; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace LiveForum.Service.Others { public class SearchService : ISearchService { private readonly IBaseRepository _postsRepository; private readonly IBaseRepository _usersRepository; private readonly IBaseRepository _followsRepository; private readonly IBaseRepository _tokensRepository; private readonly JwtUserInfoModel _userInfoModel; private readonly IConfiguration _configuration; /// /// 构造函数 /// /// 帖子仓储 /// 用户仓储 /// 用户关注仓储 /// token仓储 /// 用户信息模型 /// 配置 public SearchService( IBaseRepository postsRepository, IBaseRepository usersRepository, IBaseRepository followsRepository, IBaseRepository tokensRepository, JwtUserInfoModel userInfoModel, IConfiguration configuration) { _postsRepository = postsRepository; _usersRepository = usersRepository; _followsRepository = followsRepository; _userInfoModel = userInfoModel; _tokensRepository = tokensRepository; _configuration = configuration; } /// /// 搜索 /// /// 请求参数 /// public async Task> Search(SearchReq request) { try { // 验证搜索关键词 if (string.IsNullOrWhiteSpace(request.Keyword)) { return new BaseResponse(ResponseCode.Error, "搜索关键词不能为空"); } // 验证搜索类型 if (request.SearchType != 1 && request.SearchType != 2) { return new BaseResponse(ResponseCode.Error, "无效的搜索类型"); } var keyword = request.Keyword.Trim(); // 记录搜索历史(可选) // await RecordSearchHistory(keyword); if (request.SearchType == 1) { // 搜索帖子 return await SearchPosts(keyword, request); } else { // 搜索用户 return await SearchUsers(keyword, request); } } catch (Exception ex) { return new BaseResponse(ResponseCode.Error, $"搜索失败:{ex.Message}"); } } /// /// 搜索帖子 /// /// 关键词 /// 请求参数 /// private async Task> SearchPosts(string keyword, SearchReq request) { var query = _postsRepository.Select .Where(x => !x.IsDeleted && x.Status == Model.Enum.Posts.PostsStatusEnum.Publish) .Where(x => x.Title.Contains(keyword) || x.Content.Contains(keyword)) .OrderByDescending(x => x.PublishTime); // 获取总数 var total = await query.CountAsync(); // 分页查询 var posts = await query .Page(request.PageIndex, request.PageSize) .ToListAsync(); // 获取当前用户ID(如果已登录) var currentUserId = _userInfoModel.UserId; // 获取发帖用户信息 var userIds = posts.Select(p => p.UserId).Distinct().ToList(); var users = await _usersRepository.Select .Where(u => userIds.Contains(u.Id)) .ToListAsync(); var userDict = users.ToDictionary(u => u.Id); // 构建返回结果 var items = new List(); foreach (var post in posts) { var user = userDict.GetValueOrDefault(post.UserId); items.Add(new SearchPostDto { PostId = post.Id, Title = post.Title, Content = post.Content.Length > 200 ? post.Content.Substring(0, 200) + "..." : post.Content, CoverImage = post.CoverImage, LikeCount = post.LikeCount, CommentCount = post.CommentCount, PublishTime = post.PublishTime ?? post.CreatedAt, User = user != null ? new SearchUserDto { UserId = user.Id, UserName = "", // T_Users 没有 UserName 字段 NickName = user.NickName ?? "", Avatar = user.Avatar ?? "", IsVip = user.IsVip, IsCertified = user.IsCertified, Signature = user.Signature ?? "", FollowerCount = 0, // 需要从 T_UserFollows 统计 IsFollowed = currentUserId > 0 && await IsFollowingUser(currentUserId, user.Id) } : null }); } var totalPages = (int)Math.Ceiling(total / (double)request.PageSize); return new BaseResponse(new SearchRespDto { PageIndex = request.PageIndex, PageSize = request.PageSize, Total =(int)total, TotalPages = totalPages, Items = items }); } /// /// 搜索用户 /// /// 关键词 /// 请求参数 /// private async Task> SearchUsers(string keyword, SearchReq request) { var query = _usersRepository.Select .Where(x => x.Status == Model.Enum.Users.UserStatusEnum.Normal) .Where(x => x.NickName.Contains(keyword) || x.Signature.Contains(keyword)); // 获取总数 var total = await query.CountAsync(); // 分页查询 var users = await query .Page(request.PageIndex, request.PageSize) .OrderByDescending(x => x.CreatedAt) .ToListAsync(); // 获取当前用户ID(如果已登录) var currentUserId = _userInfoModel.UserId; // 获取关注信息 var userIds = users.Select(u => u.Id).ToList(); var followInfo = currentUserId > 0 ? await _followsRepository.Select .Where(f => f.FollowerId == currentUserId && userIds.Contains(f.FollowedUserId)) .ToListAsync() : new List(); var followSet = followInfo.Select(f => f.FollowedUserId).ToHashSet(); // 统计每个用户的粉丝数 var followerCountsDict = new Dictionary(); foreach (var userId in userIds) { var count = await _followsRepository.Select .Where(f => f.FollowedUserId == userId) .CountAsync(); followerCountsDict[userId] =(int)count; } // 构建返回结果 var items = new List(); foreach (var user in users) { items.Add(new SearchUserDto { UserId = user.Id, UserName = "", // T_Users 没有 UserName 字段 NickName = user.NickName ?? "", Avatar = user.Avatar ?? "", IsVip = user.IsVip, IsCertified = user.IsCertified, Signature = user.Signature ?? "", FollowerCount = followerCountsDict.GetValueOrDefault(user.Id, 0), IsFollowed = currentUserId > 0 && followSet.Contains(user.Id) }); } var totalPages = (int)Math.Ceiling(total / (double)request.PageSize); return new BaseResponse(new SearchRespDto { PageIndex = request.PageIndex, PageSize = request.PageSize, Total =(int)total, TotalPages = totalPages, Items = items }); } /// /// 检查是否关注用户 /// /// 当前用户ID /// 目标用户ID /// private async Task IsFollowingUser(long currentUserId, long targetUserId) { if (currentUserId <= 0) return false; var count = await _followsRepository.Select .Where(f => f.FollowerId == currentUserId && f.FollowedUserId == targetUserId) .CountAsync(); return count > 0; } /// /// 获取热门搜索关键词 /// /// 请求参数 /// public async Task> GetHotKeywords(GetHotKeywordsReq request) { try { // 从配置中获取热门关键词 // 这是一个简化的实现,实际项目中可以从数据库或缓存中获取 var hotKeywords = new List { new HotKeywordDto { Keyword = "精彩分享", SearchCount = 1250, Rank = 1 }, new HotKeywordDto { Keyword = "技术交流", SearchCount = 980, Rank = 2 }, new HotKeywordDto { Keyword = "生活分享", SearchCount = 856, Rank = 3 }, new HotKeywordDto { Keyword = "学习心得", SearchCount = 742, Rank = 4 }, new HotKeywordDto { Keyword = "经验分享", SearchCount = 689, Rank = 5 }, new HotKeywordDto { Keyword = "问题求助", SearchCount = 567, Rank = 6 }, new HotKeywordDto { Keyword = "资源分享", SearchCount = 523, Rank = 7 }, new HotKeywordDto { Keyword = "社区活动", SearchCount = 489, Rank = 8 }, new HotKeywordDto { Keyword = "行业动态", SearchCount = 456, Rank = 9 }, new HotKeywordDto { Keyword = "创新想法", SearchCount = 423, Rank = 10 } }; // 限制返回数量 var result = hotKeywords.Take(Math.Min(request.Limit, 20)).ToList(); return new BaseResponseList(result); } catch (Exception ex) { return new BaseResponseList(ResponseCode.Error, $"获取热门关键词失败:{ex.Message}"); } } } }