feat: 使用Bootstrap重写前端页面 #2

Merged
jackfiled merged 6 commits from feat-bootstrap into master 2024-07-22 16:59:43 +08:00
36 changed files with 123 additions and 1197 deletions
Showing only changes of commit 77e52fa11e - Show all commits

View File

@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.FluentUI.AspNetCore.Components;
using YaeBlog.Core.Models; using YaeBlog.Core.Models;
using YaeBlog.Core.Processors; using YaeBlog.Core.Processors;
using YaeBlog.Core.Services; using YaeBlog.Core.Services;
@ -15,7 +14,6 @@ public static class WebApplicationBuilderExtensions
builder.Services.Configure<BlogOptions>(builder.Configuration.GetSection(BlogOptions.OptionName)); builder.Services.Configure<BlogOptions>(builder.Configuration.GetSection(BlogOptions.OptionName));
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddFluentUIComponents();
builder.Services.AddMarkdig(); builder.Services.AddMarkdig();
builder.Services.AddYamlParser(); builder.Services.AddYamlParser();

View File

@ -30,8 +30,6 @@
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.6" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="YamlDotNet" Version="13.7.1" /> <PackageReference Include="YamlDotNet" Version="13.7.1" />
<PackageReference Include="Microsoft.FluentUI.AspNetCore.Components" Version="4.8.0" />
<PackageReference Include="Microsoft.FluentUI.AspNetCore.Components.Icons" Version="4.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,26 +0,0 @@
@using YaeBlog.Core.Models
@inject BlogOptions BlogOptionsInstance
<div style="width: 100%">
<FluentCard>
<div class="announcement-title">
<FluentIcon Value="@(new Icons.Regular.Size16.Note())" />
<FluentLabel Typo="@Typography.H5" Style="margin-left: 0.5rem">
公告
</FluentLabel>
</div>
<div style="height: 1rem"></div>
<FluentLabel>
@(BlogOptionsInstance.Announcement)
</FluentLabel>
<div style="height: 0.5rem"></div>
</FluentCard>
</div>
@code {
}

View File

@ -1,4 +0,0 @@
.announcement-title {
display: flex;
align-items: center;
}

View File

@ -7,21 +7,18 @@
<base href="/"/> <base href="/"/>
<link rel="stylesheet" href="YaeBlog.styles.css"/> <link rel="stylesheet" href="YaeBlog.styles.css"/>
<link rel="icon" href="images/favicon.ico"/> <link rel="icon" href="images/favicon.ico"/>
<link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/reboot.css" rel="stylesheet"/> <link rel="stylesheet" href="bootstrap.min.css"/>
<link href="globals.css" rel="stylesheet"/> <link rel="stylesheet" href="bootstrap-icons.min.css"/>
<link rel="stylesheet" href="_content/Blazor.Bootstrap/blazor.bootstrap.css"/>
<link rel="stylesheet" href="globals.css"/>
<HeadOutlet/> <HeadOutlet/>
</head> </head>
<body> <body>
<Routes/> <Routes/>
<FluentDesignTheme StorageName="theme" Mode="@DesignThemeModes.System"/>
<loading-theme storage-name="theme"></loading-theme>
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/js/loading-theme.js" type="text/javascript"></script>
<script src="_framework/blazor.web.js"></script> <script src="_framework/blazor.web.js"></script>
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.lib.module.js" type="module" async></script> <script src="bootstrap.bundle.min.js"></script>
<script src="themes.js" type="module"></script>
</body> </body>
</html> </html>

View File

@ -1,53 +0,0 @@
@using YaeBlog.Core.Models
@using YaeBlog.Core.Services
@inject BlogOptions BlogOptionsInstance
@inject EssayContentService EssayContentInstance
<div style="margin: 2rem 0; width: 100%">
<FluentCard>
<FluentStack Orientation="@Orientation.Vertical"
HorizontalAlignment="@HorizontalAlignment.Center">
<div class="about-avatar">
<img src="@(BlogOptionsInstance.About.AvatarImage)" alt="author-avatar"
class="about-avatar-img">
</div>
<FluentLabel Typo="@Typography.H3">
@(BlogOptionsInstance.Author)
</FluentLabel>
<div style="height: 0.5rem"></div>
<FluentStack Orientation="@Orientation.Horizontal"
HorizontalAlignment="@HorizontalAlignment.Center"
HorizontalGap="20">
<a href="/blog/archives">
<div>
<FluentLabel Typo="@Typography.H4">
文章
</FluentLabel>
<FluentLabel Typo="@Typography.H4">
@(EssayContentInstance.Count)
</FluentLabel>
</div>
</a>
<a href="/blog/tags">
<div>
<FluentLabel Typo="@Typography.H4">
标签
</FluentLabel>
<FluentLabel Typo="@Typography.H4">
@(EssayContentInstance.TagCount)
</FluentLabel>
</div>
</a>
</FluentStack>
</FluentStack>
</FluentCard>
</div>
@code {
}

