我最近购买了一个 HTML 模板,打算用来优化一下我 ASP.NET Core 项目的前端。我写的 html 都是原生的 ASP.NET Core 的,都太丑了。
所以,在开始之前,我们先学习一下这个模板。它的仪表板页面长这样:
```html
Welcome Back, Chris!
AppStack Dashboard
$ 24.300
Total Earnings
+5.35%
Since last week
43
Pending Orders
-4.25%
Since last week
$ 18.700
Total Revenue
+8.65%
Since last week
5m ago
Ashley Briggs started following Stacie Hall
Today 7:51 pm
30m ago
Chris Wood posted something on
Stacie Hall 's timeline
Today 7:21 pm
Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing...
1h ago
Stacie Hall posted a new blog
Today 6:35 pm
Source
Revenue
Value
Direct
$ 2602
+43%
Affiliate
$ 1253
+13%
E-mail
$ 541
+24%
Other
$ 1465
+11%
Chat with Carl and Ashley
30m ago
Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris...
The big launch
2h ago
Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum
nunc...
Coffee break
3h ago
Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada...
Chat with team
30m ago
Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum...
Name
Company
Author
Status
Action
Project Apollo
Web, UI/UX Design
Gantos
Real Estate
Carl Jenkins
HTML, JS, React
View
Adray Transportation
Transportation
Bertha Martin
HTML, JS, Vue
View
Project Canary
Web, UI/UX Design
Evans
Insurance
Stacie Hall
HTML, JS, Laravel
View
Project Edison
UI/UX Design
Monsource Investment Group
Finance
Carl Jenkins
HTML, JS, React
View
Project Indigo
Web, UI/UX Design
Edwards
Retail
Ashley Briggs
HTML, JS, Vue
View
```
看得出来,上面是一个仪表板页面,展示了基本的控件。
它的个人资料页面长这样:
```html
Profile
Stacie Hall
Lead Developer
5m ago
Ashley Briggs started following Stacie Hall
Today 7:51 pm
30m ago
Chris Wood posted something on
Stacie Hall 's timeline
Today 7:21 pm
Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus
pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante.
Like
1h ago
Stacie Hall posted a new blog
Today 6:35 pm
3h ago
Carl Jenkins posted two photos on
Stacie Hall 's timeline
Today 5:12 pm
Like
1d ago
Carl Jenkins started following
Stacie Hall
Yesterday 3:12 pm
Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus.
1d ago
Stacie Hall posted a new blog
Yesterday 2:43 pm
1d ago
Chris Wood started following Stacie Hall
Yesterdag 1:51 pm
看得出来这是一个漂亮的个人资料页面。
它的登录页面长这样:
```
看得出来是个标准的登录页面。
它还示范了文件管理器的做法:
```
File Manager
Upload File
Storage
72.6 GB (73%) of 100 GB used
```
也给出了基础的设置页面:
```html
```
这些页面,只要按照它的标准,就写出来都非常漂亮。我想你已经能想象出这些页面布局多么漂亮合理。
我们现在一起来学习一下它的使用范式。虽然我知道它是标准的bootstrap,但我们要理解它是如何建设审美以构建这么漂亮的仪表板的。
它之所以看起来美观、专业,是因为它遵循了一套现代前端设计的范式和原则。我们来一起拆解和学习它,这样你就能得心应手地将它应用到你的 ASP.NET Core 项目中了。
简单来说,这个模板的“审美”主要建立在以下几个核心支柱上:
* 坚实的框架基础:Bootstrap 5。它提供了响应式网格系统、预设样式的组件和强大的工具类。
* 模块化的内容组织:以 卡片 (Card) 作为信息承载的基本单元。
* 一致且充裕的间距:通过 工具类 (Utility Classes) 实现统一的内外边距和元素间隔。
* 清晰的视觉层级:利用字体大小、颜色和布局来引导用户的注意力。
* 现代化的图标系统:使用 Lucide Icons,风格统一、简洁清晰。
-------
现在,既然我已经购买了,为了使用而继续扩展我自己的项目,我需要严格尊重模板里的主题。请你扮演一位非常尊重上面设计范式的公司高级工程师,也非常精通 ASP.NET Core 的最佳实践,开始缜密的执行这项工作。
另外,我已经配好了 ASP.NET Core 里的 Layout,在编写视图(Views\Index.cshtml) 的时候,其内容会自动被 ` ` 包起来,而正确出现在他模板的核心位置。无需反复包一次。
重构的时候,考虑到 CSHTML 里有服务器代码和本地化代码,例如localizer,也包含了一些 ASP.NET Core 的标签,例如asp-for,我们要继续坚持我们的项目是服务器渲染。所以要保持原有的服务器渲染的功能,我们买模板只是单纯为了好看,不要舍本逐末,丢了核心功能。
* 例如,如果你要增加卡片的header,你也需要优先尊重服务器代码的范式,也就是用 @Localizer包起来需要呈现的string。当然你可以自由增加、编辑、删除无关业务的描述性文字。毕竟我本来写的就很差劲,一大堆无意义的文字,反复介绍。只要增加的文字好看,标准就行。
* 例如,如果你要重构表单 form,你也需要优先尊重服务器代码的范式,也就是用 等作为基础。
重构的时候,注意:我们在生成真正用于使用的业务代码,而不是模板的示例代码。所以不要编出来不存在的页面,不要编出来不存在的表单参数。我们是在真正将模板落地企业项目生产,而不是在产出代码示例。
现在,基于这些原则,重构我下面的代码:
```razor
@using Aiursoft.WebTools
@using Aiursoft.CSTools.Tools
@model Aiursoft.StatHub.Models.DashboardViewModels.IndexViewModel
@{
var showLast30 = ViewBag.Last30Seconds as bool? ?? false;
var unit = showLast30 ? "/s" : string.Empty;
}
Welcome, Admin!
Here you can manage your clients and view your clients' status.
Client status
@* Center *@
@{
var cumulativeActive = showLast30 ? "" : "active";
var last30Active = showLast30 ? "active" : "";
}
Cumulative
Last 30 seconds
IP
Name
SKU
Boot at
Avg Load
CPU Usage
Used at
RAM Usage
@if(showLast30)
{
Net Receiving
Net Sending
Disk Used
Disk Reading
Disk Writing
}
else
{
Net Received
Net Sent
Disk Used
Disk Read
Disk Written
}
OS
More
@* Last Update *@
@* Version *@
@foreach (var client in Model.Clients)
{
@{
// Identify
var isOutDated = client.LastUpdate < DateTime.UtcNow.AddMinutes(-1);
// Load
var load = client.GetLoad();
var loadRate = load.Load15M * 30; // Usually Load < 3.33 is safe.
var colorLoad =
loadRate < 10 ? "bg-success":
loadRate < 15 ? "bg-info":
loadRate < 30 ? "bg-secondary":
loadRate < 60 ? "bg-warning":
"bg-danger";
var promptTextLoad = $"Load:\n1 min: {load.Load1M}\n5 min: {load.Load5M}\n15 min: {load.Load15M}";
// CPU
var cpu = client.GetCpuUsage();
var cpuRate = cpu.Ratio;
var promptText = $"CPU Usage:\nUser: {cpu.Usr}%\nSystem: {cpu.Sys}%\nIdle: {cpu.Idl}%\nWait: {cpu.Wai}%\nSteal: {cpu.Stl}%";
var color =
cpuRate < 5 ? "bg-success":
cpuRate < 10 ? "bg-info":
cpuRate < 20 ? "bg-secondary":
cpuRate < 40 ? "bg-warning":
"bg-danger";
// RAM
var mem = client.GetMemUsed();
// NetWork
var net = showLast30 ? client.GetNetworkLast30Seconds() : client.GetNetwork();
// Disk
var disk = showLast30 ? client.GetDiskLast30Seconds() : client.GetDisk();
var diskUseRatio = client.UsedRoot / (double)client.TotalRoot;
var message = $"{client.UsedRoot}GB / {client.TotalRoot}GB";
var diskColor =
diskUseRatio < 0.6 ? "bg-success":
diskUseRatio < 0.7 ? "bg-warning":
"bg-danger";
// OS
var osFirstTwoWords = string.Join(" ", client.OsName.Split(' ').Take(2)).Trim();
// Overall
var reason = isOutDated ? "Server is out of sync. " : "";
reason += loadRate > 60 ? "Load critical. " : loadRate > 30 ? "Load warning. " : "";
reason += cpuRate > 40 ? "CPU usage critical. " : cpuRate > 20 ? "CPU usage warning. " : "";
reason += diskUseRatio > 0.7 ? "Disk space critical. " : diskUseRatio > 0.6 ? "Disk space warning. " : "";
}
@if (isOutDated)
{
}
else if (loadRate > 60 || cpuRate > 40 || diskUseRatio > 0.7)
{
}
else if (loadRate > 30 || cpuRate > 20 || diskUseRatio > 0.6)
{
}
else
{
}
@client.Ip
@client.Hostname
@if (!string.IsNullOrWhiteSpace(client.Motd))
{
✉️
}
@client.GetSku()
@* Load *@
@* CPU *@
@if (cpuRate < 30)
{
@(client.Process)
}
else
{
@(client.Process)
}
@* RAM *@
@* NetWork *@
@net.Recv.HumanReadableSize()@unit
@net.Send.HumanReadableSize()@unit
@* Disk *@
@disk.Read.HumanReadableSize()@unit
@disk.Writ.HumanReadableSize()@unit
@osFirstTwoWords
Details
@* *@
@* *@
@* @client.Version *@
}
```
现在请你开始编写这段razor吧!