diff --git a/VideoAnalysis/Components/Layouts/BasicLayout.razor.cs b/VideoAnalysis/Components/Layouts/BasicLayout.razor.cs index a53b2c2..232e6f2 100644 --- a/VideoAnalysis/Components/Layouts/BasicLayout.razor.cs +++ b/VideoAnalysis/Components/Layouts/BasicLayout.razor.cs @@ -49,6 +49,7 @@ namespace VideoAnalysisRazor.Layouts Name = "课堂指标", Key = "EvaluationProject", Icon = "question-circle", + HideInMenu = true, }, new MenuDataItem { @@ -63,6 +64,14 @@ namespace VideoAnalysisRazor.Layouts Name = "视频任务预览", Key = "VideoTaskShow", HideInMenu = true, + }, + new MenuDataItem + { + Path = "/NodeSubscriptionPage", + Name = "文件订阅", + Key = "NodeSubscriptionPage", + Icon="clock-circle", + HideInMenu = false, } ]; } diff --git a/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor b/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor new file mode 100644 index 0000000..49f3032 --- /dev/null +++ b/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor @@ -0,0 +1,56 @@ +@page "/NodeSubscriptionPage" +@using AntDesign +@using AntDesign.TableModels +@using System.ComponentModel.DataAnnotations +@using SqlSugar +@using VideoAnalysisCore.Model +@using UserCenter.Model.Enum + + + + + + + + + + + + + + + + + + + +
+ +@{ + RenderFragment modelfooter = @; +} + + +
+ + + + + + + +
+
+@code +{ + +} \ No newline at end of file diff --git a/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor.cs b/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor.cs new file mode 100644 index 0000000..d2da975 --- /dev/null +++ b/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor.cs @@ -0,0 +1,132 @@ +using AntDesign; +using AntDesign.TableModels; +using FreeRedis; +using Learn.VideoAnalysis.Controllers.Dto; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Web; +using SqlSugar; +using System.Drawing; +using System.Linq.Expressions; +using System.Reflection; +using UserCenter.Model; +using UserCenter.Model.Enum; +using VideoAnalysisCore.Common; +using VideoAnalysisCore.Model.Enum; +using VideoAnalysisCore.Model; + + +namespace Learn.VideoAnalysis.Components.Pages +{ + public partial class NodeSubscriptionPage : ComponentBase + { + + [Inject] private ConfirmService ComfirmService { get; set; } = default!; + [Inject] private ModalService ModalService { get; set; } = default!; + [Inject] private Repository criteria { get; set; } = default!; + [Inject] private INotificationService _notice { get; set; } = default!; + + + IEnumerable _selectedRows = []; + ITable _table; + IForm? form; + + List _dataSource = null; + RefAsync _total = 0; + + bool tableLoading = false; + Table tableRef; + List _editSource = null; + + + bool modalShow =false; + bool modalBtnLoading = false; + NodeSubscription rowData; + SubjectEnum editSubject; + + async void SubjectEnumSelect() + { + _editSource = await criteria.GetListAsync(x => x.Subject == editSubject); + await this.InvokeAsync(StateHasChanged); + } + void EditAddRow() + { + if (form is not null && form.Validate()) + { + var data = rowData; + data.Subject = editSubject; + if (_editSource is null) + _editSource = new() { data }; + else + _editSource.Add(data); + rowData = new(); + StateHasChanged(); + } + } + /// + /// 新增或者修改 + /// + void StartEdit(NodeSubscription data) + { + rowData = data?? new(); + modalShow = true; + } + + async Task EditOnOkAsync() + { + var data = rowData; + modalBtnLoading = true; + await criteria.DeleteAsync(s => s.Subject == editSubject); + await criteria.InsertRangeAsync(_editSource); + + _table.ReloadData(); + modalShow = false; + modalBtnLoading = false; + StateHasChanged(); + + } + /// + /// 分页 查询 筛选 时 + /// + /// + async void OnChange(QueryModel query) + { + tableLoading = true; + List where = default!; + if (query.FilterModel != null && ((query.FilterModel?.Count() ?? 0) > 0)) + { + where = query.ToSqlSugerWhere(); + } + _dataSource = await criteria.AsQueryable() + .Where(where) + .ToPageListAsync(query.PageIndex, query.PageSize, _total); + tableLoading = false; + StateHasChanged(); + + } + /// + /// 删除行 + /// + /// + /// + async Task Delete(NodeSubscription row) + { + if (!await Comfirm($"确定要删除这条数据吗? [{row.NodeId}]?")) + return; + await criteria.DeleteByIdAsync(row.Id); + _table.ReloadData(); + } + /// + /// 初始化 + /// + protected override void OnInitialized() + { + } + + private async Task Comfirm(string message) + { + return await ComfirmService.Show(message, "提示", ConfirmButtons.YesNo, ConfirmIcon.Warning) == ConfirmResult.Yes; + } + + } + +} diff --git a/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor.css b/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor.css new file mode 100644 index 0000000..a36c3a8 --- /dev/null +++ b/VideoAnalysis/Components/Pages/NodeSubscriptionPage.razor.css @@ -0,0 +1,9 @@ +input[aria-hidden="true"] { + display: none !important; +} +.displayNone { + display:none !important; +} +.ant-table-pagination { + display:none !important; +} diff --git a/VideoAnalysis/Expand/CoravelExpand.cs b/VideoAnalysis/Expand/CoravelExpand.cs index 06a2727..01ab627 100644 --- a/VideoAnalysis/Expand/CoravelExpand.cs +++ b/VideoAnalysis/Expand/CoravelExpand.cs @@ -25,7 +25,7 @@ namespace Learn.VideoAnalysis.Expand provider.UseScheduler(scheduler => { //每5分钟执行一次 未处理视频扫描 - //scheduler.Schedule().EveryFiveMinutes(); + scheduler.Schedule().EveryFiveMinutes(); //每天两点 scheduler.Schedule().DailyAtHour(2); }); diff --git a/VideoAnalysis/Expand/SqlSugarExpand.cs b/VideoAnalysis/Expand/SqlSugarExpand.cs index fd80c3b..41a6fe5 100644 --- a/VideoAnalysis/Expand/SqlSugarExpand.cs +++ b/VideoAnalysis/Expand/SqlSugarExpand.cs @@ -157,7 +157,7 @@ namespace Learn.VideoAnalysis.Expand foreach (var t in entityTypes) { Console.Write($"【1】{entityTypes.Count()}/{(++i).ToString().PadLeft(totalCount, '0')} 执行 {t.FullName}".PadRight(60, ' ')); - DbScoped.SugarScope.CodeFirst.InitTables(t); + DbScoped.Sugar.CodeFirst.InitTables(t); Console.WriteLine($"【√】"); } Console.WriteLine($"【1】数量{entityTypes.Count()} 执行完毕"); diff --git a/VideoAnalysis/Learn.VideoAnalysis.csproj b/VideoAnalysis/Learn.VideoAnalysis.csproj index bb84fdb..1b9556b 100644 --- a/VideoAnalysis/Learn.VideoAnalysis.csproj +++ b/VideoAnalysis/Learn.VideoAnalysis.csproj @@ -43,6 +43,9 @@ + + true + true diff --git a/VideoAnalysis/Program.cs b/VideoAnalysis/Program.cs index 3587e85..a4e7bbf 100644 --- a/VideoAnalysis/Program.cs +++ b/VideoAnalysis/Program.cs @@ -58,6 +58,7 @@ namespace Learn.VideoAnalysis //ʼ builder.Services.AddSqlSugarExpand(); + builder.Services.AddDownloadFileExpand(2); builder.Services.AddAlibabaCloudVod(); builder.Services.AddRedisExpand(); builder.Services.AddSpeakerAI(); @@ -93,6 +94,7 @@ namespace Learn.VideoAnalysis builder.Services.Configure(builder.Configuration.GetSection("ProSettings")); builder.Services.AddHttpClient(); + builder.Services.AddHttpContextAccessor(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); //builder.Services.AddSingleton(); diff --git a/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs b/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs index faf8b6a..cf92404 100644 --- a/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs +++ b/VideoAnalysisCore/AICore/FFMPGE/FFMPGEHandle.cs @@ -33,7 +33,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE public static async Task Audio2WAV16KAsync(string task) { Task = task; - var filePath = await DbScoped.SugarScope + var filePath = await DbScoped.Sugar .Queryable() .Where(s => s.Id == long.Parse(task)) .Select(s=>s.LocalMediaPath).FirstAsync(); diff --git a/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs b/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs index e747dce..f1cc766 100644 --- a/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs +++ b/VideoAnalysisCore/AICore/GPT/DeepSeek/DeepSeek_GPT.cs @@ -88,7 +88,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek throw new Exception("未能找到对应知识点=>" + fileNameInfoRes.授课章节); //提升到父级 var kInfo = await knowledgeInfoDB.GetByIdAsync(know.Parent_Id); - var knowledgeInfos = await knowledgeInfoDB.AsQueryable().ToChildListAsync(s => s.Parent_Id, kInfo.Parent_Id == 0? kInfo.Id: kInfo.Parent_Id); + var knowledgeInfos = await knowledgeInfoDB.AsQueryable().ToChildListAsync(s => s.Parent_Id, kInfo.Parent_Id == 0 ? kInfo.Id : kInfo.Parent_Id); var knows = string.Join(',', knowledgeInfos.Select(s => s.Id + "|" + s.Name)); var knowDic = knowledgeInfos .OrderBy(s => s.Id) @@ -112,15 +112,17 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek var resFormat = """[{"StartTime":开始秒(number),"Theme":主题(string),"Content":内容总结(string)}]"""; var postMessages = - $"你的任务是分析视频字幕内容并提取出中国高考考试试题方法点,然后分析出<知识块>,来帮助学生快速了解视频字幕的内容" + + $"你的任务是分析视频字幕内容并提取出中国高考考试试题方法点,然后分析出<知识块>来帮助学生快速了解视频字幕的内容。" + $"通过阅读并理解字幕内容.然后识别出{subject}学科中属于{fileNameInfoRes.授课章节}章节相关的时间段。" + $"关联合并知识内容相似的知识点来合并为<知识块>。" + $"分配空余未使用的时间段到内容相近的<知识块>时间区间来获取更加详细的上下文,但是请避免<知识块>之间时间重合。" + - $"字幕格式(开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。字幕列表 {captions.Captions}。" + - $"最后请检查某些<知识块>之间的过渡是否自然,如果<知识块>时长超过500秒则考虑拆封为两个更加贴切的<知识块>.或者<知识块>时长小于30秒则考虑合并<知识块>到相邻的<知识块>)。" + + $"字幕格式(开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。" + + $"字幕列表 {captions.Captions}。" + + $"最后请检查某些<知识块>之间的过渡是否自然,如果<知识块>时长超过500秒则考虑拆封为两个更加贴切的<知识块>。" + + $"请检查<知识块>时长小于30秒则考虑合并<知识块>到相邻的<知识块>)。" + $"输出内容只返回json格式({resFormat})"; - Console.WriteLine(DateTime.Now + "=>开始分析视频内容"); + Console.WriteLine(DateTime.Now + "=>1.开始分析视频内容"); questionRes = await ChatAsync(task, postMessages, null); @@ -130,54 +132,55 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek var thems = JsonSerializer.Serialize(questionRes.Adapt());// string.Join(',', questionRes.Select(s => s.StartTime + "->" + s.Theme)); var checkResFormat1 = """[{"StartTime":开始秒(number),"KnowPoint":知识点名称(string),"KnowPointId":知识点Id(string)}]"""; - var knowStr = string.Join(',', knowledgeInfos.Select(s => s.Name)); var knowMessages = $"我针对视频<{title}>分析出了一些视频的知识片段,现在需要你帮我将每个片段分配恰当的知识点(单个片段允许多个知识点用逗号','分割)。" + $"这是我的分段 {thems}。" + $"提供的知识点名称({knows})。 格式 (方法点Id|方法点名称) " + $"最后请确保分配的知识点是用户提供的,否则片段知识点值留空!。" + $"输出内容只返回json格式({checkResFormat1})"; - Console.WriteLine(DateTime.Now + "=>开始分析视频内容知识点"); + Console.WriteLine(DateTime.Now + "=>2.开始分析视频内容知识点"); var konwRes = await ChatAsync(task, knowMessages, null); - + for (int i = 0; i < konwRes.Count(); i++) + questionRes[i].KnowPoint = konwRes[i].KnowPoint; + for (int i = 0; i < questionRes.Length; i++) + { + var item = questionRes[i]; + if (i == questionRes.Length - 1) + item.EndTime = maxVideoTime; + else + item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1; + } + thems = JsonSerializer.Serialize(questionRes.Adapt()); var checkResFormat = """{"Score":打分(number),"Evaluation":评价(string)""";//,"Data":优化后的分段(array)}"""; - var checkMessage = "我为视频的讲解内容做了一些分段,你能帮我检查下这些分段的时间,主题,知识点分配是否合理符合实际吗?" + - $"请给出你的打分(0-100,70分及格)以及打分原因" +//,并且给出优化后的分段 分段格式(${checkResFormat1})" + - //$"如果不合理的话强帮我修改优化他们(注意优化知识点时只允许使用已存在的知识点不允许杜撰猜测捏造)" + - $"这是我的分段 {thems}." + + var checkMessage = "我为视频的讲解内容做了一些分段,希望你能通读字幕内容后检查下的分段是否符合我的要求?" + + $"检查这些分段的时间是否合理 与相邻的时间段间隔是否处于合理区间30~900秒之间?" + + $"分段的主题内容,知识点分配是否合理符合实际吗?" + + $"请给出你的打分(0-100,70分及格)以及打分原因。" + + $"这是我的分段 {thems}。" + $"后续的内容是包含时间戳的视频字幕的固定格式文本。" + $"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).以下是包含时间的视频字幕文本。字幕列表 {captions.Captions}。" + $"最后输出格式为json({checkResFormat})"; - Console.WriteLine(DateTime.Now + "=>开始检查视频分段结果"); + Console.WriteLine(DateTime.Now + "=>3.开始检查视频分段结果"); var checkRes = await ChatAsync(task, checkMessage, null); - if (checkRes != null && checkRes.Score >= 80 && questionRes.Count() == checkRes.Data.Count()) + if (checkRes != null && checkRes.Score >= 80) { - for (int i = 0; i < checkRes.Data.Count(); i++) - { - questionRes[i].Theme = checkRes.Data[i].Theme; - questionRes[i].StartTime = checkRes.Data[i].StartTime; - } break; } else { - - Console.WriteLine(DateTime.Now + $"=>{task} 得分过低/分段长度不匹配 得分{checkRes?.Score} 长度 {questionRes.Count()}/{checkRes.Data.Count()}"); + Console.WriteLine(DateTime.Now + $"=>{task} 得分过低/分段长度不匹配 得分{checkRes?.Score} "); Console.WriteLine(checkRes.Evaluation); Console.WriteLine(); } + if (questionRes.Any(s => s.KeepTime < 30)) + { + Console.WriteLine(DateTime.Now + "=>视频分段过短!! 重新进行AI分析"); + continue; + } } - for (int i = 0; i < questionRes.Length; i++) - { - var item = questionRes[i]; - if (i == questionRes.Length - 1) - item.EndTime = maxVideoTime; - else - item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1; - } //todo 未包含的知识点片段 如何处理 var insertData = questionRes diff --git a/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs b/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs index 3ceac26..1961817 100644 --- a/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs +++ b/VideoAnalysisCore/AICore/SherpaOnnx/SenseVoice.cs @@ -262,13 +262,16 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量"+ res.Count); var captionsStr = JsonSerializer.Serialize(res); - await DbScoped.SugarScope + await DbScoped.Sugar .Updateable() .SetColumns(it => it.Captions == captionsStr) .Where(it => it.Id == long.Parse(task)) .ExecuteCommandAsync(); await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res); //RedisExpand.InsertChannel(Enum.RedisChannelEnum.ParsingSpeaker, task); + //分析完成视频字幕后继续接收任务 + RedisExpand.NewTask(); + RedisExpand.InsertChannel(RedisChannelEnum.ChatModelAnalysis, task); } diff --git a/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs b/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs index 034e045..13983e8 100644 --- a/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs +++ b/VideoAnalysisCore/AICore/SherpaOnnx/Speaker.cs @@ -78,7 +78,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx var res = segments.Select(s => new OfflineSpeakerRes(s)); await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res); var speakerStr = JsonSerializer.Serialize(res); - DbScoped.SugarScope + DbScoped.Sugar .Updateable() .SetColumns(it => it.Speaker == speakerStr) .Where(it => it.Id == long.Parse(task)); diff --git a/VideoAnalysisCore/Common/DownloadFile.cs b/VideoAnalysisCore/Common/DownloadFile.cs index 16b319b..04a6fb6 100644 --- a/VideoAnalysisCore/Common/DownloadFile.cs +++ b/VideoAnalysisCore/Common/DownloadFile.cs @@ -1,5 +1,6 @@ using AntDesign; using Downloader; +using Microsoft.Extensions.DependencyInjection; using SqlSugar; using SqlSugar.IOC; using System; @@ -8,22 +9,35 @@ using System.Diagnostics; using System.IO; using System.Net; using System.Threading.Tasks; +using VideoAnalysisCore.Job; using VideoAnalysisCore.Model; using VideoAnalysisCore.Model.Enum; namespace VideoAnalysisCore.Common { + public static class DownloadFileExpand + { + /// + /// 初始化下载器 + /// + /// 下载速度mb/s 默认8 + public static void AddDownloadFileExpand(this IServiceCollection services, int DownloadSpeed) + { + DownloadFile.DownloadSpeed = DownloadSpeed; + services.AddSingleton(); + } + + } /// /// /// public class DownloadFile { - static DownloadConfiguration Opt { get; set; } = default!; - /// - /// 初始化下载器 - /// - /// 下载速度mb/s 默认8 - static void Init(int DownloadSpeed = 8) + static DownloadConfiguration Opt { get; set; } = default!; + public static int DownloadSpeed { get; set; } = default!; + private readonly Repository videoTaskDB; + + public DownloadFile(Repository videoTaskDB) { Opt = new DownloadConfiguration() { @@ -77,6 +91,7 @@ namespace VideoAnalysisCore.Common //} } }; + this.videoTaskDB = videoTaskDB; } // 根据 Content-Type 映射文件后缀 @@ -103,15 +118,15 @@ namespace VideoAnalysisCore.Common /// /// /// - public static async Task RunTask(string task) + public async Task RunTask(string task) { - if (Opt is null) - Init(); var taskId = long.Parse(task); //获取资源文件 地址 - var fileUrl =await DbScoped.SugarScope.Queryable() - .Where(s => s.Id == taskId) - .Select(s=>s.MediaUrl).FirstAsync(); + var taskInfo =await videoTaskDB.AsQueryable() + .Where(s => s.Id == taskId).FirstAsync(); + if (taskInfo is null || string.IsNullOrEmpty(taskInfo.MediaName) || taskInfo.MediaName.Contains("教研")) + throw new Exception($"任务为null/是教研视频/没有视频课程名称"); + var fileUrl = taskInfo.MediaUrl; if (string.IsNullOrEmpty(fileUrl)) throw new Exception($"任务id[{task}] 资源地址无效 {fileUrl}"); @@ -128,8 +143,8 @@ namespace VideoAnalysisCore.Common var outputPath = Path.Combine(localPath, task + fileExtension); if (!Directory.Exists(localPath)) Directory.CreateDirectory(localPath); - await DbScoped.SugarScope - .Updateable() + await videoTaskDB + .AsUpdateable() .SetColumns(it => it.LocalMediaPath == outputPath) .Where(it => it.Id == long.Parse(task)) .ExecuteCommandAsync(); diff --git a/VideoAnalysisCore/Common/RedisExpand.cs b/VideoAnalysisCore/Common/RedisExpand.cs index 5bae5bb..18c3e84 100644 --- a/VideoAnalysisCore/Common/RedisExpand.cs +++ b/VideoAnalysisCore/Common/RedisExpand.cs @@ -180,7 +180,7 @@ namespace VideoAnalysisCore.Common if (gptRes is null) throw new Exception("未能读取到GPT处理结果"); - var taskData = await DbScoped.SugarScope.Queryable() + var taskData = await DbScoped.Sugar.Queryable() .FirstAsync(s => s.Id == tId); if (taskData.Captions == "[]") taskData.Captions = (await Redis.HMGetAsync(RedisExpandKey.Task(task), "Captions")).First(); @@ -193,7 +193,7 @@ namespace VideoAnalysisCore.Common taskData.ChatAnalysisScore = gptRes?.Assessment?.Merit?.Sum(s => s.Score) ?? 0; taskData.ErrorMessage = string.Empty; taskData.LastEnum = RedisChannelEnum.EndTask; - await DbScoped.SugarScope.Updateable(taskData) + await DbScoped.Sugar.Updateable(taskData) .UpdateColumns(it => new { it.ChatAnalysis, @@ -205,9 +205,7 @@ namespace VideoAnalysisCore.Common it.LastEnum, }).ExecuteCommandAsync(); - - await Redis.DelAsync(RedisExpandKey.IDTask); - await ReceivingTaskAsync(); + //NewTask(); } /// @@ -218,8 +216,16 @@ namespace VideoAnalysisCore.Common if (Redis is null) throw new Exception("redis未初始化"); SubscribeList.Add(RedisChannelEnum.DownloadFile, - (msg) => { TouchChannel(RedisChannelEnum.DownloadFile, msg, DownloadFile.RunTask); }); - + (msg) => { TouchChannel(RedisChannelEnum.DownloadFile, msg, + (task) => + { + using var scope = AppCommon.Services?.CreateScope(); + if (scope is null || scope.ServiceProvider.GetService() is null) + throw new Exception("DownloadFile 未注入"); + else + return scope.ServiceProvider.GetService()?.RunTask(task) ?? Task.CompletedTask; + }); + }); SubscribeList.Add(RedisChannelEnum.SeparateAudio, (msg) => { TouchChannel(RedisChannelEnum.SeparateAudio, msg, FFMPGEHandle.Audio2WAV16KAsync); }); @@ -247,6 +253,19 @@ namespace VideoAnalysisCore.Common await ReceivingTaskAsync(); } + /// + /// 重新执行新任务 + /// + /// + public static void NewTask() + { + Task.Run(async () => + { + await Redis.DelAsync(RedisExpandKey.IDTask); + await ReceivingTaskAsync(); + }); + } + /// /// 重新接收新任务 /// @@ -297,7 +316,7 @@ namespace VideoAnalysisCore.Common Redis.HMSet(RedisExpandKey.Task(taskID), "ErrorMessage", error); - return await DbScoped.SugarScope.Updateable() + return await DbScoped.Sugar.Updateable() .SetColumns(it => it.ErrorMessage == error)//SetColumns是可以叠加的 写2个就2个字段赋值 .Where(it => it.Id == taskID) .ExecuteCommandAsync() == 1; @@ -323,10 +342,14 @@ namespace VideoAnalysisCore.Common { Redis.HMSet(RedisExpandKey.Task(taskId), "LastEnum", key); Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", 0); - await DbScoped.SugarScope.Updateable() - .SetColumns(it => it.LastEnum == key) - .Where(it => it.Id == tID) - .ExecuteCommandAsync(); + lock (Redis) + { + DbScoped.Sugar.Updateable() + .SetColumns(it => it.LastEnum == key) + .Where(it => it.Id == tID) + .ExecuteCommand(); + + } await action(taskId); return; } diff --git a/VideoAnalysisCore/Common/Repository.cs b/VideoAnalysisCore/Common/Repository.cs index e31ffe5..d990a64 100644 --- a/VideoAnalysisCore/Common/Repository.cs +++ b/VideoAnalysisCore/Common/Repository.cs @@ -23,15 +23,15 @@ namespace VideoAnalysisCore.Common var t = typeof(T); if (CID.ContainsKey(t)) { - base.Context = DbScoped.SugarScope.GetConnectionScope(CID[t]); + base.Context = DbScoped.Sugar.GetConnectionScope(CID[t]); return; } var c = t.GetCustomAttribute(); if (!CID.ContainsKey(typeof(T))) CID.Add(typeof(T), c?.configId); base.Context = c != null - ? DbScoped.SugarScope.GetConnectionScope(c.configId) - : DbScoped.SugarScope; + ? DbScoped.Sugar.GetConnectionScope(c.configId) + : DbScoped.Sugar; } } } diff --git a/VideoAnalysisCore/Model/NodeSubscription.cs b/VideoAnalysisCore/Model/NodeSubscription.cs index 4f6c826..2a5fa19 100644 --- a/VideoAnalysisCore/Model/NodeSubscription.cs +++ b/VideoAnalysisCore/Model/NodeSubscription.cs @@ -33,11 +33,12 @@ namespace VideoAnalysisCore.Model /// /// 绑定学科 /// - [DisplayName("绑定学科")] + [DisplayName("任务类型")] public TaskTypeEnum TaskType { get; set; } /// /// 学科 /// + [DisplayName("学科")] public SubjectEnum Subject { get; set; } /// /// 是否启用 diff --git a/VideoAnalysisCore/Model/VideoTask.cs b/VideoAnalysisCore/Model/VideoTask.cs index 1217c50..c86455e 100644 --- a/VideoAnalysisCore/Model/VideoTask.cs +++ b/VideoAnalysisCore/Model/VideoTask.cs @@ -101,6 +101,8 @@ namespace VideoAnalysisCore.Model /// 创建时间 /// public DateTime CreateTime { get; set; } = DateTime.Now; + [SugarColumn( IsNullable = true)] + public DateTime EndTime { get; set; } /// /// 开始时间轴 ///