系列文章
- 基于 abp vNext 和 .NET Core 開發博客專案 - 使用 abp cli 搭建專案
- 基于 abp vNext 和 .NET Core 開發博客專案 - 給專案瘦身,讓它跑起來
- 基于 abp vNext 和 .NET Core 開發博客專案 - 完善與美化,Swagger登場
- 基于 abp vNext 和 .NET Core 開發博客專案 - 資料訪問和代碼優先
- 基于 abp vNext 和 .NET Core 開發博客專案 - 自定義倉儲之增刪改查
- 基于 abp vNext 和 .NET Core 開發博客專案 - 統一規范API,包裝回傳模型
- 基于 abp vNext 和 .NET Core 開發博客專案 - 再說Swagger,分組、描述、小綠鎖
- 基于 abp vNext 和 .NET Core 開發博客專案 - 接入GitHub,用JWT保護你的API
- 基于 abp vNext 和 .NET Core 開發博客專案 - 例外處理和日志記錄
- 基于 abp vNext 和 .NET Core 開發博客專案 - 使用Redis快取資料
- 基于 abp vNext 和 .NET Core 開發博客專案 - 集成Hangfire實作定時任務處理
- 基于 abp vNext 和 .NET Core 開發博客專案 - 用AutoMapper搞定物件映射
- 基于 abp vNext 和 .NET Core 開發博客專案 - 定時任務最佳實戰(一)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 定時任務最佳實戰(二)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 定時任務最佳實戰(三)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 博客介面實戰篇(一)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 博客介面實戰篇(二)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 博客介面實戰篇(三)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 博客介面實戰篇(四)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 博客介面實戰篇(五)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(一)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(二)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(三)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(四)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(五)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(六)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(七)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(八)
- 基于 abp vNext 和 .NET Core 開發博客專案 - Blazor 實戰系列(九)
- 基于 abp vNext 和 .NET Core 開發博客專案 - 終結篇之發布專案
上一篇完成了分類標簽友鏈的串列查詢頁面資料系結,還剩下一個文章詳情頁的資料沒有綁,現在簡單的解決掉,
文章詳情
之前已經添加了四個引數:year、month、day、name,用來組成我們最終的URL,繼續添加一個引數用來接收API回傳的資料,
[Parameter]
public int year { get; set; }
[Parameter]
public int month { get; set; }
[Parameter]
public int day { get; set; }
[Parameter]
public string name { get; set; }
/// <summary>
/// URL
/// </summary>
private string url => $"/{year}/{(month >= 10 ? month.ToString() : $"0{month}")}/{(day >= 10 ? day.ToString() : $"0{day}")}/{name}/";
/// <summary>
/// 文章詳情資料
/// </summary>
private ServiceResult<PostDetailDto> post;
然后在初始化方法OnInitializedAsync()中請求資料,
/// <summary>
/// 初始化
/// </summary>
protected override async Task OnInitializedAsync()
{
// 獲取資料
post = await Http.GetFromJsonAsync<ServiceResult<PostDetailDto>>($"/blog/post?url={url}");
}
現在拿到了post資料,然后在HTML中系結即可,
@if (post == null)
{
<Loading />
}
else
{
@if (post.Success)
{
var _post = post.Result;
<article class="post-wrap">
<header class="post-header">
<h1 class="post-title">@_post.Title</h1>
<div class="post-meta">
Author: <a itemprop="author" rel="author" href="javascript:;">@_post.Author</a>
<span class="post-time">
Date: <a href="javascript:;">@_post.CreationTime</a>
</span>
<span class="post-category">
Category:<a href="/category/@_post.Category.DisplayName/">@_post.Category.CategoryName</a>
</span>
</div>
</header>
<div class="post-content" id="content">
@((MarkupString)_post.Html)
</div>
<section class="post-copyright">
<p class="copyright-item">
<span>Author:</span>
<span>@_post.Author</span>
</p>
<p class="copyright-item">
<span>Permalink:</span>
<span><a href="/post@_post.Url">https://meowv.com/post@_post.Url</a></span>
</p>
<p class="copyright-item">
<span>License:</span>
<span>本文采用<a target="_blank" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"> 知識共享 署名-非商業性使用-禁止演繹(CC BY-NC-ND)國際許可協議 </a>進行許可</span>
</p>
</section>
<section class="post-tags">
<div>
<span>Tag(s):</span>
<span class="tag">
@if (_post.Tags.Any())
{
@foreach (var tag in _post.Tags)
{
<a href="/tag/@tag.DisplayName/"># @tag.TagName</a>
}
}
</span>
</div>
<div>
<a @onclick="async () => await Common.BaskAsync()">back</a>
<span>· </span>
<a href="/">home</a>
</div>
</section>
<section class="post-nav">
@if (_post.Previous != null)
{
<a class="prev"
rel="prev"
@onclick="@(async () => await Common.NavigateTo($"/post{_post.Previous.Url}, true))"
href="/post@_post.Previous.Url">@_post.Previous.Title</a>
}
@if (_post.Next != null)
{
<a class="next"
rel="next"
@onclick="@(async () => await Common.NavigateTo($"/post{_post.Next.Url}", true))"
href="/post@_post.Next.Url">
@_post.Next.Title
</a>
}
</section>
</article>
}
else
{
<ErrorTip />
}
}
其中有幾個地方需要注意一下:
我們從post物件中取到的文章內容HTML,直接顯示是不行了,需要將其決議為HTML標簽,需要用到MarkupString,
然后頁面上有一個后退按鈕,這里我在Common.cs中寫了一個方法來實作,
/// <summary>
/// 后退
/// </summary>
/// <returns></returns>
public async Task BaskAsync()
{
await InvokeAsync("window.history.back");
}
還有就是上一篇和下一篇的問題,將具體的URL傳遞給NavigateTo()方法,然后跳轉過去即可,
在Common.cs中將之前文章創建RenderPage()方法修改成NavigateTo(),這個命名更好一點,
/// <summary>
/// 跳轉指定URL
/// </summary>
/// <param name="uri"></param>
/// <param name="forceLoad">true,繞過路由重繪頁面</param>
/// <returns></returns>
public async Task NavigateTo(string url, bool forceLoad = false)
{
_navigationManager.NavigateTo(url, forceLoad);
await Task.CompletedTask;
}
現在資料算是系結完了,但是遇到了一個大問題,就是詳情頁面的樣式問題,因為用到了Markdown,所以之前是加載了許多JS檔案來處理的,那么現在肯定行不通了,所以關于詳情頁的樣式問題暫時擱淺,讓我尋找一下好多解決方式,
現在顯示是沒有問題了,就是不太好看,還有關于添加文章的功能,不知道有什么好的 Markdown 編輯器可以推薦我使用,

到這里Blazor的前端展示頁面已經全部弄完了,接下來開始寫后臺相關的頁面,
后臺首頁
關于后臺管理的所有頁面都放在Admin檔案夾下,在Pages檔案夾下新建Admin檔案夾,然后先添加兩個組件頁面:Admin.razor、Auth.razor,
Admin.razor為后臺管理的首頁入口,我們在里面直接添加幾個預知的鏈接并設定其路由,
@page "/admin"
<div class="post-wrap">
<h2 class="post-title">- 博客內容管理 -</h2>
<ul>
<li>
<a href=https://www.cnblogs.com/meowv/p/"/admin/post">??~~~ 新增文章 ~~~??
??~~~ 文章管理 ~~~??
??~~~ 分類管理 ~~~??
??~~~ 標簽管理 ~~~??
??~~~ 友鏈管理 ~~~??