View File

@ -1,30 +0,0 @@
.about-avatar {
position: relative;
width: 6rem;
height: 6rem;
z-index: 3;
}
.about-avatar-img {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: transparent;
object-fit: cover;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16),
0 2px 10px 0 rgba(0, 0, 0, 0.12);
}
.about-avatar-img:hover {
animation: rotate-animation 1s ease-in-out;
}
@keyframes rotate-animation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -1,33 +0,0 @@
@using YaeBlog.Core.Models
@inject BlogOptions BlogOptionsInstance
<div class="footer-content">
<div>
<a href="https://learn.microsoft.com/zh-cn/aspnet/core/blazor/" target="_blank" rel="nofollow noopener">
<span> Blazor </span>
</a>
<i class="love-tag"></i>
<span> YaeBlog </span>
<i class="love-tag"></i>
<span>FluentUI</span>
</div>
<div style="padding-top: 0.3rem">
<span>
©@(BlogOptionsInstance.StartYear) - @(DateTime.Now.Year) By @(BlogOptionsInstance.Author)
</span>
</div>
@if (!string.IsNullOrEmpty(BlogOptionsInstance.RegisterInformation))
{
<div style="padding-top: 0.3rem">
<a href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
<span>@(BlogOptionsInstance.RegisterInformation)</span>
</a>
</div>
}
</div>
@code {
}

View File

@ -1,14 +0,0 @@
.footer-content {
padding: 2rem 0 1rem 0;
text-align: center;
}
.love-tag {
font-style: normal;
font-weight: 400;
font-family: "Font Awesome 6 Free", sans-serif;
}
.love-tag::before {
content: "\f004";
}

View File

@ -1,36 +0,0 @@
<FluentGridItem md="3" sm="6" xs="12">
<FluentStack Orientation="@Orientation.Horizontal" HorizontalAlignment="@HorizontalAlignment.Center">
<div style="margin: 10px 20px; width: 75%; height: 90%">
<a href="@Address" target="_blank">
<FluentCard Width="100%" Height="100%">
<FluentStack Orientation="@Orientation.Horizontal">
<div style="width: 25%; margin: 5px 0">
<img src="@ImageAddress" alt="@Name" width="100%"/>
</div>
<FluentStack Orientation="@Orientation.Vertical">
<FluentLabel Typo="@Typography.H3">
@Name
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
@Description
</FluentLabel>
</FluentStack>
</FluentStack>
</FluentCard>
</a>
</div>
</FluentStack>
</FluentGridItem>
@code {
[Parameter] public string Name { get; set; } = string.Empty;
[Parameter] public string Description { get; set; } = string.Empty;
[Parameter] public string ImageAddress { get; set; } = string.Empty;
[Parameter] public string Address { get; set; } = string.Empty;
}

View File

@ -1,77 +1,9 @@
@using YaeBlog.Core.Models
@inherits LayoutComponentBase @inherits LayoutComponentBase
@inject BlogOptions BlogOptionsInstance <main>
<FluentLayout>
<FluentHeader>
<FluentStack Orientation="@Orientation.Horizontal">
<div style="width: 50px"></div>
<a href="/blog">
<FluentLabel Typo="@Typography.H3" Color="@Color.Lightweight">
@BlogOptionsInstance.Author
</FluentLabel>
</a>
<FluentSpacer/>
<a href="/blog" style="margin: auto 0 auto 0">
<div class="quick-link">
<FluentIcon Value="@(new Icons.Regular.Size16.Home())" Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Color="@Color.Lightweight"
Style="margin-left: 0.2rem">
首页
</FluentLabel>
</div>
</a>
<a href="/blog/archives" style="margin: auto 0 auto 0">
<div class="quick-link">
<FluentIcon Value="@(new Icons.Regular.Size16.Archive())" Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Color="@Color.Lightweight"
Style="margin-left: 0.2rem">
归档
</FluentLabel>
</div>
</a>
<a href="/blog/tags" style="margin: auto 0 auto 0">
<div class="quick-link">
<FluentIcon Value="@(new Icons.Regular.Size16.Tag())" Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Color="@Color.Lightweight"
Style="margin-left: 0.2rem">
标签
</FluentLabel>
</div>
</a>
<a href="/blog/about" style="margin: auto 0 auto 0">
<div class="quick-link">
<FluentIcon Value="@(new Icons.Regular.Size16.PersonInfo())" Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Color="@Color.Lightweight"
Style="margin-left: 0.2rem">
关于
</FluentLabel>
</div>
</a>
<a href="/blog/links" style="margin: auto 0 auto 0">
<div class="quick-link">
<FluentIcon Value="@(new Icons.Regular.Size16.LinkMultiple())" Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Color="@Color.Lightweight"
Style="margin-left: 0.2rem">
友链
</FluentLabel>
</div>
</a>
<div style="width: 20px"></div>
</FluentStack>
</FluentHeader>
<FluentBodyContent Style="height: 100%">
<main style="height: 100%">
@Body @Body
</main> </main>
</FluentBodyContent>
</FluentLayout> @code {
}

