diff --git a/src/backend/BookmarkApi.Core/Services/BookmarkService.cs b/src/backend/BookmarkApi.Core/Services/BookmarkService.cs index de46a00..f255b05 100644 --- a/src/backend/BookmarkApi.Core/Services/BookmarkService.cs +++ b/src/backend/BookmarkApi.Core/Services/BookmarkService.cs @@ -21,61 +21,58 @@ public class BookmarkService : IBookmarkService /// public async Task> GetUserBookmarksAsync(Guid userId, Guid deviceId, bool isAdminDevice, string? tag = null) { - var query = _freeSql.Select() - .Where(b => b.UserId == userId); + // 先查询所有书签,然后在内存中过滤 + // 避免 FreeSql 无法正确转换 AllowedDevices.Contains 和 Tags.Contains 为 SQL + var bookmarks = await _freeSql.Select() + .Where(b => b.UserId == userId) + .OrderByDescending(b => b.Order) + .ToListAsync(); // 如果不是管理员设备,需要过滤可见性 if (!isAdminDevice) { - query = query.Where(b => + bookmarks = bookmarks.Where(b => b.Visibility == VisibilityType.Public || (b.Visibility == VisibilityType.Specified && b.AllowedDevices != null && b.AllowedDevices.Contains(deviceId)) - ); + ).ToList(); } // 按标签筛选 if (!string.IsNullOrEmpty(tag)) { - query = query.Where(b => b.Tags.Contains(tag)); + bookmarks = bookmarks.Where(b => b.Tags.Contains(tag)).ToList(); } - var bookmarks = await query - .OrderByDescending(b => b.Order) - .ToListAsync(); - return bookmarks.Select(MapToDto).ToList(); } /// public async Task> SearchBookmarksAsync(Guid userId, Guid deviceId, bool isAdminDevice, string keyword) { - var query = _freeSql.Select() - .Where(b => b.UserId == userId); + // 先在数据库层面进行关键词搜索,然后在内存中过滤可见性 + // 避免 FreeSql 无法正确转换 AllowedDevices.Contains 为 SQL + var lowerKeyword = keyword.ToLower(); + var bookmarks = await _freeSql.Select() + .Where(b => b.UserId == userId) + .Where(b => + b.Title.ToLower().Contains(lowerKeyword) || + b.Url.ToLower().Contains(lowerKeyword) || + (b.Description != null && b.Description.ToLower().Contains(lowerKeyword)) + ) + .OrderByDescending(b => b.VisitCount) + .OrderByDescending(b => b.Order) + .ToListAsync(); // 如果不是管理员设备,需要过滤可见性 if (!isAdminDevice) { - query = query.Where(b => + bookmarks = bookmarks.Where(b => b.Visibility == VisibilityType.Public || (b.Visibility == VisibilityType.Specified && b.AllowedDevices != null && b.AllowedDevices.Contains(deviceId)) - ); + ).ToList(); } - // 搜索关键词 - var lowerKeyword = keyword.ToLower(); - query = query.Where(b => - b.Title.ToLower().Contains(lowerKeyword) || - b.Url.ToLower().Contains(lowerKeyword) || - (b.Description != null && b.Description.ToLower().Contains(lowerKeyword)) - ); - - var bookmarks = await query - .OrderByDescending(b => b.VisitCount) - .OrderByDescending(b => b.Order) - .Take(20) - .ToListAsync(); - - return bookmarks.Select(MapToDto).ToList(); + return bookmarks.Take(20).Select(MapToDto).ToList(); } /// diff --git a/src/backend/BookmarkApi.Core/Services/TagService.cs b/src/backend/BookmarkApi.Core/Services/TagService.cs index fc7c4b3..8e5f733 100644 --- a/src/backend/BookmarkApi.Core/Services/TagService.cs +++ b/src/backend/BookmarkApi.Core/Services/TagService.cs @@ -20,20 +20,21 @@ public class TagService : ITagService /// public async Task> GetUserTagsAsync(Guid userId, Guid deviceId, bool isAdminDevice) { - var query = _freeSql.Select() - .Where(b => b.UserId == userId); + // 先查询所有书签,然后在内存中过滤 + // 避免 FreeSql 无法正确转换 AllowedDevices.Contains 为 SQL + var bookmarks = await _freeSql.Select() + .Where(b => b.UserId == userId) + .ToListAsync(); // 如果不是管理员设备,需要过滤可见性 if (!isAdminDevice) { - query = query.Where(b => + bookmarks = bookmarks.Where(b => b.Visibility == VisibilityType.Public || (b.Visibility == VisibilityType.Specified && b.AllowedDevices != null && b.AllowedDevices.Contains(deviceId)) - ); + ).ToList(); } - var bookmarks = await query.ToListAsync(); - // 统计标签使用数量 var tagCounts = new Dictionary();