// ============================================================================ // 【文件说明】HwPortalController.cs - 门户主控制器 // ============================================================================ // 这是门户模块的主控制器,提供官网前台所需的各种数据查询接口。 // // 【业务场景】 // 官网前台需要展示: // - 首页配置:轮播图、核心优势、合作伙伴等 // - 产品中心:产品列表、产品详情 // - 案例中心:案例列表、案例详情 // - 联系我们:用户留言提交 // - 关于我们:公司介绍 // // 【与 Java Spring Boot 的对比】 // Java Spring Boot: // @RestController // @RequestMapping("/portal/portal") // public class HwPortalController { ... } // // ASP.NET Core: // [ApiController] // [Route("portal/portal")] // public class HwPortalController : ControllerBase { ... } // ============================================================================ namespace Admin.NET.Plugin.HwPortal; /// /// 门户主控制器。 /// /// 【控制器职责】 /// 这个控制器是官网前台的"数据入口",提供: /// 1. 配置数据查询:首页配置、配置类型 /// 2. 产品数据查询:产品列表、产品详情 /// 3. 案例数据查询:案例列表、案例详情 /// 4. 用户留言提交:联系我们表单 /// 5. 公司信息查询:关于我们 /// /// 所有接口都是 [AllowAnonymous],因为官网前台用户不需要登录。 /// /// /// 【多服务依赖】 /// 这个控制器注入了 8 个服务,这是"服务聚合"模式: /// - 控制器协调多个服务完成复杂业务 /// - 每个服务专注一个领域 /// - 控制器不包含业务逻辑,只做服务调用和结果组装 /// /// 对比 Java Spring Boot: /// Java 的写法完全一样,只是注解不同: /// @Autowired private HwPortalConfigService configService; /// @Autowired private HwProductInfoService productInfoService; /// ... /// /// [AllowAnonymous] [Route("portal/portal")] public class HwPortalController : HwPortalControllerBase { /// /// 门户配置服务。 /// private readonly HwPortalConfigService _configService; /// /// 配置类型服务。 /// private readonly HwPortalConfigTypeService _configTypeService; /// /// 案例信息服务。 /// private readonly HwProductCaseInfoService _caseInfoService; /// /// 联系我们信息服务。 /// private readonly HwContactUsInfoService _contactUsInfoService; /// /// 产品信息服务。 /// private readonly HwProductInfoService _productInfoService; /// /// 产品明细服务。 /// private readonly HwProductInfoDetailService _productInfoDetailService; /// /// 关于我们信息服务。 /// private readonly HwAboutUsInfoService _aboutUsInfoService; /// /// 关于我们明细服务。 /// private readonly HwAboutUsInfoDetailService _aboutUsInfoDetailService; /// /// 构造函数(依赖注入)。 /// /// 【构造函数注入的优势】 /// 1. 依赖关系明确:看构造函数就知道需要哪些服务 /// 2. 便于测试:可以传入 mock 对象 /// 3. 不可变:readonly 字段保证服务实例不被替换 /// /// 对比 Java Spring: /// Java 推荐的写法也是构造函数注入: /// @Autowired /// public HwPortalController( /// HwPortalConfigService configService, /// HwPortalConfigTypeService configTypeService, /// ... /// ) { /// this.configService = configService; /// ... /// } /// /// C# 和 Java 的最佳实践是一致的。 /// /// public HwPortalController( HwPortalConfigService configService, HwPortalConfigTypeService configTypeService, HwProductCaseInfoService caseInfoService, HwContactUsInfoService contactUsInfoService, HwProductInfoService productInfoService, HwProductInfoDetailService productInfoDetailService, HwAboutUsInfoService aboutUsInfoService, HwAboutUsInfoDetailService aboutUsInfoDetailService) { _configService = configService; _configTypeService = configTypeService; _caseInfoService = caseInfoService; _contactUsInfoService = contactUsInfoService; _productInfoService = productInfoService; _productInfoDetailService = productInfoDetailService; _aboutUsInfoService = aboutUsInfoService; _aboutUsInfoDetailService = aboutUsInfoDetailService; } /// /// 查询门户配置列表(分页)。 /// /// 查询条件 /// 分页数据 [HttpGet("getPortalConfigList")] public async Task> GetPortalConfigList([FromQuery] HwPortalConfig input) { // [FromQuery] 表示从 URL 查询字符串绑定参数。 // 例如:GET portal/portal/getPortalConfigList?portalConfigType=2 // 框架会自动把 portalConfigType=2 绑定到 input.PortalConfigType。 return GetDataTable(await _configService.SelectHwPortalConfigList(input)); } /// /// 查询配置类型列表(不分页)。 /// /// 查询条件 /// 配置类型列表 [HttpGet("getPortalConfigTypeList")] public async Task> GetPortalConfigTypeList([FromQuery] HwPortalConfigType input) { // GetDataTableWithoutPaging 是基类方法,返回全部数据不做分页。 return GetDataTableWithoutPaging(await _configTypeService.SelectHwPortalConfigTypeList(input)); } /// /// 查询配置类型列表(另一种查询)。 /// /// 查询条件 /// 配置类型列表 [HttpGet("selectConfigTypeList")] public async Task> SelectConfigTypeList([FromQuery] HwPortalConfigType input) { return GetDataTableWithoutPaging(await _configTypeService.SelectConfigTypeList(input)); } /// /// 查询首页案例标题列表。 /// /// 查询条件 /// 案例标题列表 [HttpGet("getHomeCaseTitleList")] public async Task> GetHomeCaseTitleList([FromQuery] HwPortalConfigType input) { return GetDataTable(await _configTypeService.SelectHwPortalConfigTypeList(input)); } /// /// 查询首页典型案例信息。 /// /// 查询条件 /// 典型案例信息 [HttpGet("getTypicalHomeCaseInfo")] public async Task GetTypicalHomeCaseInfo([FromQuery] HwProductCaseInfo input) { return Success(await _caseInfoService.GetTypicalHomeCaseInfo(input)); } /// /// 提交联系我们信息(用户留言)。 /// /// 【业务场景】 /// 用户在官网"联系我们"页面填写表单,提交留言。 /// 系统记录用户信息、留言内容、IP 地址等。 /// /// /// 联系我们信息 /// 操作结果 [HttpPost("addContactUsInfo")] [Idempotent] public async Task AddContactUsInfo([FromBody] HwContactUsInfo input) { // 【获取客户端 IP】 // HwPortalContextHelper.CurrentRequestIp(HttpContext) 获取请求的客户端 IP。 // HttpContext 包含当前 HTTP 请求的所有信息: // - Request:请求对象(Headers、Query、Body 等) // - Response:响应对象 // - User:当前登录用户(如果有) // - Connection:连接信息(IP、端口等) // // 对比 Java Spring: // Java 通常通过注入 HttpServletRequest 获取 IP: // @Autowired private HttpServletRequest request; // String ip = request.getRemoteAddr(); // // C# 通过 HttpContext 直接访问,更简洁。 input.UserIp = HwPortalContextHelper.CurrentRequestIp(HttpContext); return ToAjax(await _contactUsInfoService.InsertHwContactUsInfo(input)); } /// /// 查询产品中心产品列表(含明细)。 /// /// 查询条件 /// 产品列表(含明细) [HttpGet("getProductCenterProductInfos")] public async Task GetProductCenterProductInfos([FromQuery] HwProductInfo input) { // SelectHwProductInfoJoinDetailList 返回产品及其明细列表。 // 这是一个复杂的关联查询,在 Service 层处理。 return Success(await _productInfoService.SelectHwProductInfoJoinDetailList(input)); } /// /// 查询产品明细列表。 /// /// 查询条件 /// 产品明细列表 [HttpGet("getProductCenterProductDetailInfos")] public async Task GetProductCenterProductDetailInfos([FromQuery] HwProductInfoDetail input) { return Success(await _productInfoDetailService.SelectHwProductInfoDetailList(input)); } /// /// 查询案例中心案例列表。 /// /// 查询条件 /// 案例列表 [HttpGet("getCaseCenterCaseInfos")] public async Task GetCaseCenterCaseInfos([FromQuery] HwProductCaseInfo input) { return Success(await _caseInfoService.SelectHwProductCaseInfoList(input)); } /// /// 查询案例详情。 /// /// 【路由参数】 /// [HttpGet("getCaseCenterCaseInfo/{caseInfoId:long}")] 中的 {caseInfoId:long} 是路由参数。 /// :long 是路由约束,确保 caseInfoId 是长整型。 /// /// 调用示例:GET portal/portal/getCaseCenterCaseInfo/123 /// 框架会把 123 绑定到 caseInfoId 参数。 /// /// 对比 Java Spring Boot: /// Java: @GetMapping("/getCaseCenterCaseInfo/{caseInfoId}") /// public Result getCaseCenterCaseInfo(@PathVariable Long caseInfoId) /// /// C# 的路由约束更强大,可以在路由模板中定义类型验证。 /// /// /// 案例ID /// 案例详情 [HttpGet("getCaseCenterCaseInfo/{caseInfoId:long}")] public async Task GetCaseCenterCaseInfo(long caseInfoId) { return Success(await _caseInfoService.SelectHwProductCaseInfoByCaseInfoId(caseInfoId)); } /// /// 查询关于我们信息。 /// /// 查询条件 /// 关于我们信息 [HttpGet("getAboutUsInfo")] public async Task GetAboutUsInfo([FromQuery] HwAboutUsInfo input) { return Success(await _aboutUsInfoService.SelectHwAboutUsInfoList(input)); } /// /// 查询关于我们明细列表。 /// /// 查询条件 /// 关于我们明细列表 [HttpGet("getAboutUsInfoDetails")] public async Task GetAboutUsInfoDetails([FromQuery] HwAboutUsInfoDetail input) { return Success(await _aboutUsInfoDetailService.SelectHwAboutUsInfoDetailList(input)); } }