View File

@ -1,4 +0,0 @@
.quick-link {
display: flex;
align-items: center;
}

View File

@ -1,18 +1,45 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<main class="center">
<FluentLayout Style="min-height: 100vh"> <div class="container" style="height: 100%">
<FluentHeader Height="60"> <div class="row" style="height: 80px">
<a href="/"> <div class="px-2 col-8">
<FluentLabel Typo="@Typography.H3" Color="@Color.Lightweight"> <a href="https://rrricardo.top" class="p-2">
Ricardo's Index <h4>Ricardo's Index</h4>
</FluentLabel>
</a> </a>
</FluentHeader> </div>
<FluentBodyContent> <div class="col-4 d-flex justify-content-around align-items-center">
<main style="height: 100%"> <a href="https://github.com/jackfiled" class="p-2" target="_blank">
<h5>Github</h5>
</a>
<a href="mailto://shicangjuner@outlook.com" class="p-2" target="_blank">
<h5>E-mail</h5>
</a>
</div>
</div>
<article class="row px-4">
<div class="py-2">
@Body @Body
</main> </div>
</FluentBodyContent> </article>
</FluentLayout>
<div class="row align-items-end text-center">
<div class="row">
<p class="fs-6"> 2021 - 2024 By <a href="https://rrricardo.top" target="_blank">Ricardo Ren</a></p>
</div>
<div class="row">
<p class="fs-6">
<a href="https://beian.miit.gov.cn">蜀ICP备2022004429号-1</a>
</p>
</div>
</div>
</div>
</main>
@code {
}

View File

@ -0,0 +1,8 @@
.center {
margin: 0 auto;
min-height: 100vh;
max-width: 48em;
position: relative;
display: flex;
flex-direction: column;
}

View File

@ -1,42 +0,0 @@
@page "/blog/about"
@using YaeBlog.Core.Models
@inject BlogOptions BlogOptionsInstance
<PageTitle>
关于 - @(BlogOptionsInstance.Author)
</PageTitle>
<div style="height: 100%">
<div class="about-background" style="background-image: url('@(BlogOptionsInstance.EssayImage)')">
<div class="about-content">
<FluentCard>
<FluentStack Orientation="@Orientation.Vertical"
HorizontalAlignment="@HorizontalAlignment.Center">
<div class="about-avatar">
<img src="@(BlogOptionsInstance.About.AvatarImage)" alt="author-avatar"
class="about-avatar-img">
</div>
<FluentLabel Typo="@Typography.H2">
@(BlogOptionsInstance.Author)
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
@(BlogOptionsInstance.About.Introduction)
</FluentLabel>
</FluentStack>
<div style="height: 2rem"></div>
<FluentLabel Typo="@Typography.Body">
@(BlogOptionsInstance.About.Description)
</FluentLabel>
</FluentCard>
</div>
</div>
<BlogFooter/>
</div>
@code {
}

View File

