diff --git a/YaeBlog.Core/Abstractions/IEssayContentService.cs b/YaeBlog.Core/Abstractions/IEssayContentService.cs new file mode 100644 index 0000000..3fbbb42 --- /dev/null +++ b/YaeBlog.Core/Abstractions/IEssayContentService.cs @@ -0,0 +1,13 @@ +using System.Diagnostics.CodeAnalysis; +using YaeBlog.Core.Models; + +namespace YaeBlog.Core.Abstractions; + +public interface IEssayContentService +{ + public IReadOnlyDictionary Essays { get; } + + public IReadOnlyDictionary> Tags { get; } + + public bool SearchByUrlEncodedTag(string tag,[NotNullWhen(true)] out List? result); +} diff --git a/YaeBlog.Core/Abstractions/ITableOfContentService.cs b/YaeBlog.Core/Abstractions/ITableOfContentService.cs new file mode 100644 index 0000000..08b997c --- /dev/null +++ b/YaeBlog.Core/Abstractions/ITableOfContentService.cs @@ -0,0 +1,8 @@ +using YaeBlog.Core.Models; + +namespace YaeBlog.Core.Abstractions; + +public interface ITableOfContentService +{ + public IReadOnlyDictionary Headlines { get; } +} diff --git a/YaeBlog.Core/Extensions/WebApplicationBuilderExtensions.cs b/YaeBlog.Core/Extensions/WebApplicationBuilderExtensions.cs index 6ed6680..d469a33 100644 --- a/YaeBlog.Core/Extensions/WebApplicationBuilderExtensions.cs +++ b/YaeBlog.Core/Extensions/WebApplicationBuilderExtensions.cs @@ -1,6 +1,8 @@ -using Microsoft.AspNetCore.Builder; +using AngleSharp; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using YaeBlog.Core.Abstractions; using YaeBlog.Core.Models; using YaeBlog.Core.Processors; using YaeBlog.Core.Services; @@ -17,10 +19,19 @@ public static class WebApplicationBuilderExtensions builder.Services.AddMarkdig(); builder.Services.AddYamlParser(); + builder.Services.AddSingleton(_ => Configuration.Default); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(provider => + provider.GetRequiredService()); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(provider => + provider.GetRequiredService()); builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(provider => provider.GetRequiredService>().Value); diff --git a/YaeBlog.Core/Extensions/WebApplicationExtensions.cs b/YaeBlog.Core/Extensions/WebApplicationExtensions.cs index f541f4a..563395c 100644 --- a/YaeBlog.Core/Extensions/WebApplicationExtensions.cs +++ b/YaeBlog.Core/Extensions/WebApplicationExtensions.cs @@ -8,11 +8,12 @@ namespace YaeBlog.Core.Extensions; public static class WebApplicationExtensions { - public static WebApplication UseMiddleRenderProcessors(this WebApplication application) + public static void UseYaeBlog(this WebApplication application) { application.UsePostRenderProcessor(); - - return application; + application.UsePostRenderProcessor(); + application.UsePostRenderProcessor(); + application.UsePostRenderProcessor(); } private static void UsePreRenderProcessor(this WebApplication application) where T : IPreRenderProcessor diff --git a/YaeBlog.Core/Models/BlogEssay.cs b/YaeBlog.Core/Models/BlogEssay.cs index 5e41f02..b8e60b6 100644 --- a/YaeBlog.Core/Models/BlogEssay.cs +++ b/YaeBlog.Core/Models/BlogEssay.cs @@ -12,6 +12,8 @@ public class BlogEssay : IComparable public required uint WordCount { get; init; } + public required string ReadTime { get; init; } + public List Tags { get; } = []; public required string HtmlContent { get; init; } @@ -25,6 +27,7 @@ public class BlogEssay : IComparable PublishTime = PublishTime, Description = Description, WordCount = WordCount, + ReadTime = ReadTime, HtmlContent = newHtmlContent }; essay.Tags.AddRange(Tags); diff --git a/YaeBlog.Core/Models/BlogHeadline.cs b/YaeBlog.Core/Models/BlogHeadline.cs new file mode 100644 index 0000000..f328290 --- /dev/null +++ b/YaeBlog.Core/Models/BlogHeadline.cs @@ -0,0 +1,10 @@ +namespace YaeBlog.Core.Models; + +public class BlogHeadline(string title, string selectorId) +{ + public string Title { get; } = title; + + public string SelectorId { get; set; } = selectorId; + + public List Children { get; } = []; +} diff --git a/YaeBlog.Core/Models/BlogOptions.cs b/YaeBlog.Core/Models/BlogOptions.cs index 69c0858..246f11d 100644 --- a/YaeBlog.Core/Models/BlogOptions.cs +++ b/YaeBlog.Core/Models/BlogOptions.cs @@ -10,10 +10,8 @@ public class BlogOptions public required string Root { get; set; } /// - /// 博客作者 + /// 博客正文的广而告之 /// - public required string Author { get; set; } - public required string Announcement { get; set; } /// @@ -22,21 +20,7 @@ public class BlogOptions public required int StartYear { get; set; } /// - /// 博客起始页面的背景图片 + /// 博客的友链 /// - public required string BannerImage { get; set; } - - /// - /// 文章页面的背景图片 - /// - public required string EssayImage { get; set; } - - /// - /// 博客底部是否显示ICP备案信息 - /// - public string? RegisterInformation { get; set; } - - public required AboutInfo About { get; set; } - public required List Links { get; set; } } diff --git a/YaeBlog.Core/Models/EssayTag.cs b/YaeBlog.Core/Models/EssayTag.cs new file mode 100644 index 0000000..6528943 --- /dev/null +++ b/YaeBlog.Core/Models/EssayTag.cs @@ -0,0 +1,16 @@ +using System.Text.Encodings.Web; + +namespace YaeBlog.Core.Models; + +public class EssayTag(string tagName) : IEquatable +{ + public string TagName { get; } = tagName; + + public string UrlEncodedTagName { get; } = UrlEncoder.Default.Encode(tagName); + + public bool Equals(EssayTag? other) => other is not null && TagName == other.TagName; + + public override bool Equals(object? obj) => obj is EssayTag other && Equals(other); + + public override int GetHashCode() => TagName.GetHashCode(); +} diff --git a/YaeBlog.Core/Processors/CodeBlockPostRenderProcessor.cs b/YaeBlog.Core/Processors/CodeBlockPostRenderProcessor.cs new file mode 100644 index 0000000..217aa38 --- /dev/null +++ b/YaeBlog.Core/Processors/CodeBlockPostRenderProcessor.cs @@ -0,0 +1,29 @@ +using AngleSharp; +using AngleSharp.Dom; +using YaeBlog.Core.Abstractions; +using YaeBlog.Core.Models; + +namespace YaeBlog.Core.Processors; + +public class CodeBlockPostRenderProcessor : IPostRenderProcessor +{ + public async Task ProcessAsync(BlogEssay essay) + { + BrowsingContext context = new(Configuration.Default); + IDocument document = await context.OpenAsync( + req => req.Content(essay.HtmlContent)); + + IEnumerable preElements = from e in document.All + where e.LocalName == "pre" + select e; + + foreach (IElement element in preElements) + { + element.ClassList.Add("p-3 text-bg-secondary rounded-1"); + } + + return essay.WithNewHtmlContent(document.DocumentElement.OuterHtml); + } + + public string Name => nameof(CodeBlockPostRenderProcessor); +} diff --git a/YaeBlog.Core/Processors/HeadlinePostRenderProcessor.cs b/YaeBlog.Core/Processors/HeadlinePostRenderProcessor.cs new file mode 100644 index 0000000..ddfed50 --- /dev/null +++ b/YaeBlog.Core/Processors/HeadlinePostRenderProcessor.cs @@ -0,0 +1,105 @@ +using AngleSharp; +using AngleSharp.Dom; +using YaeBlog.Core.Abstractions; +using YaeBlog.Core.Models; +using YaeBlog.Core.Services; + +namespace YaeBlog.Core.Processors; + +public class HeadlinePostRenderProcessor( + IConfiguration angleConfiguration, + TableOfContentService tableOfContentService) : IPostRenderProcessor +{ + public async Task ProcessAsync(BlogEssay essay) + { + BrowsingContext browsingContext = new(angleConfiguration); + IDocument document = await browsingContext.OpenAsync(req => req.Content(essay.HtmlContent)); + + IEnumerable elements = from item in document.All + where item.LocalName is "h2" or "h3" or "h4" + select item; + + BlogHeadline topHeadline = new(essay.Title, "#title"); + List level2List = []; + List level3List = []; + List level4List = []; + + foreach (IElement element in elements) + { + switch (element.LocalName) + { + case "h2": + { + FindParentHeadline(topHeadline, level2List, level3List).Children.AddRange(level4List); + level4List.Clear(); + FindParentHeadline(topHeadline, level2List).Children.AddRange(level3List); + level3List.Clear(); + + BlogHeadline headline = ParserHeadlineElement(element); + level2List.Add(headline); + break; + } + case "h3": + { + FindParentHeadline(topHeadline, level2List, level3List).Children.AddRange(level4List); + level4List.Clear(); + + BlogHeadline headline = ParserHeadlineElement(element); + level3List.Add(headline); + break; + } + case "h4": + { + BlogHeadline headline = ParserHeadlineElement(element); + level4List.Add(headline); + break; + } + } + } + + // 太抽象了((( + FindParentHeadline(topHeadline, level2List, level3List).Children.AddRange(level4List); + FindParentHeadline(topHeadline, level2List).Children.AddRange(level3List); + topHeadline.Children.AddRange(level2List); + + tableOfContentService.AddHeadline(essay.FileName, topHeadline); + + return essay.WithNewHtmlContent(document.DocumentElement.OuterHtml); + } + + private static BlogHeadline ParserHeadlineElement(IElement element) + { + element.Id ??= element.TextContent; + return new BlogHeadline(element.TextContent, element.Id); + } + + /// + /// 找到h4标题的父级标题 + /// + /// + /// + /// + /// + private static BlogHeadline FindParentHeadline(BlogHeadline topHeadline, List level2, + List level3) + { + BlogHeadline? result = level3.LastOrDefault(); + if (result is not null) + { + return result; + } + + return level2.LastOrDefault() ?? topHeadline; + } + + /// + /// 找到h3标题的父级标题 + /// + /// + /// + /// + private static BlogHeadline FindParentHeadline(BlogHeadline topHeadline, List level2) => + FindParentHeadline(topHeadline, level2, []); + + public string Name => nameof(HeadlinePostRenderProcessor); +} diff --git a/YaeBlog.Core/Processors/ImagePostRenderProcessor.cs b/YaeBlog.Core/Processors/ImagePostRenderProcessor.cs index d4a61a8..0592899 100644 --- a/YaeBlog.Core/Processors/ImagePostRenderProcessor.cs +++ b/YaeBlog.Core/Processors/ImagePostRenderProcessor.cs @@ -38,7 +38,7 @@ public class ImagePostRenderProcessor(ILogger logger, return essay.WithNewHtmlContent(html.DocumentElement.OuterHtml); } - public string Name => "ImagePostRenderProcessor"; + public string Name => nameof(ImagePostRenderProcessor); private string GenerateImageLink(string filename, string essayFilename) { diff --git a/YaeBlog.Core/Processors/TablePostRenderProcessor.cs b/YaeBlog.Core/Processors/TablePostRenderProcessor.cs new file mode 100644 index 0000000..e2c3444 --- /dev/null +++ b/YaeBlog.Core/Processors/TablePostRenderProcessor.cs @@ -0,0 +1,34 @@ +using AngleSharp; +using AngleSharp.Dom; +using AngleSharp.Html.Dom; +using YaeBlog.Core.Abstractions; +using YaeBlog.Core.Models; + +namespace YaeBlog.Core.Processors; + +public class TablePostRenderProcessor: IPostRenderProcessor +{ + public async Task ProcessAsync(BlogEssay essay) + { + BrowsingContext browsingContext = new(Configuration.Default); + IDocument document = await browsingContext.OpenAsync( + req => req.Content(essay.HtmlContent)); + + IEnumerable tableElements = from item in document.All + where item.LocalName == "table" + select item as IHtmlTableElement; + + foreach (IHtmlTableElement element in tableElements) + { + IHtmlDivElement divElement = document.CreateElement(); + divElement.InnerHtml = element.OuterHtml; + divElement.ClassList.Add("py-2", "table-wrapper"); + + element.Replace(divElement); + } + + return essay.WithNewHtmlContent(document.DocumentElement.OuterHtml); + } + + public string Name => nameof(TablePostRenderProcessor); +} diff --git a/YaeBlog.Core/Services/EssayContentService.cs b/YaeBlog.Core/Services/EssayContentService.cs index bfcbfe8..aa800f2 100644 --- a/YaeBlog.Core/Services/EssayContentService.cs +++ b/YaeBlog.Core/Services/EssayContentService.cs @@ -1,58 +1,48 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; +using YaeBlog.Core.Abstractions; using YaeBlog.Core.Models; namespace YaeBlog.Core.Services; -public class EssayContentService +public class EssayContentService : IEssayContentService { private readonly ConcurrentDictionary _essays = new(); - private readonly Dictionary> _tags = []; + private readonly Dictionary> _tags = []; - public bool TryGet(string key, out BlogEssay? essay) - => _essays.TryGetValue(key, out essay); + public bool TryAdd(BlogEssay essay) => _essays.TryAdd(essay.FileName, essay); - public bool TryAdd(string key, BlogEssay essay) => _essays.TryAdd(key, essay); + public IReadOnlyDictionary Essays => _essays; - public IEnumerable> Essays => _essays; - - public int Count => _essays.Count; + public IReadOnlyDictionary> Tags => _tags; public void RefreshTags() { - foreach (BlogEssay essay in _essays.Values) - { - foreach (string tag in essay.Tags) - { - if (_tags.TryGetValue(tag, out var list)) - { - list.Add(essay); - } - else - { - _tags[tag] = [essay]; - } - } - } + _tags.Clear(); - foreach (KeyValuePair> pair in _tags) - { - pair.Value.Sort(); - } + foreach (BlogEssay essay in _essays.Values) + { + foreach (EssayTag essayTag in essay.Tags.Select(tag => new EssayTag(tag))) + { + if (_tags.TryGetValue(essayTag, out List? essays)) + { + essays.Add(essay); + } + else + { + _tags.Add(essayTag, [essay]); + } + } + } } - public IEnumerable> Tags => from item in _tags - select KeyValuePair.Create(item.Key, item.Value.Count); - - public int TagCount => _tags.Count; - - public IEnumerable GetTag(string tag) + public bool SearchByUrlEncodedTag(string tag, [NotNullWhen(true)] out List? result) { - if (_tags.TryGetValue(tag, out var list)) - { - return list; - } + result = (from item in _tags + where item.Key.UrlEncodedTagName == tag + select item.Value).FirstOrDefault(); - throw new KeyNotFoundException("Selected tag not found."); + return result is not null; } } diff --git a/YaeBlog.Core/Services/RendererService.cs b/YaeBlog.Core/Services/RendererService.cs index a4359ea..3195efb 100644 --- a/YaeBlog.Core/Services/RendererService.cs +++ b/YaeBlog.Core/Services/RendererService.cs @@ -1,6 +1,7 @@ using System.Collections.Concurrent; using System.Diagnostics; using System.Text; +using System.Text.RegularExpressions; using Markdig; using Microsoft.Extensions.Logging; using YaeBlog.Core.Abstractions; @@ -11,7 +12,8 @@ using YamlDotNet.Serialization; namespace YaeBlog.Core.Services; -public class RendererService(ILogger logger, +public partial class RendererService( + ILogger logger, EssayScanService essayScanService, MarkdownPipeline markdownPipeline, IDeserializer yamlDeserializer, @@ -37,12 +39,14 @@ public class RendererService(ILogger logger, foreach (BlogContent content in preProcessedContents) { MarkdownMetadata? metadata = TryParseMetadata(content); + uint wordCount = GetWordCount(content); BlogEssay essay = new() { Title = metadata?.Title ?? content.FileName, FileName = content.FileName, Description = GetDescription(content), - WordCount = GetWordCount(content), + WordCount = wordCount, + ReadTime = CalculateReadTime(wordCount), PublishTime = metadata?.Date ?? DateTime.Now, HtmlContent = content.FileContent }; @@ -51,6 +55,7 @@ public class RendererService(ILogger logger, { essay.Tags.AddRange(metadata.Tags); } + essays.Add(essay); } }); @@ -125,7 +130,7 @@ public class RendererService(ILogger logger, essay = await processor.ProcessAsync(essay); } - if (!essayContentService.TryAdd(essay.FileName, essay)) + if (!essayContentService.TryAdd(essay)) { throw new BlogFileException( $"There are two essays with the same name: '{essay.FileName}'."); @@ -172,30 +177,34 @@ public class RendererService(ILogger logger, } } + [GeneratedRegex(@"(?"; int pos = content.FileContent.IndexOf(delimiter, StringComparison.Ordinal); - StringBuilder builder = new(); + bool breakSentence = false; if (pos == -1) { // 自动截取前50个字符 pos = content.FileContent.Length < 50 ? content.FileContent.Length : 50; + breakSentence = true; } - for (int i = 0; i < pos; i++) + string rawContent = content.FileContent[..pos]; + MatchCollection matches = DescriptionPattern().Matches(rawContent); + + StringBuilder builder = new(); + foreach (Match match in matches) { - char c = content.FileContent[i]; + builder.Append(match.Value); + } - if (char.IsControl(c) || char.IsSymbol(c) || - char.IsSeparator(c) || char.IsPunctuation(c) || - char.IsAsciiLetter(c)) - { - continue; - } - - builder.Append(c); + if (breakSentence) + { + builder.Append("……"); } string description = builder.ToString(); @@ -212,7 +221,7 @@ public class RendererService(ILogger logger, foreach (char c in content.FileContent) { if (char.IsControl(c) || char.IsSymbol(c) - || char.IsSeparator(c)) + || char.IsSeparator(c)) { continue; } @@ -224,4 +233,13 @@ public class RendererService(ILogger logger, count); return count; } + + private static string CalculateReadTime(uint wordCount) + { + // 据说语文教学大纲规定,中国高中问阅读现代文的速度是600字每分钟 + int second = (int)wordCount / 10; + TimeSpan span = new TimeSpan(0, 0, second); + + return span.ToString("mm'分 'ss'秒'"); + } } diff --git a/YaeBlog.Core/Services/TableOfContentService.cs b/YaeBlog.Core/Services/TableOfContentService.cs new file mode 100644 index 0000000..4426016 --- /dev/null +++ b/YaeBlog.Core/Services/TableOfContentService.cs @@ -0,0 +1,20 @@ +using System.Collections.Concurrent; +using YaeBlog.Core.Abstractions; +using YaeBlog.Core.Models; + +namespace YaeBlog.Core.Services; + +public class TableOfContentService : ITableOfContentService +{ + private readonly ConcurrentDictionary _headlines = []; + + public IReadOnlyDictionary Headlines => _headlines; + + public void AddHeadline(string filename, BlogHeadline headline) + { + if (!_headlines.TryAdd(filename, headline)) + { + throw new InvalidOperationException(); + } + } +} diff --git a/YaeBlog/Components/App.razor b/YaeBlog/Components/App.razor index d9b1f57..3a96ded 100644 --- a/YaeBlog/Components/App.razor +++ b/YaeBlog/Components/App.razor @@ -19,6 +19,10 @@ + + diff --git a/YaeBlog/Components/BlogInformationCard.razor b/YaeBlog/Components/BlogInformationCard.razor new file mode 100644 index 0000000..fd97c76 --- /dev/null +++ b/YaeBlog/Components/BlogInformationCard.razor @@ -0,0 +1,57 @@ +@using YaeBlog.Core.Abstractions +@using YaeBlog.Core.Models + +@inject IEssayContentService Contents +@inject BlogOptions Options + +
+
+
+ Ricardo's avatar +
+
+ +
+
+ “奇奇怪怪东西的聚合地” +
+
+ +
+
+ 文章 +
+ + +
+ +
+
+ 标签 +
+ + +
+ +
+
+ 广而告之 +
+
+ +
+
+

