|
|
namespace Admin.NET.Plugin.HwPortal;
|
|
|
|
|
|
// [AllowAnonymous] 是 ASP.NET Core/Furion 里的匿名放行特性。
|
|
|
// 你可以把它理解成 Spring Security 里“这个接口不要求登录”的声明式配置。
|
|
|
// 和 Spring 常见的配置类放行不同,这里直接写在控制器上,阅读时更集中。
|
|
|
[AllowAnonymous]
|
|
|
[Route("portal/search")]
|
|
|
public class HwSearchController : HwPortalControllerBase
|
|
|
{
|
|
|
// readonly 字段表示“构造完成后不允许再被重新赋值”。
|
|
|
// 这和 Java 里把依赖字段声明成 final 的意图一致:依赖一旦注入完成,就不要在运行期乱改。
|
|
|
private readonly HwSearchService _service;
|
|
|
|
|
|
public HwSearchController(HwSearchService service)
|
|
|
{
|
|
|
// 这就是 C#/ASP.NET Core 最常见的“构造函数注入”。
|
|
|
// 对应 Java Spring 你可以理解成:
|
|
|
// 1. 以前常见的 @Autowired 字段注入
|
|
|
// 2. 更推荐的 @RequiredArgsConstructor / 构造器注入
|
|
|
// 这里只是 C# 没有 Lombok,直接手写构造函数而已。
|
|
|
_service = service;
|
|
|
}
|
|
|
|
|
|
// [HttpGet] 表示这个方法处理 GET 请求。
|
|
|
// Java Spring 里对应 @GetMapping。
|
|
|
// 这里没有写路径,表示沿用类上的基础路由,也就是 /portal/search。
|
|
|
[HttpGet]
|
|
|
// 这是我们自定义的限流特性。
|
|
|
// 注意它不是“只做标记”,而是自己实现了 IAsyncActionFilter,框架执行到这里会先跑限流逻辑,再决定要不要进入方法体。
|
|
|
[HwPortalIpRateLimit("portal_search", 60, 120)]
|
|
|
public async Task<HwPortalAjaxResult> Search([FromQuery] string keyword, [FromQuery] int? pageNum, [FromQuery] int? pageSize)
|
|
|
{
|
|
|
// async + await 是 C# 异步编程的核心写法。
|
|
|
// 你可以先把它理解成“这个方法里要等待数据库/IO,但等待时不想卡死线程”。
|
|
|
// Java 里它不等于 new Thread,也不等于 CompletableFuture 全套写法,更像框架层帮你把异步 IO 写法简化了。
|
|
|
|
|
|
// [FromQuery] 表示参数从 URL 查询串里绑定,例如 ?keyword=轮胎&pageNum=1。
|
|
|
// Spring Boot 里通常你会写 @RequestParam;ASP.NET Core 则更常用 [FromQuery] 明确绑定来源。
|
|
|
return Success(await _service.Search(keyword, pageNum, pageSize));
|
|
|
}
|
|
|
|
|
|
// 这里写了 "edit",所以完整路由会变成 /portal/search/edit。
|
|
|
// 这和 Spring 的 @GetMapping("/edit") 完全是同一类路由声明思路。
|
|
|
[HttpGet("edit")]
|
|
|
[HwPortalIpRateLimit("portal_search_edit", 60, 120)]
|
|
|
public async Task<HwPortalAjaxResult> EditSearch([FromQuery] string keyword, [FromQuery] int? pageNum, [FromQuery] int? pageSize)
|
|
|
{
|
|
|
// 展示端和编辑端共用同一套搜索主逻辑,只是编辑端需要多返回 editRoute。
|
|
|
// 这种“控制器只做参数接线,真正差异交给 Service”的写法,是为了让 API 层保持薄,不把业务判断写散。
|
|
|
return Success(await _service.SearchForEdit(keyword, pageNum, pageSize));
|
|
|
}
|
|
|
}
|