using Dpz.Core.Public.ViewModel.Response;
namespace Dpz.Core.WebApi.Controllers;
/// <summary>
/// 其他的
/// </summary>
[ApiController, Route("api/[controller]")]
public class CommunityController(
IPictureRecordService pictureRecordService,
IArticleService articleService,
IAppOptionService appOptionService,
IAppLogEntryService logEntryService,
IFusionCache fusionCache,
IConfiguration configuration
) : ControllerBase
{
/// <summary>
/// 获取banner
/// </summary>
/// <returns></returns>
[HttpGet("getBanners")]
[ProducesResponseType<List<PictureRecordResponse>>(StatusCodes.Status200OK)]
public async Task<IActionResult> GetBanners()
{
var banners = await GetBannerAsync();
return Ok(banners);
}
/// <summary>
/// 获取汇总信息
/// </summary>
/// <returns></returns>
[HttpGet("summary")]
[Authorize(Policy = "System")]
[ProducesResponseType<SummaryInformation>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> GetSummary()
{
const string summaryKey = "community-summary";
var cache = await fusionCache.TryGetAsync<SummaryInformation>(summaryKey);
if (cache.HasValue)
{
return Ok(cache.Value);
}
var banner = await GetBannerAsync();
var summary = new SummaryInformation
{
ArticleTotalCount = await articleService.GetTotalCountAsync(),
Banner = banner,
LatestArticles = await articleService.GetLatestAsync(),
TodayArticleCount = await articleService.GetTodayCountAsync(),
};
if (
configuration["AgileConfig:env"]?.Equals("PROD", StringComparison.OrdinalIgnoreCase)
== false
)
{
SetRandomData(summary);
}
else
{
summary.LatestLogs = await GetTop100LogsAsync();
summary.TodayAccessNumber = await logEntryService.GetLatestAccessNumberAsync();
summary.WeekAccessNumber = await logEntryService.GetLatestAccessNumberAsync(-7);
}
await fusionCache.SetAsync(summaryKey, summary, TimeSpan.FromHours(3));
return Ok(summary);
}
[NonAction]
private static void SetRandomData(SummaryInformation summary)
{
summary.TodayAccessNumber = [];
summary.WeekAccessNumber = [];
summary.LatestLogs = $"[{DateTime.Now:HH:mm:ss} INF] this is test log";
var random = new Random();
for (var i = 0; i < 7; i++)
{
if (i == 0)
{
summary.TodayAccessNumber.Add(
new AccessSummary
{
Date = DateTime.Now.ToString("yyyy/MM/dd"),
Count = random.Next(100, 100000),
}
);
}
summary.WeekAccessNumber.Add(
new AccessSummary
{
Date = DateTime.Now.AddDays(-(i + 1)).ToString("yyyy/MM/dd"),
Count = random.Next(100, 100000),
}
);
}
}
private async Task<List<PictureRecordResponse>> GetBannerAsync()
{
var cache = await fusionCache.TryGetAsync<List<PictureRecordResponse>>(CacheKey.BannerKey);
if (cache.HasValue)
{
return cache.Value;
}
var banner = await pictureRecordService.GetBannerAsync();
await fusionCache.SetAsync(CacheKey.BannerKey, banner, TimeSpan.FromHours(12));
return banner.ToList();
}
[NonAction]
private async Task<string> GetTop100LogsAsync()
{
var logs = await logEntryService.GetPageAsync(pageSize: 100);
return string.Join(
"\n",
logs?.Events.Select(x =>
{
var recordTime = Convert.ToDateTime(x.Timestamp);
return $"[{recordTime:HH:mm:ss} {x.Level}] {x.RenderedMessage}";
})
?? new List<string>()
);
}
/// <summary>
/// 获取壁纸
/// </summary>
/// <param name="bingWallpaper"></param>
/// <returns></returns>
[HttpGet("wallpaper")]
public async Task<ActionResult<List<Wallpaper>>> Wallpaper(
[FromServices] IBingWallpaper bingWallpaper
)
{
var wallpapers = await bingWallpaper.GetTodayWallpapersAsync();
return Ok(wallpapers);
}
/// <summary>
/// 获取页脚内容
/// </summary>
/// <returns></returns>
[HttpGet("footer")]
[ProducesResponseType<string>(StatusCodes.Status200OK)]
public async Task<IActionResult> GetFooter()
{
var content = await appOptionService.GetFooterContentAsync();
return Ok(content);
}
/// <summary>
/// 保存页脚内容
/// </summary>
/// <param name="footer"></param>
/// <returns></returns>
[HttpPost("footer"), Authorize(Policy = "System")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> SaveFooter([FromBody] SaveFooterDto footer)
{
await appOptionService.SaveFooterContentAsync(footer.Content);
return NoContent();
}
/// <summary>
/// 获取robots.txt
/// </summary>
/// <returns></returns>
[HttpGet("robots.txt"), Authorize(Policy = "System")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> GetRobots()
{
var robots = await appOptionService.GetRobotsAsync();
return Ok(robots);
}
/// <summary>
/// 保存robots.txt
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost("robots.txt"), Authorize(Policy = "System")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> SaveRobots([FromBody] SvaeRobotsRequest request)
{
await appOptionService.SaveRobotsAsync(request.Content);
return NoContent();
}
/// <summary>
/// 获取友链
/// </summary>
/// <returns></returns>
[HttpGet("friends")]
public async Task<ActionResult<List<VmFriends>>> GetFriends()
{
var friends = await appOptionService.GetFriendsAsync();
return Ok(friends);
}
#if DEBUG
private static HubConnection? _connection;
/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
[HttpPost("send")]
public async Task<IActionResult> SendMessage([FromBody] string message)
{
if (_connection == null || _connection.State == HubConnectionState.Disconnected)
{
_connection = new HubConnectionBuilder()
.WithUrl("https://localhost:37701/notification")
.WithAutomaticReconnect()
.Build();
await _connection.StartAsync();
}
await _connection.InvokeCoreAsync("SendSystemNotification", [message]);
return NoContent();
}
#endif
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
这是一个ASP.NET Core Web API控制器类,名为CommunityController,主要提供社区相关的功能接口。让我详细解释一下这个代码:
类结构和依赖注入
public class CommunityController(
IPictureRecordService pictureRecordService,
IArticleService articleService,
IAppOptionService appOptionService,
IAppLogEntryService logEntryService,
IFusionCache fusionCache,
IConfiguration configuration
) : ControllerBase
使用了C# 12的主构造函数语法,通过依赖注入获取了多个服务:
IPictureRecordService: 图片记录服务IArticleService: 文章服务IAppOptionService: 应用配置选项服务IAppLogEntryService: 日志条目服务IFusionCache: 缓存服务IConfiguration: 配置服务
主要功能接口
1. Banner相关
GetBanners(): 获取banner图片列表,使用缓存机制(12小时过期)
2. 汇总信息
GetSummary(): 获取系统汇总信息,需要"System"策略授权- 包含文章总数、今日文章数、最新文章、banner等信息
- 根据环境(生产/非生产)显示不同数据
- 非生产环境显示随机测试数据
- 生产环境显示真实的访问统计和日志
- 使用缓存(3小时过期)
3. 壁纸服务
Wallpaper(): 获取必应壁纸
4. 页脚管理
GetFooter(): 获取页脚内容SaveFooter(): 保存页脚内容(需要系统授权)
5. SEO配置
GetRobots(): 获取robots.txt内容(需要系统授权)SaveRobots(): 保存robots.txt内容(需要系统授权)
6. 友链管理
GetFriends(): 获取友情链接列表
辅助方法
SetRandomData()
为非生产环境生成随机测试数据,包括:
- 随机的今日和本周访问数据
- 模拟的日志信息
GetBannerAsync()
获取banner数据的私有方法,实现了缓存机制
GetTop100LogsAsync()
获取最新100条日志并格式化为字符串
特殊功能
调试模式下的SignalR功能
#if DEBUG
[HttpPost("send")]
public async Task<IActionResult> SendMessage([FromBody] string message)
仅在DEBUG模式下编译,用于测试SignalR消息推送功能。
技术特点
- 缓存策略: 大量使用FusionCache来提高性能
- 环境区分: 根据配置区分生产和开发环境
- 授权控制: 部分接口需要特定的授权策略
- 异步编程: 所有数据库操作都使用异步方法
- 依赖注入: 充分利用.NET Core的DI容器
- 条件编译: 使用#if DEBUG实现调试功能
这个控制器是一个典型的现代ASP.NET Core Web API实现,展现了良好的架构设计和最佳实践。
评论加载中...