diff --git a/Controllers/ConfigController.cs b/Controllers/ConfigController.cs index 98908cb..e04a002 100644 --- a/Controllers/ConfigController.cs +++ b/Controllers/ConfigController.cs @@ -28,6 +28,18 @@ namespace dy.net.Controllers private readonly DouyinFollowService douyinFollowService; private readonly DouyinCookieService douyinCookieService; + // 定义允许上传的音频扩展名(小写) + private readonly string[] _allowedAudioExtensions = { ".mp3", ".wav" }; + + // 定义允许的音频 MIME 类型(增强验证) + private readonly string[] _allowedAudioMimeTypes = { + "audio/mpeg", "audio/wav" + }; + + // 最大文件大小:20MB(可根据需求调整) + private const long _maxFileSize = 20 * 1024 * 1024; + + public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService) { this.dyCookieService = dyCookieService; @@ -374,5 +386,108 @@ namespace dy.net.Controllers return ApiResult.Fail("请求失败"); } } + + + /// + /// 上传音频文件接口 + /// + /// 要上传的音频文件 + /// 上传结果 + [HttpPost("UploadAudio")] + public IActionResult UploadAudio(IFormFile file) + { + // 1. 验证文件是否为空 + if (file == null || file.Length == 0) + { + return BadRequest(new { success = false, message = "请选择要上传的音频文件" }); + } + + try + { + // 2. 验证文件大小 + if (file.Length > _maxFileSize) + { + return BadRequest(new { success = false, message = $"文件大小超过限制(最大允许 {_maxFileSize / 1024 / 1024}MB)" }); + } + + // 3. 获取文件扩展名并验证 + var fileExtension = Path.GetExtension(file.FileName).ToLower(); + if (!_allowedAudioExtensions.Contains(fileExtension)) + { + return BadRequest(new + { + success = false, + message = $"不支持的音频格式,仅允许:{string.Join(", ", _allowedAudioExtensions)}" + }); + } + + // 4. 验证 MIME 类型(可选但推荐,防止扩展名伪造) + var contentType = file.ContentType.ToLower(); + if (!_allowedAudioMimeTypes.Contains(contentType)) + { + return BadRequest(new + { + success = false, + message = "文件类型验证失败,请上传合法的音频文件" + }); + } + + //先删除 + var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) + .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") + .FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(uploadMp3) && System.IO.File.Exists(uploadMp3)) + { + System.IO.File.Delete(uploadMp3); + } + + + // 5. 生成唯一文件名(避免重复) + var uniqueFileName = $"dysync_default{fileExtension}"; + + // 6. 定义文件保存路径(建议配置在 appsettings.json 中,这里简化处理) + var uploadPath = Path.Combine(AppContext.BaseDirectory, "mp3"); + + // 确保目录存在 + if (!Directory.Exists(uploadPath)) + { + Directory.CreateDirectory(uploadPath); + } + + // 7. 保存文件 + var filePath = Path.Combine(uploadPath, uniqueFileName); + + if (System.IO.File.Exists(filePath)) + { + System.IO.File.Delete(filePath); + } + using (var stream = new FileStream(filePath, FileMode.Create)) + { + file.CopyTo(stream); + } + + // 8. 返回成功结果(可根据需求返回文件路径/URL 等) + return ApiResult.Success(new { fileName = uniqueFileName, filePath }); + } + catch (Exception ex) + { + // 捕获异常并返回错误信息 + return ApiResult.Fail(ex.Message); + } + } + [AllowAnonymous] + [HttpGet("defaudio")] + public async Task GetDefaultAudioUrl() + { + var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3")) + .Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10") + .FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(uploadMp3) && System.IO.File.Exists(uploadMp3)) + { + return File(System.IO.File.ReadAllBytes(uploadMp3), "application/octet-stream", Path.GetFileName(uploadMp3)); + } + return ApiResult.Fail("未上传音频"); + } + } } diff --git a/Controllers/LogsController.cs b/Controllers/LogsController.cs index e614d46..c9e56be 100644 --- a/Controllers/LogsController.cs +++ b/Controllers/LogsController.cs @@ -20,13 +20,13 @@ namespace dy.net.Controllers this.logInfoService = logInfoService; } - [HttpGet] - public async Task GetLog(string type, string date) + [HttpGet("/api/logs/GetLog/{type}/{date}")] + public async Task GetLog([FromRoute]string type, [FromRoute] string date) { var filePath = Path.Combine(webHostEnvironment.IsDevelopment() ? Directory.GetCurrentDirectory() : AppDomain.CurrentDomain.BaseDirectory, "logs", $"log-{type}-{date}.txt"); if (!System.IO.File.Exists(filePath)) { - var msg = $"Log file log-{type}-{date}.txt not found."; + var msg = $"{date},没有发现{type}的日志"; //Serilog.Log.Error(msg); return Ok(msg); } diff --git a/Controllers/VideoController.cs b/Controllers/VideoController.cs index 8d5760f..8b7166d 100644 --- a/Controllers/VideoController.cs +++ b/Controllers/VideoController.cs @@ -4,6 +4,7 @@ using dy.net.service; using dy.net.utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using System; namespace dy.net.Controllers { @@ -270,5 +271,45 @@ namespace dy.net.Controllers var data = await douyinVideoService.DeleteInvalidVideo(); return Ok(data); } + + /// + /// 所有视频重新生成nfo文件 + /// + /// + [HttpGet("renfo")] + public async Task ReCreateNfo() + { + var videos= await douyinVideoService.GetAllAsync(); + if (videos == null || videos.Count == 0) + { + return ApiResult.Success("暂无视频数据需要生成NFO文件"); + } + _ = Task.Run(async () => + { + try + { + var totalCount = videos.Count; + foreach (var video in videos) + { + try + { + NfoFileGenerator.GenerateVideoNfoFile(video); + Serilog.Log.Debug($"刮削视频(Path:{video.VideoSavePath})生成NFO成功!"); + await Task.Delay(50); + } + catch (Exception singleEx) + { + Serilog.Log.Error($"刮削视频(Path:{video.VideoSavePath})生成NFO失败:{singleEx.Message}"); + } + } + } + catch (Exception ex) + { + Serilog.Log.Error($"NFO文件生成任务执行异常:{ex.Message}\n{ex.StackTrace}"); + } + }); + + return ApiResult.Success(); + } } } diff --git a/Properties/PublishProfiles/docker.pubxml.user b/Properties/PublishProfiles/docker.pubxml.user index 564ba8e..b7e593f 100644 --- a/Properties/PublishProfiles/docker.pubxml.user +++ b/Properties/PublishProfiles/docker.pubxml.user @@ -3,7 +3,7 @@ <_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\ - True|2026-01-11T13:25:07.5052845Z||;False|2026-01-11T21:24:27.5744557+08:00||;True|2026-01-11T19:59:15.4734611+08:00||;False|2026-01-11T19:59:04.9543339+08:00||;True|2026-01-11T18:51:30.6649269+08:00||;True|2026-01-08T21:07:57.5094466+08:00||;True|2026-01-08T14:51:18.2266231+08:00||;True|2026-01-08T14:31:55.1137120+08:00||;True|2026-01-08T00:16:24.4451490+08:00||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;True|2026-01-07T22:36:40.0254856+08:00||;False|2026-01-07T22:36:28.8275903+08:00||;True|2026-01-07T21:59:51.4355171+08:00||;True|2026-01-03T21:38:51.4307034+08:00||;True|2026-01-02T19:09:16.9668906+08:00||;False|2026-01-02T19:09:11.7496369+08:00||;True|2026-01-02T15:42:08.2215697+08:00||;True|2026-01-02T09:46:56.1654861+08:00||;True|2026-01-02T09:35:28.0211225+08:00||;True|2026-01-01T23:07:01.9022045+08:00||;False|2026-01-01T23:06:56.0537216+08:00||;True|2026-01-01T22:16:10.2974067+08:00||;True|2026-01-01T22:16:06.2123787+08:00||;False|2026-01-01T22:15:33.3626979+08:00||;True|2026-01-01T22:01:30.7161900+08:00||;True|2026-01-01T21:10:19.3664263+08:00||;True|2026-01-01T21:09:38.6071080+08:00||;True|2025-12-30T11:45:54.5543034+08:00||;True|2025-12-30T09:19:08.3178124+08:00||;True|2025-12-29T18:57:29.7032246+08:00||;True|2025-12-27T14:52:24.4780776+08:00||;False|2025-12-27T14:52:19.5635794+08:00||;True|2025-12-27T14:48:01.6252748+08:00||;False|2025-12-27T14:47:55.7976192+08:00||;True|2025-12-27T14:38:23.9723838+08:00||;True|2025-12-27T13:00:29.8583858+08:00||;True|2025-12-26T22:18:42.4015637+08:00||;True|2025-12-26T22:10:58.5274572+08:00||;True|2025-12-26T22:06:26.3129600+08:00||;True|2025-12-26T22:03:55.6718618+08:00||;False|2025-12-26T22:03:48.3809954+08:00||;True|2025-12-26T22:02:33.1840390+08:00||;True|2025-12-26T22:01:16.1660100+08:00||;True|2025-12-25T00:50:26.1116465+08:00||;True|2025-12-25T00:48:27.3087708+08:00||;True|2025-12-25T00:47:38.4835720+08:00||; + True|2026-01-12T14:04:14.5886955Z||;False|2026-01-12T22:04:08.2008101+08:00||;True|2026-01-12T21:53:46.9947176+08:00||;True|2026-01-12T21:11:15.8358024+08:00||;True|2026-01-12T21:09:51.8663228+08:00||;True|2026-01-11T21:25:07.5052845+08:00||;False|2026-01-11T21:24:27.5744557+08:00||;True|2026-01-11T19:59:15.4734611+08:00||;False|2026-01-11T19:59:04.9543339+08:00||;True|2026-01-11T18:51:30.6649269+08:00||;True|2026-01-08T21:07:57.5094466+08:00||;True|2026-01-08T14:51:18.2266231+08:00||;True|2026-01-08T14:31:55.1137120+08:00||;True|2026-01-08T00:16:24.4451490+08:00||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;True|2026-01-07T22:36:40.0254856+08:00||;False|2026-01-07T22:36:28.8275903+08:00||;True|2026-01-07T21:59:51.4355171+08:00||;True|2026-01-03T21:38:51.4307034+08:00||;True|2026-01-02T19:09:16.9668906+08:00||;False|2026-01-02T19:09:11.7496369+08:00||;True|2026-01-02T15:42:08.2215697+08:00||;True|2026-01-02T09:46:56.1654861+08:00||;True|2026-01-02T09:35:28.0211225+08:00||;True|2026-01-01T23:07:01.9022045+08:00||;False|2026-01-01T23:06:56.0537216+08:00||;True|2026-01-01T22:16:10.2974067+08:00||;True|2026-01-01T22:16:06.2123787+08:00||;False|2026-01-01T22:15:33.3626979+08:00||;True|2026-01-01T22:01:30.7161900+08:00||;True|2026-01-01T21:10:19.3664263+08:00||;True|2026-01-01T21:09:38.6071080+08:00||;True|2025-12-30T11:45:54.5543034+08:00||;True|2025-12-30T09:19:08.3178124+08:00||;True|2025-12-29T18:57:29.7032246+08:00||;True|2025-12-27T14:52:24.4780776+08:00||;False|2025-12-27T14:52:19.5635794+08:00||;True|2025-12-27T14:48:01.6252748+08:00||;False|2025-12-27T14:47:55.7976192+08:00||;True|2025-12-27T14:38:23.9723838+08:00||;True|2025-12-27T13:00:29.8583858+08:00||;True|2025-12-26T22:18:42.4015637+08:00||;True|2025-12-26T22:10:58.5274572+08:00||;True|2025-12-26T22:06:26.3129600+08:00||;True|2025-12-26T22:03:55.6718618+08:00||;False|2025-12-26T22:03:48.3809954+08:00||;True|2025-12-26T22:02:33.1840390+08:00||;True|2025-12-26T22:01:16.1660100+08:00||;True|2025-12-25T00:50:26.1116465+08:00||;True|2025-12-25T00:48:27.3087708+08:00||;True|2025-12-25T00:47:38.4835720+08:00||; \ No newline at end of file diff --git a/app/src/components/layout/FrontView.vue b/app/src/components/layout/FrontView.vue index dd373f8..6ef95e6 100644 --- a/app/src/components/layout/FrontView.vue +++ b/app/src/components/layout/FrontView.vue @@ -31,7 +31,6 @@ const isMobileBrowser = computed(() => { const enforceMobileRoute = () => { const targetMobilePath = '/mobile'; const currentPath = route.path.toLowerCase().trim(); - // 核心规则:手机浏览器 → 强制跳转到/mobile(无论当前路由是什么) if (isMobileBrowser.value) { if (currentPath !== targetMobilePath) { diff --git a/app/src/pages/mobile/MobileDashboard.vue b/app/src/pages/mobile/MobileDashboard.vue index 303fc66..9d38145 100644 --- a/app/src/pages/mobile/MobileDashboard.vue +++ b/app/src/pages/mobile/MobileDashboard.vue @@ -368,7 +368,7 @@ const loadLogDetailContent = (log: LogItem) => { try { const type = log.type.toLowerCase(); const date = log.date; - const requestParams = `type=${type}&date=${date}`; + const requestParams = `${type}/${date}`; useApiStore() .apiGetLogs(requestParams) diff --git a/app/src/pages/mylogs/MyLogs.vue b/app/src/pages/mylogs/MyLogs.vue index 8ef7b53..70120bd 100644 --- a/app/src/pages/mylogs/MyLogs.vue +++ b/app/src/pages/mylogs/MyLogs.vue @@ -1,92 +1,196 @@ + - + +// ========== 可选:日志类型按钮颜色也同步调整(可选) ========== +.type-btn { + :deep(&.ant-btn-primary) { + background: #722ed1 !important; // 日志类型选中用紫色(可改) + border-color: #722ed1 !important; + color: #fff !important; + + &:hover { + background: #8046e0 !important; + border-color: #8046e0 !important; + } + } +} + \ No newline at end of file diff --git a/app/src/pages/set/AppSet.vue b/app/src/pages/set/AppSet.vue index 214bed9..8b8876f 100644 --- a/app/src/pages/set/AppSet.vue +++ b/app/src/pages/set/AppSet.vue @@ -1,12 +1,11 @@ \ No newline at end of file diff --git a/app/src/pages/workplace/RecordTable.vue b/app/src/pages/workplace/RecordTable.vue index 5098e7e..6bac008 100644 --- a/app/src/pages/workplace/RecordTable.vue +++ b/app/src/pages/workplace/RecordTable.vue @@ -71,10 +71,13 @@