+ @(Options.Announcement) +

+
+
+
diff --git a/YaeBlog/Components/BlogInformationCard.razor.css b/YaeBlog/Components/BlogInformationCard.razor.css new file mode 100644 index 0000000..e69de29 diff --git a/YaeBlog/Components/EssayCard.razor b/YaeBlog/Components/EssayCard.razor new file mode 100644 index 0000000..6c4c34e --- /dev/null +++ b/YaeBlog/Components/EssayCard.razor @@ -0,0 +1,39 @@ +@using YaeBlog.Core.Models + +
+ + +
+
+ @(Essay.PublishTime.ToString("yyyy-MM-dd")) +
+ + @foreach (string key in Essay.Tags) + { + + } +
+ +
+
+ @(Essay.Description) +
+
+ +
+
+ +
+
+
+ +@code { + [Parameter] + public required BlogEssay Essay { get; set; } +} diff --git a/YaeBlog/Components/EssayCard.razor.css b/YaeBlog/Components/EssayCard.razor.css new file mode 100644 index 0000000..4dd8b69 --- /dev/null +++ b/YaeBlog/Components/EssayCard.razor.css @@ -0,0 +1,3 @@ +.essay-title a { + color: var(--bs-body-color); +} diff --git a/YaeBlog/Components/Foonter.razor b/YaeBlog/Components/Foonter.razor new file mode 100644 index 0000000..d3f9910 --- /dev/null +++ b/YaeBlog/Components/Foonter.razor @@ -0,0 +1,14 @@ +
+
+

