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();