懒得勤快 4 gadi atpakaļ
vecāks
revīzija
df5a86be16

+ 1 - 1
src/Masuit.MyBlogs.Core/Common/CommonHelper.cs

@@ -294,7 +294,7 @@ namespace Masuit.MyBlogs.Core.Common
             var summary = doc.DocumentElement.GetElementsByTagName("p").FirstOrDefault(n => n.TextContent.Length > min)?.TextContent ?? "没有摘要";
             if (summary.Length > length)
             {
-                return summary.Substring(0, length) + "...";
+                return summary[..length] + "...";
             }
 
             return summary;

+ 40 - 41
src/Masuit.MyBlogs.Core/Common/PerfCounter.cs

@@ -11,7 +11,7 @@ namespace Masuit.MyBlogs.Core.Common
     public static class PerfCounter
     {
         public static ConcurrentLimitedQueue<PerformanceCounter> List { get; set; } = new(50000);
-        public static DateTime StartTime { get; set; } = DateTime.Now;
+        public static readonly DateTime StartTime = DateTime.Now;
 
         public static void Init()
         {
@@ -42,16 +42,16 @@ namespace Masuit.MyBlogs.Core.Common
 
         public static PerformanceCounter GetCurrentPerformanceCounter()
         {
-            var time = (long)DateTime.Now.GetTotalMilliseconds();
-            float load = SystemInfo.CpuLoad;
+            var time = DateTime.Now.GetTotalMilliseconds();
+            var load = SystemInfo.CpuLoad;
             var mem = (1 - SystemInfo.MemoryAvailable.ConvertTo<float>() / SystemInfo.PhysicalMemory.ConvertTo<float>()) * 100;
 
-            float read = SystemInfo.GetDiskData(DiskData.Read) / 1024f;
-            float write = SystemInfo.GetDiskData(DiskData.Write) / 1024;
+            var read = SystemInfo.GetDiskData(DiskData.Read) / 1024f;
+            var write = SystemInfo.GetDiskData(DiskData.Write) / 1024;
 
-            float up = SystemInfo.GetNetData(NetData.Received) / 1024;
-            float down = SystemInfo.GetNetData(NetData.Sent) / 1024;
-            var counter = new PerformanceCounter()
+            var up = SystemInfo.GetNetData(NetData.Received) / 1024;
+            var down = SystemInfo.GetNetData(NetData.Sent) / 1024;
+            return new PerformanceCounter()
             {
                 Time = time,
                 CpuLoad = load,
@@ -61,48 +61,47 @@ namespace Masuit.MyBlogs.Core.Common
                 Download = down,
                 Upload = up
             };
-            return counter;
         }
+    }
 
+    /// <summary>
+    /// 性能计数器
+    /// </summary>
+    public class PerformanceCounter
+    {
         /// <summary>
-        /// 性能计数器
+        /// 当前时间戳
         /// </summary>
-        public class PerformanceCounter
-        {
-            /// <summary>
-            /// 当前时间戳
-            /// </summary>
-            public long Time { get; set; }
+        public long Time { get; set; }
 
-            /// <summary>
-            /// CPU当前负载
-            /// </summary>
-            public float CpuLoad { get; set; }
+        /// <summary>
+        /// CPU当前负载
+        /// </summary>
+        public float CpuLoad { get; set; }
 
-            /// <summary>
-            /// 内存使用率
-            /// </summary>
-            public float MemoryUsage { get; set; }
+        /// <summary>
+        /// 内存使用率
+        /// </summary>
+        public float MemoryUsage { get; set; }
 
-            /// <summary>
-            /// 磁盘读
-            /// </summary>
-            public float DiskRead { get; set; }
+        /// <summary>
+        /// 磁盘读
+        /// </summary>
+        public float DiskRead { get; set; }
 
-            /// <summary>
-            /// 磁盘写
-            /// </summary>
-            public float DiskWrite { get; set; }
+        /// <summary>
+        /// 磁盘写
+        /// </summary>
+        public float DiskWrite { get; set; }
 
-            /// <summary>
-            /// 网络上行
-            /// </summary>
-            public float Upload { get; set; }
+        /// <summary>
+        /// 网络上行
+        /// </summary>
+        public float Upload { get; set; }
 
-            /// <summary>
-            /// 网络下行
-            /// </summary>
-            public float Download { get; set; }
-        }
+        /// <summary>
+        /// 网络下行
+        /// </summary>
+        public float Download { get; set; }
     }
 }

+ 1 - 1
src/Masuit.MyBlogs.Core/Controllers/LinksController.cs

