From 64aa7a2fdd471ee6b731640af06aedd8429c743b Mon Sep 17 00:00:00 2001 From: acite <1498045907@qq.com> Date: Wed, 27 Aug 2025 15:16:50 +0800 Subject: [PATCH] [feat] Sort query results --- .idea/.idea.Abyss/.idea/workspace.xml | 94 ++++++++++---- .../Controllers/Media/VideoController.cs | 5 +- Abyss/Components/Services/UserService.cs | 2 +- Abyss/Components/Static/Helpers.cs | 120 ++++++++++++++++++ 4 files changed, 191 insertions(+), 30 deletions(-) diff --git a/.idea/.idea.Abyss/.idea/workspace.xml b/.idea/.idea.Abyss/.idea/workspace.xml index f586bdd..59d545e 100644 --- a/.idea/.idea.Abyss/.idea/workspace.xml +++ b/.idea/.idea.Abyss/.idea/workspace.xml @@ -10,10 +10,10 @@ - - + + - { + "keyToString": { + ".NET Launch Settings Profile.Abyss: http.executor": "Run", + ".NET Launch Settings Profile.Abyss: https.executor": "Run", + ".NET Project.AbyssCli.executor": "Run", + "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", + "ModuleVcsDetector.initialDetectionPerformed": "true", + "Publish to folder.Publish Abyss to folder x86.executor": "Run", + "Publish to folder.Publish Abyss to folder.executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", + "RunOnceActivity.git.unshallow": "true", + "XThreadsFramesViewSplitterKey": "0.30266345", + "git-widget-placeholder": "main", + "last_opened_file_path": "/opt/security/https/server", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "preferences.pluginManager", + "vue.rearranger.settings.migration": "true" } -}]]> - +} + - + @@ -85,7 +90,7 @@ - + @@ -147,6 +152,13 @@ + + + + + + + @@ -159,7 +171,10 @@ - + + + + @@ -168,6 +183,29 @@ + + + diff --git a/Abyss/Components/Controllers/Media/VideoController.cs b/Abyss/Components/Controllers/Media/VideoController.cs index 13cc10b..3fccbdd 100644 --- a/Abyss/Components/Controllers/Media/VideoController.cs +++ b/Abyss/Components/Controllers/Media/VideoController.cs @@ -24,7 +24,7 @@ public class VideoController(ILogger logger, ResourceService rs [HttpGet] public async Task GetClass(string token) { - var r = await rs.Query(VideoFolder, token, Ip); + var r = (await rs.Query(VideoFolder, token, Ip))?.SortLikeWindows(); if(r == null) return StatusCode(401, new { message = "Unauthorized" }); @@ -38,6 +38,7 @@ public class VideoController(ILogger logger, ResourceService rs var d = Helpers.SafePathCombine(VideoFolder, klass); if (d == null) return StatusCode(403, new { message = "403 Denied" }); var r = await rs.Query(d, token, Ip); + if (r == null) return StatusCode(401, new { message = "Unauthorized" }); return Ok(r); @@ -64,6 +65,8 @@ public class VideoController(ILogger logger, ResourceService rs var r = await rs.Get(d, token, Ip); if (!r) return StatusCode(403, new { message = "403 Denied" }); + _logger.LogInformation($"Cover found for {id}"); + return PhysicalFile(d, "image/jpeg", enableRangeProcessing: true); } diff --git a/Abyss/Components/Services/UserService.cs b/Abyss/Components/Services/UserService.cs index f53b30d..ad60d98 100644 --- a/Abyss/Components/Services/UserService.cs +++ b/Abyss/Components/Services/UserService.cs @@ -117,7 +117,7 @@ public class UserService Destroy(token); return null; } - _logger.LogInformation($"Validated {userAndIp}"); + // _logger.LogInformation($"Validated {userAndIp}"); return userAndIp?.Split('@')[0]; } _logger.LogWarning($"Validation failed {token}"); diff --git a/Abyss/Components/Static/Helpers.cs b/Abyss/Components/Static/Helpers.cs index 00a24f2..3781aa5 100644 --- a/Abyss/Components/Static/Helpers.cs +++ b/Abyss/Components/Static/Helpers.cs @@ -1,4 +1,7 @@ +using System.Globalization; +using System.Text.RegularExpressions; + namespace Abyss.Components.Static; public static class Helpers @@ -57,4 +60,121 @@ public enum PathType Directory, NotFound, AccessDenied +} + + +public static class StringArrayExtensions +{ + public static string[] SortLikeWindows(this string[] array) + { + if (array == null) return null; + if (array.Length == 0) return array; + + Array.Sort(array, new WindowsFileNameComparer()); + return array; + } + + public static string[] SortLikeWindowsDescending(this string[] array) + { + if (array == null) return null; + if (array.Length == 0) return array; + + Array.Sort(array, new WindowsFileNameComparerDescending()); + return array; + } + + public static void SortLikeWindowsInPlace(this string[] array) + { + if (array == null || array.Length == 0) return; + + Array.Sort(array, new WindowsFileNameComparer()); + } + + public static void SortLikeWindowsDescendingInPlace(this string[] array) + { + if (array == null || array.Length == 0) return; + + Array.Sort(array, new WindowsFileNameComparerDescending()); + } +} + +public class WindowsFileNameComparer : IComparer +{ + private static readonly Regex _regex = new Regex(@"(\d+|\D+)", RegexOptions.Compiled); + private static readonly CompareInfo _compareInfo = CultureInfo.InvariantCulture.CompareInfo; + + public int Compare(string? x, string? y) + { + if (x == null && y == null) return 0; + if (x == null) return -1; + if (y == null) return 1; + if (ReferenceEquals(x, y)) return 0; + + var partsX = _regex.Matches(x); + var partsY = _regex.Matches(y); + + int minLength = Math.Min(partsX.Count, partsY.Count); + + for (int i = 0; i < minLength; i++) + { + string partX = partsX[i].Value; + string partY = partsY[i].Value; + + if (long.TryParse(partX, out long numX) && long.TryParse(partY, out long numY)) + { + int comparison = numX.CompareTo(numY); + if (comparison != 0) return comparison; + } + else + { + int comparison; + if (ContainsChinese(partX) || ContainsChinese(partY)) + { + comparison = _compareInfo.Compare(partX, partY, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace); + } + else + { + comparison = string.Compare(partX, partY, StringComparison.OrdinalIgnoreCase); + } + + if (comparison != 0) return comparison; + } + } + + return partsX.Count.CompareTo(partsY.Count); + } + + private static bool ContainsChinese(string text) + { + if (string.IsNullOrEmpty(text)) return false; + + foreach (char c in text) + { + if (c >= 0x4E00 && c <= 0x9FFF) + return true; + if (c >= 0x3400 && c <= 0x4DBF) + return true; + } + return false; + } +} + +public class WindowsFileNameComparerDescending : IComparer +{ + private static readonly WindowsFileNameComparer _ascendingComparer = new WindowsFileNameComparer(); + + public int Compare(string x, string y) + { + return _ascendingComparer.Compare(y, x); + } +} + +public static class StringNaturalCompare +{ + private static readonly WindowsFileNameComparer _comparer = new WindowsFileNameComparer(); + + public static int Compare(string x, string y) + { + return _comparer.Compare(x, y); + } } \ No newline at end of file