@ -1,45 +0,0 @@
.about-background {
position: relative;
height: 100%;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
}
.about-content {
top: 33%;
position: absolute;
width: 80%;
margin: 0 10%;
}
.about-avatar {
position: relative;
width: 10rem;
height: 10rem;
z-index: 3;
}
.about-avatar-img {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: transparent;
object-fit: cover;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16),
0 2px 10px 0 rgba(0, 0, 0, 0.12);
}
.about-avatar-img:hover {
animation: rotate-animation 1s ease-in-out;
}
@keyframes rotate-animation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -1,78 +0,0 @@
@page "/blog/archives"
@using YaeBlog.Core.Models
@using YaeBlog.Core.Services
@inject BlogOptions BlogOptionsInstance
@inject EssayContentService EssayContentInstance
<PageTitle>
存档
</PageTitle>
<div style="height: 100%">
<div class="archive-background" style="background-image: url('@(BlogOptionsInstance.EssayImage)')">
<div class="archive-title">
<FluentStack Orientation="@Orientation.Vertical"
HorizontalAlignment="@HorizontalAlignment.Center">
<FluentLabel Typo="@Typography.H1" Color="@Color.Fill">
存 档
</FluentLabel>
</FluentStack>
</div>
</div>
<div style="height: 2rem"></div>
<div style="margin: 0 8% 0 8%">
<FluentCard>
<div style="margin: 0 8% 0 8%">
<FluentLabel Typo="@Typography.H2" Style="margin: 3rem 0 2rem 0; color: #404853">
共计@(EssayContentInstance.Count)篇文章
</FluentLabel>
@foreach (IGrouping<DateTime, KeyValuePair<string, BlogEssay>> group in _essays)
{
<FluentLabel Typo="@Typography.H3" Style="color: #718096; margin: 2rem 0 1rem 0">
@(group.Key.ToString("yyyy年"))
</FluentLabel>
<div style="margin: 0 4% 0 4%">
@foreach (KeyValuePair<string, BlogEssay> pair in group)
{
<div class="archive-item">
<a href="/blog/essays/@(pair.Key)" target="_blank">
<FluentStack Orientation="@Orientation.Horizontal">
<FluentLabel Typo="@Typography.H5" Style="width: 80px">
@(pair.Value.PublishTime.ToString("MM-dd"))
</FluentLabel>
<FluentLabel Typo="@Typography.H5">
@(pair.Value.Title)
</FluentLabel>
</FluentStack>
</a>
</div>
}
</div>
}
</div>
</FluentCard>
</div>
<BlogFooter/>
</div>
@code {
private readonly List<IGrouping<DateTime, KeyValuePair<string, BlogEssay>>> _essays = [];
protected override void OnInitialized()
{
IEnumerable<IGrouping<DateTime, KeyValuePair<string, BlogEssay>>> essays =
from essay in EssayContentInstance.Essays
orderby essay.Value.PublishTime descending
group essay by new DateTime(essay.Value.PublishTime.Year, 1, 1);
_essays.AddRange(essays);
}
}

View File

@ -1,24 +0,0 @@
.archive-background {
position: relative;
height: 60%;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
}
.archive-title {
top: 43%;
position: absolute;
width: 100%;
}
.archive-item {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
margin: 0.5rem 0 0.5rem 0;
border-radius: 4px;
}
.archive-item:hover {
background-color: rgba(169, 169, 169, 0.22);
}

View File

