From 80e48a2043d01e0a43945eec9ee195050a0ccc2b Mon Sep 17 00:00:00 2001 From: jackfiled Date: Wed, 7 Jan 2026 23:21:09 +0800 Subject: [PATCH] feat: add update time. Make the link in blog blue. --- YaeBlog/Abstraction/IEssayScanService.cs | 6 ++++ YaeBlog/Commands/YaeBlogCommand.cs | 34 +++++++++++++++++-- YaeBlog/Components/Pages/Essays.razor | 19 +++++++---- YaeBlog/Models/BlogEssay.cs | 5 ++- YaeBlog/Models/MarkdownMetadata.cs | 4 ++- .../EssayStylesPostRenderProcessor.cs | 4 +-- YaeBlog/Services/RendererService.cs | 9 +++-- 7 files changed, 64 insertions(+), 17 deletions(-) diff --git a/YaeBlog/Abstraction/IEssayScanService.cs b/YaeBlog/Abstraction/IEssayScanService.cs index d0d2f5e..dee2a7d 100644 --- a/YaeBlog/Abstraction/IEssayScanService.cs +++ b/YaeBlog/Abstraction/IEssayScanService.cs @@ -6,5 +6,11 @@ public interface IEssayScanService { public Task ScanContents(); + /// + /// 将对应的博客文章保存在磁盘上 + /// + /// + /// 指定对应博客文章是否为草稿。因为BlogContent是不可变对象,因此提供该参数以方便publish的实现。 + /// public Task SaveBlogContent(BlogContent content, bool isDraft = true); } diff --git a/YaeBlog/Commands/YaeBlogCommand.cs b/YaeBlog/Commands/YaeBlogCommand.cs index 2f1d04e..b71539e 100644 --- a/YaeBlog/Commands/YaeBlogCommand.cs +++ b/YaeBlog/Commands/YaeBlogCommand.cs @@ -19,6 +19,7 @@ public sealed class YaeBlogCommand AddWatchCommand(_rootCommand); AddListCommand(_rootCommand); AddNewCommand(_rootCommand); + AddUpdateCommand(_rootCommand); AddPublishCommand(_rootCommand); AddScanCommand(_rootCommand); AddCompressCommand(_rootCommand); @@ -46,7 +47,7 @@ public sealed class YaeBlogCommand WebApplication application = builder.Build(); - application.UseStaticFiles(); + application.MapStaticAssets(); application.UseAntiforgery(); application.UseYaeBlog(); @@ -76,7 +77,7 @@ public sealed class YaeBlogCommand WebApplication application = builder.Build(); - application.UseStaticFiles(); + application.MapStaticAssets(); application.UseAntiforgery(); application.UseYaeBlog(); @@ -109,7 +110,7 @@ public sealed class YaeBlogCommand await essayScanService.SaveBlogContent(new BlogContent( new FileInfo(Path.Combine(blogOption.Value.Root, "drafts", file + ".md")), - new MarkdownMetadata { Title = file, Date = DateTime.Now }, + new MarkdownMetadata { Title = file, Date = DateTimeOffset.Now, UpdateTime = DateTimeOffset.Now }, string.Empty, true, [], [])); Console.WriteLine($"Created new blog '{file}."); @@ -117,6 +118,33 @@ public sealed class YaeBlogCommand new EssayScanServiceBinder()); } + private static void AddUpdateCommand(RootCommand rootCommand) + { + Command newCommand = new("update", "Update the blog essay."); + rootCommand.AddCommand(newCommand); + + Argument filenameArgument = new(name: "blog name", description: "The blog filename to update."); + newCommand.AddArgument(filenameArgument); + + newCommand.SetHandler(async (file, _, _, essayScanService) => + { + Console.WriteLine("HINT: The update command only consider published blogs."); + BlogContents contents = await essayScanService.ScanContents(); + + BlogContent? content = contents.Posts.FirstOrDefault(c => c.BlogName == file); + if (content is null) + { + Console.WriteLine($"Target essay {file} is not exist."); + return; + } + + content.Metadata.UpdateTime = DateTimeOffset.Now; + await essayScanService.SaveBlogContent(content, content.IsDraft); + + }, filenameArgument, + new BlogOptionsBinder(), new LoggerBinder(), new EssayScanServiceBinder()); + } + private static void AddListCommand(RootCommand rootCommand) { Command command = new("list", "List all blogs"); diff --git a/YaeBlog/Components/Pages/Essays.razor b/YaeBlog/Components/Pages/Essays.razor index d1d1b74..37fa6fe 100644 --- a/YaeBlog/Components/Pages/Essays.razor +++ b/YaeBlog/Components/Pages/Essays.razor @@ -19,10 +19,6 @@
-
- @(_essay!.PublishTime.ToString("yyyy-MM-dd")) -
- @foreach (string tag in _essay!.Tags) {
@@ -32,10 +28,19 @@
}
-
-
-
+
+ 发布于: @(_essay.PublishTime.ToString("yyyy年MM月dd日 hh:mm:ss")) +
+ + @if (_essay.UpdateTime != _essay.PublishTime) + { +
+ 更新于: @(_essay.UpdateTime.ToString("yyyy年MM月dd日 hh:mm:ss")) +
+ } + +
总字数:@(_essay!.WordCount)字,预计阅读时间 @(_essay!.ReadTime)。
diff --git a/YaeBlog/Models/BlogEssay.cs b/YaeBlog/Models/BlogEssay.cs index 0af5cf6..5b71515 100644 --- a/YaeBlog/Models/BlogEssay.cs +++ b/YaeBlog/Models/BlogEssay.cs @@ -8,7 +8,9 @@ public class BlogEssay : IComparable public required bool IsDraft { get; init; } - public required DateTime PublishTime { get; init; } + public required DateTimeOffset PublishTime { get; init; } + + public required DateTimeOffset UpdateTime { get; init; } public required string Description { get; init; } @@ -28,6 +30,7 @@ public class BlogEssay : IComparable FileName = FileName, IsDraft = IsDraft, PublishTime = PublishTime, + UpdateTime = UpdateTime, Description = Description, WordCount = WordCount, ReadTime = ReadTime, diff --git a/YaeBlog/Models/MarkdownMetadata.cs b/YaeBlog/Models/MarkdownMetadata.cs index 8359e7d..7ef93fa 100644 --- a/YaeBlog/Models/MarkdownMetadata.cs +++ b/YaeBlog/Models/MarkdownMetadata.cs @@ -4,7 +4,9 @@ public class MarkdownMetadata { public string? Title { get; set; } - public DateTime? Date { get; set; } + public DateTimeOffset Date { get; set; } + + public DateTimeOffset UpdateTime { get; set; } public List? Tags { get; set; } } diff --git a/YaeBlog/Processors/EssayStylesPostRenderProcessor.cs b/YaeBlog/Processors/EssayStylesPostRenderProcessor.cs index a9d2321..3d05838 100644 --- a/YaeBlog/Processors/EssayStylesPostRenderProcessor.cs +++ b/YaeBlog/Processors/EssayStylesPostRenderProcessor.cs @@ -16,8 +16,7 @@ public sealed class EssayStylesPostRenderProcessor : IPostRenderProcessor public async Task ProcessAsync(BlogEssay essay) { BrowsingContext context = new(Configuration.Default); - IDocument document = await context.OpenAsync( - req => req.Content(essay.HtmlContent)); + IDocument document = await context.OpenAsync(req => req.Content(essay.HtmlContent)); ApplyGlobalCssStyles(document); BeatifyTable(document); @@ -36,6 +35,7 @@ public sealed class EssayStylesPostRenderProcessor : IPostRenderProcessor { "h5", "text-lg font-bold py-1" }, { "p", "p-2" }, { "img", "w-11/12 block mx-auto my-2 rounded-md shadow-md" }, + { "a", "text-blue-600" } }; private void ApplyGlobalCssStyles(IDocument document) diff --git a/YaeBlog/Services/RendererService.cs b/YaeBlog/Services/RendererService.cs index 6105694..8317314 100644 --- a/YaeBlog/Services/RendererService.cs +++ b/YaeBlog/Services/RendererService.cs @@ -47,7 +47,10 @@ public partial class RendererService( Description = GetDescription(content), WordCount = wordCount, ReadTime = CalculateReadTime(wordCount), - PublishTime = content.Metadata.Date ?? DateTime.Now, + PublishTime = content.Metadata.Date == default ? DateTimeOffset.Now : content.Metadata.Date, + // 如果不存在最后的更新时间,就把更新时间设置为发布时间 + UpdateTime = + content.Metadata.UpdateTime == default ? content.Metadata.Date : content.Metadata.UpdateTime, HtmlContent = content.Content }; @@ -182,7 +185,7 @@ public partial class RendererService( string description = builder.ToString(); - logger.LogDebug("Description of {} is {}.", content.BlogName, + logger.LogDebug("Description of {name} is {desc}.", content.BlogName, description); return description; } @@ -193,7 +196,7 @@ public partial class RendererService( where char.IsLetterOrDigit(c) select c).Count(); - logger.LogDebug("Word count of {} is {}", content.BlogName, + logger.LogDebug("Word count of {blog} is {count}", content.BlogName, count); return (uint)count; }