+ 2021 - @(DateTimeOffset.Now.Year) © Ricardo Ren, + 由 .NET @(Environment.Version) 驱动。 +

+
+ + +
diff --git a/YaeBlog/Components/Foonter.razor.css b/YaeBlog/Components/Foonter.razor.css new file mode 100644 index 0000000..e69de29 diff --git a/YaeBlog/Components/LicenseDisclaimer.razor b/YaeBlog/Components/LicenseDisclaimer.razor new file mode 100644 index 0000000..75aab2e --- /dev/null +++ b/YaeBlog/Components/LicenseDisclaimer.razor @@ -0,0 +1,36 @@ +@using YaeBlog.Core.Models + +@inject BlogOptions Options + + + +@code +{ + [Parameter] public string? EssayAddress { get; set; } +} diff --git a/YaeBlog/Components/LicenseDisclaimer.razor.css b/YaeBlog/Components/LicenseDisclaimer.razor.css new file mode 100644 index 0000000..28c8621 --- /dev/null +++ b/YaeBlog/Components/LicenseDisclaimer.razor.css @@ -0,0 +1,2 @@ +.copyright { +} diff --git a/YaeBlog/Layout/BlogLayout.razor b/YaeBlog/Layout/BlogLayout.razor index ea34e77..b8c240f 100644 --- a/YaeBlog/Layout/BlogLayout.razor +++ b/YaeBlog/Layout/BlogLayout.razor @@ -1,9 +1,63 @@ @inherits LayoutComponentBase -
- @Body +@attribute [StreamRendering] + +
+ + + + +
+ @Body +
+ +
- -@code { - -} diff --git a/YaeBlog/Layout/MainLayout.razor b/YaeBlog/Layout/MainLayout.razor index 9812427..27ee167 100644 --- a/YaeBlog/Layout/MainLayout.razor +++ b/YaeBlog/Layout/MainLayout.razor @@ -1,45 +1,25 @@ @inherits LayoutComponentBase -
-
-
- - - +
+
+ -
-
- @Body -
-
- -
-
-

2021 - 2024 By Ricardo Ren