@ -1,179 +0,0 @@
@page "/blog"
@using YaeBlog.Core.Models
@using YaeBlog.Core.Services
@inject BlogOptions BlogOptionsInstance
@inject EssayContentService EssayContentInstance
@inject NavigationManager NavigationManagerInstance
<PageTitle>
@(BlogOptionsInstance.Author)'s Blog
</PageTitle>
<div style="height: 100%">
<div class="banner" style="background-image: url('@BlogOptionsInstance.BannerImage')">
<div class="blog-title">
<FluentLabel Typo="@Typography.H1" Style="color: white">
@(BlogOptionsInstance.Author)'s Blog
</FluentLabel>
</div>
<div class="scroll-down">
<i class="scroll-down-tag"></i>
</div>
</div>
<div style="height: 2rem" id="blog-content"></div>
<div style="margin: 0 8% 0 8%">
<FluentGrid>
<FluentGridItem xs="12" sm="12" md="9" lg="9">
<div>
@foreach (KeyValuePair<string, BlogEssay> essay in _essays)
{
<FluentCard Style="margin: 2rem 0 2rem 0">
<div>
<a href="/blog/essays/@(essay.Key)" target="_blank">
<FluentLabel Typo="@Typography.H4">
@(essay.Value.Title)
</FluentLabel>
</a>
<div style="margin: 0.5rem 0 0.5rem 0">
<a href="/blog/essays/@(essay.Key)" target="_blank" style="color: #718096;">
<div class="essay-description">
@(essay.Value.Description)
</div>
</a>
</div>
<FluentStack VerticalAlignment="@VerticalAlignment.Center"
Style="margin: 1rem 0 1rem 0"
HorizontalGap="4">
<FluentIcon Value="@(new Icons.Regular.Size16.Calendar())"/>
<span style="margin: auto 0 auto 0">
@(essay.Value.PublishTime.ToString("yyyy-MM-dd HH:mm:ss"))
</span>
@if (essay.Value.Tags.Count != 0)
{
<FluentIcon Value="@(new Icons.Regular.Size16.TagMultiple())"/>
@foreach (string tag in essay.Value.Tags)
{
<span style="margin: auto 0 auto 0">
@tag
</span>
}
}
</FluentStack>
</div>
</FluentCard>
}
<div class="pagination">
<FluentStack HorizontalAlignment="@HorizontalAlignment.Center"
HorizontalGap="20">
@if (Page != 1)
{
<a href="/blog/?page=@(Page - 1)#blog-content" class="pagination-item">
<i class="chevron-left"></i>
</a>
}
@if (Page == 1)
{
<a href="/blog/?page=1#blog-content" class="pagination-item">
<span>1</span>
</a>
<a href="/blog/?page=2#blog-content" class="pagination-item">
<span>2</span>
</a>
<a href="/blog/?page=3#blog-content" class="pagination-item">
<span>3</span>
</a>
}
else if (Page == _pageCount)
{
<a href="/blog/?page=@(_pageCount - 2)#blog-content" class="pagination-item">
<span>@(_pageCount - 2)</span>
</a>
<a href="/blog/?page=@(_pageCount - 1)#blog-content" class="pagination-item">
<span>@(_pageCount - 1)</span>
</a>
<a href="/blog/?page=@(_pageCount)#blog-content" class="pagination-item">
<span>@(_pageCount)</span>
</a>
}
else
{
<a href="/blog/?page=@(Page - 1)#blog-content" class="pagination-item">
<span>@(Page - 1)</span>
</a>
<a href="/blog/?page=@(Page)#blog-content" class="pagination-item">
<span>@(Page)</span>
</a>
<a href="/blog/?page=@(Page + 1)#blog-content" class="pagination-item">
<span>@(Page + 1)</span>
</a>
}
@if (Page != _pageCount)
{
<a href="/blog/?page=@(Page + 1)#blog-content" class="pagination-item">
<i class="chevron-right"></i>
</a>
}
</FluentStack>
</div>
</div>
</FluentGridItem>
<FluentGridItem xs="12" sm="12" md="3" lg="3">
<FluentStack Orientation="@Orientation.Vertical">
<AuthorInformation/>
<Announcement/>
</FluentStack>
</FluentGridItem>
</FluentGrid>
</div>
<BlogFooter/>
</div>
@code {
[SupplyParameterFromQuery] private int? Page { get; set; }
private readonly List<KeyValuePair<string, BlogEssay>> _essays = [];
private int _pageCount;
protected override void OnInitialized()
{
Page ??= 1;
IEnumerable<KeyValuePair<string, BlogEssay>[]> chunks =
EssayContentInstance.Essays
.OrderByDescending(pair => pair.Value.PublishTime)
.Chunk(10);
var count = 1;
var flag = false;
foreach (KeyValuePair<string, BlogEssay>[] chunk in chunks)
{
if (Page == count)
{
flag = true;
_essays.AddRange(chunk);
}
count += 1;
}
_pageCount = count - 1;
if (flag is false)
{
NavigationManagerInstance.NavigateTo("/NotFount");
}
}
}

View File