@@ -45,7 +45,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public async Task<ActionResult> Apply(Links links, CancellationToken cancellationToken)
         {
-            if (!links.Url.MatchUrl())
+            if (!links.Url.MatchUrl()||links.Url.Contains(Request.Host.Host))
             {
                 return ResultData(null, false, "添加失败!链接非法!");
             }

+ 2 - 1
src/Masuit.MyBlogs.Core/Controllers/PassportController.cs

@@ -7,6 +7,7 @@ using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.MyBlogs.Core.Models.ViewModel;
 using Masuit.Tools;
+using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
 using Masuit.Tools.Core.Net;
 using Masuit.Tools.Security;
@@ -181,7 +182,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             string code = Tools.Strings.ValidateCode.CreateValidateCode(6);
             HttpContext.Session.Set("valid", code); //将验证码生成到Session中
             var buffer = HttpContext.CreateValidateGraphic(code);
-            return this.ResumeFile(buffer, "image/jpeg");
+            return this.ResumeFile(buffer, ContentType.Jpeg, "验证码.jpg");
         }
 
         /// <summary>

+ 5 - 0
src/Masuit.MyBlogs.Core/Controllers/SearchController.cs

@@ -40,6 +40,11 @@ namespace Masuit.MyBlogs.Core.Controllers
         public async Task<ActionResult> Search([FromServices] IPostService postService, string wd = "", [Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")] int page = 1, [Range(1, 50, ErrorMessage = "页大小必须在0到50之间")] int size = 15)
         {
             wd = ChineseConverter.Convert(wd?.Trim() ?? "", ChineseConversionDirection.TraditionalToSimplified);
+            if (wd.Length > 128)
+            {
+                wd = wd[..128];
+            }
+
             ViewBag.PageSize = size;
             ViewBag.Keyword = wd;
             string key = "Search:" + ClientIP;

+ 4 - 3
src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs

@@ -4,6 +4,7 @@ using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.MyBlogs.Core.Models.ViewModel;
 using Masuit.Tools;
+using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.Core.Net;
 using Microsoft.AspNetCore.Mvc;
 using System;
@@ -67,7 +68,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             {
                 Encoding = Encoding.UTF8
             });
-            return Content(rss, "text/xml");
+            return Content(rss, ContentType.Xml);
         }
 
         private void InsertAdvertisement(List<Item> posts, int? cid = null)
@@ -140,7 +141,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             {
                 Encoding = Encoding.UTF8
             });
-            return Content(rss, "text/xml");
+            return Content(rss, ContentType.Xml);
         }
 
         /// <summary>
@@ -186,7 +187,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             {
                 Encoding = Encoding.UTF8
             });
-            return Content(rss, "text/xml");
+            return Content(rss, ContentType.Xml);
         }
     }
 }

+ 21 - 20
src/Masuit.MyBlogs.Core/Controllers/SystemController.cs

@@ -38,7 +38,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public IActionResult GetCounterHistory()
         {
-            var list = PerfCounter.List.Count < 5000 ? PerfCounter.List.OrderBy(c => c.Time) : PerfCounter.List.GroupBy(c => c.Time / 60000).Select(g => new PerfCounter.PerformanceCounter
+            var counters = PerfCounter.List.OrderBy(c => c.Time);
+            var list = counters.Count() < 5000 ? counters : counters.GroupBy(c => c.Time / 60000).Select(g => new PerformanceCounter
             {
                 Time = g.Key * 60000,
                 CpuLoad = g.OrderBy(c => c.CpuLoad).Skip(1).Take(g.Count() - 2).Select(c => c.CpuLoad).DefaultIfEmpty().Average(),
@@ -47,39 +48,39 @@ namespace Masuit.MyBlogs.Core.Controllers
                 Download = g.OrderBy(c => c.Download).Skip(1).Take(g.Count() - 2).Select(c => c.Download).DefaultIfEmpty().Average(),
                 Upload = g.OrderBy(c => c.Upload).Skip(1).Take(g.Count() - 2).Select(c => c.Upload).DefaultIfEmpty().Average(),
                 MemoryUsage = g.OrderBy(c => c.MemoryUsage).Skip(1).Take(g.Count() - 2).Select(c => c.MemoryUsage).DefaultIfEmpty().Average()
-            }).OrderBy(c => c.Time);
+            });
             return Ok(new
             {
                 cpu = list.Select(c => new[]
                 {
-                        c.Time,
-                        c.CpuLoad.ToDecimal(2)
-                    }),
+                    c.Time,
+                    c.CpuLoad.ToDecimal(2)
+                }),
                 mem = list.Select(c => new[]
                 {
-                        c.Time,
-                        c.MemoryUsage.ToDecimal(2)
-                    }),
+                    c.Time,
+                    c.MemoryUsage.ToDecimal(2)
+                }),
                 read = list.Select(c => new[]
                 {
-                        c.Time,
-                        c.DiskRead.ToDecimal(2)
-                    }),
+                    c.Time,
+                    c.DiskRead.ToDecimal(2)
+                }),
                 write = list.Select(c => new[]
                 {
-                        c.Time,
-                        c.DiskWrite.ToDecimal(2)
-                    }),
+                    c.Time,
+                    c.DiskWrite.ToDecimal(2)
+                }),
                 down = list.Select(c => new[]
                 {
-                        c.Time,
-                        c.Download.ToDecimal(2)
-                    }),
+                    c.Time,
+                    c.Download.ToDecimal(2)
+                }),
                 up = list.Select(c => new[]
                 {
-                        c.Time,
-                        c.Upload.ToDecimal(2)
-                    })
+                    c.Time,
+                    c.Upload.ToDecimal(2)
+                })
             });
         }
 

