using dy.net.model; using SqlSugar; using System.Linq.Expressions; namespace dy.net.repository { public class DyCollectVideoRepository : BaseRepository { // 注入SQLSugar客户端 public DyCollectVideoRepository(ISqlSugarClient db) : base(db) { } /// /// 分页查询收藏视频 /// /// 页码(从1开始) /// 每页数量 /// 可选标签过滤(单个,兼容旧版本) /// 可选标签过滤(多个) /// 可选作者过滤 /// 删除状态筛选:null=全部,true=已删除(videoSavePath为空),false=未删除(videoSavePath不为空) /// 排序字段:syncTime-同步时间, viedoType-同步类型, viedoCate-视频类型, author-作者, videoTitle-视频名称, dyUser-用户 /// 排序方向:asc-升序, desc-降序 /// 分页结果(视频列表和总数) public async Task<(List list, int totalCount)> GetPagedAsync(int pageIndex, int pageSize, string tag = null, List tags = null, string author = null,string viedoType=null, List dates = null, bool? isDeleted = null, string sortField = null, string sortOrder = null) { DateTime? start = null; DateTime? end =null; if(dates!=null && dates.Count==2) { start = Convert.ToDateTime(dates[0]); end = Convert.ToDateTime(dates[1]); } else if(dates!=null && dates.Count==1) { start = Convert.ToDateTime(dates[0]); } var where = this.Db.Queryable(); // 支持多个标签筛选(优先使用 tags,如果为空则使用 tag) // 注意:tags 匹配的是 viedoCate(Tag1/Tag2 组合),格式如 "美食/美食展示" // 特殊值 "未分类" 表示 Tag1 和 Tag2 都为空的视频 if (tags != null && tags.Any()) { // 过滤空值 var validTags = tags.Where(t => !string.IsNullOrWhiteSpace(t)).ToList(); if (validTags.Any()) { // 检查是否包含"未分类"选项 var hasEmptyCategory = validTags.Contains("未分类"); var otherTags = validTags.Where(t => t != "未分类").ToList(); // 构建 OR 条件:对于每个 tag,匹配对应的 Tag1/Tag2 组合 if (hasEmptyCategory && otherTags.Any()) { // 同时包含"未分类"和其他类型 // 使用内存过滤的方式,确保逻辑正确 var matchingVideoIds = new List(); // 获取所有视频(先应用其他筛选条件) var allVideos = await this.Db.Queryable() .WhereIF(!string.IsNullOrWhiteSpace(author), x => x.Author == author) .WhereIF(start.HasValue, x => x.SyncTime >= start.Value) .WhereIF(end.HasValue, x => x.SyncTime <= end.Value) .WhereIF(!string.IsNullOrWhiteSpace(viedoType) && viedoType != "*", x => x.ViedoType == viedoType) .WhereIF(isDeleted.HasValue && isDeleted.Value, x => string.IsNullOrWhiteSpace(x.VideoSavePath)) .WhereIF(isDeleted.HasValue && !isDeleted.Value, x => !string.IsNullOrWhiteSpace(x.VideoSavePath)) .ToListAsync(); // 在内存中过滤 viedoCate foreach (var video in allVideos) { var viedoCate = (string.IsNullOrWhiteSpace(video.Tag1) ? "" : video.Tag1) + "/" + (string.IsNullOrWhiteSpace(video.Tag2) ? "" : video.Tag2); // 检查是否是"未分类"或匹配其他标签 bool isMatch = (string.IsNullOrWhiteSpace(video.Tag1) && string.IsNullOrWhiteSpace(video.Tag2)) || // 未分类 otherTags.Contains(viedoCate); // 其他类型 if (isMatch) { matchingVideoIds.Add(video.Id); } } if (matchingVideoIds.Any()) { // 使用 ID 列表重新构建查询 where = this.Db.Queryable() .Where(x => matchingVideoIds.Contains(x.Id)); } else { // 如果没有匹配的数据,返回空结果 where = this.Db.Queryable().Where(x => false); } } else if (hasEmptyCategory) { // 只选择了"未分类" where = where.Where(x => string.IsNullOrWhiteSpace(x.Tag1) && string.IsNullOrWhiteSpace(x.Tag2)); } else { // 只选择了其他类型,构建所有条件的 OR // 使用更简单的方法:先获取所有符合条件的视频 ID,然后使用 In 方法 // 这样可以避免复杂的表达式树构建 var matchingVideoIds = new List(); // 获取所有视频 var allVideos = await this.Db.Queryable() .WhereIF(!string.IsNullOrWhiteSpace(author), x => x.Author == author) .WhereIF(start.HasValue, x => x.SyncTime >= start.Value) .WhereIF(end.HasValue, x => x.SyncTime <= end.Value) .WhereIF(!string.IsNullOrWhiteSpace(viedoType) && viedoType != "*", x => x.ViedoType == viedoType) .WhereIF(isDeleted.HasValue && isDeleted.Value, x => string.IsNullOrWhiteSpace(x.VideoSavePath)) .WhereIF(isDeleted.HasValue && !isDeleted.Value, x => !string.IsNullOrWhiteSpace(x.VideoSavePath)) .ToListAsync(); // 在内存中过滤 viedoCate foreach (var video in allVideos) { var viedoCate = (string.IsNullOrWhiteSpace(video.Tag1) ? "" : video.Tag1) + "/" + (string.IsNullOrWhiteSpace(video.Tag2) ? "" : video.Tag2); if (otherTags.Contains(viedoCate)) { matchingVideoIds.Add(video.Id); } } if (matchingVideoIds.Any()) { // 使用 ID 列表重新构建查询 where = this.Db.Queryable() .Where(x => matchingVideoIds.Contains(x.Id)); } else { // 如果没有匹配的数据,返回空结果 where = this.Db.Queryable().Where(x => false); } } } } else if (!string.IsNullOrWhiteSpace(tag)) { // 兼容旧版本的单标签筛选 if (tag.Contains("/")) { var parts = tag.Split('/', 2); var tag1 = parts[0]; var tag2 = parts.Length > 1 ? parts[1] : ""; where = where.Where(x => x.Tag1 == tag1 && (string.IsNullOrWhiteSpace(tag2) || x.Tag2 == tag2 || string.IsNullOrWhiteSpace(x.Tag2))); } else { where = where.Where(x => x.Tag1 == tag); } } // 应用其他筛选条件 where = where .WhereIF(!string.IsNullOrWhiteSpace(author), x => x.Author == author) .WhereIF(start.HasValue, x => x.SyncTime >= start.Value) .WhereIF(end.HasValue, x => x.SyncTime <= end.Value) .WhereIF(!string.IsNullOrWhiteSpace(viedoType) && viedoType != "*", x => x.ViedoType == viedoType) .WhereIF(isDeleted.HasValue && isDeleted.Value, x => string.IsNullOrWhiteSpace(x.VideoSavePath)) // 已删除:videoSavePath为空 .WhereIF(isDeleted.HasValue && !isDeleted.Value, x => !string.IsNullOrWhiteSpace(x.VideoSavePath)); // 未删除:videoSavePath不为空 var totalCount = await where.CountAsync(); // 构建排序逻辑 var isAsc = !string.IsNullOrWhiteSpace(sortOrder) && sortOrder.ToLower() == "asc"; var query = where; // 调试日志 Console.WriteLine($"Repository排序参数 - sortField: {sortField}, sortOrder: {sortOrder}, isAsc: {isAsc}"); if (!string.IsNullOrWhiteSpace(sortField)) { switch (sortField.ToLower()) { case "synctime": query = isAsc ? query.OrderBy(x => x.SyncTime) : query.OrderByDescending(x => x.SyncTime); Console.WriteLine($"应用排序: SyncTime {(isAsc ? "升序" : "降序")}"); break; case "viedotype": query = isAsc ? query.OrderBy(x => x.ViedoType) : query.OrderByDescending(x => x.ViedoType); Console.WriteLine($"应用排序: ViedoType {(isAsc ? "升序" : "降序")}"); break; case "viedocate": // 视频类型需要按Tag1和Tag2排序,SqlSugar使用OrderBy链式调用 if (isAsc) { query = query.OrderBy(x => x.Tag1).OrderBy(x => x.Tag2); } else { query = query.OrderByDescending(x => x.Tag1).OrderByDescending(x => x.Tag2); } Console.WriteLine($"应用排序: ViedoCate {(isAsc ? "升序" : "降序")}"); break; case "author": query = isAsc ? query.OrderBy(x => x.Author) : query.OrderByDescending(x => x.Author); Console.WriteLine($"应用排序: Author {(isAsc ? "升序" : "降序")}"); break; case "videotitle": query = isAsc ? query.OrderBy(x => x.VideoTitle) : query.OrderByDescending(x => x.VideoTitle); Console.WriteLine($"应用排序: VideoTitle {(isAsc ? "升序" : "降序")}"); break; case "dyuser": // 用户字段需要先查询用户信息,这里先按CookieId排序,后续会设置DyUser query = isAsc ? query.OrderBy(x => x.CookieId) : query.OrderByDescending(x => x.CookieId); Console.WriteLine($"应用排序: DyUser {(isAsc ? "升序" : "降序")}"); break; default: // 默认按同步时间降序 query = query.OrderByDescending(x => x.SyncTime); Console.WriteLine($"未识别的排序字段,使用默认排序: SyncTime 降序"); break; } } else { // 默认按同步时间降序 query = query.OrderByDescending(x => x.SyncTime); Console.WriteLine("无排序字段,使用默认排序: SyncTime 降序"); } var list = await query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(); Console.WriteLine($"查询完成,返回 {list.Count} 条记录"); if (list.Any()) { Console.WriteLine($"第一条记录的同步时间: {list.First().SyncTime}"); Console.WriteLine($"最后一条记录的同步时间: {list.Last().SyncTime}"); } if (list.Any()) { var users= await this.Db.Queryable().ToListAsync(); foreach (var item in list) { var user= users.FirstOrDefault(x=>x.Id== item.CookieId); if(user!=null) { item.DyUser = user.UserName; } } } return (list, totalCount); } } }