using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using Dpz.Core.Public.ViewModel.V4;
using Dpz.Core.Service.ObjectStorage.Services;
using Dpz.Core.Service.V4.Services;
using Dpz.Core.Web.Library.Api;
using Dpz.Core.Web.Models;
using MongoDB.Bson;
namespace Dpz.Core.Web.Controllers;
public class ArticleController(
IArticleService articleService,
IObjectStorageOperation objectStorageService,
ILogger<ArticleController> logger
) : Controller
{
public async Task<IActionResult> Index(
[FromServices] IHomeCacheService cacheService,
string? tag = "",
[Range(10, 100)] int pageSize = 10,
int pageIndex = 1
)
{
if (!ModelState.IsValid)
{
return NotFound();
}
var tags = string.IsNullOrEmpty(tag) ? [] : new[] { tag };
this.SetTitle(string.IsNullOrEmpty(tag) ? "文章列表" : $"标签-{tag}-文章列表");
var list = await articleService.GetPagesAsync(pageIndex, pageSize, tags: tags);
if (Request.Headers["X-PJAX"] == "true" && Request.Query["_pjax"] == ".blog-main-left")
return PartialView("_ArticleListPartial", list);
var model = new ArticleIndexModel
{
LikeArticle = await cacheService.GetRandomArticlesAsync(),
List = list,
News = await cacheService.GetLatestArticlesAsync(),
Tags = await cacheService.GetArticleTagsAsync(),
};
return View(model);
}
public async Task<IActionResult> Read(string id = "")
{
var article = await articleService.GetArticleAsync(id);
if (article == null)
return NotFound();
this.SetTitle(article.Title);
var pageMetaPage = new VmPageMetadata
{
Description = Regex.Replace(article.Introduction ?? "", "<[^>]*>", ""),
Keywords = new() { article.Title },
Relations = new() { "Article", "Read", id },
};
ViewData["PageMetadata"] = pageMetaPage;
return View(article);
}
[CheckAuthorize]
[HttpPost]
public async Task<IActionResult> Upload()
{
var file = Request.Form.Files.FirstOrDefault();
if (file is { Length: > 0 } && file.ContentType.Contains("image"))
{
var userInfo = User.GetIdentity();
var path = new[] { "images", "article", DateTime.Now.ToString("yyyy-MM-dd") };
var fileName =
ObjectId.GenerateNewId() + file.FileName[file.FileName.LastIndexOf('.')..];
var result = await objectStorageService.UploadAsync(
file.OpenReadStream(),
path,
fileName
);
return Json(
new
{
success = 1,
message = "",
url = result.AccessUrl,
}
);
}
return Json(
new
{
success = 0,
message = "请选择一张图片!",
url = "",
}
);
}
[HttpGet, CheckAuthorize]
public async Task<IActionResult> Publish(string id = "")
{
VmArticle? model = null;
if (!string.IsNullOrEmpty(id))
{
model = await articleService.GetArticleAsync(id);
}
return View(model);
}
[HttpPost, CheckAuthorize]
public async Task<IActionResult> Publish(VmEditArticleV4 model, string newTag = "")
{
// if (string.IsNullOrEmpty(blog.BlogTitle))
// return Json(new ResultInfo("请填写标题!"));
// if (string.IsNullOrEmpty(blog.Introduction))
// return Json(new ResultInfo("请填写简介!"));
// if (string.IsNullOrEmpty(blog.BlogContents))
// return Json(new ResultInfo("请填写内容!"));
// if (string.IsNullOrEmpty(blog.Markdown))
// return Json(new ResultInfo("Markdown is null!"));
var userInfo = User.GetStrictIdentity();
// var editArticle = new VmEditArticle
// {
// Content = model.BlogContents,
// From = "用户前台",
// Introduction = model.Introduction,
// Markdown = model.Markdown,
// Tag = model.Tag,
// Title = model.BlogTitle
// };
var checkResult = ModelState.CheckModelState();
if (checkResult.IsValid)
{
return Json(new ResultInfo(string.Join("\n", checkResult.ErrorMessages)));
}
model.Tags ??= new List<string>();
if (!string.IsNullOrEmpty(newTag))
{
model.Tags.Add(newTag);
}
// 编辑
if (!string.IsNullOrEmpty(model.Id))
{
var article = await articleService.GetArticleAsync(model.Id);
if (article == null)
return Json(new ResultInfo("文章不存在"));
if (userInfo.Id != article.Author.Id)
return Json(new ResultInfo("不能修改别人发布的文章!"));
await articleService.EditArticleAsync(model, userInfo);
return Json(new ResultInfo(data: model.Id));
}
try
{
// 新增
var createdArticle = await articleService.CreateArticleAsync(model, userInfo);
return Json(new ResultInfo(data: createdArticle.Id));
}
catch (Exception ex)
{
logger.LogInformation(ex, "创建文章失败");
return Json(ResultInfo.ToFail(ex.Message));
}
}
[CheckAuthorize, HttpPost]
public async Task<IActionResult> Delete(string id)
{
var userInfo = User.GetStrictIdentity();
var article = await articleService.GetArticleAsync(id);
if (article == null)
return Json(new ResultInfo(false));
if (userInfo.Id != article.Author.Id)
{
return Json(new ResultInfo("不能删除别人发布的文章!"));
}
await articleService.DeleteAsync(id);
return Json(new ResultInfo(true));
}
public async Task<IActionResult> Preview(string id = "")
{
if (string.IsNullOrEmpty(id))
{
return NotFound();
}
var article = await articleService.GetArticleAsync(id);
if (article == null)
return NotFound();
return View(article);
}
/// <summary>
/// 获取我的文章
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="tag"></param>
/// <param name="title"></param>
/// <returns></returns>
[HttpGet, CheckAuthorize]
public async Task<IActionResult> MyArticle(
int pageIndex = 1,
int pageSize = 10,
string tag = "",
string title = ""
)
{
var userInfo = User.GetStrictIdentity();
var source = await articleService.GetPagesAsync(
pageIndex,
pageSize,
title,
userInfo.Id,
tag
);
var data = Pagination<VmArticleMini>.Create(source);
return Json(new ResultInfo(data));
}
[HttpGet]
public async Task<IActionResult> Detail(string id = "")
{
if (string.IsNullOrEmpty(id))
{
return Json(new ResultInfo("缺失参数"));
}
var article = await articleService.GetArticleAsync(id);
if (article == null)
{
return Json(new ResultInfo("该文章不存在"));
}
return Json(new ResultInfo(article));
}
[HttpGet]
public async Task<IActionResult> Tags()
{
var tags = await articleService.GetAllTagsAsync();
return Json(new ResultInfo(tags));
}
[HttpGet]
public async Task<IActionResult> Search(string? keyword = "")
{
var searchResult = string.IsNullOrEmpty(keyword)
? []
: await articleService.SearchAsync(keyword);
ViewData["keyword"] = keyword;
this.SetTitle($"搜索 - {keyword}");
return View(searchResult);
}
}