+ 2 - 2
src/Masuit.MyBlogs.Core/Controllers/UploadController.cs

@@ -178,13 +178,13 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         [Route("download")]
         [Route("download/{**path}")]
-        public ActionResult Download(string path)
+        public ActionResult Download([FromServices] IMimeMapper mimeMapper, string path)
         {
             if (string.IsNullOrEmpty(path)) return Content("null");
             var file = Path.Combine(HostEnvironment.WebRootPath, CommonHelper.SystemSettings.GetOrAdd("UploadPath", "upload").Trim('/', '\\'), path.Trim('.', '/', '\\'));
             if (System.IO.File.Exists(file))
             {
-                return this.ResumePhysicalFile(file, Path.GetFileName(file));
+                return this.ResumePhysicalFile(file, mimeMapper.GetMimeFromPath(file), Path.GetFileName(file));
             }
 
             return Content("null");

+ 3 - 2
src/Masuit.MyBlogs.Core/Extensions/Firewall/RequestInterceptMiddleware.cs

@@ -40,10 +40,11 @@ namespace Masuit.MyBlogs.Core.Extensions.Firewall
             request.EnableBuffering();
             if (!AppConfig.EnableIPDirect && request.Host.Host.MatchInetAddress() && !request.Host.Host.IsPrivateIP())
             {
-                context.Response.StatusCode = 404;
+                context.Response.Redirect("https://www.baidu.com", true);
+                //context.Response.StatusCode = 404;
                 return Task.CompletedTask;
             }
-            var ip = context.Connection.RemoteIpAddress.ToString();
+            var ip = context.Connection.RemoteIpAddress!.ToString();
             var path = HttpUtility.UrlDecode(request.Path + request.QueryString, Encoding.UTF8);
             var requestUrl = HttpUtility.UrlDecode(request.Scheme + "://" + request.Host + path);
             var match = Regex.Match(path ?? "", CommonHelper.BanRegex);

+ 1 - 1
src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs

@@ -132,7 +132,7 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             }
 
             post.TotalViewCount += 1;
-            post.AverageViewCount = post.TotalViewCount / (DateTime.Now - post.PostDate).TotalDays;
+            post.AverageViewCount = post.TotalViewCount / Math.Ceiling((DateTime.Now - post.PostDate).TotalDays);
             _postService.SaveChanges();
         }
 

+ 23 - 14
src/Masuit.MyBlogs.Core/Extensions/TranslateMiddleware.cs

@@ -1,5 +1,6 @@
 using Masuit.MyBlogs.Core.Common;
 using Masuit.Tools;
+using Masuit.Tools.AspNetCore.Mime;
 using Microsoft.AspNetCore.Http;
 using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
 using System.IO;
