Files
dysync/repository/DyCollectVideoRepository.cs
T
yuming b328e82eb2 feat: 视频预览/数据看板/下载配置 三项业务功能
- 新增视频预览:VideoPlayer 组件、VideoController/DyCollectVideoService/Repository、VideoPageRequestDTO 对应后端改动
- 新增数据看板:workplace/statics.vue、RecordTable、相关 store/http/axios 改动
- 新增下载配置:DownloadConfigService、ConfigController、AppSet.vue、AppConfig
- 其他:DyHttpClientService / 同步 Job(Collect, Favorit) / Cookie 表 / CommonService / ServiceExtension 的配套调整
- 仓库卫生:.gitignore 追加 feiniu 过滤;运维脚本归档到 docs/scripts/
2026-04-25 00:22:33 +08:00

259 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using dy.net.model;
using SqlSugar;
using System.Linq.Expressions;
namespace dy.net.repository
{
public class DyCollectVideoRepository : BaseRepository<DyCollectVideo>
{
// 注入SQLSugar客户端
public DyCollectVideoRepository(ISqlSugarClient db) : base(db)
{
}
/// <summary>
/// 分页查询收藏视频
/// </summary>
/// <param name="pageIndex">页码(从1开始)</param>
/// <param name="pageSize">每页数量</param>
/// <param name="tag">可选标签过滤(单个,兼容旧版本)</param>
/// <param name="tags">可选标签过滤(多个)</param>
/// <param name="author">可选作者过滤</param>
/// <param name="isDeleted">删除状态筛选:null=全部,true=已删除(videoSavePath为空),false=未删除(videoSavePath不为空)</param>
/// <param name="sortField">排序字段:syncTime-同步时间, viedoType-同步类型, viedoCate-视频类型, author-作者, videoTitle-视频名称, dyUser-用户</param>
/// <param name="sortOrder">排序方向:asc-升序, desc-降序</param>
/// <returns>分页结果(视频列表和总数)</returns>
public async Task<(List<DyCollectVideo> list, int totalCount)> GetPagedAsync(int pageIndex, int pageSize, string tag = null, List<string> tags = null, string author = null,string viedoType=null, List<string> 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<DyCollectVideo>();
// 支持多个标签筛选(优先使用 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<string>();
// 获取所有视频(先应用其他筛选条件)
var allVideos = await this.Db.Queryable<DyCollectVideo>()
.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<DyCollectVideo>()
.Where(x => matchingVideoIds.Contains(x.Id));
}
else
{
// 如果没有匹配的数据,返回空结果
where = this.Db.Queryable<DyCollectVideo>().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<string>();
// 获取所有视频
var allVideos = await this.Db.Queryable<DyCollectVideo>()
.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<DyCollectVideo>()
.Where(x => matchingVideoIds.Contains(x.Id));
}
else
{
// 如果没有匹配的数据,返回空结果
where = this.Db.Queryable<DyCollectVideo>().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<DyUserCookies>().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);
}
}
}