-
- - +
+ +
+
+ @Body +
+
+ +
- -@code { - -} diff --git a/YaeBlog/Layout/MainLayout.razor.css b/YaeBlog/Layout/MainLayout.razor.css index ddff9ef..94874ec 100644 --- a/YaeBlog/Layout/MainLayout.razor.css +++ b/YaeBlog/Layout/MainLayout.razor.css @@ -1,7 +1,7 @@ .center { margin: 0 auto; - min-height: 100vh; max-width: 48em; + min-height: calc(100vh - 80px); position: relative; display: flex; flex-direction: column; diff --git a/YaeBlog/Pages/About.razor b/YaeBlog/Pages/About.razor new file mode 100644 index 0000000..d3847a0 --- /dev/null +++ b/YaeBlog/Pages/About.razor @@ -0,0 +1,145 @@ +@page "/blog/about" +@using YaeBlog.Core.Models + +@inject BlogOptions Options + + + 关于 + + +
+
+
+

关于

+
+
+ +
+
+ 把字刻在石头上!(・’ω’・) +
+
+ +
+
+
+
+

关于我

+
+
+ +
+
+ 计算机科学与技术在读大学生,明光村幼儿园附属大学所属。正处于读书和失业的叠加态。 + 一般在互联网上使用初冬的朝阳或者jackfiled的名字活动。 + 都是ICP备案过的人了,网名似乎没有太大的用处( +
+
+ +
+
+ 主要是一个C#程序员,目前也在尝试写一点Rust。总体上对于编程语言的态度是“大家都是我的翅膀.jpg”。 + 前后端分离的项目本当上手。 + 常常因为现实的压力而写一些C/C++。 + 对于Java和Go的评价很低。 + 日常使用ArchLinux。 +
+
+ +
+
+ 100%社恐。日常生活是宅在电脑前面自言自语。兴趣活动是读书和看番。 +
+
+ +
+
+ 常常被人批评没有梦想,这里就随便瞎编一下。 + 成为嵌入式工程师,修好桌面上的HoloCubic。 + 完成第一个不是课程设计的个人开源项目。 + 遇到能够搭伙过日子的人也算是一大梦想,虽然社恐人根本不知道从何开始的说, + 什么时候天上才能掉美少女? +
+
+ +
+
+ 公开的联系渠道是电子邮件。 + 也可以试试在各大平台搜索上面提到的名字。 +
+
+
+
+ +
+
+
+
+

关于本站

+
+
+ +
+
+ 本站肇始于2021年下半年,在开始的两年中个人网站和博客是分别的两个网站,个人网站是裸HTML写的,博客是用 + Hexo渲染的。 +
+
+ +
+
+ 2024年,我们决定使用.NET技术完全重构两个网站,合二为一。虽然目前这个版本还是一个半成品,但是我们一定会努力的~(确信。 +
+
+
+
+ +
+
+
+
+

友链

+
+
+ +
+
+ 欢迎所有人联系我添加友链!(´。✪ω✪。`) +
+
+ +
+ @foreach (FriendLink link in Options.Links) + { + + } +
+
+
+
+ +@code { + +} diff --git a/YaeBlog/Pages/About.razor.css b/YaeBlog/Pages/About.razor.css new file mode 100644 index 0000000..80b573c --- /dev/null +++ b/YaeBlog/Pages/About.razor.css @@ -0,0 +1,8 @@ +.link-item { + padding: 1rem; + border-radius: 4px; +} + +.link-item:hover { + background-color: var(--bs-secondary-bg); +} diff --git a/YaeBlog/Pages/Archives.razor b/YaeBlog/Pages/Archives.razor new file mode 100644 index 0000000..fcf87e9 --- /dev/null +++ b/YaeBlog/Pages/Archives.razor @@ -0,0 +1,75 @@ +@page "/blog/archives" +@using YaeBlog.Core.Abstractions +@using YaeBlog.Core.Models + +@inject IEssayContentService Contents + + + 归档 + + +
+
+
+
+
+
+

归档

+
+
+ +
+
+ 时光图书馆,黑历史集散地。 +
+
+
+
+
+ + @foreach (IGrouping> group in _essays) + { +
+
+
+
+
+

@(group.Key.Year)

+
+
+ +
+ @foreach (KeyValuePair essay in group) + { +
+
+ @(essay.Value.PublishTime.ToString("MM-dd")) +
+ + +
+ } +
+
+
+
+ } + +
+ +@code { + private readonly List>> _essays = []; + + protected override void OnInitialized() + { + base.OnInitialized(); + + _essays.AddRange(from essay in Contents.Essays + orderby essay.Value.PublishTime descending + group essay by new DateTime(essay.Value.PublishTime.Year, 1, 1)); + } +} diff --git a/YaeBlog/Pages/Archives.razor.css b/YaeBlog/Pages/Archives.razor.css new file mode 100644 index 0000000..e69de29 diff --git a/YaeBlog/Pages/BlogIndex.razor b/YaeBlog/Pages/BlogIndex.razor new file mode 100644 index 0000000..9242a4b --- /dev/null +++ b/YaeBlog/Pages/BlogIndex.razor @@ -0,0 +1,116 @@ +@page "/blog" +@using YaeBlog.Core.Abstractions +@using YaeBlog.Core.Models + +@inject IEssayContentService Contents +@inject NavigationManager NavigationInstance + + + Ricardo's Blog + + +
+
+
+ @foreach (KeyValuePair pair in _essays) + { + + } + +
+ @if (_page == 1) + { +
上一页
+ } + else + { +
+ 上一页 +
+ } + + @if (_page == 1) + { +
+ 1 +
+
+ 2 +
+
+ 3 +
+ } + else if (_page == _pageCount) + { + + +
+ @(_pageCount) +
+ } + else + { + +
+ @(_page) +
+ + } + + @if (_page == _pageCount) + { +
+ 下一页 +
+ } + else + { +
+ 下一页 +
+ } +
+
+ +
+ +
+
+
+ +@code { + + [SupplyParameterFromQuery] private int? Page { get; set; } + + private readonly List> _essays = []; + private const int EssaysPerPage = 8; + private int _pageCount = 1; + private int _page = 1; + + protected override void OnInitialized() + { + _page = Page ?? 1; + _pageCount = Contents.Essays.Count / EssaysPerPage + 1; + + if (EssaysPerPage * _page > Contents.Essays.Count + EssaysPerPage) + { + NavigationInstance.NavigateTo("/NotFount"); + return; + } + + _essays.AddRange(Contents.Essays + .OrderByDescending(p => p.Value.PublishTime) + .Skip((_page - 1) * EssaysPerPage) + .Take(EssaysPerPage)); + } + +} diff --git a/YaeBlog/Pages/BlogIndex.razor.css b/YaeBlog/Pages/BlogIndex.razor.css new file mode 100644 index 0000000..ffb2673 --- /dev/null +++ b/YaeBlog/Pages/BlogIndex.razor.css @@ -0,0 +1,7 @@ +.essay-title a { + color: var(--bs-body-color); +} + +.read-more a { + color: var(--bs-body-color); +} diff --git a/YaeBlog/Pages/Essays.razor b/YaeBlog/Pages/Essays.razor new file mode 100644 index 0000000..0a05d69 --- /dev/null +++ b/YaeBlog/Pages/Essays.razor @@ -0,0 +1,135 @@ +@page "/blog/essays/{BlogKey}" +@using YaeBlog.Core.Abstractions +@using YaeBlog.Core.Models + +@inject IEssayContentService Contents +@inject ITableOfContentService TableOfContent +@inject NavigationManager NavigationInstance + + + @(_essay!.Title) + + +
+
+
+

@(_essay!.Title)

+
+
+ +
+
+ @(_essay!.PublishTime.ToString("yyyy-MM-dd")) +
+ + @foreach (string tag in _essay!.Tags) + { +
+ # @(tag) +
+ } +
+ +
+
+ 总字数:@(_essay!.WordCount)字,预计阅读时间 @(_essay!.ReadTime)。 +
+
+ +
+
+ @((MarkupString)_essay!.HtmlContent) + + +
+ +
+
+
+
+
+

+ 文章目录 +

+
+
+ +
+
+ @foreach (BlogHeadline level2 in _headline!.Children) + { +
+ +
+ + @foreach (BlogHeadline level3 in level2.Children) + { + + + @foreach (BlogHeadline level4 in level3.Children) + { + + } + } + } +
+
+ + @if (_headline!.Children.Count == 0) + { +
+
+ 坏了(* Ŏ∀Ŏ),没有在文章中识别到目录 +
+
+ } +
+
+
+
+ +
+ +@code { + [Parameter] public string? BlogKey { get; set; } + + private BlogEssay? _essay; + + private BlogHeadline? _headline; + + protected override void OnInitialized() + { + base.OnInitialized(); + + if (string.IsNullOrWhiteSpace(BlogKey)) + { + NavigationInstance.NavigateTo("/NotFound"); + return; + } + + if (!Contents.Essays.TryGetValue(BlogKey, out _essay)) + { + NavigationInstance.NavigateTo("/NotFound"); + } + + _headline = TableOfContent.Headlines[BlogKey]; + } + + private string GenerateSelectorUrl(string selectorId) + => $"/blog/essays/{BlogKey!}#{selectorId}"; + +} diff --git a/YaeBlog/Pages/Essays.razor.css b/YaeBlog/Pages/Essays.razor.css new file mode 100644 index 0000000..e69de29 diff --git a/YaeBlog/Pages/Index.razor b/YaeBlog/Pages/Index.razor index a1ad2c6..27eeeb4 100644 --- a/YaeBlog/Pages/Index.razor +++ b/YaeBlog/Pages/Index.razor @@ -1,12 +1,16 @@ @page "/" + + Ricardo's Index + +
-
+
Ricardo's Avatar
-
+

初冬的朝阳 (Ricardo Ren)

@@ -27,25 +31,24 @@
+
-
-

恕我不能亲自为您沏茶(?),还是非常欢迎您能够来到我的主页。

-
- -
-

- 如果您想四处看看,了解一下屏幕对面的人,可以在我的 博客 看看。 - 如果您对于明光村幼儿园某附属技校的计算机教学感兴趣,您可以移步到 - 我的学习笔记, - 虽然这笔记我自己也木有看过。 - 如果您想批判一下我的代码,在 Github 和 - Gitea 都可以看见。 -

-

- 如果您真的很闲,也可以四处搜寻一下,也许存在着一些不为人知的彩蛋。 -

-
+
+

恕我不能亲自为您沏茶(?),还是非常欢迎您能够来到我的主页。

+
+
+

+ 如果您想四处看看,了解一下屏幕对面的人,可以在我的 博客 看看。 + 如果您对于明光村幼儿园某附属技校的计算机教学感兴趣,您可以移步到 + 我的学习笔记, + 虽然这笔记我自己也木有看过。 + 如果您想批判一下我的代码,在 Github 和 + Gitea 都可以找到。 +

+

+ 如果您真的很闲,也可以四处搜寻一下,也许存在着一些不为人知的彩蛋。 +

diff --git a/YaeBlog/Pages/NotFound.razor b/YaeBlog/Pages/NotFound.razor new file mode 100644 index 0000000..6440b85 --- /dev/null +++ b/YaeBlog/Pages/NotFound.razor @@ -0,0 +1,13 @@ +@page "/NotFound" + + + 啊~ 页面走丢啦~ + + +
+

NotFound!

+
+ +@code { + +} diff --git a/YaeBlog/Pages/NotFound.razor.css b/YaeBlog/Pages/NotFound.razor.css new file mode 100644 index 0000000..e69de29 diff --git a/YaeBlog/Pages/Tags.razor b/YaeBlog/Pages/Tags.razor new file mode 100644 index 0000000..c7b75bc --- /dev/null +++ b/YaeBlog/Pages/Tags.razor @@ -0,0 +1,92 @@ +@page "/blog/tags/" +@using System.Text.Encodings.Web +@using YaeBlog.Core.Abstractions +@using YaeBlog.Core.Models + +@inject IEssayContentService Contents +@inject NavigationManager NavigationInstance + + + @(TagName ?? "标签") + + +
+
+
+ @if (TagName is null) + { +

标签

+ } + else + { +

@(TagName)

+ } +
+
+ +
+
+ 在野外游荡的指针,走向未知的方向。 +
+
+ + @if (TagName is null) + { +
+ +
+ } + else + { +
+ @foreach (BlogEssay essay in _essays) + { + + } +
+ } +
+ +@code { + [SupplyParameterFromQuery] public string? TagName { get; set; } + + private readonly List _essays = []; + + protected override void OnInitialized() + { + base.OnInitialized(); + if (string.IsNullOrEmpty(TagName)) + { + return; + } + + if (!Contents.SearchByUrlEncodedTag(UrlEncoder.Default.Encode(TagName), out List? essays)) + { + NavigationInstance.NavigateTo("/NotFound"); + return; + } + + _essays.AddRange(essays.OrderDescending()); + } + +} diff --git a/YaeBlog/Pages/Tags.razor.css b/YaeBlog/Pages/Tags.razor.css new file mode 100644 index 0000000..49d2e8f --- /dev/null +++ b/YaeBlog/Pages/Tags.razor.css @@ -0,0 +1,6 @@ +.tag-count { + background: var(--bs-secondary-bg); + border-radius: 5px; + padding: 0 6px; +} + diff --git a/YaeBlog/Program.cs b/YaeBlog/Program.cs index a8f53aa..dd92dde 100644 --- a/YaeBlog/Program.cs +++ b/YaeBlog/Program.cs @@ -13,7 +13,7 @@ WebApplication application = builder.Build(); application.UseStaticFiles(); application.UseAntiforgery(); -application.UseMiddleRenderProcessors(); +application.UseYaeBlog(); application.MapRazorComponents() .AddInteractiveServerRenderMode(); diff --git a/YaeBlog/appsettings.json b/YaeBlog/appsettings.json index 9bc3b85..454c218 100644 --- a/YaeBlog/appsettings.json +++ b/YaeBlog/appsettings.json @@ -8,18 +8,8 @@ "AllowedHosts": "*", "Blog": { "Root": "source", - "Author": "Ricardo Ren", - "Announcement": "堂!堂!开!始!", + "Announcement": "博客锐意装修中,敬请期待!测试阶段如有问题还请海涵。", "StartYear": 2021, - "ProjectName": "Blog", - "BannerImage": "images/banner.png", - "EssayImage": "images/banner.png", - "RegisterInformation": "蜀ICP备2022004429号-1", - "About": { - "Introduction": "A CS Student", - "Description": "还太菜了,没有做出太多的贡献。", - "AvatarImage": "images/avatar.png" - }, "Links": [ { "Name": "Ichirinko", diff --git a/YaeBlog/docker-compose.yaml b/YaeBlog/docker-compose.yaml index 7532787..a505b3d 100644 --- a/YaeBlog/docker-compose.yaml +++ b/YaeBlog/docker-compose.yaml @@ -10,3 +10,4 @@ services: - "traefik.http.services.blog.loadbalancer.server.port=8080" - "traefik.http.routers.blog.tls=true" - "traefik.http.routers.blog.tls.certresolver=myresolver" + - "com.centurylinklabs.watchtower.enable=true" diff --git a/YaeBlog/source/2021-final.md b/YaeBlog/source/2021-final.md index aeffade..e29deb8 100644 --- a/YaeBlog/source/2021-final.md +++ b/YaeBlog/source/2021-final.md @@ -5,8 +5,6 @@ tags: - 随笔 --- - -# 2021年终总结 2021年已经过去,2022年已经来临。每每一年开始的时候,我都会展开一张纸或者新建一个文档,思量着又是一年时光,也该同诸大杂志一般,写几句意味深长的话语,怀念过去的时光,也祝福未来的自己。可往往脑海中已是三万字的长篇,落在笔头却又是一个字都没有了。 如今跨年的时候已经过去,朋友圈中已经不见文案的踪影,我也该重新提笔,细说自己2021年中做过的种种。 diff --git a/YaeBlog/source/2022-final.md b/YaeBlog/source/2022-final.md index 70ff87e..f9c31f8 100644 --- a/YaeBlog/source/2022-final.md +++ b/YaeBlog/source/2022-final.md @@ -6,8 +6,6 @@ date: 2022-12-30 14:58:12 --- -# 2022年终总结 - 2022是困难的一年。我们需要为2023年做好准备。 diff --git a/YaeBlog/source/2022-summer-vacation.md b/YaeBlog/source/2022-summer-vacation.md index 1c5b359..3fab150 100644 --- a/YaeBlog/source/2022-summer-vacation.md +++ b/YaeBlog/source/2022-summer-vacation.md @@ -6,9 +6,6 @@ typora-root-url: 2022-summer-vacation date: 2022-08-22 15:39:13 --- - -# 2022年暑假总结 - 在8个月的漫长寒假的最后两个月,~~也就是俗称的暑假中~~,我都干了些什么? diff --git a/YaeBlog/source/archlinux-sop.md b/YaeBlog/source/archlinux-sop.md index 06d3374..944feef 100644 --- a/YaeBlog/source/archlinux-sop.md +++ b/YaeBlog/source/archlinux-sop.md @@ -1,5 +1,6 @@ --- title: 日用Linux挑战第五篇 ArchLinux标准安装流程 +date: 2024-7-16 20:08:37 tags: - Linux - 技术笔记 diff --git a/YaeBlog/source/big-homework.md b/YaeBlog/source/big-homework.md index 0af5f28..f8df144 100644 --- a/YaeBlog/source/big-homework.md +++ b/YaeBlog/source/big-homework.md @@ -7,8 +7,6 @@ typora-root-url: big-homework date: 2022-07-27 11:34:49 --- -# 代码大作业初体验 - 在大学也呆了一年了,终于遇上了第一个需要多人合作的写代码项目。从四月底分组完成,任务部署下来到七月初接近尾声,在这两个多月的时间里,也算是经历了不少,学到了不少。 diff --git a/YaeBlog/source/build-blog-record.md b/YaeBlog/source/build-blog-record.md index ac84ed2..e57c557 100644 --- a/YaeBlog/source/build-blog-record.md +++ b/YaeBlog/source/build-blog-record.md @@ -7,10 +7,6 @@ tags: --- -# 建立博客过程的记录 - -## 博客之始 - 当我已经在Python的浩瀚大海遨(zheng)游(zha)了半个暑假后,我决定尝试一下传说中程序员专用的学(zhuang)习(bi)手(fangfa)段(fa)——建立自己的个人博客。作为一个半懂不懂的Python程序员,心中冒出的第一个想法自然是采用Python的Django作为开发自己的个人博客的手段。然而,在阅读了[用Django搭建个人博客](https://www.dusaiphoto.com/article/2/)等的其他人搭建这类动态博客的过程记录之后,我便义无反顾的转向了采用javascript开发的博客框架[Hexo](https://hexo.io),说好的Python信仰呢。无他,唯简单尔。 @@ -454,4 +450,4 @@ nginx大部分的默认设置都没有改动,指设置了Let's Encrypt提供 一路上读了许多人的博客,已经无法一一指出,在此一并表示感谢。 -文中也不免有许多疏漏之处,因时间飞逝,当时遇到的一些问题也无法一一记录,还请诸位读者海涵。 \ No newline at end of file +文中也不免有许多疏漏之处,因时间飞逝,当时遇到的一些问题也无法一一记录,还请诸位读者海涵。 diff --git a/YaeBlog/source/c-include-problems.md b/YaeBlog/source/c-include-problems.md index 5037201..5993d12 100644 --- a/YaeBlog/source/c-include-problems.md +++ b/YaeBlog/source/c-include-problems.md @@ -7,7 +7,6 @@ typora-root-url: c-include-problems date: 2022-05-08 11:35:19 --- - 最近在完成一门`C`语言课程的大作业,课设老师要求我们将程序分模块的开发。在编写项目头文件的时候,遇到了一些令本菜鸡大开眼界的问题。 diff --git a/YaeBlog/source/compile-mediapipe.md b/YaeBlog/source/compile-mediapipe.md index cb7cb00..15bf441 100644 --- a/YaeBlog/source/compile-mediapipe.md +++ b/YaeBlog/source/compile-mediapipe.md @@ -6,8 +6,7 @@ tags: date: 2022-11-11 22:20:25 --- -# 编译MediaPipe框架 - +编译MediaPipe框架。 最近开始研究自己的大创项目,一个关于动作捕捉的小玩意儿,第一步就是~~抄袭开源代码~~借鉴他人优秀成果。在众多的项目中,我看上了这个Google开源的优秀框架,先把这个项目在本地上跑起来再说。这篇文章就记录了我编译这个框架的过程。 diff --git a/YaeBlog/source/daily-linux-0.md b/YaeBlog/source/daily-linux-0.md index 3c0730d..b5bd2ff 100644 --- a/YaeBlog/source/daily-linux-0.md +++ b/YaeBlog/source/daily-linux-0.md @@ -7,9 +7,6 @@ date: 2023-01-15 22:23:08 typora-root-url: daily-linux-0 --- - -# 日用Linux挑战 第0篇 - 在将开发重心移到`WSL`上一年之后,我最终还是决定完全抛弃Windows,转向使用Linux作为我日常使用的主力系统。目前,我已经使用Linux作为主力系统一个月了。 diff --git a/YaeBlog/source/daily-linux-1.md b/YaeBlog/source/daily-linux-1.md index 39f1377..abae00c 100644 --- a/YaeBlog/source/daily-linux-1.md +++ b/YaeBlog/source/daily-linux-1.md @@ -7,8 +7,6 @@ date: 2023-03-08 22:37:29 --- -# 日用Linux挑战第1篇 - 从去年12月底正式切换到`Linux`开始算起,我日常使用`Linux`已经过去了2个月的时间。在本系列的上一篇文章——[日用Linux挑战 第0篇 - Ricardo的博客](https://rrricardo.top/blog/2023/01/15/daily-linux-0/)中,我讲述了我配置自己的`Arch Linux`的过程,还小小的赞扬了一波`Linux`在近些年来取得的进展。但是在这篇文章中,我将重点指出日常使用过程中遇到的问题和困难。 diff --git a/YaeBlog/source/daily-linux-2.md b/YaeBlog/source/daily-linux-2.md index 0ef64b1..be84541 100644 --- a/YaeBlog/source/daily-linux-2.md +++ b/YaeBlog/source/daily-linux-2.md @@ -8,8 +8,6 @@ typora-root-url: daily-linux-2 --- -# 日用Linux挑战 第2篇 - 使用`Linux`6个月,我成功戒掉了原神。 diff --git a/YaeBlog/source/daily-linux-3.md b/YaeBlog/source/daily-linux-3.md index 8fd3f12..b1a6160 100644 --- a/YaeBlog/source/daily-linux-3.md +++ b/YaeBlog/source/daily-linux-3.md @@ -8,8 +8,6 @@ date: 2023-09-04 14:47:46 --- -# 日用Linux挑战 第三篇 - 成也开源,败也开源。 diff --git a/YaeBlog/source/dotnet-come-to-go.md b/YaeBlog/source/dotnet-come-to-go.md deleted file mode 100644 index e857908..0000000 --- a/YaeBlog/source/dotnet-come-to-go.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: .net从入门到放弃再到入门 -tags: - - 技术笔记 - - dotnet -date: 2022-08-21 16:59:08 ---- - -# .net从入门到放弃再到入门 - -我宣布下面的内容都是我在胡扯。在写了一学期的`Java`和`Springboot`之后,我的评价是`Java`是什么垃圾东西,`C#`才是永远的神! - -~~这是一篇专业的.net劝退指南,详细记述了我为啥选择了.net又为啥选择了放弃。~~ - - - -### 开端——WPF桌面应用 - -~~在今年年初的时候,受到[通知大全](https://squidward.top/)启发,我决定编写一款自己的DDL管理应用程序。在一开始,我打算先在Windows平台上编写,当时我了解到Windows上最正统的桌面应用程序开发方式就是采用微软自家的.net平台开发,同时在[知乎](https://zhihu.com)上一群人在吹`C#`在设计上是如何如何的优于`JAVA`,当然在这里没有说他们的观点错误的意思,把我忽悠的一愣一愣的。.net在当时已经有了比较老旧的`WinForms`框架、比较流行的`WPF`框架和最新的`MAUI`框架。~~秉持着中国人中庸的思想潮流~~,我选择了`WPF`图形框架作为我当时开发的框架,从此入了.net平台的坑。~~ - -> 如今这个桌面端的项目已经基本烂尾,项目开源在[github](https://github.com/jackfiled/PostCalendarWindows),算是警醒后来的我在技术选型时应该更加的慎重 - -~~说实话,在开发的一开始,我就感觉力不从心。~~ - -~~第一,官方文档好但不完全好。微软虽然提供了本地化过的文档,但是有很大比例都是机翻的文档。我觉得吧,放机翻的文档还不如直接放英文原文的文档。同时,文档的大部分都是API列表一类的参考资料,对于初学者来说比较重要的“实用教程”等等部分内容较少,虽然文档全面而详细,但对于初学者来说并没有很大的帮助。毕竟我们不知道在数以万计的API中,哪个才能实现自己的需求。~~ - -~~第二,国内缺少.net相关的社区氛围。这点也是最为劝退的地方,相比于`JAVA`在国内广泛的应用和丰富的社区内容,国内.net和`C#`相关的内容除了在`Unity`游戏开发中还算广泛,其他称得上是乏善可陈。~~ - -~~在一堆好几年前的博客和半懂不懂的英文文档中沉浮一个月之后,我总算是写出了一个可以运行的成品。随着新学期的到来,以学业繁忙为借口,我停止了这个应用的开发。~~ - -### 重启——服务器开发 - -~~在经历了桌面应用的失败之后,我转移了自己的开发重心,开始了移动应用的开发,这次我没有坚持被微软的`MAUI`那八字还没有一撇的技术忽悠进去,选择了`flutter`框架搞开发。有应用自然就得有提供数据的后端,在开发服务器时,我又被微软的`ASP.NET`给“忽悠”了进去。~~ - -~~平心而论,`ASP.NET`开发的过程比上文中的桌面应用程序的开发还是要顺利不少。毕竟现在采用`B/S`架构的服务更多,个人感觉国内应用这项技术的人也不少,相关的技术资料也就不少,我入门的过程也就流畅许多。~~ - -~~虽然但是,在开发的过程中劝退的地方也不少。第一是微软自己的版本更迭,尤其是在微软宣布`dotnet core`,将.net开源之后,个人感觉国内的开发者似乎不是很感冒,还是用着原来的老一套。第二是和现在的技术流行方向不同,原本采用`JAVA`搞服务器的开发不太可能再更换语言,第二新入行的开发者也会选择当下流行的`GO`等语言,这就导致在开发中有一种单打独斗的感觉,很难找到人同你合作。~~ - -### 放弃 - -~~在坚持学习.net八个月之后,我还是决定放弃,转向学习`JAVA`。~~ - -- ~~没人用的技术的技术不要硬刚,即使是好技术也不要。没人用的技术就像一潭死水,只有流动起来,才能孕育生机和活力,否则只能在原地腐烂。~~ -- ~~之于我而言,语言不仅仅是开发软件的工具,更是需要计算机相关知识的工具。转向`JAVA`的原因之一就是我目前学习的数据结合课——伯克利的`CS61b`就是采用`JAVA`作为编程语言的。~~ - -~~虽然我已经决定将我的主力语言转向`JAVA`,~~但不得不承认`C#`在语言上的特性还是很不错的,以后我的重心不会放在`C#`上,但是他也不会从的技能树上消失。也许在若干年之后,我的主力语言又变回`C#`了(笑)。 - -> 全文的最后一句话可能是我现在唯一认同的了 \ No newline at end of file diff --git a/YaeBlog/source/environment-setting.md b/YaeBlog/source/environment-setting.md index e42583e..704c465 100644 --- a/YaeBlog/source/environment-setting.md +++ b/YaeBlog/source/environment-setting.md @@ -6,8 +6,6 @@ tags: typora-root-url: 环境配置 --- - -# 环境配置备忘录 电脑上的环境三天两头出问题,写下一个备忘录记录一下电脑上环境的配置过程。 diff --git a/YaeBlog/source/genshin-gacha-1.md b/YaeBlog/source/genshin-gacha-1.md index 50bfc96..278895a 100644 --- a/YaeBlog/source/genshin-gacha-1.md +++ b/YaeBlog/source/genshin-gacha-1.md @@ -5,7 +5,7 @@ tags: date: 2022-12-31 13:38:19 --- -# 原神抽卡研究一 +实际上是“概率论和随机过程”课程的期末小论文。 diff --git a/YaeBlog/source/install-pytorch.md b/YaeBlog/source/install-pytorch.md index f3cd14f..11f8314 100644 --- a/YaeBlog/source/install-pytorch.md +++ b/YaeBlog/source/install-pytorch.md @@ -7,7 +7,7 @@ tags: typora-root-url: 安装pytorch,来有深度的学习 --- -# 深度学习预备篇——安装深度学习框架——pytorch +鄙人在下不才我精通深度学习框架的安装和卸载。 @@ -238,4 +238,4 @@ True ## 写在最后 -在安装`pytorch`的这一路下来,我在网上查了无数的资料,似乎在安装`pytorch`的一路上就死了不少的人~~大概是因为他们是在Ubuntu上安装的~~,特别是调用`cuda`的那里。不过我按照[官方文档](https://pytorch.org/get-started/locally/)一路下来,没有出什么大的幺蛾子,只能说希望我自己的经历能对大家有所帮助吧。 \ No newline at end of file +在安装`pytorch`的这一路下来,我在网上查了无数的资料,似乎在安装`pytorch`的一路上就死了不少的人~~大概是因为他们是在Ubuntu上安装的~~,特别是调用`cuda`的那里。不过我按照[官方文档](https://pytorch.org/get-started/locally/)一路下来,没有出什么大的幺蛾子,只能说希望我自己的经历能对大家有所帮助吧。 diff --git a/YaeBlog/source/laptop-for-computer.md b/YaeBlog/source/laptop-for-computer.md index 7873899..d5aaff2 100644 --- a/YaeBlog/source/laptop-for-computer.md +++ b/YaeBlog/source/laptop-for-computer.md @@ -7,8 +7,6 @@ date: 2022-06-13 16:17:27 --- -# 大学生用啥配置——计算机专业 - > 本文是应B站UP主[远古时代装机猿](https://space.bilibili.com/35359510)发起的[大学生用啥配置](https://www.bilibili.com/video/BV1kZ4y1i7Le)公益活动而写 > > 目前某不知名211大学计算机专业在读 diff --git a/YaeBlog/source/linux-genshin-cloud.md b/YaeBlog/source/linux-genshin-cloud.md index 6434afe..189aa13 100644 --- a/YaeBlog/source/linux-genshin-cloud.md +++ b/YaeBlog/source/linux-genshin-cloud.md @@ -6,9 +6,6 @@ tags: date: 2023-10-09 23:56:34 --- - -# 解决云原神无法在Linux中浏览器下运行的问题 - 本文为转载`bilibili`用户[@SocialismTeen](https://space.bilibili.com/33027704)在他的[专栏](https://www.bilibili.com/read/cv26576757)中给出的解决办法。 diff --git a/YaeBlog/source/minecraft-wayland.md b/YaeBlog/source/minecraft-wayland.md index 9591e6f..645915f 100644 --- a/YaeBlog/source/minecraft-wayland.md +++ b/YaeBlog/source/minecraft-wayland.md @@ -6,10 +6,10 @@ tags: date: 2024-1-12 20:10:06 --- - - 让Minecraft游戏使用`Wayland`显示协议。 + + ## Update At 2024-2-24 在两天前,2024年的2月22日,`glfw`释出了一个新版本`3.4`。在新版本中,`glfw`大幅强化了对于`wayland`显示协议的支持,在默认情况下就会直接使用`wayland`显示协议。但是为了能够正常的运行`minecraft`,还需要对源代码进行修改: diff --git a/YaeBlog/source/post-calendar.md b/YaeBlog/source/post-calendar.md deleted file mode 100644 index 48ab983..0000000 --- a/YaeBlog/source/post-calendar.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: PostCalendar介绍 -typora-root-url: PostCalendar介绍 -date: 2022-03-05 14:18:50 -tags: ---- - - -# PostCalendar介绍 - -> 本文是[PostCalendarWindows](https://https://github.com/jackfiled/PostCalendarWindows)README文件的国内镜像 - -一款集日程管理与DDL管理于一身的日历软件。 - -下载地址:[GithubRelease](https://github.com/jackfiled/PostCalendarWindows/releases) - -# 开发未完成,仍在内测阶段 - - -## 支持的功能 - -### 日历部分 - -![日历部分截图](Calendar.png) - -1. 支持日历事件的添加,删除,修改。 -2. 支持读取教务处自动生成的excel课表文件。 - -> 这个功能需要电脑上安装excel应用程序. -> -> 目前这个功能仅作实验性的支持,不保证excel读取的完全准确。 -> -> > 使用帮助:在教务处网站“学期理论课表”页面有打印按钮,可以下载一个excel表格。 -> > -> > 下载完成后,在软件里点击“导入excel课表”按钮,选择excel文件下载的位置,即可自动导入。 - -### DDL部分 - -![DDL部分截图](DDL.png) - -1. 支持DDL事件的添加,修改,完成,删除。 - -2. 可以将活动界面中DDL类型的事件直接添加到个人DDL中。 - -### 活动部分 - -![活动部分截图](Activity.png) - -**本部分未完成,设想中将与[DDL网站](http://squidward.top)的数据进行同步** - -## 使用方法 - -软件依赖于.net6.0,请点击[链接](https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-desktop-6.0.2-windows-x64-installer)下载.net6.0运行时。 -在安装完成或者确认电脑上已安装.net6.0运行时之后,点击下载旁边的release包,双击下载文件中的PostCalendarWindows.exe即可使用。 diff --git a/YaeBlog/source/post-calendar/Activity.png b/YaeBlog/source/post-calendar/Activity.png deleted file mode 100644 index ea41cc4..0000000 --- a/YaeBlog/source/post-calendar/Activity.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cd0400f5618f0f7744f1ea9e0789801a66bc69c730026a8100a294367cb682de -size 27562 diff --git a/YaeBlog/source/post-calendar/Calendar.png b/YaeBlog/source/post-calendar/Calendar.png deleted file mode 100644 index 2a0e0a2..0000000 --- a/YaeBlog/source/post-calendar/Calendar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2b08f66405ead44d7528490af47b31c60422323ad1df12df7647a907f94cfb98 -size 96413 diff --git a/YaeBlog/source/post-calendar/DDL.png b/YaeBlog/source/post-calendar/DDL.png deleted file mode 100644 index 19ed2d3..0000000 --- a/YaeBlog/source/post-calendar/DDL.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e99070903250f8daf8ee0a14f4db63ae79ae5d6270d9aade8f62976ab1198e38 -size 29290 diff --git a/YaeBlog/source/program-design-introduction.md b/YaeBlog/source/program-design-introduction.md index 1c007aa..1171fdd 100644 --- a/YaeBlog/source/program-design-introduction.md +++ b/YaeBlog/source/program-design-introduction.md @@ -5,8 +5,6 @@ tags: - 学习资料 --- - -# 程序设计与计算导论笔记 直接扒的老黄的PPT ,简直毫无参考价值。 不保证笔记的绝对正确性。 如果导致考试爆炸,不承担任何责任。 @@ -17,4 +15,4 @@ tags: ## 第二章——C语言概述 ![第二章](./program-design-introduction/2.png) -![第二章](./program-design-introduction/3.png) \ No newline at end of file +![第二章](./program-design-introduction/3.png) diff --git a/YaeBlog/source/qt-learning.md b/YaeBlog/source/qt-learning.md index fcdf4ac..c18cf5e 100644 --- a/YaeBlog/source/qt-learning.md +++ b/YaeBlog/source/qt-learning.md @@ -7,8 +7,6 @@ typora-root-url: qt-learning date: 2022-07-01 14:32:39 --- -# 初学Qt的一点小笔记 - 最近的大作业需要用 `C/C++`的技术栈实现一个图形化界面,`Qt`作为C++图形化框架久负盛名,正好借着这个写大作业的机会学习一下这个应用广泛的框架。 diff --git a/YaeBlog/source/question-in-install-vs-2019.md b/YaeBlog/source/question-in-install-vs-2019.md index 84cdfae..4abbaf6 100644 --- a/YaeBlog/source/question-in-install-vs-2019.md +++ b/YaeBlog/source/question-in-install-vs-2019.md @@ -5,7 +5,6 @@ tags: - 技术笔记 --- -# 安装Visual Studio 2019中遇到的坑 在某个月黑风高的夜晚,我在折腾了很久的Python之后,突然感觉自己应该去学学C和C++,于是乎我便打算折腾一下在vscode上写C和C++。在网上一番搜寻之后,我发现了这篇[知乎文章](https://zhuanlan.zhihu.com/p/87864677)和这篇[知乎文章](https://zhuanlan.zhihu.com/p/147366852),然后我就被安装MinGW编译器和配置一大堆的json文件给干碎了。
于是,我决定转向传说中的宇宙第一IDE——Visual Studio。
diff --git a/YaeBlog/source/spring-boot-custom-authorize.md b/YaeBlog/source/spring-boot-custom-authorize.md index c814566..85736d1 100644 --- a/YaeBlog/source/spring-boot-custom-authorize.md +++ b/YaeBlog/source/spring-boot-custom-authorize.md @@ -6,8 +6,7 @@ tags: date: 2023-07-29 15:20:02 --- - -# SpringBoot自定义注解实现权限控制 +如题。 diff --git a/YaeBlog/source/using-vpn-elegant.md b/YaeBlog/source/using-vpn-elegant.md index ac4bffe..e508d30 100644 --- a/YaeBlog/source/using-vpn-elegant.md +++ b/YaeBlog/source/using-vpn-elegant.md @@ -5,7 +5,7 @@ tags: - 技术笔记 --- -# 优雅地使用学校VPN +睿智的Global Protect! diff --git a/YaeBlog/source/vscode-in-browser.md b/YaeBlog/source/vscode-in-browser.md index df5f086..fabede1 100644 --- a/YaeBlog/source/vscode-in-browser.md +++ b/YaeBlog/source/vscode-in-browser.md @@ -5,7 +5,6 @@ tags: - 技术笔记 --- -# 无论何处,都可以使用自己定制的VSCode开发环境 众所周知,VSCode作为大微软家开发的开源编辑器,一经发布便受到了两广大程序员群体的欢迎。如果我们深入的了解一下VSCode,就会知道VSCode是基于Electron框架构建的Web应用程序,而Electron框架是基于Web技术来开发桌面应用程序,即VSCode只要稍加改造,就可以流畅的在浏览器中运行。那么我们如何才能在浏览器打开一个VSCode呢? 最简单的方法是在浏览器中输入[这个网址](https://vscode.dev),就可以在浏览器中打开一个VSCode Online,这个版本的VSCode可以支持打开本地的文件,并且进行编辑。不过这个编辑器并不支持大部分的插件,而且并不支持程序的编译与运行,并不是一个可以开箱即用的编辑器。那么还有什么办法可以让我们拥有一个联网即可得的个人定制化开发环境呢? diff --git a/YaeBlog/source/wsl-setup-csapp.md b/YaeBlog/source/wsl-setup-csapp.md index 0f41676..9b2c144 100644 --- a/YaeBlog/source/wsl-setup-csapp.md +++ b/YaeBlog/source/wsl-setup-csapp.md @@ -7,9 +7,6 @@ typora-root-url: wsl-setup-csapp date: 2022-09-03 19:02:58 --- - -# 利用WSL设置CSAPP实验环境 - `CSAPP`这本书为自学的学生们提供了不少的`LAB`供大家在联系中提高,但是这些`LAB`的编写普遍需要一个`Linux`的实验环境,但是目前大多数人手中的环境都是`Windows`平台,没有办法原生的运行这些`LAB`。在以前的实践中,这个问题往往是通过安装虚拟机来解决的,但是现在我们有了更好的解决方案——`Windows Subsystem for Linux`,简称`WSL`。 diff --git a/YaeBlog/wwwroot/clipboard.min.js b/YaeBlog/wwwroot/clipboard.min.js new file mode 100644 index 0000000..1103f81 --- /dev/null +++ b/YaeBlog/wwwroot/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1