@@ -27,7 +28,7 @@ namespace Masuit.MyBlogs.Core.Extensions
         public Task Invoke(HttpContext context)
         {
             var path = context.Request.Path.Value ?? "";
-            if (path.StartsWith("/_blazor") || path.StartsWith("/api") || context.Request.IsRobot())
+            if (path.StartsWith("/_blazor") || path.StartsWith("/api") || path.StartsWith("/file") || path.StartsWith("/download") || context.Request.IsRobot())
             {
                 return _next(context);
             }
@@ -53,21 +54,29 @@ namespace Masuit.MyBlogs.Core.Extensions
 
         private async Task Traditional(HttpContext context)
         {
-            //设置stream存放ResponseBody
-            var responseOriginalBody = context.Response.Body;
-            var memStream = new MemoryStream();
-            context.Response.Body = memStream;
+            var accept = context.Request.Headers["Accept"][0];
+            if (accept.StartsWith("text") || accept.Contains(ContentType.Json))
+            {
+                //设置stream存放ResponseBody
+                var responseOriginalBody = context.Response.Body;
+                var memStream = new MemoryStream();
+                context.Response.Body = memStream;
 
-            // 执行其他中间件
-            await _next(context);
+                // 执行其他中间件
+                await _next(context);
 
-            //处理执行其他中间件后的ResponseBody
-            memStream.Position = 0;
-            var responseReader = new StreamReader(memStream, Encoding.UTF8);
-            var responseBody = await responseReader.ReadToEndAsync();
-            memStream = new MemoryStream(Encoding.UTF8.GetBytes(ChineseConverter.Convert(responseBody, ChineseConversionDirection.SimplifiedToTraditional)));
-            await memStream.CopyToAsync(responseOriginalBody);
-            context.Response.Body = responseOriginalBody;
+                //处理执行其他中间件后的ResponseBody
+                memStream.Position = 0;
+                var responseReader = new StreamReader(memStream, Encoding.UTF8);
+                var responseBody = await responseReader.ReadToEndAsync();
+                memStream = new MemoryStream(Encoding.UTF8.GetBytes(ChineseConverter.Convert(responseBody, ChineseConversionDirection.SimplifiedToTraditional)));
+                await memStream.CopyToAsync(responseOriginalBody);
+                context.Response.Body = responseOriginalBody;
+            }
+            else
+            {
+                await _next(context);
+            }
         }
     }
 }

+ 11 - 10
src/Masuit.MyBlogs.Core/Infrastructure/Services/PostService.cs

@@ -16,6 +16,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
+using System.Reflection;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 
@@ -130,22 +131,22 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             keyword = Regex.Replace(keyword, @":\s+", ":");
             var fields = new List<string>();
             var newkeywords = new List<string>();
-            if (keyword.Contains("intitle:"))
+            foreach (var item in keyword.Split(' ', ' ').Where(s => s.Contains(new[] { ":", ":" })))
             {
-                fields.Add("Title");
-                newkeywords.Add(keyword.Split(' ', ' ').FirstOrDefault(s => s.Contains("intitle")).Split(':')[1]);
-            }
+                var part = item.Split(':', ':');
+                var field = typeof(Post).GetProperty(part[0], BindingFlags.IgnoreCase)?.Name;
+                if (!string.IsNullOrEmpty(field))
+                {
+                    fields.Add(field);
+                }
 
-            if (keyword.Contains("content:"))
-            {
-                fields.Add("Content");
-                newkeywords.Add(keyword.Split(' ', ' ').FirstOrDefault(s => s.Contains("content")).Split(':')[1]);
+                newkeywords.Add(part[1]);
             }
 
             var searchOptions = fields.Any() ? new SearchOptions(newkeywords.Join(" "), page, size, fields.Join(",")) : new SearchOptions(keyword, page, size, typeof(Post));
-            if (keyword.Contains(new[] { " ", ",", "+", ";" }))
+            if (keyword.Contains(new[] { " ", ",", ";" }))
             {
-                searchOptions.Score = 0.2f;
+                searchOptions.Score = 0.3f;
             }
 
             return searchOptions;

+ 5 - 6
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj

@@ -34,8 +34,8 @@
         <PackageReference Include="CacheManager.StackExchange.Redis" Version="1.2.0" />
         <PackageReference Include="CHTCHSConv" Version="1.0.0" />
         <PackageReference Include="CSRedisCore" Version="3.6.6" />
-        <PackageReference Include="EFCoreSecondLevelCacheInterceptor" Version="2.9.0" />
-        <PackageReference Include="Hangfire" Version="1.7.22" />
+        <PackageReference Include="EFCoreSecondLevelCacheInterceptor" Version="3.1.0" />
+        <PackageReference Include="Hangfire" Version="1.7.23" />
         <PackageReference Include="Hangfire.Autofac" Version="2.3.1" />
         <PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
         <PackageReference Include="htmldiff.net-core" Version="1.3.6" />
@@ -47,20 +47,19 @@
         <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.6" />
         <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="5.0.6" />
         <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="5.0.1" />
-        <PackageReference Include="Microsoft.Graph" Version="3.32.0" />
+        <PackageReference Include="Microsoft.Graph" Version="3.33.0" />
         <PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.6" />
         <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
         <PackageReference Include="OpenXmlPowerTools-NetStandard" Version="4.4.21" />
         <PackageReference Include="MiniProfiler.EntityFrameworkCore" Version="4.2.22" />
         <PackageReference Include="PanGu.HighLight" Version="1.0.0" />
-        <PackageReference Include="Polly" Version="7.2.2" />
         <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0" />
         <PackageReference Include="System.Diagnostics.PerformanceCounter" Version="5.0.1" />
