// ============================================================================
// 【文件说明】HwWebController.cs - 官网页面控制器
// ============================================================================
// 这个控制器负责处理官网页面相关的 HTTP 请求。
//
// 【ASP.NET Core 控制器基础】
// 控制器是 MVC 架构中的"C",负责:
// 1. 接收 HTTP 请求
// 2. 调用业务逻辑(Service 层)
// 3. 返回 HTTP 响应
//
// 【路由规则】
// [Route("portal/hwWeb")] 定义了路由前缀:
// - GET portal/hwWeb/list -> List() 方法
// - GET portal/hwWeb/{webCode} -> GetInfo() 方法
// - POST portal/hwWeb -> Add() 方法
// - PUT portal/hwWeb -> Edit() 方法
// - DELETE portal/hwWeb/{webIds} -> Remove() 方法
//
// 【与 Java Spring Boot 的对比】
// Java Spring Boot:
// @RestController
// @RequestMapping("/portal/hwWeb")
// public class HwWebController { ... }
//
// ASP.NET Core:
// [ApiController]
// [Route("portal/hwWeb")]
// public class HwWebController : ControllerBase { ... }
//
// 两者概念相同,只是注解/特性的写法不同。
// ============================================================================
namespace Admin.NET.Plugin.HwPortal;
///
/// 官网页面控制器。
///
/// 【C# 语法知识点 - 特性组合】
/// [AllowAnonymous] + [Route("portal/hwWeb")] 是多个特性组合使用。
///
/// [AllowAnonymous] 表示"允许匿名访问",不需要登录就能调用这些接口。
/// 这对于官网前台是必要的,因为访问官网的用户通常不需要登录。
///
/// 对比 Java Spring Security:
/// Java: @PermitAll 或在 SecurityConfig 中配置 permitAll()
/// C#: [AllowAnonymous] 特性
///
///
/// 【RESTful API 设计】
/// 这个控制器遵循 RESTful 风格:
/// - GET:查询操作
/// - POST:新增操作
/// - PUT:更新操作
/// - DELETE:删除操作
///
/// 对比 Java Spring Boot:
/// Java: @GetMapping, @PostMapping, @PutMapping, @DeleteMapping
/// C#: [HttpGet], [HttpPost], [HttpPut], [HttpDelete]
///
/// 写法几乎一样,只是特性名称略有不同。
///
///
[AllowAnonymous]
[Route("portal/hwWeb")]
public class HwWebController : HwPortalControllerBase
{
///
/// 页面服务实例。
///
/// 【C# 语法知识点 - readonly 字段】
/// readonly 表示"只读字段",只能在构造函数中赋值,之后不能修改。
///
/// 为什么用 readonly?
/// 1. 防止意外修改:服务实例不应该被替换
/// 2. 线程安全:readonly 字段天然线程安全
/// 3. 编译器优化:编译器可以对 readonly 字段做优化
///
/// 对比 Java:
/// Java 通常用 final 关键字:
/// private final HwWebService service;
///
///
/// 【命名约定】
/// _service 是 C# 的私有字段命名约定(下划线前缀)。
/// 也可以用 service(无前缀),但 _service 更常见于依赖注入字段。
///
///
private readonly HwWebService _service;
///
/// 构造函数(依赖注入)。
///
/// 【C# 语法知识点 - 构造函数依赖注入】
/// public HwWebController(HwWebService service)
///
/// 这是 ASP.NET Core 最核心的设计模式:依赖注入(DI)。
///
/// 工作原理:
/// 1. 应用启动时,框架扫描所有服务并注册到 DI 容器
/// 2. 当请求到达控制器时,框架自动创建所需的服务实例
/// 3. 通过构造函数把服务实例"注入"进来
///
/// 对比 Java Spring Boot:
/// Java 有三种注入方式:
/// // 1. 字段注入(不推荐)
/// @Autowired
/// private HwWebService service;
///
/// // 2. Setter 注入(较少用)
/// @Autowired
/// public void setService(HwWebService service) { this.service = service; }
///
/// // 3. 构造函数注入(推荐,和 C# 一样)
/// @Autowired
/// public HwWebController(HwWebService service) { this.service = service; }
///
/// C# ASP.NET Core 只推荐构造函数注入,这是最佳实践。
///
///
/// 页面服务实例(由框架自动注入)
public HwWebController(HwWebService service)
{
_service = service;
}
///
/// 查询页面列表。
///
/// 【HTTP 路由】
/// [HttpGet("list")] 定义了路由:GET portal/hwWeb/list
///
/// 对比 Java Spring Boot:
/// Java: @GetMapping("/list") 或 @GetMapping("list")
/// C#: [HttpGet("list")]
///
///
/// 【C# 语法知识点 - async/await 异步编程】
/// public async Task<HwPortalTableDataInfo<HwWeb>> List(...)
///
/// async/await 是 C# 的异步编程语法:
/// - async:标记方法为异步方法
/// - await:等待异步操作完成
/// - Task<T>:表示一个返回 T 类型的异步操作
///
/// 为什么用异步?
/// 数据库操作是 I/O 密集型,使用异步可以:
/// 1. 不阻塞线程:等待数据库时,线程可以处理其他请求
/// 2. 提高吞吐量:同样的线程数可以处理更多请求
///
/// 对比 Java:
/// Java 的异步写法:
/// public CompletableFuture<TableDataInfo<HwWeb>> list(...) {
/// return CompletableFuture.supplyAsync(() -> service.selectList(input));
/// }
///
/// 或者用 Spring 的 @Async 注解。
///
/// C# 的 async/await 更简洁,是语言级别的支持。
///
///
///
/// 查询参数。
///
/// 【C# 语法知识点 - [FromQuery] 特性】
/// [FromQuery] 表示从 URL 查询字符串绑定参数。
/// 例如:GET portal/hwWeb/list?webCode=100
/// 框架会自动把 webCode=100 绑定到 input.WebCode 属性。
///
/// 对比 Java Spring Boot:
/// Java: public Result list(@RequestParam Map<String, String> params)
/// 或者:public Result list(HwWeb input) // Spring 会自动绑定
///
///
/// 分页数据包装对象
[HttpGet("list")]
public async Task> List([FromQuery] HwWeb input)
{
// await 表示"等待异步操作完成"。
// GetDataTableWithoutPaging 是基类方法,不做分页,返回全部数据。
return GetDataTableWithoutPaging(await _service.SelectHwWebList(input));
}
///
/// 导出页面数据到 Excel。
///
/// 【幂等性设计】
/// [Idempotent] 是 Furion 框架的特性,表示"幂等操作"。
///
/// 什么是幂等?
/// 多次执行相同的请求,结果和执行一次一样。
///
/// 为什么导出需要幂等?
/// 1. 防止重复请求:用户多次点击导出按钮
/// 2. 限流保护:避免服务器被大量导出请求打垮
///
/// 实现原理:
/// 框架会根据请求的唯一标识(如请求头中的请求ID)判断是否重复请求。
/// 如果是重复请求,直接返回之前的结果,不再执行方法体。
///
///
/// 查询参数
/// Excel 文件下载响应
[HttpPost("export")]
[Idempotent]
public async Task Export([FromQuery] HwWeb input)
{
// ExportExcel 是基类方法,返回 IActionResult。
// IActionResult 是 ASP.NET Core 的"动作结果"接口,
// 可以是 JsonResult、FileResult、StatusCodeResult 等。
return ExportExcel(await _service.SelectHwWebList(input), "官网页面数据");
}
///
/// 根据编码查询页面详情。
///
/// 【C# 语法知识点 - 路由参数约束】
/// [HttpGet("{webCode:long}")] 中的 :long 是"路由约束"。
///
/// 含义:webCode 参数必须是 long 类型。
/// 如果传入非数字,会返回 404 而不是 400。
///
/// 常见的路由约束:
/// - :int:整数
/// - :long:长整数
/// - :guid:GUID
/// - :regex(pattern):正则表达式
///
/// 对比 Java Spring Boot:
/// Java: @GetMapping("/{webCode}")
/// public Result getInfo(@PathVariable Long webCode)
///
/// C# 的路由约束在路由模板中定义,更声明式。
///
///
/// 页面编码(从路由中获取)
/// Ajax 响应结果
[HttpGet("{webCode:long}")]
public async Task GetInfo(long webCode)
{
// Success 是基类方法,返回成功结果。
// 这里把查询到的数据包装成 AjaxResult 返回。
return Success(await _service.SelectHwWebByWebcode(webCode));
}
///
/// 新增页面。
///
/// 【C# 语法知识点 - [FromBody] 特性】
/// [FromBody] 表示从请求体(Request Body)绑定参数。
/// 框架会自动把 JSON 请求体反序列化为 HwWeb 对象。
///
/// 对比 Java Spring Boot:
/// Java: public Result add(@RequestBody HwWeb input)
/// C#: public async Task<HwPortalAjaxResult> Add([FromBody] HwWeb input)
///
/// 两者完全一样,都是 @RequestBody / [FromBody]。
///
///
/// 页面数据(从请求体 JSON 反序列化)
/// Ajax 响应结果
[HttpPost]
[Idempotent]
public async Task Add([FromBody] HwWeb input)
{
// ToAjax 是基类方法,根据影响行数返回成功或失败。
// 如果 rows > 0 返回成功,否则返回失败。
return ToAjax(await _service.InsertHwWeb(input));
}
///
/// 更新页面。
///
/// 页面数据
/// Ajax 响应结果
[HttpPut]
[Idempotent]
public async Task Edit([FromBody] HwWeb input)
{
return ToAjax(await _service.UpdateHwWeb(input));
}
///
/// 批量删除页面。
///
/// 【批量删除的设计】
/// 前端传来的删除请求通常是:DELETE portal/hwWeb/1,2,3,4,5
/// 这里的 webIds 是 "1,2,3,4,5" 字符串,需要解析成数组。
///
/// ParseLongArray 是基类方法,把 "1,2,3" 解析成 [1, 2, 3]。
///
///
/// 逗号分隔的 ID 字符串
/// Ajax 响应结果
[HttpDelete("{webIds}")]
[Idempotent]
public async Task Remove(string webIds)
{
// ParseLongArray 把 "1,2,3" 解析成 [1, 2, 3]。
return ToAjax(await _service.DeleteHwWebByWebIds(ParseLongArray(webIds)));
}
///
/// 查询页面列表(不分页)。
///
/// 查询参数
/// Ajax 响应结果
[HttpGet("getHwWebList")]
public async Task GetHwWebList([FromQuery] HwWeb input)
{
return Success(await _service.SelectHwWebList(input));
}
}