@ -1,96 +0,0 @@
.banner {
position: relative;
height: 100%;
overflow: hidden;
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
}
.blog-title {
color: white;
text-align: center;
top: 43%;
position: absolute;
width: 100%;
}
.scroll-down {
position: absolute;
bottom: 0;
width: 100%;
}
.scroll-down-tag {
font-family: "Font Awesome 6 Free", sans-serif;
font-size: 36px;
font-style: normal;
font-weight: 900;
color: white;
text-align: center;
position: relative;
display: inline-block;
width: 100%;
animation: scroll-down-animation 1.5s infinite;
}
.scroll-down-tag::before {
content: "\f107";
}
@keyframes scroll-down-animation {
0% {
top: 0;
opacity: 0.4;
}
50% {
top: -20px;
opacity: 1;
}
100% {
top: 0;
opacity: 0.4;
}
}
.essay-description {
width: 100%;
line-height: 1.4rem;
word-break: break-word;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.pagination {
font-size: 2em;
}
.pagination-item {
margin: auto 0 auto 0;
}
.chevron-left {
font-size: 1.2rem;
font-family: "Font Awesome 6 Free", sans-serif;
font-style: normal;
font-weight: 900;
}
.chevron-left::before {
content: "\f053";
}
.chevron-right {
font-size: 1.2rem;
font-family: "Font Awesome 6 Free", sans-serif;
font-style: normal;
font-weight: 900;
}
.chevron-right::before {
content: "\f054";
}

View File

@ -1,83 +0,0 @@
@page "/blog/essays/{Filename}"
@using YaeBlog.Core.Models
@using YaeBlog.Core.Services
@inject BlogOptions BlogOptionsInstance
@inject EssayContentService EssayContent
@inject NavigationManager NavigationInstance
<PageTitle>
@(_essay!.Title)
</PageTitle>
<div style="height: 100%">
<div class="essay-background" style="background-image: url('@(BlogOptionsInstance.EssayImage)')">
<div class="essay-title">
<FluentStack Orientation="@Orientation.Vertical"
HorizontalAlignment="@HorizontalAlignment.Center">
<FluentLabel Typo="@Typography.H1" Style="color: white">
@(_essay!.Title)
</FluentLabel>
<div class="essay-subtitle">
<FluentIcon Value="@(new Icons.Regular.Size16.Calendar())"
Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Style="color: white; margin-left: 0.25rem">
@(_essay!.PublishTime.ToString("yyyy年MM月dd日"))
</FluentLabel>
</div>
<div class="essay-subtitle">
<FluentIcon Value="@(new Icons.Regular.Size16.DataBarVerticalAscending())"
Color="@Color.Fill"/>
<FluentLabel Typo="@Typography.H5" Style="color: white; margin-left: 0.25rem">
@(_essay!.WordCount)字
</FluentLabel>
</div>
</FluentStack>
</div>
</div>
<div style="height: 2rem"></div>
<div style="margin: 0 8% 0 8%">
<FluentGrid>
<FluentGridItem xs="12" sm="12" md="8" lg="8">
<FluentCard Style="margin: 2rem 0">
<div class="essay-content">
@((MarkupString)_essay!.HtmlContent)
</div>
</FluentCard>
</FluentGridItem>
<FluentGridItem xs="12" sm="12" md="4" lg="4">
<FluentStack Orientation="@Orientation.Vertical">
<AuthorInformation/>
<Announcement/>
</FluentStack>
</FluentGridItem>
</FluentGrid>
</div>
<BlogFooter/>
</div>
@code {
[Parameter] public string? Filename { get; set; }
private BlogEssay? _essay;
protected override void OnInitialized()
{
if (string.IsNullOrEmpty(Filename))
{
NavigationInstance.NavigateTo("NotFound");
return;
}
if (!EssayContent.TryGet(Filename, out _essay))
{
NavigationInstance.NavigateTo("NotFound");
}
}
}

View File

@ -1,24 +0,0 @@
.essay-background {
position: relative;
height: 80%;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
}
.essay-title {
color: white;
top: 43%;
position: absolute;
width: 100%;
}
.essay-content {
font-size: 1rem;
line-height: 1.6;
}
.essay-subtitle {
display: flex;
align-items: center;
}

View File

@ -1,89 +1,53 @@
@page "/" @page "/"
<PageTitle> <div class="container">
初冬的朝阳个人主页 <div class="row py-4">
</PageTitle> <div class="col-4">
<Image Src="images/avatar.png" Alt="Ricardo's Avatar"/>
<FluentStack Orientation="@Orientation.Vertical" Width="100%" Style="min-height: 100%">
<div style="width: 100%; height: auto">
<FluentGrid>
<FluentGridItem md="3" xs="12">
<FluentStack Orientation="@Orientation.Horizontal" HorizontalAlignment="@HorizontalAlignment.Center">
<img src="images/avatar.png" alt="Ricardo's Avatar" class="avatar-image"/>
</FluentStack>
</FluentGridItem>
<FluentGridItem md="9" xs="12">
<FluentStack Orientation="@Orientation.Vertical" Style="padding: 25px" VerticalGap="20">
<FluentLabel Typo="@Typography.H3" Weight="@FontWeight.Bold">
初冬的朝阳 (Ricardo Ren)
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
a.k.a jackfiled
</FluentLabel>
<FluentLabel Typo="@Typography.Body" Style="font-style: italic">
世界很大,时间很长。
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
一个平平无奇的CS学生。
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
还太菜了,连微小的贡献都没做。
</FluentLabel>
<div style="height: 20px"></div>
<FluentStack Orientation="@Orientation.Horizontal" HorizontalGap="20">
<FluentLabel Typo="@Typography.Body">
<a href="https://github.com/jackfiled">Github</a>
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
<a href="https://git.rrricardo.top/jackfiled">Gitea</a>
</FluentLabel>
<FluentLabel Typo="@Typography.Body">
<a href="mailto://shicangjuner@outlook.com">E-Mail</a>
</FluentLabel>
</FluentStack>
</FluentStack>
</FluentGridItem>
</FluentGrid>
</div> </div>
<FluentStack Orientation="@Orientation.Horizontal" HorizontalAlignment="@HorizontalAlignment.Center"> <div class="col-8">
<FluentDivider Style="width: 90%" Orientation="@Orientation.Horizontal" Role="@DividerRole.Separator"/> <div class="container px-3">
</FluentStack> <div class="row">
<h4 class="fw-bold">初冬的朝阳 (Ricardo Ren)</h4>
<div style="width: 100%; height: auto">
<FluentGrid Justify="@JustifyContent.Center">
<WebsiteCard Name="部落格" Address="/blog/" ImageAddress="/images/blog-icon.png"
Description="奇奇怪怪东西的聚集地"/>
<WebsiteCard Name="笔记本" Address="https://jackfiled.github.io/wiki/" ImageAddress="/images/wiki-icon.png"
Description="技校学习笔记"/>
</FluentGrid>
</div> </div>
<div class="row">
<p class="fs-5">a.k.a jackfiled</p>
</div>
<div style="flex: 1"></div> <div class="row">
<p class="fs-5 fst-italic">世界很大,时间很长。</p>
</div>
<FluentStack Orientation="@Orientation.Horizontal" HorizontalAlignment="@HorizontalAlignment.Center"> <div class="row">
<FluentStack Orientation="@Orientation.Vertical" HorizontalAlignment="@HorizontalAlignment.Center" <p class="fs-5">
Style="padding: 20px"> 平平无奇的计算机科学与技术学徒,连微小的贡献都没做。
<FluentLabel> </p>
2021 - @(DateTimeOffset.Now.Year) By <a href="https://rrricardo.top">Ricardo Ren</a> </div>
</FluentLabel> </div>
</div>
<FluentLabel> <div class="row" style="padding-top: 80px">
<a href="https://beian.miit.gov.cn">蜀ICP备2022004429号-1</a> <p class="fs-5">恕我不能亲自为您沏茶(?),还是非常欢迎您能够来到我的主页。</p>
</FluentLabel> </div>
</FluentStack>
</FluentStack> <div class="row">
</FluentStack> <p class="fs-5">
如果您想四处看看,了解一下屏幕对面的人,可以在我的 <a href="https://rrricardo.top/blog/">博客</a> 看看。
如果您对于明光村幼儿园某附属技校的计算机教学感兴趣,您可以移步到
<a href="https://jackfiled.github.io/wiki/">我的学习笔记</a>
<span class="fs-5 text-decoration-line-through">虽然这笔记我自己也木有看过。</span>
如果您想批判一下我的代码,在 <a href="https://github.com/jackfiled" target="_blank">Github</a> 和
<a href="https://git.rrricardo.top/jackfiled/" target="_blank">Gitea</a> 都可以看见。
</p>
<p class="fs-5">
如果您真的很闲,也可以四处搜寻一下,也许存在着一些不为人知的彩蛋。
</p>
</div>
</div>
</div>
@code { @code {

View File

@ -1,15 +0,0 @@
.index-container {
background-color: #f0f2f5;
}
.avatar-image {
margin: 25px;
width: 100%;
height: auto;
max-width: 300px;
max-height: 300px;
}
.footer-zone {
text-align: center;
}

View File

@ -1,58 +0,0 @@
@page "/blog/links"
@using YaeBlog.Core.Models
@inject BlogOptions BlogOptionsInstance
<PageTitle>
友链
</PageTitle>
<div style="height: 100%">
<div class="link-background" style="background-image: url('@(BlogOptionsInstance.EssayImage)')">
<div class="link-content">
<FluentStack Orientation="@Orientation.Vertical"
HorizontalAlignment="@HorizontalAlignment.Center">
<FluentLabel Typo="@Typography.H2" Style="color: white">
友 情 链 接
</FluentLabel>
<div style="height: 5rem"></div>
<FluentCard Style="padding: 3rem;">
<FluentGrid>
@foreach (FriendLink link in BlogOptionsInstance.Links)
{
<FluentGridItem xs="12" sm="6" md="4" lg="3">
<a href="@(link.Link)" target="_blank">
<div class="link-item">
<div class="link-item-image">
<img src="@(link.AvatarImage)" alt="@(link.Name)">
</div>
<div style="margin: 0.5rem">
<FluentLabel Typo="@Typography.H4">
@(link.Name)
</FluentLabel>
<FluentLabel Typo="@Typography.Body" Style="color: #718096">
@(link.Description)
</FluentLabel>
</div>
</div>
</a>
</FluentGridItem>
}
</FluentGrid>
</FluentCard>
</FluentStack>
</div>
</div>
<BlogFooter/>
</div>
@code {
}

View File

@ -1,37 +0,0 @@
.link-background {
position: relative;
height: 100%;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
}
.link-content {
top: 23%;
position: absolute;
width: 80%;
margin: 0 10%;
}
.link-item {
display: flex;
padding: 1rem;
border-radius: 4px;
}
.link-item:hover {
background-color: rgba(172, 172, 172, 0.25);
}
.link-item-image {
width: 4rem;
height: 4rem;
}
.link-item-image img {
width: 100%;
height: 100%;
border-radius: 50%;
}

View File

@ -1,17 +0,0 @@
@page "/NotFound"
<div style="height: 100%">
<div style="height: 2rem"></div>
<div style="margin: 0 8%">
<FluentCard>
<FluentLabel Typo="@Typography.H4">
前面的区域,以后再来探索吧,,
</FluentLabel>
</FluentCard>
</div>
</div>
@code {
}

View File

@ -1,96 +0,0 @@
@page "/blog/tags"
@using YaeBlog.Core.Models
@using YaeBlog.Core.Services
@inject BlogOptions BlogOptionsInstance
@inject EssayContentService EssayContentInstance
<PageTitle>
标签
</PageTitle>
<div style="height: 100%">
<div class="tag-background" style="background-image: url('@(BlogOptionsInstance.EssayImage)')">
<div class="tag-title">
<FluentStack Orientation="@Orientation.Vertical"
HorizontalAlignment="@HorizontalAlignment.Center">
<FluentLabel Typo="@Typography.H1" Color="@Color.Fill">
@(TagName ?? "标 签")
</FluentLabel>
</FluentStack>
</div>
</div>
<div style="height: 2rem"></div>
<div style="margin: 0 8% 0 8%">
<FluentCard>
<div style="margin: 0 8%">
@if (TagName is null)
{
<FluentStack Orientation="@Orientation.Horizontal"
Wrap="true" Style="margin: 2rem 0">
@foreach (KeyValuePair<string, int> pair in EssayContentInstance.Tags)
{
<div class="tag-item">
<a href="/blog/tags?TagName=@(pair.Key)">
<span style="font-size: @(14 + pair.Value)px; color: @(RandomColor())">
@pair.Key
</span>
</a>
</div>
}
</FluentStack>
}
else
{
<FluentLabel Typo="@Typography.H2" Style="margin: 3rem 0 2rem 0; color: #404853">
共计@(EssayContentInstance.GetTag(TagName).Count())篇文章
</FluentLabel>
@foreach (BlogEssay essay in EssayContentInstance.GetTag(TagName))
{
<div style="margin: 0 4% 0 4%">
<div class="tag-essay-item">
<a href="/blog/essays/@(essay.FileName)" target="_blank">
<FluentStack Orientation="@Orientation.Horizontal">
<FluentLabel Typo="@Typography.H5" Style="width: 120px">
@(essay.PublishTime.ToString("yyyy-MM-dd"))
</FluentLabel>
<FluentLabel Typo="@Typography.H5">
@(essay.Title)
</FluentLabel>
</FluentStack>
</a>
</div>
</div>
}
}
</div>
</FluentCard>
</div>
<BlogFooter/>
</div>
@code {
[SupplyParameterFromQuery]
private string? TagName { get; set; }
private static string[] s_colors =
[
"#337ab7",
"#bbe",
"#4e87c2",
"#a0aee3",
"#6994cd",
"#85a1d8"
];
private static string RandomColor()
{
return Random.Shared.GetItems(s_colors, 1)[0];
}
}

View File

@ -1,27 +0,0 @@
.tag-background {
position: relative;
height: 60%;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
}
.tag-title {
top: 43%;
position: absolute;
width: 100%;
}
.tag-item {
margin: 0.25rem auto;
}
.tag-essay-item {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
margin: 0.5rem 0 0.5rem 0;
border-radius: 4px;
}
.tag-essay-item:hover {
background-color: rgba(169, 169, 169, 0.22);
}

View File

@ -6,6 +6,7 @@ WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents() builder.Services.AddRazorComponents()
.AddInteractiveServerComponents(); .AddInteractiveServerComponents();
builder.Services.AddControllers(); builder.Services.AddControllers();
builder.Services.AddBlazorBootstrap();
builder.AddYaeBlog(); builder.AddYaeBlog();
WebApplication application = builder.Build(); WebApplication application = builder.Build();

View File

@ -4,6 +4,10 @@
<ProjectReference Include="..\YaeBlog.Core\YaeBlog.Core.csproj" /> <ProjectReference Include="..\YaeBlog.Core\YaeBlog.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Blazor.Bootstrap" Version="3.0.0-preview.2" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>

View File

@ -6,6 +6,6 @@
@using static Microsoft.AspNetCore.Components.Web.RenderMode @using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using Microsoft.FluentUI.AspNetCore.Components @using BlazorBootstrap
@using YaeBlog @using YaeBlog
@using YaeBlog.Components @using YaeBlog.Components

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
YaeBlog/wwwroot/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long