-        <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.9" />
+        <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.10" />
         <PackageReference Include="TimeZoneConverter" Version="3.5.0" />
         <PackageReference Include="WilderMinds.RssSyndication" Version="1.7.0" />
         <PackageReference Include="WinInsider.System.Net.Http.Formatting" Version="1.0.14" />
-        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="5.1.36" />
+        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="5.1.38" />
     </ItemGroup>
     <ItemGroup>
         <Content Update="appsettings.json">

+ 2 - 2
src/Masuit.MyBlogs.Core/Models/Entity/Links.cs

@@ -21,13 +21,13 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// <summary>
         /// 名字
         /// </summary>
-        [Required(ErrorMessage = "站点名不能为空!")]
+        [Required(ErrorMessage = "站点名不能为空!"),MaxLength(32,ErrorMessage = "站点名称最长限制32个字")]
         public string Name { get; set; }
 
         /// <summary>
         /// URL
         /// </summary>
-        [Required(ErrorMessage = "站点的URL不能为空!")]
+        [Required(ErrorMessage = "站点的URL不能为空!"),MaxLength(64,ErrorMessage = "站点的URL限制64个字符")]
         public string Url { get; set; }
 
         /// <summary>

+ 4 - 0
src/Masuit.MyBlogs.Core/PrepareStartup.cs

@@ -27,6 +27,7 @@ using System;
 using System.IO;
 using System.Linq;
 using System.Text.RegularExpressions;
+using System.Threading;
 using System.Threading.Tasks;
 using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 
@@ -46,6 +47,7 @@ namespace Masuit.MyBlogs.Core
 
         internal static void UseLuceneSearch(this IApplicationBuilder app, IHostEnvironment env, IHangfireBackJob hangfire, LuceneIndexerOptions luceneIndexerOptions)
         {
+            var are = new AutoResetEvent(false);
             Task.Run(() =>
             {
                 Console.WriteLine("正在导入自定义词库...");
@@ -62,11 +64,13 @@ namespace Masuit.MyBlogs.Core
                 });
                 Console.WriteLine($"导入自定义词库完成,耗时{time}s");
                 Windows.ClearMemorySilent();
+                are.Set();
             });
 
             string lucenePath = Path.Combine(env.ContentRootPath, luceneIndexerOptions.Path);
             if (!Directory.Exists(lucenePath) || Directory.GetFiles(lucenePath).Length < 1)
             {
+                are.WaitOne();
                 Console.WriteLine("索引库不存在,开始自动创建Lucene索引库...");
                 hangfire.CreateLuceneIndex();
                 Console.WriteLine("索引库创建完成!");

+ 2 - 0
src/Masuit.MyBlogs.Core/Startup.cs

@@ -16,6 +16,7 @@ using Masuit.MyBlogs.Core.Extensions.Hangfire;
 using Masuit.MyBlogs.Core.Infrastructure;
 using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.ViewModel;
+using Masuit.Tools.AspNetCore.Mime;
 using Masuit.Tools.Config;
 using Masuit.Tools.Core.AspNetCore;
 using Masuit.Tools.Core.Net;
@@ -111,6 +112,7 @@ namespace Masuit.MyBlogs.Core
             services.AddMailSender(Configuration).AddFirewallReporter(Configuration);
             services.AddBundling().UseDefaults(_env).UseNUglify().EnableMinification().EnableChangeDetection().EnableCacheHeader(TimeSpan.FromHours(1));
             services.SetupMiniProfile();
+            services.AddSingleton<IMimeMapper, MimeMapper>(p => new MimeMapper());
             services.AddOneDrive();
             services.AddRazorPages();
             services.AddServerSideBlazor();

+ 49 - 47
src/Masuit.MyBlogs.Core/Views/Dashboard/Counter.razor

@@ -3,7 +3,6 @@
 @using System.Net.Sockets
 @using Masuit.MyBlogs.Core.Common
 @using Masuit.Tools
-@using Masuit.Tools.Linq
 @using System.IO
 @inject IJSRuntime JS;
 
@@ -54,11 +53,11 @@
         </tr>
         <tr>
             <td>磁盘总空间</td>
-            <th>@DriveInfo.GetDrives().Select(kv => kv.Name + " " + (kv.TotalSize * 1.0 / 1073741824).ToDecimal(2) + "GB").Join(" | ")</th>
+            <th>@_driveInfos.Select(kv => kv.Name + " " + (kv.TotalSize * 1.0 / 1073741824).ToDecimal(2) + "GB").Join(" | ")</th>
             <td>磁盘剩余空间</td>
-            <th>@DriveInfo.GetDrives().Select(kv => kv.Name + " " + (kv.TotalFreeSpace * 1.0 / 1073741824).ToDecimal(2) + "GB").Join(" | ")</th>
+            <th>@_driveInfos.Select(kv => kv.Name + " " + (kv.TotalFreeSpace * 1.0 / 1073741824).ToDecimal(2) + "GB").Join(" | ")</th>
             <td>磁盘使用率</td>
-            <th>@DriveInfo.GetDrives().Select(kv => kv.Name + " " + (kv.AvailableFreeSpace * 1m / kv.TotalSize).ToString("P")).Join(" | ")</th>
+            <th>@_driveInfos.Select(kv => kv.Name + " " + (kv.AvailableFreeSpace * 1m / kv.TotalSize).ToString("P")).Join(" | ")</th>
         </tr>
         <tr>
             <td>MAC地址</td>
@@ -123,6 +122,7 @@
     private readonly RamInfo memory = SystemInfo.GetRamInfo();
     private readonly IList<string> macs = SystemInfo.GetMacAddress();
     private readonly IList<string> ips = SystemInfo.GetLocalIPs().OrderBy(u => u.Address.AddressFamily != AddressFamily.InterNetwork).Select(a => a.Address.ToString()).ToList();
+    private readonly DriveInfo[] _driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady).ToArray();
 
     protected override void OnInitialized()
     {
@@ -138,7 +138,7 @@
     }
 
     [JSInvokable]
-    public static PerfCounter.PerformanceCounter GetCurrentPerformanceCounter()
+    public static PerformanceCounter GetCurrentPerformanceCounter()
     {
         return PerfCounter.GetCurrentPerformanceCounter();
     }
@@ -151,67 +151,69 @@
 
     public Dictionary<string, dynamic> GetCounterPercent()
     {
+        var counters = PerfCounter.List;
+        var count = counters.Count;
         return new()
         {
             ["CPU使用率(%)"] = new
             {
-                p50 = PerfCounter.List.OrderByDescending(c => c.CpuLoad).Take(PerfCounter.List.Count / 2).MinOrDefault(c => c.CpuLoad).ToString("N2"),
-                p75 = PerfCounter.List.OrderByDescending(c => c.CpuLoad).Take(PerfCounter.List.Count / 4).MinOrDefault(c => c.CpuLoad).ToString("N2"),
-                p90 = PerfCounter.List.OrderByDescending(c => c.CpuLoad).Take(PerfCounter.List.Count / 10).MinOrDefault(c => c.CpuLoad).ToString("N2"),
-                p99 = PerfCounter.List.OrderByDescending(c => c.CpuLoad).Take(PerfCounter.List.Count / 100).MinOrDefault(c => c.CpuLoad).ToString("N2"),
-                p999 = PerfCounter.List.OrderByDescending(c => c.CpuLoad).Take(PerfCounter.List.Count / 1000).MinOrDefault(c => c.CpuLoad).ToString("N2"),
-                average = PerfCounter.List.Average(c => c.CpuLoad).ToString("N2"),
-                stdev = PerfCounter.List.StandardDeviation(c => c.CpuLoad).ToString("N2"),
+                p50 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 2).MinOrDefault(c => c.CpuLoad).ToString("N2"),
+                p75 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 4).MinOrDefault(c => c.CpuLoad).ToString("N2"),
+                p90 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 10).MinOrDefault(c => c.CpuLoad).ToString("N2"),
+                p99 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 100).MinOrDefault(c => c.CpuLoad).ToString("N2"),
+                p999 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 1000).MinOrDefault(c => c.CpuLoad).ToString("N2"),
+                average = counters.Average(c => c.CpuLoad).ToString("N2"),
+                stdev = counters.StandardDeviation(c => c.CpuLoad).ToString("N2"),
             },
             ["内存使用率(%)"] = new
             {
-                p50 = PerfCounter.List.OrderByDescending(c => c.MemoryUsage).Take(PerfCounter.List.Count / 2).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
-                p75 = PerfCounter.List.OrderByDescending(c => c.MemoryUsage).Take(PerfCounter.List.Count / 4).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
-                p90 = PerfCounter.List.OrderByDescending(c => c.MemoryUsage).Take(PerfCounter.List.Count / 10).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
-                p99 = PerfCounter.List.OrderByDescending(c => c.MemoryUsage).Take(PerfCounter.List.Count / 100).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
-                p999 = PerfCounter.List.OrderByDescending(c => c.MemoryUsage).Take(PerfCounter.List.Count / 1000).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
-                average = PerfCounter.List.Average(c => c.MemoryUsage).ToString("N2"),
-                stdev = PerfCounter.List.StandardDeviation(c => c.MemoryUsage).ToString("N2"),
+                p50 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 2).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
+                p75 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 4).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
+                p90 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 10).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
+                p99 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 100).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
+                p999 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 1000).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
+                average = counters.Average(c => c.MemoryUsage).ToString("N2"),
+                stdev = counters.StandardDeviation(c => c.MemoryUsage).ToString("N2"),
             },
             ["磁盘读(KBps)"] = new
             {
-                p50 = PerfCounter.List.OrderByDescending(c => c.DiskRead).Take(PerfCounter.List.Count / 2).MinOrDefault(c => c.DiskRead).ToString("N2"),
-                p75 = PerfCounter.List.OrderByDescending(c => c.DiskRead).Take(PerfCounter.List.Count / 4).MinOrDefault(c => c.DiskRead).ToString("N2"),
-                p90 = PerfCounter.List.OrderByDescending(c => c.DiskRead).Take(PerfCounter.List.Count / 10).MinOrDefault(c => c.DiskRead).ToString("N2"),
-                p99 = PerfCounter.List.OrderByDescending(c => c.DiskRead).Take(PerfCounter.List.Count / 100).MinOrDefault(c => c.DiskRead).ToString("N2"),
-                p999 = PerfCounter.List.OrderByDescending(c => c.DiskRead).Take(PerfCounter.List.Count / 1000).MinOrDefault(c => c.DiskRead).ToString("N2"),
-                average = PerfCounter.List.Average(c => c.DiskRead).ToString("N2"),
-                stdev = PerfCounter.List.StandardDeviation(c => c.DiskRead).ToString("N2"),
+                p50 = counters.OrderByDescending(c => c.DiskRead).Take(count / 2).MinOrDefault(c => c.DiskRead).ToString("N2"),
+                p75 = counters.OrderByDescending(c => c.DiskRead).Take(count / 4).MinOrDefault(c => c.DiskRead).ToString("N2"),
+                p90 = counters.OrderByDescending(c => c.DiskRead).Take(count / 10).MinOrDefault(c => c.DiskRead).ToString("N2"),
+                p99 = counters.OrderByDescending(c => c.DiskRead).Take(count / 100).MinOrDefault(c => c.DiskRead).ToString("N2"),
+                p999 = counters.OrderByDescending(c => c.DiskRead).Take(count / 1000).MinOrDefault(c => c.DiskRead).ToString("N2"),
+                average = counters.Average(c => c.DiskRead).ToString("N2"),
+                stdev = counters.StandardDeviation(c => c.DiskRead).ToString("N2"),
             },
             ["磁盘写(KBps)"] = new
             {
-                p50 = PerfCounter.List.OrderByDescending(c => c.DiskWrite).Take(PerfCounter.List.Count / 2).MinOrDefault(c => c.DiskWrite).ToString("N2"),
-                p75 = PerfCounter.List.OrderByDescending(c => c.DiskWrite).Take(PerfCounter.List.Count / 4).MinOrDefault(c => c.DiskWrite).ToString("N2"),
-                p90 = PerfCounter.List.OrderByDescending(c => c.DiskWrite).Take(PerfCounter.List.Count / 10).MinOrDefault(c => c.DiskWrite).ToString("N2"),
-                p99 = PerfCounter.List.OrderByDescending(c => c.DiskWrite).Take(PerfCounter.List.Count / 100).MinOrDefault(c => c.DiskWrite).ToString("N2"),
-                p999 = PerfCounter.List.OrderByDescending(c => c.DiskWrite).Take(PerfCounter.List.Count / 1000).MinOrDefault(c => c.DiskWrite).ToString("N2"),
-                average = PerfCounter.List.Average(c => c.DiskWrite).ToString("N2"),
-                stdev = PerfCounter.List.StandardDeviation(c => c.DiskWrite).ToString("N2")
+                p50 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 2).MinOrDefault(c => c.DiskWrite).ToString("N2"),
+                p75 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 4).MinOrDefault(c => c.DiskWrite).ToString("N2"),
+                p90 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 10).MinOrDefault(c => c.DiskWrite).ToString("N2"),
+                p99 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 100).MinOrDefault(c => c.DiskWrite).ToString("N2"),
+                p999 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 1000).MinOrDefault(c => c.DiskWrite).ToString("N2"),
+                average = counters.Average(c => c.DiskWrite).ToString("N2"),
+                stdev = counters.StandardDeviation(c => c.DiskWrite).ToString("N2")
             },
             ["网络下载(KBps)"] = new
             {
-                p50 = PerfCounter.List.OrderByDescending(c => c.Download).Take(PerfCounter.List.Count / 2).MinOrDefault(c => c.Download).ToString("N2"),
-                p75 = PerfCounter.List.OrderByDescending(c => c.Download).Take(PerfCounter.List.Count / 4).MinOrDefault(c => c.Download).ToString("N2"),
-                p90 = PerfCounter.List.OrderByDescending(c => c.Download).Take(PerfCounter.List.Count / 10).MinOrDefault(c => c.Download).ToString("N2"),
-                p99 = PerfCounter.List.OrderByDescending(c => c.Download).Take(PerfCounter.List.Count / 100).MinOrDefault(c => c.Download).ToString("N2"),
-                p999 = PerfCounter.List.OrderByDescending(c => c.Download).Take(PerfCounter.List.Count / 1000).MinOrDefault(c => c.Download).ToString("N2"),
-                average = PerfCounter.List.Average(c => c.Download).ToString("N2"),
-                stdev = PerfCounter.List.StandardDeviation(c => c.Download).ToString("N2")
+                p50 = counters.OrderByDescending(c => c.Download).Take(count / 2).MinOrDefault(c => c.Download).ToString("N2"),
+                p75 = counters.OrderByDescending(c => c.Download).Take(count / 4).MinOrDefault(c => c.Download).ToString("N2"),
+                p90 = counters.OrderByDescending(c => c.Download).Take(count / 10).MinOrDefault(c => c.Download).ToString("N2"),
+                p99 = counters.OrderByDescending(c => c.Download).Take(count / 100).MinOrDefault(c => c.Download).ToString("N2"),
+                p999 = counters.OrderByDescending(c => c.Download).Take(count / 1000).MinOrDefault(c => c.Download).ToString("N2"),
+                average = counters.Average(c => c.Download).ToString("N2"),
+                stdev = counters.StandardDeviation(c => c.Download).ToString("N2")
             },
             ["网络上行(KBps)"] = new
             {
-                p50 = PerfCounter.List.OrderByDescending(c => c.Upload).Take(PerfCounter.List.Count / 2).MinOrDefault(c => c.Upload).ToString("N2"),
-                p75 = PerfCounter.List.OrderByDescending(c => c.Upload).Take(PerfCounter.List.Count / 4).MinOrDefault(c => c.Upload).ToString("N2"),
-                p90 = PerfCounter.List.OrderByDescending(c => c.Upload).Take(PerfCounter.List.Count / 10).MinOrDefault(c => c.Upload).ToString("N2"),
-                p99 = PerfCounter.List.OrderByDescending(c => c.Upload).Take(PerfCounter.List.Count / 100).MinOrDefault(c => c.Upload).ToString("N2"),
-                p999 = PerfCounter.List.OrderByDescending(c => c.Upload).Take(PerfCounter.List.Count / 1000).MinOrDefault(c => c.Upload).ToString("N2"),
-                average = PerfCounter.List.Average(c => c.Upload).ToString("N2"),
-                stdev = PerfCounter.List.StandardDeviation(c => c.Upload).ToString("N2")
+                p50 = counters.OrderByDescending(c => c.Upload).Take(count / 2).MinOrDefault(c => c.Upload).ToString("N2"),
+                p75 = counters.OrderByDescending(c => c.Upload).Take(count / 4).MinOrDefault(c => c.Upload).ToString("N2"),
+                p90 = counters.OrderByDescending(c => c.Upload).Take(count / 10).MinOrDefault(c => c.Upload).ToString("N2"),
+                p99 = counters.OrderByDescending(c => c.Upload).Take(count / 100).MinOrDefault(c => c.Upload).ToString("N2"),
+                p999 = counters.OrderByDescending(c => c.Upload).Take(count / 1000).MinOrDefault(c => c.Upload).ToString("N2"),
+                average = counters.Average(c => c.Upload).ToString("N2"),
+                stdev = counters.StandardDeviation(c => c.Upload).ToString("N2")
             }
         };
     }

+ 4 - 0
src/Masuit.MyBlogs.Core/wwwroot/Content/common/style.css

@@ -523,4 +523,8 @@ Custom bottom spacer
     font-size: 16px;
     line-height: 22px;
     word-break: break-all;
+}
+
+.mp-popup {
+    max-height: 100vh !important;
 }

+ 3 - 0
src/Masuit.MyBlogs.Core/wwwroot/ng-views/views/partner.html

@@ -37,6 +37,9 @@
     </div>
     <table ng-table="list.tableParams" class="table table-bordered table-hover table-condensed listTable" ng-form="list.tableForm" tracked-table="list.tableTracker">
         <tr ng-repeat="row in $data" ng-form="rowForm" tracked-table-row="row">
+            <td title="'id'">
+                {{row.Id}}
+            </td>
             <td title="'标题'">
                 <a ng-click="detail(row)" target="_blank">{{row.Title}}</a>
             </td>